Allow attributes to be called property and itemgetter (#430)

* Allow attributes to be called property and itemgetter

* Add newsfragment
This commit is contained in:
Hynek Schlawack 2018-08-21 06:42:46 +02:00 committed by GitHub
parent 6a07b035b7
commit 068cd0ba4c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 21 additions and 2 deletions

View File

@ -0,0 +1 @@
Attributes can be named ``property`` and ``itemgetter`` now.

View File

@ -31,7 +31,9 @@ from .exceptions import (
_obj_setattr = object.__setattr__ _obj_setattr = object.__setattr__
_init_converter_pat = "__attr_converter_{}" _init_converter_pat = "__attr_converter_{}"
_init_factory_pat = "__attr_factory_{}" _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") _classvar_prefixes = ("typing.ClassVar", "t.ClassVar", "ClassVar")
# we don't use a double-underscore prefix because that triggers # we don't use a double-underscore prefix because that triggers
# name mangling when trying to create a slot for the field # 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: else:
attr_class_template.append(" pass") attr_class_template.append(" pass")
globs = {"itemgetter": itemgetter} globs = {"_attrs_itemgetter": itemgetter, "_attrs_property": property}
eval(compile("\n".join(attr_class_template), "", "exec"), globs) eval(compile("\n".join(attr_class_template), "", "exec"), globs)
return globs[attr_class_name] return globs[attr_class_name]

View File

@ -482,3 +482,18 @@ class TestDarkMagic(object):
with pytest.raises(FrozenInstanceError): with pytest.raises(FrozenInstanceError):
i.b = "3" 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