comparison data_schema/__init__.py @ 28:db3491e1b590

Allow to customize the loading of the schema dict
author Franz Glasner <fzglas.hg@dom66.de>
date Sat, 08 Jul 2023 13:51:20 +0200
parents fd2a40c3d87b
children 68286d27f27d
comparison
equal deleted inserted replaced
27:88ee7d1cc0bb 28:db3491e1b590
35 import re 35 import re
36 import urllib.parse 36 import urllib.parse
37 37
38 import rfc3986 38 import rfc3986
39 39
40 import configmix.yaml 40 try:
41 from configmix.yaml import load as default_schema_loader
42 except ImportError:
43 default_schema_loader = None
41 44
42 from .util import get_data_stream 45 from .util import get_data_stream
43 46
44 47
45 def NC_(ctx, msg): 48 def NC_(ctx, msg):
231 pass 234 pass
232 235
233 236
234 ValidationSettings = collections.namedtuple( 237 ValidationSettings = collections.namedtuple(
235 "ValidationSettings", 238 "ValidationSettings",
236 ["skip_keys", "break_on_keynames_problems"]) 239 ["skip_keys", "break_on_keynames_problems", "schema_loader"])
237 240
238 241
239 class _Schema(dict): 242 class _Schema(dict):
240 243
241 __slots__ = ("parent", "is_sub_root", "_schema_cache") 244 __slots__ = ("parent", "is_sub_root", "_schema_cache")
323 return "<_Schema " + super().__str__() + ">" 326 return "<_Schema " + super().__str__() + ">"
324 327
325 def __repr__(self): 328 def __repr__(self):
326 return "<_Schema " + super().__repr__() + ">" 329 return "<_Schema " + super().__repr__() + ">"
327 330
328 def get_cached_schema(self, key, load_if_needed=True): 331 def get_cached_schema(self, key, load_if_needed=True, schema_loader=None):
329 root = self.ROOT 332 root = self.ROOT
330 s = root._schema_cache.get(key, None) 333 s = root._schema_cache.get(key, None)
331 if s is None and load_if_needed: 334 if s is None and load_if_needed:
335 if schema_loader is None:
336 raise SchemaError("no schema loader available")
332 with get_data_stream(key) as schemastream: 337 with get_data_stream(key) as schemastream:
333 # load schema a new `$self' (i.e. sub-root is True) 338 # load schema a new `$self' (i.e. sub-root is True)
334 s = _Schema(self, True, configmix.yaml.load(schemastream)) 339 s = _Schema(self, True, schema_loader(schemastream))
335 root._schema_cache[key] = s 340 root._schema_cache[key] = s
336 return s 341 return s
337 342
338 def add_cached_schema(self, key, schema): 343 def add_cached_schema(self, key, schema):
339 r = self.ROOT 344 r = self.ROOT
494 499
495 """ 500 """
496 settings = { 501 settings = {
497 "skip_keys": None, 502 "skip_keys": None,
498 "break_on_keynames_problems": True, 503 "break_on_keynames_problems": True,
504 "schema_loader": default_schema_loader
499 } 505 }
500 settings.update(kwds) 506 settings.update(kwds)
501 if not isinstance(schema, _Schema): 507 if not isinstance(schema, _Schema):
502 if not isinstance(schema, dict): 508 if not isinstance(schema, dict):
503 raise SchemaError("Schema must be a dict-alike." 509 raise SchemaError("Schema must be a dict-alike."
1397 if not uri.path or (uri.path == SCHEMA_PATH_SELF): 1403 if not uri.path or (uri.path == SCHEMA_PATH_SELF):
1398 s = schema.SELF 1404 s = schema.SELF
1399 elif uri.path == SCHEMA_PATH_ROOT: 1405 elif uri.path == SCHEMA_PATH_ROOT:
1400 s = schema.ROOT 1406 s = schema.ROOT
1401 else: 1407 else:
1402 s = schema.get_cached_schema(uri.path, load_if_needed=True) 1408 s = schema.get_cached_schema(
1409 uri.path,
1410 load_if_needed=True,
1411 schema_loader=context.settings.schema_loader)
1403 if uri.fragment is None: 1412 if uri.fragment is None:
1404 raise SchemaError("fragment required in reference") 1413 raise SchemaError("fragment required in reference")
1405 1414
1406 if not uri.fragment.startswith('/'): 1415 if not uri.fragment.startswith('/'):
1407 raise SchemaError("references to parts of a schema must be absolute (begin with `/')") 1416 raise SchemaError("references to parts of a schema must be absolute (begin with `/')")