@@ -903,6 +903,7 @@ def __init__(
903903 self ._dynamic_anchor_index : dict [tuple [str , ...], dict [str , str ]] = {}
904904 self ._recursive_anchor_index : dict [tuple [str , ...], list [str ]] = {}
905905 self ._ref_data_type_facts : dict [str , tuple [Any , bool ]] = {}
906+ self ._local_ref_path_cache : dict [Path , Path ] = {}
906907 self ._force_base_model_refs : set [str ] = set ()
907908 self ._force_base_model_generation = False
908909 self .field_keys : set [str ] = {
@@ -1994,6 +1995,12 @@ def _get_x_python_import_path(self, x_python_import: dict[str, Any]) -> str | No
19941995 raise Error (msg )
19951996 return _validate_schema_python_import_path (f"{ module } .{ type_name } " , "x-python-import" )
19961997
1998+ def _cache_ref_data_type_facts (self , resolved_ref : str , obj : JsonSchemaObject ) -> None :
1999+ self ._ref_data_type_facts [resolved_ref ] = (
2000+ obj .extras .get ("x-python-import" ),
2001+ obj .type == "null" or (self .strict_nullable and obj .nullable is True ),
2002+ )
2003+
19972004 def get_ref_data_type (self , ref : str ) -> DataType :
19982005 """Get a data type from a reference string.
19992006
@@ -2461,18 +2468,20 @@ def _deep_merge(self, dict1: dict[Any, Any], dict2: dict[Any, Any]) -> dict[Any,
24612468 result [key ] = value
24622469 return result
24632470
2464- def _load_ref_schema_object (self , ref : str ) -> JsonSchemaObject :
2465- """Load a JsonSchemaObject from a $ref using standard resolve/load pipeline."""
2466- resolved_ref = self .model_resolver .resolve_ref (ref )
2471+ def _get_ref_raw_schema (self , resolved_ref : str ) -> dict [str , YamlValue ] | YamlValue :
24672472 file_part , fragment = ([* resolved_ref .split ("#" , 1 ), "" ])[:2 ]
24682473 raw_doc = self ._get_ref_body (file_part ) if file_part else self .raw_obj
24692474
24702475 target_schema : dict [str , YamlValue ] | YamlValue = raw_doc
24712476 if fragment :
24722477 pointer = split_json_pointer (raw_doc , fragment )
24732478 target_schema = get_model_by_path (raw_doc , pointer )
2479+ return target_schema
24742480
2475- return self ._validate_schema_object (target_schema , [resolved_ref ])
2481+ def _load_ref_schema_object (self , ref : str ) -> JsonSchemaObject :
2482+ """Load a JsonSchemaObject from a $ref using standard resolve/load pipeline."""
2483+ resolved_ref = self .model_resolver .resolve_ref (ref )
2484+ return self ._validate_schema_object (self ._get_ref_raw_schema (resolved_ref ), [resolved_ref ])
24762485
24772486 def _anchor_ref_path (self , root_key : tuple [str , ...], path : list [str ]) -> str : # noqa: PLR6301
24782487 """Return the local ref path for an anchor under the current root."""
@@ -5181,9 +5190,13 @@ def _get_ref_body(self, resolved_ref: str) -> dict[str, YamlValue]:
51815190 return self ._get_ref_body_from_remote (resolved_ref )
51825191
51835192 def _resolve_local_ref_path (self , path : Path , ref : str ) -> Path :
5193+ if cached_path := self ._local_ref_path_cache .get (path ):
5194+ return cached_path
5195+
51845196 base_path = self .base_path .resolve ()
51855197 resolved_path = path .resolve ()
51865198 if resolved_path .is_relative_to (base_path ) or self .allow_remote_refs is True :
5199+ self ._local_ref_path_cache [path ] = resolved_path
51875200 return resolved_path
51885201
51895202 details = (
@@ -5506,6 +5519,7 @@ def _parse_raw_or_validated_obj(
55065519 self ._check_version_specific_features (raw , path )
55075520
55085521 obj = validated_obj if validated_obj is not None else self ._validate_schema_object (raw , path )
5522+ self ._cache_ref_data_type_facts (self .model_resolver .join_path (tuple (path )), obj )
55095523 # Build $recursiveAnchor / $dynamicAnchor indexes for this schema
55105524 self ._build_anchor_indexes (obj , path )
55115525 self .parse_obj (name , obj , path )
@@ -5953,6 +5967,7 @@ def _parse_file( # noqa: PLR0912, PLR0913, PLR0914, PLR0915
59535967 with self .root_id_context (raw ):
59545968 # parse $id before parsing $ref
59555969 root_obj = self ._validate_schema_object (raw , path_parts or ["#" ])
5970+ self ._cache_ref_data_type_facts (self .model_resolver .join_path (tuple (path_parts or ["#" ])), root_obj )
59565971 self .parse_id (root_obj , [* path_parts , "#" ] if path_parts else ["#" ])
59575972 root_key = tuple (path_parts )
59585973 if root_obj .recursiveAnchor :
@@ -5983,6 +5998,7 @@ def _parse_file( # noqa: PLR0912, PLR0913, PLR0914, PLR0915
59835998 seen_definition_metadata_paths .add (definition_path_key )
59845999 obj = self ._validate_schema_object (model , definition_path )
59856000 validated_definition_objects [definition_path_key ] = obj
6001+ self ._cache_ref_data_type_facts (self .model_resolver .join_path (tuple (definition_path )), obj )
59866002 self .parse_id (obj , definition_path )
59876003 if obj .recursiveAnchor :
59886004 ref_path = self ._anchor_ref_path (root_key , definition_path )
0 commit comments