The documentation for the python Attrs, the Automatic Field Transformation and Modification section states
...You can add converters, change types, and even remove attributes completely or create new ones!" (emphasis added).
It also states in the API documentation regarding Attribute that "You should never instantiate this class yourself."
However, if you attempt to add a field in the field_transformer
function you cannot, at least with the attrs.field()
function.
import attrs
def transformer(cls, fields):
fields.append(attrs.field(name='bar'))
return fields
@attrs.define(field_transformer=transformer)
class A:
pass
A(bar=1)
This fails with a TypeError: field() got an unexpected keyword argument 'name'
. If you use "alias" instead you get AttributeError: '_CountingAttr' object has no attribute 'name'
.
What is the proper way to add a field in field_transformer
function?
Edit: I was able to get things to work with the following:
import attrs
def transformer(cls, fields):
ca = attrs.field()
f = attrs.Attribute.from_counting_attr(name="foo", ca=ca, type=int)
return [f, *fields]
@attrs.define(field_transformer=transformer)
class A:
pass
A(foo=1)
attrs
Here's another method of how you can add a field to the class with attrs.
from attrs import define, field, make_class
class Foo:
pass
Foo = make_class(Foo.__name__, {'bar': field(alias='bar')},
bases=(Foo,), field_transformer=None)
foo = Foo(bar=1)
foo # Foo(bar=1)
Alternatively, if your class already has other attributes defined, then the following would work.
@define()
class Foo:
foo: int
Foo = make_class(Foo.__name__, {'bar': field(alias='bar')},
bases=(Foo,), field_transformer=None)
foo = Foo(foo=10, bar=1)
foo # Foo(foo=10, bar=1)
NOTE: If you must use a transforming function (say
transformer_func
), then usefield_transformer=transformer_func
insidemake_class
function.