-
-
Notifications
You must be signed in to change notification settings - Fork 373
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Does the metadata default dict have to be a mutable 'singleton'? #278
Comments
Even with this patch all tests pass for both py2 and 3. This includes diff --git a/src/attr/_make.py b/src/attr/_make.py
index eaac084..70e612d 100644
--- a/src/attr/_make.py
+++ b/src/attr/_make.py
@@ -61,7 +61,7 @@ Sentinel to indicate the lack of a value when ``None`` is ambiguous.
def attrib(default=NOTHING, validator=None,
repr=True, cmp=True, hash=None, init=True,
- convert=None, metadata={}, type=None):
+ convert=None, metadata=None, type=None):
"""
Create a new attribute on a class.
@@ -140,6 +140,8 @@ def attrib(default=NOTHING, validator=None,
raise TypeError(
"Invalid value for hash. Must be True, False, or None."
)
+ if metadata is None:
+ metadata = {}
return _CountingAttr(
default=default,
validator=validator, |
Hi, a couple of remarks. Once the class is "baked", if an attribute has no metadata, Also, if you want to apply your changes before the That being said, I don't see a problem with making |
The single-empty-dict optimization only applies to the number of Anyways, reapplying the single-empty-dict optimization at the time of It's really about hiding the implementation (not terribly important but seems kind) and providing more isolation for each additional lib I apply to the attribute (improved legibility). In my two present cases, I already updated the metadata modifier to check for an empty dict and replace it with a fresh one to avoid this issue. The concern remains that this optimization is exposed to the user without using a read-only proxy (like I looked at I'll be heading out soon but will try to come up with a valid test that also fits in. The following ends up with several @given(lists(simple_attrs_without_metadata, min_size=2, max_size=5))
def test_empty_countingattr_metadata_independent(self, list_of_attrs):
"""
All empty metadata attributes are independent until ``@attr.s``.
"""
list_of_attrs[0].metadata[object()] = 42
C = make_class("C", dict(zip(gen_attr_names(), list_of_attrs)))
for a in fields(C)[1:]:
assert len(a.metadata) == 0 |
* Make _CountingAttr empty metadata unique Issue #278 * Correct st.none().map() to st.builds() * Add 'real' and 'force coverage' tests for not None metadata * Add changelog for pr 280 * Correct import order in tests/test_make.py * Add back coverage force test * Remove debug print from test/utils.py
This should be fixed. |
attr.ib()
creates a mutable 'singleton'{}
as the default formetadata
.attrs/src/attr/_make.py
Line 64 in 3d3d49b
attrs/tests/test_make.py
Line 776 in 3d3d49b
#96 (comment)
I just ran into this while working on a couple of libraries that leverage the structure provided by
attrs
classes. I want them to be able to easily add their own data to the attribute metadata and preferred themutate_metadata()
below over thecreate_metadata()
option. I have a couple of different things doing similar to this already so stacking them in a more decorator-like way seems cleaner.Naive mutation resulted in sharing the modified 'singleton' dictionary with other attributes that didn't specify the metadata on creation.
Perhaps immutable metadata makes sense but then it should at least be immutable instead of just global? I would obviously like it to be mutable at least until
@attr.s
for my usage, though I haven't considered the implications of that.https://repl.it/NZ22/4
The text was updated successfully, but these errors were encountered: