-
Notifications
You must be signed in to change notification settings - Fork 465
[order_utils.py] Feature/schema resolver cache #1317
[order_utils.py] Feature/schema resolver cache #1317
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.
I must say that my apprehension about exposing LocalRefResolver
, which I described in #1316 , still stands. It looks to me like we can achieve all the performance gains under consideration without exposing LocalRefResolver
. Again, though, I'm open to having my mind changed. Perhaps you could further describe your use case and why this is important to you?
Having said that, there are changes in this PR that I would love to see you land. Taking advantage of that cache in jsonschema
by simply calling to resolve()
instead of resolve_from_url()
is a great idea, and I appreciate the suggestion on importlib
.
Also, do be sure to run setup.py lint
in your local copy, in order to find and fix errors like those shown in the static-tests-python
test run on this PR. (You could let circleci find them for you, but fixing some will likely reveal others, in subsequent runs of other linters, so I suggest you run it locally.)
Finally, could you provide a web link to some discussion of the importlib
issue you mentioned? Perhaps a GitHub Issue or Stack Overflow answer or something like that?
Hi, @feuGeneA thanks for the response. From a performance perspective, I can see how we can still hide Aside from this, I'm building an order validator (both schema and on-chain) and, as part of this change, I wanted to take advantage of new schema IDs inside the 0x repository (in this case For some reason I am not able to access CI? if I open Circle I see Thanks! |
Okay, I myself am still getting a feel for what's "pythonic" and what isn't, and I was confusing myself. The idea I had does not make sense. What do you think about a solution like https://stackoverflow.com/a/279597/406289 ? That is, do something like
I do love the encapsulation this provides. However, if this is too anti-idiomatic, then I guess I'm okay with the module-level declaration and instantiation, but if we do that then we should definitely prefix the class and instance identifiers with an underscore, to scare away anyone wanting to import them. FYI, when I wrote Regarding your CI error, no, that's not expected. I can't tell what's wrong just from that message, but if you want to ping me ( @Gene ) on our community chat, I'd be happy to work with you to figure it out. |
Hi @feuGeneA thanks again for the lengthy response! While hiding attributes within functions aren't necessarily Pythonic, it's definitely done in some frameworks like Django. I personally like the module level instance definition pattern because it's less code and has less logic. Are we sure we don't want I made most of the changes you suggested. For some reason, I'm not getting |
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.
Making something that we need to maintain is exactly what I'm trying to avoid. 😄 I'm definitely sure that I personally don't want LocalRefResolver
to be importable externally, but I'm willing to defer to convention/idiom. Please either encapsulate within assert_valid
or rename LocalRefResolver
to _LocalRefResolver
and LOCAL_RESOLVER
to _LOCAL_RESOLVER
.
Regarding mypy
, you need to update stubs/jsonschema/__init__.pyi
to tell it the types of the base class' RefResolver.resolve()
method, which we weren't using before. I'm not sure why it's complaining about ValidationError
, as you didn't seem to change anything around that, but armed with my suggestion about resolve()
hopefully you can figure it out.
"""Gather zero_ex.* modules and doctest them.""" | ||
"""Gather zero_ex.* modules and doctest them. | ||
|
||
NOTE: we now use `importlib` instead of `imp` because `imp` is deprecated |
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 appreciate this content, but I think its too noisy for a code comment, and instead should be in a comment on the PR or in the commit message. And, I think you could just say "imp
is deprecated" and leave it at that.
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.
Though, there never was any mention of "imp
" in the code; care to clarify?
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.
Of course. So, walk_packages
returns a generator that crawls the module path. Eventually, it will yield a ModuleInfo
tuple. The first argument (what is defined as loader
in your for loop) is of type importlib.abc.FileLoader
. This loader inherits from Loader whose documentation specifies that load_module
is outdated (the reason this happens is that it uses imp
module internally).
Documentation here does suggest to use exec_module
instead but I failed in getting that to work (I tried exec_module
and create_module()
with no success). What did work is importlib.import_module
so I ended up using that. Happy to try alternatives if you prefer!
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.
Whatever works! I just want to make sure that there's some logical continuity between the code we had in place and what we're saying is deprecated.
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.
sounds great! I will remove the comment from here, and I will ensure it's documented in the PR. In that comment, instead of mentioning imp
which is internal, I'll simply specify that load_module
is deprecated so that it's clearer.
@@ -30,7 +31,8 @@ def resolve_from_url(self, url: str) -> str: | |||
|
|||
:param url: a string representing the URL of the JSON schema to fetch. | |||
:returns: a string representing the deserialized JSON schema | |||
:raises jsonschema.ValidationError: when the resource associated with `url` does not exist. | |||
:raises jsonschema.ValidationError: when the resource associated with | |||
`url` does not exist. |
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.
Reduce indent to be 4 spaces more than :raises
on the line above. Anal, yes, but this would make it consistent with the rest of the code.
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.
absolutely! it's important to keep the style consistent. Will make the change
"/ECSignature": "ec_signature_schema.json", | ||
"/signedOrderSchema": "signed_order_schema.json", | ||
"/ecSignatureParameterSchema": ( | ||
"ec_signature_parameter_schema.json" + "" |
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.
While you're in here would you mind removing this redundant string concatenation and the parenthesis and putting this all on one line?
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 a feeling it was added there by black
because it passes the max char length? I will take a look and make the change (or let you know)
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 confirm this is black
Thanks for the advice! I will proceed as you suggested. I will go with
|
71551eb
to
c5cad1a
Compare
Hi @feuGeneA I'm not sure what happened here, but I did a rebase and automagically that ended up adding a lot of people to review and it added a lot of tags. Sorry about that! I tried to revert but it looks like I'm not able to add/remove reviewers.
Let me know :) |
_LOCAL_RESOLVER._remote_cache.cache_info() # pylint: disable=W0212 | ||
) | ||
assert cache_info.currsize == 4 | ||
assert cache_info.hits == 10 |
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.
What are these magic numbers 4
and 10
? Are they coincident with our usage, or are they reflective of some implementation detail of the 3rd party jsonschemas
package? If the latter, I'm wary, as a change there would break this test.
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.
they are totally coincident to our usage. We fetched 4 unique files over 14 resolve
requests
It looks like everything is passing except the
Do you know why this is happening? |
Probably this: https://github.com/0xProject/0x-monorepo/blob/development/CONTRIBUTING.md#fix-submit-coverage-ci-failure |
…`load_module()` reloads modules even if they are already imported, causing tests to fail when run in non-deterministic ordering, so we replace it with `import_module()`
6ca73e4
to
7504675
Compare
All conflicts resolved! let me know if you need anything from me @feuGeneA |
Description
This PR is a proposed solution for #1316
Testing instructions
Types of changes
LocalRefResolver()
to the module levelLOCAL_RESOLVER
that is called byassert_valid()
resolve_from_url
I changed it toresolve
, because the latter uses a LRU cache.signedOrderSchema
to theLocalRefResolver()
IDs.importlib
causes my new test to fail sporadically. This is because the oldload_module()
will also reload modules that are already loaded. Aside from this,load_module()
is also deprecated in Python 3.4Checklist:
[WIP]
if necessary.[sol-cov] Fixed bug
.