Structure using the value of attr.ib converter, if defined#139
Structure using the value of attr.ib converter, if defined#139Tinche merged 10 commits intopython-attrs:masterfrom
Conversation
Codecov Report
@@ Coverage Diff @@
## master #139 +/- ##
==========================================
- Coverage 97.82% 97.79% -0.03%
==========================================
Files 14 15 +1
Lines 873 909 +36
==========================================
+ Hits 854 889 +35
- Misses 19 20 +1
Continue to review full report at Codecov.
|
|
Cool, thanks for working on this. Don't forget to add a changelog entry, and keep it updated. This will need to be a flag though, and it needs to be disabled by default due to a) backwards compatibility, and b) it breaks a very common use case: So this flag will need documentation too. I wonder if a good heuristic would be: while generating the structure function for a class, if a field does not have a handler registered, but it does have a converter, use the converter instead. That might keep backwards compatibility somewhat and help with your use case (and the example would still work). |
|
So, before I implement anything else, here are some alternatives Option 1 - behavior as I've implemented now, but add a flag which could be used to opt-out # example of opting out
c = Converter(use_attrib_converters=False)
c.structure(...)Option 2 - make this behavior an opt-in # example of opting in
c = Converter(use_attrib_converters=True)
c.structure(...)Option 3 - no new API, fallback to attr.ib converters if no handler is registered Option 4 - fallback to attr.ib converters if no handler is found, but with an option to give attr.ib converters higher priority than registered handlers c = Converter(prefer_attrib_converters=True)
c.structure(...)Benefits of option 1 and 4 are that you could register an attribute converter which then calls cattr.structure. I personally prefer option 1. As a user, this fits with what I was expecting to happen when registering an attr.ib converter. I see the sense in the backwards compatible issue. What are your thoughts doing one of the other options in a 1.x update, and making using attr.ib converters the default in a new major version later? |
|
My order of preference would be 3, 4 and then 2. Option 1 by default breaks a use case that I'd like to support (referenced in my first comment). |
f37a24a to
2cf4132
Compare
|
Thanks for the feedback, @Tinche. I've implemented option 3 from above and updated documentation. Let me know what you think! |
|
@natemcmaster Thanks! I have a couple busy days ahead so I can't look at this right away, but will as soon as I can! |
Tinche
left a comment
There was a problem hiding this comment.
Left some comments, also don't forget to modify the changelog. Thanks!
| handler = converter.structure | ||
|
|
||
| if not converter._prefer_attrib_converters and a.converter is not None: | ||
| handler = _fallback_to_passthru(handler) |
There was a problem hiding this comment.
I don't think we need to use _fallback_to_passthru, we can know here and now if we will need to passthrough, right? If the handler is equal to converter._structure_default, the type is not is_generic and calling _structure_default raises an exception. It's a little dirty but should work.
Ideally the structure_default handler can be refactored to only contain the error logic, but that might be a different task.
There was a problem hiding this comment.
Sorry, I don't quite follow what you're proposing the code should do differently here.
…g _prefer_attrib_converters of converter argument
|
Updated per your feedback, except for the one piece I didn't understand. Side note -- some thoughts about contributing to this project -- I'm not quite sure if I've done the right things, which will likely lengthen the feedback loop here. For example, the contributing.rst guide seems out of date with the changes to add poetry, use GitHub actions, and doesn't mention if I need to run formatters/linters (seems the CI may not check formatting.) Anyways, lmk how this next draft works. Also, if you have a really specific idea of how something should work, feel free to edit my PR and merge without waiting for me. |
You're right. I would be happy to merge a PR improving this :) |
|
I think this looks good, there's a small refactor I plan on making after this is merged to make it a little cleaner, but you shouldn't worry about it. Fix the conflicts and I shall merge. Thanks a lot! |
|
Thanks @Tinche. I believe there are no more merge conflicts with the master branch. Thanks for the additional review :) |
|
@Tinche does squash merge work instead? |
|
Looks like it worked! Thanks. |

Resolves https://github.com/Tinche/cattrs/issues/138
If an attrs class has defined a converter with
attr.ib, fallback that instead if dispatching to cattrs converters fails to find a handler.Also, add a new option
prefer_attrib_convertersto use them if defined instead of handlers registered in cattrs.