diff --git a/pydantic_settings/sources.py b/pydantic_settings/sources.py index cfbbac08..c8a198d1 100644 --- a/pydantic_settings/sources.py +++ b/pydantic_settings/sources.py @@ -1996,7 +1996,7 @@ def _metavar_format_recurse(self, obj: Any) -> str: return '...' elif isinstance(obj, Representation): return repr(obj) - elif isinstance(obj, typing_extensions.TypeAliasType): + elif isinstance(obj, typing.ForwardRef) or _is_type_alias_type(obj): return str(obj) if not isinstance(obj, (typing_base, WithArgsTypes, type)): @@ -2009,9 +2009,12 @@ def _metavar_format_recurse(self, obj: Any) -> str: elif lenient_issubclass(obj, Enum): return self._metavar_format_choices([val.name for val in obj]) elif isinstance(obj, WithArgsTypes): + if hasattr(obj, '__qualname__'): + obj_qualname = obj.__qualname__ + else: + obj_qualname = str(obj).replace('typing.', '').replace('typing_extensions.', '').split('[')[0] return self._metavar_format_choices( - list(map(self._metavar_format_recurse, self._get_modified_args(obj))), - obj_qualname=obj.__qualname__ if hasattr(obj, '__qualname__') else str(obj), + list(map(self._metavar_format_recurse, self._get_modified_args(obj))), obj_qualname=obj_qualname ) elif obj is type(None): return self.cli_parse_none_str @@ -2432,3 +2435,17 @@ def _get_alias_names( def _is_function(obj: Any) -> bool: return isinstance(obj, (FunctionType, BuiltinFunctionType)) + + +# _TYPE_ALIAS_TYPES is copied from `pydantic._internal._typing_extra`. +_TYPE_ALIAS_TYPES: tuple[type[typing_extensions.TypeAliasType], ...] = (typing_extensions.TypeAliasType,) +if sys.version_info >= (3, 12): + _TYPE_ALIAS_TYPES = (*_TYPE_ALIAS_TYPES, typing.TypeAliasType) + + +def _is_type_alias_type(tp: Any, /) -> typing_extensions.TypeIs[typing_extensions.TypeAliasType]: + """ + Return whether the provided argument is an instance of `TypeAliasType`. + Copied from `pydantic._internal._typing_extra`. + """ + return isinstance(tp, _TYPE_ALIAS_TYPES)