Skip to content
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

Added type parameter to attrs.field() function #1107

Merged
merged 12 commits into from
Apr 3, 2023
1 change: 1 addition & 0 deletions changelog.d/1107.change.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added `type` parameter to `attrs.field()` function.
hynek marked this conversation as resolved.
Show resolved Hide resolved
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)
hynek marked this conversation as resolved.
Show resolved Hide resolved
... 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
3 changes: 3 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,7 @@ def field(
Identical to `attr.ib`, except keyword-only and with some arguments
removed.

.. versionadded:: 22.3.0 type parameter
hynek marked this conversation as resolved.
Show resolved Hide resolved
.. versionadded:: 20.1.0
"""
return attrib(
Expand All @@ -188,6 +190,7 @@ def field(
hash=hash,
init=init,
metadata=metadata,
type=type,
converter=converter,
factory=factory,
kw_only=kw_only,
Expand Down
8 changes: 8 additions & 0 deletions tests/test_next_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ 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
hynek marked this conversation as resolved.
Show resolved Hide resolved

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