troposphere
troposphere copied to clipboard
Accept any sequence of resources, parameters, and outputs
When type checking the code below against troposphere 4.0.1, mypy complains about:
example.py:28: error: Value of type variable "__ResourceTypeVar" of "broken_bound" cannot be "List[AWSObject]" [type-var]
example.py:29: error: Value of type variable "__ResourceTypeVarNotBound" of "broken_not_bound" cannot be "List[AWSObject]" [type-var]
For works(resource: List[BaseAWSObject]), mypy is able to infer the correct type, but it fails when a TypeVar is used. I'm not using pyright and therefore cannot say if it has the same problem.
We could use @overload instead of TypeVar to help mypy infer the correct type.
Using neither a TypeVar nor @overload isn't an option, because it would not annotate that add_X returns the same type it received.
Note that with this change any Sequence[X] is accepted and processed and not just List[X].
from typing import List, Sequence, TypeVar, Union
from troposphere import BaseAWSObject
from troposphere.sns import Topic
from troposphere.s3 import Bucket
__ResourceTypeVar = TypeVar(
"__ResourceTypeVar", bound=Union[BaseAWSObject, List[BaseAWSObject]]
)
__ResourceTypeVarNotBound = TypeVar(
"__ResourceTypeVarNotBound", BaseAWSObject, List[BaseAWSObject]
)
__ResourceTypeVarWorks = TypeVar(
"__ResourceTypeVarWorks", bound=Union[BaseAWSObject, Sequence[BaseAWSObject]]
)
__ResourceTypeVarNotBoundWorks = TypeVar(
"__ResourceTypeVarNotBoundWorks", BaseAWSObject, Sequence[BaseAWSObject]
)
def main() -> None:
topic = Topic("Topic")
bucket = Bucket("Bucket")
broken_bound([topic, bucket]) # line 28
broken_not_bound([topic, bucket]) # line 29
works([topic, bucket])
works_bound([topic, bucket])
works_not_bound([topic, bucket])
def broken_bound(resources: __ResourceTypeVar) -> None:
pass
def broken_not_bound(resources: __ResourceTypeVarNotBound) -> None:
pass
def works(resource: List[BaseAWSObject]) -> None:
pass
def works_bound(resources: __ResourceTypeVarWorks) -> None:
pass
def works_not_bound(resources: __ResourceTypeVarNotBoundWorks) -> None:
pass