8000 Follow up for #283 (response to comments) including change in Union[X… · python/typing@185df0a · GitHub
[go: up one dir, main page]

Skip to content

Commit 185df0a

Browse files
ilevkivskyigvanrossum
authored andcommitted
Follow up for #283 (response to comments) including change in Union[X, Any] (#288)
1 parent 83d4b71 commit 185df0a

File tree

4 files changed

+49
-58
lines changed

4 files changed

+49
-58
lines changed

python2/test_typing.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -201,10 +201,13 @@ def test_subclass_error(self):
201201
def test_union_any(self):
202202
u = Union[Any]
203203
self.assertEqual(u, Any)
204-
u = Union[int, Any]
205-
self.assertEqual(u, Any)
206-
u = Union[Any, int]
207-
self.assertEqual(u, Any)
204+
u1 = Union[int, Any]
205+
u2 = Union[Any, int]
206+
u3 = Union[Any, object]
207+
self.assertEqual(u1, u2)
208+
self.assertNotEqual(u1, Any)
209+
self.assertNotEqual(u2, Any)
210+
self.assertNotEqual(u3, Any)
208211

209212
def test_union_object(self):
210213
u = Union[object]
@@ -214,12 +217,6 @@ def test_union_object(self):
214217
u = Union[object, int]
215218
self.assertEqual(u, object)
216219

217-
def test_union_any_object(self):
218-
u = Union[object, Any]
219-
self.assertEqual(u, Any)
220-
u = Union[Any, object]
221-
self.assertEqual(u, Any)
222-
223220
def test_unordered(self):
224221
u1 = Union[int, float]
225222
u2 = Union[float, int]

python2/typing.py

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ def __new__(cls, *args, **kwds):
149149
isinstance(args[1], tuple)):
150150
# Close enough.
151151
raise TypeError("Cannot subclass %r" % cls)
152-
return object.__new__(cls)
152+
return super(_TypingBase, cls).__new__(cls)
153153

154154
# Things that are not classes also need these.
155155
def _eval_type(self, globalns, localns):
@@ -168,7 +168,11 @@ def __call__(self, *args, **kwds):
168168

169169

170170
class _FinalTypingBase(_TypingBase):
171-
"""Mix-in class to prevent instantiation."""
171+
"""Mix-in class to prevent instantiation.
172+
173+
Prevents instantiation unless _root=True is given in class call.
174+
It is used to create pseudo-singleton instances Any, Union, Tuple, etc.
175+
"""
172176

173177
__slots__ = ()
174178

@@ -256,7 +260,7 @@ def __init__(self, name, type_var, impl_type, type_checker):
256260
assert isinstance(name, basestring), repr(name)
257261
assert isinstance(impl_type, type), repr(impl_type)
258262
assert not isinstance(impl_type, TypingMeta), repr(impl_type)
259-
assert isinstance(type_var, (type, _TypingBase))
263+
assert isinstance(type_var, (type, _TypingBase)), repr(type_var)
260264
self.name = name
261265
self.type_var = type_var
262266
self.impl_type = impl_type
@@ -427,9 +431,13 @@ def __new__(cls, name, bases, namespace):
427431
class _Any(_FinalTypingBase):
428432
"""Special type indicating an unconstrained type.
429433
430-
- Any object is an instance of Any.
431-
- Any class is a subclass of Any.
432-
- As a special case, Any and object are subclasses of each other.
434+
- Any is compatible with every type.
435+
- Any assumed to have all methods.
436+
- All values assumed to be instances of Any.
437+
438+
Note that all the above statements are true from the point of view of
439+
static type checkers. At runtime, Any should not be used with instance
440+
or class checks.
433441
"""
434442
__metaclass__ = AnyMeta
435443
__slots__ = ()
@@ -598,16 +606,10 @@ class Manager(Employee): pass
598606
Union[Manager, int, Employee] == Union[int, Employee]
599607
Union[Employee, Manager] == Employee
600608
601-
- Corollary: if Any is present it is the sole survivor, e.g.::
602-
603-
Union[int, Any] == Any
604-
605609
- Similar for object::
606610
607611
Union[int, object] == object
608612
609-
- To cut a tie: Union[object, Any] == Union[Any, object] == Any.
610-
611613
- You cannot subclass or instantiate a union.
612614
613615
- You cannot write Union[X][Y] (what would it mean?).
@@ -646,14 +648,11 @@ def __new__(cls, parameters=None, *args, **kwds):
646648
assert not all_params, all_params
647649
# Weed out subclasses.
648650
# E.g. Union[int, Employee, Manager] == Union[int, Employee].
649-
# If Any or object is present it will be the sole survivor.
650-
# If both Any and object are present, Any wins.
651-
# Never discard type variables, except against Any.
651+
# If object is present it will be sole survivor among proper classes.
652+
# Never discard type variables.
652653
# (In particular, Union[str, AnyStr] != AnyStr.)
653654
all_params = set(params)
654655
for t1 in params:
655-
if t1 is Any:
656-
return Any
657656
if not isinstance(t1, type):
658657
continue
659658
if any(isinstance(t2, type) and issubclass(t1, t2)
@@ -726,7 +725,7 @@ def __new__(cls, name, bases, namespace):
726725
class _Optional(_FinalTypingBase):
727726
"""Optional type.
728727
729-
Optional[X] is equivalent to Union[X, type(None)].
728+
Optional[X] is equivalent to Union[X, None].
730729
"""
731730

732731
__metaclass__ = OptionalMeta

src/test_typing.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -202,10 +202,13 @@ def test_subclass_error(self):
202202
def test_union_any(self):
203203
u = Union[Any]
204204
self.assertEqual(u, Any)
205-
u = Union[int, Any]
206-
self.assertEqual(u, Any)
207-
u = Union[Any, int]
208-
self.assertEqual(u, Any)
205+
u1 = Union[int, Any]
206+
u2 = Union[Any, int]
207+
u3 = Union[Any, object]
208+
self.assertEqual(u1, u2)
209+
self.assertNotEqual(u1, Any)
210+
self.assertNotEqual(u2, Any)
211+
self.assertNotEqual(u3, Any)
209212

210213
def test_union_object(self):
211214
u = Union[object]
@@ -215,12 +218,6 @@ def test_union_object(self):
215218
u = Union[object, int]
216219
self.assertEqual(u, object)
217220

218-
def test_union_any_object(self):
219-
u = Union[object, Any]
220-
self.assertEqual(u, Any)
221-
u = Union[Any, object]
222-
self.assertEqual(u, Any)
223-
224221
def test_unordered(self):
225222
u1 = Union[int, float]
226223
u2 = Union[float, int]

src/typing.py

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,6 @@ class _TypingBase(metaclass=TypingMeta, _root=True):
143143

144144
__slots__ = ()
145145

146-
147146
def __init__(self, *args, **kwds):
148147
pass
149148

@@ -158,7 +157,7 @@ def __new__(cls, *args, **kwds):
158157
isinstance(args[1], tuple)):
159158
# Close enough.
160159
raise TypeError("Cannot subclass %r" % cls)
161-
return object.__new__(cls)
160+
return super().__new__(cls)
162161

