From df75cf2aa2434224dbd99dbf5177d9bfc30558f8 Mon Sep 17 00:00:00 2001 From: Ivan Malison Date: Thu, 8 Jan 2015 01:03:52 -0800 Subject: [PATCH] Fix UnicodeDecodeError from #114. Replace definitions of _unicode and _string. Add six as a dependeny. Fix clonedigger script. --- .dir-locals.el | 1 + clonedigger.sh | 3 +++ pylast/__init__.py | 51 ++++++++++++++++--------------------------- setup.py | 1 + tests/request_test.py | 18 --------------- tests/unicode_test.py | 28 ++++++++++++++++++++++++ tox.ini | 3 ++- 7 files changed, 54 insertions(+), 51 deletions(-) create mode 100644 .dir-locals.el create mode 100755 clonedigger.sh delete mode 100644 tests/request_test.py create mode 100644 tests/unicode_test.py diff --git a/.dir-locals.el b/.dir-locals.el new file mode 100644 index 0000000..427ee57 --- /dev/null +++ b/.dir-locals.el @@ -0,0 +1 @@ +((nil . ((pytest-global-name . "source secrets.sh && tox -e py34 --")))) diff --git a/clonedigger.sh b/clonedigger.sh new file mode 100755 index 0000000..14a016f --- /dev/null +++ b/clonedigger.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +clonedigger pylast +! grep -E "Clones detected\|lines are duplicates" output.html diff --git a/pylast/__init__.py b/pylast/__init__.py index 7020eee..88b7ccb 100644 --- a/pylast/__init__.py +++ b/pylast/__init__.py @@ -37,6 +37,8 @@ import collections import warnings import re +import six + def _deprecation_warning(message): warnings.warn(message, DeprecationWarning) @@ -1910,9 +1912,12 @@ class Artist(_BaseObject, _Taggable): return "pylast.Artist(%s, %s)" % ( repr(self.get_name()), repr(self.network)) + def __unicode__(self): + return six.text_type(self.get_name()) + @_string_output def __str__(self): - return self.get_name() + return self.__unicode__() def __eq__(self, other): if type(self) is type(other): @@ -3966,40 +3971,22 @@ def md5(text): def _unicode(text): - if sys.version_info[0] == 3: - if type(text) in (bytes, bytearray): - return str(text, "utf-8") - elif type(text) == str: - return text - else: - return str(text) - - elif sys.version_info[0] == 2: - if type(text) in (str,): - return unicode(text, "utf-8") - elif type(text) == unicode: - return text - else: - return unicode(text) + if isinstance(text, six.binary_type): + return six.text_type(text, "utf-8") + elif isinstance(text, six.text_type): + return text + else: + return six.text_type(text) -def _string(text): +def _string(string): """For Python2 routines that can only process str type.""" - - if sys.version_info[0] == 3: - if type(text) != str: - return str(text) - else: - return text - - elif sys.version_info[0] == 2: - if type(text) == str: - return text - - if type(text) == int: - return str(text) - - return text.encode("utf-8") + if isinstance(string, str): + return string + casted = six.text_type(string) + if sys.version_info[0] == 2: + casted = casted.encode("utf-8") + return casted def _collect_nodes(limit, sender, method_name, cacheable, params=None): diff --git a/setup.py b/setup.py index 8e73099..2d58901 100755 --- a/setup.py +++ b/setup.py @@ -8,6 +8,7 @@ setup( name="pylast", version="1.0.0", author="Amr Hassan ", + install_requires=['six'], tests_require=['mock', 'pytest', 'coverage', 'pep8', 'pyyaml', 'pyflakes'], description=("A Python interface to Last.fm " "(and other API compatible social networks)"), diff --git a/tests/request_test.py b/tests/request_test.py deleted file mode 100644 index 24fdf66..0000000 --- a/tests/request_test.py +++ /dev/null @@ -1,18 +0,0 @@ -# -*- coding: utf-8 -*- -import mock -import pytest - -import pylast - - -def mock_network(): - return mock.Mock( - _get_ws_auth=mock.Mock(return_value=("", "", "")) - ) - - -@pytest.mark.parametrize('unicode_artist', [u'\xe9lafdasfdsafdsa', u'ééééééé']) -def test_get_cache_key(unicode_artist): - request = pylast._Request(mock_network(), 'some_method', - params={'artist': unicode_artist}) - request._get_cache_key() diff --git a/tests/unicode_test.py b/tests/unicode_test.py new file mode 100644 index 0000000..d05c529 --- /dev/null +++ b/tests/unicode_test.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +import mock +import pytest +import six + +import pylast + + +def mock_network(): + return mock.Mock( + _get_ws_auth=mock.Mock(return_value=("", "", "")) + ) + + +@pytest.mark.parametrize('artist', [ + u'\xe9lafdasfdsafdsa', u'ééééééé', + pylast.Artist(u'B\xe9l', mock_network()), + 'fdasfdsafsaf not unicode', +]) +def test_get_cache_key(artist): + request = pylast._Request(mock_network(), 'some_method', + params={'artist': artist}) + request._get_cache_key() + + +@pytest.mark.parametrize('obj', [pylast.Artist(u'B\xe9l', mock_network())]) +def test_cast(obj): + assert type(six.text_type(obj)) is six.text_type diff --git a/tox.ini b/tox.ini index 21c569b..28796b2 100644 --- a/tox.ini +++ b/tox.ini @@ -8,6 +8,7 @@ deps = pyyaml pytest mock + ipdb pytest-cov commands = py.test -v --cov pylast --cov-report term-missing {posargs} @@ -27,4 +28,4 @@ commands = pyflakes tests pep8 pylast pep8 tests - clonedigger pylast -o /dev/stdout | grep -E "Clones detected\|lines are duplicates" \ No newline at end of file + ./clonedigger.sh \ No newline at end of file