From a1d4aa66bc6b3de041ec6e4eb4fe40383945510b Mon Sep 17 00:00:00 2001 From: Daniel Pyrathon Date: Fri, 30 Nov 2018 09:59:37 -0800 Subject: feat(order_utils.py): schema resolver cache (#1317) * Implemented basic functionality for using cache layer of LocalRefResolver * Use `importlib` instead of `imp`, since it's been deprecated. Legacy `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()` --- .../src/zero_ex/json_schemas/__init__.py | 81 +++++++++++++--------- 1 file changed, 47 insertions(+), 34 deletions(-) (limited to 'python-packages/order_utils/src/zero_ex/json_schemas/__init__.py') diff --git a/python-packages/order_utils/src/zero_ex/json_schemas/__init__.py b/python-packages/order_utils/src/zero_ex/json_schemas/__init__.py index 2a1728b8a..a76a2fa3b 100644 --- a/python-packages/order_utils/src/zero_ex/json_schemas/__init__.py +++ b/python-packages/order_utils/src/zero_ex/json_schemas/__init__.py @@ -8,6 +8,51 @@ from pkg_resources import resource_string import jsonschema +class _LocalRefResolver(jsonschema.RefResolver): + """Resolve package-local JSON schema id's.""" + + def __init__(self): + """Initialize a new instance.""" + self.ref_to_file = { + "/addressSchema": "address_schema.json", + "/hexSchema": "hex_schema.json", + "/orderSchema": "order_schema.json", + "/wholeNumberSchema": "whole_number_schema.json", + "/ECSignature": "ec_signature_schema.json", + "/signedOrderSchema": "signed_order_schema.json", + "/ecSignatureParameterSchema": ( + "ec_signature_parameter_schema.json" + "" + ), + } + jsonschema.RefResolver.__init__(self, "", "") + + def resolve_from_url(self, url: str) -> str: + """Resolve the given URL. + + :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. + """ + ref = url.replace("file://", "") + if ref in self.ref_to_file: + return json.loads( + resource_string( + "zero_ex.json_schemas", f"schemas/{self.ref_to_file[ref]}" + ) + ) + raise jsonschema.ValidationError( + f"Unknown ref '{ref}'. " + + f"Known refs: {list(self.ref_to_file.keys())}." + ) + + +# Instantiate the `_LocalRefResolver()` only once so that `assert_valid()` can +# perform multiple schema validations without reading from disk the schema +# every time. +_LOCAL_RESOLVER = _LocalRefResolver() + + def assert_valid(data: Mapping, schema_id: str) -> None: """Validate the given `data` against the specified `schema`. @@ -24,38 +69,6 @@ def assert_valid(data: Mapping, schema_id: str) -> None: ... ) """ # noqa - class LocalRefResolver(jsonschema.RefResolver): - """Resolve package-local JSON schema id's.""" - - def __init__(self): - self.ref_to_file = { - "/addressSchema": "address_schema.json", - "/hexSchema": "hex_schema.json", - "/orderSchema": "order_schema.json", - "/wholeNumberSchema": "whole_number_schema.json", - "/ECSignature": "ec_signature_schema.json", - "/ecSignatureParameterSchema": ( - "ec_signature_parameter_schema.json" + "" - ), - } - jsonschema.RefResolver.__init__(self, "", "") - - def resolve_from_url(self, url): - """Resolve the given URL.""" - ref = url.replace("file://", "") - if ref in self.ref_to_file: - return json.loads( - resource_string( - "zero_ex.json_schemas", - f"schemas/{self.ref_to_file[ref]}", - ) - ) - raise jsonschema.ValidationError( - f"Unknown ref '{ref}'. " - + f"Known refs: {list(self.ref_to_file.keys())}." - ) - resolver = LocalRefResolver() - jsonschema.validate( - data, resolver.resolve_from_url(schema_id), resolver=resolver - ) + _, schema = _LOCAL_RESOLVER.resolve(schema_id) + jsonschema.validate(data, schema, resolver=_LOCAL_RESOLVER) -- cgit v1.2.3