I've got applications that consist of a data loader and a data transformer. Each loader and each transformer are subclasses of an abstract base loader and an abstract base transformer, which I'll omit in the example below. There is a 1:1 mapping between the concrete loaders and transformers, i.e. is known which loader and transformer belong together.
Say we have two loaders and two transformers, handling data
class Data1: ...
class Data2: ...
class Loader1:
def get_data(self) -> Data1: ...
class Loader2:
def get_data(self) -> Data2: ...
class Transformer1:
def transform_data(self, data: Data1) -> None: ...
class Transformer2:
def transform_data(self, data: Data2) -> None: ...
These classes could now be combined into applications
class App1:
Loader = Loader1
Transformer = Transformer1
class App2:
Loader = Loader2
Transformer = Transformer2
with an accompanying factory
from typing import Union, Type
def make_app(use_app1: bool) -> Union[Type[App1], Type[App2]]:
if use_app1:
return App1
else:
return App2
This is how I'd like to use the above
def main(use_app1: bool) -> None:
app = make_app(use_app1)
loader = app.Loader()
data = loader.get_data()
transformer = app.Transformer()
transformer.transform_data(data=data)
However, mypy
complains:
error: Argument "data" to "transform_data" of "Transformer1" has incompatible type "Union[Data1, Data2]"; expected "Data1" [arg-type]
error: Argument "data" to "transform_data" of "Transformer2" has incompatible type "Union[Data1, Data2]"; expected "Data2" [arg-type]
Is there some way to convince mypy
that the branches Loader1 -> Data1 -> Transformer1
and Loader2 -> Data2 -> Transformer2
are separate and will not be mixed?
Is there an alternative pattern that could be used for this use case?
Aucun commentaire:
Enregistrer un commentaire