def visit_conversion( self, tp: AnyType, conversion: Optional[Any], dynamic: bool, next_conversion: Optional[AnyConversion] = None, ): ref_types = [] if not dynamic: for ref_tp in self.resolve_conversion(tp): ref_types.append(ref_tp) if self._incr_ref(get_type_name(ref_tp).json_schema, ref_tp): return if not is_hashable(tp): return super().visit_conversion(tp, conversion, dynamic, next_conversion) # 2 because the first type encountered of the recursive cycle can have no ref # (see test_recursive_by_conversion_schema) if self._rec_guard[(tp, self._conversions)] > 2: raise TypeError(f"Recursive type {tp} need a ref") self._rec_guard[(tp, self._conversions)] += 1 try: super().visit_conversion(tp, conversion, dynamic, next_conversion) except Unsupported: for ref_tp in ref_types: self.refs.pop(get_type_name(ref_tp).json_schema, ...) # type: ignore finally: self._rec_guard[(tp, self._conversions)] -= 1
def generic(self, cls: AnyType) -> JsonSchema: origin = get_origin(cls) if is_hashable(origin) and self.is_extra_conversions(origin): self._schema = None else: self._merge_schema(get_schema(origin)) return super().generic(cls)
def visit(self, tp: AnyType) -> Result: if not is_hashable(tp): return super().visit(tp) cache_key = (tp, self._conversions, self._cache_key()) if cache_key in self._visit_cache: return self._visit_cache[cache_key] result = None def lazy_result(): assert result is not None return result self._visit_cache[cache_key] = self._recursive_result(lazy_result) try: result = super().visit(tp) finally: del self._visit_cache[cache_key] return result
def visit_with_schema( self, cls: AnyType, ref: Optional[str], schema: Optional[Schema]) -> Thunk[graphql.GraphQLType]: if self.is_id(cls): return graphql.GraphQLNonNull(graphql.GraphQLID) if is_hashable(cls) and not self.is_extra_conversions(cls): ref, schema = ref or get_ref(cls), merge_schema( get_schema(cls), schema) else: schema, ref = None, None ref_save, schema_save, non_null_save = self._ref, self._schema, self._non_null self._ref, self._schema, self._non_null = ref, schema, True try: result = super().visit(cls) non_null = self._non_null return lambda: exec_thunk(result, non_null=non_null) except MissingRef: raise TypeError(f"Missing ref for type {cls}") finally: self._ref, self._schema = ref_save, schema_save self._non_null = non_null_save
def visit_with_schema(self, cls: AnyType, schema: Optional[Schema]) -> JsonSchema: schema_save = self._schema if not is_hashable(cls): self._schema = schema elif self.is_extra_conversions(cls): self._schema = None else: self._schema = schema ref = get_ref(cls) if ref in self.refs: if self._ignore_first_ref: self._ignore_first_ref = False else: assert isinstance(ref, str) return self._ref_schema(ref) self._merge_schema(get_schema(cls)) try: return super().visit(cls) finally: self._schema = schema_save
def visit_conversion( self, tp: AnyType, conversion: Any, dynamic: bool, next_conversion: Optional[AnyConversion] = None, ) -> Sequence[AnyType]: if conversion is not None and self._skip_conversion: return [] if dynamic else [tp] self._skip_conversion = False results: Sequence[AnyType] = [] if not is_hashable(tp): with suppress(NotImplementedError, Unsupported): results = super().visit_conversion(tp, conversion, dynamic, next_conversion) elif (tp, conversion) not in self._rec_guard: self._rec_guard.add((tp, conversion)) with suppress(NotImplementedError, Unsupported): results = super().visit_conversion(tp, conversion, dynamic, next_conversion) self._rec_guard.remove((tp, conversion)) if not dynamic and (conversion is not None or not results): results = [tp, *results] return results
def visit(self, cls: AnyType): if (not is_hashable(cls) or self.is_extra_conversions(cls) or not self._incr_ref(get_ref(cls), cls)): super().visit(cls)