1- from collections import namedtuple
2- from typing import Any , Callable , Dict , Optional
1+ """Shared builder utilities and type helpers."""
32
4- from ..errors import ParserError
3+ from collections .abc import Callable
4+ from dataclasses import dataclass
5+ from typing import Any
56
6- PropertyMeta = namedtuple ( 'PropertyMeta' , [ 'cast' , 'name' ])
7+ from openapi_parser . errors import ParserError
78
89
9- def extract_typed_props (data : dict , attrs_map : Dict [str , PropertyMeta ]) -> Dict [str , Any ]:
10- """Extract properties from the dictionary with type-casting using passed mapping
10+ @dataclass
11+ class PropertyMeta :
12+ """Property metadata for type-casting extraction."""
13+
14+ name : str
15+ cast : Callable [..., Any ] | None = None
16+
17+
18+ def extract_typed_props (
19+ data : dict [str , Any ],
20+ attrs_map : dict [str , PropertyMeta ],
21+ ) -> dict [str , Any ]:
22+ """Extract properties from the dictionary with type-casting using passed mapping.
1123
1224 Args:
1325 data (dict): Original dictionary to process
@@ -17,13 +29,17 @@ def extract_typed_props(data: dict, attrs_map: Dict[str, PropertyMeta]) -> Dict[
1729 Dict[str, Any]: Dictionary with type-casted values
1830 """
1931
20- def cast_value (name : str , value : Any , type_cast_func : Optional [Callable ]) -> Any :
32+ def cast_value (
33+ name : str ,
34+ value : Any ,
35+ type_cast_func : Callable [..., Any ] | None ,
36+ ) -> Any :
2137 try :
22- return type_cast_func (value ) \
23- if type_cast_func is not None \
24- else value
38+ return type_cast_func (value ) if type_cast_func is not None else value
2539 except ValueError :
26- raise ParserError (f"Invalid value for '{ name } ' property, got '{ value } '" )
40+ raise ParserError (
41+ f"Invalid value for '{ name } ' property, got '{ value } '"
42+ ) from None
2743
2844 custom_attrs = {
2945 attr_name : cast_value (attr_info .name , data [attr_info .name ], attr_info .cast )
@@ -34,8 +50,8 @@ def cast_value(name: str, value: Any, type_cast_func: Optional[Callable]) -> Any
3450 return custom_attrs
3551
3652
37- def merge_schema (original : dict , other : dict ) -> dict :
38- """Merge two schema dictionaries into single dict
53+ def merge_schema (original : dict [ str , Any ], other : dict [ str , Any ] ) -> dict [ str , Any ] :
54+ """Merge two schema dictionaries into single dict.
3955
4056 Args:
4157 original (dict): Source schema dictionary
@@ -49,30 +65,35 @@ def merge_schema(original: dict, other: dict) -> dict:
4965 for key , value in other .items ():
5066 if key not in source :
5167 source [key ] = value
52- else :
53- if isinstance (value , list ):
68+ elif isinstance ( value , list ) :
69+ if isinstance (source [ key ] , list ):
5470 source [key ].extend (value )
55- elif isinstance (value , dict ):
71+ else :
72+ source [key ] = value
73+ elif isinstance (value , dict ):
74+ if isinstance (source [key ], dict ):
5675 source [key ] = merge_schema (source [key ], value )
5776 else :
5877 source [key ] = value
78+ else :
79+ source [key ] = value
5980
6081 return source
6182
6283
63- def extract_extension_attributes (schema : dict ) -> dict :
64- """Extract custom 'x-*' attributes from schema dictionary
84+ def extract_extension_attributes (schema : dict [ str , Any ] ) -> dict [ str , Any ] :
85+ """Extract custom 'x-*' attributes from schema dictionary.
6586
6687 Args:
6788 schema (dict): Schema dictionary
6889
6990 Returns:
7091 dict: Dictionary with parsed attributes w/o 'x-' prefix
7192 """
72- extension_key_format = 'x-'
93+ extension_key_format = "x-"
7394
74- extensions_dict : dict = {
75- key .replace (extension_key_format , '' ).replace ('-' , '_' ): value
95+ extensions_dict : dict [ str , Any ] = {
96+ key .replace (extension_key_format , "" ).replace ("-" , "_" ): value
7697 for key , value in schema .items ()
7798 if key .startswith (extension_key_format )
7899 }
0 commit comments