def _validate(self, value, resolve=True, **opts): String.validate(value, **opts) if resolve: try: resolve_uri(value) return True except Exception as er: return False
def _is_subclass(class_id): if class_id == scls_id: return True for e in resolve_uri(class_id).get('extends', []): if _is_subclass(e): return True return False
def _get_cname_id_cached(self, cname, current_ns): #ns = ChainMap(self._registry, NamespaceManager.builder_namespaces(), NamespaceManager.available_namespaces()) # iterate on namespace sorted from the longest to get the most qualified #ns_names = sorted([k for k, uri in ns.items() if cname.startswith(k+'.') or k == cname], reverse=True) #ns_name = ns_names[0] if ns_names else '' #ns_uri = ns[ns_name] ns_name, ns_uri = self._find_ns_by_cname(cname) fragment_cname = cname[len(ns_name):] if ns_name else cname cns = fragment_cname.split('.') if cns and not cns[0]: cns = cns[1:] fragment_parts = [] if fragment_cname: if ns_uri in UriResolver._doc_store: import dpath.util doc = resolve_uri(ns_uri) glob = ''.join(['/*/' + c for c in cns]) glob = glob.strip('/') for x in dpath.util.search(doc, glob, yielded=True): return ns_uri + ('#/' if '#' not in ns_uri else '/') + x[0] # not found: if namespace uri corresponds to local namespace, compute a path #if ns_uri != ns.get(''): # raise InvalidValue(f"impossible to find '{cname}' in {ns_uri}.") for c in cns[:-1]: fragment_parts += ['$defs', c] fragment_parts += (['properties', cns[-1]] if len(cns) > 2 and cns[-2][0].isupper() and cns[-1][0].islower() else ['$defs', cns[-1]]) ns_uri = ns_uri or self._find_ns_by_cname(current_ns)[1] return '/'.join([ns_uri + ('#' if '#' not in ns_uri else '')] + fragment_parts)
def build(self, id, schema=None, bases=(), attrs=None): from .namespace_manager import NamespaceManager from ..protocols import TypeProtocol, ObjectProtocol, ArrayProtocol, TypeProxy from ..types.constants import _True, _False if self.contains(id): return self.get(id) if id in self._on_construction: return TypeProxy.build(id) #return TypeProxy.build(id)() if schema is None: schema = resolve_uri(id) if schema is True: return _True() if schema is False: return _False() attrs = attrs or {} self._on_construction[id] = (schema, bases, attrs) if '$ref' in schema: schema = schema.copy() ref = schema.pop('$ref') cls = self.load(scope(ref, id)) if schema: cls = cls.extend_type(id, **schema) elif 'object' in schema.get('type', ''): cls = ObjectProtocol.build(id, schema, bases, attrs) elif 'array' in schema.get('type', ''): cls = ArrayProtocol.build(id, schema, bases, attrs) else: cls = TypeProtocol.build(id, schema, bases, attrs)() self._on_construction.pop(id) self._registry[id] = cls NamespaceManager.register_ns(id) return cls
def _schema_mro(id, sch): for e in sch.get('extends', []): i = scope(e, id) s = resolve_uri(i) yield i, s for m in _schema_mro(i, s): yield m
def get_cname_definitions(self, cname): ns_uri = self.get_id_cname(cname) doc = resolve_uri(ns_uri) defs = {} for tag in ['$defs', 'definitions']: for k, v in doc.get(tag, {}).items(): defs[f'{cname}.{k}'] = f'{ns_uri}/{tag}/{k}' return defs
def schema_mro(id, schema=None): schema = schema or resolve_uri(id) def _schema_mro(id, sch): for e in sch.get('extends', []): i = scope(e, id) s = resolve_uri(i) yield i, s for m in _schema_mro(i, s): yield m return OrderedDict(_schema_mro(id, schema))
def __new__(cls, clsname, bases, attrs): from ..managers.type_builder import type_builder schema = attrs.get('_schema', {}) id = attrs.get('_id') if not schema and id: schema = resolve_uri(id) elif bases: schema['extends'] = [b._id for b in bases if hasattr(b, '_id')] schema.setdefault('type', 'object') id = id or clsname # remove previous entry in registry if id in type_builder._registry: del type_builder._registry[id] attrs['_clsname'] = clsname return type_builder.build(id, schema, bases, attrs=attrs)
def expand(self, id, schema=None): def scope_refs(id, schema): def _scope_refs(coll, key, level): if isinstance(coll, Mapping): v = coll[key] if isinstance(v, Mapping) and '$ref' in v: v['$ref'] = scope(v['$ref'], id) apply_through_collection(schema, _scope_refs) schema = copy.deepcopy(schema or resolve_uri(id)) mro = self.schema_mro(id, schema) scope_refs(id, schema) for i, s in mro.items(): scope_refs(i, s) extends = list(mro.keys()) required = list(schema.get('required', [])) + sum( [list(s.get('required', [])) for s in mro.values()], []) read_only = list(schema.get('readOnly', [])) + sum( [list(s.get('readOnly', [])) for s in mro.values()], []) not_serialized = list(schema.get('notSerialized', [])) + sum( [list(s.get('notSerialized', [])) for s in mro.values()], []) properties = ReadOnlyChainMap( schema.get('properties', {}), *[s.get('properties', {}) for i, s in mro.items()]) pattern_properties = ReadOnlyChainMap( schema.get('patternProperties', {}), *[s.get('patternProperties', {}) for s in mro.values()]) if extends: schema['extends'] = extends if required: schema['required'] = set(required) if read_only: schema['readOnly'] = set(read_only) if not_serialized: schema['notSerialized'] = set(not_serialized) if properties: schema['properties'] = properties if pattern_properties: schema['patternProperties'] = pattern_properties return schema
def _resolve(self, value): return resolve_uri(value)