this repo has no description
1#!/usr/bin/env python3
2import sys
3import unittest
4
5from test_support import pyro_only
6
7try:
8 from builtins import _non_heaptype
9
10 from _builtins import _gc
11except ImportError:
12 pass
13
14
15Py_TPFLAGS_HEAPTYPE = 1 << 9
16Py_TPFLAGS_BASETYPE = 1 << 10
17Py_TPFLAGS_READY = 1 << 12
18Py_TPFLAGS_READYING = 1 << 13
19Py_TPFLAGS_IS_ABSTRACT = 1 << 20
20Py_TPFLAGS_LONG_SUBCLASS = 1 << 24
21Py_TPFLAGS_LIST_SUBCLASS = 1 << 25
22Py_TPFLAGS_TUPLE_SUBCLASS = 1 << 26
23Py_TPFLAGS_BYTES_SUBCLASS = 1 << 27
24Py_TPFLAGS_UNICODE_SUBCLASS = 1 << 28
25Py_TPFLAGS_DICT_SUBCLASS = 1 << 29
26Py_TPFLAGS_BASE_EXC_SUBCLASS = 1 << 30
27Py_TPFLAGS_TYPE_SUBCLASS = 1 << 31
28
29
30class TypeTests(unittest.TestCase):
31 def test_abstract_methods_get_with_builtin_type_raises_attribute_error(self):
32 with self.assertRaises(AttributeError) as context:
33 type.__abstractmethods__
34 self.assertEqual(str(context.exception), "__abstractmethods__")
35
36 def test_abstract_methods_get_with_type_subclass_raises_attribute_error(self):
37 class Foo(type):
38 pass
39
40 with self.assertRaises(AttributeError) as context:
41 Foo.__abstractmethods__
42 self.assertEqual(str(context.exception), "__abstractmethods__")
43
44 def test_abstract_methods_get_with_non_type_raises_type_error(self):
45 with self.assertRaises(TypeError):
46 type.__dict__["__abstractmethods__"].__get__(42)
47
48 def test_abstract_methods_set_with_builtin_type_raises_type_error(self):
49 with self.assertRaises(TypeError) as context:
50 int.__abstractmethods__ = ["foo"]
51 self.assertEqual(
52 str(context.exception),
53 "can't set attributes of built-in/extension type 'int'",
54 )
55
56 def test_abstract_methods_get_with_type_subclass_sets_attribute(self):
57 class Foo(type):
58 pass
59
60 Foo.__abstractmethods__ = 1
61 self.assertEqual(Foo.__abstractmethods__, 1)
62
63 def test_abstract_methods_del_with_builtin_type_raises_type_error(self):
64 with self.assertRaises(TypeError) as context:
65 del str.__abstractmethods__
66 self.assertEqual(
67 str(context.exception),
68 "can't set attributes of built-in/extension type 'str'",
69 )
70
71 def test_abstract_methods_del_unset_with_type_subclass_raises_attribute_error(self):
72 class Foo(type):
73 pass
74
75 with self.assertRaises(AttributeError) as context:
76 del Foo.__abstractmethods__
77 self.assertEqual(str(context.exception), "__abstractmethods__")
78
79 def test_abstract_methods_del_with_non_type_raises_type_error(self):
80 with self.assertRaises(TypeError):
81 type.__dict__["__abstractmethods__"].__delete__(42)
82
83 def test_abstract_methods_set_with_non_type_raises_type_error(self):
84 with self.assertRaises(TypeError):
85 type.__dict__["__abstractmethods__"].__set__(42, [])
86
87 def test_builtin_types_have_no_module_attribute(self):
88 from types import FrameType
89
90 self.assertNotIn("__module__", int.__dict__)
91 self.assertNotIn("__module__", object.__dict__)
92 self.assertNotIn("__module__", tuple.__dict__)
93 self.assertNotIn("__module__", FrameType.__dict__)
94
95 def test_delattr_deletes_class_attribute(self):
96 class C:
97 fld = 4
98
99 self.assertTrue(hasattr(C, "fld"))
100 self.assertIs(type.__delattr__(C, "fld"), None)
101 self.assertFalse(hasattr(C, "fld"))
102
103 def test_delattr_raises_type_error_with_instance(self):
104 class C:
105 fld = 4
106
107 c = C()
108 self.assertRaisesRegex(
109 TypeError,
110 "'__delattr__' .* 'type' object.* a 'C'",
111 type.__delattr__,
112 c,
113 "fld",
114 )
115
116 def test_dunder_base_with_object_type_returns_none(self):
117 self.assertIs(object.__base__, None)
118
119 def test_dunder_base_with_builtin_type_returns_supertype(self):
120 self.assertIs(bool.__base__, int)
121 self.assertIs(int.__base__, object)
122 self.assertIs(str.__base__, object)
123 self.assertIs(type.__base__, object)
124
125 def test_dunder_base_with_user_type_returns_best_base(self):
126 class A:
127 pass
128
129 class B(A, str):
130 pass
131
132 class C(B):
133 pass
134
135 self.assertIs(A.__base__, object)
136 self.assertIs(B.__base__, str)
137 self.assertIs(C.__base__, B)
138
139 def test_dunder_bases_del_with_builtin_type_raises_type_error(self):
140 with self.assertRaises(TypeError) as context:
141 del object.__bases__
142 self.assertEqual(
143 str(context.exception),
144 "can't set attributes of built-in/extension type 'object'",
145 )
146
147 def test_dunder_bases_del_with_user_type_raises_type_error(self):
148 class C:
149 pass
150
151 with self.assertRaises(TypeError) as context:
152 del C.__bases__
153 self.assertEqual(str(context.exception), "can't delete C.__bases__")
154
155 def test_dunder_bases_del_with_non_type_raises_type_error(self):
156 with self.assertRaises(TypeError):
157 type.__dict__["__bases__"].__delete__(42)
158
159 def test_dunder_bases_get_with_builtin_type_returns_tuple(self):
160 self.assertEqual(object.__bases__, ())
161 self.assertEqual(type.__bases__, (object,))
162 self.assertEqual(int.__bases__, (object,))
163 self.assertEqual(bool.__bases__, (int,))
164
165 def test_dunder_bases_get_with_user_type_returns_tuple(self):
166 class A:
167 pass
168
169 class B:
170 pass
171
172 class C(A):
173 pass
174
175 class D(C, B):
176 pass
177
178 self.assertEqual(A.__bases__, (object,))
179 self.assertEqual(B.__bases__, (object,))
180 self.assertEqual(C.__bases__, (A,))
181 self.assertEqual(D.__bases__, (C, B))
182
183 def test_dunder_bases_get_with_non_type_raises_type_error(self):
184 with self.assertRaises(TypeError):
185 type.__dict__["__bases__"].__get__(42)
186
187 def test_dunder_basicsize_get_with_non_type_raises_type_error(self):
188 with self.assertRaises(TypeError):
189 type.__dict__["__basicsize__"].__get__(42)
190
191 def test_dunder_call_with_non_type_self_raises_type_error(self):
192 self.assertRaisesRegex(
193 TypeError,
194 "'__call__' .* 'type' object.* a 'int'",
195 type.__call__,
196 5,
197 )
198
199 def test_dunder_dir_with_non_type_object_raises_type_error(self):
200 with self.assertRaises(TypeError):
201 type.__dir__(None)
202
203 def test_dunder_doc_on_empty_class_is_none(self):
204 class C:
205 pass
206
207 self.assertIsNone(C.__doc__)
208 instance = C()
209 self.assertIsNone(instance.__doc__)
210
211 def test_dunder_doc_accessible_via_instance(self):
212 class C:
213 """docstring"""
214
215 pass
216
217 self.assertEqual(C.__doc__, "docstring")
218 instance = C()
219 self.assertEqual(instance.__doc__, "docstring")
220
221 def test_type_dunder_doc_is_not_inheritable(self):
222 class C:
223 """docstring"""
224
225 pass
226
227 class D(C):
228 pass
229
230 self.assertEqual(C.__doc__, "docstring")
231 self.assertIsNone(D.__doc__)
232
233 def test_dunder_flags_returns_basetype_set(self):
234 class C:
235 pass
236
237 self.assertTrue(object.__flags__ & Py_TPFLAGS_BASETYPE)
238 self.assertTrue(float.__flags__ & Py_TPFLAGS_BASETYPE)
239 self.assertTrue(C.__flags__ & Py_TPFLAGS_BASETYPE)
240
241 def test_dunder_flags_returns_basetype_clear(self):
242 self.assertFalse(bool.__flags__ & Py_TPFLAGS_BASETYPE)
243 str_iter_type = type(iter(""))
244 self.assertFalse(str_iter_type.__flags__ & Py_TPFLAGS_BASETYPE)
245
246 def test_dunder_flags_with_managed_type_is_heap_type(self):
247 class C:
248 pass
249
250 self.assertTrue(C.__flags__ & Py_TPFLAGS_HEAPTYPE)
251
252 def test_dunder_flags_with_managed_type_is_ready(self):
253 class C:
254 pass
255
256 self.assertTrue(C.__flags__ & Py_TPFLAGS_READY)
257 self.assertFalse(C.__flags__ & Py_TPFLAGS_READYING)
258
259 def test_dunder_flags_without_dunder_abstractmethods_returns_false(self):
260 class C:
261 pass
262
263 with self.assertRaises(AttributeError):
264 C.__abstractmethods__
265
266 self.assertFalse(C.__flags__ & Py_TPFLAGS_IS_ABSTRACT)
267
268 def test_dunder_flags_with_empty_dunder_abstractmethods_returns_false(self):
269 import abc
270
271 class C(metaclass=abc.ABCMeta):
272 pass
273
274 self.assertEqual(len(C.__abstractmethods__), 0)
275 self.assertFalse(C.__flags__ & Py_TPFLAGS_IS_ABSTRACT)
276
277 def test_dunder_flags_with_non_empty_dunder_abstractmethods_returns_true(self):
278 import abc
279
280 class C(metaclass=abc.ABCMeta):
281 @abc.abstractmethod
282 def foo(self):
283 pass
284
285 self.assertEqual(len(C.__abstractmethods__), 1)
286 self.assertTrue(C.__flags__ & Py_TPFLAGS_IS_ABSTRACT)
287
288 def test_dunder_flags_with_non_type_raises_type_error(self):
289 with self.assertRaises(TypeError):
290 type.__dict__["__flags__"].__get__(42)
291
292 def test_dunder_flags_sets_long_subclass_if_int_subclass(self):
293 class C:
294 pass
295
296 self.assertFalse(C.__flags__ & Py_TPFLAGS_LONG_SUBCLASS)
297
298 class D(int):
299 pass
300
301 self.assertTrue(int.__flags__ & Py_TPFLAGS_LONG_SUBCLASS)
302 self.assertTrue(D.__flags__ & Py_TPFLAGS_LONG_SUBCLASS)
303
304 def test_dunder_flags_sets_list_subclass_if_list_subclass(self):
305 class C:
306 pass
307
308 self.assertFalse(C.__flags__ & Py_TPFLAGS_LIST_SUBCLASS)
309
310 class D(list):
311 pass
312
313 self.assertTrue(list.__flags__ & Py_TPFLAGS_LIST_SUBCLASS)
314 self.assertTrue(D.__flags__ & Py_TPFLAGS_LIST_SUBCLASS)
315
316 def test_dunder_flags_sets_tuple_subclass_if_tuple_subclass(self):
317 class C:
318 pass
319
320 self.assertFalse(C.__flags__ & Py_TPFLAGS_TUPLE_SUBCLASS)
321
322 class D(tuple):
323 pass
324
325 self.assertTrue(tuple.__flags__ & Py_TPFLAGS_TUPLE_SUBCLASS)
326 self.assertTrue(D.__flags__ & Py_TPFLAGS_TUPLE_SUBCLASS)
327
328 def test_dunder_flags_sets_bytes_subclass_if_bytes_subclass(self):
329 class C:
330 pass
331
332 self.assertFalse(C.__flags__ & Py_TPFLAGS_BYTES_SUBCLASS)
333
334 class D(bytes):
335 pass
336
337 self.assertTrue(bytes.__flags__ & Py_TPFLAGS_BYTES_SUBCLASS)
338 self.assertTrue(D.__flags__ & Py_TPFLAGS_BYTES_SUBCLASS)
339
340 def test_dunder_flags_sets_unicode_subclass_if_str_subclass(self):
341 class C:
342 pass
343
344 self.assertFalse(C.__flags__ & Py_TPFLAGS_UNICODE_SUBCLASS)
345
346 class D(str):
347 pass
348
349 self.assertTrue(str.__flags__ & Py_TPFLAGS_UNICODE_SUBCLASS)
350 self.assertTrue(D.__flags__ & Py_TPFLAGS_UNICODE_SUBCLASS)
351
352 def test_dunder_flags_sets_dict_subclass_if_dict_subclass(self):
353 class C:
354 pass
355
356 self.assertFalse(C.__flags__ & Py_TPFLAGS_DICT_SUBCLASS)
357
358 class D(dict):
359 pass
360
361 self.assertTrue(dict.__flags__ & Py_TPFLAGS_DICT_SUBCLASS)
362 self.assertTrue(D.__flags__ & Py_TPFLAGS_DICT_SUBCLASS)
363
364 def test_dunder_flags_sets_base_exc_subclass_if_base_exception_subclass(self):
365 class C:
366 pass
367
368 self.assertFalse(C.__flags__ & Py_TPFLAGS_BASE_EXC_SUBCLASS)
369
370 class D(BaseException):
371 pass
372
373 self.assertTrue(BaseException.__flags__ & Py_TPFLAGS_BASE_EXC_SUBCLASS)
374 self.assertTrue(D.__flags__ & Py_TPFLAGS_BASE_EXC_SUBCLASS)
375 self.assertTrue(MemoryError.__flags__ & Py_TPFLAGS_BASE_EXC_SUBCLASS)
376
377 def test_dunder_flags_sets_type_subclass_if_type_subclass(self):
378 class C:
379 pass
380
381 self.assertFalse(C.__flags__ & Py_TPFLAGS_TYPE_SUBCLASS)
382
383 class D(type):
384 pass
385
386 self.assertTrue(type.__flags__ & Py_TPFLAGS_TYPE_SUBCLASS)
387 self.assertTrue(D.__flags__ & Py_TPFLAGS_TYPE_SUBCLASS)
388
389 def test_dunder_init_with_no_name_or_object_param_raises_type_error(self):
390 with self.assertRaises(TypeError) as context:
391 type.__init__(type)
392
393 self.assertIn("type.__init__() takes 1 or 3 arguments", str(context.exception))
394
395 def test_dunder_init_with_too_many_args_raises_type_error(self):
396 with self.assertRaises(TypeError) as context:
397 type.__init__(type, "C", (), {}, 1, 2, 3, 4, 5, foobar=42)
398
399 self.assertIn("type.__init__() takes 1 or 3 arguments", str(context.exception))
400
401 def test_dunder_init_with_kwargs_does_not_raise(self):
402 type.__init__(type, "C", (), {}, foobar=42)
403
404 def test_dunder_instancecheck_with_instance_returns_true(self):
405 self.assertIs(int.__instancecheck__(3), True)
406 self.assertIs(int.__instancecheck__(False), True)
407 self.assertIs(object.__instancecheck__(type), True)
408 self.assertIs(str.__instancecheck__("123"), True)
409 self.assertIs(type.__instancecheck__(type, int), True)
410 self.assertIs(type.__instancecheck__(type, object), True)
411
412 def test_dunder_instancecheck_with_non_instance_returns_false(self):
413 self.assertIs(bool.__instancecheck__(3), False)
414 self.assertIs(int.__instancecheck__("123"), False)
415 self.assertIs(str.__instancecheck__(b"123"), False)
416 self.assertIs(type.__instancecheck__(type, 3), False)
417
418 def test_dunder_subclasscheck_with_subclass_returns_true(self):
419 self.assertIs(int.__subclasscheck__(int), True)
420 self.assertIs(int.__subclasscheck__(bool), True)
421 self.assertIs(object.__subclasscheck__(int), True)
422 self.assertIs(object.__subclasscheck__(type), True)
423
424 def test_dunder_subclasscheck_with_non_subclass_returns_false(self):
425 self.assertIs(bool.__subclasscheck__(int), False)
426 self.assertIs(int.__subclasscheck__(object), False)
427 self.assertIs(str.__subclasscheck__(object), False)
428 self.assertIs(type.__subclasscheck__(type, object), False)
429
430 def test_dunder_module_set_on_builtin_raises_type_error(self):
431 with self.assertRaisesRegex(TypeError, ".*int.*"):
432 int.__module__ = "foo"
433 with self.assertRaisesRegex(TypeError, ".*int.*"):
434 type.__dict__["__module__"].__set__(int, "foo")
435
436 def test_dunder_module_sets_module(self):
437 class C:
438 pass
439
440 type.__dict__["__module__"].__set__(C, "foo")
441 self.assertEqual(type.__dict__["__module__"].__get__(C), "foo")
442 self.assertEqual(C.__dict__["__module__"], "foo")
443 self.assertEqual(C.__module__, "foo")
444
445 def test_dunder_module_set_accepts_anything(self):
446 class C:
447 pass
448
449 type.__dict__["__module__"].__set__(C, 42.42)
450 self.assertEqual(C.__module__, 42.42)
451
452 C.__module__ = None
453 self.assertIsNone(type.__dict__["__module__"].__get__(C))
454
455 def test_dunder_module_with_builtin_type_returns_builtins(self):
456 self.assertEqual(int.__module__, "builtins")
457 self.assertEqual(dict.__module__, "builtins")
458 self.assertEqual(OSError.__module__, "builtins")
459 self.assertEqual(type.__module__, "builtins")
460
461 def test_dunder_name_returns_name(self):
462 class FooBar:
463 pass
464
465 self.assertEqual(FooBar.__name__, "FooBar")
466 self.assertEqual(type.__dict__["__name__"].__get__(FooBar), "FooBar")
467
468 def test_dunder_name_sets_name(self):
469 class C:
470 pass
471
472 type.__dict__["__name__"].__set__(C, "foo")
473 self.assertEqual(type.__dict__["__name__"].__get__(C), "foo")
474 self.assertEqual(C.__name__, "foo")
475
476 def test_dunder_name_set_with_non_string_raises_type_error(self):
477 class C:
478 pass
479
480 with self.assertRaisesRegex(
481 TypeError, "can only assign string to C.__name__, not 'int'"
482 ):
483 C.__name__ = 42
484 with self.assertRaisesRegex(
485 TypeError, "can only assign string to C.__name__, not 'float'"
486 ):
487 type.__dict__["__name__"].__set__(C, 1.2)
488
489 def test_dunder_name_set_on_builtin_raises_type_error(self):
490 with self.assertRaisesRegex(TypeError, ".*int.*"):
491 int.__name__ = "foo"
492 with self.assertRaisesRegex(TypeError, ".*int.*"):
493 type.__dict__["__name__"].__set__(int, "foo")
494
495 def test_dunder_new_with_one_arg_returns_type_of_arg(self):
496 class C:
497 pass
498
499 self.assertIs(type.__new__(type, 1), int)
500 self.assertIs(type.__new__(type, "hello"), str)
501 self.assertIs(type.__new__(type, C()), C)
502
503 def test_dunder_new_with_non_type_cls_raises_type_error(self):
504 with self.assertRaises(TypeError):
505 type.__new__(1, "X", (object,), {})
506
507 def test_dunder_new_with_non_str_name_raises_type_error(self):
508 with self.assertRaises(TypeError):
509 type.__new__(type, 1, (object,), {})
510
511 def test_dunder_new_with_non_tuple_bases_raises_type_error(self):
512 with self.assertRaises(TypeError):
513 type.__new__(type, "X", [object], {})
514
515 def test_dunder_new_with_non_basetype_raises_type_error(self):
516 with self.assertRaisesRegex(
517 TypeError, "type 'bool' is not an acceptable base type"
518 ):
519 type.__new__(type, "X", (bool,), {})
520
521 def test_dunder_new_with_non_dict_type_dict_raises_type_error(self):
522 with self.assertRaises(TypeError):
523 type.__new__(type, "X", (object,), 1)
524
525 def test_dunder_new_with_duplicated_base_raises_type_error(self):
526 class C:
527 pass
528
529 error_msg = "duplicate base class C"
530 with self.assertRaisesRegex(TypeError, error_msg):
531 type.__new__(type, "X", (C, C), {})
532
533 def test_dunder_new_returns_type_instance(self):
534 X = type.__new__(type, "X", (object,), {})
535 self.assertIsInstance(X, type)
536 self.assertEqual(X.__name__, "X")
537 self.assertEqual(X.__qualname__, "X")
538 self.assertTrue(X.__flags__ & Py_TPFLAGS_HEAPTYPE)
539
540 def test_dunder_new_sets_dunder_module(self):
541 globals = {"__name__": 8.13}
542 X = eval("type('X', (), {})", globals) # noqa: P204
543 self.assertEqual(X.__module__, 8.13)
544 self.assertEqual(X.__dict__["__module__"], 8.13)
545
546 def test_dunder_new_does_not_override_dunder_module(self):
547 X = type.__new__(type, "X", (), {"__module__": "foobar"})
548 self.assertEqual(X.__module__, "foobar")
549 self.assertEqual(X.__dict__["__module__"], "foobar")
550
551 def test_dunder_new_sets_qualname(self):
552 X = type.__new__(type, "foo.bar", (), {})
553 self.assertEqual(X.__qualname__, "foo.bar")
554 self.assertNotIn("__qualname__", X.__dict__)
555
556 def test_dunder_new_sets_qualname_from_dict(self):
557 namespace = {"__qualname__": "quux"}
558 X = type.__new__(type, "X", (), namespace)
559 self.assertEqual(X.__qualname__, "quux")
560 self.assertNotIn("__qualname__", X.__dict__)
561 self.assertEqual(namespace["__qualname__"], "quux")
562
563 def test_dunder_new_with_non_string_qualname_raises_type_error(self):
564 with self.assertRaisesRegex(
565 TypeError, "type __qualname__ must be a str, not float"
566 ):
567 type.__new__(type, "X", (), {"__qualname__": 2.3})
568
569 def test_dunder_new_adds_to_base_dunder_subclasses(self):
570 A = type.__new__(type, "A", (object,), {})
571 B = type.__new__(type, "B", (object,), {})
572 C = type.__new__(type, "C", (A, B), {})
573 D = type.__new__(type, "D", (A,), {})
574 self.assertEqual(A.__subclasses__(), [C, D])
575 self.assertEqual(B.__subclasses__(), [C])
576 self.assertEqual(C.__subclasses__(), [])
577 self.assertEqual(D.__subclasses__(), [])
578
579 @unittest.skipIf(
580 sys.version_info < (3, 10) and sys.implementation.name != "skybison",
581 "Union requrires CPython 3.10",
582 )
583 def test_dunder_or_returns_union(self):
584 from types import Union
585
586 t = int | float
587 self.assertIs(type(t), Union)
588 self.assertEqual(t.__args__, (int, float))
589 t = float | int
590 self.assertIs(type(t), Union)
591 self.assertEqual(t.__args__, (float, int))
592 t = str | None
593 self.assertIs(type(t), Union)
594 self.assertEqual(t.__args__, (str, type(None)))
595
596 @unittest.skipIf(
597 sys.version_info < (3, 10) and sys.implementation.name != "skybison",
598 "Union requrires CPython 3.10",
599 )
600 def test_dunder_ror_returns_union(self):
601 from types import Union
602
603 t = None | bytes
604 self.assertIs(type(t), Union)
605 self.assertEqual(t.__args__, (type(None), bytes))
606
607 def test_dunder_qualname_returns_qualname(self):
608 class C:
609 __qualname__ = "bar"
610
611 self.assertEqual(C.__qualname__, "bar")
612 self.assertEqual(type.__dict__["__qualname__"].__get__(C), "bar")
613
614 def test_dunder_qualname_sets_qualname(self):
615 class C:
616 pass
617
618 type.__dict__["__qualname__"].__set__(C, "baz")
619 self.assertEqual(C.__qualname__, "baz")
620 C.__qualname__ = "bam"
621 self.assertEqual(type.__dict__["__qualname__"].__get__(C), "bam")
622
623 def test_dunder_qualname_set_with_non_string_raises_type_error(self):
624 class C:
625 pass
626
627 with self.assertRaisesRegex(
628 TypeError, "can only assign string to C.__qualname__, not 'int'"
629 ):
630 C.__qualname__ = 42
631 with self.assertRaisesRegex(
632 TypeError, "can only assign string to C.__qualname__, not 'float'"
633 ):
634 type.__dict__["__qualname__"].__set__(C, 1.2)
635
636 def test_dunder_qualname_set_on_builtin_raises_type_error(self):
637 with self.assertRaisesRegex(TypeError, ".*list.*"):
638 list.__qualname__ = "foo"
639 with self.assertRaisesRegex(TypeError, ".*list.*"):
640 type.__dict__["__qualname__"].__set__(list, "foo")
641
642 def test_dunder_repr_with_bytes_raises_type_error(self):
643 with self.assertRaises(TypeError):
644 type.__repr__(b"")
645
646 def test_dunder_repr_returns_string_with_module_and_name(self):
647 class C:
648 pass
649
650 self.assertEqual(
651 type.__repr__(C),
652 "<class '__main__.TypeTests.test_dunder_repr_returns_string_with_module_and_name.<locals>.C'>",
653 )
654
655 def test_dunder_repr_for_builtins_returns_string_with_only_name(self):
656 self.assertEqual(type.__repr__(list), "<class 'list'>")
657 self.assertEqual(type.__repr__(type), "<class 'type'>")
658 self.assertEqual(type.__repr__(TypeError), "<class 'TypeError'>")
659
660 def test_dunder_repr_for_imported_class_returns_string_with_module_and_name(self):
661 self.assertEqual(
662 type.__repr__(unittest.case.TestCase), "<class 'unittest.case.TestCase'>"
663 )
664
665 def test_dunder_subclasses_with_leaf_type_returns_empty_list(self):
666 class C:
667 pass
668
669 self.assertEqual(C.__subclasses__(), [])
670
671 def test_dunder_subclasses_with_supertype_returns_list(self):
672 class C:
673 pass
674
675 class D(C):
676 pass
677
678 self.assertEqual(C.__subclasses__(), [D])
679
680 def test_dunder_subclasses_returns_new_list(self):
681 class C:
682 pass
683
684 self.assertIsNot(C.__subclasses__(), C.__subclasses__())
685
686 @pyro_only
687 def test_dunder_subclasses_does_not_return_dead_types(self):
688 class C:
689 pass
690
691 class D(C):
692 pass
693
694 D = None # noqa: F811, F841
695 _gc()
696 self.assertEqual(type.__subclasses__(C), [])
697
698 @pyro_only
699 def test_dunder_subclasses_with_multiple_subclasses_returns_list(self):
700 class B:
701 pass
702
703 class S0(B):
704 pass
705
706 class S1(B):
707 pass
708
709 class S2(B):
710 pass
711
712 class S3(B):
713 pass
714
715 class S4(B):
716 pass
717
718 S1 = None # noqa: F811, F841
719 S3 = None # noqa: F811, F841
720 _gc()
721 self.assertEqual(len(type.__subclasses__(B)), 3)
722 S0 = None # noqa: F811, F841
723 _gc()
724 self.assertEqual(type.__subclasses__(B), [S2, S4])
725
726 def test_mro_returns_list(self):
727 class C:
728 pass
729
730 mro = C.mro()
731 self.assertIsInstance(mro, list)
732 self.assertEqual(mro, [C, object])
733
734 def test_mro_with_multiple_inheritance_returns_linearization(self):
735 class A:
736 pass
737
738 class B:
739 pass
740
741 class C(A, B):
742 pass
743
744 mro = type.mro(C)
745 self.assertIsInstance(mro, list)
746 self.assertEqual(mro, [C, A, B, object])
747
748 def test_mro_with_invalid_linearization_raises_type_error(self):
749 class A:
750 pass
751
752 class B(A):
753 pass
754
755 with self.assertRaisesRegex(
756 TypeError,
757 r"Cannot create a consistent method resolution\s+order \(MRO\) for bases A, B",
758 ):
759
760 class C(A, B):
761 pass
762
763 def test_mro_with_custom_method_propagates_exception(self):
764 class Meta(type):
765 def mro(cls):
766 raise KeyError
767
768 with self.assertRaises(KeyError):
769
770 class Foo(metaclass=Meta):
771 pass
772
773 def test_new_calculates_metaclass_and_calls_dunder_new(self):
774 class M0(type):
775 def __new__(metacls, name, bases, type_dict, **kwargs):
776 metacls.new_args = (metacls, name, bases, kwargs)
777 return type.__new__(metacls, name, bases, type_dict)
778
779 class M1(M0):
780 foo = 7
781
782 class A(metaclass=M0):
783 pass
784
785 class B(metaclass=M1):
786 pass
787
788 C = type.__new__(type, "C", (A, B), {}, bar=8)
789 self.assertIs(type(C), M1)
790 self.assertEqual(C.new_args, (M1, "C", (A, B), {"bar": 8}))
791 self.assertEqual(C.foo, 7)
792
793 def test_new_with_mro_entries_base_raises_type_error(self):
794 class X:
795 def __mro_entries__(self, bases):
796 return (object,)
797
798 pseudo_base = X()
799 with self.assertRaises(TypeError) as ctx:
800 type.__new__(type, "C", (pseudo_base,), {})
801 self.assertEqual(
802 str(ctx.exception),
803 "type() doesn't support MRO entry resolution; use types.new_class()",
804 )
805
806 def test_mro_returning_iterable_returns_class_with_mro_tuple(self):
807 class A:
808 foo = 42
809
810 class X:
811 def __init__(self, cls):
812 self.cls = cls
813
814 def __iter__(self):
815 return iter((self.cls, A))
816
817 class Meta(type):
818 def mro(cls):
819 return X(cls)
820
821 C = Meta.__new__(Meta, "C", (object,), {})
822 self.assertIs(type(C.__mro__), tuple)
823 self.assertEqual(C.__mro__, (C, A))
824 self.assertEqual(C.foo, 42)
825
826 def test_new_calls_init_subclass(self):
827 class Foo:
828 def __init_subclass__(cls, *args, **kwargs):
829 cls.called_init = True
830
831 self.assertIsInstance(cls, type)
832 self.assertIn("foo", kwargs)
833
834 class Bar(Foo, foo=True):
835 pass
836
837 self.assertTrue(Bar.called_init)
838
839 def test_new_duplicates_dict(self):
840 d = {"foo": 42, "bar": 17}
841 T = type("T", (object,), d)
842 d["foo"] = -7
843 del d["bar"]
844 self.assertEqual(T.foo, 42)
845 self.assertEqual(T.bar, 17)
846 T.foo = 20
847 self.assertEqual(d["foo"], -7)
848 self.assertFalse("bar" in d)
849
850 @pyro_only
851 def test_non_heaptype_returns_non_heaptype(self):
852 X = _non_heaptype("X", (), {})
853 self.assertFalse(X.__flags__ & Py_TPFLAGS_HEAPTYPE)
854 with self.assertRaises(TypeError):
855 X.foo = 1
856
857 def test_non_heaptype_has_no_module_attribute(self):
858 from types import SimpleNamespace
859
860 self.assertNotIn("__module__", SimpleNamespace.__dict__)
861 self.assertNotIn("__module__", zip.__dict__)
862 self.assertNotIn("__module__", map.__dict__)
863
864 def test_setattr_with_metaclass_does_not_abort(self):
865 class Meta(type):
866 pass
867
868 class C(metaclass=Meta):
869 __slots__ = "attr"
870
871 def __init__(self, data):
872 self.attr = data
873
874 m = C("foo")
875 self.assertEqual(m.attr, "foo")
876 m.attr = "bar"
877 self.assertEqual(m.attr, "bar")
878
879 def test_type_new_sets_name_on_attributes(self):
880 class Descriptor:
881 def __set_name__(self, owner, name):
882 self.owner = owner
883 self.name = name
884
885 class A:
886 d = Descriptor()
887
888 self.assertEqual(A.d.name, "d")
889 self.assertIs(A.d.owner, A)
890
891 def test_type_new_propagates_set_name_error(self):
892 class Descriptor:
893 def __set_name__(self, owner, name):
894 raise Exception("I prefer to remain unnamed.")
895
896 with self.assertRaises(RuntimeError) as context:
897
898 class A:
899 d = Descriptor()
900
901 self.assertIn("A", str(context.exception))
902 self.assertIn("Descriptor", str(context.exception))
903
904 def test_type_new_with_metaclass_sets_name(self):
905 class Meta(type):
906 def __new__(metacls, name, bases, ns):
907 ret = super().__new__(metacls, name, bases, ns)
908 self.assertEqual(ret.d.name, "d")
909 self.assertIs(ret.d.owner, ret)
910 return 0
911
912 class Descriptor:
913 def __set_name__(self, owner, name):
914 self.owner = owner
915 self.name = name
916
917 class A(metaclass=Meta):
918 d = Descriptor()
919
920 self.assertEqual(A, 0)
921
922 def test_type_new_with_set_name_raising_error_propagates_exception(self):
923 class SetNameDescriptor:
924 def __get__(self, instance, owner):
925 raise ValueError("Don't call, please.")
926
927 class Descriptor:
928 __set_name__ = SetNameDescriptor()
929
930 with self.assertRaises(ValueError):
931
932 class A:
933 d = Descriptor()
934
935 def test_non_type_with_type_getattribute(self):
936 class C:
937 __getattribute__ = type.__getattribute__
938
939 c = C()
940 with self.assertRaises(TypeError):
941 c.foo
942
943
944class TypeProxyTests(unittest.TestCase):
945 def setUp(self):
946 class A:
947 placeholder = "placeholder_value"
948
949 class B(A):
950 pass
951
952 def make_placeholder():
953 b = B()
954 return b.placeholder
955
956 self.tested_type = B
957 self.type_proxy = B.__dict__
958 self.assertEqual(make_placeholder(), "placeholder_value")
959
960 def test_dunder_contains_with_non_type_proxy_raises_type_error(self):
961 with self.assertRaises(TypeError):
962 type(self.type_proxy).__contains__(None, None)
963
964 def test_dunder_contains_returns_true_for_existing_item(self):
965 self.tested_type.x = 40
966 self.assertTrue(self.type_proxy.__contains__("x"))
967
968 def test_dunder_contains_returns_false_for_not_existing_item(self):
969 self.assertFalse(self.type_proxy.__contains__("x"))
970
971 def test_dunder_contains_returns_false_for_placeholder(self):
972 self.assertFalse(self.type_proxy.__contains__("placeholder"))
973
974 def test_copy_with_non_type_proxy_raises_type_error(self):
975 with self.assertRaises(TypeError):
976 type(self.type_proxy).copy(None)
977
978 def test_copy_returns_dict_copy(self):
979 self.tested_type.x = 40
980 result = self.type_proxy.copy()
981 self.assertEqual(type(result), dict)
982 self.assertEqual(result["x"], 40)
983 self.tested_type.y = 50
984 self.assertNotIn("y", result)
985
986 def test_dunder_getitem_with_non_type_proxy_raises_type_error(self):
987 with self.assertRaises(TypeError):
988 type(self.type_proxy).__getitem__(None, None)
989
990 def test_dunder_getitem_for_existing_key_returns_that_item(self):
991 self.tested_type.x = 40
992 self.assertEqual(self.type_proxy.__getitem__("x"), 40)
993
994 def test_dunder_getitem_for_not_existing_key_raises_key_error(self):
995 with self.assertRaises(KeyError) as context:
996 self.type_proxy.__getitem__("x")
997 self.assertIn("'x'", str(context.exception))
998
999 def test_dunder_getitem_for_placeholder_raises_key_error(self):
1000 with self.assertRaises(KeyError) as context:
1001 self.type_proxy.__getitem__("placeholder")
1002 self.assertIn("'placeholder'", str(context.exception))
1003
1004 def test_dunder_iter_with_non_type_proxy_raises_type_error(self):
1005 with self.assertRaises(TypeError):
1006 type(self.type_proxy).__iter__(None)
1007
1008 def test_dunder_iter_returns_key_iterator(self):
1009 self.tested_type.x = 40
1010 self.tested_type.y = 50
1011 result = self.type_proxy.__iter__()
1012 self.assertTrue(hasattr(result, "__next__"))
1013 result_list = list(result)
1014 self.assertIn("x", result_list)
1015 self.assertIn("y", result_list)
1016
1017 def test_dunder_len_with_non_type_proxy_raises_type_error(self):
1018 with self.assertRaises(TypeError):
1019 type(self.type_proxy).__len__(None)
1020
1021 def test_dunder_len_returns_num_items(self):
1022 length = self.type_proxy.__len__()
1023 self.tested_type.x = 40
1024 self.assertEqual(self.type_proxy.__len__(), length + 1)
1025
1026 def test_dunder_len_returns_num_items_excluding_placeholder(self):
1027 length = self.type_proxy.__len__()
1028 # Overwrite the existing placeholder by creating a real one under the same name.
1029 self.tested_type.placeholder = 1
1030 self.assertEqual(self.type_proxy.__len__(), length + 1)
1031
1032 def test_dunder_repr_with_non_type_proxy_raises_type_error(self):
1033 with self.assertRaises(TypeError):
1034 type(self.type_proxy).__repr__(None)
1035
1036 def test_dunder_repr_returns_str_containing_existing_items(self):
1037 self.tested_type.x = 40
1038 self.tested_type.y = 50
1039 result = self.type_proxy.__repr__()
1040 self.assertIsInstance(result, str)
1041 self.assertIn("'x': 40", result)
1042 self.assertIn("'y': 50", result)
1043
1044 def test_dunder_repr_returns_str_not_containing_placeholder(self):
1045 result = self.type_proxy.__repr__()
1046 self.assertNotIn("'placeholder'", result)
1047
1048 def test_get_with_non_type_proxy_raises_type_error(self):
1049 with self.assertRaises(TypeError):
1050 type(self.type_proxy).get(None, None)
1051
1052 def test_get_returns_existing_item_value(self):
1053 self.tested_type.x = 40
1054 self.assertEqual(self.type_proxy.get("x"), 40)
1055
1056 def test_get_with_default_for_non_existing_item_value_returns_that_default(self):
1057 self.assertEqual(self.type_proxy.get("x", -1), -1)
1058
1059 def test_get_for_non_existing_item_returns_none(self):
1060 self.assertIs(self.type_proxy.get("x"), None)
1061
1062 def test_get_for_placeholder_returns_none(self):
1063 self.assertIs(self.type_proxy.get("placeholder"), None)
1064
1065 def test_items_with_non_type_proxy_raises_type_error(self):
1066 with self.assertRaises(TypeError):
1067 type(self.type_proxy).items(None)
1068
1069 def test_items_returns_container_for_key_value_pairs(self):
1070 self.tested_type.x = 40
1071 self.tested_type.y = 50
1072 result = self.type_proxy.items()
1073 self.assertTrue(hasattr(result, "__iter__"))
1074 result_list = list(iter(result))
1075 self.assertIn(("x", 40), result_list)
1076 self.assertIn(("y", 50), result_list)
1077
1078 def test_keys_with_non_type_proxy_raises_type_error(self):
1079 with self.assertRaises(TypeError):
1080 type(self.type_proxy).keys(None)
1081
1082 def test_keys_returns_container_for_keys(self):
1083 self.tested_type.x = 40
1084 self.tested_type.y = 50
1085 result = self.type_proxy.keys()
1086 self.assertTrue(hasattr(result, "__iter__"))
1087 result_list = list(iter(result))
1088 self.assertIn("x", result_list)
1089 self.assertIn("y", result_list)
1090
1091 def test_keys_returns_key_iterator_excluding_placeholder(self):
1092 result = self.type_proxy.keys()
1093 self.assertNotIn("placeholder", result)
1094
1095 def test_values_with_non_type_proxy_raises_type_error(self):
1096 with self.assertRaises(TypeError):
1097 type(self.type_proxy).values(None)
1098
1099 def test_values_returns_container_for_values(self):
1100 self.tested_type.x = 1243314135
1101 self.tested_type.y = -1243314135
1102 result = self.type_proxy.values()
1103 self.assertTrue(hasattr(result, "__iter__"))
1104 result_list = list(iter(result))
1105 self.assertIn(1243314135, result_list)
1106 self.assertIn(-1243314135, result_list)
1107
1108 def test_values_returns_iterator_excluding_placeholder_value(self):
1109 result = self.type_proxy.values()
1110 self.assertNotIn("placeholder_value", result)
1111
1112
1113class DunderSlotsTests(unittest.TestCase):
1114 def test_with_non_str_raises_type_error(self):
1115 with self.assertRaises(TypeError) as context:
1116
1117 class C:
1118 __slots__ = "a", 1
1119
1120 self.assertIn(
1121 "__slots__ items must be strings, not 'int'", str(context.exception)
1122 )
1123
1124 def test_with_non_identifier_raises_type_error(self):
1125 with self.assertRaises(TypeError) as context:
1126
1127 class C:
1128 __slots__ = "a", ";;"
1129
1130 self.assertIn("__slots__ must be identifiers", str(context.exception))
1131
1132 def test_with_duplicated_dunder_dict_raises_type_error(self):
1133 with self.assertRaises(TypeError) as context:
1134
1135 class C:
1136 __slots__ = "a", "__dict__", "__dict__"
1137
1138 self.assertIn(
1139 "__dict__ slot disallowed: we already got one", str(context.exception)
1140 )
1141
1142 def test_with_conflicting_name_raises_value_error(self):
1143 with self.assertRaises(ValueError) as context:
1144
1145 class C:
1146 __slots__ = "a"
1147 a = "conflicting"
1148
1149 self.assertIn(
1150 "'a' in __slots__ conflicts with class variable", str(context.exception)
1151 )
1152
1153 def test_without_dunder_dict_removes_dunder_dict_type_attribute(self):
1154 class C:
1155 __slots__ = "a"
1156
1157 self.assertNotIn("__dict__", C.__dict__)
1158
1159 def test_with_dunder_dict_keeps_dunder_dict_type_attribute(self):
1160 class C:
1161 __slots__ = "a", "__dict__"
1162
1163 self.assertIn("__dict__", C.__dict__)
1164
1165 def test_slot_descriptor_dunder_get_with_none_returns_type(self):
1166 class C:
1167 __slots__ = "a"
1168
1169 descriptor = C.__dict__["a"]
1170 slot_descriptor_type = type(descriptor)
1171 self.assertIs(descriptor.__get__(None, slot_descriptor_type), descriptor)
1172
1173 def test_slot_descriptor_dunder_get_with_instance_returns_attribute(self):
1174 class C:
1175 __slots__ = "a"
1176
1177 def __init__(self):
1178 self.a = 10
1179
1180 descriptor = C.__dict__["a"]
1181 instance = C()
1182 self.assertEqual(descriptor.__get__(instance), 10)
1183
1184 def test_slot_descriptor_dunder_get_with_instance_and_none_owner_returns_attribute(
1185 self,
1186 ):
1187 class C:
1188 __slots__ = "a"
1189
1190 def __init__(self):
1191 self.a = 10
1192
1193 descriptor = C.__dict__["a"]
1194 instance = C()
1195 self.assertEqual(descriptor.__get__(instance, None), 10)
1196
1197 def test_slot_descriptor_dunder_get_with_none_instance_and_none_owner_raises_type_error(
1198 self,
1199 ):
1200 class C:
1201 __slots__ = "a"
1202
1203 descriptor = C.__dict__["a"]
1204
1205 with self.assertRaises(TypeError) as context:
1206 descriptor.__get__(None, None)
1207 self.assertEqual(
1208 str(context.exception),
1209 "__get__(None, None) is invalid",
1210 )
1211
1212 def test_slot_descriptor_dunder_delete_returns_none(self):
1213 class C:
1214 __slots__ = "a"
1215
1216 def __init__(self):
1217 self.a = 10
1218
1219 descriptor = C.__dict__["a"]
1220 instance = C()
1221 self.assertEqual(descriptor.__delete__(instance), None)
1222
1223 def test_slot_descriptor_dunder_delete_none_raises_type_error(self):
1224 class C:
1225 __slots__ = "a"
1226
1227 descriptor = C.__dict__["a"]
1228
1229 with self.assertRaises(TypeError) as context:
1230 descriptor.__delete__(None)
1231 self.assertEqual(
1232 str(context.exception),
1233 "descriptor 'a' for 'C' objects doesn't apply to a 'NoneType' object",
1234 )
1235
1236 def test_creates_type_attributes(self):
1237 class C:
1238 __slots__ = "a", "b", "c"
1239
1240 self.assertIn("a", C.__dict__)
1241 self.assertIn("b", C.__dict__)
1242 self.assertIn("c", C.__dict__)
1243
1244 slot_descriptor_type = type(C.a)
1245 self.assertTrue(hasattr(slot_descriptor_type, "__get__"))
1246 self.assertTrue(hasattr(slot_descriptor_type, "__set__"))
1247 self.assertIsInstance(C.a, slot_descriptor_type)
1248 self.assertIsInstance(C.b, slot_descriptor_type)
1249 self.assertIsInstance(C.c, slot_descriptor_type)
1250
1251 def test_sharing_same_layout_base_can_servce_as_bases(self):
1252 class C:
1253 __slots__ = "x"
1254
1255 class D(C):
1256 pass
1257
1258 class E(C):
1259 __slots__ = "y"
1260
1261 class F(D, E):
1262 pass
1263
1264 self.assertTrue(hasattr(F, "x"))
1265 self.assertTrue(hasattr(F, "y"))
1266
1267 def test_attributes_raises_attribute_error_before_set(self):
1268 class C:
1269 __slots__ = "x"
1270
1271 c = C()
1272 self.assertFalse(hasattr(c, "x"))
1273 with self.assertRaises(AttributeError):
1274 c.x
1275
1276 def test_attributes_return_set_attributes(self):
1277 class C:
1278 __slots__ = "x"
1279
1280 c = C()
1281 c.x = 500
1282 self.assertEqual(c.x, 500)
1283
1284 def test_attributes_raises_attribute_error_after_deletion(self):
1285 class C:
1286 __slots__ = "x"
1287
1288 c = C()
1289 c.x = 50
1290 del c.x
1291 with self.assertRaises(AttributeError):
1292 c.x
1293
1294 def test_attributes_delete_raises_attribute_before_set(self):
1295 class C:
1296 __slots__ = "x"
1297
1298 c = C()
1299 with self.assertRaises(AttributeError):
1300 del c.x
1301
1302 def test_with_sealed_base_seals_type(self):
1303 class C:
1304 __slots__ = ()
1305
1306 c = C()
1307 with self.assertRaises(AttributeError):
1308 c.x = 500
1309 self.assertFalse(hasattr(c, "__dict__"))
1310
1311 def test_with_unsealed_base_unseals_type(self):
1312 class C:
1313 pass
1314
1315 class D(C):
1316 __slots__ = ()
1317
1318 d = D()
1319 d.x = 500
1320 self.assertEqual(d.x, 500)
1321 self.assertTrue(hasattr(d, "__dict__"))
1322
1323 def test_inherit_from_bases(self):
1324 class C:
1325 __slots__ = ()
1326
1327 class D(C):
1328 __slots__ = "x", "y"
1329
1330 class E(D, C):
1331 __slots__ = "z"
1332
1333 e = E()
1334 e.x = 1
1335 e.y = 2
1336 e.z = 3
1337 self.assertEqual(e.x, 1)
1338 self.assertEqual(e.y, 2)
1339 self.assertEqual(e.z, 3)
1340 with self.assertRaises(AttributeError):
1341 e.w = 500
1342 self.assertFalse(hasattr(e, "__dict__"))
1343
1344 def test_inherit_from_builtin_type(self):
1345 class C(dict):
1346 __slots__ = "x"
1347
1348 c = C()
1349 c.x = 500
1350 c["p"] = 4
1351 c["q"] = 5
1352 self.assertEqual(c.x, 500)
1353 self.assertEqual(c["p"], 4)
1354 self.assertEqual(c["q"], 5)
1355
1356 def test_are_independent_from_inherited_slots(self):
1357 class C:
1358 __slots__ = ("a", "c")
1359
1360 class D(C):
1361 __slots__ = ("b", "c")
1362
1363 obj = D()
1364 obj.a = 1
1365 obj.b = 2
1366 obj.c = 3
1367 C.c.__set__(obj, 33)
1368
1369 self.assertEqual(obj.a, 1)
1370 self.assertEqual(C.a.__get__(obj), 1)
1371 self.assertEqual(D.a.__get__(obj), 1)
1372 self.assertEqual(obj.b, 2)
1373 with self.assertRaises(AttributeError):
1374 C.b
1375 self.assertEqual(D.b.__get__(obj), 2)
1376 self.assertEqual(obj.c, 3)
1377 self.assertEqual(C.c.__get__(obj), 33)
1378 self.assertEqual(D.c.__get__(obj), 3)
1379
1380 def test_member_descriptor_works_only_for_subtypes(self):
1381 class C:
1382 __slots__ = "x"
1383
1384 class D(C):
1385 __slots__ = "y"
1386
1387 class E:
1388 __slots__ = "x"
1389
1390 d = D()
1391 # C's member_descriptor for "x" works for D instances.
1392 C.x.__set__(d, 500)
1393 self.assertEqual(C.x.__get__(d), 500)
1394 self.assertEqual(d.x, 500)
1395
1396 e = E()
1397 with self.assertRaises(TypeError) as context:
1398 C.x.__set__(e, 500)
1399 self.assertEqual(
1400 str(context.exception),
1401 "descriptor 'x' for 'C' objects doesn't apply to a 'E' object",
1402 )
1403
1404 e.x = 600
1405 with self.assertRaises(TypeError) as context:
1406 C.x.__get__(e)
1407 self.assertEqual(
1408 str(context.exception),
1409 "descriptor 'x' for 'C' objects doesn't apply to a 'E' object",
1410 )
1411
1412 def test_private_names_are_mangled(self):
1413 class C:
1414 __slots__ = ("__priv", "__priv_")
1415
1416 def __init__(self):
1417 self.__priv = 42
1418 self.__priv_ = 8
1419
1420 c = C()
1421 self.assertEqual(c._C__priv, 42)
1422 self.assertEqual(c._C__priv_, 8)
1423
1424 def test_names_are_not_mangled(self):
1425 class C:
1426 __slots__ = ("_notpriv", "__notpriv__")
1427
1428 def __init__(self):
1429 self._notpriv = "foo"
1430 self.__notpriv__ = "bar"
1431
1432 c = C()
1433 self.assertEqual(c._notpriv, "foo")
1434 self.assertEqual(c.__notpriv__, "bar")
1435
1436
1437if __name__ == "__main__":
1438 unittest.main()