aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--factory/utils.py21
-rw-r--r--tests/test_utils.py51
2 files changed, 69 insertions, 3 deletions
diff --git a/factory/utils.py b/factory/utils.py
index 48c6eed..b27fd77 100644
--- a/factory/utils.py
+++ b/factory/utils.py
@@ -20,6 +20,8 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
+from __future__ import unicode_literals
+
import collections
#: String for splitting an attribute name into a
@@ -96,11 +98,26 @@ def import_object(module_name, attribute_name):
return getattr(module, attribute_name)
+def _safe_repr(obj):
+ try:
+ obj_repr = repr(obj)
+ except UnicodeError:
+ return '<bad_repr object at %s>' % id(obj)
+
+ try: # Convert to "text type" (= unicode)
+ return '%s' % obj_repr
+ except UnicodeError: # non-ascii bytes repr on Py2
+ return obj_repr.decode('utf-8')
+
+
def log_pprint(args=(), kwargs=None):
kwargs = kwargs or {}
return ', '.join(
- [str(arg) for arg in args] +
- ['%s=%r' % item for item in kwargs.items()]
+ [repr(arg) for arg in args] +
+ [
+ '%s=%s' % (key, _safe_repr(value))
+ for key, value in kwargs.items()
+ ]
)
diff --git a/tests/test_utils.py b/tests/test_utils.py
index 8c73935..d321c2a 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -20,11 +20,14 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
+from __future__ import unicode_literals
+
+
import itertools
from factory import utils
-from .compat import unittest
+from .compat import is_python2, unittest
class ExtractDictTestCase(unittest.TestCase):
@@ -233,6 +236,52 @@ class ImportObjectTestCase(unittest.TestCase):
'this-is-an-invalid-module', '__name__')
+class LogPPrintTestCase(unittest.TestCase):
+ def test_nothing(self):
+ txt = utils.log_pprint()
+ self.assertEqual('', txt)
+
+ def test_only_args(self):
+ txt = utils.log_pprint((1, 2, 3))
+ self.assertEqual('1, 2, 3', txt)
+
+ def test_only_kwargs(self):
+ txt = utils.log_pprint(kwargs={'a': 1, 'b': 2})
+ self.assertIn(txt, ['a=1, b=2', 'b=2, a=1'])
+
+ def test_bytes_args(self):
+ txt = utils.log_pprint((b'\xe1\xe2',))
+ expected = "b'\\xe1\\xe2'"
+ if is_python2:
+ expected = expected.lstrip('b')
+ self.assertEqual(expected, txt)
+
+ def test_text_args(self):
+ txt = utils.log_pprint(('ŧêßŧ',))
+ expected = "'ŧêßŧ'"
+ if is_python2:
+ expected = "u'\\u0167\\xea\\xdf\\u0167'"
+ self.assertEqual(expected, txt)
+
+ def test_bytes_kwargs(self):
+ txt = utils.log_pprint(kwargs={'x': b'\xe1\xe2', 'y': b'\xe2\xe1'})
+ expected1 = "x=b'\\xe1\\xe2', y=b'\\xe2\\xe1'"
+ expected2 = "y=b'\\xe2\\xe1', x=b'\\xe1\\xe2'"
+ if is_python2:
+ expected1 = expected1.replace('b', '')
+ expected2 = expected2.replace('b', '')
+ self.assertIn(txt, (expected1, expected2))
+
+ def test_text_kwargs(self):
+ txt = utils.log_pprint(kwargs={'x': 'ŧêßŧ', 'y': 'ŧßêŧ'})
+ expected1 = "x='ŧêßŧ', y='ŧßêŧ'"
+ expected2 = "y='ŧßêŧ', x='ŧêßŧ'"
+ if is_python2:
+ expected1 = "x=u'\\u0167\\xea\\xdf\\u0167', y=u'\\u0167\\xdf\\xea\\u0167'"
+ expected2 = "y=u'\\u0167\\xdf\\xea\\u0167', x=u'\\u0167\\xea\\xdf\\u0167'"
+ self.assertIn(txt, (expected1, expected2))
+
+
class ResetableIteratorTestCase(unittest.TestCase):
def test_no_reset(self):
i = utils.ResetableIterator([1, 2, 3])