In one application I have code which generates dynamic classes which reduces the amount of duplicated code considerably. But adding type-hints for mypy checking resulted in an error. Consider the following example code (simplified to focus on the relevant bits):
class Mapper:
@staticmethod
def action() -> None:
raise NotImplementedError('Not yet implemnented')
def magic(new_name: str) -> type:
cls = type('%sMapper' % new_name.capitalize(), (Mapper,), {})
def action() -> None:
print('Hello')
cls.action = staticmethod(action)
return cls
MyCls = magic('My')
MyCls.action()
Checking this with mypy will result in the following error:
dynamic_type.py:15: error: "type" has no attribute "action"
dynamic_type.py:21: error: "type" has no attribute "action"
mypy is obviously unable to tell that the return-value from the type
call is a subclass of Mapper
, so it complains that "type" has not attribute "action" when I assign to it.
Note that the code functions perfectly and does what it is supposed to but mypy still complains.
Is there a way to flag cls
as being a type of Mapper
? I tried to simply append # type: Mapper
to the line which creates the class:
cls = type('%sMapper' % new_name.capitalize(), (Mapper,), {}) # type: Mapper
But then I get the following errors:
dynamic_type.py:10: error: Incompatible types in assignment (expression has type "type", variable has type "Mapper")
dynamic_type.py:15: error: Cannot assign to a method
dynamic_type.py:15: error: Incompatible types in assignment (expression has type "staticmethod", variable has type "Callable[[], None]")
dynamic_type.py:16: error: Incompatible return value type (got "Mapper", expected "type")
dynamic_type.py:21: error: "type" has no attribute "action"