'build',
}
return ignored
+
+
+def iter_builtin_types():
+ for obj in __builtins__.values():
+ if not isinstance(obj, type):
+ continue
+ cls = obj
+ if cls.__module__ != 'builtins':
+ continue
+ yield cls
+
+
+def iter_slot_wrappers(cls):
+ assert cls.__module__ == 'builtins', cls
+
+ def is_slot_wrapper(name, value):
+ if not isinstance(value, types.WrapperDescriptorType):
+ assert not repr(value).startswith('<slot wrapper '), (cls, name, value)
+ return False
+ assert repr(value).startswith('<slot wrapper '), (cls, name, value)
+ assert callable(value), (cls, name, value)
+ assert name.startswith('__') and name.endswith('__'), (cls, name, value)
+ return True
+
+ ns = vars(cls)
+ unused = set(ns)
+ for name in dir(cls):
+ if name in ns:
+ unused.remove(name)
+
+ try:
+ value = getattr(cls, name)
+ except AttributeError:
+ # It's as though it weren't in __dir__.
+ assert name in ('__annotate__', '__annotations__', '__abstractmethods__'), (cls, name)
+ if name in ns and is_slot_wrapper(name, ns[name]):
+ unused.add(name)
+ continue
+
+ if not name.startswith('__') or not name.endswith('__'):
+ assert not is_slot_wrapper(name, value), (cls, name, value)
+ if not is_slot_wrapper(name, value):
+ if name in ns:
+ assert not is_slot_wrapper(name, ns[name]), (cls, name, value, ns[name])
+ else:
+ if name in ns:
+ assert ns[name] is value, (cls, name, value, ns[name])
+ yield name, True
+ else:
+ yield name, False
+
+ for name in unused:
+ value = ns[name]
+ if is_slot_wrapper(cls, name, value):
+ yield name, True
self.assertEqual(out, '9\n' * INIT_LOOPS)
def test_static_types_inherited_slots(self):
- slots = []
- script = ['import sys']
- from test.test_types import iter_builtin_types, iter_own_slot_wrappers
- for cls in iter_builtin_types():
- for slot in iter_own_slot_wrappers(cls):
- slots.append((cls, slot))
- attr = f'{cls.__name__}.{slot}'
- script.append(f'print("{attr}:", {attr}, file=sys.stderr)')
- script.append('')
- script = os.linesep.join(script)
-
- with contextlib.redirect_stderr(io.StringIO()) as stderr:
- exec(script)
- expected = stderr.getvalue().splitlines()
-
- out, err = self.run_embedded_interpreter("test_repeated_init_exec", script)
+ script = textwrap.dedent("""
+ import test.support
+
+ results = {}
+ def add(cls, slot, own):
+ value = getattr(cls, slot)
+ try:
+ subresults = results[cls.__name__]
+ except KeyError:
+ subresults = results[cls.__name__] = {}
+ subresults[slot] = [repr(value), own]
+
+ for cls in test.support.iter_builtin_types():
+ for slot, own in test.support.iter_slot_wrappers(cls):
+ add(cls, slot, own)
+ """)
+
+ ns = {}
+ exec(script, ns, ns)
+ all_expected = ns['results']
+ del ns
+
+ script += textwrap.dedent("""
+ import json
+ import sys
+ text = json.dumps(results)
+ print(text, file=sys.stderr)
+ """)
+ out, err = self.run_embedded_interpreter(
+ "test_repeated_init_exec", script, script)
results = err.split('--- Loop #')[1:]
results = [res.rpartition(' ---\n')[-1] for res in results]
self.maxDiff = None
- for i, result in enumerate(results, start=1):
- with self.subTest(loop=i):
- self.assertEqual(result.splitlines(), expected)
+ for i, text in enumerate(results, start=1):
+ result = json.loads(text)
+ for classname, expected in all_expected.items():
+ with self.subTest(loop=i, cls=classname):
+ slots = result.pop(classname)
+ self.assertEqual(slots, expected)
+ self.assertEqual(result, {})
self.assertEqual(out, '')
# Python test set -- part 6, built-in types
-from test.support import run_with_locale, cpython_only, MISSING_C_DOCSTRINGS
+from test.support import (
+ run_with_locale, cpython_only, iter_builtin_types, iter_slot_wrappers,
+ MISSING_C_DOCSTRINGS,
+)
from test.test_import import no_rerun
import collections.abc
from collections import namedtuple
f()
-def iter_builtin_types():
- for obj in __builtins__.values():
- if not isinstance(obj, type):
- continue
- cls = obj
- if cls.__module__ != 'builtins':
- continue
- yield cls
-
-
-@cpython_only
-def iter_own_slot_wrappers(cls):
- for name, value in vars(cls).items():
- if not name.startswith('__') or not name.endswith('__'):
- continue
- if 'slot wrapper' not in str(value):
- continue
- yield name
-
-
class TypesTests(unittest.TestCase):
def test_truth_values(self):
@cpython_only
@no_rerun('channels (and queues) might have a refleak; see gh-122199')
- def test_slot_wrappers(self):
+ def test_static_types_inherited_slots(self):
rch, sch = interpreters.create_channel()
slots = []
script = ''
for cls in iter_builtin_types():
- for slot in iter_own_slot_wrappers(cls):
- slots.append((cls, slot))
+ for slot, own in iter_slot_wrappers(cls):
+ slots.append((cls, slot, own))
attr = f'{cls.__name__}.{slot}'
script += textwrap.dedent(f"""
sch.send_nowait('{attr}: ' + repr({attr}))
exec(script)
all_expected = []
- for cls, slot in slots:
+ for cls, slot, _ in slots:
result = rch.recv()
assert result.startswith(f'{cls.__name__}.{slot}: '), (cls, slot, result)
all_expected.append(result)
"""))
interp.run(script)
- for i, _ in enumerate(slots):
+ for i, (cls, slot, _) in enumerate(slots):
with self.subTest(cls=cls, slot=slot):
expected = all_expected[i]
result = rch.recv()
&& typeobj != PyExc_StopIteration
&& typeobj != PyExc_SyntaxError
&& typeobj != PyExc_UnicodeDecodeError
- && typeobj != PyExc_UnicodeEncodeError)
+ && typeobj != PyExc_UnicodeEncodeError
+
+ && type != &PyBool_Type
+ && type != &PyBytes_Type
+ && type != &PyMemoryView_Type
+ && type != &PyComplex_Type
+ && type != &PyEnum_Type
+ && type != &PyFilter_Type
+ && type != &PyFloat_Type
+ && type != &PyFrozenSet_Type
+ && type != &PyLong_Type
+ && type != &PyMap_Type
+ && type != &PyRange_Type
+ && type != &PyReversed_Type
+ && type != &PySlice_Type
+ && type != &PyTuple_Type
+ && type != &PyUnicode_Type
+ && type != &PyZip_Type)
+
{
return 1;
}
/* This is a best-effort list of builtin types
that have their own tp_getattr function. */
if (typeobj == PyExc_BaseException
- || type == &PyBool_Type
|| type == &PyByteArray_Type
|| type == &PyBytes_Type
- || type == &PyClassMethod_Type
|| type == &PyComplex_Type
|| type == &PyDict_Type
|| type == &PyEnum_Type
|| type == &PyReversed_Type
|| type == &PySet_Type
|| type == &PySlice_Type
- || type == &PyStaticMethod_Type
|| type == &PySuper_Type
|| type == &PyTuple_Type
|| type == &PyZip_Type)
static int test_repeated_init_exec(void)
{
if (main_argc < 3) {
- fprintf(stderr, "usage: %s test_repeated_init_exec CODE\n", PROGRAM);
+ fprintf(stderr,
+ "usage: %s test_repeated_init_exec CODE ...\n", PROGRAM);
exit(1);
}
const char *code = main_argv[2];
+ int loops = main_argc > 3
+ ? main_argc - 2
+ : INIT_LOOPS;
- for (int i=1; i <= INIT_LOOPS; i++) {
- fprintf(stderr, "--- Loop #%d ---\n", i);
+ for (int i=0; i < loops; i++) {
+ fprintf(stderr, "--- Loop #%d ---\n", i+1);
fflush(stderr);
+ if (main_argc > 3) {
+ code = main_argv[i+2];
+ }
+
_testembed_Py_InitializeFromConfig();
int err = PyRun_SimpleString(code);
Py_Finalize();