|
From: <mi...@us...> - 2012-10-11 22:13:41
|
Revision: 7525
http://docutils.svn.sourceforge.net/docutils/?rev=7525&view=rev
Author: milde
Date: 2012-10-11 22:13:35 +0000 (Thu, 11 Oct 2012)
Log Message:
-----------
Fix Py3k error writing to stdout with encoding differing from default.
Cleanup of the workarounds for Py3k encoding problems.
Modified Paths:
--------------
trunk/docutils/HISTORY.txt
trunk/docutils/docutils/io.py
trunk/docutils/test/test_io.py
Modified: trunk/docutils/HISTORY.txt
===================================================================
--- trunk/docutils/HISTORY.txt 2012-10-03 02:56:55 UTC (rev 7524)
+++ trunk/docutils/HISTORY.txt 2012-10-11 22:13:35 UTC (rev 7525)
@@ -32,6 +32,7 @@
- FileInput/FileOutput: no system-exit on IOError. The `handle_io_errors`
option is ignored and will be removed in a future release.
+ - Fix Py3k error writing to stdout with encoding differing from default.
* docutils/parsers/rst/directives/misc.py
Modified: trunk/docutils/docutils/io.py
===================================================================
--- trunk/docutils/docutils/io.py 2012-10-03 02:56:55 UTC (rev 7524)
+++ trunk/docutils/docutils/io.py 2012-10-11 22:13:35 UTC (rev 7525)
@@ -191,7 +191,7 @@
'a Unicode string')
return data
if not isinstance(data, unicode):
- # Non-unicode (e.g. binary) output.
+ # Non-unicode (e.g. bytes) output.
return data
else:
return data.encode(self.encoding, self.error_handler)
@@ -335,7 +335,7 @@
elif (# destination is file-type object -> check mode:
mode and hasattr(self.destination, 'mode')
and mode != self.destination.mode):
- print >>self._stderr, ('Destination mode "%s" '
+ print >>self._stderr, ('Warning: Destination mode "%s" '
'differs from specified mode "%s"' %
(self.destination.mode, mode))
if not destination_path:
@@ -343,22 +343,7 @@
self.destination_path = self.destination.name
except AttributeError:
pass
- # Special cases under Python 3: different encoding or binary output
- if sys.version_info >= (3,0):
- if ('b' in self.mode
- and self.destination in (sys.stdout, sys.stderr)
- ):
- self.destination = self.destination.buffer
- if check_encoding(self.destination, self.encoding) is False:
- if self.destination in (sys.stdout, sys.stderr):
- self.destination = self.destination.buffer
- else: # TODO: try the `write to .buffer` scheme instead?
- raise ValueError('Encoding of %s (%s) differs \n'
- ' from specified encoding (%s)' %
- (self.destination_path or 'destination',
- destination.encoding, encoding))
-
def open(self):
# Specify encoding in Python 3.
if sys.version_info >= (3,0):
@@ -381,17 +366,29 @@
"""
if not self.opened:
self.open()
+ if ('b' not in self.mode and sys.version_info < (3,0)
+ or check_encoding(self.destination, self.encoding) is False
+ ):
+ data = self.encode(data)
+ if sys.version_info >= (3,0) and os.linesep != '\n':
+ data = data.replace('\n', os.linesep) # fix endings
+
try: # In Python < 2.5, try...except has to be nested in try...finally.
try:
- if 'b' not in self.mode and (sys.version_info < (3,0) or
- check_encoding(self.destination, self.encoding) is False):
- data = self.encode(data)
- if sys.version_info >= (3,0) and os.linesep != '\n':
- # writing as binary data -> fix endings
- data = data.replace('\n', os.linesep)
-
self.destination.write(data)
-
+ except TypeError, e:
+ if sys.version_info >= (3,0) and isinstance(data, bytes):
+ try:
+ self.destination.buffer.write(data)
+ except AttributeError:
+ if check_encoding(self.destination,
+ self.encoding) is False:
+ raise ValueError('Encoding of %s (%s) differs \n'
+ ' from specified encoding (%s)' %
+ (self.destination_path or 'destination',
+ self.destination.encoding, self.encoding))
+ else:
+ raise e
except (UnicodeError, LookupError), err:
raise UnicodeError(
'Unable to encode output data. output-encoding is: '
Modified: trunk/docutils/test/test_io.py
===================================================================
--- trunk/docutils/test/test_io.py 2012-10-03 02:56:55 UTC (rev 7524)
+++ trunk/docutils/test/test_io.py 2012-10-11 22:13:35 UTC (rev 7525)
@@ -162,24 +162,26 @@
# Test for Python 3 features:
if sys.version_info >= (3,0):
def test_write_bytes_to_stdout(self):
- # binary data is written to destination.buffer, if the
- # destination is sys.stdout or sys.stdin
- backup = sys.stdout
- sys.stdout = self.mock_stdout
- fo = io.FileOutput(destination=sys.stdout, mode='wb',
- autoclose=False)
+ # try writing data to `destination.buffer`, if data is
+ # instance of `bytes` and writing to `destination` fails:
+ fo = io.FileOutput(destination=self.mock_stdout)
fo.write(self.bdata)
self.assertEqual(self.mock_stdout.buffer.getvalue(),
self.bdata)
- sys.stdout = backup
- def test_encoding_clash(self):
- # Raise error, if given and destination encodings differ
- # TODO: try the `write to .buffer` scheme instead?
- self.assertRaises(ValueError,
- io.FileOutput, destination=self.mock_stdout,
- encoding='latin1')
+ def test_encoding_clash_resolved(self):
+ fo = io.FileOutput(destination=self.mock_stdout,
+ encoding='latin1', autoclose=False)
+ fo.write(self.udata)
+ self.assertEqual(self.mock_stdout.buffer.getvalue(),
+ self.udata.encode('latin1'))
+ def test_encoding_clash_nonresolvable(self):
+ del(self.mock_stdout.buffer)
+ fo = io.FileOutput(destination=self.mock_stdout,
+ encoding='latin1', autoclose=False)
+ self.assertRaises(ValueError, fo.write, self.udata)
+
if __name__ == '__main__':
unittest.main()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|