attrs 17.1.0

Previous Topic Next Topic
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view

attrs 17.1.0

Hynek Schlawack-6
Hi everyone,

fresh for PyCon US 2017, the attrs team is relieved to present you the much-delayed attrs 17.1.0!

Full changes:


First the bad news: until 17.1.0, attrs’ logic regarding when to create a __hash__ method was in conflict with Python’s specification.  If you use instances as dict keys or put them into sets, you have to either make them frozen explicitly by passing `frozen=True` or implicitly by pinky-swearing to not mutate them and force the creation of __hash__  using `hash=True`.

*Please* double check before upgrading!

We’re honestly sorry but didn’t see any better way to handle this.  But mind you: hashing mutable objects is a bug so the breakage you’ll encounter may very well be the surfacing of latent, sneaky bugs.


Now the good news!

This release took very long (we promise improvement!) which led to the accumulation of a lot of great new features.  A few highlights:

# Decorators for validators

>>> @attr.s
... class C(object):
...     x = attr.ib()
...     @x.validator
...     def check(self, attribute, value):
...         if value > 42:
...             raise ValueError("y must be smaller or equal to 42")
>>> C(42)
>>> C(43)
Traceback (most recent call last):
ValueError: x must be smaller or equal to 42

# Decorators for defaults & self in factories

One of the most requested features: you can base the default of an attribute on a preceding attribute:

>>> @attr.s
... class C(object):
...     x = attr.ib(default=1)
...     y = attr.ib(default=attr.Factory(lambda self: self.x + 1, takes_self=True))
...     z = attr.ib()
...     @z.default
...     def name_does_not_matter(self):
...         return self.x + 1
>>> C()
C(x=1, y=2, z=3)

# New Validators: in_() & and_()

in_() allows to check whether a value is part of an enum or any container:

>>> import enum
>>> class State(enum.Enum):
...     ON = "on"
...     OFF = "off"
>>> @attr.s
... class C(object):
...     state = attr.ib(validator=attr.validators.in_(State))
...     val = attr.ib(validator=attr.validators.in_([1, 2, 3]))
>>> C(State.ON, 1)
C(state=<State.ON: 'on'>, val=1)
>>> C("on", 1)
Traceback (most recent call last):
ValueError: 'state' must be in <enum 'State'> (got 'on')
>>> C(State.ON, 4)
Traceback (most recent call last):
ValueError: 'val' must be in [1, 2, 3] (got 4)

and_() allows you to compose multiple validators to one.  As syntactic sugar, you can also just pass a list to `validator=`.  Therefore the following lines are equivalent:

x = attr.ib(validator=attr.validators.and_(v1, v2, v3))
x = attr.ib(validator=[v1, v2, v3])

For the attrs team


        Support the Python Software Foundation:

signature.asc (817 bytes) Download Attachment