Do not delete attributes from class body if these is passed (#323)
Fixes #322
This commit is contained in:
parent
9af773bdf3
commit
fc2062ea0c
|
@ -0,0 +1 @@
|
||||||
|
If ``attr.s`` is passed a *these* argument, it will not attempt to remove attributes with the same name from the class body anymore.
|
|
@ -0,0 +1 @@
|
||||||
|
If ``attr.s`` is passed a *these* argument, it will not attempt to remove attributes with the same name from the class body anymore.
|
|
@ -364,7 +364,7 @@ class _ClassBuilder(object):
|
||||||
"""
|
"""
|
||||||
__slots__ = (
|
__slots__ = (
|
||||||
"_cls", "_cls_dict", "_attrs", "_super_names", "_attr_names", "_slots",
|
"_cls", "_cls_dict", "_attrs", "_super_names", "_attr_names", "_slots",
|
||||||
"_frozen", "_has_post_init",
|
"_frozen", "_has_post_init", "_delete_attribs",
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self, cls, these, slots, frozen, auto_attribs):
|
def __init__(self, cls, these, slots, frozen, auto_attribs):
|
||||||
|
@ -378,6 +378,7 @@ class _ClassBuilder(object):
|
||||||
self._slots = slots
|
self._slots = slots
|
||||||
self._frozen = frozen or _has_frozen_superclass(cls)
|
self._frozen = frozen or _has_frozen_superclass(cls)
|
||||||
self._has_post_init = bool(getattr(cls, "__attrs_post_init__", False))
|
self._has_post_init = bool(getattr(cls, "__attrs_post_init__", False))
|
||||||
|
self._delete_attribs = not bool(these)
|
||||||
|
|
||||||
self._cls_dict["__attrs_attrs__"] = self._attrs
|
self._cls_dict["__attrs_attrs__"] = self._attrs
|
||||||
|
|
||||||
|
@ -407,6 +408,7 @@ class _ClassBuilder(object):
|
||||||
super_names = self._super_names
|
super_names = self._super_names
|
||||||
|
|
||||||
# Clean class of attribute definitions (`attr.ib()`s).
|
# Clean class of attribute definitions (`attr.ib()`s).
|
||||||
|
if self._delete_attribs:
|
||||||
for name in self._attr_names:
|
for name in self._attr_names:
|
||||||
if name not in super_names and \
|
if name not in super_names and \
|
||||||
getattr(cls, name, None) is not None:
|
getattr(cls, name, None) is not None:
|
||||||
|
@ -575,7 +577,7 @@ def attrs(maybe_cls=None, these=None, repr_ns=None,
|
||||||
Django models) or don't want to.
|
Django models) or don't want to.
|
||||||
|
|
||||||
If *these* is not ``None``, ``attrs`` will *not* search the class body
|
If *these* is not ``None``, ``attrs`` will *not* search the class body
|
||||||
for attributes.
|
for attributes and will *not* remove any attributes from it.
|
||||||
|
|
||||||
:type these: :class:`dict` of :class:`str` to :func:`attr.ib`
|
:type these: :class:`dict` of :class:`str` to :func:`attr.ib`
|
||||||
|
|
||||||
|
@ -658,11 +660,13 @@ def attrs(maybe_cls=None, these=None, repr_ns=None,
|
||||||
|
|
||||||
.. versionadded:: 16.0.0 *slots*
|
.. versionadded:: 16.0.0 *slots*
|
||||||
.. versionadded:: 16.1.0 *frozen*
|
.. versionadded:: 16.1.0 *frozen*
|
||||||
.. versionadded:: 16.3.0 *str*, and support for ``__attrs_post_init__``.
|
.. versionadded:: 16.3.0 *str*
|
||||||
.. versionchanged::
|
.. versionadded:: 16.3.0 Support for ``__attrs_post_init__``.
|
||||||
17.1.0 *hash* supports ``None`` as value which is also the default
|
.. versionchanged:: 17.1.0
|
||||||
now.
|
*hash* supports ``None`` as value which is also the default now.
|
||||||
.. versionadded:: 17.3.0 *auto_attribs*
|
.. versionadded:: 17.3.0 *auto_attribs*
|
||||||
|
.. versionchanged:: 18.1.0
|
||||||
|
If *these* is passed, no attributes are deleted from the class body.
|
||||||
"""
|
"""
|
||||||
def wrap(cls):
|
def wrap(cls):
|
||||||
if getattr(cls, "__class__", None) is None:
|
if getattr(cls, "__class__", None) is None:
|
||||||
|
|
|
@ -269,6 +269,17 @@ class TestTransformAttrs(object):
|
||||||
simple_attr("x"),
|
simple_attr("x"),
|
||||||
) == attrs
|
) == attrs
|
||||||
|
|
||||||
|
def test_these_leave_body(self):
|
||||||
|
"""
|
||||||
|
If these is passed, no attributes are removed from the body.
|
||||||
|
"""
|
||||||
|
@attr.s(init=False, these={"x": attr.ib()})
|
||||||
|
class C(object):
|
||||||
|
x = 5
|
||||||
|
|
||||||
|
assert 5 == C().x
|
||||||
|
assert "C(x=5)" == repr(C())
|
||||||
|
|
||||||
def test_multiple_inheritance(self):
|
def test_multiple_inheritance(self):
|
||||||
"""
|
"""
|
||||||
Order of attributes doesn't get mixed up by multiple inheritance.
|
Order of attributes doesn't get mixed up by multiple inheritance.
|
||||||
|
|
Loading…
Reference in New Issue