From 9cdba0165475d7164a489ee6b6029db6de74b9f9 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 21 Jun 2019 17:35:44 -0600 Subject: [PATCH 001/118] Bootstrap the "c-statics" script under the test suite. --- Lib/test/test_c_statics/__init__.py | 6 ++++++ Lib/test/test_c_statics/__main__.py | 5 +++++ Lib/test/test_c_statics/c-statics.py | 9 +++++++++ Lib/test/test_c_statics/cg/__init__.py | 0 Lib/test/test_c_statics/cg/__main__.py | 28 ++++++++++++++++++++++++++ Lib/test/test_c_statics/test_cg.py | 18 +++++++++++++++++ 6 files changed, 66 insertions(+) create mode 100644 Lib/test/test_c_statics/__init__.py create mode 100644 Lib/test/test_c_statics/__main__.py create mode 100644 Lib/test/test_c_statics/c-statics.py create mode 100644 Lib/test/test_c_statics/cg/__init__.py create mode 100644 Lib/test/test_c_statics/cg/__main__.py create mode 100644 Lib/test/test_c_statics/test_cg.py diff --git a/Lib/test/test_c_statics/__init__.py b/Lib/test/test_c_statics/__init__.py new file mode 100644 index 00000000000000..bc502ef32d2916 --- /dev/null +++ b/Lib/test/test_c_statics/__init__.py @@ -0,0 +1,6 @@ +import os.path +from test.support import load_package_tests + + +def load_tests(*args): + return load_package_tests(os.path.dirname(__file__), *args) diff --git a/Lib/test/test_c_statics/__main__.py b/Lib/test/test_c_statics/__main__.py new file mode 100644 index 00000000000000..b5b017de8a8a41 --- /dev/null +++ b/Lib/test/test_c_statics/__main__.py @@ -0,0 +1,5 @@ +from . import load_tests +import unittest + + +unittest.main() diff --git a/Lib/test/test_c_statics/c-statics.py b/Lib/test/test_c_statics/c-statics.py new file mode 100644 index 00000000000000..fcd911a3e8c5d6 --- /dev/null +++ b/Lib/test/test_c_statics/c-statics.py @@ -0,0 +1,9 @@ +# This is a script equivalent of running "python -m test.test_c_statics.cg". + +from cg.__main__ import parse_args, main + + +# This is effectively copied from cg/__main__.py: +if __name__ == '__main__': + cmd, cmdkwargs = parse_args() + main(cmd, cmdkwargs) diff --git a/Lib/test/test_c_statics/cg/__init__.py b/Lib/test/test_c_statics/cg/__init__.py new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/Lib/test/test_c_statics/cg/__main__.py b/Lib/test/test_c_statics/cg/__main__.py new file mode 100644 index 00000000000000..143cdfa3786b5f --- /dev/null +++ b/Lib/test/test_c_statics/cg/__main__.py @@ -0,0 +1,28 @@ +import argparse +import sys + + +############################# +# the script + +def parse_args(prog=sys.argv[0], argv=sys.argv[1:]): + parser = argparse.ArgumentParser( + prog=prog, + ) + parser.set_defaults(cmd=None) + + args = parser.parse_args(argv) + ns = vars(args) + + cmd = ns.pop('cmd') + + return cmd, ns + + +def main(cmd, cmdkwargs): + return + + +if __name__ == '__main__': + cmd, cmdkwargs = parse_args() + main(cmd, cmdkwargs) diff --git a/Lib/test/test_c_statics/test_cg.py b/Lib/test/test_c_statics/test_cg.py new file mode 100644 index 00000000000000..25df0530a7a369 --- /dev/null +++ b/Lib/test/test_c_statics/test_cg.py @@ -0,0 +1,18 @@ +import unittest + +from .cg.__main__ import parse_args, main + + +class ParseArgsTests(unittest.TestCase): + + def test_no_args(self): + cmd, cmdkwargs = parse_args('cg', []) + + self.assertIs(cmd, None) + self.assertEqual(cmdkwargs, {}) + + +class MainTests(unittest.TestCase): + + def test_no_command(self): + main(None, {}) From cfdf57fd4c9700968137dcf4f65a98a3253e62c6 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 21 Jun 2019 18:54:55 -0600 Subject: [PATCH 002/118] Stub out the "check" and "show" commands. --- Lib/test/test_c_statics/cg/__init__.py | 23 ++++++ Lib/test/test_c_statics/cg/__main__.py | 60 ++++++++++++++- Lib/test/test_c_statics/test_cg.py | 102 ++++++++++++++++++++++++- 3 files changed, 177 insertions(+), 8 deletions(-) diff --git a/Lib/test/test_c_statics/cg/__init__.py b/Lib/test/test_c_statics/cg/__init__.py index e69de29bb2d1d6..adfc53f48acfbf 100644 --- a/Lib/test/test_c_statics/cg/__init__.py +++ b/Lib/test/test_c_statics/cg/__init__.py @@ -0,0 +1,23 @@ +import os.path + + +PKG_ROOT = os.path.dirname(__file__) +DATA_DIR = os.path.dirname(PKG_ROOT) +REPO_ROOT = os.path.dirname( + os.path.dirname( + os.path.dirname(DATA_DIR))) + +KNOWN_FILE = os.path.join(DATA_DIR, 'known.tsv') +IGNORED_FILE = os.path.join(DATA_DIR, 'ignored.tsv') + +SOURCE_DIRS = [os.path.join(REPO_ROOT, name) for name in [ + 'Include', + 'Python', + 'Parser', + 'Objects', + 'Modules', + ]] + + +# Clean up the namespace. +del os diff --git a/Lib/test/test_c_statics/cg/__main__.py b/Lib/test/test_c_statics/cg/__main__.py index 143cdfa3786b5f..7335aba339db29 100644 --- a/Lib/test/test_c_statics/cg/__main__.py +++ b/Lib/test/test_c_statics/cg/__main__.py @@ -1,26 +1,78 @@ import argparse import sys +from . import KNOWN_FILE, IGNORED_FILE, SOURCE_DIRS + + +def check(cmd, dirs=SOURCE_DIRS, *, ignored=IGNORED_FILE, known=KNOWN_FILE): + """ + Fail if there are unsupported statics variables. + + In the failure case, the list of unsupported variables + will be printed out. + """ + + +def show(cmd, dirs=SOURCE_DIRS, *, ignored=IGNORED_FILE, known=KNOWN_FILE): + """ + print out the list of found static variables. + + The variables will be distinguished as "supported" or "unsupported". + """ + ############################# # the script -def parse_args(prog=sys.argv[0], argv=sys.argv[1:]): +COMMANDS = { + 'check': check, + 'show': show, + } + +PROG = sys.argv[0] +PROG = 'c-statics.py' + + +def parse_args(prog=PROG, argv=sys.argv[1:]): + common = argparse.ArgumentParser(add_help=False) + common.add_argument('--ignored', metavar='FILE', + default=IGNORED_FILE, + help='path to file that lists ignored vars') + common.add_argument('--known', metavar='FILE', + default=KNOWN_FILE, + help='path to file that lists known types') + common.add_argument('dirs', metavar='DIR', nargs='*', + default=SOURCE_DIRS, + help='a directory to check') + parser = argparse.ArgumentParser( prog=prog, ) - parser.set_defaults(cmd=None) + subs = parser.add_subparsers(dest='cmd') + check = subs.add_parser('check', parents=[common]) + + check = subs.add_parser('show', parents=[common]) + + # Now parse the args. args = parser.parse_args(argv) ns = vars(args) cmd = ns.pop('cmd') + if not cmd: + parser.error('missing command') return cmd, ns -def main(cmd, cmdkwargs): - return +def main(cmd, cmdkwargs=None, *, _COMMANDS=COMMANDS): + try: + cmdfunc = _COMMANDS[cmd] + except KeyError: + raise ValueError( + f'unsupported cmd {cmd!r}' if cmd else 'missing cmd') + + cmdfunc(cmd, **cmdkwargs or {}) if __name__ == '__main__': diff --git a/Lib/test/test_c_statics/test_cg.py b/Lib/test/test_c_statics/test_cg.py index 25df0530a7a369..3337ac25e9cdec 100644 --- a/Lib/test/test_c_statics/test_cg.py +++ b/Lib/test/test_c_statics/test_cg.py @@ -1,18 +1,112 @@ import unittest +from . import cg from .cg.__main__ import parse_args, main class ParseArgsTests(unittest.TestCase): def test_no_args(self): - cmd, cmdkwargs = parse_args('cg', []) + with self.assertRaises(SystemExit): + parse_args('cg', []) - self.assertIs(cmd, None) - self.assertEqual(cmdkwargs, {}) + def test_check_no_args(self): + cmd, cmdkwargs = parse_args('cg', [ + 'check', + ]) + + self.assertEqual(cmd, 'check') + self.assertEqual(cmdkwargs, { + 'ignored': cg.IGNORED_FILE, + 'known': cg.KNOWN_FILE, + 'dirs': cg.SOURCE_DIRS, + }) + + def test_check_full_args(self): + cmd, cmdkwargs = parse_args('cg', [ + 'check', + '--ignored', 'spam.tsv', + '--known', 'eggs.tsv', + 'dir1', + 'dir2', + 'dir3', + ]) + + self.assertEqual(cmd, 'check') + self.assertEqual(cmdkwargs, { + 'ignored': 'spam.tsv', + 'known': 'eggs.tsv', + 'dirs': ['dir1', 'dir2', 'dir3'] + }) + + def test_show_no_args(self): + cmd, cmdkwargs = parse_args('cg', [ + 'show', + ]) + + self.assertEqual(cmd, 'show') + self.assertEqual(cmdkwargs, { + 'ignored': cg.IGNORED_FILE, + 'known': cg.KNOWN_FILE, + 'dirs': cg.SOURCE_DIRS, + }) + + def test_show_full_args(self): + cmd, cmdkwargs = parse_args('cg', [ + 'show', + '--ignored', 'spam.tsv', + '--known', 'eggs.tsv', + 'dir1', + 'dir2', + 'dir3', + ]) + + self.assertEqual(cmd, 'show') + self.assertEqual(cmdkwargs, { + 'ignored': 'spam.tsv', + 'known': 'eggs.tsv', + 'dirs': ['dir1', 'dir2', 'dir3'] + }) + + +def new_stub_commands(*names): + calls = [] + def cmdfunc(cmd, **kwargs): + calls.append((cmd, kwargs)) + commands = {name: cmdfunc for name in names} + return commands, calls class MainTests(unittest.TestCase): def test_no_command(self): - main(None, {}) + with self.assertRaises(ValueError): + main(None, {}) + + def test_check(self): + commands, calls = new_stub_commands('check', 'show') + + cmdkwargs = { + 'ignored': 'spam.tsv', + 'known': 'eggs.tsv', + 'dirs': ['dir1', 'dir2', 'dir3'], + } + main('check', cmdkwargs, _COMMANDS=commands) + + self.assertEqual(calls, [ + ('check', cmdkwargs), + ]) + + def test_show(self): + commands, calls = new_stub_commands('check', 'show') + + cmdkwargs = { + 'ignored': 'spam.tsv', + 'known': 'eggs.tsv', + 'dirs': ['dir1', 'dir2', 'dir3'], + } + main('show', cmdkwargs, _COMMANDS=commands) + + self.assertEqual(calls, [ + ('show', cmdkwargs), + ]) From 716b13d8482c12c58daeb38680c741c7e6c6ec9d Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 21 Jun 2019 19:39:30 -0600 Subject: [PATCH 003/118] Add a README. --- Lib/test/test_c_statics/README | 72 ++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 Lib/test/test_c_statics/README diff --git a/Lib/test/test_c_statics/README b/Lib/test/test_c_statics/README new file mode 100644 index 00000000000000..772b8be27008bd --- /dev/null +++ b/Lib/test/test_c_statics/README @@ -0,0 +1,72 @@ +####################################### +# C Globals and CPython Runtime State. + +CPython's C code makes extensive use of global variables (whether static +globals or static locals). Each such variable falls into one of several +categories: + +* strictly const data +* used exclusively in main or in the REPL +* process-global state (e.g. managing process-level resources + like signals and file descriptors) +* Python "global" runtime state +* per-interpreter runtime state + +The last one can be a problem as soon as anyone creates a second +interpreter (AKA "subinterpreter") in a process. It is definitely a +problem under subinterpreters if they are no longer sharing the GIL, +since the GIL protects us from a lot of race conditions. Keep in mind +that ultimately *all* objects (PyObject) should be treated as +per-interpreter state. This includes "static types", freelists, +_PyIdentifier, and singletons. Take that in for a second. It has +significant implications on where we use static variables! + +Be aware that module-global state (stored in C statics) is a kind of +per-interpreter state. There have been efforts across many years, and +still going, to provide extension module authors mechanisms to store +that state safely (see PEPs 3121, 489, etc.). + +(Note that there has been discussion around support for running multiple +Python runtimes in the same process. That would ends up with the same +problems, relative to static variables, that subinterpreters have.) + +Historically we have been bad at keeping per-interpreter state out of +static variables, mostly because until recently subinterpreters were +not widely used nor even factored in to solutions. However, the +feature is growing in popularity and use in the community. + +Mandate: "Eliminate use of static variables for per-interpreter state." + +The "c-statics.py" script in this directory, along with its accompanying +data files, are part of the effort to resolve existing problems with +our use of static variables and to prevent future problems. + +#------------------------- +## statics for actually-global state (and runtime state consolidation) + +In general, holding any kind of state in static variables +increases maintenance burden and increases the complexity of code (e.g. +we use TSS to identify the active thread state). So it is a good idea +to avoid using statics for state even if for the "global" runtime or +for process-global state. + +Relative to maintenance burden, one problem is where the runtime +state is spread throughout the codebase in dozens of individual +globals. Unlike the other globals, the runtime state represents a set +of values that are constantly shifting in a complex way. When they are +spread out it's harder to get a clear picture of what the runtime +involves. Furthermore, when they are spread out it complicates efforts +that change the runtime. + +Consequently, the globals for Python's runtime state have been +consolidated under a single top-level _PyRuntime global. No new globals +should be added for runtime state. Instead, they should be added to +_PyRuntimeState or one of its sub-structs. The tools in this directory +are run as part of the test suite to ensure that no new globals have +been added. The script can be run manually as well: + + ./python Lib/test/test_c_statics/c-statics.py check + +If it reports any globals then they should be resolved. If the globals +are runtime state then they should be folded into _PyRuntimeState. +Otherwise they should be marked as ignored. From ff1b4473d3a9788fde757259006a279be20f3a68 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sat, 22 Jun 2019 09:08:17 -0600 Subject: [PATCH 004/118] Fix a filename. --- Lib/test/test_c_statics/{test_cg.py => test___main__.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Lib/test/test_c_statics/{test_cg.py => test___main__.py} (100%) diff --git a/Lib/test/test_c_statics/test_cg.py b/Lib/test/test_c_statics/test___main__.py similarity index 100% rename from Lib/test/test_c_statics/test_cg.py rename to Lib/test/test_c_statics/test___main__.py From 7e7d52dfd2a8cbf8ed4fc0658a23f169d63c028b Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sat, 22 Jun 2019 09:14:38 -0600 Subject: [PATCH 005/118] Run the full check as part of the test suite. --- Lib/test/test_c_statics/cg/__main__.py | 1 + Lib/test/test_c_statics/test_check_c_statics.py | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 Lib/test/test_c_statics/test_check_c_statics.py diff --git a/Lib/test/test_c_statics/cg/__main__.py b/Lib/test/test_c_statics/cg/__main__.py index 7335aba339db29..768e39539c67b3 100644 --- a/Lib/test/test_c_statics/cg/__main__.py +++ b/Lib/test/test_c_statics/cg/__main__.py @@ -11,6 +11,7 @@ def check(cmd, dirs=SOURCE_DIRS, *, ignored=IGNORED_FILE, known=KNOWN_FILE): In the failure case, the list of unsupported variables will be printed out. """ + raise NotImplementedError def show(cmd, dirs=SOURCE_DIRS, *, ignored=IGNORED_FILE, known=KNOWN_FILE): diff --git a/Lib/test/test_c_statics/test_check_c_statics.py b/Lib/test/test_c_statics/test_check_c_statics.py new file mode 100644 index 00000000000000..6bd948e7d612eb --- /dev/null +++ b/Lib/test/test_c_statics/test_check_c_statics.py @@ -0,0 +1,16 @@ +import unittest + +from .cg.__main__ import main + + +class ActualChecks(unittest.TestCase): + + # XXX Also run the check in "make check". + @unittest.expectedFailure + def test_check_c_statics(self): + main('check', {}) + + +if __name__ == '__main__': + # Test needs to be a package, so we can do relative imports. + unittest.main() From 74d03d4f117f6b04ba66aa3a9e63ea0dc4959e40 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sat, 22 Jun 2019 09:16:11 -0600 Subject: [PATCH 006/118] Frame out the functional tests. --- Lib/test/test_c_statics/test_cg_functional.py | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 Lib/test/test_c_statics/test_cg_functional.py diff --git a/Lib/test/test_c_statics/test_cg_functional.py b/Lib/test/test_c_statics/test_cg_functional.py new file mode 100644 index 00000000000000..175fa4f2bea48a --- /dev/null +++ b/Lib/test/test_c_statics/test_cg_functional.py @@ -0,0 +1,30 @@ +import unittest + + +class SelfCheckTests(unittest.TestCase): + + @unittest.expectedFailure + def test_known(self): + # Make sure known macros & vartypes aren't hiding unknown local types. + # XXX finish! + raise NotImplementedError + + @unittest.expectedFailure + def test_compare_nm_results(self): + # Make sure the "show" results match the statics found by "nm" command. + # XXX Skip if "nm" is not available. + # XXX finish! + raise NotImplementedError + + +class DummySourceTests(unittest.TestCase): + + @unittest.expectedFailure + def test_check(self): + # XXX finish! + raise NotImplementedError + + @unittest.expectedFailure + def test_show(self): + # XXX finish! + raise NotImplementedError From 34d2c7cd11fa95beca554b724607301de980bd38 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sat, 22 Jun 2019 11:38:29 -0600 Subject: [PATCH 007/118] Ignore the argparse output in tests. --- Lib/test/test_c_statics/cg/__main__.py | 8 ++++++-- Lib/test/test_c_statics/test___main__.py | 10 +++++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_c_statics/cg/__main__.py b/Lib/test/test_c_statics/cg/__main__.py index 768e39539c67b3..40e9dd8e2b88ce 100644 --- a/Lib/test/test_c_statics/cg/__main__.py +++ b/Lib/test/test_c_statics/cg/__main__.py @@ -34,7 +34,7 @@ def show(cmd, dirs=SOURCE_DIRS, *, ignored=IGNORED_FILE, known=KNOWN_FILE): PROG = 'c-statics.py' -def parse_args(prog=PROG, argv=sys.argv[1:]): +def parse_args(prog=PROG, argv=sys.argv[1:], *, _fail=None): common = argparse.ArgumentParser(add_help=False) common.add_argument('--ignored', metavar='FILE', default=IGNORED_FILE, @@ -55,13 +55,17 @@ def parse_args(prog=PROG, argv=sys.argv[1:]): check = subs.add_parser('show', parents=[common]) + if _fail is None: + def _fail(msg): + parser.error(msg) + # Now parse the args. args = parser.parse_args(argv) ns = vars(args) cmd = ns.pop('cmd') if not cmd: - parser.error('missing command') + _fail('missing command') return cmd, ns diff --git a/Lib/test/test_c_statics/test___main__.py b/Lib/test/test_c_statics/test___main__.py index 3337ac25e9cdec..cb09dd8c97b1a4 100644 --- a/Lib/test/test_c_statics/test___main__.py +++ b/Lib/test/test_c_statics/test___main__.py @@ -1,3 +1,4 @@ +import sys import unittest from . import cg @@ -7,8 +8,15 @@ class ParseArgsTests(unittest.TestCase): def test_no_args(self): + self.errmsg = None + def fail(msg): + self.errmsg = msg + sys.exit(msg) + with self.assertRaises(SystemExit): - parse_args('cg', []) + parse_args('cg', [], _fail=fail) + + self.assertEqual(self.errmsg, 'missing command') def test_check_no_args(self): cmd, cmdkwargs = parse_args('cg', [ From e8e2227867bcc60ef1c045f4590fc83ee49c8cca Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sat, 22 Jun 2019 11:39:37 -0600 Subject: [PATCH 008/118] Move relevant tests to test_cg/. --- Lib/test/test_c_statics/test_cg/__init__.py | 0 Lib/test/test_c_statics/{ => test_cg}/test___main__.py | 4 ++-- .../{test_cg_functional.py => test_cg/test_functional.py} | 0 3 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 Lib/test/test_c_statics/test_cg/__init__.py rename Lib/test/test_c_statics/{ => test_cg}/test___main__.py (96%) rename Lib/test/test_c_statics/{test_cg_functional.py => test_cg/test_functional.py} (100%) diff --git a/Lib/test/test_c_statics/test_cg/__init__.py b/Lib/test/test_c_statics/test_cg/__init__.py new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/Lib/test/test_c_statics/test___main__.py b/Lib/test/test_c_statics/test_cg/test___main__.py similarity index 96% rename from Lib/test/test_c_statics/test___main__.py rename to Lib/test/test_c_statics/test_cg/test___main__.py index cb09dd8c97b1a4..1c6560d47fabd4 100644 --- a/Lib/test/test_c_statics/test___main__.py +++ b/Lib/test/test_c_statics/test_cg/test___main__.py @@ -1,8 +1,8 @@ import sys import unittest -from . import cg -from .cg.__main__ import parse_args, main +from test.test_c_statics import cg +from test.test_c_statics.cg.__main__ import parse_args, main class ParseArgsTests(unittest.TestCase): diff --git a/Lib/test/test_c_statics/test_cg_functional.py b/Lib/test/test_c_statics/test_cg/test_functional.py similarity index 100% rename from Lib/test/test_c_statics/test_cg_functional.py rename to Lib/test/test_c_statics/test_cg/test_functional.py From 69541bf7a0378d1fa285ea3771bb0cd876522820 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sat, 22 Jun 2019 11:53:51 -0600 Subject: [PATCH 009/118] Add StaticVar. --- Lib/test/test_c_statics/cg/info.py | 60 +++++ Lib/test/test_c_statics/test_cg/test_info.py | 217 +++++++++++++++++++ 2 files changed, 277 insertions(+) create mode 100644 Lib/test/test_c_statics/cg/info.py create mode 100644 Lib/test/test_c_statics/test_cg/test_info.py diff --git a/Lib/test/test_c_statics/cg/info.py b/Lib/test/test_c_statics/cg/info.py new file mode 100644 index 00000000000000..4a7e788cec1170 --- /dev/null +++ b/Lib/test/test_c_statics/cg/info.py @@ -0,0 +1,60 @@ +from collections import namedtuple +import re + + +NAME_RE = re.compile(r'^([a-zA-Z]|_\w*[a-zA-Z]\w*|[a-zA-Z]\w*)$') + + +class StaticVar(namedtuple('StaticVar', 'filename funcname name vartype')): + """Information about a single static variable.""" + + __slots__ = () + + @classmethod + def normalize_vartype(cls, vartype): + if vartype is None: + return None + + # XXX finish! + return str(vartype) + + @classmethod + def _make(cls, iterable): # The default _make() is not subclass-friendly. + return cls.__new__(cls, *iterable) + + def __new__(cls, filename, funcname, name, vartype): + self = super().__new__( + cls, + filename=str(filename) if filename else None, + funcname=str(funcname) if funcname else None, + name=str(name) if name else None, + vartype=cls.normalize_vartype(vartype) if vartype else None, + ) + return self + + # XXX Always validate? + #def __init__(self, *args, **kwargs): + # self.validate() + + # XXX The default __repr__() is not subclass-friendly (where the name changes). + #def __repr__(self): + # _, _, sig = super().__repr__().partition('(') + # return f'{self.__class__.__name__}({sig}' + + def validate(self): + """Fail if the StaticVar is invalid (i.e. init with bad data).""" + for field in self._fields: + value = getattr(self, field) + if value is None: + if field == 'funcname': # The field can be missing (net set). + continue + raise TypeError(f'missing {field}') + elif field not in ('filename', 'vartype'): + if not NAME_RE.match(value): + raise ValueError(f'{field} must be a name, got {value!r}') + + # XXX Always validate? + #def _replace(self, **kwargs): + # obj = super()._replace(**kwargs) + # obj.validate() + # return obj diff --git a/Lib/test/test_c_statics/test_cg/test_info.py b/Lib/test/test_c_statics/test_cg/test_info.py new file mode 100644 index 00000000000000..b8e0120052e96e --- /dev/null +++ b/Lib/test/test_c_statics/test_cg/test_info.py @@ -0,0 +1,217 @@ +import string +import unittest + +from test.test_c_statics.cg.info import StaticVar + + +class PseudoStr(str): + pass + +class Proxy: + def __init__(self, value): + self.value = value + def __str__(self): + return self.value + +class Object: + def __repr__(self): + return '' + + +class StaticVarTests(unittest.TestCase): + + VALID_ARGS = ( + 'x/y/z/spam.c', + 'func', + 'eggs', + 'int', + ) + VALID_KWARGS = dict(zip(StaticVar._fields, VALID_ARGS)) + VALID_EXPECTED = VALID_ARGS + + def test_normalize_vartype(self): + tests = [ + (None, None), + ('', ''), + ('int', 'int'), + (PseudoStr('int'), 'int'), + (Proxy('int'), 'int'), + ] + for vartype, expected in tests: + with self.subTest(vartype): + normalized = StaticVar.normalize_vartype(vartype) + + self.assertEqual(normalized, expected) + + def test_init_typical_global(self): + static = StaticVar( + filename='x/y/z/spam.c', + funcname=None, + name='eggs', + vartype='int', + ) + + self.assertEqual(static, ( + 'x/y/z/spam.c', + None, + 'eggs', + 'int', + )) + + def test_init_typical_local(self): + static = StaticVar( + filename='x/y/z/spam.c', + funcname='func', + name='eggs', + vartype='int', + ) + + self.assertEqual(static, ( + 'x/y/z/spam.c', + 'func', + 'eggs', + 'int', + )) + + def test_coercion_typical(self): + static = StaticVar( + filename='x/y/z/spam.c', + funcname='func', + name='eggs', + vartype='int', + ) + + self.assertEqual(static, ( + 'x/y/z/spam.c', + 'func', + 'eggs', + 'int', + )) + + def test_init_all_missing(self): + for value in ('', None): + with self.subTest(repr(value)): + static = StaticVar( + filename=value, + funcname=value, + name=value, + vartype=value, + ) + + self.assertEqual(static, ( + None, + None, + None, + None, + )) + + def test_init_all_coerced(self): + tests = [ + ('str subclass', + dict( + filename=PseudoStr('x/y/z/spam.c'), + funcname=PseudoStr('func'), + name=PseudoStr('eggs'), + vartype=PseudoStr('int'), + ), + ('x/y/z/spam.c', + 'func', + 'eggs', + 'int', + )), + ('non-str', + dict( + filename=Proxy('x/y/z/spam.c'), + funcname=Proxy('func'), + name=('a', 'b', 'c'), + vartype=Object(), + ), + ('x/y/z/spam.c', + 'func', + "('a', 'b', 'c')", + '', + )), + ] + for summary, kwargs, expected in tests: + with self.subTest(summary): + static = StaticVar(**kwargs) + + for field in StaticVar._fields: + value = getattr(static, field) + self.assertIs(type(value), str) + self.assertEqual(tuple(static), expected) + + def test_iterable(self): + static = StaticVar(**self.VALID_KWARGS) + + filename, funcname, name, vartype = static + + values = (filename, funcname, name, vartype) + for value, expected in zip(values, self.VALID_EXPECTED): + self.assertEqual(value, expected) + + def test_fields(self): + static = StaticVar('a', 'b', 'z', 'x') + + self.assertEqual(static.filename, 'a') + self.assertEqual(static.funcname, 'b') + self.assertEqual(static.name, 'z') + self.assertEqual(static.vartype, 'x') + + def test_validate_typical(self): + static = StaticVar( + filename='x/y/z/spam.c', + funcname='func', + name='eggs', + vartype='int', + ) + + static.validate() # This does not fail. + + def test_validate_missing_field(self): + for field in StaticVar._fields: + with self.subTest(field): + static = StaticVar(**self.VALID_KWARGS) + static = static._replace(**{field: None}) + + if field == 'funcname': + static.validate() # The field can be missing (not set). + continue + + with self.assertRaises(TypeError): + static.validate() + + def test_validate_bad_field(self): + badch = tuple(c for c in string.punctuation + string.digits) + notnames = ( + '1a', + 'a.b', + 'a-b', + '&a', + 'a++', + ) + badch + tests = [ + ('filename', ()), # Any non-empty str is okay. + ('funcname', notnames), + ('name', notnames), + ('vartype', ()), # Any non-empty str is okay. + ] + seen = set() + for field, invalid in tests: + for value in invalid: + seen.add(value) + with self.subTest(f'{field}={value!r}'): + static = StaticVar(**self.VALID_KWARGS) + static = static._replace(**{field: value}) + + with self.assertRaises(ValueError): + static.validate() + + for field, invalid in tests: + valid = seen - set(invalid) + for value in valid: + with self.subTest(f'{field}={value!r}'): + static = StaticVar(**self.VALID_KWARGS) + static = static._replace(**{field: value}) + + static.validate() # This does not fail. From cab1fc8d8718f8760f9287f5de83562509bcd073 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sat, 22 Jun 2019 13:13:13 -0600 Subject: [PATCH 010/118] Add a fake find.statics(). --- Lib/test/test_c_statics/cg/find.py | 82 ++++++++++++++++++++ Lib/test/test_c_statics/test_cg/test_find.py | 72 +++++++++++++++++ 2 files changed, 154 insertions(+) create mode 100644 Lib/test/test_c_statics/cg/find.py create mode 100644 Lib/test/test_c_statics/test_cg/test_find.py diff --git a/Lib/test/test_c_statics/cg/find.py b/Lib/test/test_c_statics/cg/find.py new file mode 100644 index 00000000000000..bbbe0c4f21b8b5 --- /dev/null +++ b/Lib/test/test_c_statics/cg/find.py @@ -0,0 +1,82 @@ +from . import info + + +def statics(dirs, ignored, known): + """Return a list of (StaticVar, ) for each found static var.""" + if not dirs: + return [] + + return [ + (info.StaticVar( + filename='src1/spam.c', + funcname=None, + name='var1', + vartype='const char *', + ), + True, + ), + (info.StaticVar( + filename='src1/spam.c', + funcname='ham', + name='initialized', + vartype='int', + ), + True, + ), + (info.StaticVar( + filename='src1/spam.c', + funcname=None, + name='var2', + vartype='PyObject *', + ), + False, + ), + (info.StaticVar( + filename='src1/eggs.c', + funcname='tofu', + name='ready', + vartype='int', + ), + False, + ), + (info.StaticVar( + filename='src1/spam.c', + funcname=None, + name='freelist', + vartype='(PyTupleObject *)[10]', + ), + False, + ), + (info.StaticVar( + filename='src1/sub/ham.c', + funcname=None, + name='var1', + vartype='const char const *', + ), + True, + ), + (info.StaticVar( + filename='src2/jam.c', + funcname=None, + name='var1', + vartype='int', + ), + True, + ), + (info.StaticVar( + filename='src2/jam.c', + funcname=None, + name='var2', + vartype='MyObject *', + ), + False, + ), + (info.StaticVar( + filename='Include/spam.h', + funcname=None, + name='data', + vartype='const int', + ), + True, + ), + ] diff --git a/Lib/test/test_c_statics/test_cg/test_find.py b/Lib/test/test_c_statics/test_cg/test_find.py new file mode 100644 index 00000000000000..3a13102b6c8879 --- /dev/null +++ b/Lib/test/test_c_statics/test_cg/test_find.py @@ -0,0 +1,72 @@ +import unittest + +from test.test_c_statics.cg import info +from test.test_c_statics.cg.find import statics + + +def supported_global(filename, name, vartype): + static = info.StaticVar(filename, None, name, vartype) + return static, True + + +def unsupported_global(filename, name, vartype): + static = info.StaticVar(filename, None, name, vartype) + return static, False + + +def supported_local(filename, funcname, name, vartype): + static = info.StaticVar(filename, funcname, name, vartype) + return static, True + + +def unsupported_local(filename, funcname, name, vartype): + static = info.StaticVar(filename, funcname, name, vartype) + return static, False + + +class StaticsTest(unittest.TestCase): + + maxDiff = None + + def test_typical(self): + found = statics( + ['src1', 'src2', 'Include'], + 'ignored.tsv', + 'known.tsv', + ) + + self.assertEqual(found, [ + supported_global('src1/spam.c', 'var1', 'const char *'), + supported_local('src1/spam.c', 'ham', 'initialized', 'int'), + unsupported_global('src1/spam.c', 'var2', 'PyObject *'), + unsupported_local('src1/eggs.c', 'tofu', 'ready', 'int'), + unsupported_global('src1/spam.c', 'freelist', '(PyTupleObject *)[10]'), + supported_global('src1/sub/ham.c', 'var1', 'const char const *'), + supported_global('src2/jam.c', 'var1', 'int'), + unsupported_global('src2/jam.c', 'var2', 'MyObject *'), + supported_global('Include/spam.h', 'data', 'const int'), + ]) + + def test_no_modifiers(self): + found = statics( + ['src1', 'src2', 'Include'], + '', + '', + ) + + self.assertEqual(found, [ + supported_global('src1/spam.c', 'var1', 'const char *'), + supported_local('src1/spam.c', 'ham', 'initialized', 'int'), + unsupported_global('src1/spam.c', 'var2', 'PyObject *'), + unsupported_local('src1/eggs.c', 'tofu', 'ready', 'int'), + unsupported_global('src1/spam.c', 'freelist', '(PyTupleObject *)[10]'), + supported_global('src1/sub/ham.c', 'var1', 'const char const *'), + supported_global('src2/jam.c', 'var1', 'int'), + unsupported_global('src2/jam.c', 'var2', 'MyObject *'), + supported_global('Include/spam.h', 'data', 'const int'), + ]) + + def test_no_dirs(self): + found = statics([], '', '') + + self.assertEqual(found, []) From 4bf5299ebd853d2d9b8b6343872cb31a2309aa40 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sat, 22 Jun 2019 13:55:49 -0600 Subject: [PATCH 011/118] Add show.basic(). --- Lib/test/test_c_statics/cg/show.py | 10 ++++ Lib/test/test_c_statics/test_cg/test_show.py | 48 ++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 Lib/test/test_c_statics/cg/show.py create mode 100644 Lib/test/test_c_statics/test_cg/test_show.py diff --git a/Lib/test/test_c_statics/cg/show.py b/Lib/test/test_c_statics/cg/show.py new file mode 100644 index 00000000000000..2c6a6239d22176 --- /dev/null +++ b/Lib/test/test_c_statics/cg/show.py @@ -0,0 +1,10 @@ + +def basic(statics, *, + _print=print): + """Print each row simply.""" + for static in statics: + if static.funcname: + line = f'{static.filename}:{static.funcname}():{static.name}' + else: + line = f'{static.filename}:{static.name}' + _print(line) diff --git a/Lib/test/test_c_statics/test_cg/test_show.py b/Lib/test/test_c_statics/test_cg/test_show.py new file mode 100644 index 00000000000000..5e4becacc64061 --- /dev/null +++ b/Lib/test/test_c_statics/test_cg/test_show.py @@ -0,0 +1,48 @@ +import unittest + +from test.test_c_statics.cg import info +from test.test_c_statics.cg.show import basic + + +TYPICAL = [ + info.StaticVar('src1/spam.c', None, 'var1', 'const char *'), + info.StaticVar('src1/spam.c', 'ham', 'initialized', 'int'), + info.StaticVar('src1/spam.c', None, 'var2', 'PyObject *'), + info.StaticVar('src1/eggs.c', 'tofu', 'ready', 'int'), + info.StaticVar('src1/spam.c', None, 'freelist', '(PyTupleObject *)[10]'), + info.StaticVar('src1/sub/ham.c', None, 'var1', 'const char const *'), + info.StaticVar('src2/jam.c', None, 'var1', 'int'), + info.StaticVar('src2/jam.c', None, 'var2', 'MyObject *'), + info.StaticVar('Include/spam.h', None, 'data', 'const int'), + ] + + +class BasicTests(unittest.TestCase): + + def setUp(self): + self.lines = [] + + def print(self, line): + self.lines.append(line) + + def test_typical(self): + basic(TYPICAL, + _print=self.print) + + self.assertEqual(self.lines, [ + 'src1/spam.c:var1', + 'src1/spam.c:ham():initialized', + 'src1/spam.c:var2', + 'src1/eggs.c:tofu():ready', + 'src1/spam.c:freelist', + 'src1/sub/ham.c:var1', + 'src2/jam.c:var1', + 'src2/jam.c:var2', + 'Include/spam.h:data', + ]) + + def test_no_rows(self): + basic([], + _print=self.print) + + self.assertEqual(self.lines, []) From c74360ff83347686749ea0852dbf29670d0cc909 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sat, 22 Jun 2019 14:37:52 -0600 Subject: [PATCH 012/118] Implement cmd_show(). --- Lib/test/test_c_statics/cg/__main__.py | 33 +++++- .../test_c_statics/test_cg/test___main__.py | 102 +++++++++++++++++- 2 files changed, 129 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_c_statics/cg/__main__.py b/Lib/test/test_c_statics/cg/__main__.py index 40e9dd8e2b88ce..41afa4dc75e545 100644 --- a/Lib/test/test_c_statics/cg/__main__.py +++ b/Lib/test/test_c_statics/cg/__main__.py @@ -1,10 +1,13 @@ import argparse import sys -from . import KNOWN_FILE, IGNORED_FILE, SOURCE_DIRS +from . import ( + KNOWN_FILE, IGNORED_FILE, SOURCE_DIRS, + find, show, + ) -def check(cmd, dirs=SOURCE_DIRS, *, ignored=IGNORED_FILE, known=KNOWN_FILE): +def cmd_check(cmd, dirs=SOURCE_DIRS, *, ignored=IGNORED_FILE, known=KNOWN_FILE): """ Fail if there are unsupported statics variables. @@ -14,20 +17,40 @@ def check(cmd, dirs=SOURCE_DIRS, *, ignored=IGNORED_FILE, known=KNOWN_FILE): raise NotImplementedError -def show(cmd, dirs=SOURCE_DIRS, *, ignored=IGNORED_FILE, known=KNOWN_FILE): +def cmd_show(cmd, dirs=SOURCE_DIRS, *, + ignored=IGNORED_FILE, known=KNOWN_FILE, + _find=find.statics, + _show=show.basic, + _print=print, + ): """ print out the list of found static variables. The variables will be distinguished as "supported" or "unsupported". """ + allsupported = [] + allunsupported = [] + for found, supported in _find(dirs, ignored, known): + (allsupported if supported else allunsupported + ).append(found) + + _print('supported:') + _print('----------') + _show(allsupported) + # XXX totals? + _print() + _print('unsupported:') + _print('------------') + _show(allunsupported) + # XXX totals? ############################# # the script COMMANDS = { - 'check': check, - 'show': show, + 'check': cmd_check, + 'show': cmd_show, } PROG = sys.argv[0] diff --git a/Lib/test/test_c_statics/test_cg/test___main__.py b/Lib/test/test_c_statics/test_cg/test___main__.py index 1c6560d47fabd4..9e0055574159e1 100644 --- a/Lib/test/test_c_statics/test_cg/test___main__.py +++ b/Lib/test/test_c_statics/test_cg/test___main__.py @@ -2,7 +2,107 @@ import unittest from test.test_c_statics import cg -from test.test_c_statics.cg.__main__ import parse_args, main +from test.test_c_statics.cg import info +from test.test_c_statics.cg.__main__ import cmd_show, parse_args, main + + +TYPICAL = [ + (info.StaticVar('src1/spam.c', None, 'var1', 'const char *'), + True, + ), + (info.StaticVar('src1/spam.c', 'ham', 'initialized', 'int'), + True, + ), + (info.StaticVar('src1/spam.c', None, 'var2', 'PyObject *'), + False, + ), + (info.StaticVar('src1/eggs.c', 'tofu', 'ready', 'int'), + True, + ), + (info.StaticVar('src1/spam.c', None, 'freelist', '(PyTupleObject *)[10]'), + False, + ), + (info.StaticVar('src1/sub/ham.c', None, 'var1', 'const char const *'), + True, + ), + (info.StaticVar('src2/jam.c', None, 'var1', 'int'), + True, + ), + (info.StaticVar('src2/jam.c', None, 'var2', 'MyObject *'), + False, + ), + (info.StaticVar('Include/spam.h', None, 'data', 'const int'), + True, + ), + ] + + +class ShowTests(unittest.TestCase): + + maxDiff = None + + _return_find = () + + @property + def calls(self): + try: + return self._calls + except AttributeError: + self._calls = [] + return self._calls + + def _find(self, *args): + self.calls.append(('_find', args)) + return self._return_find + + def _show(self, *args): + self.calls.append(('_show', args)) + + def _print(self, *args): + self.calls.append(('_print', args)) + + def test_defaults(self): + self._return_find = [] + + cmd_show('show', + _find=self._find, + _show=self._show, + _print=self._print, + ) + + self.assertEqual(self.calls[0], ( + '_find', ( + cg.SOURCE_DIRS, + cg.IGNORED_FILE, + cg.KNOWN_FILE, + ), + )) + + def test_typical(self): + self._return_find = TYPICAL + dirs = ['src1', 'src2', 'Include'] + + cmd_show('show', + dirs, + ignored='ignored.tsv', + known='known.tsv', + _find=self._find, + _show=self._show, + _print=self._print, + ) + + supported = [v for v, s in TYPICAL if s] + unsupported = [v for v, s in TYPICAL if not s] + self.assertEqual(self.calls, [ + ('_find', (dirs, 'ignored.tsv', 'known.tsv')), + ('_print', ('supported:',)), + ('_print', ('----------',)), + ('_show', (supported,)), + ('_print', ()), + ('_print', ('unsupported:',)), + ('_print', ('------------',)), + ('_show', (unsupported,)), + ]) class ParseArgsTests(unittest.TestCase): From b94833d38b5629803ed36296c427db867c17bab9 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sat, 22 Jun 2019 15:39:16 -0600 Subject: [PATCH 013/118] Add a note about the normalized vartype format. --- Lib/test/test_c_statics/cg/info.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/test/test_c_statics/cg/info.py b/Lib/test/test_c_statics/cg/info.py index 4a7e788cec1170..23f4f5354a1302 100644 --- a/Lib/test/test_c_statics/cg/info.py +++ b/Lib/test/test_c_statics/cg/info.py @@ -16,6 +16,7 @@ def normalize_vartype(cls, vartype): return None # XXX finish! + # XXX Return (modifiers, type, pointer)? return str(vartype) @classmethod From 6fecaad0d8ba980d0bd414e9c329b8b55862ee9d Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sat, 22 Jun 2019 15:46:13 -0600 Subject: [PATCH 014/118] Do not run tests for find.statics() yet. --- Lib/test/test_c_statics/test_cg/test_find.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Lib/test/test_c_statics/test_cg/test_find.py b/Lib/test/test_c_statics/test_cg/test_find.py index 3a13102b6c8879..7b254d9a19bec1 100644 --- a/Lib/test/test_c_statics/test_cg/test_find.py +++ b/Lib/test/test_c_statics/test_cg/test_find.py @@ -28,7 +28,9 @@ class StaticsTest(unittest.TestCase): maxDiff = None + @unittest.expectedFailure def test_typical(self): + raise NotImplementedError found = statics( ['src1', 'src2', 'Include'], 'ignored.tsv', @@ -47,7 +49,9 @@ def test_typical(self): supported_global('Include/spam.h', 'data', 'const int'), ]) + @unittest.expectedFailure def test_no_modifiers(self): + raise NotImplementedError found = statics( ['src1', 'src2', 'Include'], '', From 8a53e698ceee39d6c32172ea0d80a36fa29797cf Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sat, 22 Jun 2019 15:48:49 -0600 Subject: [PATCH 015/118] Implement cmd_check(). --- Lib/test/test_c_statics/cg/__main__.py | 28 ++++++-- .../test_c_statics/test_cg/test___main__.py | 68 ++++++++++++++++++- 2 files changed, 87 insertions(+), 9 deletions(-) diff --git a/Lib/test/test_c_statics/cg/__main__.py b/Lib/test/test_c_statics/cg/__main__.py index 41afa4dc75e545..1bbda5251fc54a 100644 --- a/Lib/test/test_c_statics/cg/__main__.py +++ b/Lib/test/test_c_statics/cg/__main__.py @@ -7,22 +7,36 @@ ) -def cmd_check(cmd, dirs=SOURCE_DIRS, *, ignored=IGNORED_FILE, known=KNOWN_FILE): +def cmd_check(cmd, dirs=SOURCE_DIRS, *, + ignored=IGNORED_FILE, known=KNOWN_FILE, + _find=find.statics, + _show=show.basic, + _print=print, + ): """ Fail if there are unsupported statics variables. In the failure case, the list of unsupported variables will be printed out. """ - raise NotImplementedError + unsupported = [v for v, s in _find(dirs, ignored, known) if not s] + if not unsupported: + #_print('okay') + return + + _print('ERROR: found unsupported static variables') + _print() + _show(unsupported) + # XXX totals? + sys.exit(1) def cmd_show(cmd, dirs=SOURCE_DIRS, *, - ignored=IGNORED_FILE, known=KNOWN_FILE, - _find=find.statics, - _show=show.basic, - _print=print, - ): + ignored=IGNORED_FILE, known=KNOWN_FILE, + _find=find.statics, + _show=show.basic, + _print=print, + ): """ print out the list of found static variables. diff --git a/Lib/test/test_c_statics/test_cg/test___main__.py b/Lib/test/test_c_statics/test_cg/test___main__.py index 9e0055574159e1..ddc384ee26e093 100644 --- a/Lib/test/test_c_statics/test_cg/test___main__.py +++ b/Lib/test/test_c_statics/test_cg/test___main__.py @@ -3,7 +3,7 @@ from test.test_c_statics import cg from test.test_c_statics.cg import info -from test.test_c_statics.cg.__main__ import cmd_show, parse_args, main +from test.test_c_statics.cg.__main__ import cmd_check, cmd_show, parse_args, main TYPICAL = [ @@ -37,7 +37,7 @@ ] -class ShowTests(unittest.TestCase): +class CMDBase(unittest.TestCase): maxDiff = None @@ -61,6 +61,70 @@ def _show(self, *args): def _print(self, *args): self.calls.append(('_print', args)) + +class CheckTests(CMDBase): + + def test_defaults(self): + self._return_find = [] + + cmd_check('check', + _find=self._find, + _show=self._show, + _print=self._print, + ) + + self.assertEqual(self.calls[0], ( + '_find', ( + cg.SOURCE_DIRS, + cg.IGNORED_FILE, + cg.KNOWN_FILE, + ), + )) + + def test_all_supported(self): + self._return_find = [(v, s) for v, s in TYPICAL if s] + dirs = ['src1', 'src2', 'Include'] + + cmd_check('check', + dirs, + ignored='ignored.tsv', + known='known.tsv', + _find=self._find, + _show=self._show, + _print=self._print, + ) + + self.assertEqual(self.calls, [ + ('_find', (dirs, 'ignored.tsv', 'known.tsv')), + #('_print', ('okay',)), + ]) + + def test_some_unsupported(self): + self._return_find = TYPICAL + dirs = ['src1', 'src2', 'Include'] + + with self.assertRaises(SystemExit) as cm: + cmd_check('check', + dirs, + ignored='ignored.tsv', + known='known.tsv', + _find=self._find, + _show=self._show, + _print=self._print, + ) + + unsupported = [v for v, s in TYPICAL if not s] + self.assertEqual(self.calls, [ + ('_find', (dirs, 'ignored.tsv', 'known.tsv')), + ('_print', ('ERROR: found unsupported static variables',)), + ('_print', ()), + ('_show', (unsupported,)), + ]) + self.assertEqual(cm.exception.code, 1) + + +class ShowTests(CMDBase): + def test_defaults(self): self._return_find = [] From 98d373740664878a24ecd7d4fa0837343d4f87f7 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sat, 22 Jun 2019 16:51:59 -0600 Subject: [PATCH 016/118] Add scan.iter_statics(). --- Lib/test/test_c_statics/cg/scan.py | 4 ++++ Lib/test/test_c_statics/test_cg/test_scan.py | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 Lib/test/test_c_statics/cg/scan.py create mode 100644 Lib/test/test_c_statics/test_cg/test_scan.py diff --git a/Lib/test/test_c_statics/cg/scan.py b/Lib/test/test_c_statics/cg/scan.py new file mode 100644 index 00000000000000..75ffc0944056dc --- /dev/null +++ b/Lib/test/test_c_statics/cg/scan.py @@ -0,0 +1,4 @@ + +def iter_statics(filename): + """Yield a StaticVar for each one found in the file.""" + raise NotimplementedError diff --git a/Lib/test/test_c_statics/test_cg/test_scan.py b/Lib/test/test_c_statics/test_cg/test_scan.py new file mode 100644 index 00000000000000..984c31b967d17e --- /dev/null +++ b/Lib/test/test_c_statics/test_cg/test_scan.py @@ -0,0 +1,16 @@ +import unittest + +from test.test_c_statics.cg import info +from test.test_c_statics.cg.scan import iter_statics + + +class IterStaticsTests(unittest.TestCase): + + @unittest.expectedFailure + def test_typical(self): + found = list(iter_statics('spam.c')) + + self.assertEqual(found, [ + info.StaticVar('spam.c', None, 'var1', 'int'), + # ... + ]) From 28e0f99d21666ee33d730406256c8d239c178e60 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sat, 22 Jun 2019 16:52:43 -0600 Subject: [PATCH 017/118] Add supported.is_supported(). --- Lib/test/test_c_statics/cg/supported.py | 10 ++++++ .../test_c_statics/test_cg/test_supported.py | 31 +++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 Lib/test/test_c_statics/cg/supported.py create mode 100644 Lib/test/test_c_statics/test_cg/test_supported.py diff --git a/Lib/test/test_c_statics/cg/supported.py b/Lib/test/test_c_statics/cg/supported.py new file mode 100644 index 00000000000000..a97147c0777132 --- /dev/null +++ b/Lib/test/test_c_statics/cg/supported.py @@ -0,0 +1,10 @@ + +def is_supported(static): + """Return True if the given static variable is okay in CPython.""" + # XXX finish! + raise NotImplementedError + for part in static.vartype.split(): + # XXX const is automatic True? + if part == 'PyObject' or part.startswith('PyObject['): + return False + return True diff --git a/Lib/test/test_c_statics/test_cg/test_supported.py b/Lib/test/test_c_statics/test_cg/test_supported.py new file mode 100644 index 00000000000000..d9359d8299e99c --- /dev/null +++ b/Lib/test/test_c_statics/test_cg/test_supported.py @@ -0,0 +1,31 @@ +import unittest + +from test.test_c_statics.cg import info +from test.test_c_statics.cg.supported import is_supported + + +class IsSupportedTests(unittest.TestCase): + + @unittest.expectedFailure + def test_supported(self): + statics = [ + info.StaticVar('src1/spam.c', None, 'var1', 'const char *'), + info.StaticVar('src1/spam.c', None, 'var1', 'int'), + ] + for static in statics: + with self.subTest(static): + result = is_supported(static) + + self.assertTrue(result) + + @unittest.expectedFailure + def test_not_supported(self): + statics = [ + info.StaticVar('src1/spam.c', None, 'var1', 'PyObject *'), + info.StaticVar('src1/spam.c', None, 'var1', 'PyObject[10]'), + ] + for static in statics: + with self.subTest(static): + result = is_supported(static) + + self.assertFalse(result) From 1d6696c4b154bdcb05584a13c3bb148efc4de1d3 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sat, 22 Jun 2019 16:53:17 -0600 Subject: [PATCH 018/118] Add find.statics(). --- Lib/test/test_c_statics/cg/find.py | 104 +++++-------------- Lib/test/test_c_statics/test_cg/test_find.py | 101 +++++++++--------- 2 files changed, 80 insertions(+), 125 deletions(-) diff --git a/Lib/test/test_c_statics/cg/find.py b/Lib/test/test_c_statics/cg/find.py index bbbe0c4f21b8b5..6e84cf7c9e9f87 100644 --- a/Lib/test/test_c_statics/cg/find.py +++ b/Lib/test/test_c_statics/cg/find.py @@ -1,82 +1,32 @@ -from . import info +import os +import os.path +from . import info, scan +from .supported import is_supported -def statics(dirs, ignored, known): + +def _iter_files(dirnames): + for dirname in dirnames: + for parent, _, names in os.walk(dirname): + for name in names: + yield os.path.join(parent, name) + + +def _iter_statics(dirnames): + for filename in _iter_files(dirnames): + yield from scan.iter_statics(filename) + + +def statics(dirnames, ignored, known, *, + _iter_statics=_iter_statics, + _is_supported=is_supported, + ): """Return a list of (StaticVar, ) for each found static var.""" - if not dirs: + if not dirnames: return [] - return [ - (info.StaticVar( - filename='src1/spam.c', - funcname=None, - name='var1', - vartype='const char *', - ), - True, - ), - (info.StaticVar( - filename='src1/spam.c', - funcname='ham', - name='initialized', - vartype='int', - ), - True, - ), - (info.StaticVar( - filename='src1/spam.c', - funcname=None, - name='var2', - vartype='PyObject *', - ), - False, - ), - (info.StaticVar( - filename='src1/eggs.c', - funcname='tofu', - name='ready', - vartype='int', - ), - False, - ), - (info.StaticVar( - filename='src1/spam.c', - funcname=None, - name='freelist', - vartype='(PyTupleObject *)[10]', - ), - False, - ), - (info.StaticVar( - filename='src1/sub/ham.c', - funcname=None, - name='var1', - vartype='const char const *', - ), - True, - ), - (info.StaticVar( - filename='src2/jam.c', - funcname=None, - name='var1', - vartype='int', - ), - True, - ), - (info.StaticVar( - filename='src2/jam.c', - funcname=None, - name='var2', - vartype='MyObject *', - ), - False, - ), - (info.StaticVar( - filename='Include/spam.h', - funcname=None, - name='data', - vartype='const int', - ), - True, - ), - ] + found = [] + for static in _iter_statics(dirnames): + found.append( + (static, _is_supported(static))) + return found diff --git a/Lib/test/test_c_statics/test_cg/test_find.py b/Lib/test/test_c_statics/test_cg/test_find.py index 7b254d9a19bec1..eb1a1f685d4ce2 100644 --- a/Lib/test/test_c_statics/test_cg/test_find.py +++ b/Lib/test/test_c_statics/test_cg/test_find.py @@ -4,71 +4,76 @@ from test.test_c_statics.cg.find import statics -def supported_global(filename, name, vartype): - static = info.StaticVar(filename, None, name, vartype) - return static, True +class _Base(unittest.TestCase): +# _return_iter_statics = () +# _return_is_supported = () -def unsupported_global(filename, name, vartype): - static = info.StaticVar(filename, None, name, vartype) - return static, False + @property + def calls(self): + try: + return self._calls + except AttributeError: + self._calls = [] + return self._calls + def add_static(self, filename, funcname, name, vartype, *, supported=True): + static = info.StaticVar(filename, funcname, name, vartype) + try: + statics = self._return_iter_statics + except AttributeError: + statics = self._return_iter_statics = [] + statics.append(static) -def supported_local(filename, funcname, name, vartype): - static = info.StaticVar(filename, funcname, name, vartype) - return static, True + try: + unsupported = self._return_is_supported + except AttributeError: + unsupported = self._return_is_supported = set() + if not supported: + unsupported.add(static) + return static, supported -def unsupported_local(filename, funcname, name, vartype): - static = info.StaticVar(filename, funcname, name, vartype) - return static, False + def _iter_statics(self, *args): + self.calls.append(('_iter_statics', args)) + return iter(self._return_iter_statics) + def _is_supported(self, static): + self.calls.append(('_is_supported', (static,))) + return static not in self._return_is_supported -class StaticsTest(unittest.TestCase): + +class StaticsTest(_Base): maxDiff = None - @unittest.expectedFailure def test_typical(self): - raise NotImplementedError + expected = [ + self.add_static('src1/spam.c', None, 'var1', 'const char *'), + self.add_static('src1/spam.c', 'ham', 'initialized', 'int'), + self.add_static('src1/spam.c', None, 'var2', 'PyObject *', supported=False), + self.add_static('src1/eggs.c', 'tofu', 'ready', 'int', supported=False), + self.add_static('src1/spam.c', None, 'freelist', '(PyTupleObject *)[10]', supported=False), + self.add_static('src1/sub/ham.c', None, 'var1', 'const char const *'), + self.add_static('src2/jam.c', None, 'var1', 'int'), + self.add_static('src2/jam.c', None, 'var2', 'MyObject *', supported=False), + self.add_static('Include/spam.h', None, 'data', 'const int'), + ] + dirs = ['src1', 'src2', 'Include'] + found = statics( - ['src1', 'src2', 'Include'], + dirs, 'ignored.tsv', 'known.tsv', + _iter_statics=self._iter_statics, + _is_supported=self._is_supported, ) - self.assertEqual(found, [ - supported_global('src1/spam.c', 'var1', 'const char *'), - supported_local('src1/spam.c', 'ham', 'initialized', 'int'), - unsupported_global('src1/spam.c', 'var2', 'PyObject *'), - unsupported_local('src1/eggs.c', 'tofu', 'ready', 'int'), - unsupported_global('src1/spam.c', 'freelist', '(PyTupleObject *)[10]'), - supported_global('src1/sub/ham.c', 'var1', 'const char const *'), - supported_global('src2/jam.c', 'var1', 'int'), - unsupported_global('src2/jam.c', 'var2', 'MyObject *'), - supported_global('Include/spam.h', 'data', 'const int'), - ]) - - @unittest.expectedFailure - def test_no_modifiers(self): - raise NotImplementedError - found = statics( - ['src1', 'src2', 'Include'], - '', - '', - ) - - self.assertEqual(found, [ - supported_global('src1/spam.c', 'var1', 'const char *'), - supported_local('src1/spam.c', 'ham', 'initialized', 'int'), - unsupported_global('src1/spam.c', 'var2', 'PyObject *'), - unsupported_local('src1/eggs.c', 'tofu', 'ready', 'int'), - unsupported_global('src1/spam.c', 'freelist', '(PyTupleObject *)[10]'), - supported_global('src1/sub/ham.c', 'var1', 'const char const *'), - supported_global('src2/jam.c', 'var1', 'int'), - unsupported_global('src2/jam.c', 'var2', 'MyObject *'), - supported_global('Include/spam.h', 'data', 'const int'), - ]) + self.assertEqual(found, expected) + self.assertEqual(self.calls, [ + ('_iter_statics', (dirs,)), + ] + [('_is_supported', (v,)) + for v, _ in expected]) def test_no_dirs(self): found = statics([], '', '') From 7e09aa43ce037c60ba05c35a3467f30e3ddc4c02 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sat, 22 Jun 2019 18:14:59 -0600 Subject: [PATCH 019/118] Sort the output. --- Lib/test/test_c_statics/cg/__main__.py | 6 +++--- Lib/test/test_c_statics/cg/info.py | 12 ++++++++++++ Lib/test/test_c_statics/test_cg/test___main__.py | 6 +++--- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_c_statics/cg/__main__.py b/Lib/test/test_c_statics/cg/__main__.py index 1bbda5251fc54a..e75409c8910888 100644 --- a/Lib/test/test_c_statics/cg/__main__.py +++ b/Lib/test/test_c_statics/cg/__main__.py @@ -26,7 +26,7 @@ def cmd_check(cmd, dirs=SOURCE_DIRS, *, _print('ERROR: found unsupported static variables') _print() - _show(unsupported) + _show(sorted(unsupported)) # XXX totals? sys.exit(1) @@ -50,12 +50,12 @@ def cmd_show(cmd, dirs=SOURCE_DIRS, *, _print('supported:') _print('----------') - _show(allsupported) + _show(sorted(allsupported)) # XXX totals? _print() _print('unsupported:') _print('------------') - _show(allunsupported) + _show(sorted(allunsupported)) # XXX totals? diff --git a/Lib/test/test_c_statics/cg/info.py b/Lib/test/test_c_statics/cg/info.py index 23f4f5354a1302..67efec4a86518d 100644 --- a/Lib/test/test_c_statics/cg/info.py +++ b/Lib/test/test_c_statics/cg/info.py @@ -42,6 +42,18 @@ def __new__(cls, filename, funcname, name, vartype): # _, _, sig = super().__repr__().partition('(') # return f'{self.__class__.__name__}({sig}' + # To make sorting work with None: + def __lt__(self, other): + try: + return super().__lt__(other) + except TypeError: + if None in self: + return True + elif None in other: + return False + else: + raise + def validate(self): """Fail if the StaticVar is invalid (i.e. init with bad data).""" for field in self._fields: diff --git a/Lib/test/test_c_statics/test_cg/test___main__.py b/Lib/test/test_c_statics/test_cg/test___main__.py index ddc384ee26e093..488639e4b3e425 100644 --- a/Lib/test/test_c_statics/test_cg/test___main__.py +++ b/Lib/test/test_c_statics/test_cg/test___main__.py @@ -118,7 +118,7 @@ def test_some_unsupported(self): ('_find', (dirs, 'ignored.tsv', 'known.tsv')), ('_print', ('ERROR: found unsupported static variables',)), ('_print', ()), - ('_show', (unsupported,)), + ('_show', (sorted(unsupported),)), ]) self.assertEqual(cm.exception.code, 1) @@ -161,11 +161,11 @@ def test_typical(self): ('_find', (dirs, 'ignored.tsv', 'known.tsv')), ('_print', ('supported:',)), ('_print', ('----------',)), - ('_show', (supported,)), + ('_show', (sorted(supported),)), ('_print', ()), ('_print', ('unsupported:',)), ('_print', ('------------',)), - ('_show', (unsupported,)), + ('_show', (sorted(unsupported),)), ]) From 265098d3b557a455dd39daa42d4c621f3b69d502 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sat, 22 Jun 2019 19:06:32 -0600 Subject: [PATCH 020/118] Implement scan.iter_statics(). --- Lib/test/test_c_statics/cg/find.py | 19 +----- Lib/test/test_c_statics/cg/scan.py | 28 +++++++- Lib/test/test_c_statics/cg/symbols.py | 70 ++++++++++++++++++++ Lib/test/test_c_statics/test_cg/test_find.py | 1 + Lib/test/test_c_statics/test_cg/test_scan.py | 54 +++++++++++++-- 5 files changed, 148 insertions(+), 24 deletions(-) create mode 100644 Lib/test/test_c_statics/cg/symbols.py diff --git a/Lib/test/test_c_statics/cg/find.py b/Lib/test/test_c_statics/cg/find.py index 6e84cf7c9e9f87..2ee1dedd8f30a8 100644 --- a/Lib/test/test_c_statics/cg/find.py +++ b/Lib/test/test_c_statics/cg/find.py @@ -1,24 +1,9 @@ -import os -import os.path - -from . import info, scan +from . import scan from .supported import is_supported -def _iter_files(dirnames): - for dirname in dirnames: - for parent, _, names in os.walk(dirname): - for name in names: - yield os.path.join(parent, name) - - -def _iter_statics(dirnames): - for filename in _iter_files(dirnames): - yield from scan.iter_statics(filename) - - def statics(dirnames, ignored, known, *, - _iter_statics=_iter_statics, + _iter_statics=scan.iter_statics, _is_supported=is_supported, ): """Return a list of (StaticVar, ) for each found static var.""" diff --git a/Lib/test/test_c_statics/cg/scan.py b/Lib/test/test_c_statics/cg/scan.py index 75ffc0944056dc..3fb9d370bd288d 100644 --- a/Lib/test/test_c_statics/cg/scan.py +++ b/Lib/test/test_c_statics/cg/scan.py @@ -1,4 +1,28 @@ +#import os +#import os.path -def iter_statics(filename): +from . import info, symbols + + +def iter_statics(dirnames, *, + _iter_symbols=symbols.iter_binary, + ): """Yield a StaticVar for each one found in the file.""" - raise NotimplementedError + for symbol in _iter_symbols(): + if symbol.kind is not symbols.Symbol.KIND.VARIABLE: + continue + if symbol.external: + continue + yield info.StaticVar( + filename=symbol.filename or '', + funcname='' if not symbol.filename else None, + name=symbol.name, + vartype='???', + ) + + +#def _iter_files(dirnames): +# for dirname in dirnames: +# for parent, _, names in os.walk(dirname): +# for name in names: +# yield os.path.join(parent, name) diff --git a/Lib/test/test_c_statics/cg/symbols.py b/Lib/test/test_c_statics/cg/symbols.py new file mode 100644 index 00000000000000..bd6e049c422b96 --- /dev/null +++ b/Lib/test/test_c_statics/cg/symbols.py @@ -0,0 +1,70 @@ +from collections import namedtuple +import os.path +import shutil +import subprocess + +from . import REPO_ROOT + + +PYTHON = os.path.join(REPO_ROOT, 'python') + + +class Symbol(namedtuple('Symbol', 'name kind external filename')): + """Info for a single symbol compiled into a binary executable.""" + + class KIND: + VARIABLE = 'variable' + FUNCTION = 'function' + OTHER = 'other' + + +def iter_binary(binary=PYTHON): + """Yield a Symbol for each symbol found in the binary.""" + if not os.path.exists(binary): + raise Exception('executable missing (need to build it first?)') + yield from _iter_symbols_nm(binary) + + +############################# +# "nm" + +NM_KINDS = { + 'b': Symbol.KIND.VARIABLE, # uninitialized + 'd': Symbol.KIND.VARIABLE, # initialized + #'g': Symbol.KIND.VARIABLE, # uninitialized + #'s': Symbol.KIND.VARIABLE, # initialized + 't': Symbol.KIND.FUNCTION, + } + + +def _iter_symbols_nm(binary): + nm = shutil.which('nm') + try: + out = subprocess.check_output([nm, + '--line-numbers', + binary]) + except Exception: + if nm is None: + # XXX Use dumpbin.exe /SYMBOLS on Windows. + raise NotImplementedError + raise + for line in out.decode('utf-8').splitlines(): + yield _parse_nm_line(line) + + +def _parse_nm_line(line): + _, _, line = line.partition(' ') # strip off the address + line = line.strip() + + kind, _, line = line.partition(' ') + line = line.strip() + external = kind.isupper() + kind = NM_KINDS.get(kind.lower(), Symbol.KIND.OTHER) + + name, _, filename = line.partition('\t') + name = name.strip() + + if filename: + filename = os.path.relpath(filename.partition(':')[0]) + + return Symbol(name, kind, external, filename or None) diff --git a/Lib/test/test_c_statics/test_cg/test_find.py b/Lib/test/test_c_statics/test_cg/test_find.py index eb1a1f685d4ce2..ee039cfbab37fa 100644 --- a/Lib/test/test_c_statics/test_cg/test_find.py +++ b/Lib/test/test_c_statics/test_cg/test_find.py @@ -79,3 +79,4 @@ def test_no_dirs(self): found = statics([], '', '') self.assertEqual(found, []) + self.assertEqual(self.calls, []) diff --git a/Lib/test/test_c_statics/test_cg/test_scan.py b/Lib/test/test_c_statics/test_cg/test_scan.py index 984c31b967d17e..9b88d83a85a53e 100644 --- a/Lib/test/test_c_statics/test_cg/test_scan.py +++ b/Lib/test/test_c_statics/test_cg/test_scan.py @@ -1,16 +1,60 @@ import unittest -from test.test_c_statics.cg import info +from test.test_c_statics.cg import info, symbols from test.test_c_statics.cg.scan import iter_statics class IterStaticsTests(unittest.TestCase): - @unittest.expectedFailure + _return_iter_symbols = () + + @property + def calls(self): + try: + return self._calls + except AttributeError: + self._calls = [] + return self._calls + + def _iter_symbols(self, *args): + self.calls.append(('_iter_symbols', args)) + return iter(self. _return_iter_symbols) + def test_typical(self): - found = list(iter_statics('spam.c')) + self._return_iter_symbols = [ + symbols.Symbol('var1', 'variable', False, 'dir1/spam.c'), + symbols.Symbol('var2', 'variable', False, 'dir1/spam.c'), + symbols.Symbol('func1', 'function', False, 'dir1/spam.c'), + symbols.Symbol('func2', 'function', True, 'dir1/spam.c'), + symbols.Symbol('var3', 'variable', False, 'dir1/spam.c'), + symbols.Symbol('var4-1', 'variable', False, None), + symbols.Symbol('var1', 'variable', True, 'dir1/ham.c'), + symbols.Symbol('var1', 'variable', False, 'dir1/eggs.c'), + symbols.Symbol('xyz', 'other', False, 'dir1/eggs.c'), + symbols.Symbol('???', 'other', False, None), + ] + + found = list(iter_statics(['dir1'], + _iter_symbols=self._iter_symbols)) self.assertEqual(found, [ - info.StaticVar('spam.c', None, 'var1', 'int'), - # ... + info.StaticVar('dir1/spam.c', None, 'var1', '???'), + info.StaticVar('dir1/spam.c', None, 'var2', '???'), + info.StaticVar('dir1/spam.c', None, 'var3', '???'), + info.StaticVar('', '', 'var4-1', '???'), + info.StaticVar('dir1/eggs.c', None, 'var1', '???'), + ]) + self.assertEqual(self.calls, [ + ('_iter_symbols', ()), + ]) + + def test_no_symbols(self): + self._return_iter_symbols = [] + + found = list(iter_statics(['dir1'], + _iter_symbols=self._iter_symbols)) + + self.assertEqual(found, []) + self.assertEqual(self.calls, [ + ('_iter_symbols', ()), ]) From ac70e2c04258f4e1c64890efa786e70d33f2d144 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sat, 29 Jun 2019 12:58:30 -0600 Subject: [PATCH 021/118] Add cg.files.iter_files(). --- Lib/test/test_c_statics/cg/files.py | 25 ++ Lib/test/test_c_statics/cg/scan.py | 10 - Lib/test/test_c_statics/test_cg/test_files.py | 240 ++++++++++++++++++ 3 files changed, 265 insertions(+), 10 deletions(-) create mode 100644 Lib/test/test_c_statics/cg/files.py create mode 100644 Lib/test/test_c_statics/test_cg/test_files.py diff --git a/Lib/test/test_c_statics/cg/files.py b/Lib/test/test_c_statics/cg/files.py new file mode 100644 index 00000000000000..bf925f8ddc356c --- /dev/null +++ b/Lib/test/test_c_statics/cg/files.py @@ -0,0 +1,25 @@ +import os +import os.path + + +def iter_files(dirnames, filter_by_name=None, *, + _walk=os.walk, + ): + """Yield each file in the tree for each of the given directory names.""" + if filter_by_name is None: + def filter_by_name(name): + return True + elif not callable(filter_by_name): + suffixes = tuple(filter_by_name) + def filter_by_name(name): + for suffix in suffixes: + if name.endswith(suffix): + return True + return False + + for dirname in dirnames: + for parent, _, names in _walk(dirname): + for name in names: + if not filter_by_name(name): + continue + yield os.path.join(parent, name) diff --git a/Lib/test/test_c_statics/cg/scan.py b/Lib/test/test_c_statics/cg/scan.py index 3fb9d370bd288d..d5db16d7889599 100644 --- a/Lib/test/test_c_statics/cg/scan.py +++ b/Lib/test/test_c_statics/cg/scan.py @@ -1,6 +1,3 @@ -#import os -#import os.path - from . import info, symbols @@ -19,10 +16,3 @@ def iter_statics(dirnames, *, name=symbol.name, vartype='???', ) - - -#def _iter_files(dirnames): -# for dirname in dirnames: -# for parent, _, names in os.walk(dirname): -# for name in names: -# yield os.path.join(parent, name) diff --git a/Lib/test/test_c_statics/test_cg/test_files.py b/Lib/test/test_c_statics/test_cg/test_files.py new file mode 100644 index 00000000000000..e86e135a49256c --- /dev/null +++ b/Lib/test/test_c_statics/test_cg/test_files.py @@ -0,0 +1,240 @@ +import os.path +import unittest + +from test.test_c_statics.cg.files import iter_files + + +def fixpath(filename): + return filename.replace('/', os.path.sep) + + +class IterFilesTests(unittest.TestCase): + + _return_walk = None + + @property + def calls(self): + try: + return self._calls + except AttributeError: + self._calls = [] + return self._calls + + def _walk(self, dirname): + self.calls.append(('_walk', (dirname,))) + return iter(self._return_walk.pop(0)) + + def test_basic(self): + self._return_walk = [ + [('spam', (), ('file1', 'file2')), + ], + [(fixpath('eggs/ham'), (), ('file3',)), + ], + ] + dirnames = [ + 'spam', + fixpath('eggs/ham'), + ] + filter_by_name = None + + files = list(iter_files(dirnames, filter_by_name, + _walk=self._walk)) + + self.assertEqual(files, [ + fixpath('spam/file1'), + fixpath('spam/file2'), + fixpath('eggs/ham/file3'), + ]) + self.assertEqual(self.calls, [ + ('_walk', ('spam',)), + ('_walk', (fixpath('eggs/ham'),)), + ]) + + def test_no_dirnames(self): + dirnames = [] + filter_by_name = None + + files = list(iter_files(dirnames, filter_by_name, + _walk=self._walk)) + + self.assertEqual(files, []) + self.assertEqual(self.calls, []) + + def test_no_filter(self): + self._return_walk = [ + [('spam', (), ('file1', 'file2.c', 'file3.h', 'file4.o')), + ], + ] + dirnames = [ + 'spam', + ] + filter_by_name = None + + files = list(iter_files(dirnames, filter_by_name, + _walk=self._walk)) + + self.assertEqual(files, [ + fixpath('spam/file1'), + fixpath('spam/file2.c'), + fixpath('spam/file3.h'), + fixpath('spam/file4.o'), + ]) + self.assertEqual(self.calls, [ + ('_walk', ('spam',)), + ]) + + def test_no_files(self): + self._return_walk = [ + [('spam', (), ()), + ], + [(fixpath('eggs/ham'), (), ()), + ], + ] + dirnames = [ + 'spam', + fixpath('eggs/ham'), + ] + filter_by_name = None + + files = list(iter_files(dirnames, filter_by_name, + _walk=self._walk)) + + self.assertEqual(files, []) + self.assertEqual(self.calls, [ + ('_walk', ('spam',)), + ('_walk', (fixpath('eggs/ham'),)), + ]) + + def test_tree(self): + self._return_walk = [ + [('spam', ('sub1', 'sub2', 'sub3'), ('file1',)), + (fixpath('spam/sub1'), ('sub1sub1',), ('file2', 'file3')), + (fixpath('spam/sub1/sub1sub1'), (), ('file4',)), + (fixpath('spam/sub2'), (), ()), + (fixpath('spam/sub3'), (), ('file5',)), + ], + [(fixpath('eggs/ham'), (), ('file6',)), + ], + ] + dirnames = [ + 'spam', + fixpath('eggs/ham'), + ] + filter_by_name = None + + files = list(iter_files(dirnames, filter_by_name, + _walk=self._walk)) + + self.assertEqual(files, [ + fixpath('spam/file1'), + fixpath('spam/sub1/file2'), + fixpath('spam/sub1/file3'), + fixpath('spam/sub1/sub1sub1/file4'), + fixpath('spam/sub3/file5'), + fixpath('eggs/ham/file6'), + ]) + self.assertEqual(self.calls, [ + ('_walk', ('spam',)), + ('_walk', (fixpath('eggs/ham'),)), + ]) + + def test_filter_suffixes(self): + self._return_walk = [ + [('spam', (), ('file1', 'file2.c', 'file3.h', 'file4.o')), + ], + ] + dirnames = [ + 'spam', + ] + filter_by_name = ('.c', '.h') + + files = list(iter_files(dirnames, filter_by_name, + _walk=self._walk)) + + self.assertEqual(files, [ + fixpath('spam/file2.c'), + fixpath('spam/file3.h'), + ]) + self.assertEqual(self.calls, [ + ('_walk', ('spam',)), + ]) + + def test_some_filtered(self): + self._return_walk = [ + [('spam', (), ('file1', 'file2', 'file3', 'file4')), + ], + ] + dirnames = [ + 'spam', + ] + def filter_by_name(filename, results=[False, True, False, True]): + self.calls.append(('filter_by_name', (filename,))) + return results.pop(0) + + files = list(iter_files(dirnames, filter_by_name, + _walk=self._walk)) + + self.assertEqual(files, [ + fixpath('spam/file2'), + fixpath('spam/file4'), + ]) + self.assertEqual(self.calls, [ + ('_walk', ('spam',)), + ('filter_by_name', ('file1',)), + ('filter_by_name', ('file2',)), + ('filter_by_name', ('file3',)), + ('filter_by_name', ('file4',)), + ]) + + def test_none_filtered(self): + self._return_walk = [ + [('spam', (), ('file1', 'file2', 'file3', 'file4')), + ], + ] + dirnames = [ + 'spam', + ] + def filter_by_name(filename, results=[True, True, True, True]): + self.calls.append(('filter_by_name', (filename,))) + return results.pop(0) + + files = list(iter_files(dirnames, filter_by_name, + _walk=self._walk)) + + self.assertEqual(files, [ + fixpath('spam/file1'), + fixpath('spam/file2'), + fixpath('spam/file3'), + fixpath('spam/file4'), + ]) + self.assertEqual(self.calls, [ + ('_walk', ('spam',)), + ('filter_by_name', ('file1',)), + ('filter_by_name', ('file2',)), + ('filter_by_name', ('file3',)), + ('filter_by_name', ('file4',)), + ]) + + def test_all_filtered(self): + self._return_walk = [ + [('spam', (), ('file1', 'file2', 'file3', 'file4')), + ], + ] + dirnames = [ + 'spam', + ] + def filter_by_name(filename, results=[False, False, False, False]): + self.calls.append(('filter_by_name', (filename,))) + return results.pop(0) + + files = list(iter_files(dirnames, filter_by_name, + _walk=self._walk)) + + self.assertEqual(files, []) + self.assertEqual(self.calls, [ + ('_walk', ('spam',)), + ('filter_by_name', ('file1',)), + ('filter_by_name', ('file2',)), + ('filter_by_name', ('file3',)), + ('filter_by_name', ('file4',)), + ]) From 587907cf61c677599ba0a89da6b9f1d367629611 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sat, 29 Jun 2019 15:34:23 -0600 Subject: [PATCH 022/118] Add cg.info.Symbol. --- Lib/test/test_c_statics/cg/info.py | 95 +++++++- Lib/test/test_c_statics/test_cg/test_info.py | 217 +++++++++++++++++-- 2 files changed, 288 insertions(+), 24 deletions(-) diff --git a/Lib/test/test_c_statics/cg/info.py b/Lib/test/test_c_statics/cg/info.py index 67efec4a86518d..98dab6526767be 100644 --- a/Lib/test/test_c_statics/cg/info.py +++ b/Lib/test/test_c_statics/cg/info.py @@ -5,19 +5,92 @@ NAME_RE = re.compile(r'^([a-zA-Z]|_\w*[a-zA-Z]\w*|[a-zA-Z]\w*)$') -class StaticVar(namedtuple('StaticVar', 'filename funcname name vartype')): - """Information about a single static variable.""" +def normalize_vartype(vartype): + """Return the canonical form for a variable type (or func signature).""" + # We allow empty strring through for semantic reasons. + if vartype is None: + return None + + # XXX finish! + # XXX Return (modifiers, type, pointer)? + return str(vartype) + + +class Symbol(namedtuple('Symbol', + 'name kind external filename funcname declaration')): + """Info for a single compilation symbol.""" __slots__ = () + class KIND: + VARIABLE = 'variable' + FUNCTION = 'function' + OTHER = 'other' + @classmethod - def normalize_vartype(cls, vartype): - if vartype is None: - return None + def _make(cls, iterable): # The default _make() is not subclass-friendly. + return cls.__new__(cls, *iterable) + + def __new__(cls, name, kind=KIND.VARIABLE, external=None, + filename=None, funcname=None, declaration=None): + self = super().__new__( + cls, + name=str(name) if name else None, + kind=str(kind) if kind else None, + external=bool(external) if external is not None else None, + filename=str(filename) if filename else None, + funcname=str(funcname) if funcname else None, + declaration=normalize_vartype(declaration), + ) + return self - # XXX finish! - # XXX Return (modifiers, type, pointer)? - return str(vartype) + # XXX Always validate? + #def __init__(self, *args, **kwargs): + # self.validate() + + # XXX The default __repr__() is not subclass-friendly (where the name changes). + #def __repr__(self): + # _, _, sig = super().__repr__().partition('(') + # return f'{self.__class__.__name__}({sig}' + + def validate(self): + """Fail if the object is invalid (i.e. init with bad data).""" + if not self.name: + raise TypeError('missing name') + elif not NAME_RE.match(self.name): + raise ValueError(f'name must be a name, got {self.name!r}') + + if not self.kind: + raise TypeError('missing kind') + elif self.kind not in vars(Symbol.KIND).values(): + raise ValueError(f'unsupported kind {self.kind}') + + if self.external is None: + raise TypeError('missing external') + + if not self.filename and self.funcname: + raise TypeError('missing filename') + # filename, funcname and declaration can be not set. + + if not self.funcname: + # funcname can be not set. + pass + elif not NAME_RE.match(self.funcname): + raise ValueError(f'funcname must be a name, got{self.funcname!r}') + + # declaration can be not set. + + # XXX Always validate? + #def _replace(self, **kwargs): + # obj = super()._replace(**kwargs) + # obj.validate() + # return obj + + +class StaticVar(namedtuple('StaticVar', 'filename funcname name vartype')): + """Information about a single static variable.""" + + __slots__ = () @classmethod def _make(cls, iterable): # The default _make() is not subclass-friendly. @@ -29,7 +102,7 @@ def __new__(cls, filename, funcname, name, vartype): filename=str(filename) if filename else None, funcname=str(funcname) if funcname else None, name=str(name) if name else None, - vartype=cls.normalize_vartype(vartype) if vartype else None, + vartype=normalize_vartype(vartype) if vartype else None, ) return self @@ -42,7 +115,7 @@ def __new__(cls, filename, funcname, name, vartype): # _, _, sig = super().__repr__().partition('(') # return f'{self.__class__.__name__}({sig}' - # To make sorting work with None: + # To make sorting work with None (for sorting): def __lt__(self, other): try: return super().__lt__(other) @@ -55,7 +128,7 @@ def __lt__(self, other): raise def validate(self): - """Fail if the StaticVar is invalid (i.e. init with bad data).""" + """Fail if the object is invalid (i.e. init with bad data).""" for field in self._fields: value = getattr(self, field) if value is None: diff --git a/Lib/test/test_c_statics/test_cg/test_info.py b/Lib/test/test_c_statics/test_cg/test_info.py index b8e0120052e96e..f7dde1b566f36e 100644 --- a/Lib/test/test_c_statics/test_cg/test_info.py +++ b/Lib/test/test_c_statics/test_cg/test_info.py @@ -1,7 +1,9 @@ import string import unittest -from test.test_c_statics.cg.info import StaticVar +from test.test_c_statics.cg.info import ( + normalize_vartype, Symbol, StaticVar, + ) class PseudoStr(str): @@ -18,18 +20,9 @@ def __repr__(self): return '' -class StaticVarTests(unittest.TestCase): - - VALID_ARGS = ( - 'x/y/z/spam.c', - 'func', - 'eggs', - 'int', - ) - VALID_KWARGS = dict(zip(StaticVar._fields, VALID_ARGS)) - VALID_EXPECTED = VALID_ARGS +class NormalizeVartypeTests(unittest.TestCase): - def test_normalize_vartype(self): + def test_basic(self): tests = [ (None, None), ('', ''), @@ -39,10 +32,208 @@ def test_normalize_vartype(self): ] for vartype, expected in tests: with self.subTest(vartype): - normalized = StaticVar.normalize_vartype(vartype) + normalized = normalize_vartype(vartype) self.assertEqual(normalized, expected) + +class SymbolTests(unittest.TestCase): + + VALID_ARGS = ( + 'eggs', + Symbol.KIND.VARIABLE, + False, + 'x/y/z/spam.c', + 'func', + 'int', + ) + VALID_KWARGS = dict(zip(Symbol._fields, VALID_ARGS)) + VALID_EXPECTED = VALID_ARGS + + def test_init_typical_binary(self): + symbol = Symbol( + name='spam', + kind=Symbol.KIND.VARIABLE, + external=False, + filename='Python/ceval.c', + ) + + self.assertEqual(symbol, ( + 'spam', + Symbol.KIND.VARIABLE, + False, + 'Python/ceval.c', + None, + None, + )) + + def test_init_typical_source(self): + symbol = Symbol( + name='spam', + kind=Symbol.KIND.VARIABLE, + external=False, + filename='Python/ceval.c', + declaration='static const int', + ) + + self.assertEqual(symbol, ( + 'spam', + Symbol.KIND.VARIABLE, + False, + 'Python/ceval.c', + None, + 'static const int', + )) + + def test_init_coercion(self): + tests = [ + ('str subclass', + dict( + name=PseudoStr('eggs'), + kind=PseudoStr('variable'), + external=0, + filename=PseudoStr('x/y/z/spam.c'), + funcname=PseudoStr('func'), + declaration=PseudoStr('int'), + ), + ('eggs', + Symbol.KIND.VARIABLE, + False, + 'x/y/z/spam.c', + 'func', + 'int', + )), + ('non-str', + dict( + name=('a', 'b', 'c'), + kind=Proxy('variable'), + external=0, + filename=Proxy('x/y/z/spam.c'), + funcname=Proxy('func'), + declaration=Object(), + ), + ("('a', 'b', 'c')", + Symbol.KIND.VARIABLE, + False, + 'x/y/z/spam.c', + 'func', + '', + )), + ] + for summary, kwargs, expected in tests: + with self.subTest(summary): + symbol = Symbol(**kwargs) + + for field in Symbol._fields: + value = getattr(symbol, field) + if field == 'external': + self.assertIs(type(value), bool) + else: + self.assertIs(type(value), str) + self.assertEqual(tuple(symbol), expected) + + def test_init_all_missing(self): + symbol = Symbol('spam') + + self.assertEqual(symbol, ( + 'spam', + Symbol.KIND.VARIABLE, + None, + None, + None, + None, + )) + + def test_fields(self): + static = Symbol('a', 'b', False, 'z', 'x', 'w') + + self.assertEqual(static.name, 'a') + self.assertEqual(static.kind, 'b') + self.assertIs(static.external, False) + self.assertEqual(static.filename, 'z') + self.assertEqual(static.funcname, 'x') + self.assertEqual(static.declaration, 'w') + + def test_validate_typical(self): + symbol = Symbol( + name='spam', + kind=Symbol.KIND.VARIABLE, + external=False, + filename='Python/ceval.c', + declaration='static const int', + ) + + symbol.validate() # This does not fail. + + def test_validate_missing_field(self): + for field in Symbol._fields: + with self.subTest(field): + symbol = Symbol(**self.VALID_KWARGS) + symbol = symbol._replace(**{field: None}) + + if field in ('funcname', 'declaration'): + symbol.validate() # The field can be missing (not set). + continue + + with self.assertRaises(TypeError): + symbol.validate() + with self.subTest('combined'): + symbol = Symbol(**self.VALID_KWARGS) + symbol = symbol._replace(filename=None, funcname=None) + + symbol.validate() # The fields together can be missing (not set). + + def test_validate_bad_field(self): + badch = tuple(c for c in string.punctuation + string.digits) + notnames = ( + '1a', + 'a.b', + 'a-b', + '&a', + 'a++', + ) + badch + tests = [ + ('name', notnames), + ('kind', ('bogus',)), + ('filename', ()), # Any non-empty str is okay. + ('funcname', notnames), + ('declaration', ()), # Any non-empty str is okay. + ] + seen = set() + for field, invalid in tests: + for value in invalid: + if field != 'kind': + seen.add(value) + with self.subTest(f'{field}={value!r}'): + symbol = Symbol(**self.VALID_KWARGS) + symbol = symbol._replace(**{field: value}) + + with self.assertRaises(ValueError): + symbol.validate() + + for field, invalid in tests: + if field == 'kind': + continue + valid = seen - set(invalid) + for value in valid: + with self.subTest(f'{field}={value!r}'): + symbol = Symbol(**self.VALID_KWARGS) + symbol = symbol._replace(**{field: value}) + + symbol.validate() # This does not fail. + + +class StaticVarTests(unittest.TestCase): + + VALID_ARGS = ( + 'x/y/z/spam.c', + 'func', + 'eggs', + 'int', + ) + VALID_KWARGS = dict(zip(StaticVar._fields, VALID_ARGS)) + VALID_EXPECTED = VALID_ARGS + def test_init_typical_global(self): static = StaticVar( filename='x/y/z/spam.c', From 6ff136ffa0273bc5e7bac0e965535c52479f2163 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sat, 29 Jun 2019 16:10:36 -0600 Subject: [PATCH 023/118] Properly handle local variables. --- Lib/test/test_c_statics/cg/parse.py | 4 + Lib/test/test_c_statics/cg/scan.py | 8 +- Lib/test/test_c_statics/cg/symbols.py | 162 +++++++++++++++---- Lib/test/test_c_statics/test_cg/test_scan.py | 32 ++-- 4 files changed, 157 insertions(+), 49 deletions(-) create mode 100644 Lib/test/test_c_statics/cg/parse.py diff --git a/Lib/test/test_c_statics/cg/parse.py b/Lib/test/test_c_statics/cg/parse.py new file mode 100644 index 00000000000000..b3a8efa39e7afd --- /dev/null +++ b/Lib/test/test_c_statics/cg/parse.py @@ -0,0 +1,4 @@ + +def iter_variables(filename): + """Yield (funcname, name, vartype) for every variable in the given file.""" + raise NotImplementedError diff --git a/Lib/test/test_c_statics/cg/scan.py b/Lib/test/test_c_statics/cg/scan.py index d5db16d7889599..9437b49d297bb5 100644 --- a/Lib/test/test_c_statics/cg/scan.py +++ b/Lib/test/test_c_statics/cg/scan.py @@ -5,14 +5,14 @@ def iter_statics(dirnames, *, _iter_symbols=symbols.iter_binary, ): """Yield a StaticVar for each one found in the file.""" - for symbol in _iter_symbols(): - if symbol.kind is not symbols.Symbol.KIND.VARIABLE: + for symbol in _iter_symbols(dirnames): + if symbol.kind is not info.Symbol.KIND.VARIABLE: continue if symbol.external: continue yield info.StaticVar( - filename=symbol.filename or '', - funcname='' if not symbol.filename else None, + filename=symbol.filename, + funcname=symbol.funcname or None, name=symbol.name, vartype='???', ) diff --git a/Lib/test/test_c_statics/cg/symbols.py b/Lib/test/test_c_statics/cg/symbols.py index bd6e049c422b96..537005f35d09db 100644 --- a/Lib/test/test_c_statics/cg/symbols.py +++ b/Lib/test/test_c_statics/cg/symbols.py @@ -3,68 +3,172 @@ import shutil import subprocess -from . import REPO_ROOT +from . import REPO_ROOT, files, info, parse PYTHON = os.path.join(REPO_ROOT, 'python') -class Symbol(namedtuple('Symbol', 'name kind external filename')): - """Info for a single symbol compiled into a binary executable.""" +def iter_binary(dirnames, binary=PYTHON, *, + _file_exists=os.path.exists, + _find_local_symbol=(lambda *a, **k: _find_local_symbol(*a, **k)), + _iter_symbols_nm=(lambda b, fls: _iter_symbols_nm(b, fls)), + ): + """Yield a Symbol for each symbol found in the binary.""" + if not _file_exists(binary): + raise Exception('executable missing (need to build it first?)') - class KIND: - VARIABLE = 'variable' - FUNCTION = 'function' - OTHER = 'other' + cache = {} + def find_local_symbol(name): + return _find_local_symbol(name, dirnames, _perfilecache=cache) + yield from _iter_symbols_nm(binary, find_local_symbol) -def iter_binary(binary=PYTHON): - """Yield a Symbol for each symbol found in the binary.""" - if not os.path.exists(binary): - raise Exception('executable missing (need to build it first?)') - yield from _iter_symbols_nm(binary) +############################# +# C scanning (move to scan.py) + +def _get_local_symbols(filename, *, + _iter_variables=parse.iter_variables, + ): + symbols = {} + for funcname, name, vartype in _iter_variables(filename): + if not funcname: + continue + try: + instances = symbols[name] + except KeyError: + instances = symbols[name] = [] + instances.append((funcname, vartype)) + return symbols + + +def _find_local_symbol(name, dirnames, *, + _perfilecache, + _get_local_symbols=_get_local_symbols, + _iter_files=files.iter_files, + ): + for filename in _iter_files(dirnames, ('.c', '.h')): + try: + symbols = _perfilecache[filename] + except KeyError: + symbols = _perfilecache[filename] = _get_local_symbols(filename) + + try: + instances = symbols[name] + except KeyError: + continue + + funcname, vartype = instances.pop(0) + if not instances: + symbols.pop(name) + return filename, funcname, vartype + + +############################# +# binary format (e.g. ELF) + +SPECIAL_SYMBOLS = { + '__bss_start', + '__data_start', + '__dso_handle', + '_DYNAMIC', + '_edata', + '_end', + '__environ@@GLIBC_2.2.5', + '_GLOBAL_OFFSET_TABLE_', + '__JCR_END__', + '__JCR_LIST__', + '__TMC_END__', + } + + +def _is_special_symbol(name): + if name in SPECIAL_SYMBOLS: + return True + if '@@GLIBC' in name: + return True + return False ############################# # "nm" NM_KINDS = { - 'b': Symbol.KIND.VARIABLE, # uninitialized - 'd': Symbol.KIND.VARIABLE, # initialized - #'g': Symbol.KIND.VARIABLE, # uninitialized - #'s': Symbol.KIND.VARIABLE, # initialized - 't': Symbol.KIND.FUNCTION, + 'b': info.Symbol.KIND.VARIABLE, # uninitialized + 'd': info.Symbol.KIND.VARIABLE, # initialized + #'g': info.Symbol.KIND.VARIABLE, # uninitialized + #'s': info.Symbol.KIND.VARIABLE, # initialized + 't': info.Symbol.KIND.FUNCTION, } -def _iter_symbols_nm(binary): +def _iter_symbols_nm(binary, find_local_symbol=None, + *, + _run=subprocess.run, + ): nm = shutil.which('nm') + argv = [nm, + '--line-numbers', + binary, + ] try: - out = subprocess.check_output([nm, - '--line-numbers', - binary]) + proc = _run(argv, + capture_output=True, + text=True, + check=True, + ) except Exception: if nm is None: # XXX Use dumpbin.exe /SYMBOLS on Windows. raise NotImplementedError raise - for line in out.decode('utf-8').splitlines(): - yield _parse_nm_line(line) - - -def _parse_nm_line(line): + for line in proc.stdout.splitlines(): + (name, kind, external, filename, funcname, vartype, + )= _parse_nm_line(line, _find_local_symbol=find_local_symbol) + if kind != info.Symbol.KIND.VARIABLE: + continue + elif _is_special_symbol(name): + continue + elif not filename: + raise Exception(f'missing filename: {name}') + yield info.Symbol( + name=name, + kind=kind, + external=external, + filename=filename, + funcname=funcname, + declaration=vartype, + ) + + +def _parse_nm_line(line, *, _find_local_symbol=None): + _origline = line _, _, line = line.partition(' ') # strip off the address line = line.strip() kind, _, line = line.partition(' ') line = line.strip() external = kind.isupper() - kind = NM_KINDS.get(kind.lower(), Symbol.KIND.OTHER) + kind = NM_KINDS.get(kind.lower(), info.Symbol.KIND.OTHER) name, _, filename = line.partition('\t') name = name.strip() + funcname = None + vartype = None if filename: filename = os.path.relpath(filename.partition(':')[0]) - - return Symbol(name, kind, external, filename or None) + elif kind != info.Symbol.KIND.VARIABLE: + pass + elif _is_special_symbol(name): + pass + elif _find_local_symbol is not None: + orig = name + name, sep, digits = name.partition('.') + if not sep or not digits.isdigit(): + print(_origline) + raise Exception(f'expected local variable, got {orig}') + filename, funcname, vartype = _find_local_symbol(name) + +# return info.Symbol(name, kind, external, filename or None, funcname) + return name, kind, external, filename or None, funcname, vartype diff --git a/Lib/test/test_c_statics/test_cg/test_scan.py b/Lib/test/test_c_statics/test_cg/test_scan.py index 9b88d83a85a53e..690a530393bfa7 100644 --- a/Lib/test/test_c_statics/test_cg/test_scan.py +++ b/Lib/test/test_c_statics/test_cg/test_scan.py @@ -1,6 +1,6 @@ import unittest -from test.test_c_statics.cg import info, symbols +from test.test_c_statics.cg import info from test.test_c_statics.cg.scan import iter_statics @@ -16,22 +16,22 @@ def calls(self): self._calls = [] return self._calls - def _iter_symbols(self, *args): - self.calls.append(('_iter_symbols', args)) + def _iter_symbols(self, dirnames): + self.calls.append(('_iter_symbols', (dirnames,))) return iter(self. _return_iter_symbols) def test_typical(self): self._return_iter_symbols = [ - symbols.Symbol('var1', 'variable', False, 'dir1/spam.c'), - symbols.Symbol('var2', 'variable', False, 'dir1/spam.c'), - symbols.Symbol('func1', 'function', False, 'dir1/spam.c'), - symbols.Symbol('func2', 'function', True, 'dir1/spam.c'), - symbols.Symbol('var3', 'variable', False, 'dir1/spam.c'), - symbols.Symbol('var4-1', 'variable', False, None), - symbols.Symbol('var1', 'variable', True, 'dir1/ham.c'), - symbols.Symbol('var1', 'variable', False, 'dir1/eggs.c'), - symbols.Symbol('xyz', 'other', False, 'dir1/eggs.c'), - symbols.Symbol('???', 'other', False, None), + info.Symbol('var1', 'variable', False, 'dir1/spam.c', None, None), + info.Symbol('var2', 'variable', False, 'dir1/spam.c', None, None), + info.Symbol('func1', 'function', False, 'dir1/spam.c', None, None), + info.Symbol('func2', 'function', True, 'dir1/spam.c', None, None), + info.Symbol('var3', 'variable', False, 'dir1/spam.c', None, None), + info.Symbol('var4', 'variable', False, 'dir1/spam.c', 'func2', None), + info.Symbol('var1', 'variable', True, 'dir1/ham.c', None, None), + info.Symbol('var1', 'variable', False, 'dir1/eggs.c', None, None), + info.Symbol('xyz', 'other', False, 'dir1/eggs.c', None, None), + info.Symbol('???', 'other', False, None, None, None), ] found = list(iter_statics(['dir1'], @@ -41,11 +41,11 @@ def test_typical(self): info.StaticVar('dir1/spam.c', None, 'var1', '???'), info.StaticVar('dir1/spam.c', None, 'var2', '???'), info.StaticVar('dir1/spam.c', None, 'var3', '???'), - info.StaticVar('', '', 'var4-1', '???'), + info.StaticVar('dir1/spam.c', 'func2', 'var4', '???'), info.StaticVar('dir1/eggs.c', None, 'var1', '???'), ]) self.assertEqual(self.calls, [ - ('_iter_symbols', ()), + ('_iter_symbols', (['dir1'],)), ]) def test_no_symbols(self): @@ -56,5 +56,5 @@ def test_no_symbols(self): self.assertEqual(found, []) self.assertEqual(self.calls, [ - ('_iter_symbols', ()), + ('_iter_symbols', (['dir1'],)), ]) From 9faeba95ba1ab7f117a25c9a445b20f85bf916a1 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sat, 29 Jun 2019 17:41:13 -0600 Subject: [PATCH 024/118] Implement cg.parse.iter_variables(). --- Lib/test/test_c_statics/cg/parse.py | 129 ++++++++- Lib/test/test_c_statics/test_cg/test_parse.py | 274 ++++++++++++++++++ 2 files changed, 401 insertions(+), 2 deletions(-) create mode 100644 Lib/test/test_c_statics/test_cg/test_parse.py diff --git a/Lib/test/test_c_statics/cg/parse.py b/Lib/test/test_c_statics/cg/parse.py index b3a8efa39e7afd..b6ed76ede89109 100644 --- a/Lib/test/test_c_statics/cg/parse.py +++ b/Lib/test/test_c_statics/cg/parse.py @@ -1,4 +1,129 @@ +import shlex +import subprocess -def iter_variables(filename): - """Yield (funcname, name, vartype) for every variable in the given file.""" + +def iter_statements(lines): + """Yield (lines, issimple) for each statement in the given lines. + + Only the (relative) top-level statements are yielded, hence + "issimple". For compound statements (including functions), the ends + and block(s) of the statement are provided as-is. For simple + statements a single line will be provided. + """ + raise NotImplementedError + + +def parse_func(lines): + """Return (name, signature, body) for the given function definition.""" + raise NotImplementedError + + +def parse_var(lines): + """Return (name, vartype) for the given variable declaration.""" + raise NotImplementedError + + +def parse_compound(lines): + """Return (allsimple, blocks) for the given compound statement.""" + # XXX Identify declarations inside compound statements + # (if/switch/for/while). raise NotImplementedError + + +def _iter_source_lines(filename): + gcc, cflags = _get_build() + content = _preprocess(filename, gcc, cflags) + return iter(content.splitlines()) + + +def iter_variables(filename, *, + _iter_source_lines=_iter_source_lines, + _iter_statements=iter_statements, + _parse_func=parse_func, + _parse_var=parse_var, + _parse_compound=parse_compound, + ): + """Yield (funcname, name, vartype) for every variable in the given file.""" + lines = _iter_source_lines(filename) + for stmt, issimple in _iter_statements(lines): + # At the file top-level we only have to worry about vars & funcs. + if issimple: + name, vartype = _parse_var(stmt) + if name: + yield (None, name, vartype) + else: + funcname, _, body = _parse_func(stmt) + localvars = _iter_locals(body, + _iter_statements=_iter_statements, + _parse_func=_parse_func, + _parse_var=_parse_var, + _parse_compound=_parse_compound, + ) + for name, vartype in localvars: + yield (funcname, name, vartype) + + +def _iter_locals(lines, *, + _iter_statements=iter_statements, + _parse_func=parse_func, + _parse_var=parse_var, + _parse_compound=parse_compound, + ): + compound = [lines] + while compound: + block = compound.pop(0) + blocklines = block.splitlines() + for stmt, issimple in _iter_statements(blocklines): + if issimple: + name, vartype = _parse_var(stmt) + if name: + yield (name, vartype) + else: + simple, blocks = _parse_compound(stmt) + for line in simple: + name, vartype = _parse_var(line) + if name: + yield (name, vartype) + compound.extend(blocks) + + +############################# +# GCC preprocessor (platform-specific) + +def _get_build(*, + _open=open, + _run=subprocess.run, + ): + with _open('/tmp/print.mk', 'w') as tmpfile: + tmpfile.write('print-%:\n') + #tmpfile.write('\t@echo $* = $($*)\n') + tmpfile.write('\t@echo $($*)\n') + argv = ['/usr/bin/make', + '-f', 'Makefile', + '-f', '/tmp/print.mk', + 'print-CC', + 'print-PY_CORE_CFLAGS', + ] + proc = _run(argv, + capture_output=True, + text=True, + check=True, + ) + gcc, cflags = proc.stdout.strip().splitlines() + cflags = shlex.split(cflags) + return gcc, cflags + + +def _preprocess(filename, gcc, cflags, *, + _run=subprocess.run, + ): + argv = gcc.split() + cflags + argv.extend([ + '-E', filename, + ]) + proc = _run(argv, + capture_output=True, + text=True, + check=True, + ) + return proc.stdout diff --git a/Lib/test/test_c_statics/test_cg/test_parse.py b/Lib/test/test_c_statics/test_cg/test_parse.py new file mode 100644 index 00000000000000..d281db0d31b071 --- /dev/null +++ b/Lib/test/test_c_statics/test_cg/test_parse.py @@ -0,0 +1,274 @@ +import textwrap +import unittest + +from test.test_c_statics.cg.parse import ( + iter_statements, parse_func, parse_var, parse_compound, + iter_variables, + ) + + +class TestCaseBase(unittest.TestCase): + + @property + def calls(self): + try: + return self._calls + except AttributeError: + self._calls = [] + return self._calls + + +class IterStatementsTests(TestCaseBase): + + def test_(self): + ... + + +class ParseFuncTests(TestCaseBase): + + def test_(self): + ... + + +class ParseVarTests(TestCaseBase): + + def test_(self): + ... + + +class ParseCompoundTests(TestCaseBase): + + def test_(self): + ... + + +class IterVariablesTests(TestCaseBase): + + maxDiff = None + + _return_iter_source_lines = None + _return_iter_statements = None + _return_parse_func = None + _return_parse_var = None + _return_parse_compound = None + + def _iter_source_lines(self, filename): + self.calls.append( + ('_iter_source_lines', (filename,))) + return self._return_iter_source_lines.splitlines() + + def _iter_statements(self, lines): + self.calls.append( + ('_iter_statements', (lines,))) + try: + return self._return_iter_statements.pop(0) + except IndexError: + return ('???', False) + + def _parse_func(self, lines): + self.calls.append( + ('_parse_func', (lines,))) + try: + return self._return_parse_func.pop(0) + except IndexError: + return ('???', '???', '???') + + def _parse_var(self, lines): + self.calls.append( + ('_parse_var', (lines,))) + try: + return self._return_parse_var.pop(0) + except IndexError: + return ('???', '???') + + def _parse_compound(self, lines): + self.calls.append( + ('_parse_compound', (lines,))) + try: + return self._return_parse_compound.pop(0) + except IndexError: + return (['???'], ['???']) + + def test_empty_file(self): + self._return_iter_source_lines = '' + self._return_iter_statements = [ + [], + ] + self._return_parse_func = None + self._return_parse_var = None + self._return_parse_compound = None + + srcvars = list(iter_variables('spam.c', + _iter_source_lines=self._iter_source_lines, + _iter_statements=self._iter_statements, + _parse_func=self._parse_func, + _parse_var=self._parse_var, + _parse_compound=self._parse_compound, + )) + + self.assertEqual(srcvars, []) + self.assertEqual(self.calls, [ + ('_iter_source_lines', ('spam.c',)), + ('_iter_statements', ([],)), + ]) + + def test_no_statements(self): + content = textwrap.dedent(''' + ... + ''') + self._return_iter_source_lines = content + self._return_iter_statements = [ + [], + ] + self._return_parse_func = None + self._return_parse_var = None + self._return_parse_compound = None + + srcvars = list(iter_variables('spam.c', + _iter_source_lines=self._iter_source_lines, + _iter_statements=self._iter_statements, + _parse_func=self._parse_func, + _parse_var=self._parse_var, + _parse_compound=self._parse_compound, + )) + + self.assertEqual(srcvars, []) + self.assertEqual(self.calls, [ + ('_iter_source_lines', ('spam.c',)), + ('_iter_statements', (content.splitlines(),)), + ]) + + def test_typical(self): + content = textwrap.dedent(''' + ... + ''') + self._return_iter_source_lines = content + self._return_iter_statements = [ + [('', True), # var1 + ('', True), # non-var + ('', True), # var2 + ('', False), # func1 + ('', True), # var4 + ], + # func1 + [('', True), # var3 + ('', False), # if + ('', True), # non-var + ], + # if + [('', True), # var2 ("collision" with global var) + ], + ] + self._return_parse_func = [ + ('func1', '', ''), + ] + self._return_parse_var = [ + ('var1', ''), + (None, None), + ('var2', ''), + ('var3', ''), + ('var2', ''), + ('var4', ''), + (None, None), + ('var5', ''), + ] + self._return_parse_compound = [ + ([''], ['']), + ] + + srcvars = list(iter_variables('spam.c', + _iter_source_lines=self._iter_source_lines, + _iter_statements=self._iter_statements, + _parse_func=self._parse_func, + _parse_var=self._parse_var, + _parse_compound=self._parse_compound, + )) + + self.assertEqual(srcvars, [ + (None, 'var1', ''), + (None, 'var2', ''), + ('func1', 'var3', ''), + ('func1', 'var2', ''), + ('func1', 'var4', ''), + (None, 'var5', ''), + ]) + self.assertEqual(self.calls, [ + ('_iter_source_lines', ('spam.c',)), + ('_iter_statements', (content.splitlines(),)), + ('_parse_var', ('',)), + ('_parse_var', ('',)), + ('_parse_var', ('',)), + ('_parse_func', ('',)), + ('_iter_statements', ([''],)), + ('_parse_var', ('',)), + ('_parse_compound', ('',)), + ('_parse_var', ('',)), + ('_parse_var', ('',)), + ('_iter_statements', ([''],)), + ('_parse_var', ('',)), + ('_parse_var', ('',)), + ]) + + def test_no_locals(self): + content = textwrap.dedent(''' + ... + ''') + self._return_iter_source_lines = content + self._return_iter_statements = [ + [('', True), # var1 + ('', True), # non-var + ('', True), # var2 + ('', False), # func1 + ], + # func1 + [('', True), # non-var + ('', False), # if + ('', True), # non-var + ], + # if + [('', True), # non-var + ], + ] + self._return_parse_func = [ + ('func1', '', ''), + ] + self._return_parse_var = [ + ('var1', ''), + (None, None), + ('var2', ''), + (None, None), + (None, None), + (None, None), + (None, None), + ] + self._return_parse_compound = [ + ([''], ['']), + ] + + srcvars = list(iter_variables('spam.c', + _iter_source_lines=self._iter_source_lines, + _iter_statements=self._iter_statements, + _parse_func=self._parse_func, + _parse_var=self._parse_var, + _parse_compound=self._parse_compound, + )) + + self.assertEqual(srcvars, [ + (None, 'var1', ''), + (None, 'var2', ''), + ]) + self.assertEqual(self.calls, [ + ('_iter_source_lines', ('spam.c',)), + ('_iter_statements', (content.splitlines(),)), + ('_parse_var', ('',)), + ('_parse_var', ('',)), + ('_parse_var', ('',)), + ('_parse_func', ('',)), + ('_iter_statements', ([''],)), + ('_parse_var', ('',)), + ('_parse_compound', ('',)), + ('_parse_var', ('',)), + ('_parse_var', ('',)), + ('_iter_statements', ([''],)), + ('_parse_var', ('',)), + ]) From ae5c872cbfff535b5341ec9e13334fb1f3488475 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 1 Jul 2019 10:53:53 -0600 Subject: [PATCH 025/118] Start the implementation for iter_statements(). --- Lib/test/test_c_statics/cg/parse.py | 14 ++- Lib/test/test_c_statics/test_cg/test_parse.py | 119 ++++++++++++++++-- 2 files changed, 117 insertions(+), 16 deletions(-) diff --git a/Lib/test/test_c_statics/cg/parse.py b/Lib/test/test_c_statics/cg/parse.py index b6ed76ede89109..70769e1aab014e 100644 --- a/Lib/test/test_c_statics/cg/parse.py +++ b/Lib/test/test_c_statics/cg/parse.py @@ -2,7 +2,7 @@ import subprocess -def iter_statements(lines): +def iter_statements(lines, *, local=False): """Yield (lines, issimple) for each statement in the given lines. Only the (relative) top-level statements are yielded, hence @@ -10,7 +10,13 @@ def iter_statements(lines): and block(s) of the statement are provided as-is. For simple statements a single line will be provided. """ - raise NotImplementedError + # XXX Bail out upon bogus syntax. + for line in lines: + if not line.strip(): + continue + + raise NotImplementedError + yield('', True) def parse_func(lines): @@ -45,7 +51,7 @@ def iter_variables(filename, *, ): """Yield (funcname, name, vartype) for every variable in the given file.""" lines = _iter_source_lines(filename) - for stmt, issimple in _iter_statements(lines): + for stmt, issimple in _iter_statements(lines, local=False): # At the file top-level we only have to worry about vars & funcs. if issimple: name, vartype = _parse_var(stmt) @@ -73,7 +79,7 @@ def _iter_locals(lines, *, while compound: block = compound.pop(0) blocklines = block.splitlines() - for stmt, issimple in _iter_statements(blocklines): + for stmt, issimple in _iter_statements(blocklines, local=True): if issimple: name, vartype = _parse_var(stmt) if name: diff --git a/Lib/test/test_c_statics/test_cg/test_parse.py b/Lib/test/test_c_statics/test_cg/test_parse.py index d281db0d31b071..f9e0ce6fc41ca8 100644 --- a/Lib/test/test_c_statics/test_cg/test_parse.py +++ b/Lib/test/test_c_statics/test_cg/test_parse.py @@ -20,8 +20,103 @@ def calls(self): class IterStatementsTests(TestCaseBase): - def test_(self): - ... + @unittest.expectedFailure + def test_global_single(self): + raise NotImplementedError + tests = [ + ('', ('', False)), + ] + for lines, expected in tests: + with self.subTest(lines): + lines = lines.splitlines() + + stmts = list(iter_statements(lines, local=False)) + + self.assertEqual(stmts, expected) + + @unittest.expectedFailure + def test_global_mixed(self): + raise NotImplementedError + lines = textwrap.dedent(''' + ''').splitlines() + + stmts = list(iter_statements(lines, local=False)) + + self.assertEqual(stmts, [ + ('', True), + ]) + + @unittest.expectedFailure + def test_local_single(self): + raise NotImplementedError + + @unittest.expectedFailure + def test_local_mixed(self): + raise NotImplementedError + + def test_no_statements(self): + lines = textwrap.dedent(''' + ''').splitlines() + + with self.subTest('global'): + stmts = list(iter_statements(lines, local=False)) + + self.assertEqual(stmts, []) + + with self.subTest('local'): + stmts = list(iter_statements(lines, local=True)) + + self.assertEqual(stmts, []) + + @unittest.expectedFailure + def test_global_bogus(self): + raise NotImplementedError + tests = [ + ('', ('', False)), + ] + for lines, expected in tests: + with self.subTest(lines): + lines = lines.splitlines() + + stmts = list(iter_statements(lines, local=False)) + + self.assertEqual(stmts, expected) + + @unittest.expectedFailure + def test_local_bogus(self): + raise NotImplementedError + + @unittest.expectedFailure + def test_ignore_whitespace(self): + raise NotImplementedError + + @unittest.expectedFailure + def test_ignore_comments(self): + raise NotImplementedError + tests = [ + ('// msg', None), + ('// int stmt;', None), + (' // ... ', None), + ('// /*', None), + ('/* int stmt; */', None), + (""" + /** + * ... + * int stmt; + */ + """, None), + # mixed with statements +# ('int stmt; // ...', ('int stmt', True)), +# ( 'int stmt; /* ... */', ('int stmt', True)), +# ( '/* ... */ int stmt;', ('int stmt', True)), + ] + for lines, expected in tests: + with self.subTest(lines): + lines = lines.splitlines() + + stmts = list(iter_statements(lines, local=False)) + + self.assertEqual(stmts, [expected] if expected else []) class ParseFuncTests(TestCaseBase): @@ -57,9 +152,9 @@ def _iter_source_lines(self, filename): ('_iter_source_lines', (filename,))) return self._return_iter_source_lines.splitlines() - def _iter_statements(self, lines): + def _iter_statements(self, lines, local): self.calls.append( - ('_iter_statements', (lines,))) + ('_iter_statements', (lines, local))) try: return self._return_iter_statements.pop(0) except IndexError: @@ -109,7 +204,7 @@ def test_empty_file(self): self.assertEqual(srcvars, []) self.assertEqual(self.calls, [ ('_iter_source_lines', ('spam.c',)), - ('_iter_statements', ([],)), + ('_iter_statements', ([], False)), ]) def test_no_statements(self): @@ -135,7 +230,7 @@ def test_no_statements(self): self.assertEqual(srcvars, []) self.assertEqual(self.calls, [ ('_iter_source_lines', ('spam.c',)), - ('_iter_statements', (content.splitlines(),)), + ('_iter_statements', (content.splitlines(), False)), ]) def test_typical(self): @@ -194,17 +289,17 @@ def test_typical(self): ]) self.assertEqual(self.calls, [ ('_iter_source_lines', ('spam.c',)), - ('_iter_statements', (content.splitlines(),)), + ('_iter_statements', (content.splitlines(), False)), ('_parse_var', ('',)), ('_parse_var', ('',)), ('_parse_var', ('',)), ('_parse_func', ('',)), - ('_iter_statements', ([''],)), + ('_iter_statements', ([''], True)), ('_parse_var', ('',)), ('_parse_compound', ('',)), ('_parse_var', ('',)), ('_parse_var', ('',)), - ('_iter_statements', ([''],)), + ('_iter_statements', ([''], True)), ('_parse_var', ('',)), ('_parse_var', ('',)), ]) @@ -259,16 +354,16 @@ def test_no_locals(self): ]) self.assertEqual(self.calls, [ ('_iter_source_lines', ('spam.c',)), - ('_iter_statements', (content.splitlines(),)), + ('_iter_statements', (content.splitlines(), False)), ('_parse_var', ('',)), ('_parse_var', ('',)), ('_parse_var', ('',)), ('_parse_func', ('',)), - ('_iter_statements', ([''],)), + ('_iter_statements', ([''], True)), ('_parse_var', ('',)), ('_parse_compound', ('',)), ('_parse_var', ('',)), ('_parse_var', ('',)), - ('_iter_statements', ([''],)), + ('_iter_statements', ([''], True)), ('_parse_var', ('',)), ]) From 0687e098695f620e55b5b4e387997ca98db04cec Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 1 Jul 2019 10:56:16 -0600 Subject: [PATCH 026/118] Deal with comments. --- Lib/test/test_c_statics/cg/parse.py | 11 +++++++++++ Lib/test/test_c_statics/test_cg/test_parse.py | 2 -- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_c_statics/cg/parse.py b/Lib/test/test_c_statics/cg/parse.py index 70769e1aab014e..0ec8f85c7cded5 100644 --- a/Lib/test/test_c_statics/cg/parse.py +++ b/Lib/test/test_c_statics/cg/parse.py @@ -11,7 +11,18 @@ def iter_statements(lines, *, local=False): statements a single line will be provided. """ # XXX Bail out upon bogus syntax. + comment = False for line in lines: + # Deal with comments. + if comment: + _, sep, line = line.partition('*/') + if sep: + comment = False + line, _, _ = line.partition('//') + line, sep, _ = line.partition('/*') + if sep: + comment = True + if not line.strip(): continue diff --git a/Lib/test/test_c_statics/test_cg/test_parse.py b/Lib/test/test_c_statics/test_cg/test_parse.py index f9e0ce6fc41ca8..2686e85df1fcbf 100644 --- a/Lib/test/test_c_statics/test_cg/test_parse.py +++ b/Lib/test/test_c_statics/test_cg/test_parse.py @@ -90,9 +90,7 @@ def test_local_bogus(self): def test_ignore_whitespace(self): raise NotImplementedError - @unittest.expectedFailure def test_ignore_comments(self): - raise NotImplementedError tests = [ ('// msg', None), ('// int stmt;', None), From a50aa327ced93b89969f80f0c63fd6a4ed188738 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 1 Jul 2019 18:53:53 -0600 Subject: [PATCH 027/118] Handle functions in iter_global_declarations(). --- Lib/test/test_c_statics/cg/parse.py | 235 ++++++++-- Lib/test/test_c_statics/test_cg/test_parse.py | 436 ++++++++++++++---- 2 files changed, 545 insertions(+), 126 deletions(-) diff --git a/Lib/test/test_c_statics/cg/parse.py b/Lib/test/test_c_statics/cg/parse.py index 0ec8f85c7cded5..78b46c1b80d818 100644 --- a/Lib/test/test_c_statics/cg/parse.py +++ b/Lib/test/test_c_statics/cg/parse.py @@ -1,47 +1,210 @@ +import re import shlex import subprocess -def iter_statements(lines, *, local=False): - """Yield (lines, issimple) for each statement in the given lines. +IDENTIFIER = r'(?:[a-zA-z]|_+[a-zA-Z0-9]\w*)' - Only the (relative) top-level statements are yielded, hence - "issimple". For compound statements (including functions), the ends - and block(s) of the statement are provided as-is. For simple - statements a single line will be provided. +#TYPE_QUAL = r'(?:const|volatile)' + +VAR_TYPE_SPEC = r'''(?: + void | + (?: + (?:(?:un)?signed\s+)? + (?: + char | + short | + int | + long | + long\s+int | + long\s+long + ) | + ) | + float | + double | + {IDENTIFIER} | + (?:struct|union)\s+{IDENTIFIER} + )''' +#STRUCT = r'''(?: +# (?:struct|(struct\s+%s))\s*[{] +# [^}]* +# [}] +# )''' % (IDENTIFIER) +#UNION = r'''(?: +# (?:union|(union\s+%s))\s*[{] +# [^}]* +# [}] +# )''' % (IDENTIFIER) +#DECL_SPEC = rf'''(?: +# ({VAR_TYPE_SPEC}) | +# ({STRUCT}) | +# ({UNION}) +# )''' + +FUNC_START = rf'''(?: + (?: + (?: + extern | + static | + static\s+inline + )\s+ + )? + #(?:const\s+)? + {VAR_TYPE_SPEC} + )''' +#GLOBAL_VAR_START = rf'''(?: +# (?: +# (?: +# extern | +# static +# )\s+ +# )? +# (?: +# {TYPE_QUAL} +# (?:\s+{TYPE_QUAL})? +# )?\s+ +# {VAR_TYPE_SPEC} +# )''' +#LOCAL_VAR_START = rf'''(?: +# (?: +# (?: +# register | +# static +# )\s+ +# )? +# (?: +# (?: +# {TYPE_QUAL} +# (?:\s+{TYPE_QUAL})? +# )\s+ +# )? +# {VAR_TYPE_SPEC} +# )''' +GLOBAL_DECL_START_RE = re.compile(rf''' + ^ + (?: + ({FUNC_START}) + ) + ''', re.VERBOSE) + +#POINTER = rf'''(?: +# (?:\s+const)?\s*[*] +# )''' +# +#TYPEDEF = rf'''(?: +# typedef XXX {IDENTIFIER} +# )''' +#VAR_INITIALIZER = rf'''(?: +# (?:&\s*)? +# XXX +# )''' +#PARAMS = rf'''(?: +# [(] +# XXX +# [)] +# )''' + + +def iter_global_declarations(lines): + """Yield (decl, body) for each global declaration in the given lines. + + For function definitions the header is reduced to one line and + the body is provided as-is. For other compound declarations (e.g. + struct) the entire declaration is reduced to one line and "body" + is None. Likewise for simple declarations (e.g. variables). + + Declarations inside function bodies are ignored, though their text + is provided in the function body. """ # XXX Bail out upon bogus syntax. - comment = False + lines = _iter_clean_lines(lines) + for line in lines: + if not GLOBAL_DECL_START_RE.match(line): + continue + # We only need functions here, since we only need locals for now. + if line.endswith(';'): + continue + if line.endswith('{') and '(' not in line: + continue + + # Capture the function. + # (assume no func is a one-liner) + decl = line + while '{' not in line: # assume no inline structs, etc. + try: + line = next(lines) + except StopIteration: + return + decl += ' ' + line + + body, end = _extract_block(lines) + if end is None: + return + assert end == '}' + yield (f'{decl}\n{body}\n{end}', body) + + +def iter_local_statements(lines, *, local=False): + """Yield (lines, blocks) for each statement in the given lines. + + For simple statements, "blocks" is None and the statement is reduced + to a single line. For compound statements, "blocks" is a pair of + (header, body) for each block in the statement. The headers are + reduced to a single line each, but the bpdies are provided as-is. + """ + raise NotImplementedError + + +def _iter_clean_lines(lines): + incomment = False for line in lines: # Deal with comments. - if comment: + if incomment: _, sep, line = line.partition('*/') if sep: - comment = False + incomment = False + continue line, _, _ = line.partition('//') line, sep, _ = line.partition('/*') if sep: - comment = True + _, sep, line = line.partition('*/') + if not sep: + incomment = True + continue - if not line.strip(): + # Ignore blank lines and leading/trailing whitespace. + line = line.strip() + if not line: continue - raise NotImplementedError - yield('', True) + yield line + + +def _extract_block(lines): + end = None + depth = 1 + body = [] + for line in lines: + depth += line.count('{') - line.count('}') + if depth == 0: + end = line + break + body.append(line) + return '\n'.join(body), end -def parse_func(lines): - """Return (name, signature, body) for the given function definition.""" +def parse_func(stmt, body): + """Return (name, signature) for the given function definition.""" raise NotImplementedError -def parse_var(lines): +def parse_var(stmt): """Return (name, vartype) for the given variable declaration.""" raise NotImplementedError -def parse_compound(lines): - """Return (allsimple, blocks) for the given compound statement.""" +def parse_compound(stmt, blocks): + """Return (headers, bodies) for the given compound statement.""" # XXX Identify declarations inside compound statements # (if/switch/for/while). raise NotImplementedError @@ -55,24 +218,24 @@ def _iter_source_lines(filename): def iter_variables(filename, *, _iter_source_lines=_iter_source_lines, - _iter_statements=iter_statements, + _iter_global=iter_global_declarations, + _iter_local=iter_local_statements, _parse_func=parse_func, _parse_var=parse_var, _parse_compound=parse_compound, ): """Yield (funcname, name, vartype) for every variable in the given file.""" lines = _iter_source_lines(filename) - for stmt, issimple in _iter_statements(lines, local=False): + for stmt, body in _iter_global(lines): # At the file top-level we only have to worry about vars & funcs. - if issimple: + if not body: name, vartype = _parse_var(stmt) if name: yield (None, name, vartype) else: - funcname, _, body = _parse_func(stmt) + funcname, _, body = _parse_func(stmt, body) localvars = _iter_locals(body, - _iter_statements=_iter_statements, - _parse_func=_parse_func, + _iter_statements=_iter_local, _parse_var=_parse_var, _parse_compound=_parse_compound, ) @@ -81,27 +244,27 @@ def iter_variables(filename, *, def _iter_locals(lines, *, - _iter_statements=iter_statements, - _parse_func=parse_func, + _iter_statements=iter_local_statements, _parse_var=parse_var, _parse_compound=parse_compound, ): compound = [lines] while compound: - block = compound.pop(0) - blocklines = block.splitlines() - for stmt, issimple in _iter_statements(blocklines, local=True): - if issimple: + body = compound.pop(0) + bodylines = body.splitlines() + for stmt, blocks in _iter_statements(bodylines): + if not blocks: name, vartype = _parse_var(stmt) if name: yield (name, vartype) else: - simple, blocks = _parse_compound(stmt) - for line in simple: - name, vartype = _parse_var(line) - if name: - yield (name, vartype) - compound.extend(blocks) + headers, bodies = _parse_compound(stmt, blocks) + for header in headers: + for line in header: + name, vartype = _parse_var(line) + if name: + yield (name, vartype) + compound.extend(bodies) ############################# diff --git a/Lib/test/test_c_statics/test_cg/test_parse.py b/Lib/test/test_c_statics/test_cg/test_parse.py index 2686e85df1fcbf..f870167404e2ff 100644 --- a/Lib/test/test_c_statics/test_cg/test_parse.py +++ b/Lib/test/test_c_statics/test_cg/test_parse.py @@ -2,13 +2,16 @@ import unittest from test.test_c_statics.cg.parse import ( - iter_statements, parse_func, parse_var, parse_compound, + iter_global_declarations, iter_local_statements, + parse_func, parse_var, parse_compound, iter_variables, ) class TestCaseBase(unittest.TestCase): + maxDiff = None + @property def calls(self): try: @@ -18,40 +21,275 @@ def calls(self): return self._calls -class IterStatementsTests(TestCaseBase): +class IterGlobalDeclarationsTests(TestCaseBase): - @unittest.expectedFailure - def test_global_single(self): - raise NotImplementedError + def test_functions(self): tests = [ - ('', ('', False)), + (textwrap.dedent(''' + void func1() { + return; + } + '''), + textwrap.dedent(''' + void func1() { + return; + } + ''').strip(), + ), + (textwrap.dedent(''' + static unsigned int * _func1( + const char *arg1, + int *arg2 + long long arg3 + ) + { + return _do_something(arg1, arg2, arg3); + } + '''), + textwrap.dedent(''' + static unsigned int * _func1( const char *arg1, int *arg2 long long arg3 ) { + return _do_something(arg1, arg2, arg3); + } + ''').strip(), + ), + (textwrap.dedent(''' + static PyObject * + _func1(const char *arg1, PyObject *arg2) + { + static int initialized = 0; + if (!initialized) { + initialized = 1; + _init(arg1); + } + + PyObject *result = _do_something(arg1, arg2); + Py_INCREF(result); + return result; + } + '''), + textwrap.dedent(''' + static PyObject * _func1(const char *arg1, PyObject *arg2) { + static int initialized = 0; + if (!initialized) { + initialized = 1; + _init(arg1); + } + PyObject *result = _do_something(arg1, arg2); + Py_INCREF(result); + return result; + } + ''').strip(), + ), ] for lines, expected in tests: + body = textwrap.dedent( + expected.partition('{')[2].rpartition('}')[0] + ).strip() + expected = (expected, body) with self.subTest(lines): lines = lines.splitlines() - stmts = list(iter_statements(lines, local=False)) + stmts = list(iter_global_declarations(lines)) - self.assertEqual(stmts, expected) + self.assertEqual(stmts, [expected]) @unittest.expectedFailure - def test_global_mixed(self): - raise NotImplementedError - lines = textwrap.dedent(''' - ''').splitlines() + def test_global_declaration(self): + tests = [ + 'int spam;', + 'long long spam;', + 'static const int const *spam;', + 'int spam;', + 'typedef int myint;', + 'typedef PyObject * (*unaryfunc)(PyObject *);', + # typedef struct + # inline struct + # enum + # inline enum + ] + for text in tests: + expected = (text, + ' '.join(l.strip() for l in text.splitlines())) + with self.subTest(lines): + lines = lines.splitlines() + + stmts = list(iter_global_declarations(lines)) + + self.assertEqual(stmts, [expected]) + + @unittest.expectedFailure + def test_global_declaration_multiple_vars(self): + lines = ['static const int const *spam, *ham=NULL, eggs = 3;'] - stmts = list(iter_statements(lines, local=False)) + stmts = list(iter_global_declarations(lines)) self.assertEqual(stmts, [ - ('', True), + ('static const int const *spam;', True), + ('static const int *ham=NULL;', True), + ('static const int eggs = 3;', True), ]) + def test_mixed(self): + lines = textwrap.dedent(''' + int spam; + static const char const *eggs; + + PyObject * start(void) { + static int initialized = 0; + if (initialized) { + initialized = 1; + init(); + } + return _start(); + } + + char* ham; + + static int stop(char *reason) { + ham = reason; + return _stop(); + } + ''').splitlines() + expected = [ + (textwrap.dedent(''' + PyObject * start(void) { + static int initialized = 0; + if (initialized) { + initialized = 1; + init(); + } + return _start(); + } + ''').strip(), + textwrap.dedent(''' + static int initialized = 0; + if (initialized) { + initialized = 1; + init(); + } + return _start(); + ''').strip(), + ), + (textwrap.dedent(''' + static int stop(char *reason) { + ham = reason; + return _stop(); + } + ''').strip(), + textwrap.dedent(''' + ham = reason; + return _stop(); + ''').strip(), + ), + ] + + stmts = list(iter_global_declarations(lines)) + + self.assertEqual(stmts, expected) + #self.assertEqual([stmt for stmt, _ in stmts], + # [stmt for stmt, _ in expected]) + #self.assertEqual([body for _, body in stmts], + # [body for _, body in expected]) + + def test_empty(self): + lines = [] + + stmts = list(iter_global_declarations(lines)) + + self.assertEqual(stmts, []) + + def test_bogus(self): + tests = [ + (textwrap.dedent(''' + int spam; + static const char const *eggs; + + PyObject * start(void) { + static int initialized = 0; + if (initialized) { + initialized = 1; + init(); + } + return _start(); + } + + char* ham; + + static int _stop(void) { + // missing closing bracket + + static int stop(char *reason) { + ham = reason; + return _stop(); + } + '''), + [(textwrap.dedent(''' + PyObject * start(void) { + static int initialized = 0; + if (initialized) { + initialized = 1; + init(); + } + return _start(); + } + ''').strip(), + textwrap.dedent(''' + static int initialized = 0; + if (initialized) { + initialized = 1; + init(); + } + return _start(); + ''').strip(), + ), + # Neither "stop()" nor "_stop()" are here. + ], + ), + ] + for lines, expected in tests: + with self.subTest(lines): + lines = lines.splitlines() + + stmts = list(iter_global_declarations(lines)) + + self.assertEqual(stmts, expected) + #self.assertEqual([stmt for stmt, _ in stmts], + # [stmt for stmt, _ in expected]) + #self.assertEqual([body for _, body in stmts], + # [body for _, body in expected]) + + def test_ignore_comments(self): + tests = [ + ('// msg', None), + ('// int stmt;', None), + (' // ... ', None), + ('// /*', None), + ('/* int stmt; */', None), + (""" + /** + * ... + * int stmt; + */ + """, None), + ] + for lines, expected in tests: + with self.subTest(lines): + lines = lines.splitlines() + + stmts = list(iter_global_declarations(lines)) + + self.assertEqual(stmts, [expected] if expected else []) + + +@unittest.skip('not finished') +class IterLocalStatementsTests(TestCaseBase): + @unittest.expectedFailure - def test_local_single(self): + def test_single(self): raise NotImplementedError @unittest.expectedFailure - def test_local_mixed(self): + def test_mixed(self): raise NotImplementedError def test_no_statements(self): @@ -59,37 +297,20 @@ def test_no_statements(self): ''').splitlines() with self.subTest('global'): - stmts = list(iter_statements(lines, local=False)) + stmts = list(iter_local_statements(lines)) self.assertEqual(stmts, []) with self.subTest('local'): - stmts = list(iter_statements(lines, local=True)) + stmts = list(iter_local_statements(lines, local=True)) self.assertEqual(stmts, []) @unittest.expectedFailure - def test_global_bogus(self): - raise NotImplementedError - tests = [ - ('', ('', False)), - ] - for lines, expected in tests: - with self.subTest(lines): - lines = lines.splitlines() - - stmts = list(iter_statements(lines, local=False)) - - self.assertEqual(stmts, expected) - - @unittest.expectedFailure - def test_local_bogus(self): + def test_bogus(self): raise NotImplementedError @unittest.expectedFailure - def test_ignore_whitespace(self): - raise NotImplementedError - def test_ignore_comments(self): tests = [ ('// msg', None), @@ -104,15 +325,15 @@ def test_ignore_comments(self): */ """, None), # mixed with statements -# ('int stmt; // ...', ('int stmt', True)), -# ( 'int stmt; /* ... */', ('int stmt', True)), -# ( '/* ... */ int stmt;', ('int stmt', True)), + ('int stmt; // ...', ('int stmt', True)), + ( 'int stmt; /* ... */', ('int stmt', True)), + ( '/* ... */ int stmt;', ('int stmt', True)), ] for lines, expected in tests: with self.subTest(lines): lines = lines.splitlines() - stmts = list(iter_statements(lines, local=False)) + stmts = list(iter_local_statements(lines)) self.assertEqual(stmts, [expected] if expected else []) @@ -137,10 +358,9 @@ def test_(self): class IterVariablesTests(TestCaseBase): - maxDiff = None - _return_iter_source_lines = None - _return_iter_statements = None + _return_iter_global = None + _return_iter_local = None _return_parse_func = None _return_parse_var = None _return_parse_compound = None @@ -150,17 +370,25 @@ def _iter_source_lines(self, filename): ('_iter_source_lines', (filename,))) return self._return_iter_source_lines.splitlines() - def _iter_statements(self, lines, local): + def _iter_global(self, lines): self.calls.append( - ('_iter_statements', (lines, local))) + ('_iter_global', (lines,))) try: - return self._return_iter_statements.pop(0) + return self._return_iter_global.pop(0) except IndexError: - return ('???', False) + return ('???', None) - def _parse_func(self, lines): + def _iter_local(self, lines): self.calls.append( - ('_parse_func', (lines,))) + ('_iter_local', (lines,))) + try: + return self._return_iter_local.pop(0) + except IndexError: + return ('???', None) + + def _parse_func(self, stmt, body): + self.calls.append( + ('_parse_func', (stmt, body))) try: return self._return_parse_func.pop(0) except IndexError: @@ -174,9 +402,9 @@ def _parse_var(self, lines): except IndexError: return ('???', '???') - def _parse_compound(self, lines): + def _parse_compound(self, stmt, blocks): self.calls.append( - ('_parse_compound', (lines,))) + ('_parse_compound', (stmt, blocks))) try: return self._return_parse_compound.pop(0) except IndexError: @@ -184,7 +412,7 @@ def _parse_compound(self, lines): def test_empty_file(self): self._return_iter_source_lines = '' - self._return_iter_statements = [ + self._return_iter_global = [ [], ] self._return_parse_func = None @@ -193,7 +421,8 @@ def test_empty_file(self): srcvars = list(iter_variables('spam.c', _iter_source_lines=self._iter_source_lines, - _iter_statements=self._iter_statements, + _iter_global=self._iter_global, + _iter_local=self._iter_local, _parse_func=self._parse_func, _parse_var=self._parse_var, _parse_compound=self._parse_compound, @@ -202,7 +431,7 @@ def test_empty_file(self): self.assertEqual(srcvars, []) self.assertEqual(self.calls, [ ('_iter_source_lines', ('spam.c',)), - ('_iter_statements', ([], False)), + ('_iter_global', ([],)), ]) def test_no_statements(self): @@ -210,7 +439,7 @@ def test_no_statements(self): ... ''') self._return_iter_source_lines = content - self._return_iter_statements = [ + self._return_iter_global = [ [], ] self._return_parse_func = None @@ -219,7 +448,8 @@ def test_no_statements(self): srcvars = list(iter_variables('spam.c', _iter_source_lines=self._iter_source_lines, - _iter_statements=self._iter_statements, + _iter_global=self._iter_global, + _iter_local=self._iter_local, _parse_func=self._parse_func, _parse_var=self._parse_var, _parse_compound=self._parse_compound, @@ -228,7 +458,7 @@ def test_no_statements(self): self.assertEqual(srcvars, []) self.assertEqual(self.calls, [ ('_iter_source_lines', ('spam.c',)), - ('_iter_statements', (content.splitlines(), False)), + ('_iter_global', (content.splitlines(),)), ]) def test_typical(self): @@ -236,20 +466,22 @@ def test_typical(self): ... ''') self._return_iter_source_lines = content - self._return_iter_statements = [ - [('', True), # var1 - ('', True), # non-var - ('', True), # var2 - ('', False), # func1 - ('', True), # var4 + self._return_iter_global = [ + [('', None), # var1 + ('', None), # non-var + ('', None), # var2 + ('', ''), # func1 + ('', None), # var4 ], + ] + self._return_iter_local = [ # func1 - [('', True), # var3 - ('', False), # if - ('', True), # non-var + [('', None), # var3 + ('', [('
', '')]), # if + ('', None), # non-var ], # if - [('', True), # var2 ("collision" with global var) + [('', None), # var2 ("collision" with global var) ], ] self._return_parse_func = [ @@ -263,15 +495,24 @@ def test_typical(self): ('var2', ''), ('var4', ''), (None, None), + (None, None), + (None, None), ('var5', ''), ] self._return_parse_compound = [ - ([''], ['']), + ([[ + 'if (', + '', + ')', + ], + ], + ['']), ] srcvars = list(iter_variables('spam.c', _iter_source_lines=self._iter_source_lines, - _iter_statements=self._iter_statements, + _iter_global=self._iter_global, + _iter_local=self._iter_local, _parse_func=self._parse_func, _parse_var=self._parse_var, _parse_compound=self._parse_compound, @@ -287,17 +528,19 @@ def test_typical(self): ]) self.assertEqual(self.calls, [ ('_iter_source_lines', ('spam.c',)), - ('_iter_statements', (content.splitlines(), False)), + ('_iter_global', (content.splitlines(),)), ('_parse_var', ('',)), ('_parse_var', ('',)), ('_parse_var', ('',)), - ('_parse_func', ('',)), - ('_iter_statements', ([''], True)), + ('_parse_func', ('', '')), + ('_iter_local', ([''],)), ('_parse_var', ('',)), - ('_parse_compound', ('',)), + ('_parse_compound', ('', [('
', '')])), + ('_parse_var', ('if (',)), ('_parse_var', ('',)), + ('_parse_var', (')',)), ('_parse_var', ('',)), - ('_iter_statements', ([''], True)), + ('_iter_local', ([''],)), ('_parse_var', ('',)), ('_parse_var', ('',)), ]) @@ -307,19 +550,21 @@ def test_no_locals(self): ... ''') self._return_iter_source_lines = content - self._return_iter_statements = [ - [('', True), # var1 - ('', True), # non-var - ('', True), # var2 - ('', False), # func1 + self._return_iter_global = [ + [('', None), # var1 + ('', None), # non-var + ('', None), # var2 + ('', ''), # func1 ], + ] + self._return_iter_local = [ # func1 - [('', True), # non-var - ('', False), # if - ('', True), # non-var + [('', None), # non-var + ('', [('
', '')]), # if + ('', None), # non-var ], # if - [('', True), # non-var + [('', None), # non-var ], ] self._return_parse_func = [ @@ -333,14 +578,23 @@ def test_no_locals(self): (None, None), (None, None), (None, None), + (None, None), + (None, None), ] self._return_parse_compound = [ - ([''], ['']), + ([[ + 'if (', + '', + ')', + ], + ], + ['']), ] srcvars = list(iter_variables('spam.c', _iter_source_lines=self._iter_source_lines, - _iter_statements=self._iter_statements, + _iter_global=self._iter_global, + _iter_local=self._iter_local, _parse_func=self._parse_func, _parse_var=self._parse_var, _parse_compound=self._parse_compound, @@ -352,16 +606,18 @@ def test_no_locals(self): ]) self.assertEqual(self.calls, [ ('_iter_source_lines', ('spam.c',)), - ('_iter_statements', (content.splitlines(), False)), + ('_iter_global', (content.splitlines(),)), ('_parse_var', ('',)), ('_parse_var', ('',)), ('_parse_var', ('',)), - ('_parse_func', ('',)), - ('_iter_statements', ([''], True)), + ('_parse_func', ('', '')), + ('_iter_local', ([''],)), ('_parse_var', ('',)), - ('_parse_compound', ('',)), + ('_parse_compound', ('', [('
', '')])), + ('_parse_var', ('if (',)), ('_parse_var', ('',)), + ('_parse_var', (')',)), ('_parse_var', ('',)), - ('_iter_statements', ([''], True)), + ('_iter_local', ([''],)), ('_parse_var', ('',)), ]) From 044a1f41003d74fa69a969696eef267b296b1fcb Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 2 Jul 2019 16:12:22 -0600 Subject: [PATCH 028/118] Implement basic variable support. --- Lib/test/test_c_statics/cg/parse.py | 61 +++++--- Lib/test/test_c_statics/test_cg/test_parse.py | 134 +++++++++++++++--- 2 files changed, 153 insertions(+), 42 deletions(-) diff --git a/Lib/test/test_c_statics/cg/parse.py b/Lib/test/test_c_statics/cg/parse.py index 78b46c1b80d818..62a513e7242f06 100644 --- a/Lib/test/test_c_statics/cg/parse.py +++ b/Lib/test/test_c_statics/cg/parse.py @@ -5,7 +5,7 @@ IDENTIFIER = r'(?:[a-zA-z]|_+[a-zA-Z0-9]\w*)' -#TYPE_QUAL = r'(?:const|volatile)' +TYPE_QUAL = r'(?:const|volatile)' VAR_TYPE_SPEC = r'''(?: void | @@ -65,21 +65,6 @@ # )?\s+ # {VAR_TYPE_SPEC} # )''' -#LOCAL_VAR_START = rf'''(?: -# (?: -# (?: -# register | -# static -# )\s+ -# )? -# (?: -# (?: -# {TYPE_QUAL} -# (?:\s+{TYPE_QUAL})? -# )\s+ -# )? -# {VAR_TYPE_SPEC} -# )''' GLOBAL_DECL_START_RE = re.compile(rf''' ^ (?: @@ -87,6 +72,28 @@ ) ''', re.VERBOSE) +LOCAL_VAR_START = rf'''(?: + (?: + (?: + register | + static + )\s+ + )? + (?: + (?: + {TYPE_QUAL} + (?:\s+{TYPE_QUAL})? + )\s+ + )? + {VAR_TYPE_SPEC} + )''' +LOCAL_STMT_START_RE = re.compile(rf''' + ^ + (?: + ({LOCAL_VAR_START}) + ) + ''', re.VERBOSE) + #POINTER = rf'''(?: # (?:\s+const)?\s*[*] # )''' @@ -144,7 +151,7 @@ def iter_global_declarations(lines): yield (f'{decl}\n{body}\n{end}', body) -def iter_local_statements(lines, *, local=False): +def iter_local_statements(lines): """Yield (lines, blocks) for each statement in the given lines. For simple statements, "blocks" is None and the statement is reduced @@ -152,7 +159,20 @@ def iter_local_statements(lines, *, local=False): (header, body) for each block in the statement. The headers are reduced to a single line each, but the bpdies are provided as-is. """ - raise NotImplementedError + # XXX Bail out upon bogus syntax. + lines = _iter_clean_lines(lines) + for line in lines: + if not LOCAL_STMT_START_RE.match(line): + continue + + stmt = line + blocks = None + if not line.endswith(';'): + # XXX Support compound & multiline simple statements. + #blocks = [] + continue + + yield (stmt, blocks) def _iter_clean_lines(lines): @@ -165,12 +185,13 @@ def _iter_clean_lines(lines): incomment = False continue line, _, _ = line.partition('//') - line, sep, _ = line.partition('/*') + line, sep, remainder = line.partition('/*') if sep: - _, sep, line = line.partition('*/') + _, sep, after = remainder.partition('*/') if not sep: incomment = True continue + line += ' ' + after # Ignore blank lines and leading/trailing whitespace. line = line.strip() diff --git a/Lib/test/test_c_statics/test_cg/test_parse.py b/Lib/test/test_c_statics/test_cg/test_parse.py index f870167404e2ff..f459affd6811fb 100644 --- a/Lib/test/test_c_statics/test_cg/test_parse.py +++ b/Lib/test/test_c_statics/test_cg/test_parse.py @@ -94,7 +94,7 @@ def test_functions(self): self.assertEqual(stmts, [expected]) @unittest.expectedFailure - def test_global_declaration(self): + def test_declarations(self): tests = [ 'int spam;', 'long long spam;', @@ -118,15 +118,15 @@ def test_global_declaration(self): self.assertEqual(stmts, [expected]) @unittest.expectedFailure - def test_global_declaration_multiple_vars(self): + def test_declaration_multiple_vars(self): lines = ['static const int const *spam, *ham=NULL, eggs = 3;'] stmts = list(iter_global_declarations(lines)) self.assertEqual(stmts, [ - ('static const int const *spam;', True), - ('static const int *ham=NULL;', True), - ('static const int eggs = 3;', True), + ('static const int const *spam;', None), + ('static const int *ham=NULL;', None), + ('static const int eggs = 3;', None), ]) def test_mixed(self): @@ -191,7 +191,7 @@ def test_mixed(self): #self.assertEqual([body for _, body in stmts], # [body for _, body in expected]) - def test_empty(self): + def test_no_statements(self): lines = [] stmts = list(iter_global_declarations(lines)) @@ -281,11 +281,109 @@ def test_ignore_comments(self): self.assertEqual(stmts, [expected] if expected else []) -@unittest.skip('not finished') class IterLocalStatementsTests(TestCaseBase): + def test_vars(self): + tests = [ + # POTS + 'int spam;', + 'unsigned int spam;', + 'char spam;', + 'float spam;', + + # typedefs + 'uint spam;', + 'MyType spam;', + + # complex + 'struct myspam spam;', + 'union choice spam;', + # inline struct + # inline union + # enum? + ] + # pointers + tests.extend([ + # POTS + 'int * spam;', + 'unsigned int * spam;', + 'char *spam;', + 'char const *spam = "spamspamspam...";', + # typedefs + 'MyType *spam;', + # complex + 'struct myspam *spam;', + 'union choice *spam;', + # packed with details + 'const char const *spam;', + # void pointer + 'void *data = NULL;', + # function pointers + 'int (* func)(char *arg1);', + 'char * (* func)(void);', + ]) + # storage class + tests.extend([ + 'static int spam;', + 'extern int spam;', + 'static unsigned int spam;', + 'static struct myspam spam;', + ]) + # type qualifier + tests.extend([ + 'const int spam;', + 'const unsigned int spam;', + 'const struct myspam spam;', + ]) + # combined + tests.extend([ + 'const char *spam = eggs;', + 'static const char const *spam = "spamspamspam...";', + 'extern const char const *spam;', + 'static void *data = NULL;', + 'static int (const * func)(char *arg1) = func1;', + 'static char * (* func)(void);', + ]) + for line in tests: + expected = line + with self.subTest(line): + stmts = list(iter_local_statements([line])) + + self.assertEqual(stmts, [(expected, None)]) + + @unittest.expectedFailure + def test_vars_multiline_var(self): + lines = textwrap.dedent(''' + PyObject * + spam + = NULL; + ''').splitlines() + expected = 'PyObject * spam = NULL;' + + stmts = list(iter_local_statements(lines)) + + self.assertEqual(stmts, [(expected, None)]) + + @unittest.expectedFailure + def test_declaration_multiple_vars(self): + lines = ['static const int const *spam, *ham=NULL, ham2[]={1, 2, 3}, ham3[2]={1, 2}, eggs = 3;'] + + stmts = list(iter_global_declarations(lines)) + + self.assertEqual(stmts, [ + ('static const int const *spam;', None), + ('static const int *ham=NULL;', None), + ('static const int ham[]={1, 2, 3};', None), + ('static const int ham[2]={1, 2};', None), + ('static const int eggs = 3;', None), + ]) + + @unittest.expectedFailure + def test_other_simple(self): + raise NotImplementedError + @unittest.expectedFailure - def test_single(self): + def test_compound(self): raise NotImplementedError @unittest.expectedFailure @@ -293,24 +391,16 @@ def test_mixed(self): raise NotImplementedError def test_no_statements(self): - lines = textwrap.dedent(''' - ''').splitlines() - - with self.subTest('global'): - stmts = list(iter_local_statements(lines)) - - self.assertEqual(stmts, []) + lines = [] - with self.subTest('local'): - stmts = list(iter_local_statements(lines, local=True)) + stmts = list(iter_local_statements(lines)) - self.assertEqual(stmts, []) + self.assertEqual(stmts, []) @unittest.expectedFailure def test_bogus(self): raise NotImplementedError - @unittest.expectedFailure def test_ignore_comments(self): tests = [ ('// msg', None), @@ -325,9 +415,9 @@ def test_ignore_comments(self): */ """, None), # mixed with statements - ('int stmt; // ...', ('int stmt', True)), - ( 'int stmt; /* ... */', ('int stmt', True)), - ( '/* ... */ int stmt;', ('int stmt', True)), + ('int stmt; // ...', ('int stmt;', None)), + ( 'int stmt; /* ... */', ('int stmt;', None)), + ( '/* ... */ int stmt;', ('int stmt;', None)), ] for lines, expected in tests: with self.subTest(lines): From c7833c1d6d753c284d93ea799160c118037fe359 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 2 Jul 2019 16:40:32 -0600 Subject: [PATCH 029/118] Implement parse_func(). --- Lib/test/test_c_statics/cg/parse.py | 14 ++++++++-- Lib/test/test_c_statics/test_cg/test_parse.py | 28 ++++++++++++++----- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/Lib/test/test_c_statics/cg/parse.py b/Lib/test/test_c_statics/cg/parse.py index 62a513e7242f06..2fc6987623c2b9 100644 --- a/Lib/test/test_c_statics/cg/parse.py +++ b/Lib/test/test_c_statics/cg/parse.py @@ -216,7 +216,17 @@ def _extract_block(lines): def parse_func(stmt, body): """Return (name, signature) for the given function definition.""" - raise NotImplementedError + header, _, end = stmt.partition(body) + assert end.strip() == '}' + assert header.strip().endswith('{') + header, _, _= header.rpartition('{') + + signature = ' '.join(header.strip().splitlines()) + + _, _, name = signature.split('(')[0].strip().rpartition(' ') + assert name + + return name, signature def parse_var(stmt): @@ -254,7 +264,7 @@ def iter_variables(filename, *, if name: yield (None, name, vartype) else: - funcname, _, body = _parse_func(stmt, body) + funcname, _ = _parse_func(stmt, body) localvars = _iter_locals(body, _iter_statements=_iter_local, _parse_var=_parse_var, diff --git a/Lib/test/test_c_statics/test_cg/test_parse.py b/Lib/test/test_c_statics/test_cg/test_parse.py index f459affd6811fb..37fe9fffdddb9e 100644 --- a/Lib/test/test_c_statics/test_cg/test_parse.py +++ b/Lib/test/test_c_statics/test_cg/test_parse.py @@ -430,19 +430,33 @@ def test_ignore_comments(self): class ParseFuncTests(TestCaseBase): - def test_(self): - ... + def test_typical(self): + tests = [ + ('PyObject *\nspam(char *a)\n{\nreturn _spam(a);\n}', + 'return _spam(a);', + ('spam', 'PyObject * spam(char *a)'), + ), + ] + for stmt, body, expected in tests: + with self.subTest(stmt): + name, signature = parse_func(stmt, body) + + self.assertEqual((name, signature), expected) class ParseVarTests(TestCaseBase): - def test_(self): + @unittest.expectedFailure + def test_typical(self): + name, vartype = parse_var(stmt) ... +@unittest.skip('not finished') class ParseCompoundTests(TestCaseBase): - def test_(self): + def test_typical(self): + headers, bodies = parse_compound(stmt, blocks) ... @@ -482,7 +496,7 @@ def _parse_func(self, stmt, body): try: return self._return_parse_func.pop(0) except IndexError: - return ('???', '???', '???') + return ('???', '???') def _parse_var(self, lines): self.calls.append( @@ -575,7 +589,7 @@ def test_typical(self): ], ] self._return_parse_func = [ - ('func1', '', ''), + ('func1', ''), ] self._return_parse_var = [ ('var1', ''), @@ -658,7 +672,7 @@ def test_no_locals(self): ], ] self._return_parse_func = [ - ('func1', '', ''), + ('func1', ''), ] self._return_parse_var = [ ('var1', ''), From 2c164cd9fe97a1760dc98c98dda560864f517fc8 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 2 Jul 2019 17:31:43 -0600 Subject: [PATCH 030/118] Implement parse_var(). --- Lib/test/test_c_statics/cg/parse.py | 46 +++++++----- Lib/test/test_c_statics/test_cg/test_parse.py | 72 ++++++++++++++++++- 2 files changed, 97 insertions(+), 21 deletions(-) diff --git a/Lib/test/test_c_statics/cg/parse.py b/Lib/test/test_c_statics/cg/parse.py index 2fc6987623c2b9..8dc50dfcdd5f9c 100644 --- a/Lib/test/test_c_statics/cg/parse.py +++ b/Lib/test/test_c_statics/cg/parse.py @@ -25,6 +25,11 @@ {IDENTIFIER} | (?:struct|union)\s+{IDENTIFIER} )''' + +POINTER = rf'''(?: + (?:\s+const)?\s*[*] + )''' + #STRUCT = r'''(?: # (?:struct|(struct\s+%s))\s*[{] # [^}]* @@ -86,6 +91,7 @@ )\s+ )? {VAR_TYPE_SPEC} + {POINTER}? )''' LOCAL_STMT_START_RE = re.compile(rf''' ^ @@ -94,23 +100,6 @@ ) ''', re.VERBOSE) -#POINTER = rf'''(?: -# (?:\s+const)?\s*[*] -# )''' -# -#TYPEDEF = rf'''(?: -# typedef XXX {IDENTIFIER} -# )''' -#VAR_INITIALIZER = rf'''(?: -# (?:&\s*)? -# XXX -# )''' -#PARAMS = rf'''(?: -# [(] -# XXX -# [)] -# )''' - def iter_global_declarations(lines): """Yield (decl, body) for each global declaration in the given lines. @@ -231,7 +220,28 @@ def parse_func(stmt, body): def parse_var(stmt): """Return (name, vartype) for the given variable declaration.""" - raise NotImplementedError + stmt = stmt.rstrip(';') + m = LOCAL_STMT_START_RE.match(stmt) + assert m + vartype = m.group(0) + name = stmt[len(vartype):].partition('=')[0].strip() + + if name.startswith('('): + name, _, after = name[1:].partition(')') + assert after + name = name.replace('*', '* ') + inside, _, name = name.strip().rpartition(' ') + vartype = f'{vartype} ({inside.strip()}){after}' + else: + name = name.replace('*', '* ') + before, _, name = name.rpartition(' ') + vartype = f'{vartype} {before}' + + vartype = vartype.strip() + while ' ' in vartype: + vartype = vartype.replace(' ', ' ') + + return name, vartype def parse_compound(stmt, blocks): diff --git a/Lib/test/test_c_statics/test_cg/test_parse.py b/Lib/test/test_c_statics/test_cg/test_parse.py index 37fe9fffdddb9e..095dbef5fec2dd 100644 --- a/Lib/test/test_c_statics/test_cg/test_parse.py +++ b/Lib/test/test_c_statics/test_cg/test_parse.py @@ -446,10 +446,76 @@ def test_typical(self): class ParseVarTests(TestCaseBase): - @unittest.expectedFailure def test_typical(self): - name, vartype = parse_var(stmt) - ... + tests = [ + # POTS + ('int spam;', ('spam', 'int')), + ('unsigned int spam;', ('spam', 'unsigned int')), + ('char spam;', ('spam', 'char')), + ('float spam;', ('spam', 'float')), + + # typedefs + ('uint spam;', ('spam', 'uint')), + ('MyType spam;', ('spam', 'MyType')), + + # complex + ('struct myspam spam;', ('spam', 'struct myspam')), + ('union choice spam;', ('spam', 'union choice')), + # inline struct + # inline union + # enum? + ] + # pointers + tests.extend([ + # POTS + ('int * spam;', ('spam', 'int *')), + ('unsigned int * spam;', ('spam', 'unsigned int *')), + ('char *spam;', ('spam', 'char *')), + ('char const *spam = "spamspamspam...";', ('spam', 'char const *')), + # typedefs + ('MyType *spam;', ('spam', 'MyType *')), + # complex + ('struct myspam *spam;', ('spam', 'struct myspam *')), + ('union choice *spam;', ('spam', 'union choice *')), + # packed with details + ('const char const *spam;', ('spam', 'const char const *')), + # void pointer + ('void *data = NULL;', ('data', 'void *')), + # function pointers + ('int (* func)(char *);', ('func', 'int (*)(char *)')), + ('char * (* func)(void);', ('func', 'char * (*)(void)')), + ]) + # storage class + tests.extend([ + ('static int spam;', ('spam', 'static int')), + ('extern int spam;', ('spam', 'extern int')), + ('static unsigned int spam;', ('spam', 'static unsigned int')), + ('static struct myspam spam;', ('spam', 'static struct myspam')), + ]) + # type qualifier + tests.extend([ + ('const int spam;', ('spam', 'const int')), + ('const unsigned int spam;', ('spam', 'const unsigned int')), + ('const struct myspam spam;', ('spam', 'const struct myspam')), + ]) + # combined + tests.extend([ + ('const char *spam = eggs;', ('spam', 'const char *')), + ('static const char const *spam = "spamspamspam...";', + ('spam', 'static const char const *')), + ('extern const char const *spam;', + ('spam', 'extern const char const *')), + ('static void *data = NULL;', ('data', 'static void *')), + ('static int (const * func)(char *) = func1;', + ('func', 'static int (const *)(char *)')), + ('static char * (* func)(void);', + ('func', 'static char * (*)(void)')), + ]) + for stmt, expected in tests: + with self.subTest(stmt): + name, vartype = parse_var(stmt) + + self.assertEqual((name, vartype), expected) @unittest.skip('not finished') From 84cd77e53d76f571d874e2c2b746ebdb1cb1a8a6 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Thu, 4 Jul 2019 14:04:09 -0600 Subject: [PATCH 031/118] Ignore files in Include/cpython. --- Lib/test/test_c_statics/cg/files.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Lib/test/test_c_statics/cg/files.py b/Lib/test/test_c_statics/cg/files.py index bf925f8ddc356c..06cc83c58b2f11 100644 --- a/Lib/test/test_c_statics/cg/files.py +++ b/Lib/test/test_c_statics/cg/files.py @@ -19,6 +19,8 @@ def filter_by_name(name): for dirname in dirnames: for parent, _, names in _walk(dirname): + if parent.endswith(os.path.join('', 'Include', 'cpython')): + continue for name in names: if not filter_by_name(name): continue From dc471a37a42b68c3473df828b4ab784f10181c6a Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 5 Jul 2019 12:44:36 -0600 Subject: [PATCH 032/118] Rename the c-globals tool directory to be more generic. --- Tools/{c-globals => c-analyzer}/README | 0 Tools/{c-globals => c-analyzer}/check-c-globals.py | 0 Tools/{c-globals => c-analyzer}/ignored-globals.txt | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename Tools/{c-globals => c-analyzer}/README (100%) rename Tools/{c-globals => c-analyzer}/check-c-globals.py (100%) rename Tools/{c-globals => c-analyzer}/ignored-globals.txt (100%) diff --git a/Tools/c-globals/README b/Tools/c-analyzer/README similarity index 100% rename from Tools/c-globals/README rename to Tools/c-analyzer/README diff --git a/Tools/c-globals/check-c-globals.py b/Tools/c-analyzer/check-c-globals.py similarity index 100% rename from Tools/c-globals/check-c-globals.py rename to Tools/c-analyzer/check-c-globals.py diff --git a/Tools/c-globals/ignored-globals.txt b/Tools/c-analyzer/ignored-globals.txt similarity index 100% rename from Tools/c-globals/ignored-globals.txt rename to Tools/c-analyzer/ignored-globals.txt From a9c27c5485c4bc6b12156479ca5ea42f2126e344 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 5 Jul 2019 13:23:55 -0600 Subject: [PATCH 033/118] Add imports_under_tool() CM. --- Lib/test/test_clinic.py | 13 +++---------- Lib/test/test_tools/__init__.py | 31 ++++++++++++++++++++++--------- 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py index 244c5fecd34915..3d5dc4759d5018 100644 --- a/Lib/test/test_clinic.py +++ b/Lib/test/test_clinic.py @@ -2,7 +2,7 @@ # Copyright 2012-2013 by Larry Hastings. # Licensed to the PSF under a contributor agreement. -from test import support +from test import support, test_tools from unittest import TestCase import collections import inspect @@ -10,17 +10,10 @@ import sys import unittest - -clinic_path = os.path.join(os.path.dirname(__file__), '..', '..', 'Tools', 'clinic') -clinic_path = os.path.normpath(clinic_path) -if not os.path.exists(clinic_path): - raise unittest.SkipTest(f'{clinic_path!r} path does not exist') -sys.path.append(clinic_path) -try: +test_tools.skip_if_missing('clinic') +with test_tools.imports_under_tool('clinic'): import clinic from clinic import DSLParser -finally: - del sys.path[-1] class FakeConverter: diff --git a/Lib/test/test_tools/__init__.py b/Lib/test/test_tools/__init__.py index 4d0fca330a1146..eb9acad677d58a 100644 --- a/Lib/test/test_tools/__init__.py +++ b/Lib/test/test_tools/__init__.py @@ -1,20 +1,33 @@ """Support functions for testing scripts in the Tools directory.""" -import os -import unittest +import contextlib import importlib +import os.path +import unittest from test import support -basepath = os.path.dirname( # - os.path.dirname( # Lib - os.path.dirname( # test - os.path.dirname(__file__)))) # test_tools +basepath = os.path.normpath( + os.path.dirname( # + os.path.dirname( # Lib + os.path.dirname( # test + os.path.dirname(__file__))))) # test_tools toolsdir = os.path.join(basepath, 'Tools') scriptsdir = os.path.join(toolsdir, 'scripts') -def skip_if_missing(): - if not os.path.isdir(scriptsdir): - raise unittest.SkipTest('scripts directory could not be found') +def skip_if_missing(tool=None): + if tool: + tooldir = os.path.join(toolsdir, tool) + else: + tool = 'scripts' + tooldir = scriptsdir + if not os.path.isdir(tooldir): + raise unittest.SkipTest(f'{tool} directory could not be found') + +@contextlib.contextmanager +def imports_under_tool(name, *subdirs): + tooldir = os.path.join(toolsdir, name, *subdirs) + with support.DirsOnSysPath(tooldir) as cm: + yield cm def import_tool(toolname): with support.DirsOnSysPath(scriptsdir): From 60dee311708b847c53e3e67821ec0e13b55ff24e Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 5 Jul 2019 13:48:42 -0600 Subject: [PATCH 034/118] Move the code under Tools (and the tests under test_tools). --- Lib/test/test_c_statics/__init__.py | 6 ------ .../{test_c_statics => }/test_check_c_statics.py | 5 ++++- Lib/test/test_tools/test_c_analyzer/__init__.py | 15 +++++++++++++++ .../test_c_analyzer}/__main__.py | 0 .../test_c_analyzer/test_c_statics}/__init__.py | 0 .../test_c_statics}/test___main__.py | 8 +++++--- .../test_c_analyzer/test_c_statics}/test_files.py | 4 +++- .../test_c_analyzer/test_c_statics}/test_find.py | 6 ++++-- .../test_c_statics}/test_functional.py | 4 ++++ .../test_c_analyzer/test_c_statics}/test_info.py | 4 +++- .../test_c_analyzer/test_c_statics}/test_parse.py | 4 +++- .../test_c_analyzer/test_c_statics}/test_scan.py | 6 ++++-- .../test_c_analyzer/test_c_statics}/test_show.py | 6 ++++-- .../test_c_statics}/test_supported.py | 6 ++++-- .../c-analyzer}/c-statics.py | 0 .../c-analyzer/c_statics}/README | 0 .../cg => Tools/c-analyzer/c_statics}/__init__.py | 0 .../cg => Tools/c-analyzer/c_statics}/__main__.py | 0 .../cg => Tools/c-analyzer/c_statics}/files.py | 0 .../cg => Tools/c-analyzer/c_statics}/find.py | 0 .../cg => Tools/c-analyzer/c_statics}/info.py | 0 .../cg => Tools/c-analyzer/c_statics}/parse.py | 0 .../cg => Tools/c-analyzer/c_statics}/scan.py | 0 .../cg => Tools/c-analyzer/c_statics}/show.py | 0 .../c-analyzer/c_statics}/supported.py | 0 .../cg => Tools/c-analyzer/c_statics}/symbols.py | 0 26 files changed, 53 insertions(+), 21 deletions(-) delete mode 100644 Lib/test/test_c_statics/__init__.py rename Lib/test/{test_c_statics => }/test_check_c_statics.py (65%) create mode 100644 Lib/test/test_tools/test_c_analyzer/__init__.py rename Lib/test/{test_c_statics => test_tools/test_c_analyzer}/__main__.py (100%) rename Lib/test/{test_c_statics/test_cg => test_tools/test_c_analyzer/test_c_statics}/__init__.py (100%) rename Lib/test/{test_c_statics/test_cg => test_tools/test_c_analyzer/test_c_statics}/test___main__.py (97%) rename Lib/test/{test_c_statics/test_cg => test_tools/test_c_analyzer/test_c_statics}/test_files.py (98%) rename Lib/test/{test_c_statics/test_cg => test_tools/test_c_analyzer/test_c_statics}/test_find.py (94%) rename Lib/test/{test_c_statics/test_cg => test_tools/test_c_analyzer/test_c_statics}/test_functional.py (90%) rename Lib/test/{test_c_statics/test_cg => test_tools/test_c_analyzer/test_c_statics}/test_info.py (99%) rename Lib/test/{test_c_statics/test_cg => test_tools/test_c_analyzer/test_c_statics}/test_parse.py (99%) rename Lib/test/{test_c_statics/test_cg => test_tools/test_c_analyzer/test_c_statics}/test_scan.py (93%) rename Lib/test/{test_c_statics/test_cg => test_tools/test_c_analyzer/test_c_statics}/test_show.py (91%) rename Lib/test/{test_c_statics/test_cg => test_tools/test_c_analyzer/test_c_statics}/test_supported.py (85%) rename {Lib/test/test_c_statics => Tools/c-analyzer}/c-statics.py (100%) rename {Lib/test/test_c_statics => Tools/c-analyzer/c_statics}/README (100%) rename {Lib/test/test_c_statics/cg => Tools/c-analyzer/c_statics}/__init__.py (100%) rename {Lib/test/test_c_statics/cg => Tools/c-analyzer/c_statics}/__main__.py (100%) rename {Lib/test/test_c_statics/cg => Tools/c-analyzer/c_statics}/files.py (100%) rename {Lib/test/test_c_statics/cg => Tools/c-analyzer/c_statics}/find.py (100%) rename {Lib/test/test_c_statics/cg => Tools/c-analyzer/c_statics}/info.py (100%) rename {Lib/test/test_c_statics/cg => Tools/c-analyzer/c_statics}/parse.py (100%) rename {Lib/test/test_c_statics/cg => Tools/c-analyzer/c_statics}/scan.py (100%) rename {Lib/test/test_c_statics/cg => Tools/c-analyzer/c_statics}/show.py (100%) rename {Lib/test/test_c_statics/cg => Tools/c-analyzer/c_statics}/supported.py (100%) rename {Lib/test/test_c_statics/cg => Tools/c-analyzer/c_statics}/symbols.py (100%) diff --git a/Lib/test/test_c_statics/__init__.py b/Lib/test/test_c_statics/__init__.py deleted file mode 100644 index bc502ef32d2916..00000000000000 --- a/Lib/test/test_c_statics/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -import os.path -from test.support import load_package_tests - - -def load_tests(*args): - return load_package_tests(os.path.dirname(__file__), *args) diff --git a/Lib/test/test_c_statics/test_check_c_statics.py b/Lib/test/test_check_c_statics.py similarity index 65% rename from Lib/test/test_c_statics/test_check_c_statics.py rename to Lib/test/test_check_c_statics.py index 6bd948e7d612eb..1219cc9f794073 100644 --- a/Lib/test/test_c_statics/test_check_c_statics.py +++ b/Lib/test/test_check_c_statics.py @@ -1,6 +1,9 @@ import unittest +import test.test_tools -from .cg.__main__ import main +test.test_tools.skip_if_missing('c-analyzer') +with test.test_tools.imports_under_tool('c-analyzer'): + from c_statics.__main__ import main class ActualChecks(unittest.TestCase): diff --git a/Lib/test/test_tools/test_c_analyzer/__init__.py b/Lib/test/test_tools/test_c_analyzer/__init__.py new file mode 100644 index 00000000000000..d0b4c045104d76 --- /dev/null +++ b/Lib/test/test_tools/test_c_analyzer/__init__.py @@ -0,0 +1,15 @@ +import contextlib +import os.path +import test.test_tools +from test.support import load_package_tests + + +@contextlib.contextmanager +def tool_imports_for_tests(): + test.test_tools.skip_if_missing('c-analyzer') + with test.test_tools.imports_under_tool('c-analyzer'): + yield + + +def load_tests(*args): + return load_package_tests(os.path.dirname(__file__), *args) diff --git a/Lib/test/test_c_statics/__main__.py b/Lib/test/test_tools/test_c_analyzer/__main__.py similarity index 100% rename from Lib/test/test_c_statics/__main__.py rename to Lib/test/test_tools/test_c_analyzer/__main__.py diff --git a/Lib/test/test_c_statics/test_cg/__init__.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/__init__.py similarity index 100% rename from Lib/test/test_c_statics/test_cg/__init__.py rename to Lib/test/test_tools/test_c_analyzer/test_c_statics/__init__.py diff --git a/Lib/test/test_c_statics/test_cg/test___main__.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test___main__.py similarity index 97% rename from Lib/test/test_c_statics/test_cg/test___main__.py rename to Lib/test/test_tools/test_c_analyzer/test_c_statics/test___main__.py index 488639e4b3e425..6f589d4a387e9f 100644 --- a/Lib/test/test_c_statics/test_cg/test___main__.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test___main__.py @@ -1,9 +1,11 @@ import sys import unittest -from test.test_c_statics import cg -from test.test_c_statics.cg import info -from test.test_c_statics.cg.__main__ import cmd_check, cmd_show, parse_args, main +from .. import tool_imports_for_tests +with tool_imports_for_tests(): + import c_statics as cg + from c_statics import info + from c_statics.__main__ import cmd_check, cmd_show, parse_args, main TYPICAL = [ diff --git a/Lib/test/test_c_statics/test_cg/test_files.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_files.py similarity index 98% rename from Lib/test/test_c_statics/test_cg/test_files.py rename to Lib/test/test_tools/test_c_analyzer/test_c_statics/test_files.py index e86e135a49256c..d77d5812cd6793 100644 --- a/Lib/test/test_c_statics/test_cg/test_files.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_files.py @@ -1,7 +1,9 @@ import os.path import unittest -from test.test_c_statics.cg.files import iter_files +from .. import tool_imports_for_tests +with tool_imports_for_tests(): + from c_statics.files import iter_files def fixpath(filename): diff --git a/Lib/test/test_c_statics/test_cg/test_find.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py similarity index 94% rename from Lib/test/test_c_statics/test_cg/test_find.py rename to Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py index ee039cfbab37fa..906d10eb8cb74f 100644 --- a/Lib/test/test_c_statics/test_cg/test_find.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py @@ -1,7 +1,9 @@ import unittest -from test.test_c_statics.cg import info -from test.test_c_statics.cg.find import statics +from .. import tool_imports_for_tests +with tool_imports_for_tests(): + from c_statics import info + from c_statics.find import statics class _Base(unittest.TestCase): diff --git a/Lib/test/test_c_statics/test_cg/test_functional.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_functional.py similarity index 90% rename from Lib/test/test_c_statics/test_cg/test_functional.py rename to Lib/test/test_tools/test_c_analyzer/test_c_statics/test_functional.py index 175fa4f2bea48a..927979048448fa 100644 --- a/Lib/test/test_c_statics/test_cg/test_functional.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_functional.py @@ -1,5 +1,9 @@ import unittest +from .. import tool_imports_for_tests +with tool_imports_for_tests(): + pass + class SelfCheckTests(unittest.TestCase): diff --git a/Lib/test/test_c_statics/test_cg/test_info.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_info.py similarity index 99% rename from Lib/test/test_c_statics/test_cg/test_info.py rename to Lib/test/test_tools/test_c_analyzer/test_c_statics/test_info.py index f7dde1b566f36e..8bb951ad00fa66 100644 --- a/Lib/test/test_c_statics/test_cg/test_info.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_info.py @@ -1,7 +1,9 @@ import string import unittest -from test.test_c_statics.cg.info import ( +from .. import tool_imports_for_tests +with tool_imports_for_tests(): + from c_statics.info import ( normalize_vartype, Symbol, StaticVar, ) diff --git a/Lib/test/test_c_statics/test_cg/test_parse.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_parse.py similarity index 99% rename from Lib/test/test_c_statics/test_cg/test_parse.py rename to Lib/test/test_tools/test_c_analyzer/test_c_statics/test_parse.py index 095dbef5fec2dd..bd1e56b5d42c1a 100644 --- a/Lib/test/test_c_statics/test_cg/test_parse.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_parse.py @@ -1,7 +1,9 @@ import textwrap import unittest -from test.test_c_statics.cg.parse import ( +from .. import tool_imports_for_tests +with tool_imports_for_tests(): + from c_statics.parse import ( iter_global_declarations, iter_local_statements, parse_func, parse_var, parse_compound, iter_variables, diff --git a/Lib/test/test_c_statics/test_cg/test_scan.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_scan.py similarity index 93% rename from Lib/test/test_c_statics/test_cg/test_scan.py rename to Lib/test/test_tools/test_c_analyzer/test_c_statics/test_scan.py index 690a530393bfa7..cb3724e3eeea24 100644 --- a/Lib/test/test_c_statics/test_cg/test_scan.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_scan.py @@ -1,7 +1,9 @@ import unittest -from test.test_c_statics.cg import info -from test.test_c_statics.cg.scan import iter_statics +from .. import tool_imports_for_tests +with tool_imports_for_tests(): + from c_statics import info + from c_statics.scan import iter_statics class IterStaticsTests(unittest.TestCase): diff --git a/Lib/test/test_c_statics/test_cg/test_show.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_show.py similarity index 91% rename from Lib/test/test_c_statics/test_cg/test_show.py rename to Lib/test/test_tools/test_c_analyzer/test_c_statics/test_show.py index 5e4becacc64061..0679a805a6cfaa 100644 --- a/Lib/test/test_c_statics/test_cg/test_show.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_show.py @@ -1,7 +1,9 @@ import unittest -from test.test_c_statics.cg import info -from test.test_c_statics.cg.show import basic +from .. import tool_imports_for_tests +with tool_imports_for_tests(): + from c_statics import info + from c_statics.show import basic TYPICAL = [ diff --git a/Lib/test/test_c_statics/test_cg/test_supported.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_supported.py similarity index 85% rename from Lib/test/test_c_statics/test_cg/test_supported.py rename to Lib/test/test_tools/test_c_analyzer/test_c_statics/test_supported.py index d9359d8299e99c..70b9ea5ce3b902 100644 --- a/Lib/test/test_c_statics/test_cg/test_supported.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_supported.py @@ -1,7 +1,9 @@ import unittest -from test.test_c_statics.cg import info -from test.test_c_statics.cg.supported import is_supported +from .. import tool_imports_for_tests +with tool_imports_for_tests(): + from c_statics import info + from c_statics.supported import is_supported class IsSupportedTests(unittest.TestCase): diff --git a/Lib/test/test_c_statics/c-statics.py b/Tools/c-analyzer/c-statics.py similarity index 100% rename from Lib/test/test_c_statics/c-statics.py rename to Tools/c-analyzer/c-statics.py diff --git a/Lib/test/test_c_statics/README b/Tools/c-analyzer/c_statics/README similarity index 100% rename from Lib/test/test_c_statics/README rename to Tools/c-analyzer/c_statics/README diff --git a/Lib/test/test_c_statics/cg/__init__.py b/Tools/c-analyzer/c_statics/__init__.py similarity index 100% rename from Lib/test/test_c_statics/cg/__init__.py rename to Tools/c-analyzer/c_statics/__init__.py diff --git a/Lib/test/test_c_statics/cg/__main__.py b/Tools/c-analyzer/c_statics/__main__.py similarity index 100% rename from Lib/test/test_c_statics/cg/__main__.py rename to Tools/c-analyzer/c_statics/__main__.py diff --git a/Lib/test/test_c_statics/cg/files.py b/Tools/c-analyzer/c_statics/files.py similarity index 100% rename from Lib/test/test_c_statics/cg/files.py rename to Tools/c-analyzer/c_statics/files.py diff --git a/Lib/test/test_c_statics/cg/find.py b/Tools/c-analyzer/c_statics/find.py similarity index 100% rename from Lib/test/test_c_statics/cg/find.py rename to Tools/c-analyzer/c_statics/find.py diff --git a/Lib/test/test_c_statics/cg/info.py b/Tools/c-analyzer/c_statics/info.py similarity index 100% rename from Lib/test/test_c_statics/cg/info.py rename to Tools/c-analyzer/c_statics/info.py diff --git a/Lib/test/test_c_statics/cg/parse.py b/Tools/c-analyzer/c_statics/parse.py similarity index 100% rename from Lib/test/test_c_statics/cg/parse.py rename to Tools/c-analyzer/c_statics/parse.py diff --git a/Lib/test/test_c_statics/cg/scan.py b/Tools/c-analyzer/c_statics/scan.py similarity index 100% rename from Lib/test/test_c_statics/cg/scan.py rename to Tools/c-analyzer/c_statics/scan.py diff --git a/Lib/test/test_c_statics/cg/show.py b/Tools/c-analyzer/c_statics/show.py similarity index 100% rename from Lib/test/test_c_statics/cg/show.py rename to Tools/c-analyzer/c_statics/show.py diff --git a/Lib/test/test_c_statics/cg/supported.py b/Tools/c-analyzer/c_statics/supported.py similarity index 100% rename from Lib/test/test_c_statics/cg/supported.py rename to Tools/c-analyzer/c_statics/supported.py diff --git a/Lib/test/test_c_statics/cg/symbols.py b/Tools/c-analyzer/c_statics/symbols.py similarity index 100% rename from Lib/test/test_c_statics/cg/symbols.py rename to Tools/c-analyzer/c_statics/symbols.py From c0f13139be3f95157770d4c83cd3ad67e1f63675 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 5 Jul 2019 14:18:21 -0600 Subject: [PATCH 035/118] Split up the files properly. --- .../test_tools/test_c_analyzer/test_c_parser/__init__.py | 0 .../test_parse.py => test_c_parser/test_declarations.py} | 2 +- .../{test_c_statics => test_c_parser}/test_files.py | 2 +- .../{test_c_statics => test_c_parser}/test_info.py | 2 +- .../test_c_analyzer/test_c_statics/test___main__.py | 2 +- .../test_c_analyzer/test_c_statics/test_find.py | 2 +- .../test_c_analyzer/test_c_statics/test_scan.py | 2 +- .../test_c_analyzer/test_c_statics/test_show.py | 2 +- .../test_c_analyzer/test_c_statics/test_supported.py | 2 +- Tools/c-analyzer/c-statics.py | 2 +- Tools/c-analyzer/c_parser/__init__.py | 0 .../{c_statics/parse.py => c_parser/declarations.py} | 0 Tools/c-analyzer/{c_statics => c_parser}/files.py | 0 Tools/c-analyzer/{c_statics => c_parser}/info.py | 0 Tools/c-analyzer/c_statics/scan.py | 3 ++- Tools/c-analyzer/c_symbols/__init__.py | 0 .../c-analyzer/{c_statics/symbols.py => c_symbols/nm.py} | 9 ++++++--- 17 files changed, 17 insertions(+), 13 deletions(-) create mode 100644 Lib/test/test_tools/test_c_analyzer/test_c_parser/__init__.py rename Lib/test/test_tools/test_c_analyzer/{test_c_statics/test_parse.py => test_c_parser/test_declarations.py} (99%) rename Lib/test/test_tools/test_c_analyzer/{test_c_statics => test_c_parser}/test_files.py (99%) rename Lib/test/test_tools/test_c_analyzer/{test_c_statics => test_c_parser}/test_info.py (99%) create mode 100644 Tools/c-analyzer/c_parser/__init__.py rename Tools/c-analyzer/{c_statics/parse.py => c_parser/declarations.py} (100%) rename Tools/c-analyzer/{c_statics => c_parser}/files.py (100%) rename Tools/c-analyzer/{c_statics => c_parser}/info.py (100%) create mode 100644 Tools/c-analyzer/c_symbols/__init__.py rename Tools/c-analyzer/{c_statics/symbols.py => c_symbols/nm.py} (95%) diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_parser/__init__.py b/Lib/test/test_tools/test_c_analyzer/test_c_parser/__init__.py new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_parse.py b/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_declarations.py similarity index 99% rename from Lib/test/test_tools/test_c_analyzer/test_c_statics/test_parse.py rename to Lib/test/test_tools/test_c_analyzer/test_c_parser/test_declarations.py index bd1e56b5d42c1a..b68744ef0aba49 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_parse.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_declarations.py @@ -3,7 +3,7 @@ from .. import tool_imports_for_tests with tool_imports_for_tests(): - from c_statics.parse import ( + from c_parser.declarations import ( iter_global_declarations, iter_local_statements, parse_func, parse_var, parse_compound, iter_variables, diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_files.py b/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_files.py similarity index 99% rename from Lib/test/test_tools/test_c_analyzer/test_c_statics/test_files.py rename to Lib/test/test_tools/test_c_analyzer/test_c_parser/test_files.py index d77d5812cd6793..ee416cdda8c1a8 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_files.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_files.py @@ -3,7 +3,7 @@ from .. import tool_imports_for_tests with tool_imports_for_tests(): - from c_statics.files import iter_files + from c_parser.files import iter_files def fixpath(filename): diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_info.py b/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_info.py similarity index 99% rename from Lib/test/test_tools/test_c_analyzer/test_c_statics/test_info.py rename to Lib/test/test_tools/test_c_analyzer/test_c_parser/test_info.py index 8bb951ad00fa66..c8ac895b40401e 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_info.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_info.py @@ -3,7 +3,7 @@ from .. import tool_imports_for_tests with tool_imports_for_tests(): - from c_statics.info import ( + from c_parser.info import ( normalize_vartype, Symbol, StaticVar, ) diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test___main__.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test___main__.py index 6f589d4a387e9f..469b8abc162016 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test___main__.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test___main__.py @@ -3,8 +3,8 @@ from .. import tool_imports_for_tests with tool_imports_for_tests(): + from c_parser import info import c_statics as cg - from c_statics import info from c_statics.__main__ import cmd_check, cmd_show, parse_args, main diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py index 906d10eb8cb74f..cdf32cdc88902e 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py @@ -2,7 +2,7 @@ from .. import tool_imports_for_tests with tool_imports_for_tests(): - from c_statics import info + from c_parser import info from c_statics.find import statics diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_scan.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_scan.py index cb3724e3eeea24..2d8e30381568f4 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_scan.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_scan.py @@ -2,7 +2,7 @@ from .. import tool_imports_for_tests with tool_imports_for_tests(): - from c_statics import info + from c_parser import info from c_statics.scan import iter_statics diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_show.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_show.py index 0679a805a6cfaa..1a03365a86cea9 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_show.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_show.py @@ -2,7 +2,7 @@ from .. import tool_imports_for_tests with tool_imports_for_tests(): - from c_statics import info + from c_parser import info from c_statics.show import basic diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_supported.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_supported.py index 70b9ea5ce3b902..975ea5b4cf2f1e 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_supported.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_supported.py @@ -2,7 +2,7 @@ from .. import tool_imports_for_tests with tool_imports_for_tests(): - from c_statics import info + from c_parser import info from c_statics.supported import is_supported diff --git a/Tools/c-analyzer/c-statics.py b/Tools/c-analyzer/c-statics.py index fcd911a3e8c5d6..c8a9911a22cc73 100644 --- a/Tools/c-analyzer/c-statics.py +++ b/Tools/c-analyzer/c-statics.py @@ -1,6 +1,6 @@ # This is a script equivalent of running "python -m test.test_c_statics.cg". -from cg.__main__ import parse_args, main +from c_statics.__main__ import parse_args, main # This is effectively copied from cg/__main__.py: diff --git a/Tools/c-analyzer/c_parser/__init__.py b/Tools/c-analyzer/c_parser/__init__.py new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/Tools/c-analyzer/c_statics/parse.py b/Tools/c-analyzer/c_parser/declarations.py similarity index 100% rename from Tools/c-analyzer/c_statics/parse.py rename to Tools/c-analyzer/c_parser/declarations.py diff --git a/Tools/c-analyzer/c_statics/files.py b/Tools/c-analyzer/c_parser/files.py similarity index 100% rename from Tools/c-analyzer/c_statics/files.py rename to Tools/c-analyzer/c_parser/files.py diff --git a/Tools/c-analyzer/c_statics/info.py b/Tools/c-analyzer/c_parser/info.py similarity index 100% rename from Tools/c-analyzer/c_statics/info.py rename to Tools/c-analyzer/c_parser/info.py diff --git a/Tools/c-analyzer/c_statics/scan.py b/Tools/c-analyzer/c_statics/scan.py index 9437b49d297bb5..a66c2ea88e48f8 100644 --- a/Tools/c-analyzer/c_statics/scan.py +++ b/Tools/c-analyzer/c_statics/scan.py @@ -1,4 +1,5 @@ -from . import info, symbols +from c_parser import info +from c_symbols import nm as symbols def iter_statics(dirnames, *, diff --git a/Tools/c-analyzer/c_symbols/__init__.py b/Tools/c-analyzer/c_symbols/__init__.py new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/Tools/c-analyzer/c_statics/symbols.py b/Tools/c-analyzer/c_symbols/nm.py similarity index 95% rename from Tools/c-analyzer/c_statics/symbols.py rename to Tools/c-analyzer/c_symbols/nm.py index 537005f35d09db..5feb5ea9cbd74e 100644 --- a/Tools/c-analyzer/c_statics/symbols.py +++ b/Tools/c-analyzer/c_symbols/nm.py @@ -2,11 +2,14 @@ import os.path import shutil import subprocess +import sys -from . import REPO_ROOT, files, info, parse +from c_parser import files, info +from c_parser.declarations import iter_variables -PYTHON = os.path.join(REPO_ROOT, 'python') +#PYTHON = os.path.join(REPO_ROOT, 'python') +PYTHON = sys.executable def iter_binary(dirnames, binary=PYTHON, *, @@ -28,7 +31,7 @@ def find_local_symbol(name): # C scanning (move to scan.py) def _get_local_symbols(filename, *, - _iter_variables=parse.iter_variables, + _iter_variables=iter_variables, ): symbols = {} for funcname, name, vartype in _iter_variables(filename): From 54104675cb9d444e8d5272222f96d10964fd8ee6 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 5 Jul 2019 15:03:36 -0600 Subject: [PATCH 036/118] Factor out c_parser/{source,util}.py and c_symbols/local.py. --- Tools/c-analyzer/c_parser/declarations.py | 82 ++--------------------- Tools/c-analyzer/c_parser/source.py | 73 ++++++++++++++++++++ Tools/c-analyzer/c_parser/util.py | 13 ++++ Tools/c-analyzer/c_symbols/local.py | 38 +++++++++++ Tools/c-analyzer/c_symbols/nm.py | 61 +++-------------- 5 files changed, 137 insertions(+), 130 deletions(-) create mode 100644 Tools/c-analyzer/c_parser/source.py create mode 100644 Tools/c-analyzer/c_parser/util.py create mode 100644 Tools/c-analyzer/c_symbols/local.py diff --git a/Tools/c-analyzer/c_parser/declarations.py b/Tools/c-analyzer/c_parser/declarations.py index 8dc50dfcdd5f9c..26abfde1e19eba 100644 --- a/Tools/c-analyzer/c_parser/declarations.py +++ b/Tools/c-analyzer/c_parser/declarations.py @@ -2,6 +2,8 @@ import shlex import subprocess +from . import source + IDENTIFIER = r'(?:[a-zA-z]|_+[a-zA-Z0-9]\w*)' @@ -113,7 +115,7 @@ def iter_global_declarations(lines): is provided in the function body. """ # XXX Bail out upon bogus syntax. - lines = _iter_clean_lines(lines) + lines = source.iter_clean_lines(lines) for line in lines: if not GLOBAL_DECL_START_RE.match(line): continue @@ -149,7 +151,7 @@ def iter_local_statements(lines): reduced to a single line each, but the bpdies are provided as-is. """ # XXX Bail out upon bogus syntax. - lines = _iter_clean_lines(lines) + lines = source.iter_clean_lines(lines) for line in lines: if not LOCAL_STMT_START_RE.match(line): continue @@ -164,32 +166,6 @@ def iter_local_statements(lines): yield (stmt, blocks) -def _iter_clean_lines(lines): - incomment = False - for line in lines: - # Deal with comments. - if incomment: - _, sep, line = line.partition('*/') - if sep: - incomment = False - continue - line, _, _ = line.partition('//') - line, sep, remainder = line.partition('/*') - if sep: - _, sep, after = remainder.partition('*/') - if not sep: - incomment = True - continue - line += ' ' + after - - # Ignore blank lines and leading/trailing whitespace. - line = line.strip() - if not line: - continue - - yield line - - def _extract_block(lines): end = None depth = 1 @@ -251,14 +227,8 @@ def parse_compound(stmt, blocks): raise NotImplementedError -def _iter_source_lines(filename): - gcc, cflags = _get_build() - content = _preprocess(filename, gcc, cflags) - return iter(content.splitlines()) - - def iter_variables(filename, *, - _iter_source_lines=_iter_source_lines, + _iter_source_lines=source.iter_lines, _iter_global=iter_global_declarations, _iter_local=iter_local_statements, _parse_func=parse_func, @@ -306,45 +276,3 @@ def _iter_locals(lines, *, if name: yield (name, vartype) compound.extend(bodies) - - -############################# -# GCC preprocessor (platform-specific) - -def _get_build(*, - _open=open, - _run=subprocess.run, - ): - with _open('/tmp/print.mk', 'w') as tmpfile: - tmpfile.write('print-%:\n') - #tmpfile.write('\t@echo $* = $($*)\n') - tmpfile.write('\t@echo $($*)\n') - argv = ['/usr/bin/make', - '-f', 'Makefile', - '-f', '/tmp/print.mk', - 'print-CC', - 'print-PY_CORE_CFLAGS', - ] - proc = _run(argv, - capture_output=True, - text=True, - check=True, - ) - gcc, cflags = proc.stdout.strip().splitlines() - cflags = shlex.split(cflags) - return gcc, cflags - - -def _preprocess(filename, gcc, cflags, *, - _run=subprocess.run, - ): - argv = gcc.split() + cflags - argv.extend([ - '-E', filename, - ]) - proc = _run(argv, - capture_output=True, - text=True, - check=True, - ) - return proc.stdout diff --git a/Tools/c-analyzer/c_parser/source.py b/Tools/c-analyzer/c_parser/source.py new file mode 100644 index 00000000000000..52eb4ab398369c --- /dev/null +++ b/Tools/c-analyzer/c_parser/source.py @@ -0,0 +1,73 @@ +from . import util + + +def iter_clean_lines(lines): + incomment = False + for line in lines: + # Deal with comments. + if incomment: + _, sep, line = line.partition('*/') + if sep: + incomment = False + continue + line, _, _ = line.partition('//') + line, sep, remainder = line.partition('/*') + if sep: + _, sep, after = remainder.partition('*/') + if not sep: + incomment = True + continue + line += ' ' + after + + # Ignore blank lines and leading/trailing whitespace. + line = line.strip() + if not line: + continue + + yield line + + +def iter_lines(filename, *, + preprocess=True, + _get_build=(lambda: _get_build()), + _preprocess=(lambda *a, **k: _preprocess(*a, **k)), + ): + gcc, cflags = _get_build() + content = _preprocess(filename, gcc, cflags) + return iter(content.splitlines()) + + +def _get_gcc_and_cflags(*, + _open=open, + _run=util.run_cmd, + ): + with _open('/tmp/print.mk', 'w') as tmpfile: + tmpfile.write('print-%:\n') + #tmpfile.write('\t@echo $* = $($*)\n') + tmpfile.write('\t@echo $($*)\n') + argv = ['/usr/bin/make', + '-f', 'Makefile', + '-f', '/tmp/print.mk', + 'print-CC', + 'print-PY_CORE_CFLAGS', + ] + output = _run(argv) + gcc, cflags = output.strip().splitlines() + gcc, *gccflags = shlex.split(gcc) + cflags = gccflags + shlex.split(cflags) + return gcc, cflags + + +############################# +# GCC preprocessor (platform-specific) + +def _preprocess(filename, gcc, cflags, *, + _run=util.run_cmd, + ): + argv = [gcc] + argv.extend(cflags) + argv.extend([ + '-E', filename, + ]) + output = _run(argv) + return output diff --git a/Tools/c-analyzer/c_parser/util.py b/Tools/c-analyzer/c_parser/util.py new file mode 100644 index 00000000000000..d96ac2a1b020eb --- /dev/null +++ b/Tools/c-analyzer/c_parser/util.py @@ -0,0 +1,13 @@ +import subprocess + + +def run_cmd(argv): + proc = subprocess.run( + argv, + #capture_output=True, + #stderr=subprocess.STDOUT, + stdout=subprocess.PIPE, + text=True, + check=True, + ) + return proc.stdout diff --git a/Tools/c-analyzer/c_symbols/local.py b/Tools/c-analyzer/c_symbols/local.py new file mode 100644 index 00000000000000..ed36c321330aff --- /dev/null +++ b/Tools/c-analyzer/c_symbols/local.py @@ -0,0 +1,38 @@ +from c_parser import files, declarations + + +def find_symbol(name, dirnames, *, + _perfilecache, + _get_local_symbols=(lambda *a, **k: _get_symbols(*a, **k)), + _iter_files=files.iter_files, + ): + for filename in _iter_files(dirnames, ('.c', '.h')): + try: + symbols = _perfilecache[filename] + except KeyError: + symbols = _perfilecache[filename] = _get_local_symbols(filename) + + try: + instances = symbols[name] + except KeyError: + continue + + funcname, vartype = instances.pop(0) + if not instances: + symbols.pop(name) + return filename, funcname, vartype + + +def _get_symbols(filename, *, + _iter_variables=declarations.iter_variables, + ): + symbols = {} + for funcname, name, vartype in _iter_variables(filename): + if not funcname: + continue + try: + instances = symbols[name] + except KeyError: + instances = symbols[name] = [] + instances.append((funcname, vartype)) + return symbols diff --git a/Tools/c-analyzer/c_symbols/nm.py b/Tools/c-analyzer/c_symbols/nm.py index 5feb5ea9cbd74e..27cf4438fe835a 100644 --- a/Tools/c-analyzer/c_symbols/nm.py +++ b/Tools/c-analyzer/c_symbols/nm.py @@ -1,11 +1,9 @@ -from collections import namedtuple import os.path import shutil -import subprocess import sys -from c_parser import files, info -from c_parser.declarations import iter_variables +from c_parser import info, util +from . import local #PYTHON = os.path.join(REPO_ROOT, 'python') @@ -14,7 +12,7 @@ def iter_binary(dirnames, binary=PYTHON, *, _file_exists=os.path.exists, - _find_local_symbol=(lambda *a, **k: _find_local_symbol(*a, **k)), + _find_local_symbol=local.find_symbol, _iter_symbols_nm=(lambda b, fls: _iter_symbols_nm(b, fls)), ): """Yield a Symbol for each symbol found in the binary.""" @@ -27,46 +25,6 @@ def find_local_symbol(name): yield from _iter_symbols_nm(binary, find_local_symbol) -############################# -# C scanning (move to scan.py) - -def _get_local_symbols(filename, *, - _iter_variables=iter_variables, - ): - symbols = {} - for funcname, name, vartype in _iter_variables(filename): - if not funcname: - continue - try: - instances = symbols[name] - except KeyError: - instances = symbols[name] = [] - instances.append((funcname, vartype)) - return symbols - - -def _find_local_symbol(name, dirnames, *, - _perfilecache, - _get_local_symbols=_get_local_symbols, - _iter_files=files.iter_files, - ): - for filename in _iter_files(dirnames, ('.c', '.h')): - try: - symbols = _perfilecache[filename] - except KeyError: - symbols = _perfilecache[filename] = _get_local_symbols(filename) - - try: - instances = symbols[name] - except KeyError: - continue - - funcname, vartype = instances.pop(0) - if not instances: - symbols.pop(name) - return filename, funcname, vartype - - ############################# # binary format (e.g. ELF) @@ -107,25 +65,22 @@ def _is_special_symbol(name): def _iter_symbols_nm(binary, find_local_symbol=None, *, - _run=subprocess.run, + _which=shutil.which, + _run=util.run_cmd, ): - nm = shutil.which('nm') + nm = _which('nm') argv = [nm, '--line-numbers', binary, ] try: - proc = _run(argv, - capture_output=True, - text=True, - check=True, - ) + output = _run(argv) except Exception: if nm is None: # XXX Use dumpbin.exe /SYMBOLS on Windows. raise NotImplementedError raise - for line in proc.stdout.splitlines(): + for line in output.splitlines(): (name, kind, external, filename, funcname, vartype, )= _parse_nm_line(line, _find_local_symbol=find_local_symbol) if kind != info.Symbol.KIND.VARIABLE: From caac1a9a80eba502da5193c3123a59562dcbe8c6 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 5 Jul 2019 15:49:09 -0600 Subject: [PATCH 037/118] Factor out preprocessor.py. --- Tools/c-analyzer/c_parser/preprocessor.py | 43 ++++++++++++++++++++++ Tools/c-analyzer/c_parser/source.py | 45 ++--------------------- 2 files changed, 46 insertions(+), 42 deletions(-) create mode 100644 Tools/c-analyzer/c_parser/preprocessor.py diff --git a/Tools/c-analyzer/c_parser/preprocessor.py b/Tools/c-analyzer/c_parser/preprocessor.py new file mode 100644 index 00000000000000..d0aebab5a39c99 --- /dev/null +++ b/Tools/c-analyzer/c_parser/preprocessor.py @@ -0,0 +1,43 @@ +from . import util + + +def run(filename, *, + _gcc=(lambda f: _gcc(f)), + ): + return _gcc(filename) + + +############################# +# GCC preprocessor (platform-specific) + +def _gcc(filename, *, + _get_argv=(lambda: _get_gcc_argv()), + _run=util.run_cmd, + ): + argv = _get_argv() + argv.extend([ + '-E', filename, + ]) + output = _run(argv) + return output + + +def _get_gcc_argv(*, + _open=open, + _run=util.run_cmd, + ): + with _open('/tmp/print.mk', 'w') as tmpfile: + tmpfile.write('print-%:\n') + #tmpfile.write('\t@echo $* = $($*)\n') + tmpfile.write('\t@echo $($*)\n') + argv = ['/usr/bin/make', + '-f', 'Makefile', + '-f', '/tmp/print.mk', + 'print-CC', + 'print-PY_CORE_CFLAGS', + ] + output = _run(argv) + gcc, cflags = output.strip().splitlines() + argv = shlex.split(gcc.strip()) + cflags = shlex.split(cflags.strip()) + return argv + cflags diff --git a/Tools/c-analyzer/c_parser/source.py b/Tools/c-analyzer/c_parser/source.py index 52eb4ab398369c..f8998c8a338b20 100644 --- a/Tools/c-analyzer/c_parser/source.py +++ b/Tools/c-analyzer/c_parser/source.py @@ -1,4 +1,4 @@ -from . import util +from . import preprocessor def iter_clean_lines(lines): @@ -28,46 +28,7 @@ def iter_clean_lines(lines): def iter_lines(filename, *, - preprocess=True, - _get_build=(lambda: _get_build()), - _preprocess=(lambda *a, **k: _preprocess(*a, **k)), + preprocess=preprocessor.run, ): - gcc, cflags = _get_build() - content = _preprocess(filename, gcc, cflags) + content = preprocess(filename) return iter(content.splitlines()) - - -def _get_gcc_and_cflags(*, - _open=open, - _run=util.run_cmd, - ): - with _open('/tmp/print.mk', 'w') as tmpfile: - tmpfile.write('print-%:\n') - #tmpfile.write('\t@echo $* = $($*)\n') - tmpfile.write('\t@echo $($*)\n') - argv = ['/usr/bin/make', - '-f', 'Makefile', - '-f', '/tmp/print.mk', - 'print-CC', - 'print-PY_CORE_CFLAGS', - ] - output = _run(argv) - gcc, cflags = output.strip().splitlines() - gcc, *gccflags = shlex.split(gcc) - cflags = gccflags + shlex.split(cflags) - return gcc, cflags - - -############################# -# GCC preprocessor (platform-specific) - -def _preprocess(filename, gcc, cflags, *, - _run=util.run_cmd, - ): - argv = [gcc] - argv.extend(cflags) - argv.extend([ - '-E', filename, - ]) - output = _run(argv) - return output From 928cc96427db3279f659a284c9d6144a86546a5f Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 5 Jul 2019 16:28:11 -0600 Subject: [PATCH 038/118] Factor out _NTBase. --- Tools/c-analyzer/c_parser/info.py | 95 ++++++++++++++----------------- 1 file changed, 43 insertions(+), 52 deletions(-) diff --git a/Tools/c-analyzer/c_parser/info.py b/Tools/c-analyzer/c_parser/info.py index 98dab6526767be..6a5c0b066acf9b 100644 --- a/Tools/c-analyzer/c_parser/info.py +++ b/Tools/c-analyzer/c_parser/info.py @@ -16,7 +16,47 @@ def normalize_vartype(vartype): return str(vartype) -class Symbol(namedtuple('Symbol', +class _NTBase: + + __slots__ = () + + @classmethod + def _make(cls, iterable): # The default _make() is not subclass-friendly. + return cls.__new__(cls, *iterable) + + # XXX Always validate? + #def __init__(self, *args, **kwargs): + # self.validate() + + # XXX The default __repr__() is not subclass-friendly (where the name changes). + #def __repr__(self): + # _, _, sig = super().__repr__().partition('(') + # return f'{self.__class__.__name__}({sig}' + + # To make sorting work with None: + def __lt__(self, other): + try: + return super().__lt__(other) + except TypeError: + if None in self: + return True + elif None in other: + return False + else: + raise + + def validate(self): + return + + # XXX Always validate? + #def _replace(self, **kwargs): + # obj = super()._replace(**kwargs) + # obj.validate() + # return obj + + +class Symbol(_NTBase, + namedtuple('Symbol', 'name kind external filename funcname declaration')): """Info for a single compilation symbol.""" @@ -27,10 +67,6 @@ class KIND: FUNCTION = 'function' OTHER = 'other' - @classmethod - def _make(cls, iterable): # The default _make() is not subclass-friendly. - return cls.__new__(cls, *iterable) - def __new__(cls, name, kind=KIND.VARIABLE, external=None, filename=None, funcname=None, declaration=None): self = super().__new__( @@ -44,15 +80,6 @@ def __new__(cls, name, kind=KIND.VARIABLE, external=None, ) return self - # XXX Always validate? - #def __init__(self, *args, **kwargs): - # self.validate() - - # XXX The default __repr__() is not subclass-friendly (where the name changes). - #def __repr__(self): - # _, _, sig = super().__repr__().partition('(') - # return f'{self.__class__.__name__}({sig}' - def validate(self): """Fail if the object is invalid (i.e. init with bad data).""" if not self.name: @@ -80,22 +107,13 @@ def validate(self): # declaration can be not set. - # XXX Always validate? - #def _replace(self, **kwargs): - # obj = super()._replace(**kwargs) - # obj.validate() - # return obj - -class StaticVar(namedtuple('StaticVar', 'filename funcname name vartype')): +class StaticVar(_NTBase, + namedtuple('StaticVar', 'filename funcname name vartype')): """Information about a single static variable.""" __slots__ = () - @classmethod - def _make(cls, iterable): # The default _make() is not subclass-friendly. - return cls.__new__(cls, *iterable) - def __new__(cls, filename, funcname, name, vartype): self = super().__new__( cls, @@ -106,27 +124,6 @@ def __new__(cls, filename, funcname, name, vartype): ) return self - # XXX Always validate? - #def __init__(self, *args, **kwargs): - # self.validate() - - # XXX The default __repr__() is not subclass-friendly (where the name changes). - #def __repr__(self): - # _, _, sig = super().__repr__().partition('(') - # return f'{self.__class__.__name__}({sig}' - - # To make sorting work with None (for sorting): - def __lt__(self, other): - try: - return super().__lt__(other) - except TypeError: - if None in self: - return True - elif None in other: - return False - else: - raise - def validate(self): """Fail if the object is invalid (i.e. init with bad data).""" for field in self._fields: @@ -138,9 +135,3 @@ def validate(self): elif field not in ('filename', 'vartype'): if not NAME_RE.match(value): raise ValueError(f'{field} must be a name, got {value!r}') - - # XXX Always validate? - #def _replace(self, **kwargs): - # obj = super()._replace(**kwargs) - # obj.validate() - # return obj From baf2bce3eed9d59b3abdcf42d16143d2cd666540 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Wed, 10 Jul 2019 09:07:13 -0600 Subject: [PATCH 039/118] Add the wrapped_arg_combos() testing helper. --- .../test_c_parser/test_info.py | 27 +++------ .../test_c_analyzer/test_c_parser/util.py | 58 +++++++++++++++++++ 2 files changed, 65 insertions(+), 20 deletions(-) create mode 100644 Lib/test/test_tools/test_c_analyzer/test_c_parser/util.py diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_info.py b/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_info.py index c8ac895b40401e..167df1a802f9ae 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_info.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_info.py @@ -1,6 +1,7 @@ import string import unittest +from .util import PseudoStr, StrProxy, Object from .. import tool_imports_for_tests with tool_imports_for_tests(): from c_parser.info import ( @@ -8,20 +9,6 @@ ) -class PseudoStr(str): - pass - -class Proxy: - def __init__(self, value): - self.value = value - def __str__(self): - return self.value - -class Object: - def __repr__(self): - return '' - - class NormalizeVartypeTests(unittest.TestCase): def test_basic(self): @@ -30,7 +17,7 @@ def test_basic(self): ('', ''), ('int', 'int'), (PseudoStr('int'), 'int'), - (Proxy('int'), 'int'), + (StrProxy('int'), 'int'), ] for vartype, expected in tests: with self.subTest(vartype): @@ -108,10 +95,10 @@ def test_init_coercion(self): ('non-str', dict( name=('a', 'b', 'c'), - kind=Proxy('variable'), + kind=StrProxy('variable'), external=0, - filename=Proxy('x/y/z/spam.c'), - funcname=Proxy('func'), + filename=StrProxy('x/y/z/spam.c'), + funcname=StrProxy('func'), declaration=Object(), ), ("('a', 'b', 'c')", @@ -314,8 +301,8 @@ def test_init_all_coerced(self): )), ('non-str', dict( - filename=Proxy('x/y/z/spam.c'), - funcname=Proxy('func'), + filename=StrProxy('x/y/z/spam.c'), + funcname=StrProxy('func'), name=('a', 'b', 'c'), vartype=Object(), ), diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_parser/util.py b/Lib/test/test_tools/test_c_analyzer/test_c_parser/util.py new file mode 100644 index 00000000000000..f1385b246d9785 --- /dev/null +++ b/Lib/test/test_tools/test_c_analyzer/test_c_parser/util.py @@ -0,0 +1,58 @@ +import itertools + + +class PseudoStr(str): + pass + + +class StrProxy: + def __init__(self, value): + self.value = value + def __str__(self): + return self.value + + +class Object: + def __repr__(self): + return '' + + +def wrapped_arg_combos(*args, + wrappers=(PseudoStr, StrProxy), + skip=(lambda w, i, v: not isinstance(v, str)), + ): + """Yield every possible combination of wrapped items for the given args. + + Effectively, the wrappers are applied to the args according to the + powerset of the args indicies. So the result includes the args + completely unwrapped. + + If "skip" is supplied (default is to skip all non-str values) and + it returns True for a given arg index/value then that arg will + remain unwrapped, + + Only unique results are returned. If an arg was skipped for one + of the combinations then it could end up matching one of the other + combinations. In that case only one of them will be yielded. + """ + if not args: + return + indices = list(range(len(args))) + # The powerset (from recipe in the itertools docs). + combos = itertools.chain.from_iterable(itertools.combinations(indices, r) + for r in range(len(indices)+1)) + seen = set() + for combo in combos: + for wrap in wrappers: + indexes = [] + applied = list(args) + for i in combo: + arg = args[i] + if skip and skip(wrap, i, arg): + continue + indexes.append(i) + applied[i] = wrap(arg) + key = (wrap, tuple(indexes)) + if key not in seen: + yield tuple(applied) + seen.add(key) From 57ec88971474cc144fe0595b96c9ba27bac5c8f1 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 26 Jul 2019 15:00:13 -0600 Subject: [PATCH 040/118] Add preprocessor.iter_lines(). --- .../test_c_parser/test_preprocessor.py | 1514 +++++++++++++++++ .../test_c_analyzer/test_c_parser/util.py | 2 + Tools/c-analyzer/c_parser/preprocessor.py | 416 ++++- 3 files changed, 1931 insertions(+), 1 deletion(-) create mode 100644 Lib/test/test_tools/test_c_analyzer/test_c_parser/test_preprocessor.py diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_preprocessor.py b/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_preprocessor.py new file mode 100644 index 00000000000000..7a1d636f7b7ff6 --- /dev/null +++ b/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_preprocessor.py @@ -0,0 +1,1514 @@ +import itertools +import textwrap +import unittest + +from .util import wrapped_arg_combos, StrProxy +from .. import tool_imports_for_tests +with tool_imports_for_tests(): + from c_parser.preprocessor import ( + iter_lines, + # directives + parse_directive, PreprocessorDirective, + Constant, Macro, IfDirective, Include, OtherDirective, + ) + + +class TestCaseBase(unittest.TestCase): + + maxDiff = None + + def reset(self): + self._calls = [] + self.errors = None + + @property + def calls(self): + try: + return self._calls + except AttributeError: + self._calls = [] + return self._calls + + errors = None + + def try_next_exc(self): + if not self.errors: + return + if exc := self.errors.pop(0): + raise exc + + def check_calls(self, *expected): + self.assertEqual(self.calls, list(expected)) + self.assertEqual(self.errors or [], []) + + +class IterLinesTests(TestCaseBase): + + parsed = None + + def check_calls(self, *expected): + super().check_calls(*expected) + self.assertEqual(self.parsed or [], []) + + def _parse_directive(self, line): + self.calls.append( + ('_parse_directive', line)) + self.try_next_exc() + return self.parsed.pop(0) + + def test_no_lines(self): + lines = [] + + results = list( + iter_lines(lines, _parse_directive=self._parse_directive)) + + self.assertEqual(results, []) + self.check_calls() + + def test_no_directives(self): + lines = textwrap.dedent(''' + + // xyz + typedef enum { + SPAM + EGGS + } kind; + + struct info { + kind kind; + int status; + }; + + typedef struct spam { + struct info info; + } myspam; + + static int spam = 0; + + /** + * ... + */ + static char * + get_name(int arg, + char *default, + ) + { + return default + } + + int check(void) { + return 0; + } + + ''').splitlines() + + results = list( + iter_lines(lines, _parse_directive=self._parse_directive)) + + self.assertEqual(results, + [(line, None, ()) for line in lines]) + self.check_calls() + + def test_single_directives(self): + tests = [ + ('#include ', Include('')), + ('#define SPAM 1', Constant('SPAM', '1')), + ('#define SPAM() 1', Macro('SPAM', (), '1')), + ('#define SPAM(a, b) a = b;', Macro('SPAM', ('a', 'b'), 'a = b;')), + ('#if defined(SPAM)', IfDirective('if', 'defined(SPAM)')), + ('#ifdef SPAM', IfDirective('ifdef', 'SPAM')), + ('#ifndef SPAM', IfDirective('ifndef', 'SPAM')), + ('#elseif defined(SPAM)', IfDirective('elseif', 'defined(SPAM)')), + ('#else', OtherDirective('else', None)), + ('#endif', OtherDirective('endif', None)), + ('#error ...', OtherDirective('error', '...')), + ('#warning ...', OtherDirective('warning', '...')), + ('#__FILE__ ...', OtherDirective('__FILE__', '...')), + ('#__LINE__ ...', OtherDirective('__LINE__', '...')), + ('#__DATE__ ...', OtherDirective('__DATE__', '...')), + ('#__TIME__ ...', OtherDirective('__TIME__', '...')), + ('#__TIMESTAMP__ ...', OtherDirective('__TIMESTAMP__', '...')), + ] + for line, directive in tests: + with self.subTest(line): + self.reset() + self.parsed = [ + directive, + ] + text = textwrap.dedent(''' + static int spam = 0; + {} + static char buffer[256]; + ''').strip().format(line) + lines = text.strip().splitlines() + + results = list( + iter_lines(lines, _parse_directive=self._parse_directive)) + + self.assertEqual(results, [ + ('static int spam = 0;', None, ()), + (line, directive, ()), + (('static char buffer[256];', None, ('defined(SPAM)',)) + if directive.kind in ('if', 'ifdef', 'elseif') + else ('static char buffer[256];', None, ('! defined(SPAM)',)) + if directive.kind == 'ifndef' + else ('static char buffer[256];', None, ())), + ]) + self.check_calls( + ('_parse_directive', line), + ) + + def test_directive_whitespace(self): + line = ' # define eggs ( a , b ) { a = b ; } ' + directive = Macro('eggs', ('a', 'b'), '{ a = b; }') + self.parsed = [ + directive, + ] + lines = [line] + + results = list( + iter_lines(lines, _parse_directive=self._parse_directive)) + + self.assertEqual(results, [ + (line, directive, ()), + ]) + self.check_calls( + ('_parse_directive', '#define eggs ( a , b ) { a = b ; }'), + ) + + def test_split_lines(self): + directive = Macro('eggs', ('a', 'b'), '{ a = b; }') + self.parsed = [ + directive, + ] + lines = textwrap.dedent(r''' + static int spam = 0; + #define eggs(a, b) \ + { \ + a = b; \ + } + static char buffer[256]; + ''').strip().splitlines() + + results = list( + iter_lines(lines, _parse_directive=self._parse_directive)) + + self.assertEqual(results, [ + ('static int spam = 0;', None, ()), + ('#define eggs(a, b) \\', True, ()), + (' { \\', True, ()), + (' a = b; \\', True, ()), + (' }', directive, ()), + ('static char buffer[256];', None, ()), + ]) + self.check_calls( + ('_parse_directive', '#define eggs(a, b) { a = b; }'), + ) + + def test_nested_conditions(self): + directives = [ + IfDirective('ifdef', 'SPAM'), + IfDirective('if', 'SPAM == 1'), + IfDirective('elseif', 'SPAM == 2'), + OtherDirective('else', None), + OtherDirective('endif', None), + OtherDirective('endif', None), + ] + self.parsed = list(directives) + text = textwrap.dedent(r''' + static int spam = 0; + + #ifdef SPAM + static int start = 0; + # if SPAM == 1 + static char buffer[10]; + # elif SPAM == 2 + static char buffer[100]; + # else + static char buffer[256]; + # endif + static int end = 0; + #endif + + static int eggs = 0; + ''').strip() + lines = [line for line in text.splitlines() if line.strip()] + + results = list( + iter_lines(lines, _parse_directive=self._parse_directive)) + + self.assertEqual(results, [ + ('static int spam = 0;', None, ()), + ('#ifdef SPAM', directives[0], ()), + ('static int start = 0;', None, ('defined(SPAM)',)), + ('# if SPAM == 1', directives[1], ('defined(SPAM)',)), + ('static char buffer[10];', None, ('defined(SPAM)', 'SPAM == 1')), + ('# elif SPAM == 2', directives[2], ('defined(SPAM)', 'SPAM == 1')), + ('static char buffer[100];', None, ('defined(SPAM)', '! (SPAM == 1)', 'SPAM == 2')), + ('# else', directives[3], ('defined(SPAM)', '! (SPAM == 1)', 'SPAM == 2')), + ('static char buffer[256];', None, ('defined(SPAM)', '! (SPAM == 1)', '! (SPAM == 2)')), + ('# endif', directives[4], ('defined(SPAM)', '! (SPAM == 1)', '! (SPAM == 2)')), + ('static int end = 0;', None, ('defined(SPAM)',)), + ('#endif', directives[5], ('defined(SPAM)',)), + ('static int eggs = 0;', None, ()), + ]) + self.check_calls( + ('_parse_directive', '#ifdef SPAM'), + ('_parse_directive', '#if SPAM == 1'), + ('_parse_directive', '#elif SPAM == 2'), + ('_parse_directive', '#else'), + ('_parse_directive', '#endif'), + ('_parse_directive', '#endif'), + ) + + def test_split_blocks(self): + directives = [ + IfDirective('ifdef', 'SPAM'), + OtherDirective('else', None), + OtherDirective('endif', None), + ] + self.parsed = list(directives) + text = textwrap.dedent(r''' + void str_copy(char *buffer, *orig); + + int init(char *name) { + static int initialized = 0; + if (initialized) { + return 0; + } + #ifdef SPAM + static char buffer[10]; + str_copy(buffer, char); + } + + void copy(char *buffer, *orig) { + strncpy(buffer, orig, 9); + buffer[9] = 0; + } + + #else + static char buffer[256]; + str_copy(buffer, char); + } + + void copy(char *buffer, *orig) { + strcpy(buffer, orig); + } + + #endif + ''').strip() + lines = [line for line in text.splitlines() if line.strip()] + + results = list( + iter_lines(lines, _parse_directive=self._parse_directive)) + + self.assertEqual(results, [ + ('void str_copy(char *buffer, *orig);', None, ()), + ('int init(char *name) {', None, ()), + (' static int initialized = 0;', None, ()), + (' if (initialized) {', None, ()), + (' return 0;', None, ()), + (' }', None, ()), + + ('#ifdef SPAM', directives[0], ()), + + (' static char buffer[10];', None, ('defined(SPAM)',)), + (' str_copy(buffer, char);', None, ('defined(SPAM)',)), + ('}', None, ('defined(SPAM)',)), + ('void copy(char *buffer, *orig) {', None, ('defined(SPAM)',)), + (' strncpy(buffer, orig, 9);', None, ('defined(SPAM)',)), + (' buffer[9] = 0;', None, ('defined(SPAM)',)), + ('}', None, ('defined(SPAM)',)), + + ('#else', directives[1], ('defined(SPAM)',)), + + (' static char buffer[256];', None, ('! (defined(SPAM))',)), + (' str_copy(buffer, char);', None, ('! (defined(SPAM))',)), + ('}', None, ('! (defined(SPAM))',)), + ('void copy(char *buffer, *orig) {', None, ('! (defined(SPAM))',)), + (' strcpy(buffer, orig);', None, ('! (defined(SPAM))',)), + ('}', None, ('! (defined(SPAM))',)), + + ('#endif', directives[2], ('! (defined(SPAM))',)), + ]) + self.check_calls( + ('_parse_directive', '#ifdef SPAM'), + ('_parse_directive', '#else'), + ('_parse_directive', '#endif'), + ) + + def test_basic(self): + directives = [ + Include(''), + IfDirective('ifdef', 'SPAM'), + IfDirective('if', '! defined(HAM) || !HAM'), + Constant('HAM', '0'), + IfDirective('elseif', 'HAM < 0'), + Constant('HAM', '-1'), + OtherDirective('else', None), + OtherDirective('endif', None), + OtherDirective('endif', None), + IfDirective('if', 'defined(HAM) && (HAM < 0 || ! HAM)'), + OtherDirective('undef', 'HAM'), + OtherDirective('endif', None), + IfDirective('ifndef', 'HAM'), + OtherDirective('endif', None), + ] + self.parsed = list(directives) + text = textwrap.dedent(r''' + #include + print("begin"); + #ifdef SPAM + print("spam"); + #if ! defined(HAM) || !HAM + # DEFINE HAM 0 + #elseif HAM < 0 + # DEFINE HAM -1 + #else + print("ham HAM"); + #endif + #endif + + #if defined(HAM) && \ + (HAM < 0 || ! HAM) + print("ham?"); + #undef HAM + # endif + + #ifndef HAM + print("no ham"); + #endif + print("end"); + ''')[1:-1] + lines = text.splitlines() + + results = list( + iter_lines(lines, _parse_directive=self._parse_directive)) + + self.assertEqual(results, [ + ('#include ', Include(''), ()), + ('print("begin");', None, ()), + # + ('#ifdef SPAM', + IfDirective('ifdef', 'SPAM'), + ()), + (' print("spam");', + None, + ('defined(SPAM)',)), + (' #if ! defined(HAM) || !HAM', + IfDirective('if', '! defined(HAM) || !HAM'), + ('defined(SPAM)',)), + ('# DEFINE HAM 0', + Constant('HAM', '0'), + ('defined(SPAM)', '! defined(HAM) || !HAM')), + (' #elseif HAM < 0', + IfDirective('elseif', 'HAM < 0'), + ('defined(SPAM)', '! defined(HAM) || !HAM')), + ('# DEFINE HAM -1', + Constant('HAM', '-1'), + ('defined(SPAM)', '! (! defined(HAM) || !HAM)', 'HAM < 0')), + (' #else', + OtherDirective('else', None), + ('defined(SPAM)', '! (! defined(HAM) || !HAM)', 'HAM < 0')), + (' print("ham HAM");', + None, + ('defined(SPAM)', '! (! defined(HAM) || !HAM)', '! (HAM < 0)')), + (' #endif', + OtherDirective('endif', None), + ('defined(SPAM)', '! (! defined(HAM) || !HAM)', '! (HAM < 0)')), + ('#endif', + OtherDirective('endif', None), + ('defined(SPAM)',)), + # + ('', None, ()), + # + ('#if defined(HAM) && \\', True, ()), + (' (HAM < 0 || ! HAM)', + IfDirective('if', 'defined(HAM) && (HAM < 0 || ! HAM)'), + ()), + (' print("ham?");', + None, + ('defined(HAM) && (HAM < 0 || ! HAM)',)), + (' #undef HAM', + OtherDirective('undef', 'HAM'), + ('defined(HAM) && (HAM < 0 || ! HAM)',)), + ('# endif', + OtherDirective('endif', None), + ('defined(HAM) && (HAM < 0 || ! HAM)',)), + # + ('', None, ()), + # + ('#ifndef HAM', + IfDirective('ifndef', 'HAM'), + ()), + (' print("no ham");', + None, + ('! defined(HAM)',)), + ('#endif', + OtherDirective('endif', None), + ('! defined(HAM)',)), + # + ('print("end");', None, ()), + ]) + + def test_typical(self): + # We use Include/compile.h from commit 66c4f3f38b86. It has + # a good enough mix of code without being too large. + directives = [ + IfDirective('ifndef', 'Py_COMPILE_H'), + Constant('Py_COMPILE_H', None), + + IfDirective('ifndef', 'Py_LIMITED_API'), + + Include('"code.h"'), + + IfDirective('ifdef', '__cplusplus'), + OtherDirective('endif', None), + + Constant('PyCF_MASK', '(CO_FUTURE_DIVISION | CO_FUTURE_ABSOLUTE_IMPORT | CO_FUTURE_WITH_STATEMENT | CO_FUTURE_PRINT_FUNCTION | CO_FUTURE_UNICODE_LITERALS | CO_FUTURE_BARRY_AS_BDFL | CO_FUTURE_GENERATOR_STOP | CO_FUTURE_ANNOTATIONS)'), + Constant('PyCF_MASK_OBSOLETE', '(CO_NESTED)'), + Constant('PyCF_SOURCE_IS_UTF8', ' 0x0100'), + Constant('PyCF_DONT_IMPLY_DEDENT', '0x0200'), + Constant('PyCF_ONLY_AST', '0x0400'), + Constant('PyCF_IGNORE_COOKIE', '0x0800'), + Constant('PyCF_TYPE_COMMENTS', '0x1000'), + Constant('PyCF_ALLOW_TOP_LEVEL_AWAIT', '0x2000'), + + IfDirective('ifndef', 'Py_LIMITED_API'), + OtherDirective('endif', None), + + Constant('FUTURE_NESTED_SCOPES', '"nested_scopes"'), + Constant('FUTURE_GENERATORS', '"generators"'), + Constant('FUTURE_DIVISION', '"division"'), + Constant('FUTURE_ABSOLUTE_IMPORT', '"absolute_import"'), + Constant('FUTURE_WITH_STATEMENT', '"with_statement"'), + Constant('FUTURE_PRINT_FUNCTION', '"print_function"'), + Constant('FUTURE_UNICODE_LITERALS', '"unicode_literals"'), + Constant('FUTURE_BARRY_AS_BDFL', '"barry_as_FLUFL"'), + Constant('FUTURE_GENERATOR_STOP', '"generator_stop"'), + Constant('FUTURE_ANNOTATIONS', '"annotations"'), + + Macro('PyAST_Compile', ('mod', 's', 'f', 'ar'), 'PyAST_CompileEx(mod, s, f, -1, ar)'), + + Constant('PY_INVALID_STACK_EFFECT', 'INT_MAX'), + + IfDirective('ifdef', '__cplusplus'), + OtherDirective('endif', None), + + OtherDirective('endif', None), # ifndef Py_LIMITED_API + + Constant('Py_single_input', '256'), + Constant('Py_file_input', '257'), + Constant('Py_eval_input', '258'), + Constant('Py_func_type_input', '345'), + + OtherDirective('endif', None), # ifndef Py_COMPILE_H + ] + self.parsed = list(directives) + text = textwrap.dedent(r''' + #ifndef Py_COMPILE_H + #define Py_COMPILE_H + + #ifndef Py_LIMITED_API + #include "code.h" + + #ifdef __cplusplus + extern "C" { + #endif + + /* Public interface */ + struct _node; /* Declare the existence of this type */ + PyAPI_FUNC(PyCodeObject *) PyNode_Compile(struct _node *, const char *); + /* XXX (ncoghlan): Unprefixed type name in a public API! */ + + #define PyCF_MASK (CO_FUTURE_DIVISION | CO_FUTURE_ABSOLUTE_IMPORT | \ + CO_FUTURE_WITH_STATEMENT | CO_FUTURE_PRINT_FUNCTION | \ + CO_FUTURE_UNICODE_LITERALS | CO_FUTURE_BARRY_AS_BDFL | \ + CO_FUTURE_GENERATOR_STOP | CO_FUTURE_ANNOTATIONS) + #define PyCF_MASK_OBSOLETE (CO_NESTED) + #define PyCF_SOURCE_IS_UTF8 0x0100 + #define PyCF_DONT_IMPLY_DEDENT 0x0200 + #define PyCF_ONLY_AST 0x0400 + #define PyCF_IGNORE_COOKIE 0x0800 + #define PyCF_TYPE_COMMENTS 0x1000 + #define PyCF_ALLOW_TOP_LEVEL_AWAIT 0x2000 + + #ifndef Py_LIMITED_API + typedef struct { + int cf_flags; /* bitmask of CO_xxx flags relevant to future */ + int cf_feature_version; /* minor Python version (PyCF_ONLY_AST) */ + } PyCompilerFlags; + #endif + + /* Future feature support */ + + typedef struct { + int ff_features; /* flags set by future statements */ + int ff_lineno; /* line number of last future statement */ + } PyFutureFeatures; + + #define FUTURE_NESTED_SCOPES "nested_scopes" + #define FUTURE_GENERATORS "generators" + #define FUTURE_DIVISION "division" + #define FUTURE_ABSOLUTE_IMPORT "absolute_import" + #define FUTURE_WITH_STATEMENT "with_statement" + #define FUTURE_PRINT_FUNCTION "print_function" + #define FUTURE_UNICODE_LITERALS "unicode_literals" + #define FUTURE_BARRY_AS_BDFL "barry_as_FLUFL" + #define FUTURE_GENERATOR_STOP "generator_stop" + #define FUTURE_ANNOTATIONS "annotations" + + struct _mod; /* Declare the existence of this type */ + #define PyAST_Compile(mod, s, f, ar) PyAST_CompileEx(mod, s, f, -1, ar) + PyAPI_FUNC(PyCodeObject *) PyAST_CompileEx( + struct _mod *mod, + const char *filename, /* decoded from the filesystem encoding */ + PyCompilerFlags *flags, + int optimize, + PyArena *arena); + PyAPI_FUNC(PyCodeObject *) PyAST_CompileObject( + struct _mod *mod, + PyObject *filename, + PyCompilerFlags *flags, + int optimize, + PyArena *arena); + PyAPI_FUNC(PyFutureFeatures *) PyFuture_FromAST( + struct _mod * mod, + const char *filename /* decoded from the filesystem encoding */ + ); + PyAPI_FUNC(PyFutureFeatures *) PyFuture_FromASTObject( + struct _mod * mod, + PyObject *filename + ); + + /* _Py_Mangle is defined in compile.c */ + PyAPI_FUNC(PyObject*) _Py_Mangle(PyObject *p, PyObject *name); + + #define PY_INVALID_STACK_EFFECT INT_MAX + PyAPI_FUNC(int) PyCompile_OpcodeStackEffect(int opcode, int oparg); + PyAPI_FUNC(int) PyCompile_OpcodeStackEffectWithJump(int opcode, int oparg, int jump); + + PyAPI_FUNC(int) _PyAST_Optimize(struct _mod *, PyArena *arena, int optimize); + + #ifdef __cplusplus + } + #endif + + #endif /* !Py_LIMITED_API */ + + /* These definitions must match corresponding definitions in graminit.h. */ + #define Py_single_input 256 + #define Py_file_input 257 + #define Py_eval_input 258 + #define Py_func_type_input 345 + + #endif /* !Py_COMPILE_H */ + ''').strip() + lines = [line for line in text.splitlines() if line.strip()] + + results = list( + iter_lines(lines, _parse_directive=self._parse_directive)) + + self.assertEqual(results, [ + ('#ifndef Py_COMPILE_H', + IfDirective('ifndef', 'Py_COMPILE_H'), + ()), + ('#define Py_COMPILE_H', + Constant('Py_COMPILE_H', None), + ('! defined(Py_COMPILE_H)',)), + ('#ifndef Py_LIMITED_API', + IfDirective('ifndef', 'Py_LIMITED_API'), + ('! defined(Py_COMPILE_H)',)), + ('#include "code.h"', + Include('"code.h"'), + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('#ifdef __cplusplus', + IfDirective('ifdef', '__cplusplus'), + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('extern "C" {', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)', 'defined(__cplusplus)')), + ('#endif', + OtherDirective('endif', None), + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)', 'defined(__cplusplus)')), + ('/* Public interface */', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('struct _node; /* Declare the existence of this type */', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('PyAPI_FUNC(PyCodeObject *) PyNode_Compile(struct _node *, const char *);', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('/* XXX (ncoghlan): Unprefixed type name in a public API! */', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('#define PyCF_MASK (CO_FUTURE_DIVISION | CO_FUTURE_ABSOLUTE_IMPORT | \\', + True, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + (' CO_FUTURE_WITH_STATEMENT | CO_FUTURE_PRINT_FUNCTION | \\', + True, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + (' CO_FUTURE_UNICODE_LITERALS | CO_FUTURE_BARRY_AS_BDFL | \\', + True, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + (' CO_FUTURE_GENERATOR_STOP | CO_FUTURE_ANNOTATIONS)', + Constant('PyCF_MASK', '(CO_FUTURE_DIVISION | CO_FUTURE_ABSOLUTE_IMPORT | CO_FUTURE_WITH_STATEMENT | CO_FUTURE_PRINT_FUNCTION | CO_FUTURE_UNICODE_LITERALS | CO_FUTURE_BARRY_AS_BDFL | CO_FUTURE_GENERATOR_STOP | CO_FUTURE_ANNOTATIONS)'), + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('#define PyCF_MASK_OBSOLETE (CO_NESTED)', + Constant('PyCF_MASK_OBSOLETE', '(CO_NESTED)'), + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('#define PyCF_SOURCE_IS_UTF8 0x0100', + Constant('PyCF_SOURCE_IS_UTF8', ' 0x0100'), + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('#define PyCF_DONT_IMPLY_DEDENT 0x0200', + Constant('PyCF_DONT_IMPLY_DEDENT', '0x0200'), + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('#define PyCF_ONLY_AST 0x0400', + Constant('PyCF_ONLY_AST', '0x0400'), + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('#define PyCF_IGNORE_COOKIE 0x0800', + Constant('PyCF_IGNORE_COOKIE', '0x0800'), + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('#define PyCF_TYPE_COMMENTS 0x1000', + Constant('PyCF_TYPE_COMMENTS', '0x1000'), + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('#define PyCF_ALLOW_TOP_LEVEL_AWAIT 0x2000', + Constant('PyCF_ALLOW_TOP_LEVEL_AWAIT', '0x2000'), + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('#ifndef Py_LIMITED_API', + IfDirective('ifndef', 'Py_LIMITED_API'), + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('typedef struct {', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)', '! defined(Py_LIMITED_API)')), + (' int cf_flags; /* bitmask of CO_xxx flags relevant to future */', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)', '! defined(Py_LIMITED_API)')), + (' int cf_feature_version; /* minor Python version (PyCF_ONLY_AST) */', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)', '! defined(Py_LIMITED_API)')), + ('} PyCompilerFlags;', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)', '! defined(Py_LIMITED_API)')), + ('#endif', + OtherDirective('endif', None), + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)', '! defined(Py_LIMITED_API)')), + ('/* Future feature support */', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('typedef struct {', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + (' int ff_features; /* flags set by future statements */', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + (' int ff_lineno; /* line number of last future statement */', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('} PyFutureFeatures;', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('#define FUTURE_NESTED_SCOPES "nested_scopes"', + Constant('FUTURE_NESTED_SCOPES', '"nested_scopes"'), + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('#define FUTURE_GENERATORS "generators"', + Constant('FUTURE_GENERATORS', '"generators"'), + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('#define FUTURE_DIVISION "division"', + Constant('FUTURE_DIVISION', '"division"'), + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('#define FUTURE_ABSOLUTE_IMPORT "absolute_import"', + Constant('FUTURE_ABSOLUTE_IMPORT', '"absolute_import"'), + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('#define FUTURE_WITH_STATEMENT "with_statement"', + Constant('FUTURE_WITH_STATEMENT', '"with_statement"'), + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('#define FUTURE_PRINT_FUNCTION "print_function"', + Constant('FUTURE_PRINT_FUNCTION', '"print_function"'), + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('#define FUTURE_UNICODE_LITERALS "unicode_literals"', + Constant('FUTURE_UNICODE_LITERALS', '"unicode_literals"'), + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('#define FUTURE_BARRY_AS_BDFL "barry_as_FLUFL"', + Constant('FUTURE_BARRY_AS_BDFL', '"barry_as_FLUFL"'), + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('#define FUTURE_GENERATOR_STOP "generator_stop"', + Constant('FUTURE_GENERATOR_STOP', '"generator_stop"'), + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('#define FUTURE_ANNOTATIONS "annotations"', + Constant('FUTURE_ANNOTATIONS', '"annotations"'), + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('struct _mod; /* Declare the existence of this type */', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('#define PyAST_Compile(mod, s, f, ar) PyAST_CompileEx(mod, s, f, -1, ar)', + Macro('PyAST_Compile', ('mod', 's', 'f', 'ar'), 'PyAST_CompileEx(mod, s, f, -1, ar)'), + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('PyAPI_FUNC(PyCodeObject *) PyAST_CompileEx(', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + (' struct _mod *mod,', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + (' const char *filename, /* decoded from the filesystem encoding */', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + (' PyCompilerFlags *flags,', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + (' int optimize,', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + (' PyArena *arena);', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('PyAPI_FUNC(PyCodeObject *) PyAST_CompileObject(', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + (' struct _mod *mod,', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + (' PyObject *filename,', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + (' PyCompilerFlags *flags,', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + (' int optimize,', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + (' PyArena *arena);', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('PyAPI_FUNC(PyFutureFeatures *) PyFuture_FromAST(', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + (' struct _mod * mod,', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + (' const char *filename /* decoded from the filesystem encoding */', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + (' );', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('PyAPI_FUNC(PyFutureFeatures *) PyFuture_FromASTObject(', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + (' struct _mod * mod,', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + (' PyObject *filename', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + (' );', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('/* _Py_Mangle is defined in compile.c */', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('PyAPI_FUNC(PyObject*) _Py_Mangle(PyObject *p, PyObject *name);', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('#define PY_INVALID_STACK_EFFECT INT_MAX', + Constant('PY_INVALID_STACK_EFFECT', 'INT_MAX'), + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('PyAPI_FUNC(int) PyCompile_OpcodeStackEffect(int opcode, int oparg);', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('PyAPI_FUNC(int) PyCompile_OpcodeStackEffectWithJump(int opcode, int oparg, int jump);', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('PyAPI_FUNC(int) _PyAST_Optimize(struct _mod *, PyArena *arena, int optimize);', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('#ifdef __cplusplus', + IfDirective('ifdef', '__cplusplus'), + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('}', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)', 'defined(__cplusplus)')), + ('#endif', + OtherDirective('endif', None), + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)', 'defined(__cplusplus)')), + ('#endif /* !Py_LIMITED_API */', + OtherDirective('endif', None), + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + ('/* These definitions must match corresponding definitions in graminit.h. */', + None, + ('! defined(Py_COMPILE_H)',)), + ('#define Py_single_input 256', + Constant('Py_single_input', '256'), + ('! defined(Py_COMPILE_H)',)), + ('#define Py_file_input 257', + Constant('Py_file_input', '257'), + ('! defined(Py_COMPILE_H)',)), + ('#define Py_eval_input 258', + Constant('Py_eval_input', '258'), + ('! defined(Py_COMPILE_H)',)), + ('#define Py_func_type_input 345', + Constant('Py_func_type_input', '345'), + ('! defined(Py_COMPILE_H)',)), + ('#endif /* !Py_COMPILE_H */', + OtherDirective('endif', None), + ('! defined(Py_COMPILE_H)',)), + ]) + self.check_calls( + ('_parse_directive', '#ifndef Py_COMPILE_H'), + ('_parse_directive', '#define Py_COMPILE_H'), + ('_parse_directive', '#ifndef Py_LIMITED_API'), + ('_parse_directive', '#include "code.h"'), + ('_parse_directive', '#ifdef __cplusplus'), + ('_parse_directive', '#endif'), + ('_parse_directive', '#define PyCF_MASK (CO_FUTURE_DIVISION | CO_FUTURE_ABSOLUTE_IMPORT | CO_FUTURE_WITH_STATEMENT | CO_FUTURE_PRINT_FUNCTION | CO_FUTURE_UNICODE_LITERALS | CO_FUTURE_BARRY_AS_BDFL | CO_FUTURE_GENERATOR_STOP | CO_FUTURE_ANNOTATIONS)'), + ('_parse_directive', '#define PyCF_MASK_OBSOLETE (CO_NESTED)'), + ('_parse_directive', '#define PyCF_SOURCE_IS_UTF8 0x0100'), + ('_parse_directive', '#define PyCF_DONT_IMPLY_DEDENT 0x0200'), + ('_parse_directive', '#define PyCF_ONLY_AST 0x0400'), + ('_parse_directive', '#define PyCF_IGNORE_COOKIE 0x0800'), + ('_parse_directive', '#define PyCF_TYPE_COMMENTS 0x1000'), + ('_parse_directive', '#define PyCF_ALLOW_TOP_LEVEL_AWAIT 0x2000'), + ('_parse_directive', '#ifndef Py_LIMITED_API'), + ('_parse_directive', '#endif'), + ('_parse_directive', '#define FUTURE_NESTED_SCOPES "nested_scopes"'), + ('_parse_directive', '#define FUTURE_GENERATORS "generators"'), + ('_parse_directive', '#define FUTURE_DIVISION "division"'), + ('_parse_directive', '#define FUTURE_ABSOLUTE_IMPORT "absolute_import"'), + ('_parse_directive', '#define FUTURE_WITH_STATEMENT "with_statement"'), + ('_parse_directive', '#define FUTURE_PRINT_FUNCTION "print_function"'), + ('_parse_directive', '#define FUTURE_UNICODE_LITERALS "unicode_literals"'), + ('_parse_directive', '#define FUTURE_BARRY_AS_BDFL "barry_as_FLUFL"'), + ('_parse_directive', '#define FUTURE_GENERATOR_STOP "generator_stop"'), + ('_parse_directive', '#define FUTURE_ANNOTATIONS "annotations"'), + ('_parse_directive', '#define PyAST_Compile(mod, s, f, ar) PyAST_CompileEx(mod, s, f, -1, ar)'), + ('_parse_directive', '#define PY_INVALID_STACK_EFFECT INT_MAX'), + ('_parse_directive', '#ifdef __cplusplus'), + ('_parse_directive', '#endif'), + ('_parse_directive', '#endif /* !Py_LIMITED_API */'), + ('_parse_directive', '#define Py_single_input 256'), + ('_parse_directive', '#define Py_file_input 257'), + ('_parse_directive', '#define Py_eval_input 258'), + ('_parse_directive', '#define Py_func_type_input 345'), + ('_parse_directive', '#endif /* !Py_COMPILE_H */'), + ) + + +class ParseDirectiveTests(unittest.TestCase): + + def test_directives(self): + tests = [ + # includes + ('#include "internal/pycore_pystate.h"', Include('"internal/pycore_pystate.h"')), + ('#include ', Include('')), + + # defines + ('#define SPAM int', Constant('SPAM', 'int')), + ('#define SPAM', Constant('SPAM', '')), + ('#define SPAM(x, y) run(x, y)', Macro('SPAM', ('x', 'y'), 'run(x, y)')), + ('#undef SPAM', None), + + # conditionals + ('#if SPAM', IfDirective('if', 'SPAM')), + # XXX complex conditionls + ('#ifdef SPAM', IfDirective('ifdef', 'SPAM')), + ('#ifndef SPAM', IfDirective('ifndef', 'SPAM')), + ('#elseif SPAM', IfDirective('elseif', 'SPAM')), + # XXX complex conditionls + ('#else', OtherDirective('else', '')), + ('#endif', OtherDirective('endif', '')), + + # other + ('#error oops!', None), + ('#warning oops!', None), + ('#pragma ...', None), + ('#__FILE__ ...', None), + ('#__LINE__ ...', None), + ('#__DATE__ ...', None), + ('#__TIME__ ...', None), + ('#__TIMESTAMP__ ...', None), + + # extra whitespace + (' # include ', Include('')), + ('#else ', OtherDirective('else', '')), + ('#endif ', OtherDirective('endif', '')), + ('#define SPAM int ', Constant('SPAM', 'int')), + ('#define SPAM ', Constant('SPAM', '')), + ] + for line, expected in tests: + if expected is None: + kind, _, text = line[1:].partition(' ') + expected = OtherDirective(kind, text) + with self.subTest(line): + directive = parse_directive(line) + + self.assertEqual(directive, expected) + + def test_bad_directives(self): + tests = [ + # valid directives with bad text + '#define 123', + '#else spam', + '#endif spam', + ] + for kind in PreprocessorDirective.KINDS: + # missing leading "#" + tests.append(kind) + if kind in ('else', 'endif'): + continue + # valid directives with missing text + tests.append('#' + kind) + tests.append('#' + kind + ' ') + for line in tests: + with self.subTest(line): + with self.assertRaises(ValueError): + parse_directive(line) + + def test_not_directives(self): + tests = [ + '', + ' ', + 'directive', + 'directive?', + '???', + ] + for line in tests: + with self.subTest(line): + with self.assertRaises(ValueError): + parse_directive(line) + + +class ConstantTests(unittest.TestCase): + + def test_type(self): + directive = Constant('SPAM', '123') + + self.assertIs(type(directive), Constant) + self.assertIsInstance(directive, PreprocessorDirective) + + def test_attrs(self): + d = Constant('SPAM', '123') + kind, name, value = d.kind, d.name, d.value + + self.assertEqual(kind, 'define') + self.assertEqual(name, 'SPAM') + self.assertEqual(value, '123') + + def test_text(self): + tests = [ + (('SPAM', '123'), 'SPAM 123'), + (('SPAM',), 'SPAM'), + ] + for args, expected in tests: + with self.subTest(args): + d = Constant(*args) + text = d.text + + self.assertEqual(text, expected) + + def test_iter(self): + kind, name, value = Constant('SPAM', '123') + + self.assertEqual(kind, 'define') + self.assertEqual(name, 'SPAM') + self.assertEqual(value, '123') + + def test_defaults(self): + kind, name, value = Constant('SPAM') + + self.assertEqual(kind, 'define') + self.assertEqual(name, 'SPAM') + self.assertIs(value, None) + + def test_coerce(self): + tests = [] + # coerced name, value + for args in wrapped_arg_combos('SPAM', '123'): + tests.append((args, ('SPAM', '123'))) + # missing name, value + for name in ('', ' ', None, StrProxy(' '), ()): + for value in ('', ' ', None, StrProxy(' '), ()): + tests.append( + ((name, value), (None, None))) + # whitespace + tests.extend([ + ((' SPAM ', ' 123 '), ('SPAM', '123')), + ]) + + for args, expected in tests: + with self.subTest(args): + d = Constant(*args) + + self.assertEqual(d[1:], expected) + for i, exp in enumerate(expected, start=1): + if exp is not None: + self.assertIs(type(d[i]), str) + + def test_valid(self): + tests = [ + ('SPAM', '123'), + # unusual name + ('_SPAM_', '123'), + ('X_1', '123'), + # unusual value + ('SPAM', None), + ] + for args in tests: + with self.subTest(args): + directive = Constant(*args) + + directive.validate() + + def test_invalid(self): + tests = [ + # invalid name + ((None, '123'), TypeError), + (('_', '123'), ValueError), + (('1', '123'), ValueError), + (('_1_', '123'), ValueError), + # There is no invalid value (including None). + ] + for args, exctype in tests: + with self.subTest(args): + directive = Constant(*args) + + with self.assertRaises(exctype): + directive.validate() + + +class MacroTests(unittest.TestCase): + + def test_type(self): + directive = Macro('SPAM', ('x', 'y'), '123') + + self.assertIs(type(directive), Macro) + self.assertIsInstance(directive, PreprocessorDirective) + + def test_attrs(self): + d = Macro('SPAM', ('x', 'y'), '123') + kind, name, args, body = d.kind, d.name, d.args, d.body + + self.assertEqual(kind, 'define') + self.assertEqual(name, 'SPAM') + self.assertEqual(args, ('x', 'y')) + self.assertEqual(body, '123') + + def test_text(self): + tests = [ + (('SPAM', ('x', 'y'), '123'), 'SPAM(x, y) 123'), + (('SPAM', ('x', 'y'),), 'SPAM(x, y)'), + ] + for args, expected in tests: + with self.subTest(args): + d = Macro(*args) + text = d.text + + self.assertEqual(text, expected) + + def test_iter(self): + kind, name, args, body = Macro('SPAM', ('x', 'y'), '123') + + self.assertEqual(kind, 'define') + self.assertEqual(name, 'SPAM') + self.assertEqual(args, ('x', 'y')) + self.assertEqual(body, '123') + + def test_defaults(self): + kind, name, args, body = Macro('SPAM', ('x', 'y')) + + self.assertEqual(kind, 'define') + self.assertEqual(name, 'SPAM') + self.assertEqual(args, ('x', 'y')) + self.assertIs(body, None) + + def test_coerce(self): + tests = [] + # coerce name and body + for args in wrapped_arg_combos('SPAM', ('x', 'y'), '123'): + tests.append( + (args, ('SPAM', ('x', 'y'), '123'))) + # coerce args + tests.extend([ + (('SPAM', 'x', '123'), + ('SPAM', ('x',), '123')), + (('SPAM', 'x,y', '123'), + ('SPAM', ('x', 'y'), '123')), + ]) + # coerce arg names + for argnames in wrapped_arg_combos('x', 'y'): + tests.append( + (('SPAM', argnames, '123'), + ('SPAM', ('x', 'y'), '123'))) + # missing name, body + for name in ('', ' ', None, StrProxy(' '), ()): + for argnames in (None, ()): + for body in ('', ' ', None, StrProxy(' '), ()): + tests.append( + ((name, argnames, body), + (None, (), None))) + # missing args + tests.extend([ + (('SPAM', None, '123'), + ('SPAM', (), '123')), + (('SPAM', (), '123'), + ('SPAM', (), '123')), + ]) + # missing arg names + for arg in ('', ' ', None, StrProxy(' '), ()): + tests.append( + (('SPAM', (arg,), '123'), + ('SPAM', (None,), '123'))) + tests.extend([ + (('SPAM', ('x', '', 'z'), '123'), + ('SPAM', ('x', None, 'z'), '123')), + ]) + # whitespace + tests.extend([ + ((' SPAM ', (' x ', ' y '), ' 123 '), + ('SPAM', ('x', 'y'), '123')), + (('SPAM', 'x, y', '123'), + ('SPAM', ('x', 'y'), '123')), + ]) + + for args, expected in tests: + with self.subTest(args): + d = Macro(*args) + + self.assertEqual(d[1:], expected) + for i, exp in enumerate(expected, start=1): + if i == 2: + self.assertIs(type(d[i]), tuple) + elif exp is not None: + self.assertIs(type(d[i]), str) + + def test_init_bad_args(self): + tests = [ + ('SPAM', StrProxy('x'), '123'), + ('SPAM', object(), '123'), + ] + for args in tests: + with self.subTest(args): + with self.assertRaises(TypeError): + Macro(*args) + + def test_valid(self): + tests = [ + # unusual name + ('SPAM', ('x', 'y'), 'run(x, y)'), + ('_SPAM_', ('x', 'y'), 'run(x, y)'), + ('X_1', ('x', 'y'), 'run(x, y)'), + # unusual args + ('SPAM', (), 'run(x, y)'), + ('SPAM', ('_x_', 'y_1'), 'run(x, y)'), + ('SPAM', 'x', 'run(x, y)'), + ('SPAM', 'x, y', 'run(x, y)'), + # unusual body + ('SPAM', ('x', 'y'), None), + ] + for args in tests: + with self.subTest(args): + directive = Macro(*args) + + directive.validate() + + def test_invalid(self): + tests = [ + # invalid name + ((None, ('x', 'y'), '123'), TypeError), + (('_', ('x', 'y'), '123'), ValueError), + (('1', ('x', 'y'), '123'), ValueError), + (('_1', ('x', 'y'), '123'), ValueError), + # invalid args + (('SPAM', (None, 'y'), '123'), ValueError), + (('SPAM', ('x', '_'), '123'), ValueError), + (('SPAM', ('x', '1'), '123'), ValueError), + (('SPAM', ('x', '_1_'), '123'), ValueError), + # There is no invalid body (including None). + ] + for args, exctype in tests: + with self.subTest(args): + directive = Macro(*args) + + with self.assertRaises(exctype): + directive.validate() + + +class IfDirectiveTests(unittest.TestCase): + + def test_type(self): + directive = IfDirective('if', '1') + + self.assertIs(type(directive), IfDirective) + self.assertIsInstance(directive, PreprocessorDirective) + + def test_attrs(self): + d = IfDirective('if', '1') + kind, condition = d.kind, d.condition + + self.assertEqual(kind, 'if') + self.assertEqual(condition, '1') + #self.assertEqual(condition, (ArithmeticCondition('1'),)) + + def test_text(self): + tests = [ + (('if', 'defined(SPAM) && 1 || (EGGS > 3 && defined(HAM))'), + 'defined(SPAM) && 1 || (EGGS > 3 && defined(HAM))'), + ] + for kind in IfDirective.KINDS: + tests.append( + ((kind, 'SPAM'), 'SPAM')) + for args, expected in tests: + with self.subTest(args): + d = IfDirective(*args) + text = d.text + + self.assertEqual(text, expected) + + def test_iter(self): + kind, condition = IfDirective('if', '1') + + self.assertEqual(kind, 'if') + self.assertEqual(condition, '1') + #self.assertEqual(condition, (ArithmeticCondition('1'),)) + + #def test_complex_conditions(self): + # ... + + def test_coerce(self): + tests = [] + for kind in IfDirective.KINDS: + if kind == 'ifdef': + cond = 'defined(SPAM)' + elif kind == 'ifndef': + cond = '! defined(SPAM)' + else: + cond = 'SPAM' + for args in wrapped_arg_combos(kind, 'SPAM'): + tests.append((args, (kind, cond))) + tests.extend([ + ((' ' + kind + ' ', ' SPAM '), (kind, cond)), + ]) + for raw in ('', ' ', None, StrProxy(' '), ()): + tests.append(((kind, raw), (kind, None))) + for kind in ('', ' ', None, StrProxy(' '), ()): + tests.append(((kind, 'SPAM'), (None, 'SPAM'))) + for args, expected in tests: + with self.subTest(args): + d = IfDirective(*args) + + self.assertEqual(tuple(d), expected) + for i, exp in enumerate(expected): + if exp is not None: + self.assertIs(type(d[i]), str) + + def test_valid(self): + tests = [] + for kind in IfDirective.KINDS: + tests.extend([ + (kind, 'SPAM'), + (kind, '_SPAM_'), + (kind, 'X_1'), + (kind, '()'), + (kind, '--'), + (kind, '???'), + ]) + for args in tests: + with self.subTest(args): + directive = IfDirective(*args) + + directive.validate() + + def test_invalid(self): + tests = [] + # kind + tests.extend([ + ((None, 'SPAM'), TypeError), + (('_', 'SPAM'), ValueError), + (('-', 'SPAM'), ValueError), + (('spam', 'SPAM'), ValueError), + ]) + for kind in PreprocessorDirective.KINDS: + if kind in IfDirective.KINDS: + continue + tests.append( + ((kind, 'SPAM'), ValueError)) + # condition + for kind in IfDirective.KINDS: + tests.extend([ + ((kind, None), TypeError), + # Any other condition is valid. + ]) + for args, exctype in tests: + with self.subTest(args): + directive = IfDirective(*args) + + with self.assertRaises(exctype): + directive.validate() + + +class IncludeTests(unittest.TestCase): + + def test_type(self): + directive = Include('') + + self.assertIs(type(directive), Include) + self.assertIsInstance(directive, PreprocessorDirective) + + def test_attrs(self): + d = Include('') + kind, file, text = d.kind, d.file, d.text + + self.assertEqual(kind, 'include') + self.assertEqual(file, '') + self.assertEqual(text, '') + + def test_iter(self): + kind, file = Include('') + + self.assertEqual(kind, 'include') + self.assertEqual(file, '') + + def test_coerce(self): + tests = [] + for arg, in wrapped_arg_combos(''): + tests.append((arg, '')) + tests.extend([ + (' ', ''), + ]) + for arg in ('', ' ', None, StrProxy(' '), ()): + tests.append((arg, None )) + for arg, expected in tests: + with self.subTest(arg): + _, file = Include(arg) + + self.assertEqual(file, expected) + if expected is not None: + self.assertIs(type(file), str) + + def test_valid(self): + tests = [ + '', + '"spam.h"', + '"internal/pycore_pystate.h"', + ] + for arg in tests: + with self.subTest(arg): + directive = Include(arg) + + directive.validate() + + def test_invalid(self): + tests = [ + (None, TypeError), + # We currently don't check the file. + ] + for arg, exctype in tests: + with self.subTest(arg): + directive = Include(arg) + + with self.assertRaises(exctype): + directive.validate() + + +class OtherDirectiveTests(unittest.TestCase): + + def test_type(self): + directive = OtherDirective('undef', 'SPAM') + + self.assertIs(type(directive), OtherDirective) + self.assertIsInstance(directive, PreprocessorDirective) + + def test_attrs(self): + d = OtherDirective('undef', 'SPAM') + kind, text = d.kind, d.text + + self.assertEqual(kind, 'undef') + self.assertEqual(text, 'SPAM') + + def test_iter(self): + kind, text = OtherDirective('undef', 'SPAM') + + self.assertEqual(kind, 'undef') + self.assertEqual(text, 'SPAM') + + def test_coerce(self): + tests = [] + for kind in OtherDirective.KINDS: + if kind in ('else', 'endif'): + continue + for args in wrapped_arg_combos(kind, '...'): + tests.append((args, (kind, '...'))) + tests.extend([ + ((' ' + kind + ' ', ' ... '), (kind, '...')), + ]) + for raw in ('', ' ', None, StrProxy(' '), ()): + tests.append(((kind, raw), (kind, None))) + for kind in ('else', 'endif'): + for args in wrapped_arg_combos(kind, None): + tests.append((args, (kind, None))) + tests.extend([ + ((' ' + kind + ' ', None), (kind, None)), + ]) + for kind in ('', ' ', None, StrProxy(' '), ()): + tests.append(((kind, '...'), (None, '...'))) + for args, expected in tests: + with self.subTest(args): + d = OtherDirective(*args) + + self.assertEqual(tuple(d), expected) + for i, exp in enumerate(expected): + if exp is not None: + self.assertIs(type(d[i]), str) + + def test_valid(self): + tests = [] + for kind in OtherDirective.KINDS: + if kind in ('else', 'endif'): + continue + tests.extend([ + (kind, '...'), + (kind, '???'), + (kind, 'SPAM'), + (kind, '1 + 1'), + ]) + for kind in ('else', 'endif'): + tests.append((kind, None)) + for args in tests: + with self.subTest(args): + directive = OtherDirective(*args) + + directive.validate() + + def test_invalid(self): + tests = [] + # kind + tests.extend([ + ((None, '...'), TypeError), + (('_', '...'), ValueError), + (('-', '...'), ValueError), + (('spam', '...'), ValueError), + ]) + for kind in PreprocessorDirective.KINDS: + if kind in OtherDirective.KINDS: + continue + tests.append( + ((kind, None), ValueError)) + # text + for kind in OtherDirective.KINDS: + if kind in ('else', 'endif'): + tests.extend([ + # Any text is invalid. + ((kind, 'SPAM'), ValueError), + ((kind, '...'), ValueError), + ]) + else: + tests.extend([ + ((kind, None), TypeError), + # Any other text is valid. + ]) + for args, exctype in tests: + with self.subTest(args): + directive = OtherDirective(*args) + + with self.assertRaises(exctype): + directive.validate() diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_parser/util.py b/Lib/test/test_tools/test_c_analyzer/test_c_parser/util.py index f1385b246d9785..ba73b0a4b5fc6b 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_parser/util.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_parser/util.py @@ -10,6 +10,8 @@ def __init__(self, value): self.value = value def __str__(self): return self.value + def __bool__(self): + return bool(self.value) class Object: diff --git a/Tools/c-analyzer/c_parser/preprocessor.py b/Tools/c-analyzer/c_parser/preprocessor.py index d0aebab5a39c99..3ebfedd0bea7ff 100644 --- a/Tools/c-analyzer/c_parser/preprocessor.py +++ b/Tools/c-analyzer/c_parser/preprocessor.py @@ -1,12 +1,426 @@ -from . import util +from collections import namedtuple +import re + +from . import util, info + + +IDENTIFIER = r'(?:\w*[a-zA-Z]\w*)' +IDENTIFIER_RE = re.compile('^' + IDENTIFIER + '$') + + +def _coerce_str(value): + if not value: + return '' + return str(value).strip() + + +def iter_lines(lines, *, + _parse_directive=(lambda l: parse_directive(l)), + ): + """Yield (line, directive, active conditions) for each given line. + + "lines" is expected to be comment-free. Each line is returned + as-is. + + "active conditions" is the set of preprocessor conditions (e.g. + "defined()") under which the current line of code will be included + in compilation. That set is derived from every conditional + directive block (e.g. "if defined()", "ifdef", "else") containing + that line. That includes nested directives. Note that the + current line does not affect the active conditions for iteself. + It only impacts subsequent lines. That applies to directives + that close blocks (e.g. "endif") just as much as conditional + directvies. Also note that "else" and "elseif" directives + update the active conditions (for later lines), rather than + adding to them. + + If a directive has line continuations then each line is returned + with a "directive" of True, except for the last line, which has + the directive object like normal. + """ + ifdefs = [] + def _recompute_conditions(directive): + if directive.kind in ('if', 'ifdef', 'ifndef'): + ifdefs.append( + ([], directive.condition)) + elif directive.kind == 'elseif': + if ifdefs: + negated, active = ifdefs.pop() + if active: + negated.append(active) + else: + negated = [] + ifdefs.append( + (negated, directive.condition)) + elif directive.kind == 'else': + if ifdefs: + negated, active = ifdefs.pop() + if active: + negated.append(active) + ifdefs.append( + (negated, None)) + elif directive.kind == 'endif': + if ifdefs: + ifdefs.pop() + + conditions = [] + for negated, active in ifdefs: + for condition in negated: + conditions.append(f'! ({condition})') + if active: + conditions.append(active) + return tuple(conditions) + + incomment = False + conditions = () + directive = None + for line in lines: + if directive: + directive += ' ' + line.strip() + else: + stripped = line.strip() + if not stripped.startswith('#'): + yield line, None, conditions + continue + directive = '#' + stripped[1:].lstrip() + + if directive.endswith('\\'): + directive = directive[:-1] + yield line, True, conditions + else: + while ' ' in directive: + directive = directive.replace(' ', ' ') + directive = _parse_directive(directive) + yield line, directive, conditions + last = None + if directive.kind in ('else', 'endif'): + conditions = _recompute_conditions(directive) + elif isinstance(directive, IfDirective): + conditions = _recompute_conditions(directive) + directive = None def run(filename, *, _gcc=(lambda f: _gcc(f)), ): + """Return the text of the given file after running the preprocessor.""" return _gcc(filename) +############################# +# directives + +DIRECTIVE_START = r''' + (?: + ^ \s* + [#] \s* + )''' +DIRECTIVE_TEXT = r''' + (?: + (?: \s+ ( .*\S ) )? + \s* $ + )''' +DIRECTIVE = rf''' + (?: + {DIRECTIVE_START} + ( + include | + error | warning | + pragma | + define | undef | + if | ifdef | ifndef | elseif | else | endif | + __FILE__ | __LINE__ | __DATE __ | __TIME__ | __TIMESTAMP__ + ) + {DIRECTIVE_TEXT} + )''' +# (?: +# [^\\\n] | +# \\ [^\n] | +# \\ \n +# )+ +# ) \n +# )''' +DIRECTIVE_RE = re.compile(DIRECTIVE, re.VERBOSE) + +DEFINE = rf''' + (?: + {DIRECTIVE_START} define \s+ + (?: + ( \w*[a-zA-Z]\w* ) + (?: \s* [(] ([^)]*) [)] )? + ) + {DIRECTIVE_TEXT} + )''' +DEFINE_RE = re.compile(DEFINE, re.VERBOSE) + + +def parse_directive(line): + """Return the appropriate directive for the given line.""" + m = DEFINE_RE.match(line) + if m: + name, args, text = m.groups() + if args: + args = [a.strip() for a in args.split(',')] + return Macro(name, args, text) + else: + return Constant(name, text) + + m = DIRECTIVE_RE.match(line) + if not m: + raise ValueError(f'unsupported directive {line!r}') + kind, text = m.groups() + if not text: + if kind not in ('else', 'endif'): + raise ValueError(f'missing text in directive {line!r}') + elif kind in ('else', 'endif', 'define'): + raise ValueError(f'unexpected text in directive {line!r}') + if kind == 'include': + directive = Include(text) + elif kind in IfDirective.KINDS: + directive = IfDirective(kind, text) + else: + directive = OtherDirective(kind, text) + directive.validate() + return directive + + +class PreprocessorDirective(info._NTBase): + """The base class for directives.""" + + __slots__ = () + + KINDS = frozenset([ + 'include', + 'pragma', + 'error', 'warning', + 'define', 'undef', + 'if', 'ifdef', 'ifndef', 'elseif', 'else', 'endif', + '__FILE__', '__DATE__', '__LINE__', '__TIME__', '__TIMESTAMP__', + ]) + + @property + def text(self): + return ' '.join(v for v in self[1:] if v and v.strip()) or None + + def validate(self): + """Fail if the object is invalid (i.e. init with bad data).""" + super().validate() + + if not self.kind: + raise TypeError('missing kind') + elif self.kind not in self.KINDS: + raise ValueError + + # text can be anything, including None. + + +class Constant(PreprocessorDirective, + namedtuple('Constant', 'kind name value')): + """A single "constant" directive ("define").""" + + __slots__ = () + + def __new__(cls, name, value=None): + self = super().__new__( + cls, + 'define', + name=_coerce_str(name) or None, + value=_coerce_str(value) or None, + ) + return self + + def validate(self): + """Fail if the object is invalid (i.e. init with bad data).""" + super().validate() + + if not self.name: + raise TypeError('missing name') + elif not IDENTIFIER_RE.match(self.name): + raise ValueError(f'name must be identifier, got {self.name!r}') + + # value can be anything, including None + + +class Macro(PreprocessorDirective, + namedtuple('Macro', 'kind name args body')): + """A single "macro" directive ("define").""" + + __slots__ = () + + def __new__(cls, name, args, body=None): + # "args" must be a string or an iterable of strings (or "empty"). + if isinstance(args, str): + args = [v.strip() for v in args.split(',')] + if args: + args = tuple(_coerce_str(a) or None for a in args) + self = super().__new__( + cls, + kind='define', + name=_coerce_str(name) or None, + args=args if args else (), + body=_coerce_str(body) or None, + ) + return self + + @property + def text(self): + if self.body: + return f'{self.name}({", ".join(self.args)}) {self.body}' + else: + return f'{self.name}({", ".join(self.args)})' + + def validate(self): + """Fail if the object is invalid (i.e. init with bad data).""" + super().validate() + + if not self.name: + raise TypeError('missing name') + elif not IDENTIFIER_RE.match(self.name): + raise ValueError(f'name must be identifier, got {self.name!r}') + + for arg in self.args: + if not arg: + raise ValueError(f'missing arg in {self.args}') + elif not IDENTIFIER_RE.match(arg): + raise ValueError(f'arg must be identifier, got {arg!r}') + + # body can be anything, including None + + +class IfDirective(PreprocessorDirective, + namedtuple('IfDirective', 'kind condition')): + """A single conditional directive (e.g. "if", "ifdef"). + + This only includes directives that actually provide conditions. The + related directives "else" and "endif" are covered by OtherDirective + instead. + """ + + __slots__ = () + + KINDS = frozenset([ + 'if', + 'ifdef', + 'ifndef', + 'elseif', + ]) + + @classmethod + def _condition_from_raw(cls, raw, kind): + #return Condition.from_raw(raw, _kind=kind) + condition = _coerce_str(raw) + if not condition: + return None + + if kind == 'ifdef': + condition = f'defined({condition})' + elif kind == 'ifndef': + condition = f'! defined({condition})' + + return condition + + def __new__(cls, kind, condition): + kind = _coerce_str(kind) + self = super().__new__( + cls, + kind=kind or None, + condition=cls._condition_from_raw(condition, kind), + ) + return self + + @property + def text(self): + if self.kind == 'ifdef': + return self.condition[8:-1] # strip "defined(" + elif self.kind == 'ifndef': + return self.condition[10:-1] # strip "! defined(" + else: + return self.condition + #return str(self.condition) + + def validate(self): + """Fail if the object is invalid (i.e. init with bad data).""" + super().validate() + + if not self.condition: + raise TypeError('missing condition') + #else: + # for cond in self.condition: + # if not cond: + # raise ValueError(f'missing condition in {self.condition}') + # cond.validate() + # if self.kind in ('ifdef', 'ifndef'): + # if len(self.condition) != 1: + # raise ValueError('too many condition') + # if self.kind == 'ifdef': + # if not self.condition[0].startswith('defined '): + # raise ValueError('bad condition') + # else: + # if not self.condition[0].startswith('! defined '): + # raise ValueError('bad condition') + + +class Include(PreprocessorDirective, + namedtuple('Include', 'kind file')): + """A single "include" directive. + + Supported "file" values are either follow the bracket style + () or double quotes ("spam.h"). + """ + + __slots__ = () + + def __new__(cls, file): + self = super().__new__( + cls, + kind='include', + file=_coerce_str(file) or None, + ) + return self + + def validate(self): + """Fail if the object is invalid (i.e. init with bad data).""" + super().validate() + + if not self.file: + raise TypeError('missing file') + + +class OtherDirective(PreprocessorDirective, + namedtuple('OtherDirective', 'kind text')): + """A single directive not covered by another class. + + This includes the "else", "endif", and "undef" directives, which are + otherwise inherently related to the directives covered by the + Constant, Macro, and IfCondition classes. + + Note that all directives must have a text value, except for "else" + and "endif" (which must have no text). + """ + + __slots__ = () + + KINDS = PreprocessorDirective.KINDS - {'include', 'define'} - IfDirective.KINDS + + def __new__(cls, kind, text): + self = super().__new__( + cls, + kind=_coerce_str(kind) or None, + text=_coerce_str(text) or None, + ) + return self + + def validate(self): + """Fail if the object is invalid (i.e. init with bad data).""" + super().validate() + + if self.text: + if self.kind in ('else', 'endif'): + raise ValueError('unexpected text in directive') + elif self.kind not in ('else', 'endif'): + raise TypeError('missing text') + + ############################# # GCC preprocessor (platform-specific) From 400b3883c6615a2e7150eda8aaebaee70f54b3ea Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 26 Jul 2019 18:35:49 -0600 Subject: [PATCH 041/118] Remove line continuations and comments in preprocessor.iter_lines(). --- .../test_c_parser/test_preprocessor.py | 382 ++++++++++-------- Tools/c-analyzer/c_parser/preprocessor.py | 241 ++++++----- 2 files changed, 360 insertions(+), 263 deletions(-) diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_preprocessor.py b/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_preprocessor.py index 7a1d636f7b7ff6..20103cc529a630 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_preprocessor.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_preprocessor.py @@ -100,13 +100,18 @@ def test_no_directives(self): return 0; } - ''').splitlines() + ''')[1:-1].splitlines() + expected = [(lno, line, None, ()) + for lno, line in enumerate(lines, 1)] + expected[1] = (2, ' ', None, ()) + expected[20] = (21, ' ', None, ()) + del expected[19] + del expected[18] results = list( iter_lines(lines, _parse_directive=self._parse_directive)) - self.assertEqual(results, - [(line, None, ()) for line in lines]) + self.assertEqual(results, expected) self.check_calls() def test_single_directives(self): @@ -146,13 +151,13 @@ def test_single_directives(self): iter_lines(lines, _parse_directive=self._parse_directive)) self.assertEqual(results, [ - ('static int spam = 0;', None, ()), - (line, directive, ()), - (('static char buffer[256];', None, ('defined(SPAM)',)) + (1, 'static int spam = 0;', None, ()), + (2, line, directive, ()), + ((3, 'static char buffer[256];', None, ('defined(SPAM)',)) if directive.kind in ('if', 'ifdef', 'elseif') - else ('static char buffer[256];', None, ('! defined(SPAM)',)) + else (3, 'static char buffer[256];', None, ('! defined(SPAM)',)) if directive.kind == 'ifndef' - else ('static char buffer[256];', None, ())), + else (3, 'static char buffer[256];', None, ())), ]) self.check_calls( ('_parse_directive', line), @@ -170,7 +175,7 @@ def test_directive_whitespace(self): iter_lines(lines, _parse_directive=self._parse_directive)) self.assertEqual(results, [ - (line, directive, ()), + (1, line, directive, ()), ]) self.check_calls( ('_parse_directive', '#define eggs ( a , b ) { a = b ; }'), @@ -181,25 +186,24 @@ def test_split_lines(self): self.parsed = [ directive, ] - lines = textwrap.dedent(r''' + text = textwrap.dedent(r''' static int spam = 0; #define eggs(a, b) \ { \ a = b; \ } static char buffer[256]; - ''').strip().splitlines() + ''').strip() + lines = [line + '\n' for line in text.splitlines()] + lines[-1] = lines[-1][:-1] results = list( iter_lines(lines, _parse_directive=self._parse_directive)) self.assertEqual(results, [ - ('static int spam = 0;', None, ()), - ('#define eggs(a, b) \\', True, ()), - (' { \\', True, ()), - (' a = b; \\', True, ()), - (' }', directive, ()), - ('static char buffer[256];', None, ()), + (1, 'static int spam = 0;\n', None, ()), + (5, '#define eggs(a, b) { a = b; }\n', directive, ()), + (6, 'static char buffer[256];', None, ()), ]) self.check_calls( ('_parse_directive', '#define eggs(a, b) { a = b; }'), @@ -238,19 +242,19 @@ def test_nested_conditions(self): iter_lines(lines, _parse_directive=self._parse_directive)) self.assertEqual(results, [ - ('static int spam = 0;', None, ()), - ('#ifdef SPAM', directives[0], ()), - ('static int start = 0;', None, ('defined(SPAM)',)), - ('# if SPAM == 1', directives[1], ('defined(SPAM)',)), - ('static char buffer[10];', None, ('defined(SPAM)', 'SPAM == 1')), - ('# elif SPAM == 2', directives[2], ('defined(SPAM)', 'SPAM == 1')), - ('static char buffer[100];', None, ('defined(SPAM)', '! (SPAM == 1)', 'SPAM == 2')), - ('# else', directives[3], ('defined(SPAM)', '! (SPAM == 1)', 'SPAM == 2')), - ('static char buffer[256];', None, ('defined(SPAM)', '! (SPAM == 1)', '! (SPAM == 2)')), - ('# endif', directives[4], ('defined(SPAM)', '! (SPAM == 1)', '! (SPAM == 2)')), - ('static int end = 0;', None, ('defined(SPAM)',)), - ('#endif', directives[5], ('defined(SPAM)',)), - ('static int eggs = 0;', None, ()), + (1, 'static int spam = 0;', None, ()), + (2, '#ifdef SPAM', directives[0], ()), + (3, 'static int start = 0;', None, ('defined(SPAM)',)), + (4, '# if SPAM == 1', directives[1], ('defined(SPAM)',)), + (5, 'static char buffer[10];', None, ('defined(SPAM)', 'SPAM == 1')), + (6, '# elif SPAM == 2', directives[2], ('defined(SPAM)', 'SPAM == 1')), + (7, 'static char buffer[100];', None, ('defined(SPAM)', '! (SPAM == 1)', 'SPAM == 2')), + (8, '# else', directives[3], ('defined(SPAM)', '! (SPAM == 1)', 'SPAM == 2')), + (9, 'static char buffer[256];', None, ('defined(SPAM)', '! (SPAM == 1)', '! (SPAM == 2)')), + (10, '# endif', directives[4], ('defined(SPAM)', '! (SPAM == 1)', '! (SPAM == 2)')), + (11, 'static int end = 0;', None, ('defined(SPAM)',)), + (12, '#endif', directives[5], ('defined(SPAM)',)), + (13, 'static int eggs = 0;', None, ()), ]) self.check_calls( ('_parse_directive', '#ifdef SPAM'), @@ -303,33 +307,33 @@ def test_split_blocks(self): iter_lines(lines, _parse_directive=self._parse_directive)) self.assertEqual(results, [ - ('void str_copy(char *buffer, *orig);', None, ()), - ('int init(char *name) {', None, ()), - (' static int initialized = 0;', None, ()), - (' if (initialized) {', None, ()), - (' return 0;', None, ()), - (' }', None, ()), - - ('#ifdef SPAM', directives[0], ()), - - (' static char buffer[10];', None, ('defined(SPAM)',)), - (' str_copy(buffer, char);', None, ('defined(SPAM)',)), - ('}', None, ('defined(SPAM)',)), - ('void copy(char *buffer, *orig) {', None, ('defined(SPAM)',)), - (' strncpy(buffer, orig, 9);', None, ('defined(SPAM)',)), - (' buffer[9] = 0;', None, ('defined(SPAM)',)), - ('}', None, ('defined(SPAM)',)), - - ('#else', directives[1], ('defined(SPAM)',)), - - (' static char buffer[256];', None, ('! (defined(SPAM))',)), - (' str_copy(buffer, char);', None, ('! (defined(SPAM))',)), - ('}', None, ('! (defined(SPAM))',)), - ('void copy(char *buffer, *orig) {', None, ('! (defined(SPAM))',)), - (' strcpy(buffer, orig);', None, ('! (defined(SPAM))',)), - ('}', None, ('! (defined(SPAM))',)), - - ('#endif', directives[2], ('! (defined(SPAM))',)), + (1, 'void str_copy(char *buffer, *orig);', None, ()), + (2, 'int init(char *name) {', None, ()), + (3, ' static int initialized = 0;', None, ()), + (4, ' if (initialized) {', None, ()), + (5, ' return 0;', None, ()), + (6, ' }', None, ()), + + (7, '#ifdef SPAM', directives[0], ()), + + (8, ' static char buffer[10];', None, ('defined(SPAM)',)), + (9, ' str_copy(buffer, char);', None, ('defined(SPAM)',)), + (10, '}', None, ('defined(SPAM)',)), + (11, 'void copy(char *buffer, *orig) {', None, ('defined(SPAM)',)), + (12, ' strncpy(buffer, orig, 9);', None, ('defined(SPAM)',)), + (13, ' buffer[9] = 0;', None, ('defined(SPAM)',)), + (14, '}', None, ('defined(SPAM)',)), + + (15, '#else', directives[1], ('defined(SPAM)',)), + + (16, ' static char buffer[256];', None, ('! (defined(SPAM))',)), + (17, ' str_copy(buffer, char);', None, ('! (defined(SPAM))',)), + (18, '}', None, ('! (defined(SPAM))',)), + (19, 'void copy(char *buffer, *orig) {', None, ('! (defined(SPAM))',)), + (20, ' strcpy(buffer, orig);', None, ('! (defined(SPAM))',)), + (21, '}', None, ('! (defined(SPAM))',)), + + (22, '#endif', directives[2], ('! (defined(SPAM))',)), ]) self.check_calls( ('_parse_directive', '#ifdef SPAM'), @@ -380,75 +384,75 @@ def test_basic(self): #endif print("end"); ''')[1:-1] - lines = text.splitlines() + lines = [line + '\n' for line in text.splitlines()] + lines[-1] = lines[-1][:-1] results = list( iter_lines(lines, _parse_directive=self._parse_directive)) self.assertEqual(results, [ - ('#include ', Include(''), ()), - ('print("begin");', None, ()), + (1, '#include \n', Include(''), ()), + (2, 'print("begin");\n', None, ()), # - ('#ifdef SPAM', + (3, '#ifdef SPAM\n', IfDirective('ifdef', 'SPAM'), ()), - (' print("spam");', + (4, ' print("spam");\n', None, ('defined(SPAM)',)), - (' #if ! defined(HAM) || !HAM', + (5, ' #if ! defined(HAM) || !HAM\n', IfDirective('if', '! defined(HAM) || !HAM'), ('defined(SPAM)',)), - ('# DEFINE HAM 0', + (6, '# DEFINE HAM 0\n', Constant('HAM', '0'), ('defined(SPAM)', '! defined(HAM) || !HAM')), - (' #elseif HAM < 0', + (7, ' #elseif HAM < 0\n', IfDirective('elseif', 'HAM < 0'), ('defined(SPAM)', '! defined(HAM) || !HAM')), - ('# DEFINE HAM -1', + (8, '# DEFINE HAM -1\n', Constant('HAM', '-1'), ('defined(SPAM)', '! (! defined(HAM) || !HAM)', 'HAM < 0')), - (' #else', + (9, ' #else\n', OtherDirective('else', None), ('defined(SPAM)', '! (! defined(HAM) || !HAM)', 'HAM < 0')), - (' print("ham HAM");', + (10, ' print("ham HAM");\n', None, ('defined(SPAM)', '! (! defined(HAM) || !HAM)', '! (HAM < 0)')), - (' #endif', + (11, ' #endif\n', OtherDirective('endif', None), ('defined(SPAM)', '! (! defined(HAM) || !HAM)', '! (HAM < 0)')), - ('#endif', + (12, '#endif\n', OtherDirective('endif', None), ('defined(SPAM)',)), # - ('', None, ()), + (13, '\n', None, ()), # - ('#if defined(HAM) && \\', True, ()), - (' (HAM < 0 || ! HAM)', + (15, '#if defined(HAM) && (HAM < 0 || ! HAM)\n', IfDirective('if', 'defined(HAM) && (HAM < 0 || ! HAM)'), ()), - (' print("ham?");', + (16, ' print("ham?");\n', None, ('defined(HAM) && (HAM < 0 || ! HAM)',)), - (' #undef HAM', + (17, ' #undef HAM\n', OtherDirective('undef', 'HAM'), ('defined(HAM) && (HAM < 0 || ! HAM)',)), - ('# endif', + (18, '# endif\n', OtherDirective('endif', None), ('defined(HAM) && (HAM < 0 || ! HAM)',)), # - ('', None, ()), + (19, '\n', None, ()), # - ('#ifndef HAM', + (20, '#ifndef HAM\n', IfDirective('ifndef', 'HAM'), ()), - (' print("no ham");', + (21, ' print("no ham");\n', None, ('! defined(HAM)',)), - ('#endif', + (22, '#endif\n', OtherDirective('endif', None), ('! defined(HAM)',)), # - ('print("end");', None, ()), + (23, 'print("end");', None, ()), ]) def test_typical(self): @@ -604,253 +608,293 @@ def test_typical(self): #endif /* !Py_COMPILE_H */ ''').strip() - lines = [line for line in text.splitlines() if line.strip()] + lines = [line + '\n' for line in text.splitlines()] + lines[-1] = lines[-1][:-1] results = list( iter_lines(lines, _parse_directive=self._parse_directive)) self.assertEqual(results, [ - ('#ifndef Py_COMPILE_H', + (1, '#ifndef Py_COMPILE_H\n', IfDirective('ifndef', 'Py_COMPILE_H'), ()), - ('#define Py_COMPILE_H', + (2, '#define Py_COMPILE_H\n', Constant('Py_COMPILE_H', None), ('! defined(Py_COMPILE_H)',)), - ('#ifndef Py_LIMITED_API', + (3, '\n', + None, + ('! defined(Py_COMPILE_H)',)), + (4, '#ifndef Py_LIMITED_API\n', IfDirective('ifndef', 'Py_LIMITED_API'), ('! defined(Py_COMPILE_H)',)), - ('#include "code.h"', + (5, '#include "code.h"\n', Include('"code.h"'), ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('#ifdef __cplusplus', + (6, '\n', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + (7, '#ifdef __cplusplus\n', IfDirective('ifdef', '__cplusplus'), ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('extern "C" {', + (8, 'extern "C" {\n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)', 'defined(__cplusplus)')), - ('#endif', + (9, '#endif\n', OtherDirective('endif', None), ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)', 'defined(__cplusplus)')), - ('/* Public interface */', + (10, '\n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('struct _node; /* Declare the existence of this type */', + (11, ' \n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('PyAPI_FUNC(PyCodeObject *) PyNode_Compile(struct _node *, const char *);', + (12, 'struct _node; \n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('/* XXX (ncoghlan): Unprefixed type name in a public API! */', + (13, 'PyAPI_FUNC(PyCodeObject *) PyNode_Compile(struct _node *, const char *);\n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('#define PyCF_MASK (CO_FUTURE_DIVISION | CO_FUTURE_ABSOLUTE_IMPORT | \\', - True, - ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - (' CO_FUTURE_WITH_STATEMENT | CO_FUTURE_PRINT_FUNCTION | \\', - True, + (14, ' \n', + None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - (' CO_FUTURE_UNICODE_LITERALS | CO_FUTURE_BARRY_AS_BDFL | \\', - True, + (15, '\n', + None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - (' CO_FUTURE_GENERATOR_STOP | CO_FUTURE_ANNOTATIONS)', + (19, '#define PyCF_MASK (CO_FUTURE_DIVISION | CO_FUTURE_ABSOLUTE_IMPORT | CO_FUTURE_WITH_STATEMENT | CO_FUTURE_PRINT_FUNCTION | CO_FUTURE_UNICODE_LITERALS | CO_FUTURE_BARRY_AS_BDFL | CO_FUTURE_GENERATOR_STOP | CO_FUTURE_ANNOTATIONS)\n', Constant('PyCF_MASK', '(CO_FUTURE_DIVISION | CO_FUTURE_ABSOLUTE_IMPORT | CO_FUTURE_WITH_STATEMENT | CO_FUTURE_PRINT_FUNCTION | CO_FUTURE_UNICODE_LITERALS | CO_FUTURE_BARRY_AS_BDFL | CO_FUTURE_GENERATOR_STOP | CO_FUTURE_ANNOTATIONS)'), ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('#define PyCF_MASK_OBSOLETE (CO_NESTED)', + (20, '#define PyCF_MASK_OBSOLETE (CO_NESTED)\n', Constant('PyCF_MASK_OBSOLETE', '(CO_NESTED)'), ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('#define PyCF_SOURCE_IS_UTF8 0x0100', + (21, '#define PyCF_SOURCE_IS_UTF8 0x0100\n', Constant('PyCF_SOURCE_IS_UTF8', ' 0x0100'), ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('#define PyCF_DONT_IMPLY_DEDENT 0x0200', + (22, '#define PyCF_DONT_IMPLY_DEDENT 0x0200\n', Constant('PyCF_DONT_IMPLY_DEDENT', '0x0200'), ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('#define PyCF_ONLY_AST 0x0400', + (23, '#define PyCF_ONLY_AST 0x0400\n', Constant('PyCF_ONLY_AST', '0x0400'), ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('#define PyCF_IGNORE_COOKIE 0x0800', + (24, '#define PyCF_IGNORE_COOKIE 0x0800\n', Constant('PyCF_IGNORE_COOKIE', '0x0800'), ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('#define PyCF_TYPE_COMMENTS 0x1000', + (25, '#define PyCF_TYPE_COMMENTS 0x1000\n', Constant('PyCF_TYPE_COMMENTS', '0x1000'), ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('#define PyCF_ALLOW_TOP_LEVEL_AWAIT 0x2000', + (26, '#define PyCF_ALLOW_TOP_LEVEL_AWAIT 0x2000\n', Constant('PyCF_ALLOW_TOP_LEVEL_AWAIT', '0x2000'), ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('#ifndef Py_LIMITED_API', + (27, '\n', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + (28, '#ifndef Py_LIMITED_API\n', IfDirective('ifndef', 'Py_LIMITED_API'), ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('typedef struct {', + (29, 'typedef struct {\n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)', '! defined(Py_LIMITED_API)')), - (' int cf_flags; /* bitmask of CO_xxx flags relevant to future */', + (30, ' int cf_flags; \n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)', '! defined(Py_LIMITED_API)')), - (' int cf_feature_version; /* minor Python version (PyCF_ONLY_AST) */', + (31, ' int cf_feature_version; \n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)', '! defined(Py_LIMITED_API)')), - ('} PyCompilerFlags;', + (32, '} PyCompilerFlags;\n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)', '! defined(Py_LIMITED_API)')), - ('#endif', + (33, '#endif\n', OtherDirective('endif', None), ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)', '! defined(Py_LIMITED_API)')), - ('/* Future feature support */', + (34, '\n', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + (35, ' \n', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + (36, '\n', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + (37, 'typedef struct {\n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('typedef struct {', + (38, ' int ff_features; \n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - (' int ff_features; /* flags set by future statements */', + (39, ' int ff_lineno; \n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - (' int ff_lineno; /* line number of last future statement */', + (40, '} PyFutureFeatures;\n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('} PyFutureFeatures;', + (41, '\n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('#define FUTURE_NESTED_SCOPES "nested_scopes"', + (42, '#define FUTURE_NESTED_SCOPES "nested_scopes"\n', Constant('FUTURE_NESTED_SCOPES', '"nested_scopes"'), ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('#define FUTURE_GENERATORS "generators"', + (43, '#define FUTURE_GENERATORS "generators"\n', Constant('FUTURE_GENERATORS', '"generators"'), ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('#define FUTURE_DIVISION "division"', + (44, '#define FUTURE_DIVISION "division"\n', Constant('FUTURE_DIVISION', '"division"'), ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('#define FUTURE_ABSOLUTE_IMPORT "absolute_import"', + (45, '#define FUTURE_ABSOLUTE_IMPORT "absolute_import"\n', Constant('FUTURE_ABSOLUTE_IMPORT', '"absolute_import"'), ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('#define FUTURE_WITH_STATEMENT "with_statement"', + (46, '#define FUTURE_WITH_STATEMENT "with_statement"\n', Constant('FUTURE_WITH_STATEMENT', '"with_statement"'), ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('#define FUTURE_PRINT_FUNCTION "print_function"', + (47, '#define FUTURE_PRINT_FUNCTION "print_function"\n', Constant('FUTURE_PRINT_FUNCTION', '"print_function"'), ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('#define FUTURE_UNICODE_LITERALS "unicode_literals"', + (48, '#define FUTURE_UNICODE_LITERALS "unicode_literals"\n', Constant('FUTURE_UNICODE_LITERALS', '"unicode_literals"'), ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('#define FUTURE_BARRY_AS_BDFL "barry_as_FLUFL"', + (49, '#define FUTURE_BARRY_AS_BDFL "barry_as_FLUFL"\n', Constant('FUTURE_BARRY_AS_BDFL', '"barry_as_FLUFL"'), ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('#define FUTURE_GENERATOR_STOP "generator_stop"', + (50, '#define FUTURE_GENERATOR_STOP "generator_stop"\n', Constant('FUTURE_GENERATOR_STOP', '"generator_stop"'), ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('#define FUTURE_ANNOTATIONS "annotations"', + (51, '#define FUTURE_ANNOTATIONS "annotations"\n', Constant('FUTURE_ANNOTATIONS', '"annotations"'), ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('struct _mod; /* Declare the existence of this type */', + (52, '\n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('#define PyAST_Compile(mod, s, f, ar) PyAST_CompileEx(mod, s, f, -1, ar)', + (53, 'struct _mod; \n', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + (54, '#define PyAST_Compile(mod, s, f, ar) PyAST_CompileEx(mod, s, f, -1, ar)\n', Macro('PyAST_Compile', ('mod', 's', 'f', 'ar'), 'PyAST_CompileEx(mod, s, f, -1, ar)'), ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('PyAPI_FUNC(PyCodeObject *) PyAST_CompileEx(', + (55, 'PyAPI_FUNC(PyCodeObject *) PyAST_CompileEx(\n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - (' struct _mod *mod,', + (56, ' struct _mod *mod,\n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - (' const char *filename, /* decoded from the filesystem encoding */', + (57, ' const char *filename, \n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - (' PyCompilerFlags *flags,', + (58, ' PyCompilerFlags *flags,\n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - (' int optimize,', + (59, ' int optimize,\n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - (' PyArena *arena);', + (60, ' PyArena *arena);\n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('PyAPI_FUNC(PyCodeObject *) PyAST_CompileObject(', + (61, 'PyAPI_FUNC(PyCodeObject *) PyAST_CompileObject(\n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - (' struct _mod *mod,', + (62, ' struct _mod *mod,\n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - (' PyObject *filename,', + (63, ' PyObject *filename,\n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - (' PyCompilerFlags *flags,', + (64, ' PyCompilerFlags *flags,\n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - (' int optimize,', + (65, ' int optimize,\n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - (' PyArena *arena);', + (66, ' PyArena *arena);\n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('PyAPI_FUNC(PyFutureFeatures *) PyFuture_FromAST(', + (67, 'PyAPI_FUNC(PyFutureFeatures *) PyFuture_FromAST(\n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - (' struct _mod * mod,', + (68, ' struct _mod * mod,\n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - (' const char *filename /* decoded from the filesystem encoding */', + (69, ' const char *filename \n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - (' );', + (70, ' );\n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('PyAPI_FUNC(PyFutureFeatures *) PyFuture_FromASTObject(', + (71, 'PyAPI_FUNC(PyFutureFeatures *) PyFuture_FromASTObject(\n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - (' struct _mod * mod,', + (72, ' struct _mod * mod,\n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - (' PyObject *filename', + (73, ' PyObject *filename\n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - (' );', + (74, ' );\n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('/* _Py_Mangle is defined in compile.c */', + (75, '\n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('PyAPI_FUNC(PyObject*) _Py_Mangle(PyObject *p, PyObject *name);', + (76, ' \n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('#define PY_INVALID_STACK_EFFECT INT_MAX', + (77, 'PyAPI_FUNC(PyObject*) _Py_Mangle(PyObject *p, PyObject *name);\n', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + (78, '\n', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + (79, '#define PY_INVALID_STACK_EFFECT INT_MAX\n', Constant('PY_INVALID_STACK_EFFECT', 'INT_MAX'), ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('PyAPI_FUNC(int) PyCompile_OpcodeStackEffect(int opcode, int oparg);', + (80, 'PyAPI_FUNC(int) PyCompile_OpcodeStackEffect(int opcode, int oparg);\n', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + (81, 'PyAPI_FUNC(int) PyCompile_OpcodeStackEffectWithJump(int opcode, int oparg, int jump);\n', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + (82, '\n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('PyAPI_FUNC(int) PyCompile_OpcodeStackEffectWithJump(int opcode, int oparg, int jump);', + (83, 'PyAPI_FUNC(int) _PyAST_Optimize(struct _mod *, PyArena *arena, int optimize);\n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('PyAPI_FUNC(int) _PyAST_Optimize(struct _mod *, PyArena *arena, int optimize);', + (84, '\n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('#ifdef __cplusplus', + (85, '#ifdef __cplusplus\n', IfDirective('ifdef', '__cplusplus'), ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('}', + (86, '}\n', None, ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)', 'defined(__cplusplus)')), - ('#endif', + (87, '#endif\n', OtherDirective('endif', None), ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)', 'defined(__cplusplus)')), - ('#endif /* !Py_LIMITED_API */', + (88, '\n', + None, + ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), + (89, '#endif \n', OtherDirective('endif', None), ('! defined(Py_COMPILE_H)', '! defined(Py_LIMITED_API)')), - ('/* These definitions must match corresponding definitions in graminit.h. */', + (90, '\n', + None, + ('! defined(Py_COMPILE_H)',)), + (91, ' \n', None, ('! defined(Py_COMPILE_H)',)), - ('#define Py_single_input 256', + (92, '#define Py_single_input 256\n', Constant('Py_single_input', '256'), ('! defined(Py_COMPILE_H)',)), - ('#define Py_file_input 257', + (93, '#define Py_file_input 257\n', Constant('Py_file_input', '257'), ('! defined(Py_COMPILE_H)',)), - ('#define Py_eval_input 258', + (94, '#define Py_eval_input 258\n', Constant('Py_eval_input', '258'), ('! defined(Py_COMPILE_H)',)), - ('#define Py_func_type_input 345', + (95, '#define Py_func_type_input 345\n', Constant('Py_func_type_input', '345'), ('! defined(Py_COMPILE_H)',)), - ('#endif /* !Py_COMPILE_H */', + (96, '\n', + None, + ('! defined(Py_COMPILE_H)',)), + (97, '#endif ', OtherDirective('endif', None), ('! defined(Py_COMPILE_H)',)), ]) @@ -885,12 +929,12 @@ def test_typical(self): ('_parse_directive', '#define PY_INVALID_STACK_EFFECT INT_MAX'), ('_parse_directive', '#ifdef __cplusplus'), ('_parse_directive', '#endif'), - ('_parse_directive', '#endif /* !Py_LIMITED_API */'), + ('_parse_directive', '#endif'), ('_parse_directive', '#define Py_single_input 256'), ('_parse_directive', '#define Py_file_input 257'), ('_parse_directive', '#define Py_eval_input 258'), ('_parse_directive', '#define Py_func_type_input 345'), - ('_parse_directive', '#endif /* !Py_COMPILE_H */'), + ('_parse_directive', '#endif'), ) diff --git a/Tools/c-analyzer/c_parser/preprocessor.py b/Tools/c-analyzer/c_parser/preprocessor.py index 3ebfedd0bea7ff..905569d1da8ccc 100644 --- a/Tools/c-analyzer/c_parser/preprocessor.py +++ b/Tools/c-analyzer/c_parser/preprocessor.py @@ -1,9 +1,12 @@ from collections import namedtuple +import os import re from . import util, info +CONTINUATION = '\\' + os.linesep + IDENTIFIER = r'(?:\w*[a-zA-Z]\w*)' IDENTIFIER_RE = re.compile('^' + IDENTIFIER + '$') @@ -14,99 +17,6 @@ def _coerce_str(value): return str(value).strip() -def iter_lines(lines, *, - _parse_directive=(lambda l: parse_directive(l)), - ): - """Yield (line, directive, active conditions) for each given line. - - "lines" is expected to be comment-free. Each line is returned - as-is. - - "active conditions" is the set of preprocessor conditions (e.g. - "defined()") under which the current line of code will be included - in compilation. That set is derived from every conditional - directive block (e.g. "if defined()", "ifdef", "else") containing - that line. That includes nested directives. Note that the - current line does not affect the active conditions for iteself. - It only impacts subsequent lines. That applies to directives - that close blocks (e.g. "endif") just as much as conditional - directvies. Also note that "else" and "elseif" directives - update the active conditions (for later lines), rather than - adding to them. - - If a directive has line continuations then each line is returned - with a "directive" of True, except for the last line, which has - the directive object like normal. - """ - ifdefs = [] - def _recompute_conditions(directive): - if directive.kind in ('if', 'ifdef', 'ifndef'): - ifdefs.append( - ([], directive.condition)) - elif directive.kind == 'elseif': - if ifdefs: - negated, active = ifdefs.pop() - if active: - negated.append(active) - else: - negated = [] - ifdefs.append( - (negated, directive.condition)) - elif directive.kind == 'else': - if ifdefs: - negated, active = ifdefs.pop() - if active: - negated.append(active) - ifdefs.append( - (negated, None)) - elif directive.kind == 'endif': - if ifdefs: - ifdefs.pop() - - conditions = [] - for negated, active in ifdefs: - for condition in negated: - conditions.append(f'! ({condition})') - if active: - conditions.append(active) - return tuple(conditions) - - incomment = False - conditions = () - directive = None - for line in lines: - if directive: - directive += ' ' + line.strip() - else: - stripped = line.strip() - if not stripped.startswith('#'): - yield line, None, conditions - continue - directive = '#' + stripped[1:].lstrip() - - if directive.endswith('\\'): - directive = directive[:-1] - yield line, True, conditions - else: - while ' ' in directive: - directive = directive.replace(' ', ' ') - directive = _parse_directive(directive) - yield line, directive, conditions - last = None - if directive.kind in ('else', 'endif'): - conditions = _recompute_conditions(directive) - elif isinstance(directive, IfDirective): - conditions = _recompute_conditions(directive) - directive = None - - -def run(filename, *, - _gcc=(lambda f: _gcc(f)), - ): - """Return the text of the given file after running the preprocessor.""" - return _gcc(filename) - - ############################# # directives @@ -156,6 +66,18 @@ def run(filename, *, def parse_directive(line): """Return the appropriate directive for the given line.""" + line = line.strip() + if line.startswith('#'): + line = line[1:].lstrip() + line = '#' + line + directive = line + #directive = '#' + line + while ' ' in directive: + directive = directive.replace(' ', ' ') + return _parse_directive(directive) + + +def _parse_directive(line): m = DEFINE_RE.match(line) if m: name, args, text = m.groups() @@ -422,7 +344,131 @@ def validate(self): ############################# -# GCC preprocessor (platform-specific) +# iterating lines + +def _recompute_conditions(directive, ifstack): + if directive.kind in ('if', 'ifdef', 'ifndef'): + ifstack.append( + ([], directive.condition)) + elif directive.kind == 'elseif': + if ifstack: + negated, active = ifstack.pop() + if active: + negated.append(active) + else: + negated = [] + ifstack.append( + (negated, directive.condition)) + elif directive.kind == 'else': + if ifstack: + negated, active = ifstack.pop() + if active: + negated.append(active) + ifstack.append( + (negated, None)) + elif directive.kind == 'endif': + if ifstack: + ifstack.pop() + + conditions = [] + for negated, active in ifstack: + for condition in negated: + conditions.append(f'! ({condition})') + if active: + conditions.append(active) + return tuple(conditions) + + +def _iter_clean_lines(lines): + lines = iter(enumerate(lines, 1)) + for lno, line in lines: + # Handle line continuations. + while line.endswith(CONTINUATION): + try: + lno, _line = next(lines) + except StopIteration: + break + line = line[:-len(CONTINUATION)] + ' ' + _line + + # Deal with comments. + after = line + line = '' + while True: + # Look for a comment. + before, begin, remainder = after.partition('/*') + if '//' in before: + before, _, _ = before.partition('//') + line += before + ' ' # per the C99 spec + break + line += before + if not begin: + break + line += ' ' # per the C99 spec + + # Go until we find the end of the comment. + _, end, after = remainder.partition('*/') + while not end: + try: + lno, remainder = next(lines) + except StopIteration: + raise Exception('unterminated comment') + _, end, after = remainder.partition('*/') + + yield lno, line + + +def iter_lines(lines, *, + _iter_clean_lines=_iter_clean_lines, + _parse_directive=_parse_directive, + _recompute_conditions=_recompute_conditions, + ): + """Yield (lno, line, directive, active conditions) for each given line. + + This is effectively a subset of the operations taking place in + translation phases 2-4 from the C99 spec (ISO/IEC 9899:TC2); see + section 5.1.1.2. Line continuations are removed and comments + replaced with a single space. (In both cases "lno" will be the last + line involved.) Otherwise each line is returned as-is. + + "lno" is the (1-indexed) line number for the line. + + "directive" will be a PreprocessorDirective or None, depending on + whether or not there is a directive on the line. + + "active conditions" is the set of preprocessor conditions (e.g. + "defined()") under which the current line of code will be included + in compilation. That set is derived from every conditional + directive block (e.g. "if defined()", "ifdef", "else") containing + that line. That includes nested directives. Note that the + current line does not affect the active conditions for iteself. + It only impacts subsequent lines. That applies to directives + that close blocks (e.g. "endif") just as much as conditional + directvies. Also note that "else" and "elseif" directives + update the active conditions (for later lines), rather than + adding to them. + """ + ifstack = [] + conditions = () + for lno, line in _iter_clean_lines(lines): + stripped = line.strip() + if not stripped.startswith('#'): + yield lno, line, None, conditions + continue + + directive = '#' + stripped[1:].lstrip() + while ' ' in directive: + directive = directive.replace(' ', ' ') + directive = _parse_directive(directive) + yield lno, line, directive, conditions + + if directive.kind in ('else', 'endif'): + conditions = _recompute_conditions(directive, ifstack) + elif isinstance(directive, IfDirective): + conditions = _recompute_conditions(directive, ifstack) + + +############################# +# running (platform-specific?) def _gcc(filename, *, _get_argv=(lambda: _get_gcc_argv()), @@ -455,3 +501,10 @@ def _get_gcc_argv(*, argv = shlex.split(gcc.strip()) cflags = shlex.split(cflags.strip()) return argv + cflags + + +def run(filename, *, + _gcc=_gcc, + ): + """Return the text of the given file after running the preprocessor.""" + return _gcc(filename) From 13eb7b1e7f5f853ddec3a2f482e114b3db397206 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 2 Aug 2019 12:41:35 -0600 Subject: [PATCH 042/118] Fix minor formatting. --- Tools/c-analyzer/c_statics/__main__.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Tools/c-analyzer/c_statics/__main__.py b/Tools/c-analyzer/c_statics/__main__.py index e75409c8910888..86dc31469f1a63 100644 --- a/Tools/c-analyzer/c_statics/__main__.py +++ b/Tools/c-analyzer/c_statics/__main__.py @@ -8,7 +8,8 @@ def cmd_check(cmd, dirs=SOURCE_DIRS, *, - ignored=IGNORED_FILE, known=KNOWN_FILE, + ignored=IGNORED_FILE, + known=KNOWN_FILE, _find=find.statics, _show=show.basic, _print=print, @@ -32,7 +33,8 @@ def cmd_check(cmd, dirs=SOURCE_DIRS, *, def cmd_show(cmd, dirs=SOURCE_DIRS, *, - ignored=IGNORED_FILE, known=KNOWN_FILE, + ignored=IGNORED_FILE, + known=KNOWN_FILE, _find=find.statics, _show=show.basic, _print=print, From 182e3f9d02b2a55509a41472d741947004278323 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 2 Aug 2019 14:09:18 -0600 Subject: [PATCH 043/118] Handle the "ignored" and "known" args to statics(). --- .../test_c_statics/test_find.py | 77 +++++++++++++------ Tools/c-analyzer/c_statics/find.py | 8 +- Tools/c-analyzer/c_statics/supported.py | 22 +++++- 3 files changed, 81 insertions(+), 26 deletions(-) diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py index cdf32cdc88902e..abd0c7543a1d73 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py @@ -8,8 +8,12 @@ class _Base(unittest.TestCase): -# _return_iter_statics = () -# _return_is_supported = () + maxDiff = None + + _return_iter_statics = None + _return_is_supported = None + _return_load_ignored = None + _return_load_known = None @property def calls(self): @@ -19,37 +23,60 @@ def calls(self): self._calls = [] return self._calls - def add_static(self, filename, funcname, name, vartype, *, supported=True): + def _add_static(self, static, funcs): + if not funcs: + funcs = ['iter_statics'] + elif 'is_supported' in funcs and 'iter_statics' not in funcs: + funcs.append('iter_statics') + + for func in funcs: + func = f'_return_{func}' + results = getattr(self, func) + if results is None: + results = [] + setattr(self, func, results) + results.append(static) + + def add_static(self, filename, funcname, name, vartype, *, + supported=True, + ignored=False, + known=False, + ): static = info.StaticVar(filename, funcname, name, vartype) - try: - statics = self._return_iter_statics - except AttributeError: - statics = self._return_iter_statics = [] - statics.append(static) - - try: - unsupported = self._return_is_supported - except AttributeError: - unsupported = self._return_is_supported = set() - if not supported: - unsupported.add(static) - + funcs = [] + if supported is not None: + funcs.append('iter_statics') + if supported: + funcs.append('is_supported') + if ignored: + funcs.append('load_ingored') + if known: + funcs.append('load_known') + self._add_static(static, funcs) return static, supported def _iter_statics(self, *args): self.calls.append(('_iter_statics', args)) - return iter(self._return_iter_statics) + return iter(self._return_iter_statics or ()) - def _is_supported(self, static): - self.calls.append(('_is_supported', (static,))) - return static not in self._return_is_supported + def _is_supported(self, static, ignored=None, known=None): + self.calls.append(('_is_supported', (static, ignored, known))) + return static in (self._return_is_supported or ()) + def _load_ignored(self, filename): + self.calls.append(('_load_ignored', (filename,))) + return iter(self._return_load_ignored or ()) -class StaticsTest(_Base): + def _load_known(self, filename): + self.calls.append(('_load_known', (filename,))) + return iter(self._return_load_known or ()) - maxDiff = None + +class StaticsTest(_Base): def test_typical(self): + self._return_load_ignored = () + self._return_load_known = () expected = [ self.add_static('src1/spam.c', None, 'var1', 'const char *'), self.add_static('src1/spam.c', 'ham', 'initialized', 'int'), @@ -69,12 +96,16 @@ def test_typical(self): 'known.tsv', _iter_statics=self._iter_statics, _is_supported=self._is_supported, + _load_ignored=self._load_ignored, + _load_known=self._load_known, ) self.assertEqual(found, expected) self.assertEqual(self.calls, [ + ('_load_ignored', ('ignored.tsv',)), + ('_load_known', ('known.tsv',)), ('_iter_statics', (dirs,)), - ] + [('_is_supported', (v,)) + ] + [('_is_supported', (v, set(), set())) for v, _ in expected]) def test_no_dirs(self): diff --git a/Tools/c-analyzer/c_statics/find.py b/Tools/c-analyzer/c_statics/find.py index 2ee1dedd8f30a8..81a14ef3bf08a6 100644 --- a/Tools/c-analyzer/c_statics/find.py +++ b/Tools/c-analyzer/c_statics/find.py @@ -1,8 +1,10 @@ from . import scan -from .supported import is_supported +from .supported import is_supported, ignored_from_file, known_from_file def statics(dirnames, ignored, known, *, + _load_ignored=ignored_from_file, + _load_known=known_from_file, _iter_statics=scan.iter_statics, _is_supported=is_supported, ): @@ -10,8 +12,10 @@ def statics(dirnames, ignored, known, *, if not dirnames: return [] + ignored = set(_load_ignored(ignored)) if ignored else () + known = set(_load_known(known)) if known else () found = [] for static in _iter_statics(dirnames): found.append( - (static, _is_supported(static))) + (static, _is_supported(static, ignored, known))) return found diff --git a/Tools/c-analyzer/c_statics/supported.py b/Tools/c-analyzer/c_statics/supported.py index a97147c0777132..c8aca97d1916ed 100644 --- a/Tools/c-analyzer/c_statics/supported.py +++ b/Tools/c-analyzer/c_statics/supported.py @@ -1,10 +1,30 @@ -def is_supported(static): +def is_supported(static, ignored=None, known=None): """Return True if the given static variable is okay in CPython.""" # XXX finish! raise NotImplementedError + if static in ignored: + return True + if static in known: + return True for part in static.vartype.split(): # XXX const is automatic True? if part == 'PyObject' or part.startswith('PyObject['): return False return True + + +############################# +# ignored + +def ignored_from_file(infile, fmt=None): + """Yield StaticVar for each ignored var in the file.""" + raise NotImplementedError + + +############################# +# known + +def known_from_file(infile, fmt=None): + """Yield StaticVar for each ignored var in the file.""" + raise NotImplementedError From ec88a4c9e5e3aa4f0d3715c67c4e33444c727236 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 2 Aug 2019 15:12:25 -0600 Subject: [PATCH 044/118] Factor out statics_from_symbols(). --- .../test_c_statics/test_find.py | 6 +- .../test_c_statics/test_scan.py | 64 +++++++++++++++---- Tools/c-analyzer/c_statics/find.py | 3 +- Tools/c-analyzer/c_statics/scan.py | 27 ++++++-- .../c-analyzer/c_symbols/{nm.py => binary.py} | 12 ++-- .../c_symbols/{local.py => source.py} | 7 ++ 6 files changed, 92 insertions(+), 27 deletions(-) rename Tools/c-analyzer/c_symbols/{nm.py => binary.py} (92%) rename Tools/c-analyzer/c_symbols/{local.py => source.py} (80%) diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py index abd0c7543a1d73..e0fcebf347095b 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py @@ -55,8 +55,8 @@ def add_static(self, filename, funcname, name, vartype, *, self._add_static(static, funcs) return static, supported - def _iter_statics(self, *args): - self.calls.append(('_iter_statics', args)) + def _iter_statics(self, dirnames, kind=None): + self.calls.append(('_iter_statics', (dirnames, kind))) return iter(self._return_iter_statics or ()) def _is_supported(self, static, ignored=None, known=None): @@ -104,7 +104,7 @@ def test_typical(self): self.assertEqual(self.calls, [ ('_load_ignored', ('ignored.tsv',)), ('_load_known', ('known.tsv',)), - ('_iter_statics', (dirs,)), + ('_iter_statics', (dirs, None)), ] + [('_is_supported', (v, set(), set())) for v, _ in expected]) diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_scan.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_scan.py index 2d8e30381568f4..bee8001c1a05e2 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_scan.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_scan.py @@ -3,12 +3,13 @@ from .. import tool_imports_for_tests with tool_imports_for_tests(): from c_parser import info - from c_statics.scan import iter_statics + from c_statics.scan import iter_statics, statics_from_symbols + from c_symbols import binary as b_symbols, source as s_symbols -class IterStaticsTests(unittest.TestCase): +class _Base(unittest.TestCase): - _return_iter_symbols = () + maxDiff = None @property def calls(self): @@ -18,9 +19,14 @@ def calls(self): self._calls = [] return self._calls - def _iter_symbols(self, dirnames): - self.calls.append(('_iter_symbols', (dirnames,))) - return iter(self. _return_iter_symbols) + +class StaticsFromSymbolsTests(_Base): + + _return_iter_symbols = () + + def iter_symbols(self, dirnames): + self.calls.append(('iter_symbols', (dirnames,))) + return iter(self._return_iter_symbols) def test_typical(self): self._return_iter_symbols = [ @@ -36,8 +42,7 @@ def test_typical(self): info.Symbol('???', 'other', False, None, None, None), ] - found = list(iter_statics(['dir1'], - _iter_symbols=self._iter_symbols)) + found = list(statics_from_symbols(['dir1'], self.iter_symbols)) self.assertEqual(found, [ info.StaticVar('dir1/spam.c', None, 'var1', '???'), @@ -47,16 +52,53 @@ def test_typical(self): info.StaticVar('dir1/eggs.c', None, 'var1', '???'), ]) self.assertEqual(self.calls, [ - ('_iter_symbols', (['dir1'],)), + ('iter_symbols', (['dir1'],)), ]) def test_no_symbols(self): self._return_iter_symbols = [] + found = list(statics_from_symbols(['dir1'], self.iter_symbols)) + + self.assertEqual(found, []) + self.assertEqual(self.calls, [ + ('iter_symbols', (['dir1'],)), + ]) + + +class IterStaticsTests(_Base): + + _return_from_symbols = () + + def _from_symbols(self, dirnames, iter_symbols): + self.calls.append(('_from_symbols', (dirnames, iter_symbols))) + return iter(self._return_from_symbols) + + def test_typical(self): + expected = [ + info.StaticVar('dir1/spam.c', None, 'var1', '???'), + info.StaticVar('dir1/spam.c', None, 'var2', '???'), + info.StaticVar('dir1/spam.c', None, 'var3', '???'), + info.StaticVar('dir1/spam.c', 'func2', 'var4', '???'), + info.StaticVar('dir1/eggs.c', None, 'var1', '???'), + ] + self._return_from_symbols = expected + + found = list(iter_statics(['dir1'], + _from_symbols=self._from_symbols)) + + self.assertEqual(found, expected) + self.assertEqual(self.calls, [ + ('_from_symbols', (['dir1'], b_symbols.iter_symbols)), + ]) + + def test_no_symbols(self): + self._return_from_symbols = [] + found = list(iter_statics(['dir1'], - _iter_symbols=self._iter_symbols)) + _from_symbols=self._from_symbols)) self.assertEqual(found, []) self.assertEqual(self.calls, [ - ('_iter_symbols', (['dir1'],)), + ('_from_symbols', (['dir1'], b_symbols.iter_symbols)), ]) diff --git a/Tools/c-analyzer/c_statics/find.py b/Tools/c-analyzer/c_statics/find.py index 81a14ef3bf08a6..f5dd75d58422d6 100644 --- a/Tools/c-analyzer/c_statics/find.py +++ b/Tools/c-analyzer/c_statics/find.py @@ -3,6 +3,7 @@ def statics(dirnames, ignored, known, *, + kind=None, # Use the default. _load_ignored=ignored_from_file, _load_known=known_from_file, _iter_statics=scan.iter_statics, @@ -15,7 +16,7 @@ def statics(dirnames, ignored, known, *, ignored = set(_load_ignored(ignored)) if ignored else () known = set(_load_known(known)) if known else () found = [] - for static in _iter_statics(dirnames): + for static in _iter_statics(dirnames, kind=kind): found.append( (static, _is_supported(static, ignored, known))) return found diff --git a/Tools/c-analyzer/c_statics/scan.py b/Tools/c-analyzer/c_statics/scan.py index a66c2ea88e48f8..fbbaeaaefb90b8 100644 --- a/Tools/c-analyzer/c_statics/scan.py +++ b/Tools/c-analyzer/c_statics/scan.py @@ -1,12 +1,13 @@ from c_parser import info -from c_symbols import nm as symbols +from c_symbols import binary as b_symbols, source as s_symbols -def iter_statics(dirnames, *, - _iter_symbols=symbols.iter_binary, - ): - """Yield a StaticVar for each one found in the file.""" - for symbol in _iter_symbols(dirnames): +# Once we start parsing directly, getting symbols from a binary will +# still be useful for tool validation. + +def statics_from_symbols(dirnames, iter_symbols): + """Yield a StaticVar for each found symbol.""" + for symbol in iter_symbols(dirnames): if symbol.kind is not info.Symbol.KIND.VARIABLE: continue if symbol.external: @@ -17,3 +18,17 @@ def iter_statics(dirnames, *, name=symbol.name, vartype='???', ) + + +def iter_statics(dirnames, kind=None, *, + _from_symbols=statics_from_symbols, + ): + """Yield a StaticVar for each one found in the files.""" + kind = kind or 'platform' + + if kind == 'symbols': + return _from_symbols(dirnames, s_symbols.iter_symbols) + elif kind == 'platform': + return _from_symbols(dirnames, b_symbols.iter_symbols) + else: + raise NotImplementedError diff --git a/Tools/c-analyzer/c_symbols/nm.py b/Tools/c-analyzer/c_symbols/binary.py similarity index 92% rename from Tools/c-analyzer/c_symbols/nm.py rename to Tools/c-analyzer/c_symbols/binary.py index 27cf4438fe835a..16a7906141430c 100644 --- a/Tools/c-analyzer/c_symbols/nm.py +++ b/Tools/c-analyzer/c_symbols/binary.py @@ -3,18 +3,18 @@ import sys from c_parser import info, util -from . import local +from . import source #PYTHON = os.path.join(REPO_ROOT, 'python') PYTHON = sys.executable -def iter_binary(dirnames, binary=PYTHON, *, - _file_exists=os.path.exists, - _find_local_symbol=local.find_symbol, - _iter_symbols_nm=(lambda b, fls: _iter_symbols_nm(b, fls)), - ): +def iter_symbols(dirnames, binary=PYTHON, *, + _file_exists=os.path.exists, + _find_local_symbol=source.find_symbol, + _iter_symbols_nm=(lambda b, fls: _iter_symbols_nm(b, fls)), + ): """Yield a Symbol for each symbol found in the binary.""" if not _file_exists(binary): raise Exception('executable missing (need to build it first?)') diff --git a/Tools/c-analyzer/c_symbols/local.py b/Tools/c-analyzer/c_symbols/source.py similarity index 80% rename from Tools/c-analyzer/c_symbols/local.py rename to Tools/c-analyzer/c_symbols/source.py index ed36c321330aff..9d9f5b0e977b56 100644 --- a/Tools/c-analyzer/c_symbols/local.py +++ b/Tools/c-analyzer/c_symbols/source.py @@ -6,6 +6,7 @@ def find_symbol(name, dirnames, *, _get_local_symbols=(lambda *a, **k: _get_symbols(*a, **k)), _iter_files=files.iter_files, ): + """Return (filename, funcname, vartype) for the matching Symbol.""" for filename in _iter_files(dirnames, ('.c', '.h')): try: symbols = _perfilecache[filename] @@ -26,6 +27,7 @@ def find_symbol(name, dirnames, *, def _get_symbols(filename, *, _iter_variables=declarations.iter_variables, ): + """Return the list of Symbols found in the given file.""" symbols = {} for funcname, name, vartype in _iter_variables(filename): if not funcname: @@ -36,3 +38,8 @@ def _get_symbols(filename, *, instances = symbols[name] = [] instances.append((funcname, vartype)) return symbols + + +def iter_symbols(dirnames): + """Yield a Symbol for each symbol found in files under the directories.""" + raise NotImplementedError From a269b152e9d9c482c0cb184b5792d7578b3e297f Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 2 Aug 2019 16:31:53 -0600 Subject: [PATCH 045/118] StaticVar -> Variable. --- .../test_c_parser/test_info.py | 32 +++++++++---------- .../test_c_statics/test___main__.py | 18 +++++------ .../test_c_statics/test_find.py | 2 +- .../test_c_statics/test_scan.py | 20 ++++++------ .../test_c_statics/test_show.py | 18 +++++------ Tools/c-analyzer/c_parser/info.py | 6 ++-- Tools/c-analyzer/c_statics/scan.py | 12 ++++--- 7 files changed, 56 insertions(+), 52 deletions(-) diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_info.py b/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_info.py index 167df1a802f9ae..e797af10b9c4f7 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_info.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_info.py @@ -5,7 +5,7 @@ from .. import tool_imports_for_tests with tool_imports_for_tests(): from c_parser.info import ( - normalize_vartype, Symbol, StaticVar, + normalize_vartype, Symbol, Variable, ) @@ -212,7 +212,7 @@ def test_validate_bad_field(self): symbol.validate() # This does not fail. -class StaticVarTests(unittest.TestCase): +class VariableTests(unittest.TestCase): VALID_ARGS = ( 'x/y/z/spam.c', @@ -220,11 +220,11 @@ class StaticVarTests(unittest.TestCase): 'eggs', 'int', ) - VALID_KWARGS = dict(zip(StaticVar._fields, VALID_ARGS)) + VALID_KWARGS = dict(zip(Variable._fields, VALID_ARGS)) VALID_EXPECTED = VALID_ARGS def test_init_typical_global(self): - static = StaticVar( + static = Variable( filename='x/y/z/spam.c', funcname=None, name='eggs', @@ -239,7 +239,7 @@ def test_init_typical_global(self): )) def test_init_typical_local(self): - static = StaticVar( + static = Variable( filename='x/y/z/spam.c', funcname='func', name='eggs', @@ -254,7 +254,7 @@ def test_init_typical_local(self): )) def test_coercion_typical(self): - static = StaticVar( + static = Variable( filename='x/y/z/spam.c', funcname='func', name='eggs', @@ -271,7 +271,7 @@ def test_coercion_typical(self): def test_init_all_missing(self): for value in ('', None): with self.subTest(repr(value)): - static = StaticVar( + static = Variable( filename=value, funcname=value, name=value, @@ -314,15 +314,15 @@ def test_init_all_coerced(self): ] for summary, kwargs, expected in tests: with self.subTest(summary): - static = StaticVar(**kwargs) + static = Variable(**kwargs) - for field in StaticVar._fields: + for field in Variable._fields: value = getattr(static, field) self.assertIs(type(value), str) self.assertEqual(tuple(static), expected) def test_iterable(self): - static = StaticVar(**self.VALID_KWARGS) + static = Variable(**self.VALID_KWARGS) filename, funcname, name, vartype = static @@ -331,7 +331,7 @@ def test_iterable(self): self.assertEqual(value, expected) def test_fields(self): - static = StaticVar('a', 'b', 'z', 'x') + static = Variable('a', 'b', 'z', 'x') self.assertEqual(static.filename, 'a') self.assertEqual(static.funcname, 'b') @@ -339,7 +339,7 @@ def test_fields(self): self.assertEqual(static.vartype, 'x') def test_validate_typical(self): - static = StaticVar( + static = Variable( filename='x/y/z/spam.c', funcname='func', name='eggs', @@ -349,9 +349,9 @@ def test_validate_typical(self): static.validate() # This does not fail. def test_validate_missing_field(self): - for field in StaticVar._fields: + for field in Variable._fields: with self.subTest(field): - static = StaticVar(**self.VALID_KWARGS) + static = Variable(**self.VALID_KWARGS) static = static._replace(**{field: None}) if field == 'funcname': @@ -381,7 +381,7 @@ def test_validate_bad_field(self): for value in invalid: seen.add(value) with self.subTest(f'{field}={value!r}'): - static = StaticVar(**self.VALID_KWARGS) + static = Variable(**self.VALID_KWARGS) static = static._replace(**{field: value}) with self.assertRaises(ValueError): @@ -391,7 +391,7 @@ def test_validate_bad_field(self): valid = seen - set(invalid) for value in valid: with self.subTest(f'{field}={value!r}'): - static = StaticVar(**self.VALID_KWARGS) + static = Variable(**self.VALID_KWARGS) static = static._replace(**{field: value}) static.validate() # This does not fail. diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test___main__.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test___main__.py index 469b8abc162016..464ea69a2f8929 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test___main__.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test___main__.py @@ -9,31 +9,31 @@ TYPICAL = [ - (info.StaticVar('src1/spam.c', None, 'var1', 'const char *'), + (info.Variable('src1/spam.c', None, 'var1', 'const char *'), True, ), - (info.StaticVar('src1/spam.c', 'ham', 'initialized', 'int'), + (info.Variable('src1/spam.c', 'ham', 'initialized', 'int'), True, ), - (info.StaticVar('src1/spam.c', None, 'var2', 'PyObject *'), + (info.Variable('src1/spam.c', None, 'var2', 'PyObject *'), False, ), - (info.StaticVar('src1/eggs.c', 'tofu', 'ready', 'int'), + (info.Variable('src1/eggs.c', 'tofu', 'ready', 'int'), True, ), - (info.StaticVar('src1/spam.c', None, 'freelist', '(PyTupleObject *)[10]'), + (info.Variable('src1/spam.c', None, 'freelist', '(PyTupleObject *)[10]'), False, ), - (info.StaticVar('src1/sub/ham.c', None, 'var1', 'const char const *'), + (info.Variable('src1/sub/ham.c', None, 'var1', 'const char const *'), True, ), - (info.StaticVar('src2/jam.c', None, 'var1', 'int'), + (info.Variable('src2/jam.c', None, 'var1', 'int'), True, ), - (info.StaticVar('src2/jam.c', None, 'var2', 'MyObject *'), + (info.Variable('src2/jam.c', None, 'var2', 'MyObject *'), False, ), - (info.StaticVar('Include/spam.h', None, 'data', 'const int'), + (info.Variable('Include/spam.h', None, 'data', 'const int'), True, ), ] diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py index e0fcebf347095b..d9f05020675cf9 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py @@ -42,7 +42,7 @@ def add_static(self, filename, funcname, name, vartype, *, ignored=False, known=False, ): - static = info.StaticVar(filename, funcname, name, vartype) + static = info.Variable(filename, funcname, name, vartype) funcs = [] if supported is not None: funcs.append('iter_statics') diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_scan.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_scan.py index bee8001c1a05e2..21763bced315b8 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_scan.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_scan.py @@ -45,11 +45,11 @@ def test_typical(self): found = list(statics_from_symbols(['dir1'], self.iter_symbols)) self.assertEqual(found, [ - info.StaticVar('dir1/spam.c', None, 'var1', '???'), - info.StaticVar('dir1/spam.c', None, 'var2', '???'), - info.StaticVar('dir1/spam.c', None, 'var3', '???'), - info.StaticVar('dir1/spam.c', 'func2', 'var4', '???'), - info.StaticVar('dir1/eggs.c', None, 'var1', '???'), + info.Variable('dir1/spam.c', None, 'var1', '???'), + info.Variable('dir1/spam.c', None, 'var2', '???'), + info.Variable('dir1/spam.c', None, 'var3', '???'), + info.Variable('dir1/spam.c', 'func2', 'var4', '???'), + info.Variable('dir1/eggs.c', None, 'var1', '???'), ]) self.assertEqual(self.calls, [ ('iter_symbols', (['dir1'],)), @@ -76,11 +76,11 @@ def _from_symbols(self, dirnames, iter_symbols): def test_typical(self): expected = [ - info.StaticVar('dir1/spam.c', None, 'var1', '???'), - info.StaticVar('dir1/spam.c', None, 'var2', '???'), - info.StaticVar('dir1/spam.c', None, 'var3', '???'), - info.StaticVar('dir1/spam.c', 'func2', 'var4', '???'), - info.StaticVar('dir1/eggs.c', None, 'var1', '???'), + info.Variable('dir1/spam.c', None, 'var1', '???'), + info.Variable('dir1/spam.c', None, 'var2', '???'), + info.Variable('dir1/spam.c', None, 'var3', '???'), + info.Variable('dir1/spam.c', 'func2', 'var4', '???'), + info.Variable('dir1/eggs.c', None, 'var1', '???'), ] self._return_from_symbols = expected diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_show.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_show.py index 1a03365a86cea9..c94ec263b4a6b8 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_show.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_show.py @@ -7,15 +7,15 @@ TYPICAL = [ - info.StaticVar('src1/spam.c', None, 'var1', 'const char *'), - info.StaticVar('src1/spam.c', 'ham', 'initialized', 'int'), - info.StaticVar('src1/spam.c', None, 'var2', 'PyObject *'), - info.StaticVar('src1/eggs.c', 'tofu', 'ready', 'int'), - info.StaticVar('src1/spam.c', None, 'freelist', '(PyTupleObject *)[10]'), - info.StaticVar('src1/sub/ham.c', None, 'var1', 'const char const *'), - info.StaticVar('src2/jam.c', None, 'var1', 'int'), - info.StaticVar('src2/jam.c', None, 'var2', 'MyObject *'), - info.StaticVar('Include/spam.h', None, 'data', 'const int'), + info.Variable('src1/spam.c', None, 'var1', 'const char *'), + info.Variable('src1/spam.c', 'ham', 'initialized', 'int'), + info.Variable('src1/spam.c', None, 'var2', 'PyObject *'), + info.Variable('src1/eggs.c', 'tofu', 'ready', 'int'), + info.Variable('src1/spam.c', None, 'freelist', '(PyTupleObject *)[10]'), + info.Variable('src1/sub/ham.c', None, 'var1', 'const char const *'), + info.Variable('src2/jam.c', None, 'var1', 'int'), + info.Variable('src2/jam.c', None, 'var2', 'MyObject *'), + info.Variable('Include/spam.h', None, 'data', 'const int'), ] diff --git a/Tools/c-analyzer/c_parser/info.py b/Tools/c-analyzer/c_parser/info.py index 6a5c0b066acf9b..42188dd8dc2ae6 100644 --- a/Tools/c-analyzer/c_parser/info.py +++ b/Tools/c-analyzer/c_parser/info.py @@ -108,9 +108,9 @@ def validate(self): # declaration can be not set. -class StaticVar(_NTBase, - namedtuple('StaticVar', 'filename funcname name vartype')): - """Information about a single static variable.""" +class Variable(_NTBase, + namedtuple('Variable', 'filename funcname name vartype')): + """Information about a single variable declaration.""" __slots__ = () diff --git a/Tools/c-analyzer/c_statics/scan.py b/Tools/c-analyzer/c_statics/scan.py index fbbaeaaefb90b8..347b76baa3ef7d 100644 --- a/Tools/c-analyzer/c_statics/scan.py +++ b/Tools/c-analyzer/c_statics/scan.py @@ -6,13 +6,13 @@ # still be useful for tool validation. def statics_from_symbols(dirnames, iter_symbols): - """Yield a StaticVar for each found symbol.""" + """Yield a Variable for each found symbol (static only).""" for symbol in iter_symbols(dirnames): if symbol.kind is not info.Symbol.KIND.VARIABLE: continue if symbol.external: continue - yield info.StaticVar( + yield info.Variable( filename=symbol.filename, funcname=symbol.funcname or None, name=symbol.name, @@ -23,12 +23,16 @@ def statics_from_symbols(dirnames, iter_symbols): def iter_statics(dirnames, kind=None, *, _from_symbols=statics_from_symbols, ): - """Yield a StaticVar for each one found in the files.""" + """Yield a Variable for each one found in the files.""" kind = kind or 'platform' if kind == 'symbols': return _from_symbols(dirnames, s_symbols.iter_symbols) elif kind == 'platform': return _from_symbols(dirnames, b_symbols.iter_symbols) - else: + elif kind == 'declarations': + raise NotImplementedError + elif kind == 'preprocessed': raise NotImplementedError + else: + raise ValueError(f'unsupported kind {kind!r}') From 842ef7ceed16dcbb079dfa17e5575d57a56a8c73 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 2 Aug 2019 16:51:43 -0600 Subject: [PATCH 046/118] Add statics_from_declarations(). --- .../test_c_statics/test_scan.py | 139 +++++++++++++++++- Tools/c-analyzer/c_parser/declarations.py | 17 +++ Tools/c-analyzer/c_parser/info.py | 8 + Tools/c-analyzer/c_statics/scan.py | 17 ++- 4 files changed, 174 insertions(+), 7 deletions(-) diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_scan.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_scan.py index 21763bced315b8..1796f2c377fca1 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_scan.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_scan.py @@ -2,8 +2,10 @@ from .. import tool_imports_for_tests with tool_imports_for_tests(): - from c_parser import info - from c_statics.scan import iter_statics, statics_from_symbols + from c_parser import info, declarations + from c_statics.scan import ( + iter_statics, statics_from_symbols, statics_from_declarations + ) from c_symbols import binary as b_symbols, source as s_symbols @@ -66,14 +68,65 @@ def test_no_symbols(self): ]) +class StaticFromDeclarationsTests(_Base): + + _return_iter_declarations = () + + def iter_declarations(self, dirnames): + self.calls.append(('iter_declarations', (dirnames,))) + return iter(self._return_iter_declarations) + + def test_typical(self): + self._return_iter_declarations = [ + None, + info.Variable('dir1/spam.c', None, 'var1', '???'), + object(), + info.Variable('dir1/spam.c', None, 'var2', '???'), + info.Variable('dir1/spam.c', None, 'var3', '???'), + object(), + info.Variable('dir1/spam.c', 'func2', 'var4', '???'), + object(), + info.Variable('dir1/eggs.c', None, 'var1', '???'), + object(), + ] + + found = list(statics_from_declarations(['dir1'], self.iter_declarations)) + + self.assertEqual(found, [ + info.Variable('dir1/spam.c', None, 'var1', '???'), + info.Variable('dir1/spam.c', None, 'var2', '???'), + info.Variable('dir1/spam.c', None, 'var3', '???'), + info.Variable('dir1/spam.c', 'func2', 'var4', '???'), + info.Variable('dir1/eggs.c', None, 'var1', '???'), + ]) + self.assertEqual(self.calls, [ + ('iter_declarations', (['dir1'],)), + ]) + + def test_no_declarations(self): + self._return_iter_declarations = [] + + found = list(statics_from_declarations(['dir1'], self.iter_declarations)) + + self.assertEqual(found, []) + self.assertEqual(self.calls, [ + ('iter_declarations', (['dir1'],)), + ]) + + class IterStaticsTests(_Base): _return_from_symbols = () + _return_from_declarations = () def _from_symbols(self, dirnames, iter_symbols): self.calls.append(('_from_symbols', (dirnames, iter_symbols))) return iter(self._return_from_symbols) + def _from_declarations(self, dirnames, iter_declarations): + self.calls.append(('_from_declarations', (dirnames, iter_declarations))) + return iter(self._return_from_declarations) + def test_typical(self): expected = [ info.Variable('dir1/spam.c', None, 'var1', '???'), @@ -85,7 +138,8 @@ def test_typical(self): self._return_from_symbols = expected found = list(iter_statics(['dir1'], - _from_symbols=self._from_symbols)) + _from_symbols=self._from_symbols, + _from_declarations=self._from_declarations)) self.assertEqual(found, expected) self.assertEqual(self.calls, [ @@ -96,9 +150,86 @@ def test_no_symbols(self): self._return_from_symbols = [] found = list(iter_statics(['dir1'], - _from_symbols=self._from_symbols)) + _from_symbols=self._from_symbols, + _from_declarations=self._from_declarations)) self.assertEqual(found, []) self.assertEqual(self.calls, [ ('_from_symbols', (['dir1'], b_symbols.iter_symbols)), ]) + + def test_from_binary(self): + expected = [ + info.Variable('dir1/spam.c', None, 'var1', '???'), + info.Variable('dir1/spam.c', None, 'var2', '???'), + info.Variable('dir1/spam.c', None, 'var3', '???'), + info.Variable('dir1/spam.c', 'func2', 'var4', '???'), + info.Variable('dir1/eggs.c', None, 'var1', '???'), + ] + self._return_from_symbols = expected + + found = list(iter_statics(['dir1'], 'platform', + _from_symbols=self._from_symbols, + _from_declarations=self._from_declarations)) + + self.assertEqual(found, expected) + self.assertEqual(self.calls, [ + ('_from_symbols', (['dir1'], b_symbols.iter_symbols)), + ]) + + def test_from_symbols(self): + expected = [ + info.Variable('dir1/spam.c', None, 'var1', '???'), + info.Variable('dir1/spam.c', None, 'var2', '???'), + info.Variable('dir1/spam.c', None, 'var3', '???'), + info.Variable('dir1/spam.c', 'func2', 'var4', '???'), + info.Variable('dir1/eggs.c', None, 'var1', '???'), + ] + self._return_from_symbols = expected + + found = list(iter_statics(['dir1'], 'symbols', + _from_symbols=self._from_symbols, + _from_declarations=self._from_declarations)) + + self.assertEqual(found, expected) + self.assertEqual(self.calls, [ + ('_from_symbols', (['dir1'], s_symbols.iter_symbols)), + ]) + + def test_from_declarations(self): + expected = [ + info.Variable('dir1/spam.c', None, 'var1', '???'), + info.Variable('dir1/spam.c', None, 'var2', '???'), + info.Variable('dir1/spam.c', None, 'var3', '???'), + info.Variable('dir1/spam.c', 'func2', 'var4', '???'), + info.Variable('dir1/eggs.c', None, 'var1', '???'), + ] + self._return_from_declarations = expected + + found = list(iter_statics(['dir1'], 'declarations', + _from_symbols=self._from_symbols, + _from_declarations=self._from_declarations)) + + self.assertEqual(found, expected) + self.assertEqual(self.calls, [ + ('_from_declarations', (['dir1'], declarations.iter_all)), + ]) + + def test_from_preprocessed(self): + expected = [ + info.Variable('dir1/spam.c', None, 'var1', '???'), + info.Variable('dir1/spam.c', None, 'var2', '???'), + info.Variable('dir1/spam.c', None, 'var3', '???'), + info.Variable('dir1/spam.c', 'func2', 'var4', '???'), + info.Variable('dir1/eggs.c', None, 'var1', '???'), + ] + self._return_from_declarations = expected + + found = list(iter_statics(['dir1'], 'preprocessed', + _from_symbols=self._from_symbols, + _from_declarations=self._from_declarations)) + + self.assertEqual(found, expected) + self.assertEqual(self.calls, [ + ('_from_declarations', (['dir1'], declarations.iter_preprocessed)), + ]) diff --git a/Tools/c-analyzer/c_parser/declarations.py b/Tools/c-analyzer/c_parser/declarations.py index 26abfde1e19eba..19fa3ff4e66bb1 100644 --- a/Tools/c-analyzer/c_parser/declarations.py +++ b/Tools/c-analyzer/c_parser/declarations.py @@ -276,3 +276,20 @@ def _iter_locals(lines, *, if name: yield (name, vartype) compound.extend(bodies) + + +def iter_all(dirnames): + """Yield a Declaration for each one found. + + If there are duplicates, due to preprocessor conditionals, then + they are checked to make sure they are the same. + """ + raise NotImplementedError + + +def iter_preprocessed(dirnames): + """Yield a Declaration for each one found. + + All source files are run through the preprocessor first. + """ + raise NotImplementedError diff --git a/Tools/c-analyzer/c_parser/info.py b/Tools/c-analyzer/c_parser/info.py index 42188dd8dc2ae6..6e9bbb8cfc0c32 100644 --- a/Tools/c-analyzer/c_parser/info.py +++ b/Tools/c-analyzer/c_parser/info.py @@ -135,3 +135,11 @@ def validate(self): elif field not in ('filename', 'vartype'): if not NAME_RE.match(value): raise ValueError(f'{field} must be a name, got {value!r}') + + @property + def isstatic(self): + return 'static' in self.vartype.split() + + @property + def isconst(self): + return 'const' in self.vartype.split() diff --git a/Tools/c-analyzer/c_statics/scan.py b/Tools/c-analyzer/c_statics/scan.py index 347b76baa3ef7d..c7d368901d2a70 100644 --- a/Tools/c-analyzer/c_statics/scan.py +++ b/Tools/c-analyzer/c_statics/scan.py @@ -1,4 +1,4 @@ -from c_parser import info +from c_parser import info, declarations from c_symbols import binary as b_symbols, source as s_symbols @@ -20,8 +20,19 @@ def statics_from_symbols(dirnames, iter_symbols): ) +def statics_from_declarations(dirnames, iter_declarations): + """Yield a Variable for each static variable declaration.""" + for decl in iter_declarations(dirnames): + if not isinstance(decl, info.Variable): + continue + if decl.isstatic: + continue + yield decl + + def iter_statics(dirnames, kind=None, *, _from_symbols=statics_from_symbols, + _from_declarations=statics_from_declarations, ): """Yield a Variable for each one found in the files.""" kind = kind or 'platform' @@ -31,8 +42,8 @@ def iter_statics(dirnames, kind=None, *, elif kind == 'platform': return _from_symbols(dirnames, b_symbols.iter_symbols) elif kind == 'declarations': - raise NotImplementedError + return _from_declarations(dirnames, declarations.iter_all) elif kind == 'preprocessed': - raise NotImplementedError + return _from_declarations(dirnames, declarations.iter_preprocessed) else: raise ValueError(f'unsupported kind {kind!r}') From 853768af91cf94bef2e96b51468aa591e03e4d36 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 2 Aug 2019 17:30:41 -0600 Subject: [PATCH 047/118] Track the per-variable preprocessor conditions. --- Tools/c-analyzer/c_parser/info.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Tools/c-analyzer/c_parser/info.py b/Tools/c-analyzer/c_parser/info.py index 6e9bbb8cfc0c32..6927cba71967f4 100644 --- a/Tools/c-analyzer/c_parser/info.py +++ b/Tools/c-analyzer/c_parser/info.py @@ -113,8 +113,9 @@ class Variable(_NTBase, """Information about a single variable declaration.""" __slots__ = () + _OBJ_CONDITIONS = {} - def __new__(cls, filename, funcname, name, vartype): + def __new__(cls, filename, funcname, name, vartype, conditions=None): self = super().__new__( cls, filename=str(filename) if filename else None, @@ -122,6 +123,8 @@ def __new__(cls, filename, funcname, name, vartype): name=str(name) if name else None, vartype=normalize_vartype(vartype) if vartype else None, ) + cls._OBJ_CONDITIONS[id(self)] = tuple(str(s) if s else None + for s in conditions or ()) return self def validate(self): @@ -136,6 +139,10 @@ def validate(self): if not NAME_RE.match(value): raise ValueError(f'{field} must be a name, got {value!r}') + @property + def conditions(self): + return self._OBJ_CONDITIONS[id(self)] + @property def isstatic(self): return 'static' in self.vartype.split() From 5f1b8b98d81d8605bbdba0635428f38bf2c58d5a Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 23 Aug 2019 13:46:34 -0600 Subject: [PATCH 048/118] Add util.Slot (a descriptor). --- Tools/c-analyzer/c_parser/util.py | 62 +++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/Tools/c-analyzer/c_parser/util.py b/Tools/c-analyzer/c_parser/util.py index d96ac2a1b020eb..5d52993fcb6e92 100644 --- a/Tools/c-analyzer/c_parser/util.py +++ b/Tools/c-analyzer/c_parser/util.py @@ -11,3 +11,65 @@ def run_cmd(argv): check=True, ) return proc.stdout + + +class Slot: + """A descriptor that provides a slot. + + This is useful for types that can't have slots via __slots__, + e.g. tuple subclasses. + """ + + __slots__ = ('initial', 'default', 'readonly', 'instances', 'name') + + def __init__(self, initial=_NOT_SET, *, + default=_NOT_SET, + readonly=False, + ): + self.initial = initial + self.default = default + self.readonly = readonly + + self.instances = {} + self.name = None + + def __set_name__(self, cls, name): + if self.name is not None: + raise TypeError('already used') + self.name = name + + def __get__(self, obj, cls): + if obj is None: # called on the class + return self + try: + value = self.instances[id(obj)] + except KeyError: + if self.initial is _NOT_SET: + value = self.default + else: + value = self.initial + self.instances[id(obj)] = value + if value is _NOT_SET: + raise AttributeError(self.name) + # XXX Optionally make a copy? + return value + + def __set__(self, obj, value): + if self.readonly: + raise AttributeError(f'{self.name} is readonly') + # XXX Optionally coerce? + self.instances[id(obj)] = value + + def __delete__(self, obj): + if self.readonly: + raise AttributeError(f'{self.name} is readonly') + self.instances[id(obj)] = self.default + + def set(self, obj, value): + """Update the cached value for an object. + + This works even if the descriptor is read-only. This is + particularly useful when initializing the object (e.g. in + its __new__ or __init__). + """ + self.instances[id(obj)] = value From b850c05a0f2cfd333f24e3a71c298ac501b377fd Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 23 Aug 2019 14:04:13 -0600 Subject: [PATCH 049/118] Add util.classonly (a la classmethod). --- Tools/c-analyzer/c_parser/util.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Tools/c-analyzer/c_parser/util.py b/Tools/c-analyzer/c_parser/util.py index 5d52993fcb6e92..bc5f9a91b50129 100644 --- a/Tools/c-analyzer/c_parser/util.py +++ b/Tools/c-analyzer/c_parser/util.py @@ -73,3 +73,27 @@ def set(self, obj, value): its __new__ or __init__). """ self.instances[id(obj)] = value + + +class classonly: + """A non-data descriptor that makes a value only visible on the class. + + This is like the "classmethod" builtin, but does not show up on + instances of the class. It may be used as a decorator. + """ + + def __init__(self, value): + self.value = value + self.getter = classmethod(value).__get__ + self.name = None + + def __set_name__(self, cls, name): + if self.name is not None: + raise TypeError('already used') + self.name = name + + def __get__(self, obj, cls): + if obj is not None: + raise AttributeError(self.name) + # called on the class + return self.getter(None, cls) From cde5b3220fd00839a7c1c6d7b38db71221071e40 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 23 Aug 2019 14:07:01 -0600 Subject: [PATCH 050/118] Add util._NOT_SET. --- Tools/c-analyzer/c_parser/util.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Tools/c-analyzer/c_parser/util.py b/Tools/c-analyzer/c_parser/util.py index bc5f9a91b50129..e3d8719059104b 100644 --- a/Tools/c-analyzer/c_parser/util.py +++ b/Tools/c-analyzer/c_parser/util.py @@ -1,6 +1,9 @@ import subprocess +_NOT_SET = object() + + def run_cmd(argv): proc = subprocess.run( argv, From 11377dd87f250f527e276627537351d9cedc3d25 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 23 Aug 2019 14:51:35 -0600 Subject: [PATCH 051/118] Add _NTBase.from_raw(). --- Tools/c-analyzer/c_parser/info.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/Tools/c-analyzer/c_parser/info.py b/Tools/c-analyzer/c_parser/info.py index 6927cba71967f4..14864429e0bef1 100644 --- a/Tools/c-analyzer/c_parser/info.py +++ b/Tools/c-analyzer/c_parser/info.py @@ -1,6 +1,8 @@ from collections import namedtuple import re +from .util import classonly + NAME_RE = re.compile(r'^([a-zA-Z]|_\w*[a-zA-Z]\w*|[a-zA-Z]\w*)$') @@ -20,6 +22,30 @@ class _NTBase: __slots__ = () + @classonly + def from_raw(cls, raw): + if not raw: + return None + elif isinstance(raw, cls): + return raw + elif isinstance(raw, str): + return cls.from_string(raw) + else: + if hasattr(raw, 'items'): + return cls(**raw) + try: + args = tuple(raw) + except TypeError: + pass + else: + return cls(*args) + raise NotImplementedError + + @classonly + def from_string(cls, value): + """Return a new instance based on the given string.""" + raise NotImplementedError + @classmethod def _make(cls, iterable): # The default _make() is not subclass-friendly. return cls.__new__(cls, *iterable) From acbedc7941fb487f99834c0a88f64222210a4547 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 23 Aug 2019 14:52:04 -0600 Subject: [PATCH 052/118] Add info.ID. --- .../test_c_parser/test_info.py | 189 +++++++++++++++++- Tools/c-analyzer/c_parser/info.py | 53 +++++ 2 files changed, 241 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_info.py b/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_info.py index e797af10b9c4f7..60d29b62f196f3 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_info.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_info.py @@ -5,7 +5,7 @@ from .. import tool_imports_for_tests with tool_imports_for_tests(): from c_parser.info import ( - normalize_vartype, Symbol, Variable, + normalize_vartype, ID, Symbol, Variable, ) @@ -26,6 +26,193 @@ def test_basic(self): self.assertEqual(normalized, expected) +class IDTests(unittest.TestCase): + + VALID_ARGS = ( + 'x/y/z/spam.c', + 'func', + 'eggs', + ) + VALID_KWARGS = dict(zip(ID._fields, VALID_ARGS)) + VALID_EXPECTED = VALID_ARGS + + def test_from_raw(self): + tests = [ + ('', None), + (None, None), + ('spam', (None, None, 'spam')), + (('spam',), (None, None, 'spam')), + (('x/y/z/spam.c', 'spam'), ('x/y/z/spam.c', None, 'spam')), + (self.VALID_ARGS, self.VALID_EXPECTED), + (self.VALID_KWARGS, self.VALID_EXPECTED), + ] + for raw, expected in tests: + with self.subTest(raw): + id = ID.from_raw(raw) + + self.assertEqual(id, expected) + + def test_minimal(self): + id = ID( + filename=None, + funcname=None, + name='eggs', + ) + + self.assertEqual(id, ( + None, + None, + 'eggs', + )) + + def test_init_typical_global(self): + id = ID( + filename='x/y/z/spam.c', + funcname=None, + name='eggs', + ) + + self.assertEqual(id, ( + 'x/y/z/spam.c', + None, + 'eggs', + )) + + def test_init_typical_local(self): + id = ID( + filename='x/y/z/spam.c', + funcname='func', + name='eggs', + ) + + self.assertEqual(id, ( + 'x/y/z/spam.c', + 'func', + 'eggs', + )) + + def test_init_all_missing(self): + for value in ('', None): + with self.subTest(repr(value)): + id = ID( + filename=value, + funcname=value, + name=value, + ) + + self.assertEqual(id, ( + None, + None, + None, + )) + + def test_init_all_coerced(self): + tests = [ + ('str subclass', + dict( + filename=PseudoStr('x/y/z/spam.c'), + funcname=PseudoStr('func'), + name=PseudoStr('eggs'), + ), + ('x/y/z/spam.c', + 'func', + 'eggs', + )), + ('non-str', + dict( + filename=StrProxy('x/y/z/spam.c'), + funcname=Object(), + name=('a', 'b', 'c'), + ), + ('x/y/z/spam.c', + '', + "('a', 'b', 'c')", + )), + ] + for summary, kwargs, expected in tests: + with self.subTest(summary): + id = ID(**kwargs) + + for field in ID._fields: + value = getattr(id, field) + self.assertIs(type(value), str) + self.assertEqual(tuple(id), expected) + + def test_iterable(self): + id = ID(**self.VALID_KWARGS) + + filename, funcname, name = id + + values = (filename, funcname, name) + for value, expected in zip(values, self.VALID_EXPECTED): + self.assertEqual(value, expected) + + def test_fields(self): + id = ID('a', 'b', 'z') + + self.assertEqual(id.filename, 'a') + self.assertEqual(id.funcname, 'b') + self.assertEqual(id.name, 'z') + + def test_validate_typical(self): + id = ID( + filename='x/y/z/spam.c', + funcname='func', + name='eggs', + ) + + id.validate() # This does not fail. + + def test_validate_missing_field(self): + for field in ID._fields: + with self.subTest(field): + id = ID(**self.VALID_KWARGS) + id = id._replace(**{field: None}) + + if field == 'funcname': + id.validate() # The field can be missing (not set). + id = id._replace(filename=None) + id.validate() # Both fields can be missing (not set). + continue + + with self.assertRaises(TypeError): + id.validate() + + def test_validate_bad_field(self): + badch = tuple(c for c in string.punctuation + string.digits) + notnames = ( + '1a', + 'a.b', + 'a-b', + '&a', + 'a++', + ) + badch + tests = [ + ('filename', ()), # Any non-empty str is okay. + ('funcname', notnames), + ('name', notnames), + ] + seen = set() + for field, invalid in tests: + for value in invalid: + seen.add(value) + with self.subTest(f'{field}={value!r}'): + id = ID(**self.VALID_KWARGS) + id = id._replace(**{field: value}) + + with self.assertRaises(ValueError): + id.validate() + + for field, invalid in tests: + valid = seen - set(invalid) + for value in valid: + with self.subTest(f'{field}={value!r}'): + id = ID(**self.VALID_KWARGS) + id = id._replace(**{field: value}) + + id.validate() # This does not fail. + + class SymbolTests(unittest.TestCase): VALID_ARGS = ( diff --git a/Tools/c-analyzer/c_parser/info.py b/Tools/c-analyzer/c_parser/info.py index 14864429e0bef1..81754af98e02b6 100644 --- a/Tools/c-analyzer/c_parser/info.py +++ b/Tools/c-analyzer/c_parser/info.py @@ -81,6 +81,59 @@ def validate(self): # return obj +class ID(_NTBase, namedtuple('ID', 'filename funcname name')): + """A unique ID for a single symbol or declaration.""" + + # XXX Add optional conditions (tuple of strings) field. + + __slots__ = () + + @classonly + def from_raw(cls, raw): + if not raw: + return None + if isinstance(raw, str): + return cls(None, None, raw) + try: + name, = raw + filename = None + except ValueError: + try: + filename, name = raw + except ValueError: + return super().from_raw(raw) + return cls(filename, None, name) + + def __new__(cls, filename, funcname, name): + self = super().__new__( + cls, + filename=str(filename) if filename else None, + funcname=str(funcname) if funcname else None, + name=str(name) if name else None, + ) + return self + + def validate(self): + """Fail if the object is invalid (i.e. init with bad data).""" + if not self.name: + raise TypeError('missing name') + else: + if not NAME_RE.match(self.name): + raise ValueError( + f'name must be an identifier, got {self.name!r}') + + # Symbols from a binary might not have filename/funcname info. + + if self.funcname: + if not self.filename: + raise TypeError('missing filename') + if not NAME_RE.match(self.funcname): + raise ValueError( + f'name must be an identifier, got {self.funcname!r}') + + # XXX Check the filename? + + class Symbol(_NTBase, namedtuple('Symbol', 'name kind external filename funcname declaration')): From 08310bf3c742d5eee9f48c661868e34f77fff86e Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 23 Aug 2019 15:33:45 -0600 Subject: [PATCH 053/118] Use ID in Symbol. --- .../test_c_parser/test_info.py | 124 +++++++++--------- .../test_c_statics/test_scan.py | 20 +-- Tools/c-analyzer/c_parser/info.py | 41 +++--- 3 files changed, 87 insertions(+), 98 deletions(-) diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_info.py b/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_info.py index 60d29b62f196f3..4f01fde087c930 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_info.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_info.py @@ -216,84 +216,82 @@ def test_validate_bad_field(self): class SymbolTests(unittest.TestCase): VALID_ARGS = ( - 'eggs', + ID('x/y/z/spam.c', 'func', 'eggs'), Symbol.KIND.VARIABLE, False, - 'x/y/z/spam.c', - 'func', - 'int', ) VALID_KWARGS = dict(zip(Symbol._fields, VALID_ARGS)) VALID_EXPECTED = VALID_ARGS - def test_init_typical_binary(self): + def test_init_typical_binary_local(self): + id = ID(None, None, 'spam') symbol = Symbol( - name='spam', + id=id, kind=Symbol.KIND.VARIABLE, external=False, - filename='Python/ceval.c', ) self.assertEqual(symbol, ( - 'spam', + id, Symbol.KIND.VARIABLE, False, - 'Python/ceval.c', - None, - None, )) - def test_init_typical_source(self): + def test_init_typical_binary_global(self): + id = ID('Python/ceval.c', None, 'spam') symbol = Symbol( - name='spam', + id=id, kind=Symbol.KIND.VARIABLE, external=False, - filename='Python/ceval.c', - declaration='static const int', ) self.assertEqual(symbol, ( - 'spam', + id, Symbol.KIND.VARIABLE, False, - 'Python/ceval.c', - None, - 'static const int', )) def test_init_coercion(self): tests = [ ('str subclass', dict( - name=PseudoStr('eggs'), + id=PseudoStr('eggs'), kind=PseudoStr('variable'), external=0, - filename=PseudoStr('x/y/z/spam.c'), - funcname=PseudoStr('func'), - declaration=PseudoStr('int'), ), - ('eggs', + (ID(None, None, 'eggs'), Symbol.KIND.VARIABLE, False, - 'x/y/z/spam.c', - 'func', - 'int', )), - ('non-str', + ('with filename', dict( - name=('a', 'b', 'c'), + id=('x/y/z/spam.c', 'eggs'), + kind=PseudoStr('variable'), + external=0, + ), + (ID('x/y/z/spam.c', None, 'eggs'), + Symbol.KIND.VARIABLE, + False, + )), + ('non-str 1', + dict( + id=('a', 'b', 'c'), kind=StrProxy('variable'), external=0, - filename=StrProxy('x/y/z/spam.c'), - funcname=StrProxy('func'), - declaration=Object(), ), - ("('a', 'b', 'c')", + (ID('a', 'b', 'c'), Symbol.KIND.VARIABLE, False, - 'x/y/z/spam.c', - 'func', + )), + ('non-str 2', + dict( + id=('a', 'b', 'c'), + kind=Object(), + external=0, + ), + (ID('a', 'b', 'c'), '', + False, )), ] for summary, kwargs, expected in tests: @@ -304,39 +302,51 @@ def test_init_coercion(self): value = getattr(symbol, field) if field == 'external': self.assertIs(type(value), bool) + elif field == 'id': + self.assertIs(type(value), ID) else: self.assertIs(type(value), str) self.assertEqual(tuple(symbol), expected) def test_init_all_missing(self): - symbol = Symbol('spam') + id = ID(None, None, 'spam') + + symbol = Symbol(id) self.assertEqual(symbol, ( - 'spam', + id, Symbol.KIND.VARIABLE, None, - None, - None, - None, )) def test_fields(self): - static = Symbol('a', 'b', False, 'z', 'x', 'w') + id = ID('z', 'x', 'a') - self.assertEqual(static.name, 'a') - self.assertEqual(static.kind, 'b') - self.assertIs(static.external, False) - self.assertEqual(static.filename, 'z') - self.assertEqual(static.funcname, 'x') - self.assertEqual(static.declaration, 'w') + symbol = Symbol(id, 'b', False) + + self.assertEqual(symbol.id, id) + self.assertEqual(symbol.kind, 'b') + self.assertIs(symbol.external, False) + + def test___getattr__(self): + id = ID('z', 'x', 'a') + symbol = Symbol(id, 'b', False) + + filename = symbol.filename + funcname = symbol.funcname + name = symbol.name + + self.assertEqual(filename, 'z') + self.assertEqual(funcname, 'x') + self.assertEqual(name, 'a') def test_validate_typical(self): + id = ID('z', 'x', 'a') + symbol = Symbol( - name='spam', + id=id, kind=Symbol.KIND.VARIABLE, external=False, - filename='Python/ceval.c', - declaration='static const int', ) symbol.validate() # This does not fail. @@ -347,17 +357,8 @@ def test_validate_missing_field(self): symbol = Symbol(**self.VALID_KWARGS) symbol = symbol._replace(**{field: None}) - if field in ('funcname', 'declaration'): - symbol.validate() # The field can be missing (not set). - continue - with self.assertRaises(TypeError): symbol.validate() - with self.subTest('combined'): - symbol = Symbol(**self.VALID_KWARGS) - symbol = symbol._replace(filename=None, funcname=None) - - symbol.validate() # The fields together can be missing (not set). def test_validate_bad_field(self): badch = tuple(c for c in string.punctuation + string.digits) @@ -369,11 +370,8 @@ def test_validate_bad_field(self): 'a++', ) + badch tests = [ - ('name', notnames), + ('id', notnames), ('kind', ('bogus',)), - ('filename', ()), # Any non-empty str is okay. - ('funcname', notnames), - ('declaration', ()), # Any non-empty str is okay. ] seen = set() for field, invalid in tests: diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_scan.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_scan.py index 1796f2c377fca1..49603bec7af36f 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_scan.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_scan.py @@ -32,16 +32,16 @@ def iter_symbols(self, dirnames): def test_typical(self): self._return_iter_symbols = [ - info.Symbol('var1', 'variable', False, 'dir1/spam.c', None, None), - info.Symbol('var2', 'variable', False, 'dir1/spam.c', None, None), - info.Symbol('func1', 'function', False, 'dir1/spam.c', None, None), - info.Symbol('func2', 'function', True, 'dir1/spam.c', None, None), - info.Symbol('var3', 'variable', False, 'dir1/spam.c', None, None), - info.Symbol('var4', 'variable', False, 'dir1/spam.c', 'func2', None), - info.Symbol('var1', 'variable', True, 'dir1/ham.c', None, None), - info.Symbol('var1', 'variable', False, 'dir1/eggs.c', None, None), - info.Symbol('xyz', 'other', False, 'dir1/eggs.c', None, None), - info.Symbol('???', 'other', False, None, None, None), + info.Symbol(('dir1/spam.c', None, 'var1'), 'variable', False), + info.Symbol(('dir1/spam.c', None, 'var2'), 'variable', False), + info.Symbol(('dir1/spam.c', None, 'func1'), 'function', False), + info.Symbol(('dir1/spam.c', None, 'func2'), 'function', True), + info.Symbol(('dir1/spam.c', None, 'var3'), 'variable', False), + info.Symbol(('dir1/spam.c', 'func2', 'var4'), 'variable', False), + info.Symbol(('dir1/ham.c', None, 'var1'), 'variable', True), + info.Symbol(('dir1/eggs.c', None, 'var1'), 'variable', False), + info.Symbol(('dir1/eggs.c', None, 'xyz'), 'other', False), + info.Symbol((None, None, '???'), 'other', False), ] found = list(statics_from_symbols(['dir1'], self.iter_symbols)) diff --git a/Tools/c-analyzer/c_parser/info.py b/Tools/c-analyzer/c_parser/info.py index 81754af98e02b6..4aef8e01288207 100644 --- a/Tools/c-analyzer/c_parser/info.py +++ b/Tools/c-analyzer/c_parser/info.py @@ -134,9 +134,7 @@ def validate(self): # XXX Check the filename? -class Symbol(_NTBase, - namedtuple('Symbol', - 'name kind external filename funcname declaration')): +class Symbol(_NTBase, namedtuple('Symbol', 'id kind external')): """Info for a single compilation symbol.""" __slots__ = () @@ -146,25 +144,30 @@ class KIND: FUNCTION = 'function' OTHER = 'other' - def __new__(cls, name, kind=KIND.VARIABLE, external=None, - filename=None, funcname=None, declaration=None): + @classonly + def from_name(cls, name, filename=None, kind=KIND.VARIABLE, external=None): + """Return a new symbol based on the given name.""" + id = ID(filename, None, name) + return cls(id, kind, external) + + def __new__(cls, id, kind=KIND.VARIABLE, external=None): self = super().__new__( cls, - name=str(name) if name else None, + id=ID.from_raw(id), kind=str(kind) if kind else None, external=bool(external) if external is not None else None, - filename=str(filename) if filename else None, - funcname=str(funcname) if funcname else None, - declaration=normalize_vartype(declaration), ) return self + def __getattr__(self, name): + return getattr(self.id, name) + def validate(self): """Fail if the object is invalid (i.e. init with bad data).""" - if not self.name: - raise TypeError('missing name') - elif not NAME_RE.match(self.name): - raise ValueError(f'name must be a name, got {self.name!r}') + if not self.id: + raise TypeError('missing id') + else: + self.id.validate() if not self.kind: raise TypeError('missing kind') @@ -174,18 +177,6 @@ def validate(self): if self.external is None: raise TypeError('missing external') - if not self.filename and self.funcname: - raise TypeError('missing filename') - # filename, funcname and declaration can be not set. - - if not self.funcname: - # funcname can be not set. - pass - elif not NAME_RE.match(self.funcname): - raise ValueError(f'funcname must be a name, got{self.funcname!r}') - - # declaration can be not set. - class Variable(_NTBase, namedtuple('Variable', 'filename funcname name vartype')): From 1d5e9bff22c1b7a00ab1660f93944cd967403792 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 23 Aug 2019 16:01:56 -0600 Subject: [PATCH 054/118] Use ID in Variable. --- .../test_c_parser/test_info.py | 122 +++++++++--------- .../test_c_statics/test___main__.py | 18 +-- .../test_c_statics/test_find.py | 2 +- .../test_c_statics/test_scan.py | 80 ++++++------ .../test_c_statics/test_show.py | 18 +-- Tools/c-analyzer/c_parser/info.py | 37 +++--- Tools/c-analyzer/c_statics/scan.py | 2 +- 7 files changed, 136 insertions(+), 143 deletions(-) diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_info.py b/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_info.py index 4f01fde087c930..1319cbc1307bc7 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_info.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_info.py @@ -400,9 +400,7 @@ def test_validate_bad_field(self): class VariableTests(unittest.TestCase): VALID_ARGS = ( - 'x/y/z/spam.c', - 'func', - 'eggs', + ('x/y/z/spam.c', 'func', 'eggs'), 'int', ) VALID_KWARGS = dict(zip(Variable._fields, VALID_ARGS)) @@ -410,46 +408,31 @@ class VariableTests(unittest.TestCase): def test_init_typical_global(self): static = Variable( - filename='x/y/z/spam.c', - funcname=None, - name='eggs', + id=ID( + filename='x/y/z/spam.c', + funcname=None, + name='eggs', + ), vartype='int', ) self.assertEqual(static, ( - 'x/y/z/spam.c', - None, - 'eggs', + ('x/y/z/spam.c', None, 'eggs'), 'int', )) def test_init_typical_local(self): static = Variable( - filename='x/y/z/spam.c', - funcname='func', - name='eggs', + id=ID( + filename='x/y/z/spam.c', + funcname='func', + name='eggs', + ), vartype='int', ) self.assertEqual(static, ( - 'x/y/z/spam.c', - 'func', - 'eggs', - 'int', - )) - - def test_coercion_typical(self): - static = Variable( - filename='x/y/z/spam.c', - funcname='func', - name='eggs', - vartype='int', - ) - - self.assertEqual(static, ( - 'x/y/z/spam.c', - 'func', - 'eggs', + ('x/y/z/spam.c', 'func', 'eggs'), 'int', )) @@ -457,45 +440,54 @@ def test_init_all_missing(self): for value in ('', None): with self.subTest(repr(value)): static = Variable( - filename=value, - funcname=value, - name=value, + id=value, vartype=value, ) self.assertEqual(static, ( - None, - None, None, None, )) def test_init_all_coerced(self): + id = ID('x/y/z/spam.c', 'func', 'spam') tests = [ ('str subclass', dict( - filename=PseudoStr('x/y/z/spam.c'), - funcname=PseudoStr('func'), - name=PseudoStr('eggs'), + id=( + PseudoStr('x/y/z/spam.c'), + PseudoStr('func'), + PseudoStr('spam'), + ), vartype=PseudoStr('int'), ), - ('x/y/z/spam.c', - 'func', - 'eggs', + (id, 'int', )), - ('non-str', + ('non-str 1', dict( - filename=StrProxy('x/y/z/spam.c'), - funcname=StrProxy('func'), - name=('a', 'b', 'c'), + id=id, vartype=Object(), ), - ('x/y/z/spam.c', - 'func', - "('a', 'b', 'c')", + (id, '', )), + ('non-str 2', + dict( + id=id, + vartype=StrProxy('variable'), + ), + (id, + 'variable', + )), + ('non-str', + dict( + id=id, + vartype=('a', 'b', 'c'), + ), + (id, + "('a', 'b', 'c')", + )), ] for summary, kwargs, expected in tests: with self.subTest(summary): @@ -503,31 +495,41 @@ def test_init_all_coerced(self): for field in Variable._fields: value = getattr(static, field) - self.assertIs(type(value), str) + if field == 'id': + self.assertIs(type(value), ID) + else: + self.assertIs(type(value), str) self.assertEqual(tuple(static), expected) def test_iterable(self): static = Variable(**self.VALID_KWARGS) - filename, funcname, name, vartype = static + id, vartype = static - values = (filename, funcname, name, vartype) + values = (id, vartype) for value, expected in zip(values, self.VALID_EXPECTED): self.assertEqual(value, expected) def test_fields(self): - static = Variable('a', 'b', 'z', 'x') + static = Variable(('a', 'b', 'z'), 'x') + + self.assertEqual(static.id, ('a', 'b', 'z')) + self.assertEqual(static.vartype, 'x') + + def test___getattr__(self): + static = Variable(('a', 'b', 'z'), 'x') self.assertEqual(static.filename, 'a') self.assertEqual(static.funcname, 'b') self.assertEqual(static.name, 'z') - self.assertEqual(static.vartype, 'x') def test_validate_typical(self): static = Variable( - filename='x/y/z/spam.c', - funcname='func', - name='eggs', + id=ID( + filename='x/y/z/spam.c', + funcname='func', + name='eggs', + ), vartype='int', ) @@ -539,10 +541,6 @@ def test_validate_missing_field(self): static = Variable(**self.VALID_KWARGS) static = static._replace(**{field: None}) - if field == 'funcname': - static.validate() # The field can be missing (not set). - continue - with self.assertRaises(TypeError): static.validate() @@ -556,9 +554,7 @@ def test_validate_bad_field(self): 'a++', ) + badch tests = [ - ('filename', ()), # Any non-empty str is okay. - ('funcname', notnames), - ('name', notnames), + ('id', ()), # Any non-empty str is okay. ('vartype', ()), # Any non-empty str is okay. ] seen = set() diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test___main__.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test___main__.py index 464ea69a2f8929..56886b6f8a5c5b 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test___main__.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test___main__.py @@ -9,31 +9,31 @@ TYPICAL = [ - (info.Variable('src1/spam.c', None, 'var1', 'const char *'), + (info.Variable.from_parts('src1/spam.c', None, 'var1', 'const char *'), True, ), - (info.Variable('src1/spam.c', 'ham', 'initialized', 'int'), + (info.Variable.from_parts('src1/spam.c', 'ham', 'initialized', 'int'), True, ), - (info.Variable('src1/spam.c', None, 'var2', 'PyObject *'), + (info.Variable.from_parts('src1/spam.c', None, 'var2', 'PyObject *'), False, ), - (info.Variable('src1/eggs.c', 'tofu', 'ready', 'int'), + (info.Variable.from_parts('src1/eggs.c', 'tofu', 'ready', 'int'), True, ), - (info.Variable('src1/spam.c', None, 'freelist', '(PyTupleObject *)[10]'), + (info.Variable.from_parts('src1/spam.c', None, 'freelist', '(PyTupleObject *)[10]'), False, ), - (info.Variable('src1/sub/ham.c', None, 'var1', 'const char const *'), + (info.Variable.from_parts('src1/sub/ham.c', None, 'var1', 'const char const *'), True, ), - (info.Variable('src2/jam.c', None, 'var1', 'int'), + (info.Variable.from_parts('src2/jam.c', None, 'var1', 'int'), True, ), - (info.Variable('src2/jam.c', None, 'var2', 'MyObject *'), + (info.Variable.from_parts('src2/jam.c', None, 'var2', 'MyObject *'), False, ), - (info.Variable('Include/spam.h', None, 'data', 'const int'), + (info.Variable.from_parts('Include/spam.h', None, 'data', 'const int'), True, ), ] diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py index d9f05020675cf9..3e2acdfcaa451b 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py @@ -42,7 +42,7 @@ def add_static(self, filename, funcname, name, vartype, *, ignored=False, known=False, ): - static = info.Variable(filename, funcname, name, vartype) + static = info.Variable.from_parts(filename, funcname, name, vartype) funcs = [] if supported is not None: funcs.append('iter_statics') diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_scan.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_scan.py index 49603bec7af36f..e08c6879bd9341 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_scan.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_scan.py @@ -47,11 +47,11 @@ def test_typical(self): found = list(statics_from_symbols(['dir1'], self.iter_symbols)) self.assertEqual(found, [ - info.Variable('dir1/spam.c', None, 'var1', '???'), - info.Variable('dir1/spam.c', None, 'var2', '???'), - info.Variable('dir1/spam.c', None, 'var3', '???'), - info.Variable('dir1/spam.c', 'func2', 'var4', '???'), - info.Variable('dir1/eggs.c', None, 'var1', '???'), + info.Variable.from_parts('dir1/spam.c', None, 'var1', '???'), + info.Variable.from_parts('dir1/spam.c', None, 'var2', '???'), + info.Variable.from_parts('dir1/spam.c', None, 'var3', '???'), + info.Variable.from_parts('dir1/spam.c', 'func2', 'var4', '???'), + info.Variable.from_parts('dir1/eggs.c', None, 'var1', '???'), ]) self.assertEqual(self.calls, [ ('iter_symbols', (['dir1'],)), @@ -79,25 +79,25 @@ def iter_declarations(self, dirnames): def test_typical(self): self._return_iter_declarations = [ None, - info.Variable('dir1/spam.c', None, 'var1', '???'), + info.Variable.from_parts('dir1/spam.c', None, 'var1', '???'), object(), - info.Variable('dir1/spam.c', None, 'var2', '???'), - info.Variable('dir1/spam.c', None, 'var3', '???'), + info.Variable.from_parts('dir1/spam.c', None, 'var2', '???'), + info.Variable.from_parts('dir1/spam.c', None, 'var3', '???'), object(), - info.Variable('dir1/spam.c', 'func2', 'var4', '???'), + info.Variable.from_parts('dir1/spam.c', 'func2', 'var4', '???'), object(), - info.Variable('dir1/eggs.c', None, 'var1', '???'), + info.Variable.from_parts('dir1/eggs.c', None, 'var1', '???'), object(), ] found = list(statics_from_declarations(['dir1'], self.iter_declarations)) self.assertEqual(found, [ - info.Variable('dir1/spam.c', None, 'var1', '???'), - info.Variable('dir1/spam.c', None, 'var2', '???'), - info.Variable('dir1/spam.c', None, 'var3', '???'), - info.Variable('dir1/spam.c', 'func2', 'var4', '???'), - info.Variable('dir1/eggs.c', None, 'var1', '???'), + info.Variable.from_parts('dir1/spam.c', None, 'var1', '???'), + info.Variable.from_parts('dir1/spam.c', None, 'var2', '???'), + info.Variable.from_parts('dir1/spam.c', None, 'var3', '???'), + info.Variable.from_parts('dir1/spam.c', 'func2', 'var4', '???'), + info.Variable.from_parts('dir1/eggs.c', None, 'var1', '???'), ]) self.assertEqual(self.calls, [ ('iter_declarations', (['dir1'],)), @@ -129,11 +129,11 @@ def _from_declarations(self, dirnames, iter_declarations): def test_typical(self): expected = [ - info.Variable('dir1/spam.c', None, 'var1', '???'), - info.Variable('dir1/spam.c', None, 'var2', '???'), - info.Variable('dir1/spam.c', None, 'var3', '???'), - info.Variable('dir1/spam.c', 'func2', 'var4', '???'), - info.Variable('dir1/eggs.c', None, 'var1', '???'), + info.Variable.from_parts('dir1/spam.c', None, 'var1', '???'), + info.Variable.from_parts('dir1/spam.c', None, 'var2', '???'), + info.Variable.from_parts('dir1/spam.c', None, 'var3', '???'), + info.Variable.from_parts('dir1/spam.c', 'func2', 'var4', '???'), + info.Variable.from_parts('dir1/eggs.c', None, 'var1', '???'), ] self._return_from_symbols = expected @@ -160,11 +160,11 @@ def test_no_symbols(self): def test_from_binary(self): expected = [ - info.Variable('dir1/spam.c', None, 'var1', '???'), - info.Variable('dir1/spam.c', None, 'var2', '???'), - info.Variable('dir1/spam.c', None, 'var3', '???'), - info.Variable('dir1/spam.c', 'func2', 'var4', '???'), - info.Variable('dir1/eggs.c', None, 'var1', '???'), + info.Variable.from_parts('dir1/spam.c', None, 'var1', '???'), + info.Variable.from_parts('dir1/spam.c', None, 'var2', '???'), + info.Variable.from_parts('dir1/spam.c', None, 'var3', '???'), + info.Variable.from_parts('dir1/spam.c', 'func2', 'var4', '???'), + info.Variable.from_parts('dir1/eggs.c', None, 'var1', '???'), ] self._return_from_symbols = expected @@ -179,11 +179,11 @@ def test_from_binary(self): def test_from_symbols(self): expected = [ - info.Variable('dir1/spam.c', None, 'var1', '???'), - info.Variable('dir1/spam.c', None, 'var2', '???'), - info.Variable('dir1/spam.c', None, 'var3', '???'), - info.Variable('dir1/spam.c', 'func2', 'var4', '???'), - info.Variable('dir1/eggs.c', None, 'var1', '???'), + info.Variable.from_parts('dir1/spam.c', None, 'var1', '???'), + info.Variable.from_parts('dir1/spam.c', None, 'var2', '???'), + info.Variable.from_parts('dir1/spam.c', None, 'var3', '???'), + info.Variable.from_parts('dir1/spam.c', 'func2', 'var4', '???'), + info.Variable.from_parts('dir1/eggs.c', None, 'var1', '???'), ] self._return_from_symbols = expected @@ -198,11 +198,11 @@ def test_from_symbols(self): def test_from_declarations(self): expected = [ - info.Variable('dir1/spam.c', None, 'var1', '???'), - info.Variable('dir1/spam.c', None, 'var2', '???'), - info.Variable('dir1/spam.c', None, 'var3', '???'), - info.Variable('dir1/spam.c', 'func2', 'var4', '???'), - info.Variable('dir1/eggs.c', None, 'var1', '???'), + info.Variable.from_parts('dir1/spam.c', None, 'var1', '???'), + info.Variable.from_parts('dir1/spam.c', None, 'var2', '???'), + info.Variable.from_parts('dir1/spam.c', None, 'var3', '???'), + info.Variable.from_parts('dir1/spam.c', 'func2', 'var4', '???'), + info.Variable.from_parts('dir1/eggs.c', None, 'var1', '???'), ] self._return_from_declarations = expected @@ -217,11 +217,11 @@ def test_from_declarations(self): def test_from_preprocessed(self): expected = [ - info.Variable('dir1/spam.c', None, 'var1', '???'), - info.Variable('dir1/spam.c', None, 'var2', '???'), - info.Variable('dir1/spam.c', None, 'var3', '???'), - info.Variable('dir1/spam.c', 'func2', 'var4', '???'), - info.Variable('dir1/eggs.c', None, 'var1', '???'), + info.Variable.from_parts('dir1/spam.c', None, 'var1', '???'), + info.Variable.from_parts('dir1/spam.c', None, 'var2', '???'), + info.Variable.from_parts('dir1/spam.c', None, 'var3', '???'), + info.Variable.from_parts('dir1/spam.c', 'func2', 'var4', '???'), + info.Variable.from_parts('dir1/eggs.c', None, 'var1', '???'), ] self._return_from_declarations = expected diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_show.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_show.py index c94ec263b4a6b8..b9baed3f313bca 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_show.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_show.py @@ -7,15 +7,15 @@ TYPICAL = [ - info.Variable('src1/spam.c', None, 'var1', 'const char *'), - info.Variable('src1/spam.c', 'ham', 'initialized', 'int'), - info.Variable('src1/spam.c', None, 'var2', 'PyObject *'), - info.Variable('src1/eggs.c', 'tofu', 'ready', 'int'), - info.Variable('src1/spam.c', None, 'freelist', '(PyTupleObject *)[10]'), - info.Variable('src1/sub/ham.c', None, 'var1', 'const char const *'), - info.Variable('src2/jam.c', None, 'var1', 'int'), - info.Variable('src2/jam.c', None, 'var2', 'MyObject *'), - info.Variable('Include/spam.h', None, 'data', 'const int'), + info.Variable.from_parts('src1/spam.c', None, 'var1', 'const char *'), + info.Variable.from_parts('src1/spam.c', 'ham', 'initialized', 'int'), + info.Variable.from_parts('src1/spam.c', None, 'var2', 'PyObject *'), + info.Variable.from_parts('src1/eggs.c', 'tofu', 'ready', 'int'), + info.Variable.from_parts('src1/spam.c', None, 'freelist', '(PyTupleObject *)[10]'), + info.Variable.from_parts('src1/sub/ham.c', None, 'var1', 'const char const *'), + info.Variable.from_parts('src2/jam.c', None, 'var1', 'int'), + info.Variable.from_parts('src2/jam.c', None, 'var2', 'MyObject *'), + info.Variable.from_parts('Include/spam.h', None, 'data', 'const int'), ] diff --git a/Tools/c-analyzer/c_parser/info.py b/Tools/c-analyzer/c_parser/info.py index 4aef8e01288207..bfb3af4fa3aa7e 100644 --- a/Tools/c-analyzer/c_parser/info.py +++ b/Tools/c-analyzer/c_parser/info.py @@ -179,39 +179,36 @@ def validate(self): class Variable(_NTBase, - namedtuple('Variable', 'filename funcname name vartype')): + namedtuple('Variable', 'id vartype')): """Information about a single variable declaration.""" __slots__ = () - _OBJ_CONDITIONS = {} - def __new__(cls, filename, funcname, name, vartype, conditions=None): + @classonly + def from_parts(cls, filename, funcname, name, vartype): + id = ID(filename, funcname, name) + return cls(id, vartype) + + def __new__(cls, id, vartype): self = super().__new__( cls, - filename=str(filename) if filename else None, - funcname=str(funcname) if funcname else None, - name=str(name) if name else None, + id=ID.from_raw(id), vartype=normalize_vartype(vartype) if vartype else None, ) - cls._OBJ_CONDITIONS[id(self)] = tuple(str(s) if s else None - for s in conditions or ()) return self + def __getattr__(self, name): + return getattr(self.id, name) + def validate(self): """Fail if the object is invalid (i.e. init with bad data).""" - for field in self._fields: - value = getattr(self, field) - if value is None: - if field == 'funcname': # The field can be missing (net set). - continue - raise TypeError(f'missing {field}') - elif field not in ('filename', 'vartype'): - if not NAME_RE.match(value): - raise ValueError(f'{field} must be a name, got {value!r}') + if not self.id: + raise TypeError('missing id') + else: + self.id.validate() - @property - def conditions(self): - return self._OBJ_CONDITIONS[id(self)] + if self.vartype is None: + raise TypeError('missing vartype') @property def isstatic(self): diff --git a/Tools/c-analyzer/c_statics/scan.py b/Tools/c-analyzer/c_statics/scan.py index c7d368901d2a70..dc01fa8f49b8ad 100644 --- a/Tools/c-analyzer/c_statics/scan.py +++ b/Tools/c-analyzer/c_statics/scan.py @@ -12,7 +12,7 @@ def statics_from_symbols(dirnames, iter_symbols): continue if symbol.external: continue - yield info.Variable( + yield info.Variable.from_parts( filename=symbol.filename, funcname=symbol.funcname or None, name=symbol.name, From 0c56fd9685e583a0a10407f4e8c21f8595cce79c Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 23 Aug 2019 16:18:22 -0600 Subject: [PATCH 055/118] Add a note about a "conditions" slot for info.ID. --- Tools/c-analyzer/c_parser/info.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Tools/c-analyzer/c_parser/info.py b/Tools/c-analyzer/c_parser/info.py index bfb3af4fa3aa7e..7ee0db23ab94d5 100644 --- a/Tools/c-analyzer/c_parser/info.py +++ b/Tools/c-analyzer/c_parser/info.py @@ -84,9 +84,9 @@ def validate(self): class ID(_NTBase, namedtuple('ID', 'filename funcname name')): """A unique ID for a single symbol or declaration.""" - # XXX Add optional conditions (tuple of strings) field. - __slots__ = () + # XXX Add optional conditions (tuple of strings) field. + #conditions = Slot() @classonly def from_raw(cls, raw): @@ -111,6 +111,8 @@ def __new__(cls, filename, funcname, name): funcname=str(funcname) if funcname else None, name=str(name) if name else None, ) + #cls.conditions.set(self, tuple(str(s) if s else None + # for s in conditions or ())) return self def validate(self): From 9563689db465543cc23d0969b56c5291eca3a890 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 23 Aug 2019 16:30:23 -0600 Subject: [PATCH 056/118] Require Variable to have filename set. --- Tools/c-analyzer/c_parser/info.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Tools/c-analyzer/c_parser/info.py b/Tools/c-analyzer/c_parser/info.py index 7ee0db23ab94d5..e326c9fc90ff03 100644 --- a/Tools/c-analyzer/c_parser/info.py +++ b/Tools/c-analyzer/c_parser/info.py @@ -209,6 +209,9 @@ def validate(self): else: self.id.validate() + if not self.filename: + raise TypeError('id missing filename') + if self.vartype is None: raise TypeError('missing vartype') From 7ad89b20a22320b06693c6b58812d87eaf704c6c Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 23 Aug 2019 17:21:11 -0600 Subject: [PATCH 057/118] "???" means "unknown". --- Tools/c-analyzer/c_parser/info.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Tools/c-analyzer/c_parser/info.py b/Tools/c-analyzer/c_parser/info.py index e326c9fc90ff03..6b902f4a4a5076 100644 --- a/Tools/c-analyzer/c_parser/info.py +++ b/Tools/c-analyzer/c_parser/info.py @@ -4,6 +4,8 @@ from .util import classonly +UNKNOWN = '???' + NAME_RE = re.compile(r'^([a-zA-Z]|_\w*[a-zA-Z]\w*|[a-zA-Z]\w*)$') @@ -129,10 +131,11 @@ def validate(self): if self.funcname: if not self.filename: raise TypeError('missing filename') - if not NAME_RE.match(self.funcname): + if not NAME_RE.match(self.funcname) and self.funcname != UNKNOWN: raise ValueError( f'name must be an identifier, got {self.funcname!r}') + # XXX Require the filename (at least UNKONWN)? # XXX Check the filename? From 2b2bc66f4b796cd0e7722ec7e322bf2d7da0a281 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sat, 24 Aug 2019 11:29:37 -0600 Subject: [PATCH 058/118] Make find_local_symbol() a "public" argument. --- Tools/c-analyzer/c_symbols/binary.py | 78 +++++++++++++++++----------- 1 file changed, 49 insertions(+), 29 deletions(-) diff --git a/Tools/c-analyzer/c_symbols/binary.py b/Tools/c-analyzer/c_symbols/binary.py index 16a7906141430c..0a134c41699ffb 100644 --- a/Tools/c-analyzer/c_symbols/binary.py +++ b/Tools/c-analyzer/c_symbols/binary.py @@ -11,18 +11,23 @@ def iter_symbols(dirnames, binary=PYTHON, *, + # Alternately, use look_up_known_symbol() + # from c_statics.supported. + find_local_symbol=source.find_symbol, _file_exists=os.path.exists, - _find_local_symbol=source.find_symbol, _iter_symbols_nm=(lambda b, fls: _iter_symbols_nm(b, fls)), ): """Yield a Symbol for each symbol found in the binary.""" if not _file_exists(binary): raise Exception('executable missing (need to build it first?)') - cache = {} - def find_local_symbol(name): - return _find_local_symbol(name, dirnames, _perfilecache=cache) - yield from _iter_symbols_nm(binary, find_local_symbol) + if not find_local_symbol: + yield from _iter_symbols_nm(binary) + else: + cache = {} + def find_local_symbol(name, *, _find=find_local_symbol): + return _find(name, dirnames, _perfilecache=cache) + yield from _iter_symbols_nm(binary, find_local_symbol) ############################# @@ -82,20 +87,22 @@ def _iter_symbols_nm(binary, find_local_symbol=None, raise for line in output.splitlines(): (name, kind, external, filename, funcname, vartype, - )= _parse_nm_line(line, _find_local_symbol=find_local_symbol) + ) = _parse_nm_line(line, + _find_local_symbol=find_local_symbol, + ) if kind != info.Symbol.KIND.VARIABLE: continue elif _is_special_symbol(name): continue - elif not filename: - raise Exception(f'missing filename: {name}') + assert vartype is None yield info.Symbol( - name=name, + id=info.ID( + filename=filename, + funcname=funcname, + name=name, + ), kind=kind, external=external, - filename=filename, - funcname=funcname, - declaration=vartype, ) @@ -111,22 +118,35 @@ def _parse_nm_line(line, *, _find_local_symbol=None): name, _, filename = line.partition('\t') name = name.strip() - - funcname = None - vartype = None if filename: filename = os.path.relpath(filename.partition(':')[0]) - elif kind != info.Symbol.KIND.VARIABLE: - pass - elif _is_special_symbol(name): - pass - elif _find_local_symbol is not None: - orig = name - name, sep, digits = name.partition('.') - if not sep or not digits.isdigit(): - print(_origline) - raise Exception(f'expected local variable, got {orig}') - filename, funcname, vartype = _find_local_symbol(name) - -# return info.Symbol(name, kind, external, filename or None, funcname) - return name, kind, external, filename or None, funcname, vartype + else: + filename = info.UNKNOWN + + vartype = None + name, islocal = _parse_nm_name(name, kind) + if islocal: + funcname = info.UNKNOWN + if _find_local_symbol is not None: + filename, funcname, vartype = _find_local_symbol(name) + filename = filename or info.UNKNOWN + funcname = funcname or info.UNKNOWN + else: + funcname = None + # XXX fine filename and vartype? + return name, kind, external, filename, funcname, vartype + + +def _parse_nm_name(name, kind): + if kind != info.Symbol.KIND.VARIABLE: + return name, None + if _is_special_symbol(name): + return name, None + + actual, sep, digits = name.partition('.') + if not sep: + return name, False + + if not digits.isdigit(): + raise Exception(f'got bogus name {name}') + return actual, True From 1316a3b46a962241beeebe863cdd8934e340606f Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sat, 24 Aug 2019 11:35:06 -0600 Subject: [PATCH 059/118] Add info.ID.islocal. --- Tools/c-analyzer/c_parser/info.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Tools/c-analyzer/c_parser/info.py b/Tools/c-analyzer/c_parser/info.py index 6b902f4a4a5076..eb96d97763a331 100644 --- a/Tools/c-analyzer/c_parser/info.py +++ b/Tools/c-analyzer/c_parser/info.py @@ -138,6 +138,10 @@ def validate(self): # XXX Require the filename (at least UNKONWN)? # XXX Check the filename? + @property + def islocal(self): + return self.funcname is not None + class Symbol(_NTBase, namedtuple('Symbol', 'id kind external')): """Info for a single compilation symbol.""" From 4bdd9a622fc969f13d09efa6ea84479741fb19ac Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sat, 24 Aug 2019 12:29:50 -0600 Subject: [PATCH 060/118] Factor out c_analyzer_common package. --- .../test_c_analyzer_common/__init__.py | 0 .../test_c_analyzer_common/test_info.py | 194 ++++++++++++++++++ .../test_c_parser/test_info.py | 192 +---------------- .../test_c_parser/test_preprocessor.py | 2 +- .../{test_c_parser => }/util.py | 0 .../c-analyzer/c_analyzer_common/__init__.py | 0 Tools/c-analyzer/c_analyzer_common/info.py | 69 +++++++ .../{c_parser => c_analyzer_common}/util.py | 63 ++++++ Tools/c-analyzer/c_parser/info.py | 132 +----------- Tools/c-analyzer/c_parser/preprocessor.py | 5 +- Tools/c-analyzer/c_symbols/binary.py | 9 +- 11 files changed, 338 insertions(+), 328 deletions(-) create mode 100644 Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/__init__.py create mode 100644 Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/test_info.py rename Lib/test/test_tools/test_c_analyzer/{test_c_parser => }/util.py (100%) create mode 100644 Tools/c-analyzer/c_analyzer_common/__init__.py create mode 100644 Tools/c-analyzer/c_analyzer_common/info.py rename Tools/c-analyzer/{c_parser => c_analyzer_common}/util.py (63%) diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/__init__.py b/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/__init__.py new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/test_info.py b/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/test_info.py new file mode 100644 index 00000000000000..2d386713b9989c --- /dev/null +++ b/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/test_info.py @@ -0,0 +1,194 @@ +import string +import unittest + +from ..util import PseudoStr, StrProxy, Object +from .. import tool_imports_for_tests +with tool_imports_for_tests(): + from c_analyzer_common.info import ID + + +class IDTests(unittest.TestCase): + + VALID_ARGS = ( + 'x/y/z/spam.c', + 'func', + 'eggs', + ) + VALID_KWARGS = dict(zip(ID._fields, VALID_ARGS)) + VALID_EXPECTED = VALID_ARGS + + def test_from_raw(self): + tests = [ + ('', None), + (None, None), + ('spam', (None, None, 'spam')), + (('spam',), (None, None, 'spam')), + (('x/y/z/spam.c', 'spam'), ('x/y/z/spam.c', None, 'spam')), + (self.VALID_ARGS, self.VALID_EXPECTED), + (self.VALID_KWARGS, self.VALID_EXPECTED), + ] + for raw, expected in tests: + with self.subTest(raw): + id = ID.from_raw(raw) + + self.assertEqual(id, expected) + + def test_minimal(self): + id = ID( + filename=None, + funcname=None, + name='eggs', + ) + + self.assertEqual(id, ( + None, + None, + 'eggs', + )) + + def test_init_typical_global(self): + id = ID( + filename='x/y/z/spam.c', + funcname=None, + name='eggs', + ) + + self.assertEqual(id, ( + 'x/y/z/spam.c', + None, + 'eggs', + )) + + def test_init_typical_local(self): + id = ID( + filename='x/y/z/spam.c', + funcname='func', + name='eggs', + ) + + self.assertEqual(id, ( + 'x/y/z/spam.c', + 'func', + 'eggs', + )) + + def test_init_all_missing(self): + for value in ('', None): + with self.subTest(repr(value)): + id = ID( + filename=value, + funcname=value, + name=value, + ) + + self.assertEqual(id, ( + None, + None, + None, + )) + + def test_init_all_coerced(self): + tests = [ + ('str subclass', + dict( + filename=PseudoStr('x/y/z/spam.c'), + funcname=PseudoStr('func'), + name=PseudoStr('eggs'), + ), + ('x/y/z/spam.c', + 'func', + 'eggs', + )), + ('non-str', + dict( + filename=StrProxy('x/y/z/spam.c'), + funcname=Object(), + name=('a', 'b', 'c'), + ), + ('x/y/z/spam.c', + '', + "('a', 'b', 'c')", + )), + ] + for summary, kwargs, expected in tests: + with self.subTest(summary): + id = ID(**kwargs) + + for field in ID._fields: + value = getattr(id, field) + self.assertIs(type(value), str) + self.assertEqual(tuple(id), expected) + + def test_iterable(self): + id = ID(**self.VALID_KWARGS) + + filename, funcname, name = id + + values = (filename, funcname, name) + for value, expected in zip(values, self.VALID_EXPECTED): + self.assertEqual(value, expected) + + def test_fields(self): + id = ID('a', 'b', 'z') + + self.assertEqual(id.filename, 'a') + self.assertEqual(id.funcname, 'b') + self.assertEqual(id.name, 'z') + + def test_validate_typical(self): + id = ID( + filename='x/y/z/spam.c', + funcname='func', + name='eggs', + ) + + id.validate() # This does not fail. + + def test_validate_missing_field(self): + for field in ID._fields: + with self.subTest(field): + id = ID(**self.VALID_KWARGS) + id = id._replace(**{field: None}) + + if field == 'funcname': + id.validate() # The field can be missing (not set). + id = id._replace(filename=None) + id.validate() # Both fields can be missing (not set). + continue + + with self.assertRaises(TypeError): + id.validate() + + def test_validate_bad_field(self): + badch = tuple(c for c in string.punctuation + string.digits) + notnames = ( + '1a', + 'a.b', + 'a-b', + '&a', + 'a++', + ) + badch + tests = [ + ('filename', ()), # Any non-empty str is okay. + ('funcname', notnames), + ('name', notnames), + ] + seen = set() + for field, invalid in tests: + for value in invalid: + seen.add(value) + with self.subTest(f'{field}={value!r}'): + id = ID(**self.VALID_KWARGS) + id = id._replace(**{field: value}) + + with self.assertRaises(ValueError): + id.validate() + + for field, invalid in tests: + valid = seen - set(invalid) + for value in valid: + with self.subTest(f'{field}={value!r}'): + id = ID(**self.VALID_KWARGS) + id = id._replace(**{field: value}) + + id.validate() # This does not fail. diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_info.py b/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_info.py index 1319cbc1307bc7..da6ba8f27c2929 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_info.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_info.py @@ -1,11 +1,12 @@ import string import unittest -from .util import PseudoStr, StrProxy, Object +from ..util import PseudoStr, StrProxy, Object from .. import tool_imports_for_tests with tool_imports_for_tests(): + from c_analyzer_common.info import ID from c_parser.info import ( - normalize_vartype, ID, Symbol, Variable, + normalize_vartype, Symbol, Variable, ) @@ -26,193 +27,6 @@ def test_basic(self): self.assertEqual(normalized, expected) -class IDTests(unittest.TestCase): - - VALID_ARGS = ( - 'x/y/z/spam.c', - 'func', - 'eggs', - ) - VALID_KWARGS = dict(zip(ID._fields, VALID_ARGS)) - VALID_EXPECTED = VALID_ARGS - - def test_from_raw(self): - tests = [ - ('', None), - (None, None), - ('spam', (None, None, 'spam')), - (('spam',), (None, None, 'spam')), - (('x/y/z/spam.c', 'spam'), ('x/y/z/spam.c', None, 'spam')), - (self.VALID_ARGS, self.VALID_EXPECTED), - (self.VALID_KWARGS, self.VALID_EXPECTED), - ] - for raw, expected in tests: - with self.subTest(raw): - id = ID.from_raw(raw) - - self.assertEqual(id, expected) - - def test_minimal(self): - id = ID( - filename=None, - funcname=None, - name='eggs', - ) - - self.assertEqual(id, ( - None, - None, - 'eggs', - )) - - def test_init_typical_global(self): - id = ID( - filename='x/y/z/spam.c', - funcname=None, - name='eggs', - ) - - self.assertEqual(id, ( - 'x/y/z/spam.c', - None, - 'eggs', - )) - - def test_init_typical_local(self): - id = ID( - filename='x/y/z/spam.c', - funcname='func', - name='eggs', - ) - - self.assertEqual(id, ( - 'x/y/z/spam.c', - 'func', - 'eggs', - )) - - def test_init_all_missing(self): - for value in ('', None): - with self.subTest(repr(value)): - id = ID( - filename=value, - funcname=value, - name=value, - ) - - self.assertEqual(id, ( - None, - None, - None, - )) - - def test_init_all_coerced(self): - tests = [ - ('str subclass', - dict( - filename=PseudoStr('x/y/z/spam.c'), - funcname=PseudoStr('func'), - name=PseudoStr('eggs'), - ), - ('x/y/z/spam.c', - 'func', - 'eggs', - )), - ('non-str', - dict( - filename=StrProxy('x/y/z/spam.c'), - funcname=Object(), - name=('a', 'b', 'c'), - ), - ('x/y/z/spam.c', - '', - "('a', 'b', 'c')", - )), - ] - for summary, kwargs, expected in tests: - with self.subTest(summary): - id = ID(**kwargs) - - for field in ID._fields: - value = getattr(id, field) - self.assertIs(type(value), str) - self.assertEqual(tuple(id), expected) - - def test_iterable(self): - id = ID(**self.VALID_KWARGS) - - filename, funcname, name = id - - values = (filename, funcname, name) - for value, expected in zip(values, self.VALID_EXPECTED): - self.assertEqual(value, expected) - - def test_fields(self): - id = ID('a', 'b', 'z') - - self.assertEqual(id.filename, 'a') - self.assertEqual(id.funcname, 'b') - self.assertEqual(id.name, 'z') - - def test_validate_typical(self): - id = ID( - filename='x/y/z/spam.c', - funcname='func', - name='eggs', - ) - - id.validate() # This does not fail. - - def test_validate_missing_field(self): - for field in ID._fields: - with self.subTest(field): - id = ID(**self.VALID_KWARGS) - id = id._replace(**{field: None}) - - if field == 'funcname': - id.validate() # The field can be missing (not set). - id = id._replace(filename=None) - id.validate() # Both fields can be missing (not set). - continue - - with self.assertRaises(TypeError): - id.validate() - - def test_validate_bad_field(self): - badch = tuple(c for c in string.punctuation + string.digits) - notnames = ( - '1a', - 'a.b', - 'a-b', - '&a', - 'a++', - ) + badch - tests = [ - ('filename', ()), # Any non-empty str is okay. - ('funcname', notnames), - ('name', notnames), - ] - seen = set() - for field, invalid in tests: - for value in invalid: - seen.add(value) - with self.subTest(f'{field}={value!r}'): - id = ID(**self.VALID_KWARGS) - id = id._replace(**{field: value}) - - with self.assertRaises(ValueError): - id.validate() - - for field, invalid in tests: - valid = seen - set(invalid) - for value in valid: - with self.subTest(f'{field}={value!r}'): - id = ID(**self.VALID_KWARGS) - id = id._replace(**{field: value}) - - id.validate() # This does not fail. - - class SymbolTests(unittest.TestCase): VALID_ARGS = ( diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_preprocessor.py b/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_preprocessor.py index 20103cc529a630..8b16dddaeb57bf 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_preprocessor.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_preprocessor.py @@ -2,7 +2,7 @@ import textwrap import unittest -from .util import wrapped_arg_combos, StrProxy +from ..util import wrapped_arg_combos, StrProxy from .. import tool_imports_for_tests with tool_imports_for_tests(): from c_parser.preprocessor import ( diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_parser/util.py b/Lib/test/test_tools/test_c_analyzer/util.py similarity index 100% rename from Lib/test/test_tools/test_c_analyzer/test_c_parser/util.py rename to Lib/test/test_tools/test_c_analyzer/util.py diff --git a/Tools/c-analyzer/c_analyzer_common/__init__.py b/Tools/c-analyzer/c_analyzer_common/__init__.py new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/Tools/c-analyzer/c_analyzer_common/info.py b/Tools/c-analyzer/c_analyzer_common/info.py new file mode 100644 index 00000000000000..e2173804064576 --- /dev/null +++ b/Tools/c-analyzer/c_analyzer_common/info.py @@ -0,0 +1,69 @@ +from collections import namedtuple +import re + +from .util import classonly, _NTBase + + +UNKNOWN = '???' + +NAME_RE = re.compile(r'^([a-zA-Z]|_\w*[a-zA-Z]\w*|[a-zA-Z]\w*)$') + + +class ID(_NTBase, namedtuple('ID', 'filename funcname name')): + """A unique ID for a single symbol or declaration.""" + + __slots__ = () + # XXX Add optional conditions (tuple of strings) field. + #conditions = Slot() + + @classonly + def from_raw(cls, raw): + if not raw: + return None + if isinstance(raw, str): + return cls(None, None, raw) + try: + name, = raw + filename = None + except ValueError: + try: + filename, name = raw + except ValueError: + return super().from_raw(raw) + return cls(filename, None, name) + + def __new__(cls, filename, funcname, name): + self = super().__new__( + cls, + filename=str(filename) if filename else None, + funcname=str(funcname) if funcname else None, + name=str(name) if name else None, + ) + #cls.conditions.set(self, tuple(str(s) if s else None + # for s in conditions or ())) + return self + + def validate(self): + """Fail if the object is invalid (i.e. init with bad data).""" + if not self.name: + raise TypeError('missing name') + else: + if not NAME_RE.match(self.name): + raise ValueError( + f'name must be an identifier, got {self.name!r}') + + # Symbols from a binary might not have filename/funcname info. + + if self.funcname: + if not self.filename: + raise TypeError('missing filename') + if not NAME_RE.match(self.funcname) and self.funcname != UNKNOWN: + raise ValueError( + f'name must be an identifier, got {self.funcname!r}') + + # XXX Require the filename (at least UNKONWN)? + # XXX Check the filename? + + @property + def islocal(self): + return self.funcname is not None diff --git a/Tools/c-analyzer/c_parser/util.py b/Tools/c-analyzer/c_analyzer_common/util.py similarity index 63% rename from Tools/c-analyzer/c_parser/util.py rename to Tools/c-analyzer/c_analyzer_common/util.py index e3d8719059104b..e9d71915d99776 100644 --- a/Tools/c-analyzer/c_parser/util.py +++ b/Tools/c-analyzer/c_analyzer_common/util.py @@ -100,3 +100,66 @@ def __get__(self, obj, cls): raise AttributeError(self.name) # called on the class return self.getter(None, cls) + + +class _NTBase: + + __slots__ = () + + @classonly + def from_raw(cls, raw): + if not raw: + return None + elif isinstance(raw, cls): + return raw + elif isinstance(raw, str): + return cls.from_string(raw) + else: + if hasattr(raw, 'items'): + return cls(**raw) + try: + args = tuple(raw) + except TypeError: + pass + else: + return cls(*args) + raise NotImplementedError + + @classonly + def from_string(cls, value): + """Return a new instance based on the given string.""" + raise NotImplementedError + + @classmethod + def _make(cls, iterable): # The default _make() is not subclass-friendly. + return cls.__new__(cls, *iterable) + + # XXX Always validate? + #def __init__(self, *args, **kwargs): + # self.validate() + + # XXX The default __repr__() is not subclass-friendly (where the name changes). + #def __repr__(self): + # _, _, sig = super().__repr__().partition('(') + # return f'{self.__class__.__name__}({sig}' + + # To make sorting work with None: + def __lt__(self, other): + try: + return super().__lt__(other) + except TypeError: + if None in self: + return True + elif None in other: + return False + else: + raise + + def validate(self): + return + + # XXX Always validate? + #def _replace(self, **kwargs): + # obj = super()._replace(**kwargs) + # obj.validate() + # return obj diff --git a/Tools/c-analyzer/c_parser/info.py b/Tools/c-analyzer/c_parser/info.py index eb96d97763a331..cb221b15cc3e8d 100644 --- a/Tools/c-analyzer/c_parser/info.py +++ b/Tools/c-analyzer/c_parser/info.py @@ -1,12 +1,7 @@ from collections import namedtuple -import re -from .util import classonly - - -UNKNOWN = '???' - -NAME_RE = re.compile(r'^([a-zA-Z]|_\w*[a-zA-Z]\w*|[a-zA-Z]\w*)$') +from c_analyzer_common.info import UNKNOWN, NAME_RE, ID +from c_analyzer_common.util import classonly, _NTBase def normalize_vartype(vartype): @@ -20,129 +15,6 @@ def normalize_vartype(vartype): return str(vartype) -class _NTBase: - - __slots__ = () - - @classonly - def from_raw(cls, raw): - if not raw: - return None - elif isinstance(raw, cls): - return raw - elif isinstance(raw, str): - return cls.from_string(raw) - else: - if hasattr(raw, 'items'): - return cls(**raw) - try: - args = tuple(raw) - except TypeError: - pass - else: - return cls(*args) - raise NotImplementedError - - @classonly - def from_string(cls, value): - """Return a new instance based on the given string.""" - raise NotImplementedError - - @classmethod - def _make(cls, iterable): # The default _make() is not subclass-friendly. - return cls.__new__(cls, *iterable) - - # XXX Always validate? - #def __init__(self, *args, **kwargs): - # self.validate() - - # XXX The default __repr__() is not subclass-friendly (where the name changes). - #def __repr__(self): - # _, _, sig = super().__repr__().partition('(') - # return f'{self.__class__.__name__}({sig}' - - # To make sorting work with None: - def __lt__(self, other): - try: - return super().__lt__(other) - except TypeError: - if None in self: - return True - elif None in other: - return False - else: - raise - - def validate(self): - return - - # XXX Always validate? - #def _replace(self, **kwargs): - # obj = super()._replace(**kwargs) - # obj.validate() - # return obj - - -class ID(_NTBase, namedtuple('ID', 'filename funcname name')): - """A unique ID for a single symbol or declaration.""" - - __slots__ = () - # XXX Add optional conditions (tuple of strings) field. - #conditions = Slot() - - @classonly - def from_raw(cls, raw): - if not raw: - return None - if isinstance(raw, str): - return cls(None, None, raw) - try: - name, = raw - filename = None - except ValueError: - try: - filename, name = raw - except ValueError: - return super().from_raw(raw) - return cls(filename, None, name) - - def __new__(cls, filename, funcname, name): - self = super().__new__( - cls, - filename=str(filename) if filename else None, - funcname=str(funcname) if funcname else None, - name=str(name) if name else None, - ) - #cls.conditions.set(self, tuple(str(s) if s else None - # for s in conditions or ())) - return self - - def validate(self): - """Fail if the object is invalid (i.e. init with bad data).""" - if not self.name: - raise TypeError('missing name') - else: - if not NAME_RE.match(self.name): - raise ValueError( - f'name must be an identifier, got {self.name!r}') - - # Symbols from a binary might not have filename/funcname info. - - if self.funcname: - if not self.filename: - raise TypeError('missing filename') - if not NAME_RE.match(self.funcname) and self.funcname != UNKNOWN: - raise ValueError( - f'name must be an identifier, got {self.funcname!r}') - - # XXX Require the filename (at least UNKONWN)? - # XXX Check the filename? - - @property - def islocal(self): - return self.funcname is not None - - class Symbol(_NTBase, namedtuple('Symbol', 'id kind external')): """Info for a single compilation symbol.""" diff --git a/Tools/c-analyzer/c_parser/preprocessor.py b/Tools/c-analyzer/c_parser/preprocessor.py index 905569d1da8ccc..288c0ba41ff73c 100644 --- a/Tools/c-analyzer/c_parser/preprocessor.py +++ b/Tools/c-analyzer/c_parser/preprocessor.py @@ -2,7 +2,8 @@ import os import re -from . import util, info +from c_analyzer_common import util +from . import info CONTINUATION = '\\' + os.linesep @@ -106,7 +107,7 @@ def _parse_directive(line): return directive -class PreprocessorDirective(info._NTBase): +class PreprocessorDirective(util._NTBase): """The base class for directives.""" __slots__ = () diff --git a/Tools/c-analyzer/c_symbols/binary.py b/Tools/c-analyzer/c_symbols/binary.py index 0a134c41699ffb..5b110930129991 100644 --- a/Tools/c-analyzer/c_symbols/binary.py +++ b/Tools/c-analyzer/c_symbols/binary.py @@ -2,7 +2,8 @@ import shutil import sys -from c_parser import info, util +from c_analyzer_common import util +from c_parser import info from . import source @@ -96,11 +97,7 @@ def _iter_symbols_nm(binary, find_local_symbol=None, continue assert vartype is None yield info.Symbol( - id=info.ID( - filename=filename, - funcname=funcname, - name=name, - ), + id=(filename, funcname, name), kind=kind, external=external, ) From 5d52d9f11bf4426d3a4fb191b0947c497e8aa2ad Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sat, 24 Aug 2019 12:57:45 -0600 Subject: [PATCH 061/118] Move info.Symbol under c_symbols. --- .../test_c_parser/test_info.py | 186 +---------------- .../test_c_statics/test_scan.py | 26 ++- .../test_c_symbols/__init__.py | 0 .../test_c_symbols/test_info.py | 192 ++++++++++++++++++ Tools/c-analyzer/c_parser/info.py | 46 +---- Tools/c-analyzer/c_statics/scan.py | 8 +- Tools/c-analyzer/c_symbols/binary.py | 22 +- Tools/c-analyzer/c_symbols/info.py | 48 +++++ 8 files changed, 274 insertions(+), 254 deletions(-) create mode 100644 Lib/test/test_tools/test_c_analyzer/test_c_symbols/__init__.py create mode 100644 Lib/test/test_tools/test_c_analyzer/test_c_symbols/test_info.py create mode 100644 Tools/c-analyzer/c_symbols/info.py diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_info.py b/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_info.py index da6ba8f27c2929..1dfe5d066a3311 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_info.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_info.py @@ -6,7 +6,7 @@ with tool_imports_for_tests(): from c_analyzer_common.info import ID from c_parser.info import ( - normalize_vartype, Symbol, Variable, + normalize_vartype, Variable, ) @@ -27,190 +27,6 @@ def test_basic(self): self.assertEqual(normalized, expected) -class SymbolTests(unittest.TestCase): - - VALID_ARGS = ( - ID('x/y/z/spam.c', 'func', 'eggs'), - Symbol.KIND.VARIABLE, - False, - ) - VALID_KWARGS = dict(zip(Symbol._fields, VALID_ARGS)) - VALID_EXPECTED = VALID_ARGS - - def test_init_typical_binary_local(self): - id = ID(None, None, 'spam') - symbol = Symbol( - id=id, - kind=Symbol.KIND.VARIABLE, - external=False, - ) - - self.assertEqual(symbol, ( - id, - Symbol.KIND.VARIABLE, - False, - )) - - def test_init_typical_binary_global(self): - id = ID('Python/ceval.c', None, 'spam') - symbol = Symbol( - id=id, - kind=Symbol.KIND.VARIABLE, - external=False, - ) - - self.assertEqual(symbol, ( - id, - Symbol.KIND.VARIABLE, - False, - )) - - def test_init_coercion(self): - tests = [ - ('str subclass', - dict( - id=PseudoStr('eggs'), - kind=PseudoStr('variable'), - external=0, - ), - (ID(None, None, 'eggs'), - Symbol.KIND.VARIABLE, - False, - )), - ('with filename', - dict( - id=('x/y/z/spam.c', 'eggs'), - kind=PseudoStr('variable'), - external=0, - ), - (ID('x/y/z/spam.c', None, 'eggs'), - Symbol.KIND.VARIABLE, - False, - )), - ('non-str 1', - dict( - id=('a', 'b', 'c'), - kind=StrProxy('variable'), - external=0, - ), - (ID('a', 'b', 'c'), - Symbol.KIND.VARIABLE, - False, - )), - ('non-str 2', - dict( - id=('a', 'b', 'c'), - kind=Object(), - external=0, - ), - (ID('a', 'b', 'c'), - '', - False, - )), - ] - for summary, kwargs, expected in tests: - with self.subTest(summary): - symbol = Symbol(**kwargs) - - for field in Symbol._fields: - value = getattr(symbol, field) - if field == 'external': - self.assertIs(type(value), bool) - elif field == 'id': - self.assertIs(type(value), ID) - else: - self.assertIs(type(value), str) - self.assertEqual(tuple(symbol), expected) - - def test_init_all_missing(self): - id = ID(None, None, 'spam') - - symbol = Symbol(id) - - self.assertEqual(symbol, ( - id, - Symbol.KIND.VARIABLE, - None, - )) - - def test_fields(self): - id = ID('z', 'x', 'a') - - symbol = Symbol(id, 'b', False) - - self.assertEqual(symbol.id, id) - self.assertEqual(symbol.kind, 'b') - self.assertIs(symbol.external, False) - - def test___getattr__(self): - id = ID('z', 'x', 'a') - symbol = Symbol(id, 'b', False) - - filename = symbol.filename - funcname = symbol.funcname - name = symbol.name - - self.assertEqual(filename, 'z') - self.assertEqual(funcname, 'x') - self.assertEqual(name, 'a') - - def test_validate_typical(self): - id = ID('z', 'x', 'a') - - symbol = Symbol( - id=id, - kind=Symbol.KIND.VARIABLE, - external=False, - ) - - symbol.validate() # This does not fail. - - def test_validate_missing_field(self): - for field in Symbol._fields: - with self.subTest(field): - symbol = Symbol(**self.VALID_KWARGS) - symbol = symbol._replace(**{field: None}) - - with self.assertRaises(TypeError): - symbol.validate() - - def test_validate_bad_field(self): - badch = tuple(c for c in string.punctuation + string.digits) - notnames = ( - '1a', - 'a.b', - 'a-b', - '&a', - 'a++', - ) + badch - tests = [ - ('id', notnames), - ('kind', ('bogus',)), - ] - seen = set() - for field, invalid in tests: - for value in invalid: - if field != 'kind': - seen.add(value) - with self.subTest(f'{field}={value!r}'): - symbol = Symbol(**self.VALID_KWARGS) - symbol = symbol._replace(**{field: value}) - - with self.assertRaises(ValueError): - symbol.validate() - - for field, invalid in tests: - if field == 'kind': - continue - valid = seen - set(invalid) - for value in valid: - with self.subTest(f'{field}={value!r}'): - symbol = Symbol(**self.VALID_KWARGS) - symbol = symbol._replace(**{field: value}) - - symbol.validate() # This does not fail. - - class VariableTests(unittest.TestCase): VALID_ARGS = ( diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_scan.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_scan.py index e08c6879bd9341..baa67418ed9108 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_scan.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_scan.py @@ -6,7 +6,11 @@ from c_statics.scan import ( iter_statics, statics_from_symbols, statics_from_declarations ) - from c_symbols import binary as b_symbols, source as s_symbols + from c_symbols import ( + info as s_info, + binary as b_symbols, + source as s_symbols, + ) class _Base(unittest.TestCase): @@ -32,16 +36,16 @@ def iter_symbols(self, dirnames): def test_typical(self): self._return_iter_symbols = [ - info.Symbol(('dir1/spam.c', None, 'var1'), 'variable', False), - info.Symbol(('dir1/spam.c', None, 'var2'), 'variable', False), - info.Symbol(('dir1/spam.c', None, 'func1'), 'function', False), - info.Symbol(('dir1/spam.c', None, 'func2'), 'function', True), - info.Symbol(('dir1/spam.c', None, 'var3'), 'variable', False), - info.Symbol(('dir1/spam.c', 'func2', 'var4'), 'variable', False), - info.Symbol(('dir1/ham.c', None, 'var1'), 'variable', True), - info.Symbol(('dir1/eggs.c', None, 'var1'), 'variable', False), - info.Symbol(('dir1/eggs.c', None, 'xyz'), 'other', False), - info.Symbol((None, None, '???'), 'other', False), + s_info.Symbol(('dir1/spam.c', None, 'var1'), 'variable', False), + s_info.Symbol(('dir1/spam.c', None, 'var2'), 'variable', False), + s_info.Symbol(('dir1/spam.c', None, 'func1'), 'function', False), + s_info.Symbol(('dir1/spam.c', None, 'func2'), 'function', True), + s_info.Symbol(('dir1/spam.c', None, 'var3'), 'variable', False), + s_info.Symbol(('dir1/spam.c', 'func2', 'var4'), 'variable', False), + s_info.Symbol(('dir1/ham.c', None, 'var1'), 'variable', True), + s_info.Symbol(('dir1/eggs.c', None, 'var1'), 'variable', False), + s_info.Symbol(('dir1/eggs.c', None, 'xyz'), 'other', False), + s_info.Symbol((None, None, '???'), 'other', False), ] found = list(statics_from_symbols(['dir1'], self.iter_symbols)) diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_symbols/__init__.py b/Lib/test/test_tools/test_c_analyzer/test_c_symbols/__init__.py new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_symbols/test_info.py b/Lib/test/test_tools/test_c_analyzer/test_c_symbols/test_info.py new file mode 100644 index 00000000000000..e029dcf66124dc --- /dev/null +++ b/Lib/test/test_tools/test_c_analyzer/test_c_symbols/test_info.py @@ -0,0 +1,192 @@ +import string +import unittest + +from ..util import PseudoStr, StrProxy, Object +from .. import tool_imports_for_tests +with tool_imports_for_tests(): + from c_analyzer_common.info import ID + from c_symbols.info import Symbol + + +class SymbolTests(unittest.TestCase): + + VALID_ARGS = ( + ID('x/y/z/spam.c', 'func', 'eggs'), + Symbol.KIND.VARIABLE, + False, + ) + VALID_KWARGS = dict(zip(Symbol._fields, VALID_ARGS)) + VALID_EXPECTED = VALID_ARGS + + def test_init_typical_binary_local(self): + id = ID(None, None, 'spam') + symbol = Symbol( + id=id, + kind=Symbol.KIND.VARIABLE, + external=False, + ) + + self.assertEqual(symbol, ( + id, + Symbol.KIND.VARIABLE, + False, + )) + + def test_init_typical_binary_global(self): + id = ID('Python/ceval.c', None, 'spam') + symbol = Symbol( + id=id, + kind=Symbol.KIND.VARIABLE, + external=False, + ) + + self.assertEqual(symbol, ( + id, + Symbol.KIND.VARIABLE, + False, + )) + + def test_init_coercion(self): + tests = [ + ('str subclass', + dict( + id=PseudoStr('eggs'), + kind=PseudoStr('variable'), + external=0, + ), + (ID(None, None, 'eggs'), + Symbol.KIND.VARIABLE, + False, + )), + ('with filename', + dict( + id=('x/y/z/spam.c', 'eggs'), + kind=PseudoStr('variable'), + external=0, + ), + (ID('x/y/z/spam.c', None, 'eggs'), + Symbol.KIND.VARIABLE, + False, + )), + ('non-str 1', + dict( + id=('a', 'b', 'c'), + kind=StrProxy('variable'), + external=0, + ), + (ID('a', 'b', 'c'), + Symbol.KIND.VARIABLE, + False, + )), + ('non-str 2', + dict( + id=('a', 'b', 'c'), + kind=Object(), + external=0, + ), + (ID('a', 'b', 'c'), + '', + False, + )), + ] + for summary, kwargs, expected in tests: + with self.subTest(summary): + symbol = Symbol(**kwargs) + + for field in Symbol._fields: + value = getattr(symbol, field) + if field == 'external': + self.assertIs(type(value), bool) + elif field == 'id': + self.assertIs(type(value), ID) + else: + self.assertIs(type(value), str) + self.assertEqual(tuple(symbol), expected) + + def test_init_all_missing(self): + id = ID(None, None, 'spam') + + symbol = Symbol(id) + + self.assertEqual(symbol, ( + id, + Symbol.KIND.VARIABLE, + None, + )) + + def test_fields(self): + id = ID('z', 'x', 'a') + + symbol = Symbol(id, 'b', False) + + self.assertEqual(symbol.id, id) + self.assertEqual(symbol.kind, 'b') + self.assertIs(symbol.external, False) + + def test___getattr__(self): + id = ID('z', 'x', 'a') + symbol = Symbol(id, 'b', False) + + filename = symbol.filename + funcname = symbol.funcname + name = symbol.name + + self.assertEqual(filename, 'z') + self.assertEqual(funcname, 'x') + self.assertEqual(name, 'a') + + def test_validate_typical(self): + id = ID('z', 'x', 'a') + + symbol = Symbol( + id=id, + kind=Symbol.KIND.VARIABLE, + external=False, + ) + + symbol.validate() # This does not fail. + + def test_validate_missing_field(self): + for field in Symbol._fields: + with self.subTest(field): + symbol = Symbol(**self.VALID_KWARGS) + symbol = symbol._replace(**{field: None}) + + with self.assertRaises(TypeError): + symbol.validate() + + def test_validate_bad_field(self): + badch = tuple(c for c in string.punctuation + string.digits) + notnames = ( + '1a', + 'a.b', + 'a-b', + '&a', + 'a++', + ) + badch + tests = [ + ('id', notnames), + ('kind', ('bogus',)), + ] + seen = set() + for field, invalid in tests: + for value in invalid: + if field != 'kind': + seen.add(value) + with self.subTest(f'{field}={value!r}'): + symbol = Symbol(**self.VALID_KWARGS) + symbol = symbol._replace(**{field: value}) + + with self.assertRaises(ValueError): + symbol.validate() + + for field, invalid in tests: + if field == 'kind': + continue + valid = seen - set(invalid) + for value in valid: + with self.subTest(f'{field}={value!r}'): + symbol = Symbol(**self.VALID_KWARGS) + symbol = symbol._replace(**{field: value}) + + symbol.validate() # This does not fail. diff --git a/Tools/c-analyzer/c_parser/info.py b/Tools/c-analyzer/c_parser/info.py index cb221b15cc3e8d..d9d9d56e0f61e8 100644 --- a/Tools/c-analyzer/c_parser/info.py +++ b/Tools/c-analyzer/c_parser/info.py @@ -1,6 +1,6 @@ from collections import namedtuple -from c_analyzer_common.info import UNKNOWN, NAME_RE, ID +from c_analyzer_common.info import ID from c_analyzer_common.util import classonly, _NTBase @@ -15,50 +15,6 @@ def normalize_vartype(vartype): return str(vartype) -class Symbol(_NTBase, namedtuple('Symbol', 'id kind external')): - """Info for a single compilation symbol.""" - - __slots__ = () - - class KIND: - VARIABLE = 'variable' - FUNCTION = 'function' - OTHER = 'other' - - @classonly - def from_name(cls, name, filename=None, kind=KIND.VARIABLE, external=None): - """Return a new symbol based on the given name.""" - id = ID(filename, None, name) - return cls(id, kind, external) - - def __new__(cls, id, kind=KIND.VARIABLE, external=None): - self = super().__new__( - cls, - id=ID.from_raw(id), - kind=str(kind) if kind else None, - external=bool(external) if external is not None else None, - ) - return self - - def __getattr__(self, name): - return getattr(self.id, name) - - def validate(self): - """Fail if the object is invalid (i.e. init with bad data).""" - if not self.id: - raise TypeError('missing id') - else: - self.id.validate() - - if not self.kind: - raise TypeError('missing kind') - elif self.kind not in vars(Symbol.KIND).values(): - raise ValueError(f'unsupported kind {self.kind}') - - if self.external is None: - raise TypeError('missing external') - - class Variable(_NTBase, namedtuple('Variable', 'id vartype')): """Information about a single variable declaration.""" diff --git a/Tools/c-analyzer/c_statics/scan.py b/Tools/c-analyzer/c_statics/scan.py index dc01fa8f49b8ad..c70ad5e7ba9e3b 100644 --- a/Tools/c-analyzer/c_statics/scan.py +++ b/Tools/c-analyzer/c_statics/scan.py @@ -1,5 +1,9 @@ from c_parser import info, declarations -from c_symbols import binary as b_symbols, source as s_symbols +from c_symbols import ( + info as s_info, + binary as b_symbols, + source as s_symbols, + ) # Once we start parsing directly, getting symbols from a binary will @@ -8,7 +12,7 @@ def statics_from_symbols(dirnames, iter_symbols): """Yield a Variable for each found symbol (static only).""" for symbol in iter_symbols(dirnames): - if symbol.kind is not info.Symbol.KIND.VARIABLE: + if symbol.kind is not s_info.Symbol.KIND.VARIABLE: continue if symbol.external: continue diff --git a/Tools/c-analyzer/c_symbols/binary.py b/Tools/c-analyzer/c_symbols/binary.py index 5b110930129991..40c98d4498147f 100644 --- a/Tools/c-analyzer/c_symbols/binary.py +++ b/Tools/c-analyzer/c_symbols/binary.py @@ -2,9 +2,9 @@ import shutil import sys -from c_analyzer_common import util -from c_parser import info +from c_analyzer_common import util, info from . import source +from .info import Symbol #PYTHON = os.path.join(REPO_ROOT, 'python') @@ -61,11 +61,11 @@ def _is_special_symbol(name): # "nm" NM_KINDS = { - 'b': info.Symbol.KIND.VARIABLE, # uninitialized - 'd': info.Symbol.KIND.VARIABLE, # initialized - #'g': info.Symbol.KIND.VARIABLE, # uninitialized - #'s': info.Symbol.KIND.VARIABLE, # initialized - 't': info.Symbol.KIND.FUNCTION, + 'b': Symbol.KIND.VARIABLE, # uninitialized + 'd': Symbol.KIND.VARIABLE, # initialized + #'g': Symbol.KIND.VARIABLE, # uninitialized + #'s': Symbol.KIND.VARIABLE, # initialized + 't': Symbol.KIND.FUNCTION, } @@ -91,12 +91,12 @@ def _iter_symbols_nm(binary, find_local_symbol=None, ) = _parse_nm_line(line, _find_local_symbol=find_local_symbol, ) - if kind != info.Symbol.KIND.VARIABLE: + if kind != Symbol.KIND.VARIABLE: continue elif _is_special_symbol(name): continue assert vartype is None - yield info.Symbol( + yield Symbol( id=(filename, funcname, name), kind=kind, external=external, @@ -111,7 +111,7 @@ def _parse_nm_line(line, *, _find_local_symbol=None): kind, _, line = line.partition(' ') line = line.strip() external = kind.isupper() - kind = NM_KINDS.get(kind.lower(), info.Symbol.KIND.OTHER) + kind = NM_KINDS.get(kind.lower(), Symbol.KIND.OTHER) name, _, filename = line.partition('\t') name = name.strip() @@ -135,7 +135,7 @@ def _parse_nm_line(line, *, _find_local_symbol=None): def _parse_nm_name(name, kind): - if kind != info.Symbol.KIND.VARIABLE: + if kind != Symbol.KIND.VARIABLE: return name, None if _is_special_symbol(name): return name, None diff --git a/Tools/c-analyzer/c_symbols/info.py b/Tools/c-analyzer/c_symbols/info.py new file mode 100644 index 00000000000000..fc4d40c17034a5 --- /dev/null +++ b/Tools/c-analyzer/c_symbols/info.py @@ -0,0 +1,48 @@ +from collections import namedtuple + +from c_analyzer_common.info import ID +from c_analyzer_common.util import classonly, _NTBase + + +class Symbol(_NTBase, namedtuple('Symbol', 'id kind external')): + """Info for a single compilation symbol.""" + + __slots__ = () + + class KIND: + VARIABLE = 'variable' + FUNCTION = 'function' + OTHER = 'other' + + @classonly + def from_name(cls, name, filename=None, kind=KIND.VARIABLE, external=None): + """Return a new symbol based on the given name.""" + id = ID(filename, None, name) + return cls(id, kind, external) + + def __new__(cls, id, kind=KIND.VARIABLE, external=None): + self = super().__new__( + cls, + id=ID.from_raw(id), + kind=str(kind) if kind else None, + external=bool(external) if external is not None else None, + ) + return self + + def __getattr__(self, name): + return getattr(self.id, name) + + def validate(self): + """Fail if the object is invalid (i.e. init with bad data).""" + if not self.id: + raise TypeError('missing id') + else: + self.id.validate() + + if not self.kind: + raise TypeError('missing kind') + elif self.kind not in vars(self.KIND).values(): + raise ValueError(f'unsupported kind {self.kind}') + + if self.external is None: + raise TypeError('missing external') From d7d0d91ee62b40af2b7f604d167d1bf8399ee2a9 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sat, 24 Aug 2019 13:12:26 -0600 Subject: [PATCH 062/118] Do not allow Variable.id to have UNKNOWN in it. --- Tools/c-analyzer/c_parser/info.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/Tools/c-analyzer/c_parser/info.py b/Tools/c-analyzer/c_parser/info.py index d9d9d56e0f61e8..80c99b4cf865af 100644 --- a/Tools/c-analyzer/c_parser/info.py +++ b/Tools/c-analyzer/c_parser/info.py @@ -1,6 +1,6 @@ from collections import namedtuple -from c_analyzer_common.info import ID +from c_analyzer_common import info from c_analyzer_common.util import classonly, _NTBase @@ -23,13 +23,13 @@ class Variable(_NTBase, @classonly def from_parts(cls, filename, funcname, name, vartype): - id = ID(filename, funcname, name) + id = info.ID(filename, funcname, name) return cls(id, vartype) def __new__(cls, id, vartype): self = super().__new__( cls, - id=ID.from_raw(id), + id=info.ID.from_raw(id), vartype=normalize_vartype(vartype) if vartype else None, ) return self @@ -37,17 +37,23 @@ def __new__(cls, id, vartype): def __getattr__(self, name): return getattr(self.id, name) - def validate(self): - """Fail if the object is invalid (i.e. init with bad data).""" + def _validate_id(self): if not self.id: raise TypeError('missing id') - else: - self.id.validate() - if not self.filename: + if not self.filename or self.filename == info.UNKNOWN: raise TypeError('id missing filename') - if self.vartype is None: + if self.funcname and self.funcname == info.UNKNOWN: + raise TypeError('id missing funcname') + + self.id.validate() + + def validate(self): + """Fail if the object is invalid (i.e. init with bad data).""" + self._validate_id() + + if self.vartype is None or self.vartype == info.UNKNOWN: raise TypeError('missing vartype') @property From f662b63055186c7feb50cf06e0c59adcee61820a Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sat, 24 Aug 2019 13:29:28 -0600 Subject: [PATCH 063/118] Cache Variable.isstatic. --- Tools/c-analyzer/c_parser/info.py | 16 ++++++++++++---- Tools/c-analyzer/c_statics/scan.py | 1 + 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Tools/c-analyzer/c_parser/info.py b/Tools/c-analyzer/c_parser/info.py index 80c99b4cf865af..0d9e38902f200c 100644 --- a/Tools/c-analyzer/c_parser/info.py +++ b/Tools/c-analyzer/c_parser/info.py @@ -1,6 +1,6 @@ from collections import namedtuple -from c_analyzer_common import info +from c_analyzer_common import info, util from c_analyzer_common.util import classonly, _NTBase @@ -20,11 +20,15 @@ class Variable(_NTBase, """Information about a single variable declaration.""" __slots__ = () + _isstatic = util.Slot() @classonly - def from_parts(cls, filename, funcname, name, vartype): + def from_parts(cls, filename, funcname, name, vartype, isstatic=False): id = info.ID(filename, funcname, name) - return cls(id, vartype) + self = cls(id, vartype) + if isstatic: + self._isstatic = True + return self def __new__(cls, id, vartype): self = super().__new__( @@ -58,7 +62,11 @@ def validate(self): @property def isstatic(self): - return 'static' in self.vartype.split() + try: + return self._isstatic + except AttributeError: + self._isstatic = ('static' in self.vartype.split()) + return self._isstatic @property def isconst(self): diff --git a/Tools/c-analyzer/c_statics/scan.py b/Tools/c-analyzer/c_statics/scan.py index c70ad5e7ba9e3b..f7b6b10b4def6c 100644 --- a/Tools/c-analyzer/c_statics/scan.py +++ b/Tools/c-analyzer/c_statics/scan.py @@ -21,6 +21,7 @@ def statics_from_symbols(dirnames, iter_symbols): funcname=symbol.funcname or None, name=symbol.name, vartype='???', + isstatic=True, ) From e9631031c55416dbfa6fc4561c2d8da0aeb8d58b Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 26 Aug 2019 10:44:47 -0600 Subject: [PATCH 064/118] Move known_from_file() to common/known.py. --- Tools/c-analyzer/c_analyzer_common/known.py | 17 +++++++++++++++++ Tools/c-analyzer/c_statics/find.py | 3 ++- Tools/c-analyzer/c_statics/supported.py | 8 -------- 3 files changed, 19 insertions(+), 9 deletions(-) create mode 100644 Tools/c-analyzer/c_analyzer_common/known.py diff --git a/Tools/c-analyzer/c_analyzer_common/known.py b/Tools/c-analyzer/c_analyzer_common/known.py new file mode 100644 index 00000000000000..712d6c4ded4006 --- /dev/null +++ b/Tools/c-analyzer/c_analyzer_common/known.py @@ -0,0 +1,17 @@ +from c_parser.info import Variable + +from . import info, util + + +# XXX need tests: +# * known_from_file() + +def known_from_file(infile, fmt=None): + """Yield StaticVar for each ignored var in the file.""" + raise NotImplementedError + return { + 'variables': {}, + 'types': {}, + #'constants': {}, + #'macros': {}, + } diff --git a/Tools/c-analyzer/c_statics/find.py b/Tools/c-analyzer/c_statics/find.py index f5dd75d58422d6..ad4eb3d01925fd 100644 --- a/Tools/c-analyzer/c_statics/find.py +++ b/Tools/c-analyzer/c_statics/find.py @@ -1,5 +1,6 @@ +from c_analyzer_common.known import known_from_file from . import scan -from .supported import is_supported, ignored_from_file, known_from_file +from .supported import is_supported, ignored_from_file def statics(dirnames, ignored, known, *, diff --git a/Tools/c-analyzer/c_statics/supported.py b/Tools/c-analyzer/c_statics/supported.py index c8aca97d1916ed..04e1cd5521e7cd 100644 --- a/Tools/c-analyzer/c_statics/supported.py +++ b/Tools/c-analyzer/c_statics/supported.py @@ -20,11 +20,3 @@ def is_supported(static, ignored=None, known=None): def ignored_from_file(infile, fmt=None): """Yield StaticVar for each ignored var in the file.""" raise NotImplementedError - - -############################# -# known - -def known_from_file(infile, fmt=None): - """Yield StaticVar for each ignored var in the file.""" - raise NotImplementedError From 2cf6d6a866374e4ebc715804bf9a1cac76130c77 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 26 Aug 2019 10:56:00 -0600 Subject: [PATCH 065/118] Add look_up_known_symbol() and symbols_to_variables(). --- Tools/c-analyzer/c_symbols/resolve.py | 134 ++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 Tools/c-analyzer/c_symbols/resolve.py diff --git a/Tools/c-analyzer/c_symbols/resolve.py b/Tools/c-analyzer/c_symbols/resolve.py new file mode 100644 index 00000000000000..50d503403e77f7 --- /dev/null +++ b/Tools/c-analyzer/c_symbols/resolve.py @@ -0,0 +1,134 @@ +from c_analyzer_common.info import UNKNOWN +from c_parser import files, declarations, info +from .info import Symbol +from .source import _find_symbol + + +# XXX need tests: +# * look_up_known_symbol() +# * symbol_from_source() +# * get_resolver() +# * symbols_to_variables() + +def look_up_known_symbol(symbol, knownvars, *, + match_files=(lambda f1, f2: f1 == f2), + ): + """Return the known variable matching the given symbol. + + "knownvars" is a mapping of common.ID to parser.Variable. + + "match_files" is used to verify if two filenames point to + the same file. + """ + if not knownvars: + return None + + if symbol.funcname == UNKNOWN: + if not symbol.filename or symbol.filename == UNKNOWN: + for varid in knownvars: + if not varid.funcname: + continue + if varid.name == symbol.name: + return knownvars[varid] + else: + for varid in knownvars: + if not varid.funcname: + continue + if not match_files(varid.filename, symbol.filename): + continue + if varid.name == symbol.name: + return knownvars[varid] + elif not symbol.filename or symbol.filename == UNKNOWN: + raise NotImplementedError + else: + return knownvars.get(symbol.id) + + +def find_in_source(symbol, dirnames, *, + _perfilecache={}, + _find_symbol=_find_symbol, + ): + """Return the Variable matching the given Symbol. + + If there is no match then return None. + """ + if symbol.filename and symbol.filename != UNKONWN: + filenames = [symbol.filename] + else: + filenames = _iter_files(dirnames, ('.c', '.h')) + + if symbol.funcname and symbol.funcname != UNKNOWN: + raise NotImplementedError + + (filename, funcname, vartype + ) = _find_symbol(symbol.name, filenames, _perfilecache) + if filename == UNKNOWN: + return None + return info.Variable( + id=(filename, funcname, symbol.name), + vartype=vartype, + ) + + +def get_resolver(knownvars=None, dirnames=None, *, + _look_up_known=look_up_known_symbol, + _from_source=find_in_source, + ): + """Return a "resolver" func for the given known vars and dirnames. + + The func takes a single Symbol and returns a corresponding Variable. + If the symbol was located then the variable will be valid, populated + with the corresponding information. Otherwise None is returned. + """ + if knownvars: + known = dict((known or {}).get('variables', ())) # a copy + def resolve_known(symbol): + found = _look_up_known(symbol, known) + if found is None: + return None + elif symbol.funcname == UNKNOWN: + known.pop(var.id) + elif not symbol.filename or symbol.filename == UNKNOWN: + known.pop(var.id) + return found + if dirnames: + def resolve(symbol): + found = resolve_known(symbol) + if found is None: + return _from_source(symbol, dirnames) + else: + return found + else: + resolve = resolve_known + elif dirnames: + def resolve(symbol): + return _from_source(symbol, dirnames) + else: + def resolve(symbol): + return None + return resolve + + +def symbols_to_variables(symbols, *, + resolve=(lambda s: look_up_known_symbol(s, None)), + ): + """Yield the variable the matches each given symbol. + + Use get_resolver() for a "resolve" func to use. + """ + for symbol in symbols: + if isinstance(symbol, info.Variable): + # XXX validate? + yield symbol + continue + if symbol.kind is not Symbol.KIND.VARIABLE: + continue + resolved = resolve(symbol) + if resolved is None: + raise NotImplementedError + #yield Variable( + # id=symbol.ID, + # vartype=info.UNKNOWN, + # ) + #continue + yield resolved From 3d8034262f141bc160695013f92a022c7206f824 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 26 Aug 2019 11:04:03 -0600 Subject: [PATCH 066/118] Move files.py under common. --- .../test_files.py | 2 +- .../{c_parser => c_analyzer_common}/files.py | 0 Tools/c-analyzer/c_symbols/resolve.py | 3 +- Tools/c-analyzer/c_symbols/source.py | 55 ++++++++++++------- 4 files changed, 37 insertions(+), 23 deletions(-) rename Lib/test/test_tools/test_c_analyzer/{test_c_parser => test_c_analyzer_common}/test_files.py (99%) rename Tools/c-analyzer/{c_parser => c_analyzer_common}/files.py (100%) diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_files.py b/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/test_files.py similarity index 99% rename from Lib/test/test_tools/test_c_analyzer/test_c_parser/test_files.py rename to Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/test_files.py index ee416cdda8c1a8..0ab5a7bd4966c9 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_files.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/test_files.py @@ -3,7 +3,7 @@ from .. import tool_imports_for_tests with tool_imports_for_tests(): - from c_parser.files import iter_files + from c_analyzer_common.files import iter_files def fixpath(filename): diff --git a/Tools/c-analyzer/c_parser/files.py b/Tools/c-analyzer/c_analyzer_common/files.py similarity index 100% rename from Tools/c-analyzer/c_parser/files.py rename to Tools/c-analyzer/c_analyzer_common/files.py diff --git a/Tools/c-analyzer/c_symbols/resolve.py b/Tools/c-analyzer/c_symbols/resolve.py index 50d503403e77f7..1809f24264331c 100644 --- a/Tools/c-analyzer/c_symbols/resolve.py +++ b/Tools/c-analyzer/c_symbols/resolve.py @@ -1,5 +1,6 @@ +from c_analyzer_common import files from c_analyzer_common.info import UNKNOWN -from c_parser import files, declarations, info +from c_parser import declarations, info from .info import Symbol from .source import _find_symbol diff --git a/Tools/c-analyzer/c_symbols/source.py b/Tools/c-analyzer/c_symbols/source.py index 9d9f5b0e977b56..c17d0a7b00a712 100644 --- a/Tools/c-analyzer/c_symbols/source.py +++ b/Tools/c-analyzer/c_symbols/source.py @@ -1,32 +1,24 @@ -from c_parser import files, declarations +from c_analyzer_common import files +from c_analyzer_common.info import UNKNOWN +from c_parser import declarations +# XXX need tests: +# * find_symbol() + def find_symbol(name, dirnames, *, _perfilecache, - _get_local_symbols=(lambda *a, **k: _get_symbols(*a, **k)), _iter_files=files.iter_files, + **kwargs ): """Return (filename, funcname, vartype) for the matching Symbol.""" - for filename in _iter_files(dirnames, ('.c', '.h')): - try: - symbols = _perfilecache[filename] - except KeyError: - symbols = _perfilecache[filename] = _get_local_symbols(filename) - - try: - instances = symbols[name] - except KeyError: - continue - - funcname, vartype = instances.pop(0) - if not instances: - symbols.pop(name) - return filename, funcname, vartype + filenames = _iter_files(dirnames, ('.c', '.h')) + return _find_symbol(name, filenames, _perfilecache, **kwargs) def _get_symbols(filename, *, - _iter_variables=declarations.iter_variables, - ): + _iter_variables=declarations.iter_variables, + ): """Return the list of Symbols found in the given file.""" symbols = {} for funcname, name, vartype in _iter_variables(filename): @@ -40,6 +32,27 @@ def _get_symbols(filename, *, return symbols -def iter_symbols(dirnames): - """Yield a Symbol for each symbol found in files under the directories.""" +def _find_symbol(name, filenames, _perfilecache, *, + _get_local_symbols=_get_symbols, + ): + for filename in filenames: + try: + symbols = _perfilecache[filename] + except KeyError: + symbols = _perfilecache[filename] = _get_local_symbols(filename) + + try: + instances = symbols[name] + except KeyError: + continue + + funcname, vartype = instances.pop(0) + if not instances: + symbols.pop(name) + return filename, funcname, vartype + else: + return UNKONWN, UNKNOWN, UNKNOWN + + +def iter_symbols(): raise NotImplementedError From d58c7c49a9ee11026c54e649038bfd2a469d793b Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 26 Aug 2019 13:42:01 -0600 Subject: [PATCH 067/118] known_from_file() -> known.from_file(). --- Tools/c-analyzer/c_analyzer_common/known.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tools/c-analyzer/c_analyzer_common/known.py b/Tools/c-analyzer/c_analyzer_common/known.py index 712d6c4ded4006..ee82c34a98d77e 100644 --- a/Tools/c-analyzer/c_analyzer_common/known.py +++ b/Tools/c-analyzer/c_analyzer_common/known.py @@ -4,9 +4,9 @@ # XXX need tests: -# * known_from_file() +# * from_file() -def known_from_file(infile, fmt=None): +def from_file(infile, fmt=None): """Yield StaticVar for each ignored var in the file.""" raise NotImplementedError return { From 2fca1e7a069c72ab8cb82816ded7e60d358374e9 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 26 Aug 2019 13:43:45 -0600 Subject: [PATCH 068/118] Make dirnames optional. --- Tools/c-analyzer/c_symbols/binary.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tools/c-analyzer/c_symbols/binary.py b/Tools/c-analyzer/c_symbols/binary.py index 40c98d4498147f..10aad348e144ba 100644 --- a/Tools/c-analyzer/c_symbols/binary.py +++ b/Tools/c-analyzer/c_symbols/binary.py @@ -11,7 +11,7 @@ PYTHON = sys.executable -def iter_symbols(dirnames, binary=PYTHON, *, +def iter_symbols(binary=PYTHON, dirnames=None, *, # Alternately, use look_up_known_symbol() # from c_statics.supported. find_local_symbol=source.find_symbol, From 1e34a1a2fbafcd675297fce8d1db9d4886139359 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 26 Aug 2019 14:09:40 -0600 Subject: [PATCH 069/118] Drop c_statics.scan. --- .../test_c_statics/test___main__.py | 12 +- .../test_c_statics/test_find.py | 391 ++++++++++++++---- .../test_c_statics/test_scan.py | 239 ----------- Tools/c-analyzer/c_statics/__main__.py | 21 +- Tools/c-analyzer/c_statics/find.py | 103 ++++- Tools/c-analyzer/c_statics/scan.py | 54 --- 6 files changed, 411 insertions(+), 409 deletions(-) delete mode 100644 Lib/test/test_tools/test_c_analyzer/test_c_statics/test_scan.py delete mode 100644 Tools/c-analyzer/c_statics/scan.py diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test___main__.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test___main__.py index 56886b6f8a5c5b..98823af493458c 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test___main__.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test___main__.py @@ -78,8 +78,8 @@ def test_defaults(self): self.assertEqual(self.calls[0], ( '_find', ( cg.SOURCE_DIRS, - cg.IGNORED_FILE, cg.KNOWN_FILE, + cg.IGNORED_FILE, ), )) @@ -97,7 +97,7 @@ def test_all_supported(self): ) self.assertEqual(self.calls, [ - ('_find', (dirs, 'ignored.tsv', 'known.tsv')), + ('_find', (dirs, 'known.tsv', 'ignored.tsv')), #('_print', ('okay',)), ]) @@ -117,7 +117,7 @@ def test_some_unsupported(self): unsupported = [v for v, s in TYPICAL if not s] self.assertEqual(self.calls, [ - ('_find', (dirs, 'ignored.tsv', 'known.tsv')), + ('_find', (dirs, 'known.tsv', 'ignored.tsv')), ('_print', ('ERROR: found unsupported static variables',)), ('_print', ()), ('_show', (sorted(unsupported),)), @@ -139,8 +139,8 @@ def test_defaults(self): self.assertEqual(self.calls[0], ( '_find', ( cg.SOURCE_DIRS, - cg.IGNORED_FILE, cg.KNOWN_FILE, + cg.IGNORED_FILE, ), )) @@ -150,8 +150,8 @@ def test_typical(self): cmd_show('show', dirs, - ignored='ignored.tsv', known='known.tsv', + ignored='ignored.tsv', _find=self._find, _show=self._show, _print=self._print, @@ -160,7 +160,7 @@ def test_typical(self): supported = [v for v, s in TYPICAL if s] unsupported = [v for v, s in TYPICAL if not s] self.assertEqual(self.calls, [ - ('_find', (dirs, 'ignored.tsv', 'known.tsv')), + ('_find', (dirs, 'known.tsv', 'ignored.tsv')), ('_print', ('supported:',)), ('_print', ('----------',)), ('_show', (sorted(supported),)), diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py index 3e2acdfcaa451b..c22f334985e6ea 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py @@ -3,18 +3,13 @@ from .. import tool_imports_for_tests with tool_imports_for_tests(): from c_parser import info - from c_statics.find import statics + from c_statics.find import statics_from_binary, statics class _Base(unittest.TestCase): maxDiff = None - _return_iter_statics = None - _return_is_supported = None - _return_load_ignored = None - _return_load_known = None - @property def calls(self): try: @@ -23,93 +18,315 @@ def calls(self): self._calls = [] return self._calls - def _add_static(self, static, funcs): - if not funcs: - funcs = ['iter_statics'] - elif 'is_supported' in funcs and 'iter_statics' not in funcs: - funcs.append('iter_statics') - - for func in funcs: - func = f'_return_{func}' - results = getattr(self, func) - if results is None: - results = [] - setattr(self, func, results) - results.append(static) - - def add_static(self, filename, funcname, name, vartype, *, - supported=True, - ignored=False, - known=False, - ): - static = info.Variable.from_parts(filename, funcname, name, vartype) - funcs = [] - if supported is not None: - funcs.append('iter_statics') - if supported: - funcs.append('is_supported') - if ignored: - funcs.append('load_ingored') - if known: - funcs.append('load_known') - self._add_static(static, funcs) - return static, supported - - def _iter_statics(self, dirnames, kind=None): - self.calls.append(('_iter_statics', (dirnames, kind))) - return iter(self._return_iter_statics or ()) - - def _is_supported(self, static, ignored=None, known=None): - self.calls.append(('_is_supported', (static, ignored, known))) - return static in (self._return_is_supported or ()) - - def _load_ignored(self, filename): - self.calls.append(('_load_ignored', (filename,))) - return iter(self._return_load_ignored or ()) - - def _load_known(self, filename): - self.calls.append(('_load_known', (filename,))) - return iter(self._return_load_known or ()) +class StaticsFromBinaryTests(_Base): -class StaticsTest(_Base): + _return_iter_symbols = () + _return_resolve_symbols = () + _return_get_symbol_resolver = None + + def setUp(self): + super().setUp() + + self.kwargs = dict( + _iter_symbols=self._iter_symbols, + _resolve=self._resolve_symbols, + _get_symbol_resolver=self._get_symbol_resolver, + ) + + def _iter_symbols(self, binfile, find_local_symbol): + self.calls.append(('_iter_symbols', (binfile, find_local_symbol))) + return self._return_iter_symbols + + def _resolve_symbols(self, symbols, resolve): + self.calls.append(('_resolve_symbols', (symbols, resolve,))) + return self._return_resolve_symbols + + def _get_symbol_resolver(self, knownvars): + self.calls.append(('_get_symbol_resolver', (knownvars,))) + return self._return_get_symbol_resolver def test_typical(self): - self._return_load_ignored = () - self._return_load_known = () - expected = [ - self.add_static('src1/spam.c', None, 'var1', 'const char *'), - self.add_static('src1/spam.c', 'ham', 'initialized', 'int'), - self.add_static('src1/spam.c', None, 'var2', 'PyObject *', supported=False), - self.add_static('src1/eggs.c', 'tofu', 'ready', 'int', supported=False), - self.add_static('src1/spam.c', None, 'freelist', '(PyTupleObject *)[10]', supported=False), - self.add_static('src1/sub/ham.c', None, 'var1', 'const char const *'), - self.add_static('src2/jam.c', None, 'var1', 'int'), - self.add_static('src2/jam.c', None, 'var2', 'MyObject *', supported=False), - self.add_static('Include/spam.h', None, 'data', 'const int'), + symbols = self._return_iter_symbols = () + resolver = self._return_get_symbol_resolver = object() + variables = self._return_resolve_symbols = [ + info.Variable.from_parts('dir1/spam.c', None, 'var1', 'int'), + info.Variable.from_parts('dir1/spam.c', None, 'var2', 'static int'), + info.Variable.from_parts('dir1/spam.c', None, 'var3', 'char *'), + info.Variable.from_parts('dir1/spam.c', 'func2', 'var4', 'const char *'), + info.Variable.from_parts('dir1/eggs.c', None, 'var1', 'static int'), + info.Variable.from_parts('dir1/eggs.c', 'func1', 'var2', 'static char *'), ] - dirs = ['src1', 'src2', 'Include'] - - found = statics( - dirs, - 'ignored.tsv', - 'known.tsv', - _iter_statics=self._iter_statics, - _is_supported=self._is_supported, - _load_ignored=self._load_ignored, - _load_known=self._load_known, - ) + knownvars = object() + + found = list(statics_from_binary('python', + knownvars=knownvars, + **self.kwargs)) - self.assertEqual(found, expected) + self.assertEqual(found, [ + info.Variable.from_parts('dir1/spam.c', None, 'var2', 'static int'), + info.Variable.from_parts('dir1/eggs.c', None, 'var1', 'static int'), + info.Variable.from_parts('dir1/eggs.c', 'func1', 'var2', 'static char *'), + ]) self.assertEqual(self.calls, [ - ('_load_ignored', ('ignored.tsv',)), - ('_load_known', ('known.tsv',)), - ('_iter_statics', (dirs, None)), - ] + [('_is_supported', (v, set(), set())) - for v, _ in expected]) + ('_iter_symbols', ('python', None)), + ('_get_symbol_resolver', (knownvars,)), + ('_resolve_symbols', (symbols, resolver)), + ]) + +# self._return_iter_symbols = [ +# s_info.Symbol(('dir1/spam.c', None, 'var1'), 'variable', False), +# s_info.Symbol(('dir1/spam.c', None, 'var2'), 'variable', False), +# s_info.Symbol(('dir1/spam.c', None, 'func1'), 'function', False), +# s_info.Symbol(('dir1/spam.c', None, 'func2'), 'function', True), +# s_info.Symbol(('dir1/spam.c', None, 'var3'), 'variable', False), +# s_info.Symbol(('dir1/spam.c', 'func2', 'var4'), 'variable', False), +# s_info.Symbol(('dir1/ham.c', None, 'var1'), 'variable', True), +# s_info.Symbol(('dir1/eggs.c', None, 'var1'), 'variable', False), +# s_info.Symbol(('dir1/eggs.c', None, 'xyz'), 'other', False), +# s_info.Symbol(('dir1/eggs.c', '???', 'var2'), 'variable', False), +# s_info.Symbol(('???', None, 'var_x'), 'variable', False), +# s_info.Symbol(('???', '???', 'var_y'), 'variable', False), +# s_info.Symbol((None, None, '???'), 'other', False), +# ] +# known = object() +# +# statics_from_binary('python', knownvars=known, **this.kwargs) +# found = list(statics_from_symbols(['dir1'], self.iter_symbols)) +# +# self.assertEqual(found, [ +# info.Variable.from_parts('dir1/spam.c', None, 'var1', '???'), +# info.Variable.from_parts('dir1/spam.c', None, 'var2', '???'), +# info.Variable.from_parts('dir1/spam.c', None, 'var3', '???'), +# info.Variable.from_parts('dir1/spam.c', 'func2', 'var4', '???'), +# info.Variable.from_parts('dir1/eggs.c', None, 'var1', '???'), +# ]) +# self.assertEqual(self.calls, [ +# ('iter_symbols', (['dir1'],)), +# ]) +# +# def test_no_symbols(self): +# self._return_iter_symbols = [] +# +# found = list(statics_from_symbols(['dir1'], self.iter_symbols)) +# +# self.assertEqual(found, []) +# self.assertEqual(self.calls, [ +# ('iter_symbols', (['dir1'],)), +# ]) + + # XXX need functional test + - def test_no_dirs(self): - found = statics([], '', '') +#class StaticFromDeclarationsTests(_Base): +# +# _return_iter_declarations = () +# +# def iter_declarations(self, dirnames): +# self.calls.append(('iter_declarations', (dirnames,))) +# return iter(self._return_iter_declarations) +# +# def test_typical(self): +# self._return_iter_declarations = [ +# None, +# info.Variable.from_parts('dir1/spam.c', None, 'var1', '???'), +# object(), +# info.Variable.from_parts('dir1/spam.c', None, 'var2', '???'), +# info.Variable.from_parts('dir1/spam.c', None, 'var3', '???'), +# object(), +# info.Variable.from_parts('dir1/spam.c', 'func2', 'var4', '???'), +# object(), +# info.Variable.from_parts('dir1/eggs.c', None, 'var1', '???'), +# object(), +# ] +# +# found = list(statics_from_declarations(['dir1'], self.iter_declarations)) +# +# self.assertEqual(found, [ +# info.Variable.from_parts('dir1/spam.c', None, 'var1', '???'), +# info.Variable.from_parts('dir1/spam.c', None, 'var2', '???'), +# info.Variable.from_parts('dir1/spam.c', None, 'var3', '???'), +# info.Variable.from_parts('dir1/spam.c', 'func2', 'var4', '???'), +# info.Variable.from_parts('dir1/eggs.c', None, 'var1', '???'), +# ]) +# self.assertEqual(self.calls, [ +# ('iter_declarations', (['dir1'],)), +# ]) +# +# def test_no_declarations(self): +# self._return_iter_declarations = [] +# +# found = list(statics_from_declarations(['dir1'], self.iter_declarations)) +# +# self.assertEqual(found, []) +# self.assertEqual(self.calls, [ +# ('iter_declarations', (['dir1'],)), +# ]) - self.assertEqual(found, []) - self.assertEqual(self.calls, []) + +#class IterVariablesTests(_Base): +# +# _return_from_symbols = () +# _return_from_declarations = () +# +# def _from_symbols(self, dirnames, iter_symbols): +# self.calls.append(('_from_symbols', (dirnames, iter_symbols))) +# return iter(self._return_from_symbols) +# +# def _from_declarations(self, dirnames, iter_declarations): +# self.calls.append(('_from_declarations', (dirnames, iter_declarations))) +# return iter(self._return_from_declarations) +# +# def test_typical(self): +# expected = [ +# info.Variable.from_parts('dir1/spam.c', None, 'var1', '???'), +# info.Variable.from_parts('dir1/spam.c', None, 'var2', '???'), +# info.Variable.from_parts('dir1/spam.c', None, 'var3', '???'), +# info.Variable.from_parts('dir1/spam.c', 'func2', 'var4', '???'), +# info.Variable.from_parts('dir1/eggs.c', None, 'var1', '???'), +# ] +# self._return_from_symbols = expected +# +# found = list(iter_variables(['dir1'], +# _from_symbols=self._from_symbols, +# _from_declarations=self._from_declarations)) +# +# self.assertEqual(found, expected) +# self.assertEqual(self.calls, [ +# ('_from_symbols', (['dir1'], b_symbols.iter_symbols)), +# ]) +# +# def test_no_symbols(self): +# self._return_from_symbols = [] +# +# found = list(iter_variables(['dir1'], +# _from_symbols=self._from_symbols, +# _from_declarations=self._from_declarations)) +# +# self.assertEqual(found, []) +# self.assertEqual(self.calls, [ +# ('_from_symbols', (['dir1'], b_symbols.iter_symbols)), +# ]) +# +# def test_from_binary(self): +# expected = [ +# info.Variable.from_parts('dir1/spam.c', None, 'var1', '???'), +# info.Variable.from_parts('dir1/spam.c', None, 'var2', '???'), +# info.Variable.from_parts('dir1/spam.c', None, 'var3', '???'), +# info.Variable.from_parts('dir1/spam.c', 'func2', 'var4', '???'), +# info.Variable.from_parts('dir1/eggs.c', None, 'var1', '???'), +# ] +# self._return_from_symbols = expected +# +# found = list(iter_variables(['dir1'], 'platform', +# _from_symbols=self._from_symbols, +# _from_declarations=self._from_declarations)) +# +# self.assertEqual(found, expected) +# self.assertEqual(self.calls, [ +# ('_from_symbols', (['dir1'], b_symbols.iter_symbols)), +# ]) +# +# def test_from_symbols(self): +# expected = [ +# info.Variable.from_parts('dir1/spam.c', None, 'var1', '???'), +# info.Variable.from_parts('dir1/spam.c', None, 'var2', '???'), +# info.Variable.from_parts('dir1/spam.c', None, 'var3', '???'), +# info.Variable.from_parts('dir1/spam.c', 'func2', 'var4', '???'), +# info.Variable.from_parts('dir1/eggs.c', None, 'var1', '???'), +# ] +# self._return_from_symbols = expected +# +# found = list(iter_variables(['dir1'], 'symbols', +# _from_symbols=self._from_symbols, +# _from_declarations=self._from_declarations)) +# +# self.assertEqual(found, expected) +# self.assertEqual(self.calls, [ +# ('_from_symbols', (['dir1'], s_symbols.iter_symbols)), +# ]) +# +# def test_from_declarations(self): +# expected = [ +# info.Variable.from_parts('dir1/spam.c', None, 'var1', '???'), +# info.Variable.from_parts('dir1/spam.c', None, 'var2', '???'), +# info.Variable.from_parts('dir1/spam.c', None, 'var3', '???'), +# info.Variable.from_parts('dir1/spam.c', 'func2', 'var4', '???'), +# info.Variable.from_parts('dir1/eggs.c', None, 'var1', '???'), +# ] +# self._return_from_declarations = expected +# +# found = list(iter_variables(['dir1'], 'declarations', +# _from_symbols=self._from_symbols, +# _from_declarations=self._from_declarations)) +# +# self.assertEqual(found, expected) +# self.assertEqual(self.calls, [ +# ('_from_declarations', (['dir1'], declarations.iter_all)), +# ]) +# +# def test_from_preprocessed(self): +# expected = [ +# info.Variable.from_parts('dir1/spam.c', None, 'var1', '???'), +# info.Variable.from_parts('dir1/spam.c', None, 'var2', '???'), +# info.Variable.from_parts('dir1/spam.c', None, 'var3', '???'), +# info.Variable.from_parts('dir1/spam.c', 'func2', 'var4', '???'), +# info.Variable.from_parts('dir1/eggs.c', None, 'var1', '???'), +# ] +# self._return_from_declarations = expected +# +# found = list(iter_variables(['dir1'], 'preprocessed', +# _from_symbols=self._from_symbols, +# _from_declarations=self._from_declarations)) +# +# self.assertEqual(found, expected) +# self.assertEqual(self.calls, [ +# ('_from_declarations', (['dir1'], declarations.iter_preprocessed)), +# ]) + + +class StaticsTest(_Base): + + _return_iter_variables = None + + def _iter_variables(self, kind, *, known, dirnames): + self.calls.append( + ('_iter_variables', (kind, known, dirnames))) + return iter(self._return_iter_variables or ()) + + def test_typical(self): + self._return_iter_variables = [ + info.Variable.from_parts('src1/spam.c', None, 'var1', 'static const char *'), + info.Variable.from_parts('src1/spam.c', None, 'var1b', 'const char *'), + info.Variable.from_parts('src1/spam.c', 'ham', 'initialized', 'static int'), + info.Variable.from_parts('src1/spam.c', 'ham', 'result', 'int'), + info.Variable.from_parts('src1/spam.c', None, 'var2', 'static PyObject *'), + info.Variable.from_parts('src1/eggs.c', 'tofu', 'ready', 'static int'), + info.Variable.from_parts('src1/spam.c', None, 'freelist', 'static (PyTupleObject *)[10]'), + info.Variable.from_parts('src1/sub/ham.c', None, 'var1', 'static const char const *'), + info.Variable.from_parts('src2/jam.c', None, 'var1', 'static int'), + info.Variable.from_parts('src2/jam.c', None, 'var2', 'static MyObject *'), + info.Variable.from_parts('Include/spam.h', None, 'data', 'static const int'), + ] + dirnames = object() + known = object() + + found = list(statics(dirnames, known, + kind='platform', + _iter_variables=self._iter_variables, + )) + + self.assertEqual(found, [ + info.Variable.from_parts('src1/spam.c', None, 'var1', 'static const char *'), + info.Variable.from_parts('src1/spam.c', 'ham', 'initialized', 'static int'), + info.Variable.from_parts('src1/spam.c', None, 'var2', 'static PyObject *'), + info.Variable.from_parts('src1/eggs.c', 'tofu', 'ready', 'static int'), + info.Variable.from_parts('src1/spam.c', None, 'freelist', 'static (PyTupleObject *)[10]'), + info.Variable.from_parts('src1/sub/ham.c', None, 'var1', 'static const char const *'), + info.Variable.from_parts('src2/jam.c', None, 'var1', 'static int'), + info.Variable.from_parts('src2/jam.c', None, 'var2', 'static MyObject *'), + info.Variable.from_parts('Include/spam.h', None, 'data', 'static const int'), + ]) + self.assertEqual(self.calls, [ + ('_iter_variables', ('platform', known, dirnames)), + ]) diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_scan.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_scan.py deleted file mode 100644 index baa67418ed9108..00000000000000 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_scan.py +++ /dev/null @@ -1,239 +0,0 @@ -import unittest - -from .. import tool_imports_for_tests -with tool_imports_for_tests(): - from c_parser import info, declarations - from c_statics.scan import ( - iter_statics, statics_from_symbols, statics_from_declarations - ) - from c_symbols import ( - info as s_info, - binary as b_symbols, - source as s_symbols, - ) - - -class _Base(unittest.TestCase): - - maxDiff = None - - @property - def calls(self): - try: - return self._calls - except AttributeError: - self._calls = [] - return self._calls - - -class StaticsFromSymbolsTests(_Base): - - _return_iter_symbols = () - - def iter_symbols(self, dirnames): - self.calls.append(('iter_symbols', (dirnames,))) - return iter(self._return_iter_symbols) - - def test_typical(self): - self._return_iter_symbols = [ - s_info.Symbol(('dir1/spam.c', None, 'var1'), 'variable', False), - s_info.Symbol(('dir1/spam.c', None, 'var2'), 'variable', False), - s_info.Symbol(('dir1/spam.c', None, 'func1'), 'function', False), - s_info.Symbol(('dir1/spam.c', None, 'func2'), 'function', True), - s_info.Symbol(('dir1/spam.c', None, 'var3'), 'variable', False), - s_info.Symbol(('dir1/spam.c', 'func2', 'var4'), 'variable', False), - s_info.Symbol(('dir1/ham.c', None, 'var1'), 'variable', True), - s_info.Symbol(('dir1/eggs.c', None, 'var1'), 'variable', False), - s_info.Symbol(('dir1/eggs.c', None, 'xyz'), 'other', False), - s_info.Symbol((None, None, '???'), 'other', False), - ] - - found = list(statics_from_symbols(['dir1'], self.iter_symbols)) - - self.assertEqual(found, [ - info.Variable.from_parts('dir1/spam.c', None, 'var1', '???'), - info.Variable.from_parts('dir1/spam.c', None, 'var2', '???'), - info.Variable.from_parts('dir1/spam.c', None, 'var3', '???'), - info.Variable.from_parts('dir1/spam.c', 'func2', 'var4', '???'), - info.Variable.from_parts('dir1/eggs.c', None, 'var1', '???'), - ]) - self.assertEqual(self.calls, [ - ('iter_symbols', (['dir1'],)), - ]) - - def test_no_symbols(self): - self._return_iter_symbols = [] - - found = list(statics_from_symbols(['dir1'], self.iter_symbols)) - - self.assertEqual(found, []) - self.assertEqual(self.calls, [ - ('iter_symbols', (['dir1'],)), - ]) - - -class StaticFromDeclarationsTests(_Base): - - _return_iter_declarations = () - - def iter_declarations(self, dirnames): - self.calls.append(('iter_declarations', (dirnames,))) - return iter(self._return_iter_declarations) - - def test_typical(self): - self._return_iter_declarations = [ - None, - info.Variable.from_parts('dir1/spam.c', None, 'var1', '???'), - object(), - info.Variable.from_parts('dir1/spam.c', None, 'var2', '???'), - info.Variable.from_parts('dir1/spam.c', None, 'var3', '???'), - object(), - info.Variable.from_parts('dir1/spam.c', 'func2', 'var4', '???'), - object(), - info.Variable.from_parts('dir1/eggs.c', None, 'var1', '???'), - object(), - ] - - found = list(statics_from_declarations(['dir1'], self.iter_declarations)) - - self.assertEqual(found, [ - info.Variable.from_parts('dir1/spam.c', None, 'var1', '???'), - info.Variable.from_parts('dir1/spam.c', None, 'var2', '???'), - info.Variable.from_parts('dir1/spam.c', None, 'var3', '???'), - info.Variable.from_parts('dir1/spam.c', 'func2', 'var4', '???'), - info.Variable.from_parts('dir1/eggs.c', None, 'var1', '???'), - ]) - self.assertEqual(self.calls, [ - ('iter_declarations', (['dir1'],)), - ]) - - def test_no_declarations(self): - self._return_iter_declarations = [] - - found = list(statics_from_declarations(['dir1'], self.iter_declarations)) - - self.assertEqual(found, []) - self.assertEqual(self.calls, [ - ('iter_declarations', (['dir1'],)), - ]) - - -class IterStaticsTests(_Base): - - _return_from_symbols = () - _return_from_declarations = () - - def _from_symbols(self, dirnames, iter_symbols): - self.calls.append(('_from_symbols', (dirnames, iter_symbols))) - return iter(self._return_from_symbols) - - def _from_declarations(self, dirnames, iter_declarations): - self.calls.append(('_from_declarations', (dirnames, iter_declarations))) - return iter(self._return_from_declarations) - - def test_typical(self): - expected = [ - info.Variable.from_parts('dir1/spam.c', None, 'var1', '???'), - info.Variable.from_parts('dir1/spam.c', None, 'var2', '???'), - info.Variable.from_parts('dir1/spam.c', None, 'var3', '???'), - info.Variable.from_parts('dir1/spam.c', 'func2', 'var4', '???'), - info.Variable.from_parts('dir1/eggs.c', None, 'var1', '???'), - ] - self._return_from_symbols = expected - - found = list(iter_statics(['dir1'], - _from_symbols=self._from_symbols, - _from_declarations=self._from_declarations)) - - self.assertEqual(found, expected) - self.assertEqual(self.calls, [ - ('_from_symbols', (['dir1'], b_symbols.iter_symbols)), - ]) - - def test_no_symbols(self): - self._return_from_symbols = [] - - found = list(iter_statics(['dir1'], - _from_symbols=self._from_symbols, - _from_declarations=self._from_declarations)) - - self.assertEqual(found, []) - self.assertEqual(self.calls, [ - ('_from_symbols', (['dir1'], b_symbols.iter_symbols)), - ]) - - def test_from_binary(self): - expected = [ - info.Variable.from_parts('dir1/spam.c', None, 'var1', '???'), - info.Variable.from_parts('dir1/spam.c', None, 'var2', '???'), - info.Variable.from_parts('dir1/spam.c', None, 'var3', '???'), - info.Variable.from_parts('dir1/spam.c', 'func2', 'var4', '???'), - info.Variable.from_parts('dir1/eggs.c', None, 'var1', '???'), - ] - self._return_from_symbols = expected - - found = list(iter_statics(['dir1'], 'platform', - _from_symbols=self._from_symbols, - _from_declarations=self._from_declarations)) - - self.assertEqual(found, expected) - self.assertEqual(self.calls, [ - ('_from_symbols', (['dir1'], b_symbols.iter_symbols)), - ]) - - def test_from_symbols(self): - expected = [ - info.Variable.from_parts('dir1/spam.c', None, 'var1', '???'), - info.Variable.from_parts('dir1/spam.c', None, 'var2', '???'), - info.Variable.from_parts('dir1/spam.c', None, 'var3', '???'), - info.Variable.from_parts('dir1/spam.c', 'func2', 'var4', '???'), - info.Variable.from_parts('dir1/eggs.c', None, 'var1', '???'), - ] - self._return_from_symbols = expected - - found = list(iter_statics(['dir1'], 'symbols', - _from_symbols=self._from_symbols, - _from_declarations=self._from_declarations)) - - self.assertEqual(found, expected) - self.assertEqual(self.calls, [ - ('_from_symbols', (['dir1'], s_symbols.iter_symbols)), - ]) - - def test_from_declarations(self): - expected = [ - info.Variable.from_parts('dir1/spam.c', None, 'var1', '???'), - info.Variable.from_parts('dir1/spam.c', None, 'var2', '???'), - info.Variable.from_parts('dir1/spam.c', None, 'var3', '???'), - info.Variable.from_parts('dir1/spam.c', 'func2', 'var4', '???'), - info.Variable.from_parts('dir1/eggs.c', None, 'var1', '???'), - ] - self._return_from_declarations = expected - - found = list(iter_statics(['dir1'], 'declarations', - _from_symbols=self._from_symbols, - _from_declarations=self._from_declarations)) - - self.assertEqual(found, expected) - self.assertEqual(self.calls, [ - ('_from_declarations', (['dir1'], declarations.iter_all)), - ]) - - def test_from_preprocessed(self): - expected = [ - info.Variable.from_parts('dir1/spam.c', None, 'var1', '???'), - info.Variable.from_parts('dir1/spam.c', None, 'var2', '???'), - info.Variable.from_parts('dir1/spam.c', None, 'var3', '???'), - info.Variable.from_parts('dir1/spam.c', 'func2', 'var4', '???'), - info.Variable.from_parts('dir1/eggs.c', None, 'var1', '???'), - ] - self._return_from_declarations = expected - - found = list(iter_statics(['dir1'], 'preprocessed', - _from_symbols=self._from_symbols, - _from_declarations=self._from_declarations)) - - self.assertEqual(found, expected) - self.assertEqual(self.calls, [ - ('_from_declarations', (['dir1'], declarations.iter_preprocessed)), - ]) diff --git a/Tools/c-analyzer/c_statics/__main__.py b/Tools/c-analyzer/c_statics/__main__.py index 86dc31469f1a63..cc76ee64195917 100644 --- a/Tools/c-analyzer/c_statics/__main__.py +++ b/Tools/c-analyzer/c_statics/__main__.py @@ -1,16 +1,27 @@ import argparse import sys +from c_analyzer_common.known import from_file as known_from_file from . import ( KNOWN_FILE, IGNORED_FILE, SOURCE_DIRS, - find, show, + supported, find, show, ) +def _find_statics(dirnames, known, ignored): + ignored = supported.ignored_from_file(ignored) + known = known_from_file(known, dirnames) + + knownvars = (known or {}).get('variables') + for static in find.statics_from_binary(knownvars=knownvars): + #for static in find.statics(dirnames, known, kind='platform'): + yield static, is_supported(statics, ignored, known) + + def cmd_check(cmd, dirs=SOURCE_DIRS, *, ignored=IGNORED_FILE, known=KNOWN_FILE, - _find=find.statics, + _find=_find_statics, _show=show.basic, _print=print, ): @@ -20,7 +31,7 @@ def cmd_check(cmd, dirs=SOURCE_DIRS, *, In the failure case, the list of unsupported variables will be printed out. """ - unsupported = [v for v, s in _find(dirs, ignored, known) if not s] + unsupported = [v for v, s in _find(dirs, known, ignored) if not s] if not unsupported: #_print('okay') return @@ -35,7 +46,7 @@ def cmd_check(cmd, dirs=SOURCE_DIRS, *, def cmd_show(cmd, dirs=SOURCE_DIRS, *, ignored=IGNORED_FILE, known=KNOWN_FILE, - _find=find.statics, + _find=_find_statics, _show=show.basic, _print=print, ): @@ -46,7 +57,7 @@ def cmd_show(cmd, dirs=SOURCE_DIRS, *, """ allsupported = [] allunsupported = [] - for found, supported in _find(dirs, ignored, known): + for found, supported in _find(dirs, known, ignored): (allsupported if supported else allunsupported ).append(found) diff --git a/Tools/c-analyzer/c_statics/find.py b/Tools/c-analyzer/c_statics/find.py index ad4eb3d01925fd..fe98f12dbb5776 100644 --- a/Tools/c-analyzer/c_statics/find.py +++ b/Tools/c-analyzer/c_statics/find.py @@ -1,23 +1,90 @@ -from c_analyzer_common.known import known_from_file -from . import scan -from .supported import is_supported, ignored_from_file +from c_analyzer_common import known +from c_symbols import ( + info as s_info, + binary as b_symbols, + source as s_symbols, + resolve, + ) +from c_parser import info, declarations -def statics(dirnames, ignored, known, *, +# XXX needs tests: +# * iter_variables + +def statics_from_binary(binfile=b_symbols.PYTHON, *, + knownvars=None, + _iter_symbols=b_symbols.iter_symbols, + _resolve=resolve.symbols_to_variables, + _get_symbol_resolver=resolve.get_resolver, + ): + """Yield a Variable for each found Symbol. + + Details are filled in from the given "known" variables and types. + """ + symbols = _iter_symbols(binfile, find_local_symbol=None) + for variable in _resolve(symbols, + resolve=_get_symbol_resolver(knownvars), + ): + if not variable.isstatic: + continue + yield variable + + +def statics_from_declarations(dirnames, *, + known=None, + ): + """Yield a Variable for each found declaration. + + Details are filled in from the given "known" variables and types. + """ + raise NotImplementedError + + +def iter_variables(kind='platform', *, + known=None, + dirnames=None, + _resolve_symbols=resolve.symbols_to_variables, + _get_symbol_resolver=resolve.get_resolver, + _symbols_from_binary=b_symbols.iter_symbols, + _symbols_from_source=s_symbols.iter_symbols, + _iter_raw=declarations.iter_all, + _iter_preprocessed=declarations.iter_preprocessed, + ): + """Yield a Variable for each one found (e.g. in files).""" + kind = kind or 'platform' + + if kind == 'symbols': + knownvars = (known or {}).get('variables') + yield from _resolve_symbols( + _symbols_from_source(dirnames, known), + resolve=_get_symbol_resolver(knownvars, dirnames), + ) + elif kind == 'platform': + knownvars = (known or {}).get('variables') + yield from _resolve_symbols( + _symbols_from_binary(find_local_symbol=None), + resolve=_get_symbol_resolver(knownvars, dirnames), + ) + elif kind == 'declarations': + for decl in _iter_raw(dirnames): + if not isinstance(decl, info.Variable): + continue + yield decl + elif kind == 'preprocessed': + for decl in _iter_preprocessed(dirnames): + if not isinstance(decl, info.Variable): + continue + yield decl + else: + raise ValueError(f'unsupported kind {kind!r}') + + +def statics(dirnames, known, *, kind=None, # Use the default. - _load_ignored=ignored_from_file, - _load_known=known_from_file, - _iter_statics=scan.iter_statics, - _is_supported=is_supported, + _iter_variables=iter_variables, ): """Return a list of (StaticVar, ) for each found static var.""" - if not dirnames: - return [] - - ignored = set(_load_ignored(ignored)) if ignored else () - known = set(_load_known(known)) if known else () - found = [] - for static in _iter_statics(dirnames, kind=kind): - found.append( - (static, _is_supported(static, ignored, known))) - return found + for found in _iter_variables(kind, known=known, dirnames=dirnames): + if not found.isstatic: + continue + yield found diff --git a/Tools/c-analyzer/c_statics/scan.py b/Tools/c-analyzer/c_statics/scan.py deleted file mode 100644 index f7b6b10b4def6c..00000000000000 --- a/Tools/c-analyzer/c_statics/scan.py +++ /dev/null @@ -1,54 +0,0 @@ -from c_parser import info, declarations -from c_symbols import ( - info as s_info, - binary as b_symbols, - source as s_symbols, - ) - - -# Once we start parsing directly, getting symbols from a binary will -# still be useful for tool validation. - -def statics_from_symbols(dirnames, iter_symbols): - """Yield a Variable for each found symbol (static only).""" - for symbol in iter_symbols(dirnames): - if symbol.kind is not s_info.Symbol.KIND.VARIABLE: - continue - if symbol.external: - continue - yield info.Variable.from_parts( - filename=symbol.filename, - funcname=symbol.funcname or None, - name=symbol.name, - vartype='???', - isstatic=True, - ) - - -def statics_from_declarations(dirnames, iter_declarations): - """Yield a Variable for each static variable declaration.""" - for decl in iter_declarations(dirnames): - if not isinstance(decl, info.Variable): - continue - if decl.isstatic: - continue - yield decl - - -def iter_statics(dirnames, kind=None, *, - _from_symbols=statics_from_symbols, - _from_declarations=statics_from_declarations, - ): - """Yield a Variable for each one found in the files.""" - kind = kind or 'platform' - - if kind == 'symbols': - return _from_symbols(dirnames, s_symbols.iter_symbols) - elif kind == 'platform': - return _from_symbols(dirnames, b_symbols.iter_symbols) - elif kind == 'declarations': - return _from_declarations(dirnames, declarations.iter_all) - elif kind == 'preprocessed': - return _from_declarations(dirnames, declarations.iter_preprocessed) - else: - raise ValueError(f'unsupported kind {kind!r}') From 3f2e4f62db1a9217d3faf745725b110097343f66 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 26 Aug 2019 16:17:58 -0600 Subject: [PATCH 070/118] Implement known.from_file() and ignored_from_file(). --- .../test_c_analyzer_common/test_known.py | 46 +++++++++++++++++++ .../test_c_statics/test_supported.py | 42 ++++++++++++++++- Tools/c-analyzer/c_analyzer_common/known.py | 43 ++++++++++++++--- Tools/c-analyzer/c_statics/__main__.py | 2 +- Tools/c-analyzer/c_statics/supported.py | 41 ++++++++++++++++- Tools/c-analyzer/ignored.tsv | 1 + Tools/c-analyzer/known.tsv | 1 + 7 files changed, 166 insertions(+), 10 deletions(-) create mode 100644 Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/test_known.py create mode 100644 Tools/c-analyzer/ignored.tsv create mode 100644 Tools/c-analyzer/known.tsv diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/test_known.py b/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/test_known.py new file mode 100644 index 00000000000000..3f0621f5f3f0dc --- /dev/null +++ b/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/test_known.py @@ -0,0 +1,46 @@ +import textwrap +import unittest + +from .. import tool_imports_for_tests +with tool_imports_for_tests(): + from c_parser.info import Variable + from c_analyzer_common.info import ID + from c_analyzer_common.known import from_file + + +class FromFileTests(unittest.TestCase): + + maxDiff = None + + def test_typical(self): + lines = textwrap.dedent(''' + filename funcname name kind declaration + file1.c var1 variable static int + file1.c func1 local1 variable static int + file1.c var2 variable int + file1.c func2 local2 variable char * + file2.c var1 variable char * + ''').strip().splitlines() + + known = from_file(lines, _open=None) + + self.assertEqual(known, { + 'variables': {v.id: v for v in [ + Variable.from_parts('file1.c', '', 'var1', 'static int'), + Variable.from_parts('file1.c', 'func1', 'local1', 'static int'), + Variable.from_parts('file1.c', '', 'var2', 'int'), + Variable.from_parts('file1.c', 'func2', 'local2', 'char *'), + Variable.from_parts('file2.c', '', 'var1', 'char *'), + ]}, + }) + + def test_empty(self): + lines = textwrap.dedent(''' + filename funcname name kind declaration + '''.strip()).splitlines() + + known = from_file(lines, _open=None) + + self.assertEqual(known, { + 'variables': {}, + }) diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_supported.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_supported.py index 975ea5b4cf2f1e..1b4afc3577e64e 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_supported.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_supported.py @@ -1,9 +1,11 @@ +import textwrap import unittest from .. import tool_imports_for_tests with tool_imports_for_tests(): + from c_analyzer_common.info import ID from c_parser import info - from c_statics.supported import is_supported + from c_statics.supported import is_supported, ignored_from_file class IsSupportedTests(unittest.TestCase): @@ -31,3 +33,41 @@ def test_not_supported(self): result = is_supported(static) self.assertFalse(result) + + +class IgnoredFromFileTests(unittest.TestCase): + + maxDiff = None + + def test_typical(self): + lines = textwrap.dedent(''' + filename funcname name kind reason + file1.c var1 variable ... + file1.c func1 local1 variable + file1.c var2 variable ??? + file1.c func2 local2 variable + file2.c var1 variable reasons + ''').strip().splitlines() + + ignored = ignored_from_file(lines, _open=None) + + self.assertEqual(ignored, { + 'variables': { + ID('file1.c', '', 'var1'): '...', + ID('file1.c', 'func1', 'local1'): '', + ID('file1.c', '', 'var2'): '???', + ID('file1.c', 'func2', 'local2'): '', + ID('file2.c', '', 'var1'): 'reasons', + }, + }) + + def test_empty(self): + lines = textwrap.dedent(''' + filename funcname name kind reason + '''.strip()).splitlines() + + ignored = ignored_from_file(lines, _open=None) + + self.assertEqual(ignored, { + 'variables': {}, + }) diff --git a/Tools/c-analyzer/c_analyzer_common/known.py b/Tools/c-analyzer/c_analyzer_common/known.py index ee82c34a98d77e..87705536c8a496 100644 --- a/Tools/c-analyzer/c_analyzer_common/known.py +++ b/Tools/c-analyzer/c_analyzer_common/known.py @@ -1,17 +1,48 @@ +import csv + from c_parser.info import Variable -from . import info, util +from . import info + + +COLUMNS = ('filename', 'funcname', 'name', 'kind', 'declaration') +HEADER = '\t'.join(COLUMNS) # XXX need tests: # * from_file() -def from_file(infile, fmt=None): - """Yield StaticVar for each ignored var in the file.""" - raise NotImplementedError - return { +def from_file(infile, *, + _open=open, + ): + """Return the info for known declarations in the given file.""" + if isinstance(infile, str): + with _open(infile) as infile: + return from_file(infile, _open=open) + + lines = iter(infile) + try: + header = next(lines).strip() + except StopIteration: + header = '' + if header != HEADER: + raise ValueError(f'bad header {header!r}') + + known = { 'variables': {}, - 'types': {}, + #'types': {}, #'constants': {}, #'macros': {}, } + for row in csv.reader(lines, delimiter='\t'): + filename, funcname, name, kind, declaration = row + id = info.ID(filename.strip(), funcname.strip(), name.strip()) + kind = kind.strip() + if kind == 'variable': + values = known['variables'] + value = Variable(id, declaration.strip()) + else: + raise ValueError(f'unsupported kind in row {row}') + value.validate() + values[id] = value + return known diff --git a/Tools/c-analyzer/c_statics/__main__.py b/Tools/c-analyzer/c_statics/__main__.py index cc76ee64195917..e0652e5535f049 100644 --- a/Tools/c-analyzer/c_statics/__main__.py +++ b/Tools/c-analyzer/c_statics/__main__.py @@ -10,7 +10,7 @@ def _find_statics(dirnames, known, ignored): ignored = supported.ignored_from_file(ignored) - known = known_from_file(known, dirnames) + known = known_from_file(known) knownvars = (known or {}).get('variables') for static in find.statics_from_binary(knownvars=knownvars): diff --git a/Tools/c-analyzer/c_statics/supported.py b/Tools/c-analyzer/c_statics/supported.py index 04e1cd5521e7cd..1009685eec607c 100644 --- a/Tools/c-analyzer/c_statics/supported.py +++ b/Tools/c-analyzer/c_statics/supported.py @@ -1,3 +1,7 @@ +import csv + +from c_analyzer_common.info import ID + def is_supported(static, ignored=None, known=None): """Return True if the given static variable is okay in CPython.""" @@ -17,6 +21,39 @@ def is_supported(static, ignored=None, known=None): ############################# # ignored -def ignored_from_file(infile, fmt=None): +COLUMNS = ('filename', 'funcname', 'name', 'kind', 'reason') +HEADER = '\t'.join(COLUMNS) + + +def ignored_from_file(infile, *, + _open=open, + ): """Yield StaticVar for each ignored var in the file.""" - raise NotImplementedError + if isinstance(infile, str): + with _open(infile) as infile: + return ignored_from_file(infile, _open=open) + + lines = iter(infile) + try: + header = next(lines).strip() + except StopIteration: + header = '' + if header != HEADER: + raise ValueError(f'bad header {header!r}') + + ignored = { + 'variables': {}, + #'types': {}, + #'constants': {}, + #'macros': {}, + } + for row in csv.reader(lines, delimiter='\t'): + filename, funcname, name, kind, reason = row + id = ID(filename, funcname, name) + kind = kind.strip() + if kind == 'variable': + values = ignored['variables'] + else: + raise ValueError(f'unsupported kind in row {row}') + values[id] = reason.strip() + return ignored diff --git a/Tools/c-analyzer/ignored.tsv b/Tools/c-analyzer/ignored.tsv new file mode 100644 index 00000000000000..a0e0e503da6ab0 --- /dev/null +++ b/Tools/c-analyzer/ignored.tsv @@ -0,0 +1 @@ +filename funcname name kind reason diff --git a/Tools/c-analyzer/known.tsv b/Tools/c-analyzer/known.tsv new file mode 100644 index 00000000000000..e8b5439e7682eb --- /dev/null +++ b/Tools/c-analyzer/known.tsv @@ -0,0 +1 @@ +filename funcname name kind declaration From 3e1657ad9a6e36e0aa899e15612ca83ef49cb3f9 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 27 Aug 2019 09:04:56 -0600 Subject: [PATCH 071/118] Fix REPO_ROOT. --- Tools/c-analyzer/c_statics/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Tools/c-analyzer/c_statics/__init__.py b/Tools/c-analyzer/c_statics/__init__.py index adfc53f48acfbf..762e04a69e2bb5 100644 --- a/Tools/c-analyzer/c_statics/__init__.py +++ b/Tools/c-analyzer/c_statics/__init__.py @@ -4,8 +4,7 @@ PKG_ROOT = os.path.dirname(__file__) DATA_DIR = os.path.dirname(PKG_ROOT) REPO_ROOT = os.path.dirname( - os.path.dirname( - os.path.dirname(DATA_DIR))) + os.path.dirname(DATA_DIR)) KNOWN_FILE = os.path.join(DATA_DIR, 'known.tsv') IGNORED_FILE = os.path.join(DATA_DIR, 'ignored.tsv') From a2779b4a1e30d2dd0c3dbe0b656b2acc699b7aef Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 27 Aug 2019 09:08:28 -0600 Subject: [PATCH 072/118] Various minor fixes to get to stable. --- Tools/c-analyzer/c_parser/preprocessor.py | 1 + Tools/c-analyzer/c_statics/__main__.py | 3 ++- Tools/c-analyzer/c_statics/find.py | 3 ++- Tools/c-analyzer/c_symbols/binary.py | 2 +- Tools/c-analyzer/c_symbols/resolve.py | 16 ++++++++-------- Tools/c-analyzer/c_symbols/source.py | 2 +- 6 files changed, 15 insertions(+), 12 deletions(-) diff --git a/Tools/c-analyzer/c_parser/preprocessor.py b/Tools/c-analyzer/c_parser/preprocessor.py index 288c0ba41ff73c..0e2866e4873e67 100644 --- a/Tools/c-analyzer/c_parser/preprocessor.py +++ b/Tools/c-analyzer/c_parser/preprocessor.py @@ -1,4 +1,5 @@ from collections import namedtuple +import shlex import os import re diff --git a/Tools/c-analyzer/c_statics/__main__.py b/Tools/c-analyzer/c_statics/__main__.py index e0652e5535f049..48803f7827d02b 100644 --- a/Tools/c-analyzer/c_statics/__main__.py +++ b/Tools/c-analyzer/c_statics/__main__.py @@ -13,7 +13,8 @@ def _find_statics(dirnames, known, ignored): known = known_from_file(known) knownvars = (known or {}).get('variables') - for static in find.statics_from_binary(knownvars=knownvars): + for static in find.statics_from_binary(knownvars=knownvars, + dirnames=dirnames): #for static in find.statics(dirnames, known, kind='platform'): yield static, is_supported(statics, ignored, known) diff --git a/Tools/c-analyzer/c_statics/find.py b/Tools/c-analyzer/c_statics/find.py index fe98f12dbb5776..f942608ab390ae 100644 --- a/Tools/c-analyzer/c_statics/find.py +++ b/Tools/c-analyzer/c_statics/find.py @@ -13,6 +13,7 @@ def statics_from_binary(binfile=b_symbols.PYTHON, *, knownvars=None, + dirnames=None, _iter_symbols=b_symbols.iter_symbols, _resolve=resolve.symbols_to_variables, _get_symbol_resolver=resolve.get_resolver, @@ -23,7 +24,7 @@ def statics_from_binary(binfile=b_symbols.PYTHON, *, """ symbols = _iter_symbols(binfile, find_local_symbol=None) for variable in _resolve(symbols, - resolve=_get_symbol_resolver(knownvars), + resolve=_get_symbol_resolver(knownvars, dirnames), ): if not variable.isstatic: continue diff --git a/Tools/c-analyzer/c_symbols/binary.py b/Tools/c-analyzer/c_symbols/binary.py index 10aad348e144ba..976d1a478a42b5 100644 --- a/Tools/c-analyzer/c_symbols/binary.py +++ b/Tools/c-analyzer/c_symbols/binary.py @@ -16,7 +16,7 @@ def iter_symbols(binary=PYTHON, dirnames=None, *, # from c_statics.supported. find_local_symbol=source.find_symbol, _file_exists=os.path.exists, - _iter_symbols_nm=(lambda b, fls: _iter_symbols_nm(b, fls)), + _iter_symbols_nm=(lambda b, *a: _iter_symbols_nm(b, *a)), ): """Yield a Symbol for each symbol found in the binary.""" if not _file_exists(binary): diff --git a/Tools/c-analyzer/c_symbols/resolve.py b/Tools/c-analyzer/c_symbols/resolve.py index 1809f24264331c..ab76798064197e 100644 --- a/Tools/c-analyzer/c_symbols/resolve.py +++ b/Tools/c-analyzer/c_symbols/resolve.py @@ -48,12 +48,13 @@ def look_up_known_symbol(symbol, knownvars, *, def find_in_source(symbol, dirnames, *, _perfilecache={}, _find_symbol=_find_symbol, + _iter_files=files.iter_files, ): """Return the Variable matching the given Symbol. If there is no match then return None. """ - if symbol.filename and symbol.filename != UNKONWN: + if symbol.filename and symbol.filename != UNKNOWN: filenames = [symbol.filename] else: filenames = _iter_files(dirnames, ('.c', '.h')) @@ -122,14 +123,13 @@ def symbols_to_variables(symbols, *, # XXX validate? yield symbol continue - if symbol.kind is not Symbol.KIND.VARIABLE: + if symbol.kind != Symbol.KIND.VARIABLE: continue resolved = resolve(symbol) if resolved is None: - raise NotImplementedError - #yield Variable( - # id=symbol.ID, - # vartype=info.UNKNOWN, - # ) - #continue + raise NotImplementedError(symbol) + resolved = info.Variable( + id=symbol.id, + vartype=UNKNOWN, + ) yield resolved diff --git a/Tools/c-analyzer/c_symbols/source.py b/Tools/c-analyzer/c_symbols/source.py index c17d0a7b00a712..b37699c2c71cae 100644 --- a/Tools/c-analyzer/c_symbols/source.py +++ b/Tools/c-analyzer/c_symbols/source.py @@ -51,7 +51,7 @@ def _find_symbol(name, filenames, _perfilecache, *, symbols.pop(name) return filename, funcname, vartype else: - return UNKONWN, UNKNOWN, UNKNOWN + return UNKNOWN, UNKNOWN, UNKNOWN def iter_symbols(): From 89b887a12e055232a08d41310770fcfa68db415a Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 27 Aug 2019 09:10:54 -0600 Subject: [PATCH 073/118] Add util.read_tsv() and util.write_tsv(). --- .../test_c_analyzer_common/test_known.py | 30 +++++++++-- .../test_c_statics/test_find.py | 6 +-- .../test_c_statics/test_supported.py | 30 +++++++++-- Tools/c-analyzer/c_analyzer_common/known.py | 21 ++------ Tools/c-analyzer/c_analyzer_common/util.py | 51 ++++++++++++++++++- Tools/c-analyzer/c_statics/supported.py | 17 ++----- 6 files changed, 111 insertions(+), 44 deletions(-) diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/test_known.py b/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/test_known.py index 3f0621f5f3f0dc..ceb1c4c7ff7c68 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/test_known.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/test_known.py @@ -12,6 +12,20 @@ class FromFileTests(unittest.TestCase): maxDiff = None + _return_read_tsv = () + + @property + def calls(self): + try: + return self._calls + except AttributeError: + self._calls = [] + return self._calls + + def _read_tsv(self, *args): + self.calls.append(('_read_tsv', args)) + return self._return_read_tsv + def test_typical(self): lines = textwrap.dedent(''' filename funcname name kind declaration @@ -21,8 +35,10 @@ def test_typical(self): file1.c func2 local2 variable char * file2.c var1 variable char * ''').strip().splitlines() + self._return_read_tsv = [tuple(v.strip() for v in line.split('\t')) + for line in lines[1:]] - known = from_file(lines, _open=None) + known = from_file('spam.c', _read_tsv=self._read_tsv) self.assertEqual(known, { 'variables': {v.id: v for v in [ @@ -33,14 +49,18 @@ def test_typical(self): Variable.from_parts('file2.c', '', 'var1', 'char *'), ]}, }) + self.assertEqual(self.calls, [ + ('_read_tsv', ('spam.c', 'filename funcname name kind declaration')), + ]) def test_empty(self): - lines = textwrap.dedent(''' - filename funcname name kind declaration - '''.strip()).splitlines() + self._return_read_tsv = [] - known = from_file(lines, _open=None) + known = from_file('spam.c', _read_tsv=self._read_tsv) self.assertEqual(known, { 'variables': {}, }) + self.assertEqual(self.calls, [ + ('_read_tsv', ('spam.c', 'filename funcname name kind declaration')), + ]) diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py index c22f334985e6ea..4a20ce38d4f039 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py @@ -42,8 +42,8 @@ def _resolve_symbols(self, symbols, resolve): self.calls.append(('_resolve_symbols', (symbols, resolve,))) return self._return_resolve_symbols - def _get_symbol_resolver(self, knownvars): - self.calls.append(('_get_symbol_resolver', (knownvars,))) + def _get_symbol_resolver(self, knownvars, dirnames): + self.calls.append(('_get_symbol_resolver', (knownvars, dirnames))) return self._return_get_symbol_resolver def test_typical(self): @@ -70,7 +70,7 @@ def test_typical(self): ]) self.assertEqual(self.calls, [ ('_iter_symbols', ('python', None)), - ('_get_symbol_resolver', (knownvars,)), + ('_get_symbol_resolver', (knownvars, None)), ('_resolve_symbols', (symbols, resolver)), ]) diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_supported.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_supported.py index 1b4afc3577e64e..b02dcbee1d4e55 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_supported.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_supported.py @@ -39,6 +39,20 @@ class IgnoredFromFileTests(unittest.TestCase): maxDiff = None + _return_read_tsv = () + + @property + def calls(self): + try: + return self._calls + except AttributeError: + self._calls = [] + return self._calls + + def _read_tsv(self, *args): + self.calls.append(('_read_tsv', args)) + return self._return_read_tsv + def test_typical(self): lines = textwrap.dedent(''' filename funcname name kind reason @@ -48,8 +62,10 @@ def test_typical(self): file1.c func2 local2 variable file2.c var1 variable reasons ''').strip().splitlines() + self._return_read_tsv = [tuple(v.strip() for v in line.split('\t')) + for line in lines[1:]] - ignored = ignored_from_file(lines, _open=None) + ignored = ignored_from_file('spam.c', _read_tsv=self._read_tsv) self.assertEqual(ignored, { 'variables': { @@ -60,14 +76,18 @@ def test_typical(self): ID('file2.c', '', 'var1'): 'reasons', }, }) + self.assertEqual(self.calls, [ + ('_read_tsv', ('spam.c', 'filename funcname name kind reason')), + ]) def test_empty(self): - lines = textwrap.dedent(''' - filename funcname name kind reason - '''.strip()).splitlines() + self._return_read_tsv = [] - ignored = ignored_from_file(lines, _open=None) + ignored = ignored_from_file('spam.c', _read_tsv=self._read_tsv) self.assertEqual(ignored, { 'variables': {}, }) + self.assertEqual(self.calls, [ + ('_read_tsv', ('spam.c', 'filename funcname name kind reason')), + ]) diff --git a/Tools/c-analyzer/c_analyzer_common/known.py b/Tools/c-analyzer/c_analyzer_common/known.py index 87705536c8a496..e237eb3b86c27b 100644 --- a/Tools/c-analyzer/c_analyzer_common/known.py +++ b/Tools/c-analyzer/c_analyzer_common/known.py @@ -2,7 +2,8 @@ from c_parser.info import Variable -from . import info +from .info import ID +from .util import read_tsv COLUMNS = ('filename', 'funcname', 'name', 'kind', 'declaration') @@ -13,30 +14,18 @@ # * from_file() def from_file(infile, *, - _open=open, + _read_tsv=read_tsv, ): """Return the info for known declarations in the given file.""" - if isinstance(infile, str): - with _open(infile) as infile: - return from_file(infile, _open=open) - - lines = iter(infile) - try: - header = next(lines).strip() - except StopIteration: - header = '' - if header != HEADER: - raise ValueError(f'bad header {header!r}') - known = { 'variables': {}, #'types': {}, #'constants': {}, #'macros': {}, } - for row in csv.reader(lines, delimiter='\t'): + for row in _read_tsv(infile, HEADER): filename, funcname, name, kind, declaration = row - id = info.ID(filename.strip(), funcname.strip(), name.strip()) + id = ID(filename.strip(), funcname.strip(), name.strip()) kind = kind.strip() if kind == 'variable': values = known['variables'] diff --git a/Tools/c-analyzer/c_analyzer_common/util.py b/Tools/c-analyzer/c_analyzer_common/util.py index e9d71915d99776..ea3b27fe3e33b0 100644 --- a/Tools/c-analyzer/c_analyzer_common/util.py +++ b/Tools/c-analyzer/c_analyzer_common/util.py @@ -1,10 +1,11 @@ +import csv import subprocess _NOT_SET = object() -def run_cmd(argv): +def run_cmd(argv, **kwargs): proc = subprocess.run( argv, #capture_output=True, @@ -12,10 +13,58 @@ def run_cmd(argv): stdout=subprocess.PIPE, text=True, check=True, + **kwargs ) return proc.stdout +def read_tsv(infile, header, *, + _open=open, + _get_reader=csv.reader, + ): + """Yield each row of the given TSV (tab-separated) file.""" + if isinstance(infile, str): + with _open(infile, newline='') as infile: + yield from read_tsv(infile, header, + _open=_open, + _get_reader=_get_reader, + ) + return + lines = iter(infile) + + # Validate the header. + try: + actualheader = next(lines).strip() + except StopIteration: + actualheader = '' + if actualheader != header: + raise ValueError(f'bad header {actualheader!r}') + + for row in _get_reader(lines, delimiter='\t'): + yield tuple(v.strip() for v in row) + + +def write_tsv(outfile, header, rows, *, + _open=open, + _get_writer=csv.writer, + ): + """Write each of the rows to the given TSV (tab-separated) file.""" + if isinstance(outfile, str): + with _open(outfile, 'w', newline='') as outfile: + return write_tsv(outfile, header, rows, + _open=_open, + _get_writer=_get_writer, + ) + + if isinstance(header, str): + header = header.split('\t') + writer = _get_writer(outfile, delimiter='\t') + writer.writerow(header) + for row in rows: + writer.writerow('' if v is None else str(v) + for v in row) + + class Slot: """A descriptor that provides a slot. diff --git a/Tools/c-analyzer/c_statics/supported.py b/Tools/c-analyzer/c_statics/supported.py index 1009685eec607c..d05d388bdcfd8f 100644 --- a/Tools/c-analyzer/c_statics/supported.py +++ b/Tools/c-analyzer/c_statics/supported.py @@ -1,6 +1,7 @@ import csv from c_analyzer_common.info import ID +from c_analyzer_common.util import read_tsv def is_supported(static, ignored=None, known=None): @@ -26,28 +27,16 @@ def is_supported(static, ignored=None, known=None): def ignored_from_file(infile, *, - _open=open, + _read_tsv=read_tsv, ): """Yield StaticVar for each ignored var in the file.""" - if isinstance(infile, str): - with _open(infile) as infile: - return ignored_from_file(infile, _open=open) - - lines = iter(infile) - try: - header = next(lines).strip() - except StopIteration: - header = '' - if header != HEADER: - raise ValueError(f'bad header {header!r}') - ignored = { 'variables': {}, #'types': {}, #'constants': {}, #'macros': {}, } - for row in csv.reader(lines, delimiter='\t'): + for row in _read_tsv(infile, HEADER): filename, funcname, name, kind, reason = row id = ID(filename, funcname, name) kind = kind.strip() From 89a02c3adab61f33d41d4923b17d74f03e147d5c Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 27 Aug 2019 09:45:15 -0600 Subject: [PATCH 074/118] Treat "-" in .tsv file as None. --- .../test_c_analyzer/test_c_analyzer_common/test_known.py | 6 +++--- .../test_c_analyzer/test_c_statics/test_supported.py | 6 +++--- Tools/c-analyzer/c_analyzer_common/known.py | 7 ++++--- Tools/c-analyzer/c_statics/supported.py | 5 +++-- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/test_known.py b/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/test_known.py index ceb1c4c7ff7c68..95eac915d7f3e2 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/test_known.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/test_known.py @@ -29,11 +29,11 @@ def _read_tsv(self, *args): def test_typical(self): lines = textwrap.dedent(''' filename funcname name kind declaration - file1.c var1 variable static int + file1.c - var1 variable static int file1.c func1 local1 variable static int - file1.c var2 variable int + file1.c - var2 variable int file1.c func2 local2 variable char * - file2.c var1 variable char * + file2.c - var1 variable char * ''').strip().splitlines() self._return_read_tsv = [tuple(v.strip() for v in line.split('\t')) for line in lines[1:]] diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_supported.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_supported.py index b02dcbee1d4e55..e3f0eb089cb630 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_supported.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_supported.py @@ -56,11 +56,11 @@ def _read_tsv(self, *args): def test_typical(self): lines = textwrap.dedent(''' filename funcname name kind reason - file1.c var1 variable ... + file1.c - var1 variable ... file1.c func1 local1 variable - file1.c var2 variable ??? + file1.c - var2 variable ??? file1.c func2 local2 variable - file2.c var1 variable reasons + file2.c - var1 variable reasons ''').strip().splitlines() self._return_read_tsv = [tuple(v.strip() for v in line.split('\t')) for line in lines[1:]] diff --git a/Tools/c-analyzer/c_analyzer_common/known.py b/Tools/c-analyzer/c_analyzer_common/known.py index e237eb3b86c27b..e4cba1ddf0c473 100644 --- a/Tools/c-analyzer/c_analyzer_common/known.py +++ b/Tools/c-analyzer/c_analyzer_common/known.py @@ -25,11 +25,12 @@ def from_file(infile, *, } for row in _read_tsv(infile, HEADER): filename, funcname, name, kind, declaration = row - id = ID(filename.strip(), funcname.strip(), name.strip()) - kind = kind.strip() + if not funcname or funcname == '-': + funcname = None + id = ID(filename, funcname, name) if kind == 'variable': values = known['variables'] - value = Variable(id, declaration.strip()) + value = Variable(id, declaration) else: raise ValueError(f'unsupported kind in row {row}') value.validate() diff --git a/Tools/c-analyzer/c_statics/supported.py b/Tools/c-analyzer/c_statics/supported.py index d05d388bdcfd8f..7c45bc309b67eb 100644 --- a/Tools/c-analyzer/c_statics/supported.py +++ b/Tools/c-analyzer/c_statics/supported.py @@ -38,11 +38,12 @@ def ignored_from_file(infile, *, } for row in _read_tsv(infile, HEADER): filename, funcname, name, kind, reason = row + if not funcname or funcname == '-': + funcname = None id = ID(filename, funcname, name) - kind = kind.strip() if kind == 'variable': values = ignored['variables'] else: raise ValueError(f'unsupported kind in row {row}') - values[id] = reason.strip() + values[id] = reason return ignored From 697ab5987f12b818691fb9a3c4f3a5d9b94cd790 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 27 Aug 2019 10:17:02 -0600 Subject: [PATCH 075/118] Fix the statics_from_binary() tests. --- .../test_tools/test_c_analyzer/test_c_statics/test_find.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py index 4a20ce38d4f039..75fc6cb46ff8fa 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py @@ -42,7 +42,7 @@ def _resolve_symbols(self, symbols, resolve): self.calls.append(('_resolve_symbols', (symbols, resolve,))) return self._return_resolve_symbols - def _get_symbol_resolver(self, knownvars, dirnames): + def _get_symbol_resolver(self, knownvars, dirnames=None): self.calls.append(('_get_symbol_resolver', (knownvars, dirnames))) return self._return_get_symbol_resolver @@ -71,7 +71,7 @@ def test_typical(self): self.assertEqual(self.calls, [ ('_iter_symbols', ('python', None)), ('_get_symbol_resolver', (knownvars, None)), - ('_resolve_symbols', (symbols, resolver)), + ('_resolve_symbols', (list(symbols), resolver)), ]) # self._return_iter_symbols = [ From 66a69c4b45e205fe690a07597fa523d1ca406a39 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 27 Aug 2019 10:19:34 -0600 Subject: [PATCH 076/118] Add code to generate known.tsv. --- .../c-analyzer/c_analyzer_common/_generate.py | 109 ++++++++++++++++++ Tools/c-analyzer/c_statics/find.py | 4 +- 2 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 Tools/c-analyzer/c_analyzer_common/_generate.py diff --git a/Tools/c-analyzer/c_analyzer_common/_generate.py b/Tools/c-analyzer/c_analyzer_common/_generate.py new file mode 100644 index 00000000000000..dab67d349e5273 --- /dev/null +++ b/Tools/c-analyzer/c_analyzer_common/_generate.py @@ -0,0 +1,109 @@ +# The code here consists of hacks for pre-populating the known.tsv file. + +import contextlib +import glob +import os.path +import re + +from c_statics import KNOWN_FILE, SOURCE_DIRS, REPO_ROOT + +from . import known +from .info import UNKNOWN, ID +from .util import run_cmd, write_tsv + + +@contextlib.contextmanager +def get_srclines(filename, srclines=None, *, + cache=None, + _open=open, + ): + if srclines is None: + if cache is None: + with _open(filename) as srcfile: + srclines = list(srcfile) + else: + try: + srclines = cache[filename] + except KeyError: + with open(filename) as srcfile: + srclines = [line.rstrip() for line in srcfile] + cache[filename] = srclines + yield srclines + + +def find_matching_variable(varid, filename, srclines=None, *, + cache=None, + _used=set(), + _get_srclines=get_srclines, + ): + # XXX Store found variables in the cache instead of the src lines? + # Then we would pop from cache instead of using "_used". + name = varid.name + funcname = varid.funcname + with _get_srclines(filename, srclines, cache=cache) as srclines: + for line in srclines: + # XXX remember current funcname + if name not in line: + continue + if funcname: + if not line.startswith(' '): + continue + line = line.strip() + if not line.startswith('static '): + continue + filename = os.path.relpath(filename, REPO_ROOT) + newid = ID(filename, funcname, name) + if newid in _used: + continue + _used.add(newid) + + decl = line.split('=')[0].strip() + decl = decl.strip(';').strip() + return newid, decl + return varid, UNKNOWN + + +def known_rows(symbols, *, + dirnames=SOURCE_DIRS, + _find_match=find_matching_variable, + ): + cache = {} + for symbol in symbols: + if symbol.filename and symbol.filename != UNKNOWN: + filenames = [symbol.filename] + else: + filenames = [] + for suffix in ('.c', '.h'): + for dirname in SOURCE_DIRS: + filenames.extend(glob.glob(f'{dirname}/*{suffix}')) + filenames.extend(glob.glob(f'{dirname}/**/*{suffix}')) + + if symbol.funcname == UNKNOWN: + print(symbol) + + if not filenames: + raise ValueError(f'no files found for dirnames {dirnames}') + for filename in filenames: + found, decl = _find_match(symbol.id, filename, cache=cache) + if decl != UNKNOWN: + break + # else we will have made at least one pass, so found will be + # symbol.id and decl will be UNKNOWN. + + yield ( + found.filename, + found.funcname or '-', + found.name, + 'variable', + decl, + ) + + +def known_file(symbols, filename=None, *, + _generate_rows=known_rows, + ): + if not filename: + filename = KNOWN_FILE + '.new' + + rows = _generate_rows(symbols) + write_tsv(filename, known.HEADER, rows) diff --git a/Tools/c-analyzer/c_statics/find.py b/Tools/c-analyzer/c_statics/find.py index f942608ab390ae..e828c77cf8487b 100644 --- a/Tools/c-analyzer/c_statics/find.py +++ b/Tools/c-analyzer/c_statics/find.py @@ -1,4 +1,3 @@ -from c_analyzer_common import known from c_symbols import ( info as s_info, binary as b_symbols, @@ -23,6 +22,9 @@ def statics_from_binary(binfile=b_symbols.PYTHON, *, Details are filled in from the given "known" variables and types. """ symbols = _iter_symbols(binfile, find_local_symbol=None) + symbols = list(symbols) + #import c_analyzer_common._generate + #c_analyzer_common._generate.known_file(symbols) for variable in _resolve(symbols, resolve=_get_symbol_resolver(knownvars, dirnames), ): From 411aadd9b4a7c5039a076c6fcc03bee2a2abfeef Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 27 Aug 2019 10:26:45 -0600 Subject: [PATCH 077/118] Fix a typo in get_resolver(). --- Tools/c-analyzer/c_symbols/resolve.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Tools/c-analyzer/c_symbols/resolve.py b/Tools/c-analyzer/c_symbols/resolve.py index ab76798064197e..954ac3ed4420e6 100644 --- a/Tools/c-analyzer/c_symbols/resolve.py +++ b/Tools/c-analyzer/c_symbols/resolve.py @@ -83,15 +83,15 @@ def get_resolver(knownvars=None, dirnames=None, *, with the corresponding information. Otherwise None is returned. """ if knownvars: - known = dict((known or {}).get('variables', ())) # a copy + knownvars = dict(knownvars) # a copy def resolve_known(symbol): - found = _look_up_known(symbol, known) + found = _look_up_known(symbol, knownvars) if found is None: return None elif symbol.funcname == UNKNOWN: - known.pop(var.id) + knownvars.pop(var.id) elif not symbol.filename or symbol.filename == UNKNOWN: - known.pop(var.id) + knownvars.pop(var.id) return found if dirnames: def resolve(symbol): From 3bfb3450e2d24491f53e785822566bd4ec838a0b Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 27 Aug 2019 10:28:37 -0600 Subject: [PATCH 078/118] Fix a typo in _find_statics(). --- Tools/c-analyzer/c_statics/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tools/c-analyzer/c_statics/__main__.py b/Tools/c-analyzer/c_statics/__main__.py index 48803f7827d02b..ad1d56ba2f2ce5 100644 --- a/Tools/c-analyzer/c_statics/__main__.py +++ b/Tools/c-analyzer/c_statics/__main__.py @@ -16,7 +16,7 @@ def _find_statics(dirnames, known, ignored): for static in find.statics_from_binary(knownvars=knownvars, dirnames=dirnames): #for static in find.statics(dirnames, known, kind='platform'): - yield static, is_supported(statics, ignored, known) + yield static, supported.is_supported(static, ignored, known) def cmd_check(cmd, dirs=SOURCE_DIRS, *, From 9d731e7084d0ed77b5fccb042a2e8c927561197b Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 27 Aug 2019 15:55:31 -0600 Subject: [PATCH 079/118] Implement is_supported() (first pass). --- .../c-analyzer/c_analyzer_common/_generate.py | 2 +- Tools/c-analyzer/c_statics/supported.py | 162 +++++++++++++++++- 2 files changed, 155 insertions(+), 9 deletions(-) diff --git a/Tools/c-analyzer/c_analyzer_common/_generate.py b/Tools/c-analyzer/c_analyzer_common/_generate.py index dab67d349e5273..193ac5c5a81c42 100644 --- a/Tools/c-analyzer/c_analyzer_common/_generate.py +++ b/Tools/c-analyzer/c_analyzer_common/_generate.py @@ -43,7 +43,7 @@ def find_matching_variable(varid, filename, srclines=None, *, with _get_srclines(filename, srclines, cache=cache) as srclines: for line in srclines: # XXX remember current funcname - if name not in line: + if not re.match(rf'.*\b{name}\b', line): continue if funcname: if not line.startswith(' '): diff --git a/Tools/c-analyzer/c_statics/supported.py b/Tools/c-analyzer/c_statics/supported.py index 7c45bc309b67eb..ce5e9341976234 100644 --- a/Tools/c-analyzer/c_statics/supported.py +++ b/Tools/c-analyzer/c_statics/supported.py @@ -1,4 +1,5 @@ import csv +import re from c_analyzer_common.info import ID from c_analyzer_common.util import read_tsv @@ -6,17 +7,162 @@ def is_supported(static, ignored=None, known=None): """Return True if the given static variable is okay in CPython.""" + if _is_ignored(static, ignored and ignored.get('variables')): + return True + elif _is_vartype_okay(static.vartype, ignored.get('types')): + return True + else: + return False + + +# XXX Move these to ignored.tsv. +IGNORED = { + # global + 'PyImport_FrozenModules', + 'M___hello__', + 'inittab_copy', + 'PyHash_Func', + '_Py_HashSecret_Initialized', + '_TARGET_LOCALES', + 'runtime_initialized', + + # startup + 'static_arg_parsers', + 'orig_argv', + 'opt_ptr', + '_preinit_warnoptions', + '_Py_StandardStreamEncoding', + '_Py_StandardStreamErrors', + + # should be const + 'tracemalloc_empty_traceback', + '_empty_bitmap_node', + 'posix_constants_pathconf', + 'posix_constants_confstr', + 'posix_constants_sysconf', + + # signals are main-thread only + 'faulthandler_handlers', + 'user_signals', + } + + +def _is_ignored(static, ignoredvars=None): + if static.name in IGNORED: + return True + + if ignoredvars and static.id in ignoredvars: + return True + + # compiler + if static.filename == 'Python/graminit.c': + if static.vartype.startswith('static state '): + return True + if static.filename == 'Python/symtable.c': + if static.vartype.startswith('static identifier '): + return True + if static.filename == 'Python/Python-ast.c': + # These should be const. + if static.name.endswith('_field'): + return True + if static.name.endswith('_attribute'): + return True + + # other + if static.filename == 'Python/dtoa.c': + # guarded by lock? + if static.name in ('p5s', 'freelist'): + return True + if static.name in ('private_mem', 'pmem_next'): + return True + + return False + + +def _is_vartype_okay(vartype, ignoredtypes=None): + if _is_object(vartype): + return False + + # components for TypeObject definitions + for name in ('PyMethodDef', 'PyGetSetDef', 'PyMemberDef'): + if name in vartype: + return True + for name in ('PyNumberMethods', 'PySequenceMethods', 'PyMappingMethods', + 'PyBufferProcs', 'PyAsyncMethods'): + if name in vartype: + return True + for name in ('slotdef', 'newfunc'): + if name in vartype: + return True + + # structseq + for name in ('PyStructSequence_Desc', 'PyStructSequence_Field'): + if name in vartype: + return True + + # other definiitions + if 'PyModuleDef' in vartype: + return True + + # thread-safe + if '_Py_atomic_int' in vartype: + return True + if 'pthread_condattr_t' in vartype: + return True + + # startup + if '_Py_PreInitEntry' in vartype: + return True + + # global + if 'PyMemAllocatorEx' in vartype: + return True + + # others + if 'PyThread_type_lock' in vartype: + return True + #if '_Py_hashtable_t' in vartype: + # return True # ??? + + # XXX ??? + # _Py_tss_t + # _Py_hashtable_t + # stack_t + # _PyUnicode_Name_CAPI + + # funcsions + if '(' in vartype and '[' not in vartype: + return True + # XXX finish! - raise NotImplementedError - if static in ignored: + # * allow const values? + #raise NotImplementedError + return False + + +def _is_object(vartype): + if re.match(r'.*\bPy\w*Object\b', vartype): + return True + if '_Py_Identifier' in vartype: + return True + if 'traceback_t' in vartype: return True - if static in known: + if 'PyAsyncGenASend' in vartype: return True - for part in static.vartype.split(): - # XXX const is automatic True? - if part == 'PyObject' or part.startswith('PyObject['): - return False - return True + if '_PyAsyncGenWrappedValue' in vartype: + return True + if 'PyContext' in vartype: + return True + if 'method_cache_entry' in vartype: + return True + + # XXX Add more? + + #for part in vartype.split(): + # # XXX const is automatic True? + # if part == 'PyObject' or part.startswith('PyObject['): + # return True + return False ############################# From 021be3c942f37d66ed2e1e3a6762e0f4cadc6f2c Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 27 Aug 2019 16:02:00 -0600 Subject: [PATCH 080/118] Show the vartype in the basic output format. --- .../test_c_statics/test_show.py | 38 ++++++++++--------- Tools/c-analyzer/c_statics/show.py | 1 + 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_show.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_show.py index b9baed3f313bca..a512f00834b4b7 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_show.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_show.py @@ -7,20 +7,22 @@ TYPICAL = [ - info.Variable.from_parts('src1/spam.c', None, 'var1', 'const char *'), - info.Variable.from_parts('src1/spam.c', 'ham', 'initialized', 'int'), - info.Variable.from_parts('src1/spam.c', None, 'var2', 'PyObject *'), - info.Variable.from_parts('src1/eggs.c', 'tofu', 'ready', 'int'), - info.Variable.from_parts('src1/spam.c', None, 'freelist', '(PyTupleObject *)[10]'), - info.Variable.from_parts('src1/sub/ham.c', None, 'var1', 'const char const *'), - info.Variable.from_parts('src2/jam.c', None, 'var1', 'int'), - info.Variable.from_parts('src2/jam.c', None, 'var2', 'MyObject *'), - info.Variable.from_parts('Include/spam.h', None, 'data', 'const int'), + info.Variable.from_parts('src1/spam.c', None, 'var1', 'statc const char *'), + info.Variable.from_parts('src1/spam.c', 'ham', 'initialized', 'static int'), + info.Variable.from_parts('src1/spam.c', None, 'var2', 'static PyObject *'), + info.Variable.from_parts('src1/eggs.c', 'tofu', 'ready', 'static int'), + info.Variable.from_parts('src1/spam.c', None, 'freelist', 'static (PyTupleObject *)[10]'), + info.Variable.from_parts('src1/sub/ham.c', None, 'var1', 'static const char const *'), + info.Variable.from_parts('src2/jam.c', None, 'var1', 'static int'), + info.Variable.from_parts('src2/jam.c', None, 'var2', 'static MyObject *'), + info.Variable.from_parts('Include/spam.h', None, 'data', 'static const int'), ] class BasicTests(unittest.TestCase): + maxDiff = None + def setUp(self): self.lines = [] @@ -32,15 +34,15 @@ def test_typical(self): _print=self.print) self.assertEqual(self.lines, [ - 'src1/spam.c:var1', - 'src1/spam.c:ham():initialized', - 'src1/spam.c:var2', - 'src1/eggs.c:tofu():ready', - 'src1/spam.c:freelist', - 'src1/sub/ham.c:var1', - 'src2/jam.c:var1', - 'src2/jam.c:var2', - 'Include/spam.h:data', + 'src1/spam.c:var1 const char *', + 'src1/spam.c:ham():initialized int', + 'src1/spam.c:var2 PyObject *', + 'src1/eggs.c:tofu():ready int', + 'src1/spam.c:freelist (PyTupleObject *)[10]', + 'src1/sub/ham.c:var1 const char const *', + 'src2/jam.c:var1 int', + 'src2/jam.c:var2 MyObject *', + 'Include/spam.h:data const int', ]) def test_no_rows(self): diff --git a/Tools/c-analyzer/c_statics/show.py b/Tools/c-analyzer/c_statics/show.py index 2c6a6239d22176..8228b52704bfc6 100644 --- a/Tools/c-analyzer/c_statics/show.py +++ b/Tools/c-analyzer/c_statics/show.py @@ -7,4 +7,5 @@ def basic(statics, *, line = f'{static.filename}:{static.funcname}():{static.name}' else: line = f'{static.filename}:{static.name}' + line = f'{line:<64} {static.vartype.partition(" ")[2]}' _print(line) From f62013589d8bfae3b00d85d3f1409fc9990a7b61 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Wed, 28 Aug 2019 08:59:05 -0600 Subject: [PATCH 081/118] Use the underlying ID for the hash of Symbol and Variable. --- Tools/c-analyzer/c_parser/info.py | 3 +++ Tools/c-analyzer/c_symbols/info.py | 3 +++ 2 files changed, 6 insertions(+) diff --git a/Tools/c-analyzer/c_parser/info.py b/Tools/c-analyzer/c_parser/info.py index 0d9e38902f200c..0e60a011c5dec3 100644 --- a/Tools/c-analyzer/c_parser/info.py +++ b/Tools/c-analyzer/c_parser/info.py @@ -38,6 +38,9 @@ def __new__(cls, id, vartype): ) return self + def __hash__(self): + return hash(self.id) + def __getattr__(self, name): return getattr(self.id, name) diff --git a/Tools/c-analyzer/c_symbols/info.py b/Tools/c-analyzer/c_symbols/info.py index fc4d40c17034a5..f6ed52c8f07142 100644 --- a/Tools/c-analyzer/c_symbols/info.py +++ b/Tools/c-analyzer/c_symbols/info.py @@ -29,6 +29,9 @@ def __new__(cls, id, kind=KIND.VARIABLE, external=None): ) return self + def __hash__(self): + return hash(self.id) + def __getattr__(self, name): return getattr(self.id, name) From e7a029d847ec16d61d0996b6e2f20b1dd12f42f4 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Wed, 28 Aug 2019 09:40:27 -0600 Subject: [PATCH 082/118] Move constants out of c_statics.__init__. --- .../test_c_statics/test___main__.py | 27 ++++++++++--------- .../c-analyzer/c_analyzer_common/__init__.py | 19 +++++++++++++ Tools/c-analyzer/c_analyzer_common/known.py | 4 +++ Tools/c-analyzer/c_statics/__init__.py | 22 --------------- Tools/c-analyzer/c_statics/__main__.py | 12 +++++---- Tools/c-analyzer/c_statics/supported.py | 4 +++ 6 files changed, 49 insertions(+), 39 deletions(-) diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test___main__.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test___main__.py index 98823af493458c..5237b05de0bc80 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test___main__.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test___main__.py @@ -3,8 +3,11 @@ from .. import tool_imports_for_tests with tool_imports_for_tests(): + from c_analyzer_common import SOURCE_DIRS + from c_analyzer_common.known import DATA_FILE as KNOWN_FILE from c_parser import info import c_statics as cg + from c_statics.supported import IGNORED_FILE from c_statics.__main__ import cmd_check, cmd_show, parse_args, main @@ -77,9 +80,9 @@ def test_defaults(self): self.assertEqual(self.calls[0], ( '_find', ( - cg.SOURCE_DIRS, - cg.KNOWN_FILE, - cg.IGNORED_FILE, + SOURCE_DIRS, + KNOWN_FILE, + IGNORED_FILE, ), )) @@ -138,9 +141,9 @@ def test_defaults(self): self.assertEqual(self.calls[0], ( '_find', ( - cg.SOURCE_DIRS, - cg.KNOWN_FILE, - cg.IGNORED_FILE, + SOURCE_DIRS, + KNOWN_FILE, + IGNORED_FILE, ), )) @@ -191,9 +194,9 @@ def test_check_no_args(self): self.assertEqual(cmd, 'check') self.assertEqual(cmdkwargs, { - 'ignored': cg.IGNORED_FILE, - 'known': cg.KNOWN_FILE, - 'dirs': cg.SOURCE_DIRS, + 'ignored': IGNORED_FILE, + 'known': KNOWN_FILE, + 'dirs': SOURCE_DIRS, }) def test_check_full_args(self): @@ -220,9 +223,9 @@ def test_show_no_args(self): self.assertEqual(cmd, 'show') self.assertEqual(cmdkwargs, { - 'ignored': cg.IGNORED_FILE, - 'known': cg.KNOWN_FILE, - 'dirs': cg.SOURCE_DIRS, + 'ignored': IGNORED_FILE, + 'known': KNOWN_FILE, + 'dirs': SOURCE_DIRS, }) def test_show_full_args(self): diff --git a/Tools/c-analyzer/c_analyzer_common/__init__.py b/Tools/c-analyzer/c_analyzer_common/__init__.py index e69de29bb2d1d6..888b16ff41d10d 100644 --- a/Tools/c-analyzer/c_analyzer_common/__init__.py +++ b/Tools/c-analyzer/c_analyzer_common/__init__.py @@ -0,0 +1,19 @@ +import os.path + + +PKG_ROOT = os.path.dirname(__file__) +DATA_DIR = os.path.dirname(PKG_ROOT) +REPO_ROOT = os.path.dirname( + os.path.dirname(DATA_DIR)) + +SOURCE_DIRS = [os.path.join(REPO_ROOT, name) for name in [ + 'Include', + 'Python', + 'Parser', + 'Objects', + 'Modules', + ]] + + +# Clean up the namespace. +del os diff --git a/Tools/c-analyzer/c_analyzer_common/known.py b/Tools/c-analyzer/c_analyzer_common/known.py index e4cba1ddf0c473..d40513822637ee 100644 --- a/Tools/c-analyzer/c_analyzer_common/known.py +++ b/Tools/c-analyzer/c_analyzer_common/known.py @@ -1,11 +1,15 @@ import csv +import os.path +from c_analyzer_common import DATA_DIR from c_parser.info import Variable from .info import ID from .util import read_tsv +DATA_FILE = os.path.join(DATA_DIR, 'known.tsv') + COLUMNS = ('filename', 'funcname', 'name', 'kind', 'declaration') HEADER = '\t'.join(COLUMNS) diff --git a/Tools/c-analyzer/c_statics/__init__.py b/Tools/c-analyzer/c_statics/__init__.py index 762e04a69e2bb5..e69de29bb2d1d6 100644 --- a/Tools/c-analyzer/c_statics/__init__.py +++ b/Tools/c-analyzer/c_statics/__init__.py @@ -1,22 +0,0 @@ -import os.path - - -PKG_ROOT = os.path.dirname(__file__) -DATA_DIR = os.path.dirname(PKG_ROOT) -REPO_ROOT = os.path.dirname( - os.path.dirname(DATA_DIR)) - -KNOWN_FILE = os.path.join(DATA_DIR, 'known.tsv') -IGNORED_FILE = os.path.join(DATA_DIR, 'ignored.tsv') - -SOURCE_DIRS = [os.path.join(REPO_ROOT, name) for name in [ - 'Include', - 'Python', - 'Parser', - 'Objects', - 'Modules', - ]] - - -# Clean up the namespace. -del os diff --git a/Tools/c-analyzer/c_statics/__main__.py b/Tools/c-analyzer/c_statics/__main__.py index ad1d56ba2f2ce5..5079a5453b1cf7 100644 --- a/Tools/c-analyzer/c_statics/__main__.py +++ b/Tools/c-analyzer/c_statics/__main__.py @@ -1,11 +1,13 @@ import argparse import sys -from c_analyzer_common.known import from_file as known_from_file -from . import ( - KNOWN_FILE, IGNORED_FILE, SOURCE_DIRS, - supported, find, show, - ) +from c_analyzer_common import SOURCE_DIRS +from c_analyzer_common.known import ( + from_file as known_from_file, + DATA_FILE as KNOWN_FILE, + ) +from . import find, show +from .supported import is_supported, ignored_from_file, IGNORED_FILE def _find_statics(dirnames, known, ignored): diff --git a/Tools/c-analyzer/c_statics/supported.py b/Tools/c-analyzer/c_statics/supported.py index ce5e9341976234..c74067480a0c4c 100644 --- a/Tools/c-analyzer/c_statics/supported.py +++ b/Tools/c-analyzer/c_statics/supported.py @@ -1,6 +1,8 @@ import csv +import os.path import re +from c_analyzer_common import DATA_DIR from c_analyzer_common.info import ID from c_analyzer_common.util import read_tsv @@ -168,6 +170,8 @@ def _is_object(vartype): ############################# # ignored +IGNORED_FILE = os.path.join(DATA_DIR, 'ignored.tsv') + COLUMNS = ('filename', 'funcname', 'name', 'kind', 'reason') HEADER = '\t'.join(COLUMNS) From b99c9f207b20f1a3f30e618db5e5cf6495c8b825 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Wed, 28 Aug 2019 17:02:26 -0600 Subject: [PATCH 083/118] Fix a typo. --- Tools/c-analyzer/c_statics/__main__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tools/c-analyzer/c_statics/__main__.py b/Tools/c-analyzer/c_statics/__main__.py index 5079a5453b1cf7..b2129db54dde85 100644 --- a/Tools/c-analyzer/c_statics/__main__.py +++ b/Tools/c-analyzer/c_statics/__main__.py @@ -11,14 +11,14 @@ def _find_statics(dirnames, known, ignored): - ignored = supported.ignored_from_file(ignored) + ignored = ignored_from_file(ignored) known = known_from_file(known) knownvars = (known or {}).get('variables') for static in find.statics_from_binary(knownvars=knownvars, dirnames=dirnames): #for static in find.statics(dirnames, known, kind='platform'): - yield static, supported.is_supported(static, ignored, known) + yield static, is_supported(static, ignored, known) def cmd_check(cmd, dirs=SOURCE_DIRS, *, From 3aeb32d05e1df8bb0bba242a60e2fb5cc3e816c8 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Wed, 28 Aug 2019 17:56:55 -0600 Subject: [PATCH 084/118] Clean up iter_files(). --- .../test_c_analyzer_common/test_files.py | 516 +++++++++++++----- Tools/c-analyzer/c_analyzer_common/files.py | 152 +++++- Tools/c-analyzer/c_symbols/resolve.py | 2 +- Tools/c-analyzer/c_symbols/source.py | 2 +- 4 files changed, 505 insertions(+), 167 deletions(-) diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/test_files.py b/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/test_files.py index 0ab5a7bd4966c9..92d2a2ab3abea8 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/test_files.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/test_files.py @@ -3,7 +3,9 @@ from .. import tool_imports_for_tests with tool_imports_for_tests(): - from c_analyzer_common.files import iter_files + from c_analyzer_common.files import ( + iter_files, _walk_tree, glob_tree, + ) def fixpath(filename): @@ -12,6 +14,8 @@ def fixpath(filename): class IterFilesTests(unittest.TestCase): + maxDiff = None + _return_walk = None @property @@ -22,221 +26,445 @@ def calls(self): self._calls = [] return self._calls - def _walk(self, dirname): - self.calls.append(('_walk', (dirname,))) + def set_files(self, *filesperroot): + roots = [] + result = [] + for root, files in filesperroot: + root = fixpath(root) + roots.append(root) + result.append([os.path.join(root, fixpath(f)) + for f in files]) + self._return_walk = result + return roots + + def _walk(self, root, *, suffix=None, walk=None): + self.calls.append(('_walk', (root, suffix, walk))) return iter(self._return_walk.pop(0)) - def test_basic(self): - self._return_walk = [ - [('spam', (), ('file1', 'file2')), - ], - [(fixpath('eggs/ham'), (), ('file3',)), - ], - ] - dirnames = [ - 'spam', - fixpath('eggs/ham'), - ] - filter_by_name = None + def _glob(self, root, *, suffix=None): + self.calls.append(('_glob', (root, suffix))) + return iter(self._return_walk.pop(0)) - files = list(iter_files(dirnames, filter_by_name, + def test_typical(self): + dirnames = self.set_files( + ('spam', ['file1.c', 'file2.c']), + ('eggs', ['ham/file3.h']), + ) + suffixes = ('.c', '.h') + + files = list(iter_files(dirnames, suffixes, + _glob=self._glob, _walk=self._walk)) self.assertEqual(files, [ - fixpath('spam/file1'), - fixpath('spam/file2'), - fixpath('eggs/ham/file3'), + fixpath('spam/file1.c'), + fixpath('spam/file2.c'), + fixpath('eggs/ham/file3.h'), ]) self.assertEqual(self.calls, [ - ('_walk', ('spam',)), - ('_walk', (fixpath('eggs/ham'),)), + ('_walk', ('spam', None, _walk_tree)), + ('_walk', ('eggs', None, _walk_tree)), ]) - def test_no_dirnames(self): - dirnames = [] - filter_by_name = None + def test_single_root(self): + self._return_walk = [ + [fixpath('spam/file1.c'), fixpath('spam/file2.c')], + ] - files = list(iter_files(dirnames, filter_by_name, + files = list(iter_files('spam', '.c', + _glob=self._glob, _walk=self._walk)) - self.assertEqual(files, []) - self.assertEqual(self.calls, []) + self.assertEqual(files, [ + fixpath('spam/file1.c'), + fixpath('spam/file2.c'), + ]) + self.assertEqual(self.calls, [ + ('_walk', ('spam', '.c', _walk_tree)), + ]) - def test_no_filter(self): + def test_one_root(self): self._return_walk = [ - [('spam', (), ('file1', 'file2.c', 'file3.h', 'file4.o')), - ], - ] - dirnames = [ - 'spam', + [fixpath('spam/file1.c'), fixpath('spam/file2.c')], ] - filter_by_name = None - files = list(iter_files(dirnames, filter_by_name, + files = list(iter_files(['spam'], '.c', + _glob=self._glob, _walk=self._walk)) self.assertEqual(files, [ - fixpath('spam/file1'), + fixpath('spam/file1.c'), fixpath('spam/file2.c'), - fixpath('spam/file3.h'), - fixpath('spam/file4.o'), ]) self.assertEqual(self.calls, [ - ('_walk', ('spam',)), + ('_walk', ('spam', '.c', _walk_tree)), ]) - def test_no_files(self): - self._return_walk = [ - [('spam', (), ()), - ], - [(fixpath('eggs/ham'), (), ()), - ], - ] - dirnames = [ - 'spam', - fixpath('eggs/ham'), - ] - filter_by_name = None + def test_multiple_roots(self): + dirnames = self.set_files( + ('spam', ['file1.c', 'file2.c']), + ('eggs', ['ham/file3.c']), + ) - files = list(iter_files(dirnames, filter_by_name, + files = list(iter_files(dirnames, '.c', + _glob=self._glob, _walk=self._walk)) - self.assertEqual(files, []) + self.assertEqual(files, [ + fixpath('spam/file1.c'), + fixpath('spam/file2.c'), + fixpath('eggs/ham/file3.c'), + ]) self.assertEqual(self.calls, [ - ('_walk', ('spam',)), - ('_walk', (fixpath('eggs/ham'),)), + ('_walk', ('spam', '.c', _walk_tree)), + ('_walk', ('eggs', '.c', _walk_tree)), ]) - def test_tree(self): + def test_no_roots(self): + files = list(iter_files([], '.c', + _glob=self._glob, + _walk=self._walk)) + + self.assertEqual(files, []) + self.assertEqual(self.calls, []) + + def test_single_suffix(self): self._return_walk = [ - [('spam', ('sub1', 'sub2', 'sub3'), ('file1',)), - (fixpath('spam/sub1'), ('sub1sub1',), ('file2', 'file3')), - (fixpath('spam/sub1/sub1sub1'), (), ('file4',)), - (fixpath('spam/sub2'), (), ()), - (fixpath('spam/sub3'), (), ('file5',)), + [fixpath('spam/file1.c'), + fixpath('spam/eggs/file3.c'), ], - [(fixpath('eggs/ham'), (), ('file6',)), - ], - ] - dirnames = [ - 'spam', - fixpath('eggs/ham'), ] - filter_by_name = None - files = list(iter_files(dirnames, filter_by_name, + files = list(iter_files('spam', '.c', + _glob=self._glob, _walk=self._walk)) self.assertEqual(files, [ - fixpath('spam/file1'), - fixpath('spam/sub1/file2'), - fixpath('spam/sub1/file3'), - fixpath('spam/sub1/sub1sub1/file4'), - fixpath('spam/sub3/file5'), - fixpath('eggs/ham/file6'), + fixpath('spam/file1.c'), + fixpath('spam/eggs/file3.c'), ]) self.assertEqual(self.calls, [ - ('_walk', ('spam',)), - ('_walk', (fixpath('eggs/ham'),)), + ('_walk', ('spam', '.c', _walk_tree)), ]) - def test_filter_suffixes(self): + def test_one_suffix(self): self._return_walk = [ - [('spam', (), ('file1', 'file2.c', 'file3.h', 'file4.o')), + [fixpath('spam/file1.c'), + fixpath('spam/file1.h'), + fixpath('spam/file1.o'), + fixpath('spam/eggs/file3.c'), ], ] - dirnames = [ - 'spam', - ] - filter_by_name = ('.c', '.h') - files = list(iter_files(dirnames, filter_by_name, + files = list(iter_files('spam', ['.c'], + _glob=self._glob, _walk=self._walk)) self.assertEqual(files, [ - fixpath('spam/file2.c'), - fixpath('spam/file3.h'), + fixpath('spam/file1.c'), + fixpath('spam/eggs/file3.c'), ]) self.assertEqual(self.calls, [ - ('_walk', ('spam',)), + ('_walk', ('spam', None, _walk_tree)), ]) - def test_some_filtered(self): + def test_multiple_suffixes(self): self._return_walk = [ - [('spam', (), ('file1', 'file2', 'file3', 'file4')), + [fixpath('spam/file1.c'), + fixpath('spam/file1.h'), + fixpath('spam/file1.o'), + fixpath('spam/eggs/file3.c'), ], ] - dirnames = [ - 'spam', - ] - def filter_by_name(filename, results=[False, True, False, True]): - self.calls.append(('filter_by_name', (filename,))) - return results.pop(0) - files = list(iter_files(dirnames, filter_by_name, + files = list(iter_files('spam', ('.c', '.h'), + _glob=self._glob, _walk=self._walk)) self.assertEqual(files, [ - fixpath('spam/file2'), - fixpath('spam/file4'), + fixpath('spam/file1.c'), + fixpath('spam/file1.h'), + fixpath('spam/eggs/file3.c'), ]) self.assertEqual(self.calls, [ - ('_walk', ('spam',)), - ('filter_by_name', ('file1',)), - ('filter_by_name', ('file2',)), - ('filter_by_name', ('file3',)), - ('filter_by_name', ('file4',)), + ('_walk', ('spam', None, _walk_tree)), ]) - def test_none_filtered(self): - self._return_walk = [ - [('spam', (), ('file1', 'file2', 'file3', 'file4')), - ], - ] - dirnames = [ - 'spam', - ] - def filter_by_name(filename, results=[True, True, True, True]): - self.calls.append(('filter_by_name', (filename,))) - return results.pop(0) - - files = list(iter_files(dirnames, filter_by_name, + def test_no_suffix(self): + expected = [fixpath('spam/file1.c'), + fixpath('spam/file1.h'), + fixpath('spam/file1.o'), + fixpath('spam/eggs/file3.c'), + ] + for suffix in (None, '', ()): + with self.subTest(suffix): + self.calls.clear() + self._return_walk = [list(expected)] + + files = list(iter_files('spam', suffix, + _glob=self._glob, + _walk=self._walk)) + + self.assertEqual(files, expected) + self.assertEqual(self.calls, [ + ('_walk', ('spam', suffix, _walk_tree)), + ]) + + def test_relparent(self): + dirnames = self.set_files( + ('/x/y/z/spam', ['file1.c', 'file2.c']), + ('/x/y/z/eggs', ['ham/file3.c']), + ) + + files = list(iter_files(dirnames, '.c', fixpath('/x/y'), + _glob=self._glob, _walk=self._walk)) self.assertEqual(files, [ - fixpath('spam/file1'), - fixpath('spam/file2'), - fixpath('spam/file3'), - fixpath('spam/file4'), + fixpath('z/spam/file1.c'), + fixpath('z/spam/file2.c'), + fixpath('z/eggs/ham/file3.c'), ]) self.assertEqual(self.calls, [ - ('_walk', ('spam',)), - ('filter_by_name', ('file1',)), - ('filter_by_name', ('file2',)), - ('filter_by_name', ('file3',)), - ('filter_by_name', ('file4',)), + ('_walk', ('/x/y/z/spam', '.c', _walk_tree)), + ('_walk', ('/x/y/z/eggs', '.c', _walk_tree)), ]) - def test_all_filtered(self): - self._return_walk = [ - [('spam', (), ('file1', 'file2', 'file3', 'file4')), - ], - ] - dirnames = [ - 'spam', - ] - def filter_by_name(filename, results=[False, False, False, False]): - self.calls.append(('filter_by_name', (filename,))) - return results.pop(0) + def test_glob(self): + dirnames = self.set_files( + ('spam', ['file1.c', 'file2.c']), + ('eggs', ['ham/file3.c']), + ) - files = list(iter_files(dirnames, filter_by_name, - _walk=self._walk)) + files = list(iter_files(dirnames, '.c', + get_files=glob_tree, + _walk=self._walk, + _glob=self._glob)) - self.assertEqual(files, []) + self.assertEqual(files, [ + fixpath('spam/file1.c'), + fixpath('spam/file2.c'), + fixpath('eggs/ham/file3.c'), + ]) self.assertEqual(self.calls, [ - ('_walk', ('spam',)), - ('filter_by_name', ('file1',)), - ('filter_by_name', ('file2',)), - ('filter_by_name', ('file3',)), - ('filter_by_name', ('file4',)), + ('_glob', ('spam', '.c')), + ('_glob', ('eggs', '.c')), + ]) + + + def test_alt_walk_func(self): + dirnames = self.set_files( + ('spam', ['file1.c', 'file2.c']), + ('eggs', ['ham/file3.c']), + ) + def get_files(root): + return None + + files = list(iter_files(dirnames, '.c', + get_files=get_files, + _walk=self._walk, + _glob=self._glob)) + + self.assertEqual(files, [ + fixpath('spam/file1.c'), + fixpath('spam/file2.c'), + fixpath('eggs/ham/file3.c'), ]) + self.assertEqual(self.calls, [ + ('_walk', ('spam', '.c', get_files)), + ('_walk', ('eggs', '.c', get_files)), + ]) + + + + + + +# def test_no_dirnames(self): +# dirnames = [] +# filter_by_name = None +# +# files = list(iter_files(dirnames, filter_by_name, +# _walk=self._walk)) +# +# self.assertEqual(files, []) +# self.assertEqual(self.calls, []) +# +# def test_no_filter(self): +# self._return_walk = [ +# [('spam', (), ('file1', 'file2.c', 'file3.h', 'file4.o')), +# ], +# ] +# dirnames = [ +# 'spam', +# ] +# filter_by_name = None +# +# files = list(iter_files(dirnames, filter_by_name, +# _walk=self._walk)) +# +# self.assertEqual(files, [ +# fixpath('spam/file1'), +# fixpath('spam/file2.c'), +# fixpath('spam/file3.h'), +# fixpath('spam/file4.o'), +# ]) +# self.assertEqual(self.calls, [ +# ('_walk', ('spam',)), +# ]) +# +# def test_no_files(self): +# self._return_walk = [ +# [('spam', (), ()), +# ], +# [(fixpath('eggs/ham'), (), ()), +# ], +# ] +# dirnames = [ +# 'spam', +# fixpath('eggs/ham'), +# ] +# filter_by_name = None +# +# files = list(iter_files(dirnames, filter_by_name, +# _walk=self._walk)) +# +# self.assertEqual(files, []) +# self.assertEqual(self.calls, [ +# ('_walk', ('spam',)), +# ('_walk', (fixpath('eggs/ham'),)), +# ]) +# +# def test_tree(self): +# self._return_walk = [ +# [('spam', ('sub1', 'sub2', 'sub3'), ('file1',)), +# (fixpath('spam/sub1'), ('sub1sub1',), ('file2', 'file3')), +# (fixpath('spam/sub1/sub1sub1'), (), ('file4',)), +# (fixpath('spam/sub2'), (), ()), +# (fixpath('spam/sub3'), (), ('file5',)), +# ], +# [(fixpath('eggs/ham'), (), ('file6',)), +# ], +# ] +# dirnames = [ +# 'spam', +# fixpath('eggs/ham'), +# ] +# filter_by_name = None +# +# files = list(iter_files(dirnames, filter_by_name, +# _walk=self._walk)) +# +# self.assertEqual(files, [ +# fixpath('spam/file1'), +# fixpath('spam/sub1/file2'), +# fixpath('spam/sub1/file3'), +# fixpath('spam/sub1/sub1sub1/file4'), +# fixpath('spam/sub3/file5'), +# fixpath('eggs/ham/file6'), +# ]) +# self.assertEqual(self.calls, [ +# ('_walk', ('spam',)), +# ('_walk', (fixpath('eggs/ham'),)), +# ]) +# +# def test_filter_suffixes(self): +# self._return_walk = [ +# [('spam', (), ('file1', 'file2.c', 'file3.h', 'file4.o')), +# ], +# ] +# dirnames = [ +# 'spam', +# ] +# filter_by_name = ('.c', '.h') +# +# files = list(iter_files(dirnames, filter_by_name, +# _walk=self._walk)) +# +# self.assertEqual(files, [ +# fixpath('spam/file2.c'), +# fixpath('spam/file3.h'), +# ]) +# self.assertEqual(self.calls, [ +# ('_walk', ('spam',)), +# ]) +# +# def test_some_filtered(self): +# self._return_walk = [ +# [('spam', (), ('file1', 'file2', 'file3', 'file4')), +# ], +# ] +# dirnames = [ +# 'spam', +# ] +# def filter_by_name(filename, results=[False, True, False, True]): +# self.calls.append(('filter_by_name', (filename,))) +# return results.pop(0) +# +# files = list(iter_files(dirnames, filter_by_name, +# _walk=self._walk)) +# +# self.assertEqual(files, [ +# fixpath('spam/file2'), +# fixpath('spam/file4'), +# ]) +# self.assertEqual(self.calls, [ +# ('_walk', ('spam',)), +# ('filter_by_name', ('file1',)), +# ('filter_by_name', ('file2',)), +# ('filter_by_name', ('file3',)), +# ('filter_by_name', ('file4',)), +# ]) +# +# def test_none_filtered(self): +# self._return_walk = [ +# [('spam', (), ('file1', 'file2', 'file3', 'file4')), +# ], +# ] +# dirnames = [ +# 'spam', +# ] +# def filter_by_name(filename, results=[True, True, True, True]): +# self.calls.append(('filter_by_name', (filename,))) +# return results.pop(0) +# +# files = list(iter_files(dirnames, filter_by_name, +# _walk=self._walk)) +# +# self.assertEqual(files, [ +# fixpath('spam/file1'), +# fixpath('spam/file2'), +# fixpath('spam/file3'), +# fixpath('spam/file4'), +# ]) +# self.assertEqual(self.calls, [ +# ('_walk', ('spam',)), +# ('filter_by_name', ('file1',)), +# ('filter_by_name', ('file2',)), +# ('filter_by_name', ('file3',)), +# ('filter_by_name', ('file4',)), +# ]) +# +# def test_all_filtered(self): +# self._return_walk = [ +# [('spam', (), ('file1', 'file2', 'file3', 'file4')), +# ], +# ] +# dirnames = [ +# 'spam', +# ] +# def filter_by_name(filename, results=[False, False, False, False]): +# self.calls.append(('filter_by_name', (filename,))) +# return results.pop(0) +# +# files = list(iter_files(dirnames, filter_by_name, +# _walk=self._walk)) +# +# self.assertEqual(files, []) +# self.assertEqual(self.calls, [ +# ('_walk', ('spam',)), +# ('filter_by_name', ('file1',)), +# ('filter_by_name', ('file2',)), +# ('filter_by_name', ('file3',)), +# ('filter_by_name', ('file4',)), +# ]) diff --git a/Tools/c-analyzer/c_analyzer_common/files.py b/Tools/c-analyzer/c_analyzer_common/files.py index 06cc83c58b2f11..c97dc466509d90 100644 --- a/Tools/c-analyzer/c_analyzer_common/files.py +++ b/Tools/c-analyzer/c_analyzer_common/files.py @@ -1,27 +1,137 @@ +import glob import os import os.path -def iter_files(dirnames, filter_by_name=None, *, - _walk=os.walk, +C_SOURCE_SUFFIXES = ('.c', '.h') + + +def _walk_tree(root): + # A wrapper around os.walk that resolves the filenames. + for parent, _, names in _walk(root): + for name in names: + yield os.path.join(parent, name) + + +def walk_tree(root, *, + suffix=None, + walk=_walk_tree, + ): + """Yield each file in the tree under the given directory name. + + If "suffix" is provided then only files with that suffix will + be included. + """ + if suffix and not isinstance(suffix, str): + raise ValueError('suffix must be a string') + + for parent, _, names in walk(root): + for name in names: + if suffix and not name.endswith(suffix): + continue + yield os.path.join(parent, name) + + +def glob_tree(root, *, + suffix=None, + _glob=glob.iglob, + ): + """Yield each file in the tree under the given directory name. + + If "suffix" is provided then only files with that suffix will + be included. + """ + suffix = suffix or '' + if not isinstance(suffix, str): + raise ValueError('suffix must be a string') + + for filename in _glob(f'{root}/*{suffix}'): + yield filename + for filename in _glob(f'{root}/**/*{suffix}'): + yield filename + + +def iter_files(root, suffix=None, relparent=None, *, + get_files=os.walk, + _glob=glob_tree, + _walk=walk_tree, ): - """Yield each file in the tree for each of the given directory names.""" - if filter_by_name is None: - def filter_by_name(name): - return True - elif not callable(filter_by_name): - suffixes = tuple(filter_by_name) - def filter_by_name(name): - for suffix in suffixes: - if name.endswith(suffix): - return True - return False - - for dirname in dirnames: - for parent, _, names in _walk(dirname): - if parent.endswith(os.path.join('', 'Include', 'cpython')): + """Yield each file in the tree under the given directory name. + + If "root" is a non-string iterable then do the same for each of + those trees. + + If "suffix" is provided then only files with that suffix will + be included. + + if "relparent" is provided then it is used to resolve each + filename as a relative path. + """ + if not isinstance(root, str): + roots = root + for root in roots: + yield from iter_files(root, suffix, relparent, + get_files=get_files, + _glob=_glob, _walk=_walk) + return + + # Use the right "walk" function. + if get_files in (glob.glob, glob.iglob, glob_tree): + get_files = _glob + else: + _files = _walk_tree if get_files in (os.walk, walk_tree) else get_files + get_files = (lambda *a, **k: _walk(*a, walk=_files, **k)) + + # Handle a single suffix. + if suffix and not isinstance(suffix, str): + filenames = get_files(root) + suffix = tuple(suffix) + else: + filenames = get_files(root, suffix=suffix) + suffix = None + + for filename in filenames: + if suffix and not isinstance(suffix, str): # multiple suffixes + if not filename.endswith(suffix): continue - for name in names: - if not filter_by_name(name): - continue - yield os.path.join(parent, name) + if relparent: + filename = os.path.relpath(filename, relparent) + yield filename + + +def iter_files_by_suffix(root, suffixes, relparent=None, *, + walk=walk_tree, + _iter_files=iter_files, + ): + """Yield each file in the tree that has the given suffixes. + + Unlike iter_files(), the results are in the original suffix order. + """ + if isinstance(suffixes, str): + suffixes = [suffixes] + # XXX Ignore repeated suffixes? + for suffix in suffixes: + yield from _iter_files(root, None, relparent, + get_files=get_files, + ) + + +def iter_cpython_files(*, + walk=walk_tree, + _files=iter_files_by_suffix, + ): + """Yield each file in the tree for each of the given directory names.""" + excludedtrees = [ + os.path.join('Include', 'cpython', ''), + ] + def is_excluded(filename): + for root in excludedtrees: + if filename.startswith(root): + return True + return False + for filename in _files(SOURCE_DIRS, C_SOURCE_SUFFIXES, REPO_ROOT, + walk=walk, + ): + if is_excluded(filename): + continue + yield filename diff --git a/Tools/c-analyzer/c_symbols/resolve.py b/Tools/c-analyzer/c_symbols/resolve.py index 954ac3ed4420e6..10383a5a86f14f 100644 --- a/Tools/c-analyzer/c_symbols/resolve.py +++ b/Tools/c-analyzer/c_symbols/resolve.py @@ -48,7 +48,7 @@ def look_up_known_symbol(symbol, knownvars, *, def find_in_source(symbol, dirnames, *, _perfilecache={}, _find_symbol=_find_symbol, - _iter_files=files.iter_files, + _iter_files=files.iter_files_by_suffix, ): """Return the Variable matching the given Symbol. diff --git a/Tools/c-analyzer/c_symbols/source.py b/Tools/c-analyzer/c_symbols/source.py index b37699c2c71cae..a7248104c94ca9 100644 --- a/Tools/c-analyzer/c_symbols/source.py +++ b/Tools/c-analyzer/c_symbols/source.py @@ -8,7 +8,7 @@ def find_symbol(name, dirnames, *, _perfilecache, - _iter_files=files.iter_files, + _iter_files=files.iter_files_by_suffix, **kwargs ): """Return (filename, funcname, vartype) for the matching Symbol.""" From 8a97e503190b92e6a9affbbc3038eb290fef0ed1 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 30 Aug 2019 18:27:08 -0600 Subject: [PATCH 085/118] Fix typos. --- Tools/c-analyzer/c_analyzer_common/files.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/Tools/c-analyzer/c_analyzer_common/files.py b/Tools/c-analyzer/c_analyzer_common/files.py index c97dc466509d90..b3cd16c8dc0080 100644 --- a/Tools/c-analyzer/c_analyzer_common/files.py +++ b/Tools/c-analyzer/c_analyzer_common/files.py @@ -2,11 +2,15 @@ import os import os.path +from . import SOURCE_DIRS, REPO_ROOT + C_SOURCE_SUFFIXES = ('.c', '.h') -def _walk_tree(root): +def _walk_tree(root, *, + _walk=os.walk, + ): # A wrapper around os.walk that resolves the filenames. for parent, _, names in _walk(root): for name in names: @@ -25,11 +29,10 @@ def walk_tree(root, *, if suffix and not isinstance(suffix, str): raise ValueError('suffix must be a string') - for parent, _, names in walk(root): - for name in names: - if suffix and not name.endswith(suffix): - continue - yield os.path.join(parent, name) + for filename in walk(root): + if suffix and not filename.endswith(suffix): + continue + yield filename def glob_tree(root, *, @@ -111,9 +114,7 @@ def iter_files_by_suffix(root, suffixes, relparent=None, *, suffixes = [suffixes] # XXX Ignore repeated suffixes? for suffix in suffixes: - yield from _iter_files(root, None, relparent, - get_files=get_files, - ) + yield from _iter_files(root, suffix, relparent) def iter_cpython_files(*, From 51d5a195de752d99ae6972e8785e9a793de8bc78 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 2 Sep 2019 17:42:11 -0600 Subject: [PATCH 086/118] Minor fix to find/resolve. --- Tools/c-analyzer/c_statics/find.py | 8 ++++---- Tools/c-analyzer/c_symbols/resolve.py | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Tools/c-analyzer/c_statics/find.py b/Tools/c-analyzer/c_statics/find.py index e828c77cf8487b..4dedfad04e89eb 100644 --- a/Tools/c-analyzer/c_statics/find.py +++ b/Tools/c-analyzer/c_statics/find.py @@ -1,3 +1,4 @@ +from c_analyzer_common import SOURCE_DIRS from c_symbols import ( info as s_info, binary as b_symbols, @@ -23,17 +24,16 @@ def statics_from_binary(binfile=b_symbols.PYTHON, *, """ symbols = _iter_symbols(binfile, find_local_symbol=None) symbols = list(symbols) - #import c_analyzer_common._generate - #c_analyzer_common._generate.known_file(symbols) for variable in _resolve(symbols, - resolve=_get_symbol_resolver(knownvars, dirnames), + #resolve=_get_symbol_resolver(knownvars, dirnames), + resolve=_get_symbol_resolver(knownvars), ): if not variable.isstatic: continue yield variable -def statics_from_declarations(dirnames, *, +def statics_from_declarations(dirnames=SOURCE_DIRS, *, known=None, ): """Yield a Variable for each found declaration. diff --git a/Tools/c-analyzer/c_symbols/resolve.py b/Tools/c-analyzer/c_symbols/resolve.py index 10383a5a86f14f..bad2bdbe7d50a8 100644 --- a/Tools/c-analyzer/c_symbols/resolve.py +++ b/Tools/c-analyzer/c_symbols/resolve.py @@ -89,9 +89,9 @@ def resolve_known(symbol): if found is None: return None elif symbol.funcname == UNKNOWN: - knownvars.pop(var.id) + knownvars.pop(found.id) elif not symbol.filename or symbol.filename == UNKNOWN: - knownvars.pop(var.id) + knownvars.pop(found.id) return found if dirnames: def resolve(symbol): @@ -127,7 +127,7 @@ def symbols_to_variables(symbols, *, continue resolved = resolve(symbol) if resolved is None: - raise NotImplementedError(symbol) + #raise NotImplementedError(symbol) resolved = info.Variable( id=symbol.id, vartype=UNKNOWN, From 19b9f97964d8ce534ac8539bd7e36f1fbdc86b44 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 2 Sep 2019 17:42:34 -0600 Subject: [PATCH 087/118] Include ID in error message. --- Tools/c-analyzer/c_parser/info.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Tools/c-analyzer/c_parser/info.py b/Tools/c-analyzer/c_parser/info.py index 0e60a011c5dec3..da4bd48e265de0 100644 --- a/Tools/c-analyzer/c_parser/info.py +++ b/Tools/c-analyzer/c_parser/info.py @@ -49,15 +49,18 @@ def _validate_id(self): raise TypeError('missing id') if not self.filename or self.filename == info.UNKNOWN: - raise TypeError('id missing filename') + raise TypeError(f'id missing filename ({self.id})') if self.funcname and self.funcname == info.UNKNOWN: - raise TypeError('id missing funcname') + raise TypeError(f'id missing funcname ({self.id})') self.id.validate() def validate(self): """Fail if the object is invalid (i.e. init with bad data).""" + if self.name == 'id': # XXX drop this case + return + self._validate_id() if self.vartype is None or self.vartype == info.UNKNOWN: From a9c68c56b0912332ecc66e0e6a55d9a838efc12d Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 2 Sep 2019 17:44:11 -0600 Subject: [PATCH 088/118] Add some "naive" parsing tools. --- Tools/c-analyzer/c_parser/naive.py | 180 +++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 Tools/c-analyzer/c_parser/naive.py diff --git a/Tools/c-analyzer/c_parser/naive.py b/Tools/c-analyzer/c_parser/naive.py new file mode 100644 index 00000000000000..e9524e30e88726 --- /dev/null +++ b/Tools/c-analyzer/c_parser/naive.py @@ -0,0 +1,180 @@ +import re + +from c_analyzer_common.info import UNKNOWN + +from .info import Variable +from .preprocessor import _iter_clean_lines + + +_NOT_SET = object() + + +def get_srclines(filename, *, + cache=None, + _open=open, + _iter_lines=_iter_clean_lines, + ): + """Return the file's lines as a list. + + Each line will have trailing whitespace removed (including newline). + + If a cache is given the it is used. + """ + if cache is not None: + try: + return cache[filename] + except KeyError: + pass + + with _open(filename) as srcfile: + srclines = [line + for _, line in _iter_lines(srcfile) + if not line.startswith('#')] + for i, line in enumerate(srclines): + srclines[i] = line.rstrip() + + if cache is not None: + cache[filename] = srclines + return srclines + + +def parse_variable_declaration(srcline): + """Return (name, decl) for the given declaration line.""" + # XXX possible false negatives... + decl, sep, _ = srcline.partition('=') + if not sep: + if not srcline.endswith(';'): + return None, None + decl = decl.strip(';') + decl = decl.strip() + m = re.match(r'.*\b(\w+)\s*(?:\[[^\]]*\])?$', decl) + if not m: + return None, None + name = m.group(1) + return name, decl + + +def parse_variable(srcline, funcname=None): + """Return a Variable for the variable declared on the line (or None).""" + line = srcline.strip() + + # XXX Handle more than just static variables. + if line.startswith('static '): + if '(' in line and '[' not in line: + # a function + return None, None + return parse_variable_declaration(line) + else: + return None, None + + +def iter_variables(filename, *, + srccache=None, + parse_variable=None, + _get_srclines=get_srclines, + _default_parse_variable=parse_variable, + ): + """Yield a Variable for each in the given source file.""" + if parse_variable is None: + parse_variable = _default_parse_variable + + indent = '' + prev = '' + funcname = None + for line in _get_srclines(filename, cache=srccache): + # remember current funcname + if funcname: + if line == indent + '}': + funcname = None + continue + else: + if '(' in prev and line == indent + '{': + if not prev.startswith('__attribute__'): + funcname = prev.split('(')[0].split()[-1] + prev = '' + continue + indent = line[:-len(line.lstrip())] + prev = line + + info = parse_variable(line, funcname) + if isinstance(info, list): + for name, _funcname, decl in info: + yield Variable.from_parts(filename, _funcname, name, decl) + continue + name, decl = info + + if name is None: + continue + yield Variable.from_parts(filename, funcname, name, decl) + + +def _match_varid(variable, name, funcname, ignored=None): + if ignored and variable in ignored: + return False + + if variable.name != name: + return False + + if funcname == UNKNOWN: + if not variable.funcname: + return False + elif variable.funcname != funcname: + return False + + return True + + +def find_variable(filename, funcname, name, *, + ignored=None, + srccache=None, # {filename: lines} + parse_variable=None, + _iter_variables=iter_variables, + ): + """Return the matching variable. + + Return None if the variable is not found. + """ + for variable in _iter_variables(filename, + srccache=srccache, + parse_variable=parse_variable, + ): + if _match_varid(variable, name, funcname, ignored): + return variable + else: + return None + + +def find_variables(varids, filenames=None, *, + srccache=_NOT_SET, + parse_variable=None, + _find_symbol=find_variable, + ): + """Yield a Variable for each ID. + + If the variable is not found then its decl will be UNKNOWN. That + way there will be one resulting Variable per given ID. + """ + if srccache is _NOT_SET: + srccache = {} + + used = set() + for varid in varids: + if varid.filename and varid.filename != UNKNOWN: + srcfiles = [varid.filename] + else: + if not filenames: + yield Variable(varid, UNKNOWN) + continue + srcfiles = filenames + for filename in srcfiles: + found = _find_varid(filename, varid.funcname, varid.name, + ignored=used, + srccache=srccache, + parse_variable=parse_variable, + ) + if found: + yield found + used.add(found) + break + else: + yield Variable(varid, UNKNOWN) From 2af678175f524952b40a97d262f23711ee2a02a6 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 2 Sep 2019 17:44:56 -0600 Subject: [PATCH 089/118] Expand the capability of the "known" generator. --- .../c-analyzer/c_analyzer_common/_generate.py | 372 ++++++++++++++---- 1 file changed, 296 insertions(+), 76 deletions(-) diff --git a/Tools/c-analyzer/c_analyzer_common/_generate.py b/Tools/c-analyzer/c_analyzer_common/_generate.py index 193ac5c5a81c42..71aa744c2b7c19 100644 --- a/Tools/c-analyzer/c_analyzer_common/_generate.py +++ b/Tools/c-analyzer/c_analyzer_common/_generate.py @@ -5,100 +5,311 @@ import os.path import re -from c_statics import KNOWN_FILE, SOURCE_DIRS, REPO_ROOT +from c_parser.preprocessor import _iter_clean_lines +from c_parser.naive import ( + iter_variables, parse_variable_declaration, find_variables, + ) +from c_parser.info import Variable -from . import known +from . import SOURCE_DIRS, REPO_ROOT +from .known import DATA_FILE as KNOWN_FILE, HEADER as KNOWN_HEADER from .info import UNKNOWN, ID from .util import run_cmd, write_tsv +from .files import iter_cpython_files -@contextlib.contextmanager -def get_srclines(filename, srclines=None, *, - cache=None, - _open=open, - ): - if srclines is None: - if cache is None: - with _open(filename) as srcfile: - srclines = list(srcfile) +POTS = ('char ', 'wchar_t ', 'int ', 'Py_ssize_t ') +POTS += tuple('const ' + v for v in POTS) +STRUCTS = ('PyTypeObject', 'PyObject', 'PyMethodDef', 'PyModuleDef', 'grammar') + + +def _parse_static(line, funcname=None): + line = line.strip() + if line.startswith('static '): + if '(' in line and '[' not in line and ' = ' not in line: + return None, None + name, decl = parse_variable_declaration(line) + elif line.startswith(('Py_LOCAL(', 'Py_LOCAL_INLINE(')): + name, decl = parse_variable_declaration(line) + elif line.startswith('_Py_static_string('): + decl = line.strip(';').strip() + name = line.split('(')[1].split(',')[0].strip() + elif line.startswith('_Py_IDENTIFIER('): + decl = line.strip(';').strip() + name = 'PyId_' + line.split('(')[1].split(')')[0].strip() + elif funcname: + return None, None + + # global-only + elif line.startswith(POTS): # implied static + if '(' in line and '[' not in line and ' = ' not in line: + return None, None + name, decl = parse_variable_declaration(line) + elif line.startswith('PyAPI_DATA('): + name, decl = parse_variable_declaration(line) + elif line.startswith(STRUCTS) and line.endswith(' = {'): # implied static + name, decl = parse_variable_declaration(line) + elif line.startswith(STRUCTS) and line.endswith(' = NULL;'): # implied static + name, decl = parse_variable_declaration(line) + elif line.startswith('struct '): + if not line.endswith(' = {'): + return None, None + if not line.partition(' ')[2].startswith(STRUCTS): + return None, None + # implied static + name, decl = parse_variable_declaration(line) + elif line.startswith('PyDoc_VAR('): + decl = line.strip(';').strip() + name = line.split('(')[1].split(')')[0].strip() + + # file-specific + elif line.startswith(('SLOT1BINFULL(', 'SLOT1BIN(')): + # Objects/typeobject.c + funcname = line.split('(')[1].split(',')[0] + return [ + ('op_id', funcname, '_Py_static_string(op_id, OPSTR)'), + ('rop_id', funcname, '_Py_static_string(op_id, OPSTR)'), + ] + elif line.startswith('WRAP_METHOD('): + # Objects/weakrefobject.c + funcname, name = (v.strip() for v in line.split('(')[1].split(')')[0].split(',')) + return [ + ('PyId_' + name, funcname, f'_Py_IDENTIFIER({name})'), + ] + else: + return None, None + return name, decl + + +def _pop_cached(varcache, filename, funcname, name, *, + _iter_variables=iter_variables, + ): + # Look for the file. + try: + cached = varcache[filename] + except KeyError: + cached = varcache[filename] = {} + for variable in _iter_variables(filename, + parse_variable=_parse_static, + ): + variable._isstatic = True + cached[variable.id] = variable + for var in cached: + print(' ', var) + + # Look for the variable. + if funcname == UNKNOWN: + for varid in cached: + if varid.name == name: + break else: - try: - srclines = cache[filename] - except KeyError: - with open(filename) as srcfile: - srclines = [line.rstrip() for line in srcfile] - cache[filename] = srclines - yield srclines + return None + return cached.pop(varid) + else: + return cached.pop((filename, funcname, name), None) -def find_matching_variable(varid, filename, srclines=None, *, - cache=None, - _used=set(), - _get_srclines=get_srclines, +def find_matching_variable(varid, varcache, allfilenames, *, + _pop_cached=_pop_cached, ): - # XXX Store found variables in the cache instead of the src lines? - # Then we would pop from cache instead of using "_used". - name = varid.name - funcname = varid.funcname - with _get_srclines(filename, srclines, cache=cache) as srclines: - for line in srclines: - # XXX remember current funcname - if not re.match(rf'.*\b{name}\b', line): - continue - if funcname: - if not line.startswith(' '): + if varid.filename and varid.filename != UNKNOWN: + filenames = [varid.filename] + else: + filenames = allfilenames + for filename in filenames: + static = _pop_cached(varcache, filename, varid.funcname, varid.name) + if static is not None: + return static + else: + if varid.filename and varid.filename != UNKNOWN and varid.funcname is None: + for filename in allfilenames: + if not filename.endswith('.h'): continue - line = line.strip() - if not line.startswith('static '): - continue - filename = os.path.relpath(filename, REPO_ROOT) - newid = ID(filename, funcname, name) - if newid in _used: - continue - _used.add(newid) + static = _pop_cached(varcache, filename, None, varid.name) + if static is not None: + return static + return None - decl = line.split('=')[0].strip() - decl = decl.strip(';').strip() - return newid, decl - return varid, UNKNOWN +MULTILINE = { + # Python/Python-ast.c + 'Load_singleton': 'PyObject *', + 'Store_singleton': 'PyObject *', + 'Del_singleton': 'PyObject *', + 'AugLoad_singleton': 'PyObject *', + 'AugStore_singleton': 'PyObject *', + 'Param_singleton': 'PyObject *', + 'And_singleton': 'PyObject *', + 'Or_singleton': 'PyObject *', + 'Add_singleton': 'static PyObject *', + 'Sub_singleton': 'static PyObject *', + 'Mult_singleton': 'static PyObject *', + 'MatMult_singleton': 'static PyObject *', + 'Div_singleton': 'static PyObject *', + 'Mod_singleton': 'static PyObject *', + 'Pow_singleton': 'static PyObject *', + 'LShift_singleton': 'static PyObject *', + 'RShift_singleton': 'static PyObject *', + 'BitOr_singleton': 'static PyObject *', + 'BitXor_singleton': 'static PyObject *', + 'BitAnd_singleton': 'static PyObject *', + 'FloorDiv_singleton': 'static PyObject *', + 'Invert_singleton': 'static PyObject *', + 'Not_singleton': 'static PyObject *', + 'UAdd_singleton': 'static PyObject *', + 'USub_singleton': 'static PyObject *', + 'Eq_singleton': 'static PyObject *', + 'NotEq_singleton': 'static PyObject *', + 'Lt_singleton': 'static PyObject *', + 'LtE_singleton': 'static PyObject *', + 'Gt_singleton': 'static PyObject *', + 'GtE_singleton': 'static PyObject *', + 'Is_singleton': 'static PyObject *', + 'IsNot_singleton': 'static PyObject *', + 'In_singleton': 'static PyObject *', + 'NotIn_singleton': 'static PyObject *', + # Python/symtable.c + 'top': 'static identifier ', + 'lambda': 'static identifier ', + 'genexpr': 'static identifier ', + 'listcomp': 'static identifier ', + 'setcomp': 'static identifier ', + 'dictcomp': 'static identifier ', + '__class__': 'static identifier ', + # Python/compile.c + '__doc__': 'static PyObject *', + '__annotations__': 'static PyObject *', + # Objects/floatobject.c + 'double_format': 'static float_format_type ', + 'float_format': 'static float_format_type ', + 'detected_double_format': 'static float_format_type ', + 'detected_float_format': 'static float_format_type ', + # Parser/listnode.c + 'level': 'static int ', + 'atbol': 'static int ', + # Python/dtoa.c + 'private_mem': 'static double private_mem[PRIVATE_mem]', + 'pmem_next': 'static double *', + # Modules/_weakref.c + 'weakref_functions': 'static PyMethodDef ', +} +INLINE = { + # Modules/_tracemalloc.c + 'allocators': 'static struct { PyMemAllocatorEx mem; PyMemAllocatorEx raw; PyMemAllocatorEx obj; } ', + # Modules/faulthandler.c + 'fatal_error': 'static struct { int enabled; PyObject *file; int fd; int all_threads; PyInterpreterState *interp; void *exc_handler; } ', + 'thread': 'static struct { PyObject *file; int fd; PY_TIMEOUT_T timeout_us; int repeat; PyInterpreterState *interp; int exit; char *header; size_t header_len; PyThread_type_lock cancel_event; PyThread_type_lock running; } ', + # Modules/signalmodule.c + 'Handlers': 'static volatile struct { _Py_atomic_int tripped; PyObject *func; } Handlers[NSIG]', + 'wakeup': 'static volatile struct { SOCKET_T fd; int warn_on_full_buffer; int use_send; } ', + # Python/dynload_shlib.c + 'handles': 'static struct { dev_t dev; ino_t ino; void *handle; } handles[128]', + # Objects/obmalloc.c + '_PyMem_Debug': 'static struct { debug_alloc_api_t raw; debug_alloc_api_t mem; debug_alloc_api_t obj; } ', + # Python/bootstrap_hash.c + 'urandom_cache': 'static struct { int fd; dev_t st_dev; ino_t st_ino; } ', + } +FUNC = { + # Objects/object.c + '_Py_abstract_hack': 'Py_ssize_t (*_Py_abstract_hack)(PyObject *)', + # Parser/myreadline.c + 'PyOS_InputHook': 'int (*PyOS_InputHook)(void)', + # Python/pylifecycle.c + '_PyOS_mystrnicmp_hack': 'int (*_PyOS_mystrnicmp_hack)(const char *, const char *, Py_ssize_t)', + # Parser/myreadline.c + 'PyOS_ReadlineFunctionPointer': 'char *(*PyOS_ReadlineFunctionPointer)(FILE *, FILE *, const char *)', + } +IMPLIED = { + # Objects/boolobject.c + '_Py_FalseStruct': 'static struct _longobject ', + '_Py_TrueStruct': 'static struct _longobject ', + # Modules/config.c + '_PyImport_Inittab': 'struct _inittab _PyImport_Inittab[]', + } +GLOBALS = {} +GLOBALS.update(MULTILINE) +GLOBALS.update(INLINE) +GLOBALS.update(FUNC) +GLOBALS.update(IMPLIED) -def known_rows(symbols, *, - dirnames=SOURCE_DIRS, - _find_match=find_matching_variable, - ): - cache = {} - for symbol in symbols: - if symbol.filename and symbol.filename != UNKNOWN: - filenames = [symbol.filename] - else: - filenames = [] - for suffix in ('.c', '.h'): - for dirname in SOURCE_DIRS: - filenames.extend(glob.glob(f'{dirname}/*{suffix}')) - filenames.extend(glob.glob(f'{dirname}/**/*{suffix}')) - - if symbol.funcname == UNKNOWN: - print(symbol) - - if not filenames: - raise ValueError(f'no files found for dirnames {dirnames}') - for filename in filenames: - found, decl = _find_match(symbol.id, filename, cache=cache) - if decl != UNKNOWN: - break - # else we will have made at least one pass, so found will be - # symbol.id and decl will be UNKNOWN. +LOCALS = { + 'buildinfo': ('Modules/getbuildinfo.c', + 'Py_GetBuildInfo', + 'static char buildinfo[50 + sizeof(GITVERSION) + ((sizeof(GITTAG) > sizeof(GITBRANCH)) ? sizeof(GITTAG) : sizeof(GITBRANCH))]'), + 'methods': ('Python/codecs.c', + '_PyCodecRegistry_Init', + 'static struct { char *name; PyMethodDef def; } methods[]'), + } - yield ( - found.filename, - found.funcname or '-', - found.name, + +def _known(symbol): + if symbol.funcname: + if symbol.funcname != UNKNOWN or symbol.filename != UNKNOWN: + raise KeyError(symbol.name) + filename, funcname, decl = LOCALS[symbol.name] + varid = ID(filename, funcname, symbol.name) + elif not symbol.filename or symbol.filename == UNKNOWN: + raise KeyError(symbol.name) + else: + varid = symbol.id + try: + decl = GLOBALS[symbol.name] + except KeyError: + + if symbol.name.endswith('_methods'): + decl = 'static PyMethodDef ' + elif symbol.filename == 'Objects/exceptions.c' and symbol.name.startswith(('PyExc_', '_PyExc_')): + decl = 'static PyTypeObject ' + else: + raise + if symbol.name not in decl: + decl = decl + symbol.name + return Variable(varid, decl) + + +def known_row(varid, decl): + return ( + varid.filename, + varid.funcname or '-', + varid.name, 'variable', decl, ) +def known_rows(symbols, *, + cached=True, + _get_filenames=iter_cpython_files, + _find_match=find_matching_variable, + _find_symbols=find_variables, + _as_known=known_row, + ): + filenames = list(_get_filenames()) + cache = {} + if cached: + for symbol in symbols: + try: + found = _known(symbol) + except KeyError: + found = _find_match(symbol, cache, filenames) + if found is None: + found = Variable(symbol.id, UNKNOWN) + yield _as_known(found.id, found.vartype) + else: + raise NotImplementedError # XXX incorporate KNOWN + for static in _find_symbols(symbols, filenames, + srccache=cache, + parse_variable=_parse_static, + ): + #static = static._replace( + # filename=os.path.relpath(static.filename, REPO_ROOT)) + if static.funcname == UNKNOWN: + print(static) + if static.vartype== UNKNOWN: + print(static) + yield _as_known(static.id, static.vartype) + + def known_file(symbols, filename=None, *, _generate_rows=known_rows, ): @@ -106,4 +317,13 @@ def known_file(symbols, filename=None, *, filename = KNOWN_FILE + '.new' rows = _generate_rows(symbols) - write_tsv(filename, known.HEADER, rows) + write_tsv(filename, KNOWN_HEADER, rows) + + +if __name__ == '__main__': + from c_symbols import binary + symbols = binary.iter_symbols( + binary.PYTHON, + find_local_symbol=None, + ) + known_file(symbols) From aa8495abfffee3bcccf9d0a6371f3ba4a24018bc Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 2 Sep 2019 17:45:28 -0600 Subject: [PATCH 090/118] Update the "known" variables with generated values. --- Tools/c-analyzer/known.tsv | 1943 +++++++++++++++++++++++++++++++++++- 1 file changed, 1942 insertions(+), 1 deletion(-) diff --git a/Tools/c-analyzer/known.tsv b/Tools/c-analyzer/known.tsv index e8b5439e7682eb..708c7a2ab6c2e9 100644 --- a/Tools/c-analyzer/known.tsv +++ b/Tools/c-analyzer/known.tsv @@ -1 +1,1942 @@ -filename funcname name kind declaration +filename funcname name kind declaration +Modules/_abc.c - _abc_data_type variable static PyTypeObject _abc_data_type +Modules/_abc.c - abc_invalidation_counter variable static unsigned long long abc_invalidation_counter +Modules/_abc.c - _abcmodule variable static struct PyModuleDef _abcmodule +Python/import.c import_find_and_load accumulated variable static _PyTime_t accumulated +Modules/itertoolsmodule.c - accumulate_methods variable static PyMethodDef accumulate_methods +Modules/itertoolsmodule.c - accumulate_type variable static PyTypeObject accumulate_type +Python/Python-ast.c - Add_singleton variable static PyObject *Add_singleton +Python/Python-ast.c - Add_type variable static PyTypeObject *Add_type +Objects/genobject.c - ag_asend_freelist variable static PyAsyncGenASend *ag_asend_freelist[_PyAsyncGen_MAXFREELIST] +Objects/genobject.c - ag_asend_freelist_free variable static int ag_asend_freelist_free +Objects/genobject.c - ag_value_freelist variable static _PyAsyncGenWrappedValue *ag_value_freelist[_PyAsyncGen_MAXFREELIST] +Objects/genobject.c - ag_value_freelist_free variable static int ag_value_freelist_free +Python/Python-ast.c - alias_fields variable static char *alias_fields[] +Python/Python-ast.c - alias_type variable static PyTypeObject *alias_type +Modules/_tracemalloc.c - allocators variable static struct { PyMemAllocatorEx mem; PyMemAllocatorEx raw; PyMemAllocatorEx obj; } allocators +Python/Python-ast.c - And_singleton variable PyObject *And_singleton +Python/Python-ast.c - And_type variable static PyTypeObject *And_type +Python/Python-ast.c - AnnAssign_fields variable static char *AnnAssign_fields[] +Python/Python-ast.c - AnnAssign_type variable static PyTypeObject *AnnAssign_type +Python/compile.c - __annotations__ variable static PyObject *__annotations__ +Objects/obmalloc.c - arenas variable static struct arena_object* arenas +Python/Python-ast.c - arg_attributes variable static char *arg_attributes[] +Python/Python-ast.c - arg_fields variable static char *arg_fields[] +Python/Python-ast.c - arg_type variable static PyTypeObject *arg_type +Python/Python-ast.c - arguments_fields variable static char *arguments_fields[] +Python/Python-ast.c - arguments_type variable static PyTypeObject *arguments_type +Python/Python-ast.c - Assert_fields variable static char *Assert_fields[] +Python/compile.c compiler_assert assertion_error variable static PyObject *assertion_error +Python/Python-ast.c - Assert_type variable static PyTypeObject *Assert_type +Python/Python-ast.c - Assign_fields variable static char *Assign_fields[] +Python/Python-ast.c - Assign_type variable static PyTypeObject *Assign_type +Python/Python-ast.c - _astmodule variable static struct PyModuleDef _astmodule +Python/Python-ast.c - AST_type variable static PyTypeObject AST_type +Python/Python-ast.c - ast_type_getsets variable static PyGetSetDef ast_type_getsets[] +Python/Python-ast.c - ast_type_methods variable static PyMethodDef ast_type_methods +Python/Python-ast.c - AsyncFor_fields variable static char *AsyncFor_fields[] +Python/Python-ast.c - AsyncFor_type variable static PyTypeObject *AsyncFor_type +Python/Python-ast.c - AsyncFunctionDef_fields variable static char *AsyncFunctionDef_fields[] +Python/Python-ast.c - AsyncFunctionDef_type variable static PyTypeObject *AsyncFunctionDef_type +Objects/genobject.c - async_gen_as_async variable static PyAsyncMethods async_gen_as_async +Objects/genobject.c - async_gen_asend_as_async variable static PyAsyncMethods async_gen_asend_as_async +Objects/genobject.c - async_gen_asend_methods variable static PyMethodDef async_gen_asend_methods +Objects/genobject.c - async_gen_athrow_as_async variable static PyAsyncMethods async_gen_athrow_as_async +Objects/genobject.c - async_gen_athrow_methods variable static PyMethodDef async_gen_athrow_methods +Objects/genobject.c - async_gen_getsetlist variable static PyGetSetDef async_gen_getsetlist[] +Python/sysmodule.c - asyncgen_hooks_desc variable static PyStructSequence_Desc asyncgen_hooks_desc +Python/sysmodule.c - asyncgen_hooks_fields variable static PyStructSequence_Field asyncgen_hooks_fields[] +Python/sysmodule.c - AsyncGenHooksType variable static PyTypeObject AsyncGenHooksType +Objects/genobject.c - async_gen_memberlist variable static PyMemberDef async_gen_memberlist[] +Objects/genobject.c - async_gen_methods variable static PyMethodDef async_gen_methods +Python/Python-ast.c - AsyncWith_fields variable static char *AsyncWith_fields[] +Python/Python-ast.c - AsyncWith_type variable static PyTypeObject *AsyncWith_type +Parser/listnode.c - atbol variable static int atbol +Modules/atexitmodule.c - atexit_methods variable static PyMethodDef atexit_methods +Modules/atexitmodule.c - atexitmodule variable static struct PyModuleDef atexitmodule +Modules/atexitmodule.c - atexit_slots variable static PyModuleDef_Slot atexit_slots[] +Modules/_operator.c - attrgetter_methods variable static PyMethodDef attrgetter_methods +Modules/_operator.c - attrgetter_type variable static PyTypeObject attrgetter_type +Python/Python-ast.c - Attribute_fields variable static char *Attribute_fields[] +Python/Python-ast.c - Attribute_type variable static PyTypeObject *Attribute_type +Python/Python-ast.c - AugAssign_fields variable static char *AugAssign_fields[] +Python/Python-ast.c - AugAssign_type variable static PyTypeObject *AugAssign_type +Python/Python-ast.c - AugLoad_singleton variable PyObject *AugLoad_singleton +Python/Python-ast.c - AugLoad_type variable static PyTypeObject *AugLoad_type +Python/Python-ast.c - AugStore_singleton variable PyObject *AugStore_singleton +Python/Python-ast.c - AugStore_type variable static PyTypeObject *AugStore_type +Python/Python-ast.c - Await_fields variable static char *Await_fields[] +Python/Python-ast.c - Await_type variable static PyTypeObject *Await_type +Objects/exceptions.c - BaseException_getset variable static PyGetSetDef BaseException_getset[] +Objects/exceptions.c - BaseException_members variable static struct PyMemberDef BaseException_members[] +Objects/exceptions.c - BaseException_methods variable static PyMethodDef BaseException_methods +Modules/posixmodule.c - billion variable static PyObject *billion +Python/Python-ast.c - BinOp_fields variable static char *BinOp_fields[] +Python/Python-ast.c - BinOp_type variable static PyTypeObject *BinOp_type +Python/Python-ast.c - BitAnd_singleton variable static PyObject *BitAnd_singleton +Python/Python-ast.c - BitAnd_type variable static PyTypeObject *BitAnd_type +Python/Python-ast.c - BitOr_singleton variable static PyObject *BitOr_singleton +Python/Python-ast.c - BitOr_type variable static PyTypeObject *BitOr_type +Python/Python-ast.c - BitXor_singleton variable static PyObject *BitXor_singleton +Python/Python-ast.c - BitXor_type variable static PyTypeObject *BitXor_type +Objects/unicodeobject.c - bloom_linebreak variable static BLOOM_MASK bloom_linebreak +Objects/boolobject.c - bool_as_number variable static PyNumberMethods bool_as_number +Python/Python-ast.c - BoolOp_fields variable static char *BoolOp_fields[] +Python/Python-ast.c - boolop_type variable static PyTypeObject *boolop_type +Python/Python-ast.c - BoolOp_type variable static PyTypeObject *BoolOp_type +Python/_warnings.c is_internal_frame bootstrap_string variable static PyObject *bootstrap_string +Python/Python-ast.c - Break_type variable static PyTypeObject *Break_type +Python/ast.c - buf variable char *buf +Modules/_io/bufferedio.c - bufferediobase_methods variable static PyMethodDef bufferediobase_methods +Modules/_io/bufferedio.c - bufferedrandom_getset variable static PyGetSetDef bufferedrandom_getset[] +Modules/_io/bufferedio.c - bufferedrandom_members variable static PyMemberDef bufferedrandom_members[] +Modules/_io/bufferedio.c - bufferedrandom_methods variable static PyMethodDef bufferedrandom_methods +Modules/_io/bufferedio.c - bufferedreader_getset variable static PyGetSetDef bufferedreader_getset[] +Modules/_io/bufferedio.c - bufferedreader_members variable static PyMemberDef bufferedreader_members[] +Modules/_io/bufferedio.c - bufferedreader_methods variable static PyMethodDef bufferedreader_methods +Modules/_io/bufferedio.c - bufferedrwpair_getset variable static PyGetSetDef bufferedrwpair_getset[] +Modules/_io/bufferedio.c - bufferedrwpair_methods variable static PyMethodDef bufferedrwpair_methods +Modules/_io/bufferedio.c - bufferedwriter_getset variable static PyGetSetDef bufferedwriter_getset[] +Modules/_io/bufferedio.c - bufferedwriter_members variable static PyMemberDef bufferedwriter_members[] +Modules/_io/bufferedio.c - bufferedwriter_methods variable static PyMethodDef bufferedwriter_methods +Modules/getbuildinfo.c Py_GetBuildInfo buildinfo variable static char buildinfo[50 + sizeof(GITVERSION) + ((sizeof(GITTAG) > sizeof(GITBRANCH)) ? sizeof(GITTAG) : sizeof(GITBRANCH))] +Python/bltinmodule.c - builtin_methods variable static PyMethodDef builtin_methods +Python/bltinmodule.c - builtinsmodule variable static struct PyModuleDef builtinsmodule +Python/import.c PyImport_Import builtins_str variable static PyObject *builtins_str +Python/ceval.c make_pending_calls busy variable static int busy +Objects/bytearrayobject.c - bytearray_as_buffer variable static PyBufferProcs bytearray_as_buffer +Objects/bytearrayobject.c - bytearray_as_mapping variable static PyMappingMethods bytearray_as_mapping +Objects/bytearrayobject.c - bytearray_as_number variable static PyNumberMethods bytearray_as_number +Objects/bytearrayobject.c - bytearray_as_sequence variable static PySequenceMethods bytearray_as_sequence +Objects/bytearrayobject.c - bytearrayiter_methods variable static PyMethodDef bytearrayiter_methods +Objects/bytearrayobject.c - bytearray_methods variable static PyMethodDef bytearray_methods +Objects/bytesobject.c - bytes_as_buffer variable static PyBufferProcs bytes_as_buffer +Objects/bytesobject.c - bytes_as_mapping variable static PyMappingMethods bytes_as_mapping +Objects/bytesobject.c - bytes_as_number variable static PyNumberMethods bytes_as_number +Objects/bytesobject.c - bytes_as_sequence variable static PySequenceMethods bytes_as_sequence +Modules/_io/bytesio.c - bytesiobuf_as_buffer variable static PyBufferProcs bytesiobuf_as_buffer +Modules/_io/bytesio.c - bytesio_getsetlist variable static PyGetSetDef bytesio_getsetlist[] +Modules/_io/bytesio.c - bytesio_methods variable static PyMethodDef bytesio_methods +Objects/bytesobject.c - bytes_methods variable static PyMethodDef bytes_methods +Python/thread_pthread.h init_condattr ca variable static pthread_condattr_t ca +Python/Python-ast.c - Call_fields variable static char *Call_fields[] +Objects/iterobject.c - calliter_methods variable static PyMethodDef calliter_methods +Python/Python-ast.c - Call_type variable static PyTypeObject *Call_type +Objects/cellobject.c - cell_getsetlist variable static PyGetSetDef cell_getsetlist[] +Modules/itertoolsmodule.c - chain_methods variable static PyMethodDef chain_methods +Modules/itertoolsmodule.c - chain_type variable static PyTypeObject chain_type +Objects/bytesobject.c - characters variable static PyBytesObject *characters[UCHAR_MAX + 1] +Python/symtable.c - __class__ variable static identifier __class__ +Python/Python-ast.c - ClassDef_fields variable static char *ClassDef_fields[] +Python/Python-ast.c - ClassDef_type variable static PyTypeObject *ClassDef_type +Objects/funcobject.c - cm_getsetlist variable static PyGetSetDef cm_getsetlist[] +Objects/funcobject.c - cm_memberlist variable static PyMemberDef cm_memberlist[] +Python/Python-ast.c - cmpop_type variable static PyTypeObject *cmpop_type +Modules/_codecsmodule.c - _codecs_functions variable static PyMethodDef _codecs_functions[] +Modules/_codecsmodule.c - codecsmodule variable static struct PyModuleDef codecsmodule +Objects/codeobject.c - code_memberlist variable static PyMemberDef code_memberlist[] +Objects/codeobject.c - code_methods variable static PyMethodDef code_methods +Modules/_collectionsmodule.c - _collectionsmodule variable static struct PyModuleDef _collectionsmodule +Modules/itertoolsmodule.c - combinations_methods variable static PyMethodDef combinations_methods +Modules/itertoolsmodule.c - combinations_type variable static PyTypeObject combinations_type +Objects/typeobject.c object_new comma_id variable "_Py_static_string(comma_id, "", "")" +Python/Python-ast.c - Compare_fields variable static char *Compare_fields[] +Python/Python-ast.c - Compare_type variable static PyTypeObject *Compare_type +Modules/_winapi.c - completed variable int completed +Objects/complexobject.c - complex_as_number variable static PyNumberMethods complex_as_number +Objects/complexobject.c - complex_members variable static PyMemberDef complex_members[] +Objects/complexobject.c - complex_methods variable static PyMethodDef complex_methods +Python/Python-ast.c - comprehension_fields variable static char *comprehension_fields[] +Python/Python-ast.c - comprehension_type variable static PyTypeObject *comprehension_type +Modules/itertoolsmodule.c - compress_methods variable static PyMethodDef compress_methods +Modules/itertoolsmodule.c - compress_type variable static PyTypeObject compress_type +Python/thread_pthread.h - condattr_monotonic variable static pthread_condattr_t *condattr_monotonic +Python/Python-ast.c - Constant_fields variable static char *Constant_fields[] +Python/Python-ast.c - Constant_type variable static PyTypeObject *Constant_type +Python/Python-ast.c - Continue_type variable static PyTypeObject *Continue_type +Objects/longobject.c PyLong_FromString convmultmax_base variable static twodigits convmultmax_base[37] +Objects/longobject.c PyLong_FromString convwidth_base variable static int convwidth_base[37] +Objects/genobject.c - coro_as_async variable static PyAsyncMethods coro_as_async +Objects/genobject.c - coro_getsetlist variable static PyGetSetDef coro_getsetlist[] +Objects/genobject.c - coro_memberlist variable static PyMemberDef coro_memberlist[] +Objects/genobject.c - coro_methods variable static PyMethodDef coro_methods +Objects/genobject.c - coro_wrapper_methods variable static PyMethodDef coro_wrapper_methods +Modules/itertoolsmodule.c - count_methods variable static PyMethodDef count_methods +Modules/itertoolsmodule.c - count_type variable static PyTypeObject count_type +Python/context.c - ctx_freelist variable static PyContext *ctx_freelist +Python/context.c - ctx_freelist_len variable static int ctx_freelist_len +Modules/itertoolsmodule.c - cwr_methods variable static PyMethodDef cwr_methods +Modules/itertoolsmodule.c - cwr_type variable static PyTypeObject cwr_type +Modules/itertoolsmodule.c - cycle_methods variable static PyMethodDef cycle_methods +Modules/itertoolsmodule.c - cycle_type variable static PyTypeObject cycle_type +Objects/obmalloc.c new_arena debug_stats variable static int debug_stats +Modules/signalmodule.c - DefaultHandler variable static PyObject *DefaultHandler +Modules/_collectionsmodule.c - defdict_members variable static PyMemberDef defdict_members[] +Modules/_collectionsmodule.c - defdict_methods variable static PyMethodDef defdict_methods +Modules/_collectionsmodule.c - defdict_type variable static PyTypeObject defdict_type +Python/Python-ast.c - Delete_fields variable static char *Delete_fields[] +Python/Python-ast.c - Delete_type variable static PyTypeObject *Delete_type +Python/Python-ast.c - Del_singleton variable PyObject *Del_singleton +Python/Python-ast.c - Del_type variable static PyTypeObject *Del_type +Modules/_collectionsmodule.c - deque_as_number variable static PyNumberMethods deque_as_number +Modules/_collectionsmodule.c - deque_as_sequence variable static PySequenceMethods deque_as_sequence +Modules/_collectionsmodule.c - deque_getset variable static PyGetSetDef deque_getset[] +Modules/_collectionsmodule.c - dequeiter_methods variable static PyMethodDef dequeiter_methods +Modules/_collectionsmodule.c - dequeiter_type variable static PyTypeObject dequeiter_type +Modules/_collectionsmodule.c - deque_methods variable static PyMethodDef deque_methods +Modules/_collectionsmodule.c - dequereviter_type variable static PyTypeObject dequereviter_type +Modules/_collectionsmodule.c - deque_type variable static PyTypeObject deque_type +Objects/descrobject.c - descr_members variable static PyMemberDef descr_members[] +Objects/descrobject.c - descr_methods variable static PyMethodDef descr_methods +Modules/_abc.c - _destroy_def variable static PyMethodDef _destroy_def +Objects/floatobject.c - detected_double_format variable static float_format_type detected_double_format +Objects/floatobject.c - detected_float_format variable static float_format_type detected_float_format +Objects/dictobject.c - dict_as_mapping variable static PyMappingMethods dict_as_mapping +Objects/dictobject.c - dict_as_sequence variable static PySequenceMethods dict_as_sequence +Python/symtable.c - dictcomp variable static identifier dictcomp +Python/Python-ast.c - DictComp_fields variable static char *DictComp_fields[] +Python/Python-ast.c - DictComp_type variable static PyTypeObject *DictComp_type +Python/Python-ast.c - Dict_fields variable static char *Dict_fields[] +Objects/dictobject.c - dictitems_as_sequence variable static PySequenceMethods dictitems_as_sequence +Objects/dictobject.c - dictitems_methods variable static PyMethodDef dictitems_methods +Objects/dictobject.c - dictiter_methods variable static PyMethodDef dictiter_methods +Objects/dictobject.c - dictkeys_as_sequence variable static PySequenceMethods dictkeys_as_sequence +Objects/dictobject.c - dictkeys_methods variable static PyMethodDef dictkeys_methods +Python/Python-ast.c - Dict_type variable static PyTypeObject *Dict_type +Objects/dictobject.c - dictvalues_as_sequence variable static PySequenceMethods dictvalues_as_sequence +Objects/dictobject.c - dictvalues_methods variable static PyMethodDef dictvalues_methods +Objects/dictobject.c - dictviews_as_number variable static PyNumberMethods dictviews_as_number +Modules/posixmodule.c - DirEntry_members variable static PyMemberDef DirEntry_members[] +Modules/posixmodule.c - DirEntry_methods variable static PyMethodDef DirEntry_methods +Modules/posixmodule.c - DirEntryType variable static PyTypeObject DirEntryType +Python/Python-ast.c - Div_singleton variable static PyObject *Div_singleton +Python/Python-ast.c - Div_type variable static PyTypeObject *Div_type +Python/compile.c - __doc__ variable static PyObject *__doc__ +Objects/classobject.c method_get_doc docstr variable static PyObject *docstr +Objects/classobject.c instancemethod_get_doc docstr variable static PyObject *docstr +Python/compile.c compiler_set_qualname dot variable "_Py_static_string(dot, ""."")" +Python/compile.c compiler_set_qualname dot_locals variable "_Py_static_string(dot_locals, ""."")" +Objects/floatobject.c - double_format variable static float_format_type double_format +Modules/itertoolsmodule.c - dropwhile_methods variable static PyMethodDef dropwhile_methods +Modules/itertoolsmodule.c - dropwhile_type variable static PyTypeObject dropwhile_type +Objects/setobject.c - _dummy_struct variable static PyObject _dummy_struct +Modules/posixmodule.c - dup3_works variable static int dup3_works +Modules/_io/bufferedio.c _PyIO_trap_eintr eintr_int variable static PyObject *eintr_int +Objects/sliceobject.c - ellipsis_methods variable static PyMethodDef ellipsis_methods +Python/hamt.c - _empty_bitmap_node variable static PyHamtNode_Bitmap *_empty_bitmap_node +Objects/setobject.c - emptyfrozenset variable static PyObject *emptyfrozenset +Python/hamt.c - _empty_hamt variable static PyHamtObject *_empty_hamt +Objects/dictobject.c - empty_keys_struct variable static PyDictKeysObject empty_keys_struct +Objects/codeobject.c PyCode_NewEmpty emptystring variable static PyObject *emptystring +Python/compile.c compiler_from_import empty_string variable static PyObject *empty_string +Objects/dictobject.c - empty_values variable static PyObject *empty_values[1] +Objects/unicodeobject.c - encoding_map_methods variable static PyMethodDef encoding_map_methods +Objects/unicodeobject.c - EncodingMapType variable static PyTypeObject EncodingMapType +Objects/enumobject.c - enum_methods variable static PyMethodDef enum_methods +Python/Python-ast.c - Eq_singleton variable static PyObject *Eq_singleton +Python/Python-ast.c - Eq_type variable static PyTypeObject *Eq_type +Objects/exceptions.c - errnomap variable static PyObject *errnomap +Modules/errnomodule.c - errno_methods variable static PyMethodDef errno_methods +Modules/errnomodule.c - errnomodule variable static struct PyModuleDef errnomodule +Modules/_localemodule.c - Error variable static PyObject *Error +Python/Python-ast.c - excepthandler_attributes variable static char *excepthandler_attributes[] +Python/Python-ast.c - ExceptHandler_fields variable static char *ExceptHandler_fields[] +Python/Python-ast.c - excepthandler_type variable static PyTypeObject *excepthandler_type +Python/Python-ast.c - ExceptHandler_type variable static PyTypeObject *ExceptHandler_type +Modules/_threadmodule.c - ExceptHookArgs_desc variable static PyStructSequence_Desc ExceptHookArgs_desc +Modules/_threadmodule.c - ExceptHookArgs_fields variable static PyStructSequence_Field ExceptHookArgs_fields[] +Modules/_threadmodule.c - ExceptHookArgsType variable static PyTypeObject ExceptHookArgsType +Objects/exceptions.c _check_for_legacy_statements exec_prefix variable static PyObject *exec_prefix +Python/Python-ast.c - expr_attributes variable static char *expr_attributes[] +Python/Python-ast.c - expr_context_type variable static PyTypeObject *expr_context_type +Python/Python-ast.c - Expression_fields variable static char *Expression_fields[] +Python/Python-ast.c - Expression_type variable static PyTypeObject *Expression_type +Python/Python-ast.c - Expr_fields variable static char *Expr_fields[] +Python/Python-ast.c - expr_type variable static PyTypeObject *expr_type +Python/Python-ast.c - Expr_type variable static PyTypeObject *Expr_type +Python/import.c - extensions variable static PyObject *extensions +Python/Python-ast.c - ExtSlice_fields variable static char *ExtSlice_fields[] +Python/Python-ast.c - ExtSlice_type variable static PyTypeObject *ExtSlice_type +Objects/boolobject.c - false_str variable static PyObject *false_str +Modules/faulthandler.c - fatal_error variable static struct { int enabled; PyObject *file; int fd; int all_threads; PyInterpreterState *interp; void *exc_handler; } fatal_error +Modules/faulthandler.c - faulthandler_handlers variable static fault_handler_t faulthandler_handlers[] +Objects/stringlib/unicode_format.h - fieldnameiter_methods variable static PyMethodDef fieldnameiter_methods +Modules/_io/fileio.c - fileio_getsetlist variable static PyGetSetDef fileio_getsetlist[] +Modules/_io/fileio.c - fileio_members variable static PyMemberDef fileio_members[] +Modules/_io/fileio.c - fileio_methods variable static PyMethodDef fileio_methods +Modules/itertoolsmodule.c - filterfalse_methods variable static PyMethodDef filterfalse_methods +Modules/itertoolsmodule.c - filterfalse_type variable static PyTypeObject filterfalse_type +Python/bltinmodule.c - filter_methods variable static PyMethodDef filter_methods +Python/sysmodule.c - flags_desc variable static PyStructSequence_Desc flags_desc +Python/sysmodule.c - flags_fields variable static PyStructSequence_Field flags_fields[] +Python/sysmodule.c - FlagsType variable static PyTypeObject FlagsType +Objects/floatobject.c - float_as_number variable static PyNumberMethods float_as_number +Objects/floatobject.c - float_format variable static float_format_type +Objects/floatobject.c - float_getset variable static PyGetSetDef float_getset[] +Objects/floatobject.c - floatinfo_desc variable static PyStructSequence_Desc floatinfo_desc +Objects/floatobject.c - floatinfo_fields variable static PyStructSequence_Field floatinfo_fields[] +Objects/floatobject.c - FloatInfoType variable static PyTypeObject FloatInfoType +Objects/floatobject.c - float_methods variable static PyMethodDef float_methods +Python/Python-ast.c - FloorDiv_singleton variable static PyObject *FloorDiv_singleton +Python/Python-ast.c - FloorDiv_type variable static PyTypeObject *FloorDiv_type +Python/fileutils.c - force_ascii variable static int force_ascii +Python/Python-ast.c - For_fields variable static char *For_fields[] +Python/Python-ast.c - FormattedValue_fields variable static char *FormattedValue_fields[] +Python/Python-ast.c - FormattedValue_type variable static PyTypeObject *FormattedValue_type +Objects/stringlib/unicode_format.h - formatteriter_methods variable static PyMethodDef formatteriter_methods +Python/Python-ast.c - For_type variable static PyTypeObject *For_type +Objects/frameobject.c - frame_getsetlist variable static PyGetSetDef frame_getsetlist[] +Objects/frameobject.c - frame_memberlist variable static PyMemberDef frame_memberlist[] +Objects/frameobject.c - frame_methods variable static PyMethodDef frame_methods +Modules/_collectionsmodule.c - freeblocks variable static block *freeblocks[MAXFREEBLOCKS] +Python/dtoa.c - freelist variable static Bigint *freelist[Kmax+1] +Objects/floatobject.c - free_list variable static PyFloatObject *free_list +Objects/frameobject.c - free_list variable static PyFrameObject *free_list +Objects/listobject.c - free_list variable static PyListObject *free_list[PyList_MAXFREELIST] +Objects/dictobject.c - free_list variable static PyDictObject *free_list[PyDict_MAXFREELIST] +Objects/methodobject.c - free_list variable static PyCFunctionObject *free_list +Objects/tupleobject.c - free_list variable static PyTupleObject *free_list[PyTuple_MAXSAVESIZE] +Objects/classobject.c - free_list variable static PyMethodObject *free_list +Objects/setobject.c - frozenset_as_number variable static PyNumberMethods frozenset_as_number +Objects/setobject.c - frozenset_methods variable static PyMethodDef frozenset_methods +Objects/funcobject.c - func_getsetlist variable static PyGetSetDef func_getsetlist[] +Objects/funcobject.c - func_memberlist variable static PyMemberDef func_memberlist[] +Python/Python-ast.c - FunctionDef_fields variable static char *FunctionDef_fields[] +Python/Python-ast.c - FunctionDef_type variable static PyTypeObject *FunctionDef_type +Modules/_sre.c - _functions variable static PyMethodDef _functions[] +Python/Python-ast.c - FunctionType_fields variable static char *FunctionType_fields[] +Python/Python-ast.c - FunctionType_type variable static PyTypeObject *FunctionType_type +Modules/_functoolsmodule.c - _functoolsmodule variable static struct PyModuleDef _functoolsmodule +Modules/gcmodule.c - GcMethods variable static PyMethodDef GcMethods[] +Modules/gcmodule.c - gcmodule variable static struct PyModuleDef gcmodule +Modules/gcmodule.c - gc_str variable static PyObject *gc_str +Python/Python-ast.c - GeneratorExp_fields variable static char *GeneratorExp_fields[] +Python/Python-ast.c - GeneratorExp_type variable static PyTypeObject *GeneratorExp_type +Python/symtable.c - genexpr variable static identifier genexpr +Objects/genobject.c - gen_getsetlist variable static PyGetSetDef gen_getsetlist[] +Objects/genobject.c - gen_memberlist variable static PyMemberDef gen_memberlist[] +Objects/genobject.c - gen_methods variable static PyMethodDef gen_methods +Python/bootstrap_hash.c py_getrandom getrandom_works variable static int getrandom_works +Objects/descrobject.c - getset_getset variable static PyGetSetDef getset_getset[] +Python/Python-ast.c - Global_fields variable static char *Global_fields[] +Python/Python-ast.c - Global_type variable static PyTypeObject *Global_type +Modules/itertoolsmodule.c - groupby_methods variable static PyMethodDef groupby_methods +Modules/itertoolsmodule.c - groupby_type variable static PyTypeObject groupby_type +Modules/itertoolsmodule.c - _grouper_methods variable static PyMethodDef _grouper_methods +Modules/itertoolsmodule.c - _grouper_type variable static PyTypeObject _grouper_type +Python/Python-ast.c - GtE_singleton variable static PyObject *GtE_singleton +Python/Python-ast.c - GtE_type variable static PyTypeObject *GtE_type +Python/Python-ast.c - Gt_singleton variable static PyObject *Gt_singleton +Python/Python-ast.c - Gt_type variable static PyTypeObject *Gt_type +Modules/signalmodule.c - Handlers variable static volatile struct { _Py_atomic_int tripped; PyObject *func; } Handlers[NSIG] +Python/dynload_shlib.c - handles variable static struct { dev_t dev; ino_t ino; void *handle; } handles[128] +Python/sysmodule.c - hash_info_desc variable static PyStructSequence_Desc hash_info_desc +Python/sysmodule.c - hash_info_fields variable static PyStructSequence_Field hash_info_fields[] +Python/sysmodule.c - Hash_InfoType variable static PyTypeObject Hash_InfoType +Python/import.c import_find_and_load header variable static int header +Modules/_tkinter.c - id variable int id +??? ??? id variable ??? +??? ??? id variable ??? +??? ??? id variable ??? +??? ??? id variable ??? +??? ??? id variable ??? +??? ??? id variable ??? +??? ??? id variable ??? +??? ??? id variable ??? +??? ??? id variable ??? +??? ??? id variable ??? +??? ??? id variable ??? +??? ??? id variable ??? +??? ??? id variable ??? +??? ??? id variable ??? +??? ??? id variable ??? +??? ??? id variable ??? +??? ??? id variable ??? +??? ??? id variable ??? +??? ??? id variable ??? +Python/Python-ast.c - IfExp_fields variable static char *IfExp_fields[] +Python/Python-ast.c - IfExp_type variable static PyTypeObject *IfExp_type +Python/Python-ast.c - If_fields variable static char *If_fields[] +Python/Python-ast.c - If_type variable static PyTypeObject *If_type +Modules/signalmodule.c - IgnoreHandler variable static PyObject *IgnoreHandler +Python/import.c - imp_methods variable static PyMethodDef imp_methods +Python/import.c - impmodule variable static struct PyModuleDef impmodule +Objects/exceptions.c - ImportError_members variable static PyMemberDef ImportError_members[] +Objects/exceptions.c - ImportError_methods variable static PyMethodDef ImportError_methods +Python/Python-ast.c - Import_fields variable static char *Import_fields[] +Python/Python-ast.c - ImportFrom_fields variable static char *ImportFrom_fields[] +Python/Python-ast.c - ImportFrom_type variable static PyTypeObject *ImportFrom_type +Python/import.c import_find_and_load import_level variable static int import_level +Python/_warnings.c is_internal_frame importlib_string variable static PyObject *importlib_string +Python/import.c - import_lock variable static PyThread_type_lock import_lock +Python/import.c - import_lock_level variable static int import_lock_level +Python/import.c - import_lock_thread variable static unsigned long import_lock_thread +Python/import.c PyImport_Import import_str variable static PyObject *import_str +Python/Python-ast.c - Import_type variable static PyTypeObject *Import_type +Modules/_io/textio.c - incrementalnewlinedecoder_getset variable static PyGetSetDef incrementalnewlinedecoder_getset[] +Modules/_io/textio.c - incrementalnewlinedecoder_methods variable static PyMethodDef incrementalnewlinedecoder_methods +Objects/listobject.c - indexerr variable static PyObject *indexerr +Python/Python-ast.c - Index_fields variable static char *Index_fields[] +Python/Python-ast.c - Index_type variable static PyTypeObject *Index_type +Python/thread.c - initialized variable static int initialized +Modules/posixmodule.c - initialized variable static int initialized +Modules/pwdmodule.c - initialized variable static int initialized +Modules/signalmodule.c - initialized variable static int initialized +Modules/timemodule.c - initialized variable static int initialized +Python/Python-ast.c init_types initialized variable static int initialized +Objects/listobject.c PyList_New initialized variable static int initialized +Python/import.c - inittab_copy variable static struct _inittab *inittab_copy +Python/Python-ast.c - In_singleton variable static PyObject *In_singleton +Objects/classobject.c - instancemethod_getset variable static PyGetSetDef instancemethod_getset[] +Objects/classobject.c - instancemethod_memberlist variable static PyMemberDef instancemethod_memberlist[] +Python/Python-ast.c - Interactive_fields variable static char *Interactive_fields[] +Python/Python-ast.c - Interactive_type variable static PyTypeObject *Interactive_type +Objects/unicodeobject.c - interned variable static PyObject *interned +Objects/interpreteridobject.c - interpid_as_number variable static PyNumberMethods interpid_as_number +Modules/signalmodule.c - IntHandler variable static PyObject *IntHandler +Objects/longobject.c - int_info_desc variable static PyStructSequence_Desc int_info_desc +Objects/longobject.c - int_info_fields variable static PyStructSequence_Field int_info_fields[] +Objects/longobject.c - Int_InfoType variable static PyTypeObject Int_InfoType +Python/Python-ast.c - In_type variable static PyTypeObject *In_type +Python/Python-ast.c - Invert_singleton variable static PyObject *Invert_singleton +Python/Python-ast.c - Invert_type variable static PyTypeObject *Invert_type +Modules/_io/iobase.c - iobase_getset variable static PyGetSetDef iobase_getset[] +Modules/_io/iobase.c - iobase_methods variable static PyMethodDef iobase_methods +Python/fileutils.c set_inheritable ioctl_works variable static int ioctl_works +Modules/itertoolsmodule.c - islice_methods variable static PyMethodDef islice_methods +Modules/itertoolsmodule.c - islice_type variable static PyTypeObject islice_type +Python/Python-ast.c - IsNot_singleton variable static PyObject *IsNot_singleton +Python/Python-ast.c - IsNot_type variable static PyTypeObject *IsNot_type +Python/Python-ast.c - Is_singleton variable static PyObject *Is_singleton +Modules/signalmodule.c - is_tripped variable static _Py_atomic_int is_tripped +Python/Python-ast.c - Is_type variable static PyTypeObject *Is_type +Modules/_operator.c - itemgetter_methods variable static PyMethodDef itemgetter_methods +Modules/_operator.c - itemgetter_type variable static PyTypeObject itemgetter_type +Modules/itertoolsmodule.c - itertoolsmodule variable static struct PyModuleDef itertoolsmodule +Modules/signalmodule.c - ItimerError variable static PyObject *ItimerError +Python/Python-ast.c - JoinedStr_fields variable static char *JoinedStr_fields[] +Python/Python-ast.c - JoinedStr_type variable static PyTypeObject *JoinedStr_type +Modules/_functoolsmodule.c - keyobject_members variable static PyMemberDef keyobject_members[] +Modules/_functoolsmodule.c - keyobject_type variable static PyTypeObject keyobject_type +Objects/dictobject.c - keys_free_list variable static PyDictKeysObject *keys_free_list[PyDict_MAXFREELIST] +Python/Python-ast.c - keyword_fields variable static char *keyword_fields[] +Python/sysmodule.c sys_set_asyncgen_hooks keywords variable static char *keywords[] +Modules/_bisectmodule.c bisect_right keywords variable static char *keywords[] +Modules/_bisectmodule.c insort_right keywords variable static char *keywords[] +Python/Python-ast.c - keyword_type variable static PyTypeObject *keyword_type +Modules/_functoolsmodule.c keyobject_call kwargs variable static char *kwargs[] +Modules/_functoolsmodule.c functools_cmp_to_key kwargs variable static char *kwargs[] +Modules/itertoolsmodule.c repeat_new kwargs variable static char *kwargs[] +Python/_warnings.c warnings_warn_explicit kwd_list variable static char *kwd_list[] +Modules/_functoolsmodule.c - kwd_mark variable static PyObject *kwd_mark +Python/bltinmodule.c builtin___import__ kwlist variable static char *kwlist[] +Python/bltinmodule.c min_max kwlist variable static char *kwlist[] +Python/context.c contextvar_tp_new kwlist variable static char *kwlist[] +Python/sysmodule.c sys_getsizeof kwlist variable static char *kwlist[] +Objects/bytearrayobject.c bytearray_init kwlist variable static char *kwlist[] +Objects/bytesobject.c bytes_new kwlist variable static char *kwlist[] +Objects/exceptions.c ImportError_init kwlist variable static char *kwlist[] +Objects/interpreteridobject.c interpid_new kwlist variable static char *kwlist[] +Objects/memoryobject.c memory_new kwlist variable static char *kwlist[] +Objects/memoryobject.c memory_cast kwlist variable static char *kwlist[] +Objects/memoryobject.c memory_tobytes kwlist variable static char *kwlist[] +Objects/odictobject.c odict_pop kwlist variable static char *kwlist[] +Objects/unicodeobject.c unicode_new kwlist variable static char *kwlist[] +Objects/weakrefobject.c weakref_call kwlist variable static char *kwlist[] +Modules/_elementtree.c element_setstate_from_Python kwlist variable static char *kwlist[] +Modules/_json.c scanner_call kwlist variable static char *kwlist[] +Modules/_json.c scanner_new kwlist variable static char *kwlist[] +Modules/_json.c encoder_new kwlist variable static char *kwlist[] +Modules/_json.c encoder_call kwlist variable static char *kwlist[] +Python/symtable.c - lambda variable static identifier lambda +Python/Python-ast.c - Lambda_fields variable static char *Lambda_fields[] +Python/Python-ast.c - Lambda_type variable static PyTypeObject *Lambda_type +Parser/listnode.c - level variable static int level +Objects/listobject.c - list_as_mapping variable static PyMappingMethods list_as_mapping +Objects/listobject.c - list_as_sequence variable static PySequenceMethods list_as_sequence +Python/symtable.c - listcomp variable static identifier listcomp +Python/Python-ast.c - ListComp_fields variable static char *ListComp_fields[] +Python/Python-ast.c - ListComp_type variable static PyTypeObject *ListComp_type +Python/Python-ast.c - List_fields variable static char *List_fields[] +Objects/listobject.c - listiter_methods variable static PyMethodDef listiter_methods +Objects/listobject.c - list_methods variable static PyMethodDef list_methods +Objects/listobject.c - listreviter_methods variable static PyMethodDef listreviter_methods +Python/Python-ast.c - List_type variable static PyTypeObject *List_type +Python/ceval.c - lltrace variable static int lltrace +Python/Python-ast.c - Load_singleton variable PyObject *Load_singleton +Python/Python-ast.c - Load_type variable static PyTypeObject *Load_type +Modules/_threadmodule.c - localdummytype variable static PyTypeObject localdummytype +Modules/_localemodule.c - _localemodule variable static struct PyModuleDef _localemodule +Modules/_threadmodule.c - localtype variable static PyTypeObject localtype +Modules/_threadmodule.c - lock_methods variable static PyMethodDef lock_methods +Modules/_threadmodule.c - Locktype variable static PyTypeObject Locktype +Objects/longobject.c PyLong_FromString log_base_BASE variable static double log_base_BASE[37] +Objects/longobject.c - long_as_number variable static PyNumberMethods long_as_number +Objects/longobject.c - long_getset variable static PyGetSetDef long_getset[] +Objects/longobject.c - long_methods variable static PyMethodDef long_methods +Objects/rangeobject.c - longrangeiter_methods variable static PyMethodDef longrangeiter_methods +Modules/_functoolsmodule.c - lru_cache_getsetlist variable static PyGetSetDef lru_cache_getsetlist[] +Modules/_functoolsmodule.c - lru_cache_methods variable static PyMethodDef lru_cache_methods +Modules/_functoolsmodule.c - lru_cache_type variable static PyTypeObject lru_cache_type +Modules/_functoolsmodule.c - lru_list_elem_type variable static PyTypeObject lru_list_elem_type +Python/Python-ast.c - LShift_singleton variable static PyObject *LShift_singleton +Python/Python-ast.c - LShift_type variable static PyTypeObject *LShift_type +Python/Python-ast.c - LtE_singleton variable static PyObject *LtE_singleton +Python/Python-ast.c - LtE_type variable static PyTypeObject *LtE_type +Python/Python-ast.c - Lt_singleton variable static PyObject *Lt_singleton +Python/Python-ast.c - Lt_type variable static PyTypeObject *Lt_type +Python/bltinmodule.c - map_methods variable static PyMethodDef map_methods +Objects/descrobject.c - mappingproxy_as_mapping variable static PyMappingMethods mappingproxy_as_mapping +Objects/descrobject.c - mappingproxy_as_sequence variable static PySequenceMethods mappingproxy_as_sequence +Objects/descrobject.c - mappingproxy_methods variable static PyMethodDef mappingproxy_methods +Objects/dictobject.c - mapp_methods variable static PyMethodDef mapp_methods +Python/marshal.c - marshal_methods variable static PyMethodDef marshal_methods +Python/marshal.c - marshalmodule variable static struct PyModuleDef marshalmodule +Modules/_sre.c - match_as_mapping variable static PyMappingMethods match_as_mapping +Modules/_sre.c - match_getset variable static PyGetSetDef match_getset[] +Modules/_sre.c - match_members variable static PyMemberDef match_members[] +Modules/_sre.c - match_methods variable static PyMethodDef match_methods +Modules/_sre.c - Match_Type variable static PyTypeObject Match_Type +Python/Python-ast.c - MatMult_singleton variable static PyObject *MatMult_singleton +Python/Python-ast.c - MatMult_type variable static PyTypeObject *MatMult_type +Objects/obmalloc.c - maxarenas variable static uint maxarenas +Objects/moduleobject.c - max_module_number variable static Py_ssize_t max_module_number +Objects/descrobject.c - member_getset variable static PyGetSetDef member_getset[] +Objects/exceptions.c - memerrors_freelist variable static PyBaseExceptionObject *memerrors_freelist +Objects/exceptions.c - memerrors_numfree variable static int memerrors_numfree +Objects/memoryobject.c - memory_as_buffer variable static PyBufferProcs memory_as_buffer +Objects/memoryobject.c - memory_as_mapping variable static PyMappingMethods memory_as_mapping +Objects/memoryobject.c - memory_as_sequence variable static PySequenceMethods memory_as_sequence +Objects/memoryobject.c - memory_getsetlist variable static PyGetSetDef memory_getsetlist[] +Objects/memoryobject.c - memory_methods variable static PyMethodDef memory_methods +Objects/methodobject.c - meth_getsets variable static PyGetSetDef meth_getsets [] +Objects/methodobject.c - meth_members variable static PyMemberDef meth_members[] +Objects/methodobject.c - meth_methods variable static PyMethodDef meth_methods +Objects/typeobject.c - method_cache variable static struct method_cache_entry method_cache[1 << MCACHE_SIZE_EXP] +Modules/_operator.c - methodcaller_methods variable static PyMethodDef methodcaller_methods +Modules/_operator.c - methodcaller_type variable static PyTypeObject methodcaller_type +Objects/classobject.c - method_getset variable static PyGetSetDef method_getset[] +Objects/descrobject.c - method_getset variable static PyGetSetDef method_getset[] +Objects/classobject.c - method_memberlist variable static PyMemberDef method_memberlist[] +Objects/classobject.c - method_methods variable static PyMethodDef method_methods +Python/codecs.c _PyCodecRegistry_Init methods variable static struct { char *name; PyMethodDef def; } methods[] +Python/frozen.c - M___hello__ variable static unsigned char M___hello__[] +Python/Python-ast.c - Mod_singleton variable static PyObject *Mod_singleton +Python/Python-ast.c - mod_type variable static PyTypeObject *mod_type +Python/Python-ast.c - Mod_type variable static PyTypeObject *Mod_type +Python/_warnings.c - module variable PyObject *module +Modules/faulthandler.c - module_def variable static struct PyModuleDef module_def +Modules/_tracemalloc.c - module_def variable static struct PyModuleDef module_def +Python/Python-ast.c - Module_fields variable static char *Module_fields[] +Modules/_collectionsmodule.c - module_functions variable static struct PyMethodDef module_functions[] +Modules/_abc.c - module_functions variable static struct PyMethodDef module_functions[] +Objects/moduleobject.c - module_members variable static PyMemberDef module_members[] +Objects/moduleobject.c - module_methods variable static PyMethodDef module_methods +Modules/_functoolsmodule.c - module_methods variable static PyMethodDef module_methods +Modules/itertoolsmodule.c - module_methods variable static PyMethodDef module_methods +Modules/_io/_iomodule.c - module_methods variable static PyMethodDef module_methods +Modules/faulthandler.c - module_methods variable static PyMethodDef module_methods +Modules/_tracemalloc.c - module_methods variable static PyMethodDef module_methods +Python/Python-ast.c - Module_type variable static PyTypeObject *Module_type +Python/Python-ast.c - Mult_singleton variable static PyObject *Mult_singleton +Python/Python-ast.c - Mult_type variable static PyTypeObject *Mult_type +Objects/funcobject.c PyFunction_NewWithQualName __name__ variable static PyObject *__name__ +Python/compile.c compiler_lambda name variable static identifier name +Python/compile.c compiler_genexp name variable static identifier name +Python/compile.c compiler_listcomp name variable static identifier name +Python/compile.c compiler_setcomp name variable static identifier name +Python/compile.c compiler_dictcomp name variable static identifier name +Python/Python-ast.c - NamedExpr_fields variable static char *NamedExpr_fields[] +Python/Python-ast.c - NamedExpr_type variable static PyTypeObject *NamedExpr_type +Python/Python-ast.c - Name_fields variable static char *Name_fields[] +Objects/typeobject.c - name_op variable static _Py_Identifier name_op[] +Objects/namespaceobject.c - namespace_members variable static PyMemberDef namespace_members[] +Objects/namespaceobject.c - namespace_methods variable static PyMethodDef namespace_methods +Python/Python-ast.c - Name_type variable static PyTypeObject *Name_type +Objects/obmalloc.c - narenas_currently_allocated variable static size_t narenas_currently_allocated +Objects/obmalloc.c - narenas_highwater variable static size_t narenas_highwater +Python/sysmodule.c - newline variable static PyObject *newline +Objects/typeobject.c - next_version_tag variable static unsigned int next_version_tag +Objects/obmalloc.c - nfp2lasta variable static struct arena_object* nfp2lasta[MAX_POOLS_IN_ARENA + 1] +Python/dynload_shlib.c - nhandles variable static int nhandles +Objects/object.c - none_as_number variable static PyNumberMethods none_as_number +Python/Python-ast.c - Nonlocal_fields variable static char *Nonlocal_fields[] +Python/Python-ast.c - Nonlocal_type variable static PyTypeObject *Nonlocal_type +Python/Python-ast.c - NotEq_singleton variable static PyObject *NotEq_singleton +Python/Python-ast.c - NotEq_type variable static PyTypeObject *NotEq_type +Objects/object.c - notimplemented_methods variable static PyMethodDef notimplemented_methods +Python/Python-ast.c - NotIn_singleton variable static PyObject *NotIn_singleton +Python/Python-ast.c - NotIn_type variable static PyTypeObject *NotIn_type +Python/Python-ast.c - Not_singleton variable static PyObject *Not_singleton +Python/Python-ast.c - Not_type variable static PyTypeObject *Not_type +Objects/obmalloc.c - ntimes_arena_allocated variable static size_t ntimes_arena_allocated +Objects/bytesobject.c - nullstring variable static PyBytesObject *nullstring +Objects/codeobject.c PyCode_NewEmpty nulltuple variable static PyObject *nulltuple +Objects/floatobject.c - numfree variable static int numfree +Objects/frameobject.c - numfree variable static int numfree +Objects/listobject.c - numfree variable static int numfree +Objects/dictobject.c - numfree variable static int numfree +Objects/methodobject.c - numfree variable static int numfree +Objects/tupleobject.c - numfree variable static int numfree[PyTuple_MAXSAVESIZE] +Objects/classobject.c - numfree variable static int numfree +Modules/_collectionsmodule.c - numfreeblocks variable static Py_ssize_t numfreeblocks +Objects/dictobject.c - numfreekeys variable static int numfreekeys +Objects/typeobject.c - object_getsets variable static PyGetSetDef object_getsets[] +Objects/typeobject.c - object_methods variable static PyMethodDef object_methods +Objects/typeobject.c - objreduce variable static PyObject *objreduce +Objects/odictobject.c - odict_as_mapping variable static PyMappingMethods odict_as_mapping +Objects/odictobject.c - odict_getset variable static PyGetSetDef odict_getset[] +Objects/odictobject.c - odictitems_methods variable static PyMethodDef odictitems_methods +Objects/odictobject.c - odictiter_methods variable static PyMethodDef odictiter_methods +Objects/odictobject.c - odictkeys_methods variable static PyMethodDef odictkeys_methods +Objects/odictobject.c - odict_methods variable static PyMethodDef odict_methods +Objects/odictobject.c - odictvalues_methods variable static PyMethodDef odictvalues_methods +Modules/faulthandler.c - old_stack variable static stack_t old_stack +Modules/_operator.c - operator_methods variable static PyMethodDef operator_methods +Modules/_operator.c - operatormodule variable static struct PyModuleDef operatormodule +Python/Python-ast.c - operator_type variable static PyTypeObject *operator_type +Objects/typeobject.c slot_nb_add op_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_subtract op_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_multiply op_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_matrix_multiply op_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_remainder op_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_divmod op_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_power_binary op_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_lshift op_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_rshift op_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_and op_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_xor op_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_or op_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_floor_divide op_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_true_divide op_id variable _Py_static_string(op_id, OPSTR) +Python/getopt.c - opt_ptr variable static const wchar_t *opt_ptr +Python/initconfig.c - orig_argv variable static PyWideStringList orig_argv +Python/Python-ast.c - Or_singleton variable PyObject *Or_singleton +Python/Python-ast.c - Or_type variable static PyTypeObject *Or_type +Objects/exceptions.c - OSError_getset variable static PyGetSetDef OSError_getset[] +Objects/exceptions.c - OSError_members variable static PyMemberDef OSError_members[] +Objects/exceptions.c - OSError_methods variable static PyMethodDef OSError_methods +Python/dtoa.c - p5s variable static Bigint *p5s +Python/Python-ast.c - Param_singleton variable PyObject *Param_singleton +Python/Python-ast.c - Param_type variable static PyTypeObject *Param_type +Python/bltinmodule.c builtin_print _parser variable static struct _PyArg_Parser _parser +Python/clinic/_warnings.c.h warnings_warn _parser variable static _PyArg_Parser _parser +Python/clinic/bltinmodule.c.h builtin_compile _parser variable static _PyArg_Parser _parser +Python/clinic/bltinmodule.c.h builtin_round _parser variable static _PyArg_Parser _parser +Python/clinic/bltinmodule.c.h builtin_sum _parser variable static _PyArg_Parser _parser +Python/clinic/import.c.h _imp_source_hash _parser variable static _PyArg_Parser _parser +Python/clinic/sysmodule.c.h sys_addaudithook _parser variable static _PyArg_Parser _parser +Python/clinic/sysmodule.c.h sys_set_coroutine_origin_tracking_depth _parser variable static _PyArg_Parser _parser +Python/clinic/traceback.c.h tb_new _parser variable static _PyArg_Parser _parser +Objects/clinic/bytearrayobject.c.h bytearray_translate _parser variable static _PyArg_Parser _parser +Objects/clinic/bytearrayobject.c.h bytearray_split _parser variable static _PyArg_Parser _parser +Objects/clinic/bytearrayobject.c.h bytearray_rsplit _parser variable static _PyArg_Parser _parser +Objects/clinic/bytearrayobject.c.h bytearray_decode _parser variable static _PyArg_Parser _parser +Objects/clinic/bytearrayobject.c.h bytearray_splitlines _parser variable static _PyArg_Parser _parser +Objects/clinic/bytearrayobject.c.h bytearray_hex _parser variable static _PyArg_Parser _parser +Objects/clinic/bytesobject.c.h bytes_split _parser variable static _PyArg_Parser _parser +Objects/clinic/bytesobject.c.h bytes_rsplit _parser variable static _PyArg_Parser _parser +Objects/clinic/bytesobject.c.h bytes_translate _parser variable static _PyArg_Parser _parser +Objects/clinic/bytesobject.c.h bytes_decode _parser variable static _PyArg_Parser _parser +Objects/clinic/bytesobject.c.h bytes_splitlines _parser variable static _PyArg_Parser _parser +Objects/clinic/bytesobject.c.h bytes_hex _parser variable static _PyArg_Parser _parser +Objects/clinic/codeobject.c.h code_replace _parser variable static _PyArg_Parser _parser +Objects/clinic/complexobject.c.h complex_new _parser variable static _PyArg_Parser _parser +Objects/clinic/descrobject.c.h mappingproxy_new _parser variable static _PyArg_Parser _parser +Objects/clinic/descrobject.c.h property_init _parser variable static _PyArg_Parser _parser +Objects/clinic/enumobject.c.h enum_new _parser variable static _PyArg_Parser _parser +Objects/clinic/funcobject.c.h func_new _parser variable static _PyArg_Parser _parser +Objects/clinic/listobject.c.h list_sort _parser variable static _PyArg_Parser _parser +Objects/clinic/longobject.c.h long_new _parser variable static _PyArg_Parser _parser +Objects/clinic/longobject.c.h int_to_bytes _parser variable static _PyArg_Parser _parser +Objects/clinic/longobject.c.h int_from_bytes _parser variable static _PyArg_Parser _parser +Objects/clinic/memoryobject.c.h memoryview_hex _parser variable static _PyArg_Parser _parser +Objects/clinic/moduleobject.c.h module___init__ _parser variable static _PyArg_Parser _parser +Objects/clinic/odictobject.c.h OrderedDict_fromkeys _parser variable static _PyArg_Parser _parser +Objects/clinic/odictobject.c.h OrderedDict_setdefault _parser variable static _PyArg_Parser _parser +Objects/clinic/odictobject.c.h OrderedDict_popitem _parser variable static _PyArg_Parser _parser +Objects/clinic/odictobject.c.h OrderedDict_move_to_end _parser variable static _PyArg_Parser _parser +Objects/clinic/structseq.c.h structseq_new _parser variable static _PyArg_Parser _parser +Objects/clinic/unicodeobject.c.h unicode_encode _parser variable static _PyArg_Parser _parser +Objects/clinic/unicodeobject.c.h unicode_expandtabs _parser variable static _PyArg_Parser _parser +Objects/clinic/unicodeobject.c.h unicode_split _parser variable static _PyArg_Parser _parser +Objects/clinic/unicodeobject.c.h unicode_rsplit _parser variable static _PyArg_Parser _parser +Objects/clinic/unicodeobject.c.h unicode_splitlines _parser variable static _PyArg_Parser _parser +Objects/stringlib/clinic/transmogrify.h.h stringlib_expandtabs _parser variable static _PyArg_Parser _parser +Modules/_blake2/clinic/blake2b_impl.c.h py_blake2b_new _parser variable static _PyArg_Parser _parser +Modules/_blake2/clinic/blake2s_impl.c.h py_blake2s_new _parser variable static _PyArg_Parser _parser +Modules/_io/clinic/_iomodule.c.h _io_open _parser variable static _PyArg_Parser _parser +Modules/_io/clinic/_iomodule.c.h _io_open_code _parser variable static _PyArg_Parser _parser +Modules/_io/clinic/bufferedio.c.h _io_BufferedReader___init__ _parser variable static _PyArg_Parser _parser +Modules/_io/clinic/bufferedio.c.h _io_BufferedWriter___init__ _parser variable static _PyArg_Parser _parser +Modules/_io/clinic/bufferedio.c.h _io_BufferedRandom___init__ _parser variable static _PyArg_Parser _parser +Modules/_io/clinic/bytesio.c.h _io_BytesIO___init__ _parser variable static _PyArg_Parser _parser +Modules/_io/clinic/fileio.c.h _io_FileIO___init__ _parser variable static _PyArg_Parser _parser +Modules/_io/clinic/stringio.c.h _io_StringIO___init__ _parser variable static _PyArg_Parser _parser +Modules/_io/clinic/textio.c.h _io_IncrementalNewlineDecoder___init__ _parser variable static _PyArg_Parser _parser +Modules/_io/clinic/textio.c.h _io_IncrementalNewlineDecoder_decode _parser variable static _PyArg_Parser _parser +Modules/_io/clinic/textio.c.h _io_TextIOWrapper___init__ _parser variable static _PyArg_Parser _parser +Modules/_io/clinic/textio.c.h _io_TextIOWrapper_reconfigure _parser variable static _PyArg_Parser _parser +Modules/_io/clinic/winconsoleio.c.h _io__WindowsConsoleIO___init__ _parser variable static _PyArg_Parser _parser +Modules/_multiprocessing/clinic/posixshmem.c.h _posixshmem_shm_open _parser variable static _PyArg_Parser _parser +Modules/_multiprocessing/clinic/posixshmem.c.h _posixshmem_shm_unlink _parser variable static _PyArg_Parser _parser +Modules/cjkcodecs/clinic/multibytecodec.c.h _multibytecodec_MultibyteCodec_encode _parser variable static _PyArg_Parser _parser +Modules/cjkcodecs/clinic/multibytecodec.c.h _multibytecodec_MultibyteCodec_decode _parser variable static _PyArg_Parser _parser +Modules/cjkcodecs/clinic/multibytecodec.c.h _multibytecodec_MultibyteIncrementalEncoder_encode _parser variable static _PyArg_Parser _parser +Modules/cjkcodecs/clinic/multibytecodec.c.h _multibytecodec_MultibyteIncrementalDecoder_decode _parser variable static _PyArg_Parser _parser +Modules/clinic/_asynciomodule.c.h _asyncio_Future___init__ _parser variable static _PyArg_Parser _parser +Modules/clinic/_asynciomodule.c.h _asyncio_Future_add_done_callback _parser variable static _PyArg_Parser _parser +Modules/clinic/_asynciomodule.c.h _asyncio_Task___init__ _parser variable static _PyArg_Parser _parser +Modules/clinic/_asynciomodule.c.h _asyncio_Task_current_task _parser variable static _PyArg_Parser _parser +Modules/clinic/_asynciomodule.c.h _asyncio_Task_all_tasks _parser variable static _PyArg_Parser _parser +Modules/clinic/_asynciomodule.c.h _asyncio_Task_get_stack _parser variable static _PyArg_Parser _parser +Modules/clinic/_asynciomodule.c.h _asyncio_Task_print_stack _parser variable static _PyArg_Parser _parser +Modules/clinic/_asynciomodule.c.h _asyncio__register_task _parser variable static _PyArg_Parser _parser +Modules/clinic/_asynciomodule.c.h _asyncio__unregister_task _parser variable static _PyArg_Parser _parser +Modules/clinic/_asynciomodule.c.h _asyncio__enter_task _parser variable static _PyArg_Parser _parser +Modules/clinic/_asynciomodule.c.h _asyncio__leave_task _parser variable static _PyArg_Parser _parser +Modules/clinic/_bz2module.c.h _bz2_BZ2Decompressor_decompress _parser variable static _PyArg_Parser _parser +Modules/clinic/_codecsmodule.c.h _codecs_encode _parser variable static _PyArg_Parser _parser +Modules/clinic/_codecsmodule.c.h _codecs_decode _parser variable static _PyArg_Parser _parser +Modules/clinic/_cursesmodule.c.h _curses_setupterm _parser variable static _PyArg_Parser _parser +Modules/clinic/_datetimemodule.c.h datetime_datetime_now _parser variable static _PyArg_Parser _parser +Modules/clinic/_elementtree.c.h _elementtree_Element_find _parser variable static _PyArg_Parser _parser +Modules/clinic/_elementtree.c.h _elementtree_Element_findtext _parser variable static _PyArg_Parser _parser +Modules/clinic/_elementtree.c.h _elementtree_Element_findall _parser variable static _PyArg_Parser _parser +Modules/clinic/_elementtree.c.h _elementtree_Element_iterfind _parser variable static _PyArg_Parser _parser +Modules/clinic/_elementtree.c.h _elementtree_Element_get _parser variable static _PyArg_Parser _parser +Modules/clinic/_elementtree.c.h _elementtree_Element_iter _parser variable static _PyArg_Parser _parser +Modules/clinic/_elementtree.c.h _elementtree_Element_getiterator _parser variable static _PyArg_Parser _parser +Modules/clinic/_elementtree.c.h _elementtree_TreeBuilder___init__ _parser variable static _PyArg_Parser _parser +Modules/clinic/_elementtree.c.h _elementtree_XMLParser___init__ _parser variable static _PyArg_Parser _parser +Modules/clinic/_hashopenssl.c.h EVP_new _parser variable static _PyArg_Parser _parser +Modules/clinic/_hashopenssl.c.h pbkdf2_hmac _parser variable static _PyArg_Parser _parser +Modules/clinic/_hashopenssl.c.h _hashlib_scrypt _parser variable static _PyArg_Parser _parser +Modules/clinic/_hashopenssl.c.h _hashlib_hmac_digest _parser variable static _PyArg_Parser _parser +Modules/clinic/_lzmamodule.c.h _lzma_LZMADecompressor_decompress _parser variable static _PyArg_Parser _parser +Modules/clinic/_lzmamodule.c.h _lzma_LZMADecompressor___init__ _parser variable static _PyArg_Parser _parser +Modules/clinic/_opcode.c.h _opcode_stack_effect _parser variable static _PyArg_Parser _parser +Modules/clinic/_pickle.c.h _pickle_Pickler___init__ _parser variable static _PyArg_Parser _parser +Modules/clinic/_pickle.c.h _pickle_Unpickler___init__ _parser variable static _PyArg_Parser _parser +Modules/clinic/_pickle.c.h _pickle_dump _parser variable static _PyArg_Parser _parser +Modules/clinic/_pickle.c.h _pickle_dumps _parser variable static _PyArg_Parser _parser +Modules/clinic/_pickle.c.h _pickle_load _parser variable static _PyArg_Parser _parser +Modules/clinic/_pickle.c.h _pickle_loads _parser variable static _PyArg_Parser _parser +Modules/clinic/_queuemodule.c.h _queue_SimpleQueue_put _parser variable static _PyArg_Parser _parser +Modules/clinic/_queuemodule.c.h _queue_SimpleQueue_put_nowait _parser variable static _PyArg_Parser _parser +Modules/clinic/_queuemodule.c.h _queue_SimpleQueue_get _parser variable static _PyArg_Parser _parser +Modules/clinic/_sre.c.h _sre_SRE_Pattern_match _parser variable static _PyArg_Parser _parser +Modules/clinic/_sre.c.h _sre_SRE_Pattern_fullmatch _parser variable static _PyArg_Parser _parser +Modules/clinic/_sre.c.h _sre_SRE_Pattern_search _parser variable static _PyArg_Parser _parser +Modules/clinic/_sre.c.h _sre_SRE_Pattern_findall _parser variable static _PyArg_Parser _parser +Modules/clinic/_sre.c.h _sre_SRE_Pattern_finditer _parser variable static _PyArg_Parser _parser +Modules/clinic/_sre.c.h _sre_SRE_Pattern_scanner _parser variable static _PyArg_Parser _parser +Modules/clinic/_sre.c.h _sre_SRE_Pattern_split _parser variable static _PyArg_Parser _parser +Modules/clinic/_sre.c.h _sre_SRE_Pattern_sub _parser variable static _PyArg_Parser _parser +Modules/clinic/_sre.c.h _sre_SRE_Pattern_subn _parser variable static _PyArg_Parser _parser +Modules/clinic/_sre.c.h _sre_compile _parser variable static _PyArg_Parser _parser +Modules/clinic/_sre.c.h _sre_SRE_Match_expand _parser variable static _PyArg_Parser _parser +Modules/clinic/_sre.c.h _sre_SRE_Match_groups _parser variable static _PyArg_Parser _parser +Modules/clinic/_sre.c.h _sre_SRE_Match_groupdict _parser variable static _PyArg_Parser _parser +Modules/clinic/_ssl.c.h _ssl__SSLSocket_get_channel_binding _parser variable static _PyArg_Parser _parser +Modules/clinic/_ssl.c.h _ssl__SSLContext_load_cert_chain _parser variable static _PyArg_Parser _parser +Modules/clinic/_ssl.c.h _ssl__SSLContext_load_verify_locations _parser variable static _PyArg_Parser _parser +Modules/clinic/_ssl.c.h _ssl__SSLContext__wrap_socket _parser variable static _PyArg_Parser _parser +Modules/clinic/_ssl.c.h _ssl__SSLContext__wrap_bio _parser variable static _PyArg_Parser _parser +Modules/clinic/_ssl.c.h _ssl__SSLContext_get_ca_certs _parser variable static _PyArg_Parser _parser +Modules/clinic/_ssl.c.h _ssl_txt2obj _parser variable static _PyArg_Parser _parser +Modules/clinic/_ssl.c.h _ssl_enum_certificates _parser variable static _PyArg_Parser _parser +Modules/clinic/_ssl.c.h _ssl_enum_crls _parser variable static _PyArg_Parser _parser +Modules/clinic/_struct.c.h Struct___init__ _parser variable static _PyArg_Parser _parser +Modules/clinic/_struct.c.h Struct_unpack_from _parser variable static _PyArg_Parser _parser +Modules/clinic/_struct.c.h unpack_from _parser variable static _PyArg_Parser _parser +Modules/clinic/_winapi.c.h _winapi_ConnectNamedPipe _parser variable static _PyArg_Parser _parser +Modules/clinic/_winapi.c.h _winapi_ReadFile _parser variable static _PyArg_Parser _parser +Modules/clinic/_winapi.c.h _winapi_WriteFile _parser variable static _PyArg_Parser _parser +Modules/clinic/_winapi.c.h _winapi_GetFileType _parser variable static _PyArg_Parser _parser +Modules/clinic/binascii.c.h binascii_b2a_uu _parser variable static _PyArg_Parser _parser +Modules/clinic/binascii.c.h binascii_b2a_base64 _parser variable static _PyArg_Parser _parser +Modules/clinic/binascii.c.h binascii_b2a_hex _parser variable static _PyArg_Parser _parser +Modules/clinic/binascii.c.h binascii_hexlify _parser variable static _PyArg_Parser _parser +Modules/clinic/binascii.c.h binascii_a2b_qp _parser variable static _PyArg_Parser _parser +Modules/clinic/binascii.c.h binascii_b2a_qp _parser variable static _PyArg_Parser _parser +Modules/clinic/cmathmodule.c.h cmath_isclose _parser variable static _PyArg_Parser _parser +Modules/clinic/gcmodule.c.h gc_collect _parser variable static _PyArg_Parser _parser +Modules/clinic/gcmodule.c.h gc_get_objects _parser variable static _PyArg_Parser _parser +Modules/clinic/grpmodule.c.h grp_getgrgid _parser variable static _PyArg_Parser _parser +Modules/clinic/grpmodule.c.h grp_getgrnam _parser variable static _PyArg_Parser _parser +Modules/_functoolsmodule.c - partial_getsetlist variable static PyGetSetDef partial_getsetlist[] +Modules/_functoolsmodule.c - partial_memberlist variable static PyMemberDef partial_memberlist[] +Modules/_functoolsmodule.c - partial_methods variable static PyMethodDef partial_methods +Modules/_functoolsmodule.c - partial_type variable static PyTypeObject partial_type +Python/Python-ast.c - Pass_type variable static PyTypeObject *Pass_type +Modules/_sre.c - pattern_getset variable static PyGetSetDef pattern_getset[] +Modules/_sre.c - pattern_members variable static PyMemberDef pattern_members[] +Modules/_sre.c - pattern_methods variable static PyMethodDef pattern_methods +Modules/_sre.c - Pattern_Type variable static PyTypeObject Pattern_Type +Modules/itertoolsmodule.c - permuations_methods variable static PyMethodDef permuations_methods +Modules/itertoolsmodule.c - permutations_type variable static PyTypeObject permutations_type +Objects/picklebufobject.c - picklebuf_as_buffer variable static PyBufferProcs picklebuf_as_buffer +Objects/picklebufobject.c - picklebuf_methods variable static PyMethodDef picklebuf_methods +Python/dtoa.c - pmem_next variable static double *pmem_next +Objects/typeobject.c resolve_slotdups pname variable static PyObject *pname +Modules/posixmodule.c - posix_constants_confstr variable static struct constdef posix_constants_confstr[] +Modules/posixmodule.c - posix_constants_pathconf variable static struct constdef posix_constants_pathconf[] +Modules/posixmodule.c - posix_constants_sysconf variable static struct constdef posix_constants_sysconf[] +Modules/posixmodule.c - posix_methods variable static PyMethodDef posix_methods +Modules/posixmodule.c - posixmodule variable static struct PyModuleDef posixmodule +Modules/posixmodule.c - posix_putenv_garbage variable static PyObject *posix_putenv_garbage +Python/Python-ast.c - Pow_singleton variable static PyObject *Pow_singleton +Python/Python-ast.c - Pow_type variable static PyTypeObject *Pow_type +Python/sysmodule.c - _preinit_warnoptions variable static _Py_PreInitEntry _preinit_warnoptions +Python/sysmodule.c - _preinit_xoptions variable static _Py_PreInitEntry _preinit_xoptions +Objects/exceptions.c _check_for_legacy_statements print_prefix variable static PyObject *print_prefix +Python/dtoa.c - private_mem variable static double private_mem[PRIVATE_mem] +Modules/itertoolsmodule.c - product_methods variable static PyMethodDef product_methods +Modules/itertoolsmodule.c - product_type variable static PyTypeObject product_type +Objects/descrobject.c - property_getsetlist variable static PyGetSetDef property_getsetlist[] +Objects/descrobject.c - property_members variable static PyMemberDef property_members[] +Objects/descrobject.c - property_methods variable static PyMethodDef property_methods +Objects/weakrefobject.c - proxy_as_mapping variable static PyMappingMethods proxy_as_mapping +Objects/weakrefobject.c - proxy_as_number variable static PyNumberMethods proxy_as_number +Objects/weakrefobject.c - proxy_as_sequence variable static PySequenceMethods proxy_as_sequence +Objects/weakrefobject.c - proxy_methods variable static PyMethodDef proxy_methods +Objects/typeobject.c resolve_slotdups ptrs variable static slotdef *ptrs[MAX_EQUIV] +Modules/pwdmodule.c - pwd_methods variable static PyMethodDef pwd_methods +Modules/pwdmodule.c - pwdmodule variable static struct PyModuleDef pwdmodule +Objects/object.c - _Py_abstract_hack variable Py_ssize_t (*_Py_abstract_hack)(PyObject *) +Objects/obmalloc.c - _Py_AllocatedBlocks variable static Py_ssize_t _Py_AllocatedBlocks +Objects/genobject.c - _PyAsyncGenASend_Type variable PyTypeObject _PyAsyncGenASend_Type +Objects/genobject.c - _PyAsyncGenAThrow_Type variable PyTypeObject _PyAsyncGenAThrow_Type +Objects/genobject.c - PyAsyncGen_Type variable PyTypeObject PyAsyncGen_Type +Objects/genobject.c - _PyAsyncGenWrappedValue_Type variable PyTypeObject _PyAsyncGenWrappedValue_Type +Objects/typeobject.c - PyBaseObject_Type variable PyTypeObject PyBaseObject_Type +Objects/boolobject.c - PyBool_Type variable PyTypeObject PyBool_Type +Modules/_io/bufferedio.c - PyBufferedIOBase_Type variable PyTypeObject PyBufferedIOBase_Type +Modules/_io/bufferedio.c - PyBufferedRandom_Type variable PyTypeObject PyBufferedRandom_Type +Modules/_io/bufferedio.c - PyBufferedReader_Type variable PyTypeObject PyBufferedReader_Type +Modules/_io/bufferedio.c - PyBufferedRWPair_Type variable PyTypeObject PyBufferedRWPair_Type +Modules/_io/bufferedio.c - PyBufferedWriter_Type variable PyTypeObject PyBufferedWriter_Type +Objects/bytearrayobject.c - _PyByteArray_empty_string variable char _PyByteArray_empty_string[] +Objects/bytearrayobject.c - PyByteArrayIter_Type variable PyTypeObject PyByteArrayIter_Type +Objects/bytearrayobject.c - PyByteArray_Type variable PyTypeObject PyByteArray_Type +Modules/_io/bytesio.c - _PyBytesIOBuffer_Type variable PyTypeObject _PyBytesIOBuffer_Type +Modules/_io/bytesio.c - PyBytesIO_Type variable PyTypeObject PyBytesIO_Type +Objects/bytesobject.c - PyBytesIter_Type variable PyTypeObject PyBytesIter_Type +Objects/bytesobject.c - PyBytes_Type variable PyTypeObject PyBytes_Type +Python/initconfig.c - Py_BytesWarningFlag variable int Py_BytesWarningFlag +Objects/iterobject.c - PyCallIter_Type variable PyTypeObject PyCallIter_Type +Objects/capsule.c - PyCapsule_Type variable PyTypeObject PyCapsule_Type +Objects/cellobject.c - PyCell_Type variable PyTypeObject PyCell_Type +Objects/methodobject.c - PyCFunction_Type variable PyTypeObject PyCFunction_Type +Python/ceval.c - _Py_CheckRecursionLimit variable int _Py_CheckRecursionLimit +Objects/descrobject.c - PyClassMethodDescr_Type variable PyTypeObject PyClassMethodDescr_Type +Objects/funcobject.c - PyClassMethod_Type variable PyTypeObject PyClassMethod_Type +Objects/codeobject.c - PyCode_Type variable PyTypeObject PyCode_Type +Objects/complexobject.c - PyComplex_Type variable PyTypeObject PyComplex_Type +Python/context.c - PyContext_as_mapping variable static PyMappingMethods PyContext_as_mapping +Python/context.c - PyContext_as_sequence variable static PySequenceMethods PyContext_as_sequence +Python/context.c - PyContext_methods variable static PyMethodDef PyContext_methods +Python/context.c - PyContextTokenMissing_Type variable PyTypeObject PyContextTokenMissing_Type +Python/context.c - PyContextToken_Type variable PyTypeObject PyContextToken_Type +Python/context.c - PyContextTokenType_getsetlist variable static PyGetSetDef PyContextTokenType_getsetlist[] +Python/context.c - PyContext_Type variable PyTypeObject PyContext_Type +Python/context.c - PyContextVar_members variable static PyMemberDef PyContextVar_members[] +Python/context.c - PyContextVar_methods variable static PyMethodDef PyContextVar_methods +Python/context.c - PyContextVar_Type variable PyTypeObject PyContextVar_Type +Objects/genobject.c - PyCoro_Type variable PyTypeObject PyCoro_Type +Objects/genobject.c - _PyCoroWrapper_Type variable PyTypeObject _PyCoroWrapper_Type +Python/initconfig.c - Py_DebugFlag variable int Py_DebugFlag +Objects/dictobject.c - pydict_global_version variable static uint64_t pydict_global_version +Objects/dictobject.c - PyDictItems_Type variable PyTypeObject PyDictItems_Type +Objects/dictobject.c - PyDictIterItem_Type variable PyTypeObject PyDictIterItem_Type +Objects/dictobject.c - PyDictIterKey_Type variable PyTypeObject PyDictIterKey_Type +Objects/dictobject.c - PyDictIterValue_Type variable PyTypeObject PyDictIterValue_Type +Objects/dictobject.c - PyDictKeys_Type variable PyTypeObject PyDictKeys_Type +Objects/descrobject.c - PyDictProxy_Type variable PyTypeObject PyDictProxy_Type +Objects/dictobject.c - PyDictRevIterItem_Type variable PyTypeObject PyDictRevIterItem_Type +Objects/dictobject.c - PyDictRevIterKey_Type variable PyTypeObject PyDictRevIterKey_Type +Objects/dictobject.c - PyDictRevIterValue_Type variable PyTypeObject PyDictRevIterValue_Type +Objects/dictobject.c - PyDict_Type variable PyTypeObject PyDict_Type +Objects/dictobject.c - PyDictValues_Type variable PyTypeObject PyDictValues_Type +Python/initconfig.c - Py_DontWriteBytecodeFlag variable int Py_DontWriteBytecodeFlag +Objects/sliceobject.c - _Py_EllipsisObject variable PyObject _Py_EllipsisObject +Objects/sliceobject.c - PyEllipsis_Type variable PyTypeObject PyEllipsis_Type +Objects/enumobject.c - PyEnum_Type variable PyTypeObject PyEnum_Type +Objects/exceptions.c - _PyExc_ArithmeticError variable static PyTypeObject _PyExc_ArithmeticError +Objects/exceptions.c - PyExc_ArithmeticError variable static PyTypeObject PyExc_ArithmeticError +Objects/exceptions.c - _PyExc_AssertionError variable static PyTypeObject _PyExc_AssertionError +Objects/exceptions.c - PyExc_AssertionError variable static PyTypeObject PyExc_AssertionError +Objects/exceptions.c - _PyExc_AttributeError variable static PyTypeObject _PyExc_AttributeError +Objects/exceptions.c - PyExc_AttributeError variable static PyTypeObject PyExc_AttributeError +Objects/exceptions.c - _PyExc_BaseException variable static PyTypeObject _PyExc_BaseException +Objects/exceptions.c - PyExc_BaseException variable static PyTypeObject PyExc_BaseException +Objects/exceptions.c - _PyExc_BlockingIOError variable static PyTypeObject _PyExc_BlockingIOError +Objects/exceptions.c - PyExc_BlockingIOError variable static PyTypeObject PyExc_BlockingIOError +Objects/exceptions.c - _PyExc_BrokenPipeError variable static PyTypeObject _PyExc_BrokenPipeError +Objects/exceptions.c - PyExc_BrokenPipeError variable static PyTypeObject PyExc_BrokenPipeError +Objects/exceptions.c - _PyExc_BufferError variable static PyTypeObject _PyExc_BufferError +Objects/exceptions.c - PyExc_BufferError variable static PyTypeObject PyExc_BufferError +Objects/exceptions.c - _PyExc_BytesWarning variable static PyTypeObject _PyExc_BytesWarning +Objects/exceptions.c - PyExc_BytesWarning variable static PyTypeObject PyExc_BytesWarning +Objects/exceptions.c - _PyExc_ChildProcessError variable static PyTypeObject _PyExc_ChildProcessError +Objects/exceptions.c - PyExc_ChildProcessError variable static PyTypeObject PyExc_ChildProcessError +Objects/exceptions.c - _PyExc_ConnectionAbortedError variable static PyTypeObject _PyExc_ConnectionAbortedError +Objects/exceptions.c - PyExc_ConnectionAbortedError variable static PyTypeObject PyExc_ConnectionAbortedError +Objects/exceptions.c - _PyExc_ConnectionError variable static PyTypeObject _PyExc_ConnectionError +Objects/exceptions.c - PyExc_ConnectionError variable static PyTypeObject PyExc_ConnectionError +Objects/exceptions.c - _PyExc_ConnectionRefusedError variable static PyTypeObject _PyExc_ConnectionRefusedError +Objects/exceptions.c - PyExc_ConnectionRefusedError variable static PyTypeObject PyExc_ConnectionRefusedError +Objects/exceptions.c - _PyExc_ConnectionResetError variable static PyTypeObject _PyExc_ConnectionResetError +Objects/exceptions.c - PyExc_ConnectionResetError variable static PyTypeObject PyExc_ConnectionResetError +Objects/exceptions.c - _PyExc_DeprecationWarning variable static PyTypeObject _PyExc_DeprecationWarning +Objects/exceptions.c - PyExc_DeprecationWarning variable static PyTypeObject PyExc_DeprecationWarning +Objects/exceptions.c - PyExc_EnvironmentError variable static PyTypeObject PyExc_EnvironmentError +Objects/exceptions.c - _PyExc_EOFError variable static PyTypeObject _PyExc_EOFError +Objects/exceptions.c - PyExc_EOFError variable static PyTypeObject PyExc_EOFError +Objects/exceptions.c - _PyExc_Exception variable static PyTypeObject _PyExc_Exception +Objects/exceptions.c - PyExc_Exception variable static PyTypeObject PyExc_Exception +Objects/exceptions.c - _PyExc_FileExistsError variable static PyTypeObject _PyExc_FileExistsError +Objects/exceptions.c - PyExc_FileExistsError variable static PyTypeObject PyExc_FileExistsError +Objects/exceptions.c - _PyExc_FileNotFoundError variable static PyTypeObject _PyExc_FileNotFoundError +Objects/exceptions.c - PyExc_FileNotFoundError variable static PyTypeObject PyExc_FileNotFoundError +Objects/exceptions.c - _PyExc_FloatingPointError variable static PyTypeObject _PyExc_FloatingPointError +Objects/exceptions.c - PyExc_FloatingPointError variable static PyTypeObject PyExc_FloatingPointError +Objects/exceptions.c - _PyExc_FutureWarning variable static PyTypeObject _PyExc_FutureWarning +Objects/exceptions.c - PyExc_FutureWarning variable static PyTypeObject PyExc_FutureWarning +Objects/exceptions.c - _PyExc_GeneratorExit variable static PyTypeObject _PyExc_GeneratorExit +Objects/exceptions.c - PyExc_GeneratorExit variable static PyTypeObject PyExc_GeneratorExit +Objects/exceptions.c - _PyExc_ImportError variable static PyTypeObject _PyExc_ImportError +Objects/exceptions.c - PyExc_ImportError variable static PyTypeObject PyExc_ImportError +Objects/exceptions.c - _PyExc_ImportWarning variable static PyTypeObject _PyExc_ImportWarning +Objects/exceptions.c - PyExc_ImportWarning variable static PyTypeObject PyExc_ImportWarning +Objects/exceptions.c - _PyExc_IndentationError variable static PyTypeObject _PyExc_IndentationError +Objects/exceptions.c - PyExc_IndentationError variable static PyTypeObject PyExc_IndentationError +Objects/exceptions.c - _PyExc_IndexError variable static PyTypeObject _PyExc_IndexError +Objects/exceptions.c - PyExc_IndexError variable static PyTypeObject PyExc_IndexError +Objects/exceptions.c - _PyExc_InterruptedError variable static PyTypeObject _PyExc_InterruptedError +Objects/exceptions.c - PyExc_InterruptedError variable static PyTypeObject PyExc_InterruptedError +Objects/exceptions.c - PyExc_IOError variable static PyTypeObject PyExc_IOError +Objects/exceptions.c - _PyExc_IsADirectoryError variable static PyTypeObject _PyExc_IsADirectoryError +Objects/exceptions.c - PyExc_IsADirectoryError variable static PyTypeObject PyExc_IsADirectoryError +Objects/exceptions.c - _PyExc_KeyboardInterrupt variable static PyTypeObject _PyExc_KeyboardInterrupt +Objects/exceptions.c - PyExc_KeyboardInterrupt variable static PyTypeObject PyExc_KeyboardInterrupt +Objects/exceptions.c - _PyExc_KeyError variable static PyTypeObject _PyExc_KeyError +Objects/exceptions.c - PyExc_KeyError variable static PyTypeObject PyExc_KeyError +Objects/exceptions.c - _PyExc_LookupError variable static PyTypeObject _PyExc_LookupError +Objects/exceptions.c - PyExc_LookupError variable static PyTypeObject PyExc_LookupError +Objects/exceptions.c - _PyExc_MemoryError variable static PyTypeObject _PyExc_MemoryError +Objects/exceptions.c - PyExc_MemoryError variable static PyTypeObject PyExc_MemoryError +Objects/exceptions.c - _PyExc_ModuleNotFoundError variable static PyTypeObject _PyExc_ModuleNotFoundError +Objects/exceptions.c - PyExc_ModuleNotFoundError variable static PyTypeObject PyExc_ModuleNotFoundError +Objects/exceptions.c - _PyExc_NameError variable static PyTypeObject _PyExc_NameError +Objects/exceptions.c - PyExc_NameError variable static PyTypeObject PyExc_NameError +Objects/exceptions.c - _PyExc_NotADirectoryError variable static PyTypeObject _PyExc_NotADirectoryError +Objects/exceptions.c - PyExc_NotADirectoryError variable static PyTypeObject PyExc_NotADirectoryError +Objects/exceptions.c - _PyExc_NotImplementedError variable static PyTypeObject _PyExc_NotImplementedError +Objects/exceptions.c - PyExc_NotImplementedError variable static PyTypeObject PyExc_NotImplementedError +Objects/exceptions.c - _PyExc_OSError variable static PyTypeObject _PyExc_OSError +Objects/exceptions.c - PyExc_OSError variable static PyTypeObject PyExc_OSError +Objects/exceptions.c - _PyExc_OverflowError variable static PyTypeObject _PyExc_OverflowError +Objects/exceptions.c - PyExc_OverflowError variable static PyTypeObject PyExc_OverflowError +Objects/exceptions.c - _PyExc_PendingDeprecationWarning variable static PyTypeObject _PyExc_PendingDeprecationWarning +Objects/exceptions.c - PyExc_PendingDeprecationWarning variable static PyTypeObject PyExc_PendingDeprecationWarning +Objects/exceptions.c - _PyExc_PermissionError variable static PyTypeObject _PyExc_PermissionError +Objects/exceptions.c - PyExc_PermissionError variable static PyTypeObject PyExc_PermissionError +Objects/exceptions.c - _PyExc_ProcessLookupError variable static PyTypeObject _PyExc_ProcessLookupError +Objects/exceptions.c - PyExc_ProcessLookupError variable static PyTypeObject PyExc_ProcessLookupError +Objects/exceptions.c - _PyExc_RecursionError variable static PyTypeObject _PyExc_RecursionError +Objects/exceptions.c - PyExc_RecursionError variable static PyTypeObject PyExc_RecursionError +Objects/exceptions.c - _PyExc_ReferenceError variable static PyTypeObject _PyExc_ReferenceError +Objects/exceptions.c - PyExc_ReferenceError variable static PyTypeObject PyExc_ReferenceError +Objects/exceptions.c - _PyExc_ResourceWarning variable static PyTypeObject _PyExc_ResourceWarning +Objects/exceptions.c - PyExc_ResourceWarning variable static PyTypeObject PyExc_ResourceWarning +Objects/exceptions.c - _PyExc_RuntimeError variable static PyTypeObject _PyExc_RuntimeError +Objects/exceptions.c - PyExc_RuntimeError variable static PyTypeObject PyExc_RuntimeError +Objects/exceptions.c - _PyExc_RuntimeWarning variable static PyTypeObject _PyExc_RuntimeWarning +Objects/exceptions.c - PyExc_RuntimeWarning variable static PyTypeObject PyExc_RuntimeWarning +Objects/exceptions.c - _PyExc_StopAsyncIteration variable static PyTypeObject _PyExc_StopAsyncIteration +Objects/exceptions.c - PyExc_StopAsyncIteration variable static PyTypeObject PyExc_StopAsyncIteration +Objects/exceptions.c - _PyExc_StopIteration variable static PyTypeObject _PyExc_StopIteration +Objects/exceptions.c - PyExc_StopIteration variable static PyTypeObject PyExc_StopIteration +Objects/exceptions.c - _PyExc_SyntaxError variable static PyTypeObject _PyExc_SyntaxError +Objects/exceptions.c - PyExc_SyntaxError variable static PyTypeObject PyExc_SyntaxError +Objects/exceptions.c - _PyExc_SyntaxWarning variable static PyTypeObject _PyExc_SyntaxWarning +Objects/exceptions.c - PyExc_SyntaxWarning variable static PyTypeObject PyExc_SyntaxWarning +Objects/exceptions.c - _PyExc_SystemError variable static PyTypeObject _PyExc_SystemError +Objects/exceptions.c - PyExc_SystemError variable static PyTypeObject PyExc_SystemError +Objects/exceptions.c - _PyExc_SystemExit variable static PyTypeObject _PyExc_SystemExit +Objects/exceptions.c - PyExc_SystemExit variable static PyTypeObject PyExc_SystemExit +Objects/exceptions.c - _PyExc_TabError variable static PyTypeObject _PyExc_TabError +Objects/exceptions.c - PyExc_TabError variable static PyTypeObject PyExc_TabError +Objects/exceptions.c - _PyExc_TargetScopeError variable static PyTypeObject _PyExc_TargetScopeError +Objects/exceptions.c - PyExc_TargetScopeError variable static PyTypeObject PyExc_TargetScopeError +Objects/exceptions.c - _PyExc_TimeoutError variable static PyTypeObject _PyExc_TimeoutError +Objects/exceptions.c - PyExc_TimeoutError variable static PyTypeObject PyExc_TimeoutError +Objects/exceptions.c - _PyExc_TypeError variable static PyTypeObject _PyExc_TypeError +Objects/exceptions.c - PyExc_TypeError variable static PyTypeObject PyExc_TypeError +Objects/exceptions.c - _PyExc_UnboundLocalError variable static PyTypeObject _PyExc_UnboundLocalError +Objects/exceptions.c - PyExc_UnboundLocalError variable static PyTypeObject PyExc_UnboundLocalError +Objects/exceptions.c - _PyExc_UnicodeDecodeError variable static PyTypeObject _PyExc_UnicodeDecodeError +Objects/exceptions.c - PyExc_UnicodeDecodeError variable static PyTypeObject PyExc_UnicodeDecodeError +Objects/exceptions.c - _PyExc_UnicodeEncodeError variable static PyTypeObject _PyExc_UnicodeEncodeError +Objects/exceptions.c - PyExc_UnicodeEncodeError variable static PyTypeObject PyExc_UnicodeEncodeError +Objects/exceptions.c - _PyExc_UnicodeError variable static PyTypeObject _PyExc_UnicodeError +Objects/exceptions.c - PyExc_UnicodeError variable static PyTypeObject PyExc_UnicodeError +Objects/exceptions.c - _PyExc_UnicodeTranslateError variable static PyTypeObject _PyExc_UnicodeTranslateError +Objects/exceptions.c - PyExc_UnicodeTranslateError variable static PyTypeObject PyExc_UnicodeTranslateError +Objects/exceptions.c - _PyExc_UnicodeWarning variable static PyTypeObject _PyExc_UnicodeWarning +Objects/exceptions.c - PyExc_UnicodeWarning variable static PyTypeObject PyExc_UnicodeWarning +Objects/exceptions.c - _PyExc_UserWarning variable static PyTypeObject _PyExc_UserWarning +Objects/exceptions.c - PyExc_UserWarning variable static PyTypeObject PyExc_UserWarning +Objects/exceptions.c - _PyExc_ValueError variable static PyTypeObject _PyExc_ValueError +Objects/exceptions.c - PyExc_ValueError variable static PyTypeObject PyExc_ValueError +Objects/exceptions.c - _PyExc_Warning variable static PyTypeObject _PyExc_Warning +Objects/exceptions.c - PyExc_Warning variable static PyTypeObject PyExc_Warning +Objects/exceptions.c - _PyExc_ZeroDivisionError variable static PyTypeObject _PyExc_ZeroDivisionError +Objects/exceptions.c - PyExc_ZeroDivisionError variable static PyTypeObject PyExc_ZeroDivisionError +Objects/boolobject.c - _Py_FalseStruct variable static struct _longobject _Py_FalseStruct +Objects/stringlib/unicode_format.h - PyFieldNameIter_Type variable static PyTypeObject PyFieldNameIter_Type +Modules/_io/fileio.c - PyFileIO_Type variable PyTypeObject PyFileIO_Type +Python/preconfig.c - Py_FileSystemDefaultEncodeErrors variable const char *Py_FileSystemDefaultEncodeErrors +Python/preconfig.c - Py_FileSystemDefaultEncoding variable const char *Py_FileSystemDefaultEncoding +Python/bltinmodule.c - PyFilter_Type variable PyTypeObject PyFilter_Type +Objects/floatobject.c - PyFloat_Type variable PyTypeObject PyFloat_Type +Objects/stringlib/unicode_format.h - PyFormatterIter_Type variable static PyTypeObject PyFormatterIter_Type +Objects/frameobject.c - PyFrame_Type variable PyTypeObject PyFrame_Type +Python/initconfig.c - Py_FrozenFlag variable int Py_FrozenFlag +Objects/setobject.c - PyFrozenSet_Type variable PyTypeObject PyFrozenSet_Type +Objects/funcobject.c - PyFunction_Type variable PyTypeObject PyFunction_Type +Objects/genobject.c - PyGen_Type variable PyTypeObject PyGen_Type +Objects/descrobject.c - PyGetSetDescr_Type variable PyTypeObject PyGetSetDescr_Type +Python/hamt.c - _PyHamt_ArrayNode_Type variable PyTypeObject _PyHamt_ArrayNode_Type +Python/hamt.c - PyHamt_as_mapping variable static PyMappingMethods PyHamt_as_mapping +Python/hamt.c - PyHamt_as_sequence variable static PySequenceMethods PyHamt_as_sequence +Python/hamt.c - _PyHamt_BitmapNode_Type variable PyTypeObject _PyHamt_BitmapNode_Type +Python/hamt.c - _PyHamt_CollisionNode_Type variable PyTypeObject _PyHamt_CollisionNode_Type +Python/hamt.c - _PyHamtItems_Type variable PyTypeObject _PyHamtItems_Type +Python/hamt.c - PyHamtIterator_as_mapping variable static PyMappingMethods PyHamtIterator_as_mapping +Python/hamt.c - _PyHamtKeys_Type variable PyTypeObject _PyHamtKeys_Type +Python/hamt.c - PyHamt_methods variable static PyMethodDef PyHamt_methods +Python/hamt.c - _PyHamt_Type variable PyTypeObject _PyHamt_Type +Python/hamt.c - _PyHamtValues_Type variable PyTypeObject _PyHamtValues_Type +Python/preconfig.c - _Py_HasFileSystemDefaultEncodeErrors variable int _Py_HasFileSystemDefaultEncodeErrors +Python/preconfig.c - Py_HasFileSystemDefaultEncoding variable int Py_HasFileSystemDefaultEncoding +Python/pyhash.c - PyHash_Func variable static PyHash_FuncDef PyHash_Func +Python/initconfig.c - Py_HashRandomizationFlag variable int Py_HashRandomizationFlag +Include/pyhash.h - _Py_HashSecret variable PyAPI_DATA(_Py_HashSecret_t) _Py_HashSecret +Python/bootstrap_hash.c - _Py_HashSecret_Initialized variable static int _Py_HashSecret_Initialized +Python/codecs.c - Py_hexdigits variable const char *Py_hexdigits +Python/sysmodule.c - PyId__ variable _Py_IDENTIFIER(_) +Modules/_abc.c - PyId__abc_impl variable _Py_IDENTIFIER(_abc_impl) +Objects/typeobject.c - PyId___abstractmethods__ variable _Py_IDENTIFIER(__abstractmethods__) +Modules/_abc.c - PyId___abstractmethods__ variable _Py_IDENTIFIER(__abstractmethods__) +Python/ceval.c _PyEval_EvalFrameDefault PyId___aenter__ variable _Py_IDENTIFIER(__aenter__) +Python/ceval.c _PyEval_EvalFrameDefault PyId___aexit__ variable _Py_IDENTIFIER(__aexit__) +Objects/typeobject.c slot_am_aiter PyId___aiter__ variable _Py_IDENTIFIER(__aiter__) +Python/ceval.c import_all_from PyId___all__ variable _Py_IDENTIFIER(__all__) +Objects/typeobject.c slot_am_anext PyId___anext__ variable _Py_IDENTIFIER(__anext__) +Python/Python-ast.c - PyId_annotation variable _Py_IDENTIFIER(annotation) +Python/ceval.c _PyEval_EvalFrameDefault PyId___annotations__ variable _Py_IDENTIFIER(__annotations__) +Python/Python-ast.c - PyId_arg variable _Py_IDENTIFIER(arg) +Python/Python-ast.c - PyId_args variable _Py_IDENTIFIER(args) +Python/Python-ast.c - PyId_argtypes variable _Py_IDENTIFIER(argtypes) +Python/Python-ast.c - PyId_asname variable _Py_IDENTIFIER(asname) +Python/Python-ast.c make_type PyId__ast variable _Py_IDENTIFIER(_ast) +Python/Python-ast.c - PyId_attr variable _Py_IDENTIFIER(attr) +Python/Python-ast.c - PyId__attributes variable _Py_IDENTIFIER(_attributes) +Objects/typeobject.c slot_am_await PyId___await__ variable _Py_IDENTIFIER(__await__) +Python/Python-ast.c - PyId_bases variable _Py_IDENTIFIER(bases) +Modules/_abc.c - PyId___bases__ variable _Py_IDENTIFIER(__bases__) +Objects/abstract.c abstract_get_bases PyId___bases__ variable _Py_IDENTIFIER(__bases__) +Objects/typeobject.c merge_class_dict PyId___bases__ variable _Py_IDENTIFIER(__bases__) +Objects/longobject.c - PyId_big variable _Py_IDENTIFIER(big) +Modules/_io/_iomodule.c - PyId__blksize variable _Py_IDENTIFIER(_blksize) +Python/Python-ast.c - PyId_body variable _Py_IDENTIFIER(body) +Objects/typeobject.c slot_nb_bool PyId___bool__ variable _Py_IDENTIFIER(__bool__) +Python/sysmodule.c - PyId_buffer variable _Py_IDENTIFIER(buffer) +Python/ceval.c _PyEval_EvalFrameDefault PyId___build_class__ variable _Py_IDENTIFIER(__build_class__) +Objects/typeobject.c - PyId_builtins variable _Py_IDENTIFIER(builtins) +Python/errors.c - PyId_builtins variable _Py_IDENTIFIER(builtins) +Python/pythonrun.c - PyId_builtins variable _Py_IDENTIFIER(builtins) +Python/sysmodule.c - PyId_builtins variable _Py_IDENTIFIER(builtins) +Objects/frameobject.c - PyId___builtins__ variable _Py_IDENTIFIER(__builtins__) +Python/bltinmodule.c - PyId___builtins__ variable _Py_IDENTIFIER(__builtins__) +Python/import.c module_dict_for_exec PyId___builtins__ variable _Py_IDENTIFIER(__builtins__) +Objects/object.c - PyId___bytes__ variable _Py_IDENTIFIER(__bytes__) +Objects/bytesobject.c format_obj PyId___bytes__ variable _Py_IDENTIFIER(__bytes__) +Objects/bytesobject.c bytes_new PyId___bytes__ variable _Py_IDENTIFIER(__bytes__) +Objects/weakrefobject.c proxy_bytes PyId___bytes__ variable _Py_IDENTIFIER(__bytes__) +Objects/typeobject.c slot_tp_call PyId___call__ variable _Py_IDENTIFIER(__call__) +Python/Python-ast.c - PyId_cause variable _Py_IDENTIFIER(cause) +Objects/typeobject.c - PyId___class__ variable _Py_IDENTIFIER(__class__) +Modules/_abc.c - PyId___class__ variable _Py_IDENTIFIER(__class__) +Python/compile.c - PyId___class__ variable _Py_IDENTIFIER(__class__) +Objects/abstract.c recursive_isinstance PyId___class__ variable _Py_IDENTIFIER(__class__) +Objects/typeobject.c type_new PyId___classcell__ variable _Py_IDENTIFIER(__classcell__) +Objects/typeobject.c - PyId___class_getitem__ variable _Py_IDENTIFIER(__class_getitem__) +Objects/abstract.c PyObject_GetItem PyId___class_getitem__ variable _Py_IDENTIFIER(__class_getitem__) +Python/import.c PyImport_Cleanup PyId_clear variable _Py_IDENTIFIER(clear) +Python/traceback.c - PyId_close variable _Py_IDENTIFIER(close) +Modules/_io/bufferedio.c - PyId_close variable _Py_IDENTIFIER(close) +Modules/_io/textio.c - PyId_close variable _Py_IDENTIFIER(close) +Objects/genobject.c gen_close_iter PyId_close variable _Py_IDENTIFIER(close) +Modules/_dbmmodule.c dbm__exit__ PyId_close variable _Py_IDENTIFIER(close) +Modules/_gdbmmodule.c dbm__exit__ PyId_close variable _Py_IDENTIFIER(close) +Python/pythonrun.c _Py_HandleSystemExit PyId_code variable _Py_IDENTIFIER(code) +Python/Python-ast.c - PyId_col_offset variable _Py_IDENTIFIER(col_offset) +Python/Python-ast.c - PyId_comparators variable _Py_IDENTIFIER(comparators) +Objects/complexobject.c try_complex_special_method PyId___complex__ variable _Py_IDENTIFIER(__complex__) +Objects/typeobject.c slot_sq_contains PyId___contains__ variable _Py_IDENTIFIER(__contains__) +Python/Python-ast.c - PyId_context_expr variable _Py_IDENTIFIER(context_expr) +Python/Python-ast.c - PyId_conversion variable _Py_IDENTIFIER(conversion) +Modules/itertoolsmodule.c - PyId___copy__ variable _Py_IDENTIFIER(__copy__) +Objects/descrobject.c mappingproxy_copy PyId_copy variable _Py_IDENTIFIER(copy) +Objects/typeobject.c import_copyreg PyId_copyreg variable _Py_IDENTIFIER(copyreg) +Python/Python-ast.c - PyId_ctx variable _Py_IDENTIFIER(ctx) +Modules/_io/bufferedio.c - PyId__dealloc_warn variable _Py_IDENTIFIER(_dealloc_warn) +Modules/_io/textio.c - PyId__dealloc_warn variable _Py_IDENTIFIER(_dealloc_warn) +Modules/_io/textio.c - PyId_decode variable _Py_IDENTIFIER(decode) +Python/Python-ast.c - PyId_decorator_list variable _Py_IDENTIFIER(decorator_list) +Python/_warnings.c get_default_action PyId_defaultaction variable _Py_IDENTIFIER(defaultaction) +Python/Python-ast.c - PyId_defaults variable _Py_IDENTIFIER(defaults) +Objects/typeobject.c slot_tp_finalize PyId___del__ variable _Py_IDENTIFIER(__del__) +Objects/typeobject.c slot_tp_setattro PyId___delattr__ variable _Py_IDENTIFIER(__delattr__) +Objects/typeobject.c slot_tp_descr_set PyId___delete__ variable _Py_IDENTIFIER(__delete__) +Objects/typeobject.c - PyId___delitem__ variable _Py_IDENTIFIER(__delitem__) +Objects/typeobject.c - PyId___dict__ variable _Py_IDENTIFIER(__dict__) +Modules/_abc.c - PyId___dict__ variable _Py_IDENTIFIER(__dict__) +Python/bltinmodule.c - PyId___dict__ variable _Py_IDENTIFIER(__dict__) +Python/Python-ast.c ast_type_reduce PyId___dict__ variable _Py_IDENTIFIER(__dict__) +Python/ceval.c import_all_from PyId___dict__ variable _Py_IDENTIFIER(__dict__) +Objects/bytearrayobject.c _common_reduce PyId___dict__ variable _Py_IDENTIFIER(__dict__) +Objects/moduleobject.c module_dir PyId___dict__ variable _Py_IDENTIFIER(__dict__) +Objects/odictobject.c odict_reduce PyId___dict__ variable _Py_IDENTIFIER(__dict__) +Objects/setobject.c set_reduce PyId___dict__ variable _Py_IDENTIFIER(__dict__) +Modules/_collectionsmodule.c deque_reduce PyId___dict__ variable _Py_IDENTIFIER(__dict__) +Objects/dictobject.c dictviews_sub PyId_difference_update variable _Py_IDENTIFIER(difference_update) +Python/Python-ast.c - PyId_dims variable _Py_IDENTIFIER(dims) +Objects/object.c - PyId___dir__ variable _Py_IDENTIFIER(__dir__) +Objects/moduleobject.c module_dir PyId___dir__ variable _Py_IDENTIFIER(__dir__) +Python/ceval.c _PyEval_EvalFrameDefault PyId_displayhook variable _Py_IDENTIFIER(displayhook) +Objects/typeobject.c - PyId___doc__ variable _Py_IDENTIFIER(__doc__) +Objects/descrobject.c - PyId___doc__ variable _Py_IDENTIFIER(__doc__) +Objects/moduleobject.c - PyId___doc__ variable _Py_IDENTIFIER(__doc__) +Objects/moduleobject.c PyModule_SetDocString PyId___doc__ variable _Py_IDENTIFIER(__doc__) +Python/Python-ast.c - PyId_elt variable _Py_IDENTIFIER(elt) +Python/Python-ast.c - PyId_elts variable _Py_IDENTIFIER(elts) +Modules/faulthandler.c - PyId_enable variable _Py_IDENTIFIER(enable) +Python/sysmodule.c - PyId_encoding variable _Py_IDENTIFIER(encoding) +Python/bltinmodule.c - PyId_encoding variable _Py_IDENTIFIER(encoding) +Python/pythonrun.c - PyId_encoding variable _Py_IDENTIFIER(encoding) +Python/Python-ast.c - PyId_end_col_offset variable _Py_IDENTIFIER(end_col_offset) +Python/Python-ast.c - PyId_end_lineno variable _Py_IDENTIFIER(end_lineno) +Python/ceval.c _PyEval_EvalFrameDefault PyId___enter__ variable _Py_IDENTIFIER(__enter__) +Objects/typeobject.c overrides_hash PyId___eq__ variable _Py_IDENTIFIER(__eq__) +Python/bltinmodule.c - PyId_errors variable _Py_IDENTIFIER(errors) +Python/Python-ast.c - PyId_exc variable _Py_IDENTIFIER(exc) +Python/pythonrun.c - PyId_excepthook variable _Py_IDENTIFIER(excepthook) +Python/ceval.c _PyEval_EvalFrameDefault PyId___exit__ variable _Py_IDENTIFIER(__exit__) +Modules/_pickle.c do_append PyId_extend variable _Py_IDENTIFIER(extend) +Python/Python-ast.c - PyId__fields variable _Py_IDENTIFIER(_fields) +Objects/moduleobject.c PyModule_GetFilenameObject PyId___file__ variable _Py_IDENTIFIER(__file__) +Python/errors.c PyErr_SyntaxLocationObject PyId_filename variable _Py_IDENTIFIER(filename) +Python/pythonrun.c - PyId_filename variable _Py_IDENTIFIER(filename) +Modules/_io/textio.c - PyId_fileno variable _Py_IDENTIFIER(fileno) +Modules/faulthandler.c - PyId_fileno variable _Py_IDENTIFIER(fileno) +Python/bltinmodule.c - PyId_fileno variable _Py_IDENTIFIER(fileno) +Objects/fileobject.c PyObject_AsFileDescriptor PyId_fileno variable _Py_IDENTIFIER(fileno) +Modules/itertoolsmodule.c zip_longest_new PyId_fillvalue variable _Py_IDENTIFIER(fillvalue) +Python/_warnings.c - PyId_filters variable _Py_IDENTIFIER(filters) +Python/Python-ast.c - PyId_finalbody variable _Py_IDENTIFIER(finalbody) +Modules/_io/iobase.c iobase_finalize PyId__finalizing variable _Py_IDENTIFIER(_finalizing) +Python/import.c import_find_and_load PyId__find_and_load variable _Py_IDENTIFIER(_find_and_load) +Python/import.c - PyId__fix_up_module variable _Py_IDENTIFIER(_fix_up_module) +Python/errors.c - PyId_flush variable _Py_IDENTIFIER(flush) +Python/pylifecycle.c - PyId_flush variable _Py_IDENTIFIER(flush) +Python/pythonrun.c - PyId_flush variable _Py_IDENTIFIER(flush) +Modules/_threadmodule.c - PyId_flush variable _Py_IDENTIFIER(flush) +Modules/_io/bufferedio.c - PyId_flush variable _Py_IDENTIFIER(flush) +Modules/_io/textio.c - PyId_flush variable _Py_IDENTIFIER(flush) +Modules/faulthandler.c - PyId_flush variable _Py_IDENTIFIER(flush) +Python/bltinmodule.c - PyId_flush variable _Py_IDENTIFIER(flush) +Objects/abstract.c PyObject_Format PyId___format__ variable _Py_IDENTIFIER(__format__) +Python/Python-ast.c - PyId_format_spec variable _Py_IDENTIFIER(format_spec) +Modules/posixmodule.c path_converter PyId___fspath__ variable _Py_IDENTIFIER(__fspath__) +Modules/posixmodule.c PyOS_FSPath PyId___fspath__ variable _Py_IDENTIFIER(__fspath__) +Python/Python-ast.c - PyId_func variable _Py_IDENTIFIER(func) +Python/Python-ast.c - PyId_generators variable _Py_IDENTIFIER(generators) +Objects/descrobject.c mappingproxy_get PyId_get variable _Py_IDENTIFIER(get) +Modules/_collectionsmodule.c _count_elements PyId_get variable _Py_IDENTIFIER(get) +Objects/typeobject.c slot_tp_descr_get PyId___get__ variable _Py_IDENTIFIER(__get__) +Objects/classobject.c method_reduce PyId_getattr variable _Py_IDENTIFIER(getattr) +Objects/descrobject.c descr_reduce PyId_getattr variable _Py_IDENTIFIER(getattr) +Objects/descrobject.c wrapper_reduce PyId_getattr variable _Py_IDENTIFIER(getattr) +Objects/moduleobject.c module_getattro PyId___getattr__ variable _Py_IDENTIFIER(__getattr__) +Objects/methodobject.c meth_reduce PyId_getattr variable _Py_IDENTIFIER(getattr) +Objects/typeobject.c slot_tp_getattr_hook PyId___getattr__ variable _Py_IDENTIFIER(__getattr__) +Objects/typeobject.c - PyId___getattribute__ variable _Py_IDENTIFIER(__getattribute__) +Objects/typeobject.c - PyId___getitem__ variable _Py_IDENTIFIER(__getitem__) +Objects/typeobject.c _PyObject_GetNewArguments PyId___getnewargs__ variable _Py_IDENTIFIER(__getnewargs__) +Objects/typeobject.c _PyObject_GetNewArguments PyId___getnewargs_ex__ variable _Py_IDENTIFIER(__getnewargs_ex__) +Modules/_io/textio.c - PyId_getpreferredencoding variable _Py_IDENTIFIER(getpreferredencoding) +Python/_warnings.c get_source_line PyId_get_source variable _Py_IDENTIFIER(get_source) +Python/import.c - PyId__get_sourcefile variable _Py_IDENTIFIER(_get_sourcefile) +Objects/typeobject.c _PyObject_GetState PyId___getstate__ variable _Py_IDENTIFIER(__getstate__) +Python/import.c - PyId__handle_fromlist variable _Py_IDENTIFIER(_handle_fromlist) +Python/Python-ast.c - PyId_handlers variable _Py_IDENTIFIER(handlers) +Objects/typeobject.c - PyId___hash__ variable _Py_IDENTIFIER(__hash__) +Python/Python-ast.c - PyId_id variable _Py_IDENTIFIER(id) +Python/Python-ast.c - PyId_ifs variable _Py_IDENTIFIER(ifs) +Python/import.c PyImport_ReloadModule PyId_imp variable _Py_IDENTIFIER(imp) +Python/ceval.c - PyId___import__ variable _Py_IDENTIFIER(__import__) +Objects/typeobject.c slot_nb_index PyId___index__ variable _Py_IDENTIFIER(__index__) +Objects/typeobject.c slot_tp_init PyId___init__ variable _Py_IDENTIFIER(__init__) +Objects/moduleobject.c _PyModuleSpec_IsInitializing PyId__initializing variable _Py_IDENTIFIER(_initializing) +Objects/typeobject.c - PyId___init_subclass__ variable _Py_IDENTIFIER(__init_subclass__) +Objects/abstract.c PyObject_IsInstance PyId___instancecheck__ variable _Py_IDENTIFIER(__instancecheck__) +Objects/dictobject.c _PyDictView_Intersect PyId_intersection_update variable _Py_IDENTIFIER(intersection_update) +Modules/_io/iobase.c - PyId___IOBase_closed variable _Py_IDENTIFIER(__IOBase_closed) +Objects/typeobject.c slot_nb_inplace_power PyId___ipow__ variable _Py_IDENTIFIER(__ipow__) +Objects/object.c - PyId___isabstractmethod__ variable _Py_IDENTIFIER(__isabstractmethod__) +Python/Python-ast.c - PyId_is_async variable _Py_IDENTIFIER(is_async) +Modules/_io/bufferedio.c - PyId_isatty variable _Py_IDENTIFIER(isatty) +Modules/_io/textio.c - PyId_isatty variable _Py_IDENTIFIER(isatty) +Python/pylifecycle.c - PyId_isatty variable _Py_IDENTIFIER(isatty) +Modules/_io/_iomodule.c - PyId_isatty variable _Py_IDENTIFIER(isatty) +Python/codecs.c - PyId__is_text_encoding variable _Py_IDENTIFIER(_is_text_encoding) +Python/Python-ast.c - PyId_items variable _Py_IDENTIFIER(items) +Objects/abstract.c PyMapping_Items PyId_items variable _Py_IDENTIFIER(items) +Objects/descrobject.c mappingproxy_items PyId_items variable _Py_IDENTIFIER(items) +Objects/odictobject.c odict_reduce PyId_items variable _Py_IDENTIFIER(items) +Objects/odictobject.c odict_repr PyId_items variable _Py_IDENTIFIER(items) +Objects/odictobject.c mutablemapping_update PyId_items variable _Py_IDENTIFIER(items) +Objects/typeobject.c - PyId_items variable _Py_IDENTIFIER(items) +Modules/_collectionsmodule.c defdict_reduce PyId_items variable _Py_IDENTIFIER(items) +Python/Python-ast.c - PyId_iter variable _Py_IDENTIFIER(iter) +Objects/bytearrayobject.c bytearrayiter_reduce PyId_iter variable _Py_IDENTIFIER(iter) +Objects/bytesobject.c striter_reduce PyId_iter variable _Py_IDENTIFIER(iter) +Objects/dictobject.c dictiter_reduce PyId_iter variable _Py_IDENTIFIER(iter) +Objects/iterobject.c iter_reduce PyId_iter variable _Py_IDENTIFIER(iter) +Objects/iterobject.c calliter_reduce PyId_iter variable _Py_IDENTIFIER(iter) +Objects/listobject.c listiter_reduce_general PyId_iter variable _Py_IDENTIFIER(iter) +Objects/odictobject.c odictiter_reduce PyId_iter variable _Py_IDENTIFIER(iter) +Objects/rangeobject.c rangeiter_reduce PyId_iter variable _Py_IDENTIFIER(iter) +Objects/rangeobject.c longrangeiter_reduce PyId_iter variable _Py_IDENTIFIER(iter) +Objects/setobject.c setiter_reduce PyId_iter variable _Py_IDENTIFIER(iter) +Objects/tupleobject.c tupleiter_reduce PyId_iter variable _Py_IDENTIFIER(iter) +Objects/unicodeobject.c unicodeiter_reduce PyId_iter variable _Py_IDENTIFIER(iter) +Objects/typeobject.c slot_tp_iter PyId___iter__ variable _Py_IDENTIFIER(__iter__) +Modules/arraymodule.c - PyId_iter variable _Py_IDENTIFIER(iter) +Python/Python-ast.c - PyId_key variable _Py_IDENTIFIER(key) +Python/Python-ast.c - PyId_keys variable _Py_IDENTIFIER(keys) +Objects/abstract.c PyMapping_Keys PyId_keys variable _Py_IDENTIFIER(keys) +Objects/descrobject.c mappingproxy_keys PyId_keys variable _Py_IDENTIFIER(keys) +Objects/dictobject.c - PyId_keys variable _Py_IDENTIFIER(keys) +Objects/odictobject.c mutablemapping_update PyId_keys variable _Py_IDENTIFIER(keys) +Python/Python-ast.c - PyId_keywords variable _Py_IDENTIFIER(keywords) +Python/Python-ast.c - PyId_kind variable _Py_IDENTIFIER(kind) +Python/Python-ast.c - PyId_kwarg variable _Py_IDENTIFIER(kwarg) +Python/Python-ast.c - PyId_kw_defaults variable _Py_IDENTIFIER(kw_defaults) +Python/Python-ast.c - PyId_kwonlyargs variable _Py_IDENTIFIER(kwonlyargs) +Python/pythonrun.c - PyId_last_traceback variable _Py_IDENTIFIER(last_traceback) +Python/pythonrun.c - PyId_last_type variable _Py_IDENTIFIER(last_type) +Python/pythonrun.c - PyId_last_value variable _Py_IDENTIFIER(last_value) +Python/Python-ast.c - PyId_left variable _Py_IDENTIFIER(left) +Objects/typeobject.c - PyId___len__ variable _Py_IDENTIFIER(__len__) +Objects/abstract.c PyObject_LengthHint PyId___length_hint__ variable _Py_IDENTIFIER(__length_hint__) +Python/Python-ast.c - PyId_level variable _Py_IDENTIFIER(level) +Python/Python-ast.c - PyId_lineno variable _Py_IDENTIFIER(lineno) +Python/errors.c PyErr_SyntaxLocationObject PyId_lineno variable _Py_IDENTIFIER(lineno) +Python/pythonrun.c - PyId_lineno variable _Py_IDENTIFIER(lineno) +Objects/longobject.c - PyId_little variable _Py_IDENTIFIER(little) +Python/_warnings.c get_source_line PyId___loader__ variable _Py_IDENTIFIER(__loader__) +Objects/moduleobject.c - PyId___loader__ variable _Py_IDENTIFIER(__loader__) +Python/import.c - PyId__lock_unlock_module variable _Py_IDENTIFIER(_lock_unlock_module) +Python/Python-ast.c - PyId_lower variable _Py_IDENTIFIER(lower) +Python/ceval.c _PyEval_EvalFrameDefault PyId___ltrace__ variable _Py_IDENTIFIER(__ltrace__) +Python/pythonrun.c - PyId___main__ variable _Py_IDENTIFIER(__main__) +Python/_warnings.c check_matched PyId_match variable _Py_IDENTIFIER(match) +Python/bltinmodule.c - PyId_metaclass variable _Py_IDENTIFIER(metaclass) +Objects/dictobject.c dict_subscript PyId___missing__ variable _Py_IDENTIFIER(__missing__) +Modules/_io/bufferedio.c - PyId_mode variable _Py_IDENTIFIER(mode) +Modules/_io/textio.c - PyId_mode variable _Py_IDENTIFIER(mode) +Python/pylifecycle.c - PyId_mode variable _Py_IDENTIFIER(mode) +Modules/_io/_iomodule.c - PyId_mode variable _Py_IDENTIFIER(mode) +Python/Python-ast.c - PyId_module variable _Py_IDENTIFIER(module) +Objects/typeobject.c - PyId___module__ variable _Py_IDENTIFIER(__module__) +Python/Python-ast.c make_type PyId___module__ variable _Py_IDENTIFIER(__module__) +Python/errors.c PyErr_NewException PyId___module__ variable _Py_IDENTIFIER(__module__) +Python/errors.c - PyId___module__ variable _Py_IDENTIFIER(__module__) +Python/pythonrun.c print_exception PyId___module__ variable _Py_IDENTIFIER(__module__) +Objects/typeobject.c - PyId_mro variable _Py_IDENTIFIER(mro) +Objects/typeobject.c mro_invoke PyId_mro variable _Py_IDENTIFIER(mro) +Python/bltinmodule.c - PyId___mro_entries__ variable _Py_IDENTIFIER(__mro_entries__) +Objects/typeobject.c type_new PyId___mro_entries__ variable _Py_IDENTIFIER(__mro_entries__) +Python/Python-ast.c - PyId_msg variable _Py_IDENTIFIER(msg) +Python/errors.c PyErr_SyntaxLocationObject PyId_msg variable _Py_IDENTIFIER(msg) +Python/pythonrun.c - PyId_msg variable _Py_IDENTIFIER(msg) +Python/pylifecycle.c - PyId_name variable _Py_IDENTIFIER(name) +Modules/_io/fileio.c - PyId_name variable _Py_IDENTIFIER(name) +Modules/_io/bufferedio.c - PyId_name variable _Py_IDENTIFIER(name) +Modules/_io/textio.c - PyId_name variable _Py_IDENTIFIER(name) +Python/Python-ast.c - PyId_name variable _Py_IDENTIFIER(name) +Objects/typeobject.c - PyId___name__ variable _Py_IDENTIFIER(__name__) +Objects/classobject.c - PyId___name__ variable _Py_IDENTIFIER(__name__) +Python/_warnings.c - PyId___name__ variable _Py_IDENTIFIER(__name__) +Python/_warnings.c get_source_line PyId___name__ variable _Py_IDENTIFIER(__name__) +Python/ceval.c import_from PyId___name__ variable _Py_IDENTIFIER(__name__) +Python/ceval.c import_all_from PyId___name__ variable _Py_IDENTIFIER(__name__) +Python/import.c resolve_name PyId___name__ variable _Py_IDENTIFIER(__name__) +Objects/moduleobject.c - PyId___name__ variable _Py_IDENTIFIER(__name__) +Objects/moduleobject.c PyModule_GetNameObject PyId___name__ variable _Py_IDENTIFIER(__name__) +Objects/exceptions.c ImportError_getstate PyId_name variable _Py_IDENTIFIER(name) +Objects/moduleobject.c module_getattro PyId___name__ variable _Py_IDENTIFIER(__name__) +Objects/weakrefobject.c weakref_repr PyId___name__ variable _Py_IDENTIFIER(__name__) +Modules/_pickle.c save_global PyId___name__ variable _Py_IDENTIFIER(__name__) +Python/Python-ast.c - PyId_names variable _Py_IDENTIFIER(names) +Objects/typeobject.c - PyId___new__ variable _Py_IDENTIFIER(__new__) +Objects/typeobject.c reduce_newobj PyId___newobj__ variable _Py_IDENTIFIER(__newobj__) +Objects/typeobject.c reduce_newobj PyId___newobj_ex__ variable _Py_IDENTIFIER(__newobj_ex__) +Objects/typeobject.c slot_tp_iternext PyId___next__ variable _Py_IDENTIFIER(__next__) +Objects/structseq.c - PyId_n_fields variable _Py_IDENTIFIER(n_fields) +Python/ast.c new_identifier PyId_NFKC variable _Py_IDENTIFIER(NFKC) +Objects/structseq.c - PyId_n_sequence_fields variable _Py_IDENTIFIER(n_sequence_fields) +Objects/structseq.c - PyId_n_unnamed_fields variable _Py_IDENTIFIER(n_unnamed_fields) +Python/errors.c PyErr_SyntaxLocationObject PyId_offset variable _Py_IDENTIFIER(offset) +Python/pythonrun.c - PyId_offset variable _Py_IDENTIFIER(offset) +Python/_warnings.c get_once_registry PyId_onceregistry variable _Py_IDENTIFIER(onceregistry) +Python/Python-ast.c - PyId_op variable _Py_IDENTIFIER(op) +Python/traceback.c - PyId_open variable _Py_IDENTIFIER(open) +Python/pylifecycle.c - PyId_open variable _Py_IDENTIFIER(open) +Parser/tokenizer.c fp_setreadl PyId_open variable _Py_IDENTIFIER(open) +Objects/fileobject.c - PyId_open variable _Py_IDENTIFIER(open) +Objects/fileobject.c PyFile_OpenCodeObject PyId_open variable _Py_IDENTIFIER(open) +Python/Python-ast.c - PyId_operand variable _Py_IDENTIFIER(operand) +Python/Python-ast.c - PyId_ops variable _Py_IDENTIFIER(ops) +Python/Python-ast.c - PyId_optional_vars variable _Py_IDENTIFIER(optional_vars) +Python/Python-ast.c - PyId_orelse variable _Py_IDENTIFIER(orelse) +Python/import.c resolve_name PyId___package__ variable _Py_IDENTIFIER(__package__) +Objects/moduleobject.c - PyId___package__ variable _Py_IDENTIFIER(__package__) +Python/import.c resolve_name PyId_parent variable _Py_IDENTIFIER(parent) +Modules/_operator.c methodcaller_reduce PyId_partial variable _Py_IDENTIFIER(partial) +Python/sysmodule.c - PyId_path variable _Py_IDENTIFIER(path) +Python/traceback.c - PyId_path variable _Py_IDENTIFIER(path) +Objects/exceptions.c ImportError_getstate PyId_path variable _Py_IDENTIFIER(path) +Modules/main.c pymain_sys_path_add_path0 PyId_path variable _Py_IDENTIFIER(path) +Python/import.c resolve_name PyId___path__ variable _Py_IDENTIFIER(__path__) +Python/import.c - PyId___path__ variable _Py_IDENTIFIER(__path__) +Modules/_io/bufferedio.c - PyId_peek variable _Py_IDENTIFIER(peek) +Python/Python-ast.c - PyId_posonlyargs variable _Py_IDENTIFIER(posonlyargs) +Objects/typeobject.c slot_nb_power PyId___pow__ variable _Py_IDENTIFIER(__pow__) +Python/bltinmodule.c - PyId___prepare__ variable _Py_IDENTIFIER(__prepare__) +Python/errors.c PyErr_SyntaxLocationObject PyId_print_file_and_line variable _Py_IDENTIFIER(print_file_and_line) +Python/pythonrun.c print_exception PyId_print_file_and_line variable _Py_IDENTIFIER(print_file_and_line) +Python/pythonrun.c - PyId_ps1 variable _Py_IDENTIFIER(ps1) +Python/pythonrun.c - PyId_ps2 variable _Py_IDENTIFIER(ps2) +Objects/object.c - PyId_Py_Repr variable _Py_IDENTIFIER(Py_Repr) +Objects/classobject.c - PyId___qualname__ variable _Py_IDENTIFIER(__qualname__) +Objects/descrobject.c calculate_qualname PyId___qualname__ variable _Py_IDENTIFIER(__qualname__) +Objects/methodobject.c meth_get__qualname__ PyId___qualname__ variable _Py_IDENTIFIER(__qualname__) +Objects/typeobject.c type_new PyId___qualname__ variable _Py_IDENTIFIER(__qualname__) +Modules/_io/textio.c - PyId_raw variable _Py_IDENTIFIER(raw) +Python/pylifecycle.c - PyId_raw variable _Py_IDENTIFIER(raw) +Modules/_io/iobase.c - PyId_read variable _Py_IDENTIFIER(read) +Modules/_io/bufferedio.c - PyId_read variable _Py_IDENTIFIER(read) +Modules/_io/textio.c - PyId_read variable _Py_IDENTIFIER(read) +Modules/_io/bufferedio.c - PyId_read1 variable _Py_IDENTIFIER(read1) +Python/marshal.c - PyId_read variable _Py_IDENTIFIER(read) +Modules/_io/bufferedio.c - PyId_readable variable _Py_IDENTIFIER(readable) +Modules/_io/textio.c - PyId_readable variable _Py_IDENTIFIER(readable) +Modules/_io/iobase.c - PyId_readall variable _Py_IDENTIFIER(readall) +Modules/_io/bufferedio.c - PyId_readinto variable _Py_IDENTIFIER(readinto) +Modules/_io/bufferedio.c - PyId_readinto1 variable _Py_IDENTIFIER(readinto1) +Python/marshal.c r_string PyId_readinto variable _Py_IDENTIFIER(readinto) +Parser/tokenizer.c fp_setreadl PyId_readline variable _Py_IDENTIFIER(readline) +Objects/fileobject.c PyFile_GetLine PyId_readline variable _Py_IDENTIFIER(readline) +Objects/typeobject.c - PyId___reduce__ variable _Py_IDENTIFIER(__reduce__) +Python/import.c PyImport_ReloadModule PyId_reload variable _Py_IDENTIFIER(reload) +Modules/_io/textio.c - PyId_replace variable _Py_IDENTIFIER(replace) +Python/importdl.c - PyId_replace variable _Py_IDENTIFIER(replace) +Objects/typeobject.c slot_tp_repr PyId___repr__ variable _Py_IDENTIFIER(__repr__) +Modules/_io/textio.c - PyId_reset variable _Py_IDENTIFIER(reset) +Python/Python-ast.c - PyId_returns variable _Py_IDENTIFIER(returns) +Objects/enumobject.c - PyId___reversed__ variable _Py_IDENTIFIER(__reversed__) +Objects/listobject.c listiter_reduce_general PyId_reversed variable _Py_IDENTIFIER(reversed) +Python/Python-ast.c - PyId_right variable _Py_IDENTIFIER(right) +Python/bltinmodule.c - PyId___round__ variable _Py_IDENTIFIER(__round__) +Modules/_io/textio.c - PyId_seek variable _Py_IDENTIFIER(seek) +Modules/_io/iobase.c - PyId_seek variable _Py_IDENTIFIER(seek) +Modules/_io/textio.c - PyId_seekable variable _Py_IDENTIFIER(seekable) +Python/ceval.c _PyEval_EvalFrameDefault PyId_send variable _Py_IDENTIFIER(send) +Objects/typeobject.c slot_tp_descr_set PyId___set__ variable _Py_IDENTIFIER(__set__) +Objects/typeobject.c slot_tp_setattro PyId___setattr__ variable _Py_IDENTIFIER(__setattr__) +Objects/typeobject.c - PyId___setitem__ variable _Py_IDENTIFIER(__setitem__) +Modules/_collectionsmodule.c _count_elements PyId___setitem__ variable _Py_IDENTIFIER(__setitem__) +Objects/typeobject.c - PyId___set_name__ variable _Py_IDENTIFIER(__set_name__) +Modules/_io/textio.c - PyId_setstate variable _Py_IDENTIFIER(setstate) +Modules/_pickle.c load_build PyId___setstate__ variable _Py_IDENTIFIER(__setstate__) +Python/_warnings.c - PyId__showwarnmsg variable _Py_IDENTIFIER(_showwarnmsg) +Python/pylifecycle.c wait_for_thread_shutdown PyId__shutdown variable _Py_IDENTIFIER(_shutdown) +Python/Python-ast.c - PyId_simple variable _Py_IDENTIFIER(simple) +Python/sysmodule.c - PyId___sizeof__ variable _Py_IDENTIFIER(__sizeof__) +Python/Python-ast.c - PyId_slice variable _Py_IDENTIFIER(slice) +Objects/typeobject.c _PyType_GetSlotNames PyId___slotnames__ variable _Py_IDENTIFIER(__slotnames__) +Objects/typeobject.c _PyType_GetSlotNames PyId__slotnames variable _Py_IDENTIFIER(_slotnames) +Objects/typeobject.c type_new PyId___slots__ variable _Py_IDENTIFIER(__slots__) +Python/bltinmodule.c - PyId_sort variable _Py_IDENTIFIER(sort) +Python/import.c resolve_name PyId___spec__ variable _Py_IDENTIFIER(__spec__) +Python/import.c - PyId___spec__ variable _Py_IDENTIFIER(__spec__) +Objects/moduleobject.c - PyId___spec__ variable _Py_IDENTIFIER(__spec__) +Objects/moduleobject.c module_getattro PyId___spec__ variable _Py_IDENTIFIER(__spec__) +Python/_warnings.c - PyId_stderr variable _Py_IDENTIFIER(stderr) +Python/errors.c - PyId_stderr variable _Py_IDENTIFIER(stderr) +Python/pylifecycle.c - PyId_stderr variable _Py_IDENTIFIER(stderr) +Python/pythonrun.c - PyId_stderr variable _Py_IDENTIFIER(stderr) +Python/sysmodule.c - PyId_stderr variable _Py_IDENTIFIER(stderr) +Modules/_threadmodule.c - PyId_stderr variable _Py_IDENTIFIER(stderr) +Modules/faulthandler.c - PyId_stderr variable _Py_IDENTIFIER(stderr) +Python/bltinmodule.c - PyId_stderr variable _Py_IDENTIFIER(stderr) +Python/pylifecycle.c - PyId_stdin variable _Py_IDENTIFIER(stdin) +Python/pythonrun.c - PyId_stdin variable _Py_IDENTIFIER(stdin) +Python/bltinmodule.c - PyId_stdin variable _Py_IDENTIFIER(stdin) +Python/pylifecycle.c - PyId_stdout variable _Py_IDENTIFIER(stdout) +Python/pythonrun.c - PyId_stdout variable _Py_IDENTIFIER(stdout) +Python/sysmodule.c - PyId_stdout variable _Py_IDENTIFIER(stdout) +Python/bltinmodule.c - PyId_stdout variable _Py_IDENTIFIER(stdout) +Python/Python-ast.c - PyId_step variable _Py_IDENTIFIER(step) +Modules/posixmodule.c DirEntry_test_mode PyId_st_mode variable _Py_IDENTIFIER(st_mode) +Modules/_io/textio.c - PyId_strict variable _Py_IDENTIFIER(strict) +Python/pythonrun.c - PyId_string variable "_Py_static_string(PyId_string, """")" +Modules/timemodule.c time_strptime PyId__strptime_time variable _Py_IDENTIFIER(_strptime_time) +Modules/posixmodule.c wait_helper PyId_struct_rusage variable _Py_IDENTIFIER(struct_rusage) +Modules/_abc.c - PyId___subclasscheck__ variable _Py_IDENTIFIER(__subclasscheck__) +Objects/abstract.c PyObject_IsSubclass PyId___subclasscheck__ variable _Py_IDENTIFIER(__subclasscheck__) +Modules/_abc.c - PyId___subclasshook__ variable _Py_IDENTIFIER(__subclasshook__) +Objects/dictobject.c dictviews_xor PyId_symmetric_difference_update variable _Py_IDENTIFIER(symmetric_difference_update) +Python/Python-ast.c - PyId_tag variable _Py_IDENTIFIER(tag) +Python/Python-ast.c - PyId_target variable _Py_IDENTIFIER(target) +Python/Python-ast.c - PyId_targets variable _Py_IDENTIFIER(targets) +Modules/_io/textio.c - PyId_tell variable _Py_IDENTIFIER(tell) +Python/Python-ast.c - PyId_test variable _Py_IDENTIFIER(test) +Python/errors.c PyErr_SyntaxLocationObject PyId_text variable _Py_IDENTIFIER(text) +Python/pythonrun.c - PyId_text variable _Py_IDENTIFIER(text) +Python/traceback.c - PyId_TextIOWrapper variable _Py_IDENTIFIER(TextIOWrapper) +Python/pylifecycle.c - PyId_TextIOWrapper variable _Py_IDENTIFIER(TextIOWrapper) +Python/pylifecycle.c - PyId_threading variable _Py_IDENTIFIER(threading) +Objects/genobject.c - PyId_throw variable _Py_IDENTIFIER(throw) +Objects/abstract.c PyNumber_Long PyId___trunc__ variable _Py_IDENTIFIER(__trunc__) +Python/Python-ast.c - PyId_type variable _Py_IDENTIFIER(type) +Python/Python-ast.c - PyId_type_comment variable _Py_IDENTIFIER(type_comment) +Python/Python-ast.c - PyId_type_ignores variable _Py_IDENTIFIER(type_ignores) +Python/errors.c _PyErr_WriteUnraisableMsg PyId_unraisablehook variable _Py_IDENTIFIER(unraisablehook) +Objects/dictobject.c dictviews_or PyId_update variable _Py_IDENTIFIER(update) +Python/Python-ast.c - PyId_upper variable _Py_IDENTIFIER(upper) +Python/Python-ast.c - PyId_value variable _Py_IDENTIFIER(value) +Python/Python-ast.c - PyId_values variable _Py_IDENTIFIER(values) +Objects/abstract.c PyMapping_Values PyId_values variable _Py_IDENTIFIER(values) +Objects/descrobject.c mappingproxy_values PyId_values variable _Py_IDENTIFIER(values) +Python/Python-ast.c - PyId_vararg variable _Py_IDENTIFIER(vararg) +Python/_warnings.c already_warned PyId_version variable _Py_IDENTIFIER(version) +Python/_warnings.c - PyId_WarningMessage variable _Py_IDENTIFIER(WarningMessage) +Python/_warnings.c - PyId___warningregistry__ variable _Py_IDENTIFIER(__warningregistry__) +Python/_warnings.c get_warnings_attr PyId_warnings variable _Py_IDENTIFIER(warnings) +Python/sysmodule.c - PyId_warnoptions variable _Py_IDENTIFIER(warnoptions) +Python/_warnings.c _PyErr_WarnUnawaitedCoroutine PyId__warn_unawaited_coroutine variable _Py_IDENTIFIER(_warn_unawaited_coroutine) +Modules/_io/bufferedio.c - PyId_writable variable _Py_IDENTIFIER(writable) +Modules/_io/textio.c - PyId_writable variable _Py_IDENTIFIER(writable) +Python/sysmodule.c - PyId_write variable _Py_IDENTIFIER(write) +Modules/_io/bufferedio.c - PyId_write variable _Py_IDENTIFIER(write) +Python/marshal.c - PyId_write variable _Py_IDENTIFIER(write) +Objects/fileobject.c PyFile_WriteObject PyId_write variable _Py_IDENTIFIER(write) +Python/sysmodule.c - PyId__xoptions variable _Py_IDENTIFIER(_xoptions) +Python/import.c _PyImportZip_Init PyId_zipimporter variable _Py_IDENTIFIER(zipimporter) +Python/initconfig.c - Py_IgnoreEnvironmentFlag variable int Py_IgnoreEnvironmentFlag +Python/dynload_shlib.c - _PyImport_DynLoadFiletab variable const char *_PyImport_DynLoadFiletab[] +Include/import.h - PyImport_FrozenModules variable PyAPI_DATA(const struct _frozen *) PyImport_FrozenModules +Modules/config.c - _PyImport_Inittab variable struct _inittab _PyImport_Inittab[] +Include/import.h - PyImport_Inittab variable PyAPI_DATA(struct _inittab *) PyImport_Inittab +Modules/_io/textio.c - PyIncrementalNewlineDecoder_Type variable PyTypeObject PyIncrementalNewlineDecoder_Type +Python/initconfig.c - Py_InspectFlag variable int Py_InspectFlag +Objects/classobject.c - PyInstanceMethod_Type variable PyTypeObject PyInstanceMethod_Type +Python/initconfig.c - Py_InteractiveFlag variable int Py_InteractiveFlag +Objects/interpreteridobject.c - _PyInterpreterID_Type variable PyTypeObject _PyInterpreterID_Type +Modules/_io/iobase.c - PyIOBase_Type variable PyTypeObject PyIOBase_Type +Modules/_io/_iomodule.c - _PyIO_empty_bytes variable PyObject *_PyIO_empty_bytes +Modules/_io/_iomodule.c - _PyIO_empty_str variable PyObject *_PyIO_empty_str +Modules/_io/_iomodule.c - _PyIO_Module variable struct PyModuleDef _PyIO_Module +Modules/_io/_iomodule.c - _PyIO_str_close variable PyObject *_PyIO_str_close +Modules/_io/_iomodule.c - _PyIO_str_closed variable PyObject *_PyIO_str_closed +Modules/_io/_iomodule.c - _PyIO_str_decode variable PyObject *_PyIO_str_decode +Modules/_io/_iomodule.c - _PyIO_str_encode variable PyObject *_PyIO_str_encode +Modules/_io/_iomodule.c - _PyIO_str_fileno variable PyObject *_PyIO_str_fileno +Modules/_io/_iomodule.c - _PyIO_str_flush variable PyObject *_PyIO_str_flush +Modules/_io/_iomodule.c - _PyIO_str_getstate variable PyObject *_PyIO_str_getstate +Modules/_io/_iomodule.c - _PyIO_str_isatty variable PyObject *_PyIO_str_isatty +Modules/_io/_iomodule.c - _PyIO_str_newlines variable PyObject *_PyIO_str_newlines +Modules/_io/_iomodule.c - _PyIO_str_nl variable PyObject *_PyIO_str_nl +Modules/_io/_iomodule.c - _PyIO_str_peek variable PyObject *_PyIO_str_peek +Modules/_io/_iomodule.c - _PyIO_str_read variable PyObject *_PyIO_str_read +Modules/_io/_iomodule.c - _PyIO_str_read1 variable PyObject *_PyIO_str_read1 +Modules/_io/_iomodule.c - _PyIO_str_readable variable PyObject *_PyIO_str_readable +Modules/_io/_iomodule.c - _PyIO_str_readall variable PyObject *_PyIO_str_readall +Modules/_io/_iomodule.c - _PyIO_str_readinto variable PyObject *_PyIO_str_readinto +Modules/_io/_iomodule.c - _PyIO_str_readline variable PyObject *_PyIO_str_readline +Modules/_io/_iomodule.c - _PyIO_str_reset variable PyObject *_PyIO_str_reset +Modules/_io/_iomodule.c - _PyIO_str_seek variable PyObject *_PyIO_str_seek +Modules/_io/_iomodule.c - _PyIO_str_seekable variable PyObject *_PyIO_str_seekable +Modules/_io/_iomodule.c - _PyIO_str_setstate variable PyObject *_PyIO_str_setstate +Modules/_io/_iomodule.c - _PyIO_str_tell variable PyObject *_PyIO_str_tell +Modules/_io/_iomodule.c - _PyIO_str_truncate variable PyObject *_PyIO_str_truncate +Modules/_io/_iomodule.c - _PyIO_str_writable variable PyObject *_PyIO_str_writable +Modules/_io/_iomodule.c - _PyIO_str_write variable PyObject *_PyIO_str_write +Python/initconfig.c - Py_IsolatedFlag variable int Py_IsolatedFlag +Objects/listobject.c - PyListIter_Type variable PyTypeObject PyListIter_Type +Objects/listobject.c - PyListRevIter_Type variable PyTypeObject PyListRevIter_Type +Objects/listobject.c - PyList_Type variable PyTypeObject PyList_Type +Modules/_localemodule.c - PyLocale_Methods variable static struct PyMethodDef PyLocale_Methods[] +Include/longobject.h - _PyLong_DigitValue variable PyAPI_DATA(unsigned char) _PyLong_DigitValue[256] +Objects/longobject.c - _PyLong_One variable PyObject *_PyLong_One +Objects/rangeobject.c - PyLongRangeIter_Type variable PyTypeObject PyLongRangeIter_Type +Objects/longobject.c - PyLong_Type variable PyTypeObject PyLong_Type +Objects/longobject.c - _PyLong_Zero variable PyObject *_PyLong_Zero +Objects/memoryobject.c - _PyManagedBuffer_Type variable PyTypeObject _PyManagedBuffer_Type +Python/bltinmodule.c - PyMap_Type variable PyTypeObject PyMap_Type +Objects/obmalloc.c - _PyMem variable static PyMemAllocatorEx _PyMem +Objects/descrobject.c - PyMemberDescr_Type variable PyTypeObject PyMemberDescr_Type +Objects/obmalloc.c - _PyMem_Debug variable static struct { debug_alloc_api_t raw; debug_alloc_api_t mem; debug_alloc_api_t obj; } _PyMem_Debug +Objects/memoryobject.c - PyMemoryView_Type variable PyTypeObject PyMemoryView_Type +Objects/obmalloc.c - _PyMem_Raw variable static PyMemAllocatorEx _PyMem_Raw +Objects/descrobject.c - PyMethodDescr_Type variable PyTypeObject PyMethodDescr_Type +Objects/classobject.c - PyMethod_Type variable PyTypeObject PyMethod_Type +Objects/descrobject.c - _PyMethodWrapper_Type variable PyTypeObject _PyMethodWrapper_Type +Objects/moduleobject.c - PyModuleDef_Type variable PyTypeObject PyModuleDef_Type +Objects/moduleobject.c - PyModule_Type variable PyTypeObject PyModule_Type +Objects/namespaceobject.c - _PyNamespace_Type variable PyTypeObject _PyNamespace_Type +Objects/object.c - _Py_NoneStruct variable PyObject _Py_NoneStruct +Objects/object.c - _PyNone_Type variable PyTypeObject _PyNone_Type +Python/initconfig.c - Py_NoSiteFlag variable int Py_NoSiteFlag +Objects/object.c - _Py_NotImplementedStruct variable PyObject _Py_NotImplementedStruct +Objects/object.c - _PyNotImplemented_Type variable PyTypeObject _PyNotImplemented_Type +Python/initconfig.c - Py_NoUserSiteDirectory variable int Py_NoUserSiteDirectory +Objects/obmalloc.c - _PyObject variable static PyMemAllocatorEx _PyObject +Objects/obmalloc.c - _PyObject_Arena variable static PyObjectArenaAllocator _PyObject_Arena +Objects/odictobject.c - PyODictItems_Type variable PyTypeObject PyODictItems_Type +Objects/odictobject.c - PyODictIter_Type variable PyTypeObject PyODictIter_Type +Objects/odictobject.c - PyODictKeys_Type variable PyTypeObject PyODictKeys_Type +Objects/odictobject.c - PyODict_Type variable PyTypeObject PyODict_Type +Objects/odictobject.c - PyODictValues_Type variable PyTypeObject PyODictValues_Type +Python/fileutils.c - _Py_open_cloexec_works variable int _Py_open_cloexec_works +Python/initconfig.c - Py_OptimizeFlag variable int Py_OptimizeFlag +Parser/myreadline.c - PyOS_InputHook variable int (*PyOS_InputHook)(void) +Python/pylifecycle.c - _PyOS_mystrnicmp_hack variable int (*_PyOS_mystrnicmp_hack)(const char *, const char *, Py_ssize_t) +Python/getopt.c - _PyOS_optarg variable const wchar_t *_PyOS_optarg +Python/getopt.c - _PyOS_opterr variable int _PyOS_opterr +Python/getopt.c - _PyOS_optind variable Py_ssize_t _PyOS_optind +Parser/myreadline.c - PyOS_ReadlineFunctionPointer variable char *(*PyOS_ReadlineFunctionPointer)(FILE *, FILE *, const char *) +Parser/myreadline.c - _PyOS_ReadlineLock variable static PyThread_type_lock _PyOS_ReadlineLock +Include/pythonrun.h - _PyOS_ReadlineTState variable PyAPI_DATA(PyThreadState*) _PyOS_ReadlineTState +Python/modsupport.c - _Py_PackageContext variable const char *_Py_PackageContext +Python/graminit.c - _PyParser_Grammar variable grammar _PyParser_Grammar +Include/internal/pycore_pathconfig.h - _Py_path_config variable PyAPI_DATA(_PyPathConfig) _Py_path_config +Objects/picklebufobject.c - PyPickleBuffer_Type variable PyTypeObject PyPickleBuffer_Type +Objects/descrobject.c - PyProperty_Type variable PyTypeObject PyProperty_Type +Python/initconfig.c - Py_QuietFlag variable int Py_QuietFlag +Objects/rangeobject.c - PyRangeIter_Type variable PyTypeObject PyRangeIter_Type +Objects/rangeobject.c - PyRange_Type variable PyTypeObject PyRange_Type +Modules/_io/iobase.c - PyRawIOBase_Type variable PyTypeObject PyRawIOBase_Type +Objects/object.c - _Py_RefTotal variable Py_ssize_t _Py_RefTotal +Objects/enumobject.c - PyReversed_Type variable PyTypeObject PyReversed_Type +Include/internal/pycore_pystate.h - _PyRuntime variable PyAPI_DATA(_PyRuntimeState) _PyRuntime +Objects/iterobject.c - PySeqIter_Type variable PyTypeObject PySeqIter_Type +Include/setobject.h - _PySet_Dummy variable PyAPI_DATA(PyObject *) _PySet_Dummy +Objects/setobject.c - _PySetDummy_Type variable static PyTypeObject _PySetDummy_Type +Objects/setobject.c - PySetIter_Type variable PyTypeObject PySetIter_Type +Objects/setobject.c - PySet_Type variable PyTypeObject PySet_Type +Objects/sliceobject.c - PySlice_Type variable PyTypeObject PySlice_Type +Python/initconfig.c - _Py_StandardStreamEncoding variable static char *_Py_StandardStreamEncoding +Python/initconfig.c - _Py_StandardStreamErrors variable static char *_Py_StandardStreamErrors +Objects/funcobject.c - PyStaticMethod_Type variable PyTypeObject PyStaticMethod_Type +Objects/fileobject.c - PyStdPrinter_Type variable PyTypeObject PyStdPrinter_Type +Python/symtable.c - PySTEntry_Type variable PyTypeObject PySTEntry_Type +Modules/_io/stringio.c - PyStringIO_Type variable PyTypeObject PyStringIO_Type +Objects/structseq.c - PyStructSequence_UnnamedField variable char *PyStructSequence_UnnamedField +Objects/typeobject.c - PySuper_Type variable PyTypeObject PySuper_Type +Objects/object.c - _Py_SwappedOp variable int _Py_SwappedOp[] +Python/sysmodule.c - _PySys_ImplCacheTag variable const char *_PySys_ImplCacheTag +Python/sysmodule.c - _PySys_ImplName variable const char *_PySys_ImplName +Modules/_io/textio.c - PyTextIOBase_Type variable PyTypeObject PyTextIOBase_Type +Modules/_io/textio.c - PyTextIOWrapper_Type variable PyTypeObject PyTextIOWrapper_Type +Python/traceback.c - PyTraceBack_Type variable PyTypeObject PyTraceBack_Type +Include/pymem.h - _Py_tracemalloc_config variable PyAPI_DATA(struct _PyTraceMalloc_Config) _Py_tracemalloc_config +Objects/boolobject.c - _Py_TrueStruct variable static struct _longobject _Py_TrueStruct +Objects/tupleobject.c - PyTupleIter_Type variable PyTypeObject PyTupleIter_Type +Objects/tupleobject.c - PyTuple_Type variable PyTypeObject PyTuple_Type +Objects/typeobject.c - PyType_Type variable PyTypeObject PyType_Type +Python/initconfig.c - Py_UnbufferedStdioFlag variable int Py_UnbufferedStdioFlag +Python/pylifecycle.c - _Py_UnhandledKeyboardInterrupt variable int _Py_UnhandledKeyboardInterrupt +Objects/unicodeobject.c - PyUnicodeIter_Type variable PyTypeObject PyUnicodeIter_Type +Objects/unicodeobject.c - PyUnicode_Type variable PyTypeObject PyUnicode_Type +Python/initconfig.c - Py_UTF8Mode variable int Py_UTF8Mode +Python/initconfig.c - Py_VerboseFlag variable int Py_VerboseFlag +Include/weakrefobject.h - _PyWeakref_CallableProxyType variable PyAPI_DATA(PyTypeObject) _PyWeakref_CallableProxyType +Include/weakrefobject.h - _PyWeakref_ProxyType variable PyAPI_DATA(PyTypeObject) _PyWeakref_ProxyType +Include/weakrefobject.h - _PyWeakref_RefType variable PyAPI_DATA(PyTypeObject) _PyWeakref_RefType +Objects/descrobject.c - PyWrapperDescr_Type variable PyTypeObject PyWrapperDescr_Type +Python/bltinmodule.c - PyZip_Type variable PyTypeObject PyZip_Type +Python/Python-ast.c - Raise_fields variable static char *Raise_fields[] +Python/Python-ast.c - Raise_type variable static PyTypeObject *Raise_type +Objects/rangeobject.c - range_as_mapping variable static PyMappingMethods range_as_mapping +Objects/rangeobject.c - range_as_number variable static PyNumberMethods range_as_number +Objects/rangeobject.c - range_as_sequence variable static PySequenceMethods range_as_sequence +Objects/rangeobject.c - rangeiter_methods variable static PyMethodDef rangeiter_methods +Objects/rangeobject.c - range_members variable static PyMemberDef range_members[] +Objects/rangeobject.c - range_methods variable static PyMethodDef range_methods +Modules/_io/iobase.c - rawiobase_methods variable static PyMethodDef rawiobase_methods +Python/pylifecycle.c fatal_error reentrant variable static int reentrant +Modules/faulthandler.c - reentrant variable static volatile int reentrant +Modules/itertoolsmodule.c - repeat_methods variable static PyMethodDef repeat_methods +Modules/itertoolsmodule.c - repeat_type variable static PyTypeObject repeat_type +Python/Python-ast.c - Return_fields variable static char *Return_fields[] +Python/compile.c - return_str variable static identifier return_str +Python/Python-ast.c - Return_type variable static PyTypeObject *Return_type +Objects/enumobject.c - reversediter_methods variable static PyMethodDef reversediter_methods +Modules/_threadmodule.c - rlock_methods variable static PyMethodDef rlock_methods +Modules/_threadmodule.c - RLocktype variable static PyTypeObject RLocktype +Objects/typeobject.c slot_nb_add rop_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_subtract rop_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_multiply rop_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_matrix_multiply rop_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_remainder rop_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_divmod rop_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_power_binary rop_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_lshift rop_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_rshift rop_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_and rop_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_xor rop_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_or rop_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_floor_divide rop_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_true_divide rop_id variable _Py_static_string(op_id, OPSTR) +Python/Python-ast.c - RShift_singleton variable static PyObject *RShift_singleton +Python/Python-ast.c - RShift_type variable static PyTypeObject *RShift_type +Python/pylifecycle.c - runtime_initialized variable static int runtime_initialized +Modules/posixmodule.c - ScandirIterator_methods variable static PyMethodDef ScandirIterator_methods +Modules/posixmodule.c - ScandirIteratorType variable static PyTypeObject ScandirIteratorType +Modules/_sre.c - scanner_members variable static PyMemberDef scanner_members[] +Modules/_sre.c - scanner_methods variable static PyMethodDef scanner_methods +Modules/_sre.c - Scanner_Type variable static PyTypeObject Scanner_Type +Modules/posixmodule.c - sched_param_desc variable static PyStructSequence_Desc sched_param_desc +Modules/posixmodule.c - sched_param_fields variable static PyStructSequence_Field sched_param_fields[] +Modules/posixmodule.c - SchedParamType variable static PyTypeObject* SchedParamType +Objects/iterobject.c - seqiter_methods variable static PyMethodDef seqiter_methods +Objects/setobject.c - set_as_number variable static PyNumberMethods set_as_number +Objects/setobject.c - set_as_sequence variable static PySequenceMethods set_as_sequence +Python/symtable.c - setcomp variable static identifier setcomp +Python/Python-ast.c - SetComp_fields variable static char *SetComp_fields[] +Python/Python-ast.c - SetComp_type variable static PyTypeObject *SetComp_type +Python/Python-ast.c - Set_fields variable static char *Set_fields[] +Objects/setobject.c - setiter_methods variable static PyMethodDef setiter_methods +Objects/setobject.c - set_methods variable static PyMethodDef set_methods +Python/Python-ast.c - Set_type variable static PyTypeObject *Set_type +Modules/signalmodule.c - SiginfoType variable static PyTypeObject SiginfoType +Modules/signalmodule.c - signal_methods variable static PyMethodDef signal_methods +Modules/signalmodule.c - signalmodule variable static struct PyModuleDef signalmodule +Python/import.c PyImport_Import silly_list variable static PyObject *silly_list +Objects/sliceobject.c - slice_cache variable static PySliceObject *slice_cache +Python/Python-ast.c - Slice_fields variable static char *Slice_fields[] +Objects/sliceobject.c - slice_members variable static PyMemberDef slice_members[] +Objects/sliceobject.c - slice_methods variable static PyMethodDef slice_methods +Python/Python-ast.c - slice_type variable static PyTypeObject *slice_type +Python/Python-ast.c - Slice_type variable static PyTypeObject *Slice_type +Objects/typeobject.c - slotdefs variable static slotdef slotdefs[] +Objects/typeobject.c - slotdefs_initialized variable static int slotdefs_initialized +Objects/longobject.c - small_ints variable static PyLongObject small_ints[NSMALLNEGINTS + NSMALLPOSINTS] +Objects/funcobject.c - sm_getsetlist variable static PyGetSetDef sm_getsetlist[] +Objects/funcobject.c - sm_memberlist variable static PyMemberDef sm_memberlist[] +Modules/xxsubtype.c - spamdict_members variable static PyMemberDef spamdict_members[] +Modules/xxsubtype.c - spamdict_methods variable static PyMethodDef spamdict_methods +Modules/xxsubtype.c - spamdict_type variable static PyTypeObject spamdict_type +Modules/xxsubtype.c - spamlist_getsets variable static PyGetSetDef spamlist_getsets[] +Modules/xxsubtype.c - spamlist_methods variable static PyMethodDef spamlist_methods +Modules/xxsubtype.c - spamlist_type variable static PyTypeObject spamlist_type +Modules/_sre.c - sremodule variable static struct PyModuleDef sremodule +Modules/faulthandler.c - stack variable static stack_t stack +Modules/itertoolsmodule.c - starmap_methods variable static PyMethodDef starmap_methods +Modules/itertoolsmodule.c - starmap_type variable static PyTypeObject starmap_type +Python/Python-ast.c - Starred_fields variable static char *Starred_fields[] +Python/Python-ast.c - Starred_type variable static PyTypeObject *Starred_type +Python/graminit.c - states_0 variable static state states_0[3] +Python/graminit.c - states_1 variable static state states_1[2] +Python/graminit.c - states_10 variable static state states_10[4] +Python/graminit.c - states_11 variable static state states_11[34] +Python/graminit.c - states_12 variable static state states_12[2] +Python/graminit.c - states_13 variable static state states_13[2] +Python/graminit.c - states_14 variable static state states_14[4] +Python/graminit.c - states_15 variable static state states_15[2] +Python/graminit.c - states_16 variable static state states_16[6] +Python/graminit.c - states_17 variable static state states_17[5] +Python/graminit.c - states_18 variable static state states_18[3] +Python/graminit.c - states_19 variable static state states_19[2] +Python/graminit.c - states_2 variable static state states_2[3] +Python/graminit.c - states_20 variable static state states_20[3] +Python/graminit.c - states_21 variable static state states_21[2] +Python/graminit.c - states_22 variable static state states_22[2] +Python/graminit.c - states_23 variable static state states_23[2] +Python/graminit.c - states_24 variable static state states_24[2] +Python/graminit.c - states_25 variable static state states_25[3] +Python/graminit.c - states_26 variable static state states_26[2] +Python/graminit.c - states_27 variable static state states_27[5] +Python/graminit.c - states_28 variable static state states_28[2] +Python/graminit.c - states_29 variable static state states_29[3] +Python/graminit.c - states_3 variable static state states_3[7] +Python/graminit.c - states_30 variable static state states_30[8] +Python/graminit.c - states_31 variable static state states_31[4] +Python/graminit.c - states_32 variable static state states_32[4] +Python/graminit.c - states_33 variable static state states_33[3] +Python/graminit.c - states_34 variable static state states_34[2] +Python/graminit.c - states_35 variable static state states_35[2] +Python/graminit.c - states_36 variable static state states_36[3] +Python/graminit.c - states_37 variable static state states_37[3] +Python/graminit.c - states_38 variable static state states_38[5] +Python/graminit.c - states_39 variable static state states_39[2] +Python/graminit.c - states_4 variable static state states_4[2] +Python/graminit.c - states_40 variable static state states_40[3] +Python/graminit.c - states_41 variable static state states_41[8] +Python/graminit.c - states_42 variable static state states_42[8] +Python/graminit.c - states_43 variable static state states_43[11] +Python/graminit.c - states_44 variable static state states_44[13] +Python/graminit.c - states_45 variable static state states_45[6] +Python/graminit.c - states_46 variable static state states_46[4] +Python/graminit.c - states_47 variable static state states_47[5] +Python/graminit.c - states_48 variable static state states_48[5] +Python/graminit.c - states_49 variable static state states_49[4] +Python/graminit.c - states_5 variable static state states_5[3] +Python/graminit.c - states_50 variable static state states_50[6] +Python/graminit.c - states_51 variable static state states_51[2] +Python/graminit.c - states_52 variable static state states_52[5] +Python/graminit.c - states_53 variable static state states_53[5] +Python/graminit.c - states_54 variable static state states_54[2] +Python/graminit.c - states_55 variable static state states_55[2] +Python/graminit.c - states_56 variable static state states_56[3] +Python/graminit.c - states_57 variable static state states_57[2] +Python/graminit.c - states_58 variable static state states_58[4] +Python/graminit.c - states_59 variable static state states_59[3] +Python/graminit.c - states_6 variable static state states_6[3] +Python/graminit.c - states_60 variable static state states_60[2] +Python/graminit.c - states_61 variable static state states_61[2] +Python/graminit.c - states_62 variable static state states_62[2] +Python/graminit.c - states_63 variable static state states_63[2] +Python/graminit.c - states_64 variable static state states_64[2] +Python/graminit.c - states_65 variable static state states_65[2] +Python/graminit.c - states_66 variable static state states_66[3] +Python/graminit.c - states_67 variable static state states_67[4] +Python/graminit.c - states_68 variable static state states_68[3] +Python/graminit.c - states_69 variable static state states_69[9] +Python/graminit.c - states_7 variable static state states_7[9] +Python/graminit.c - states_70 variable static state states_70[5] +Python/graminit.c - states_71 variable static state states_71[7] +Python/graminit.c - states_72 variable static state states_72[3] +Python/graminit.c - states_73 variable static state states_73[5] +Python/graminit.c - states_74 variable static state states_74[3] +Python/graminit.c - states_75 variable static state states_75[3] +Python/graminit.c - states_76 variable static state states_76[3] +Python/graminit.c - states_77 variable static state states_77[14] +Python/graminit.c - states_78 variable static state states_78[8] +Python/graminit.c - states_79 variable static state states_79[3] +Python/graminit.c - states_8 variable static state states_8[4] +Python/graminit.c - states_80 variable static state states_80[4] +Python/graminit.c - states_81 variable static state states_81[2] +Python/graminit.c - states_82 variable static state states_82[6] +Python/graminit.c - states_83 variable static state states_83[3] +Python/graminit.c - states_84 variable static state states_84[4] +Python/graminit.c - states_85 variable static state states_85[2] +Python/graminit.c - states_86 variable static state states_86[3] +Python/graminit.c - states_87 variable static state states_87[3] +Python/graminit.c - states_88 variable static state states_88[7] +Python/graminit.c - states_89 variable static state states_89[3] +Python/graminit.c - states_9 variable static state states_9[42] +Python/graminit.c - states_90 variable static state states_90[6] +Python/graminit.c - states_91 variable static state states_91[11] +Python/getargs.c - static_arg_parsers variable static struct _PyArg_Parser *static_arg_parsers +Objects/unicodeobject.c - static_strings variable static _Py_Identifier *static_strings +Modules/_stat.c - stat_methods variable static PyMethodDef stat_methods +Modules/_stat.c - statmodule variable static struct PyModuleDef statmodule +Modules/posixmodule.c - stat_result_desc variable static PyStructSequence_Desc stat_result_desc +Modules/posixmodule.c - stat_result_fields variable static PyStructSequence_Field stat_result_fields[] +Modules/posixmodule.c - StatResultType variable static PyTypeObject* StatResultType +Modules/posixmodule.c - statvfs_result_desc variable static PyStructSequence_Desc statvfs_result_desc +Modules/posixmodule.c - statvfs_result_fields variable static PyStructSequence_Field statvfs_result_fields[] +Modules/posixmodule.c - StatVFSResultType variable static PyTypeObject* StatVFSResultType +Objects/fileobject.c - stdprinter_getsetlist variable static PyGetSetDef stdprinter_getsetlist[] +Objects/fileobject.c - stdprinter_methods variable static PyMethodDef stdprinter_methods +Python/symtable.c - ste_memberlist variable static PyMemberDef ste_memberlist[] +Python/Python-ast.c - stmt_attributes variable static char *stmt_attributes[] +Python/Python-ast.c - stmt_type variable static PyTypeObject *stmt_type +Objects/exceptions.c - StopIteration_members variable static PyMemberDef StopIteration_members[] +Python/Python-ast.c - Store_singleton variable PyObject *Store_singleton +Python/Python-ast.c - Store_type variable static PyTypeObject *Store_type +Python/ast_unparse.c - _str_close_br variable static PyObject *_str_close_br +Python/ast_unparse.c - _str_dbl_close_br variable static PyObject *_str_dbl_close_br +Python/ast_unparse.c - _str_dbl_open_br variable static PyObject *_str_dbl_open_br +Modules/_threadmodule.c - str_dict variable static PyObject *str_dict +Modules/_io/stringio.c - stringio_getset variable static PyGetSetDef stringio_getset[] +Modules/_io/stringio.c - stringio_methods variable static PyMethodDef stringio_methods +Objects/unicodeobject.c - _string_methods variable static PyMethodDef _string_methods +Objects/unicodeobject.c - _string_module variable static struct PyModuleDef _string_module +Objects/bytesobject.c - striter_methods variable static PyMethodDef striter_methods +Python/ast_unparse.c - _str_open_br variable static PyObject *_str_open_br +Modules/pwdmodule.c - StructPwdType variable static PyTypeObject StructPwdType +Modules/pwdmodule.c - struct_pwd_type_desc variable static PyStructSequence_Desc struct_pwd_type_desc +Modules/pwdmodule.c - struct_pwd_type_fields variable static PyStructSequence_Field struct_pwd_type_fields[] +Modules/posixmodule.c wait_helper struct_rusage variable static PyObject *struct_rusage +Objects/structseq.c - structseq_methods variable static PyMethodDef structseq_methods +Modules/posixmodule.c - structseq_new variable static newfunc structseq_new +Modules/signalmodule.c - struct_siginfo_desc variable static PyStructSequence_Desc struct_siginfo_desc +Modules/signalmodule.c - struct_siginfo_fields variable static PyStructSequence_Field struct_siginfo_fields[] +Modules/timemodule.c - StructTimeType variable static PyTypeObject StructTimeType +Modules/timemodule.c - struct_time_type_desc variable static PyStructSequence_Desc struct_time_type_desc +Modules/timemodule.c - struct_time_type_fields variable static PyStructSequence_Field struct_time_type_fields[] +Python/Python-ast.c - Subscript_fields variable static char *Subscript_fields[] +Python/Python-ast.c - Subscript_type variable static PyTypeObject *Subscript_type +Python/Python-ast.c - Sub_singleton variable static PyObject *Sub_singleton +Python/Python-ast.c - Sub_type variable static PyTypeObject *Sub_type +Objects/typeobject.c - subtype_getsets_dict_only variable static PyGetSetDef subtype_getsets_dict_only[] +Objects/typeobject.c - subtype_getsets_full variable static PyGetSetDef subtype_getsets_full[] +Objects/typeobject.c - subtype_getsets_weakref_only variable static PyGetSetDef subtype_getsets_weakref_only[] +Python/Python-ast.c - Suite_fields variable static char *Suite_fields[] +Python/Python-ast.c - Suite_type variable static PyTypeObject *Suite_type +Objects/typeobject.c - super_members variable static PyMemberDef super_members[] +Modules/symtablemodule.c - symtable_methods variable static PyMethodDef symtable_methods +Modules/symtablemodule.c - symtablemodule variable static struct PyModuleDef symtablemodule +Objects/exceptions.c - SyntaxError_members variable static PyMemberDef SyntaxError_members[] +Python/sysmodule.c - sys_methods variable static PyMethodDef sys_methods +Python/sysmodule.c - sysmodule variable static struct PyModuleDef sysmodule +Objects/exceptions.c - SystemExit_members variable static PyMemberDef SystemExit_members[] +Modules/_tracemalloc.c - tables_lock variable static PyThread_type_lock tables_lock +Modules/itertoolsmodule.c - takewhile_reduce_methods variable static PyMethodDef takewhile_reduce_methods +Modules/itertoolsmodule.c - takewhile_type variable static PyTypeObject takewhile_type +Python/pylifecycle.c - _TARGET_LOCALES variable static _LocaleCoercionTarget _TARGET_LOCALES[] +Python/traceback.c - tb_getsetters variable static PyGetSetDef tb_getsetters[] +Python/traceback.c - tb_memberlist variable static PyMemberDef tb_memberlist[] +Python/traceback.c - tb_methods variable static PyMethodDef tb_methods +Modules/itertoolsmodule.c - teedataobject_methods variable static PyMethodDef teedataobject_methods +Modules/itertoolsmodule.c - teedataobject_type variable static PyTypeObject teedataobject_type +Modules/itertoolsmodule.c - tee_methods variable static PyMethodDef tee_methods +Modules/itertoolsmodule.c - tee_type variable static PyTypeObject tee_type +Modules/posixmodule.c - TerminalSize_desc variable static PyStructSequence_Desc TerminalSize_desc +Modules/posixmodule.c - TerminalSize_fields variable static PyStructSequence_Field TerminalSize_fields[] +Modules/posixmodule.c - TerminalSizeType variable static PyTypeObject* TerminalSizeType +Modules/_io/textio.c - textiobase_getset variable static PyGetSetDef textiobase_getset[] +Modules/_io/textio.c - textiobase_methods variable static PyMethodDef textiobase_methods +Modules/_io/textio.c - textiowrapper_getset variable static PyGetSetDef textiowrapper_getset[] +Modules/_io/textio.c - textiowrapper_members variable static PyMemberDef textiowrapper_members[] +Modules/_io/textio.c - textiowrapper_methods variable static PyMethodDef textiowrapper_methods +Modules/faulthandler.c - thread variable static struct { PyObject *file; int fd; PY_TIMEOUT_T timeout_us; int repeat; PyInterpreterState *interp; int exit; char *header; size_t header_len; PyThread_type_lock cancel_event; PyThread_type_lock running; } thread +Python/thread.c - thread_debug variable static int thread_debug +Modules/_threadmodule.c - ThreadError variable static PyObject *ThreadError +Python/thread.c - threadinfo_desc variable static PyStructSequence_Desc threadinfo_desc +Python/thread.c - threadinfo_fields variable static PyStructSequence_Field threadinfo_fields[] +Python/thread.c - ThreadInfoType variable static PyTypeObject ThreadInfoType +Modules/_threadmodule.c - thread_methods variable static PyMethodDef thread_methods +Modules/_threadmodule.c - threadmodule variable static struct PyModuleDef threadmodule +Modules/posixmodule.c - ticks_per_second variable static long ticks_per_second +Modules/timemodule.c _PyTime_GetProcessTimeWithInfo ticks_per_second variable static long ticks_per_second +Modules/timemodule.c - time_methods variable static PyMethodDef time_methods +Modules/timemodule.c - timemodule variable static struct PyModuleDef timemodule +Modules/posixmodule.c - times_result_desc variable static PyStructSequence_Desc times_result_desc +Modules/posixmodule.c - times_result_fields variable static PyStructSequence_Field times_result_fields[] +Modules/posixmodule.c - TimesResultType variable static PyTypeObject* TimesResultType +Python/context.c - _token_missing variable static PyObject *_token_missing +Python/symtable.c - top variable static identifier top +Objects/typeobject.c - tp_new_methoddef variable static struct PyMethodDef tp_new_methoddef[] +Modules/_tracemalloc.c - tracemalloc_empty_traceback variable static traceback_t tracemalloc_empty_traceback +Modules/_tracemalloc.c - tracemalloc_filenames variable static _Py_hashtable_t *tracemalloc_filenames +Modules/_tracemalloc.c - tracemalloc_peak_traced_memory variable static size_t tracemalloc_peak_traced_memory +Modules/_tracemalloc.c - tracemalloc_reentrant_key variable static Py_tss_t tracemalloc_reentrant_key +Modules/_tracemalloc.c - tracemalloc_traceback variable static traceback_t *tracemalloc_traceback +Modules/_tracemalloc.c - tracemalloc_tracebacks variable static _Py_hashtable_t *tracemalloc_tracebacks +Modules/_tracemalloc.c - tracemalloc_traced_memory variable static size_t tracemalloc_traced_memory +Modules/_tracemalloc.c - tracemalloc_traces variable static _Py_hashtable_t *tracemalloc_traces +Objects/boolobject.c - true_str variable static PyObject *true_str +Python/Python-ast.c - Try_fields variable static char *Try_fields[] +Python/Python-ast.c - Try_type variable static PyTypeObject *Try_type +Objects/tupleobject.c - tuple_as_mapping variable static PyMappingMethods tuple_as_mapping +Objects/tupleobject.c - tuple_as_sequence variable static PySequenceMethods tuple_as_sequence +Python/Python-ast.c - Tuple_fields variable static char *Tuple_fields[] +Modules/_collectionsmodule.c - tuplegetter_members variable static PyMemberDef tuplegetter_members[] +Modules/_collectionsmodule.c - tuplegetter_methods variable static PyMethodDef tuplegetter_methods +Modules/_collectionsmodule.c - tuplegetter_type variable static PyTypeObject tuplegetter_type +Objects/tupleobject.c - tupleiter_methods variable static PyMethodDef tupleiter_methods +Objects/tupleobject.c - tuple_methods variable static PyMethodDef tuple_methods +Python/Python-ast.c - Tuple_type variable static PyTypeObject *Tuple_type +Objects/typeobject.c - type_getsets variable static PyGetSetDef type_getsets[] +Python/Python-ast.c - TypeIgnore_fields variable static char *TypeIgnore_fields[] +Python/Python-ast.c - type_ignore_type variable static PyTypeObject *type_ignore_type +Python/Python-ast.c - TypeIgnore_type variable static PyTypeObject *TypeIgnore_type +Objects/typeobject.c - type_members variable static PyMemberDef type_members[] +Objects/typeobject.c - type_methods variable static PyMethodDef type_methods +Python/Python-ast.c - UAdd_singleton variable static PyObject *UAdd_singleton +Python/Python-ast.c - UAdd_type variable static PyTypeObject *UAdd_type +Objects/unicodeobject.c - ucnhash_CAPI variable static _PyUnicode_Name_CAPI *ucnhash_CAPI +Python/codecs.c - ucnhash_CAPI variable static _PyUnicode_Name_CAPI *ucnhash_CAPI +Python/ast.c - u_kind variable static PyObject *u_kind +Modules/posixmodule.c - uname_result_desc variable static PyStructSequence_Desc uname_result_desc +Modules/posixmodule.c - uname_result_fields variable static PyStructSequence_Field uname_result_fields[] +Modules/posixmodule.c - UnameResultType variable static PyTypeObject* UnameResultType +Python/Python-ast.c - UnaryOp_fields variable static char *UnaryOp_fields[] +Python/Python-ast.c - unaryop_type variable static PyTypeObject *unaryop_type +Python/Python-ast.c - UnaryOp_type variable static PyTypeObject *UnaryOp_type +Objects/unicodeobject.c - unicode_as_mapping variable static PyMappingMethods unicode_as_mapping +Objects/unicodeobject.c - unicode_as_number variable static PyNumberMethods unicode_as_number +Objects/unicodeobject.c - unicode_as_sequence variable static PySequenceMethods unicode_as_sequence +Objects/unicodeobject.c - unicode_empty variable static PyObject *unicode_empty +Objects/exceptions.c - UnicodeError_members variable static PyMemberDef UnicodeError_members[] +Objects/unicodeobject.c - unicodeiter_methods variable static PyMethodDef unicodeiter_methods +Objects/unicodeobject.c - unicode_latin1 variable static PyObject *unicode_latin1[256] +Objects/unicodeobject.c - unicode_methods variable static PyMethodDef unicode_methods +Modules/_tracemalloc.c - unknown_filename variable static PyObject *unknown_filename +Python/errors.c - UnraisableHookArgs_desc variable static PyStructSequence_Desc UnraisableHookArgs_desc +Python/errors.c - UnraisableHookArgs_fields variable static PyStructSequence_Field UnraisableHookArgs_fields[] +Python/errors.c - UnraisableHookArgsType variable static PyTypeObject UnraisableHookArgsType +Objects/obmalloc.c - unused_arena_objects variable static struct arena_object* unused_arena_objects +Python/bootstrap_hash.c - urandom_cache variable static struct { int fd; dev_t st_dev; ino_t st_ino; } urandom_cache +Objects/obmalloc.c - usable_arenas variable static struct arena_object* usable_arenas +Objects/obmalloc.c - usedpools variable static poolp usedpools[2 * ((NB_SMALL_SIZE_CLASSES + 7) / 8) * 8] +Modules/faulthandler.c - user_signals variable static user_signal_t *user_signals +Python/Python-ast.c - USub_singleton variable static PyObject *USub_singleton +Python/Python-ast.c - USub_type variable static PyTypeObject *USub_type +Python/getversion.c Py_GetVersion version variable static char version[250] +Python/sysmodule.c - version_info_desc variable static PyStructSequence_Desc version_info_desc +Python/sysmodule.c - version_info_fields variable static PyStructSequence_Field version_info_fields[] +Python/sysmodule.c - VersionInfoType variable static PyTypeObject VersionInfoType +Modules/posixmodule.c - waitid_result_desc variable static PyStructSequence_Desc waitid_result_desc +Modules/posixmodule.c - waitid_result_fields variable static PyStructSequence_Field waitid_result_fields[] +Modules/posixmodule.c - WaitidResultType variable static PyTypeObject* WaitidResultType +Modules/signalmodule.c - wakeup variable static volatile struct { SOCKET_T fd; int warn_on_full_buffer; int use_send; } wakeup +Python/_warnings.c - warnings_functions variable static PyMethodDef warnings_functions[] +Python/_warnings.c - warningsmodule variable static struct PyModuleDef warningsmodule +Modules/_weakref.c - weakref_functions variable static PyMethodDef weakref_functions +Objects/weakrefobject.c - weakref_members variable static PyMemberDef weakref_members[] +Modules/_weakref.c - weakrefmodule variable static struct PyModuleDef weakrefmodule +Python/sysmodule.c - whatstrings variable static PyObject *whatstrings[8] +Python/Python-ast.c - While_fields variable static char *While_fields[] +Python/Python-ast.c - While_type variable static PyTypeObject *While_type +Python/Python-ast.c - With_fields variable static char *With_fields[] +Python/Python-ast.c - withitem_fields variable static char *withitem_fields[] +Python/Python-ast.c - withitem_type variable static PyTypeObject *withitem_type +Python/Python-ast.c - With_type variable static PyTypeObject *With_type +Objects/descrobject.c - wrapperdescr_getset variable static PyGetSetDef wrapperdescr_getset[] +Objects/descrobject.c - wrapper_getsets variable static PyGetSetDef wrapper_getsets[] +Objects/descrobject.c - wrapper_members variable static PyMemberDef wrapper_members[] +Objects/descrobject.c - wrapper_methods variable static PyMethodDef wrapper_methods +Modules/_threadmodule.c local_new wr_callback_def variable static PyMethodDef wr_callback_def +Modules/xxsubtype.c - xxsubtype_functions variable static PyMethodDef xxsubtype_functions[] +Modules/xxsubtype.c - xxsubtypemodule variable static struct PyModuleDef xxsubtypemodule +Modules/xxsubtype.c - xxsubtype_slots variable static struct PyModuleDef_Slot xxsubtype_slots[] +Python/Python-ast.c - Yield_fields variable static char *Yield_fields[] +Python/Python-ast.c - YieldFrom_fields variable static char *YieldFrom_fields[] +Python/Python-ast.c - YieldFrom_type variable static PyTypeObject *YieldFrom_type +Python/Python-ast.c - Yield_type variable static PyTypeObject *Yield_type +Modules/itertoolsmodule.c - zip_longest_methods variable static PyMethodDef zip_longest_methods +Modules/itertoolsmodule.c - ziplongest_type variable static PyTypeObject ziplongest_type +Python/bltinmodule.c - zip_methods variable static PyMethodDef zip_methods From 921a4651d079926d38575099b1566bb46f62bee9 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 2 Sep 2019 17:59:27 -0600 Subject: [PATCH 091/118] Consider all known variables as static. --- Tools/c-analyzer/c_analyzer_common/known.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Tools/c-analyzer/c_analyzer_common/known.py b/Tools/c-analyzer/c_analyzer_common/known.py index d40513822637ee..a5c08e32d2a9d7 100644 --- a/Tools/c-analyzer/c_analyzer_common/known.py +++ b/Tools/c-analyzer/c_analyzer_common/known.py @@ -35,6 +35,7 @@ def from_file(infile, *, if kind == 'variable': values = known['variables'] value = Variable(id, declaration) + value._isstatic = True else: raise ValueError(f'unsupported kind in row {row}') value.validate() From 48b2460066ed1ce1ba76db44c441d80334abf447 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 2 Sep 2019 19:16:36 -0600 Subject: [PATCH 092/118] Distinguish "static" vars in output. --- Tools/c-analyzer/c_statics/show.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Tools/c-analyzer/c_statics/show.py b/Tools/c-analyzer/c_statics/show.py index 8228b52704bfc6..3b2a431404aca6 100644 --- a/Tools/c-analyzer/c_statics/show.py +++ b/Tools/c-analyzer/c_statics/show.py @@ -7,5 +7,10 @@ def basic(statics, *, line = f'{static.filename}:{static.funcname}():{static.name}' else: line = f'{static.filename}:{static.name}' - line = f'{line:<64} {static.vartype.partition(" ")[2]}' + vartype = static.vartype + if vartype.startswith('static '): + vartype = vartype.partition(' ')[2] + else: + vartype = '=' + vartype + line = f'{line:<64} {vartype}' _print(line) From c0a631bd1f1a4509d6c6f105178ebfd417c6091d Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 6 Sep 2019 13:42:07 -0600 Subject: [PATCH 093/118] Special-case variables named "id". --- Tools/c-analyzer/c_analyzer_common/known.py | 10 +++++++--- Tools/c-analyzer/c_parser/info.py | 3 --- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Tools/c-analyzer/c_analyzer_common/known.py b/Tools/c-analyzer/c_analyzer_common/known.py index a5c08e32d2a9d7..087da001a33cc7 100644 --- a/Tools/c-analyzer/c_analyzer_common/known.py +++ b/Tools/c-analyzer/c_analyzer_common/known.py @@ -1,10 +1,10 @@ import csv import os.path -from c_analyzer_common import DATA_DIR from c_parser.info import Variable -from .info import ID +from . import DATA_DIR +from .info import ID, UNKNOWN from .util import read_tsv @@ -38,6 +38,10 @@ def from_file(infile, *, value._isstatic = True else: raise ValueError(f'unsupported kind in row {row}') - value.validate() + if value.name == 'id' and declaration == UNKNOWN: + # None of these are static variables. + declaration = 'int id'; + else: + value.validate() values[id] = value return known diff --git a/Tools/c-analyzer/c_parser/info.py b/Tools/c-analyzer/c_parser/info.py index da4bd48e265de0..01c820e7411130 100644 --- a/Tools/c-analyzer/c_parser/info.py +++ b/Tools/c-analyzer/c_parser/info.py @@ -58,9 +58,6 @@ def _validate_id(self): def validate(self): """Fail if the object is invalid (i.e. init with bad data).""" - if self.name == 'id': # XXX drop this case - return - self._validate_id() if self.vartype is None or self.vartype == info.UNKNOWN: From 3989a69dae2cbf2ef41b81f54438d87f67b1676f Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 6 Sep 2019 13:43:11 -0600 Subject: [PATCH 094/118] Fix a test. --- Lib/test/test_tools/test_c_analyzer/test_c_statics/test_show.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_show.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_show.py index a512f00834b4b7..1506d8179271fd 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_show.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_show.py @@ -7,7 +7,7 @@ TYPICAL = [ - info.Variable.from_parts('src1/spam.c', None, 'var1', 'statc const char *'), + info.Variable.from_parts('src1/spam.c', None, 'var1', 'static const char *'), info.Variable.from_parts('src1/spam.c', 'ham', 'initialized', 'static int'), info.Variable.from_parts('src1/spam.c', None, 'var2', 'static PyObject *'), info.Variable.from_parts('src1/eggs.c', 'tofu', 'ready', 'static int'), From 8118454a5e0c5105bc5b7a7e9a004f5763385817 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 6 Sep 2019 13:52:46 -0600 Subject: [PATCH 095/118] Print totals. --- Tools/c-analyzer/c_statics/__main__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Tools/c-analyzer/c_statics/__main__.py b/Tools/c-analyzer/c_statics/__main__.py index b2129db54dde85..a2f52555a02cf5 100644 --- a/Tools/c-analyzer/c_statics/__main__.py +++ b/Tools/c-analyzer/c_statics/__main__.py @@ -42,7 +42,7 @@ def cmd_check(cmd, dirs=SOURCE_DIRS, *, _print('ERROR: found unsupported static variables') _print() _show(sorted(unsupported)) - # XXX totals? + _print(f' ({len(unsupported)} total)') sys.exit(1) @@ -67,12 +67,12 @@ def cmd_show(cmd, dirs=SOURCE_DIRS, *, _print('supported:') _print('----------') _show(sorted(allsupported)) - # XXX totals? + _print(f' ({len(allsupported)} total)') _print() _print('unsupported:') _print('------------') _show(sorted(allunsupported)) - # XXX totals? + _print(f' ({len(allunsupported)} total)') ############################# From cae5e3ac78d508cb1ca8eafdca998a7426623109 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 6 Sep 2019 14:30:38 -0600 Subject: [PATCH 096/118] Fail if we couldn't find any of the symbols. --- Tools/c-analyzer/c_statics/__main__.py | 58 ++++++++++++++++++++++++++ Tools/c-analyzer/c_statics/find.py | 7 +++- Tools/c-analyzer/c_symbols/resolve.py | 4 ++ 3 files changed, 67 insertions(+), 2 deletions(-) diff --git a/Tools/c-analyzer/c_statics/__main__.py b/Tools/c-analyzer/c_statics/__main__.py index a2f52555a02cf5..7ee541e369f242 100644 --- a/Tools/c-analyzer/c_statics/__main__.py +++ b/Tools/c-analyzer/c_statics/__main__.py @@ -2,6 +2,7 @@ import sys from c_analyzer_common import SOURCE_DIRS +from c_analyzer_common.info import UNKNOWN from c_analyzer_common.known import ( from_file as known_from_file, DATA_FILE as KNOWN_FILE, @@ -10,15 +11,72 @@ from .supported import is_supported, ignored_from_file, IGNORED_FILE +def _match_unused_global(static, knownvars, used): + found = [] + for varid in knownvars: + if varid in used: + continue + if varid.funcname is not None: + continue + if varid.name != static.name: + continue + if static.filename and static.filename != UNKNOWN: + if static.filename == varid.filename: + found.append(varid) + else: + found.append(varid) + return found + + def _find_statics(dirnames, known, ignored): ignored = ignored_from_file(ignored) known = known_from_file(known) + used = set() + unknown = set() knownvars = (known or {}).get('variables') for static in find.statics_from_binary(knownvars=knownvars, dirnames=dirnames): #for static in find.statics(dirnames, known, kind='platform'): + if static.vartype == UNKNOWN: + unknown.add(static) + continue yield static, is_supported(static, ignored, known) + used.add(static.id) + + #return + badknown = set() + for static in sorted(unknown): + msg = None + if static.funcname != UNKNOWN: + msg = f'could not find global symbol {static.id}' + elif m := _match_unused_global(static, knownvars, used): + assert isinstance(m, list) + badknown.update(m) + elif static.name in ('completed', 'id'): # XXX Figure out where these variables are. + unknown.remove(static) + else: + msg = f'could not find local symbol {static.id}' + if msg: + #raise Exception(msg) + print(msg) + if badknown: + print('---') + print(f'{len(badknown)} globals in known.tsv, but may actually be local:') + for varid in sorted(badknown): + print(f'{varid.filename:30} {varid.name}') + unused = sorted(varid + for varid in set(knownvars) - used + if varid.name != 'id') # XXX Figure out where these variables are. + if unused: + print('---') + print(f'did not use {len(unused)} known vars:') + for varid in unused: + print(f'{varid.filename:30} {varid.funcname or "-":20} {varid.name}') + raise Exception('not all known symbols used') + if unknown: + print('---') + raise Exception('could not find all symbols') def cmd_check(cmd, dirs=SOURCE_DIRS, *, diff --git a/Tools/c-analyzer/c_statics/find.py b/Tools/c-analyzer/c_statics/find.py index 4dedfad04e89eb..5112978e4f792c 100644 --- a/Tools/c-analyzer/c_statics/find.py +++ b/Tools/c-analyzer/c_statics/find.py @@ -1,4 +1,5 @@ from c_analyzer_common import SOURCE_DIRS +from c_analyzer_common.info import UNKNOWN from c_symbols import ( info as s_info, binary as b_symbols, @@ -23,12 +24,14 @@ def statics_from_binary(binfile=b_symbols.PYTHON, *, Details are filled in from the given "known" variables and types. """ symbols = _iter_symbols(binfile, find_local_symbol=None) - symbols = list(symbols) + #symbols = list(symbols) for variable in _resolve(symbols, #resolve=_get_symbol_resolver(knownvars, dirnames), resolve=_get_symbol_resolver(knownvars), ): - if not variable.isstatic: + # Skip each non-static variable (unless we couldn't find it). + # XXX Drop the "UNKNOWN" condition? + if not variable.isstatic and variable.vartype != UNKNOWN: continue yield variable diff --git a/Tools/c-analyzer/c_symbols/resolve.py b/Tools/c-analyzer/c_symbols/resolve.py index bad2bdbe7d50a8..40a2ad3872ded1 100644 --- a/Tools/c-analyzer/c_symbols/resolve.py +++ b/Tools/c-analyzer/c_symbols/resolve.py @@ -31,6 +31,8 @@ def look_up_known_symbol(symbol, knownvars, *, continue if varid.name == symbol.name: return knownvars[varid] + else: + return None else: for varid in knownvars: if not varid.funcname: @@ -39,6 +41,8 @@ def look_up_known_symbol(symbol, knownvars, *, continue if varid.name == symbol.name: return knownvars[varid] + else: + return None elif not symbol.filename or symbol.filename == UNKNOWN: raise NotImplementedError else: From 87ebe87ae02cb80f4e0d676201122924b8ad9106 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sun, 8 Sep 2019 15:36:55 +0100 Subject: [PATCH 097/118] Factor out _check_results(). --- Tools/c-analyzer/c_statics/__main__.py | 38 ++++++++++++++------------ 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/Tools/c-analyzer/c_statics/__main__.py b/Tools/c-analyzer/c_statics/__main__.py index 7ee541e369f242..89d19922b77614 100644 --- a/Tools/c-analyzer/c_statics/__main__.py +++ b/Tools/c-analyzer/c_statics/__main__.py @@ -28,23 +28,8 @@ def _match_unused_global(static, knownvars, used): return found -def _find_statics(dirnames, known, ignored): - ignored = ignored_from_file(ignored) - known = known_from_file(known) - - used = set() - unknown = set() - knownvars = (known or {}).get('variables') - for static in find.statics_from_binary(knownvars=knownvars, - dirnames=dirnames): - #for static in find.statics(dirnames, known, kind='platform'): - if static.vartype == UNKNOWN: - unknown.add(static) - continue - yield static, is_supported(static, ignored, known) - used.add(static.id) - - #return +def _check_results(unknown, knownvars, used): + return badknown = set() for static in sorted(unknown): msg = None @@ -79,6 +64,25 @@ def _find_statics(dirnames, known, ignored): raise Exception('could not find all symbols') +def _find_statics(dirnames, known, ignored): + ignored = ignored_from_file(ignored) + known = known_from_file(known) + + used = set() + unknown = set() + knownvars = (known or {}).get('variables') + for static in find.statics_from_binary(knownvars=knownvars, + dirnames=dirnames): + #for static in find.statics(dirnames, known, kind='platform'): + if static.vartype == UNKNOWN: + unknown.add(static) + continue + yield static, is_supported(static, ignored, known) + used.add(static.id) + + _check_results(unknown, knownvars, used) + + def cmd_check(cmd, dirs=SOURCE_DIRS, *, ignored=IGNORED_FILE, known=KNOWN_FILE, From 91e4fb1ab0e8f86b10e448a62bc54fa908fa78b6 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sun, 8 Sep 2019 15:57:19 +0100 Subject: [PATCH 098/118] Fill in gaps in known.tsv. --- Tools/c-analyzer/known.tsv | 3886 ++++++++++++++++++------------------ 1 file changed, 1944 insertions(+), 1942 deletions(-) diff --git a/Tools/c-analyzer/known.tsv b/Tools/c-analyzer/known.tsv index 708c7a2ab6c2e9..446b187a9a53e3 100644 --- a/Tools/c-analyzer/known.tsv +++ b/Tools/c-analyzer/known.tsv @@ -1,1942 +1,1944 @@ -filename funcname name kind declaration -Modules/_abc.c - _abc_data_type variable static PyTypeObject _abc_data_type -Modules/_abc.c - abc_invalidation_counter variable static unsigned long long abc_invalidation_counter -Modules/_abc.c - _abcmodule variable static struct PyModuleDef _abcmodule -Python/import.c import_find_and_load accumulated variable static _PyTime_t accumulated -Modules/itertoolsmodule.c - accumulate_methods variable static PyMethodDef accumulate_methods -Modules/itertoolsmodule.c - accumulate_type variable static PyTypeObject accumulate_type -Python/Python-ast.c - Add_singleton variable static PyObject *Add_singleton -Python/Python-ast.c - Add_type variable static PyTypeObject *Add_type -Objects/genobject.c - ag_asend_freelist variable static PyAsyncGenASend *ag_asend_freelist[_PyAsyncGen_MAXFREELIST] -Objects/genobject.c - ag_asend_freelist_free variable static int ag_asend_freelist_free -Objects/genobject.c - ag_value_freelist variable static _PyAsyncGenWrappedValue *ag_value_freelist[_PyAsyncGen_MAXFREELIST] -Objects/genobject.c - ag_value_freelist_free variable static int ag_value_freelist_free -Python/Python-ast.c - alias_fields variable static char *alias_fields[] -Python/Python-ast.c - alias_type variable static PyTypeObject *alias_type -Modules/_tracemalloc.c - allocators variable static struct { PyMemAllocatorEx mem; PyMemAllocatorEx raw; PyMemAllocatorEx obj; } allocators -Python/Python-ast.c - And_singleton variable PyObject *And_singleton -Python/Python-ast.c - And_type variable static PyTypeObject *And_type -Python/Python-ast.c - AnnAssign_fields variable static char *AnnAssign_fields[] -Python/Python-ast.c - AnnAssign_type variable static PyTypeObject *AnnAssign_type -Python/compile.c - __annotations__ variable static PyObject *__annotations__ -Objects/obmalloc.c - arenas variable static struct arena_object* arenas -Python/Python-ast.c - arg_attributes variable static char *arg_attributes[] -Python/Python-ast.c - arg_fields variable static char *arg_fields[] -Python/Python-ast.c - arg_type variable static PyTypeObject *arg_type -Python/Python-ast.c - arguments_fields variable static char *arguments_fields[] -Python/Python-ast.c - arguments_type variable static PyTypeObject *arguments_type -Python/Python-ast.c - Assert_fields variable static char *Assert_fields[] -Python/compile.c compiler_assert assertion_error variable static PyObject *assertion_error -Python/Python-ast.c - Assert_type variable static PyTypeObject *Assert_type -Python/Python-ast.c - Assign_fields variable static char *Assign_fields[] -Python/Python-ast.c - Assign_type variable static PyTypeObject *Assign_type -Python/Python-ast.c - _astmodule variable static struct PyModuleDef _astmodule -Python/Python-ast.c - AST_type variable static PyTypeObject AST_type -Python/Python-ast.c - ast_type_getsets variable static PyGetSetDef ast_type_getsets[] -Python/Python-ast.c - ast_type_methods variable static PyMethodDef ast_type_methods -Python/Python-ast.c - AsyncFor_fields variable static char *AsyncFor_fields[] -Python/Python-ast.c - AsyncFor_type variable static PyTypeObject *AsyncFor_type -Python/Python-ast.c - AsyncFunctionDef_fields variable static char *AsyncFunctionDef_fields[] -Python/Python-ast.c - AsyncFunctionDef_type variable static PyTypeObject *AsyncFunctionDef_type -Objects/genobject.c - async_gen_as_async variable static PyAsyncMethods async_gen_as_async -Objects/genobject.c - async_gen_asend_as_async variable static PyAsyncMethods async_gen_asend_as_async -Objects/genobject.c - async_gen_asend_methods variable static PyMethodDef async_gen_asend_methods -Objects/genobject.c - async_gen_athrow_as_async variable static PyAsyncMethods async_gen_athrow_as_async -Objects/genobject.c - async_gen_athrow_methods variable static PyMethodDef async_gen_athrow_methods -Objects/genobject.c - async_gen_getsetlist variable static PyGetSetDef async_gen_getsetlist[] -Python/sysmodule.c - asyncgen_hooks_desc variable static PyStructSequence_Desc asyncgen_hooks_desc -Python/sysmodule.c - asyncgen_hooks_fields variable static PyStructSequence_Field asyncgen_hooks_fields[] -Python/sysmodule.c - AsyncGenHooksType variable static PyTypeObject AsyncGenHooksType -Objects/genobject.c - async_gen_memberlist variable static PyMemberDef async_gen_memberlist[] -Objects/genobject.c - async_gen_methods variable static PyMethodDef async_gen_methods -Python/Python-ast.c - AsyncWith_fields variable static char *AsyncWith_fields[] -Python/Python-ast.c - AsyncWith_type variable static PyTypeObject *AsyncWith_type -Parser/listnode.c - atbol variable static int atbol -Modules/atexitmodule.c - atexit_methods variable static PyMethodDef atexit_methods -Modules/atexitmodule.c - atexitmodule variable static struct PyModuleDef atexitmodule -Modules/atexitmodule.c - atexit_slots variable static PyModuleDef_Slot atexit_slots[] -Modules/_operator.c - attrgetter_methods variable static PyMethodDef attrgetter_methods -Modules/_operator.c - attrgetter_type variable static PyTypeObject attrgetter_type -Python/Python-ast.c - Attribute_fields variable static char *Attribute_fields[] -Python/Python-ast.c - Attribute_type variable static PyTypeObject *Attribute_type -Python/Python-ast.c - AugAssign_fields variable static char *AugAssign_fields[] -Python/Python-ast.c - AugAssign_type variable static PyTypeObject *AugAssign_type -Python/Python-ast.c - AugLoad_singleton variable PyObject *AugLoad_singleton -Python/Python-ast.c - AugLoad_type variable static PyTypeObject *AugLoad_type -Python/Python-ast.c - AugStore_singleton variable PyObject *AugStore_singleton -Python/Python-ast.c - AugStore_type variable static PyTypeObject *AugStore_type -Python/Python-ast.c - Await_fields variable static char *Await_fields[] -Python/Python-ast.c - Await_type variable static PyTypeObject *Await_type -Objects/exceptions.c - BaseException_getset variable static PyGetSetDef BaseException_getset[] -Objects/exceptions.c - BaseException_members variable static struct PyMemberDef BaseException_members[] -Objects/exceptions.c - BaseException_methods variable static PyMethodDef BaseException_methods -Modules/posixmodule.c - billion variable static PyObject *billion -Python/Python-ast.c - BinOp_fields variable static char *BinOp_fields[] -Python/Python-ast.c - BinOp_type variable static PyTypeObject *BinOp_type -Python/Python-ast.c - BitAnd_singleton variable static PyObject *BitAnd_singleton -Python/Python-ast.c - BitAnd_type variable static PyTypeObject *BitAnd_type -Python/Python-ast.c - BitOr_singleton variable static PyObject *BitOr_singleton -Python/Python-ast.c - BitOr_type variable static PyTypeObject *BitOr_type -Python/Python-ast.c - BitXor_singleton variable static PyObject *BitXor_singleton -Python/Python-ast.c - BitXor_type variable static PyTypeObject *BitXor_type -Objects/unicodeobject.c - bloom_linebreak variable static BLOOM_MASK bloom_linebreak -Objects/boolobject.c - bool_as_number variable static PyNumberMethods bool_as_number -Python/Python-ast.c - BoolOp_fields variable static char *BoolOp_fields[] -Python/Python-ast.c - boolop_type variable static PyTypeObject *boolop_type -Python/Python-ast.c - BoolOp_type variable static PyTypeObject *BoolOp_type -Python/_warnings.c is_internal_frame bootstrap_string variable static PyObject *bootstrap_string -Python/Python-ast.c - Break_type variable static PyTypeObject *Break_type -Python/ast.c - buf variable char *buf -Modules/_io/bufferedio.c - bufferediobase_methods variable static PyMethodDef bufferediobase_methods -Modules/_io/bufferedio.c - bufferedrandom_getset variable static PyGetSetDef bufferedrandom_getset[] -Modules/_io/bufferedio.c - bufferedrandom_members variable static PyMemberDef bufferedrandom_members[] -Modules/_io/bufferedio.c - bufferedrandom_methods variable static PyMethodDef bufferedrandom_methods -Modules/_io/bufferedio.c - bufferedreader_getset variable static PyGetSetDef bufferedreader_getset[] -Modules/_io/bufferedio.c - bufferedreader_members variable static PyMemberDef bufferedreader_members[] -Modules/_io/bufferedio.c - bufferedreader_methods variable static PyMethodDef bufferedreader_methods -Modules/_io/bufferedio.c - bufferedrwpair_getset variable static PyGetSetDef bufferedrwpair_getset[] -Modules/_io/bufferedio.c - bufferedrwpair_methods variable static PyMethodDef bufferedrwpair_methods -Modules/_io/bufferedio.c - bufferedwriter_getset variable static PyGetSetDef bufferedwriter_getset[] -Modules/_io/bufferedio.c - bufferedwriter_members variable static PyMemberDef bufferedwriter_members[] -Modules/_io/bufferedio.c - bufferedwriter_methods variable static PyMethodDef bufferedwriter_methods -Modules/getbuildinfo.c Py_GetBuildInfo buildinfo variable static char buildinfo[50 + sizeof(GITVERSION) + ((sizeof(GITTAG) > sizeof(GITBRANCH)) ? sizeof(GITTAG) : sizeof(GITBRANCH))] -Python/bltinmodule.c - builtin_methods variable static PyMethodDef builtin_methods -Python/bltinmodule.c - builtinsmodule variable static struct PyModuleDef builtinsmodule -Python/import.c PyImport_Import builtins_str variable static PyObject *builtins_str -Python/ceval.c make_pending_calls busy variable static int busy -Objects/bytearrayobject.c - bytearray_as_buffer variable static PyBufferProcs bytearray_as_buffer -Objects/bytearrayobject.c - bytearray_as_mapping variable static PyMappingMethods bytearray_as_mapping -Objects/bytearrayobject.c - bytearray_as_number variable static PyNumberMethods bytearray_as_number -Objects/bytearrayobject.c - bytearray_as_sequence variable static PySequenceMethods bytearray_as_sequence -Objects/bytearrayobject.c - bytearrayiter_methods variable static PyMethodDef bytearrayiter_methods -Objects/bytearrayobject.c - bytearray_methods variable static PyMethodDef bytearray_methods -Objects/bytesobject.c - bytes_as_buffer variable static PyBufferProcs bytes_as_buffer -Objects/bytesobject.c - bytes_as_mapping variable static PyMappingMethods bytes_as_mapping -Objects/bytesobject.c - bytes_as_number variable static PyNumberMethods bytes_as_number -Objects/bytesobject.c - bytes_as_sequence variable static PySequenceMethods bytes_as_sequence -Modules/_io/bytesio.c - bytesiobuf_as_buffer variable static PyBufferProcs bytesiobuf_as_buffer -Modules/_io/bytesio.c - bytesio_getsetlist variable static PyGetSetDef bytesio_getsetlist[] -Modules/_io/bytesio.c - bytesio_methods variable static PyMethodDef bytesio_methods -Objects/bytesobject.c - bytes_methods variable static PyMethodDef bytes_methods -Python/thread_pthread.h init_condattr ca variable static pthread_condattr_t ca -Python/Python-ast.c - Call_fields variable static char *Call_fields[] -Objects/iterobject.c - calliter_methods variable static PyMethodDef calliter_methods -Python/Python-ast.c - Call_type variable static PyTypeObject *Call_type -Objects/cellobject.c - cell_getsetlist variable static PyGetSetDef cell_getsetlist[] -Modules/itertoolsmodule.c - chain_methods variable static PyMethodDef chain_methods -Modules/itertoolsmodule.c - chain_type variable static PyTypeObject chain_type -Objects/bytesobject.c - characters variable static PyBytesObject *characters[UCHAR_MAX + 1] -Python/symtable.c - __class__ variable static identifier __class__ -Python/Python-ast.c - ClassDef_fields variable static char *ClassDef_fields[] -Python/Python-ast.c - ClassDef_type variable static PyTypeObject *ClassDef_type -Objects/funcobject.c - cm_getsetlist variable static PyGetSetDef cm_getsetlist[] -Objects/funcobject.c - cm_memberlist variable static PyMemberDef cm_memberlist[] -Python/Python-ast.c - cmpop_type variable static PyTypeObject *cmpop_type -Modules/_codecsmodule.c - _codecs_functions variable static PyMethodDef _codecs_functions[] -Modules/_codecsmodule.c - codecsmodule variable static struct PyModuleDef codecsmodule -Objects/codeobject.c - code_memberlist variable static PyMemberDef code_memberlist[] -Objects/codeobject.c - code_methods variable static PyMethodDef code_methods -Modules/_collectionsmodule.c - _collectionsmodule variable static struct PyModuleDef _collectionsmodule -Modules/itertoolsmodule.c - combinations_methods variable static PyMethodDef combinations_methods -Modules/itertoolsmodule.c - combinations_type variable static PyTypeObject combinations_type -Objects/typeobject.c object_new comma_id variable "_Py_static_string(comma_id, "", "")" -Python/Python-ast.c - Compare_fields variable static char *Compare_fields[] -Python/Python-ast.c - Compare_type variable static PyTypeObject *Compare_type -Modules/_winapi.c - completed variable int completed -Objects/complexobject.c - complex_as_number variable static PyNumberMethods complex_as_number -Objects/complexobject.c - complex_members variable static PyMemberDef complex_members[] -Objects/complexobject.c - complex_methods variable static PyMethodDef complex_methods -Python/Python-ast.c - comprehension_fields variable static char *comprehension_fields[] -Python/Python-ast.c - comprehension_type variable static PyTypeObject *comprehension_type -Modules/itertoolsmodule.c - compress_methods variable static PyMethodDef compress_methods -Modules/itertoolsmodule.c - compress_type variable static PyTypeObject compress_type -Python/thread_pthread.h - condattr_monotonic variable static pthread_condattr_t *condattr_monotonic -Python/Python-ast.c - Constant_fields variable static char *Constant_fields[] -Python/Python-ast.c - Constant_type variable static PyTypeObject *Constant_type -Python/Python-ast.c - Continue_type variable static PyTypeObject *Continue_type -Objects/longobject.c PyLong_FromString convmultmax_base variable static twodigits convmultmax_base[37] -Objects/longobject.c PyLong_FromString convwidth_base variable static int convwidth_base[37] -Objects/genobject.c - coro_as_async variable static PyAsyncMethods coro_as_async -Objects/genobject.c - coro_getsetlist variable static PyGetSetDef coro_getsetlist[] -Objects/genobject.c - coro_memberlist variable static PyMemberDef coro_memberlist[] -Objects/genobject.c - coro_methods variable static PyMethodDef coro_methods -Objects/genobject.c - coro_wrapper_methods variable static PyMethodDef coro_wrapper_methods -Modules/itertoolsmodule.c - count_methods variable static PyMethodDef count_methods -Modules/itertoolsmodule.c - count_type variable static PyTypeObject count_type -Python/context.c - ctx_freelist variable static PyContext *ctx_freelist -Python/context.c - ctx_freelist_len variable static int ctx_freelist_len -Modules/itertoolsmodule.c - cwr_methods variable static PyMethodDef cwr_methods -Modules/itertoolsmodule.c - cwr_type variable static PyTypeObject cwr_type -Modules/itertoolsmodule.c - cycle_methods variable static PyMethodDef cycle_methods -Modules/itertoolsmodule.c - cycle_type variable static PyTypeObject cycle_type -Objects/obmalloc.c new_arena debug_stats variable static int debug_stats -Modules/signalmodule.c - DefaultHandler variable static PyObject *DefaultHandler -Modules/_collectionsmodule.c - defdict_members variable static PyMemberDef defdict_members[] -Modules/_collectionsmodule.c - defdict_methods variable static PyMethodDef defdict_methods -Modules/_collectionsmodule.c - defdict_type variable static PyTypeObject defdict_type -Python/Python-ast.c - Delete_fields variable static char *Delete_fields[] -Python/Python-ast.c - Delete_type variable static PyTypeObject *Delete_type -Python/Python-ast.c - Del_singleton variable PyObject *Del_singleton -Python/Python-ast.c - Del_type variable static PyTypeObject *Del_type -Modules/_collectionsmodule.c - deque_as_number variable static PyNumberMethods deque_as_number -Modules/_collectionsmodule.c - deque_as_sequence variable static PySequenceMethods deque_as_sequence -Modules/_collectionsmodule.c - deque_getset variable static PyGetSetDef deque_getset[] -Modules/_collectionsmodule.c - dequeiter_methods variable static PyMethodDef dequeiter_methods -Modules/_collectionsmodule.c - dequeiter_type variable static PyTypeObject dequeiter_type -Modules/_collectionsmodule.c - deque_methods variable static PyMethodDef deque_methods -Modules/_collectionsmodule.c - dequereviter_type variable static PyTypeObject dequereviter_type -Modules/_collectionsmodule.c - deque_type variable static PyTypeObject deque_type -Objects/descrobject.c - descr_members variable static PyMemberDef descr_members[] -Objects/descrobject.c - descr_methods variable static PyMethodDef descr_methods -Modules/_abc.c - _destroy_def variable static PyMethodDef _destroy_def -Objects/floatobject.c - detected_double_format variable static float_format_type detected_double_format -Objects/floatobject.c - detected_float_format variable static float_format_type detected_float_format -Objects/dictobject.c - dict_as_mapping variable static PyMappingMethods dict_as_mapping -Objects/dictobject.c - dict_as_sequence variable static PySequenceMethods dict_as_sequence -Python/symtable.c - dictcomp variable static identifier dictcomp -Python/Python-ast.c - DictComp_fields variable static char *DictComp_fields[] -Python/Python-ast.c - DictComp_type variable static PyTypeObject *DictComp_type -Python/Python-ast.c - Dict_fields variable static char *Dict_fields[] -Objects/dictobject.c - dictitems_as_sequence variable static PySequenceMethods dictitems_as_sequence -Objects/dictobject.c - dictitems_methods variable static PyMethodDef dictitems_methods -Objects/dictobject.c - dictiter_methods variable static PyMethodDef dictiter_methods -Objects/dictobject.c - dictkeys_as_sequence variable static PySequenceMethods dictkeys_as_sequence -Objects/dictobject.c - dictkeys_methods variable static PyMethodDef dictkeys_methods -Python/Python-ast.c - Dict_type variable static PyTypeObject *Dict_type -Objects/dictobject.c - dictvalues_as_sequence variable static PySequenceMethods dictvalues_as_sequence -Objects/dictobject.c - dictvalues_methods variable static PyMethodDef dictvalues_methods -Objects/dictobject.c - dictviews_as_number variable static PyNumberMethods dictviews_as_number -Modules/posixmodule.c - DirEntry_members variable static PyMemberDef DirEntry_members[] -Modules/posixmodule.c - DirEntry_methods variable static PyMethodDef DirEntry_methods -Modules/posixmodule.c - DirEntryType variable static PyTypeObject DirEntryType -Python/Python-ast.c - Div_singleton variable static PyObject *Div_singleton -Python/Python-ast.c - Div_type variable static PyTypeObject *Div_type -Python/compile.c - __doc__ variable static PyObject *__doc__ -Objects/classobject.c method_get_doc docstr variable static PyObject *docstr -Objects/classobject.c instancemethod_get_doc docstr variable static PyObject *docstr -Python/compile.c compiler_set_qualname dot variable "_Py_static_string(dot, ""."")" -Python/compile.c compiler_set_qualname dot_locals variable "_Py_static_string(dot_locals, ""."")" -Objects/floatobject.c - double_format variable static float_format_type double_format -Modules/itertoolsmodule.c - dropwhile_methods variable static PyMethodDef dropwhile_methods -Modules/itertoolsmodule.c - dropwhile_type variable static PyTypeObject dropwhile_type -Objects/setobject.c - _dummy_struct variable static PyObject _dummy_struct -Modules/posixmodule.c - dup3_works variable static int dup3_works -Modules/_io/bufferedio.c _PyIO_trap_eintr eintr_int variable static PyObject *eintr_int -Objects/sliceobject.c - ellipsis_methods variable static PyMethodDef ellipsis_methods -Python/hamt.c - _empty_bitmap_node variable static PyHamtNode_Bitmap *_empty_bitmap_node -Objects/setobject.c - emptyfrozenset variable static PyObject *emptyfrozenset -Python/hamt.c - _empty_hamt variable static PyHamtObject *_empty_hamt -Objects/dictobject.c - empty_keys_struct variable static PyDictKeysObject empty_keys_struct -Objects/codeobject.c PyCode_NewEmpty emptystring variable static PyObject *emptystring -Python/compile.c compiler_from_import empty_string variable static PyObject *empty_string -Objects/dictobject.c - empty_values variable static PyObject *empty_values[1] -Objects/unicodeobject.c - encoding_map_methods variable static PyMethodDef encoding_map_methods -Objects/unicodeobject.c - EncodingMapType variable static PyTypeObject EncodingMapType -Objects/enumobject.c - enum_methods variable static PyMethodDef enum_methods -Python/Python-ast.c - Eq_singleton variable static PyObject *Eq_singleton -Python/Python-ast.c - Eq_type variable static PyTypeObject *Eq_type -Objects/exceptions.c - errnomap variable static PyObject *errnomap -Modules/errnomodule.c - errno_methods variable static PyMethodDef errno_methods -Modules/errnomodule.c - errnomodule variable static struct PyModuleDef errnomodule -Modules/_localemodule.c - Error variable static PyObject *Error -Python/Python-ast.c - excepthandler_attributes variable static char *excepthandler_attributes[] -Python/Python-ast.c - ExceptHandler_fields variable static char *ExceptHandler_fields[] -Python/Python-ast.c - excepthandler_type variable static PyTypeObject *excepthandler_type -Python/Python-ast.c - ExceptHandler_type variable static PyTypeObject *ExceptHandler_type -Modules/_threadmodule.c - ExceptHookArgs_desc variable static PyStructSequence_Desc ExceptHookArgs_desc -Modules/_threadmodule.c - ExceptHookArgs_fields variable static PyStructSequence_Field ExceptHookArgs_fields[] -Modules/_threadmodule.c - ExceptHookArgsType variable static PyTypeObject ExceptHookArgsType -Objects/exceptions.c _check_for_legacy_statements exec_prefix variable static PyObject *exec_prefix -Python/Python-ast.c - expr_attributes variable static char *expr_attributes[] -Python/Python-ast.c - expr_context_type variable static PyTypeObject *expr_context_type -Python/Python-ast.c - Expression_fields variable static char *Expression_fields[] -Python/Python-ast.c - Expression_type variable static PyTypeObject *Expression_type -Python/Python-ast.c - Expr_fields variable static char *Expr_fields[] -Python/Python-ast.c - expr_type variable static PyTypeObject *expr_type -Python/Python-ast.c - Expr_type variable static PyTypeObject *Expr_type -Python/import.c - extensions variable static PyObject *extensions -Python/Python-ast.c - ExtSlice_fields variable static char *ExtSlice_fields[] -Python/Python-ast.c - ExtSlice_type variable static PyTypeObject *ExtSlice_type -Objects/boolobject.c - false_str variable static PyObject *false_str -Modules/faulthandler.c - fatal_error variable static struct { int enabled; PyObject *file; int fd; int all_threads; PyInterpreterState *interp; void *exc_handler; } fatal_error -Modules/faulthandler.c - faulthandler_handlers variable static fault_handler_t faulthandler_handlers[] -Objects/stringlib/unicode_format.h - fieldnameiter_methods variable static PyMethodDef fieldnameiter_methods -Modules/_io/fileio.c - fileio_getsetlist variable static PyGetSetDef fileio_getsetlist[] -Modules/_io/fileio.c - fileio_members variable static PyMemberDef fileio_members[] -Modules/_io/fileio.c - fileio_methods variable static PyMethodDef fileio_methods -Modules/itertoolsmodule.c - filterfalse_methods variable static PyMethodDef filterfalse_methods -Modules/itertoolsmodule.c - filterfalse_type variable static PyTypeObject filterfalse_type -Python/bltinmodule.c - filter_methods variable static PyMethodDef filter_methods -Python/sysmodule.c - flags_desc variable static PyStructSequence_Desc flags_desc -Python/sysmodule.c - flags_fields variable static PyStructSequence_Field flags_fields[] -Python/sysmodule.c - FlagsType variable static PyTypeObject FlagsType -Objects/floatobject.c - float_as_number variable static PyNumberMethods float_as_number -Objects/floatobject.c - float_format variable static float_format_type -Objects/floatobject.c - float_getset variable static PyGetSetDef float_getset[] -Objects/floatobject.c - floatinfo_desc variable static PyStructSequence_Desc floatinfo_desc -Objects/floatobject.c - floatinfo_fields variable static PyStructSequence_Field floatinfo_fields[] -Objects/floatobject.c - FloatInfoType variable static PyTypeObject FloatInfoType -Objects/floatobject.c - float_methods variable static PyMethodDef float_methods -Python/Python-ast.c - FloorDiv_singleton variable static PyObject *FloorDiv_singleton -Python/Python-ast.c - FloorDiv_type variable static PyTypeObject *FloorDiv_type -Python/fileutils.c - force_ascii variable static int force_ascii -Python/Python-ast.c - For_fields variable static char *For_fields[] -Python/Python-ast.c - FormattedValue_fields variable static char *FormattedValue_fields[] -Python/Python-ast.c - FormattedValue_type variable static PyTypeObject *FormattedValue_type -Objects/stringlib/unicode_format.h - formatteriter_methods variable static PyMethodDef formatteriter_methods -Python/Python-ast.c - For_type variable static PyTypeObject *For_type -Objects/frameobject.c - frame_getsetlist variable static PyGetSetDef frame_getsetlist[] -Objects/frameobject.c - frame_memberlist variable static PyMemberDef frame_memberlist[] -Objects/frameobject.c - frame_methods variable static PyMethodDef frame_methods -Modules/_collectionsmodule.c - freeblocks variable static block *freeblocks[MAXFREEBLOCKS] -Python/dtoa.c - freelist variable static Bigint *freelist[Kmax+1] -Objects/floatobject.c - free_list variable static PyFloatObject *free_list -Objects/frameobject.c - free_list variable static PyFrameObject *free_list -Objects/listobject.c - free_list variable static PyListObject *free_list[PyList_MAXFREELIST] -Objects/dictobject.c - free_list variable static PyDictObject *free_list[PyDict_MAXFREELIST] -Objects/methodobject.c - free_list variable static PyCFunctionObject *free_list -Objects/tupleobject.c - free_list variable static PyTupleObject *free_list[PyTuple_MAXSAVESIZE] -Objects/classobject.c - free_list variable static PyMethodObject *free_list -Objects/setobject.c - frozenset_as_number variable static PyNumberMethods frozenset_as_number -Objects/setobject.c - frozenset_methods variable static PyMethodDef frozenset_methods -Objects/funcobject.c - func_getsetlist variable static PyGetSetDef func_getsetlist[] -Objects/funcobject.c - func_memberlist variable static PyMemberDef func_memberlist[] -Python/Python-ast.c - FunctionDef_fields variable static char *FunctionDef_fields[] -Python/Python-ast.c - FunctionDef_type variable static PyTypeObject *FunctionDef_type -Modules/_sre.c - _functions variable static PyMethodDef _functions[] -Python/Python-ast.c - FunctionType_fields variable static char *FunctionType_fields[] -Python/Python-ast.c - FunctionType_type variable static PyTypeObject *FunctionType_type -Modules/_functoolsmodule.c - _functoolsmodule variable static struct PyModuleDef _functoolsmodule -Modules/gcmodule.c - GcMethods variable static PyMethodDef GcMethods[] -Modules/gcmodule.c - gcmodule variable static struct PyModuleDef gcmodule -Modules/gcmodule.c - gc_str variable static PyObject *gc_str -Python/Python-ast.c - GeneratorExp_fields variable static char *GeneratorExp_fields[] -Python/Python-ast.c - GeneratorExp_type variable static PyTypeObject *GeneratorExp_type -Python/symtable.c - genexpr variable static identifier genexpr -Objects/genobject.c - gen_getsetlist variable static PyGetSetDef gen_getsetlist[] -Objects/genobject.c - gen_memberlist variable static PyMemberDef gen_memberlist[] -Objects/genobject.c - gen_methods variable static PyMethodDef gen_methods -Python/bootstrap_hash.c py_getrandom getrandom_works variable static int getrandom_works -Objects/descrobject.c - getset_getset variable static PyGetSetDef getset_getset[] -Python/Python-ast.c - Global_fields variable static char *Global_fields[] -Python/Python-ast.c - Global_type variable static PyTypeObject *Global_type -Modules/itertoolsmodule.c - groupby_methods variable static PyMethodDef groupby_methods -Modules/itertoolsmodule.c - groupby_type variable static PyTypeObject groupby_type -Modules/itertoolsmodule.c - _grouper_methods variable static PyMethodDef _grouper_methods -Modules/itertoolsmodule.c - _grouper_type variable static PyTypeObject _grouper_type -Python/Python-ast.c - GtE_singleton variable static PyObject *GtE_singleton -Python/Python-ast.c - GtE_type variable static PyTypeObject *GtE_type -Python/Python-ast.c - Gt_singleton variable static PyObject *Gt_singleton -Python/Python-ast.c - Gt_type variable static PyTypeObject *Gt_type -Modules/signalmodule.c - Handlers variable static volatile struct { _Py_atomic_int tripped; PyObject *func; } Handlers[NSIG] -Python/dynload_shlib.c - handles variable static struct { dev_t dev; ino_t ino; void *handle; } handles[128] -Python/sysmodule.c - hash_info_desc variable static PyStructSequence_Desc hash_info_desc -Python/sysmodule.c - hash_info_fields variable static PyStructSequence_Field hash_info_fields[] -Python/sysmodule.c - Hash_InfoType variable static PyTypeObject Hash_InfoType -Python/import.c import_find_and_load header variable static int header -Modules/_tkinter.c - id variable int id -??? ??? id variable ??? -??? ??? id variable ??? -??? ??? id variable ??? -??? ??? id variable ??? -??? ??? id variable ??? -??? ??? id variable ??? -??? ??? id variable ??? -??? ??? id variable ??? -??? ??? id variable ??? -??? ??? id variable ??? -??? ??? id variable ??? -??? ??? id variable ??? -??? ??? id variable ??? -??? ??? id variable ??? -??? ??? id variable ??? -??? ??? id variable ??? -??? ??? id variable ??? -??? ??? id variable ??? -??? ??? id variable ??? -Python/Python-ast.c - IfExp_fields variable static char *IfExp_fields[] -Python/Python-ast.c - IfExp_type variable static PyTypeObject *IfExp_type -Python/Python-ast.c - If_fields variable static char *If_fields[] -Python/Python-ast.c - If_type variable static PyTypeObject *If_type -Modules/signalmodule.c - IgnoreHandler variable static PyObject *IgnoreHandler -Python/import.c - imp_methods variable static PyMethodDef imp_methods -Python/import.c - impmodule variable static struct PyModuleDef impmodule -Objects/exceptions.c - ImportError_members variable static PyMemberDef ImportError_members[] -Objects/exceptions.c - ImportError_methods variable static PyMethodDef ImportError_methods -Python/Python-ast.c - Import_fields variable static char *Import_fields[] -Python/Python-ast.c - ImportFrom_fields variable static char *ImportFrom_fields[] -Python/Python-ast.c - ImportFrom_type variable static PyTypeObject *ImportFrom_type -Python/import.c import_find_and_load import_level variable static int import_level -Python/_warnings.c is_internal_frame importlib_string variable static PyObject *importlib_string -Python/import.c - import_lock variable static PyThread_type_lock import_lock -Python/import.c - import_lock_level variable static int import_lock_level -Python/import.c - import_lock_thread variable static unsigned long import_lock_thread -Python/import.c PyImport_Import import_str variable static PyObject *import_str -Python/Python-ast.c - Import_type variable static PyTypeObject *Import_type -Modules/_io/textio.c - incrementalnewlinedecoder_getset variable static PyGetSetDef incrementalnewlinedecoder_getset[] -Modules/_io/textio.c - incrementalnewlinedecoder_methods variable static PyMethodDef incrementalnewlinedecoder_methods -Objects/listobject.c - indexerr variable static PyObject *indexerr -Python/Python-ast.c - Index_fields variable static char *Index_fields[] -Python/Python-ast.c - Index_type variable static PyTypeObject *Index_type -Python/thread.c - initialized variable static int initialized -Modules/posixmodule.c - initialized variable static int initialized -Modules/pwdmodule.c - initialized variable static int initialized -Modules/signalmodule.c - initialized variable static int initialized -Modules/timemodule.c - initialized variable static int initialized -Python/Python-ast.c init_types initialized variable static int initialized -Objects/listobject.c PyList_New initialized variable static int initialized -Python/import.c - inittab_copy variable static struct _inittab *inittab_copy -Python/Python-ast.c - In_singleton variable static PyObject *In_singleton -Objects/classobject.c - instancemethod_getset variable static PyGetSetDef instancemethod_getset[] -Objects/classobject.c - instancemethod_memberlist variable static PyMemberDef instancemethod_memberlist[] -Python/Python-ast.c - Interactive_fields variable static char *Interactive_fields[] -Python/Python-ast.c - Interactive_type variable static PyTypeObject *Interactive_type -Objects/unicodeobject.c - interned variable static PyObject *interned -Objects/interpreteridobject.c - interpid_as_number variable static PyNumberMethods interpid_as_number -Modules/signalmodule.c - IntHandler variable static PyObject *IntHandler -Objects/longobject.c - int_info_desc variable static PyStructSequence_Desc int_info_desc -Objects/longobject.c - int_info_fields variable static PyStructSequence_Field int_info_fields[] -Objects/longobject.c - Int_InfoType variable static PyTypeObject Int_InfoType -Python/Python-ast.c - In_type variable static PyTypeObject *In_type -Python/Python-ast.c - Invert_singleton variable static PyObject *Invert_singleton -Python/Python-ast.c - Invert_type variable static PyTypeObject *Invert_type -Modules/_io/iobase.c - iobase_getset variable static PyGetSetDef iobase_getset[] -Modules/_io/iobase.c - iobase_methods variable static PyMethodDef iobase_methods -Python/fileutils.c set_inheritable ioctl_works variable static int ioctl_works -Modules/itertoolsmodule.c - islice_methods variable static PyMethodDef islice_methods -Modules/itertoolsmodule.c - islice_type variable static PyTypeObject islice_type -Python/Python-ast.c - IsNot_singleton variable static PyObject *IsNot_singleton -Python/Python-ast.c - IsNot_type variable static PyTypeObject *IsNot_type -Python/Python-ast.c - Is_singleton variable static PyObject *Is_singleton -Modules/signalmodule.c - is_tripped variable static _Py_atomic_int is_tripped -Python/Python-ast.c - Is_type variable static PyTypeObject *Is_type -Modules/_operator.c - itemgetter_methods variable static PyMethodDef itemgetter_methods -Modules/_operator.c - itemgetter_type variable static PyTypeObject itemgetter_type -Modules/itertoolsmodule.c - itertoolsmodule variable static struct PyModuleDef itertoolsmodule -Modules/signalmodule.c - ItimerError variable static PyObject *ItimerError -Python/Python-ast.c - JoinedStr_fields variable static char *JoinedStr_fields[] -Python/Python-ast.c - JoinedStr_type variable static PyTypeObject *JoinedStr_type -Modules/_functoolsmodule.c - keyobject_members variable static PyMemberDef keyobject_members[] -Modules/_functoolsmodule.c - keyobject_type variable static PyTypeObject keyobject_type -Objects/dictobject.c - keys_free_list variable static PyDictKeysObject *keys_free_list[PyDict_MAXFREELIST] -Python/Python-ast.c - keyword_fields variable static char *keyword_fields[] -Python/sysmodule.c sys_set_asyncgen_hooks keywords variable static char *keywords[] -Modules/_bisectmodule.c bisect_right keywords variable static char *keywords[] -Modules/_bisectmodule.c insort_right keywords variable static char *keywords[] -Python/Python-ast.c - keyword_type variable static PyTypeObject *keyword_type -Modules/_functoolsmodule.c keyobject_call kwargs variable static char *kwargs[] -Modules/_functoolsmodule.c functools_cmp_to_key kwargs variable static char *kwargs[] -Modules/itertoolsmodule.c repeat_new kwargs variable static char *kwargs[] -Python/_warnings.c warnings_warn_explicit kwd_list variable static char *kwd_list[] -Modules/_functoolsmodule.c - kwd_mark variable static PyObject *kwd_mark -Python/bltinmodule.c builtin___import__ kwlist variable static char *kwlist[] -Python/bltinmodule.c min_max kwlist variable static char *kwlist[] -Python/context.c contextvar_tp_new kwlist variable static char *kwlist[] -Python/sysmodule.c sys_getsizeof kwlist variable static char *kwlist[] -Objects/bytearrayobject.c bytearray_init kwlist variable static char *kwlist[] -Objects/bytesobject.c bytes_new kwlist variable static char *kwlist[] -Objects/exceptions.c ImportError_init kwlist variable static char *kwlist[] -Objects/interpreteridobject.c interpid_new kwlist variable static char *kwlist[] -Objects/memoryobject.c memory_new kwlist variable static char *kwlist[] -Objects/memoryobject.c memory_cast kwlist variable static char *kwlist[] -Objects/memoryobject.c memory_tobytes kwlist variable static char *kwlist[] -Objects/odictobject.c odict_pop kwlist variable static char *kwlist[] -Objects/unicodeobject.c unicode_new kwlist variable static char *kwlist[] -Objects/weakrefobject.c weakref_call kwlist variable static char *kwlist[] -Modules/_elementtree.c element_setstate_from_Python kwlist variable static char *kwlist[] -Modules/_json.c scanner_call kwlist variable static char *kwlist[] -Modules/_json.c scanner_new kwlist variable static char *kwlist[] -Modules/_json.c encoder_new kwlist variable static char *kwlist[] -Modules/_json.c encoder_call kwlist variable static char *kwlist[] -Python/symtable.c - lambda variable static identifier lambda -Python/Python-ast.c - Lambda_fields variable static char *Lambda_fields[] -Python/Python-ast.c - Lambda_type variable static PyTypeObject *Lambda_type -Parser/listnode.c - level variable static int level -Objects/listobject.c - list_as_mapping variable static PyMappingMethods list_as_mapping -Objects/listobject.c - list_as_sequence variable static PySequenceMethods list_as_sequence -Python/symtable.c - listcomp variable static identifier listcomp -Python/Python-ast.c - ListComp_fields variable static char *ListComp_fields[] -Python/Python-ast.c - ListComp_type variable static PyTypeObject *ListComp_type -Python/Python-ast.c - List_fields variable static char *List_fields[] -Objects/listobject.c - listiter_methods variable static PyMethodDef listiter_methods -Objects/listobject.c - list_methods variable static PyMethodDef list_methods -Objects/listobject.c - listreviter_methods variable static PyMethodDef listreviter_methods -Python/Python-ast.c - List_type variable static PyTypeObject *List_type -Python/ceval.c - lltrace variable static int lltrace -Python/Python-ast.c - Load_singleton variable PyObject *Load_singleton -Python/Python-ast.c - Load_type variable static PyTypeObject *Load_type -Modules/_threadmodule.c - localdummytype variable static PyTypeObject localdummytype -Modules/_localemodule.c - _localemodule variable static struct PyModuleDef _localemodule -Modules/_threadmodule.c - localtype variable static PyTypeObject localtype -Modules/_threadmodule.c - lock_methods variable static PyMethodDef lock_methods -Modules/_threadmodule.c - Locktype variable static PyTypeObject Locktype -Objects/longobject.c PyLong_FromString log_base_BASE variable static double log_base_BASE[37] -Objects/longobject.c - long_as_number variable static PyNumberMethods long_as_number -Objects/longobject.c - long_getset variable static PyGetSetDef long_getset[] -Objects/longobject.c - long_methods variable static PyMethodDef long_methods -Objects/rangeobject.c - longrangeiter_methods variable static PyMethodDef longrangeiter_methods -Modules/_functoolsmodule.c - lru_cache_getsetlist variable static PyGetSetDef lru_cache_getsetlist[] -Modules/_functoolsmodule.c - lru_cache_methods variable static PyMethodDef lru_cache_methods -Modules/_functoolsmodule.c - lru_cache_type variable static PyTypeObject lru_cache_type -Modules/_functoolsmodule.c - lru_list_elem_type variable static PyTypeObject lru_list_elem_type -Python/Python-ast.c - LShift_singleton variable static PyObject *LShift_singleton -Python/Python-ast.c - LShift_type variable static PyTypeObject *LShift_type -Python/Python-ast.c - LtE_singleton variable static PyObject *LtE_singleton -Python/Python-ast.c - LtE_type variable static PyTypeObject *LtE_type -Python/Python-ast.c - Lt_singleton variable static PyObject *Lt_singleton -Python/Python-ast.c - Lt_type variable static PyTypeObject *Lt_type -Python/bltinmodule.c - map_methods variable static PyMethodDef map_methods -Objects/descrobject.c - mappingproxy_as_mapping variable static PyMappingMethods mappingproxy_as_mapping -Objects/descrobject.c - mappingproxy_as_sequence variable static PySequenceMethods mappingproxy_as_sequence -Objects/descrobject.c - mappingproxy_methods variable static PyMethodDef mappingproxy_methods -Objects/dictobject.c - mapp_methods variable static PyMethodDef mapp_methods -Python/marshal.c - marshal_methods variable static PyMethodDef marshal_methods -Python/marshal.c - marshalmodule variable static struct PyModuleDef marshalmodule -Modules/_sre.c - match_as_mapping variable static PyMappingMethods match_as_mapping -Modules/_sre.c - match_getset variable static PyGetSetDef match_getset[] -Modules/_sre.c - match_members variable static PyMemberDef match_members[] -Modules/_sre.c - match_methods variable static PyMethodDef match_methods -Modules/_sre.c - Match_Type variable static PyTypeObject Match_Type -Python/Python-ast.c - MatMult_singleton variable static PyObject *MatMult_singleton -Python/Python-ast.c - MatMult_type variable static PyTypeObject *MatMult_type -Objects/obmalloc.c - maxarenas variable static uint maxarenas -Objects/moduleobject.c - max_module_number variable static Py_ssize_t max_module_number -Objects/descrobject.c - member_getset variable static PyGetSetDef member_getset[] -Objects/exceptions.c - memerrors_freelist variable static PyBaseExceptionObject *memerrors_freelist -Objects/exceptions.c - memerrors_numfree variable static int memerrors_numfree -Objects/memoryobject.c - memory_as_buffer variable static PyBufferProcs memory_as_buffer -Objects/memoryobject.c - memory_as_mapping variable static PyMappingMethods memory_as_mapping -Objects/memoryobject.c - memory_as_sequence variable static PySequenceMethods memory_as_sequence -Objects/memoryobject.c - memory_getsetlist variable static PyGetSetDef memory_getsetlist[] -Objects/memoryobject.c - memory_methods variable static PyMethodDef memory_methods -Objects/methodobject.c - meth_getsets variable static PyGetSetDef meth_getsets [] -Objects/methodobject.c - meth_members variable static PyMemberDef meth_members[] -Objects/methodobject.c - meth_methods variable static PyMethodDef meth_methods -Objects/typeobject.c - method_cache variable static struct method_cache_entry method_cache[1 << MCACHE_SIZE_EXP] -Modules/_operator.c - methodcaller_methods variable static PyMethodDef methodcaller_methods -Modules/_operator.c - methodcaller_type variable static PyTypeObject methodcaller_type -Objects/classobject.c - method_getset variable static PyGetSetDef method_getset[] -Objects/descrobject.c - method_getset variable static PyGetSetDef method_getset[] -Objects/classobject.c - method_memberlist variable static PyMemberDef method_memberlist[] -Objects/classobject.c - method_methods variable static PyMethodDef method_methods -Python/codecs.c _PyCodecRegistry_Init methods variable static struct { char *name; PyMethodDef def; } methods[] -Python/frozen.c - M___hello__ variable static unsigned char M___hello__[] -Python/Python-ast.c - Mod_singleton variable static PyObject *Mod_singleton -Python/Python-ast.c - mod_type variable static PyTypeObject *mod_type -Python/Python-ast.c - Mod_type variable static PyTypeObject *Mod_type -Python/_warnings.c - module variable PyObject *module -Modules/faulthandler.c - module_def variable static struct PyModuleDef module_def -Modules/_tracemalloc.c - module_def variable static struct PyModuleDef module_def -Python/Python-ast.c - Module_fields variable static char *Module_fields[] -Modules/_collectionsmodule.c - module_functions variable static struct PyMethodDef module_functions[] -Modules/_abc.c - module_functions variable static struct PyMethodDef module_functions[] -Objects/moduleobject.c - module_members variable static PyMemberDef module_members[] -Objects/moduleobject.c - module_methods variable static PyMethodDef module_methods -Modules/_functoolsmodule.c - module_methods variable static PyMethodDef module_methods -Modules/itertoolsmodule.c - module_methods variable static PyMethodDef module_methods -Modules/_io/_iomodule.c - module_methods variable static PyMethodDef module_methods -Modules/faulthandler.c - module_methods variable static PyMethodDef module_methods -Modules/_tracemalloc.c - module_methods variable static PyMethodDef module_methods -Python/Python-ast.c - Module_type variable static PyTypeObject *Module_type -Python/Python-ast.c - Mult_singleton variable static PyObject *Mult_singleton -Python/Python-ast.c - Mult_type variable static PyTypeObject *Mult_type -Objects/funcobject.c PyFunction_NewWithQualName __name__ variable static PyObject *__name__ -Python/compile.c compiler_lambda name variable static identifier name -Python/compile.c compiler_genexp name variable static identifier name -Python/compile.c compiler_listcomp name variable static identifier name -Python/compile.c compiler_setcomp name variable static identifier name -Python/compile.c compiler_dictcomp name variable static identifier name -Python/Python-ast.c - NamedExpr_fields variable static char *NamedExpr_fields[] -Python/Python-ast.c - NamedExpr_type variable static PyTypeObject *NamedExpr_type -Python/Python-ast.c - Name_fields variable static char *Name_fields[] -Objects/typeobject.c - name_op variable static _Py_Identifier name_op[] -Objects/namespaceobject.c - namespace_members variable static PyMemberDef namespace_members[] -Objects/namespaceobject.c - namespace_methods variable static PyMethodDef namespace_methods -Python/Python-ast.c - Name_type variable static PyTypeObject *Name_type -Objects/obmalloc.c - narenas_currently_allocated variable static size_t narenas_currently_allocated -Objects/obmalloc.c - narenas_highwater variable static size_t narenas_highwater -Python/sysmodule.c - newline variable static PyObject *newline -Objects/typeobject.c - next_version_tag variable static unsigned int next_version_tag -Objects/obmalloc.c - nfp2lasta variable static struct arena_object* nfp2lasta[MAX_POOLS_IN_ARENA + 1] -Python/dynload_shlib.c - nhandles variable static int nhandles -Objects/object.c - none_as_number variable static PyNumberMethods none_as_number -Python/Python-ast.c - Nonlocal_fields variable static char *Nonlocal_fields[] -Python/Python-ast.c - Nonlocal_type variable static PyTypeObject *Nonlocal_type -Python/Python-ast.c - NotEq_singleton variable static PyObject *NotEq_singleton -Python/Python-ast.c - NotEq_type variable static PyTypeObject *NotEq_type -Objects/object.c - notimplemented_methods variable static PyMethodDef notimplemented_methods -Python/Python-ast.c - NotIn_singleton variable static PyObject *NotIn_singleton -Python/Python-ast.c - NotIn_type variable static PyTypeObject *NotIn_type -Python/Python-ast.c - Not_singleton variable static PyObject *Not_singleton -Python/Python-ast.c - Not_type variable static PyTypeObject *Not_type -Objects/obmalloc.c - ntimes_arena_allocated variable static size_t ntimes_arena_allocated -Objects/bytesobject.c - nullstring variable static PyBytesObject *nullstring -Objects/codeobject.c PyCode_NewEmpty nulltuple variable static PyObject *nulltuple -Objects/floatobject.c - numfree variable static int numfree -Objects/frameobject.c - numfree variable static int numfree -Objects/listobject.c - numfree variable static int numfree -Objects/dictobject.c - numfree variable static int numfree -Objects/methodobject.c - numfree variable static int numfree -Objects/tupleobject.c - numfree variable static int numfree[PyTuple_MAXSAVESIZE] -Objects/classobject.c - numfree variable static int numfree -Modules/_collectionsmodule.c - numfreeblocks variable static Py_ssize_t numfreeblocks -Objects/dictobject.c - numfreekeys variable static int numfreekeys -Objects/typeobject.c - object_getsets variable static PyGetSetDef object_getsets[] -Objects/typeobject.c - object_methods variable static PyMethodDef object_methods -Objects/typeobject.c - objreduce variable static PyObject *objreduce -Objects/odictobject.c - odict_as_mapping variable static PyMappingMethods odict_as_mapping -Objects/odictobject.c - odict_getset variable static PyGetSetDef odict_getset[] -Objects/odictobject.c - odictitems_methods variable static PyMethodDef odictitems_methods -Objects/odictobject.c - odictiter_methods variable static PyMethodDef odictiter_methods -Objects/odictobject.c - odictkeys_methods variable static PyMethodDef odictkeys_methods -Objects/odictobject.c - odict_methods variable static PyMethodDef odict_methods -Objects/odictobject.c - odictvalues_methods variable static PyMethodDef odictvalues_methods -Modules/faulthandler.c - old_stack variable static stack_t old_stack -Modules/_operator.c - operator_methods variable static PyMethodDef operator_methods -Modules/_operator.c - operatormodule variable static struct PyModuleDef operatormodule -Python/Python-ast.c - operator_type variable static PyTypeObject *operator_type -Objects/typeobject.c slot_nb_add op_id variable _Py_static_string(op_id, OPSTR) -Objects/typeobject.c slot_nb_subtract op_id variable _Py_static_string(op_id, OPSTR) -Objects/typeobject.c slot_nb_multiply op_id variable _Py_static_string(op_id, OPSTR) -Objects/typeobject.c slot_nb_matrix_multiply op_id variable _Py_static_string(op_id, OPSTR) -Objects/typeobject.c slot_nb_remainder op_id variable _Py_static_string(op_id, OPSTR) -Objects/typeobject.c slot_nb_divmod op_id variable _Py_static_string(op_id, OPSTR) -Objects/typeobject.c slot_nb_power_binary op_id variable _Py_static_string(op_id, OPSTR) -Objects/typeobject.c slot_nb_lshift op_id variable _Py_static_string(op_id, OPSTR) -Objects/typeobject.c slot_nb_rshift op_id variable _Py_static_string(op_id, OPSTR) -Objects/typeobject.c slot_nb_and op_id variable _Py_static_string(op_id, OPSTR) -Objects/typeobject.c slot_nb_xor op_id variable _Py_static_string(op_id, OPSTR) -Objects/typeobject.c slot_nb_or op_id variable _Py_static_string(op_id, OPSTR) -Objects/typeobject.c slot_nb_floor_divide op_id variable _Py_static_string(op_id, OPSTR) -Objects/typeobject.c slot_nb_true_divide op_id variable _Py_static_string(op_id, OPSTR) -Python/getopt.c - opt_ptr variable static const wchar_t *opt_ptr -Python/initconfig.c - orig_argv variable static PyWideStringList orig_argv -Python/Python-ast.c - Or_singleton variable PyObject *Or_singleton -Python/Python-ast.c - Or_type variable static PyTypeObject *Or_type -Objects/exceptions.c - OSError_getset variable static PyGetSetDef OSError_getset[] -Objects/exceptions.c - OSError_members variable static PyMemberDef OSError_members[] -Objects/exceptions.c - OSError_methods variable static PyMethodDef OSError_methods -Python/dtoa.c - p5s variable static Bigint *p5s -Python/Python-ast.c - Param_singleton variable PyObject *Param_singleton -Python/Python-ast.c - Param_type variable static PyTypeObject *Param_type -Python/bltinmodule.c builtin_print _parser variable static struct _PyArg_Parser _parser -Python/clinic/_warnings.c.h warnings_warn _parser variable static _PyArg_Parser _parser -Python/clinic/bltinmodule.c.h builtin_compile _parser variable static _PyArg_Parser _parser -Python/clinic/bltinmodule.c.h builtin_round _parser variable static _PyArg_Parser _parser -Python/clinic/bltinmodule.c.h builtin_sum _parser variable static _PyArg_Parser _parser -Python/clinic/import.c.h _imp_source_hash _parser variable static _PyArg_Parser _parser -Python/clinic/sysmodule.c.h sys_addaudithook _parser variable static _PyArg_Parser _parser -Python/clinic/sysmodule.c.h sys_set_coroutine_origin_tracking_depth _parser variable static _PyArg_Parser _parser -Python/clinic/traceback.c.h tb_new _parser variable static _PyArg_Parser _parser -Objects/clinic/bytearrayobject.c.h bytearray_translate _parser variable static _PyArg_Parser _parser -Objects/clinic/bytearrayobject.c.h bytearray_split _parser variable static _PyArg_Parser _parser -Objects/clinic/bytearrayobject.c.h bytearray_rsplit _parser variable static _PyArg_Parser _parser -Objects/clinic/bytearrayobject.c.h bytearray_decode _parser variable static _PyArg_Parser _parser -Objects/clinic/bytearrayobject.c.h bytearray_splitlines _parser variable static _PyArg_Parser _parser -Objects/clinic/bytearrayobject.c.h bytearray_hex _parser variable static _PyArg_Parser _parser -Objects/clinic/bytesobject.c.h bytes_split _parser variable static _PyArg_Parser _parser -Objects/clinic/bytesobject.c.h bytes_rsplit _parser variable static _PyArg_Parser _parser -Objects/clinic/bytesobject.c.h bytes_translate _parser variable static _PyArg_Parser _parser -Objects/clinic/bytesobject.c.h bytes_decode _parser variable static _PyArg_Parser _parser -Objects/clinic/bytesobject.c.h bytes_splitlines _parser variable static _PyArg_Parser _parser -Objects/clinic/bytesobject.c.h bytes_hex _parser variable static _PyArg_Parser _parser -Objects/clinic/codeobject.c.h code_replace _parser variable static _PyArg_Parser _parser -Objects/clinic/complexobject.c.h complex_new _parser variable static _PyArg_Parser _parser -Objects/clinic/descrobject.c.h mappingproxy_new _parser variable static _PyArg_Parser _parser -Objects/clinic/descrobject.c.h property_init _parser variable static _PyArg_Parser _parser -Objects/clinic/enumobject.c.h enum_new _parser variable static _PyArg_Parser _parser -Objects/clinic/funcobject.c.h func_new _parser variable static _PyArg_Parser _parser -Objects/clinic/listobject.c.h list_sort _parser variable static _PyArg_Parser _parser -Objects/clinic/longobject.c.h long_new _parser variable static _PyArg_Parser _parser -Objects/clinic/longobject.c.h int_to_bytes _parser variable static _PyArg_Parser _parser -Objects/clinic/longobject.c.h int_from_bytes _parser variable static _PyArg_Parser _parser -Objects/clinic/memoryobject.c.h memoryview_hex _parser variable static _PyArg_Parser _parser -Objects/clinic/moduleobject.c.h module___init__ _parser variable static _PyArg_Parser _parser -Objects/clinic/odictobject.c.h OrderedDict_fromkeys _parser variable static _PyArg_Parser _parser -Objects/clinic/odictobject.c.h OrderedDict_setdefault _parser variable static _PyArg_Parser _parser -Objects/clinic/odictobject.c.h OrderedDict_popitem _parser variable static _PyArg_Parser _parser -Objects/clinic/odictobject.c.h OrderedDict_move_to_end _parser variable static _PyArg_Parser _parser -Objects/clinic/structseq.c.h structseq_new _parser variable static _PyArg_Parser _parser -Objects/clinic/unicodeobject.c.h unicode_encode _parser variable static _PyArg_Parser _parser -Objects/clinic/unicodeobject.c.h unicode_expandtabs _parser variable static _PyArg_Parser _parser -Objects/clinic/unicodeobject.c.h unicode_split _parser variable static _PyArg_Parser _parser -Objects/clinic/unicodeobject.c.h unicode_rsplit _parser variable static _PyArg_Parser _parser -Objects/clinic/unicodeobject.c.h unicode_splitlines _parser variable static _PyArg_Parser _parser -Objects/stringlib/clinic/transmogrify.h.h stringlib_expandtabs _parser variable static _PyArg_Parser _parser -Modules/_blake2/clinic/blake2b_impl.c.h py_blake2b_new _parser variable static _PyArg_Parser _parser -Modules/_blake2/clinic/blake2s_impl.c.h py_blake2s_new _parser variable static _PyArg_Parser _parser -Modules/_io/clinic/_iomodule.c.h _io_open _parser variable static _PyArg_Parser _parser -Modules/_io/clinic/_iomodule.c.h _io_open_code _parser variable static _PyArg_Parser _parser -Modules/_io/clinic/bufferedio.c.h _io_BufferedReader___init__ _parser variable static _PyArg_Parser _parser -Modules/_io/clinic/bufferedio.c.h _io_BufferedWriter___init__ _parser variable static _PyArg_Parser _parser -Modules/_io/clinic/bufferedio.c.h _io_BufferedRandom___init__ _parser variable static _PyArg_Parser _parser -Modules/_io/clinic/bytesio.c.h _io_BytesIO___init__ _parser variable static _PyArg_Parser _parser -Modules/_io/clinic/fileio.c.h _io_FileIO___init__ _parser variable static _PyArg_Parser _parser -Modules/_io/clinic/stringio.c.h _io_StringIO___init__ _parser variable static _PyArg_Parser _parser -Modules/_io/clinic/textio.c.h _io_IncrementalNewlineDecoder___init__ _parser variable static _PyArg_Parser _parser -Modules/_io/clinic/textio.c.h _io_IncrementalNewlineDecoder_decode _parser variable static _PyArg_Parser _parser -Modules/_io/clinic/textio.c.h _io_TextIOWrapper___init__ _parser variable static _PyArg_Parser _parser -Modules/_io/clinic/textio.c.h _io_TextIOWrapper_reconfigure _parser variable static _PyArg_Parser _parser -Modules/_io/clinic/winconsoleio.c.h _io__WindowsConsoleIO___init__ _parser variable static _PyArg_Parser _parser -Modules/_multiprocessing/clinic/posixshmem.c.h _posixshmem_shm_open _parser variable static _PyArg_Parser _parser -Modules/_multiprocessing/clinic/posixshmem.c.h _posixshmem_shm_unlink _parser variable static _PyArg_Parser _parser -Modules/cjkcodecs/clinic/multibytecodec.c.h _multibytecodec_MultibyteCodec_encode _parser variable static _PyArg_Parser _parser -Modules/cjkcodecs/clinic/multibytecodec.c.h _multibytecodec_MultibyteCodec_decode _parser variable static _PyArg_Parser _parser -Modules/cjkcodecs/clinic/multibytecodec.c.h _multibytecodec_MultibyteIncrementalEncoder_encode _parser variable static _PyArg_Parser _parser -Modules/cjkcodecs/clinic/multibytecodec.c.h _multibytecodec_MultibyteIncrementalDecoder_decode _parser variable static _PyArg_Parser _parser -Modules/clinic/_asynciomodule.c.h _asyncio_Future___init__ _parser variable static _PyArg_Parser _parser -Modules/clinic/_asynciomodule.c.h _asyncio_Future_add_done_callback _parser variable static _PyArg_Parser _parser -Modules/clinic/_asynciomodule.c.h _asyncio_Task___init__ _parser variable static _PyArg_Parser _parser -Modules/clinic/_asynciomodule.c.h _asyncio_Task_current_task _parser variable static _PyArg_Parser _parser -Modules/clinic/_asynciomodule.c.h _asyncio_Task_all_tasks _parser variable static _PyArg_Parser _parser -Modules/clinic/_asynciomodule.c.h _asyncio_Task_get_stack _parser variable static _PyArg_Parser _parser -Modules/clinic/_asynciomodule.c.h _asyncio_Task_print_stack _parser variable static _PyArg_Parser _parser -Modules/clinic/_asynciomodule.c.h _asyncio__register_task _parser variable static _PyArg_Parser _parser -Modules/clinic/_asynciomodule.c.h _asyncio__unregister_task _parser variable static _PyArg_Parser _parser -Modules/clinic/_asynciomodule.c.h _asyncio__enter_task _parser variable static _PyArg_Parser _parser -Modules/clinic/_asynciomodule.c.h _asyncio__leave_task _parser variable static _PyArg_Parser _parser -Modules/clinic/_bz2module.c.h _bz2_BZ2Decompressor_decompress _parser variable static _PyArg_Parser _parser -Modules/clinic/_codecsmodule.c.h _codecs_encode _parser variable static _PyArg_Parser _parser -Modules/clinic/_codecsmodule.c.h _codecs_decode _parser variable static _PyArg_Parser _parser -Modules/clinic/_cursesmodule.c.h _curses_setupterm _parser variable static _PyArg_Parser _parser -Modules/clinic/_datetimemodule.c.h datetime_datetime_now _parser variable static _PyArg_Parser _parser -Modules/clinic/_elementtree.c.h _elementtree_Element_find _parser variable static _PyArg_Parser _parser -Modules/clinic/_elementtree.c.h _elementtree_Element_findtext _parser variable static _PyArg_Parser _parser -Modules/clinic/_elementtree.c.h _elementtree_Element_findall _parser variable static _PyArg_Parser _parser -Modules/clinic/_elementtree.c.h _elementtree_Element_iterfind _parser variable static _PyArg_Parser _parser -Modules/clinic/_elementtree.c.h _elementtree_Element_get _parser variable static _PyArg_Parser _parser -Modules/clinic/_elementtree.c.h _elementtree_Element_iter _parser variable static _PyArg_Parser _parser -Modules/clinic/_elementtree.c.h _elementtree_Element_getiterator _parser variable static _PyArg_Parser _parser -Modules/clinic/_elementtree.c.h _elementtree_TreeBuilder___init__ _parser variable static _PyArg_Parser _parser -Modules/clinic/_elementtree.c.h _elementtree_XMLParser___init__ _parser variable static _PyArg_Parser _parser -Modules/clinic/_hashopenssl.c.h EVP_new _parser variable static _PyArg_Parser _parser -Modules/clinic/_hashopenssl.c.h pbkdf2_hmac _parser variable static _PyArg_Parser _parser -Modules/clinic/_hashopenssl.c.h _hashlib_scrypt _parser variable static _PyArg_Parser _parser -Modules/clinic/_hashopenssl.c.h _hashlib_hmac_digest _parser variable static _PyArg_Parser _parser -Modules/clinic/_lzmamodule.c.h _lzma_LZMADecompressor_decompress _parser variable static _PyArg_Parser _parser -Modules/clinic/_lzmamodule.c.h _lzma_LZMADecompressor___init__ _parser variable static _PyArg_Parser _parser -Modules/clinic/_opcode.c.h _opcode_stack_effect _parser variable static _PyArg_Parser _parser -Modules/clinic/_pickle.c.h _pickle_Pickler___init__ _parser variable static _PyArg_Parser _parser -Modules/clinic/_pickle.c.h _pickle_Unpickler___init__ _parser variable static _PyArg_Parser _parser -Modules/clinic/_pickle.c.h _pickle_dump _parser variable static _PyArg_Parser _parser -Modules/clinic/_pickle.c.h _pickle_dumps _parser variable static _PyArg_Parser _parser -Modules/clinic/_pickle.c.h _pickle_load _parser variable static _PyArg_Parser _parser -Modules/clinic/_pickle.c.h _pickle_loads _parser variable static _PyArg_Parser _parser -Modules/clinic/_queuemodule.c.h _queue_SimpleQueue_put _parser variable static _PyArg_Parser _parser -Modules/clinic/_queuemodule.c.h _queue_SimpleQueue_put_nowait _parser variable static _PyArg_Parser _parser -Modules/clinic/_queuemodule.c.h _queue_SimpleQueue_get _parser variable static _PyArg_Parser _parser -Modules/clinic/_sre.c.h _sre_SRE_Pattern_match _parser variable static _PyArg_Parser _parser -Modules/clinic/_sre.c.h _sre_SRE_Pattern_fullmatch _parser variable static _PyArg_Parser _parser -Modules/clinic/_sre.c.h _sre_SRE_Pattern_search _parser variable static _PyArg_Parser _parser -Modules/clinic/_sre.c.h _sre_SRE_Pattern_findall _parser variable static _PyArg_Parser _parser -Modules/clinic/_sre.c.h _sre_SRE_Pattern_finditer _parser variable static _PyArg_Parser _parser -Modules/clinic/_sre.c.h _sre_SRE_Pattern_scanner _parser variable static _PyArg_Parser _parser -Modules/clinic/_sre.c.h _sre_SRE_Pattern_split _parser variable static _PyArg_Parser _parser -Modules/clinic/_sre.c.h _sre_SRE_Pattern_sub _parser variable static _PyArg_Parser _parser -Modules/clinic/_sre.c.h _sre_SRE_Pattern_subn _parser variable static _PyArg_Parser _parser -Modules/clinic/_sre.c.h _sre_compile _parser variable static _PyArg_Parser _parser -Modules/clinic/_sre.c.h _sre_SRE_Match_expand _parser variable static _PyArg_Parser _parser -Modules/clinic/_sre.c.h _sre_SRE_Match_groups _parser variable static _PyArg_Parser _parser -Modules/clinic/_sre.c.h _sre_SRE_Match_groupdict _parser variable static _PyArg_Parser _parser -Modules/clinic/_ssl.c.h _ssl__SSLSocket_get_channel_binding _parser variable static _PyArg_Parser _parser -Modules/clinic/_ssl.c.h _ssl__SSLContext_load_cert_chain _parser variable static _PyArg_Parser _parser -Modules/clinic/_ssl.c.h _ssl__SSLContext_load_verify_locations _parser variable static _PyArg_Parser _parser -Modules/clinic/_ssl.c.h _ssl__SSLContext__wrap_socket _parser variable static _PyArg_Parser _parser -Modules/clinic/_ssl.c.h _ssl__SSLContext__wrap_bio _parser variable static _PyArg_Parser _parser -Modules/clinic/_ssl.c.h _ssl__SSLContext_get_ca_certs _parser variable static _PyArg_Parser _parser -Modules/clinic/_ssl.c.h _ssl_txt2obj _parser variable static _PyArg_Parser _parser -Modules/clinic/_ssl.c.h _ssl_enum_certificates _parser variable static _PyArg_Parser _parser -Modules/clinic/_ssl.c.h _ssl_enum_crls _parser variable static _PyArg_Parser _parser -Modules/clinic/_struct.c.h Struct___init__ _parser variable static _PyArg_Parser _parser -Modules/clinic/_struct.c.h Struct_unpack_from _parser variable static _PyArg_Parser _parser -Modules/clinic/_struct.c.h unpack_from _parser variable static _PyArg_Parser _parser -Modules/clinic/_winapi.c.h _winapi_ConnectNamedPipe _parser variable static _PyArg_Parser _parser -Modules/clinic/_winapi.c.h _winapi_ReadFile _parser variable static _PyArg_Parser _parser -Modules/clinic/_winapi.c.h _winapi_WriteFile _parser variable static _PyArg_Parser _parser -Modules/clinic/_winapi.c.h _winapi_GetFileType _parser variable static _PyArg_Parser _parser -Modules/clinic/binascii.c.h binascii_b2a_uu _parser variable static _PyArg_Parser _parser -Modules/clinic/binascii.c.h binascii_b2a_base64 _parser variable static _PyArg_Parser _parser -Modules/clinic/binascii.c.h binascii_b2a_hex _parser variable static _PyArg_Parser _parser -Modules/clinic/binascii.c.h binascii_hexlify _parser variable static _PyArg_Parser _parser -Modules/clinic/binascii.c.h binascii_a2b_qp _parser variable static _PyArg_Parser _parser -Modules/clinic/binascii.c.h binascii_b2a_qp _parser variable static _PyArg_Parser _parser -Modules/clinic/cmathmodule.c.h cmath_isclose _parser variable static _PyArg_Parser _parser -Modules/clinic/gcmodule.c.h gc_collect _parser variable static _PyArg_Parser _parser -Modules/clinic/gcmodule.c.h gc_get_objects _parser variable static _PyArg_Parser _parser -Modules/clinic/grpmodule.c.h grp_getgrgid _parser variable static _PyArg_Parser _parser -Modules/clinic/grpmodule.c.h grp_getgrnam _parser variable static _PyArg_Parser _parser -Modules/_functoolsmodule.c - partial_getsetlist variable static PyGetSetDef partial_getsetlist[] -Modules/_functoolsmodule.c - partial_memberlist variable static PyMemberDef partial_memberlist[] -Modules/_functoolsmodule.c - partial_methods variable static PyMethodDef partial_methods -Modules/_functoolsmodule.c - partial_type variable static PyTypeObject partial_type -Python/Python-ast.c - Pass_type variable static PyTypeObject *Pass_type -Modules/_sre.c - pattern_getset variable static PyGetSetDef pattern_getset[] -Modules/_sre.c - pattern_members variable static PyMemberDef pattern_members[] -Modules/_sre.c - pattern_methods variable static PyMethodDef pattern_methods -Modules/_sre.c - Pattern_Type variable static PyTypeObject Pattern_Type -Modules/itertoolsmodule.c - permuations_methods variable static PyMethodDef permuations_methods -Modules/itertoolsmodule.c - permutations_type variable static PyTypeObject permutations_type -Objects/picklebufobject.c - picklebuf_as_buffer variable static PyBufferProcs picklebuf_as_buffer -Objects/picklebufobject.c - picklebuf_methods variable static PyMethodDef picklebuf_methods -Python/dtoa.c - pmem_next variable static double *pmem_next -Objects/typeobject.c resolve_slotdups pname variable static PyObject *pname -Modules/posixmodule.c - posix_constants_confstr variable static struct constdef posix_constants_confstr[] -Modules/posixmodule.c - posix_constants_pathconf variable static struct constdef posix_constants_pathconf[] -Modules/posixmodule.c - posix_constants_sysconf variable static struct constdef posix_constants_sysconf[] -Modules/posixmodule.c - posix_methods variable static PyMethodDef posix_methods -Modules/posixmodule.c - posixmodule variable static struct PyModuleDef posixmodule -Modules/posixmodule.c - posix_putenv_garbage variable static PyObject *posix_putenv_garbage -Python/Python-ast.c - Pow_singleton variable static PyObject *Pow_singleton -Python/Python-ast.c - Pow_type variable static PyTypeObject *Pow_type -Python/sysmodule.c - _preinit_warnoptions variable static _Py_PreInitEntry _preinit_warnoptions -Python/sysmodule.c - _preinit_xoptions variable static _Py_PreInitEntry _preinit_xoptions -Objects/exceptions.c _check_for_legacy_statements print_prefix variable static PyObject *print_prefix -Python/dtoa.c - private_mem variable static double private_mem[PRIVATE_mem] -Modules/itertoolsmodule.c - product_methods variable static PyMethodDef product_methods -Modules/itertoolsmodule.c - product_type variable static PyTypeObject product_type -Objects/descrobject.c - property_getsetlist variable static PyGetSetDef property_getsetlist[] -Objects/descrobject.c - property_members variable static PyMemberDef property_members[] -Objects/descrobject.c - property_methods variable static PyMethodDef property_methods -Objects/weakrefobject.c - proxy_as_mapping variable static PyMappingMethods proxy_as_mapping -Objects/weakrefobject.c - proxy_as_number variable static PyNumberMethods proxy_as_number -Objects/weakrefobject.c - proxy_as_sequence variable static PySequenceMethods proxy_as_sequence -Objects/weakrefobject.c - proxy_methods variable static PyMethodDef proxy_methods -Objects/typeobject.c resolve_slotdups ptrs variable static slotdef *ptrs[MAX_EQUIV] -Modules/pwdmodule.c - pwd_methods variable static PyMethodDef pwd_methods -Modules/pwdmodule.c - pwdmodule variable static struct PyModuleDef pwdmodule -Objects/object.c - _Py_abstract_hack variable Py_ssize_t (*_Py_abstract_hack)(PyObject *) -Objects/obmalloc.c - _Py_AllocatedBlocks variable static Py_ssize_t _Py_AllocatedBlocks -Objects/genobject.c - _PyAsyncGenASend_Type variable PyTypeObject _PyAsyncGenASend_Type -Objects/genobject.c - _PyAsyncGenAThrow_Type variable PyTypeObject _PyAsyncGenAThrow_Type -Objects/genobject.c - PyAsyncGen_Type variable PyTypeObject PyAsyncGen_Type -Objects/genobject.c - _PyAsyncGenWrappedValue_Type variable PyTypeObject _PyAsyncGenWrappedValue_Type -Objects/typeobject.c - PyBaseObject_Type variable PyTypeObject PyBaseObject_Type -Objects/boolobject.c - PyBool_Type variable PyTypeObject PyBool_Type -Modules/_io/bufferedio.c - PyBufferedIOBase_Type variable PyTypeObject PyBufferedIOBase_Type -Modules/_io/bufferedio.c - PyBufferedRandom_Type variable PyTypeObject PyBufferedRandom_Type -Modules/_io/bufferedio.c - PyBufferedReader_Type variable PyTypeObject PyBufferedReader_Type -Modules/_io/bufferedio.c - PyBufferedRWPair_Type variable PyTypeObject PyBufferedRWPair_Type -Modules/_io/bufferedio.c - PyBufferedWriter_Type variable PyTypeObject PyBufferedWriter_Type -Objects/bytearrayobject.c - _PyByteArray_empty_string variable char _PyByteArray_empty_string[] -Objects/bytearrayobject.c - PyByteArrayIter_Type variable PyTypeObject PyByteArrayIter_Type -Objects/bytearrayobject.c - PyByteArray_Type variable PyTypeObject PyByteArray_Type -Modules/_io/bytesio.c - _PyBytesIOBuffer_Type variable PyTypeObject _PyBytesIOBuffer_Type -Modules/_io/bytesio.c - PyBytesIO_Type variable PyTypeObject PyBytesIO_Type -Objects/bytesobject.c - PyBytesIter_Type variable PyTypeObject PyBytesIter_Type -Objects/bytesobject.c - PyBytes_Type variable PyTypeObject PyBytes_Type -Python/initconfig.c - Py_BytesWarningFlag variable int Py_BytesWarningFlag -Objects/iterobject.c - PyCallIter_Type variable PyTypeObject PyCallIter_Type -Objects/capsule.c - PyCapsule_Type variable PyTypeObject PyCapsule_Type -Objects/cellobject.c - PyCell_Type variable PyTypeObject PyCell_Type -Objects/methodobject.c - PyCFunction_Type variable PyTypeObject PyCFunction_Type -Python/ceval.c - _Py_CheckRecursionLimit variable int _Py_CheckRecursionLimit -Objects/descrobject.c - PyClassMethodDescr_Type variable PyTypeObject PyClassMethodDescr_Type -Objects/funcobject.c - PyClassMethod_Type variable PyTypeObject PyClassMethod_Type -Objects/codeobject.c - PyCode_Type variable PyTypeObject PyCode_Type -Objects/complexobject.c - PyComplex_Type variable PyTypeObject PyComplex_Type -Python/context.c - PyContext_as_mapping variable static PyMappingMethods PyContext_as_mapping -Python/context.c - PyContext_as_sequence variable static PySequenceMethods PyContext_as_sequence -Python/context.c - PyContext_methods variable static PyMethodDef PyContext_methods -Python/context.c - PyContextTokenMissing_Type variable PyTypeObject PyContextTokenMissing_Type -Python/context.c - PyContextToken_Type variable PyTypeObject PyContextToken_Type -Python/context.c - PyContextTokenType_getsetlist variable static PyGetSetDef PyContextTokenType_getsetlist[] -Python/context.c - PyContext_Type variable PyTypeObject PyContext_Type -Python/context.c - PyContextVar_members variable static PyMemberDef PyContextVar_members[] -Python/context.c - PyContextVar_methods variable static PyMethodDef PyContextVar_methods -Python/context.c - PyContextVar_Type variable PyTypeObject PyContextVar_Type -Objects/genobject.c - PyCoro_Type variable PyTypeObject PyCoro_Type -Objects/genobject.c - _PyCoroWrapper_Type variable PyTypeObject _PyCoroWrapper_Type -Python/initconfig.c - Py_DebugFlag variable int Py_DebugFlag -Objects/dictobject.c - pydict_global_version variable static uint64_t pydict_global_version -Objects/dictobject.c - PyDictItems_Type variable PyTypeObject PyDictItems_Type -Objects/dictobject.c - PyDictIterItem_Type variable PyTypeObject PyDictIterItem_Type -Objects/dictobject.c - PyDictIterKey_Type variable PyTypeObject PyDictIterKey_Type -Objects/dictobject.c - PyDictIterValue_Type variable PyTypeObject PyDictIterValue_Type -Objects/dictobject.c - PyDictKeys_Type variable PyTypeObject PyDictKeys_Type -Objects/descrobject.c - PyDictProxy_Type variable PyTypeObject PyDictProxy_Type -Objects/dictobject.c - PyDictRevIterItem_Type variable PyTypeObject PyDictRevIterItem_Type -Objects/dictobject.c - PyDictRevIterKey_Type variable PyTypeObject PyDictRevIterKey_Type -Objects/dictobject.c - PyDictRevIterValue_Type variable PyTypeObject PyDictRevIterValue_Type -Objects/dictobject.c - PyDict_Type variable PyTypeObject PyDict_Type -Objects/dictobject.c - PyDictValues_Type variable PyTypeObject PyDictValues_Type -Python/initconfig.c - Py_DontWriteBytecodeFlag variable int Py_DontWriteBytecodeFlag -Objects/sliceobject.c - _Py_EllipsisObject variable PyObject _Py_EllipsisObject -Objects/sliceobject.c - PyEllipsis_Type variable PyTypeObject PyEllipsis_Type -Objects/enumobject.c - PyEnum_Type variable PyTypeObject PyEnum_Type -Objects/exceptions.c - _PyExc_ArithmeticError variable static PyTypeObject _PyExc_ArithmeticError -Objects/exceptions.c - PyExc_ArithmeticError variable static PyTypeObject PyExc_ArithmeticError -Objects/exceptions.c - _PyExc_AssertionError variable static PyTypeObject _PyExc_AssertionError -Objects/exceptions.c - PyExc_AssertionError variable static PyTypeObject PyExc_AssertionError -Objects/exceptions.c - _PyExc_AttributeError variable static PyTypeObject _PyExc_AttributeError -Objects/exceptions.c - PyExc_AttributeError variable static PyTypeObject PyExc_AttributeError -Objects/exceptions.c - _PyExc_BaseException variable static PyTypeObject _PyExc_BaseException -Objects/exceptions.c - PyExc_BaseException variable static PyTypeObject PyExc_BaseException -Objects/exceptions.c - _PyExc_BlockingIOError variable static PyTypeObject _PyExc_BlockingIOError -Objects/exceptions.c - PyExc_BlockingIOError variable static PyTypeObject PyExc_BlockingIOError -Objects/exceptions.c - _PyExc_BrokenPipeError variable static PyTypeObject _PyExc_BrokenPipeError -Objects/exceptions.c - PyExc_BrokenPipeError variable static PyTypeObject PyExc_BrokenPipeError -Objects/exceptions.c - _PyExc_BufferError variable static PyTypeObject _PyExc_BufferError -Objects/exceptions.c - PyExc_BufferError variable static PyTypeObject PyExc_BufferError -Objects/exceptions.c - _PyExc_BytesWarning variable static PyTypeObject _PyExc_BytesWarning -Objects/exceptions.c - PyExc_BytesWarning variable static PyTypeObject PyExc_BytesWarning -Objects/exceptions.c - _PyExc_ChildProcessError variable static PyTypeObject _PyExc_ChildProcessError -Objects/exceptions.c - PyExc_ChildProcessError variable static PyTypeObject PyExc_ChildProcessError -Objects/exceptions.c - _PyExc_ConnectionAbortedError variable static PyTypeObject _PyExc_ConnectionAbortedError -Objects/exceptions.c - PyExc_ConnectionAbortedError variable static PyTypeObject PyExc_ConnectionAbortedError -Objects/exceptions.c - _PyExc_ConnectionError variable static PyTypeObject _PyExc_ConnectionError -Objects/exceptions.c - PyExc_ConnectionError variable static PyTypeObject PyExc_ConnectionError -Objects/exceptions.c - _PyExc_ConnectionRefusedError variable static PyTypeObject _PyExc_ConnectionRefusedError -Objects/exceptions.c - PyExc_ConnectionRefusedError variable static PyTypeObject PyExc_ConnectionRefusedError -Objects/exceptions.c - _PyExc_ConnectionResetError variable static PyTypeObject _PyExc_ConnectionResetError -Objects/exceptions.c - PyExc_ConnectionResetError variable static PyTypeObject PyExc_ConnectionResetError -Objects/exceptions.c - _PyExc_DeprecationWarning variable static PyTypeObject _PyExc_DeprecationWarning -Objects/exceptions.c - PyExc_DeprecationWarning variable static PyTypeObject PyExc_DeprecationWarning -Objects/exceptions.c - PyExc_EnvironmentError variable static PyTypeObject PyExc_EnvironmentError -Objects/exceptions.c - _PyExc_EOFError variable static PyTypeObject _PyExc_EOFError -Objects/exceptions.c - PyExc_EOFError variable static PyTypeObject PyExc_EOFError -Objects/exceptions.c - _PyExc_Exception variable static PyTypeObject _PyExc_Exception -Objects/exceptions.c - PyExc_Exception variable static PyTypeObject PyExc_Exception -Objects/exceptions.c - _PyExc_FileExistsError variable static PyTypeObject _PyExc_FileExistsError -Objects/exceptions.c - PyExc_FileExistsError variable static PyTypeObject PyExc_FileExistsError -Objects/exceptions.c - _PyExc_FileNotFoundError variable static PyTypeObject _PyExc_FileNotFoundError -Objects/exceptions.c - PyExc_FileNotFoundError variable static PyTypeObject PyExc_FileNotFoundError -Objects/exceptions.c - _PyExc_FloatingPointError variable static PyTypeObject _PyExc_FloatingPointError -Objects/exceptions.c - PyExc_FloatingPointError variable static PyTypeObject PyExc_FloatingPointError -Objects/exceptions.c - _PyExc_FutureWarning variable static PyTypeObject _PyExc_FutureWarning -Objects/exceptions.c - PyExc_FutureWarning variable static PyTypeObject PyExc_FutureWarning -Objects/exceptions.c - _PyExc_GeneratorExit variable static PyTypeObject _PyExc_GeneratorExit -Objects/exceptions.c - PyExc_GeneratorExit variable static PyTypeObject PyExc_GeneratorExit -Objects/exceptions.c - _PyExc_ImportError variable static PyTypeObject _PyExc_ImportError -Objects/exceptions.c - PyExc_ImportError variable static PyTypeObject PyExc_ImportError -Objects/exceptions.c - _PyExc_ImportWarning variable static PyTypeObject _PyExc_ImportWarning -Objects/exceptions.c - PyExc_ImportWarning variable static PyTypeObject PyExc_ImportWarning -Objects/exceptions.c - _PyExc_IndentationError variable static PyTypeObject _PyExc_IndentationError -Objects/exceptions.c - PyExc_IndentationError variable static PyTypeObject PyExc_IndentationError -Objects/exceptions.c - _PyExc_IndexError variable static PyTypeObject _PyExc_IndexError -Objects/exceptions.c - PyExc_IndexError variable static PyTypeObject PyExc_IndexError -Objects/exceptions.c - _PyExc_InterruptedError variable static PyTypeObject _PyExc_InterruptedError -Objects/exceptions.c - PyExc_InterruptedError variable static PyTypeObject PyExc_InterruptedError -Objects/exceptions.c - PyExc_IOError variable static PyTypeObject PyExc_IOError -Objects/exceptions.c - _PyExc_IsADirectoryError variable static PyTypeObject _PyExc_IsADirectoryError -Objects/exceptions.c - PyExc_IsADirectoryError variable static PyTypeObject PyExc_IsADirectoryError -Objects/exceptions.c - _PyExc_KeyboardInterrupt variable static PyTypeObject _PyExc_KeyboardInterrupt -Objects/exceptions.c - PyExc_KeyboardInterrupt variable static PyTypeObject PyExc_KeyboardInterrupt -Objects/exceptions.c - _PyExc_KeyError variable static PyTypeObject _PyExc_KeyError -Objects/exceptions.c - PyExc_KeyError variable static PyTypeObject PyExc_KeyError -Objects/exceptions.c - _PyExc_LookupError variable static PyTypeObject _PyExc_LookupError -Objects/exceptions.c - PyExc_LookupError variable static PyTypeObject PyExc_LookupError -Objects/exceptions.c - _PyExc_MemoryError variable static PyTypeObject _PyExc_MemoryError -Objects/exceptions.c - PyExc_MemoryError variable static PyTypeObject PyExc_MemoryError -Objects/exceptions.c - _PyExc_ModuleNotFoundError variable static PyTypeObject _PyExc_ModuleNotFoundError -Objects/exceptions.c - PyExc_ModuleNotFoundError variable static PyTypeObject PyExc_ModuleNotFoundError -Objects/exceptions.c - _PyExc_NameError variable static PyTypeObject _PyExc_NameError -Objects/exceptions.c - PyExc_NameError variable static PyTypeObject PyExc_NameError -Objects/exceptions.c - _PyExc_NotADirectoryError variable static PyTypeObject _PyExc_NotADirectoryError -Objects/exceptions.c - PyExc_NotADirectoryError variable static PyTypeObject PyExc_NotADirectoryError -Objects/exceptions.c - _PyExc_NotImplementedError variable static PyTypeObject _PyExc_NotImplementedError -Objects/exceptions.c - PyExc_NotImplementedError variable static PyTypeObject PyExc_NotImplementedError -Objects/exceptions.c - _PyExc_OSError variable static PyTypeObject _PyExc_OSError -Objects/exceptions.c - PyExc_OSError variable static PyTypeObject PyExc_OSError -Objects/exceptions.c - _PyExc_OverflowError variable static PyTypeObject _PyExc_OverflowError -Objects/exceptions.c - PyExc_OverflowError variable static PyTypeObject PyExc_OverflowError -Objects/exceptions.c - _PyExc_PendingDeprecationWarning variable static PyTypeObject _PyExc_PendingDeprecationWarning -Objects/exceptions.c - PyExc_PendingDeprecationWarning variable static PyTypeObject PyExc_PendingDeprecationWarning -Objects/exceptions.c - _PyExc_PermissionError variable static PyTypeObject _PyExc_PermissionError -Objects/exceptions.c - PyExc_PermissionError variable static PyTypeObject PyExc_PermissionError -Objects/exceptions.c - _PyExc_ProcessLookupError variable static PyTypeObject _PyExc_ProcessLookupError -Objects/exceptions.c - PyExc_ProcessLookupError variable static PyTypeObject PyExc_ProcessLookupError -Objects/exceptions.c - _PyExc_RecursionError variable static PyTypeObject _PyExc_RecursionError -Objects/exceptions.c - PyExc_RecursionError variable static PyTypeObject PyExc_RecursionError -Objects/exceptions.c - _PyExc_ReferenceError variable static PyTypeObject _PyExc_ReferenceError -Objects/exceptions.c - PyExc_ReferenceError variable static PyTypeObject PyExc_ReferenceError -Objects/exceptions.c - _PyExc_ResourceWarning variable static PyTypeObject _PyExc_ResourceWarning -Objects/exceptions.c - PyExc_ResourceWarning variable static PyTypeObject PyExc_ResourceWarning -Objects/exceptions.c - _PyExc_RuntimeError variable static PyTypeObject _PyExc_RuntimeError -Objects/exceptions.c - PyExc_RuntimeError variable static PyTypeObject PyExc_RuntimeError -Objects/exceptions.c - _PyExc_RuntimeWarning variable static PyTypeObject _PyExc_RuntimeWarning -Objects/exceptions.c - PyExc_RuntimeWarning variable static PyTypeObject PyExc_RuntimeWarning -Objects/exceptions.c - _PyExc_StopAsyncIteration variable static PyTypeObject _PyExc_StopAsyncIteration -Objects/exceptions.c - PyExc_StopAsyncIteration variable static PyTypeObject PyExc_StopAsyncIteration -Objects/exceptions.c - _PyExc_StopIteration variable static PyTypeObject _PyExc_StopIteration -Objects/exceptions.c - PyExc_StopIteration variable static PyTypeObject PyExc_StopIteration -Objects/exceptions.c - _PyExc_SyntaxError variable static PyTypeObject _PyExc_SyntaxError -Objects/exceptions.c - PyExc_SyntaxError variable static PyTypeObject PyExc_SyntaxError -Objects/exceptions.c - _PyExc_SyntaxWarning variable static PyTypeObject _PyExc_SyntaxWarning -Objects/exceptions.c - PyExc_SyntaxWarning variable static PyTypeObject PyExc_SyntaxWarning -Objects/exceptions.c - _PyExc_SystemError variable static PyTypeObject _PyExc_SystemError -Objects/exceptions.c - PyExc_SystemError variable static PyTypeObject PyExc_SystemError -Objects/exceptions.c - _PyExc_SystemExit variable static PyTypeObject _PyExc_SystemExit -Objects/exceptions.c - PyExc_SystemExit variable static PyTypeObject PyExc_SystemExit -Objects/exceptions.c - _PyExc_TabError variable static PyTypeObject _PyExc_TabError -Objects/exceptions.c - PyExc_TabError variable static PyTypeObject PyExc_TabError -Objects/exceptions.c - _PyExc_TargetScopeError variable static PyTypeObject _PyExc_TargetScopeError -Objects/exceptions.c - PyExc_TargetScopeError variable static PyTypeObject PyExc_TargetScopeError -Objects/exceptions.c - _PyExc_TimeoutError variable static PyTypeObject _PyExc_TimeoutError -Objects/exceptions.c - PyExc_TimeoutError variable static PyTypeObject PyExc_TimeoutError -Objects/exceptions.c - _PyExc_TypeError variable static PyTypeObject _PyExc_TypeError -Objects/exceptions.c - PyExc_TypeError variable static PyTypeObject PyExc_TypeError -Objects/exceptions.c - _PyExc_UnboundLocalError variable static PyTypeObject _PyExc_UnboundLocalError -Objects/exceptions.c - PyExc_UnboundLocalError variable static PyTypeObject PyExc_UnboundLocalError -Objects/exceptions.c - _PyExc_UnicodeDecodeError variable static PyTypeObject _PyExc_UnicodeDecodeError -Objects/exceptions.c - PyExc_UnicodeDecodeError variable static PyTypeObject PyExc_UnicodeDecodeError -Objects/exceptions.c - _PyExc_UnicodeEncodeError variable static PyTypeObject _PyExc_UnicodeEncodeError -Objects/exceptions.c - PyExc_UnicodeEncodeError variable static PyTypeObject PyExc_UnicodeEncodeError -Objects/exceptions.c - _PyExc_UnicodeError variable static PyTypeObject _PyExc_UnicodeError -Objects/exceptions.c - PyExc_UnicodeError variable static PyTypeObject PyExc_UnicodeError -Objects/exceptions.c - _PyExc_UnicodeTranslateError variable static PyTypeObject _PyExc_UnicodeTranslateError -Objects/exceptions.c - PyExc_UnicodeTranslateError variable static PyTypeObject PyExc_UnicodeTranslateError -Objects/exceptions.c - _PyExc_UnicodeWarning variable static PyTypeObject _PyExc_UnicodeWarning -Objects/exceptions.c - PyExc_UnicodeWarning variable static PyTypeObject PyExc_UnicodeWarning -Objects/exceptions.c - _PyExc_UserWarning variable static PyTypeObject _PyExc_UserWarning -Objects/exceptions.c - PyExc_UserWarning variable static PyTypeObject PyExc_UserWarning -Objects/exceptions.c - _PyExc_ValueError variable static PyTypeObject _PyExc_ValueError -Objects/exceptions.c - PyExc_ValueError variable static PyTypeObject PyExc_ValueError -Objects/exceptions.c - _PyExc_Warning variable static PyTypeObject _PyExc_Warning -Objects/exceptions.c - PyExc_Warning variable static PyTypeObject PyExc_Warning -Objects/exceptions.c - _PyExc_ZeroDivisionError variable static PyTypeObject _PyExc_ZeroDivisionError -Objects/exceptions.c - PyExc_ZeroDivisionError variable static PyTypeObject PyExc_ZeroDivisionError -Objects/boolobject.c - _Py_FalseStruct variable static struct _longobject _Py_FalseStruct -Objects/stringlib/unicode_format.h - PyFieldNameIter_Type variable static PyTypeObject PyFieldNameIter_Type -Modules/_io/fileio.c - PyFileIO_Type variable PyTypeObject PyFileIO_Type -Python/preconfig.c - Py_FileSystemDefaultEncodeErrors variable const char *Py_FileSystemDefaultEncodeErrors -Python/preconfig.c - Py_FileSystemDefaultEncoding variable const char *Py_FileSystemDefaultEncoding -Python/bltinmodule.c - PyFilter_Type variable PyTypeObject PyFilter_Type -Objects/floatobject.c - PyFloat_Type variable PyTypeObject PyFloat_Type -Objects/stringlib/unicode_format.h - PyFormatterIter_Type variable static PyTypeObject PyFormatterIter_Type -Objects/frameobject.c - PyFrame_Type variable PyTypeObject PyFrame_Type -Python/initconfig.c - Py_FrozenFlag variable int Py_FrozenFlag -Objects/setobject.c - PyFrozenSet_Type variable PyTypeObject PyFrozenSet_Type -Objects/funcobject.c - PyFunction_Type variable PyTypeObject PyFunction_Type -Objects/genobject.c - PyGen_Type variable PyTypeObject PyGen_Type -Objects/descrobject.c - PyGetSetDescr_Type variable PyTypeObject PyGetSetDescr_Type -Python/hamt.c - _PyHamt_ArrayNode_Type variable PyTypeObject _PyHamt_ArrayNode_Type -Python/hamt.c - PyHamt_as_mapping variable static PyMappingMethods PyHamt_as_mapping -Python/hamt.c - PyHamt_as_sequence variable static PySequenceMethods PyHamt_as_sequence -Python/hamt.c - _PyHamt_BitmapNode_Type variable PyTypeObject _PyHamt_BitmapNode_Type -Python/hamt.c - _PyHamt_CollisionNode_Type variable PyTypeObject _PyHamt_CollisionNode_Type -Python/hamt.c - _PyHamtItems_Type variable PyTypeObject _PyHamtItems_Type -Python/hamt.c - PyHamtIterator_as_mapping variable static PyMappingMethods PyHamtIterator_as_mapping -Python/hamt.c - _PyHamtKeys_Type variable PyTypeObject _PyHamtKeys_Type -Python/hamt.c - PyHamt_methods variable static PyMethodDef PyHamt_methods -Python/hamt.c - _PyHamt_Type variable PyTypeObject _PyHamt_Type -Python/hamt.c - _PyHamtValues_Type variable PyTypeObject _PyHamtValues_Type -Python/preconfig.c - _Py_HasFileSystemDefaultEncodeErrors variable int _Py_HasFileSystemDefaultEncodeErrors -Python/preconfig.c - Py_HasFileSystemDefaultEncoding variable int Py_HasFileSystemDefaultEncoding -Python/pyhash.c - PyHash_Func variable static PyHash_FuncDef PyHash_Func -Python/initconfig.c - Py_HashRandomizationFlag variable int Py_HashRandomizationFlag -Include/pyhash.h - _Py_HashSecret variable PyAPI_DATA(_Py_HashSecret_t) _Py_HashSecret -Python/bootstrap_hash.c - _Py_HashSecret_Initialized variable static int _Py_HashSecret_Initialized -Python/codecs.c - Py_hexdigits variable const char *Py_hexdigits -Python/sysmodule.c - PyId__ variable _Py_IDENTIFIER(_) -Modules/_abc.c - PyId__abc_impl variable _Py_IDENTIFIER(_abc_impl) -Objects/typeobject.c - PyId___abstractmethods__ variable _Py_IDENTIFIER(__abstractmethods__) -Modules/_abc.c - PyId___abstractmethods__ variable _Py_IDENTIFIER(__abstractmethods__) -Python/ceval.c _PyEval_EvalFrameDefault PyId___aenter__ variable _Py_IDENTIFIER(__aenter__) -Python/ceval.c _PyEval_EvalFrameDefault PyId___aexit__ variable _Py_IDENTIFIER(__aexit__) -Objects/typeobject.c slot_am_aiter PyId___aiter__ variable _Py_IDENTIFIER(__aiter__) -Python/ceval.c import_all_from PyId___all__ variable _Py_IDENTIFIER(__all__) -Objects/typeobject.c slot_am_anext PyId___anext__ variable _Py_IDENTIFIER(__anext__) -Python/Python-ast.c - PyId_annotation variable _Py_IDENTIFIER(annotation) -Python/ceval.c _PyEval_EvalFrameDefault PyId___annotations__ variable _Py_IDENTIFIER(__annotations__) -Python/Python-ast.c - PyId_arg variable _Py_IDENTIFIER(arg) -Python/Python-ast.c - PyId_args variable _Py_IDENTIFIER(args) -Python/Python-ast.c - PyId_argtypes variable _Py_IDENTIFIER(argtypes) -Python/Python-ast.c - PyId_asname variable _Py_IDENTIFIER(asname) -Python/Python-ast.c make_type PyId__ast variable _Py_IDENTIFIER(_ast) -Python/Python-ast.c - PyId_attr variable _Py_IDENTIFIER(attr) -Python/Python-ast.c - PyId__attributes variable _Py_IDENTIFIER(_attributes) -Objects/typeobject.c slot_am_await PyId___await__ variable _Py_IDENTIFIER(__await__) -Python/Python-ast.c - PyId_bases variable _Py_IDENTIFIER(bases) -Modules/_abc.c - PyId___bases__ variable _Py_IDENTIFIER(__bases__) -Objects/abstract.c abstract_get_bases PyId___bases__ variable _Py_IDENTIFIER(__bases__) -Objects/typeobject.c merge_class_dict PyId___bases__ variable _Py_IDENTIFIER(__bases__) -Objects/longobject.c - PyId_big variable _Py_IDENTIFIER(big) -Modules/_io/_iomodule.c - PyId__blksize variable _Py_IDENTIFIER(_blksize) -Python/Python-ast.c - PyId_body variable _Py_IDENTIFIER(body) -Objects/typeobject.c slot_nb_bool PyId___bool__ variable _Py_IDENTIFIER(__bool__) -Python/sysmodule.c - PyId_buffer variable _Py_IDENTIFIER(buffer) -Python/ceval.c _PyEval_EvalFrameDefault PyId___build_class__ variable _Py_IDENTIFIER(__build_class__) -Objects/typeobject.c - PyId_builtins variable _Py_IDENTIFIER(builtins) -Python/errors.c - PyId_builtins variable _Py_IDENTIFIER(builtins) -Python/pythonrun.c - PyId_builtins variable _Py_IDENTIFIER(builtins) -Python/sysmodule.c - PyId_builtins variable _Py_IDENTIFIER(builtins) -Objects/frameobject.c - PyId___builtins__ variable _Py_IDENTIFIER(__builtins__) -Python/bltinmodule.c - PyId___builtins__ variable _Py_IDENTIFIER(__builtins__) -Python/import.c module_dict_for_exec PyId___builtins__ variable _Py_IDENTIFIER(__builtins__) -Objects/object.c - PyId___bytes__ variable _Py_IDENTIFIER(__bytes__) -Objects/bytesobject.c format_obj PyId___bytes__ variable _Py_IDENTIFIER(__bytes__) -Objects/bytesobject.c bytes_new PyId___bytes__ variable _Py_IDENTIFIER(__bytes__) -Objects/weakrefobject.c proxy_bytes PyId___bytes__ variable _Py_IDENTIFIER(__bytes__) -Objects/typeobject.c slot_tp_call PyId___call__ variable _Py_IDENTIFIER(__call__) -Python/Python-ast.c - PyId_cause variable _Py_IDENTIFIER(cause) -Objects/typeobject.c - PyId___class__ variable _Py_IDENTIFIER(__class__) -Modules/_abc.c - PyId___class__ variable _Py_IDENTIFIER(__class__) -Python/compile.c - PyId___class__ variable _Py_IDENTIFIER(__class__) -Objects/abstract.c recursive_isinstance PyId___class__ variable _Py_IDENTIFIER(__class__) -Objects/typeobject.c type_new PyId___classcell__ variable _Py_IDENTIFIER(__classcell__) -Objects/typeobject.c - PyId___class_getitem__ variable _Py_IDENTIFIER(__class_getitem__) -Objects/abstract.c PyObject_GetItem PyId___class_getitem__ variable _Py_IDENTIFIER(__class_getitem__) -Python/import.c PyImport_Cleanup PyId_clear variable _Py_IDENTIFIER(clear) -Python/traceback.c - PyId_close variable _Py_IDENTIFIER(close) -Modules/_io/bufferedio.c - PyId_close variable _Py_IDENTIFIER(close) -Modules/_io/textio.c - PyId_close variable _Py_IDENTIFIER(close) -Objects/genobject.c gen_close_iter PyId_close variable _Py_IDENTIFIER(close) -Modules/_dbmmodule.c dbm__exit__ PyId_close variable _Py_IDENTIFIER(close) -Modules/_gdbmmodule.c dbm__exit__ PyId_close variable _Py_IDENTIFIER(close) -Python/pythonrun.c _Py_HandleSystemExit PyId_code variable _Py_IDENTIFIER(code) -Python/Python-ast.c - PyId_col_offset variable _Py_IDENTIFIER(col_offset) -Python/Python-ast.c - PyId_comparators variable _Py_IDENTIFIER(comparators) -Objects/complexobject.c try_complex_special_method PyId___complex__ variable _Py_IDENTIFIER(__complex__) -Objects/typeobject.c slot_sq_contains PyId___contains__ variable _Py_IDENTIFIER(__contains__) -Python/Python-ast.c - PyId_context_expr variable _Py_IDENTIFIER(context_expr) -Python/Python-ast.c - PyId_conversion variable _Py_IDENTIFIER(conversion) -Modules/itertoolsmodule.c - PyId___copy__ variable _Py_IDENTIFIER(__copy__) -Objects/descrobject.c mappingproxy_copy PyId_copy variable _Py_IDENTIFIER(copy) -Objects/typeobject.c import_copyreg PyId_copyreg variable _Py_IDENTIFIER(copyreg) -Python/Python-ast.c - PyId_ctx variable _Py_IDENTIFIER(ctx) -Modules/_io/bufferedio.c - PyId__dealloc_warn variable _Py_IDENTIFIER(_dealloc_warn) -Modules/_io/textio.c - PyId__dealloc_warn variable _Py_IDENTIFIER(_dealloc_warn) -Modules/_io/textio.c - PyId_decode variable _Py_IDENTIFIER(decode) -Python/Python-ast.c - PyId_decorator_list variable _Py_IDENTIFIER(decorator_list) -Python/_warnings.c get_default_action PyId_defaultaction variable _Py_IDENTIFIER(defaultaction) -Python/Python-ast.c - PyId_defaults variable _Py_IDENTIFIER(defaults) -Objects/typeobject.c slot_tp_finalize PyId___del__ variable _Py_IDENTIFIER(__del__) -Objects/typeobject.c slot_tp_setattro PyId___delattr__ variable _Py_IDENTIFIER(__delattr__) -Objects/typeobject.c slot_tp_descr_set PyId___delete__ variable _Py_IDENTIFIER(__delete__) -Objects/typeobject.c - PyId___delitem__ variable _Py_IDENTIFIER(__delitem__) -Objects/typeobject.c - PyId___dict__ variable _Py_IDENTIFIER(__dict__) -Modules/_abc.c - PyId___dict__ variable _Py_IDENTIFIER(__dict__) -Python/bltinmodule.c - PyId___dict__ variable _Py_IDENTIFIER(__dict__) -Python/Python-ast.c ast_type_reduce PyId___dict__ variable _Py_IDENTIFIER(__dict__) -Python/ceval.c import_all_from PyId___dict__ variable _Py_IDENTIFIER(__dict__) -Objects/bytearrayobject.c _common_reduce PyId___dict__ variable _Py_IDENTIFIER(__dict__) -Objects/moduleobject.c module_dir PyId___dict__ variable _Py_IDENTIFIER(__dict__) -Objects/odictobject.c odict_reduce PyId___dict__ variable _Py_IDENTIFIER(__dict__) -Objects/setobject.c set_reduce PyId___dict__ variable _Py_IDENTIFIER(__dict__) -Modules/_collectionsmodule.c deque_reduce PyId___dict__ variable _Py_IDENTIFIER(__dict__) -Objects/dictobject.c dictviews_sub PyId_difference_update variable _Py_IDENTIFIER(difference_update) -Python/Python-ast.c - PyId_dims variable _Py_IDENTIFIER(dims) -Objects/object.c - PyId___dir__ variable _Py_IDENTIFIER(__dir__) -Objects/moduleobject.c module_dir PyId___dir__ variable _Py_IDENTIFIER(__dir__) -Python/ceval.c _PyEval_EvalFrameDefault PyId_displayhook variable _Py_IDENTIFIER(displayhook) -Objects/typeobject.c - PyId___doc__ variable _Py_IDENTIFIER(__doc__) -Objects/descrobject.c - PyId___doc__ variable _Py_IDENTIFIER(__doc__) -Objects/moduleobject.c - PyId___doc__ variable _Py_IDENTIFIER(__doc__) -Objects/moduleobject.c PyModule_SetDocString PyId___doc__ variable _Py_IDENTIFIER(__doc__) -Python/Python-ast.c - PyId_elt variable _Py_IDENTIFIER(elt) -Python/Python-ast.c - PyId_elts variable _Py_IDENTIFIER(elts) -Modules/faulthandler.c - PyId_enable variable _Py_IDENTIFIER(enable) -Python/sysmodule.c - PyId_encoding variable _Py_IDENTIFIER(encoding) -Python/bltinmodule.c - PyId_encoding variable _Py_IDENTIFIER(encoding) -Python/pythonrun.c - PyId_encoding variable _Py_IDENTIFIER(encoding) -Python/Python-ast.c - PyId_end_col_offset variable _Py_IDENTIFIER(end_col_offset) -Python/Python-ast.c - PyId_end_lineno variable _Py_IDENTIFIER(end_lineno) -Python/ceval.c _PyEval_EvalFrameDefault PyId___enter__ variable _Py_IDENTIFIER(__enter__) -Objects/typeobject.c overrides_hash PyId___eq__ variable _Py_IDENTIFIER(__eq__) -Python/bltinmodule.c - PyId_errors variable _Py_IDENTIFIER(errors) -Python/Python-ast.c - PyId_exc variable _Py_IDENTIFIER(exc) -Python/pythonrun.c - PyId_excepthook variable _Py_IDENTIFIER(excepthook) -Python/ceval.c _PyEval_EvalFrameDefault PyId___exit__ variable _Py_IDENTIFIER(__exit__) -Modules/_pickle.c do_append PyId_extend variable _Py_IDENTIFIER(extend) -Python/Python-ast.c - PyId__fields variable _Py_IDENTIFIER(_fields) -Objects/moduleobject.c PyModule_GetFilenameObject PyId___file__ variable _Py_IDENTIFIER(__file__) -Python/errors.c PyErr_SyntaxLocationObject PyId_filename variable _Py_IDENTIFIER(filename) -Python/pythonrun.c - PyId_filename variable _Py_IDENTIFIER(filename) -Modules/_io/textio.c - PyId_fileno variable _Py_IDENTIFIER(fileno) -Modules/faulthandler.c - PyId_fileno variable _Py_IDENTIFIER(fileno) -Python/bltinmodule.c - PyId_fileno variable _Py_IDENTIFIER(fileno) -Objects/fileobject.c PyObject_AsFileDescriptor PyId_fileno variable _Py_IDENTIFIER(fileno) -Modules/itertoolsmodule.c zip_longest_new PyId_fillvalue variable _Py_IDENTIFIER(fillvalue) -Python/_warnings.c - PyId_filters variable _Py_IDENTIFIER(filters) -Python/Python-ast.c - PyId_finalbody variable _Py_IDENTIFIER(finalbody) -Modules/_io/iobase.c iobase_finalize PyId__finalizing variable _Py_IDENTIFIER(_finalizing) -Python/import.c import_find_and_load PyId__find_and_load variable _Py_IDENTIFIER(_find_and_load) -Python/import.c - PyId__fix_up_module variable _Py_IDENTIFIER(_fix_up_module) -Python/errors.c - PyId_flush variable _Py_IDENTIFIER(flush) -Python/pylifecycle.c - PyId_flush variable _Py_IDENTIFIER(flush) -Python/pythonrun.c - PyId_flush variable _Py_IDENTIFIER(flush) -Modules/_threadmodule.c - PyId_flush variable _Py_IDENTIFIER(flush) -Modules/_io/bufferedio.c - PyId_flush variable _Py_IDENTIFIER(flush) -Modules/_io/textio.c - PyId_flush variable _Py_IDENTIFIER(flush) -Modules/faulthandler.c - PyId_flush variable _Py_IDENTIFIER(flush) -Python/bltinmodule.c - PyId_flush variable _Py_IDENTIFIER(flush) -Objects/abstract.c PyObject_Format PyId___format__ variable _Py_IDENTIFIER(__format__) -Python/Python-ast.c - PyId_format_spec variable _Py_IDENTIFIER(format_spec) -Modules/posixmodule.c path_converter PyId___fspath__ variable _Py_IDENTIFIER(__fspath__) -Modules/posixmodule.c PyOS_FSPath PyId___fspath__ variable _Py_IDENTIFIER(__fspath__) -Python/Python-ast.c - PyId_func variable _Py_IDENTIFIER(func) -Python/Python-ast.c - PyId_generators variable _Py_IDENTIFIER(generators) -Objects/descrobject.c mappingproxy_get PyId_get variable _Py_IDENTIFIER(get) -Modules/_collectionsmodule.c _count_elements PyId_get variable _Py_IDENTIFIER(get) -Objects/typeobject.c slot_tp_descr_get PyId___get__ variable _Py_IDENTIFIER(__get__) -Objects/classobject.c method_reduce PyId_getattr variable _Py_IDENTIFIER(getattr) -Objects/descrobject.c descr_reduce PyId_getattr variable _Py_IDENTIFIER(getattr) -Objects/descrobject.c wrapper_reduce PyId_getattr variable _Py_IDENTIFIER(getattr) -Objects/moduleobject.c module_getattro PyId___getattr__ variable _Py_IDENTIFIER(__getattr__) -Objects/methodobject.c meth_reduce PyId_getattr variable _Py_IDENTIFIER(getattr) -Objects/typeobject.c slot_tp_getattr_hook PyId___getattr__ variable _Py_IDENTIFIER(__getattr__) -Objects/typeobject.c - PyId___getattribute__ variable _Py_IDENTIFIER(__getattribute__) -Objects/typeobject.c - PyId___getitem__ variable _Py_IDENTIFIER(__getitem__) -Objects/typeobject.c _PyObject_GetNewArguments PyId___getnewargs__ variable _Py_IDENTIFIER(__getnewargs__) -Objects/typeobject.c _PyObject_GetNewArguments PyId___getnewargs_ex__ variable _Py_IDENTIFIER(__getnewargs_ex__) -Modules/_io/textio.c - PyId_getpreferredencoding variable _Py_IDENTIFIER(getpreferredencoding) -Python/_warnings.c get_source_line PyId_get_source variable _Py_IDENTIFIER(get_source) -Python/import.c - PyId__get_sourcefile variable _Py_IDENTIFIER(_get_sourcefile) -Objects/typeobject.c _PyObject_GetState PyId___getstate__ variable _Py_IDENTIFIER(__getstate__) -Python/import.c - PyId__handle_fromlist variable _Py_IDENTIFIER(_handle_fromlist) -Python/Python-ast.c - PyId_handlers variable _Py_IDENTIFIER(handlers) -Objects/typeobject.c - PyId___hash__ variable _Py_IDENTIFIER(__hash__) -Python/Python-ast.c - PyId_id variable _Py_IDENTIFIER(id) -Python/Python-ast.c - PyId_ifs variable _Py_IDENTIFIER(ifs) -Python/import.c PyImport_ReloadModule PyId_imp variable _Py_IDENTIFIER(imp) -Python/ceval.c - PyId___import__ variable _Py_IDENTIFIER(__import__) -Objects/typeobject.c slot_nb_index PyId___index__ variable _Py_IDENTIFIER(__index__) -Objects/typeobject.c slot_tp_init PyId___init__ variable _Py_IDENTIFIER(__init__) -Objects/moduleobject.c _PyModuleSpec_IsInitializing PyId__initializing variable _Py_IDENTIFIER(_initializing) -Objects/typeobject.c - PyId___init_subclass__ variable _Py_IDENTIFIER(__init_subclass__) -Objects/abstract.c PyObject_IsInstance PyId___instancecheck__ variable _Py_IDENTIFIER(__instancecheck__) -Objects/dictobject.c _PyDictView_Intersect PyId_intersection_update variable _Py_IDENTIFIER(intersection_update) -Modules/_io/iobase.c - PyId___IOBase_closed variable _Py_IDENTIFIER(__IOBase_closed) -Objects/typeobject.c slot_nb_inplace_power PyId___ipow__ variable _Py_IDENTIFIER(__ipow__) -Objects/object.c - PyId___isabstractmethod__ variable _Py_IDENTIFIER(__isabstractmethod__) -Python/Python-ast.c - PyId_is_async variable _Py_IDENTIFIER(is_async) -Modules/_io/bufferedio.c - PyId_isatty variable _Py_IDENTIFIER(isatty) -Modules/_io/textio.c - PyId_isatty variable _Py_IDENTIFIER(isatty) -Python/pylifecycle.c - PyId_isatty variable _Py_IDENTIFIER(isatty) -Modules/_io/_iomodule.c - PyId_isatty variable _Py_IDENTIFIER(isatty) -Python/codecs.c - PyId__is_text_encoding variable _Py_IDENTIFIER(_is_text_encoding) -Python/Python-ast.c - PyId_items variable _Py_IDENTIFIER(items) -Objects/abstract.c PyMapping_Items PyId_items variable _Py_IDENTIFIER(items) -Objects/descrobject.c mappingproxy_items PyId_items variable _Py_IDENTIFIER(items) -Objects/odictobject.c odict_reduce PyId_items variable _Py_IDENTIFIER(items) -Objects/odictobject.c odict_repr PyId_items variable _Py_IDENTIFIER(items) -Objects/odictobject.c mutablemapping_update PyId_items variable _Py_IDENTIFIER(items) -Objects/typeobject.c - PyId_items variable _Py_IDENTIFIER(items) -Modules/_collectionsmodule.c defdict_reduce PyId_items variable _Py_IDENTIFIER(items) -Python/Python-ast.c - PyId_iter variable _Py_IDENTIFIER(iter) -Objects/bytearrayobject.c bytearrayiter_reduce PyId_iter variable _Py_IDENTIFIER(iter) -Objects/bytesobject.c striter_reduce PyId_iter variable _Py_IDENTIFIER(iter) -Objects/dictobject.c dictiter_reduce PyId_iter variable _Py_IDENTIFIER(iter) -Objects/iterobject.c iter_reduce PyId_iter variable _Py_IDENTIFIER(iter) -Objects/iterobject.c calliter_reduce PyId_iter variable _Py_IDENTIFIER(iter) -Objects/listobject.c listiter_reduce_general PyId_iter variable _Py_IDENTIFIER(iter) -Objects/odictobject.c odictiter_reduce PyId_iter variable _Py_IDENTIFIER(iter) -Objects/rangeobject.c rangeiter_reduce PyId_iter variable _Py_IDENTIFIER(iter) -Objects/rangeobject.c longrangeiter_reduce PyId_iter variable _Py_IDENTIFIER(iter) -Objects/setobject.c setiter_reduce PyId_iter variable _Py_IDENTIFIER(iter) -Objects/tupleobject.c tupleiter_reduce PyId_iter variable _Py_IDENTIFIER(iter) -Objects/unicodeobject.c unicodeiter_reduce PyId_iter variable _Py_IDENTIFIER(iter) -Objects/typeobject.c slot_tp_iter PyId___iter__ variable _Py_IDENTIFIER(__iter__) -Modules/arraymodule.c - PyId_iter variable _Py_IDENTIFIER(iter) -Python/Python-ast.c - PyId_key variable _Py_IDENTIFIER(key) -Python/Python-ast.c - PyId_keys variable _Py_IDENTIFIER(keys) -Objects/abstract.c PyMapping_Keys PyId_keys variable _Py_IDENTIFIER(keys) -Objects/descrobject.c mappingproxy_keys PyId_keys variable _Py_IDENTIFIER(keys) -Objects/dictobject.c - PyId_keys variable _Py_IDENTIFIER(keys) -Objects/odictobject.c mutablemapping_update PyId_keys variable _Py_IDENTIFIER(keys) -Python/Python-ast.c - PyId_keywords variable _Py_IDENTIFIER(keywords) -Python/Python-ast.c - PyId_kind variable _Py_IDENTIFIER(kind) -Python/Python-ast.c - PyId_kwarg variable _Py_IDENTIFIER(kwarg) -Python/Python-ast.c - PyId_kw_defaults variable _Py_IDENTIFIER(kw_defaults) -Python/Python-ast.c - PyId_kwonlyargs variable _Py_IDENTIFIER(kwonlyargs) -Python/pythonrun.c - PyId_last_traceback variable _Py_IDENTIFIER(last_traceback) -Python/pythonrun.c - PyId_last_type variable _Py_IDENTIFIER(last_type) -Python/pythonrun.c - PyId_last_value variable _Py_IDENTIFIER(last_value) -Python/Python-ast.c - PyId_left variable _Py_IDENTIFIER(left) -Objects/typeobject.c - PyId___len__ variable _Py_IDENTIFIER(__len__) -Objects/abstract.c PyObject_LengthHint PyId___length_hint__ variable _Py_IDENTIFIER(__length_hint__) -Python/Python-ast.c - PyId_level variable _Py_IDENTIFIER(level) -Python/Python-ast.c - PyId_lineno variable _Py_IDENTIFIER(lineno) -Python/errors.c PyErr_SyntaxLocationObject PyId_lineno variable _Py_IDENTIFIER(lineno) -Python/pythonrun.c - PyId_lineno variable _Py_IDENTIFIER(lineno) -Objects/longobject.c - PyId_little variable _Py_IDENTIFIER(little) -Python/_warnings.c get_source_line PyId___loader__ variable _Py_IDENTIFIER(__loader__) -Objects/moduleobject.c - PyId___loader__ variable _Py_IDENTIFIER(__loader__) -Python/import.c - PyId__lock_unlock_module variable _Py_IDENTIFIER(_lock_unlock_module) -Python/Python-ast.c - PyId_lower variable _Py_IDENTIFIER(lower) -Python/ceval.c _PyEval_EvalFrameDefault PyId___ltrace__ variable _Py_IDENTIFIER(__ltrace__) -Python/pythonrun.c - PyId___main__ variable _Py_IDENTIFIER(__main__) -Python/_warnings.c check_matched PyId_match variable _Py_IDENTIFIER(match) -Python/bltinmodule.c - PyId_metaclass variable _Py_IDENTIFIER(metaclass) -Objects/dictobject.c dict_subscript PyId___missing__ variable _Py_IDENTIFIER(__missing__) -Modules/_io/bufferedio.c - PyId_mode variable _Py_IDENTIFIER(mode) -Modules/_io/textio.c - PyId_mode variable _Py_IDENTIFIER(mode) -Python/pylifecycle.c - PyId_mode variable _Py_IDENTIFIER(mode) -Modules/_io/_iomodule.c - PyId_mode variable _Py_IDENTIFIER(mode) -Python/Python-ast.c - PyId_module variable _Py_IDENTIFIER(module) -Objects/typeobject.c - PyId___module__ variable _Py_IDENTIFIER(__module__) -Python/Python-ast.c make_type PyId___module__ variable _Py_IDENTIFIER(__module__) -Python/errors.c PyErr_NewException PyId___module__ variable _Py_IDENTIFIER(__module__) -Python/errors.c - PyId___module__ variable _Py_IDENTIFIER(__module__) -Python/pythonrun.c print_exception PyId___module__ variable _Py_IDENTIFIER(__module__) -Objects/typeobject.c - PyId_mro variable _Py_IDENTIFIER(mro) -Objects/typeobject.c mro_invoke PyId_mro variable _Py_IDENTIFIER(mro) -Python/bltinmodule.c - PyId___mro_entries__ variable _Py_IDENTIFIER(__mro_entries__) -Objects/typeobject.c type_new PyId___mro_entries__ variable _Py_IDENTIFIER(__mro_entries__) -Python/Python-ast.c - PyId_msg variable _Py_IDENTIFIER(msg) -Python/errors.c PyErr_SyntaxLocationObject PyId_msg variable _Py_IDENTIFIER(msg) -Python/pythonrun.c - PyId_msg variable _Py_IDENTIFIER(msg) -Python/pylifecycle.c - PyId_name variable _Py_IDENTIFIER(name) -Modules/_io/fileio.c - PyId_name variable _Py_IDENTIFIER(name) -Modules/_io/bufferedio.c - PyId_name variable _Py_IDENTIFIER(name) -Modules/_io/textio.c - PyId_name variable _Py_IDENTIFIER(name) -Python/Python-ast.c - PyId_name variable _Py_IDENTIFIER(name) -Objects/typeobject.c - PyId___name__ variable _Py_IDENTIFIER(__name__) -Objects/classobject.c - PyId___name__ variable _Py_IDENTIFIER(__name__) -Python/_warnings.c - PyId___name__ variable _Py_IDENTIFIER(__name__) -Python/_warnings.c get_source_line PyId___name__ variable _Py_IDENTIFIER(__name__) -Python/ceval.c import_from PyId___name__ variable _Py_IDENTIFIER(__name__) -Python/ceval.c import_all_from PyId___name__ variable _Py_IDENTIFIER(__name__) -Python/import.c resolve_name PyId___name__ variable _Py_IDENTIFIER(__name__) -Objects/moduleobject.c - PyId___name__ variable _Py_IDENTIFIER(__name__) -Objects/moduleobject.c PyModule_GetNameObject PyId___name__ variable _Py_IDENTIFIER(__name__) -Objects/exceptions.c ImportError_getstate PyId_name variable _Py_IDENTIFIER(name) -Objects/moduleobject.c module_getattro PyId___name__ variable _Py_IDENTIFIER(__name__) -Objects/weakrefobject.c weakref_repr PyId___name__ variable _Py_IDENTIFIER(__name__) -Modules/_pickle.c save_global PyId___name__ variable _Py_IDENTIFIER(__name__) -Python/Python-ast.c - PyId_names variable _Py_IDENTIFIER(names) -Objects/typeobject.c - PyId___new__ variable _Py_IDENTIFIER(__new__) -Objects/typeobject.c reduce_newobj PyId___newobj__ variable _Py_IDENTIFIER(__newobj__) -Objects/typeobject.c reduce_newobj PyId___newobj_ex__ variable _Py_IDENTIFIER(__newobj_ex__) -Objects/typeobject.c slot_tp_iternext PyId___next__ variable _Py_IDENTIFIER(__next__) -Objects/structseq.c - PyId_n_fields variable _Py_IDENTIFIER(n_fields) -Python/ast.c new_identifier PyId_NFKC variable _Py_IDENTIFIER(NFKC) -Objects/structseq.c - PyId_n_sequence_fields variable _Py_IDENTIFIER(n_sequence_fields) -Objects/structseq.c - PyId_n_unnamed_fields variable _Py_IDENTIFIER(n_unnamed_fields) -Python/errors.c PyErr_SyntaxLocationObject PyId_offset variable _Py_IDENTIFIER(offset) -Python/pythonrun.c - PyId_offset variable _Py_IDENTIFIER(offset) -Python/_warnings.c get_once_registry PyId_onceregistry variable _Py_IDENTIFIER(onceregistry) -Python/Python-ast.c - PyId_op variable _Py_IDENTIFIER(op) -Python/traceback.c - PyId_open variable _Py_IDENTIFIER(open) -Python/pylifecycle.c - PyId_open variable _Py_IDENTIFIER(open) -Parser/tokenizer.c fp_setreadl PyId_open variable _Py_IDENTIFIER(open) -Objects/fileobject.c - PyId_open variable _Py_IDENTIFIER(open) -Objects/fileobject.c PyFile_OpenCodeObject PyId_open variable _Py_IDENTIFIER(open) -Python/Python-ast.c - PyId_operand variable _Py_IDENTIFIER(operand) -Python/Python-ast.c - PyId_ops variable _Py_IDENTIFIER(ops) -Python/Python-ast.c - PyId_optional_vars variable _Py_IDENTIFIER(optional_vars) -Python/Python-ast.c - PyId_orelse variable _Py_IDENTIFIER(orelse) -Python/import.c resolve_name PyId___package__ variable _Py_IDENTIFIER(__package__) -Objects/moduleobject.c - PyId___package__ variable _Py_IDENTIFIER(__package__) -Python/import.c resolve_name PyId_parent variable _Py_IDENTIFIER(parent) -Modules/_operator.c methodcaller_reduce PyId_partial variable _Py_IDENTIFIER(partial) -Python/sysmodule.c - PyId_path variable _Py_IDENTIFIER(path) -Python/traceback.c - PyId_path variable _Py_IDENTIFIER(path) -Objects/exceptions.c ImportError_getstate PyId_path variable _Py_IDENTIFIER(path) -Modules/main.c pymain_sys_path_add_path0 PyId_path variable _Py_IDENTIFIER(path) -Python/import.c resolve_name PyId___path__ variable _Py_IDENTIFIER(__path__) -Python/import.c - PyId___path__ variable _Py_IDENTIFIER(__path__) -Modules/_io/bufferedio.c - PyId_peek variable _Py_IDENTIFIER(peek) -Python/Python-ast.c - PyId_posonlyargs variable _Py_IDENTIFIER(posonlyargs) -Objects/typeobject.c slot_nb_power PyId___pow__ variable _Py_IDENTIFIER(__pow__) -Python/bltinmodule.c - PyId___prepare__ variable _Py_IDENTIFIER(__prepare__) -Python/errors.c PyErr_SyntaxLocationObject PyId_print_file_and_line variable _Py_IDENTIFIER(print_file_and_line) -Python/pythonrun.c print_exception PyId_print_file_and_line variable _Py_IDENTIFIER(print_file_and_line) -Python/pythonrun.c - PyId_ps1 variable _Py_IDENTIFIER(ps1) -Python/pythonrun.c - PyId_ps2 variable _Py_IDENTIFIER(ps2) -Objects/object.c - PyId_Py_Repr variable _Py_IDENTIFIER(Py_Repr) -Objects/classobject.c - PyId___qualname__ variable _Py_IDENTIFIER(__qualname__) -Objects/descrobject.c calculate_qualname PyId___qualname__ variable _Py_IDENTIFIER(__qualname__) -Objects/methodobject.c meth_get__qualname__ PyId___qualname__ variable _Py_IDENTIFIER(__qualname__) -Objects/typeobject.c type_new PyId___qualname__ variable _Py_IDENTIFIER(__qualname__) -Modules/_io/textio.c - PyId_raw variable _Py_IDENTIFIER(raw) -Python/pylifecycle.c - PyId_raw variable _Py_IDENTIFIER(raw) -Modules/_io/iobase.c - PyId_read variable _Py_IDENTIFIER(read) -Modules/_io/bufferedio.c - PyId_read variable _Py_IDENTIFIER(read) -Modules/_io/textio.c - PyId_read variable _Py_IDENTIFIER(read) -Modules/_io/bufferedio.c - PyId_read1 variable _Py_IDENTIFIER(read1) -Python/marshal.c - PyId_read variable _Py_IDENTIFIER(read) -Modules/_io/bufferedio.c - PyId_readable variable _Py_IDENTIFIER(readable) -Modules/_io/textio.c - PyId_readable variable _Py_IDENTIFIER(readable) -Modules/_io/iobase.c - PyId_readall variable _Py_IDENTIFIER(readall) -Modules/_io/bufferedio.c - PyId_readinto variable _Py_IDENTIFIER(readinto) -Modules/_io/bufferedio.c - PyId_readinto1 variable _Py_IDENTIFIER(readinto1) -Python/marshal.c r_string PyId_readinto variable _Py_IDENTIFIER(readinto) -Parser/tokenizer.c fp_setreadl PyId_readline variable _Py_IDENTIFIER(readline) -Objects/fileobject.c PyFile_GetLine PyId_readline variable _Py_IDENTIFIER(readline) -Objects/typeobject.c - PyId___reduce__ variable _Py_IDENTIFIER(__reduce__) -Python/import.c PyImport_ReloadModule PyId_reload variable _Py_IDENTIFIER(reload) -Modules/_io/textio.c - PyId_replace variable _Py_IDENTIFIER(replace) -Python/importdl.c - PyId_replace variable _Py_IDENTIFIER(replace) -Objects/typeobject.c slot_tp_repr PyId___repr__ variable _Py_IDENTIFIER(__repr__) -Modules/_io/textio.c - PyId_reset variable _Py_IDENTIFIER(reset) -Python/Python-ast.c - PyId_returns variable _Py_IDENTIFIER(returns) -Objects/enumobject.c - PyId___reversed__ variable _Py_IDENTIFIER(__reversed__) -Objects/listobject.c listiter_reduce_general PyId_reversed variable _Py_IDENTIFIER(reversed) -Python/Python-ast.c - PyId_right variable _Py_IDENTIFIER(right) -Python/bltinmodule.c - PyId___round__ variable _Py_IDENTIFIER(__round__) -Modules/_io/textio.c - PyId_seek variable _Py_IDENTIFIER(seek) -Modules/_io/iobase.c - PyId_seek variable _Py_IDENTIFIER(seek) -Modules/_io/textio.c - PyId_seekable variable _Py_IDENTIFIER(seekable) -Python/ceval.c _PyEval_EvalFrameDefault PyId_send variable _Py_IDENTIFIER(send) -Objects/typeobject.c slot_tp_descr_set PyId___set__ variable _Py_IDENTIFIER(__set__) -Objects/typeobject.c slot_tp_setattro PyId___setattr__ variable _Py_IDENTIFIER(__setattr__) -Objects/typeobject.c - PyId___setitem__ variable _Py_IDENTIFIER(__setitem__) -Modules/_collectionsmodule.c _count_elements PyId___setitem__ variable _Py_IDENTIFIER(__setitem__) -Objects/typeobject.c - PyId___set_name__ variable _Py_IDENTIFIER(__set_name__) -Modules/_io/textio.c - PyId_setstate variable _Py_IDENTIFIER(setstate) -Modules/_pickle.c load_build PyId___setstate__ variable _Py_IDENTIFIER(__setstate__) -Python/_warnings.c - PyId__showwarnmsg variable _Py_IDENTIFIER(_showwarnmsg) -Python/pylifecycle.c wait_for_thread_shutdown PyId__shutdown variable _Py_IDENTIFIER(_shutdown) -Python/Python-ast.c - PyId_simple variable _Py_IDENTIFIER(simple) -Python/sysmodule.c - PyId___sizeof__ variable _Py_IDENTIFIER(__sizeof__) -Python/Python-ast.c - PyId_slice variable _Py_IDENTIFIER(slice) -Objects/typeobject.c _PyType_GetSlotNames PyId___slotnames__ variable _Py_IDENTIFIER(__slotnames__) -Objects/typeobject.c _PyType_GetSlotNames PyId__slotnames variable _Py_IDENTIFIER(_slotnames) -Objects/typeobject.c type_new PyId___slots__ variable _Py_IDENTIFIER(__slots__) -Python/bltinmodule.c - PyId_sort variable _Py_IDENTIFIER(sort) -Python/import.c resolve_name PyId___spec__ variable _Py_IDENTIFIER(__spec__) -Python/import.c - PyId___spec__ variable _Py_IDENTIFIER(__spec__) -Objects/moduleobject.c - PyId___spec__ variable _Py_IDENTIFIER(__spec__) -Objects/moduleobject.c module_getattro PyId___spec__ variable _Py_IDENTIFIER(__spec__) -Python/_warnings.c - PyId_stderr variable _Py_IDENTIFIER(stderr) -Python/errors.c - PyId_stderr variable _Py_IDENTIFIER(stderr) -Python/pylifecycle.c - PyId_stderr variable _Py_IDENTIFIER(stderr) -Python/pythonrun.c - PyId_stderr variable _Py_IDENTIFIER(stderr) -Python/sysmodule.c - PyId_stderr variable _Py_IDENTIFIER(stderr) -Modules/_threadmodule.c - PyId_stderr variable _Py_IDENTIFIER(stderr) -Modules/faulthandler.c - PyId_stderr variable _Py_IDENTIFIER(stderr) -Python/bltinmodule.c - PyId_stderr variable _Py_IDENTIFIER(stderr) -Python/pylifecycle.c - PyId_stdin variable _Py_IDENTIFIER(stdin) -Python/pythonrun.c - PyId_stdin variable _Py_IDENTIFIER(stdin) -Python/bltinmodule.c - PyId_stdin variable _Py_IDENTIFIER(stdin) -Python/pylifecycle.c - PyId_stdout variable _Py_IDENTIFIER(stdout) -Python/pythonrun.c - PyId_stdout variable _Py_IDENTIFIER(stdout) -Python/sysmodule.c - PyId_stdout variable _Py_IDENTIFIER(stdout) -Python/bltinmodule.c - PyId_stdout variable _Py_IDENTIFIER(stdout) -Python/Python-ast.c - PyId_step variable _Py_IDENTIFIER(step) -Modules/posixmodule.c DirEntry_test_mode PyId_st_mode variable _Py_IDENTIFIER(st_mode) -Modules/_io/textio.c - PyId_strict variable _Py_IDENTIFIER(strict) -Python/pythonrun.c - PyId_string variable "_Py_static_string(PyId_string, """")" -Modules/timemodule.c time_strptime PyId__strptime_time variable _Py_IDENTIFIER(_strptime_time) -Modules/posixmodule.c wait_helper PyId_struct_rusage variable _Py_IDENTIFIER(struct_rusage) -Modules/_abc.c - PyId___subclasscheck__ variable _Py_IDENTIFIER(__subclasscheck__) -Objects/abstract.c PyObject_IsSubclass PyId___subclasscheck__ variable _Py_IDENTIFIER(__subclasscheck__) -Modules/_abc.c - PyId___subclasshook__ variable _Py_IDENTIFIER(__subclasshook__) -Objects/dictobject.c dictviews_xor PyId_symmetric_difference_update variable _Py_IDENTIFIER(symmetric_difference_update) -Python/Python-ast.c - PyId_tag variable _Py_IDENTIFIER(tag) -Python/Python-ast.c - PyId_target variable _Py_IDENTIFIER(target) -Python/Python-ast.c - PyId_targets variable _Py_IDENTIFIER(targets) -Modules/_io/textio.c - PyId_tell variable _Py_IDENTIFIER(tell) -Python/Python-ast.c - PyId_test variable _Py_IDENTIFIER(test) -Python/errors.c PyErr_SyntaxLocationObject PyId_text variable _Py_IDENTIFIER(text) -Python/pythonrun.c - PyId_text variable _Py_IDENTIFIER(text) -Python/traceback.c - PyId_TextIOWrapper variable _Py_IDENTIFIER(TextIOWrapper) -Python/pylifecycle.c - PyId_TextIOWrapper variable _Py_IDENTIFIER(TextIOWrapper) -Python/pylifecycle.c - PyId_threading variable _Py_IDENTIFIER(threading) -Objects/genobject.c - PyId_throw variable _Py_IDENTIFIER(throw) -Objects/abstract.c PyNumber_Long PyId___trunc__ variable _Py_IDENTIFIER(__trunc__) -Python/Python-ast.c - PyId_type variable _Py_IDENTIFIER(type) -Python/Python-ast.c - PyId_type_comment variable _Py_IDENTIFIER(type_comment) -Python/Python-ast.c - PyId_type_ignores variable _Py_IDENTIFIER(type_ignores) -Python/errors.c _PyErr_WriteUnraisableMsg PyId_unraisablehook variable _Py_IDENTIFIER(unraisablehook) -Objects/dictobject.c dictviews_or PyId_update variable _Py_IDENTIFIER(update) -Python/Python-ast.c - PyId_upper variable _Py_IDENTIFIER(upper) -Python/Python-ast.c - PyId_value variable _Py_IDENTIFIER(value) -Python/Python-ast.c - PyId_values variable _Py_IDENTIFIER(values) -Objects/abstract.c PyMapping_Values PyId_values variable _Py_IDENTIFIER(values) -Objects/descrobject.c mappingproxy_values PyId_values variable _Py_IDENTIFIER(values) -Python/Python-ast.c - PyId_vararg variable _Py_IDENTIFIER(vararg) -Python/_warnings.c already_warned PyId_version variable _Py_IDENTIFIER(version) -Python/_warnings.c - PyId_WarningMessage variable _Py_IDENTIFIER(WarningMessage) -Python/_warnings.c - PyId___warningregistry__ variable _Py_IDENTIFIER(__warningregistry__) -Python/_warnings.c get_warnings_attr PyId_warnings variable _Py_IDENTIFIER(warnings) -Python/sysmodule.c - PyId_warnoptions variable _Py_IDENTIFIER(warnoptions) -Python/_warnings.c _PyErr_WarnUnawaitedCoroutine PyId__warn_unawaited_coroutine variable _Py_IDENTIFIER(_warn_unawaited_coroutine) -Modules/_io/bufferedio.c - PyId_writable variable _Py_IDENTIFIER(writable) -Modules/_io/textio.c - PyId_writable variable _Py_IDENTIFIER(writable) -Python/sysmodule.c - PyId_write variable _Py_IDENTIFIER(write) -Modules/_io/bufferedio.c - PyId_write variable _Py_IDENTIFIER(write) -Python/marshal.c - PyId_write variable _Py_IDENTIFIER(write) -Objects/fileobject.c PyFile_WriteObject PyId_write variable _Py_IDENTIFIER(write) -Python/sysmodule.c - PyId__xoptions variable _Py_IDENTIFIER(_xoptions) -Python/import.c _PyImportZip_Init PyId_zipimporter variable _Py_IDENTIFIER(zipimporter) -Python/initconfig.c - Py_IgnoreEnvironmentFlag variable int Py_IgnoreEnvironmentFlag -Python/dynload_shlib.c - _PyImport_DynLoadFiletab variable const char *_PyImport_DynLoadFiletab[] -Include/import.h - PyImport_FrozenModules variable PyAPI_DATA(const struct _frozen *) PyImport_FrozenModules -Modules/config.c - _PyImport_Inittab variable struct _inittab _PyImport_Inittab[] -Include/import.h - PyImport_Inittab variable PyAPI_DATA(struct _inittab *) PyImport_Inittab -Modules/_io/textio.c - PyIncrementalNewlineDecoder_Type variable PyTypeObject PyIncrementalNewlineDecoder_Type -Python/initconfig.c - Py_InspectFlag variable int Py_InspectFlag -Objects/classobject.c - PyInstanceMethod_Type variable PyTypeObject PyInstanceMethod_Type -Python/initconfig.c - Py_InteractiveFlag variable int Py_InteractiveFlag -Objects/interpreteridobject.c - _PyInterpreterID_Type variable PyTypeObject _PyInterpreterID_Type -Modules/_io/iobase.c - PyIOBase_Type variable PyTypeObject PyIOBase_Type -Modules/_io/_iomodule.c - _PyIO_empty_bytes variable PyObject *_PyIO_empty_bytes -Modules/_io/_iomodule.c - _PyIO_empty_str variable PyObject *_PyIO_empty_str -Modules/_io/_iomodule.c - _PyIO_Module variable struct PyModuleDef _PyIO_Module -Modules/_io/_iomodule.c - _PyIO_str_close variable PyObject *_PyIO_str_close -Modules/_io/_iomodule.c - _PyIO_str_closed variable PyObject *_PyIO_str_closed -Modules/_io/_iomodule.c - _PyIO_str_decode variable PyObject *_PyIO_str_decode -Modules/_io/_iomodule.c - _PyIO_str_encode variable PyObject *_PyIO_str_encode -Modules/_io/_iomodule.c - _PyIO_str_fileno variable PyObject *_PyIO_str_fileno -Modules/_io/_iomodule.c - _PyIO_str_flush variable PyObject *_PyIO_str_flush -Modules/_io/_iomodule.c - _PyIO_str_getstate variable PyObject *_PyIO_str_getstate -Modules/_io/_iomodule.c - _PyIO_str_isatty variable PyObject *_PyIO_str_isatty -Modules/_io/_iomodule.c - _PyIO_str_newlines variable PyObject *_PyIO_str_newlines -Modules/_io/_iomodule.c - _PyIO_str_nl variable PyObject *_PyIO_str_nl -Modules/_io/_iomodule.c - _PyIO_str_peek variable PyObject *_PyIO_str_peek -Modules/_io/_iomodule.c - _PyIO_str_read variable PyObject *_PyIO_str_read -Modules/_io/_iomodule.c - _PyIO_str_read1 variable PyObject *_PyIO_str_read1 -Modules/_io/_iomodule.c - _PyIO_str_readable variable PyObject *_PyIO_str_readable -Modules/_io/_iomodule.c - _PyIO_str_readall variable PyObject *_PyIO_str_readall -Modules/_io/_iomodule.c - _PyIO_str_readinto variable PyObject *_PyIO_str_readinto -Modules/_io/_iomodule.c - _PyIO_str_readline variable PyObject *_PyIO_str_readline -Modules/_io/_iomodule.c - _PyIO_str_reset variable PyObject *_PyIO_str_reset -Modules/_io/_iomodule.c - _PyIO_str_seek variable PyObject *_PyIO_str_seek -Modules/_io/_iomodule.c - _PyIO_str_seekable variable PyObject *_PyIO_str_seekable -Modules/_io/_iomodule.c - _PyIO_str_setstate variable PyObject *_PyIO_str_setstate -Modules/_io/_iomodule.c - _PyIO_str_tell variable PyObject *_PyIO_str_tell -Modules/_io/_iomodule.c - _PyIO_str_truncate variable PyObject *_PyIO_str_truncate -Modules/_io/_iomodule.c - _PyIO_str_writable variable PyObject *_PyIO_str_writable -Modules/_io/_iomodule.c - _PyIO_str_write variable PyObject *_PyIO_str_write -Python/initconfig.c - Py_IsolatedFlag variable int Py_IsolatedFlag -Objects/listobject.c - PyListIter_Type variable PyTypeObject PyListIter_Type -Objects/listobject.c - PyListRevIter_Type variable PyTypeObject PyListRevIter_Type -Objects/listobject.c - PyList_Type variable PyTypeObject PyList_Type -Modules/_localemodule.c - PyLocale_Methods variable static struct PyMethodDef PyLocale_Methods[] -Include/longobject.h - _PyLong_DigitValue variable PyAPI_DATA(unsigned char) _PyLong_DigitValue[256] -Objects/longobject.c - _PyLong_One variable PyObject *_PyLong_One -Objects/rangeobject.c - PyLongRangeIter_Type variable PyTypeObject PyLongRangeIter_Type -Objects/longobject.c - PyLong_Type variable PyTypeObject PyLong_Type -Objects/longobject.c - _PyLong_Zero variable PyObject *_PyLong_Zero -Objects/memoryobject.c - _PyManagedBuffer_Type variable PyTypeObject _PyManagedBuffer_Type -Python/bltinmodule.c - PyMap_Type variable PyTypeObject PyMap_Type -Objects/obmalloc.c - _PyMem variable static PyMemAllocatorEx _PyMem -Objects/descrobject.c - PyMemberDescr_Type variable PyTypeObject PyMemberDescr_Type -Objects/obmalloc.c - _PyMem_Debug variable static struct { debug_alloc_api_t raw; debug_alloc_api_t mem; debug_alloc_api_t obj; } _PyMem_Debug -Objects/memoryobject.c - PyMemoryView_Type variable PyTypeObject PyMemoryView_Type -Objects/obmalloc.c - _PyMem_Raw variable static PyMemAllocatorEx _PyMem_Raw -Objects/descrobject.c - PyMethodDescr_Type variable PyTypeObject PyMethodDescr_Type -Objects/classobject.c - PyMethod_Type variable PyTypeObject PyMethod_Type -Objects/descrobject.c - _PyMethodWrapper_Type variable PyTypeObject _PyMethodWrapper_Type -Objects/moduleobject.c - PyModuleDef_Type variable PyTypeObject PyModuleDef_Type -Objects/moduleobject.c - PyModule_Type variable PyTypeObject PyModule_Type -Objects/namespaceobject.c - _PyNamespace_Type variable PyTypeObject _PyNamespace_Type -Objects/object.c - _Py_NoneStruct variable PyObject _Py_NoneStruct -Objects/object.c - _PyNone_Type variable PyTypeObject _PyNone_Type -Python/initconfig.c - Py_NoSiteFlag variable int Py_NoSiteFlag -Objects/object.c - _Py_NotImplementedStruct variable PyObject _Py_NotImplementedStruct -Objects/object.c - _PyNotImplemented_Type variable PyTypeObject _PyNotImplemented_Type -Python/initconfig.c - Py_NoUserSiteDirectory variable int Py_NoUserSiteDirectory -Objects/obmalloc.c - _PyObject variable static PyMemAllocatorEx _PyObject -Objects/obmalloc.c - _PyObject_Arena variable static PyObjectArenaAllocator _PyObject_Arena -Objects/odictobject.c - PyODictItems_Type variable PyTypeObject PyODictItems_Type -Objects/odictobject.c - PyODictIter_Type variable PyTypeObject PyODictIter_Type -Objects/odictobject.c - PyODictKeys_Type variable PyTypeObject PyODictKeys_Type -Objects/odictobject.c - PyODict_Type variable PyTypeObject PyODict_Type -Objects/odictobject.c - PyODictValues_Type variable PyTypeObject PyODictValues_Type -Python/fileutils.c - _Py_open_cloexec_works variable int _Py_open_cloexec_works -Python/initconfig.c - Py_OptimizeFlag variable int Py_OptimizeFlag -Parser/myreadline.c - PyOS_InputHook variable int (*PyOS_InputHook)(void) -Python/pylifecycle.c - _PyOS_mystrnicmp_hack variable int (*_PyOS_mystrnicmp_hack)(const char *, const char *, Py_ssize_t) -Python/getopt.c - _PyOS_optarg variable const wchar_t *_PyOS_optarg -Python/getopt.c - _PyOS_opterr variable int _PyOS_opterr -Python/getopt.c - _PyOS_optind variable Py_ssize_t _PyOS_optind -Parser/myreadline.c - PyOS_ReadlineFunctionPointer variable char *(*PyOS_ReadlineFunctionPointer)(FILE *, FILE *, const char *) -Parser/myreadline.c - _PyOS_ReadlineLock variable static PyThread_type_lock _PyOS_ReadlineLock -Include/pythonrun.h - _PyOS_ReadlineTState variable PyAPI_DATA(PyThreadState*) _PyOS_ReadlineTState -Python/modsupport.c - _Py_PackageContext variable const char *_Py_PackageContext -Python/graminit.c - _PyParser_Grammar variable grammar _PyParser_Grammar -Include/internal/pycore_pathconfig.h - _Py_path_config variable PyAPI_DATA(_PyPathConfig) _Py_path_config -Objects/picklebufobject.c - PyPickleBuffer_Type variable PyTypeObject PyPickleBuffer_Type -Objects/descrobject.c - PyProperty_Type variable PyTypeObject PyProperty_Type -Python/initconfig.c - Py_QuietFlag variable int Py_QuietFlag -Objects/rangeobject.c - PyRangeIter_Type variable PyTypeObject PyRangeIter_Type -Objects/rangeobject.c - PyRange_Type variable PyTypeObject PyRange_Type -Modules/_io/iobase.c - PyRawIOBase_Type variable PyTypeObject PyRawIOBase_Type -Objects/object.c - _Py_RefTotal variable Py_ssize_t _Py_RefTotal -Objects/enumobject.c - PyReversed_Type variable PyTypeObject PyReversed_Type -Include/internal/pycore_pystate.h - _PyRuntime variable PyAPI_DATA(_PyRuntimeState) _PyRuntime -Objects/iterobject.c - PySeqIter_Type variable PyTypeObject PySeqIter_Type -Include/setobject.h - _PySet_Dummy variable PyAPI_DATA(PyObject *) _PySet_Dummy -Objects/setobject.c - _PySetDummy_Type variable static PyTypeObject _PySetDummy_Type -Objects/setobject.c - PySetIter_Type variable PyTypeObject PySetIter_Type -Objects/setobject.c - PySet_Type variable PyTypeObject PySet_Type -Objects/sliceobject.c - PySlice_Type variable PyTypeObject PySlice_Type -Python/initconfig.c - _Py_StandardStreamEncoding variable static char *_Py_StandardStreamEncoding -Python/initconfig.c - _Py_StandardStreamErrors variable static char *_Py_StandardStreamErrors -Objects/funcobject.c - PyStaticMethod_Type variable PyTypeObject PyStaticMethod_Type -Objects/fileobject.c - PyStdPrinter_Type variable PyTypeObject PyStdPrinter_Type -Python/symtable.c - PySTEntry_Type variable PyTypeObject PySTEntry_Type -Modules/_io/stringio.c - PyStringIO_Type variable PyTypeObject PyStringIO_Type -Objects/structseq.c - PyStructSequence_UnnamedField variable char *PyStructSequence_UnnamedField -Objects/typeobject.c - PySuper_Type variable PyTypeObject PySuper_Type -Objects/object.c - _Py_SwappedOp variable int _Py_SwappedOp[] -Python/sysmodule.c - _PySys_ImplCacheTag variable const char *_PySys_ImplCacheTag -Python/sysmodule.c - _PySys_ImplName variable const char *_PySys_ImplName -Modules/_io/textio.c - PyTextIOBase_Type variable PyTypeObject PyTextIOBase_Type -Modules/_io/textio.c - PyTextIOWrapper_Type variable PyTypeObject PyTextIOWrapper_Type -Python/traceback.c - PyTraceBack_Type variable PyTypeObject PyTraceBack_Type -Include/pymem.h - _Py_tracemalloc_config variable PyAPI_DATA(struct _PyTraceMalloc_Config) _Py_tracemalloc_config -Objects/boolobject.c - _Py_TrueStruct variable static struct _longobject _Py_TrueStruct -Objects/tupleobject.c - PyTupleIter_Type variable PyTypeObject PyTupleIter_Type -Objects/tupleobject.c - PyTuple_Type variable PyTypeObject PyTuple_Type -Objects/typeobject.c - PyType_Type variable PyTypeObject PyType_Type -Python/initconfig.c - Py_UnbufferedStdioFlag variable int Py_UnbufferedStdioFlag -Python/pylifecycle.c - _Py_UnhandledKeyboardInterrupt variable int _Py_UnhandledKeyboardInterrupt -Objects/unicodeobject.c - PyUnicodeIter_Type variable PyTypeObject PyUnicodeIter_Type -Objects/unicodeobject.c - PyUnicode_Type variable PyTypeObject PyUnicode_Type -Python/initconfig.c - Py_UTF8Mode variable int Py_UTF8Mode -Python/initconfig.c - Py_VerboseFlag variable int Py_VerboseFlag -Include/weakrefobject.h - _PyWeakref_CallableProxyType variable PyAPI_DATA(PyTypeObject) _PyWeakref_CallableProxyType -Include/weakrefobject.h - _PyWeakref_ProxyType variable PyAPI_DATA(PyTypeObject) _PyWeakref_ProxyType -Include/weakrefobject.h - _PyWeakref_RefType variable PyAPI_DATA(PyTypeObject) _PyWeakref_RefType -Objects/descrobject.c - PyWrapperDescr_Type variable PyTypeObject PyWrapperDescr_Type -Python/bltinmodule.c - PyZip_Type variable PyTypeObject PyZip_Type -Python/Python-ast.c - Raise_fields variable static char *Raise_fields[] -Python/Python-ast.c - Raise_type variable static PyTypeObject *Raise_type -Objects/rangeobject.c - range_as_mapping variable static PyMappingMethods range_as_mapping -Objects/rangeobject.c - range_as_number variable static PyNumberMethods range_as_number -Objects/rangeobject.c - range_as_sequence variable static PySequenceMethods range_as_sequence -Objects/rangeobject.c - rangeiter_methods variable static PyMethodDef rangeiter_methods -Objects/rangeobject.c - range_members variable static PyMemberDef range_members[] -Objects/rangeobject.c - range_methods variable static PyMethodDef range_methods -Modules/_io/iobase.c - rawiobase_methods variable static PyMethodDef rawiobase_methods -Python/pylifecycle.c fatal_error reentrant variable static int reentrant -Modules/faulthandler.c - reentrant variable static volatile int reentrant -Modules/itertoolsmodule.c - repeat_methods variable static PyMethodDef repeat_methods -Modules/itertoolsmodule.c - repeat_type variable static PyTypeObject repeat_type -Python/Python-ast.c - Return_fields variable static char *Return_fields[] -Python/compile.c - return_str variable static identifier return_str -Python/Python-ast.c - Return_type variable static PyTypeObject *Return_type -Objects/enumobject.c - reversediter_methods variable static PyMethodDef reversediter_methods -Modules/_threadmodule.c - rlock_methods variable static PyMethodDef rlock_methods -Modules/_threadmodule.c - RLocktype variable static PyTypeObject RLocktype -Objects/typeobject.c slot_nb_add rop_id variable _Py_static_string(op_id, OPSTR) -Objects/typeobject.c slot_nb_subtract rop_id variable _Py_static_string(op_id, OPSTR) -Objects/typeobject.c slot_nb_multiply rop_id variable _Py_static_string(op_id, OPSTR) -Objects/typeobject.c slot_nb_matrix_multiply rop_id variable _Py_static_string(op_id, OPSTR) -Objects/typeobject.c slot_nb_remainder rop_id variable _Py_static_string(op_id, OPSTR) -Objects/typeobject.c slot_nb_divmod rop_id variable _Py_static_string(op_id, OPSTR) -Objects/typeobject.c slot_nb_power_binary rop_id variable _Py_static_string(op_id, OPSTR) -Objects/typeobject.c slot_nb_lshift rop_id variable _Py_static_string(op_id, OPSTR) -Objects/typeobject.c slot_nb_rshift rop_id variable _Py_static_string(op_id, OPSTR) -Objects/typeobject.c slot_nb_and rop_id variable _Py_static_string(op_id, OPSTR) -Objects/typeobject.c slot_nb_xor rop_id variable _Py_static_string(op_id, OPSTR) -Objects/typeobject.c slot_nb_or rop_id variable _Py_static_string(op_id, OPSTR) -Objects/typeobject.c slot_nb_floor_divide rop_id variable _Py_static_string(op_id, OPSTR) -Objects/typeobject.c slot_nb_true_divide rop_id variable _Py_static_string(op_id, OPSTR) -Python/Python-ast.c - RShift_singleton variable static PyObject *RShift_singleton -Python/Python-ast.c - RShift_type variable static PyTypeObject *RShift_type -Python/pylifecycle.c - runtime_initialized variable static int runtime_initialized -Modules/posixmodule.c - ScandirIterator_methods variable static PyMethodDef ScandirIterator_methods -Modules/posixmodule.c - ScandirIteratorType variable static PyTypeObject ScandirIteratorType -Modules/_sre.c - scanner_members variable static PyMemberDef scanner_members[] -Modules/_sre.c - scanner_methods variable static PyMethodDef scanner_methods -Modules/_sre.c - Scanner_Type variable static PyTypeObject Scanner_Type -Modules/posixmodule.c - sched_param_desc variable static PyStructSequence_Desc sched_param_desc -Modules/posixmodule.c - sched_param_fields variable static PyStructSequence_Field sched_param_fields[] -Modules/posixmodule.c - SchedParamType variable static PyTypeObject* SchedParamType -Objects/iterobject.c - seqiter_methods variable static PyMethodDef seqiter_methods -Objects/setobject.c - set_as_number variable static PyNumberMethods set_as_number -Objects/setobject.c - set_as_sequence variable static PySequenceMethods set_as_sequence -Python/symtable.c - setcomp variable static identifier setcomp -Python/Python-ast.c - SetComp_fields variable static char *SetComp_fields[] -Python/Python-ast.c - SetComp_type variable static PyTypeObject *SetComp_type -Python/Python-ast.c - Set_fields variable static char *Set_fields[] -Objects/setobject.c - setiter_methods variable static PyMethodDef setiter_methods -Objects/setobject.c - set_methods variable static PyMethodDef set_methods -Python/Python-ast.c - Set_type variable static PyTypeObject *Set_type -Modules/signalmodule.c - SiginfoType variable static PyTypeObject SiginfoType -Modules/signalmodule.c - signal_methods variable static PyMethodDef signal_methods -Modules/signalmodule.c - signalmodule variable static struct PyModuleDef signalmodule -Python/import.c PyImport_Import silly_list variable static PyObject *silly_list -Objects/sliceobject.c - slice_cache variable static PySliceObject *slice_cache -Python/Python-ast.c - Slice_fields variable static char *Slice_fields[] -Objects/sliceobject.c - slice_members variable static PyMemberDef slice_members[] -Objects/sliceobject.c - slice_methods variable static PyMethodDef slice_methods -Python/Python-ast.c - slice_type variable static PyTypeObject *slice_type -Python/Python-ast.c - Slice_type variable static PyTypeObject *Slice_type -Objects/typeobject.c - slotdefs variable static slotdef slotdefs[] -Objects/typeobject.c - slotdefs_initialized variable static int slotdefs_initialized -Objects/longobject.c - small_ints variable static PyLongObject small_ints[NSMALLNEGINTS + NSMALLPOSINTS] -Objects/funcobject.c - sm_getsetlist variable static PyGetSetDef sm_getsetlist[] -Objects/funcobject.c - sm_memberlist variable static PyMemberDef sm_memberlist[] -Modules/xxsubtype.c - spamdict_members variable static PyMemberDef spamdict_members[] -Modules/xxsubtype.c - spamdict_methods variable static PyMethodDef spamdict_methods -Modules/xxsubtype.c - spamdict_type variable static PyTypeObject spamdict_type -Modules/xxsubtype.c - spamlist_getsets variable static PyGetSetDef spamlist_getsets[] -Modules/xxsubtype.c - spamlist_methods variable static PyMethodDef spamlist_methods -Modules/xxsubtype.c - spamlist_type variable static PyTypeObject spamlist_type -Modules/_sre.c - sremodule variable static struct PyModuleDef sremodule -Modules/faulthandler.c - stack variable static stack_t stack -Modules/itertoolsmodule.c - starmap_methods variable static PyMethodDef starmap_methods -Modules/itertoolsmodule.c - starmap_type variable static PyTypeObject starmap_type -Python/Python-ast.c - Starred_fields variable static char *Starred_fields[] -Python/Python-ast.c - Starred_type variable static PyTypeObject *Starred_type -Python/graminit.c - states_0 variable static state states_0[3] -Python/graminit.c - states_1 variable static state states_1[2] -Python/graminit.c - states_10 variable static state states_10[4] -Python/graminit.c - states_11 variable static state states_11[34] -Python/graminit.c - states_12 variable static state states_12[2] -Python/graminit.c - states_13 variable static state states_13[2] -Python/graminit.c - states_14 variable static state states_14[4] -Python/graminit.c - states_15 variable static state states_15[2] -Python/graminit.c - states_16 variable static state states_16[6] -Python/graminit.c - states_17 variable static state states_17[5] -Python/graminit.c - states_18 variable static state states_18[3] -Python/graminit.c - states_19 variable static state states_19[2] -Python/graminit.c - states_2 variable static state states_2[3] -Python/graminit.c - states_20 variable static state states_20[3] -Python/graminit.c - states_21 variable static state states_21[2] -Python/graminit.c - states_22 variable static state states_22[2] -Python/graminit.c - states_23 variable static state states_23[2] -Python/graminit.c - states_24 variable static state states_24[2] -Python/graminit.c - states_25 variable static state states_25[3] -Python/graminit.c - states_26 variable static state states_26[2] -Python/graminit.c - states_27 variable static state states_27[5] -Python/graminit.c - states_28 variable static state states_28[2] -Python/graminit.c - states_29 variable static state states_29[3] -Python/graminit.c - states_3 variable static state states_3[7] -Python/graminit.c - states_30 variable static state states_30[8] -Python/graminit.c - states_31 variable static state states_31[4] -Python/graminit.c - states_32 variable static state states_32[4] -Python/graminit.c - states_33 variable static state states_33[3] -Python/graminit.c - states_34 variable static state states_34[2] -Python/graminit.c - states_35 variable static state states_35[2] -Python/graminit.c - states_36 variable static state states_36[3] -Python/graminit.c - states_37 variable static state states_37[3] -Python/graminit.c - states_38 variable static state states_38[5] -Python/graminit.c - states_39 variable static state states_39[2] -Python/graminit.c - states_4 variable static state states_4[2] -Python/graminit.c - states_40 variable static state states_40[3] -Python/graminit.c - states_41 variable static state states_41[8] -Python/graminit.c - states_42 variable static state states_42[8] -Python/graminit.c - states_43 variable static state states_43[11] -Python/graminit.c - states_44 variable static state states_44[13] -Python/graminit.c - states_45 variable static state states_45[6] -Python/graminit.c - states_46 variable static state states_46[4] -Python/graminit.c - states_47 variable static state states_47[5] -Python/graminit.c - states_48 variable static state states_48[5] -Python/graminit.c - states_49 variable static state states_49[4] -Python/graminit.c - states_5 variable static state states_5[3] -Python/graminit.c - states_50 variable static state states_50[6] -Python/graminit.c - states_51 variable static state states_51[2] -Python/graminit.c - states_52 variable static state states_52[5] -Python/graminit.c - states_53 variable static state states_53[5] -Python/graminit.c - states_54 variable static state states_54[2] -Python/graminit.c - states_55 variable static state states_55[2] -Python/graminit.c - states_56 variable static state states_56[3] -Python/graminit.c - states_57 variable static state states_57[2] -Python/graminit.c - states_58 variable static state states_58[4] -Python/graminit.c - states_59 variable static state states_59[3] -Python/graminit.c - states_6 variable static state states_6[3] -Python/graminit.c - states_60 variable static state states_60[2] -Python/graminit.c - states_61 variable static state states_61[2] -Python/graminit.c - states_62 variable static state states_62[2] -Python/graminit.c - states_63 variable static state states_63[2] -Python/graminit.c - states_64 variable static state states_64[2] -Python/graminit.c - states_65 variable static state states_65[2] -Python/graminit.c - states_66 variable static state states_66[3] -Python/graminit.c - states_67 variable static state states_67[4] -Python/graminit.c - states_68 variable static state states_68[3] -Python/graminit.c - states_69 variable static state states_69[9] -Python/graminit.c - states_7 variable static state states_7[9] -Python/graminit.c - states_70 variable static state states_70[5] -Python/graminit.c - states_71 variable static state states_71[7] -Python/graminit.c - states_72 variable static state states_72[3] -Python/graminit.c - states_73 variable static state states_73[5] -Python/graminit.c - states_74 variable static state states_74[3] -Python/graminit.c - states_75 variable static state states_75[3] -Python/graminit.c - states_76 variable static state states_76[3] -Python/graminit.c - states_77 variable static state states_77[14] -Python/graminit.c - states_78 variable static state states_78[8] -Python/graminit.c - states_79 variable static state states_79[3] -Python/graminit.c - states_8 variable static state states_8[4] -Python/graminit.c - states_80 variable static state states_80[4] -Python/graminit.c - states_81 variable static state states_81[2] -Python/graminit.c - states_82 variable static state states_82[6] -Python/graminit.c - states_83 variable static state states_83[3] -Python/graminit.c - states_84 variable static state states_84[4] -Python/graminit.c - states_85 variable static state states_85[2] -Python/graminit.c - states_86 variable static state states_86[3] -Python/graminit.c - states_87 variable static state states_87[3] -Python/graminit.c - states_88 variable static state states_88[7] -Python/graminit.c - states_89 variable static state states_89[3] -Python/graminit.c - states_9 variable static state states_9[42] -Python/graminit.c - states_90 variable static state states_90[6] -Python/graminit.c - states_91 variable static state states_91[11] -Python/getargs.c - static_arg_parsers variable static struct _PyArg_Parser *static_arg_parsers -Objects/unicodeobject.c - static_strings variable static _Py_Identifier *static_strings -Modules/_stat.c - stat_methods variable static PyMethodDef stat_methods -Modules/_stat.c - statmodule variable static struct PyModuleDef statmodule -Modules/posixmodule.c - stat_result_desc variable static PyStructSequence_Desc stat_result_desc -Modules/posixmodule.c - stat_result_fields variable static PyStructSequence_Field stat_result_fields[] -Modules/posixmodule.c - StatResultType variable static PyTypeObject* StatResultType -Modules/posixmodule.c - statvfs_result_desc variable static PyStructSequence_Desc statvfs_result_desc -Modules/posixmodule.c - statvfs_result_fields variable static PyStructSequence_Field statvfs_result_fields[] -Modules/posixmodule.c - StatVFSResultType variable static PyTypeObject* StatVFSResultType -Objects/fileobject.c - stdprinter_getsetlist variable static PyGetSetDef stdprinter_getsetlist[] -Objects/fileobject.c - stdprinter_methods variable static PyMethodDef stdprinter_methods -Python/symtable.c - ste_memberlist variable static PyMemberDef ste_memberlist[] -Python/Python-ast.c - stmt_attributes variable static char *stmt_attributes[] -Python/Python-ast.c - stmt_type variable static PyTypeObject *stmt_type -Objects/exceptions.c - StopIteration_members variable static PyMemberDef StopIteration_members[] -Python/Python-ast.c - Store_singleton variable PyObject *Store_singleton -Python/Python-ast.c - Store_type variable static PyTypeObject *Store_type -Python/ast_unparse.c - _str_close_br variable static PyObject *_str_close_br -Python/ast_unparse.c - _str_dbl_close_br variable static PyObject *_str_dbl_close_br -Python/ast_unparse.c - _str_dbl_open_br variable static PyObject *_str_dbl_open_br -Modules/_threadmodule.c - str_dict variable static PyObject *str_dict -Modules/_io/stringio.c - stringio_getset variable static PyGetSetDef stringio_getset[] -Modules/_io/stringio.c - stringio_methods variable static PyMethodDef stringio_methods -Objects/unicodeobject.c - _string_methods variable static PyMethodDef _string_methods -Objects/unicodeobject.c - _string_module variable static struct PyModuleDef _string_module -Objects/bytesobject.c - striter_methods variable static PyMethodDef striter_methods -Python/ast_unparse.c - _str_open_br variable static PyObject *_str_open_br -Modules/pwdmodule.c - StructPwdType variable static PyTypeObject StructPwdType -Modules/pwdmodule.c - struct_pwd_type_desc variable static PyStructSequence_Desc struct_pwd_type_desc -Modules/pwdmodule.c - struct_pwd_type_fields variable static PyStructSequence_Field struct_pwd_type_fields[] -Modules/posixmodule.c wait_helper struct_rusage variable static PyObject *struct_rusage -Objects/structseq.c - structseq_methods variable static PyMethodDef structseq_methods -Modules/posixmodule.c - structseq_new variable static newfunc structseq_new -Modules/signalmodule.c - struct_siginfo_desc variable static PyStructSequence_Desc struct_siginfo_desc -Modules/signalmodule.c - struct_siginfo_fields variable static PyStructSequence_Field struct_siginfo_fields[] -Modules/timemodule.c - StructTimeType variable static PyTypeObject StructTimeType -Modules/timemodule.c - struct_time_type_desc variable static PyStructSequence_Desc struct_time_type_desc -Modules/timemodule.c - struct_time_type_fields variable static PyStructSequence_Field struct_time_type_fields[] -Python/Python-ast.c - Subscript_fields variable static char *Subscript_fields[] -Python/Python-ast.c - Subscript_type variable static PyTypeObject *Subscript_type -Python/Python-ast.c - Sub_singleton variable static PyObject *Sub_singleton -Python/Python-ast.c - Sub_type variable static PyTypeObject *Sub_type -Objects/typeobject.c - subtype_getsets_dict_only variable static PyGetSetDef subtype_getsets_dict_only[] -Objects/typeobject.c - subtype_getsets_full variable static PyGetSetDef subtype_getsets_full[] -Objects/typeobject.c - subtype_getsets_weakref_only variable static PyGetSetDef subtype_getsets_weakref_only[] -Python/Python-ast.c - Suite_fields variable static char *Suite_fields[] -Python/Python-ast.c - Suite_type variable static PyTypeObject *Suite_type -Objects/typeobject.c - super_members variable static PyMemberDef super_members[] -Modules/symtablemodule.c - symtable_methods variable static PyMethodDef symtable_methods -Modules/symtablemodule.c - symtablemodule variable static struct PyModuleDef symtablemodule -Objects/exceptions.c - SyntaxError_members variable static PyMemberDef SyntaxError_members[] -Python/sysmodule.c - sys_methods variable static PyMethodDef sys_methods -Python/sysmodule.c - sysmodule variable static struct PyModuleDef sysmodule -Objects/exceptions.c - SystemExit_members variable static PyMemberDef SystemExit_members[] -Modules/_tracemalloc.c - tables_lock variable static PyThread_type_lock tables_lock -Modules/itertoolsmodule.c - takewhile_reduce_methods variable static PyMethodDef takewhile_reduce_methods -Modules/itertoolsmodule.c - takewhile_type variable static PyTypeObject takewhile_type -Python/pylifecycle.c - _TARGET_LOCALES variable static _LocaleCoercionTarget _TARGET_LOCALES[] -Python/traceback.c - tb_getsetters variable static PyGetSetDef tb_getsetters[] -Python/traceback.c - tb_memberlist variable static PyMemberDef tb_memberlist[] -Python/traceback.c - tb_methods variable static PyMethodDef tb_methods -Modules/itertoolsmodule.c - teedataobject_methods variable static PyMethodDef teedataobject_methods -Modules/itertoolsmodule.c - teedataobject_type variable static PyTypeObject teedataobject_type -Modules/itertoolsmodule.c - tee_methods variable static PyMethodDef tee_methods -Modules/itertoolsmodule.c - tee_type variable static PyTypeObject tee_type -Modules/posixmodule.c - TerminalSize_desc variable static PyStructSequence_Desc TerminalSize_desc -Modules/posixmodule.c - TerminalSize_fields variable static PyStructSequence_Field TerminalSize_fields[] -Modules/posixmodule.c - TerminalSizeType variable static PyTypeObject* TerminalSizeType -Modules/_io/textio.c - textiobase_getset variable static PyGetSetDef textiobase_getset[] -Modules/_io/textio.c - textiobase_methods variable static PyMethodDef textiobase_methods -Modules/_io/textio.c - textiowrapper_getset variable static PyGetSetDef textiowrapper_getset[] -Modules/_io/textio.c - textiowrapper_members variable static PyMemberDef textiowrapper_members[] -Modules/_io/textio.c - textiowrapper_methods variable static PyMethodDef textiowrapper_methods -Modules/faulthandler.c - thread variable static struct { PyObject *file; int fd; PY_TIMEOUT_T timeout_us; int repeat; PyInterpreterState *interp; int exit; char *header; size_t header_len; PyThread_type_lock cancel_event; PyThread_type_lock running; } thread -Python/thread.c - thread_debug variable static int thread_debug -Modules/_threadmodule.c - ThreadError variable static PyObject *ThreadError -Python/thread.c - threadinfo_desc variable static PyStructSequence_Desc threadinfo_desc -Python/thread.c - threadinfo_fields variable static PyStructSequence_Field threadinfo_fields[] -Python/thread.c - ThreadInfoType variable static PyTypeObject ThreadInfoType -Modules/_threadmodule.c - thread_methods variable static PyMethodDef thread_methods -Modules/_threadmodule.c - threadmodule variable static struct PyModuleDef threadmodule -Modules/posixmodule.c - ticks_per_second variable static long ticks_per_second -Modules/timemodule.c _PyTime_GetProcessTimeWithInfo ticks_per_second variable static long ticks_per_second -Modules/timemodule.c - time_methods variable static PyMethodDef time_methods -Modules/timemodule.c - timemodule variable static struct PyModuleDef timemodule -Modules/posixmodule.c - times_result_desc variable static PyStructSequence_Desc times_result_desc -Modules/posixmodule.c - times_result_fields variable static PyStructSequence_Field times_result_fields[] -Modules/posixmodule.c - TimesResultType variable static PyTypeObject* TimesResultType -Python/context.c - _token_missing variable static PyObject *_token_missing -Python/symtable.c - top variable static identifier top -Objects/typeobject.c - tp_new_methoddef variable static struct PyMethodDef tp_new_methoddef[] -Modules/_tracemalloc.c - tracemalloc_empty_traceback variable static traceback_t tracemalloc_empty_traceback -Modules/_tracemalloc.c - tracemalloc_filenames variable static _Py_hashtable_t *tracemalloc_filenames -Modules/_tracemalloc.c - tracemalloc_peak_traced_memory variable static size_t tracemalloc_peak_traced_memory -Modules/_tracemalloc.c - tracemalloc_reentrant_key variable static Py_tss_t tracemalloc_reentrant_key -Modules/_tracemalloc.c - tracemalloc_traceback variable static traceback_t *tracemalloc_traceback -Modules/_tracemalloc.c - tracemalloc_tracebacks variable static _Py_hashtable_t *tracemalloc_tracebacks -Modules/_tracemalloc.c - tracemalloc_traced_memory variable static size_t tracemalloc_traced_memory -Modules/_tracemalloc.c - tracemalloc_traces variable static _Py_hashtable_t *tracemalloc_traces -Objects/boolobject.c - true_str variable static PyObject *true_str -Python/Python-ast.c - Try_fields variable static char *Try_fields[] -Python/Python-ast.c - Try_type variable static PyTypeObject *Try_type -Objects/tupleobject.c - tuple_as_mapping variable static PyMappingMethods tuple_as_mapping -Objects/tupleobject.c - tuple_as_sequence variable static PySequenceMethods tuple_as_sequence -Python/Python-ast.c - Tuple_fields variable static char *Tuple_fields[] -Modules/_collectionsmodule.c - tuplegetter_members variable static PyMemberDef tuplegetter_members[] -Modules/_collectionsmodule.c - tuplegetter_methods variable static PyMethodDef tuplegetter_methods -Modules/_collectionsmodule.c - tuplegetter_type variable static PyTypeObject tuplegetter_type -Objects/tupleobject.c - tupleiter_methods variable static PyMethodDef tupleiter_methods -Objects/tupleobject.c - tuple_methods variable static PyMethodDef tuple_methods -Python/Python-ast.c - Tuple_type variable static PyTypeObject *Tuple_type -Objects/typeobject.c - type_getsets variable static PyGetSetDef type_getsets[] -Python/Python-ast.c - TypeIgnore_fields variable static char *TypeIgnore_fields[] -Python/Python-ast.c - type_ignore_type variable static PyTypeObject *type_ignore_type -Python/Python-ast.c - TypeIgnore_type variable static PyTypeObject *TypeIgnore_type -Objects/typeobject.c - type_members variable static PyMemberDef type_members[] -Objects/typeobject.c - type_methods variable static PyMethodDef type_methods -Python/Python-ast.c - UAdd_singleton variable static PyObject *UAdd_singleton -Python/Python-ast.c - UAdd_type variable static PyTypeObject *UAdd_type -Objects/unicodeobject.c - ucnhash_CAPI variable static _PyUnicode_Name_CAPI *ucnhash_CAPI -Python/codecs.c - ucnhash_CAPI variable static _PyUnicode_Name_CAPI *ucnhash_CAPI -Python/ast.c - u_kind variable static PyObject *u_kind -Modules/posixmodule.c - uname_result_desc variable static PyStructSequence_Desc uname_result_desc -Modules/posixmodule.c - uname_result_fields variable static PyStructSequence_Field uname_result_fields[] -Modules/posixmodule.c - UnameResultType variable static PyTypeObject* UnameResultType -Python/Python-ast.c - UnaryOp_fields variable static char *UnaryOp_fields[] -Python/Python-ast.c - unaryop_type variable static PyTypeObject *unaryop_type -Python/Python-ast.c - UnaryOp_type variable static PyTypeObject *UnaryOp_type -Objects/unicodeobject.c - unicode_as_mapping variable static PyMappingMethods unicode_as_mapping -Objects/unicodeobject.c - unicode_as_number variable static PyNumberMethods unicode_as_number -Objects/unicodeobject.c - unicode_as_sequence variable static PySequenceMethods unicode_as_sequence -Objects/unicodeobject.c - unicode_empty variable static PyObject *unicode_empty -Objects/exceptions.c - UnicodeError_members variable static PyMemberDef UnicodeError_members[] -Objects/unicodeobject.c - unicodeiter_methods variable static PyMethodDef unicodeiter_methods -Objects/unicodeobject.c - unicode_latin1 variable static PyObject *unicode_latin1[256] -Objects/unicodeobject.c - unicode_methods variable static PyMethodDef unicode_methods -Modules/_tracemalloc.c - unknown_filename variable static PyObject *unknown_filename -Python/errors.c - UnraisableHookArgs_desc variable static PyStructSequence_Desc UnraisableHookArgs_desc -Python/errors.c - UnraisableHookArgs_fields variable static PyStructSequence_Field UnraisableHookArgs_fields[] -Python/errors.c - UnraisableHookArgsType variable static PyTypeObject UnraisableHookArgsType -Objects/obmalloc.c - unused_arena_objects variable static struct arena_object* unused_arena_objects -Python/bootstrap_hash.c - urandom_cache variable static struct { int fd; dev_t st_dev; ino_t st_ino; } urandom_cache -Objects/obmalloc.c - usable_arenas variable static struct arena_object* usable_arenas -Objects/obmalloc.c - usedpools variable static poolp usedpools[2 * ((NB_SMALL_SIZE_CLASSES + 7) / 8) * 8] -Modules/faulthandler.c - user_signals variable static user_signal_t *user_signals -Python/Python-ast.c - USub_singleton variable static PyObject *USub_singleton -Python/Python-ast.c - USub_type variable static PyTypeObject *USub_type -Python/getversion.c Py_GetVersion version variable static char version[250] -Python/sysmodule.c - version_info_desc variable static PyStructSequence_Desc version_info_desc -Python/sysmodule.c - version_info_fields variable static PyStructSequence_Field version_info_fields[] -Python/sysmodule.c - VersionInfoType variable static PyTypeObject VersionInfoType -Modules/posixmodule.c - waitid_result_desc variable static PyStructSequence_Desc waitid_result_desc -Modules/posixmodule.c - waitid_result_fields variable static PyStructSequence_Field waitid_result_fields[] -Modules/posixmodule.c - WaitidResultType variable static PyTypeObject* WaitidResultType -Modules/signalmodule.c - wakeup variable static volatile struct { SOCKET_T fd; int warn_on_full_buffer; int use_send; } wakeup -Python/_warnings.c - warnings_functions variable static PyMethodDef warnings_functions[] -Python/_warnings.c - warningsmodule variable static struct PyModuleDef warningsmodule -Modules/_weakref.c - weakref_functions variable static PyMethodDef weakref_functions -Objects/weakrefobject.c - weakref_members variable static PyMemberDef weakref_members[] -Modules/_weakref.c - weakrefmodule variable static struct PyModuleDef weakrefmodule -Python/sysmodule.c - whatstrings variable static PyObject *whatstrings[8] -Python/Python-ast.c - While_fields variable static char *While_fields[] -Python/Python-ast.c - While_type variable static PyTypeObject *While_type -Python/Python-ast.c - With_fields variable static char *With_fields[] -Python/Python-ast.c - withitem_fields variable static char *withitem_fields[] -Python/Python-ast.c - withitem_type variable static PyTypeObject *withitem_type -Python/Python-ast.c - With_type variable static PyTypeObject *With_type -Objects/descrobject.c - wrapperdescr_getset variable static PyGetSetDef wrapperdescr_getset[] -Objects/descrobject.c - wrapper_getsets variable static PyGetSetDef wrapper_getsets[] -Objects/descrobject.c - wrapper_members variable static PyMemberDef wrapper_members[] -Objects/descrobject.c - wrapper_methods variable static PyMethodDef wrapper_methods -Modules/_threadmodule.c local_new wr_callback_def variable static PyMethodDef wr_callback_def -Modules/xxsubtype.c - xxsubtype_functions variable static PyMethodDef xxsubtype_functions[] -Modules/xxsubtype.c - xxsubtypemodule variable static struct PyModuleDef xxsubtypemodule -Modules/xxsubtype.c - xxsubtype_slots variable static struct PyModuleDef_Slot xxsubtype_slots[] -Python/Python-ast.c - Yield_fields variable static char *Yield_fields[] -Python/Python-ast.c - YieldFrom_fields variable static char *YieldFrom_fields[] -Python/Python-ast.c - YieldFrom_type variable static PyTypeObject *YieldFrom_type -Python/Python-ast.c - Yield_type variable static PyTypeObject *Yield_type -Modules/itertoolsmodule.c - zip_longest_methods variable static PyMethodDef zip_longest_methods -Modules/itertoolsmodule.c - ziplongest_type variable static PyTypeObject ziplongest_type -Python/bltinmodule.c - zip_methods variable static PyMethodDef zip_methods +filename funcname name kind declaration +Modules/_abc.c - _abc_data_type variable static PyTypeObject _abc_data_type +Modules/_abc.c - abc_invalidation_counter variable static unsigned long long abc_invalidation_counter +Modules/_abc.c - _abcmodule variable static struct PyModuleDef _abcmodule +Python/import.c import_find_and_load accumulated variable static _PyTime_t accumulated +Modules/itertoolsmodule.c - accumulate_methods variable static PyMethodDef accumulate_methods +Modules/itertoolsmodule.c - accumulate_type variable static PyTypeObject accumulate_type +Python/Python-ast.c - Add_singleton variable static PyObject *Add_singleton +Python/Python-ast.c - Add_type variable static PyTypeObject *Add_type +Objects/genobject.c - ag_asend_freelist variable static PyAsyncGenASend *ag_asend_freelist[_PyAsyncGen_MAXFREELIST] +Objects/genobject.c - ag_asend_freelist_free variable static int ag_asend_freelist_free +Objects/genobject.c - ag_value_freelist variable static _PyAsyncGenWrappedValue *ag_value_freelist[_PyAsyncGen_MAXFREELIST] +Objects/genobject.c - ag_value_freelist_free variable static int ag_value_freelist_free +Python/Python-ast.c - alias_fields variable static char *alias_fields[] +Python/Python-ast.c - alias_type variable static PyTypeObject *alias_type +Modules/_tracemalloc.c - allocators variable static struct { PyMemAllocatorEx mem; PyMemAllocatorEx raw; PyMemAllocatorEx obj; } allocators +Python/Python-ast.c - And_singleton variable PyObject *And_singleton +Python/Python-ast.c - And_type variable static PyTypeObject *And_type +Python/Python-ast.c - AnnAssign_fields variable static char *AnnAssign_fields[] +Python/Python-ast.c - AnnAssign_type variable static PyTypeObject *AnnAssign_type +Python/compile.c - __annotations__ variable static PyObject *__annotations__ +Objects/obmalloc.c - arenas variable static struct arena_object* arenas +Python/Python-ast.c - arg_attributes variable static char *arg_attributes[] +Python/Python-ast.c - arg_fields variable static char *arg_fields[] +Python/Python-ast.c - arg_type variable static PyTypeObject *arg_type +Python/Python-ast.c - arguments_fields variable static char *arguments_fields[] +Python/Python-ast.c - arguments_type variable static PyTypeObject *arguments_type +Python/Python-ast.c - Assert_fields variable static char *Assert_fields[] +Python/compile.c compiler_assert assertion_error variable static PyObject *assertion_error +Python/Python-ast.c - Assert_type variable static PyTypeObject *Assert_type +Python/Python-ast.c - Assign_fields variable static char *Assign_fields[] +Python/Python-ast.c - Assign_type variable static PyTypeObject *Assign_type +Python/Python-ast.c - _astmodule variable static struct PyModuleDef _astmodule +Python/Python-ast.c - AST_type variable static PyTypeObject AST_type +Python/Python-ast.c - ast_type_getsets variable static PyGetSetDef ast_type_getsets[] +Python/Python-ast.c - ast_type_methods variable static PyMethodDef ast_type_methods +Python/Python-ast.c - AsyncFor_fields variable static char *AsyncFor_fields[] +Python/Python-ast.c - AsyncFor_type variable static PyTypeObject *AsyncFor_type +Python/Python-ast.c - AsyncFunctionDef_fields variable static char *AsyncFunctionDef_fields[] +Python/Python-ast.c - AsyncFunctionDef_type variable static PyTypeObject *AsyncFunctionDef_type +Objects/genobject.c - async_gen_as_async variable static PyAsyncMethods async_gen_as_async +Objects/genobject.c - async_gen_asend_as_async variable static PyAsyncMethods async_gen_asend_as_async +Objects/genobject.c - async_gen_asend_methods variable static PyMethodDef async_gen_asend_methods +Objects/genobject.c - async_gen_athrow_as_async variable static PyAsyncMethods async_gen_athrow_as_async +Objects/genobject.c - async_gen_athrow_methods variable static PyMethodDef async_gen_athrow_methods +Objects/genobject.c - async_gen_getsetlist variable static PyGetSetDef async_gen_getsetlist[] +Python/sysmodule.c - asyncgen_hooks_desc variable static PyStructSequence_Desc asyncgen_hooks_desc +Python/sysmodule.c - asyncgen_hooks_fields variable static PyStructSequence_Field asyncgen_hooks_fields[] +Python/sysmodule.c - AsyncGenHooksType variable static PyTypeObject AsyncGenHooksType +Objects/genobject.c - async_gen_memberlist variable static PyMemberDef async_gen_memberlist[] +Objects/genobject.c - async_gen_methods variable static PyMethodDef async_gen_methods +Python/Python-ast.c - AsyncWith_fields variable static char *AsyncWith_fields[] +Python/Python-ast.c - AsyncWith_type variable static PyTypeObject *AsyncWith_type +Parser/listnode.c - atbol variable static int atbol +Modules/atexitmodule.c - atexit_methods variable static PyMethodDef atexit_methods +Modules/atexitmodule.c - atexitmodule variable static struct PyModuleDef atexitmodule +Modules/atexitmodule.c - atexit_slots variable static PyModuleDef_Slot atexit_slots[] +Modules/_operator.c - attrgetter_methods variable static PyMethodDef attrgetter_methods +Modules/_operator.c - attrgetter_type variable static PyTypeObject attrgetter_type +Python/Python-ast.c - Attribute_fields variable static char *Attribute_fields[] +Python/Python-ast.c - Attribute_type variable static PyTypeObject *Attribute_type +Python/Python-ast.c - AugAssign_fields variable static char *AugAssign_fields[] +Python/Python-ast.c - AugAssign_type variable static PyTypeObject *AugAssign_type +Python/Python-ast.c - AugLoad_singleton variable PyObject *AugLoad_singleton +Python/Python-ast.c - AugLoad_type variable static PyTypeObject *AugLoad_type +Python/Python-ast.c - AugStore_singleton variable PyObject *AugStore_singleton +Python/Python-ast.c - AugStore_type variable static PyTypeObject *AugStore_type +Python/Python-ast.c - Await_fields variable static char *Await_fields[] +Python/Python-ast.c - Await_type variable static PyTypeObject *Await_type +Objects/exceptions.c - BaseException_getset variable static PyGetSetDef BaseException_getset[] +Objects/exceptions.c - BaseException_members variable static struct PyMemberDef BaseException_members[] +Objects/exceptions.c - BaseException_methods variable static PyMethodDef BaseException_methods +Modules/posixmodule.c - billion variable static PyObject *billion +Python/Python-ast.c - BinOp_fields variable static char *BinOp_fields[] +Python/Python-ast.c - BinOp_type variable static PyTypeObject *BinOp_type +Python/Python-ast.c - BitAnd_singleton variable static PyObject *BitAnd_singleton +Python/Python-ast.c - BitAnd_type variable static PyTypeObject *BitAnd_type +Python/Python-ast.c - BitOr_singleton variable static PyObject *BitOr_singleton +Python/Python-ast.c - BitOr_type variable static PyTypeObject *BitOr_type +Python/Python-ast.c - BitXor_singleton variable static PyObject *BitXor_singleton +Python/Python-ast.c - BitXor_type variable static PyTypeObject *BitXor_type +Objects/unicodeobject.c - bloom_linebreak variable static BLOOM_MASK bloom_linebreak +Objects/boolobject.c - bool_as_number variable static PyNumberMethods bool_as_number +Python/Python-ast.c - BoolOp_fields variable static char *BoolOp_fields[] +Python/Python-ast.c - boolop_type variable static PyTypeObject *boolop_type +Python/Python-ast.c - BoolOp_type variable static PyTypeObject *BoolOp_type +Python/_warnings.c is_internal_frame bootstrap_string variable static PyObject *bootstrap_string +Python/Python-ast.c - Break_type variable static PyTypeObject *Break_type +Python/ast.c decode_unicode_with_escapes buf variable char *buf +Modules/_io/bufferedio.c - bufferediobase_methods variable static PyMethodDef bufferediobase_methods +Modules/_io/bufferedio.c - bufferedrandom_getset variable static PyGetSetDef bufferedrandom_getset[] +Modules/_io/bufferedio.c - bufferedrandom_members variable static PyMemberDef bufferedrandom_members[] +Modules/_io/bufferedio.c - bufferedrandom_methods variable static PyMethodDef bufferedrandom_methods +Modules/_io/bufferedio.c - bufferedreader_getset variable static PyGetSetDef bufferedreader_getset[] +Modules/_io/bufferedio.c - bufferedreader_members variable static PyMemberDef bufferedreader_members[] +Modules/_io/bufferedio.c - bufferedreader_methods variable static PyMethodDef bufferedreader_methods +Modules/_io/bufferedio.c - bufferedrwpair_getset variable static PyGetSetDef bufferedrwpair_getset[] +Modules/_io/bufferedio.c - bufferedrwpair_methods variable static PyMethodDef bufferedrwpair_methods +Modules/_io/bufferedio.c - bufferedwriter_getset variable static PyGetSetDef bufferedwriter_getset[] +Modules/_io/bufferedio.c - bufferedwriter_members variable static PyMemberDef bufferedwriter_members[] +Modules/_io/bufferedio.c - bufferedwriter_methods variable static PyMethodDef bufferedwriter_methods +Modules/getbuildinfo.c Py_GetBuildInfo buildinfo variable static char buildinfo[50 + sizeof(GITVERSION) + ((sizeof(GITTAG) > sizeof(GITBRANCH)) ? sizeof(GITTAG) : sizeof(GITBRANCH))] +Python/bltinmodule.c - builtin_methods variable static PyMethodDef builtin_methods +Python/bltinmodule.c - builtinsmodule variable static struct PyModuleDef builtinsmodule +Python/import.c PyImport_Import builtins_str variable static PyObject *builtins_str +Python/ceval.c make_pending_calls busy variable static int busy +Objects/bytearrayobject.c - bytearray_as_buffer variable static PyBufferProcs bytearray_as_buffer +Objects/bytearrayobject.c - bytearray_as_mapping variable static PyMappingMethods bytearray_as_mapping +Objects/bytearrayobject.c - bytearray_as_number variable static PyNumberMethods bytearray_as_number +Objects/bytearrayobject.c - bytearray_as_sequence variable static PySequenceMethods bytearray_as_sequence +Objects/bytearrayobject.c - bytearrayiter_methods variable static PyMethodDef bytearrayiter_methods +Objects/bytearrayobject.c - bytearray_methods variable static PyMethodDef bytearray_methods +Objects/bytesobject.c - bytes_as_buffer variable static PyBufferProcs bytes_as_buffer +Objects/bytesobject.c - bytes_as_mapping variable static PyMappingMethods bytes_as_mapping +Objects/bytesobject.c - bytes_as_number variable static PyNumberMethods bytes_as_number +Objects/bytesobject.c - bytes_as_sequence variable static PySequenceMethods bytes_as_sequence +Modules/_io/bytesio.c - bytesiobuf_as_buffer variable static PyBufferProcs bytesiobuf_as_buffer +Modules/_io/bytesio.c - bytesio_getsetlist variable static PyGetSetDef bytesio_getsetlist[] +Modules/_io/bytesio.c - bytesio_methods variable static PyMethodDef bytesio_methods +Objects/bytesobject.c - bytes_methods variable static PyMethodDef bytes_methods +Python/thread_pthread.h init_condattr ca variable static pthread_condattr_t ca +Python/Python-ast.c - Call_fields variable static char *Call_fields[] +Objects/iterobject.c - calliter_methods variable static PyMethodDef calliter_methods +Python/Python-ast.c - Call_type variable static PyTypeObject *Call_type +Objects/cellobject.c - cell_getsetlist variable static PyGetSetDef cell_getsetlist[] +Modules/itertoolsmodule.c - chain_methods variable static PyMethodDef chain_methods +Modules/itertoolsmodule.c - chain_type variable static PyTypeObject chain_type +Objects/bytesobject.c - characters variable static PyBytesObject *characters[UCHAR_MAX + 1] +Python/symtable.c - __class__ variable static identifier __class__ +Python/Python-ast.c - ClassDef_fields variable static char *ClassDef_fields[] +Python/Python-ast.c - ClassDef_type variable static PyTypeObject *ClassDef_type +Objects/funcobject.c - cm_getsetlist variable static PyGetSetDef cm_getsetlist[] +Objects/funcobject.c - cm_memberlist variable static PyMemberDef cm_memberlist[] +Python/Python-ast.c - cmpop_type variable static PyTypeObject *cmpop_type +Modules/_codecsmodule.c - _codecs_functions variable static PyMethodDef _codecs_functions[] +Modules/_codecsmodule.c - codecsmodule variable static struct PyModuleDef codecsmodule +Objects/codeobject.c - code_memberlist variable static PyMemberDef code_memberlist[] +Objects/codeobject.c - code_methods variable static PyMethodDef code_methods +Modules/_collectionsmodule.c - _collectionsmodule variable static struct PyModuleDef _collectionsmodule +Modules/itertoolsmodule.c - combinations_methods variable static PyMethodDef combinations_methods +Modules/itertoolsmodule.c - combinations_type variable static PyTypeObject combinations_type +Objects/typeobject.c object_new comma_id variable "_Py_static_string(comma_id, "", "")" +Python/Python-ast.c - Compare_fields variable static char *Compare_fields[] +Python/Python-ast.c - Compare_type variable static PyTypeObject *Compare_type +Objects/complexobject.c - complex_as_number variable static PyNumberMethods complex_as_number +Objects/complexobject.c - complex_members variable static PyMemberDef complex_members[] +Objects/complexobject.c - complex_methods variable static PyMethodDef complex_methods +Python/Python-ast.c - comprehension_fields variable static char *comprehension_fields[] +Python/Python-ast.c - comprehension_type variable static PyTypeObject *comprehension_type +Modules/itertoolsmodule.c - compress_methods variable static PyMethodDef compress_methods +Modules/itertoolsmodule.c - compress_type variable static PyTypeObject compress_type +Python/thread_pthread.h - condattr_monotonic variable static pthread_condattr_t *condattr_monotonic +Python/Python-ast.c - Constant_fields variable static char *Constant_fields[] +Python/Python-ast.c - Constant_type variable static PyTypeObject *Constant_type +Python/Python-ast.c - Continue_type variable static PyTypeObject *Continue_type +Objects/longobject.c PyLong_FromString convmultmax_base variable static twodigits convmultmax_base[37] +Objects/longobject.c PyLong_FromString convwidth_base variable static int convwidth_base[37] +Objects/genobject.c - coro_as_async variable static PyAsyncMethods coro_as_async +Objects/genobject.c - coro_getsetlist variable static PyGetSetDef coro_getsetlist[] +Objects/genobject.c - coro_memberlist variable static PyMemberDef coro_memberlist[] +Objects/genobject.c - coro_methods variable static PyMethodDef coro_methods +Objects/genobject.c - coro_wrapper_methods variable static PyMethodDef coro_wrapper_methods +Modules/itertoolsmodule.c - count_methods variable static PyMethodDef count_methods +Modules/itertoolsmodule.c - count_type variable static PyTypeObject count_type +Python/context.c - ctx_freelist variable static PyContext *ctx_freelist +Python/context.c - ctx_freelist_len variable static int ctx_freelist_len +Modules/itertoolsmodule.c - cwr_methods variable static PyMethodDef cwr_methods +Modules/itertoolsmodule.c - cwr_type variable static PyTypeObject cwr_type +Modules/itertoolsmodule.c - cycle_methods variable static PyMethodDef cycle_methods +Modules/itertoolsmodule.c - cycle_type variable static PyTypeObject cycle_type +Objects/obmalloc.c new_arena debug_stats variable static int debug_stats +Modules/signalmodule.c - DefaultHandler variable static PyObject *DefaultHandler +Modules/_collectionsmodule.c - defdict_members variable static PyMemberDef defdict_members[] +Modules/_collectionsmodule.c - defdict_methods variable static PyMethodDef defdict_methods +Modules/_collectionsmodule.c - defdict_type variable static PyTypeObject defdict_type +Python/Python-ast.c - Delete_fields variable static char *Delete_fields[] +Python/Python-ast.c - Delete_type variable static PyTypeObject *Delete_type +Python/Python-ast.c - Del_singleton variable PyObject *Del_singleton +Python/Python-ast.c - Del_type variable static PyTypeObject *Del_type +Modules/_collectionsmodule.c - deque_as_number variable static PyNumberMethods deque_as_number +Modules/_collectionsmodule.c - deque_as_sequence variable static PySequenceMethods deque_as_sequence +Modules/_collectionsmodule.c - deque_getset variable static PyGetSetDef deque_getset[] +Modules/_collectionsmodule.c - dequeiter_methods variable static PyMethodDef dequeiter_methods +Modules/_collectionsmodule.c - dequeiter_type variable static PyTypeObject dequeiter_type +Modules/_collectionsmodule.c - deque_methods variable static PyMethodDef deque_methods +Modules/_collectionsmodule.c - dequereviter_type variable static PyTypeObject dequereviter_type +Modules/_collectionsmodule.c - deque_type variable static PyTypeObject deque_type +Objects/descrobject.c - descr_members variable static PyMemberDef descr_members[] +Objects/descrobject.c - descr_methods variable static PyMethodDef descr_methods +Modules/_abc.c - _destroy_def variable static PyMethodDef _destroy_def +Objects/floatobject.c - detected_double_format variable static float_format_type detected_double_format +Objects/floatobject.c - detected_float_format variable static float_format_type detected_float_format +Objects/dictobject.c - dict_as_mapping variable static PyMappingMethods dict_as_mapping +Objects/dictobject.c - dict_as_sequence variable static PySequenceMethods dict_as_sequence +Python/symtable.c - dictcomp variable static identifier dictcomp +Python/Python-ast.c - DictComp_fields variable static char *DictComp_fields[] +Python/Python-ast.c - DictComp_type variable static PyTypeObject *DictComp_type +Python/Python-ast.c - Dict_fields variable static char *Dict_fields[] +Objects/dictobject.c - dictitems_as_sequence variable static PySequenceMethods dictitems_as_sequence +Objects/dictobject.c - dictitems_methods variable static PyMethodDef dictitems_methods +Objects/dictobject.c - dictiter_methods variable static PyMethodDef dictiter_methods +Objects/dictobject.c - dictkeys_as_sequence variable static PySequenceMethods dictkeys_as_sequence +Objects/dictobject.c - dictkeys_methods variable static PyMethodDef dictkeys_methods +Python/Python-ast.c - Dict_type variable static PyTypeObject *Dict_type +Objects/dictobject.c - dictvalues_as_sequence variable static PySequenceMethods dictvalues_as_sequence +Objects/dictobject.c - dictvalues_methods variable static PyMethodDef dictvalues_methods +Objects/dictobject.c - dictviews_as_number variable static PyNumberMethods dictviews_as_number +Modules/posixmodule.c - DirEntry_members variable static PyMemberDef DirEntry_members[] +Modules/posixmodule.c - DirEntry_methods variable static PyMethodDef DirEntry_methods +Modules/posixmodule.c - DirEntryType variable static PyTypeObject DirEntryType +Python/Python-ast.c - Div_singleton variable static PyObject *Div_singleton +Python/Python-ast.c - Div_type variable static PyTypeObject *Div_type +Python/compile.c - __doc__ variable static PyObject *__doc__ +Objects/classobject.c method_get_doc docstr variable static PyObject *docstr +Objects/classobject.c instancemethod_get_doc docstr variable static PyObject *docstr +Python/compile.c compiler_set_qualname dot variable "_Py_static_string(dot, ""."")" +Python/compile.c compiler_set_qualname dot_locals variable "_Py_static_string(dot_locals, ""."")" +Objects/floatobject.c - double_format variable static float_format_type double_format +Modules/itertoolsmodule.c - dropwhile_methods variable static PyMethodDef dropwhile_methods +Modules/itertoolsmodule.c - dropwhile_type variable static PyTypeObject dropwhile_type +Objects/setobject.c - _dummy_struct variable static PyObject _dummy_struct +Modules/posixmodule.c os_dup2_impl dup3_works variable static int dup3_works +Modules/_io/bufferedio.c _PyIO_trap_eintr eintr_int variable static PyObject *eintr_int +Objects/sliceobject.c - ellipsis_methods variable static PyMethodDef ellipsis_methods +Python/hamt.c - _empty_bitmap_node variable static PyHamtNode_Bitmap *_empty_bitmap_node +Objects/setobject.c - emptyfrozenset variable static PyObject *emptyfrozenset +Python/hamt.c - _empty_hamt variable static PyHamtObject *_empty_hamt +Objects/dictobject.c - empty_keys_struct variable static PyDictKeysObject empty_keys_struct +Objects/codeobject.c PyCode_NewEmpty emptystring variable static PyObject *emptystring +Python/compile.c compiler_from_import empty_string variable static PyObject *empty_string +Objects/dictobject.c - empty_values variable static PyObject *empty_values[1] +Objects/unicodeobject.c - encoding_map_methods variable static PyMethodDef encoding_map_methods +Objects/unicodeobject.c - EncodingMapType variable static PyTypeObject EncodingMapType +Objects/enumobject.c - enum_methods variable static PyMethodDef enum_methods +Python/Python-ast.c - Eq_singleton variable static PyObject *Eq_singleton +Python/Python-ast.c - Eq_type variable static PyTypeObject *Eq_type +Objects/exceptions.c - errnomap variable static PyObject *errnomap +Modules/errnomodule.c - errno_methods variable static PyMethodDef errno_methods +Modules/errnomodule.c - errnomodule variable static struct PyModuleDef errnomodule +Modules/_localemodule.c - Error variable static PyObject *Error +Python/Python-ast.c - excepthandler_attributes variable static char *excepthandler_attributes[] +Python/Python-ast.c - ExceptHandler_fields variable static char *ExceptHandler_fields[] +Python/Python-ast.c - excepthandler_type variable static PyTypeObject *excepthandler_type +Python/Python-ast.c - ExceptHandler_type variable static PyTypeObject *ExceptHandler_type +Modules/_threadmodule.c - ExceptHookArgs_desc variable static PyStructSequence_Desc ExceptHookArgs_desc +Modules/_threadmodule.c - ExceptHookArgs_fields variable static PyStructSequence_Field ExceptHookArgs_fields[] +Modules/_threadmodule.c - ExceptHookArgsType variable static PyTypeObject ExceptHookArgsType +Objects/exceptions.c _check_for_legacy_statements exec_prefix variable static PyObject *exec_prefix +Python/Python-ast.c - expr_attributes variable static char *expr_attributes[] +Python/Python-ast.c - expr_context_type variable static PyTypeObject *expr_context_type +Python/Python-ast.c - Expression_fields variable static char *Expression_fields[] +Python/Python-ast.c - Expression_type variable static PyTypeObject *Expression_type +Python/Python-ast.c - Expr_fields variable static char *Expr_fields[] +Python/Python-ast.c - expr_type variable static PyTypeObject *expr_type +Python/Python-ast.c - Expr_type variable static PyTypeObject *Expr_type +Python/import.c - extensions variable static PyObject *extensions +Python/Python-ast.c - ExtSlice_fields variable static char *ExtSlice_fields[] +Python/Python-ast.c - ExtSlice_type variable static PyTypeObject *ExtSlice_type +Objects/boolobject.c - false_str variable static PyObject *false_str +Modules/faulthandler.c - fatal_error variable static struct { int enabled; PyObject *file; int fd; int all_threads; PyInterpreterState *interp; void *exc_handler; } fatal_error +Modules/faulthandler.c - faulthandler_handlers variable static fault_handler_t faulthandler_handlers[] +Objects/stringlib/unicode_format.h - fieldnameiter_methods variable static PyMethodDef fieldnameiter_methods +Modules/_io/fileio.c - fileio_getsetlist variable static PyGetSetDef fileio_getsetlist[] +Modules/_io/fileio.c - fileio_members variable static PyMemberDef fileio_members[] +Modules/_io/fileio.c - fileio_methods variable static PyMethodDef fileio_methods +Modules/itertoolsmodule.c - filterfalse_methods variable static PyMethodDef filterfalse_methods +Modules/itertoolsmodule.c - filterfalse_type variable static PyTypeObject filterfalse_type +Python/bltinmodule.c - filter_methods variable static PyMethodDef filter_methods +Python/sysmodule.c - flags_desc variable static PyStructSequence_Desc flags_desc +Python/sysmodule.c - flags_fields variable static PyStructSequence_Field flags_fields[] +Python/sysmodule.c - FlagsType variable static PyTypeObject FlagsType +Objects/floatobject.c - float_as_number variable static PyNumberMethods float_as_number +Objects/floatobject.c - float_format variable static float_format_type +Objects/floatobject.c - float_getset variable static PyGetSetDef float_getset[] +Objects/floatobject.c - floatinfo_desc variable static PyStructSequence_Desc floatinfo_desc +Objects/floatobject.c - floatinfo_fields variable static PyStructSequence_Field floatinfo_fields[] +Objects/floatobject.c - FloatInfoType variable static PyTypeObject FloatInfoType +Objects/floatobject.c - float_methods variable static PyMethodDef float_methods +Python/Python-ast.c - FloorDiv_singleton variable static PyObject *FloorDiv_singleton +Python/Python-ast.c - FloorDiv_type variable static PyTypeObject *FloorDiv_type +Python/fileutils.c - force_ascii variable static int force_ascii +Python/Python-ast.c - For_fields variable static char *For_fields[] +Python/Python-ast.c - FormattedValue_fields variable static char *FormattedValue_fields[] +Python/Python-ast.c - FormattedValue_type variable static PyTypeObject *FormattedValue_type +Objects/stringlib/unicode_format.h - formatteriter_methods variable static PyMethodDef formatteriter_methods +Python/Python-ast.c - For_type variable static PyTypeObject *For_type +Objects/frameobject.c - frame_getsetlist variable static PyGetSetDef frame_getsetlist[] +Objects/frameobject.c - frame_memberlist variable static PyMemberDef frame_memberlist[] +Objects/frameobject.c - frame_methods variable static PyMethodDef frame_methods +Modules/_collectionsmodule.c - freeblocks variable static block *freeblocks[MAXFREEBLOCKS] +Python/dtoa.c - freelist variable static Bigint *freelist[Kmax+1] +Objects/floatobject.c - free_list variable static PyFloatObject *free_list +Objects/frameobject.c - free_list variable static PyFrameObject *free_list +Objects/listobject.c - free_list variable static PyListObject *free_list[PyList_MAXFREELIST] +Objects/dictobject.c - free_list variable static PyDictObject *free_list[PyDict_MAXFREELIST] +Objects/methodobject.c - free_list variable static PyCFunctionObject *free_list +Objects/tupleobject.c - free_list variable static PyTupleObject *free_list[PyTuple_MAXSAVESIZE] +Objects/classobject.c - free_list variable static PyMethodObject *free_list +Objects/setobject.c - frozenset_as_number variable static PyNumberMethods frozenset_as_number +Objects/setobject.c - frozenset_methods variable static PyMethodDef frozenset_methods +Objects/funcobject.c - func_getsetlist variable static PyGetSetDef func_getsetlist[] +Objects/funcobject.c - func_memberlist variable static PyMemberDef func_memberlist[] +Python/Python-ast.c - FunctionDef_fields variable static char *FunctionDef_fields[] +Python/Python-ast.c - FunctionDef_type variable static PyTypeObject *FunctionDef_type +Modules/_sre.c - _functions variable static PyMethodDef _functions[] +Python/Python-ast.c - FunctionType_fields variable static char *FunctionType_fields[] +Python/Python-ast.c - FunctionType_type variable static PyTypeObject *FunctionType_type +Modules/_functoolsmodule.c - _functoolsmodule variable static struct PyModuleDef _functoolsmodule +Modules/gcmodule.c - GcMethods variable static PyMethodDef GcMethods[] +Modules/gcmodule.c - gcmodule variable static struct PyModuleDef gcmodule +Modules/gcmodule.c - gc_str variable static PyObject *gc_str +Python/Python-ast.c - GeneratorExp_fields variable static char *GeneratorExp_fields[] +Python/Python-ast.c - GeneratorExp_type variable static PyTypeObject *GeneratorExp_type +Python/symtable.c - genexpr variable static identifier genexpr +Objects/genobject.c - gen_getsetlist variable static PyGetSetDef gen_getsetlist[] +Objects/genobject.c - gen_memberlist variable static PyMemberDef gen_memberlist[] +Objects/genobject.c - gen_methods variable static PyMethodDef gen_methods +Python/bootstrap_hash.c py_getrandom getrandom_works variable static int getrandom_works +Objects/descrobject.c - getset_getset variable static PyGetSetDef getset_getset[] +Python/Python-ast.c - Global_fields variable static char *Global_fields[] +Python/Python-ast.c - Global_type variable static PyTypeObject *Global_type +Modules/itertoolsmodule.c - groupby_methods variable static PyMethodDef groupby_methods +Modules/itertoolsmodule.c - groupby_type variable static PyTypeObject groupby_type +Modules/itertoolsmodule.c - _grouper_methods variable static PyMethodDef _grouper_methods +Modules/itertoolsmodule.c - _grouper_type variable static PyTypeObject _grouper_type +Python/Python-ast.c - GtE_singleton variable static PyObject *GtE_singleton +Python/Python-ast.c - GtE_type variable static PyTypeObject *GtE_type +Python/Python-ast.c - Gt_singleton variable static PyObject *Gt_singleton +Python/Python-ast.c - Gt_type variable static PyTypeObject *Gt_type +Modules/signalmodule.c - Handlers variable static volatile struct { _Py_atomic_int tripped; PyObject *func; } Handlers[NSIG] +Python/dynload_shlib.c - handles variable static struct { dev_t dev; ino_t ino; void *handle; } handles[128] +Python/sysmodule.c - hash_info_desc variable static PyStructSequence_Desc hash_info_desc +Python/sysmodule.c - hash_info_fields variable static PyStructSequence_Field hash_info_fields[] +Python/sysmodule.c - Hash_InfoType variable static PyTypeObject Hash_InfoType +Python/import.c import_find_and_load header variable static int header +Modules/_elementtree.c _elementtree_Element___deepcopy___impl id variable PyObject* id +Objects/obmalloc.c _PyMem_DebugCheckAddress id variable char id +Objects/obmalloc.c _PyObject_DebugDumpAddress id variable char id +Python/ast.c ast_for_dotted_name id variable identifier id +Python/Python-ast.c obj2ast_expr id variable identifier id +Modules/_xxsubinterpretersmodule.c _channels_next_id id variable int64_t id +Modules/_xxsubinterpretersmodule.c _channels_add id variable int64_t id +Modules/_xxsubinterpretersmodule.c _channel_create id variable int64_t id +Modules/_xxsubinterpretersmodule.c interp_get_main id variable PY_INT64_T id +Objects/interpreteridobject.c _Py_CoerceID id variable int64_t id +Objects/interpreteridobject.c interpid_new id variable int64_t id +Objects/interpreteridobject.c interpid_dealloc id variable int64_t id +Objects/interpreteridobject.c _PyInterpreterID_LookUp id variable int64_t id +Objects/interpreteridobject.c _PyInterpreterState_GetIDObject id variable PY_INT64_T id +Python/pystate.c interp_look_up_id id variable PY_INT64_T id +??? ??? id variable ??? +??? ??? id variable ??? +??? ??? id variable ??? +??? ??? id variable ??? +Python/Python-ast.c - IfExp_fields variable static char *IfExp_fields[] +Python/Python-ast.c - IfExp_type variable static PyTypeObject *IfExp_type +Python/Python-ast.c - If_fields variable static char *If_fields[] +Python/Python-ast.c - If_type variable static PyTypeObject *If_type +Modules/signalmodule.c - IgnoreHandler variable static PyObject *IgnoreHandler +Python/import.c - imp_methods variable static PyMethodDef imp_methods +Python/import.c - impmodule variable static struct PyModuleDef impmodule +Objects/exceptions.c - ImportError_members variable static PyMemberDef ImportError_members[] +Objects/exceptions.c - ImportError_methods variable static PyMethodDef ImportError_methods +Python/Python-ast.c - Import_fields variable static char *Import_fields[] +Python/Python-ast.c - ImportFrom_fields variable static char *ImportFrom_fields[] +Python/Python-ast.c - ImportFrom_type variable static PyTypeObject *ImportFrom_type +Python/import.c import_find_and_load import_level variable static int import_level +Python/_warnings.c is_internal_frame importlib_string variable static PyObject *importlib_string +Python/import.c - import_lock variable static PyThread_type_lock import_lock +Python/import.c - import_lock_level variable static int import_lock_level +Python/import.c - import_lock_thread variable static unsigned long import_lock_thread +Python/import.c PyImport_Import import_str variable static PyObject *import_str +Python/Python-ast.c - Import_type variable static PyTypeObject *Import_type +Modules/_io/textio.c - incrementalnewlinedecoder_getset variable static PyGetSetDef incrementalnewlinedecoder_getset[] +Modules/_io/textio.c - incrementalnewlinedecoder_methods variable static PyMethodDef incrementalnewlinedecoder_methods +Objects/listobject.c - indexerr variable static PyObject *indexerr +Python/Python-ast.c - Index_fields variable static char *Index_fields[] +Python/Python-ast.c - Index_type variable static PyTypeObject *Index_type +Python/thread.c - initialized variable static int initialized +Modules/posixmodule.c - initialized variable static int initialized +Modules/pwdmodule.c - initialized variable static int initialized +Modules/signalmodule.c - initialized variable static int initialized +Modules/timemodule.c - initialized variable static int initialized +Python/Python-ast.c init_types initialized variable static int initialized +Objects/listobject.c PyList_New initialized variable static int initialized +Python/import.c - inittab_copy variable static struct _inittab *inittab_copy +Python/Python-ast.c - In_singleton variable static PyObject *In_singleton +Objects/classobject.c - instancemethod_getset variable static PyGetSetDef instancemethod_getset[] +Objects/classobject.c - instancemethod_memberlist variable static PyMemberDef instancemethod_memberlist[] +Python/Python-ast.c - Interactive_fields variable static char *Interactive_fields[] +Python/Python-ast.c - Interactive_type variable static PyTypeObject *Interactive_type +Objects/unicodeobject.c - interned variable static PyObject *interned +Objects/interpreteridobject.c - interpid_as_number variable static PyNumberMethods interpid_as_number +Modules/signalmodule.c - IntHandler variable static PyObject *IntHandler +Objects/longobject.c - int_info_desc variable static PyStructSequence_Desc int_info_desc +Objects/longobject.c - int_info_fields variable static PyStructSequence_Field int_info_fields[] +Objects/longobject.c - Int_InfoType variable static PyTypeObject Int_InfoType +Python/Python-ast.c - In_type variable static PyTypeObject *In_type +Python/Python-ast.c - Invert_singleton variable static PyObject *Invert_singleton +Python/Python-ast.c - Invert_type variable static PyTypeObject *Invert_type +Modules/_io/iobase.c - iobase_getset variable static PyGetSetDef iobase_getset[] +Modules/_io/iobase.c - iobase_methods variable static PyMethodDef iobase_methods +Python/fileutils.c set_inheritable ioctl_works variable static int ioctl_works +Modules/itertoolsmodule.c - islice_methods variable static PyMethodDef islice_methods +Modules/itertoolsmodule.c - islice_type variable static PyTypeObject islice_type +Python/Python-ast.c - IsNot_singleton variable static PyObject *IsNot_singleton +Python/Python-ast.c - IsNot_type variable static PyTypeObject *IsNot_type +Python/Python-ast.c - Is_singleton variable static PyObject *Is_singleton +Modules/signalmodule.c - is_tripped variable static _Py_atomic_int is_tripped +Python/Python-ast.c - Is_type variable static PyTypeObject *Is_type +Modules/_operator.c - itemgetter_methods variable static PyMethodDef itemgetter_methods +Modules/_operator.c - itemgetter_type variable static PyTypeObject itemgetter_type +Modules/itertoolsmodule.c - itertoolsmodule variable static struct PyModuleDef itertoolsmodule +Modules/signalmodule.c - ItimerError variable static PyObject *ItimerError +Python/Python-ast.c - JoinedStr_fields variable static char *JoinedStr_fields[] +Python/Python-ast.c - JoinedStr_type variable static PyTypeObject *JoinedStr_type +Modules/_functoolsmodule.c - keyobject_members variable static PyMemberDef keyobject_members[] +Modules/_functoolsmodule.c - keyobject_type variable static PyTypeObject keyobject_type +Objects/dictobject.c - keys_free_list variable static PyDictKeysObject *keys_free_list[PyDict_MAXFREELIST] +Python/Python-ast.c - keyword_fields variable static char *keyword_fields[] +Python/sysmodule.c sys_set_asyncgen_hooks keywords variable static char *keywords[] +Modules/_bisectmodule.c bisect_right keywords variable static char *keywords[] +Modules/_bisectmodule.c insort_right keywords variable static char *keywords[] +Python/Python-ast.c - keyword_type variable static PyTypeObject *keyword_type +Modules/_functoolsmodule.c keyobject_call kwargs variable static char *kwargs[] +Modules/_functoolsmodule.c functools_cmp_to_key kwargs variable static char *kwargs[] +Modules/itertoolsmodule.c repeat_new kwargs variable static char *kwargs[] +Python/_warnings.c warnings_warn_explicit kwd_list variable static char *kwd_list[] +Modules/_functoolsmodule.c - kwd_mark variable static PyObject *kwd_mark +Python/bltinmodule.c builtin___import__ kwlist variable static char *kwlist[] +Python/bltinmodule.c min_max kwlist variable static char *kwlist[] +Python/context.c contextvar_tp_new kwlist variable static char *kwlist[] +Python/sysmodule.c sys_getsizeof kwlist variable static char *kwlist[] +Objects/bytearrayobject.c bytearray_init kwlist variable static char *kwlist[] +Objects/bytesobject.c bytes_new kwlist variable static char *kwlist[] +Objects/exceptions.c ImportError_init kwlist variable static char *kwlist[] +Objects/interpreteridobject.c interpid_new kwlist variable static char *kwlist[] +Objects/memoryobject.c memory_new kwlist variable static char *kwlist[] +Objects/memoryobject.c memory_cast kwlist variable static char *kwlist[] +Objects/memoryobject.c memory_tobytes kwlist variable static char *kwlist[] +Objects/odictobject.c odict_pop kwlist variable static char *kwlist[] +Objects/unicodeobject.c unicode_new kwlist variable static char *kwlist[] +Objects/weakrefobject.c weakref_call kwlist variable static char *kwlist[] +Modules/_elementtree.c element_setstate_from_Python kwlist variable static char *kwlist[] +Modules/_json.c scanner_call kwlist variable static char *kwlist[] +Modules/_json.c scanner_new kwlist variable static char *kwlist[] +Modules/_json.c encoder_new kwlist variable static char *kwlist[] +Modules/_json.c encoder_call kwlist variable static char *kwlist[] +Python/symtable.c - lambda variable static identifier lambda +Python/Python-ast.c - Lambda_fields variable static char *Lambda_fields[] +Python/Python-ast.c - Lambda_type variable static PyTypeObject *Lambda_type +Parser/listnode.c - level variable static int level +Objects/listobject.c - list_as_mapping variable static PyMappingMethods list_as_mapping +Objects/listobject.c - list_as_sequence variable static PySequenceMethods list_as_sequence +Python/symtable.c - listcomp variable static identifier listcomp +Python/Python-ast.c - ListComp_fields variable static char *ListComp_fields[] +Python/Python-ast.c - ListComp_type variable static PyTypeObject *ListComp_type +Python/Python-ast.c - List_fields variable static char *List_fields[] +Objects/listobject.c - listiter_methods variable static PyMethodDef listiter_methods +Objects/listobject.c - list_methods variable static PyMethodDef list_methods +Objects/listobject.c - listreviter_methods variable static PyMethodDef listreviter_methods +Python/Python-ast.c - List_type variable static PyTypeObject *List_type +Python/ceval.c - lltrace variable static int lltrace +Python/Python-ast.c - Load_singleton variable PyObject *Load_singleton +Python/Python-ast.c - Load_type variable static PyTypeObject *Load_type +Modules/_threadmodule.c - localdummytype variable static PyTypeObject localdummytype +Modules/_localemodule.c - _localemodule variable static struct PyModuleDef _localemodule +Modules/_threadmodule.c - localtype variable static PyTypeObject localtype +Modules/_threadmodule.c - lock_methods variable static PyMethodDef lock_methods +Modules/_threadmodule.c - Locktype variable static PyTypeObject Locktype +Objects/longobject.c PyLong_FromString log_base_BASE variable static double log_base_BASE[37] +Objects/longobject.c - long_as_number variable static PyNumberMethods long_as_number +Objects/longobject.c - long_getset variable static PyGetSetDef long_getset[] +Objects/longobject.c - long_methods variable static PyMethodDef long_methods +Objects/rangeobject.c - longrangeiter_methods variable static PyMethodDef longrangeiter_methods +Modules/_functoolsmodule.c - lru_cache_getsetlist variable static PyGetSetDef lru_cache_getsetlist[] +Modules/_functoolsmodule.c - lru_cache_methods variable static PyMethodDef lru_cache_methods +Modules/_functoolsmodule.c - lru_cache_type variable static PyTypeObject lru_cache_type +Modules/_functoolsmodule.c - lru_list_elem_type variable static PyTypeObject lru_list_elem_type +Python/Python-ast.c - LShift_singleton variable static PyObject *LShift_singleton +Python/Python-ast.c - LShift_type variable static PyTypeObject *LShift_type +Python/Python-ast.c - LtE_singleton variable static PyObject *LtE_singleton +Python/Python-ast.c - LtE_type variable static PyTypeObject *LtE_type +Python/Python-ast.c - Lt_singleton variable static PyObject *Lt_singleton +Python/Python-ast.c - Lt_type variable static PyTypeObject *Lt_type +Python/bltinmodule.c - map_methods variable static PyMethodDef map_methods +Objects/descrobject.c - mappingproxy_as_mapping variable static PyMappingMethods mappingproxy_as_mapping +Objects/descrobject.c - mappingproxy_as_sequence variable static PySequenceMethods mappingproxy_as_sequence +Objects/descrobject.c - mappingproxy_methods variable static PyMethodDef mappingproxy_methods +Objects/dictobject.c - mapp_methods variable static PyMethodDef mapp_methods +Python/marshal.c - marshal_methods variable static PyMethodDef marshal_methods +Python/marshal.c - marshalmodule variable static struct PyModuleDef marshalmodule +Modules/_sre.c - match_as_mapping variable static PyMappingMethods match_as_mapping +Modules/_sre.c - match_getset variable static PyGetSetDef match_getset[] +Modules/_sre.c - match_members variable static PyMemberDef match_members[] +Modules/_sre.c - match_methods variable static PyMethodDef match_methods +Modules/_sre.c - Match_Type variable static PyTypeObject Match_Type +Python/Python-ast.c - MatMult_singleton variable static PyObject *MatMult_singleton +Python/Python-ast.c - MatMult_type variable static PyTypeObject *MatMult_type +Objects/obmalloc.c - maxarenas variable static uint maxarenas +Objects/moduleobject.c - max_module_number variable static Py_ssize_t max_module_number +Objects/descrobject.c - member_getset variable static PyGetSetDef member_getset[] +Objects/exceptions.c - memerrors_freelist variable static PyBaseExceptionObject *memerrors_freelist +Objects/exceptions.c - memerrors_numfree variable static int memerrors_numfree +Objects/memoryobject.c - memory_as_buffer variable static PyBufferProcs memory_as_buffer +Objects/memoryobject.c - memory_as_mapping variable static PyMappingMethods memory_as_mapping +Objects/memoryobject.c - memory_as_sequence variable static PySequenceMethods memory_as_sequence +Objects/memoryobject.c - memory_getsetlist variable static PyGetSetDef memory_getsetlist[] +Objects/memoryobject.c - memory_methods variable static PyMethodDef memory_methods +Objects/methodobject.c - meth_getsets variable static PyGetSetDef meth_getsets [] +Objects/methodobject.c - meth_members variable static PyMemberDef meth_members[] +Objects/methodobject.c - meth_methods variable static PyMethodDef meth_methods +Objects/typeobject.c - method_cache variable static struct method_cache_entry method_cache[1 << MCACHE_SIZE_EXP] +Modules/_operator.c - methodcaller_methods variable static PyMethodDef methodcaller_methods +Modules/_operator.c - methodcaller_type variable static PyTypeObject methodcaller_type +Objects/classobject.c - method_getset variable static PyGetSetDef method_getset[] +Objects/descrobject.c - method_getset variable static PyGetSetDef method_getset[] +Objects/classobject.c - method_memberlist variable static PyMemberDef method_memberlist[] +Objects/classobject.c - method_methods variable static PyMethodDef method_methods +Python/codecs.c _PyCodecRegistry_Init methods variable static struct { char *name; PyMethodDef def; } methods[] +Python/frozen.c - M___hello__ variable static unsigned char M___hello__[] +Python/Python-ast.c - Mod_singleton variable static PyObject *Mod_singleton +Python/Python-ast.c - mod_type variable static PyTypeObject *mod_type +Python/Python-ast.c - Mod_type variable static PyTypeObject *Mod_type +Python/_warnings.c normalize_module module variable PyObject *module +Modules/faulthandler.c - module_def variable static struct PyModuleDef module_def +Modules/_tracemalloc.c - module_def variable static struct PyModuleDef module_def +Python/Python-ast.c - Module_fields variable static char *Module_fields[] +Modules/_collectionsmodule.c - module_functions variable static struct PyMethodDef module_functions[] +Modules/_abc.c - module_functions variable static struct PyMethodDef module_functions[] +Objects/moduleobject.c - module_members variable static PyMemberDef module_members[] +Objects/moduleobject.c - module_methods variable static PyMethodDef module_methods +Modules/_functoolsmodule.c - module_methods variable static PyMethodDef module_methods +Modules/itertoolsmodule.c - module_methods variable static PyMethodDef module_methods +Modules/_io/_iomodule.c - module_methods variable static PyMethodDef module_methods +Modules/faulthandler.c - module_methods variable static PyMethodDef module_methods +Modules/_tracemalloc.c - module_methods variable static PyMethodDef module_methods +Python/Python-ast.c - Module_type variable static PyTypeObject *Module_type +Python/Python-ast.c - Mult_singleton variable static PyObject *Mult_singleton +Python/Python-ast.c - Mult_type variable static PyTypeObject *Mult_type +Objects/funcobject.c PyFunction_NewWithQualName __name__ variable static PyObject *__name__ +Python/compile.c compiler_lambda name variable static identifier name +Python/compile.c compiler_genexp name variable static identifier name +Python/compile.c compiler_listcomp name variable static identifier name +Python/compile.c compiler_setcomp name variable static identifier name +Python/compile.c compiler_dictcomp name variable static identifier name +Python/Python-ast.c - NamedExpr_fields variable static char *NamedExpr_fields[] +Python/Python-ast.c - NamedExpr_type variable static PyTypeObject *NamedExpr_type +Python/Python-ast.c - Name_fields variable static char *Name_fields[] +Objects/typeobject.c - name_op variable static _Py_Identifier name_op[] +Objects/namespaceobject.c - namespace_members variable static PyMemberDef namespace_members[] +Objects/namespaceobject.c - namespace_methods variable static PyMethodDef namespace_methods +Python/Python-ast.c - Name_type variable static PyTypeObject *Name_type +Objects/obmalloc.c - narenas_currently_allocated variable static size_t narenas_currently_allocated +Objects/obmalloc.c - narenas_highwater variable static size_t narenas_highwater +Python/sysmodule.c sys_displayhook newline variable static PyObject *newline +Objects/typeobject.c - next_version_tag variable static unsigned int next_version_tag +Objects/obmalloc.c - nfp2lasta variable static struct arena_object* nfp2lasta[MAX_POOLS_IN_ARENA + 1] +Python/dynload_shlib.c - nhandles variable static int nhandles +Objects/object.c - none_as_number variable static PyNumberMethods none_as_number +Python/Python-ast.c - Nonlocal_fields variable static char *Nonlocal_fields[] +Python/Python-ast.c - Nonlocal_type variable static PyTypeObject *Nonlocal_type +Python/Python-ast.c - NotEq_singleton variable static PyObject *NotEq_singleton +Python/Python-ast.c - NotEq_type variable static PyTypeObject *NotEq_type +Objects/object.c - notimplemented_methods variable static PyMethodDef notimplemented_methods +Python/Python-ast.c - NotIn_singleton variable static PyObject *NotIn_singleton +Python/Python-ast.c - NotIn_type variable static PyTypeObject *NotIn_type +Python/Python-ast.c - Not_singleton variable static PyObject *Not_singleton +Python/Python-ast.c - Not_type variable static PyTypeObject *Not_type +Objects/obmalloc.c - ntimes_arena_allocated variable static size_t ntimes_arena_allocated +Objects/bytesobject.c - nullstring variable static PyBytesObject *nullstring +Objects/codeobject.c PyCode_NewEmpty nulltuple variable static PyObject *nulltuple +Objects/floatobject.c - numfree variable static int numfree +Objects/frameobject.c - numfree variable static int numfree +Objects/listobject.c - numfree variable static int numfree +Objects/dictobject.c - numfree variable static int numfree +Objects/methodobject.c - numfree variable static int numfree +Objects/tupleobject.c - numfree variable static int numfree[PyTuple_MAXSAVESIZE] +Objects/classobject.c - numfree variable static int numfree +Modules/_collectionsmodule.c - numfreeblocks variable static Py_ssize_t numfreeblocks +Objects/dictobject.c - numfreekeys variable static int numfreekeys +Objects/typeobject.c - object_getsets variable static PyGetSetDef object_getsets[] +Objects/typeobject.c - object_methods variable static PyMethodDef object_methods +Objects/typeobject.c object___reduce_ex___impl objreduce variable static PyObject *objreduce +Objects/odictobject.c - odict_as_mapping variable static PyMappingMethods odict_as_mapping +Objects/odictobject.c - odict_getset variable static PyGetSetDef odict_getset[] +Objects/odictobject.c - odictitems_methods variable static PyMethodDef odictitems_methods +Objects/odictobject.c - odictiter_methods variable static PyMethodDef odictiter_methods +Objects/odictobject.c - odictkeys_methods variable static PyMethodDef odictkeys_methods +Objects/odictobject.c - odict_methods variable static PyMethodDef odict_methods +Objects/odictobject.c - odictvalues_methods variable static PyMethodDef odictvalues_methods +Modules/faulthandler.c - old_stack variable static stack_t old_stack +Modules/_operator.c - operator_methods variable static PyMethodDef operator_methods +Modules/_operator.c - operatormodule variable static struct PyModuleDef operatormodule +Python/Python-ast.c - operator_type variable static PyTypeObject *operator_type +Objects/typeobject.c slot_nb_add op_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_subtract op_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_multiply op_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_matrix_multiply op_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_remainder op_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_divmod op_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_power_binary op_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_lshift op_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_rshift op_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_and op_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_xor op_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_or op_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_floor_divide op_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_true_divide op_id variable _Py_static_string(op_id, OPSTR) +Python/getopt.c - opt_ptr variable static const wchar_t *opt_ptr +Python/initconfig.c - orig_argv variable static PyWideStringList orig_argv +Python/Python-ast.c - Or_singleton variable PyObject *Or_singleton +Python/Python-ast.c - Or_type variable static PyTypeObject *Or_type +Objects/exceptions.c - OSError_getset variable static PyGetSetDef OSError_getset[] +Objects/exceptions.c - OSError_members variable static PyMemberDef OSError_members[] +Objects/exceptions.c - OSError_methods variable static PyMethodDef OSError_methods +Python/dtoa.c - p5s variable static Bigint *p5s +Python/Python-ast.c - Param_singleton variable PyObject *Param_singleton +Python/Python-ast.c - Param_type variable static PyTypeObject *Param_type +Python/bltinmodule.c builtin_print _parser variable static struct _PyArg_Parser _parser +Python/clinic/_warnings.c.h warnings_warn _parser variable static _PyArg_Parser _parser +Python/clinic/bltinmodule.c.h builtin_compile _parser variable static _PyArg_Parser _parser +Python/clinic/bltinmodule.c.h builtin_round _parser variable static _PyArg_Parser _parser +Python/clinic/bltinmodule.c.h builtin_sum _parser variable static _PyArg_Parser _parser +Python/clinic/import.c.h _imp_source_hash _parser variable static _PyArg_Parser _parser +Python/clinic/sysmodule.c.h sys_addaudithook _parser variable static _PyArg_Parser _parser +Python/clinic/sysmodule.c.h sys_set_coroutine_origin_tracking_depth _parser variable static _PyArg_Parser _parser +Python/clinic/traceback.c.h tb_new _parser variable static _PyArg_Parser _parser +Objects/clinic/bytearrayobject.c.h bytearray_translate _parser variable static _PyArg_Parser _parser +Objects/clinic/bytearrayobject.c.h bytearray_split _parser variable static _PyArg_Parser _parser +Objects/clinic/bytearrayobject.c.h bytearray_rsplit _parser variable static _PyArg_Parser _parser +Objects/clinic/bytearrayobject.c.h bytearray_decode _parser variable static _PyArg_Parser _parser +Objects/clinic/bytearrayobject.c.h bytearray_splitlines _parser variable static _PyArg_Parser _parser +Objects/clinic/bytearrayobject.c.h bytearray_hex _parser variable static _PyArg_Parser _parser +Objects/clinic/bytesobject.c.h bytes_split _parser variable static _PyArg_Parser _parser +Objects/clinic/bytesobject.c.h bytes_rsplit _parser variable static _PyArg_Parser _parser +Objects/clinic/bytesobject.c.h bytes_translate _parser variable static _PyArg_Parser _parser +Objects/clinic/bytesobject.c.h bytes_decode _parser variable static _PyArg_Parser _parser +Objects/clinic/bytesobject.c.h bytes_splitlines _parser variable static _PyArg_Parser _parser +Objects/clinic/bytesobject.c.h bytes_hex _parser variable static _PyArg_Parser _parser +Objects/clinic/codeobject.c.h code_replace _parser variable static _PyArg_Parser _parser +Objects/clinic/complexobject.c.h complex_new _parser variable static _PyArg_Parser _parser +Objects/clinic/descrobject.c.h mappingproxy_new _parser variable static _PyArg_Parser _parser +Objects/clinic/descrobject.c.h property_init _parser variable static _PyArg_Parser _parser +Objects/clinic/enumobject.c.h enum_new _parser variable static _PyArg_Parser _parser +Objects/clinic/funcobject.c.h func_new _parser variable static _PyArg_Parser _parser +Objects/clinic/listobject.c.h list_sort _parser variable static _PyArg_Parser _parser +Objects/clinic/longobject.c.h long_new _parser variable static _PyArg_Parser _parser +Objects/clinic/longobject.c.h int_to_bytes _parser variable static _PyArg_Parser _parser +Objects/clinic/longobject.c.h int_from_bytes _parser variable static _PyArg_Parser _parser +Objects/clinic/memoryobject.c.h memoryview_hex _parser variable static _PyArg_Parser _parser +Objects/clinic/moduleobject.c.h module___init__ _parser variable static _PyArg_Parser _parser +Objects/clinic/odictobject.c.h OrderedDict_fromkeys _parser variable static _PyArg_Parser _parser +Objects/clinic/odictobject.c.h OrderedDict_setdefault _parser variable static _PyArg_Parser _parser +Objects/clinic/odictobject.c.h OrderedDict_popitem _parser variable static _PyArg_Parser _parser +Objects/clinic/odictobject.c.h OrderedDict_move_to_end _parser variable static _PyArg_Parser _parser +Objects/clinic/structseq.c.h structseq_new _parser variable static _PyArg_Parser _parser +Objects/clinic/unicodeobject.c.h unicode_encode _parser variable static _PyArg_Parser _parser +Objects/clinic/unicodeobject.c.h unicode_expandtabs _parser variable static _PyArg_Parser _parser +Objects/clinic/unicodeobject.c.h unicode_split _parser variable static _PyArg_Parser _parser +Objects/clinic/unicodeobject.c.h unicode_rsplit _parser variable static _PyArg_Parser _parser +Objects/clinic/unicodeobject.c.h unicode_splitlines _parser variable static _PyArg_Parser _parser +Objects/stringlib/clinic/transmogrify.h.h stringlib_expandtabs _parser variable static _PyArg_Parser _parser +Modules/_blake2/clinic/blake2b_impl.c.h py_blake2b_new _parser variable static _PyArg_Parser _parser +Modules/_blake2/clinic/blake2s_impl.c.h py_blake2s_new _parser variable static _PyArg_Parser _parser +Modules/_io/clinic/_iomodule.c.h _io_open _parser variable static _PyArg_Parser _parser +Modules/_io/clinic/_iomodule.c.h _io_open_code _parser variable static _PyArg_Parser _parser +Modules/_io/clinic/bufferedio.c.h _io_BufferedReader___init__ _parser variable static _PyArg_Parser _parser +Modules/_io/clinic/bufferedio.c.h _io_BufferedWriter___init__ _parser variable static _PyArg_Parser _parser +Modules/_io/clinic/bufferedio.c.h _io_BufferedRandom___init__ _parser variable static _PyArg_Parser _parser +Modules/_io/clinic/bytesio.c.h _io_BytesIO___init__ _parser variable static _PyArg_Parser _parser +Modules/_io/clinic/fileio.c.h _io_FileIO___init__ _parser variable static _PyArg_Parser _parser +Modules/_io/clinic/stringio.c.h _io_StringIO___init__ _parser variable static _PyArg_Parser _parser +Modules/_io/clinic/textio.c.h _io_IncrementalNewlineDecoder___init__ _parser variable static _PyArg_Parser _parser +Modules/_io/clinic/textio.c.h _io_IncrementalNewlineDecoder_decode _parser variable static _PyArg_Parser _parser +Modules/_io/clinic/textio.c.h _io_TextIOWrapper___init__ _parser variable static _PyArg_Parser _parser +Modules/_io/clinic/textio.c.h _io_TextIOWrapper_reconfigure _parser variable static _PyArg_Parser _parser +Modules/_io/clinic/winconsoleio.c.h _io__WindowsConsoleIO___init__ _parser variable static _PyArg_Parser _parser +Modules/_multiprocessing/clinic/posixshmem.c.h _posixshmem_shm_open _parser variable static _PyArg_Parser _parser +Modules/_multiprocessing/clinic/posixshmem.c.h _posixshmem_shm_unlink _parser variable static _PyArg_Parser _parser +Modules/cjkcodecs/clinic/multibytecodec.c.h _multibytecodec_MultibyteCodec_encode _parser variable static _PyArg_Parser _parser +Modules/cjkcodecs/clinic/multibytecodec.c.h _multibytecodec_MultibyteCodec_decode _parser variable static _PyArg_Parser _parser +Modules/cjkcodecs/clinic/multibytecodec.c.h _multibytecodec_MultibyteIncrementalEncoder_encode _parser variable static _PyArg_Parser _parser +Modules/cjkcodecs/clinic/multibytecodec.c.h _multibytecodec_MultibyteIncrementalDecoder_decode _parser variable static _PyArg_Parser _parser +Modules/clinic/_asynciomodule.c.h _asyncio_Future___init__ _parser variable static _PyArg_Parser _parser +Modules/clinic/_asynciomodule.c.h _asyncio_Future_add_done_callback _parser variable static _PyArg_Parser _parser +Modules/clinic/_asynciomodule.c.h _asyncio_Task___init__ _parser variable static _PyArg_Parser _parser +Modules/clinic/_asynciomodule.c.h _asyncio_Task_current_task _parser variable static _PyArg_Parser _parser +Modules/clinic/_asynciomodule.c.h _asyncio_Task_all_tasks _parser variable static _PyArg_Parser _parser +Modules/clinic/_asynciomodule.c.h _asyncio_Task_get_stack _parser variable static _PyArg_Parser _parser +Modules/clinic/_asynciomodule.c.h _asyncio_Task_print_stack _parser variable static _PyArg_Parser _parser +Modules/clinic/_asynciomodule.c.h _asyncio__register_task _parser variable static _PyArg_Parser _parser +Modules/clinic/_asynciomodule.c.h _asyncio__unregister_task _parser variable static _PyArg_Parser _parser +Modules/clinic/_asynciomodule.c.h _asyncio__enter_task _parser variable static _PyArg_Parser _parser +Modules/clinic/_asynciomodule.c.h _asyncio__leave_task _parser variable static _PyArg_Parser _parser +Modules/clinic/_bz2module.c.h _bz2_BZ2Decompressor_decompress _parser variable static _PyArg_Parser _parser +Modules/clinic/_codecsmodule.c.h _codecs_encode _parser variable static _PyArg_Parser _parser +Modules/clinic/_codecsmodule.c.h _codecs_decode _parser variable static _PyArg_Parser _parser +Modules/clinic/_cursesmodule.c.h _curses_setupterm _parser variable static _PyArg_Parser _parser +Modules/clinic/_datetimemodule.c.h datetime_datetime_now _parser variable static _PyArg_Parser _parser +Modules/clinic/_elementtree.c.h _elementtree_Element_find _parser variable static _PyArg_Parser _parser +Modules/clinic/_elementtree.c.h _elementtree_Element_findtext _parser variable static _PyArg_Parser _parser +Modules/clinic/_elementtree.c.h _elementtree_Element_findall _parser variable static _PyArg_Parser _parser +Modules/clinic/_elementtree.c.h _elementtree_Element_iterfind _parser variable static _PyArg_Parser _parser +Modules/clinic/_elementtree.c.h _elementtree_Element_get _parser variable static _PyArg_Parser _parser +Modules/clinic/_elementtree.c.h _elementtree_Element_iter _parser variable static _PyArg_Parser _parser +Modules/clinic/_elementtree.c.h _elementtree_Element_getiterator _parser variable static _PyArg_Parser _parser +Modules/clinic/_elementtree.c.h _elementtree_TreeBuilder___init__ _parser variable static _PyArg_Parser _parser +Modules/clinic/_elementtree.c.h _elementtree_XMLParser___init__ _parser variable static _PyArg_Parser _parser +Modules/clinic/_hashopenssl.c.h EVP_new _parser variable static _PyArg_Parser _parser +Modules/clinic/_hashopenssl.c.h pbkdf2_hmac _parser variable static _PyArg_Parser _parser +Modules/clinic/_hashopenssl.c.h _hashlib_scrypt _parser variable static _PyArg_Parser _parser +Modules/clinic/_hashopenssl.c.h _hashlib_hmac_digest _parser variable static _PyArg_Parser _parser +Modules/clinic/_lzmamodule.c.h _lzma_LZMADecompressor_decompress _parser variable static _PyArg_Parser _parser +Modules/clinic/_lzmamodule.c.h _lzma_LZMADecompressor___init__ _parser variable static _PyArg_Parser _parser +Modules/clinic/_opcode.c.h _opcode_stack_effect _parser variable static _PyArg_Parser _parser +Modules/clinic/_pickle.c.h _pickle_Pickler___init__ _parser variable static _PyArg_Parser _parser +Modules/clinic/_pickle.c.h _pickle_Unpickler___init__ _parser variable static _PyArg_Parser _parser +Modules/clinic/_pickle.c.h _pickle_dump _parser variable static _PyArg_Parser _parser +Modules/clinic/_pickle.c.h _pickle_dumps _parser variable static _PyArg_Parser _parser +Modules/clinic/_pickle.c.h _pickle_load _parser variable static _PyArg_Parser _parser +Modules/clinic/_pickle.c.h _pickle_loads _parser variable static _PyArg_Parser _parser +Modules/clinic/_queuemodule.c.h _queue_SimpleQueue_put _parser variable static _PyArg_Parser _parser +Modules/clinic/_queuemodule.c.h _queue_SimpleQueue_put_nowait _parser variable static _PyArg_Parser _parser +Modules/clinic/_queuemodule.c.h _queue_SimpleQueue_get _parser variable static _PyArg_Parser _parser +Modules/clinic/_sre.c.h _sre_SRE_Pattern_match _parser variable static _PyArg_Parser _parser +Modules/clinic/_sre.c.h _sre_SRE_Pattern_fullmatch _parser variable static _PyArg_Parser _parser +Modules/clinic/_sre.c.h _sre_SRE_Pattern_search _parser variable static _PyArg_Parser _parser +Modules/clinic/_sre.c.h _sre_SRE_Pattern_findall _parser variable static _PyArg_Parser _parser +Modules/clinic/_sre.c.h _sre_SRE_Pattern_finditer _parser variable static _PyArg_Parser _parser +Modules/clinic/_sre.c.h _sre_SRE_Pattern_scanner _parser variable static _PyArg_Parser _parser +Modules/clinic/_sre.c.h _sre_SRE_Pattern_split _parser variable static _PyArg_Parser _parser +Modules/clinic/_sre.c.h _sre_SRE_Pattern_sub _parser variable static _PyArg_Parser _parser +Modules/clinic/_sre.c.h _sre_SRE_Pattern_subn _parser variable static _PyArg_Parser _parser +Modules/clinic/_sre.c.h _sre_compile _parser variable static _PyArg_Parser _parser +Modules/clinic/_sre.c.h _sre_SRE_Match_expand _parser variable static _PyArg_Parser _parser +Modules/clinic/_sre.c.h _sre_SRE_Match_groups _parser variable static _PyArg_Parser _parser +Modules/clinic/_sre.c.h _sre_SRE_Match_groupdict _parser variable static _PyArg_Parser _parser +Modules/clinic/_ssl.c.h _ssl__SSLSocket_get_channel_binding _parser variable static _PyArg_Parser _parser +Modules/clinic/_ssl.c.h _ssl__SSLContext_load_cert_chain _parser variable static _PyArg_Parser _parser +Modules/clinic/_ssl.c.h _ssl__SSLContext_load_verify_locations _parser variable static _PyArg_Parser _parser +Modules/clinic/_ssl.c.h _ssl__SSLContext__wrap_socket _parser variable static _PyArg_Parser _parser +Modules/clinic/_ssl.c.h _ssl__SSLContext__wrap_bio _parser variable static _PyArg_Parser _parser +Modules/clinic/_ssl.c.h _ssl__SSLContext_get_ca_certs _parser variable static _PyArg_Parser _parser +Modules/clinic/_ssl.c.h _ssl_txt2obj _parser variable static _PyArg_Parser _parser +Modules/clinic/_ssl.c.h _ssl_enum_certificates _parser variable static _PyArg_Parser _parser +Modules/clinic/_ssl.c.h _ssl_enum_crls _parser variable static _PyArg_Parser _parser +Modules/clinic/_struct.c.h Struct___init__ _parser variable static _PyArg_Parser _parser +Modules/clinic/_struct.c.h Struct_unpack_from _parser variable static _PyArg_Parser _parser +Modules/clinic/_struct.c.h unpack_from _parser variable static _PyArg_Parser _parser +Modules/clinic/_winapi.c.h _winapi_ConnectNamedPipe _parser variable static _PyArg_Parser _parser +Modules/clinic/_winapi.c.h _winapi_ReadFile _parser variable static _PyArg_Parser _parser +Modules/clinic/_winapi.c.h _winapi_WriteFile _parser variable static _PyArg_Parser _parser +Modules/clinic/_winapi.c.h _winapi_GetFileType _parser variable static _PyArg_Parser _parser +Modules/clinic/binascii.c.h binascii_b2a_uu _parser variable static _PyArg_Parser _parser +Modules/clinic/binascii.c.h binascii_b2a_base64 _parser variable static _PyArg_Parser _parser +Modules/clinic/binascii.c.h binascii_b2a_hex _parser variable static _PyArg_Parser _parser +Modules/clinic/binascii.c.h binascii_hexlify _parser variable static _PyArg_Parser _parser +Modules/clinic/binascii.c.h binascii_a2b_qp _parser variable static _PyArg_Parser _parser +Modules/clinic/binascii.c.h binascii_b2a_qp _parser variable static _PyArg_Parser _parser +Modules/clinic/cmathmodule.c.h cmath_isclose _parser variable static _PyArg_Parser _parser +Modules/clinic/gcmodule.c.h gc_collect _parser variable static _PyArg_Parser _parser +Modules/clinic/gcmodule.c.h gc_get_objects _parser variable static _PyArg_Parser _parser +Modules/clinic/grpmodule.c.h grp_getgrgid _parser variable static _PyArg_Parser _parser +Modules/clinic/grpmodule.c.h grp_getgrnam _parser variable static _PyArg_Parser _parser +Modules/_functoolsmodule.c - partial_getsetlist variable static PyGetSetDef partial_getsetlist[] +Modules/_functoolsmodule.c - partial_memberlist variable static PyMemberDef partial_memberlist[] +Modules/_functoolsmodule.c - partial_methods variable static PyMethodDef partial_methods +Modules/_functoolsmodule.c - partial_type variable static PyTypeObject partial_type +Python/Python-ast.c - Pass_type variable static PyTypeObject *Pass_type +Modules/_sre.c - pattern_getset variable static PyGetSetDef pattern_getset[] +Modules/_sre.c - pattern_members variable static PyMemberDef pattern_members[] +Modules/_sre.c - pattern_methods variable static PyMethodDef pattern_methods +Modules/_sre.c - Pattern_Type variable static PyTypeObject Pattern_Type +Modules/itertoolsmodule.c - permuations_methods variable static PyMethodDef permuations_methods +Modules/itertoolsmodule.c - permutations_type variable static PyTypeObject permutations_type +Objects/picklebufobject.c - picklebuf_as_buffer variable static PyBufferProcs picklebuf_as_buffer +Objects/picklebufobject.c - picklebuf_methods variable static PyMethodDef picklebuf_methods +Python/dtoa.c - pmem_next variable static double *pmem_next +Objects/typeobject.c resolve_slotdups pname variable static PyObject *pname +Modules/posixmodule.c - posix_constants_confstr variable static struct constdef posix_constants_confstr[] +Modules/posixmodule.c - posix_constants_pathconf variable static struct constdef posix_constants_pathconf[] +Modules/posixmodule.c - posix_constants_sysconf variable static struct constdef posix_constants_sysconf[] +Modules/posixmodule.c - posix_methods variable static PyMethodDef posix_methods +Modules/posixmodule.c - posixmodule variable static struct PyModuleDef posixmodule +Modules/posixmodule.c - posix_putenv_garbage variable static PyObject *posix_putenv_garbage +Python/Python-ast.c - Pow_singleton variable static PyObject *Pow_singleton +Python/Python-ast.c - Pow_type variable static PyTypeObject *Pow_type +Python/sysmodule.c - _preinit_warnoptions variable static _Py_PreInitEntry _preinit_warnoptions +Python/sysmodule.c - _preinit_xoptions variable static _Py_PreInitEntry _preinit_xoptions +Objects/exceptions.c _check_for_legacy_statements print_prefix variable static PyObject *print_prefix +Python/dtoa.c - private_mem variable static double private_mem[PRIVATE_mem] +Modules/itertoolsmodule.c - product_methods variable static PyMethodDef product_methods +Modules/itertoolsmodule.c - product_type variable static PyTypeObject product_type +Objects/descrobject.c - property_getsetlist variable static PyGetSetDef property_getsetlist[] +Objects/descrobject.c - property_members variable static PyMemberDef property_members[] +Objects/descrobject.c - property_methods variable static PyMethodDef property_methods +Objects/weakrefobject.c - proxy_as_mapping variable static PyMappingMethods proxy_as_mapping +Objects/weakrefobject.c - proxy_as_number variable static PyNumberMethods proxy_as_number +Objects/weakrefobject.c - proxy_as_sequence variable static PySequenceMethods proxy_as_sequence +Objects/weakrefobject.c - proxy_methods variable static PyMethodDef proxy_methods +Objects/typeobject.c resolve_slotdups ptrs variable static slotdef *ptrs[MAX_EQUIV] +Modules/pwdmodule.c - pwd_methods variable static PyMethodDef pwd_methods +Modules/pwdmodule.c - pwdmodule variable static struct PyModuleDef pwdmodule +Objects/object.c - _Py_abstract_hack variable Py_ssize_t (*_Py_abstract_hack)(PyObject *) +Objects/obmalloc.c - _Py_AllocatedBlocks variable static Py_ssize_t _Py_AllocatedBlocks +Objects/genobject.c - _PyAsyncGenASend_Type variable PyTypeObject _PyAsyncGenASend_Type +Objects/genobject.c - _PyAsyncGenAThrow_Type variable PyTypeObject _PyAsyncGenAThrow_Type +Objects/genobject.c - PyAsyncGen_Type variable PyTypeObject PyAsyncGen_Type +Objects/genobject.c - _PyAsyncGenWrappedValue_Type variable PyTypeObject _PyAsyncGenWrappedValue_Type +Objects/typeobject.c - PyBaseObject_Type variable PyTypeObject PyBaseObject_Type +Objects/boolobject.c - PyBool_Type variable PyTypeObject PyBool_Type +Modules/_io/bufferedio.c - PyBufferedIOBase_Type variable PyTypeObject PyBufferedIOBase_Type +Modules/_io/bufferedio.c - PyBufferedRandom_Type variable PyTypeObject PyBufferedRandom_Type +Modules/_io/bufferedio.c - PyBufferedReader_Type variable PyTypeObject PyBufferedReader_Type +Modules/_io/bufferedio.c - PyBufferedRWPair_Type variable PyTypeObject PyBufferedRWPair_Type +Modules/_io/bufferedio.c - PyBufferedWriter_Type variable PyTypeObject PyBufferedWriter_Type +Objects/bytearrayobject.c - _PyByteArray_empty_string variable char _PyByteArray_empty_string[] +Objects/bytearrayobject.c - PyByteArrayIter_Type variable PyTypeObject PyByteArrayIter_Type +Objects/bytearrayobject.c - PyByteArray_Type variable PyTypeObject PyByteArray_Type +Modules/_io/bytesio.c - _PyBytesIOBuffer_Type variable PyTypeObject _PyBytesIOBuffer_Type +Modules/_io/bytesio.c - PyBytesIO_Type variable PyTypeObject PyBytesIO_Type +Objects/bytesobject.c - PyBytesIter_Type variable PyTypeObject PyBytesIter_Type +Objects/bytesobject.c - PyBytes_Type variable PyTypeObject PyBytes_Type +Python/initconfig.c - Py_BytesWarningFlag variable int Py_BytesWarningFlag +Objects/iterobject.c - PyCallIter_Type variable PyTypeObject PyCallIter_Type +Objects/capsule.c - PyCapsule_Type variable PyTypeObject PyCapsule_Type +Objects/cellobject.c - PyCell_Type variable PyTypeObject PyCell_Type +Objects/methodobject.c - PyCFunction_Type variable PyTypeObject PyCFunction_Type +Python/ceval.c - _Py_CheckRecursionLimit variable int _Py_CheckRecursionLimit +Objects/descrobject.c - PyClassMethodDescr_Type variable PyTypeObject PyClassMethodDescr_Type +Objects/funcobject.c - PyClassMethod_Type variable PyTypeObject PyClassMethod_Type +Objects/codeobject.c - PyCode_Type variable PyTypeObject PyCode_Type +Objects/complexobject.c - PyComplex_Type variable PyTypeObject PyComplex_Type +Python/context.c - PyContext_as_mapping variable static PyMappingMethods PyContext_as_mapping +Python/context.c - PyContext_as_sequence variable static PySequenceMethods PyContext_as_sequence +Python/context.c - PyContext_methods variable static PyMethodDef PyContext_methods +Python/context.c - PyContextTokenMissing_Type variable PyTypeObject PyContextTokenMissing_Type +Python/context.c - PyContextToken_Type variable PyTypeObject PyContextToken_Type +Python/context.c - PyContextTokenType_getsetlist variable static PyGetSetDef PyContextTokenType_getsetlist[] +Python/context.c - PyContext_Type variable PyTypeObject PyContext_Type +Python/context.c - PyContextVar_members variable static PyMemberDef PyContextVar_members[] +Python/context.c - PyContextVar_methods variable static PyMethodDef PyContextVar_methods +Python/context.c - PyContextVar_Type variable PyTypeObject PyContextVar_Type +Objects/genobject.c - PyCoro_Type variable PyTypeObject PyCoro_Type +Objects/genobject.c - _PyCoroWrapper_Type variable PyTypeObject _PyCoroWrapper_Type +Python/initconfig.c - Py_DebugFlag variable int Py_DebugFlag +Objects/dictobject.c - pydict_global_version variable static uint64_t pydict_global_version +Objects/dictobject.c - PyDictItems_Type variable PyTypeObject PyDictItems_Type +Objects/dictobject.c - PyDictIterItem_Type variable PyTypeObject PyDictIterItem_Type +Objects/dictobject.c - PyDictIterKey_Type variable PyTypeObject PyDictIterKey_Type +Objects/dictobject.c - PyDictIterValue_Type variable PyTypeObject PyDictIterValue_Type +Objects/dictobject.c - PyDictKeys_Type variable PyTypeObject PyDictKeys_Type +Objects/descrobject.c - PyDictProxy_Type variable PyTypeObject PyDictProxy_Type +Objects/dictobject.c - PyDictRevIterItem_Type variable PyTypeObject PyDictRevIterItem_Type +Objects/dictobject.c - PyDictRevIterKey_Type variable PyTypeObject PyDictRevIterKey_Type +Objects/dictobject.c - PyDictRevIterValue_Type variable PyTypeObject PyDictRevIterValue_Type +Objects/dictobject.c - PyDict_Type variable PyTypeObject PyDict_Type +Objects/dictobject.c - PyDictValues_Type variable PyTypeObject PyDictValues_Type +Python/initconfig.c - Py_DontWriteBytecodeFlag variable int Py_DontWriteBytecodeFlag +Objects/sliceobject.c - _Py_EllipsisObject variable PyObject _Py_EllipsisObject +Objects/sliceobject.c - PyEllipsis_Type variable PyTypeObject PyEllipsis_Type +Objects/enumobject.c - PyEnum_Type variable PyTypeObject PyEnum_Type +Objects/exceptions.c - _PyExc_ArithmeticError variable static PyTypeObject _PyExc_ArithmeticError +Objects/exceptions.c - PyExc_ArithmeticError variable static PyTypeObject PyExc_ArithmeticError +Objects/exceptions.c - _PyExc_AssertionError variable static PyTypeObject _PyExc_AssertionError +Objects/exceptions.c - PyExc_AssertionError variable static PyTypeObject PyExc_AssertionError +Objects/exceptions.c - _PyExc_AttributeError variable static PyTypeObject _PyExc_AttributeError +Objects/exceptions.c - PyExc_AttributeError variable static PyTypeObject PyExc_AttributeError +Objects/exceptions.c - _PyExc_BaseException variable static PyTypeObject _PyExc_BaseException +Objects/exceptions.c - PyExc_BaseException variable static PyTypeObject PyExc_BaseException +Objects/exceptions.c - _PyExc_BlockingIOError variable static PyTypeObject _PyExc_BlockingIOError +Objects/exceptions.c - PyExc_BlockingIOError variable static PyTypeObject PyExc_BlockingIOError +Objects/exceptions.c - _PyExc_BrokenPipeError variable static PyTypeObject _PyExc_BrokenPipeError +Objects/exceptions.c - PyExc_BrokenPipeError variable static PyTypeObject PyExc_BrokenPipeError +Objects/exceptions.c - _PyExc_BufferError variable static PyTypeObject _PyExc_BufferError +Objects/exceptions.c - PyExc_BufferError variable static PyTypeObject PyExc_BufferError +Objects/exceptions.c - _PyExc_BytesWarning variable static PyTypeObject _PyExc_BytesWarning +Objects/exceptions.c - PyExc_BytesWarning variable static PyTypeObject PyExc_BytesWarning +Objects/exceptions.c - _PyExc_ChildProcessError variable static PyTypeObject _PyExc_ChildProcessError +Objects/exceptions.c - PyExc_ChildProcessError variable static PyTypeObject PyExc_ChildProcessError +Objects/exceptions.c - _PyExc_ConnectionAbortedError variable static PyTypeObject _PyExc_ConnectionAbortedError +Objects/exceptions.c - PyExc_ConnectionAbortedError variable static PyTypeObject PyExc_ConnectionAbortedError +Objects/exceptions.c - _PyExc_ConnectionError variable static PyTypeObject _PyExc_ConnectionError +Objects/exceptions.c - PyExc_ConnectionError variable static PyTypeObject PyExc_ConnectionError +Objects/exceptions.c - _PyExc_ConnectionRefusedError variable static PyTypeObject _PyExc_ConnectionRefusedError +Objects/exceptions.c - PyExc_ConnectionRefusedError variable static PyTypeObject PyExc_ConnectionRefusedError +Objects/exceptions.c - _PyExc_ConnectionResetError variable static PyTypeObject _PyExc_ConnectionResetError +Objects/exceptions.c - PyExc_ConnectionResetError variable static PyTypeObject PyExc_ConnectionResetError +Objects/exceptions.c - _PyExc_DeprecationWarning variable static PyTypeObject _PyExc_DeprecationWarning +Objects/exceptions.c - PyExc_DeprecationWarning variable static PyTypeObject PyExc_DeprecationWarning +Objects/exceptions.c - PyExc_EnvironmentError variable static PyTypeObject PyExc_EnvironmentError +Objects/exceptions.c - _PyExc_EOFError variable static PyTypeObject _PyExc_EOFError +Objects/exceptions.c - PyExc_EOFError variable static PyTypeObject PyExc_EOFError +Objects/exceptions.c - _PyExc_Exception variable static PyTypeObject _PyExc_Exception +Objects/exceptions.c - PyExc_Exception variable static PyTypeObject PyExc_Exception +Objects/exceptions.c - _PyExc_FileExistsError variable static PyTypeObject _PyExc_FileExistsError +Objects/exceptions.c - PyExc_FileExistsError variable static PyTypeObject PyExc_FileExistsError +Objects/exceptions.c - _PyExc_FileNotFoundError variable static PyTypeObject _PyExc_FileNotFoundError +Objects/exceptions.c - PyExc_FileNotFoundError variable static PyTypeObject PyExc_FileNotFoundError +Objects/exceptions.c - _PyExc_FloatingPointError variable static PyTypeObject _PyExc_FloatingPointError +Objects/exceptions.c - PyExc_FloatingPointError variable static PyTypeObject PyExc_FloatingPointError +Objects/exceptions.c - _PyExc_FutureWarning variable static PyTypeObject _PyExc_FutureWarning +Objects/exceptions.c - PyExc_FutureWarning variable static PyTypeObject PyExc_FutureWarning +Objects/exceptions.c - _PyExc_GeneratorExit variable static PyTypeObject _PyExc_GeneratorExit +Objects/exceptions.c - PyExc_GeneratorExit variable static PyTypeObject PyExc_GeneratorExit +Objects/exceptions.c - _PyExc_ImportError variable static PyTypeObject _PyExc_ImportError +Objects/exceptions.c - PyExc_ImportError variable static PyTypeObject PyExc_ImportError +Objects/exceptions.c - _PyExc_ImportWarning variable static PyTypeObject _PyExc_ImportWarning +Objects/exceptions.c - PyExc_ImportWarning variable static PyTypeObject PyExc_ImportWarning +Objects/exceptions.c - _PyExc_IndentationError variable static PyTypeObject _PyExc_IndentationError +Objects/exceptions.c - PyExc_IndentationError variable static PyTypeObject PyExc_IndentationError +Objects/exceptions.c - _PyExc_IndexError variable static PyTypeObject _PyExc_IndexError +Objects/exceptions.c - PyExc_IndexError variable static PyTypeObject PyExc_IndexError +Objects/exceptions.c - _PyExc_InterruptedError variable static PyTypeObject _PyExc_InterruptedError +Objects/exceptions.c - PyExc_InterruptedError variable static PyTypeObject PyExc_InterruptedError +Objects/exceptions.c - PyExc_IOError variable static PyTypeObject PyExc_IOError +Objects/exceptions.c - _PyExc_IsADirectoryError variable static PyTypeObject _PyExc_IsADirectoryError +Objects/exceptions.c - PyExc_IsADirectoryError variable static PyTypeObject PyExc_IsADirectoryError +Objects/exceptions.c - _PyExc_KeyboardInterrupt variable static PyTypeObject _PyExc_KeyboardInterrupt +Objects/exceptions.c - PyExc_KeyboardInterrupt variable static PyTypeObject PyExc_KeyboardInterrupt +Objects/exceptions.c - _PyExc_KeyError variable static PyTypeObject _PyExc_KeyError +Objects/exceptions.c - PyExc_KeyError variable static PyTypeObject PyExc_KeyError +Objects/exceptions.c - _PyExc_LookupError variable static PyTypeObject _PyExc_LookupError +Objects/exceptions.c - PyExc_LookupError variable static PyTypeObject PyExc_LookupError +Objects/exceptions.c - _PyExc_MemoryError variable static PyTypeObject _PyExc_MemoryError +Objects/exceptions.c - PyExc_MemoryError variable static PyTypeObject PyExc_MemoryError +Objects/exceptions.c - _PyExc_ModuleNotFoundError variable static PyTypeObject _PyExc_ModuleNotFoundError +Objects/exceptions.c - PyExc_ModuleNotFoundError variable static PyTypeObject PyExc_ModuleNotFoundError +Objects/exceptions.c - _PyExc_NameError variable static PyTypeObject _PyExc_NameError +Objects/exceptions.c - PyExc_NameError variable static PyTypeObject PyExc_NameError +Objects/exceptions.c - _PyExc_NotADirectoryError variable static PyTypeObject _PyExc_NotADirectoryError +Objects/exceptions.c - PyExc_NotADirectoryError variable static PyTypeObject PyExc_NotADirectoryError +Objects/exceptions.c - _PyExc_NotImplementedError variable static PyTypeObject _PyExc_NotImplementedError +Objects/exceptions.c - PyExc_NotImplementedError variable static PyTypeObject PyExc_NotImplementedError +Objects/exceptions.c - _PyExc_OSError variable static PyTypeObject _PyExc_OSError +Objects/exceptions.c - PyExc_OSError variable static PyTypeObject PyExc_OSError +Objects/exceptions.c - _PyExc_OverflowError variable static PyTypeObject _PyExc_OverflowError +Objects/exceptions.c - PyExc_OverflowError variable static PyTypeObject PyExc_OverflowError +Objects/exceptions.c - _PyExc_PendingDeprecationWarning variable static PyTypeObject _PyExc_PendingDeprecationWarning +Objects/exceptions.c - PyExc_PendingDeprecationWarning variable static PyTypeObject PyExc_PendingDeprecationWarning +Objects/exceptions.c - _PyExc_PermissionError variable static PyTypeObject _PyExc_PermissionError +Objects/exceptions.c - PyExc_PermissionError variable static PyTypeObject PyExc_PermissionError +Objects/exceptions.c - _PyExc_ProcessLookupError variable static PyTypeObject _PyExc_ProcessLookupError +Objects/exceptions.c - PyExc_ProcessLookupError variable static PyTypeObject PyExc_ProcessLookupError +Objects/exceptions.c - _PyExc_RecursionError variable static PyTypeObject _PyExc_RecursionError +Objects/exceptions.c - PyExc_RecursionError variable static PyTypeObject PyExc_RecursionError +Objects/exceptions.c - _PyExc_ReferenceError variable static PyTypeObject _PyExc_ReferenceError +Objects/exceptions.c - PyExc_ReferenceError variable static PyTypeObject PyExc_ReferenceError +Objects/exceptions.c - _PyExc_ResourceWarning variable static PyTypeObject _PyExc_ResourceWarning +Objects/exceptions.c - PyExc_ResourceWarning variable static PyTypeObject PyExc_ResourceWarning +Objects/exceptions.c - _PyExc_RuntimeError variable static PyTypeObject _PyExc_RuntimeError +Objects/exceptions.c - PyExc_RuntimeError variable static PyTypeObject PyExc_RuntimeError +Objects/exceptions.c - _PyExc_RuntimeWarning variable static PyTypeObject _PyExc_RuntimeWarning +Objects/exceptions.c - PyExc_RuntimeWarning variable static PyTypeObject PyExc_RuntimeWarning +Objects/exceptions.c - _PyExc_StopAsyncIteration variable static PyTypeObject _PyExc_StopAsyncIteration +Objects/exceptions.c - PyExc_StopAsyncIteration variable static PyTypeObject PyExc_StopAsyncIteration +Objects/exceptions.c - _PyExc_StopIteration variable static PyTypeObject _PyExc_StopIteration +Objects/exceptions.c - PyExc_StopIteration variable static PyTypeObject PyExc_StopIteration +Objects/exceptions.c - _PyExc_SyntaxError variable static PyTypeObject _PyExc_SyntaxError +Objects/exceptions.c - PyExc_SyntaxError variable static PyTypeObject PyExc_SyntaxError +Objects/exceptions.c - _PyExc_SyntaxWarning variable static PyTypeObject _PyExc_SyntaxWarning +Objects/exceptions.c - PyExc_SyntaxWarning variable static PyTypeObject PyExc_SyntaxWarning +Objects/exceptions.c - _PyExc_SystemError variable static PyTypeObject _PyExc_SystemError +Objects/exceptions.c - PyExc_SystemError variable static PyTypeObject PyExc_SystemError +Objects/exceptions.c - _PyExc_SystemExit variable static PyTypeObject _PyExc_SystemExit +Objects/exceptions.c - PyExc_SystemExit variable static PyTypeObject PyExc_SystemExit +Objects/exceptions.c - _PyExc_TabError variable static PyTypeObject _PyExc_TabError +Objects/exceptions.c - PyExc_TabError variable static PyTypeObject PyExc_TabError +Objects/exceptions.c - _PyExc_TargetScopeError variable static PyTypeObject _PyExc_TargetScopeError +Objects/exceptions.c - PyExc_TargetScopeError variable static PyTypeObject PyExc_TargetScopeError +Objects/exceptions.c - _PyExc_TimeoutError variable static PyTypeObject _PyExc_TimeoutError +Objects/exceptions.c - PyExc_TimeoutError variable static PyTypeObject PyExc_TimeoutError +Objects/exceptions.c - _PyExc_TypeError variable static PyTypeObject _PyExc_TypeError +Objects/exceptions.c - PyExc_TypeError variable static PyTypeObject PyExc_TypeError +Objects/exceptions.c - _PyExc_UnboundLocalError variable static PyTypeObject _PyExc_UnboundLocalError +Objects/exceptions.c - PyExc_UnboundLocalError variable static PyTypeObject PyExc_UnboundLocalError +Objects/exceptions.c - _PyExc_UnicodeDecodeError variable static PyTypeObject _PyExc_UnicodeDecodeError +Objects/exceptions.c - PyExc_UnicodeDecodeError variable static PyTypeObject PyExc_UnicodeDecodeError +Objects/exceptions.c - _PyExc_UnicodeEncodeError variable static PyTypeObject _PyExc_UnicodeEncodeError +Objects/exceptions.c - PyExc_UnicodeEncodeError variable static PyTypeObject PyExc_UnicodeEncodeError +Objects/exceptions.c - _PyExc_UnicodeError variable static PyTypeObject _PyExc_UnicodeError +Objects/exceptions.c - PyExc_UnicodeError variable static PyTypeObject PyExc_UnicodeError +Objects/exceptions.c - _PyExc_UnicodeTranslateError variable static PyTypeObject _PyExc_UnicodeTranslateError +Objects/exceptions.c - PyExc_UnicodeTranslateError variable static PyTypeObject PyExc_UnicodeTranslateError +Objects/exceptions.c - _PyExc_UnicodeWarning variable static PyTypeObject _PyExc_UnicodeWarning +Objects/exceptions.c - PyExc_UnicodeWarning variable static PyTypeObject PyExc_UnicodeWarning +Objects/exceptions.c - _PyExc_UserWarning variable static PyTypeObject _PyExc_UserWarning +Objects/exceptions.c - PyExc_UserWarning variable static PyTypeObject PyExc_UserWarning +Objects/exceptions.c - _PyExc_ValueError variable static PyTypeObject _PyExc_ValueError +Objects/exceptions.c - PyExc_ValueError variable static PyTypeObject PyExc_ValueError +Objects/exceptions.c - _PyExc_Warning variable static PyTypeObject _PyExc_Warning +Objects/exceptions.c - PyExc_Warning variable static PyTypeObject PyExc_Warning +Objects/exceptions.c - _PyExc_ZeroDivisionError variable static PyTypeObject _PyExc_ZeroDivisionError +Objects/exceptions.c - PyExc_ZeroDivisionError variable static PyTypeObject PyExc_ZeroDivisionError +Objects/boolobject.c - _Py_FalseStruct variable static struct _longobject _Py_FalseStruct +Objects/stringlib/unicode_format.h - PyFieldNameIter_Type variable static PyTypeObject PyFieldNameIter_Type +Modules/_io/fileio.c - PyFileIO_Type variable PyTypeObject PyFileIO_Type +Python/preconfig.c - Py_FileSystemDefaultEncodeErrors variable const char *Py_FileSystemDefaultEncodeErrors +Python/preconfig.c - Py_FileSystemDefaultEncoding variable const char *Py_FileSystemDefaultEncoding +Python/bltinmodule.c - PyFilter_Type variable PyTypeObject PyFilter_Type +Objects/floatobject.c - PyFloat_Type variable PyTypeObject PyFloat_Type +Objects/stringlib/unicode_format.h - PyFormatterIter_Type variable static PyTypeObject PyFormatterIter_Type +Objects/frameobject.c - PyFrame_Type variable PyTypeObject PyFrame_Type +Python/initconfig.c - Py_FrozenFlag variable int Py_FrozenFlag +Objects/setobject.c - PyFrozenSet_Type variable PyTypeObject PyFrozenSet_Type +Objects/funcobject.c - PyFunction_Type variable PyTypeObject PyFunction_Type +Objects/genobject.c - PyGen_Type variable PyTypeObject PyGen_Type +Objects/descrobject.c - PyGetSetDescr_Type variable PyTypeObject PyGetSetDescr_Type +Python/hamt.c - _PyHamt_ArrayNode_Type variable PyTypeObject _PyHamt_ArrayNode_Type +Python/hamt.c - PyHamt_as_mapping variable static PyMappingMethods PyHamt_as_mapping +Python/hamt.c - PyHamt_as_sequence variable static PySequenceMethods PyHamt_as_sequence +Python/hamt.c - _PyHamt_BitmapNode_Type variable PyTypeObject _PyHamt_BitmapNode_Type +Python/hamt.c - _PyHamt_CollisionNode_Type variable PyTypeObject _PyHamt_CollisionNode_Type +Python/hamt.c - _PyHamtItems_Type variable PyTypeObject _PyHamtItems_Type +Python/hamt.c - PyHamtIterator_as_mapping variable static PyMappingMethods PyHamtIterator_as_mapping +Python/hamt.c - _PyHamtKeys_Type variable PyTypeObject _PyHamtKeys_Type +Python/hamt.c - PyHamt_methods variable static PyMethodDef PyHamt_methods +Python/hamt.c - _PyHamt_Type variable PyTypeObject _PyHamt_Type +Python/hamt.c - _PyHamtValues_Type variable PyTypeObject _PyHamtValues_Type +Python/preconfig.c - _Py_HasFileSystemDefaultEncodeErrors variable int _Py_HasFileSystemDefaultEncodeErrors +Python/preconfig.c - Py_HasFileSystemDefaultEncoding variable int Py_HasFileSystemDefaultEncoding +Python/pyhash.c - PyHash_Func variable static PyHash_FuncDef PyHash_Func +Python/initconfig.c - Py_HashRandomizationFlag variable int Py_HashRandomizationFlag +Python/pyhash.c - _Py_HashSecret variable _Py_HashSecret_t _Py_HashSecret +Python/bootstrap_hash.c - _Py_HashSecret_Initialized variable static int _Py_HashSecret_Initialized +Python/codecs.c - Py_hexdigits variable const char *Py_hexdigits +Python/sysmodule.c - PyId__ variable _Py_IDENTIFIER(_) +Modules/_abc.c - PyId__abc_impl variable _Py_IDENTIFIER(_abc_impl) +Objects/typeobject.c - PyId___abstractmethods__ variable _Py_IDENTIFIER(__abstractmethods__) +Modules/_abc.c - PyId___abstractmethods__ variable _Py_IDENTIFIER(__abstractmethods__) +Python/ceval.c _PyEval_EvalFrameDefault PyId___aenter__ variable _Py_IDENTIFIER(__aenter__) +Python/ceval.c _PyEval_EvalFrameDefault PyId___aexit__ variable _Py_IDENTIFIER(__aexit__) +Objects/typeobject.c slot_am_aiter PyId___aiter__ variable _Py_IDENTIFIER(__aiter__) +Python/ceval.c import_all_from PyId___all__ variable _Py_IDENTIFIER(__all__) +Objects/typeobject.c slot_am_anext PyId___anext__ variable _Py_IDENTIFIER(__anext__) +Python/Python-ast.c - PyId_annotation variable _Py_IDENTIFIER(annotation) +Python/ceval.c _PyEval_EvalFrameDefault PyId___annotations__ variable _Py_IDENTIFIER(__annotations__) +Python/Python-ast.c - PyId_arg variable _Py_IDENTIFIER(arg) +Python/Python-ast.c - PyId_args variable _Py_IDENTIFIER(args) +Python/Python-ast.c - PyId_argtypes variable _Py_IDENTIFIER(argtypes) +Python/Python-ast.c - PyId_asname variable _Py_IDENTIFIER(asname) +Python/Python-ast.c make_type PyId__ast variable _Py_IDENTIFIER(_ast) +Python/Python-ast.c - PyId_attr variable _Py_IDENTIFIER(attr) +Python/Python-ast.c - PyId__attributes variable _Py_IDENTIFIER(_attributes) +Objects/typeobject.c slot_am_await PyId___await__ variable _Py_IDENTIFIER(__await__) +Python/Python-ast.c - PyId_bases variable _Py_IDENTIFIER(bases) +Modules/_abc.c - PyId___bases__ variable _Py_IDENTIFIER(__bases__) +Objects/abstract.c abstract_get_bases PyId___bases__ variable _Py_IDENTIFIER(__bases__) +Objects/typeobject.c merge_class_dict PyId___bases__ variable _Py_IDENTIFIER(__bases__) +Objects/longobject.c - PyId_big variable _Py_IDENTIFIER(big) +Modules/_io/_iomodule.c _io_open_impl PyId__blksize variable _Py_IDENTIFIER(_blksize) +Python/Python-ast.c - PyId_body variable _Py_IDENTIFIER(body) +Objects/typeobject.c slot_nb_bool PyId___bool__ variable _Py_IDENTIFIER(__bool__) +Python/sysmodule.c - PyId_buffer variable _Py_IDENTIFIER(buffer) +Python/ceval.c _PyEval_EvalFrameDefault PyId___build_class__ variable _Py_IDENTIFIER(__build_class__) +Objects/typeobject.c - PyId_builtins variable _Py_IDENTIFIER(builtins) +Python/errors.c - PyId_builtins variable _Py_IDENTIFIER(builtins) +Python/pythonrun.c - PyId_builtins variable _Py_IDENTIFIER(builtins) +Python/sysmodule.c - PyId_builtins variable _Py_IDENTIFIER(builtins) +Objects/frameobject.c - PyId___builtins__ variable _Py_IDENTIFIER(__builtins__) +Python/bltinmodule.c - PyId___builtins__ variable _Py_IDENTIFIER(__builtins__) +Python/import.c module_dict_for_exec PyId___builtins__ variable _Py_IDENTIFIER(__builtins__) +Objects/object.c - PyId___bytes__ variable _Py_IDENTIFIER(__bytes__) +Objects/bytesobject.c format_obj PyId___bytes__ variable _Py_IDENTIFIER(__bytes__) +Objects/bytesobject.c bytes_new PyId___bytes__ variable _Py_IDENTIFIER(__bytes__) +Objects/weakrefobject.c proxy_bytes PyId___bytes__ variable _Py_IDENTIFIER(__bytes__) +Objects/typeobject.c slot_tp_call PyId___call__ variable _Py_IDENTIFIER(__call__) +Python/Python-ast.c - PyId_cause variable _Py_IDENTIFIER(cause) +Objects/typeobject.c - PyId___class__ variable _Py_IDENTIFIER(__class__) +Modules/_abc.c - PyId___class__ variable _Py_IDENTIFIER(__class__) +Python/compile.c compiler_enter_scope PyId___class__ variable _Py_IDENTIFIER(__class__) +Objects/abstract.c recursive_isinstance PyId___class__ variable _Py_IDENTIFIER(__class__) +Objects/typeobject.c type_new PyId___classcell__ variable _Py_IDENTIFIER(__classcell__) +Objects/typeobject.c - PyId___class_getitem__ variable _Py_IDENTIFIER(__class_getitem__) +Objects/abstract.c PyObject_GetItem PyId___class_getitem__ variable _Py_IDENTIFIER(__class_getitem__) +Python/import.c PyImport_Cleanup PyId_clear variable _Py_IDENTIFIER(clear) +Python/traceback.c - PyId_close variable _Py_IDENTIFIER(close) +Modules/_io/bufferedio.c - PyId_close variable _Py_IDENTIFIER(close) +Modules/_io/textio.c - PyId_close variable _Py_IDENTIFIER(close) +Objects/genobject.c gen_close_iter PyId_close variable _Py_IDENTIFIER(close) +Modules/_dbmmodule.c dbm__exit__ PyId_close variable _Py_IDENTIFIER(close) +Modules/_gdbmmodule.c dbm__exit__ PyId_close variable _Py_IDENTIFIER(close) +Python/pythonrun.c _Py_HandleSystemExit PyId_code variable _Py_IDENTIFIER(code) +Python/Python-ast.c - PyId_col_offset variable _Py_IDENTIFIER(col_offset) +Python/Python-ast.c - PyId_comparators variable _Py_IDENTIFIER(comparators) +Objects/complexobject.c try_complex_special_method PyId___complex__ variable _Py_IDENTIFIER(__complex__) +Objects/typeobject.c slot_sq_contains PyId___contains__ variable _Py_IDENTIFIER(__contains__) +Python/Python-ast.c - PyId_context_expr variable _Py_IDENTIFIER(context_expr) +Python/Python-ast.c - PyId_conversion variable _Py_IDENTIFIER(conversion) +Modules/itertoolsmodule.c itertools_tee_impl PyId___copy__ variable _Py_IDENTIFIER(__copy__) +Objects/descrobject.c mappingproxy_copy PyId_copy variable _Py_IDENTIFIER(copy) +Objects/typeobject.c import_copyreg PyId_copyreg variable _Py_IDENTIFIER(copyreg) +Python/Python-ast.c - PyId_ctx variable _Py_IDENTIFIER(ctx) +Modules/_io/bufferedio.c - PyId__dealloc_warn variable _Py_IDENTIFIER(_dealloc_warn) +Modules/_io/textio.c - PyId__dealloc_warn variable _Py_IDENTIFIER(_dealloc_warn) +Modules/_io/textio.c - PyId_decode variable _Py_IDENTIFIER(decode) +Python/Python-ast.c - PyId_decorator_list variable _Py_IDENTIFIER(decorator_list) +Python/_warnings.c get_default_action PyId_defaultaction variable _Py_IDENTIFIER(defaultaction) +Python/Python-ast.c - PyId_defaults variable _Py_IDENTIFIER(defaults) +Objects/typeobject.c slot_tp_finalize PyId___del__ variable _Py_IDENTIFIER(__del__) +Objects/typeobject.c slot_tp_setattro PyId___delattr__ variable _Py_IDENTIFIER(__delattr__) +Objects/typeobject.c slot_tp_descr_set PyId___delete__ variable _Py_IDENTIFIER(__delete__) +Objects/typeobject.c - PyId___delitem__ variable _Py_IDENTIFIER(__delitem__) +Objects/typeobject.c - PyId___dict__ variable _Py_IDENTIFIER(__dict__) +Modules/_abc.c - PyId___dict__ variable _Py_IDENTIFIER(__dict__) +Python/bltinmodule.c - PyId___dict__ variable _Py_IDENTIFIER(__dict__) +Python/Python-ast.c ast_type_reduce PyId___dict__ variable _Py_IDENTIFIER(__dict__) +Python/ceval.c import_all_from PyId___dict__ variable _Py_IDENTIFIER(__dict__) +Objects/bytearrayobject.c _common_reduce PyId___dict__ variable _Py_IDENTIFIER(__dict__) +Objects/moduleobject.c module_dir PyId___dict__ variable _Py_IDENTIFIER(__dict__) +Objects/odictobject.c odict_reduce PyId___dict__ variable _Py_IDENTIFIER(__dict__) +Objects/setobject.c set_reduce PyId___dict__ variable _Py_IDENTIFIER(__dict__) +Modules/_collectionsmodule.c deque_reduce PyId___dict__ variable _Py_IDENTIFIER(__dict__) +Objects/dictobject.c dictviews_sub PyId_difference_update variable _Py_IDENTIFIER(difference_update) +Python/Python-ast.c - PyId_dims variable _Py_IDENTIFIER(dims) +Objects/object.c - PyId___dir__ variable _Py_IDENTIFIER(__dir__) +Objects/moduleobject.c module_dir PyId___dir__ variable _Py_IDENTIFIER(__dir__) +Python/ceval.c _PyEval_EvalFrameDefault PyId_displayhook variable _Py_IDENTIFIER(displayhook) +Objects/typeobject.c - PyId___doc__ variable _Py_IDENTIFIER(__doc__) +Objects/descrobject.c property_init_impl PyId___doc__ variable _Py_IDENTIFIER(__doc__) +Objects/moduleobject.c module_init_dict PyId___doc__ variable _Py_IDENTIFIER(__doc__) +Objects/moduleobject.c PyModule_SetDocString PyId___doc__ variable _Py_IDENTIFIER(__doc__) +Python/Python-ast.c - PyId_elt variable _Py_IDENTIFIER(elt) +Python/Python-ast.c - PyId_elts variable _Py_IDENTIFIER(elts) +Modules/faulthandler.c - PyId_enable variable _Py_IDENTIFIER(enable) +Python/sysmodule.c - PyId_encoding variable _Py_IDENTIFIER(encoding) +Python/bltinmodule.c - PyId_encoding variable _Py_IDENTIFIER(encoding) +Python/pythonrun.c PyRun_InteractiveOneObjectEx PyId_encoding variable _Py_IDENTIFIER(encoding) +Python/Python-ast.c - PyId_end_col_offset variable _Py_IDENTIFIER(end_col_offset) +Python/Python-ast.c - PyId_end_lineno variable _Py_IDENTIFIER(end_lineno) +Python/ceval.c _PyEval_EvalFrameDefault PyId___enter__ variable _Py_IDENTIFIER(__enter__) +Objects/typeobject.c overrides_hash PyId___eq__ variable _Py_IDENTIFIER(__eq__) +Python/bltinmodule.c - PyId_errors variable _Py_IDENTIFIER(errors) +Python/Python-ast.c - PyId_exc variable _Py_IDENTIFIER(exc) +Python/pythonrun.c - PyId_excepthook variable _Py_IDENTIFIER(excepthook) +Python/ceval.c _PyEval_EvalFrameDefault PyId___exit__ variable _Py_IDENTIFIER(__exit__) +Modules/_pickle.c do_append PyId_extend variable _Py_IDENTIFIER(extend) +Python/Python-ast.c - PyId__fields variable _Py_IDENTIFIER(_fields) +Objects/moduleobject.c PyModule_GetFilenameObject PyId___file__ variable _Py_IDENTIFIER(__file__) +Python/errors.c PyErr_SyntaxLocationObject PyId_filename variable _Py_IDENTIFIER(filename) +Python/pythonrun.c parse_syntax_error PyId_filename variable _Py_IDENTIFIER(filename) +Modules/_io/textio.c - PyId_fileno variable _Py_IDENTIFIER(fileno) +Modules/faulthandler.c - PyId_fileno variable _Py_IDENTIFIER(fileno) +Python/bltinmodule.c - PyId_fileno variable _Py_IDENTIFIER(fileno) +Objects/fileobject.c PyObject_AsFileDescriptor PyId_fileno variable _Py_IDENTIFIER(fileno) +Modules/itertoolsmodule.c zip_longest_new PyId_fillvalue variable _Py_IDENTIFIER(fillvalue) +Python/_warnings.c get_filter PyId_filters variable _Py_IDENTIFIER(filters) +Python/Python-ast.c - PyId_finalbody variable _Py_IDENTIFIER(finalbody) +Modules/_io/iobase.c iobase_finalize PyId__finalizing variable _Py_IDENTIFIER(_finalizing) +Python/import.c import_find_and_load PyId__find_and_load variable _Py_IDENTIFIER(_find_and_load) +Python/import.c PyImport_ExecCodeModuleObject PyId__fix_up_module variable _Py_IDENTIFIER(_fix_up_module) +Python/errors.c - PyId_flush variable _Py_IDENTIFIER(flush) +Python/pylifecycle.c - PyId_flush variable _Py_IDENTIFIER(flush) +Python/pythonrun.c - PyId_flush variable _Py_IDENTIFIER(flush) +Modules/_threadmodule.c - PyId_flush variable _Py_IDENTIFIER(flush) +Modules/_io/bufferedio.c - PyId_flush variable _Py_IDENTIFIER(flush) +Modules/_io/textio.c - PyId_flush variable _Py_IDENTIFIER(flush) +Modules/faulthandler.c - PyId_flush variable _Py_IDENTIFIER(flush) +Python/bltinmodule.c - PyId_flush variable _Py_IDENTIFIER(flush) +Objects/abstract.c PyObject_Format PyId___format__ variable _Py_IDENTIFIER(__format__) +Python/Python-ast.c - PyId_format_spec variable _Py_IDENTIFIER(format_spec) +Modules/posixmodule.c path_converter PyId___fspath__ variable _Py_IDENTIFIER(__fspath__) +Modules/posixmodule.c PyOS_FSPath PyId___fspath__ variable _Py_IDENTIFIER(__fspath__) +Python/Python-ast.c - PyId_func variable _Py_IDENTIFIER(func) +Python/Python-ast.c - PyId_generators variable _Py_IDENTIFIER(generators) +Objects/descrobject.c mappingproxy_get PyId_get variable _Py_IDENTIFIER(get) +Modules/_collectionsmodule.c _count_elements PyId_get variable _Py_IDENTIFIER(get) +Objects/typeobject.c slot_tp_descr_get PyId___get__ variable _Py_IDENTIFIER(__get__) +Objects/classobject.c method_reduce PyId_getattr variable _Py_IDENTIFIER(getattr) +Objects/descrobject.c descr_reduce PyId_getattr variable _Py_IDENTIFIER(getattr) +Objects/descrobject.c wrapper_reduce PyId_getattr variable _Py_IDENTIFIER(getattr) +Objects/moduleobject.c module_getattro PyId___getattr__ variable _Py_IDENTIFIER(__getattr__) +Objects/methodobject.c meth_reduce PyId_getattr variable _Py_IDENTIFIER(getattr) +Objects/typeobject.c slot_tp_getattr_hook PyId___getattr__ variable _Py_IDENTIFIER(__getattr__) +Objects/typeobject.c - PyId___getattribute__ variable _Py_IDENTIFIER(__getattribute__) +Objects/typeobject.c - PyId___getitem__ variable _Py_IDENTIFIER(__getitem__) +Objects/typeobject.c _PyObject_GetNewArguments PyId___getnewargs__ variable _Py_IDENTIFIER(__getnewargs__) +Objects/typeobject.c _PyObject_GetNewArguments PyId___getnewargs_ex__ variable _Py_IDENTIFIER(__getnewargs_ex__) +Modules/_io/textio.c - PyId_getpreferredencoding variable _Py_IDENTIFIER(getpreferredencoding) +Python/_warnings.c get_source_line PyId_get_source variable _Py_IDENTIFIER(get_source) +Python/import.c PyImport_ExecCodeModuleWithPathnames PyId__get_sourcefile variable _Py_IDENTIFIER(_get_sourcefile) +Objects/typeobject.c _PyObject_GetState PyId___getstate__ variable _Py_IDENTIFIER(__getstate__) +Python/import.c PyImport_ImportModuleLevelObject PyId__handle_fromlist variable _Py_IDENTIFIER(_handle_fromlist) +Python/Python-ast.c - PyId_handlers variable _Py_IDENTIFIER(handlers) +Objects/typeobject.c - PyId___hash__ variable _Py_IDENTIFIER(__hash__) +Python/Python-ast.c - PyId_id variable _Py_IDENTIFIER(id) +Python/Python-ast.c - PyId_ifs variable _Py_IDENTIFIER(ifs) +Python/import.c PyImport_ReloadModule PyId_imp variable _Py_IDENTIFIER(imp) +Python/ceval.c import_name PyId___import__ variable _Py_IDENTIFIER(__import__) +Objects/typeobject.c slot_nb_index PyId___index__ variable _Py_IDENTIFIER(__index__) +Objects/typeobject.c slot_tp_init PyId___init__ variable _Py_IDENTIFIER(__init__) +Objects/moduleobject.c _PyModuleSpec_IsInitializing PyId__initializing variable _Py_IDENTIFIER(_initializing) +Objects/typeobject.c - PyId___init_subclass__ variable _Py_IDENTIFIER(__init_subclass__) +Objects/abstract.c PyObject_IsInstance PyId___instancecheck__ variable _Py_IDENTIFIER(__instancecheck__) +Objects/dictobject.c _PyDictView_Intersect PyId_intersection_update variable _Py_IDENTIFIER(intersection_update) +Modules/_io/iobase.c - PyId___IOBase_closed variable _Py_IDENTIFIER(__IOBase_closed) +Objects/typeobject.c slot_nb_inplace_power PyId___ipow__ variable _Py_IDENTIFIER(__ipow__) +Objects/object.c - PyId___isabstractmethod__ variable _Py_IDENTIFIER(__isabstractmethod__) +Python/Python-ast.c - PyId_is_async variable _Py_IDENTIFIER(is_async) +Modules/_io/bufferedio.c - PyId_isatty variable _Py_IDENTIFIER(isatty) +Modules/_io/textio.c - PyId_isatty variable _Py_IDENTIFIER(isatty) +Python/pylifecycle.c create_stdio PyId_isatty variable _Py_IDENTIFIER(isatty) +Modules/_io/_iomodule.c _io_open_impl PyId_isatty variable _Py_IDENTIFIER(isatty) +Python/codecs.c _PyCodec_LookupTextEncoding PyId__is_text_encoding variable _Py_IDENTIFIER(_is_text_encoding) +Python/Python-ast.c - PyId_items variable _Py_IDENTIFIER(items) +Objects/abstract.c PyMapping_Items PyId_items variable _Py_IDENTIFIER(items) +Objects/descrobject.c mappingproxy_items PyId_items variable _Py_IDENTIFIER(items) +Objects/odictobject.c odict_reduce PyId_items variable _Py_IDENTIFIER(items) +Objects/odictobject.c odict_repr PyId_items variable _Py_IDENTIFIER(items) +Objects/odictobject.c mutablemapping_update PyId_items variable _Py_IDENTIFIER(items) +Objects/typeobject.c _PyObject_GetItemsIter PyId_items variable _Py_IDENTIFIER(items) +Modules/_collectionsmodule.c defdict_reduce PyId_items variable _Py_IDENTIFIER(items) +Python/Python-ast.c - PyId_iter variable _Py_IDENTIFIER(iter) +Objects/bytearrayobject.c bytearrayiter_reduce PyId_iter variable _Py_IDENTIFIER(iter) +Objects/bytesobject.c striter_reduce PyId_iter variable _Py_IDENTIFIER(iter) +Objects/dictobject.c dictiter_reduce PyId_iter variable _Py_IDENTIFIER(iter) +Objects/iterobject.c iter_reduce PyId_iter variable _Py_IDENTIFIER(iter) +Objects/iterobject.c calliter_reduce PyId_iter variable _Py_IDENTIFIER(iter) +Objects/listobject.c listiter_reduce_general PyId_iter variable _Py_IDENTIFIER(iter) +Objects/odictobject.c odictiter_reduce PyId_iter variable _Py_IDENTIFIER(iter) +Objects/rangeobject.c rangeiter_reduce PyId_iter variable _Py_IDENTIFIER(iter) +Objects/rangeobject.c longrangeiter_reduce PyId_iter variable _Py_IDENTIFIER(iter) +Objects/setobject.c setiter_reduce PyId_iter variable _Py_IDENTIFIER(iter) +Objects/tupleobject.c tupleiter_reduce PyId_iter variable _Py_IDENTIFIER(iter) +Objects/unicodeobject.c unicodeiter_reduce PyId_iter variable _Py_IDENTIFIER(iter) +Objects/typeobject.c slot_tp_iter PyId___iter__ variable _Py_IDENTIFIER(__iter__) +Modules/arraymodule.c array_arrayiterator___reduce___impl PyId_iter variable _Py_IDENTIFIER(iter) +Python/Python-ast.c - PyId_key variable _Py_IDENTIFIER(key) +Python/Python-ast.c - PyId_keys variable _Py_IDENTIFIER(keys) +Objects/abstract.c PyMapping_Keys PyId_keys variable _Py_IDENTIFIER(keys) +Objects/descrobject.c mappingproxy_keys PyId_keys variable _Py_IDENTIFIER(keys) +Objects/dictobject.c dict_update_common PyId_keys variable _Py_IDENTIFIER(keys) +Objects/odictobject.c mutablemapping_update PyId_keys variable _Py_IDENTIFIER(keys) +Python/Python-ast.c - PyId_keywords variable _Py_IDENTIFIER(keywords) +Python/Python-ast.c - PyId_kind variable _Py_IDENTIFIER(kind) +Python/Python-ast.c - PyId_kwarg variable _Py_IDENTIFIER(kwarg) +Python/Python-ast.c - PyId_kw_defaults variable _Py_IDENTIFIER(kw_defaults) +Python/Python-ast.c - PyId_kwonlyargs variable _Py_IDENTIFIER(kwonlyargs) +Python/pythonrun.c - PyId_last_traceback variable _Py_IDENTIFIER(last_traceback) +Python/pythonrun.c - PyId_last_type variable _Py_IDENTIFIER(last_type) +Python/pythonrun.c - PyId_last_value variable _Py_IDENTIFIER(last_value) +Python/Python-ast.c - PyId_left variable _Py_IDENTIFIER(left) +Objects/typeobject.c - PyId___len__ variable _Py_IDENTIFIER(__len__) +Objects/abstract.c PyObject_LengthHint PyId___length_hint__ variable _Py_IDENTIFIER(__length_hint__) +Python/Python-ast.c - PyId_level variable _Py_IDENTIFIER(level) +Python/Python-ast.c - PyId_lineno variable _Py_IDENTIFIER(lineno) +Python/errors.c PyErr_SyntaxLocationObject PyId_lineno variable _Py_IDENTIFIER(lineno) +Python/pythonrun.c parse_syntax_error PyId_lineno variable _Py_IDENTIFIER(lineno) +Objects/longobject.c - PyId_little variable _Py_IDENTIFIER(little) +Python/_warnings.c get_source_line PyId___loader__ variable _Py_IDENTIFIER(__loader__) +Objects/moduleobject.c module_init_dict PyId___loader__ variable _Py_IDENTIFIER(__loader__) +Python/import.c PyImport_ImportModuleLevelObject PyId__lock_unlock_module variable _Py_IDENTIFIER(_lock_unlock_module) +Python/Python-ast.c - PyId_lower variable _Py_IDENTIFIER(lower) +Python/ceval.c _PyEval_EvalFrameDefault PyId___ltrace__ variable _Py_IDENTIFIER(__ltrace__) +Python/pythonrun.c PyRun_InteractiveOneObjectEx PyId___main__ variable _Py_IDENTIFIER(__main__) +Python/_warnings.c check_matched PyId_match variable _Py_IDENTIFIER(match) +Python/bltinmodule.c - PyId_metaclass variable _Py_IDENTIFIER(metaclass) +Objects/dictobject.c dict_subscript PyId___missing__ variable _Py_IDENTIFIER(__missing__) +Modules/_io/bufferedio.c - PyId_mode variable _Py_IDENTIFIER(mode) +Modules/_io/textio.c - PyId_mode variable _Py_IDENTIFIER(mode) +Python/pylifecycle.c create_stdio PyId_mode variable _Py_IDENTIFIER(mode) +Modules/_io/_iomodule.c _io_open_impl PyId_mode variable _Py_IDENTIFIER(mode) +Python/Python-ast.c - PyId_module variable _Py_IDENTIFIER(module) +Objects/typeobject.c - PyId___module__ variable _Py_IDENTIFIER(__module__) +Python/Python-ast.c make_type PyId___module__ variable _Py_IDENTIFIER(__module__) +Python/errors.c PyErr_NewException PyId___module__ variable _Py_IDENTIFIER(__module__) +Python/errors.c PyErr_NewException PyId___module__ variable _Py_IDENTIFIER(__module__) +Python/pythonrun.c print_exception PyId___module__ variable _Py_IDENTIFIER(__module__) +Modules/_pickle.c whichmodule PyId___module__ variable _Py_IDENTIFIER(__module__) +Objects/typeobject.c type_mro_modified PyId_mro variable _Py_IDENTIFIER(mro) +Objects/typeobject.c mro_invoke PyId_mro variable _Py_IDENTIFIER(mro) +Python/bltinmodule.c - PyId___mro_entries__ variable _Py_IDENTIFIER(__mro_entries__) +Objects/typeobject.c type_new PyId___mro_entries__ variable _Py_IDENTIFIER(__mro_entries__) +Python/Python-ast.c - PyId_msg variable _Py_IDENTIFIER(msg) +Python/errors.c PyErr_SyntaxLocationObject PyId_msg variable _Py_IDENTIFIER(msg) +Python/pythonrun.c parse_syntax_error PyId_msg variable _Py_IDENTIFIER(msg) +Python/pylifecycle.c - PyId_name variable _Py_IDENTIFIER(name) +Modules/_io/fileio.c - PyId_name variable _Py_IDENTIFIER(name) +Modules/_io/bufferedio.c - PyId_name variable _Py_IDENTIFIER(name) +Modules/_io/textio.c - PyId_name variable _Py_IDENTIFIER(name) +Python/Python-ast.c - PyId_name variable _Py_IDENTIFIER(name) +Objects/exceptions.c ImportError_getstate PyId_name variable _Py_IDENTIFIER(name) +Objects/typeobject.c - PyId___name__ variable _Py_IDENTIFIER(__name__) +Objects/classobject.c - PyId___name__ variable _Py_IDENTIFIER(__name__) +Python/_warnings.c setup_context PyId___name__ variable _Py_IDENTIFIER(__name__) +Python/_warnings.c get_source_line PyId___name__ variable _Py_IDENTIFIER(__name__) +Python/_warnings.c show_warning PyId___name__ variable _Py_IDENTIFIER(__name__) +Python/ceval.c import_from PyId___name__ variable _Py_IDENTIFIER(__name__) +Python/ceval.c import_all_from PyId___name__ variable _Py_IDENTIFIER(__name__) +Python/import.c resolve_name PyId___name__ variable _Py_IDENTIFIER(__name__) +Objects/moduleobject.c module_init_dict PyId___name__ variable _Py_IDENTIFIER(__name__) +Objects/moduleobject.c PyModule_GetNameObject PyId___name__ variable _Py_IDENTIFIER(__name__) +Objects/moduleobject.c module_getattro PyId___name__ variable _Py_IDENTIFIER(__name__) +Objects/weakrefobject.c weakref_repr PyId___name__ variable _Py_IDENTIFIER(__name__) +Modules/_pickle.c save_global PyId___name__ variable _Py_IDENTIFIER(__name__) +Modules/_pickle.c save_reduce PyId___name__ variable _Py_IDENTIFIER(__name__) +Python/Python-ast.c - PyId_names variable _Py_IDENTIFIER(names) +Objects/typeobject.c - PyId___new__ variable _Py_IDENTIFIER(__new__) +Objects/typeobject.c reduce_newobj PyId___newobj__ variable _Py_IDENTIFIER(__newobj__) +Objects/typeobject.c reduce_newobj PyId___newobj_ex__ variable _Py_IDENTIFIER(__newobj_ex__) +Objects/typeobject.c slot_tp_iternext PyId___next__ variable _Py_IDENTIFIER(__next__) +Objects/structseq.c - PyId_n_fields variable _Py_IDENTIFIER(n_fields) +Python/ast.c new_identifier PyId_NFKC variable _Py_IDENTIFIER(NFKC) +Objects/structseq.c - PyId_n_sequence_fields variable _Py_IDENTIFIER(n_sequence_fields) +Objects/structseq.c - PyId_n_unnamed_fields variable _Py_IDENTIFIER(n_unnamed_fields) +Python/errors.c PyErr_SyntaxLocationObject PyId_offset variable _Py_IDENTIFIER(offset) +Python/pythonrun.c parse_syntax_error PyId_offset variable _Py_IDENTIFIER(offset) +Python/_warnings.c get_once_registry PyId_onceregistry variable _Py_IDENTIFIER(onceregistry) +Python/Python-ast.c - PyId_op variable _Py_IDENTIFIER(op) +Python/traceback.c - PyId_open variable _Py_IDENTIFIER(open) +Python/pylifecycle.c create_stdio PyId_open variable _Py_IDENTIFIER(open) +Parser/tokenizer.c fp_setreadl PyId_open variable _Py_IDENTIFIER(open) +Objects/fileobject.c PyFile_FromFd PyId_open variable _Py_IDENTIFIER(open) +Objects/fileobject.c PyFile_OpenCodeObject PyId_open variable _Py_IDENTIFIER(open) +Python/Python-ast.c - PyId_operand variable _Py_IDENTIFIER(operand) +Python/Python-ast.c - PyId_ops variable _Py_IDENTIFIER(ops) +Python/Python-ast.c - PyId_optional_vars variable _Py_IDENTIFIER(optional_vars) +Python/Python-ast.c - PyId_orelse variable _Py_IDENTIFIER(orelse) +Python/import.c resolve_name PyId___package__ variable _Py_IDENTIFIER(__package__) +Objects/moduleobject.c module_init_dict PyId___package__ variable _Py_IDENTIFIER(__package__) +Python/import.c resolve_name PyId_parent variable _Py_IDENTIFIER(parent) +Modules/_operator.c methodcaller_reduce PyId_partial variable _Py_IDENTIFIER(partial) +Python/sysmodule.c - PyId_path variable _Py_IDENTIFIER(path) +Python/traceback.c - PyId_path variable _Py_IDENTIFIER(path) +Objects/exceptions.c ImportError_getstate PyId_path variable _Py_IDENTIFIER(path) +Modules/main.c pymain_sys_path_add_path0 PyId_path variable _Py_IDENTIFIER(path) +Python/import.c resolve_name PyId___path__ variable _Py_IDENTIFIER(__path__) +Python/import.c PyImport_ImportModuleLevelObject PyId___path__ variable _Py_IDENTIFIER(__path__) +Modules/_io/bufferedio.c - PyId_peek variable _Py_IDENTIFIER(peek) +Python/Python-ast.c - PyId_posonlyargs variable _Py_IDENTIFIER(posonlyargs) +Objects/typeobject.c slot_nb_power PyId___pow__ variable _Py_IDENTIFIER(__pow__) +Python/bltinmodule.c - PyId___prepare__ variable _Py_IDENTIFIER(__prepare__) +Python/errors.c PyErr_SyntaxLocationObject PyId_print_file_and_line variable _Py_IDENTIFIER(print_file_and_line) +Python/pythonrun.c print_exception PyId_print_file_and_line variable _Py_IDENTIFIER(print_file_and_line) +Python/pythonrun.c - PyId_ps1 variable _Py_IDENTIFIER(ps1) +Python/pythonrun.c - PyId_ps2 variable _Py_IDENTIFIER(ps2) +Objects/object.c - PyId_Py_Repr variable _Py_IDENTIFIER(Py_Repr) +Objects/classobject.c - PyId___qualname__ variable _Py_IDENTIFIER(__qualname__) +Objects/descrobject.c calculate_qualname PyId___qualname__ variable _Py_IDENTIFIER(__qualname__) +Objects/methodobject.c meth_get__qualname__ PyId___qualname__ variable _Py_IDENTIFIER(__qualname__) +Objects/typeobject.c type_new PyId___qualname__ variable _Py_IDENTIFIER(__qualname__) +Modules/_io/textio.c - PyId_raw variable _Py_IDENTIFIER(raw) +Python/pylifecycle.c create_stdio PyId_raw variable _Py_IDENTIFIER(raw) +Modules/_io/iobase.c - PyId_read variable _Py_IDENTIFIER(read) +Modules/_io/bufferedio.c - PyId_read variable _Py_IDENTIFIER(read) +Modules/_io/textio.c - PyId_read variable _Py_IDENTIFIER(read) +Modules/_io/bufferedio.c - PyId_read1 variable _Py_IDENTIFIER(read1) +Python/marshal.c marshal_load PyId_read variable _Py_IDENTIFIER(read) +Modules/_io/bufferedio.c - PyId_readable variable _Py_IDENTIFIER(readable) +Modules/_io/textio.c - PyId_readable variable _Py_IDENTIFIER(readable) +Modules/_io/iobase.c _io__RawIOBase_read_impl PyId_readall variable _Py_IDENTIFIER(readall) +Modules/_io/bufferedio.c - PyId_readinto variable _Py_IDENTIFIER(readinto) +Modules/_io/bufferedio.c - PyId_readinto1 variable _Py_IDENTIFIER(readinto1) +Python/marshal.c r_string PyId_readinto variable _Py_IDENTIFIER(readinto) +Parser/tokenizer.c fp_setreadl PyId_readline variable _Py_IDENTIFIER(readline) +Objects/fileobject.c PyFile_GetLine PyId_readline variable _Py_IDENTIFIER(readline) +Objects/typeobject.c object___reduce_ex___impl PyId___reduce__ variable _Py_IDENTIFIER(__reduce__) +Python/import.c PyImport_ReloadModule PyId_reload variable _Py_IDENTIFIER(reload) +Modules/_io/textio.c - PyId_replace variable _Py_IDENTIFIER(replace) +Python/importdl.c get_encoded_name PyId_replace variable _Py_IDENTIFIER(replace) +Objects/typeobject.c slot_tp_repr PyId___repr__ variable _Py_IDENTIFIER(__repr__) +Modules/_io/textio.c - PyId_reset variable _Py_IDENTIFIER(reset) +Python/Python-ast.c - PyId_returns variable _Py_IDENTIFIER(returns) +Objects/enumobject.c reversed_new_impl PyId___reversed__ variable _Py_IDENTIFIER(__reversed__) +Objects/listobject.c listiter_reduce_general PyId_reversed variable _Py_IDENTIFIER(reversed) +Python/Python-ast.c - PyId_right variable _Py_IDENTIFIER(right) +Python/bltinmodule.c - PyId___round__ variable _Py_IDENTIFIER(__round__) +Modules/_io/textio.c - PyId_seek variable _Py_IDENTIFIER(seek) +Modules/_io/iobase.c _io__IOBase_tell_impl PyId_seek variable _Py_IDENTIFIER(seek) +Modules/_io/textio.c - PyId_seekable variable _Py_IDENTIFIER(seekable) +Python/ceval.c _PyEval_EvalFrameDefault PyId_send variable _Py_IDENTIFIER(send) +Objects/typeobject.c slot_tp_descr_set PyId___set__ variable _Py_IDENTIFIER(__set__) +Objects/typeobject.c slot_tp_setattro PyId___setattr__ variable _Py_IDENTIFIER(__setattr__) +Objects/typeobject.c - PyId___setitem__ variable _Py_IDENTIFIER(__setitem__) +Modules/_collectionsmodule.c _count_elements PyId___setitem__ variable _Py_IDENTIFIER(__setitem__) +Objects/typeobject.c - PyId___set_name__ variable _Py_IDENTIFIER(__set_name__) +Modules/_io/textio.c - PyId_setstate variable _Py_IDENTIFIER(setstate) +Modules/_pickle.c load_build PyId___setstate__ variable _Py_IDENTIFIER(__setstate__) +Python/_warnings.c call_show_warning PyId__showwarnmsg variable _Py_IDENTIFIER(_showwarnmsg) +Python/pylifecycle.c wait_for_thread_shutdown PyId__shutdown variable _Py_IDENTIFIER(_shutdown) +Python/Python-ast.c - PyId_simple variable _Py_IDENTIFIER(simple) +Python/sysmodule.c - PyId___sizeof__ variable _Py_IDENTIFIER(__sizeof__) +Python/Python-ast.c - PyId_slice variable _Py_IDENTIFIER(slice) +Objects/typeobject.c _PyType_GetSlotNames PyId___slotnames__ variable _Py_IDENTIFIER(__slotnames__) +Objects/typeobject.c _PyType_GetSlotNames PyId__slotnames variable _Py_IDENTIFIER(_slotnames) +Objects/typeobject.c type_new PyId___slots__ variable _Py_IDENTIFIER(__slots__) +Python/bltinmodule.c - PyId_sort variable _Py_IDENTIFIER(sort) +Python/import.c resolve_name PyId___spec__ variable _Py_IDENTIFIER(__spec__) +Python/import.c PyImport_ImportModuleLevelObject PyId___spec__ variable _Py_IDENTIFIER(__spec__) +Objects/moduleobject.c module_init_dict PyId___spec__ variable _Py_IDENTIFIER(__spec__) +Objects/moduleobject.c module_getattro PyId___spec__ variable _Py_IDENTIFIER(__spec__) +Python/_warnings.c - PyId_stderr variable _Py_IDENTIFIER(stderr) +Python/errors.c - PyId_stderr variable _Py_IDENTIFIER(stderr) +Python/pylifecycle.c - PyId_stderr variable _Py_IDENTIFIER(stderr) +Python/pythonrun.c - PyId_stderr variable _Py_IDENTIFIER(stderr) +Python/sysmodule.c - PyId_stderr variable _Py_IDENTIFIER(stderr) +Modules/_threadmodule.c - PyId_stderr variable _Py_IDENTIFIER(stderr) +Modules/faulthandler.c - PyId_stderr variable _Py_IDENTIFIER(stderr) +Python/bltinmodule.c - PyId_stderr variable _Py_IDENTIFIER(stderr) +Python/pylifecycle.c - PyId_stdin variable _Py_IDENTIFIER(stdin) +Python/pythonrun.c - PyId_stdin variable _Py_IDENTIFIER(stdin) +Python/bltinmodule.c - PyId_stdin variable _Py_IDENTIFIER(stdin) +Python/pylifecycle.c - PyId_stdout variable _Py_IDENTIFIER(stdout) +Python/pythonrun.c - PyId_stdout variable _Py_IDENTIFIER(stdout) +Python/sysmodule.c - PyId_stdout variable _Py_IDENTIFIER(stdout) +Python/bltinmodule.c - PyId_stdout variable _Py_IDENTIFIER(stdout) +Python/Python-ast.c - PyId_step variable _Py_IDENTIFIER(step) +Modules/posixmodule.c DirEntry_test_mode PyId_st_mode variable _Py_IDENTIFIER(st_mode) +Modules/_io/textio.c - PyId_strict variable _Py_IDENTIFIER(strict) +Python/pythonrun.c - PyId_string variable "_Py_static_string(PyId_string, """")" +Modules/timemodule.c time_strptime PyId__strptime_time variable _Py_IDENTIFIER(_strptime_time) +Modules/posixmodule.c wait_helper PyId_struct_rusage variable _Py_IDENTIFIER(struct_rusage) +Modules/_abc.c - PyId___subclasscheck__ variable _Py_IDENTIFIER(__subclasscheck__) +Objects/abstract.c PyObject_IsSubclass PyId___subclasscheck__ variable _Py_IDENTIFIER(__subclasscheck__) +Modules/_abc.c - PyId___subclasshook__ variable _Py_IDENTIFIER(__subclasshook__) +Objects/dictobject.c dictviews_xor PyId_symmetric_difference_update variable _Py_IDENTIFIER(symmetric_difference_update) +Python/Python-ast.c - PyId_tag variable _Py_IDENTIFIER(tag) +Python/Python-ast.c - PyId_target variable _Py_IDENTIFIER(target) +Python/Python-ast.c - PyId_targets variable _Py_IDENTIFIER(targets) +Modules/_io/textio.c - PyId_tell variable _Py_IDENTIFIER(tell) +Python/Python-ast.c - PyId_test variable _Py_IDENTIFIER(test) +Python/errors.c PyErr_SyntaxLocationObject PyId_text variable _Py_IDENTIFIER(text) +Python/pythonrun.c parse_syntax_error PyId_text variable _Py_IDENTIFIER(text) +Python/traceback.c - PyId_TextIOWrapper variable _Py_IDENTIFIER(TextIOWrapper) +Python/pylifecycle.c create_stdio PyId_TextIOWrapper variable _Py_IDENTIFIER(TextIOWrapper) +Python/pylifecycle.c - PyId_threading variable _Py_IDENTIFIER(threading) +Objects/genobject.c _gen_throw PyId_throw variable _Py_IDENTIFIER(throw) +Objects/abstract.c PyNumber_Long PyId___trunc__ variable _Py_IDENTIFIER(__trunc__) +Python/Python-ast.c - PyId_type variable _Py_IDENTIFIER(type) +Python/Python-ast.c - PyId_type_comment variable _Py_IDENTIFIER(type_comment) +Python/Python-ast.c - PyId_type_ignores variable _Py_IDENTIFIER(type_ignores) +Python/errors.c _PyErr_WriteUnraisableMsg PyId_unraisablehook variable _Py_IDENTIFIER(unraisablehook) +Objects/dictobject.c dictviews_or PyId_update variable _Py_IDENTIFIER(update) +Python/Python-ast.c - PyId_upper variable _Py_IDENTIFIER(upper) +Python/Python-ast.c - PyId_value variable _Py_IDENTIFIER(value) +Python/Python-ast.c - PyId_values variable _Py_IDENTIFIER(values) +Objects/abstract.c PyMapping_Values PyId_values variable _Py_IDENTIFIER(values) +Objects/descrobject.c mappingproxy_values PyId_values variable _Py_IDENTIFIER(values) +Python/Python-ast.c - PyId_vararg variable _Py_IDENTIFIER(vararg) +Python/_warnings.c already_warned PyId_version variable _Py_IDENTIFIER(version) +Python/_warnings.c call_show_warning PyId_WarningMessage variable _Py_IDENTIFIER(WarningMessage) +Python/_warnings.c setup_context PyId___warningregistry__ variable _Py_IDENTIFIER(__warningregistry__) +Python/_warnings.c get_warnings_attr PyId_warnings variable _Py_IDENTIFIER(warnings) +Python/sysmodule.c - PyId_warnoptions variable _Py_IDENTIFIER(warnoptions) +Python/_warnings.c _PyErr_WarnUnawaitedCoroutine PyId__warn_unawaited_coroutine variable _Py_IDENTIFIER(_warn_unawaited_coroutine) +Modules/_io/bufferedio.c - PyId_writable variable _Py_IDENTIFIER(writable) +Modules/_io/textio.c - PyId_writable variable _Py_IDENTIFIER(writable) +Python/sysmodule.c - PyId_write variable _Py_IDENTIFIER(write) +Modules/_io/bufferedio.c - PyId_write variable _Py_IDENTIFIER(write) +Python/marshal.c marshal_dump_impl PyId_write variable _Py_IDENTIFIER(write) +Objects/fileobject.c PyFile_WriteObject PyId_write variable _Py_IDENTIFIER(write) +Python/sysmodule.c - PyId__xoptions variable _Py_IDENTIFIER(_xoptions) +Python/import.c _PyImportZip_Init PyId_zipimporter variable _Py_IDENTIFIER(zipimporter) +Python/initconfig.c - Py_IgnoreEnvironmentFlag variable int Py_IgnoreEnvironmentFlag +Python/dynload_shlib.c - _PyImport_DynLoadFiletab variable const char *_PyImport_DynLoadFiletab[] +Python/frozen.c - PyImport_FrozenModules variable const struct _frozen * PyImport_FrozenModules +Modules/config.c - _PyImport_Inittab variable struct _inittab _PyImport_Inittab[] +Python/import.c - PyImport_Inittab variable struct _inittab * PyImport_Inittab +Modules/_io/textio.c - PyIncrementalNewlineDecoder_Type variable PyTypeObject PyIncrementalNewlineDecoder_Type +Python/initconfig.c - Py_InspectFlag variable int Py_InspectFlag +Objects/classobject.c - PyInstanceMethod_Type variable PyTypeObject PyInstanceMethod_Type +Python/initconfig.c - Py_InteractiveFlag variable int Py_InteractiveFlag +Objects/interpreteridobject.c - _PyInterpreterID_Type variable PyTypeObject _PyInterpreterID_Type +Modules/_io/iobase.c - PyIOBase_Type variable PyTypeObject PyIOBase_Type +Modules/_io/_iomodule.c - _PyIO_empty_bytes variable PyObject *_PyIO_empty_bytes +Modules/_io/_iomodule.c - _PyIO_empty_str variable PyObject *_PyIO_empty_str +Modules/_io/_iomodule.c - _PyIO_Module variable struct PyModuleDef _PyIO_Module +Modules/_io/_iomodule.c - _PyIO_str_close variable PyObject *_PyIO_str_close +Modules/_io/_iomodule.c - _PyIO_str_closed variable PyObject *_PyIO_str_closed +Modules/_io/_iomodule.c - _PyIO_str_decode variable PyObject *_PyIO_str_decode +Modules/_io/_iomodule.c - _PyIO_str_encode variable PyObject *_PyIO_str_encode +Modules/_io/_iomodule.c - _PyIO_str_fileno variable PyObject *_PyIO_str_fileno +Modules/_io/_iomodule.c - _PyIO_str_flush variable PyObject *_PyIO_str_flush +Modules/_io/_iomodule.c - _PyIO_str_getstate variable PyObject *_PyIO_str_getstate +Modules/_io/_iomodule.c - _PyIO_str_isatty variable PyObject *_PyIO_str_isatty +Modules/_io/_iomodule.c - _PyIO_str_newlines variable PyObject *_PyIO_str_newlines +Modules/_io/_iomodule.c - _PyIO_str_nl variable PyObject *_PyIO_str_nl +Modules/_io/_iomodule.c - _PyIO_str_peek variable PyObject *_PyIO_str_peek +Modules/_io/_iomodule.c - _PyIO_str_read variable PyObject *_PyIO_str_read +Modules/_io/_iomodule.c - _PyIO_str_read1 variable PyObject *_PyIO_str_read1 +Modules/_io/_iomodule.c - _PyIO_str_readable variable PyObject *_PyIO_str_readable +Modules/_io/_iomodule.c - _PyIO_str_readall variable PyObject *_PyIO_str_readall +Modules/_io/_iomodule.c - _PyIO_str_readinto variable PyObject *_PyIO_str_readinto +Modules/_io/_iomodule.c - _PyIO_str_readline variable PyObject *_PyIO_str_readline +Modules/_io/_iomodule.c - _PyIO_str_reset variable PyObject *_PyIO_str_reset +Modules/_io/_iomodule.c - _PyIO_str_seek variable PyObject *_PyIO_str_seek +Modules/_io/_iomodule.c - _PyIO_str_seekable variable PyObject *_PyIO_str_seekable +Modules/_io/_iomodule.c - _PyIO_str_setstate variable PyObject *_PyIO_str_setstate +Modules/_io/_iomodule.c - _PyIO_str_tell variable PyObject *_PyIO_str_tell +Modules/_io/_iomodule.c - _PyIO_str_truncate variable PyObject *_PyIO_str_truncate +Modules/_io/_iomodule.c - _PyIO_str_writable variable PyObject *_PyIO_str_writable +Modules/_io/_iomodule.c - _PyIO_str_write variable PyObject *_PyIO_str_write +Python/initconfig.c - Py_IsolatedFlag variable int Py_IsolatedFlag +Objects/listobject.c - PyListIter_Type variable PyTypeObject PyListIter_Type +Objects/listobject.c - PyListRevIter_Type variable PyTypeObject PyListRevIter_Type +Objects/listobject.c - PyList_Type variable PyTypeObject PyList_Type +Modules/_localemodule.c - PyLocale_Methods variable static struct PyMethodDef PyLocale_Methods[] +Objects/longobject.c - _PyLong_DigitValue variable unsigned char _PyLong_DigitValue[256] +Objects/longobject.c - _PyLong_One variable PyObject *_PyLong_One +Objects/rangeobject.c - PyLongRangeIter_Type variable PyTypeObject PyLongRangeIter_Type +Objects/longobject.c - PyLong_Type variable PyTypeObject PyLong_Type +Objects/longobject.c - _PyLong_Zero variable PyObject *_PyLong_Zero +Objects/memoryobject.c - _PyManagedBuffer_Type variable PyTypeObject _PyManagedBuffer_Type +Python/bltinmodule.c - PyMap_Type variable PyTypeObject PyMap_Type +Objects/obmalloc.c - _PyMem variable static PyMemAllocatorEx _PyMem +Objects/descrobject.c - PyMemberDescr_Type variable PyTypeObject PyMemberDescr_Type +Objects/obmalloc.c - _PyMem_Debug variable static struct { debug_alloc_api_t raw; debug_alloc_api_t mem; debug_alloc_api_t obj; } _PyMem_Debug +Objects/memoryobject.c - PyMemoryView_Type variable PyTypeObject PyMemoryView_Type +Objects/obmalloc.c - _PyMem_Raw variable static PyMemAllocatorEx _PyMem_Raw +Objects/descrobject.c - PyMethodDescr_Type variable PyTypeObject PyMethodDescr_Type +Objects/classobject.c - PyMethod_Type variable PyTypeObject PyMethod_Type +Objects/descrobject.c - _PyMethodWrapper_Type variable PyTypeObject _PyMethodWrapper_Type +Objects/moduleobject.c - PyModuleDef_Type variable PyTypeObject PyModuleDef_Type +Objects/moduleobject.c - PyModule_Type variable PyTypeObject PyModule_Type +Objects/namespaceobject.c - _PyNamespace_Type variable PyTypeObject _PyNamespace_Type +Objects/object.c - _Py_NoneStruct variable PyObject _Py_NoneStruct +Objects/object.c - _PyNone_Type variable PyTypeObject _PyNone_Type +Python/initconfig.c - Py_NoSiteFlag variable int Py_NoSiteFlag +Objects/object.c - _Py_NotImplementedStruct variable PyObject _Py_NotImplementedStruct +Objects/object.c - _PyNotImplemented_Type variable PyTypeObject _PyNotImplemented_Type +Python/initconfig.c - Py_NoUserSiteDirectory variable int Py_NoUserSiteDirectory +Objects/obmalloc.c - _PyObject variable static PyMemAllocatorEx _PyObject +Objects/obmalloc.c - _PyObject_Arena variable static PyObjectArenaAllocator _PyObject_Arena +Objects/odictobject.c - PyODictItems_Type variable PyTypeObject PyODictItems_Type +Objects/odictobject.c - PyODictIter_Type variable PyTypeObject PyODictIter_Type +Objects/odictobject.c - PyODictKeys_Type variable PyTypeObject PyODictKeys_Type +Objects/odictobject.c - PyODict_Type variable PyTypeObject PyODict_Type +Objects/odictobject.c - PyODictValues_Type variable PyTypeObject PyODictValues_Type +Python/fileutils.c - _Py_open_cloexec_works variable int _Py_open_cloexec_works +Python/initconfig.c - Py_OptimizeFlag variable int Py_OptimizeFlag +Parser/myreadline.c - PyOS_InputHook variable int (*PyOS_InputHook)(void) +Python/pylifecycle.c - _PyOS_mystrnicmp_hack variable int (*_PyOS_mystrnicmp_hack)(const char *, const char *, Py_ssize_t) +Python/getopt.c - _PyOS_optarg variable const wchar_t *_PyOS_optarg +Python/getopt.c - _PyOS_opterr variable int _PyOS_opterr +Python/getopt.c - _PyOS_optind variable Py_ssize_t _PyOS_optind +Parser/myreadline.c - PyOS_ReadlineFunctionPointer variable char *(*PyOS_ReadlineFunctionPointer)(FILE *, FILE *, const char *) +Parser/myreadline.c - _PyOS_ReadlineLock variable static PyThread_type_lock _PyOS_ReadlineLock +Parser/myreadline.c - _PyOS_ReadlineTState variable PyThreadState* _PyOS_ReadlineTState +Python/modsupport.c - _Py_PackageContext variable const char *_Py_PackageContext +Python/graminit.c - _PyParser_Grammar variable grammar _PyParser_Grammar +Python/pathconfig.c - _Py_path_config variable _PyPathConfig _Py_path_config +Objects/picklebufobject.c - PyPickleBuffer_Type variable PyTypeObject PyPickleBuffer_Type +Objects/descrobject.c - PyProperty_Type variable PyTypeObject PyProperty_Type +Python/initconfig.c - Py_QuietFlag variable int Py_QuietFlag +Objects/rangeobject.c - PyRangeIter_Type variable PyTypeObject PyRangeIter_Type +Objects/rangeobject.c - PyRange_Type variable PyTypeObject PyRange_Type +Modules/_io/iobase.c - PyRawIOBase_Type variable PyTypeObject PyRawIOBase_Type +Objects/object.c - _Py_RefTotal variable Py_ssize_t _Py_RefTotal +Objects/enumobject.c - PyReversed_Type variable PyTypeObject PyReversed_Type +Python/pylifecycle.c - _PyRuntime variable _PyRuntimeState _PyRuntime +Objects/iterobject.c - PySeqIter_Type variable PyTypeObject PySeqIter_Type +Objects/setobject.c - _PySet_Dummy variable PyObject * _PySet_Dummy +Objects/setobject.c - _PySetDummy_Type variable static PyTypeObject _PySetDummy_Type +Objects/setobject.c - PySetIter_Type variable PyTypeObject PySetIter_Type +Objects/setobject.c - PySet_Type variable PyTypeObject PySet_Type +Objects/sliceobject.c - PySlice_Type variable PyTypeObject PySlice_Type +Python/initconfig.c - _Py_StandardStreamEncoding variable static char *_Py_StandardStreamEncoding +Python/initconfig.c - _Py_StandardStreamErrors variable static char *_Py_StandardStreamErrors +Objects/funcobject.c - PyStaticMethod_Type variable PyTypeObject PyStaticMethod_Type +Objects/fileobject.c - PyStdPrinter_Type variable PyTypeObject PyStdPrinter_Type +Python/symtable.c - PySTEntry_Type variable PyTypeObject PySTEntry_Type +Modules/_io/stringio.c - PyStringIO_Type variable PyTypeObject PyStringIO_Type +Objects/structseq.c - PyStructSequence_UnnamedField variable char *PyStructSequence_UnnamedField +Objects/typeobject.c - PySuper_Type variable PyTypeObject PySuper_Type +Objects/object.c - _Py_SwappedOp variable int _Py_SwappedOp[] +Python/sysmodule.c - _PySys_ImplCacheTag variable const char *_PySys_ImplCacheTag +Python/sysmodule.c - _PySys_ImplName variable const char *_PySys_ImplName +Modules/_io/textio.c - PyTextIOBase_Type variable PyTypeObject PyTextIOBase_Type +Modules/_io/textio.c - PyTextIOWrapper_Type variable PyTypeObject PyTextIOWrapper_Type +Python/traceback.c - PyTraceBack_Type variable PyTypeObject PyTraceBack_Type +Objects/obmalloc.c - _Py_tracemalloc_config variable struct _PyTraceMalloc_Config _Py_tracemalloc_config +Objects/boolobject.c - _Py_TrueStruct variable static struct _longobject _Py_TrueStruct +Objects/tupleobject.c - PyTupleIter_Type variable PyTypeObject PyTupleIter_Type +Objects/tupleobject.c - PyTuple_Type variable PyTypeObject PyTuple_Type +Objects/typeobject.c - PyType_Type variable PyTypeObject PyType_Type +Python/initconfig.c - Py_UnbufferedStdioFlag variable int Py_UnbufferedStdioFlag +Python/pylifecycle.c - _Py_UnhandledKeyboardInterrupt variable int _Py_UnhandledKeyboardInterrupt +Objects/unicodeobject.c - PyUnicodeIter_Type variable PyTypeObject PyUnicodeIter_Type +Objects/unicodeobject.c - PyUnicode_Type variable PyTypeObject PyUnicode_Type +Python/initconfig.c - Py_UTF8Mode variable int Py_UTF8Mode +Python/initconfig.c - Py_VerboseFlag variable int Py_VerboseFlag +Objects/weakrefobject.c - _PyWeakref_CallableProxyType variable PyTypeObject _PyWeakref_CallableProxyType +Objects/weakrefobject.c - _PyWeakref_ProxyType variable PyTypeObject _PyWeakref_ProxyType +Objects/weakrefobject.c - _PyWeakref_RefType variable PyTypeObject _PyWeakref_RefType +Objects/weakrefobject.c - _PyWeakref_RefType variable PyTypeObject _PyWeakref_RefType +Objects/descrobject.c - PyWrapperDescr_Type variable PyTypeObject PyWrapperDescr_Type +Python/bltinmodule.c - PyZip_Type variable PyTypeObject PyZip_Type +Python/Python-ast.c - Raise_fields variable static char *Raise_fields[] +Python/Python-ast.c - Raise_type variable static PyTypeObject *Raise_type +Objects/rangeobject.c - range_as_mapping variable static PyMappingMethods range_as_mapping +Objects/rangeobject.c - range_as_number variable static PyNumberMethods range_as_number +Objects/rangeobject.c - range_as_sequence variable static PySequenceMethods range_as_sequence +Objects/rangeobject.c - rangeiter_methods variable static PyMethodDef rangeiter_methods +Objects/rangeobject.c - range_members variable static PyMemberDef range_members[] +Objects/rangeobject.c - range_methods variable static PyMethodDef range_methods +Modules/_io/iobase.c - rawiobase_methods variable static PyMethodDef rawiobase_methods +Python/pylifecycle.c fatal_error reentrant variable static int reentrant +Modules/faulthandler.c faulthandler_dump_traceback reentrant variable static volatile int reentrant +Modules/itertoolsmodule.c - repeat_methods variable static PyMethodDef repeat_methods +Modules/itertoolsmodule.c - repeat_type variable static PyTypeObject repeat_type +Python/Python-ast.c - Return_fields variable static char *Return_fields[] +Python/compile.c compiler_visit_annotations return_str variable static identifier return_str +Python/Python-ast.c - Return_type variable static PyTypeObject *Return_type +Objects/enumobject.c - reversediter_methods variable static PyMethodDef reversediter_methods +Modules/_threadmodule.c - rlock_methods variable static PyMethodDef rlock_methods +Modules/_threadmodule.c - RLocktype variable static PyTypeObject RLocktype +Objects/typeobject.c slot_nb_add rop_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_subtract rop_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_multiply rop_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_matrix_multiply rop_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_remainder rop_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_divmod rop_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_power_binary rop_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_lshift rop_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_rshift rop_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_and rop_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_xor rop_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_or rop_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_floor_divide rop_id variable _Py_static_string(op_id, OPSTR) +Objects/typeobject.c slot_nb_true_divide rop_id variable _Py_static_string(op_id, OPSTR) +Python/Python-ast.c - RShift_singleton variable static PyObject *RShift_singleton +Python/Python-ast.c - RShift_type variable static PyTypeObject *RShift_type +Python/pylifecycle.c - runtime_initialized variable static int runtime_initialized +Modules/posixmodule.c - ScandirIterator_methods variable static PyMethodDef ScandirIterator_methods +Modules/posixmodule.c - ScandirIteratorType variable static PyTypeObject ScandirIteratorType +Modules/_sre.c - scanner_members variable static PyMemberDef scanner_members[] +Modules/_sre.c - scanner_methods variable static PyMethodDef scanner_methods +Modules/_sre.c - Scanner_Type variable static PyTypeObject Scanner_Type +Modules/posixmodule.c - sched_param_desc variable static PyStructSequence_Desc sched_param_desc +Modules/posixmodule.c - sched_param_fields variable static PyStructSequence_Field sched_param_fields[] +Modules/posixmodule.c - SchedParamType variable static PyTypeObject* SchedParamType +Objects/iterobject.c - seqiter_methods variable static PyMethodDef seqiter_methods +Objects/setobject.c - set_as_number variable static PyNumberMethods set_as_number +Objects/setobject.c - set_as_sequence variable static PySequenceMethods set_as_sequence +Python/symtable.c - setcomp variable static identifier setcomp +Python/Python-ast.c - SetComp_fields variable static char *SetComp_fields[] +Python/Python-ast.c - SetComp_type variable static PyTypeObject *SetComp_type +Python/Python-ast.c - Set_fields variable static char *Set_fields[] +Objects/setobject.c - setiter_methods variable static PyMethodDef setiter_methods +Objects/setobject.c - set_methods variable static PyMethodDef set_methods +Python/Python-ast.c - Set_type variable static PyTypeObject *Set_type +Modules/signalmodule.c - SiginfoType variable static PyTypeObject SiginfoType +Modules/signalmodule.c - signal_methods variable static PyMethodDef signal_methods +Modules/signalmodule.c - signalmodule variable static struct PyModuleDef signalmodule +Python/import.c PyImport_Import silly_list variable static PyObject *silly_list +Objects/sliceobject.c - slice_cache variable static PySliceObject *slice_cache +Python/Python-ast.c - Slice_fields variable static char *Slice_fields[] +Objects/sliceobject.c - slice_members variable static PyMemberDef slice_members[] +Objects/sliceobject.c - slice_methods variable static PyMethodDef slice_methods +Python/Python-ast.c - slice_type variable static PyTypeObject *slice_type +Python/Python-ast.c - Slice_type variable static PyTypeObject *Slice_type +Objects/typeobject.c - slotdefs variable static slotdef slotdefs[] +Objects/typeobject.c - slotdefs_initialized variable static int slotdefs_initialized +Objects/longobject.c - small_ints variable static PyLongObject small_ints[NSMALLNEGINTS + NSMALLPOSINTS] +Objects/funcobject.c - sm_getsetlist variable static PyGetSetDef sm_getsetlist[] +Objects/funcobject.c - sm_memberlist variable static PyMemberDef sm_memberlist[] +Modules/xxsubtype.c - spamdict_members variable static PyMemberDef spamdict_members[] +Modules/xxsubtype.c - spamdict_methods variable static PyMethodDef spamdict_methods +Modules/xxsubtype.c - spamdict_type variable static PyTypeObject spamdict_type +Modules/xxsubtype.c - spamlist_getsets variable static PyGetSetDef spamlist_getsets[] +Modules/xxsubtype.c - spamlist_methods variable static PyMethodDef spamlist_methods +Modules/xxsubtype.c - spamlist_type variable static PyTypeObject spamlist_type +Modules/_sre.c - sremodule variable static struct PyModuleDef sremodule +Modules/faulthandler.c - stack variable static stack_t stack +Modules/itertoolsmodule.c - starmap_methods variable static PyMethodDef starmap_methods +Modules/itertoolsmodule.c - starmap_type variable static PyTypeObject starmap_type +Python/Python-ast.c - Starred_fields variable static char *Starred_fields[] +Python/Python-ast.c - Starred_type variable static PyTypeObject *Starred_type +Python/graminit.c - states_0 variable static state states_0[3] +Python/graminit.c - states_1 variable static state states_1[2] +Python/graminit.c - states_10 variable static state states_10[4] +Python/graminit.c - states_11 variable static state states_11[34] +Python/graminit.c - states_12 variable static state states_12[2] +Python/graminit.c - states_13 variable static state states_13[2] +Python/graminit.c - states_14 variable static state states_14[4] +Python/graminit.c - states_15 variable static state states_15[2] +Python/graminit.c - states_16 variable static state states_16[6] +Python/graminit.c - states_17 variable static state states_17[5] +Python/graminit.c - states_18 variable static state states_18[3] +Python/graminit.c - states_19 variable static state states_19[2] +Python/graminit.c - states_2 variable static state states_2[3] +Python/graminit.c - states_20 variable static state states_20[3] +Python/graminit.c - states_21 variable static state states_21[2] +Python/graminit.c - states_22 variable static state states_22[2] +Python/graminit.c - states_23 variable static state states_23[2] +Python/graminit.c - states_24 variable static state states_24[2] +Python/graminit.c - states_25 variable static state states_25[3] +Python/graminit.c - states_26 variable static state states_26[2] +Python/graminit.c - states_27 variable static state states_27[5] +Python/graminit.c - states_28 variable static state states_28[2] +Python/graminit.c - states_29 variable static state states_29[3] +Python/graminit.c - states_3 variable static state states_3[7] +Python/graminit.c - states_30 variable static state states_30[8] +Python/graminit.c - states_31 variable static state states_31[4] +Python/graminit.c - states_32 variable static state states_32[4] +Python/graminit.c - states_33 variable static state states_33[3] +Python/graminit.c - states_34 variable static state states_34[2] +Python/graminit.c - states_35 variable static state states_35[2] +Python/graminit.c - states_36 variable static state states_36[3] +Python/graminit.c - states_37 variable static state states_37[3] +Python/graminit.c - states_38 variable static state states_38[5] +Python/graminit.c - states_39 variable static state states_39[2] +Python/graminit.c - states_4 variable static state states_4[2] +Python/graminit.c - states_40 variable static state states_40[3] +Python/graminit.c - states_41 variable static state states_41[8] +Python/graminit.c - states_42 variable static state states_42[8] +Python/graminit.c - states_43 variable static state states_43[11] +Python/graminit.c - states_44 variable static state states_44[13] +Python/graminit.c - states_45 variable static state states_45[6] +Python/graminit.c - states_46 variable static state states_46[4] +Python/graminit.c - states_47 variable static state states_47[5] +Python/graminit.c - states_48 variable static state states_48[5] +Python/graminit.c - states_49 variable static state states_49[4] +Python/graminit.c - states_5 variable static state states_5[3] +Python/graminit.c - states_50 variable static state states_50[6] +Python/graminit.c - states_51 variable static state states_51[2] +Python/graminit.c - states_52 variable static state states_52[5] +Python/graminit.c - states_53 variable static state states_53[5] +Python/graminit.c - states_54 variable static state states_54[2] +Python/graminit.c - states_55 variable static state states_55[2] +Python/graminit.c - states_56 variable static state states_56[3] +Python/graminit.c - states_57 variable static state states_57[2] +Python/graminit.c - states_58 variable static state states_58[4] +Python/graminit.c - states_59 variable static state states_59[3] +Python/graminit.c - states_6 variable static state states_6[3] +Python/graminit.c - states_60 variable static state states_60[2] +Python/graminit.c - states_61 variable static state states_61[2] +Python/graminit.c - states_62 variable static state states_62[2] +Python/graminit.c - states_63 variable static state states_63[2] +Python/graminit.c - states_64 variable static state states_64[2] +Python/graminit.c - states_65 variable static state states_65[2] +Python/graminit.c - states_66 variable static state states_66[3] +Python/graminit.c - states_67 variable static state states_67[4] +Python/graminit.c - states_68 variable static state states_68[3] +Python/graminit.c - states_69 variable static state states_69[9] +Python/graminit.c - states_7 variable static state states_7[9] +Python/graminit.c - states_70 variable static state states_70[5] +Python/graminit.c - states_71 variable static state states_71[7] +Python/graminit.c - states_72 variable static state states_72[3] +Python/graminit.c - states_73 variable static state states_73[5] +Python/graminit.c - states_74 variable static state states_74[3] +Python/graminit.c - states_75 variable static state states_75[3] +Python/graminit.c - states_76 variable static state states_76[3] +Python/graminit.c - states_77 variable static state states_77[14] +Python/graminit.c - states_78 variable static state states_78[8] +Python/graminit.c - states_79 variable static state states_79[3] +Python/graminit.c - states_8 variable static state states_8[4] +Python/graminit.c - states_80 variable static state states_80[4] +Python/graminit.c - states_81 variable static state states_81[2] +Python/graminit.c - states_82 variable static state states_82[6] +Python/graminit.c - states_83 variable static state states_83[3] +Python/graminit.c - states_84 variable static state states_84[4] +Python/graminit.c - states_85 variable static state states_85[2] +Python/graminit.c - states_86 variable static state states_86[3] +Python/graminit.c - states_87 variable static state states_87[3] +Python/graminit.c - states_88 variable static state states_88[7] +Python/graminit.c - states_89 variable static state states_89[3] +Python/graminit.c - states_9 variable static state states_9[42] +Python/graminit.c - states_90 variable static state states_90[6] +Python/graminit.c - states_91 variable static state states_91[11] +Python/getargs.c - static_arg_parsers variable static struct _PyArg_Parser *static_arg_parsers +Objects/unicodeobject.c - static_strings variable static _Py_Identifier *static_strings +Modules/_stat.c - stat_methods variable static PyMethodDef stat_methods +Modules/_stat.c - statmodule variable static struct PyModuleDef statmodule +Modules/posixmodule.c - stat_result_desc variable static PyStructSequence_Desc stat_result_desc +Modules/posixmodule.c - stat_result_fields variable static PyStructSequence_Field stat_result_fields[] +Modules/posixmodule.c - StatResultType variable static PyTypeObject* StatResultType +Modules/posixmodule.c - statvfs_result_desc variable static PyStructSequence_Desc statvfs_result_desc +Modules/posixmodule.c - statvfs_result_fields variable static PyStructSequence_Field statvfs_result_fields[] +Modules/posixmodule.c - StatVFSResultType variable static PyTypeObject* StatVFSResultType +Objects/fileobject.c - stdprinter_getsetlist variable static PyGetSetDef stdprinter_getsetlist[] +Objects/fileobject.c - stdprinter_methods variable static PyMethodDef stdprinter_methods +Python/symtable.c - ste_memberlist variable static PyMemberDef ste_memberlist[] +Python/Python-ast.c - stmt_attributes variable static char *stmt_attributes[] +Python/Python-ast.c - stmt_type variable static PyTypeObject *stmt_type +Objects/exceptions.c - StopIteration_members variable static PyMemberDef StopIteration_members[] +Python/Python-ast.c - Store_singleton variable PyObject *Store_singleton +Python/Python-ast.c - Store_type variable static PyTypeObject *Store_type +Python/ast_unparse.c - _str_close_br variable static PyObject *_str_close_br +Python/ast_unparse.c - _str_dbl_close_br variable static PyObject *_str_dbl_close_br +Python/ast_unparse.c - _str_dbl_open_br variable static PyObject *_str_dbl_open_br +Modules/_threadmodule.c - str_dict variable static PyObject *str_dict +Modules/_io/stringio.c - stringio_getset variable static PyGetSetDef stringio_getset[] +Modules/_io/stringio.c - stringio_methods variable static PyMethodDef stringio_methods +Objects/unicodeobject.c - _string_methods variable static PyMethodDef _string_methods +Objects/unicodeobject.c - _string_module variable static struct PyModuleDef _string_module +Objects/bytesobject.c - striter_methods variable static PyMethodDef striter_methods +Python/ast_unparse.c - _str_open_br variable static PyObject *_str_open_br +Modules/pwdmodule.c - StructPwdType variable static PyTypeObject StructPwdType +Modules/pwdmodule.c - struct_pwd_type_desc variable static PyStructSequence_Desc struct_pwd_type_desc +Modules/pwdmodule.c - struct_pwd_type_fields variable static PyStructSequence_Field struct_pwd_type_fields[] +Modules/posixmodule.c wait_helper struct_rusage variable static PyObject *struct_rusage +Objects/structseq.c - structseq_methods variable static PyMethodDef structseq_methods +Modules/posixmodule.c - structseq_new variable static newfunc structseq_new +Modules/signalmodule.c - struct_siginfo_desc variable static PyStructSequence_Desc struct_siginfo_desc +Modules/signalmodule.c - struct_siginfo_fields variable static PyStructSequence_Field struct_siginfo_fields[] +Modules/timemodule.c - StructTimeType variable static PyTypeObject StructTimeType +Modules/timemodule.c - struct_time_type_desc variable static PyStructSequence_Desc struct_time_type_desc +Modules/timemodule.c - struct_time_type_fields variable static PyStructSequence_Field struct_time_type_fields[] +Python/Python-ast.c - Subscript_fields variable static char *Subscript_fields[] +Python/Python-ast.c - Subscript_type variable static PyTypeObject *Subscript_type +Python/Python-ast.c - Sub_singleton variable static PyObject *Sub_singleton +Python/Python-ast.c - Sub_type variable static PyTypeObject *Sub_type +Objects/typeobject.c - subtype_getsets_dict_only variable static PyGetSetDef subtype_getsets_dict_only[] +Objects/typeobject.c - subtype_getsets_full variable static PyGetSetDef subtype_getsets_full[] +Objects/typeobject.c - subtype_getsets_weakref_only variable static PyGetSetDef subtype_getsets_weakref_only[] +Python/Python-ast.c - Suite_fields variable static char *Suite_fields[] +Python/Python-ast.c - Suite_type variable static PyTypeObject *Suite_type +Objects/typeobject.c - super_members variable static PyMemberDef super_members[] +Modules/symtablemodule.c - symtable_methods variable static PyMethodDef symtable_methods +Modules/symtablemodule.c - symtablemodule variable static struct PyModuleDef symtablemodule +Objects/exceptions.c - SyntaxError_members variable static PyMemberDef SyntaxError_members[] +Python/sysmodule.c - sys_methods variable static PyMethodDef sys_methods +Python/sysmodule.c - sysmodule variable static struct PyModuleDef sysmodule +Objects/exceptions.c - SystemExit_members variable static PyMemberDef SystemExit_members[] +Modules/_tracemalloc.c - tables_lock variable static PyThread_type_lock tables_lock +Modules/itertoolsmodule.c - takewhile_reduce_methods variable static PyMethodDef takewhile_reduce_methods +Modules/itertoolsmodule.c - takewhile_type variable static PyTypeObject takewhile_type +Python/pylifecycle.c - _TARGET_LOCALES variable static _LocaleCoercionTarget _TARGET_LOCALES[] +Python/traceback.c - tb_getsetters variable static PyGetSetDef tb_getsetters[] +Python/traceback.c - tb_memberlist variable static PyMemberDef tb_memberlist[] +Python/traceback.c - tb_methods variable static PyMethodDef tb_methods +Modules/itertoolsmodule.c - teedataobject_methods variable static PyMethodDef teedataobject_methods +Modules/itertoolsmodule.c - teedataobject_type variable static PyTypeObject teedataobject_type +Modules/itertoolsmodule.c - tee_methods variable static PyMethodDef tee_methods +Modules/itertoolsmodule.c - tee_type variable static PyTypeObject tee_type +Modules/posixmodule.c - TerminalSize_desc variable static PyStructSequence_Desc TerminalSize_desc +Modules/posixmodule.c - TerminalSize_fields variable static PyStructSequence_Field TerminalSize_fields[] +Modules/posixmodule.c - TerminalSizeType variable static PyTypeObject* TerminalSizeType +Modules/_io/textio.c - textiobase_getset variable static PyGetSetDef textiobase_getset[] +Modules/_io/textio.c - textiobase_methods variable static PyMethodDef textiobase_methods +Modules/_io/textio.c - textiowrapper_getset variable static PyGetSetDef textiowrapper_getset[] +Modules/_io/textio.c - textiowrapper_members variable static PyMemberDef textiowrapper_members[] +Modules/_io/textio.c - textiowrapper_methods variable static PyMethodDef textiowrapper_methods +Modules/faulthandler.c - thread variable static struct { PyObject *file; int fd; PY_TIMEOUT_T timeout_us; int repeat; PyInterpreterState *interp; int exit; char *header; size_t header_len; PyThread_type_lock cancel_event; PyThread_type_lock running; } thread +Python/thread.c - thread_debug variable static int thread_debug +Modules/_threadmodule.c - ThreadError variable static PyObject *ThreadError +Python/thread.c - threadinfo_desc variable static PyStructSequence_Desc threadinfo_desc +Python/thread.c - threadinfo_fields variable static PyStructSequence_Field threadinfo_fields[] +Python/thread.c - ThreadInfoType variable static PyTypeObject ThreadInfoType +Modules/_threadmodule.c - thread_methods variable static PyMethodDef thread_methods +Modules/_threadmodule.c - threadmodule variable static struct PyModuleDef threadmodule +Modules/posixmodule.c - ticks_per_second variable static long ticks_per_second +Modules/timemodule.c _PyTime_GetProcessTimeWithInfo ticks_per_second variable static long ticks_per_second +Modules/timemodule.c - time_methods variable static PyMethodDef time_methods +Modules/timemodule.c - timemodule variable static struct PyModuleDef timemodule +Modules/posixmodule.c - times_result_desc variable static PyStructSequence_Desc times_result_desc +Modules/posixmodule.c - times_result_fields variable static PyStructSequence_Field times_result_fields[] +Modules/posixmodule.c - TimesResultType variable static PyTypeObject* TimesResultType +Python/context.c - _token_missing variable static PyObject *_token_missing +Python/symtable.c - top variable static identifier top +Objects/typeobject.c - tp_new_methoddef variable static struct PyMethodDef tp_new_methoddef[] +Modules/_tracemalloc.c - tracemalloc_empty_traceback variable static traceback_t tracemalloc_empty_traceback +Modules/_tracemalloc.c - tracemalloc_filenames variable static _Py_hashtable_t *tracemalloc_filenames +Modules/_tracemalloc.c - tracemalloc_peak_traced_memory variable static size_t tracemalloc_peak_traced_memory +Modules/_tracemalloc.c - tracemalloc_reentrant_key variable static Py_tss_t tracemalloc_reentrant_key +Modules/_tracemalloc.c - tracemalloc_traceback variable static traceback_t *tracemalloc_traceback +Modules/_tracemalloc.c - tracemalloc_tracebacks variable static _Py_hashtable_t *tracemalloc_tracebacks +Modules/_tracemalloc.c - tracemalloc_traced_memory variable static size_t tracemalloc_traced_memory +Modules/_tracemalloc.c - tracemalloc_traces variable static _Py_hashtable_t *tracemalloc_traces +Objects/boolobject.c - true_str variable static PyObject *true_str +Python/Python-ast.c - Try_fields variable static char *Try_fields[] +Python/Python-ast.c - Try_type variable static PyTypeObject *Try_type +Objects/tupleobject.c - tuple_as_mapping variable static PyMappingMethods tuple_as_mapping +Objects/tupleobject.c - tuple_as_sequence variable static PySequenceMethods tuple_as_sequence +Python/Python-ast.c - Tuple_fields variable static char *Tuple_fields[] +Modules/_collectionsmodule.c - tuplegetter_members variable static PyMemberDef tuplegetter_members[] +Modules/_collectionsmodule.c - tuplegetter_methods variable static PyMethodDef tuplegetter_methods +Modules/_collectionsmodule.c - tuplegetter_type variable static PyTypeObject tuplegetter_type +Objects/tupleobject.c - tupleiter_methods variable static PyMethodDef tupleiter_methods +Objects/tupleobject.c - tuple_methods variable static PyMethodDef tuple_methods +Python/Python-ast.c - Tuple_type variable static PyTypeObject *Tuple_type +Objects/typeobject.c - type_getsets variable static PyGetSetDef type_getsets[] +Python/Python-ast.c - TypeIgnore_fields variable static char *TypeIgnore_fields[] +Python/Python-ast.c - type_ignore_type variable static PyTypeObject *type_ignore_type +Python/Python-ast.c - TypeIgnore_type variable static PyTypeObject *TypeIgnore_type +Objects/typeobject.c - type_members variable static PyMemberDef type_members[] +Objects/typeobject.c - type_methods variable static PyMethodDef type_methods +Python/Python-ast.c - UAdd_singleton variable static PyObject *UAdd_singleton +Python/Python-ast.c - UAdd_type variable static PyTypeObject *UAdd_type +Objects/unicodeobject.c - ucnhash_CAPI variable static _PyUnicode_Name_CAPI *ucnhash_CAPI +Python/codecs.c - ucnhash_CAPI variable static _PyUnicode_Name_CAPI *ucnhash_CAPI +Python/ast.c - u_kind variable static PyObject *u_kind +Modules/posixmodule.c - uname_result_desc variable static PyStructSequence_Desc uname_result_desc +Modules/posixmodule.c - uname_result_fields variable static PyStructSequence_Field uname_result_fields[] +Modules/posixmodule.c - UnameResultType variable static PyTypeObject* UnameResultType +Python/Python-ast.c - UnaryOp_fields variable static char *UnaryOp_fields[] +Python/Python-ast.c - unaryop_type variable static PyTypeObject *unaryop_type +Python/Python-ast.c - UnaryOp_type variable static PyTypeObject *UnaryOp_type +Objects/unicodeobject.c - unicode_as_mapping variable static PyMappingMethods unicode_as_mapping +Objects/unicodeobject.c - unicode_as_number variable static PyNumberMethods unicode_as_number +Objects/unicodeobject.c - unicode_as_sequence variable static PySequenceMethods unicode_as_sequence +Objects/unicodeobject.c - unicode_empty variable static PyObject *unicode_empty +Objects/exceptions.c - UnicodeError_members variable static PyMemberDef UnicodeError_members[] +Objects/unicodeobject.c - unicodeiter_methods variable static PyMethodDef unicodeiter_methods +Objects/unicodeobject.c - unicode_latin1 variable static PyObject *unicode_latin1[256] +Objects/unicodeobject.c - unicode_methods variable static PyMethodDef unicode_methods +Modules/_tracemalloc.c - unknown_filename variable static PyObject *unknown_filename +Python/errors.c - UnraisableHookArgs_desc variable static PyStructSequence_Desc UnraisableHookArgs_desc +Python/errors.c - UnraisableHookArgs_fields variable static PyStructSequence_Field UnraisableHookArgs_fields[] +Python/errors.c - UnraisableHookArgsType variable static PyTypeObject UnraisableHookArgsType +Objects/obmalloc.c - unused_arena_objects variable static struct arena_object* unused_arena_objects +Python/bootstrap_hash.c - urandom_cache variable static struct { int fd; dev_t st_dev; ino_t st_ino; } urandom_cache +Objects/obmalloc.c - usable_arenas variable static struct arena_object* usable_arenas +Objects/obmalloc.c - usedpools variable static poolp usedpools[2 * ((NB_SMALL_SIZE_CLASSES + 7) / 8) * 8] +Modules/faulthandler.c - user_signals variable static user_signal_t *user_signals +Python/Python-ast.c - USub_singleton variable static PyObject *USub_singleton +Python/Python-ast.c - USub_type variable static PyTypeObject *USub_type +Python/getversion.c Py_GetVersion version variable static char version[250] +Python/sysmodule.c - version_info_desc variable static PyStructSequence_Desc version_info_desc +Python/sysmodule.c - version_info_fields variable static PyStructSequence_Field version_info_fields[] +Python/sysmodule.c - VersionInfoType variable static PyTypeObject VersionInfoType +Modules/posixmodule.c - waitid_result_desc variable static PyStructSequence_Desc waitid_result_desc +Modules/posixmodule.c - waitid_result_fields variable static PyStructSequence_Field waitid_result_fields[] +Modules/posixmodule.c - WaitidResultType variable static PyTypeObject* WaitidResultType +Modules/signalmodule.c - wakeup variable static volatile struct { SOCKET_T fd; int warn_on_full_buffer; int use_send; } wakeup +Python/_warnings.c - warnings_functions variable static PyMethodDef warnings_functions[] +Python/_warnings.c - warningsmodule variable static struct PyModuleDef warningsmodule +Modules/_weakref.c - weakref_functions variable static PyMethodDef weakref_functions +Objects/weakrefobject.c - weakref_members variable static PyMemberDef weakref_members[] +Modules/_weakref.c - weakrefmodule variable static struct PyModuleDef weakrefmodule +Python/sysmodule.c - whatstrings variable static PyObject *whatstrings[8] +Python/Python-ast.c - While_fields variable static char *While_fields[] +Python/Python-ast.c - While_type variable static PyTypeObject *While_type +Python/Python-ast.c - With_fields variable static char *With_fields[] +Python/Python-ast.c - withitem_fields variable static char *withitem_fields[] +Python/Python-ast.c - withitem_type variable static PyTypeObject *withitem_type +Python/Python-ast.c - With_type variable static PyTypeObject *With_type +Objects/descrobject.c - wrapperdescr_getset variable static PyGetSetDef wrapperdescr_getset[] +Objects/descrobject.c - wrapper_getsets variable static PyGetSetDef wrapper_getsets[] +Objects/descrobject.c - wrapper_members variable static PyMemberDef wrapper_members[] +Objects/descrobject.c - wrapper_methods variable static PyMethodDef wrapper_methods +Modules/_threadmodule.c local_new wr_callback_def variable static PyMethodDef wr_callback_def +Modules/xxsubtype.c - xxsubtype_functions variable static PyMethodDef xxsubtype_functions[] +Modules/xxsubtype.c - xxsubtypemodule variable static struct PyModuleDef xxsubtypemodule +Modules/xxsubtype.c - xxsubtype_slots variable static struct PyModuleDef_Slot xxsubtype_slots[] +Python/Python-ast.c - Yield_fields variable static char *Yield_fields[] +Python/Python-ast.c - YieldFrom_fields variable static char *YieldFrom_fields[] +Python/Python-ast.c - YieldFrom_type variable static PyTypeObject *YieldFrom_type +Python/Python-ast.c - Yield_type variable static PyTypeObject *Yield_type +Modules/itertoolsmodule.c - zip_longest_methods variable static PyMethodDef zip_longest_methods +Modules/itertoolsmodule.c - ziplongest_type variable static PyTypeObject ziplongest_type +Python/bltinmodule.c - zip_methods variable static PyMethodDef zip_methods From 21c41757b3d4e6b0861de574c0d1d2ad6c345c2c Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sun, 8 Sep 2019 16:03:22 +0100 Subject: [PATCH 099/118] Mark _Py_IDENTIFIER() as unsupported. --- Tools/c-analyzer/c_statics/supported.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Tools/c-analyzer/c_statics/supported.py b/Tools/c-analyzer/c_statics/supported.py index c74067480a0c4c..71df7f514e924e 100644 --- a/Tools/c-analyzer/c_statics/supported.py +++ b/Tools/c-analyzer/c_statics/supported.py @@ -132,9 +132,10 @@ def _is_vartype_okay(vartype, ignoredtypes=None): # stack_t # _PyUnicode_Name_CAPI - # funcsions + # functions if '(' in vartype and '[' not in vartype: - return True + if not vartype.startswith(('_Py_IDENTIFIER(', '_Py_static_string(')): + return True # XXX finish! # * allow const values? From a245849e141a1de9b25dec7873541e259af04fff Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sun, 8 Sep 2019 16:06:57 +0100 Subject: [PATCH 100/118] Keep "static" in output. --- Tools/c-analyzer/c_statics/show.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Tools/c-analyzer/c_statics/show.py b/Tools/c-analyzer/c_statics/show.py index 3b2a431404aca6..7e2015ec96b53e 100644 --- a/Tools/c-analyzer/c_statics/show.py +++ b/Tools/c-analyzer/c_statics/show.py @@ -8,9 +8,9 @@ def basic(statics, *, else: line = f'{static.filename}:{static.name}' vartype = static.vartype - if vartype.startswith('static '): - vartype = vartype.partition(' ')[2] - else: - vartype = '=' + vartype + #if vartype.startswith('static '): + # vartype = vartype.partition(' ')[2] + #else: + # vartype = '=' + vartype line = f'{line:<64} {vartype}' _print(line) From 1437d56b5ef52e818cda7ebaf96dfb90bed7b204 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sun, 8 Sep 2019 16:13:24 +0100 Subject: [PATCH 101/118] Fix a typo in __main__.py. --- Tools/c-analyzer/c_statics/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tools/c-analyzer/c_statics/__main__.py b/Tools/c-analyzer/c_statics/__main__.py index 89d19922b77614..b4161876d5fedd 100644 --- a/Tools/c-analyzer/c_statics/__main__.py +++ b/Tools/c-analyzer/c_statics/__main__.py @@ -168,7 +168,7 @@ def parse_args(prog=PROG, argv=sys.argv[1:], *, _fail=None): check = subs.add_parser('check', parents=[common]) - check = subs.add_parser('show', parents=[common]) + show = subs.add_parser('show', parents=[common]) if _fail is None: def _fail(msg): From 7feea9d38a8af2843ab2a348b634e6ab6203bb99 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sun, 8 Sep 2019 16:21:01 +0100 Subject: [PATCH 102/118] Honor provided dirnames. --- Tools/c-analyzer/c_statics/find.py | 3 +-- Tools/c-analyzer/c_symbols/resolve.py | 12 +++++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Tools/c-analyzer/c_statics/find.py b/Tools/c-analyzer/c_statics/find.py index 5112978e4f792c..b8e99fd3a2f902 100644 --- a/Tools/c-analyzer/c_statics/find.py +++ b/Tools/c-analyzer/c_statics/find.py @@ -26,8 +26,7 @@ def statics_from_binary(binfile=b_symbols.PYTHON, *, symbols = _iter_symbols(binfile, find_local_symbol=None) #symbols = list(symbols) for variable in _resolve(symbols, - #resolve=_get_symbol_resolver(knownvars, dirnames), - resolve=_get_symbol_resolver(knownvars), + resolve=_get_symbol_resolver(knownvars, dirnames), ): # Skip each non-static variable (unless we couldn't find it). # XXX Drop the "UNKNOWN" condition? diff --git a/Tools/c-analyzer/c_symbols/resolve.py b/Tools/c-analyzer/c_symbols/resolve.py index 40a2ad3872ded1..dc876ae0b75966 100644 --- a/Tools/c-analyzer/c_symbols/resolve.py +++ b/Tools/c-analyzer/c_symbols/resolve.py @@ -1,3 +1,5 @@ +import os.path + from c_analyzer_common import files from c_analyzer_common.info import UNKNOWN from c_parser import declarations, info @@ -101,8 +103,16 @@ def resolve_known(symbol): def resolve(symbol): found = resolve_known(symbol) if found is None: - return _from_source(symbol, dirnames) + return None + #return _from_source(symbol, dirnames) else: + for dirname in dirnames: + if not dirname.endswith(os.path.sep): + dirname += os.path.sep + if found.filename.startswith(dirname): + break + else: + return None return found else: resolve = resolve_known From ae238018091092b8e7a478012a986c2f0835b9ca Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sun, 8 Sep 2019 16:30:26 +0100 Subject: [PATCH 103/118] Fix tests. --- .../test_c_statics/test___main__.py | 3 +++ .../test_c_statics/test_find.py | 2 +- .../test_c_statics/test_show.py | 18 +++++++++--------- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test___main__.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test___main__.py index 5237b05de0bc80..5408111c641602 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test___main__.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test___main__.py @@ -124,6 +124,7 @@ def test_some_unsupported(self): ('_print', ('ERROR: found unsupported static variables',)), ('_print', ()), ('_show', (sorted(unsupported),)), + ('_print', (' (3 total)',)), ]) self.assertEqual(cm.exception.code, 1) @@ -167,10 +168,12 @@ def test_typical(self): ('_print', ('supported:',)), ('_print', ('----------',)), ('_show', (sorted(supported),)), + ('_print', (' (6 total)',)), ('_print', ()), ('_print', ('unsupported:',)), ('_print', ('------------',)), ('_show', (sorted(unsupported),)), + ('_print', (' (3 total)',)), ]) diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py index 75fc6cb46ff8fa..7f14fe0e23c76b 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py @@ -71,7 +71,7 @@ def test_typical(self): self.assertEqual(self.calls, [ ('_iter_symbols', ('python', None)), ('_get_symbol_resolver', (knownvars, None)), - ('_resolve_symbols', (list(symbols), resolver)), + ('_resolve_symbols', (symbols, resolver)), ]) # self._return_iter_symbols = [ diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_show.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_show.py index 1506d8179271fd..bcfb2e5c3fbef7 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_show.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_show.py @@ -34,15 +34,15 @@ def test_typical(self): _print=self.print) self.assertEqual(self.lines, [ - 'src1/spam.c:var1 const char *', - 'src1/spam.c:ham():initialized int', - 'src1/spam.c:var2 PyObject *', - 'src1/eggs.c:tofu():ready int', - 'src1/spam.c:freelist (PyTupleObject *)[10]', - 'src1/sub/ham.c:var1 const char const *', - 'src2/jam.c:var1 int', - 'src2/jam.c:var2 MyObject *', - 'Include/spam.h:data const int', + 'src1/spam.c:var1 static const char *', + 'src1/spam.c:ham():initialized static int', + 'src1/spam.c:var2 static PyObject *', + 'src1/eggs.c:tofu():ready static int', + 'src1/spam.c:freelist static (PyTupleObject *)[10]', + 'src1/sub/ham.c:var1 static const char const *', + 'src2/jam.c:var1 static int', + 'src2/jam.c:var2 static MyObject *', + 'Include/spam.h:data static const int', ]) def test_no_rows(self): From 26aaccbf7cae90361a4333d1566bb79b69444aff Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sun, 8 Sep 2019 16:46:34 +0100 Subject: [PATCH 104/118] Deal with default dirnames properly. --- Tools/c-analyzer/c_statics/__main__.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Tools/c-analyzer/c_statics/__main__.py b/Tools/c-analyzer/c_statics/__main__.py index b4161876d5fedd..b7f6b2f7c9a7be 100644 --- a/Tools/c-analyzer/c_statics/__main__.py +++ b/Tools/c-analyzer/c_statics/__main__.py @@ -1,7 +1,8 @@ import argparse +import os.path import sys -from c_analyzer_common import SOURCE_DIRS +from c_analyzer_common import SOURCE_DIRS, REPO_ROOT from c_analyzer_common.info import UNKNOWN from c_analyzer_common.known import ( from_file as known_from_file, @@ -65,6 +66,9 @@ def _check_results(unknown, knownvars, used): def _find_statics(dirnames, known, ignored): + if dirnames == SOURCE_DIRS: + dirnames = [os.path.relpath(d, REPO_ROOT) for d in dirnames] + ignored = ignored_from_file(ignored) known = known_from_file(known) From 4aaad5fe998edb5086f2277c926102ae86d336fd Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sun, 8 Sep 2019 16:50:51 +0100 Subject: [PATCH 105/118] Supporting hiding objects in output. --- .../test_c_analyzer/test_c_statics/test___main__.py | 6 +++++- Tools/c-analyzer/c_statics/__main__.py | 8 ++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test___main__.py b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test___main__.py index 5408111c641602..d1a346c71c2c76 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test___main__.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_statics/test___main__.py @@ -179,6 +179,8 @@ def test_typical(self): class ParseArgsTests(unittest.TestCase): + maxDiff = None + def test_no_args(self): self.errmsg = None def fail(msg): @@ -229,6 +231,7 @@ def test_show_no_args(self): 'ignored': IGNORED_FILE, 'known': KNOWN_FILE, 'dirs': SOURCE_DIRS, + 'skip_objects': False, }) def test_show_full_args(self): @@ -245,7 +248,8 @@ def test_show_full_args(self): self.assertEqual(cmdkwargs, { 'ignored': 'spam.tsv', 'known': 'eggs.tsv', - 'dirs': ['dir1', 'dir2', 'dir3'] + 'dirs': ['dir1', 'dir2', 'dir3'], + 'skip_objects': False, }) diff --git a/Tools/c-analyzer/c_statics/__main__.py b/Tools/c-analyzer/c_statics/__main__.py index b7f6b2f7c9a7be..91eef9aceacee0 100644 --- a/Tools/c-analyzer/c_statics/__main__.py +++ b/Tools/c-analyzer/c_statics/__main__.py @@ -1,5 +1,6 @@ import argparse import os.path +import re import sys from c_analyzer_common import SOURCE_DIRS, REPO_ROOT @@ -115,6 +116,7 @@ def cmd_check(cmd, dirs=SOURCE_DIRS, *, def cmd_show(cmd, dirs=SOURCE_DIRS, *, ignored=IGNORED_FILE, known=KNOWN_FILE, + skip_objects=False, _find=_find_statics, _show=show.basic, _print=print, @@ -127,6 +129,11 @@ def cmd_show(cmd, dirs=SOURCE_DIRS, *, allsupported = [] allunsupported = [] for found, supported in _find(dirs, known, ignored): + if skip_objects: # XXX Support proper filters instead. + if found.vartype.startswith(('_Py_IDENTIFIER(', '_Py_static_string(')): + continue + if re.match(r'.*Py[a-zA-z]*Object', found.vartype): + continue (allsupported if supported else allunsupported ).append(found) @@ -173,6 +180,7 @@ def parse_args(prog=PROG, argv=sys.argv[1:], *, _fail=None): check = subs.add_parser('check', parents=[common]) show = subs.add_parser('show', parents=[common]) + show.add_argument('--skip-objects', action='store_true') if _fail is None: def _fail(msg): From 3d36cfcdf1b207a6cf5c2026594f4a238ba73043 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sun, 8 Sep 2019 17:25:51 +0100 Subject: [PATCH 106/118] Recognize more object types. --- Tools/c-analyzer/c_statics/__main__.py | 6 ++---- Tools/c-analyzer/c_statics/supported.py | 7 ++++--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Tools/c-analyzer/c_statics/__main__.py b/Tools/c-analyzer/c_statics/__main__.py index 91eef9aceacee0..4630289ad23cd7 100644 --- a/Tools/c-analyzer/c_statics/__main__.py +++ b/Tools/c-analyzer/c_statics/__main__.py @@ -10,7 +10,7 @@ DATA_FILE as KNOWN_FILE, ) from . import find, show -from .supported import is_supported, ignored_from_file, IGNORED_FILE +from .supported import is_supported, ignored_from_file, IGNORED_FILE, _is_object def _match_unused_global(static, knownvars, used): @@ -130,9 +130,7 @@ def cmd_show(cmd, dirs=SOURCE_DIRS, *, allunsupported = [] for found, supported in _find(dirs, known, ignored): if skip_objects: # XXX Support proper filters instead. - if found.vartype.startswith(('_Py_IDENTIFIER(', '_Py_static_string(')): - continue - if re.match(r'.*Py[a-zA-z]*Object', found.vartype): + if _is_object(found.vartype): continue (allsupported if supported else allunsupported ).append(found) diff --git a/Tools/c-analyzer/c_statics/supported.py b/Tools/c-analyzer/c_statics/supported.py index 71df7f514e924e..a1bb13d7337c7f 100644 --- a/Tools/c-analyzer/c_statics/supported.py +++ b/Tools/c-analyzer/c_statics/supported.py @@ -134,8 +134,7 @@ def _is_vartype_okay(vartype, ignoredtypes=None): # functions if '(' in vartype and '[' not in vartype: - if not vartype.startswith(('_Py_IDENTIFIER(', '_Py_static_string(')): - return True + return True # XXX finish! # * allow const values? @@ -146,7 +145,9 @@ def _is_vartype_okay(vartype, ignoredtypes=None): def _is_object(vartype): if re.match(r'.*\bPy\w*Object\b', vartype): return True - if '_Py_Identifier' in vartype: + if '_PyArg_Parser ' in vartype: + return True + if vartype.startswith(('_Py_IDENTIFIER(', '_Py_static_string(')): return True if 'traceback_t' in vartype: return True From b7420d5b3e78c9200382f8b304c292f58452284a Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sun, 8 Sep 2019 17:26:13 +0100 Subject: [PATCH 107/118] Ignore known non-statics. --- Tools/c-analyzer/c_analyzer_common/known.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/Tools/c-analyzer/c_analyzer_common/known.py b/Tools/c-analyzer/c_analyzer_common/known.py index 087da001a33cc7..b302ea77806f76 100644 --- a/Tools/c-analyzer/c_analyzer_common/known.py +++ b/Tools/c-analyzer/c_analyzer_common/known.py @@ -35,7 +35,7 @@ def from_file(infile, *, if kind == 'variable': values = known['variables'] value = Variable(id, declaration) - value._isstatic = True + value._isstatic = _is_static(declaration) else: raise ValueError(f'unsupported kind in row {row}') if value.name == 'id' and declaration == UNKNOWN: @@ -45,3 +45,19 @@ def from_file(infile, *, value.validate() values[id] = value return known + + +def _is_static(vartype): + if vartype.startswith('static '): + return True + if vartype.startswith(('Py_LOCAL(', 'Py_LOCAL_INLINE(')): + return True + if vartype.startswith(('_Py_IDENTIFIER(', '_Py_static_string(')): + return True + if vartype.startswith('PyDoc_VAR('): + return True + if vartype.startswith(('SLOT1BINFULL(', 'SLOT1BIN(')): + return True + if vartype.startswith('WRAP_METHOD('): + return True + return False From da151a703a309cf83ee163580e8903b70ea6f3d7 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 9 Sep 2019 12:34:45 +0100 Subject: [PATCH 108/118] Always support "static const" (non-object) variables. --- Tools/c-analyzer/c_statics/supported.py | 3 + Tools/c-analyzer/known.tsv | 188 ++++++++++++------------ 2 files changed, 97 insertions(+), 94 deletions(-) diff --git a/Tools/c-analyzer/c_statics/supported.py b/Tools/c-analyzer/c_statics/supported.py index a1bb13d7337c7f..eaf095b3a202d8 100644 --- a/Tools/c-analyzer/c_statics/supported.py +++ b/Tools/c-analyzer/c_statics/supported.py @@ -85,6 +85,9 @@ def _is_vartype_okay(vartype, ignoredtypes=None): if _is_object(vartype): return False + if vartype.startswith('static const '): + return True + # components for TypeObject definitions for name in ('PyMethodDef', 'PyGetSetDef', 'PyMemberDef'): if name in vartype: diff --git a/Tools/c-analyzer/known.tsv b/Tools/c-analyzer/known.tsv index 446b187a9a53e3..0b31baaa5f99b3 100644 --- a/Tools/c-analyzer/known.tsv +++ b/Tools/c-analyzer/known.tsv @@ -11,32 +11,32 @@ Objects/genobject.c - ag_asend_freelist variable static PyAsyncGenASend *ag_asen Objects/genobject.c - ag_asend_freelist_free variable static int ag_asend_freelist_free Objects/genobject.c - ag_value_freelist variable static _PyAsyncGenWrappedValue *ag_value_freelist[_PyAsyncGen_MAXFREELIST] Objects/genobject.c - ag_value_freelist_free variable static int ag_value_freelist_free -Python/Python-ast.c - alias_fields variable static char *alias_fields[] +Python/Python-ast.c - alias_fields variable static const char *alias_fields[] Python/Python-ast.c - alias_type variable static PyTypeObject *alias_type Modules/_tracemalloc.c - allocators variable static struct { PyMemAllocatorEx mem; PyMemAllocatorEx raw; PyMemAllocatorEx obj; } allocators Python/Python-ast.c - And_singleton variable PyObject *And_singleton Python/Python-ast.c - And_type variable static PyTypeObject *And_type -Python/Python-ast.c - AnnAssign_fields variable static char *AnnAssign_fields[] +Python/Python-ast.c - AnnAssign_fields variable static const char *AnnAssign_fields[] Python/Python-ast.c - AnnAssign_type variable static PyTypeObject *AnnAssign_type Python/compile.c - __annotations__ variable static PyObject *__annotations__ Objects/obmalloc.c - arenas variable static struct arena_object* arenas -Python/Python-ast.c - arg_attributes variable static char *arg_attributes[] -Python/Python-ast.c - arg_fields variable static char *arg_fields[] +Python/Python-ast.c - arg_attributes variable static const char *arg_attributes[] +Python/Python-ast.c - arg_fields variable static const char *arg_fields[] Python/Python-ast.c - arg_type variable static PyTypeObject *arg_type -Python/Python-ast.c - arguments_fields variable static char *arguments_fields[] +Python/Python-ast.c - arguments_fields variable static const char *arguments_fields[] Python/Python-ast.c - arguments_type variable static PyTypeObject *arguments_type -Python/Python-ast.c - Assert_fields variable static char *Assert_fields[] +Python/Python-ast.c - Assert_fields variable static const char *Assert_fields[] Python/compile.c compiler_assert assertion_error variable static PyObject *assertion_error Python/Python-ast.c - Assert_type variable static PyTypeObject *Assert_type -Python/Python-ast.c - Assign_fields variable static char *Assign_fields[] +Python/Python-ast.c - Assign_fields variable static const char *Assign_fields[] Python/Python-ast.c - Assign_type variable static PyTypeObject *Assign_type Python/Python-ast.c - _astmodule variable static struct PyModuleDef _astmodule Python/Python-ast.c - AST_type variable static PyTypeObject AST_type Python/Python-ast.c - ast_type_getsets variable static PyGetSetDef ast_type_getsets[] Python/Python-ast.c - ast_type_methods variable static PyMethodDef ast_type_methods -Python/Python-ast.c - AsyncFor_fields variable static char *AsyncFor_fields[] +Python/Python-ast.c - AsyncFor_fields variable static const char *AsyncFor_fields[] Python/Python-ast.c - AsyncFor_type variable static PyTypeObject *AsyncFor_type -Python/Python-ast.c - AsyncFunctionDef_fields variable static char *AsyncFunctionDef_fields[] +Python/Python-ast.c - AsyncFunctionDef_fields variable static const char *AsyncFunctionDef_fields[] Python/Python-ast.c - AsyncFunctionDef_type variable static PyTypeObject *AsyncFunctionDef_type Objects/genobject.c - async_gen_as_async variable static PyAsyncMethods async_gen_as_async Objects/genobject.c - async_gen_asend_as_async variable static PyAsyncMethods async_gen_asend_as_async @@ -49,7 +49,7 @@ Python/sysmodule.c - asyncgen_hooks_fields variable static PyStructSequence_Fiel Python/sysmodule.c - AsyncGenHooksType variable static PyTypeObject AsyncGenHooksType Objects/genobject.c - async_gen_memberlist variable static PyMemberDef async_gen_memberlist[] Objects/genobject.c - async_gen_methods variable static PyMethodDef async_gen_methods -Python/Python-ast.c - AsyncWith_fields variable static char *AsyncWith_fields[] +Python/Python-ast.c - AsyncWith_fields variable static const char *AsyncWith_fields[] Python/Python-ast.c - AsyncWith_type variable static PyTypeObject *AsyncWith_type Parser/listnode.c - atbol variable static int atbol Modules/atexitmodule.c - atexit_methods variable static PyMethodDef atexit_methods @@ -57,21 +57,21 @@ Modules/atexitmodule.c - atexitmodule variable static struct PyModuleDef atexitm Modules/atexitmodule.c - atexit_slots variable static PyModuleDef_Slot atexit_slots[] Modules/_operator.c - attrgetter_methods variable static PyMethodDef attrgetter_methods Modules/_operator.c - attrgetter_type variable static PyTypeObject attrgetter_type -Python/Python-ast.c - Attribute_fields variable static char *Attribute_fields[] +Python/Python-ast.c - Attribute_fields variable static const char *Attribute_fields[] Python/Python-ast.c - Attribute_type variable static PyTypeObject *Attribute_type -Python/Python-ast.c - AugAssign_fields variable static char *AugAssign_fields[] +Python/Python-ast.c - AugAssign_fields variable static const char *AugAssign_fields[] Python/Python-ast.c - AugAssign_type variable static PyTypeObject *AugAssign_type Python/Python-ast.c - AugLoad_singleton variable PyObject *AugLoad_singleton Python/Python-ast.c - AugLoad_type variable static PyTypeObject *AugLoad_type Python/Python-ast.c - AugStore_singleton variable PyObject *AugStore_singleton Python/Python-ast.c - AugStore_type variable static PyTypeObject *AugStore_type -Python/Python-ast.c - Await_fields variable static char *Await_fields[] +Python/Python-ast.c - Await_fields variable static const char *Await_fields[] Python/Python-ast.c - Await_type variable static PyTypeObject *Await_type Objects/exceptions.c - BaseException_getset variable static PyGetSetDef BaseException_getset[] Objects/exceptions.c - BaseException_members variable static struct PyMemberDef BaseException_members[] Objects/exceptions.c - BaseException_methods variable static PyMethodDef BaseException_methods Modules/posixmodule.c - billion variable static PyObject *billion -Python/Python-ast.c - BinOp_fields variable static char *BinOp_fields[] +Python/Python-ast.c - BinOp_fields variable static const char *BinOp_fields[] Python/Python-ast.c - BinOp_type variable static PyTypeObject *BinOp_type Python/Python-ast.c - BitAnd_singleton variable static PyObject *BitAnd_singleton Python/Python-ast.c - BitAnd_type variable static PyTypeObject *BitAnd_type @@ -81,7 +81,7 @@ Python/Python-ast.c - BitXor_singleton variable static PyObject *BitXor_singleto Python/Python-ast.c - BitXor_type variable static PyTypeObject *BitXor_type Objects/unicodeobject.c - bloom_linebreak variable static BLOOM_MASK bloom_linebreak Objects/boolobject.c - bool_as_number variable static PyNumberMethods bool_as_number -Python/Python-ast.c - BoolOp_fields variable static char *BoolOp_fields[] +Python/Python-ast.c - BoolOp_fields variable static const char *BoolOp_fields[] Python/Python-ast.c - boolop_type variable static PyTypeObject *boolop_type Python/Python-ast.c - BoolOp_type variable static PyTypeObject *BoolOp_type Python/_warnings.c is_internal_frame bootstrap_string variable static PyObject *bootstrap_string @@ -119,7 +119,7 @@ Modules/_io/bytesio.c - bytesio_getsetlist variable static PyGetSetDef bytesio_g Modules/_io/bytesio.c - bytesio_methods variable static PyMethodDef bytesio_methods Objects/bytesobject.c - bytes_methods variable static PyMethodDef bytes_methods Python/thread_pthread.h init_condattr ca variable static pthread_condattr_t ca -Python/Python-ast.c - Call_fields variable static char *Call_fields[] +Python/Python-ast.c - Call_fields variable static const char *Call_fields[] Objects/iterobject.c - calliter_methods variable static PyMethodDef calliter_methods Python/Python-ast.c - Call_type variable static PyTypeObject *Call_type Objects/cellobject.c - cell_getsetlist variable static PyGetSetDef cell_getsetlist[] @@ -127,7 +127,7 @@ Modules/itertoolsmodule.c - chain_methods variable static PyMethodDef chain_meth Modules/itertoolsmodule.c - chain_type variable static PyTypeObject chain_type Objects/bytesobject.c - characters variable static PyBytesObject *characters[UCHAR_MAX + 1] Python/symtable.c - __class__ variable static identifier __class__ -Python/Python-ast.c - ClassDef_fields variable static char *ClassDef_fields[] +Python/Python-ast.c - ClassDef_fields variable static const char *ClassDef_fields[] Python/Python-ast.c - ClassDef_type variable static PyTypeObject *ClassDef_type Objects/funcobject.c - cm_getsetlist variable static PyGetSetDef cm_getsetlist[] Objects/funcobject.c - cm_memberlist variable static PyMemberDef cm_memberlist[] @@ -140,17 +140,17 @@ Modules/_collectionsmodule.c - _collectionsmodule variable static struct PyModul Modules/itertoolsmodule.c - combinations_methods variable static PyMethodDef combinations_methods Modules/itertoolsmodule.c - combinations_type variable static PyTypeObject combinations_type Objects/typeobject.c object_new comma_id variable "_Py_static_string(comma_id, "", "")" -Python/Python-ast.c - Compare_fields variable static char *Compare_fields[] +Python/Python-ast.c - Compare_fields variable static const char *Compare_fields[] Python/Python-ast.c - Compare_type variable static PyTypeObject *Compare_type Objects/complexobject.c - complex_as_number variable static PyNumberMethods complex_as_number Objects/complexobject.c - complex_members variable static PyMemberDef complex_members[] Objects/complexobject.c - complex_methods variable static PyMethodDef complex_methods -Python/Python-ast.c - comprehension_fields variable static char *comprehension_fields[] +Python/Python-ast.c - comprehension_fields variable static const char *comprehension_fields[] Python/Python-ast.c - comprehension_type variable static PyTypeObject *comprehension_type Modules/itertoolsmodule.c - compress_methods variable static PyMethodDef compress_methods Modules/itertoolsmodule.c - compress_type variable static PyTypeObject compress_type Python/thread_pthread.h - condattr_monotonic variable static pthread_condattr_t *condattr_monotonic -Python/Python-ast.c - Constant_fields variable static char *Constant_fields[] +Python/Python-ast.c - Constant_fields variable static const char *Constant_fields[] Python/Python-ast.c - Constant_type variable static PyTypeObject *Constant_type Python/Python-ast.c - Continue_type variable static PyTypeObject *Continue_type Objects/longobject.c PyLong_FromString convmultmax_base variable static twodigits convmultmax_base[37] @@ -173,7 +173,7 @@ Modules/signalmodule.c - DefaultHandler variable static PyObject *DefaultHandler Modules/_collectionsmodule.c - defdict_members variable static PyMemberDef defdict_members[] Modules/_collectionsmodule.c - defdict_methods variable static PyMethodDef defdict_methods Modules/_collectionsmodule.c - defdict_type variable static PyTypeObject defdict_type -Python/Python-ast.c - Delete_fields variable static char *Delete_fields[] +Python/Python-ast.c - Delete_fields variable static const char *Delete_fields[] Python/Python-ast.c - Delete_type variable static PyTypeObject *Delete_type Python/Python-ast.c - Del_singleton variable PyObject *Del_singleton Python/Python-ast.c - Del_type variable static PyTypeObject *Del_type @@ -193,9 +193,9 @@ Objects/floatobject.c - detected_float_format variable static float_format_type Objects/dictobject.c - dict_as_mapping variable static PyMappingMethods dict_as_mapping Objects/dictobject.c - dict_as_sequence variable static PySequenceMethods dict_as_sequence Python/symtable.c - dictcomp variable static identifier dictcomp -Python/Python-ast.c - DictComp_fields variable static char *DictComp_fields[] +Python/Python-ast.c - DictComp_fields variable static const char *DictComp_fields[] Python/Python-ast.c - DictComp_type variable static PyTypeObject *DictComp_type -Python/Python-ast.c - Dict_fields variable static char *Dict_fields[] +Python/Python-ast.c - Dict_fields variable static const char *Dict_fields[] Objects/dictobject.c - dictitems_as_sequence variable static PySequenceMethods dictitems_as_sequence Objects/dictobject.c - dictitems_methods variable static PyMethodDef dictitems_methods Objects/dictobject.c - dictiter_methods variable static PyMethodDef dictiter_methods @@ -238,23 +238,23 @@ Objects/exceptions.c - errnomap variable static PyObject *errnomap Modules/errnomodule.c - errno_methods variable static PyMethodDef errno_methods Modules/errnomodule.c - errnomodule variable static struct PyModuleDef errnomodule Modules/_localemodule.c - Error variable static PyObject *Error -Python/Python-ast.c - excepthandler_attributes variable static char *excepthandler_attributes[] -Python/Python-ast.c - ExceptHandler_fields variable static char *ExceptHandler_fields[] +Python/Python-ast.c - excepthandler_attributes variable static const char *excepthandler_attributes[] +Python/Python-ast.c - ExceptHandler_fields variable static const char *ExceptHandler_fields[] Python/Python-ast.c - excepthandler_type variable static PyTypeObject *excepthandler_type Python/Python-ast.c - ExceptHandler_type variable static PyTypeObject *ExceptHandler_type Modules/_threadmodule.c - ExceptHookArgs_desc variable static PyStructSequence_Desc ExceptHookArgs_desc Modules/_threadmodule.c - ExceptHookArgs_fields variable static PyStructSequence_Field ExceptHookArgs_fields[] Modules/_threadmodule.c - ExceptHookArgsType variable static PyTypeObject ExceptHookArgsType Objects/exceptions.c _check_for_legacy_statements exec_prefix variable static PyObject *exec_prefix -Python/Python-ast.c - expr_attributes variable static char *expr_attributes[] +Python/Python-ast.c - expr_attributes variable static const char *expr_attributes[] Python/Python-ast.c - expr_context_type variable static PyTypeObject *expr_context_type -Python/Python-ast.c - Expression_fields variable static char *Expression_fields[] +Python/Python-ast.c - Expression_fields variable static const char *Expression_fields[] Python/Python-ast.c - Expression_type variable static PyTypeObject *Expression_type -Python/Python-ast.c - Expr_fields variable static char *Expr_fields[] +Python/Python-ast.c - Expr_fields variable static const char *Expr_fields[] Python/Python-ast.c - expr_type variable static PyTypeObject *expr_type Python/Python-ast.c - Expr_type variable static PyTypeObject *Expr_type Python/import.c - extensions variable static PyObject *extensions -Python/Python-ast.c - ExtSlice_fields variable static char *ExtSlice_fields[] +Python/Python-ast.c - ExtSlice_fields variable static const char *ExtSlice_fields[] Python/Python-ast.c - ExtSlice_type variable static PyTypeObject *ExtSlice_type Objects/boolobject.c - false_str variable static PyObject *false_str Modules/faulthandler.c - fatal_error variable static struct { int enabled; PyObject *file; int fd; int all_threads; PyInterpreterState *interp; void *exc_handler; } fatal_error @@ -279,8 +279,8 @@ Objects/floatobject.c - float_methods variable static PyMethodDef float_methods Python/Python-ast.c - FloorDiv_singleton variable static PyObject *FloorDiv_singleton Python/Python-ast.c - FloorDiv_type variable static PyTypeObject *FloorDiv_type Python/fileutils.c - force_ascii variable static int force_ascii -Python/Python-ast.c - For_fields variable static char *For_fields[] -Python/Python-ast.c - FormattedValue_fields variable static char *FormattedValue_fields[] +Python/Python-ast.c - For_fields variable static const char *For_fields[] +Python/Python-ast.c - FormattedValue_fields variable static const char *FormattedValue_fields[] Python/Python-ast.c - FormattedValue_type variable static PyTypeObject *FormattedValue_type Objects/stringlib/unicode_format.h - formatteriter_methods variable static PyMethodDef formatteriter_methods Python/Python-ast.c - For_type variable static PyTypeObject *For_type @@ -300,16 +300,16 @@ Objects/setobject.c - frozenset_as_number variable static PyNumberMethods frozen Objects/setobject.c - frozenset_methods variable static PyMethodDef frozenset_methods Objects/funcobject.c - func_getsetlist variable static PyGetSetDef func_getsetlist[] Objects/funcobject.c - func_memberlist variable static PyMemberDef func_memberlist[] -Python/Python-ast.c - FunctionDef_fields variable static char *FunctionDef_fields[] +Python/Python-ast.c - FunctionDef_fields variable static const char *FunctionDef_fields[] Python/Python-ast.c - FunctionDef_type variable static PyTypeObject *FunctionDef_type Modules/_sre.c - _functions variable static PyMethodDef _functions[] -Python/Python-ast.c - FunctionType_fields variable static char *FunctionType_fields[] +Python/Python-ast.c - FunctionType_fields variable static const char *FunctionType_fields[] Python/Python-ast.c - FunctionType_type variable static PyTypeObject *FunctionType_type Modules/_functoolsmodule.c - _functoolsmodule variable static struct PyModuleDef _functoolsmodule Modules/gcmodule.c - GcMethods variable static PyMethodDef GcMethods[] Modules/gcmodule.c - gcmodule variable static struct PyModuleDef gcmodule Modules/gcmodule.c - gc_str variable static PyObject *gc_str -Python/Python-ast.c - GeneratorExp_fields variable static char *GeneratorExp_fields[] +Python/Python-ast.c - GeneratorExp_fields variable static const char *GeneratorExp_fields[] Python/Python-ast.c - GeneratorExp_type variable static PyTypeObject *GeneratorExp_type Python/symtable.c - genexpr variable static identifier genexpr Objects/genobject.c - gen_getsetlist variable static PyGetSetDef gen_getsetlist[] @@ -317,7 +317,7 @@ Objects/genobject.c - gen_memberlist variable static PyMemberDef gen_memberlist[ Objects/genobject.c - gen_methods variable static PyMethodDef gen_methods Python/bootstrap_hash.c py_getrandom getrandom_works variable static int getrandom_works Objects/descrobject.c - getset_getset variable static PyGetSetDef getset_getset[] -Python/Python-ast.c - Global_fields variable static char *Global_fields[] +Python/Python-ast.c - Global_fields variable static const char *Global_fields[] Python/Python-ast.c - Global_type variable static PyTypeObject *Global_type Modules/itertoolsmodule.c - groupby_methods variable static PyMethodDef groupby_methods Modules/itertoolsmodule.c - groupby_type variable static PyTypeObject groupby_type @@ -352,17 +352,17 @@ Python/pystate.c interp_look_up_id id variable PY_INT64_T id ??? ??? id variable ??? ??? ??? id variable ??? ??? ??? id variable ??? -Python/Python-ast.c - IfExp_fields variable static char *IfExp_fields[] +Python/Python-ast.c - IfExp_fields variable static const char *IfExp_fields[] Python/Python-ast.c - IfExp_type variable static PyTypeObject *IfExp_type -Python/Python-ast.c - If_fields variable static char *If_fields[] +Python/Python-ast.c - If_fields variable static const char *If_fields[] Python/Python-ast.c - If_type variable static PyTypeObject *If_type Modules/signalmodule.c - IgnoreHandler variable static PyObject *IgnoreHandler Python/import.c - imp_methods variable static PyMethodDef imp_methods Python/import.c - impmodule variable static struct PyModuleDef impmodule Objects/exceptions.c - ImportError_members variable static PyMemberDef ImportError_members[] Objects/exceptions.c - ImportError_methods variable static PyMethodDef ImportError_methods -Python/Python-ast.c - Import_fields variable static char *Import_fields[] -Python/Python-ast.c - ImportFrom_fields variable static char *ImportFrom_fields[] +Python/Python-ast.c - Import_fields variable static const char *Import_fields[] +Python/Python-ast.c - ImportFrom_fields variable static const char *ImportFrom_fields[] Python/Python-ast.c - ImportFrom_type variable static PyTypeObject *ImportFrom_type Python/import.c import_find_and_load import_level variable static int import_level Python/_warnings.c is_internal_frame importlib_string variable static PyObject *importlib_string @@ -374,7 +374,7 @@ Python/Python-ast.c - Import_type variable static PyTypeObject *Import_type Modules/_io/textio.c - incrementalnewlinedecoder_getset variable static PyGetSetDef incrementalnewlinedecoder_getset[] Modules/_io/textio.c - incrementalnewlinedecoder_methods variable static PyMethodDef incrementalnewlinedecoder_methods Objects/listobject.c - indexerr variable static PyObject *indexerr -Python/Python-ast.c - Index_fields variable static char *Index_fields[] +Python/Python-ast.c - Index_fields variable static const char *Index_fields[] Python/Python-ast.c - Index_type variable static PyTypeObject *Index_type Python/thread.c - initialized variable static int initialized Modules/posixmodule.c - initialized variable static int initialized @@ -387,7 +387,7 @@ Python/import.c - inittab_copy variable static struct _inittab *inittab_copy Python/Python-ast.c - In_singleton variable static PyObject *In_singleton Objects/classobject.c - instancemethod_getset variable static PyGetSetDef instancemethod_getset[] Objects/classobject.c - instancemethod_memberlist variable static PyMemberDef instancemethod_memberlist[] -Python/Python-ast.c - Interactive_fields variable static char *Interactive_fields[] +Python/Python-ast.c - Interactive_fields variable static const char *Interactive_fields[] Python/Python-ast.c - Interactive_type variable static PyTypeObject *Interactive_type Objects/unicodeobject.c - interned variable static PyObject *interned Objects/interpreteridobject.c - interpid_as_number variable static PyNumberMethods interpid_as_number @@ -412,50 +412,50 @@ Modules/_operator.c - itemgetter_methods variable static PyMethodDef itemgetter_ Modules/_operator.c - itemgetter_type variable static PyTypeObject itemgetter_type Modules/itertoolsmodule.c - itertoolsmodule variable static struct PyModuleDef itertoolsmodule Modules/signalmodule.c - ItimerError variable static PyObject *ItimerError -Python/Python-ast.c - JoinedStr_fields variable static char *JoinedStr_fields[] +Python/Python-ast.c - JoinedStr_fields variable static const char *JoinedStr_fields[] Python/Python-ast.c - JoinedStr_type variable static PyTypeObject *JoinedStr_type Modules/_functoolsmodule.c - keyobject_members variable static PyMemberDef keyobject_members[] Modules/_functoolsmodule.c - keyobject_type variable static PyTypeObject keyobject_type Objects/dictobject.c - keys_free_list variable static PyDictKeysObject *keys_free_list[PyDict_MAXFREELIST] -Python/Python-ast.c - keyword_fields variable static char *keyword_fields[] -Python/sysmodule.c sys_set_asyncgen_hooks keywords variable static char *keywords[] -Modules/_bisectmodule.c bisect_right keywords variable static char *keywords[] -Modules/_bisectmodule.c insort_right keywords variable static char *keywords[] +Python/Python-ast.c - keyword_fields variable static const char *keyword_fields[] +Python/sysmodule.c sys_set_asyncgen_hooks keywords variable static const char *keywords[] +Modules/_bisectmodule.c bisect_right keywords variable static const char *keywords[] +Modules/_bisectmodule.c insort_right keywords variable static const char *keywords[] Python/Python-ast.c - keyword_type variable static PyTypeObject *keyword_type -Modules/_functoolsmodule.c keyobject_call kwargs variable static char *kwargs[] -Modules/_functoolsmodule.c functools_cmp_to_key kwargs variable static char *kwargs[] -Modules/itertoolsmodule.c repeat_new kwargs variable static char *kwargs[] -Python/_warnings.c warnings_warn_explicit kwd_list variable static char *kwd_list[] +Modules/_functoolsmodule.c keyobject_call kwargs variable static const char *kwargs[] +Modules/_functoolsmodule.c functools_cmp_to_key kwargs variable static const char *kwargs[] +Modules/itertoolsmodule.c repeat_new kwargs variable static const char *kwargs[] +Python/_warnings.c warnings_warn_explicit kwd_list variable static const char *kwd_list[] Modules/_functoolsmodule.c - kwd_mark variable static PyObject *kwd_mark -Python/bltinmodule.c builtin___import__ kwlist variable static char *kwlist[] -Python/bltinmodule.c min_max kwlist variable static char *kwlist[] -Python/context.c contextvar_tp_new kwlist variable static char *kwlist[] -Python/sysmodule.c sys_getsizeof kwlist variable static char *kwlist[] -Objects/bytearrayobject.c bytearray_init kwlist variable static char *kwlist[] -Objects/bytesobject.c bytes_new kwlist variable static char *kwlist[] -Objects/exceptions.c ImportError_init kwlist variable static char *kwlist[] -Objects/interpreteridobject.c interpid_new kwlist variable static char *kwlist[] -Objects/memoryobject.c memory_new kwlist variable static char *kwlist[] -Objects/memoryobject.c memory_cast kwlist variable static char *kwlist[] -Objects/memoryobject.c memory_tobytes kwlist variable static char *kwlist[] -Objects/odictobject.c odict_pop kwlist variable static char *kwlist[] -Objects/unicodeobject.c unicode_new kwlist variable static char *kwlist[] -Objects/weakrefobject.c weakref_call kwlist variable static char *kwlist[] -Modules/_elementtree.c element_setstate_from_Python kwlist variable static char *kwlist[] -Modules/_json.c scanner_call kwlist variable static char *kwlist[] -Modules/_json.c scanner_new kwlist variable static char *kwlist[] -Modules/_json.c encoder_new kwlist variable static char *kwlist[] -Modules/_json.c encoder_call kwlist variable static char *kwlist[] +Python/bltinmodule.c builtin___import__ kwlist variable static const char *kwlist[] +Python/bltinmodule.c min_max kwlist variable static const char *kwlist[] +Python/context.c contextvar_tp_new kwlist variable static const char *kwlist[] +Python/sysmodule.c sys_getsizeof kwlist variable static const char *kwlist[] +Objects/bytearrayobject.c bytearray_init kwlist variable static const char *kwlist[] +Objects/bytesobject.c bytes_new kwlist variable static const char *kwlist[] +Objects/exceptions.c ImportError_init kwlist variable static const char *kwlist[] +Objects/interpreteridobject.c interpid_new kwlist variable static const char *kwlist[] +Objects/memoryobject.c memory_new kwlist variable static const char *kwlist[] +Objects/memoryobject.c memory_cast kwlist variable static const char *kwlist[] +Objects/memoryobject.c memory_tobytes kwlist variable static const char *kwlist[] +Objects/odictobject.c odict_pop kwlist variable static const char *kwlist[] +Objects/unicodeobject.c unicode_new kwlist variable static const char *kwlist[] +Objects/weakrefobject.c weakref_call kwlist variable static const char *kwlist[] +Modules/_elementtree.c element_setstate_from_Python kwlist variable static const char *kwlist[] +Modules/_json.c scanner_call kwlist variable static const char *kwlist[] +Modules/_json.c scanner_new kwlist variable static const char *kwlist[] +Modules/_json.c encoder_new kwlist variable static const char *kwlist[] +Modules/_json.c encoder_call kwlist variable static const char *kwlist[] Python/symtable.c - lambda variable static identifier lambda -Python/Python-ast.c - Lambda_fields variable static char *Lambda_fields[] +Python/Python-ast.c - Lambda_fields variable static const char *Lambda_fields[] Python/Python-ast.c - Lambda_type variable static PyTypeObject *Lambda_type Parser/listnode.c - level variable static int level Objects/listobject.c - list_as_mapping variable static PyMappingMethods list_as_mapping Objects/listobject.c - list_as_sequence variable static PySequenceMethods list_as_sequence Python/symtable.c - listcomp variable static identifier listcomp -Python/Python-ast.c - ListComp_fields variable static char *ListComp_fields[] +Python/Python-ast.c - ListComp_fields variable static const char *ListComp_fields[] Python/Python-ast.c - ListComp_type variable static PyTypeObject *ListComp_type -Python/Python-ast.c - List_fields variable static char *List_fields[] +Python/Python-ast.c - List_fields variable static const char *List_fields[] Objects/listobject.c - listiter_methods variable static PyMethodDef listiter_methods Objects/listobject.c - list_methods variable static PyMethodDef list_methods Objects/listobject.c - listreviter_methods variable static PyMethodDef listreviter_methods @@ -525,7 +525,7 @@ Python/Python-ast.c - Mod_type variable static PyTypeObject *Mod_type Python/_warnings.c normalize_module module variable PyObject *module Modules/faulthandler.c - module_def variable static struct PyModuleDef module_def Modules/_tracemalloc.c - module_def variable static struct PyModuleDef module_def -Python/Python-ast.c - Module_fields variable static char *Module_fields[] +Python/Python-ast.c - Module_fields variable static const char *Module_fields[] Modules/_collectionsmodule.c - module_functions variable static struct PyMethodDef module_functions[] Modules/_abc.c - module_functions variable static struct PyMethodDef module_functions[] Objects/moduleobject.c - module_members variable static PyMemberDef module_members[] @@ -544,9 +544,9 @@ Python/compile.c compiler_genexp name variable static identifier name Python/compile.c compiler_listcomp name variable static identifier name Python/compile.c compiler_setcomp name variable static identifier name Python/compile.c compiler_dictcomp name variable static identifier name -Python/Python-ast.c - NamedExpr_fields variable static char *NamedExpr_fields[] +Python/Python-ast.c - NamedExpr_fields variable static const char *NamedExpr_fields[] Python/Python-ast.c - NamedExpr_type variable static PyTypeObject *NamedExpr_type -Python/Python-ast.c - Name_fields variable static char *Name_fields[] +Python/Python-ast.c - Name_fields variable static const char *Name_fields[] Objects/typeobject.c - name_op variable static _Py_Identifier name_op[] Objects/namespaceobject.c - namespace_members variable static PyMemberDef namespace_members[] Objects/namespaceobject.c - namespace_methods variable static PyMethodDef namespace_methods @@ -558,7 +558,7 @@ Objects/typeobject.c - next_version_tag variable static unsigned int next_versio Objects/obmalloc.c - nfp2lasta variable static struct arena_object* nfp2lasta[MAX_POOLS_IN_ARENA + 1] Python/dynload_shlib.c - nhandles variable static int nhandles Objects/object.c - none_as_number variable static PyNumberMethods none_as_number -Python/Python-ast.c - Nonlocal_fields variable static char *Nonlocal_fields[] +Python/Python-ast.c - Nonlocal_fields variable static const char *Nonlocal_fields[] Python/Python-ast.c - Nonlocal_type variable static PyTypeObject *Nonlocal_type Python/Python-ast.c - NotEq_singleton variable static PyObject *NotEq_singleton Python/Python-ast.c - NotEq_type variable static PyTypeObject *NotEq_type @@ -1586,7 +1586,7 @@ Objects/weakrefobject.c - _PyWeakref_RefType variable PyTypeObject _PyWeakref_Re Objects/weakrefobject.c - _PyWeakref_RefType variable PyTypeObject _PyWeakref_RefType Objects/descrobject.c - PyWrapperDescr_Type variable PyTypeObject PyWrapperDescr_Type Python/bltinmodule.c - PyZip_Type variable PyTypeObject PyZip_Type -Python/Python-ast.c - Raise_fields variable static char *Raise_fields[] +Python/Python-ast.c - Raise_fields variable static const char *Raise_fields[] Python/Python-ast.c - Raise_type variable static PyTypeObject *Raise_type Objects/rangeobject.c - range_as_mapping variable static PyMappingMethods range_as_mapping Objects/rangeobject.c - range_as_number variable static PyNumberMethods range_as_number @@ -1599,7 +1599,7 @@ Python/pylifecycle.c fatal_error reentrant variable static int reentrant Modules/faulthandler.c faulthandler_dump_traceback reentrant variable static volatile int reentrant Modules/itertoolsmodule.c - repeat_methods variable static PyMethodDef repeat_methods Modules/itertoolsmodule.c - repeat_type variable static PyTypeObject repeat_type -Python/Python-ast.c - Return_fields variable static char *Return_fields[] +Python/Python-ast.c - Return_fields variable static const char *Return_fields[] Python/compile.c compiler_visit_annotations return_str variable static identifier return_str Python/Python-ast.c - Return_type variable static PyTypeObject *Return_type Objects/enumobject.c - reversediter_methods variable static PyMethodDef reversediter_methods @@ -1634,9 +1634,9 @@ Objects/iterobject.c - seqiter_methods variable static PyMethodDef seqiter_metho Objects/setobject.c - set_as_number variable static PyNumberMethods set_as_number Objects/setobject.c - set_as_sequence variable static PySequenceMethods set_as_sequence Python/symtable.c - setcomp variable static identifier setcomp -Python/Python-ast.c - SetComp_fields variable static char *SetComp_fields[] +Python/Python-ast.c - SetComp_fields variable static const char *SetComp_fields[] Python/Python-ast.c - SetComp_type variable static PyTypeObject *SetComp_type -Python/Python-ast.c - Set_fields variable static char *Set_fields[] +Python/Python-ast.c - Set_fields variable static const char *Set_fields[] Objects/setobject.c - setiter_methods variable static PyMethodDef setiter_methods Objects/setobject.c - set_methods variable static PyMethodDef set_methods Python/Python-ast.c - Set_type variable static PyTypeObject *Set_type @@ -1645,7 +1645,7 @@ Modules/signalmodule.c - signal_methods variable static PyMethodDef signal_metho Modules/signalmodule.c - signalmodule variable static struct PyModuleDef signalmodule Python/import.c PyImport_Import silly_list variable static PyObject *silly_list Objects/sliceobject.c - slice_cache variable static PySliceObject *slice_cache -Python/Python-ast.c - Slice_fields variable static char *Slice_fields[] +Python/Python-ast.c - Slice_fields variable static const char *Slice_fields[] Objects/sliceobject.c - slice_members variable static PyMemberDef slice_members[] Objects/sliceobject.c - slice_methods variable static PyMethodDef slice_methods Python/Python-ast.c - slice_type variable static PyTypeObject *slice_type @@ -1665,7 +1665,7 @@ Modules/_sre.c - sremodule variable static struct PyModuleDef sremodule Modules/faulthandler.c - stack variable static stack_t stack Modules/itertoolsmodule.c - starmap_methods variable static PyMethodDef starmap_methods Modules/itertoolsmodule.c - starmap_type variable static PyTypeObject starmap_type -Python/Python-ast.c - Starred_fields variable static char *Starred_fields[] +Python/Python-ast.c - Starred_fields variable static const char *Starred_fields[] Python/Python-ast.c - Starred_type variable static PyTypeObject *Starred_type Python/graminit.c - states_0 variable static state states_0[3] Python/graminit.c - states_1 variable static state states_1[2] @@ -1772,7 +1772,7 @@ Modules/posixmodule.c - StatVFSResultType variable static PyTypeObject* StatVFSR Objects/fileobject.c - stdprinter_getsetlist variable static PyGetSetDef stdprinter_getsetlist[] Objects/fileobject.c - stdprinter_methods variable static PyMethodDef stdprinter_methods Python/symtable.c - ste_memberlist variable static PyMemberDef ste_memberlist[] -Python/Python-ast.c - stmt_attributes variable static char *stmt_attributes[] +Python/Python-ast.c - stmt_attributes variable static const char *stmt_attributes[] Python/Python-ast.c - stmt_type variable static PyTypeObject *stmt_type Objects/exceptions.c - StopIteration_members variable static PyMemberDef StopIteration_members[] Python/Python-ast.c - Store_singleton variable PyObject *Store_singleton @@ -1798,14 +1798,14 @@ Modules/signalmodule.c - struct_siginfo_fields variable static PyStructSequence_ Modules/timemodule.c - StructTimeType variable static PyTypeObject StructTimeType Modules/timemodule.c - struct_time_type_desc variable static PyStructSequence_Desc struct_time_type_desc Modules/timemodule.c - struct_time_type_fields variable static PyStructSequence_Field struct_time_type_fields[] -Python/Python-ast.c - Subscript_fields variable static char *Subscript_fields[] +Python/Python-ast.c - Subscript_fields variable static const char *Subscript_fields[] Python/Python-ast.c - Subscript_type variable static PyTypeObject *Subscript_type Python/Python-ast.c - Sub_singleton variable static PyObject *Sub_singleton Python/Python-ast.c - Sub_type variable static PyTypeObject *Sub_type Objects/typeobject.c - subtype_getsets_dict_only variable static PyGetSetDef subtype_getsets_dict_only[] Objects/typeobject.c - subtype_getsets_full variable static PyGetSetDef subtype_getsets_full[] Objects/typeobject.c - subtype_getsets_weakref_only variable static PyGetSetDef subtype_getsets_weakref_only[] -Python/Python-ast.c - Suite_fields variable static char *Suite_fields[] +Python/Python-ast.c - Suite_fields variable static const char *Suite_fields[] Python/Python-ast.c - Suite_type variable static PyTypeObject *Suite_type Objects/typeobject.c - super_members variable static PyMemberDef super_members[] Modules/symtablemodule.c - symtable_methods variable static PyMethodDef symtable_methods @@ -1860,11 +1860,11 @@ Modules/_tracemalloc.c - tracemalloc_tracebacks variable static _Py_hashtable_t Modules/_tracemalloc.c - tracemalloc_traced_memory variable static size_t tracemalloc_traced_memory Modules/_tracemalloc.c - tracemalloc_traces variable static _Py_hashtable_t *tracemalloc_traces Objects/boolobject.c - true_str variable static PyObject *true_str -Python/Python-ast.c - Try_fields variable static char *Try_fields[] +Python/Python-ast.c - Try_fields variable static const char *Try_fields[] Python/Python-ast.c - Try_type variable static PyTypeObject *Try_type Objects/tupleobject.c - tuple_as_mapping variable static PyMappingMethods tuple_as_mapping Objects/tupleobject.c - tuple_as_sequence variable static PySequenceMethods tuple_as_sequence -Python/Python-ast.c - Tuple_fields variable static char *Tuple_fields[] +Python/Python-ast.c - Tuple_fields variable static const char *Tuple_fields[] Modules/_collectionsmodule.c - tuplegetter_members variable static PyMemberDef tuplegetter_members[] Modules/_collectionsmodule.c - tuplegetter_methods variable static PyMethodDef tuplegetter_methods Modules/_collectionsmodule.c - tuplegetter_type variable static PyTypeObject tuplegetter_type @@ -1872,7 +1872,7 @@ Objects/tupleobject.c - tupleiter_methods variable static PyMethodDef tupleiter_ Objects/tupleobject.c - tuple_methods variable static PyMethodDef tuple_methods Python/Python-ast.c - Tuple_type variable static PyTypeObject *Tuple_type Objects/typeobject.c - type_getsets variable static PyGetSetDef type_getsets[] -Python/Python-ast.c - TypeIgnore_fields variable static char *TypeIgnore_fields[] +Python/Python-ast.c - TypeIgnore_fields variable static const char *TypeIgnore_fields[] Python/Python-ast.c - type_ignore_type variable static PyTypeObject *type_ignore_type Python/Python-ast.c - TypeIgnore_type variable static PyTypeObject *TypeIgnore_type Objects/typeobject.c - type_members variable static PyMemberDef type_members[] @@ -1885,7 +1885,7 @@ Python/ast.c - u_kind variable static PyObject *u_kind Modules/posixmodule.c - uname_result_desc variable static PyStructSequence_Desc uname_result_desc Modules/posixmodule.c - uname_result_fields variable static PyStructSequence_Field uname_result_fields[] Modules/posixmodule.c - UnameResultType variable static PyTypeObject* UnameResultType -Python/Python-ast.c - UnaryOp_fields variable static char *UnaryOp_fields[] +Python/Python-ast.c - UnaryOp_fields variable static const char *UnaryOp_fields[] Python/Python-ast.c - unaryop_type variable static PyTypeObject *unaryop_type Python/Python-ast.c - UnaryOp_type variable static PyTypeObject *UnaryOp_type Objects/unicodeobject.c - unicode_as_mapping variable static PyMappingMethods unicode_as_mapping @@ -1921,10 +1921,10 @@ Modules/_weakref.c - weakref_functions variable static PyMethodDef weakref_funct Objects/weakrefobject.c - weakref_members variable static PyMemberDef weakref_members[] Modules/_weakref.c - weakrefmodule variable static struct PyModuleDef weakrefmodule Python/sysmodule.c - whatstrings variable static PyObject *whatstrings[8] -Python/Python-ast.c - While_fields variable static char *While_fields[] +Python/Python-ast.c - While_fields variable static const char *While_fields[] Python/Python-ast.c - While_type variable static PyTypeObject *While_type -Python/Python-ast.c - With_fields variable static char *With_fields[] -Python/Python-ast.c - withitem_fields variable static char *withitem_fields[] +Python/Python-ast.c - With_fields variable static const char *With_fields[] +Python/Python-ast.c - withitem_fields variable static const char *withitem_fields[] Python/Python-ast.c - withitem_type variable static PyTypeObject *withitem_type Python/Python-ast.c - With_type variable static PyTypeObject *With_type Objects/descrobject.c - wrapperdescr_getset variable static PyGetSetDef wrapperdescr_getset[] @@ -1935,8 +1935,8 @@ Modules/_threadmodule.c local_new wr_callback_def variable static PyMethodDef wr Modules/xxsubtype.c - xxsubtype_functions variable static PyMethodDef xxsubtype_functions[] Modules/xxsubtype.c - xxsubtypemodule variable static struct PyModuleDef xxsubtypemodule Modules/xxsubtype.c - xxsubtype_slots variable static struct PyModuleDef_Slot xxsubtype_slots[] -Python/Python-ast.c - Yield_fields variable static char *Yield_fields[] -Python/Python-ast.c - YieldFrom_fields variable static char *YieldFrom_fields[] +Python/Python-ast.c - Yield_fields variable static const char *Yield_fields[] +Python/Python-ast.c - YieldFrom_fields variable static const char *YieldFrom_fields[] Python/Python-ast.c - YieldFrom_type variable static PyTypeObject *YieldFrom_type Python/Python-ast.c - Yield_type variable static PyTypeObject *Yield_type Modules/itertoolsmodule.c - zip_longest_methods variable static PyMethodDef zip_longest_methods From 6470eb109c60f4d1f1f6795f8e8241837312efd9 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 9 Sep 2019 16:53:29 +0100 Subject: [PATCH 109/118] "statics" -> "globals". --- ...k_c_statics.py => test_check_c_globals.py} | 4 +- .../__init__.py | 0 .../test___main__.py | 8 ++-- .../test_find.py | 16 +++---- .../test_functional.py | 0 .../test_show.py | 2 +- .../test_supported.py | 2 +- .../c-analyzer/{c-statics.py => c-globals.py} | 4 +- .../c-analyzer/c_analyzer_common/_generate.py | 40 ++++++++-------- Tools/c-analyzer/c_analyzer_common/known.py | 10 ++-- .../{c_statics => c_globals}/README | 0 .../{c_statics => c_globals}/__init__.py | 0 .../{c_statics => c_globals}/__main__.py | 48 +++++++++---------- .../{c_statics => c_globals}/find.py | 14 +++--- .../{c_statics => c_globals}/show.py | 12 ++--- .../{c_statics => c_globals}/supported.py | 34 ++++++------- Tools/c-analyzer/c_parser/info.py | 18 +++---- Tools/c-analyzer/c_symbols/binary.py | 2 +- 18 files changed, 110 insertions(+), 104 deletions(-) rename Lib/test/{test_check_c_statics.py => test_check_c_globals.py} (84%) rename Lib/test/test_tools/test_c_analyzer/{test_c_statics => test_c_globals}/__init__.py (100%) rename Lib/test/test_tools/test_c_analyzer/{test_c_statics => test_c_globals}/test___main__.py (97%) rename Lib/test/test_tools/test_c_analyzer/{test_c_statics => test_c_globals}/test_find.py (96%) rename Lib/test/test_tools/test_c_analyzer/{test_c_statics => test_c_globals}/test_functional.py (100%) rename Lib/test/test_tools/test_c_analyzer/{test_c_statics => test_c_globals}/test_show.py (98%) rename Lib/test/test_tools/test_c_analyzer/{test_c_statics => test_c_globals}/test_supported.py (97%) rename Tools/c-analyzer/{c-statics.py => c-globals.py} (76%) rename Tools/c-analyzer/{c_statics => c_globals}/README (100%) rename Tools/c-analyzer/{c_statics => c_globals}/__init__.py (100%) rename Tools/c-analyzer/{c_statics => c_globals}/__main__.py (80%) rename Tools/c-analyzer/{c_statics => c_globals}/find.py (90%) rename Tools/c-analyzer/{c_statics => c_globals}/show.py (52%) rename Tools/c-analyzer/{c_statics => c_globals}/supported.py (83%) diff --git a/Lib/test/test_check_c_statics.py b/Lib/test/test_check_c_globals.py similarity index 84% rename from Lib/test/test_check_c_statics.py rename to Lib/test/test_check_c_globals.py index 1219cc9f794073..210cf39bad981c 100644 --- a/Lib/test/test_check_c_statics.py +++ b/Lib/test/test_check_c_globals.py @@ -3,14 +3,14 @@ test.test_tools.skip_if_missing('c-analyzer') with test.test_tools.imports_under_tool('c-analyzer'): - from c_statics.__main__ import main + from c_globals.__main__ import main class ActualChecks(unittest.TestCase): # XXX Also run the check in "make check". @unittest.expectedFailure - def test_check_c_statics(self): + def test_check_c_globals(self): main('check', {}) diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/__init__.py b/Lib/test/test_tools/test_c_analyzer/test_c_globals/__init__.py similarity index 100% rename from Lib/test/test_tools/test_c_analyzer/test_c_statics/__init__.py rename to Lib/test/test_tools/test_c_analyzer/test_c_globals/__init__.py diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test___main__.py b/Lib/test/test_tools/test_c_analyzer/test_c_globals/test___main__.py similarity index 97% rename from Lib/test/test_tools/test_c_analyzer/test_c_statics/test___main__.py rename to Lib/test/test_tools/test_c_analyzer/test_c_globals/test___main__.py index d1a346c71c2c76..5f52c588d7c8bd 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test___main__.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_globals/test___main__.py @@ -6,9 +6,9 @@ from c_analyzer_common import SOURCE_DIRS from c_analyzer_common.known import DATA_FILE as KNOWN_FILE from c_parser import info - import c_statics as cg - from c_statics.supported import IGNORED_FILE - from c_statics.__main__ import cmd_check, cmd_show, parse_args, main + import c_globals as cg + from c_globals.supported import IGNORED_FILE + from c_globals.__main__ import cmd_check, cmd_show, parse_args, main TYPICAL = [ @@ -121,7 +121,7 @@ def test_some_unsupported(self): unsupported = [v for v, s in TYPICAL if not s] self.assertEqual(self.calls, [ ('_find', (dirs, 'known.tsv', 'ignored.tsv')), - ('_print', ('ERROR: found unsupported static variables',)), + ('_print', ('ERROR: found unsupported global variables',)), ('_print', ()), ('_show', (sorted(unsupported),)), ('_print', (' (3 total)',)), diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py b/Lib/test/test_tools/test_c_analyzer/test_c_globals/test_find.py similarity index 96% rename from Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py rename to Lib/test/test_tools/test_c_analyzer/test_c_globals/test_find.py index 7f14fe0e23c76b..b29f966fd2ad0f 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_find.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_globals/test_find.py @@ -3,7 +3,7 @@ from .. import tool_imports_for_tests with tool_imports_for_tests(): from c_parser import info - from c_statics.find import statics_from_binary, statics + from c_globals.find import globals_from_binary, globals class _Base(unittest.TestCase): @@ -59,7 +59,7 @@ def test_typical(self): ] knownvars = object() - found = list(statics_from_binary('python', + found = list(globals_from_binary('python', knownvars=knownvars, **self.kwargs)) @@ -91,8 +91,8 @@ def test_typical(self): # ] # known = object() # -# statics_from_binary('python', knownvars=known, **this.kwargs) -# found = list(statics_from_symbols(['dir1'], self.iter_symbols)) +# globals_from_binary('python', knownvars=known, **this.kwargs) +# found = list(globals_from_symbols(['dir1'], self.iter_symbols)) # # self.assertEqual(found, [ # info.Variable.from_parts('dir1/spam.c', None, 'var1', '???'), @@ -108,7 +108,7 @@ def test_typical(self): # def test_no_symbols(self): # self._return_iter_symbols = [] # -# found = list(statics_from_symbols(['dir1'], self.iter_symbols)) +# found = list(globals_from_symbols(['dir1'], self.iter_symbols)) # # self.assertEqual(found, []) # self.assertEqual(self.calls, [ @@ -140,7 +140,7 @@ def test_typical(self): # object(), # ] # -# found = list(statics_from_declarations(['dir1'], self.iter_declarations)) +# found = list(globals_from_declarations(['dir1'], self.iter_declarations)) # # self.assertEqual(found, [ # info.Variable.from_parts('dir1/spam.c', None, 'var1', '???'), @@ -156,7 +156,7 @@ def test_typical(self): # def test_no_declarations(self): # self._return_iter_declarations = [] # -# found = list(statics_from_declarations(['dir1'], self.iter_declarations)) +# found = list(globals_from_declarations(['dir1'], self.iter_declarations)) # # self.assertEqual(found, []) # self.assertEqual(self.calls, [ @@ -311,7 +311,7 @@ def test_typical(self): dirnames = object() known = object() - found = list(statics(dirnames, known, + found = list(globals(dirnames, known, kind='platform', _iter_variables=self._iter_variables, )) diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_functional.py b/Lib/test/test_tools/test_c_analyzer/test_c_globals/test_functional.py similarity index 100% rename from Lib/test/test_tools/test_c_analyzer/test_c_statics/test_functional.py rename to Lib/test/test_tools/test_c_analyzer/test_c_globals/test_functional.py diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_show.py b/Lib/test/test_tools/test_c_analyzer/test_c_globals/test_show.py similarity index 98% rename from Lib/test/test_tools/test_c_analyzer/test_c_statics/test_show.py rename to Lib/test/test_tools/test_c_analyzer/test_c_globals/test_show.py index bcfb2e5c3fbef7..ce1dad85db1b87 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_show.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_globals/test_show.py @@ -3,7 +3,7 @@ from .. import tool_imports_for_tests with tool_imports_for_tests(): from c_parser import info - from c_statics.show import basic + from c_globals.show import basic TYPICAL = [ diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_supported.py b/Lib/test/test_tools/test_c_analyzer/test_c_globals/test_supported.py similarity index 97% rename from Lib/test/test_tools/test_c_analyzer/test_c_statics/test_supported.py rename to Lib/test/test_tools/test_c_analyzer/test_c_globals/test_supported.py index e3f0eb089cb630..3d71ba2609d84a 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_statics/test_supported.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_globals/test_supported.py @@ -5,7 +5,7 @@ with tool_imports_for_tests(): from c_analyzer_common.info import ID from c_parser import info - from c_statics.supported import is_supported, ignored_from_file + from c_globals.supported import is_supported, ignored_from_file class IsSupportedTests(unittest.TestCase): diff --git a/Tools/c-analyzer/c-statics.py b/Tools/c-analyzer/c-globals.py similarity index 76% rename from Tools/c-analyzer/c-statics.py rename to Tools/c-analyzer/c-globals.py index c8a9911a22cc73..9afe059b28c664 100644 --- a/Tools/c-analyzer/c-statics.py +++ b/Tools/c-analyzer/c-globals.py @@ -1,6 +1,6 @@ -# This is a script equivalent of running "python -m test.test_c_statics.cg". +# This is a script equivalent of running "python -m test.test_c_globals.cg". -from c_statics.__main__ import parse_args, main +from c_globals.__main__ import parse_args, main # This is effectively copied from cg/__main__.py: diff --git a/Tools/c-analyzer/c_analyzer_common/_generate.py b/Tools/c-analyzer/c_analyzer_common/_generate.py index 71aa744c2b7c19..07fd0ed9f2cde5 100644 --- a/Tools/c-analyzer/c_analyzer_common/_generate.py +++ b/Tools/c-analyzer/c_analyzer_common/_generate.py @@ -23,7 +23,7 @@ STRUCTS = ('PyTypeObject', 'PyObject', 'PyMethodDef', 'PyModuleDef', 'grammar') -def _parse_static(line, funcname=None): +def _parse_global(line, funcname=None): line = line.strip() if line.startswith('static '): if '(' in line and '[' not in line and ' = ' not in line: @@ -90,9 +90,9 @@ def _pop_cached(varcache, filename, funcname, name, *, except KeyError: cached = varcache[filename] = {} for variable in _iter_variables(filename, - parse_variable=_parse_static, + parse_variable=_parse_global, ): - variable._isstatic = True + variable._isglobal = True cached[variable.id] = variable for var in cached: print(' ', var) @@ -117,17 +117,17 @@ def find_matching_variable(varid, varcache, allfilenames, *, else: filenames = allfilenames for filename in filenames: - static = _pop_cached(varcache, filename, varid.funcname, varid.name) - if static is not None: - return static + variable = _pop_cached(varcache, filename, varid.funcname, varid.name) + if variable is not None: + return variable else: if varid.filename and varid.filename != UNKNOWN and varid.funcname is None: for filename in allfilenames: if not filename.endswith('.h'): continue - static = _pop_cached(varcache, filename, None, varid.name) - if static is not None: - return static + variable = _pop_cached(varcache, filename, None, varid.name) + if variable is not None: + return variable return None @@ -297,17 +297,17 @@ def known_rows(symbols, *, yield _as_known(found.id, found.vartype) else: raise NotImplementedError # XXX incorporate KNOWN - for static in _find_symbols(symbols, filenames, - srccache=cache, - parse_variable=_parse_static, - ): - #static = static._replace( - # filename=os.path.relpath(static.filename, REPO_ROOT)) - if static.funcname == UNKNOWN: - print(static) - if static.vartype== UNKNOWN: - print(static) - yield _as_known(static.id, static.vartype) + for variable in _find_symbols(symbols, filenames, + srccache=cache, + parse_variable=_parse_global, + ): + #variable = variable._replace( + # filename=os.path.relpath(variable.filename, REPO_ROOT)) + if variable.funcname == UNKNOWN: + print(variable) + if variable.vartype== UNKNOWN: + print(variable) + yield _as_known(variable.id, variable.vartype) def known_file(symbols, filename=None, *, diff --git a/Tools/c-analyzer/c_analyzer_common/known.py b/Tools/c-analyzer/c_analyzer_common/known.py index b302ea77806f76..e5e98a1db3cedc 100644 --- a/Tools/c-analyzer/c_analyzer_common/known.py +++ b/Tools/c-analyzer/c_analyzer_common/known.py @@ -35,11 +35,11 @@ def from_file(infile, *, if kind == 'variable': values = known['variables'] value = Variable(id, declaration) - value._isstatic = _is_static(declaration) + value._isglobal = _is_global(declaration) else: raise ValueError(f'unsupported kind in row {row}') if value.name == 'id' and declaration == UNKNOWN: - # None of these are static variables. + # None of these are variables. declaration = 'int id'; else: value.validate() @@ -47,7 +47,8 @@ def from_file(infile, *, return known -def _is_static(vartype): +def _is_global(vartype): + # statics if vartype.startswith('static '): return True if vartype.startswith(('Py_LOCAL(', 'Py_LOCAL_INLINE(')): @@ -60,4 +61,7 @@ def _is_static(vartype): return True if vartype.startswith('WRAP_METHOD('): return True + # public extern + if vartype.startswith('PyAPI_DATA('): + return True return False diff --git a/Tools/c-analyzer/c_statics/README b/Tools/c-analyzer/c_globals/README similarity index 100% rename from Tools/c-analyzer/c_statics/README rename to Tools/c-analyzer/c_globals/README diff --git a/Tools/c-analyzer/c_statics/__init__.py b/Tools/c-analyzer/c_globals/__init__.py similarity index 100% rename from Tools/c-analyzer/c_statics/__init__.py rename to Tools/c-analyzer/c_globals/__init__.py diff --git a/Tools/c-analyzer/c_statics/__main__.py b/Tools/c-analyzer/c_globals/__main__.py similarity index 80% rename from Tools/c-analyzer/c_statics/__main__.py rename to Tools/c-analyzer/c_globals/__main__.py index 4630289ad23cd7..1dfc668db50c54 100644 --- a/Tools/c-analyzer/c_statics/__main__.py +++ b/Tools/c-analyzer/c_globals/__main__.py @@ -13,17 +13,17 @@ from .supported import is_supported, ignored_from_file, IGNORED_FILE, _is_object -def _match_unused_global(static, knownvars, used): +def _match_unused_global(variable, knownvars, used): found = [] for varid in knownvars: if varid in used: continue if varid.funcname is not None: continue - if varid.name != static.name: + if varid.name != variable.name: continue - if static.filename and static.filename != UNKNOWN: - if static.filename == varid.filename: + if variable.filename and variable.filename != UNKNOWN: + if variable.filename == varid.filename: found.append(varid) else: found.append(varid) @@ -33,17 +33,17 @@ def _match_unused_global(static, knownvars, used): def _check_results(unknown, knownvars, used): return badknown = set() - for static in sorted(unknown): + for variable in sorted(unknown): msg = None - if static.funcname != UNKNOWN: - msg = f'could not find global symbol {static.id}' - elif m := _match_unused_global(static, knownvars, used): + if variable.funcname != UNKNOWN: + msg = f'could not find global symbol {variable.id}' + elif m := _match_unused_global(variable, knownvars, used): assert isinstance(m, list) badknown.update(m) - elif static.name in ('completed', 'id'): # XXX Figure out where these variables are. - unknown.remove(static) + elif variable.name in ('completed', 'id'): # XXX Figure out where these variables are. + unknown.remove(variable) else: - msg = f'could not find local symbol {static.id}' + msg = f'could not find local symbol {variable.id}' if msg: #raise Exception(msg) print(msg) @@ -66,7 +66,7 @@ def _check_results(unknown, knownvars, used): raise Exception('could not find all symbols') -def _find_statics(dirnames, known, ignored): +def _find_globals(dirnames, known, ignored): if dirnames == SOURCE_DIRS: dirnames = [os.path.relpath(d, REPO_ROOT) for d in dirnames] @@ -76,14 +76,14 @@ def _find_statics(dirnames, known, ignored): used = set() unknown = set() knownvars = (known or {}).get('variables') - for static in find.statics_from_binary(knownvars=knownvars, + for variable in find.globals_from_binary(knownvars=knownvars, dirnames=dirnames): - #for static in find.statics(dirnames, known, kind='platform'): - if static.vartype == UNKNOWN: - unknown.add(static) + #for variable in find.globals(dirnames, known, kind='platform'): + if variable.vartype == UNKNOWN: + unknown.add(variable) continue - yield static, is_supported(static, ignored, known) - used.add(static.id) + yield variable, is_supported(variable, ignored, known) + used.add(variable.id) _check_results(unknown, knownvars, used) @@ -91,12 +91,12 @@ def _find_statics(dirnames, known, ignored): def cmd_check(cmd, dirs=SOURCE_DIRS, *, ignored=IGNORED_FILE, known=KNOWN_FILE, - _find=_find_statics, + _find=_find_globals, _show=show.basic, _print=print, ): """ - Fail if there are unsupported statics variables. + Fail if there are unsupported globals variables. In the failure case, the list of unsupported variables will be printed out. @@ -106,7 +106,7 @@ def cmd_check(cmd, dirs=SOURCE_DIRS, *, #_print('okay') return - _print('ERROR: found unsupported static variables') + _print('ERROR: found unsupported global variables') _print() _show(sorted(unsupported)) _print(f' ({len(unsupported)} total)') @@ -117,12 +117,12 @@ def cmd_show(cmd, dirs=SOURCE_DIRS, *, ignored=IGNORED_FILE, known=KNOWN_FILE, skip_objects=False, - _find=_find_statics, + _find=_find_globals, _show=show.basic, _print=print, ): """ - print out the list of found static variables. + Print out the list of found global variables. The variables will be distinguished as "supported" or "unsupported". """ @@ -155,7 +155,7 @@ def cmd_show(cmd, dirs=SOURCE_DIRS, *, } PROG = sys.argv[0] -PROG = 'c-statics.py' +PROG = 'c-globals.py' def parse_args(prog=PROG, argv=sys.argv[1:], *, _fail=None): diff --git a/Tools/c-analyzer/c_statics/find.py b/Tools/c-analyzer/c_globals/find.py similarity index 90% rename from Tools/c-analyzer/c_statics/find.py rename to Tools/c-analyzer/c_globals/find.py index b8e99fd3a2f902..a51b947cbdf10d 100644 --- a/Tools/c-analyzer/c_statics/find.py +++ b/Tools/c-analyzer/c_globals/find.py @@ -12,7 +12,7 @@ # XXX needs tests: # * iter_variables -def statics_from_binary(binfile=b_symbols.PYTHON, *, +def globals_from_binary(binfile=b_symbols.PYTHON, *, knownvars=None, dirnames=None, _iter_symbols=b_symbols.iter_symbols, @@ -28,14 +28,14 @@ def statics_from_binary(binfile=b_symbols.PYTHON, *, for variable in _resolve(symbols, resolve=_get_symbol_resolver(knownvars, dirnames), ): - # Skip each non-static variable (unless we couldn't find it). + # Skip each non-global variable (unless we couldn't find it). # XXX Drop the "UNKNOWN" condition? - if not variable.isstatic and variable.vartype != UNKNOWN: + if not variable.isglobal and variable.vartype != UNKNOWN: continue yield variable -def statics_from_declarations(dirnames=SOURCE_DIRS, *, +def globals_from_declarations(dirnames=SOURCE_DIRS, *, known=None, ): """Yield a Variable for each found declaration. @@ -84,12 +84,12 @@ def iter_variables(kind='platform', *, raise ValueError(f'unsupported kind {kind!r}') -def statics(dirnames, known, *, +def globals(dirnames, known, *, kind=None, # Use the default. _iter_variables=iter_variables, ): - """Return a list of (StaticVar, ) for each found static var.""" + """Return a list of (StaticVar, ) for each found global var.""" for found in _iter_variables(kind, known=known, dirnames=dirnames): - if not found.isstatic: + if not found.isglobal: continue yield found diff --git a/Tools/c-analyzer/c_statics/show.py b/Tools/c-analyzer/c_globals/show.py similarity index 52% rename from Tools/c-analyzer/c_statics/show.py rename to Tools/c-analyzer/c_globals/show.py index 7e2015ec96b53e..f4298b17b67884 100644 --- a/Tools/c-analyzer/c_statics/show.py +++ b/Tools/c-analyzer/c_globals/show.py @@ -1,13 +1,13 @@ -def basic(statics, *, +def basic(globals, *, _print=print): """Print each row simply.""" - for static in statics: - if static.funcname: - line = f'{static.filename}:{static.funcname}():{static.name}' + for variable in globals: + if variable.funcname: + line = f'{variable.filename}:{variable.funcname}():{variable.name}' else: - line = f'{static.filename}:{static.name}' - vartype = static.vartype + line = f'{variable.filename}:{variable.name}' + vartype = variable.vartype #if vartype.startswith('static '): # vartype = vartype.partition(' ')[2] #else: diff --git a/Tools/c-analyzer/c_statics/supported.py b/Tools/c-analyzer/c_globals/supported.py similarity index 83% rename from Tools/c-analyzer/c_statics/supported.py rename to Tools/c-analyzer/c_globals/supported.py index eaf095b3a202d8..3bba7a1f2fc196 100644 --- a/Tools/c-analyzer/c_statics/supported.py +++ b/Tools/c-analyzer/c_globals/supported.py @@ -7,11 +7,11 @@ from c_analyzer_common.util import read_tsv -def is_supported(static, ignored=None, known=None): - """Return True if the given static variable is okay in CPython.""" - if _is_ignored(static, ignored and ignored.get('variables')): +def is_supported(variable, ignored=None, known=None): + """Return True if the given global variable is okay in CPython.""" + if _is_ignored(variable, ignored and ignored.get('variables')): return True - elif _is_vartype_okay(static.vartype, ignored.get('types')): + elif _is_vartype_okay(variable.vartype, ignored.get('types')): return True else: return False @@ -49,33 +49,33 @@ def is_supported(static, ignored=None, known=None): } -def _is_ignored(static, ignoredvars=None): - if static.name in IGNORED: +def _is_ignored(variable, ignoredvars=None): + if variable.name in IGNORED: return True - if ignoredvars and static.id in ignoredvars: + if ignoredvars and variable.id in ignoredvars: return True # compiler - if static.filename == 'Python/graminit.c': - if static.vartype.startswith('static state '): + if variable.filename == 'Python/graminit.c': + if variable.vartype.startswith('static state '): return True - if static.filename == 'Python/symtable.c': - if static.vartype.startswith('static identifier '): + if variable.filename == 'Python/symtable.c': + if variable.vartype.startswith('static identifier '): return True - if static.filename == 'Python/Python-ast.c': + if variable.filename == 'Python/Python-ast.c': # These should be const. - if static.name.endswith('_field'): + if variable.name.endswith('_field'): return True - if static.name.endswith('_attribute'): + if variable.name.endswith('_attribute'): return True # other - if static.filename == 'Python/dtoa.c': + if variable.filename == 'Python/dtoa.c': # guarded by lock? - if static.name in ('p5s', 'freelist'): + if variable.name in ('p5s', 'freelist'): return True - if static.name in ('private_mem', 'pmem_next'): + if variable.name in ('private_mem', 'pmem_next'): return True return False diff --git a/Tools/c-analyzer/c_parser/info.py b/Tools/c-analyzer/c_parser/info.py index 01c820e7411130..9ab697978638fd 100644 --- a/Tools/c-analyzer/c_parser/info.py +++ b/Tools/c-analyzer/c_parser/info.py @@ -20,14 +20,14 @@ class Variable(_NTBase, """Information about a single variable declaration.""" __slots__ = () - _isstatic = util.Slot() + _isglobal = util.Slot() @classonly - def from_parts(cls, filename, funcname, name, vartype, isstatic=False): + def from_parts(cls, filename, funcname, name, vartype, isglobal=False): id = info.ID(filename, funcname, name) self = cls(id, vartype) - if isstatic: - self._isstatic = True + if isglobal: + self._isglobal = True return self def __new__(cls, id, vartype): @@ -64,12 +64,14 @@ def validate(self): raise TypeError('missing vartype') @property - def isstatic(self): + def isglobal(self): try: - return self._isstatic + return self._isglobal except AttributeError: - self._isstatic = ('static' in self.vartype.split()) - return self._isstatic + # XXX Include extern variables. + # XXX Ignore functions. + self._isglobal = ('static' in self.vartype.split()) + return self._isglobal @property def isconst(self): diff --git a/Tools/c-analyzer/c_symbols/binary.py b/Tools/c-analyzer/c_symbols/binary.py index 976d1a478a42b5..07feced9ed2e7b 100644 --- a/Tools/c-analyzer/c_symbols/binary.py +++ b/Tools/c-analyzer/c_symbols/binary.py @@ -13,7 +13,7 @@ def iter_symbols(binary=PYTHON, dirnames=None, *, # Alternately, use look_up_known_symbol() - # from c_statics.supported. + # from c_globals.supported. find_local_symbol=source.find_symbol, _file_exists=os.path.exists, _iter_symbols_nm=(lambda b, *a: _iter_symbols_nm(b, *a)), From 1233cf9ace2e0a624203ee12c367ee303101712d Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 10 Sep 2019 22:11:18 +0100 Subject: [PATCH 110/118] Maybe limit the variables in known.tsv. --- .../c-analyzer/c_analyzer_common/_generate.py | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/Tools/c-analyzer/c_analyzer_common/_generate.py b/Tools/c-analyzer/c_analyzer_common/_generate.py index 07fd0ed9f2cde5..7a954472b02f75 100644 --- a/Tools/c-analyzer/c_analyzer_common/_generate.py +++ b/Tools/c-analyzer/c_analyzer_common/_generate.py @@ -41,26 +41,26 @@ def _parse_global(line, funcname=None): return None, None # global-only - elif line.startswith(POTS): # implied static - if '(' in line and '[' not in line and ' = ' not in line: - return None, None - name, decl = parse_variable_declaration(line) - elif line.startswith('PyAPI_DATA('): - name, decl = parse_variable_declaration(line) - elif line.startswith(STRUCTS) and line.endswith(' = {'): # implied static - name, decl = parse_variable_declaration(line) - elif line.startswith(STRUCTS) and line.endswith(' = NULL;'): # implied static - name, decl = parse_variable_declaration(line) - elif line.startswith('struct '): - if not line.endswith(' = {'): - return None, None - if not line.partition(' ')[2].startswith(STRUCTS): - return None, None - # implied static + elif line.startswith('PyAPI_DATA('): # only in .h files name, decl = parse_variable_declaration(line) elif line.startswith('PyDoc_VAR('): decl = line.strip(';').strip() name = line.split('(')[1].split(')')[0].strip() +# elif line.startswith(POTS): # implied static +# if '(' in line and '[' not in line and ' = ' not in line: +# return None, None +# name, decl = parse_variable_declaration(line) +# elif line.startswith(STRUCTS) and line.endswith(' = {'): # implied static +# name, decl = parse_variable_declaration(line) +# elif line.startswith(STRUCTS) and line.endswith(' = NULL;'): # implied static +# name, decl = parse_variable_declaration(line) +# elif line.startswith('struct '): +# if not line.endswith(' = {'): +# return None, None +# if not line.partition(' ')[2].startswith(STRUCTS): +# return None, None +# # implied static +# name, decl = parse_variable_declaration(line) # file-specific elif line.startswith(('SLOT1BINFULL(', 'SLOT1BIN(')): @@ -76,6 +76,7 @@ def _parse_global(line, funcname=None): return [ ('PyId_' + name, funcname, f'_Py_IDENTIFIER({name})'), ] + else: return None, None return name, decl From fc6c97ec9955794586978bbb0f4e0e23ecf0ca1d Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 10 Sep 2019 23:41:29 +0100 Subject: [PATCH 111/118] Generate the ignored.tsv file. --- .../c-analyzer/c_analyzer_common/_generate.py | 18 +- Tools/c-analyzer/c_globals/__main__.py | 2 +- Tools/c-analyzer/c_globals/supported.py | 205 ++++++++++++------ 3 files changed, 143 insertions(+), 82 deletions(-) diff --git a/Tools/c-analyzer/c_analyzer_common/_generate.py b/Tools/c-analyzer/c_analyzer_common/_generate.py index 7a954472b02f75..0abb55cb1b7fa8 100644 --- a/Tools/c-analyzer/c_analyzer_common/_generate.py +++ b/Tools/c-analyzer/c_analyzer_common/_generate.py @@ -1,10 +1,5 @@ # The code here consists of hacks for pre-populating the known.tsv file. -import contextlib -import glob -import os.path -import re - from c_parser.preprocessor import _iter_clean_lines from c_parser.naive import ( iter_variables, parse_variable_declaration, find_variables, @@ -14,7 +9,7 @@ from . import SOURCE_DIRS, REPO_ROOT from .known import DATA_FILE as KNOWN_FILE, HEADER as KNOWN_HEADER from .info import UNKNOWN, ID -from .util import run_cmd, write_tsv +from .util import write_tsv from .files import iter_cpython_files @@ -311,14 +306,15 @@ def known_rows(symbols, *, yield _as_known(variable.id, variable.vartype) -def known_file(symbols, filename=None, *, - _generate_rows=known_rows, - ): +def generate(symbols, filename=None, *, + _generate_rows=known_rows, + _write_tsv=write_tsv, + ): if not filename: filename = KNOWN_FILE + '.new' rows = _generate_rows(symbols) - write_tsv(filename, KNOWN_HEADER, rows) + _write_tsv(filename, KNOWN_HEADER, rows) if __name__ == '__main__': @@ -327,4 +323,4 @@ def known_file(symbols, filename=None, *, binary.PYTHON, find_local_symbol=None, ) - known_file(symbols) + generate(symbols) diff --git a/Tools/c-analyzer/c_globals/__main__.py b/Tools/c-analyzer/c_globals/__main__.py index 1dfc668db50c54..413958afb8a8d7 100644 --- a/Tools/c-analyzer/c_globals/__main__.py +++ b/Tools/c-analyzer/c_globals/__main__.py @@ -77,7 +77,7 @@ def _find_globals(dirnames, known, ignored): unknown = set() knownvars = (known or {}).get('variables') for variable in find.globals_from_binary(knownvars=knownvars, - dirnames=dirnames): + dirnames=dirnames): #for variable in find.globals(dirnames, known, kind='platform'): if variable.vartype == UNKNOWN: unknown.add(variable) diff --git a/Tools/c-analyzer/c_globals/supported.py b/Tools/c-analyzer/c_globals/supported.py index 3bba7a1f2fc196..5a08acaaf396fc 100644 --- a/Tools/c-analyzer/c_globals/supported.py +++ b/Tools/c-analyzer/c_globals/supported.py @@ -1,133 +1,147 @@ -import csv import os.path import re from c_analyzer_common import DATA_DIR from c_analyzer_common.info import ID -from c_analyzer_common.util import read_tsv +from c_analyzer_common.util import read_tsv, write_tsv -def is_supported(variable, ignored=None, known=None): - """Return True if the given global variable is okay in CPython.""" - if _is_ignored(variable, ignored and ignored.get('variables')): - return True - elif _is_vartype_okay(variable.vartype, ignored.get('types')): - return True - else: - return False +IGNORED_FILE = os.path.join(DATA_DIR, 'ignored.tsv') +IGNORED_COLUMNS = ('filename', 'funcname', 'name', 'kind', 'reason') +IGNORED_HEADER = '\t'.join(IGNORED_COLUMNS) # XXX Move these to ignored.tsv. IGNORED = { # global - 'PyImport_FrozenModules', - 'M___hello__', - 'inittab_copy', - 'PyHash_Func', - '_Py_HashSecret_Initialized', - '_TARGET_LOCALES', - 'runtime_initialized', + 'PyImport_FrozenModules': 'process-global', + 'M___hello__': 'process-global', + 'inittab_copy': 'process-global', + 'PyHash_Func': 'process-global', + '_Py_HashSecret_Initialized': 'process-global', + '_TARGET_LOCALES': 'process-global', # startup - 'static_arg_parsers', - 'orig_argv', - 'opt_ptr', - '_preinit_warnoptions', - '_Py_StandardStreamEncoding', - '_Py_StandardStreamErrors', + 'runtime_initialized': 'runtime startup', + 'static_arg_parsers': 'runtime startup', + 'orig_argv': 'runtime startup', + 'opt_ptr': 'runtime startup', + '_preinit_warnoptions': 'runtime startup', + '_Py_StandardStreamEncoding': 'runtime startup', + '_Py_StandardStreamErrors': 'runtime startup', # should be const - 'tracemalloc_empty_traceback', - '_empty_bitmap_node', - 'posix_constants_pathconf', - 'posix_constants_confstr', - 'posix_constants_sysconf', + 'tracemalloc_empty_traceback': 'const', + '_empty_bitmap_node': 'const', + 'posix_constants_pathconf': 'const', + 'posix_constants_confstr': 'const', + 'posix_constants_sysconf': 'const', # signals are main-thread only - 'faulthandler_handlers', - 'user_signals', + 'faulthandler_handlers': 'signals are main-thread only', + 'user_signals': 'signals are main-thread only', } -def _is_ignored(variable, ignoredvars=None): - if variable.name in IGNORED: +def is_supported(variable, ignored=None, known=None, *, + _ignored=(lambda *a, **k: _is_ignored(*a, **k)), + _vartype_okay=(lambda *a, **k: _is_vartype_okay(*a, **k)), + ): + """Return True if the given global variable is okay in CPython.""" + if _ignored(variable, + ignored and ignored.get('variables')): return True - - if ignoredvars and variable.id in ignoredvars: + elif _vartype_okay(variable.vartype, + ignored.get('types')): return True + else: + return False + + +def _is_ignored(variable, ignoredvars=None, *, + _IGNORED=IGNORED, + ): + """Return the reason if the variable is a supported global. + + Return None if the variable is not a supported global. + """ + if ignoredvars and (reason := ignoredvars.get(variable.id)): + return reason + + if variable.funcname is None: + if reason := _IGNORED.get(variable.name): + return reason # compiler if variable.filename == 'Python/graminit.c': if variable.vartype.startswith('static state '): - return True + return 'compiler' if variable.filename == 'Python/symtable.c': if variable.vartype.startswith('static identifier '): - return True + return 'compiler' if variable.filename == 'Python/Python-ast.c': # These should be const. if variable.name.endswith('_field'): - return True + return 'compiler' if variable.name.endswith('_attribute'): - return True + return 'compiler' # other if variable.filename == 'Python/dtoa.c': # guarded by lock? if variable.name in ('p5s', 'freelist'): - return True + return 'dtoa is thread-safe?' if variable.name in ('private_mem', 'pmem_next'): - return True + return 'dtoa is thread-safe?' - return False + return None def _is_vartype_okay(vartype, ignoredtypes=None): if _is_object(vartype): - return False + return None if vartype.startswith('static const '): - return True + return 'const' # components for TypeObject definitions for name in ('PyMethodDef', 'PyGetSetDef', 'PyMemberDef'): if name in vartype: - return True + return 'const' for name in ('PyNumberMethods', 'PySequenceMethods', 'PyMappingMethods', 'PyBufferProcs', 'PyAsyncMethods'): if name in vartype: - return True + return 'const' for name in ('slotdef', 'newfunc'): if name in vartype: - return True + return 'const' # structseq for name in ('PyStructSequence_Desc', 'PyStructSequence_Field'): if name in vartype: - return True + return 'const' # other definiitions if 'PyModuleDef' in vartype: - return True + return 'const' # thread-safe if '_Py_atomic_int' in vartype: - return True + return 'thread-safe' if 'pthread_condattr_t' in vartype: - return True + return 'thread-safe' # startup if '_Py_PreInitEntry' in vartype: - return True + return 'startup' # global - if 'PyMemAllocatorEx' in vartype: - return True +# if 'PyMemAllocatorEx' in vartype: +# return True # others - if 'PyThread_type_lock' in vartype: - return True - #if '_Py_hashtable_t' in vartype: - # return True # ??? +# if 'PyThread_type_lock' in vartype: +# return True # XXX ??? # _Py_tss_t @@ -137,12 +151,12 @@ def _is_vartype_okay(vartype, ignoredtypes=None): # functions if '(' in vartype and '[' not in vartype: - return True + return 'function pointer' # XXX finish! # * allow const values? #raise NotImplementedError - return False + return None def _is_object(vartype): @@ -172,26 +186,17 @@ def _is_object(vartype): return False -############################# -# ignored - -IGNORED_FILE = os.path.join(DATA_DIR, 'ignored.tsv') - -COLUMNS = ('filename', 'funcname', 'name', 'kind', 'reason') -HEADER = '\t'.join(COLUMNS) - - def ignored_from_file(infile, *, _read_tsv=read_tsv, ): - """Yield StaticVar for each ignored var in the file.""" + """Yield a Variable for each ignored var in the file.""" ignored = { 'variables': {}, #'types': {}, #'constants': {}, #'macros': {}, } - for row in _read_tsv(infile, HEADER): + for row in _read_tsv(infile, IGNORED_HEADER): filename, funcname, name, kind, reason = row if not funcname or funcname == '-': funcname = None @@ -202,3 +207,63 @@ def ignored_from_file(infile, *, raise ValueError(f'unsupported kind in row {row}') values[id] = reason return ignored + + +################################## +# generate + +def _get_row(varid, reason): + return ( + varid.filename, + varid.funcname or '-', + varid.name, + 'variable', + str(reason), + ) + + +def _get_rows(variables, ignored=None, *, + _as_row=_get_row, + _is_ignored=_is_ignored, + _vartype_okay=_is_vartype_okay, + ): + count = 0 + for variable in variables: + reason = _is_ignored(variable, + ignored and ignored.get('variables'), + ) + if not reason: + reason = _vartype_okay(variable.vartype, + ignored and ignored.get('types')) + if not reason: + continue + + print(' ', variable, repr(reason)) + yield _as_row(variable.id, reason) + count += 1 + print(f'total: {count}') + + +def _generate_ignored_file(variables, filename=None, *, + _generate_rows=_get_rows, + _write_tsv=write_tsv, + ): + if not filename: + filename = IGNORED_FILE + '.new' + rows = _generate_rows(variables) + _write_tsv(filename, IGNORED_HEADER, rows) + + +if __name__ == '__main__': + from c_analyzer_common import SOURCE_DIRS + from c_analyzer_common.known import ( + from_file as known_from_file, + DATA_FILE as KNOWN_FILE, + ) + from . import find + known = known_from_file(KNOWN_FILE) + knownvars = (known or {}).get('variables') + variables = find.globals_from_binary(knownvars=knownvars, + dirnames=SOURCE_DIRS) + + _generate_ignored_file(variables) From 6f8a22394207e730f1fcbfb8c2d369397a3900cd Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 10 Sep 2019 23:52:18 +0100 Subject: [PATCH 112/118] Ignore variables with benign races. --- Tools/c-analyzer/c_globals/supported.py | 47 +++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/Tools/c-analyzer/c_globals/supported.py b/Tools/c-analyzer/c_globals/supported.py index 5a08acaaf396fc..30f4bde3801d48 100644 --- a/Tools/c-analyzer/c_globals/supported.py +++ b/Tools/c-analyzer/c_globals/supported.py @@ -42,6 +42,8 @@ 'user_signals': 'signals are main-thread only', } +BENIGN = 'races here are benign and unlikely' + def is_supported(variable, ignored=None, known=None, *, _ignored=(lambda *a, **k: _is_ignored(*a, **k)), @@ -93,6 +95,51 @@ def _is_ignored(variable, ignoredvars=None, *, return 'dtoa is thread-safe?' if variable.name in ('private_mem', 'pmem_next'): return 'dtoa is thread-safe?' + if variable.filename == 'Python/thread.c': + # Threads do not become an issue until after these have been set + # and these never get changed after that. + if variable.name in ('initialized', 'thread_debug'): + return 'thread-safe' + if variable.filename == 'Python/getversion.c': + if variable.name == 'version': + # Races are benign here, as well as unlikely. + return BENIGN + if variable.filename == 'Python/fileutils.c': + if variable.name == 'force_ascii': + return BENIGN + if variable.name == 'ioctl_works': + return BENIGN + if variable.filename == 'Python/codecs.c': + if variable.name == 'ucnhash_CAPI': + return BENIGN + if variable.filename == 'Python/bootstrap_hash.c': + if variable.name == 'getrandom_works': + return BENIGN + if variable.filename == 'Objects/unicodeobject.c': + if variable.name == 'ucnhash_CAPI': + return BENIGN + if variable.name == 'bloom_linebreak': + # *mostly* benign + return BENIGN + if variable.filename == 'Modules/getbuildinfo.c': + if variable.name == 'buildinfo': + # The static is used for pre-allocation. + return BENIGN + if variable.filename == 'Modules/posixmodule.c': + if variable.name == 'ticks_per_second': + return BENIGN + if variable.name == 'dup3_works': + return BENIGN + if variable.filename == 'Modules/timemodule.c': + if variable.name == 'ticks_per_second': + return BENIGN + if variable.filename == 'Objects/longobject.c': + if variable.name == 'log_base_BASE': + return BENIGN + if variable.name == 'convwidth_base': + return BENIGN + if variable.name == 'convmultmax_base': + return BENIGN return None From 6c1db44b9a22613b5e542fc94a292a8ddf2751b1 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 10 Sep 2019 23:54:51 +0100 Subject: [PATCH 113/118] Mark more variables as PyObject. --- Tools/c-analyzer/c_globals/supported.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Tools/c-analyzer/c_globals/supported.py b/Tools/c-analyzer/c_globals/supported.py index 30f4bde3801d48..37455ac3eb48bb 100644 --- a/Tools/c-analyzer/c_globals/supported.py +++ b/Tools/c-analyzer/c_globals/supported.py @@ -211,7 +211,8 @@ def _is_object(vartype): return True if '_PyArg_Parser ' in vartype: return True - if vartype.startswith(('_Py_IDENTIFIER(', '_Py_static_string(')): + if vartype.startswith(('_Py_IDENTIFIER(', 'static _Py_Identifier', + '_Py_static_string(')): return True if 'traceback_t' in vartype: return True @@ -223,6 +224,10 @@ def _is_object(vartype): return True if 'method_cache_entry' in vartype: return True + if vartype.startswith('static identifier '): + return True + if vartype.endswith((' _Py_FalseStruct', ' _Py_TrueStruct')): + return True # XXX Add more? From 5888d4845289bb64859ebfd532603a4fe63b7f28 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Wed, 11 Sep 2019 03:37:38 +0100 Subject: [PATCH 114/118] Consider private, non-static globals. --- .../c-analyzer/c_analyzer_common/_generate.py | 32 +++++------ Tools/c-analyzer/c_analyzer_common/known.py | 2 +- Tools/c-analyzer/c_globals/__main__.py | 3 +- Tools/c-analyzer/known.tsv | 54 ++++++------------- 4 files changed, 35 insertions(+), 56 deletions(-) diff --git a/Tools/c-analyzer/c_analyzer_common/_generate.py b/Tools/c-analyzer/c_analyzer_common/_generate.py index 0abb55cb1b7fa8..1629aa6b5210fa 100644 --- a/Tools/c-analyzer/c_analyzer_common/_generate.py +++ b/Tools/c-analyzer/c_analyzer_common/_generate.py @@ -38,24 +38,26 @@ def _parse_global(line, funcname=None): # global-only elif line.startswith('PyAPI_DATA('): # only in .h files name, decl = parse_variable_declaration(line) + elif line.startswith('extern '): # only in .h files + name, decl = parse_variable_declaration(line) elif line.startswith('PyDoc_VAR('): decl = line.strip(';').strip() name = line.split('(')[1].split(')')[0].strip() -# elif line.startswith(POTS): # implied static -# if '(' in line and '[' not in line and ' = ' not in line: -# return None, None -# name, decl = parse_variable_declaration(line) -# elif line.startswith(STRUCTS) and line.endswith(' = {'): # implied static -# name, decl = parse_variable_declaration(line) -# elif line.startswith(STRUCTS) and line.endswith(' = NULL;'): # implied static -# name, decl = parse_variable_declaration(line) -# elif line.startswith('struct '): -# if not line.endswith(' = {'): -# return None, None -# if not line.partition(' ')[2].startswith(STRUCTS): -# return None, None -# # implied static -# name, decl = parse_variable_declaration(line) + elif line.startswith(POTS): # implied static + if '(' in line and '[' not in line and ' = ' not in line: + return None, None + name, decl = parse_variable_declaration(line) + elif line.startswith(STRUCTS) and line.endswith(' = {'): # implied static + name, decl = parse_variable_declaration(line) + elif line.startswith(STRUCTS) and line.endswith(' = NULL;'): # implied static + name, decl = parse_variable_declaration(line) + elif line.startswith('struct '): + if not line.endswith(' = {'): + return None, None + if not line.partition(' ')[2].startswith(STRUCTS): + return None, None + # implied static + name, decl = parse_variable_declaration(line) # file-specific elif line.startswith(('SLOT1BINFULL(', 'SLOT1BIN(')): diff --git a/Tools/c-analyzer/c_analyzer_common/known.py b/Tools/c-analyzer/c_analyzer_common/known.py index e5e98a1db3cedc..a0c6dfa5aa47d7 100644 --- a/Tools/c-analyzer/c_analyzer_common/known.py +++ b/Tools/c-analyzer/c_analyzer_common/known.py @@ -35,7 +35,7 @@ def from_file(infile, *, if kind == 'variable': values = known['variables'] value = Variable(id, declaration) - value._isglobal = _is_global(declaration) + value._isglobal = _is_global(declaration) or id.funcname is None else: raise ValueError(f'unsupported kind in row {row}') if value.name == 'id' and declaration == UNKNOWN: diff --git a/Tools/c-analyzer/c_globals/__main__.py b/Tools/c-analyzer/c_globals/__main__.py index 413958afb8a8d7..9570fb6a14c4e6 100644 --- a/Tools/c-analyzer/c_globals/__main__.py +++ b/Tools/c-analyzer/c_globals/__main__.py @@ -31,7 +31,6 @@ def _match_unused_global(variable, knownvars, used): def _check_results(unknown, knownvars, used): - return badknown = set() for variable in sorted(unknown): msg = None @@ -85,7 +84,7 @@ def _find_globals(dirnames, known, ignored): yield variable, is_supported(variable, ignored, known) used.add(variable.id) - _check_results(unknown, knownvars, used) + #_check_results(unknown, knownvars, used) def cmd_check(cmd, dirs=SOURCE_DIRS, *, diff --git a/Tools/c-analyzer/known.tsv b/Tools/c-analyzer/known.tsv index 0b31baaa5f99b3..ce2afcb9591ea1 100644 --- a/Tools/c-analyzer/known.tsv +++ b/Tools/c-analyzer/known.tsv @@ -14,7 +14,7 @@ Objects/genobject.c - ag_value_freelist_free variable static int ag_value_freeli Python/Python-ast.c - alias_fields variable static const char *alias_fields[] Python/Python-ast.c - alias_type variable static PyTypeObject *alias_type Modules/_tracemalloc.c - allocators variable static struct { PyMemAllocatorEx mem; PyMemAllocatorEx raw; PyMemAllocatorEx obj; } allocators -Python/Python-ast.c - And_singleton variable PyObject *And_singleton +Python/Python-ast.c - And_singleton variable static PyObject *And_singleton Python/Python-ast.c - And_type variable static PyTypeObject *And_type Python/Python-ast.c - AnnAssign_fields variable static const char *AnnAssign_fields[] Python/Python-ast.c - AnnAssign_type variable static PyTypeObject *AnnAssign_type @@ -61,9 +61,9 @@ Python/Python-ast.c - Attribute_fields variable static const char *Attribute_fie Python/Python-ast.c - Attribute_type variable static PyTypeObject *Attribute_type Python/Python-ast.c - AugAssign_fields variable static const char *AugAssign_fields[] Python/Python-ast.c - AugAssign_type variable static PyTypeObject *AugAssign_type -Python/Python-ast.c - AugLoad_singleton variable PyObject *AugLoad_singleton +Python/Python-ast.c - AugLoad_singleton variable static PyObject *AugLoad_singleton Python/Python-ast.c - AugLoad_type variable static PyTypeObject *AugLoad_type -Python/Python-ast.c - AugStore_singleton variable PyObject *AugStore_singleton +Python/Python-ast.c - AugStore_singleton variable static PyObject *AugStore_singleton Python/Python-ast.c - AugStore_type variable static PyTypeObject *AugStore_type Python/Python-ast.c - Await_fields variable static const char *Await_fields[] Python/Python-ast.c - Await_type variable static PyTypeObject *Await_type @@ -86,7 +86,6 @@ Python/Python-ast.c - boolop_type variable static PyTypeObject *boolop_type Python/Python-ast.c - BoolOp_type variable static PyTypeObject *BoolOp_type Python/_warnings.c is_internal_frame bootstrap_string variable static PyObject *bootstrap_string Python/Python-ast.c - Break_type variable static PyTypeObject *Break_type -Python/ast.c decode_unicode_with_escapes buf variable char *buf Modules/_io/bufferedio.c - bufferediobase_methods variable static PyMethodDef bufferediobase_methods Modules/_io/bufferedio.c - bufferedrandom_getset variable static PyGetSetDef bufferedrandom_getset[] Modules/_io/bufferedio.c - bufferedrandom_members variable static PyMemberDef bufferedrandom_members[] @@ -139,7 +138,7 @@ Objects/codeobject.c - code_methods variable static PyMethodDef code_methods Modules/_collectionsmodule.c - _collectionsmodule variable static struct PyModuleDef _collectionsmodule Modules/itertoolsmodule.c - combinations_methods variable static PyMethodDef combinations_methods Modules/itertoolsmodule.c - combinations_type variable static PyTypeObject combinations_type -Objects/typeobject.c object_new comma_id variable "_Py_static_string(comma_id, "", "")" +Objects/typeobject.c object_new comma_id variable _Py_static_string(comma_id, "", "") Python/Python-ast.c - Compare_fields variable static const char *Compare_fields[] Python/Python-ast.c - Compare_type variable static PyTypeObject *Compare_type Objects/complexobject.c - complex_as_number variable static PyNumberMethods complex_as_number @@ -175,7 +174,7 @@ Modules/_collectionsmodule.c - defdict_methods variable static PyMethodDef defdi Modules/_collectionsmodule.c - defdict_type variable static PyTypeObject defdict_type Python/Python-ast.c - Delete_fields variable static const char *Delete_fields[] Python/Python-ast.c - Delete_type variable static PyTypeObject *Delete_type -Python/Python-ast.c - Del_singleton variable PyObject *Del_singleton +Python/Python-ast.c - Del_singleton variable static PyObject *Del_singleton Python/Python-ast.c - Del_type variable static PyTypeObject *Del_type Modules/_collectionsmodule.c - deque_as_number variable static PyNumberMethods deque_as_number Modules/_collectionsmodule.c - deque_as_sequence variable static PySequenceMethods deque_as_sequence @@ -213,8 +212,8 @@ Python/Python-ast.c - Div_type variable static PyTypeObject *Div_type Python/compile.c - __doc__ variable static PyObject *__doc__ Objects/classobject.c method_get_doc docstr variable static PyObject *docstr Objects/classobject.c instancemethod_get_doc docstr variable static PyObject *docstr -Python/compile.c compiler_set_qualname dot variable "_Py_static_string(dot, ""."")" -Python/compile.c compiler_set_qualname dot_locals variable "_Py_static_string(dot_locals, ""."")" +Python/compile.c compiler_set_qualname dot variable _Py_static_string(dot, ""."") +Python/compile.c compiler_set_qualname dot_locals variable _Py_static_string(dot_locals, ""."") Objects/floatobject.c - double_format variable static float_format_type double_format Modules/itertoolsmodule.c - dropwhile_methods variable static PyMethodDef dropwhile_methods Modules/itertoolsmodule.c - dropwhile_type variable static PyTypeObject dropwhile_type @@ -333,25 +332,6 @@ Python/sysmodule.c - hash_info_desc variable static PyStructSequence_Desc hash_i Python/sysmodule.c - hash_info_fields variable static PyStructSequence_Field hash_info_fields[] Python/sysmodule.c - Hash_InfoType variable static PyTypeObject Hash_InfoType Python/import.c import_find_and_load header variable static int header -Modules/_elementtree.c _elementtree_Element___deepcopy___impl id variable PyObject* id -Objects/obmalloc.c _PyMem_DebugCheckAddress id variable char id -Objects/obmalloc.c _PyObject_DebugDumpAddress id variable char id -Python/ast.c ast_for_dotted_name id variable identifier id -Python/Python-ast.c obj2ast_expr id variable identifier id -Modules/_xxsubinterpretersmodule.c _channels_next_id id variable int64_t id -Modules/_xxsubinterpretersmodule.c _channels_add id variable int64_t id -Modules/_xxsubinterpretersmodule.c _channel_create id variable int64_t id -Modules/_xxsubinterpretersmodule.c interp_get_main id variable PY_INT64_T id -Objects/interpreteridobject.c _Py_CoerceID id variable int64_t id -Objects/interpreteridobject.c interpid_new id variable int64_t id -Objects/interpreteridobject.c interpid_dealloc id variable int64_t id -Objects/interpreteridobject.c _PyInterpreterID_LookUp id variable int64_t id -Objects/interpreteridobject.c _PyInterpreterState_GetIDObject id variable PY_INT64_T id -Python/pystate.c interp_look_up_id id variable PY_INT64_T id -??? ??? id variable ??? -??? ??? id variable ??? -??? ??? id variable ??? -??? ??? id variable ??? Python/Python-ast.c - IfExp_fields variable static const char *IfExp_fields[] Python/Python-ast.c - IfExp_type variable static PyTypeObject *IfExp_type Python/Python-ast.c - If_fields variable static const char *If_fields[] @@ -461,7 +441,7 @@ Objects/listobject.c - list_methods variable static PyMethodDef list_methods Objects/listobject.c - listreviter_methods variable static PyMethodDef listreviter_methods Python/Python-ast.c - List_type variable static PyTypeObject *List_type Python/ceval.c - lltrace variable static int lltrace -Python/Python-ast.c - Load_singleton variable PyObject *Load_singleton +Python/Python-ast.c - Load_singleton variable static PyObject *Load_singleton Python/Python-ast.c - Load_type variable static PyTypeObject *Load_type Modules/_threadmodule.c - localdummytype variable static PyTypeObject localdummytype Modules/_localemodule.c - _localemodule variable static struct PyModuleDef _localemodule @@ -522,7 +502,6 @@ Python/frozen.c - M___hello__ variable static unsigned char M___hello__[] Python/Python-ast.c - Mod_singleton variable static PyObject *Mod_singleton Python/Python-ast.c - mod_type variable static PyTypeObject *mod_type Python/Python-ast.c - Mod_type variable static PyTypeObject *Mod_type -Python/_warnings.c normalize_module module variable PyObject *module Modules/faulthandler.c - module_def variable static struct PyModuleDef module_def Modules/_tracemalloc.c - module_def variable static struct PyModuleDef module_def Python/Python-ast.c - Module_fields variable static const char *Module_fields[] @@ -609,13 +588,13 @@ Objects/typeobject.c slot_nb_floor_divide op_id variable _Py_static_string(op_id Objects/typeobject.c slot_nb_true_divide op_id variable _Py_static_string(op_id, OPSTR) Python/getopt.c - opt_ptr variable static const wchar_t *opt_ptr Python/initconfig.c - orig_argv variable static PyWideStringList orig_argv -Python/Python-ast.c - Or_singleton variable PyObject *Or_singleton +Python/Python-ast.c - Or_singleton variable static PyObject *Or_singleton Python/Python-ast.c - Or_type variable static PyTypeObject *Or_type Objects/exceptions.c - OSError_getset variable static PyGetSetDef OSError_getset[] Objects/exceptions.c - OSError_members variable static PyMemberDef OSError_members[] Objects/exceptions.c - OSError_methods variable static PyMethodDef OSError_methods Python/dtoa.c - p5s variable static Bigint *p5s -Python/Python-ast.c - Param_singleton variable PyObject *Param_singleton +Python/Python-ast.c - Param_singleton variable static PyObject *Param_singleton Python/Python-ast.c - Param_type variable static PyTypeObject *Param_type Python/bltinmodule.c builtin_print _parser variable static struct _PyArg_Parser _parser Python/clinic/_warnings.c.h warnings_warn _parser variable static _PyArg_Parser _parser @@ -802,7 +781,6 @@ Objects/weakrefobject.c - proxy_methods variable static PyMethodDef proxy_method Objects/typeobject.c resolve_slotdups ptrs variable static slotdef *ptrs[MAX_EQUIV] Modules/pwdmodule.c - pwd_methods variable static PyMethodDef pwd_methods Modules/pwdmodule.c - pwdmodule variable static struct PyModuleDef pwdmodule -Objects/object.c - _Py_abstract_hack variable Py_ssize_t (*_Py_abstract_hack)(PyObject *) Objects/obmalloc.c - _Py_AllocatedBlocks variable static Py_ssize_t _Py_AllocatedBlocks Objects/genobject.c - _PyAsyncGenASend_Type variable PyTypeObject _PyAsyncGenASend_Type Objects/genobject.c - _PyAsyncGenAThrow_Type variable PyTypeObject _PyAsyncGenAThrow_Type @@ -997,7 +975,7 @@ Objects/boolobject.c - _Py_FalseStruct variable static struct _longobject _Py_Fa Objects/stringlib/unicode_format.h - PyFieldNameIter_Type variable static PyTypeObject PyFieldNameIter_Type Modules/_io/fileio.c - PyFileIO_Type variable PyTypeObject PyFileIO_Type Python/preconfig.c - Py_FileSystemDefaultEncodeErrors variable const char *Py_FileSystemDefaultEncodeErrors -Python/preconfig.c - Py_FileSystemDefaultEncoding variable const char *Py_FileSystemDefaultEncoding +Python/preconfig.c - Py_FileSystemDefaultEncoding variable const char * Py_FileSystemDefaultEncoding Python/bltinmodule.c - PyFilter_Type variable PyTypeObject PyFilter_Type Objects/floatobject.c - PyFloat_Type variable PyTypeObject PyFloat_Type Objects/stringlib/unicode_format.h - PyFormatterIter_Type variable static PyTypeObject PyFormatterIter_Type @@ -1018,13 +996,13 @@ Python/hamt.c - _PyHamtKeys_Type variable PyTypeObject _PyHamtKeys_Type Python/hamt.c - PyHamt_methods variable static PyMethodDef PyHamt_methods Python/hamt.c - _PyHamt_Type variable PyTypeObject _PyHamt_Type Python/hamt.c - _PyHamtValues_Type variable PyTypeObject _PyHamtValues_Type -Python/preconfig.c - _Py_HasFileSystemDefaultEncodeErrors variable int _Py_HasFileSystemDefaultEncodeErrors -Python/preconfig.c - Py_HasFileSystemDefaultEncoding variable int Py_HasFileSystemDefaultEncoding +Python/preconfig.c - _Py_HasFileSystemDefaultEncodeErrors variable const(int) _Py_HasFileSystemDefaultEncodeErrors +Python/preconfig.c - Py_HasFileSystemDefaultEncoding variable const(int) Py_HasFileSystemDefaultEncoding Python/pyhash.c - PyHash_Func variable static PyHash_FuncDef PyHash_Func Python/initconfig.c - Py_HashRandomizationFlag variable int Py_HashRandomizationFlag Python/pyhash.c - _Py_HashSecret variable _Py_HashSecret_t _Py_HashSecret Python/bootstrap_hash.c - _Py_HashSecret_Initialized variable static int _Py_HashSecret_Initialized -Python/codecs.c - Py_hexdigits variable const char *Py_hexdigits +Python/codecs.c - Py_hexdigits variable const char * Py_hexdigits Python/sysmodule.c - PyId__ variable _Py_IDENTIFIER(_) Modules/_abc.c - PyId__abc_impl variable _Py_IDENTIFIER(_abc_impl) Objects/typeobject.c - PyId___abstractmethods__ variable _Py_IDENTIFIER(__abstractmethods__) @@ -1408,7 +1386,7 @@ Python/bltinmodule.c - PyId_stdout variable _Py_IDENTIFIER(stdout) Python/Python-ast.c - PyId_step variable _Py_IDENTIFIER(step) Modules/posixmodule.c DirEntry_test_mode PyId_st_mode variable _Py_IDENTIFIER(st_mode) Modules/_io/textio.c - PyId_strict variable _Py_IDENTIFIER(strict) -Python/pythonrun.c - PyId_string variable "_Py_static_string(PyId_string, """")" +Python/pythonrun.c - PyId_string variable _Py_static_string(PyId_string, """") Modules/timemodule.c time_strptime PyId__strptime_time variable _Py_IDENTIFIER(_strptime_time) Modules/posixmodule.c wait_helper PyId_struct_rusage variable _Py_IDENTIFIER(struct_rusage) Modules/_abc.c - PyId___subclasscheck__ variable _Py_IDENTIFIER(__subclasscheck__) @@ -1775,7 +1753,7 @@ Python/symtable.c - ste_memberlist variable static PyMemberDef ste_memberlist[] Python/Python-ast.c - stmt_attributes variable static const char *stmt_attributes[] Python/Python-ast.c - stmt_type variable static PyTypeObject *stmt_type Objects/exceptions.c - StopIteration_members variable static PyMemberDef StopIteration_members[] -Python/Python-ast.c - Store_singleton variable PyObject *Store_singleton +Python/Python-ast.c - Store_singleton variable static PyObject *Store_singleton Python/Python-ast.c - Store_type variable static PyTypeObject *Store_type Python/ast_unparse.c - _str_close_br variable static PyObject *_str_close_br Python/ast_unparse.c - _str_dbl_close_br variable static PyObject *_str_dbl_close_br From cdeb1d9f66a9120ad1d05dd26cd362c7805b9d68 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Wed, 11 Sep 2019 04:15:07 +0100 Subject: [PATCH 115/118] Update ignored global variables. --- Tools/c-analyzer/c_globals/supported.py | 46 +++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/Tools/c-analyzer/c_globals/supported.py b/Tools/c-analyzer/c_globals/supported.py index 37455ac3eb48bb..8758d2499a6bbd 100644 --- a/Tools/c-analyzer/c_globals/supported.py +++ b/Tools/c-analyzer/c_globals/supported.py @@ -21,25 +21,61 @@ '_Py_HashSecret_Initialized': 'process-global', '_TARGET_LOCALES': 'process-global', - # startup + # startup (only changed before/during) + '_PyRuntime': 'runtime startup', 'runtime_initialized': 'runtime startup', 'static_arg_parsers': 'runtime startup', 'orig_argv': 'runtime startup', 'opt_ptr': 'runtime startup', '_preinit_warnoptions': 'runtime startup', '_Py_StandardStreamEncoding': 'runtime startup', + 'Py_FileSystemDefaultEncoding': 'runtime startup', '_Py_StandardStreamErrors': 'runtime startup', - - # should be const + 'Py_FileSystemDefaultEncodeErrors': 'runtime startup', + 'Py_BytesWarningFlag': 'runtime startup', + 'Py_DebugFlag': 'runtime startup', + 'Py_DontWriteBytecodeFlag': 'runtime startup', + 'Py_FrozenFlag': 'runtime startup', + 'Py_HashRandomizationFlag': 'runtime startup', + 'Py_IgnoreEnvironmentFlag': 'runtime startup', + 'Py_InspectFlag': 'runtime startup', + 'Py_InteractiveFlag': 'runtime startup', + 'Py_IsolatedFlag': 'runtime startup', + 'Py_NoSiteFlag': 'runtime startup', + 'Py_NoUserSiteDirectory': 'runtime startup', + 'Py_OptimizeFlag': 'runtime startup', + 'Py_QuietFlag': 'runtime startup', + 'Py_UTF8Mode': 'runtime startup', + 'Py_UnbufferedStdioFlag': 'runtime startup', + 'Py_VerboseFlag': 'runtime startup', + '_Py_path_config': 'runtime startup', + '_PyOS_optarg': 'runtime startup', + '_PyOS_opterr': 'runtime startup', + '_PyOS_optind': 'runtime startup', + '_Py_HashSecret': 'runtime startup', + + # effectively const 'tracemalloc_empty_traceback': 'const', '_empty_bitmap_node': 'const', 'posix_constants_pathconf': 'const', 'posix_constants_confstr': 'const', 'posix_constants_sysconf': 'const', + '_PySys_ImplCacheTag': 'const', + '_PySys_ImplName': 'const', + 'PyImport_Inittab': 'const', + '_PyImport_DynLoadFiletab': 'const', + '_PyParser_Grammar': 'const', + 'Py_hexdigits': 'const', + '_PyImport_Inittab': 'const', + '_PyByteArray_empty_string': 'const', + '_PyLong_DigitValue': 'const', + '_Py_SwappedOp': 'const', + 'PyStructSequence_UnnamedField': 'const', # signals are main-thread only 'faulthandler_handlers': 'signals are main-thread only', 'user_signals': 'signals are main-thread only', + 'wakeup': 'signals are main-thread only', } BENIGN = 'races here are benign and unlikely' @@ -109,6 +145,8 @@ def _is_ignored(variable, ignoredvars=None, *, return BENIGN if variable.name == 'ioctl_works': return BENIGN + if variable.name == '_Py_open_cloexec_works': + return BENIGN if variable.filename == 'Python/codecs.c': if variable.name == 'ucnhash_CAPI': return BENIGN @@ -150,6 +188,8 @@ def _is_vartype_okay(vartype, ignoredtypes=None): if vartype.startswith('static const '): return 'const' + if vartype.startswith('const '): + return 'const' # components for TypeObject definitions for name in ('PyMethodDef', 'PyGetSetDef', 'PyMemberDef'): From 569c57e2cc83f8cdf71a2599b07e9a34db2691e0 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Thu, 12 Sep 2019 00:05:53 +0100 Subject: [PATCH 116/118] Skip the check where "nm" isn't available. --- Lib/test/test_check_c_globals.py | 5 ++++- .../test_c_analyzer_common/test_files.py | 4 ++-- .../test_c_parser/test_preprocessor.py | 4 ++++ Tools/c-analyzer/c_symbols/binary.py | 14 +++++++++++--- 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_check_c_globals.py b/Lib/test/test_check_c_globals.py index 210cf39bad981c..009560e8d98d97 100644 --- a/Lib/test/test_check_c_globals.py +++ b/Lib/test/test_check_c_globals.py @@ -11,7 +11,10 @@ class ActualChecks(unittest.TestCase): # XXX Also run the check in "make check". @unittest.expectedFailure def test_check_c_globals(self): - main('check', {}) + try: + main('check', {}) + except NotImplementedError: + raise unittest.SkipTest('not supported on this host') if __name__ == '__main__': diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/test_files.py b/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/test_files.py index 92d2a2ab3abea8..6d14aea78a486e 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/test_files.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/test_files.py @@ -226,8 +226,8 @@ def test_relparent(self): fixpath('z/eggs/ham/file3.c'), ]) self.assertEqual(self.calls, [ - ('_walk', ('/x/y/z/spam', '.c', _walk_tree)), - ('_walk', ('/x/y/z/eggs', '.c', _walk_tree)), + ('_walk', (fixpath('/x/y/z/spam'), '.c', _walk_tree)), + ('_walk', (fixpath('/x/y/z/eggs'), '.c', _walk_tree)), ]) def test_glob(self): diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_preprocessor.py b/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_preprocessor.py index 8b16dddaeb57bf..89e15570d65309 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_preprocessor.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_parser/test_preprocessor.py @@ -1,6 +1,7 @@ import itertools import textwrap import unittest +import sys from ..util import wrapped_arg_combos, StrProxy from .. import tool_imports_for_tests @@ -181,6 +182,7 @@ def test_directive_whitespace(self): ('_parse_directive', '#define eggs ( a , b ) { a = b ; }'), ) + @unittest.skipIf(sys.platform == 'win32', 'needs fix under Windows') def test_split_lines(self): directive = Macro('eggs', ('a', 'b'), '{ a = b; }') self.parsed = [ @@ -341,6 +343,7 @@ def test_split_blocks(self): ('_parse_directive', '#endif'), ) + @unittest.skipIf(sys.platform == 'win32', 'needs fix under Windows') def test_basic(self): directives = [ Include(''), @@ -455,6 +458,7 @@ def test_basic(self): (23, 'print("end");', None, ()), ]) + @unittest.skipIf(sys.platform == 'win32', 'needs fix under Windows') def test_typical(self): # We use Include/compile.h from commit 66c4f3f38b86. It has # a good enough mix of code without being too large. diff --git a/Tools/c-analyzer/c_symbols/binary.py b/Tools/c-analyzer/c_symbols/binary.py index 07feced9ed2e7b..e125dbd5b5edc5 100644 --- a/Tools/c-analyzer/c_symbols/binary.py +++ b/Tools/c-analyzer/c_symbols/binary.py @@ -1,3 +1,4 @@ +import os import os.path import shutil import sys @@ -22,12 +23,17 @@ def iter_symbols(binary=PYTHON, dirnames=None, *, if not _file_exists(binary): raise Exception('executable missing (need to build it first?)') - if not find_local_symbol: - yield from _iter_symbols_nm(binary) - else: + if find_local_symbol: cache = {} def find_local_symbol(name, *, _find=find_local_symbol): return _find(name, dirnames, _perfilecache=cache) + else: + find_local_symbol = None + + if os.name == 'nt': + # XXX Support this. + raise NotImplementedError + else: yield from _iter_symbols_nm(binary, find_local_symbol) @@ -75,6 +81,8 @@ def _iter_symbols_nm(binary, find_local_symbol=None, _run=util.run_cmd, ): nm = _which('nm') + if not nm: + raise NotImplementedError argv = [nm, '--line-numbers', binary, From 7b0745fbef50606326f9d6993f1997b02fab0d68 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Thu, 12 Sep 2019 01:33:44 +0100 Subject: [PATCH 117/118] Ignore REPL-related variables. --- Tools/c-analyzer/c_globals/supported.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Tools/c-analyzer/c_globals/supported.py b/Tools/c-analyzer/c_globals/supported.py index 8758d2499a6bbd..4643e4ef6e8896 100644 --- a/Tools/c-analyzer/c_globals/supported.py +++ b/Tools/c-analyzer/c_globals/supported.py @@ -54,6 +54,10 @@ '_PyOS_optind': 'runtime startup', '_Py_HashSecret': 'runtime startup', + # REPL + '_PyOS_ReadlineLock': 'repl', + '_PyOS_ReadlineTState': 'repl', + # effectively const 'tracemalloc_empty_traceback': 'const', '_empty_bitmap_node': 'const', @@ -76,6 +80,9 @@ 'faulthandler_handlers': 'signals are main-thread only', 'user_signals': 'signals are main-thread only', 'wakeup': 'signals are main-thread only', + + # hacks + '_PySet_Dummy': 'only used as a placeholder', } BENIGN = 'races here are benign and unlikely' From b5dd31b4bc212f71f29c069364d3de1f81a6d4bf Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Wed, 11 Sep 2019 16:37:10 +0100 Subject: [PATCH 118/118] Fix whitespace. --- .../test_c_analyzer_common/test_known.py | 18 ++++++++++-------- .../test_c_globals/test_supported.py | 19 +++++++++++-------- Tools/c-analyzer/c_analyzer_common/util.py | 2 +- Tools/c-analyzer/c_parser/naive.py | 2 +- 4 files changed, 23 insertions(+), 18 deletions(-) diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/test_known.py b/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/test_known.py index 95eac915d7f3e2..215023da577b9c 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/test_known.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_analyzer_common/test_known.py @@ -1,3 +1,4 @@ +import re import textwrap import unittest @@ -28,13 +29,14 @@ def _read_tsv(self, *args): def test_typical(self): lines = textwrap.dedent(''' - filename funcname name kind declaration - file1.c - var1 variable static int - file1.c func1 local1 variable static int - file1.c - var2 variable int - file1.c func2 local2 variable char * - file2.c - var1 variable char * + filename funcname name kind declaration + file1.c - var1 variable static int + file1.c func1 local1 variable static int + file1.c - var2 variable int + file1.c func2 local2 variable char * + file2.c - var1 variable char * ''').strip().splitlines() + lines = [re.sub(r'\s+', '\t', line, 4) for line in lines] self._return_read_tsv = [tuple(v.strip() for v in line.split('\t')) for line in lines[1:]] @@ -50,7 +52,7 @@ def test_typical(self): ]}, }) self.assertEqual(self.calls, [ - ('_read_tsv', ('spam.c', 'filename funcname name kind declaration')), + ('_read_tsv', ('spam.c', 'filename\tfuncname\tname\tkind\tdeclaration')), ]) def test_empty(self): @@ -62,5 +64,5 @@ def test_empty(self): 'variables': {}, }) self.assertEqual(self.calls, [ - ('_read_tsv', ('spam.c', 'filename funcname name kind declaration')), + ('_read_tsv', ('spam.c', 'filename\tfuncname\tname\tkind\tdeclaration')), ]) diff --git a/Lib/test/test_tools/test_c_analyzer/test_c_globals/test_supported.py b/Lib/test/test_tools/test_c_analyzer/test_c_globals/test_supported.py index 3d71ba2609d84a..1e7d40e2afcbda 100644 --- a/Lib/test/test_tools/test_c_analyzer/test_c_globals/test_supported.py +++ b/Lib/test/test_tools/test_c_analyzer/test_c_globals/test_supported.py @@ -1,3 +1,4 @@ +import re import textwrap import unittest @@ -55,13 +56,15 @@ def _read_tsv(self, *args): def test_typical(self): lines = textwrap.dedent(''' - filename funcname name kind reason - file1.c - var1 variable ... - file1.c func1 local1 variable - file1.c - var2 variable ??? - file1.c func2 local2 variable - file2.c - var1 variable reasons + filename funcname name kind reason + file1.c - var1 variable ... + file1.c func1 local1 variable | + file1.c - var2 variable ??? + file1.c func2 local2 variable | + file2.c - var1 variable reasons ''').strip().splitlines() + lines = [re.sub(r'\s{1,8}', '\t', line, 4).replace('|', '') + for line in lines] self._return_read_tsv = [tuple(v.strip() for v in line.split('\t')) for line in lines[1:]] @@ -77,7 +80,7 @@ def test_typical(self): }, }) self.assertEqual(self.calls, [ - ('_read_tsv', ('spam.c', 'filename funcname name kind reason')), + ('_read_tsv', ('spam.c', 'filename\tfuncname\tname\tkind\treason')), ]) def test_empty(self): @@ -89,5 +92,5 @@ def test_empty(self): 'variables': {}, }) self.assertEqual(self.calls, [ - ('_read_tsv', ('spam.c', 'filename funcname name kind reason')), + ('_read_tsv', ('spam.c', 'filename\tfuncname\tname\tkind\treason')), ]) diff --git a/Tools/c-analyzer/c_analyzer_common/util.py b/Tools/c-analyzer/c_analyzer_common/util.py index ea3b27fe3e33b0..511c54f1783450 100644 --- a/Tools/c-analyzer/c_analyzer_common/util.py +++ b/Tools/c-analyzer/c_analyzer_common/util.py @@ -1,5 +1,5 @@ import csv -import subprocess +import subprocess _NOT_SET = object() diff --git a/Tools/c-analyzer/c_parser/naive.py b/Tools/c-analyzer/c_parser/naive.py index e9524e30e88726..e0370cc3d1d439 100644 --- a/Tools/c-analyzer/c_parser/naive.py +++ b/Tools/c-analyzer/c_parser/naive.py @@ -165,7 +165,7 @@ def find_variables(varids, filenames=None, *, if not filenames: yield Variable(varid, UNKNOWN) continue - srcfiles = filenames + srcfiles = filenames for filename in srcfiles: found = _find_varid(filename, varid.funcname, varid.name, ignored=used,