163162
# Things that are not classes also need these.
164163
def _eval_type(self, globalns, localns):
@@ -177,7 +176,11 @@ def __call__(self, *args, **kwds):
177176

178177

179178
class _FinalTypingBase(_TypingBase, _root=True):
180-
"""Mix-in class to prevent instantiation."""
179+
"""Mix-in class to prevent instantiation.
180+
181+
Prevents instantiation unless _root=True is given in class call.
182+
It is used to create pseudo-singleton instances Any, Union, Tuple, etc.
183+
"""
181184

182185
__slots__ = ()
183186

@@ -273,7 +276,7 @@ def __init__(self, name, type_var, impl_type, type_checker):
273276
assert isinstance(name, str), repr(name)
274277
assert isinstance(impl_type, type), repr(impl_type)
275278
assert not isinstance(impl_type, TypingMeta), repr(impl_type)
276-
assert isinstance(type_var, (type, _TypingBase))
279+
assert isinstance(type_var, (type, _TypingBase)), repr(type_var)
277280
self.name = name
278281
self.type_var = type_var
279282
self.impl_type = impl_type
@@ -375,9 +378,13 @@ def _type_repr(obj):
375378
class _Any(_FinalTypingBase, _root=True):
376379
"""Special type indicating an unconstrained type.
377380
378-
- Any object is an instance of Any.
379-
- Any class is a subclass of Any.
380-
- As a special case, Any and object are subclasses of each other.
381+
- Any is compatible with every type.
382+
- Any assumed to have all methods.
383+
- All values assumed to be instances of Any.
384+
385+
Note that all the above statements are true from the point of view of
386+
static type checkers. At runtime, Any should not be used with instance
387+
or class checks.
381388
"""
382389

383390
__slots__ = ()
@@ -502,7 +509,7 @@ def inner(*args, **kwds):
502509
try:
503510
return cached(*args, **kwds)
504511
except TypeError:
505-
pass # Do not duplicate real errors.
512+
pass # All real errors (not unhashable args) are raised below.
506513
return func(*args, **kwds)
507514
return inner
508515

@@ -542,16 +549,10 @@ class Manager(Employee): pass
542549
Union[Manager, int, Employee] == Union[int, Employee]
543550
Union[Employee, Manager] == Employee
544551
545-
- Corollary: if Any is present it is the sole survivor, e.g.::
546-
547-
Union[int, Any] == Any
548-
549552
- Similar for object::
550553
551554
Union[int, object] == object
552555
553-
- To cut a tie: Union[object, Any] == Union[Any, object] == Any.
554-
555556
- You cannot subclass or instantiate a union.
556557
557558
- You cannot write Union[X][Y] (what would it mean?).
@@ -589,14 +590,11 @@ def __new__(cls, parameters=None, *args, _root=False):
589590
assert not all_params, all_params
590591
# Weed out subclasses.
591592
# E.g. Union[int, Employee, Manager] == Union[int, Employee].
592-
# If Any or object is present it will be the sole survivor.
593-
# If both Any and object are present, Any wins.
594-
# Never discard type variables, except against Any.
593+
# If object is present it will be sole survivor among proper classes.
594+
# Never discard type variables.
595595
# (In particular, Union[str, AnyStr] != AnyStr.)
596596
all_params = set(params)
597597
for t1 in params:
598-
if t1 is Any:
599-
return Any
600598
if not isinstance(t1, type):
601599
continue
602600
if any(isinstance(t2, type) and issubclass(t1, t2)
@@ -662,7 +660,7 @@ def __subclasscheck__(self, cls):
662660
class _Optional(_FinalTypingBase, _root=True):
663661
"""Optional type.
664662
665-
Optional[X] is equivalent to Union[X, type(None)].
663+
Optional[X] is equivalent to Union[X, None].
666664
"""
667665

668666
__slots__ = ()

0 commit comments

Comments
 (0)
0