-
Notifications
You must be signed in to change notification settings - Fork 239
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
readonly
conflicts with default
(and rule_filter
)
#272
Conversation
i have several concerns here. i hope to write them up until Monday. |
This looks good to me! |
just a short summary of my concerns: while i think this pr approaches a valid problem, i think it's still not sufficent and may be a burden in the end. the whole normalization/validation/rules dispatching logic/andwewantitalltobecustomizable thing needs proper attention for too long. it shouldn't be continued to just fix things up when lacks of design become obvious. introducing new attributes now that may later be unnecessary doesn't make it easier as they will have to be dealt with for legacy reasons. my current plan is to dig through issues and code (history) on Friday to come up with proposals in a broader frame. it will simply take some hours, i couldn't spare yet. and most certainly, lambdas as configuration values should be avoided. |
I understand your concerns and am of course happy with finding a better solution. We don't have to rush here. Some things I noticed when digging into this:
Maybe we can have one base class for doing all the recursing stuff ("walking" the document) and calling somehow registered rule handlers? This class could be the base for both a Validator class and a Normalizer class and then we could combine two Validators and one Normalizer to get what we need, which is validating some fields before normalization and then validate again afterwards. A lot of maybes here and I am nowhere as deep into codebase and prior design decisions as you are @funkyfuture, so I think it's best to leave this up to you and maybe I can help with the actual implementation later. |
first thing i will do is to comprehend the problems with the current implementation, then propose design changes. i'll be happy to get your feedback on that as you already dove into parts of a solution. |
okay, i'm clearly overthinking things here. at least for the particular issue in question. what about the following? let's consider if this approach worked, further cluttering of evaluation blocks and more properties that determine evaluation order can be avoided. (yes, afair i introduced those, but i consider them rather hacky.) nonetheless i got some impulses that resulted in ideas for a possible 'next generation' of how we define rules (dependencies and other properties) and control their evaluation order. but having ideas is one thing, having time to act on them is another. |
I'm not sure about If your concern for this issue is mainly the introduction of a new feature ( |
I'm merging this. Eve (which is the main reason why Cerberus was born in the first place 😄) needs support for |
Maybe we can at least remove the section in the documentation so we're not pointing users to use a feature we're not sure about? I'd leave the comments/docstrings in the code as they will help future coders to understand what |
👍 |
I will do this and rebase on master tonight! |
imo, you could even drop that property and 'hardcode' the evaluation order. what are you going to do with the testcases? (they have to be refactored anyway.) though they make hardly sense and are irritating with a non-public feature, they are very usable for a later finer-grained customization mechanic. maybe mark them with
but Cerberus has emancipated from Eve, there are numerous other uses in the real world. and the users have contributed for a more general library. the Eve shall prosper, and Cerberus shall be capable to support this. but imo its heritage is not an argument for exclusive hot fixes and workarounds. we should take Eve's needs as an impulse to improve a generally usable, configurable validation library that is unique in the Python ecosystem. |
@dkellner do you think that would be feasible? |
I don't think we can (easily) hardcode the evaluation order. We need a way to pass the information to child validators that they should only process certain rules (the ones to process before normalization). We need to validate all
I'd keep them even for a non-public feature. The test-cases for using
Can we really use custom validators or custom rules here? They are both called after normalization. As far as I know, there is currently no "native" way to validate before normalization. @funkyfuture By the way, I absolutely agree with you that there are use cases for Cerberus apart from Eve and that changes we introduce here should be reasonable in that regard. I myself use it in a non-Eve project, too. In my opinion, it all leads to the question if we see pre-normalization-validation as a feature in Cerberus itself, or if we think this should be handled by the application (e.g. by splitting the schema and using two different |
I agree that it should/could be a Cerberus feature. |
@dkellner have you considered to include the |
Yes I did but I have the same concerns as implementing it as a "standalone" normalization rule (see #272 (comment)). Nevertheless I will play around with that idea later today or tomorrow and actually show some code. Maybe it's a "good" compromise solution. |
OK, here's some code: https://github.com/dkellner/cerberus/tree/normalize-readonly . I've implemented If you both agree that this is a way to solve this problem here, I'm going to update the docs in that branch and create a PR. |
Well, it works and... implementation is pretty straightforward. I would tag it an acceptable compromise. |
some points: there's a misunderstanding, i didn't mean that you can extend the as one of cerberus' paradigm is to be non-blocking, i don't agree that a failing normalization skips validation. the tests consider nested schemas and expected errors, perfect! :-D a diff-view for reviewing would be great. |
@funkyfuture Ah, got it. :) One more question about the non-blocking paradigm: so right now it stops validating if some "priority" rule fails, and |
to clarify, i don't think i mean the following as pseudo-code: def normalize_default(...):
if do_readonly_logic(...) == 'failed':
self.error(..., READONLY_FIELD, ...)
else:
do_default_logic(...)
def validate_readonly(...):
# don't re-evaluate if an error was already submitted by default during normalization
if READONLY_FIELD in self.document_error_tree.fetch_errors_from(self.document_path + (field,)):
return
... the aborting |
Hm, but this is not enough. You should not run |
okay, you can test whether default is defined for that field in validation as well. |
See #282 |
This allows using
default
andreadonly
on the same field. See #268 for details.Furthermore, this PR introduces a new feature called
rule_filter
to solve #268 in an (in my opinion) elegant way. I'm not sure if this feature will be ever used externally, but just in case I wrote some documentation for it. Briefly speaking, it allows to do the following: