Skip to content

Commit 5fe058e

Browse files
committed
Merge branch 'main' into pep646-tuple
2 parents eda60f9 + 54ab9ad commit 5fe058e

File tree

10 files changed

+130
-166
lines changed

10 files changed

+130
-166
lines changed

Doc/library/sqlite3.rst

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ SQLite for internal data storage. It's also possible to prototype an
1717
application using SQLite and then port the code to a larger database such as
1818
PostgreSQL or Oracle.
1919

20-
The sqlite3 module was written by Gerhard Häring. It provides a SQL interface
20+
The sqlite3 module was written by Gerhard Häring. It provides an SQL interface
2121
compliant with the DB-API 2.0 specification described by :pep:`249`, and
2222
requires SQLite 3.7.15 or newer.
2323

@@ -373,7 +373,7 @@ Connection Objects
373373

374374
.. class:: Connection
375375

376-
A SQLite database connection has the following attributes and methods:
376+
An SQLite database connection has the following attributes and methods:
377377

378378
.. attribute:: isolation_level
379379

@@ -589,7 +589,7 @@ Connection Objects
589589

590590
.. method:: load_extension(path)
591591

592-
This routine loads a SQLite extension from a shared library. You have to
592+
This routine loads an SQLite extension from a shared library. You have to
593593
enable extension loading with :meth:`enable_load_extension` before you can
594594
use this routine.
595595

@@ -665,7 +665,7 @@ Connection Objects
665665

666666
.. method:: backup(target, *, pages=-1, progress=None, name="main", sleep=0.250)
667667

668-
This method makes a backup of a SQLite database even while it's being accessed
668+
This method makes a backup of an SQLite database even while it's being accessed
669669
by other clients, or concurrently by the same connection. The copy will be
670670
written into the mandatory argument *target*, that must be another
671671
:class:`Connection` instance.
@@ -1068,7 +1068,7 @@ This is how SQLite types are converted to Python types by default:
10681068
+-------------+----------------------------------------------+
10691069

10701070
The type system of the :mod:`sqlite3` module is extensible in two ways: you can
1071-
store additional Python types in a SQLite database via object adaptation, and
1071+
store additional Python types in an SQLite database via object adaptation, and
10721072
you can let the :mod:`sqlite3` module convert SQLite types to different Python
10731073
types via converters.
10741074

Include/internal/pycore_global_strings.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ struct _Py_global_strings {
199199
STRUCT_FOR_ID(__subclasshook__)
200200
STRUCT_FOR_ID(__truediv__)
201201
STRUCT_FOR_ID(__trunc__)
202+
STRUCT_FOR_ID(__typing_subst__)
202203
STRUCT_FOR_ID(__warningregistry__)
203204
STRUCT_FOR_ID(__weakref__)
204205
STRUCT_FOR_ID(__xor__)

Include/internal/pycore_runtime_init.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,7 @@ extern "C" {
822822
INIT_ID(__subclasshook__), \
823823
INIT_ID(__truediv__), \
824824
INIT_ID(__trunc__), \
825+
INIT_ID(__typing_subst__), \
825826
INIT_ID(__warningregistry__), \
826827
INIT_ID(__weakref__), \
827828
INIT_ID(__xor__), \

Lib/_collections_abc.py

Lines changed: 9 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -430,25 +430,13 @@ def __new__(cls, origin, args):
430430
raise TypeError(
431431
"Callable must be used as Callable[[arg, ...], result].")
432432
t_args, t_result = args
433-
if isinstance(t_args, list):
433+
if isinstance(t_args, (tuple, list)):
434434
args = (*t_args, t_result)
435435
elif not _is_param_expr(t_args):
436436
raise TypeError(f"Expected a list of types, an ellipsis, "
437437
f"ParamSpec, or Concatenate. Got {t_args}")
438438
return super().__new__(cls, origin, args)
439439

440-
@property
441-
def __parameters__(self):
442-
params = []
443-
for arg in self.__args__:
444-
# Looks like a genericalias
445-
if hasattr(arg, "__parameters__") and isinstance(arg.__parameters__, tuple):
446-
params.extend(arg.__parameters__)
447-
else:
448-
if _is_typevarlike(arg):
449-
params.append(arg)
450-
return tuple(dict.fromkeys(params))
451-
452440
def __repr__(self):
453441
if len(self.__args__) == 2 and _is_param_expr(self.__args__[0]):
454442
return super().__repr__()
@@ -468,57 +456,24 @@ def __getitem__(self, item):
468456
# code is copied from typing's _GenericAlias and the builtin
469457
# types.GenericAlias.
470458

471-
# A special case in PEP 612 where if X = Callable[P, int],
472-
# then X[int, str] == X[[int, str]].
473-
param_len = len(self.__parameters__)
474-
if param_len == 0:
475-
raise TypeError(f'{self} is not a generic class')
476459
if not isinstance(item, tuple):
477460
item = (item,)
478-
if (param_len == 1 and _is_param_expr(self.__parameters__[0])
461+
# A special case in PEP 612 where if X = Callable[P, int],
462+
# then X[int, str] == X[[int, str]].
463+
if (len(self.__parameters__) == 1
464+
and _is_param_expr(self.__parameters__[0])
479465
and item and not _is_param_expr(item[0])):
480-
item = (list(item),)
481-
item_len = len(item)
482-
if item_len != param_len:
483-
raise TypeError(f'Too {"many" if item_len > param_len else "few"}'
484-
f' arguments for {self};'
485-
f' actual {item_len}, expected {param_len}')
486-
subst = dict(zip(self.__parameters__, item))
487-
new_args = []
488-
for arg in self.__args__:
489-
if _is_typevarlike(arg):
490-
if _is_param_expr(arg):
491-
arg = subst[arg]
492-
if not _is_param_expr(arg):
493-
raise TypeError(f"Expected a list of types, an ellipsis, "
494-
f"ParamSpec, or Concatenate. Got {arg}")
495-
else:
496-
arg = subst[arg]
497-
# Looks like a GenericAlias
498-
elif hasattr(arg, '__parameters__') and isinstance(arg.__parameters__, tuple):
499-
subparams = arg.__parameters__
500-
if subparams:
501-
subargs = tuple(subst[x] for x in subparams)
502-
arg = arg[subargs]
503-
if isinstance(arg, tuple):
504-
new_args.extend(arg)
505-
else:
506-
new_args.append(arg)
466+
item = (item,)
467+
468+
new_args = super().__getitem__(item).__args__
507469

508470
# args[0] occurs due to things like Z[[int, str, bool]] from PEP 612
509-
if not isinstance(new_args[0], list):
471+
if not isinstance(new_args[0], (tuple, list)):
510472
t_result = new_args[-1]
511473
t_args = new_args[:-1]
512474
new_args = (t_args, t_result)
513475
return _CallableGenericAlias(Callable, tuple(new_args))
514476

515-
516-
def _is_typevarlike(arg):
517-
obj = type(arg)
518-
# looks like a TypeVar/ParamSpec
519-
return (obj.__module__ == 'typing'
520-
and obj.__name__ in {'ParamSpec', 'TypeVar'})
521-
522477
def _is_param_expr(obj):
523478
"""Checks if obj matches either a list of types, ``...``, ``ParamSpec`` or
524479
``_ConcatenateGenericAlias`` from typing.py

Lib/test/test_typing.py

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -360,10 +360,31 @@ def test_no_bivariant(self):
360360
with self.assertRaises(ValueError):
361361
TypeVar('T', covariant=True, contravariant=True)
362362

363+
def test_var_substitution(self):
364+
T = TypeVar('T')
365+
subst = T.__typing_subst__
366+
self.assertIs(subst(int), int)
367+
self.assertEqual(subst(list[int]), list[int])
368+
self.assertEqual(subst(List[int]), List[int])
369+
self.assertEqual(subst(List), List)
370+
self.assertIs(subst(Any), Any)
371+
self.assertIs(subst(None), type(None))
372+
self.assertIs(subst(T), T)
373+
self.assertEqual(subst(int|str), int|str)
374+
self.assertEqual(subst(Union[int, str]), Union[int, str])
375+
363376
def test_bad_var_substitution(self):
364377
T = TypeVar('T')
365-
for arg in (), (int, str):
378+
P = ParamSpec("P")
379+
bad_args = (
380+
42, ..., [int], (), (int, str), Union,
381+
Generic, Generic[T], Protocol, Protocol[T],
382+
Final, Final[int], ClassVar, ClassVar[int],
383+
)
384+
for arg in bad_args:
366385
with self.subTest(arg=arg):
386+
with self.assertRaises(TypeError):
387+
T.__typing_subst__(arg)
367388
with self.assertRaises(TypeError):
368389
List[T][arg]
369390
with self.assertRaises(TypeError):
@@ -1110,8 +1131,7 @@ def test_var_substitution(self):
11101131
C2 = Callable[[KT, T], VT]
11111132
C3 = Callable[..., T]
11121133
self.assertEqual(C1[str], Callable[[int, str], str])
1113-
if Callable is typing.Callable:
1114-
self.assertEqual(C1[None], Callable[[int, type(None)], type(None)])
1134+
self.assertEqual(C1[None], Callable[[int, type(None)], type(None)])
11151135
self.assertEqual(C2[int, float, str], Callable[[int, float], str])
11161136
self.assertEqual(C3[int], Callable[..., int])
11171137
self.assertEqual(C3[NoReturn], Callable[..., NoReturn])
@@ -2696,7 +2716,10 @@ def test_all_repr_eq_any(self):
26962716
for obj in objs:
26972717
self.assertNotEqual(repr(obj), '')
26982718
self.assertEqual(obj, obj)
2699-
if getattr(obj, '__parameters__', None) and len(obj.__parameters__) == 1:
2719+
if (getattr(obj, '__parameters__', None)
2720+
and not isinstance(obj, typing.TypeVar)
2721+
and isinstance(obj.__parameters__, tuple)
2722+
and len(obj.__parameters__) == 1):
27002723
self.assertEqual(obj[Any].__args__, (Any,))
27012724
if isinstance(obj, type):
27022725
for base in obj.__mro__:
@@ -5748,33 +5771,30 @@ class X(Generic[P, P2]):
57485771
self.assertEqual(G1.__args__, ((int, str), (bytes,)))
57495772
self.assertEqual(G2.__args__, ((int,), (str, bytes)))
57505773

5774+
def test_var_substitution(self):
5775+
T = TypeVar("T")
5776+
P = ParamSpec("P")
5777+
subst = P.__typing_subst__
5778+
self.assertEqual(subst((int, str)), (int, str))
5779+
self.assertEqual(subst([int, str]), (int, str))
5780+
self.assertEqual(subst([None]), (type(None),))
5781+
self.assertIs(subst(...), ...)
5782+
self.assertIs(subst(P), P)
5783+
self.assertEqual(subst(Concatenate[int, P]), Concatenate[int, P])
5784+
57515785
def test_bad_var_substitution(self):
57525786
T = TypeVar('T')
57535787
P = ParamSpec('P')
57545788
bad_args = (42, int, None, T, int|str, Union[int, str])
57555789
for arg in bad_args:
57565790
with self.subTest(arg=arg):
5791+
with self.assertRaises(TypeError):
5792+
P.__typing_subst__(arg)
57575793
with self.assertRaises(TypeError):
57585794
typing.Callable[P, T][arg, str]
57595795
with self.assertRaises(TypeError):
57605796
collections.abc.Callable[P, T][arg, str]
57615797

5762-
def test_no_paramspec_in__parameters__(self):
5763-
# ParamSpec should not be found in __parameters__
5764-
# of generics. Usages outside Callable, Concatenate
5765-
# and Generic are invalid.
5766-
T = TypeVar("T")
5767-
P = ParamSpec("P")
5768-
self.assertNotIn(P, List[P].__parameters__)
5769-
self.assertIn(T, Tuple[T, P].__parameters__)
5770-
5771-
# Test for consistency with builtin generics.
5772-
self.assertNotIn(P, list[P].__parameters__)
5773-
self.assertIn(T, tuple[T, P].__parameters__)
5774-
5775-
self.assertNotIn(P, (list[P] | int).__parameters__)
5776-
self.assertIn(T, (tuple[T, P] | int).__parameters__)
5777-
57785798
def test_paramspec_in_nested_generics(self):
57795799
# Although ParamSpec should not be found in __parameters__ of most
57805800
# generics, they probably should be found when nested in

0 commit comments

Comments
 (0)