You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Added support for keyword-only arguments on Python 3+ [rebase] (#411)
* Added support for keyword-only attributes. Closes#106, and closes#38
(Rebases #281)
Co-authored-by: Alex Ford <[email protected]>
* Add `attr.s`-level `kw_only` flag.
Add `kw_only` flag to `attr.s` decorator, indicating that all class
attributes should be keyword-only in __init__.
Minor updates to internal interface of `Attribute` to support
evolution of attributes to `kw_only` in class factory.
Expand examples with `attr.s` level kw_only.
* Add `kw_only` to type stubs.
* Update changelog for rebased PR.
Hear ye, hear ye. A duplicate PR is born.
* Tidy docs from review.
* Tidy code from review.
* Add explicit tests of PY2 kw_only SyntaxError behavior.
* Add `PythonToOldError`, raise for kw_only on PY2.
* `Attribute._evolve` to `Attribute._assoc`.
Added ``kw_only`` arguments to ``attr.ib`` and ``attr.s```, and a corresponding ``kw_only`` attribute to ``attr.Attribute``.
2
+
This change makes it possible to have a generated ``__init__`` with keyword-only arguments on Python 3, relaxing the required ordering of default and non-default valued attributes.
Added ``kw_only`` arguments to ``attr.ib`` and ``attr.s```, and a corresponding ``kw_only`` attribute to ``attr.Attribute``.
2
+
This change makes it possible to have a generated ``__init__`` with keyword-only arguments on Python 3, relaxing the required ordering of default and non-default valued attributes.
@@ -275,7 +275,7 @@ See :ref:`asdict` for examples.
275
275
>>> attr.validate(i)
276
276
Traceback (most recent call last):
277
277
...
278
-
TypeError: ("'x' must be <type 'int'> (got '1' that is a <type 'str'>).", Attribute(name='x', default=NOTHING, validator=<instance_of validator for type <type 'int'>>, repr=True, cmp=True, hash=None, init=True, type=None), <type 'int'>, '1')
278
+
TypeError: ("'x' must be <type 'int'> (got '1' that is a <type 'str'>).", Attribute(name='x', default=NOTHING, validator=<instance_of validator for type <type 'int'>>, repr=True, cmp=True, hash=None, init=True, type=None, kw_only=False), <type 'int'>, '1')
279
279
280
280
281
281
Validators can be globally disabled if you want to run them only in development and tests but not in production because you fear their performance impact:
@@ -308,11 +308,11 @@ Validators
308
308
>>> C("42")
309
309
Traceback (most recent call last):
310
310
...
311
-
TypeError: ("'x' must be <type 'int'> (got '42' that is a <type 'str'>).", Attribute(name='x', default=NOTHING, validator=<instance_of validator for type <type 'int'>>, type=None), <type 'int'>, '42')
311
+
TypeError: ("'x' must be <type 'int'> (got '42' that is a <type 'str'>).", Attribute(name='x', default=NOTHING, validator=<instance_of validator for type <type 'int'>>, type=None, kw_only=False), <type 'int'>, '42')
312
312
>>> C(None)
313
313
Traceback (most recent call last):
314
314
...
315
-
TypeError: ("'x' must be <type 'int'> (got None that is a <type 'NoneType'>).", Attribute(name='x', default=NOTHING, validator=<instance_of validator for type <type 'int'>>, repr=True, cmp=True, hash=None, init=True, type=None), <type 'int'>, None)
315
+
TypeError: ("'x' must be <type 'int'> (got None that is a <type 'NoneType'>).", Attribute(name='x', default=NOTHING, validator=<instance_of validator for type <type 'int'>>, repr=True, cmp=True, hash=None, init=True, type=None, kw_only=False), <type 'int'>, None)
316
316
317
317
.. autofunction:: attr.validators.in_
318
318
@@ -364,7 +364,7 @@ Validators
364
364
>>> C("42")
365
365
Traceback (most recent call last):
366
366
...
367
-
TypeError: ("'x' must be <type 'int'> (got '42' that is a <type 'str'>).", Attribute(name='x', default=NOTHING, validator=<instance_of validator for type <type 'int'>>, type=None), <type 'int'>, '42')
367
+
TypeError: ("'x' must be <type 'int'> (got '42' that is a <type 'str'>).", Attribute(name='x', default=NOTHING, validator=<instance_of validator for type <type 'int'>>, type=None, kw_only=False), <type 'int'>, '42')
If you don't set ``kw_only=True``, then there's is no valid attribute ordering and you'll get an error:
202
+
203
+
.. doctest::
204
+
205
+
>>> @attr.s
206
+
... classA:
207
+
... a = attr.ib(default=0)
208
+
>>> @attr.s
209
+
... classB(A):
210
+
... b = attr.ib()
211
+
Traceback (most recent call last):
212
+
...
213
+
ValueError: No mandatory attributes allowed after an attribute with a default value or factory. Attribute in question: Attribute(name='b', default=NOTHING, validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}), type=None, kw_only=False)
214
+
148
215
.. _asdict:
149
216
150
217
Converting to Collections Types
@@ -352,7 +419,7 @@ You can use a decorator:
352
419
>>> C("128")
353
420
Traceback (most recent call last):
354
421
...
355
-
TypeError: ("'x' must be <class 'int'> (got '128' that is a <class 'str'>).", Attribute(name='x', default=NOTHING, validator=[<instance_of validator for type <class 'int'>>, <function fits_byte at 0x10fd7a0d0>], repr=True, cmp=True, hash=True, init=True, metadata=mappingproxy({}), type=None, converter=one), <class 'int'>, '128')
422
+
TypeError: ("'x' must be <class 'int'> (got '128' that is a <class 'str'>).", Attribute(name='x', default=NOTHING, validator=[<instance_of validator for type <class 'int'>>, <function fits_byte at 0x10fd7a0d0>], repr=True, cmp=True, hash=True, init=True, metadata=mappingproxy({}), type=None, converter=one, kw_only=False), <class 'int'>, '128')
356
423
>>> C(256)
357
424
Traceback (most recent call last):
358
425
...
@@ -371,7 +438,7 @@ You can use a decorator:
371
438
>>> C("42")
372
439
Traceback (most recent call last):
373
440
...
374
-
TypeError: ("'x' must be <type 'int'> (got '42' that is a <type 'str'>).", Attribute(name='x', default=NOTHING, factory=NOTHING, validator=<instance_of validator for type <type 'int'>>, type=None), <type 'int'>, '42')
441
+
TypeError: ("'x' must be <type 'int'> (got '42' that is a <type 'str'>).", Attribute(name='x', default=NOTHING, factory=NOTHING, validator=<instance_of validator for type <type 'int'>>, type=None, kw_only=False), <type 'int'>, '42')
0 commit comments