attrs icon indicating copy to clipboard operation
attrs copied to clipboard

Question: `make_class` equivalent of the "new API" - defining fields using type annotations

Open burnpanck opened this issue 2 years ago • 1 comments

I have been trying to use attr.make_class to create a class based on type annotations. This is exemplified by the following code:

import attr
import inspect

class Test:
    a: int
    b: str

aTest = attr.frozen(Test)

sig = inspect.get_annotations(Test)
print(sig) # {"a": int, "b": str}

# fails with AttributeError: type object 'int' has no attribute 'type'
bTest = attr.make_class("Test", sig, frozen=True, on_setattr=True, auto_attribs=True)

The intent were for bTest to be equivalent to aTest, but generated programatically. However, that doesn't seem to work. What is the standard way to create an attr class programmatically from type annotations?

burnpanck avatar Nov 21 '21 19:11 burnpanck

import attr import inspect

Define a function to create an attr class from type annotations

def create_attr_class(cls_name, annotations, frozen=True): attr_fields = {} for attr_name, attr_type in annotations.items(): attr_fields[attr_name] = attr.ib(type=attr_type)

return attr.define(cls_name, **attr_fields, frozen=frozen)

Define your class with type annotations

class Test: a: int b: str

Get the annotations from the class

annotations = inspect.get_type_hints(Test)

Create an attr class programmatically

GeneratedTestClass = create_attr_class("GeneratedTest", annotations, frozen=True)

Create instances of the generated class

test_instance = GeneratedTestClass(a=42, b="Hello")

Verify that it's frozen

try: test_instance.a = 10 # This should raise an AttributeError except AttributeError as e: print(e)

Print the instance

print(test_instance)

ljluestc avatar Sep 20 '23 23:09 ljluestc