-
Notifications
You must be signed in to change notification settings - Fork 33
Add strain field to subject metadata and corresponding test case #1716
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
Changes from all commits
3dee789
e371001
4026e84
b0b07c6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,6 +27,7 @@ | |
| "genotype", | ||
| "sex", | ||
| "species", | ||
| "strain", | ||
| "subject_id", | ||
| ) | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,5 +1,6 @@ | ||||||||||||||||||||
| from __future__ import annotations | ||||||||||||||||||||
|
|
||||||||||||||||||||
| from dandischema.models import DandiBaseModel | ||||||||||||||||||||
| from pytest import Config, Item, Parser | ||||||||||||||||||||
|
|
||||||||||||||||||||
| from .tests.fixtures import * # noqa: F401, F403 # lgtm [py/polluting-import] | ||||||||||||||||||||
|
|
@@ -28,9 +29,7 @@ | |||||||||||||||||||
| "ai_generated", | ||||||||||||||||||||
| ] | ||||||||||||||||||||
| for marker in markers: | ||||||||||||||||||||
| config.addinivalue_line( | ||||||||||||||||||||
| "markers", marker | ||||||||||||||||||||
| ) | ||||||||||||||||||||
| config.addinivalue_line("markers", marker) | ||||||||||||||||||||
|
|
||||||||||||||||||||
|
|
||||||||||||||||||||
| def pytest_collection_modifyitems(items: list[Item], config: Config) -> None: | ||||||||||||||||||||
|
|
@@ -46,3 +45,24 @@ | |||||||||||||||||||
| deselected_items.append(item) | ||||||||||||||||||||
| config.hook.pytest_deselected(items=deselected_items) | ||||||||||||||||||||
| items[:] = selected_items | ||||||||||||||||||||
|
|
||||||||||||||||||||
|
|
||||||||||||||||||||
| def pytest_assertrepr_compare(op, left, right): | ||||||||||||||||||||
| """Custom comparison representation for your classes.""" | ||||||||||||||||||||
| if ( | ||||||||||||||||||||
| isinstance(left, DandiBaseModel) | ||||||||||||||||||||
| and isinstance(right, DandiBaseModel) | ||||||||||||||||||||
| and op == "==" | ||||||||||||||||||||
| ): | ||||||||||||||||||||
| ldict, rdict = dict(left), dict(right) | ||||||||||||||||||||
| if ldict == rdict: | ||||||||||||||||||||
| return [ | ||||||||||||||||||||
| "dict representations of models are equal, but values aren't!", | ||||||||||||||||||||
| f"Left: {left!r}", | ||||||||||||||||||||
| f"Right: {right!r}", | ||||||||||||||||||||
| ] | ||||||||||||||||||||
| else: | ||||||||||||||||||||
| # Rely on pytest just "recursing" into interpreting the dict fails | ||||||||||||||||||||
| # TODO: could be further improved by account for ANY values etc | ||||||||||||||||||||
| assert ldict == rdict # for easier comprehension of diffs | ||||||||||||||||||||
|
||||||||||||||||||||
| @@ -64,5 +64,4 @@ | ||
| else: | ||
| # Rely on pytest just "recursing" into interpreting the dict fails | ||
| # TODO: could be further improved by account for ANY values etc | ||
| assert ldict == rdict # for easier comprehension of diffs | ||
| return 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.
Instead of
ldict, rdict = dict(left), dict(right)
we can
ldict, rdict = left.model_dump(), right.model_dump()
so we can get all the sub-models recursively converted to dictionaries.
Beyond that, we can use library like https://zepworks.com/deepdiff/8.6.1/diff.html and https://github.com/xlwings/jsondiff to locate the exact difference in the nested structure.
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.
@candleindark if you see how to improve this -- the goal is to make it easier to understand diffs on our pydantic models. If you see how -- please try your idea first before suggesting since there could be "gotchas" ;-)
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.
Instead of
we can
so we can get all the sub-models recursively converted to dictionaries.
Beyond that, we can use library like https://zepworks.com/deepdiff/8.6.1/diff.html and https://github.com/xlwings/jsondiff to locate the exact difference in the nested structure.
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 believe model dump doesn't work here, hence I suggested to try first ;-)
Uh oh!
There was an error while loading. Please reload this page.
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.
After digging into it a bit more. Here is what I found.
The reason
model_dump()doesn't work is because the right operant is not a validDandiBaseModelinstance and contains values such asanys.ANY_AWARE_DATETIME, which is not serializable Pydantic by default. The right operate is constructed by calling themodel_constructmethod to bypass the validation.One way to allow a meaningful comparison illustration of the two operants is to make
model_dump()to work on the right operant as well. This can be accomplished by using a custom serializer to thedandischema.models.DandiBaseModel. This custom serializer is depicted in the simplified model below.Custom serializer example
Once this custom serializer is added to
dandischema.models.DandiBaseModel. We can change the line https://github.com/dandi/dandi-cli/blob/28d954c7620f80d96fc749dcd39410acdbbd10d9/tox.ini#L16C5-L16C46to
coverage run -m pytest -vv {posargs} dandito see the detailed difference in the structure of the objects.
Note This solution involves changing the
dandi-schemarepo, including adding theanysdependency to thedandischemapacakge.@yarikoptic Please let me know if you want to proceed with this solution. I will send a PR if yes.
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.
Since you did this analysis already, I think it might well be with adding. But I wonder if we could avoid need too depend on
any. Presumably we can get instance only ifanyalready installed, at we can easily just try to import any and if gains to import just not to do that check.