-
-
Notifications
You must be signed in to change notification settings - Fork 385
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Converter functions remove type annotations from __init__ #694
Comments
I feel like this has come up before, but just to be clear: are you talking about whatever is in |
I'm just talking about >>> Example.__init__.__annotations__
{'return': None} whereas I would expect >>> Example.__init__.__annotations__
{'x': typing.Union[str, int], 'return': None} |
Ah. This happens here Line 2115 in 4875590
|
So the q is why did the |
@nosewings are you still game for a PR? |
Yes. School has kept me busy, but I think I can get the PR out within the next few days. |
I will note that a choice has to be made if both a converter and an explicit type annotation or import attr
def int2str(x: int) -> str:
return str(x)
@attr.s
class A:
a: str = attr.ib(converter=int2str) A plausible reading of this code's intent is that the attribute |
I suspect this muddying might be reason, why we have punted on it? I mean the correct annotation for |
@hynek Different users could have different intents, but I feel like it would be surprising if the In any case, I've submitted a PR. Of course, it's completely reasonable if the issue I've raised above makes you wary of implementing this change. |
IMHO, the type of the Vise versa, the return type of all converers must be the same and must also match an explicitly annotated type for an attribute. This is the type that a "getattr()" would return. If the converters and validators do use type annotations and if these annotations do not mach, attrs should raise a TypeError while creating the class. This would avoid the need for attrs to handle ambiguities in the user's code. :) Here is an example in pseudo code for illustration: T_IN = Type(...)
T_OUT = Type(...)
def validator(value: T_IN) -> None:
pass
def converter(value: T_IN) -> T_OUT:
return T_OUT(value)
@attr.define
class C:
x: T_OUT = attr.field(converter=converter, validator=validator)
# Resulting/generated class:
class C:
def __init__(self, x: T_IN): -> None:
self.__validate_x(x)
self.x: T_OUT = self.__convert_x(x) |
Oof, I think this leads down a dangerous path with types that are actually compatible even though the look differently. This should be left to the type checking crowd (i.e. mypy) IMHO. |
This has been fixed by #710 |
Example:
My expectation is that the generated
__init__
should take a parameterx: Union[str, int]
. Instead, the generated__init__
simply takes an untyped parameterx
.It seems like this could be solved by looking at the type annotations attached to the converter method and then annotating
__init__
appropriately.If this is a desirable feature, I can submit a PR.
The text was updated successfully, but these errors were encountered: