aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/Lib/typing.py
diff options
context:
space:
mode:
authorshadchin <shadchin@yandex-team.com>2024-04-28 21:17:44 +0300
committershadchin <shadchin@yandex-team.com>2024-04-28 21:25:54 +0300
commita55d99a3eb72f90355bc146baeda18aa7eb97352 (patch)
treeb17cfed786effe8b81bba022239d6729f716fbeb /contrib/tools/python3/Lib/typing.py
parent67bf49d08acf1277eff4c336021ac22d964bb4c4 (diff)
downloadydb-a55d99a3eb72f90355bc146baeda18aa7eb97352.tar.gz
Update Python 3 to 3.12.3
7d09de7d8b99ea2be554ef0fc61276942ca9c2e1
Diffstat (limited to 'contrib/tools/python3/Lib/typing.py')
-rw-r--r--contrib/tools/python3/Lib/typing.py82
1 files changed, 52 insertions, 30 deletions
diff --git a/contrib/tools/python3/Lib/typing.py b/contrib/tools/python3/Lib/typing.py
index ffe7ce8d8a..b58c2d3064 100644
--- a/contrib/tools/python3/Lib/typing.py
+++ b/contrib/tools/python3/Lib/typing.py
@@ -314,19 +314,33 @@ def _unpack_args(args):
newargs.append(arg)
return newargs
-def _deduplicate(params):
+def _deduplicate(params, *, unhashable_fallback=False):
# Weed out strict duplicates, preserving the first of each occurrence.
- all_params = set(params)
- if len(all_params) < len(params):
- new_params = []
- for t in params:
- if t in all_params:
- new_params.append(t)
- all_params.remove(t)
- params = new_params
- assert not all_params, all_params
- return params
-
+ try:
+ return dict.fromkeys(params)
+ except TypeError:
+ if not unhashable_fallback:
+ raise
+ # Happens for cases like `Annotated[dict, {'x': IntValidator()}]`
+ return _deduplicate_unhashable(params)
+
+def _deduplicate_unhashable(unhashable_params):
+ new_unhashable = []
+ for t in unhashable_params:
+ if t not in new_unhashable:
+ new_unhashable.append(t)
+ return new_unhashable
+
+def _compare_args_orderless(first_args, second_args):
+ first_unhashable = _deduplicate_unhashable(first_args)
+ second_unhashable = _deduplicate_unhashable(second_args)
+ t = list(second_unhashable)
+ try:
+ for elem in first_unhashable:
+ t.remove(elem)
+ except ValueError:
+ return False
+ return not t
def _remove_dups_flatten(parameters):
"""Internal helper for Union creation and substitution.
@@ -341,7 +355,7 @@ def _remove_dups_flatten(parameters):
else:
params.append(p)
- return tuple(_deduplicate(params))
+ return tuple(_deduplicate(params, unhashable_fallback=True))
def _flatten_literal_params(parameters):
@@ -530,7 +544,7 @@ class Any(metaclass=_AnyMeta):
def __new__(cls, *args, **kwargs):
if cls is Any:
raise TypeError("Any cannot be instantiated")
- return super().__new__(cls, *args, **kwargs)
+ return super().__new__(cls)
@_SpecialForm
@@ -832,22 +846,25 @@ def TypeGuard(self, parameters):
2. If the return value is ``True``, the type of its argument
is the type inside ``TypeGuard``.
- For example::
+ For example::
+
+ def is_str_list(val: list[object]) -> TypeGuard[list[str]]:
+ '''Determines whether all objects in the list are strings'''
+ return all(isinstance(x, str) for x in val)
- def is_str(val: Union[str, float]):
- # "isinstance" type guard
- if isinstance(val, str):
- # Type of ``val`` is narrowed to ``str``
- ...
- else:
- # Else, type of ``val`` is narrowed to ``float``.
- ...
+ def func1(val: list[object]):
+ if is_str_list(val):
+ # Type of ``val`` is narrowed to ``list[str]``.
+ print(" ".join(val))
+ else:
+ # Type of ``val`` remains as ``list[object]``.
+ print("Not a list of strings!")
Strict type narrowing is not enforced -- ``TypeB`` need not be a narrower
form of ``TypeA`` (it can even be a wider form) and this may lead to
type-unsafe results. The main reason is to allow for things like
- narrowing ``List[object]`` to ``List[str]`` even though the latter is not
- a subtype of the former, since ``List`` is invariant. The responsibility of
+ narrowing ``list[object]`` to ``list[str]`` even though the latter is not
+ a subtype of the former, since ``list`` is invariant. The responsibility of
writing type-safe type guards is left to the user.
``TypeGuard`` also works with type variables. For more information, see
@@ -872,7 +889,7 @@ class ForwardRef(_Final, _root=True):
# If we do `def f(*args: *Ts)`, then we'll have `arg = '*Ts'`.
# Unfortunately, this isn't a valid expression on its own, so we
# do the unpacking manually.
- if arg[0] == '*':
+ if arg.startswith('*'):
arg_to_compile = f'({arg},)[0]' # E.g. (*Ts,)[0] or (*tuple[int, int],)[0]
else:
arg_to_compile = arg
@@ -1140,7 +1157,9 @@ class _BaseGenericAlias(_Final, _root=True):
result = self.__origin__(*args, **kwargs)
try:
result.__orig_class__ = self
- except AttributeError:
+ # Some objects raise TypeError (or something even more exotic)
+ # if you try to set attributes on them; we guard against that here
+ except Exception:
pass
return result
@@ -1546,7 +1565,10 @@ class _UnionGenericAlias(_NotIterable, _GenericAlias, _root=True):
def __eq__(self, other):
if not isinstance(other, (_UnionGenericAlias, types.UnionType)):
return NotImplemented
- return set(self.__args__) == set(other.__args__)
+ try: # fast path
+ return set(self.__args__) == set(other.__args__)
+ except TypeError: # not hashable, slow path
+ return _compare_args_orderless(self.__args__, other.__args__)
def __hash__(self):
return hash(frozenset(self.__args__))
@@ -3254,11 +3276,11 @@ class TextIO(IO[str]):
class _DeprecatedType(type):
def __getattribute__(cls, name):
- if name not in ("__dict__", "__module__") and name in cls.__dict__:
+ if name not in {"__dict__", "__module__", "__doc__"} and name in cls.__dict__:
warnings.warn(
f"{cls.__name__} is deprecated, import directly "
f"from typing instead. {cls.__name__} will be removed "
- "in Python 3.12.",
+ "in Python 3.13.",
DeprecationWarning,
stacklevel=2,
)