-
-
Notifications
You must be signed in to change notification settings - Fork 409
Allow converter.optional to take a Converter such as converter.pipe as its argument #1372
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
Conversation
2c43211 to
9b22892
Compare
| def optional_converter(val, inst, field): | ||
| if val is None: | ||
| return None | ||
| return converter(val, inst, field) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not guaranteed that the converter takes 3 arguments.
The root issue is that earlier versions of attrs had a "basic" converter that just took a single val. But now with the Converter class, Converter callables may take one, two (self), two(field), or three parameters.
Some introspection here may be necessary.
Also, since converters now may be callables with one two or three params, the type signature ought to be updated as well
https://github.com/python-attrs/attrs/blob/main/src/attrs/__init__.pyi#L54
Something like Callable[[Any], Any] | Callable[[Any, Any], Any] | Callable[[Any, Any, Any], Any]?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually a Converter instance always takes three arguments:
Lines 2712 to 2725 in 13e9a6a
| if not (self.takes_self or self.takes_field): | |
| self.__call__ = lambda value, _, __: self.converter(value) | |
| elif self.takes_self and not self.takes_field: | |
| self.__call__ = lambda value, instance, __: self.converter( | |
| value, instance | |
| ) | |
| elif not self.takes_self and self.takes_field: | |
| self.__call__ = lambda value, __, field: self.converter( | |
| value, field | |
| ) | |
| else: | |
| self.__call__ = lambda value, instance, field: self.converter( | |
| value, instance, field | |
| ) |
The callable it takes as an argument can take one, two or three, but the Converter class normalizes it to always take three arguments
So I believe this is correct
I think the typing information might need an update, to accept Callable[[Any], Any] | Converter but I think that's a separate issue so maybe we should follow up on that on a separate PR?
Hnasar
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for starting on a fix!
The constructor consumes __annotations__, so move the constructor call to after those have been set on the optional_converter function
hynek
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for sorting it out yourself y'all! Feel free to open a PR re the typing issue you mentioned.
|
Thanks for merging @hynek ! I have a follow up on typing on #1373 but looks like that's still failing CI, looks like mypy on 3.10+ breaks with the error in the comments (even though I also posted #1374 to fix another issue I uncovered in converters, in a situation where they evaluate to False. Long story short, but doing an explicit comparison to None fixes that and I believe it makes sense here. Cheers! |
Summary
Allow
converter.optionalto take a Converter such asconverter.pipeas its argument.Fixes #1348
Pull Request Check List
mainbranch – use a separate branch!Our CI fails if coverage is not 100%.
.pyi)..rstand.mdfiles is written using semantic newlines.changelog.d.