def _dive(self, ref: str, path: Path, visited_refs: ty.Optional[VisitedRefs] = None, ref_resolver: ty.Optional[RefResolver] = None, registry: ty.Optional[Registry] = None, **context: ty.Any) -> ty.Any: visited_refs = visited_refs or set() assert ref_resolver is not None assert registry is not None try: with ref_resolver.resolving(ref) as target: target_path = Path(ref_resolver.resolution_scope) if target_path in visited_refs: raise RecursiveReferenceError() result = registry.get(target_path) if result is Bad: raise SchemaError( Error(path, self.messages['bad_reference'])) elif result is not None: return result proxy = ObjectProxy(Dummy) registry[target_path] = proxy visited_refs.add(target_path) try: result = self._deeper(target, target_path, visited_refs=visited_refs, ref_resolver=ref_resolver, registry=registry, **context) except SchemaError as e: registry[target_path] = Bad raise SchemaError( Error(path, self.messages['bad_reference']), *e.errors) except RecursiveReferenceError: registry[target_path] = Bad raise SchemaError( Error(path, self.messages['recursive_reference'])) else: proxy.__wrapped__ = weakref.proxy(result) registry[target_path] = result finally: visited_refs.discard(target_path) return result except RefResolutionError: raise SchemaError( Error(path, self.messages['unresolvable_reference']))
def _entry(self, value: ty.Any, path: Path, visited_refs: ty.Optional[VisitedRefs] = None, registry: ty.Optional[Registry] = None, **context: ty.Any) -> ty.Any: ref = self._get_ref(value) if ref is not None: return self._dive(ref, path, visited_refs=visited_refs, registry=registry, **context) else: assert registry is not None result = registry.get(path) if result is Bad: pass elif result is not None: return result proxy = ObjectProxy(Dummy) registry[path] = proxy try: result = self.subtype.convert(value, path, registry=registry, **context) except SchemaError: registry[path] = Bad raise else: proxy.__wrapped__ = weakref.proxy(result) registry[path] = result return result