From 69dbfa2905117d8ff694d167d96d9d8c041c4fd3 Mon Sep 17 00:00:00 2001 From: "alastair.mccormack" Date: Tue, 27 Feb 2018 21:02:02 +0000 Subject: [PATCH 1/4] Feat: `repr()` uses class name. Useful when subclassing Attrdict. --- attrdict/default.py | 3 ++- attrdict/dictionary.py | 3 ++- attrdict/mapping.py | 2 +- tests/test_attrdefault.py | 26 ++++++++++++++++++++++++++ tests/test_attrdict.py | 19 +++++++++++++++++++ tests/test_attrmap.py | 19 +++++++++++++++++++ 6 files changed, 69 insertions(+), 3 deletions(-) diff --git a/attrdict/default.py b/attrdict/default.py index a5e5bcb..2365a20 100644 --- a/attrdict/default.py +++ b/attrdict/default.py @@ -88,8 +88,9 @@ def __repr__(self): Return a string representation of the object. """ return six.u( - "AttrDefault({default_factory}, {pass_key}, {mapping})" + "{name}({default_factory}, {pass_key}, {mapping})" ).format( + name=self.__class__.__name__, default_factory=repr(self._default_factory), pass_key=repr(self._pass_key), mapping=repr(self._mapping), diff --git a/attrdict/dictionary.py b/attrdict/dictionary.py index 874e4a4..9b5c4a0 100644 --- a/attrdict/dictionary.py +++ b/attrdict/dictionary.py @@ -45,7 +45,8 @@ def __setstate__(self, state): self._setattr('_allow_invalid_attributes', allow_invalid_attributes) def __repr__(self): - return six.u('AttrDict({contents})').format( + return six.u('{name}({contents})').format( + name=self.__class__.__name__, contents=super(AttrDict, self).__repr__() ) diff --git a/attrdict/mapping.py b/attrdict/mapping.py index 02ebac8..53dfe58 100644 --- a/attrdict/mapping.py +++ b/attrdict/mapping.py @@ -68,7 +68,7 @@ def __repr__(self): # sequence type seems like more trouble than it is worth. # If people want full serialization, they can pickle, and in # 99% of cases, sequence_type won't change anyway - return six.u("AttrMap({mapping})").format(mapping=repr(self._mapping)) + return six.u("{name}({mapping})").format(name=self.__class__.__name__, mapping=repr(self._mapping)) def __getstate__(self): """ diff --git a/tests/test_attrdefault.py b/tests/test_attrdefault.py index dec9fc1..c9ee6b5 100644 --- a/tests/test_attrdefault.py +++ b/tests/test_attrdefault.py @@ -50,3 +50,29 @@ def test_repr(): ("AttrDefault(<", " 'list'>, True, {'foo': 'bar'})") ) ) + +def test_repr_subclass(): + """ + repr(AttrDefault) + """ + from attrdict.default import AttrDefault + + class MySubClass(AttrDefault): + pass + + assert_equals(repr(MySubClass(None)), "MySubClass(None, False, {})") + + # list's repr changes between python 2 and python 3 + type_or_class = 'type' if PY2 else 'class' + + assert_equals( + repr(MySubClass(list)), + type_or_class.join(("MySubClass(<", " 'list'>, False, {})")) + ) + + assert_equals( + repr(MySubClass(list, {'foo': 'bar'}, pass_key=True)), + type_or_class.join( + ("MySubClass(<", " 'list'>, True, {'foo': 'bar'})") + ) + ) diff --git a/tests/test_attrdict.py b/tests/test_attrdict.py index b376765..f980fcf 100644 --- a/tests/test_attrdict.py +++ b/tests/test_attrdict.py @@ -114,6 +114,25 @@ def test_repr(): "AttrDict({1: AttrDict({'foo': 'bar'})})" ) +def test_repr_subclass(): + """ + repr(AttrDict) + """ + + from attrdict.dictionary import AttrDict + + class MySubClass(AttrDict): + pass + + assert_equals(repr(MySubClass()), "MySubClass({})") + assert_equals(repr(MySubClass({'foo': 'bar'})), "MySubClass({'foo': 'bar'})") + assert_equals( + repr(MySubClass({1: {'foo': 'bar'}})), "MySubClass({1: {'foo': 'bar'}})" + ) + assert_equals( + repr(MySubClass({1: MySubClass({'foo': 'bar'})})), + "MySubClass({1: MySubClass({'foo': 'bar'})})" + ) if not PY2: def test_has_key(): diff --git a/tests/test_attrmap.py b/tests/test_attrmap.py index c802f33..a091213 100644 --- a/tests/test_attrmap.py +++ b/tests/test_attrmap.py @@ -19,3 +19,22 @@ def test_repr(): repr(AttrMap({1: AttrMap({'foo': 'bar'})})), "AttrMap({1: AttrMap({'foo': 'bar'})})" ) + +def test_repr_subclass(): + """ + repr(AttrMap) + """ + from attrdict.mapping import AttrMap + + class MySubClass(AttrMap): + pass + + assert_equals(repr(MySubClass()), "MySubClass({})") + assert_equals(repr(MySubClass({'foo': 'bar'})), "MySubClass({'foo': 'bar'})") + assert_equals( + repr(MySubClass({1: {'foo': 'bar'}})), "MySubClass({1: {'foo': 'bar'}})" + ) + assert_equals( + repr(MySubClass({1: MySubClass({'foo': 'bar'})})), + "MySubClass({1: MySubClass({'foo': 'bar'})})" + ) From a7421d913542cf074d0d094ea844915e61a3f1e2 Mon Sep 17 00:00:00 2001 From: "alastair.mccormack" Date: Tue, 27 Feb 2018 21:29:02 +0000 Subject: [PATCH 2/4] Feat: Code formatting to conform with PEP8 --- attrdict/mapping.py | 3 ++- tests/test_attrdefault.py | 1 + tests/test_attrdict.py | 45 +++++++++++++++++++++++---------------- tests/test_attrmap.py | 43 +++++++++++++++++++++---------------- 4 files changed, 55 insertions(+), 37 deletions(-) diff --git a/attrdict/mapping.py b/attrdict/mapping.py index 53dfe58..6f03b28 100644 --- a/attrdict/mapping.py +++ b/attrdict/mapping.py @@ -68,7 +68,8 @@ def __repr__(self): # sequence type seems like more trouble than it is worth. # If people want full serialization, they can pickle, and in # 99% of cases, sequence_type won't change anyway - return six.u("{name}({mapping})").format(name=self.__class__.__name__, mapping=repr(self._mapping)) + return six.u("{name}({mapping})").format(name=self.__class__.__name__, + mapping=repr(self._mapping)) def __getstate__(self): """ diff --git a/tests/test_attrdefault.py b/tests/test_attrdefault.py index c9ee6b5..be68fc2 100644 --- a/tests/test_attrdefault.py +++ b/tests/test_attrdefault.py @@ -51,6 +51,7 @@ def test_repr(): ) ) + def test_repr_subclass(): """ repr(AttrDefault) diff --git a/tests/test_attrdict.py b/tests/test_attrdict.py index f980fcf..5b363e3 100644 --- a/tests/test_attrdict.py +++ b/tests/test_attrdict.py @@ -104,15 +104,20 @@ def test_repr(): """ from attrdict.dictionary import AttrDict - assert_equals(repr(AttrDict()), "AttrDict({})") - assert_equals(repr(AttrDict({'foo': 'bar'})), "AttrDict({'foo': 'bar'})") - assert_equals( - repr(AttrDict({1: {'foo': 'bar'}})), "AttrDict({1: {'foo': 'bar'}})" - ) - assert_equals( - repr(AttrDict({1: AttrDict({'foo': 'bar'})})), - "AttrDict({1: AttrDict({'foo': 'bar'})})" - ) + assert_equals(repr(AttrDict()), + "AttrDict({})" + ) + + assert_equals(repr(AttrDict({'foo': 'bar'})), + "AttrDict({'foo': 'bar'})" + ) + assert_equals(repr(AttrDict({1: {'foo': 'bar'}})), + "AttrDict({1: {'foo': 'bar'}})" + ) + assert_equals(repr(AttrDict({1: AttrDict({'foo': 'bar'})})), + "AttrDict({1: AttrDict({'foo': 'bar'})})" + ) + def test_repr_subclass(): """ @@ -124,15 +129,19 @@ def test_repr_subclass(): class MySubClass(AttrDict): pass - assert_equals(repr(MySubClass()), "MySubClass({})") - assert_equals(repr(MySubClass({'foo': 'bar'})), "MySubClass({'foo': 'bar'})") - assert_equals( - repr(MySubClass({1: {'foo': 'bar'}})), "MySubClass({1: {'foo': 'bar'}})" - ) - assert_equals( - repr(MySubClass({1: MySubClass({'foo': 'bar'})})), - "MySubClass({1: MySubClass({'foo': 'bar'})})" - ) + assert_equals(repr(MySubClass()), + "MySubClass({})" + ) + assert_equals(repr(MySubClass({'foo': 'bar'})), + "MySubClass({'foo': 'bar'})" + ) + assert_equals(repr(MySubClass({1: {'foo': 'bar'}})), + "MySubClass({1: {'foo': 'bar'}})" + ) + assert_equals(repr(MySubClass({1: MySubClass({'foo': 'bar'})})), + "MySubClass({1: MySubClass({'foo': 'bar'})})" + ) + if not PY2: def test_has_key(): diff --git a/tests/test_attrmap.py b/tests/test_attrmap.py index a091213..ccd980c 100644 --- a/tests/test_attrmap.py +++ b/tests/test_attrmap.py @@ -10,15 +10,19 @@ def test_repr(): """ from attrdict.mapping import AttrMap - assert_equals(repr(AttrMap()), "AttrMap({})") - assert_equals(repr(AttrMap({'foo': 'bar'})), "AttrMap({'foo': 'bar'})") - assert_equals( - repr(AttrMap({1: {'foo': 'bar'}})), "AttrMap({1: {'foo': 'bar'}})" - ) - assert_equals( - repr(AttrMap({1: AttrMap({'foo': 'bar'})})), - "AttrMap({1: AttrMap({'foo': 'bar'})})" - ) + assert_equals(repr(AttrMap()), + "AttrMap({})" + ) + assert_equals(repr(AttrMap({'foo': 'bar'})), + "AttrMap({'foo': 'bar'})" + ) + assert_equals(repr(AttrMap({1: {'foo': 'bar'}})), + "AttrMap({1: {'foo': 'bar'}})" + ) + assert_equals(repr(AttrMap({1: AttrMap({'foo': 'bar'})})), + "AttrMap({1: AttrMap({'foo': 'bar'})})" + ) + def test_repr_subclass(): """ @@ -29,12 +33,15 @@ def test_repr_subclass(): class MySubClass(AttrMap): pass - assert_equals(repr(MySubClass()), "MySubClass({})") - assert_equals(repr(MySubClass({'foo': 'bar'})), "MySubClass({'foo': 'bar'})") - assert_equals( - repr(MySubClass({1: {'foo': 'bar'}})), "MySubClass({1: {'foo': 'bar'}})" - ) - assert_equals( - repr(MySubClass({1: MySubClass({'foo': 'bar'})})), - "MySubClass({1: MySubClass({'foo': 'bar'})})" - ) + assert_equals(repr(MySubClass()), + "MySubClass({})" + ) + assert_equals(repr(MySubClass({'foo': 'bar'})), + "MySubClass({'foo': 'bar'})" + ) + assert_equals(repr(MySubClass({1: {'foo': 'bar'}})), + "MySubClass({1: {'foo': 'bar'}})" + ) + assert_equals(repr(MySubClass({1: MySubClass({'foo': 'bar'})})), + "MySubClass({1: MySubClass({'foo': 'bar'})})" + ) From 26d1e9306529f17ac004271f86f6ee81056c507d Mon Sep 17 00:00:00 2001 From: "alastair.mccormack" Date: Tue, 27 Feb 2018 21:43:16 +0000 Subject: [PATCH 3/4] Fix: Travis-CI: Ensure pip, wheel and setuptools are up-to-date --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 92845bb..c14e4c8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,7 @@ python: - "pypy" - "pypy3" install: + - "pip install -U pip wheel setuptools" - "pip install -r requirements-tests.txt" - "python setup.py install" script: "python setup.py nosetests && flake8 attrdict tests" From f6b6fdeb68cca90b776266bad8cd9711c003f3cc Mon Sep 17 00:00:00 2001 From: "alastair.mccormack" Date: Tue, 27 Feb 2018 21:53:49 +0000 Subject: [PATCH 4/4] Fix: Travis-CI: Removed Python 2.6 and 3.2 Testing Support for dependent libraries of nose and Flake 8 in Py 2.6 and Py 3.2 is being removed. Example: Requests: https://github.com/requests/requests/issues/3479 --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index c14e4c8..24ef46d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,9 +2,7 @@ language: python python: - "3.4" - "3.3" - - "3.2" - "2.7" - - "2.6" - "pypy" - "pypy3" install: