-
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
("simple" fix)
#282
Conversation
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.
nice and tidy.
@@ -665,6 +678,12 @@ def _normalize_rename_handler(self, mapping, schema, field): | |||
mapping[new_name] = mapping[field] | |||
del mapping[field] | |||
|
|||
def __validate_readonly_fields(self, mapping, schema): | |||
for field in [x for x in schema if x in mapping and |
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.
i'd prefer a generator- over a list-comprehension here.
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.
You're right, I will change that.
# If the document was normalized (and therefore already been | ||
# checked for readonly fields), we still have to return True | ||
# if an error was filed if readonly is a priority rule. | ||
if 'readonly' in self.priority_validations: |
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.
isn't that always true? or is this different in the eve-validator?
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.
No, I did not think about Eve at all when implementing this. There is this "configuration" for priority validations, so I thought it's best to reuse it instead of hardcoding the fact. But thinking about that again it's special anyway because returning True is just something priority validations do. I will remove that check.
# checked for readonly fields), we still have to return True | ||
# if an error was filed if readonly is a priority rule. | ||
if 'readonly' in self.priority_validations: | ||
has_error = self.schema_error_tree.fetch_errors_from( |
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.
shall any (or a prior readonly) error be respected here?
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.
Just a prior readonly error on this particular field. I think it's more clean and specific when the readonly-logic just cares about it's own errors. Do you see any problems with that approach?
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.
no problem with the approach, but that would be errors.READONLY_FIELD in self.schema_error_tree...
.
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.
Are you sure? I thought the SchemaErrorTree
allows to access errors for certain rules. In fact, I just tried that and indeed only get the error for readonly
:
d = errors.DocumentErrorTree()
s = errors.SchemaErrorTree()
e = errors.ValidationError(('a'), ('a', errors.READONLY_FIELD.rule),
errors.READONLY_FIELD.code, errors.READONLY_FIELD.rule,
None, None, None)
f = errors.ValidationError(('a'), ('a', errors.MIN_VALUE.rule),
errors.MIN_VALUE.code, errors.MIN_VALUE.rule,
None, None, None)
[tree.add(error) for tree in (d, s) for error in (e, f)]
# DocumentErrorTree returns all errors for the given field.
print(d.fetch_errors_from(('a',)))
>> [ValidationError @ 0x7f7686359ed0 ( document_path=a,schema_path=('a', 'min'),code=0x42,constraint=None,value=None,info=None ), ValidationError @ 0x7f76874f2150 ( document_path=a,schema_path=('a', 'readonly'),code=0x63,constraint=None,value=None,info=None )]
# SchemaErrorTree returns just the readonly error.
print(s.fetch_errors_from(('a', 'readonly'))))
>> [ValidationError @ 0x7f76874f2150 ( document_path=a,schema_path=('a', 'readonly'),code=0x63,constraint=None,value=None,info=None )]
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.
sorry, my mistake. i confused it with the document tree. but i learned that there can be more than one iteraton in a comprehension from your example. :-)
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.
shower thought: wouldn't a query on the document error tree be safer with regards to implicit validation like from allow_unknown
?
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.
I'm not sure if an unknown field can ever be readonly
in a meaningful way. I find querying the schema tree much clearer to understand, but that's maybe just my way of thinking. If you agree I would like to keep it this way :).
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.
i have no preference here. you are right that the example case is hardly meaningful, but people come up with uses the issue tracker i'd never thought of, regularly.
my way of thinking here is: schemas can be tricky constructs and sometimes rules are evaluated that have not been adressed directly. documents on the other hand are clearer, in the document error tree you will find all errros associated with a field at exactly one node and nowhere else. it seems less error prone to me for the rather weird cases. and as mentioned above, someone will come up with something weird (which is charming).
why would you say the scheme error tree is clearer to understand? genetically they are the same.
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.
I did not mean my understanding of both trees, but the code readability at that specific location. But we don't need a deep discussion about this small issue, I am happy to go with your suggestion as well - you are way more experienced with the Cerberus codebase than I am, so I trust you with that.
some elaboration on this in the docs would be good. |
Very nice. Agree that a docs upgrade would be good. |
Yep, I will update the docs later today and update this PR so we can hopefully close this issue soon. |
97a0d85
to
c90acaf
Compare
Looks like the pypy3 test fails for some technical reason. @nicolaiarocci: Can you fix that? |
@@ -90,6 +90,14 @@ string, it points to a :doc:`custom method <customize>`. | |||
>>> v.errors | |||
{'a': ["default value for 'a' cannot be set: Circular dependencies of default setters."]} | |||
|
|||
You can even use both `default` and `readonly` on the same field. This will |
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.
don't let this bit delay this pr to be merged, but a link do the other doc on each side would be handy as amendment.
other rule names are commonly enclosed by double backticks for monospaced appearance.
is the feature/fix worthenough to extend the docs edit: examples?
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.
I will look into that. First I finally have to setup Sphinx to compile the docs locally ;).
@@ -427,6 +427,9 @@ present in the target dictionary. This is useful, for example, when receiving | |||
a payload which is to be validated before it is sent to the datastore. The field | |||
might be provided by the datastore, but should not writable. | |||
|
|||
.. versionchanged:: 1.0.2 | |||
Can be used in conjunction with `default`. |
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.
and default_setter
this issue may be of interested concerning PyPy3 on travis. the tests succeed locally. |
c90acaf
to
d675240
Compare
I temporarily removed pypy3 from CI matrix, I'll just test PRs locally until it's fixed upstream. |
Merged after rebase: 7408da5 Thanks! |
This is a careful fix for issue #268 without introducing any new features (like in #272) and without any (known) breaking changes.
For the full discussion see #272.