@@ -338,6 +338,8 @@ class TypeVar(TypingMeta, metaclass=TypingMeta, _root=True):
338
338
T1 = TypeVar('T1') # Unconstrained
339
339
T2 = TypeVar('T2', t1, t2, ...) # Constrained to any of (t1, t2, ...)
340
340
341
+ (TODO: The rules below are inconsistent. See issue 62.)
342
+
341
343
For an unconstrained type variable T, isinstance(x, T) is false
342
344
for all x, and similar for issubclass(cls, T). Example::
343
345
@@ -388,9 +390,15 @@ class MyStr(str):
388
390
389
391
"""
390
392
391
- def __new__ (cls , name , * constraints ):
393
+ def __new__ (cls , name , * constraints , kind = None ):
392
394
self = super ().__new__ (cls , name , (Final ,), {}, _root = True )
395
+ if kind not in (None , 'in' , 'out' ):
396
+ raise ValueError ("kind must be 'in', 'out' or None; got %r." %
397
+ (kind ,))
398
+ if kind is not None and constraints :
399
+ raise TypeError ("kind does not combine with constraints" )
393
400
msg = "TypeVar(name, constraint, ...): constraints must be types."
401
+ self .__kind__ = kind
394
402
self .__constraints__ = tuple (_type_check (t , msg ) for t in constraints )
395
403
self .__binding__ = None
396
404
return self
@@ -399,7 +407,13 @@ def _has_type_var(self):
399
407
return True
400
408
401
409
def __repr__ (self ):
402
- return '~' + self .__name__
410
+ if self .__kind__ == 'in' :
411
+ prefix = '+'
412
+ elif self .__kind__ == 'out' :
413
+ prefix = '-'
414
+ else :
415
+ prefix = '~'
416
+ return prefix + self .__name__
403
417
404
418
def __instancecheck__ (self , instance ):
405
419
if self .__binding__ is not None :
@@ -500,6 +514,9 @@ def __exit__(self, *args):
500
514
T = TypeVar ('T' ) # Any type.
501
515
KT = TypeVar ('KT' ) # Key type.
502
516
VT = TypeVar ('VT' ) # Value type.
517
+ T_in = TypeVar ('T_in' , kind = 'in' ) # Any type, for covariant containers.
518
+ KT_in = TypeVar ('KT_in' , kind = 'in' ) # Key type, for covariant containers.
519
+ VT_in = TypeVar ('VT_in' , kind = 'in' ) # Value type, for covariant containers.
503
520
504
521
# A useful type variable with constraints. This represents string types.
505
522
# TODO: What about bytearray, memoryview?
@@ -947,9 +964,15 @@ class GenericMeta(TypingMeta, abc.ABCMeta):
947
964
# TODO: Constrain more how Generic is used; only a few
948
965
# standard patterns should be allowed.
949
966
967
+ # TODO: Use a more precise rule than matching __name__ to decide
968
+ # whether two classes are the same. Also, save the formal
969
+ # parameters. (These things are related! A solution lies in
970
+ # using origin.)
971
+
950
972
__extra__ = None
951
973
952
- def __new__ (cls , name , bases , namespace , parameters = None , extra = None ):
974
+ def __new__ (cls , name , bases , namespace ,
975
+ parameters = None , origin = None , extra = None ):
953
976
if parameters is None :
954
977
# Extract parameters from direct base classes. Only
955
978
# direct bases are considered and only those that are
@@ -983,6 +1006,7 @@ def __new__(cls, name, bases, namespace, parameters=None, extra=None):
983
1006
self .__extra__ = extra
984
1007
# Else __extra__ is inherited, eventually from the
985
1008
# (meta-)class default above.
1009
+ self .__origin__ = origin
986
1010
return self
987
1011
988
1012
def _has_type_var (self ):
@@ -1035,14 +1059,49 @@ def __getitem__(self, params):
1035
1059
1036
1060
return self .__class__ (self .__name__ , self .__bases__ ,
1037
1061
dict (self .__dict__ ),
1038
- parameters = params , extra = self .__extra__ )
1062
+ parameters = params ,
1063
+ origin = self ,
1064
+ extra = self .__extra__ )
1039
1065
1040
1066
def __subclasscheck__ (self , cls ):
1041
1067
if cls is Any :
1042
1068
return True
1069
+ if isinstance (cls , GenericMeta ):
1070
+ # For a class C(Generic[T]) where T is co-variant,
1071
+ # C[X] is a subclass of C[Y] iff X is a subclass of Y.
1072
+ origin = self .__origin__
1073
+ if origin is not None and origin is cls .__origin__ :
1074
+ assert len (self .__parameters__ ) == len (origin .__parameters__ )
1075
+ assert len (cls .__parameters__ ) == len (origin .__parameters__ )
1076
+ for p_self , p_cls , p_origin in zip (self .__parameters__ ,
1077
+ cls .__parameters__ ,
1078
+ origin .__parameters__ ):
1079
+ if isinstance (p_origin , TypeVar ):
1080
+ if p_origin .__kind__ is None :
1081
+ # Invariant -- p_cls and p_self must equal.
1082
+ if p_self != p_cls :
1083
+ break
1084
+ elif p_origin .__kind__ == 'in' :
1085
+ # Covariant -- p_cls must be a subclass of p_self.
1086
+ if not issubclass (p_cls , p_self ):
1087
+ break
1088
+ elif p_origin .__kind__ == 'out' :
1089
+ # Contravariant. I think it's the opposite. :-)
1090
+ if not issubclass (p_self , p_cls ):
1091
+ break
1092
+ else :
1093
+ assert False , p_origin .__kind__
1094
+ else :
1095
+ # If the origin's parameter is not a typevar,
1096
+ # insist on invariance.
1097
+ if p_self != p_cls :
1098
+ break
1099
+ else :
1100
+ return True
1101
+ # If we break out of the loop, the superclass gets a chance.
1043
1102
if super ().__subclasscheck__ (cls ):
1044
1103
return True
1045
- if self .__extra__ is None :
1104
+ if self .__extra__ is None or isinstance ( cls , GenericMeta ) :
1046
1105
return False
1047
1106
return issubclass (cls , self .__extra__ )
1048
1107
@@ -1233,18 +1292,14 @@ def overload(func):
1233
1292
raise RuntimeError ("Overloading is only supported in library stubs" )
1234
1293
1235
1294
1236
- class _Protocol ( Generic ):
1237
- """Internal base class for protocol classes .
1295
+ class _ProtocolMeta ( GenericMeta ):
1296
+ """Internal metaclass for _Protocol .
1238
1297
1239
- This implements a simple-minded structural isinstance check
1240
- (similar but more general than the one-offs in collections.abc
1241
- such as Hashable).
1298
+ This exists so _Protocol classes can be generic without deriving
1299
+ from Generic.
1242
1300
"""
1243
1301
1244
- _is_protocol = True
1245
-
1246
- @classmethod
1247
- def __subclasshook__ (self , cls ):
1302
+ def __subclasscheck__ (self , cls ):
1248
1303
if not self ._is_protocol :
1249
1304
# No structural checks since this isn't a protocol.
1250
1305
return NotImplemented
@@ -1258,10 +1313,9 @@ def __subclasshook__(self, cls):
1258
1313
1259
1314
for attr in attrs :
1260
1315
if not any (attr in d .__dict__ for d in cls .__mro__ ):
1261
- return NotImplemented
1316
+ return False
1262
1317
return True
1263
1318
1264
- @classmethod
1265
1319
def _get_protocol_attrs (self ):
1266
1320
# Get all Protocol base classes.
1267
1321
protocol_bases = []
@@ -1284,19 +1338,32 @@ def _get_protocol_attrs(self):
1284
1338
attr != '_is_protocol' and
1285
1339
attr != '__dict__' and
1286
1340
attr != '_get_protocol_attrs' and
1341
+ attr != '__parameters__' and
1342
+ attr != '__origin__' and
1287
1343
attr != '__module__' ):
1288
1344
attrs .add (attr )
1289
1345
1290
1346
return attrs
1291
1347
1292
1348
1349
+ class _Protocol (metaclass = _ProtocolMeta ):
1350
+ """Internal base class for protocol classes.
1351
+
1352
+ This implements a simple-minded structural isinstance check
1353
+ (similar but more general than the one-offs in collections.abc
1354
+ such as Hashable).
1355
+ """
1356
+
1357
+ _is_protocol = True
1358
+
1359
+
1293
1360
# Various ABCs mimicking those in collections.abc.
1294
1361
# A few are simply re-exported for completeness.
1295
1362
1296
1363
Hashable = collections_abc .Hashable # Not generic.
1297
1364
1298
1365
1299
- class Iterable (Generic [T ], extra = collections_abc .Iterable ):
1366
+ class Iterable (Generic [T_in ], extra = collections_abc .Iterable ):
1300
1367
pass
1301
1368
1302
1369
@@ -1356,7 +1423,7 @@ def __reversed__(self) -> 'Iterator[T]':
1356
1423
Sized = collections_abc .Sized # Not generic.
1357
1424
1358
1425
1359
- class Container (Generic [T ], extra = collections_abc .Container ):
1426
+ class Container (Generic [T_in ], extra = collections_abc .Container ):
1360
1427
pass
1361
1428
1362
1429
@@ -1367,24 +1434,24 @@ class AbstractSet(Sized, Iterable, Container, extra=collections_abc.Set):
1367
1434
pass
1368
1435
1369
1436
1370
- class MutableSet (AbstractSet , extra = collections_abc .MutableSet ):
1437
+ class MutableSet (AbstractSet [ T ] , extra = collections_abc .MutableSet ):
1371
1438
pass
1372
1439
1373
1440
1374
- class Mapping (Sized , Iterable [KT ], Container [KT ], Generic [KT , VT ],
1441
+ class Mapping (Sized , Iterable [KT_in ], Container [KT_in ], Generic [KT_in , VT_in ],
1375
1442
extra = collections_abc .Mapping ):
1376
1443
pass
1377
1444
1378
1445
1379
- class MutableMapping (Mapping , extra = collections_abc .MutableMapping ):
1446
+ class MutableMapping (Mapping [ KT , VT ] , extra = collections_abc .MutableMapping ):
1380
1447
pass
1381
1448
1382
1449
1383
1450
class Sequence (Sized , Iterable , Container , extra = collections_abc .Sequence ):
1384
1451
pass
1385
1452
1386
1453
1387
- class MutableSequence (Sequence , extra = collections_abc .MutableSequence ):
1454
+ class MutableSequence (Sequence [ T ] , extra = collections_abc .MutableSequence ):
1388
1455
pass
1389
1456
1390
1457
@@ -1459,7 +1526,8 @@ class KeysView(MappingView, Set[KT], extra=collections_abc.KeysView):
1459
1526
1460
1527
1461
1528
# TODO: Enable Set[Tuple[KT, VT]] instead of Generic[KT, VT].
1462
- class ItemsView (MappingView , Generic [KT , VT ], extra = collections_abc .ItemsView ):
1529
+ class ItemsView (MappingView , Generic [KT_in , VT_in ],
1530
+ extra = collections_abc .ItemsView ):
1463
1531
pass
1464
1532
1465
1533
0 commit comments