diff --git a/Doc/c-api/arg.rst b/Doc/c-api/arg.rst index 58456a36b96c151..a878b20c928ea3d 100644 --- a/Doc/c-api/arg.rst +++ b/Doc/c-api/arg.rst @@ -399,13 +399,18 @@ inside nested parentheses. They are: their default value --- when an optional argument is not specified, :c:func:`PyArg_ParseTuple` does not touch the contents of the corresponding C variable(s). + For example, the format string ``"OO|OO"`` corresponds to the Python + signature ``f(a, b, c=None, d=None)``. ``$`` :c:func:`PyArg_ParseTupleAndKeywords` only: Indicates that the remaining arguments in the Python argument list are - keyword-only. Currently, all keyword-only arguments must also be optional - arguments, so ``|`` must always be specified before ``$`` in the format - string. + keyword-only. + They are optional if ``|`` was specified before ``$``, and required otherwise. + ``|`` cannot be specified after ``$``. + For example, the format string ``"O|O$O"`` corresponds to the Python + signature ``f(a, b=None, *, c=None)``, + and the format string ``"OO$OO"`` corresponds to ``f(a, b, *, c, d)``. .. versionadded:: 3.3 diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 619d0cb2fe541a6..2875303fb156197 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -9806,6 +9806,7 @@ def test_order_in_union(self): for args in itertools.permutations(get_args(expr1)): with self.subTest(args=args): self.assertEqual(expr1, reduce(operator.or_, args)) + self.assertEqual(expr1, Union[args]) expr2 = Union[Annotated[int, 1], str, Annotated[str, {}], int] for args in itertools.permutations(get_args(expr2)): diff --git a/Lib/typing.py b/Lib/typing.py index 809c0ff88607a59..b56ba954ad38be1 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -494,7 +494,7 @@ def _eval_type(t, globalns, localns, type_params, *, recursive_guard=frozenset() if isinstance(t, GenericAlias): return _rebuild_generic_alias(t, ev_args) if isinstance(t, Union): - return functools.reduce(operator.or_, ev_args) + return Union[ev_args] else: return t.copy_with(ev_args) return t @@ -2546,7 +2546,7 @@ def _strip_annotations(t): stripped_args = tuple(_strip_annotations(a) for a in t.__args__) if stripped_args == t.__args__: return t - return functools.reduce(operator.or_, stripped_args) + return Union[stripped_args] return t