in HowTo/gRPC/Linux/OpenAI/LangChain/PyServer/venv/Lib/pydantic/v1/fields.py [0:0]
def _type_analysis(self) -> None: # noqa: C901 (ignore complexity)
# typing interface is horrible, we have to do some ugly checks
if lenient_issubclass(self.type_, JsonWrapper):
self.type_ = self.type_.inner_type
self.parse_json = True
elif lenient_issubclass(self.type_, Json):
self.type_ = Any
self.parse_json = True
elif isinstance(self.type_, TypeVar):
if self.type_.__bound__:
self.type_ = self.type_.__bound__
elif self.type_.__constraints__:
self.type_ = Union[self.type_.__constraints__]
else:
self.type_ = Any
elif is_new_type(self.type_):
self.type_ = new_type_supertype(self.type_)
if self.type_ is Any or self.type_ is object:
if self.required is Undefined:
self.required = False
self.allow_none = True
return
elif self.type_ is Pattern or self.type_ is re.Pattern:
# python 3.7 only, Pattern is a typing object but without sub fields
return
elif is_literal_type(self.type_):
return
elif is_typeddict(self.type_):
return
if is_finalvar(self.type_):
self.final = True
if self.type_ is Final:
self.type_ = Any
else:
self.type_ = get_args(self.type_)[0]
self._type_analysis()
return
origin = get_origin(self.type_)
if origin is Annotated or is_typeddict_special(origin):
self.type_ = get_args(self.type_)[0]
self._type_analysis()
return
if self.discriminator_key is not None and not is_union(origin):
raise TypeError('`discriminator` can only be used with `Union` type with more than one variant')
# add extra check for `collections.abc.Hashable` for python 3.10+ where origin is not `None`
if origin is None or origin is CollectionsHashable:
# field is not "typing" object eg. Union, Dict, List etc.
# allow None for virtual superclasses of NoneType, e.g. Hashable
if isinstance(self.type_, type) and isinstance(None, self.type_):
self.allow_none = True
return
elif origin is Callable:
return
elif is_union(origin):
types_ = []
for type_ in get_args(self.type_):
if is_none_type(type_) or type_ is Any or type_ is object:
if self.required is Undefined:
self.required = False
self.allow_none = True
if is_none_type(type_):
continue
types_.append(type_)
if len(types_) == 1:
# Optional[]
self.type_ = types_[0]
# this is the one case where the "outer type" isn't just the original type
self.outer_type_ = self.type_
# re-run to correctly interpret the new self.type_
self._type_analysis()
else:
self.sub_fields = [self._create_sub_type(t, f'{self.name}_{display_as_type(t)}') for t in types_]
if self.discriminator_key is not None:
self.prepare_discriminated_union_sub_fields()
return
elif issubclass(origin, Tuple): # type: ignore
# origin == Tuple without item type
args = get_args(self.type_)
if not args: # plain tuple
self.type_ = Any
self.shape = SHAPE_TUPLE_ELLIPSIS
elif len(args) == 2 and args[1] is Ellipsis: # e.g. Tuple[int, ...]
self.type_ = args[0]
self.shape = SHAPE_TUPLE_ELLIPSIS
self.sub_fields = [self._create_sub_type(args[0], f'{self.name}_0')]
elif args == ((),): # Tuple[()] means empty tuple
self.shape = SHAPE_TUPLE
self.type_ = Any
self.sub_fields = []
else:
self.shape = SHAPE_TUPLE
self.sub_fields = [self._create_sub_type(t, f'{self.name}_{i}') for i, t in enumerate(args)]
return
elif issubclass(origin, List):
# Create self validators
get_validators = getattr(self.type_, '__get_validators__', None)
if get_validators:
self.class_validators.update(
{f'list_{i}': Validator(validator, pre=True) for i, validator in enumerate(get_validators())}
)
self.type_ = get_args(self.type_)[0]
self.shape = SHAPE_LIST
elif issubclass(origin, Set):
# Create self validators
get_validators = getattr(self.type_, '__get_validators__', None)
if get_validators:
self.class_validators.update(
{f'set_{i}': Validator(validator, pre=True) for i, validator in enumerate(get_validators())}
)
self.type_ = get_args(self.type_)[0]
self.shape = SHAPE_SET
elif issubclass(origin, FrozenSet):
# Create self validators
get_validators = getattr(self.type_, '__get_validators__', None)
if get_validators:
self.class_validators.update(
{f'frozenset_{i}': Validator(validator, pre=True) for i, validator in enumerate(get_validators())}
)
self.type_ = get_args(self.type_)[0]
self.shape = SHAPE_FROZENSET
elif issubclass(origin, Deque):
self.type_ = get_args(self.type_)[0]
self.shape = SHAPE_DEQUE
elif issubclass(origin, Sequence):
self.type_ = get_args(self.type_)[0]
self.shape = SHAPE_SEQUENCE
# priority to most common mapping: dict
elif origin is dict or origin is Dict:
self.key_field = self._create_sub_type(get_args(self.type_)[0], 'key_' + self.name, for_keys=True)
self.type_ = get_args(self.type_)[1]
self.shape = SHAPE_DICT
elif issubclass(origin, DefaultDict):
self.key_field = self._create_sub_type(get_args(self.type_)[0], 'key_' + self.name, for_keys=True)
self.type_ = get_args(self.type_)[1]
self.shape = SHAPE_DEFAULTDICT
elif issubclass(origin, Counter):
self.key_field = self._create_sub_type(get_args(self.type_)[0], 'key_' + self.name, for_keys=True)
self.type_ = int
self.shape = SHAPE_COUNTER
elif issubclass(origin, Mapping):
self.key_field = self._create_sub_type(get_args(self.type_)[0], 'key_' + self.name, for_keys=True)
self.type_ = get_args(self.type_)[1]
self.shape = SHAPE_MAPPING
# Equality check as almost everything inherits form Iterable, including str
# check for Iterable and CollectionsIterable, as it could receive one even when declared with the other
elif origin in {Iterable, CollectionsIterable}:
self.type_ = get_args(self.type_)[0]
self.shape = SHAPE_ITERABLE
self.sub_fields = [self._create_sub_type(self.type_, f'{self.name}_type')]
elif issubclass(origin, Type): # type: ignore
return
elif hasattr(origin, '__get_validators__') or self.model_config.arbitrary_types_allowed:
# Is a Pydantic-compatible generic that handles itself
# or we have arbitrary_types_allowed = True
self.shape = SHAPE_GENERIC
self.sub_fields = [self._create_sub_type(t, f'{self.name}_{i}') for i, t in enumerate(get_args(self.type_))]
self.type_ = origin
return
else:
raise TypeError(f'Fields of type "{origin}" are not supported.')
# type_ has been refined eg. as the type of a List and sub_fields needs to be populated
self.sub_fields = [self._create_sub_type(self.type_, '_' + self.name)]