[GRASS-SVN] r68927 - in grass/trunk/lib/python/script: . testsuite
svn_grass at osgeo.org
svn_grass at osgeo.org
Sat Jul 9 17:16:06 PDT 2016
Author: wenzeslaus
Date: 2016-07-09 17:16:06 -0700 (Sat, 09 Jul 2016)
New Revision: 68927
Modified:
grass/trunk/lib/python/script/testsuite/test_start_command_functions.py
grass/trunk/lib/python/script/testsuite/test_utils.py
grass/trunk/lib/python/script/utils.py
Log:
pythonlib: use isinstance to distinguish string types (fixes r65787)
isinstance(bytes) seems to better distinguish if we can/need to decode/encode
a string. hasattr with decode/encode fails in Python 2 because all are
present everywhere (see below).
This enables Python modules to be executed with non-ascii characters
as option values (test which uses UTF-8 included). This also asks for locale
only when needed.
In Python 2:
>>> print(hasattr(b"", "decode"), hasattr("", "decode"), hasattr(u"", "decode"))
(True, True, True)
>>> print(hasattr(b"", "encode"), hasattr("", "encode"), hasattr(u"", "encode"))
(True, True, True)
>>> print(isinstance(b"", bytes), isinstance("", bytes), isinstance(u"", bytes))
(True, True, False)
In Python 3:
>>> print(hasattr(b"", "decode"), hasattr("", "decode"), hasattr(u"", "decode"))
True False False
>>> print(hasattr(b"", "encode"), hasattr("", "encode"), hasattr(u"", "encode"))
False True True
>>> print(isinstance(b"", bytes), isinstance("", bytes), isinstance(u"", bytes))
True False False
Modified: grass/trunk/lib/python/script/testsuite/test_start_command_functions.py
===================================================================
--- grass/trunk/lib/python/script/testsuite/test_start_command_functions.py 2016-07-10 00:03:04 UTC (rev 68926)
+++ grass/trunk/lib/python/script/testsuite/test_start_command_functions.py 2016-07-10 00:16:06 UTC (rev 68927)
@@ -1,3 +1,5 @@
+# -*- coding: utf-8 -*-
+# the utf-8 is important because we do use the characters
"""Tests of start_command function family (location independent)"""
from grass.gunittest.case import TestCase
@@ -3,5 +5,5 @@
from grass.gunittest.main import test
-from grass.script.core import start_command, PIPE
+from grass.script.core import start_command, PIPE, run_command
@@ -38,5 +40,28 @@
self.assertEquals(returncode, 1)
self.assertIn(b'raster', stderr)
+
+class TestPythonModuleWithUnicodeParameters(TestCase):
+ """Tests if unicode works in parameters of Python modules
+
+ This in fact tests also the `parser()` function (original motivation
+ for this tests).
+
+ Using g.search.module because it takes any option values.
+ """
+
+ def test_python_module_ascii(self):
+ """This tests if Python module works"""
+ run_command('g.search.modules', keyword=b'Priserny kun')
+
+ def test_python_module_czech_nonascii(self):
+ """This likely fails on non-UTF-8 systems (i.e. MS Win)"""
+ run_command('g.search.modules', keyword=b'Příšerný kůň')
+
+ def test_python_module_czech_unicode(self):
+ """This likely fails on non-UTF-8 systems (i.e. MS Win)"""
+ run_command('g.search.modules', keyword=u'Příšerný kůň')
+
+
if __name__ == '__main__':
test()
Modified: grass/trunk/lib/python/script/testsuite/test_utils.py
===================================================================
--- grass/trunk/lib/python/script/testsuite/test_utils.py 2016-07-10 00:03:04 UTC (rev 68926)
+++ grass/trunk/lib/python/script/testsuite/test_utils.py 2016-07-10 00:16:06 UTC (rev 68927)
@@ -39,7 +39,11 @@
def test_unicode(self):
self.assertEqual(b'text', utils.encode(u'text'))
+ def test_bytes_grabage_in_out(self):
+ """If the input is bytes we should not touch it for encoding"""
+ self.assertEqual(b'Příšerný kůň', utils.encode(b'Příšerný kůň'))
+
class TestDecode(TestCase):
"""Tests function `encode` that convert value to unicode."""
Modified: grass/trunk/lib/python/script/utils.py
===================================================================
--- grass/trunk/lib/python/script/utils.py 2016-07-10 00:03:04 UTC (rev 68926)
+++ grass/trunk/lib/python/script/utils.py 2016-07-10 00:16:06 UTC (rev 68927)
@@ -150,26 +150,31 @@
self[key] = value
-def decode(bytes):
- """Decode bytes with default locale
+def decode(bytes_):
+ """Decode bytes with default locale and return (unicode) string
- :param bytes bytes: the bytes to decode
+ No-op if parameter is not bytes (assumed unicode string).
+
+ :param bytes bytes_: the bytes to decode
"""
- enc = locale.getdefaultlocale()[1]
- if hasattr(bytes, 'decode'):
- return bytes.decode(enc) if enc else bytes.decode()
- return bytes
+ if isinstance(bytes_, bytes):
+ enc = locale.getdefaultlocale()[1]
+ return bytes_.decode(enc) if enc else bytes_.decode()
+ return bytes_
def encode(string):
- """Encode string with default locale -> bytes
+ """Encode string with default locale and return bytes with that encoding
+ No-op if parameter is bytes (assumed already encoded).
+ This ensures garbage in, garbage out.
+
:param str string: the string to encode
"""
+ if isinstance(string, bytes):
+ return string
enc = locale.getdefaultlocale()[1]
- if hasattr(string, 'encode'):
- return string.encode(enc) if enc else string.encode()
- return string
+ return string.encode(enc) if enc else string.encode()
def parse_key_val(s, sep='=', dflt=None, val_type=None, vsep=None):
More information about the grass-commit
mailing list