diff --git a/.hgtags b/.hgtags index 0ce14b51bba18c794989839bf2bb9cd55f87ff45_LmhndGFncw==..219b18bb38d8091f0a1f18d2eba9e59fb2d2aec4_LmhndGFncw== 100644 --- a/.hgtags +++ b/.hgtags @@ -13,3 +13,5 @@ 1ec96eae270f2bac3b80666e469d67d24b27874b 15.0.3.1.0 0f20c71059ad5c526588f6b8ad65fa685a8b71f5 16.0.0.0.0 a269f2a9de83b2393cee75c58f3c675232273b45 16.0.1.0.0 +da9a0fe039b65f5cfd3d5a5a60eaac2665026a91 13.0.3.2.0 +32a53dec98817ee36336896716cbacf8477a6d0a 15.0.3.2.0 diff --git a/NEWS.rst b/NEWS.rst index 0ce14b51bba18c794989839bf2bb9cd55f87ff45_TkVXUy5yc3Q=..219b18bb38d8091f0a1f18d2eba9e59fb2d2aec4_TkVXUy5yc3Q= 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -1,6 +1,17 @@ Changelog ========= +16.0.1.1.0 +---------- + +(port from 15.0.3.2.0 / 13.0.3.2.0) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Export constants from ``.base``. +Used by other modules; these exports got removed when I replaced an ``import *`` earlier. + +``jsonschema`` âž” ``fastjsonschema``. + 16.0.1.0.0 ---------- diff --git a/__init__.py b/__init__.py index 0ce14b51bba18c794989839bf2bb9cd55f87ff45_X19pbml0X18ucHk=..219b18bb38d8091f0a1f18d2eba9e59fb2d2aec4_X19pbml0X18ucHk= 100644 --- a/__init__.py +++ b/__init__.py @@ -20,6 +20,11 @@ from . import models from .base import ( + OPERATION_CREATION, + OPERATION_UPDATE, + PHASE_POSTCREATE, + PHASE_PRECREATE, + PHASE_UPDATE, Computed, Constant, ContextBuilder, diff --git a/__manifest__.py b/__manifest__.py index 0ce14b51bba18c794989839bf2bb9cd55f87ff45_X19tYW5pZmVzdF9fLnB5..219b18bb38d8091f0a1f18d2eba9e59fb2d2aec4_X19tYW5pZmVzdF9fLnB5 100644 --- a/__manifest__.py +++ b/__manifest__.py @@ -22,10 +22,10 @@ "name": "Converter", "license": "AGPL-3", "summary": "Convert odoo records to/from plain data structures.", - "version": "16.0.1.0.0", + "version": "16.0.1.1.0", "category": "Hidden", "author": "XCG Consulting", "website": "https://orbeet.io/", "depends": ["base", "mail"], "data": [], "installable": True, @@ -26,8 +26,8 @@ "category": "Hidden", "author": "XCG Consulting", "website": "https://orbeet.io/", "depends": ["base", "mail"], "data": [], "installable": True, - "external_dependencies": {"python": ["jsonschema"]}, + "external_dependencies": {"python": ["fastjsonschema"]}, } diff --git a/model.py b/model.py index 0ce14b51bba18c794989839bf2bb9cd55f87ff45_bW9kZWwucHk=..219b18bb38d8091f0a1f18d2eba9e59fb2d2aec4_bW9kZWwucHk= 100644 --- a/model.py +++ b/model.py @@ -23,8 +23,6 @@ from collections.abc import Iterable, Mapping from typing import Any, Optional -import jsonschema - from odoo import api, models from .base import ( @@ -97,7 +95,7 @@ if self.validation != VALIDATION_SKIP and self._jsonschema is not None: try: self.validator.validate(self._jsonschema, message_data) - except jsonschema.exceptions.ValidationError as exception: + except Exception as exception: _logger.warning("Validation failed", exc_info=1) if self.validation == VALIDATION_STRICT: raise exception diff --git a/pyproject.toml b/pyproject.toml index 0ce14b51bba18c794989839bf2bb9cd55f87ff45_cHlwcm9qZWN0LnRvbWw=..219b18bb38d8091f0a1f18d2eba9e59fb2d2aec4_cHlwcm9qZWN0LnRvbWw= 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,7 +13,7 @@ "Framework :: Odoo :: 16.0", "License :: OSI Approved :: GNU Affero General Public License v3" ] -dependencies = ["odoo==16.0.*", "jsonschema"] +dependencies = ["odoo==16.0.*", "fastjsonschema"] [project.optional-dependencies] doc = ["sphinx", "sphinx-odoo-autodoc"] diff --git a/validate.py b/validate.py index 0ce14b51bba18c794989839bf2bb9cd55f87ff45_dmFsaWRhdGUucHk=..219b18bb38d8091f0a1f18d2eba9e59fb2d2aec4_dmFsaWRhdGUucHk= 100644 --- a/validate.py +++ b/validate.py @@ -19,6 +19,5 @@ ############################################################################## import json -import math import os @@ -23,6 +22,6 @@ import os -import jsonschema +import fastjsonschema import odoo.addons @@ -46,5 +45,4 @@ self.repository = repository # exemple "https://annonces-legales.fr/xbus/schemas/v1/{}.schema.json" self.default_url_pattern = default_url_pattern - self.schemastore = {} self.validators = {} @@ -50,5 +48,4 @@ self.validators = {} - self.search_path = "not initialized, please call initialize()" self.initialized = False self.encoding = "UTF-8" @@ -56,6 +53,9 @@ repo_module_basepath = os.path.dirname( getattr(odoo.addons, self.repository_module_name).__file__ ) + + # Read local schema definitions. + schemas = {} schema_search_path = os.path.abspath( os.path.join(repo_module_basepath, self.repository) ) @@ -59,12 +59,10 @@ schema_search_path = os.path.abspath( os.path.join(repo_module_basepath, self.repository) ) - self.search_path = schema_search_path - - for root, _dirs, files in os.walk(self.search_path): + for root, _dirs, files in os.walk(schema_search_path): for fname in files: fpath = os.path.join(root, fname) if fpath.endswith((".json",)): with open(fpath, "r", encoding=self.encoding) as schema_fd: schema = json.load(schema_fd) if "$id" in schema: @@ -65,9 +63,18 @@ for fname in files: fpath = os.path.join(root, fname) if fpath.endswith((".json",)): with open(fpath, "r", encoding=self.encoding) as schema_fd: schema = json.load(schema_fd) if "$id" in schema: - self.schemastore[schema["$id"]] = schema + schemas[schema["$id"]] = schema + + # Prepare validators for each schema. We add an HTTPS handler that + # points back to our schema definition cache built above. + for schema_id, schema in schemas.items(): + self.validators[schema_id] = fastjsonschema.compile( + schema, + handlers={"https": lambda uri: schemas[uri]}, + use_default=False, + ) self.initialized = True @@ -72,6 +79,6 @@ self.initialized = True - def validate(self, schema_id, doc) -> None: + def validate(self, schema_id, payload) -> None: if not self.initialized: raise NotInitialized("please call the initialize() method") @@ -75,34 +82,4 @@ if not self.initialized: raise NotInitialized("please call the initialize() method") - uri = "file://{}/{}.schema.json".format(self.search_path, schema_id) - validator = self.validators.get(uri) - if validator is None: - schema = self.schemastore[self.default_url_pattern.format(schema_id)] - - resolver = jsonschema.RefResolver(uri, schema, self.schemastore) - - validator = jsonschema.Draft7Validator(schema, resolver=resolver) - self.validators[uri] = validator - - validator.validate(doc) - - -def multiple_of(validator, db, instance, schema): - """Fix rounding which fails when comparing e.g. 66.6 vs 0.01""" - - if not validator.is_type(instance, "number"): - return - - if isinstance(db, float): - quotient = instance / db - failed = not math.isclose(round(quotient), quotient) - else: - failed = instance % db - - if failed: - yield jsonschema.ValidationError("%r is not a multiple of %r" % (instance, db)) - - -# Fix rounding which fails when comparing e.g. 66.6 vs 0.01 -jsonschema.Draft7Validator.VALIDATORS["multipleOf"] = multiple_of + self.validators[self.default_url_pattern.format(schema_id)](payload)