Skip to content

Commit

Permalink
Added type parameter to attrs.field() function (#1107)
Browse files Browse the repository at this point in the history
* 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 <hs@ox.cx>
  • Loading branch information
3 people committed Apr 3, 2023
1 parent 359c2db commit 65ee286
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 3 deletions.
3 changes: 3 additions & 0 deletions changelog.d/1107.change.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Added *type* parameter to `attrs.field()` function for use with `attrs.make_class().

Please note that type checkers ignore type metadata passed into `make_class()`, but it can be useful if you're wrapping _attrs_.
8 changes: 5 additions & 3 deletions docs/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ If you're the author of a third-party library with *attrs* integration, please s

## Types

*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:
*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:

```{doctest}
>>> @define
Expand Down Expand Up @@ -626,11 +626,13 @@ Sometimes you may want to create a class programmatically.
>>> from attrs import make_class
>>> @define
... class C1:
... x = field()
... x = field(type=int)
... y = field()
>>> C2 = make_class("C2", ["x", "y"])
>>> C2 = make_class("C2", {"x": field(type=int), "y": field()})
>>> fields(C1) == fields(C2)
True
>>> fields(C1).x.type
<class 'int'>
```

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`:
Expand Down
4 changes: 4 additions & 0 deletions src/attr/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ def field(
order: Optional[bool] = ...,
on_setattr: Optional[_OnSetAttrArgType] = ...,
alias: Optional[str] = ...,
type: Optional[type] = ...,
) -> Any: ...

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

# This form catches an explicit default argument.
Expand All @@ -298,6 +300,7 @@ def field(
order: Optional[_EqOrderType] = ...,
on_setattr: Optional[_OnSetAttrArgType] = ...,
alias: Optional[str] = ...,
type: Optional[type] = ...,
) -> _T: ...

# This form covers type=non-Type: e.g. forward references (str), Any
Expand All @@ -317,6 +320,7 @@ def field(
order: Optional[_EqOrderType] = ...,
on_setattr: Optional[_OnSetAttrArgType] = ...,
alias: Optional[str] = ...,
type: Optional[type] = ...,
) -> Any: ...
@overload
@__dataclass_transform__(order_default=True, field_descriptors=(attrib, field))
Expand Down
6 changes: 6 additions & 0 deletions src/attr/_next_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ def field(
hash=None,
init=True,
metadata=None,
type=None,
converter=None,
factory=None,
kw_only=False,
Expand All @@ -179,6 +180,10 @@ def field(
Identical to `attr.ib`, except keyword-only and with some arguments
removed.
.. versionadded:: 22.3.0
The *type* parameter has been re-added; mostly for
{func}`attrs.make_class`. Please note that type checkers ignore this
metadata.
.. versionadded:: 20.1.0
"""
return attrib(
Expand All @@ -188,6 +193,7 @@ def field(
hash=hash,
init=init,
metadata=metadata,
type=type,
converter=converter,
factory=factory,
kw_only=kw_only,
Expand Down
10 changes: 10 additions & 0 deletions tests/test_next_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,16 @@ def test_simple(self):
"""
C("1", 2)

def test_field_type(self):
"""
Make class with attrs.field and type parameter.
"""
classFields = {"testint": attrs.field(type=int)}

A = attrs.make_class("A", classFields)

assert int == attrs.fields(A).testint.type

def test_no_slots(self):
"""
slots can be deactivated.
Expand Down

0 comments on commit 65ee286

Please sign in to comment.