From 068cd0ba4c43a662bfd8eb2289ffcf9e4d122424 Mon Sep 17 00:00:00 2001 From: Hynek Schlawack Date: Tue, 21 Aug 2018 06:42:46 +0200 Subject: [PATCH] Allow attributes to be called property and itemgetter (#430) * Allow attributes to be called property and itemgetter * Add newsfragment --- changelog.d/430.change.rst | 1 + src/attr/_make.py | 7 +++++-- tests/test_dark_magic.py | 15 +++++++++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 changelog.d/430.change.rst diff --git a/changelog.d/430.change.rst b/changelog.d/430.change.rst new file mode 100644 index 00000000..f4ac16f9 --- /dev/null +++ b/changelog.d/430.change.rst @@ -0,0 +1 @@ +Attributes can be named ``property`` and ``itemgetter`` now. diff --git a/src/attr/_make.py b/src/attr/_make.py index ecb668ba..4a0095f4 100644 --- a/src/attr/_make.py +++ b/src/attr/_make.py @@ -31,7 +31,9 @@ from .exceptions import ( _obj_setattr = object.__setattr__ _init_converter_pat = "__attr_converter_{}" _init_factory_pat = "__attr_factory_{}" -_tuple_property_pat = " {attr_name} = property(itemgetter({index}))" +_tuple_property_pat = ( + " {attr_name} = _attrs_property(_attrs_itemgetter({index}))" +) _classvar_prefixes = ("typing.ClassVar", "t.ClassVar", "ClassVar") # we don't use a double-underscore prefix because that triggers # name mangling when trying to create a slot for the field @@ -243,8 +245,9 @@ def _make_attr_tuple_class(cls_name, attr_names): ) else: attr_class_template.append(" pass") - globs = {"itemgetter": itemgetter} + globs = {"_attrs_itemgetter": itemgetter, "_attrs_property": property} eval(compile("\n".join(attr_class_template), "", "exec"), globs) + return globs[attr_class_name] diff --git a/tests/test_dark_magic.py b/tests/test_dark_magic.py index 988d4a92..4c93b3f6 100644 --- a/tests/test_dark_magic.py +++ b/tests/test_dark_magic.py @@ -482,3 +482,18 @@ class TestDarkMagic(object): with pytest.raises(FrozenInstanceError): i.b = "3" + + def test_tuple_class_aliasing(self): + """ + itemgetter and property are legal attribute names. + """ + + @attr.s + class C(object): + property = attr.ib() + itemgetter = attr.ib() + x = attr.ib() + + assert "property" == attr.fields(C).property.name + assert "itemgetter" == attr.fields(C).itemgetter.name + assert "x" == attr.fields(C).x.name