~ubuntu-branches/ubuntu/jaunty/python-docutils/jaunty

« back to all changes in this revision

Viewing changes to docutils/io.py

  • Committer: Bazaar Package Importer
  • Author(s): Simon McVittie
  • Date: 2008-07-24 10:39:53 UTC
  • mfrom: (1.1.4 upstream) (3.1.7 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080724103953-8gh4uezg17g9ysgy
Tags: 0.5-2
* Upload docutils 0.5 to unstable
* Update rst.el to upstream Subversion r5596, which apparently fixes
  all its performance problems (17_speed_up_rst_el.dpatch, closes: #474941)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Author: David Goodger
2
 
# Contact: goodger@users.sourceforge.net
3
 
# Revision: $Revision: 3654 $
4
 
# Date: $Date: 2005-07-03 17:02:15 +0200 (Sun, 03 Jul 2005) $
 
1
# $Id: io.py 4750 2006-09-16 21:32:29Z wiemann $
 
2
# Author: David Goodger <goodger@python.org>
5
3
# Copyright: This module has been placed in the public domain.
6
4
 
7
5
"""
16
14
    import locale
17
15
except:
18
16
    pass
 
17
import re
19
18
from types import UnicodeType
20
19
from docutils import TransformSpec
21
20
 
74
73
        if isinstance(data, UnicodeType):
75
74
            # Accept unicode even if self.encoding != 'unicode'.
76
75
            return data
77
 
        encodings = [self.encoding]
78
 
        if not self.encoding:
79
 
            # Apply heuristics only if no encoding is explicitly given.
80
 
            encodings.append('utf-8')
81
 
            try:
82
 
                encodings.append(locale.nl_langinfo(locale.CODESET))
83
 
            except:
84
 
                pass
85
 
            try:
86
 
                encodings.append(locale.getlocale()[1])
87
 
            except:
88
 
                pass
89
 
            try:
90
 
                encodings.append(locale.getdefaultlocale()[1])
91
 
            except:
92
 
                pass
93
 
            encodings.append('latin-1')
 
76
        if self.encoding:
 
77
            # We believe the user/application when the encoding is
 
78
            # explicitly given.
 
79
            encodings = [self.encoding]
 
80
        else:
 
81
            data_encoding = self.determine_encoding_from_data(data)
 
82
            if data_encoding:
 
83
                # If the data declares its encoding (explicitly or via a BOM),
 
84
                # we believe it.
 
85
                encodings = [data_encoding]
 
86
            else:
 
87
                # Apply heuristics only if no encoding is explicitly given and
 
88
                # no BOM found.  Start with UTF-8, because that only matches
 
89
                # data that *IS* UTF-8:
 
90
                encodings = ['utf-8']
 
91
                try:
 
92
                    # for Python 2.2 compatibility
 
93
                    encodings.append(locale.nl_langinfo(locale.CODESET))
 
94
                except:
 
95
                    pass
 
96
                try:
 
97
                    encodings.append(locale.getlocale()[1])
 
98
                except:
 
99
                    pass
 
100
                try:
 
101
                    encodings.append(locale.getdefaultlocale()[1])
 
102
                except:
 
103
                    pass
 
104
                # fallback encoding:
 
105
                encodings.append('latin-1')
94
106
        error = None
95
107
        error_details = ''
96
108
        for enc in encodings:
111
123
            % (', '.join([repr(enc) for enc in encodings if enc]),
112
124
               error_details))
113
125
 
 
126
    coding_slug = re.compile("coding[:=]\s*([-\w.]+)")
 
127
    """Encoding declaration pattern."""
 
128
 
 
129
    byte_order_marks = (('\xef\xbb\xbf', 'utf-8'),
 
130
                        ('\xfe\xff', 'utf-16-be'),
 
131
                        ('\xff\xfe', 'utf-16-le'),)
 
132
    """Sequence of (start_bytes, encoding) tuples to for encoding detection.
 
133
    The first bytes of input data are checked against the start_bytes strings.
 
134
    A match indicates the given encoding."""
 
135
 
 
136
    def determine_encoding_from_data(self, data):
 
137
        """
 
138
        Try to determine the encoding of `data` by looking *in* `data`.
 
139
        Check for a byte order mark (BOM) or an encoding declaration.
 
140
        """
 
141
        # check for a byte order mark:
 
142
        for start_bytes, encoding in self.byte_order_marks:
 
143
            if data.startswith(start_bytes):
 
144
                return encoding
 
145
        # check for an encoding declaration pattern in first 2 lines of file:
 
146
        for line in data.splitlines()[:2]:
 
147
            match = self.coding_slug.search(line)
 
148
            if match:
 
149
                return match.group(1)
 
150
        return None
 
151
 
114
152
 
115
153
class Output(TransformSpec):
116
154
 
159
197
        else:
160
198
            try:
161
199
                return data.encode(self.encoding, self.error_handler)
162
 
            except ValueError:
163
 
                # ValueError is raised if there are unencodable chars
164
 
                # in data and the error_handler isn't found.
 
200
            except (LookupError, ValueError):
 
201
                # LookupError is raised if there are unencodable chars
 
202
                # in data and the error_handler isn't found. In old
 
203
                # Python versions, ValueError is raised.
165
204
                if self.error_handler == 'xmlcharrefreplace':
166
205
                    # We are using xmlcharrefreplace with a Python
167
 
                    # version that doesn't support it (2.1 or 2.2), so
168
 
                    # we emulate its behavior.
 
206
                    # version that doesn't support it (2.1, 2.2, or
 
207
                    # IronPython 1.0) so we emulate its behavior.
169
208
                    return ''.join([self.xmlcharref_encode(char)
170
209
                                    for char in data])
171
210
                else: