Skip to content

Commit 65ee286

Browse files
chryslepre-commit-ci[bot]hynek
authored
Added type parameter to attrs.field() function (#1107)
* Added `type` parameter to `attrs.field` and test * Added notice in examples.md * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Added changelog entry * Fixed docs * Apply suggestions from code review --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Hynek Schlawack <[email protected]>
1 parent 359c2db commit 65ee286

File tree

5 files changed

+28
-3
lines changed

5 files changed

+28
-3
lines changed

changelog.d/1107.change.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Added *type* parameter to `attrs.field()` function for use with `attrs.make_class().
2+
3+
Please note that type checkers ignore type metadata passed into `make_class()`, but it can be useful if you're wrapping _attrs_.

docs/examples.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ If you're the author of a third-party library with *attrs* integration, please s
471471

472472
## Types
473473

474-
*attrs* also allows you to associate a type with an attribute using either the *type* argument to {func}`attr.ib` or using {pep}`526`-annotations:
474+
*attrs* also allows you to associate a type with an attribute using either the *type* argument to {func}`attr.ib` and {func}`attr.field` or using {pep}`526`-annotations:
475475

476476
```{doctest}
477477
>>> @define
@@ -626,11 +626,13 @@ Sometimes you may want to create a class programmatically.
626626
>>> from attrs import make_class
627627
>>> @define
628628
... class C1:
629-
... x = field()
629+
... x = field(type=int)
630630
... y = field()
631-
>>> C2 = make_class("C2", ["x", "y"])
631+
>>> C2 = make_class("C2", {"x": field(type=int), "y": field()})
632632
>>> fields(C1) == fields(C2)
633633
True
634+
>>> fields(C1).x.type
635+
<class 'int'>
634636
```
635637

636638
You can still have power over the attributes if you pass a dictionary of name: {func}`~attrs.field` mappings and can pass arguments to `@attr.s`:

src/attr/__init__.pyi

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,7 @@ def field(
259259
order: Optional[bool] = ...,
260260
on_setattr: Optional[_OnSetAttrArgType] = ...,
261261
alias: Optional[str] = ...,
262+
type: Optional[type] = ...,
262263
) -> Any: ...
263264

264265
# This form catches an explicit None or no default and infers the type from the
@@ -279,6 +280,7 @@ def field(
279280
order: Optional[_EqOrderType] = ...,
280281
on_setattr: Optional[_OnSetAttrArgType] = ...,
281282
alias: Optional[str] = ...,
283+
type: Optional[type] = ...,
282284
) -> _T: ...
283285

284286
# This form catches an explicit default argument.
@@ -298,6 +300,7 @@ def field(
298300
order: Optional[_EqOrderType] = ...,
299301
on_setattr: Optional[_OnSetAttrArgType] = ...,
300302
alias: Optional[str] = ...,
303+
type: Optional[type] = ...,
301304
) -> _T: ...
302305

303306
# This form covers type=non-Type: e.g. forward references (str), Any
@@ -317,6 +320,7 @@ def field(
317320
order: Optional[_EqOrderType] = ...,
318321
on_setattr: Optional[_OnSetAttrArgType] = ...,
319322
alias: Optional[str] = ...,
323+
type: Optional[type] = ...,
320324
) -> Any: ...
321325
@overload
322326
@__dataclass_transform__(order_default=True, field_descriptors=(attrib, field))

src/attr/_next_gen.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ def field(
167167
hash=None,
168168
init=True,
169169
metadata=None,
170+
type=None,
170171
converter=None,
171172
factory=None,
172173
kw_only=False,
@@ -179,6 +180,10 @@ def field(
179180
Identical to `attr.ib`, except keyword-only and with some arguments
180181
removed.
181182
183+
.. versionadded:: 22.3.0
184+
The *type* parameter has been re-added; mostly for
185+
{func}`attrs.make_class`. Please note that type checkers ignore this
186+
metadata.
182187
.. versionadded:: 20.1.0
183188
"""
184189
return attrib(
@@ -188,6 +193,7 @@ def field(
188193
hash=hash,
189194
init=init,
190195
metadata=metadata,
196+
type=type,
191197
converter=converter,
192198
factory=factory,
193199
kw_only=kw_only,

tests/test_next_gen.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,16 @@ def test_simple(self):
2828
"""
2929
C("1", 2)
3030

31+
def test_field_type(self):
32+
"""
33+
Make class with attrs.field and type parameter.
34+
"""
35+
classFields = {"testint": attrs.field(type=int)}
36+
37+
A = attrs.make_class("A", classFields)
38+
39+
assert int == attrs.fields(A).testint.type
40+
3141
def test_no_slots(self):
3242
"""
3343
slots can be deactivated.

0 commit comments

Comments
 (0)