diff options
author | Eric Snow <ericsnowcurrently@gmail.com> | 2022-07-19 01:03:57 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-07-19 01:03:57 (GMT) |
commit | 7a1a85d64088a9eaefaf30d6aa50711cb4ed8245 (patch) | |
tree | 6caaac193bc01417111ddb268b50a3b02ac33437 /Tools | |
parent | 0daba822212cd5d6c63384a27f390f0945330c2b (diff) | |
download | cpython-7a1a85d64088a9eaefaf30d6aa50711cb4ed8245.zip cpython-7a1a85d64088a9eaefaf30d6aa50711cb4ed8245.tar.gz cpython-7a1a85d64088a9eaefaf30d6aa50711cb4ed8245.tar.bz2 |
gh-94673: [c-analyzer] Add a Script to Identify Static Types (#94989)
issue: https://github.com/python/cpython/issues/94673
Diffstat (limited to 'Tools')
-rw-r--r-- | Tools/c-analyzer/c_common/tables.py | 285 | ||||
-rw-r--r-- | Tools/c-analyzer/cpython/__main__.py | 48 | ||||
-rw-r--r-- | Tools/c-analyzer/cpython/_builtin_types.py | 365 | ||||
-rw-r--r-- | Tools/c-analyzer/cpython/globals-to-fix.tsv | 54 |
4 files changed, 611 insertions, 141 deletions
diff --git a/Tools/c-analyzer/c_common/tables.py b/Tools/c-analyzer/c_common/tables.py index 130be6b..fe8e8cf 100644 --- a/Tools/c-analyzer/c_common/tables.py +++ b/Tools/c-analyzer/c_common/tables.py @@ -1,3 +1,4 @@ +from collections import namedtuple import csv import re import textwrap @@ -225,7 +226,11 @@ WIDTH = 20 def resolve_columns(specs): if isinstance(specs, str): specs = specs.replace(',', ' ').strip().split() - return _resolve_colspecs(specs) + resolved = [] + for raw in specs: + column = ColumnSpec.from_raw(raw) + resolved.append(column) + return resolved def build_table(specs, *, sep=' ', defaultwidth=None): @@ -233,37 +238,145 @@ def build_table(specs, *, sep=' ', defaultwidth=None): return _build_table(columns, sep=sep, defaultwidth=defaultwidth) -_COLSPEC_RE = re.compile(textwrap.dedent(r''' - ^ - (?: - \[ - ( - (?: [^\s\]] [^\]]* )? - [^\s\]] - ) # <label> - ] - )? - ( \w+ ) # <field> - (?: +class ColumnSpec(namedtuple('ColumnSpec', 'field label fmt')): + + REGEX = re.compile(textwrap.dedent(r''' + ^ (?: - : - ( [<^>] ) # <align> - ( \d+ ) # <width1> - ) - | + \[ + ( + (?: [^\s\]] [^\]]* )? + [^\s\]] + ) # <label> + ] + )? + ( [-\w]+ ) # <field> (?: (?: : - ( \d+ ) # <width2> - )? + ( [<^>] ) # <align> + ( \d+ )? # <width1> + ) + | (?: - : - ( .*? ) # <fmt> - )? - ) - )? - $ -'''), re.VERBOSE) + (?: + : + ( \d+ ) # <width2> + )? + (?: + : + ( .*? ) # <fmt> + )? + ) + )? + $ + '''), re.VERBOSE) + + @classmethod + def from_raw(cls, raw): + if not raw: + raise ValueError('missing column spec') + elif isinstance(raw, cls): + return raw + + if isinstance(raw, str): + *values, _ = cls._parse(raw) + else: + *values, _ = cls._normalize(raw) + if values is None: + raise ValueError(f'unsupported column spec {raw!r}') + return cls(*values) + + @classmethod + def parse(cls, specstr): + parsed = cls._parse(specstr) + if not parsed: + return None + *values, _ = parsed + return cls(*values) + + @classmethod + def _parse(cls, specstr): + m = cls.REGEX.match(specstr) + if not m: + return None + (label, field, + align, width1, + width2, fmt, + ) = m.groups() + if not label: + label = field + if fmt: + assert not align and not width1, (specstr,) + _parsed = _parse_fmt(fmt) + if not _parsed: + raise NotImplementedError + elif width2: + width, _ = _parsed + if width != int(width2): + raise NotImplementedError(specstr) + elif width2: + fmt = width2 + width = int(width2) + else: + assert not fmt, (fmt, specstr) + if align: + width = int(width1) if width1 else len(label) + fmt = f'{align}{width}' + else: + width = None + return field, label, fmt, width + + @classmethod + def _normalize(cls, spec): + if len(spec) == 1: + raw, = spec + raise NotImplementedError + return _resolve_column(raw) + + if len(spec) == 4: + label, field, width, fmt = spec + if width: + if not fmt: + fmt = str(width) + elif _parse_fmt(fmt)[0] != width: + raise ValueError(f'width mismatch in {spec}') + elif len(raw) == 3: + label, field, fmt = spec + if not field: + label, field = None, label + elif not isinstance(field, str) or not field.isidentifier(): + # XXX This doesn't seem right... + fmt = f'{field}:{fmt}' if fmt else field + label, field = None, label + elif len(raw) == 2: + label = None + field, fmt = raw + if not field: + field, fmt = fmt, None + elif not field.isidentifier() or fmt.isidentifier(): + label, field = field, fmt + else: + raise NotImplementedError + + fmt = f':{fmt}' if fmt else '' + if label: + return cls._parse(f'[{label}]{field}{fmt}') + else: + return cls._parse(f'{field}{fmt}') + + @property + def width(self): + if not self.fmt: + return None + parsed = _parse_fmt(self.fmt) + if not parsed: + return None + width, _ = parsed + return width + + def resolve_width(self, default=None): + return _resolve_width(self.width, self.fmt, self.label, default) def _parse_fmt(fmt): @@ -272,100 +385,31 @@ def _parse_fmt(fmt): width = fmt[1:] if width.isdigit(): return int(width), align - return None, None + elif fmt.isdigit(): + return int(fmt), '<' + return None -def _parse_colspec(raw): - m = _COLSPEC_RE.match(raw) - if not m: - return None - label, field, align, width1, width2, fmt = m.groups() - if not label: - label = field - if width1: - width = None - fmt = f'{align}{width1}' - elif width2: - width = int(width2) - if fmt: - _width, _ = _parse_fmt(fmt) - if _width == width: - width = None - else: - width = None - return field, label, width, fmt - - -def _normalize_colspec(spec): - if len(spec) == 1: - raw, = spec - return _resolve_column(raw) - - if len(spec) == 4: - label, field, width, fmt = spec - if width: - fmt = f'{width}:{fmt}' if fmt else width - elif len(raw) == 3: - label, field, fmt = spec - if not field: - label, field = None, label - elif not isinstance(field, str) or not field.isidentifier(): - fmt = f'{field}:{fmt}' if fmt else field - label, field = None, label - elif len(raw) == 2: - label = None - field, fmt = raw - if not field: - field, fmt = fmt, None - elif not field.isidentifier() or fmt.isidentifier(): - label, field = field, fmt - else: - raise NotImplementedError - - fmt = f':{fmt}' if fmt else '' - if label: - return _parse_colspec(f'[{label}]{field}{fmt}') - else: - return _parse_colspec(f'{field}{fmt}') - - -def _resolve_colspec(raw): - if isinstance(raw, str): - spec = _parse_colspec(raw) - else: - spec = _normalize_colspec(raw) - if spec is None: - raise ValueError(f'unsupported column spec {raw!r}') - return spec - - -def _resolve_colspecs(columns): - parsed = [] - for raw in columns: - column = _resolve_colspec(raw) - parsed.append(column) - return parsed - - -def _resolve_width(spec, defaultwidth): - _, label, width, fmt = spec +def _resolve_width(width, fmt, label, default): if width: if not isinstance(width, int): raise NotImplementedError return width - elif width and fmt: - width, _ = _parse_fmt(fmt) - if width: - return width - - if not defaultwidth: + elif fmt: + parsed = _parse_fmt(fmt) + if parsed: + width, _ = parsed + if width: + return width + + if not default: return WIDTH - elif not hasattr(defaultwidth, 'get'): - return defaultwidth or WIDTH - - defaultwidths = defaultwidth - defaultwidth = defaultwidths.get(None) or WIDTH - return defaultwidths.get(label) or defaultwidth + elif hasattr(default, 'get'): + defaults = default + default = defaults.get(None) or WIDTH + return defaults.get(label) or default + else: + return default or WIDTH def _build_table(columns, *, sep=' ', defaultwidth=None): @@ -373,16 +417,13 @@ def _build_table(columns, *, sep=' ', defaultwidth=None): div = [] rowfmt = [] for spec in columns: - label, field, _, colfmt = spec - width = _resolve_width(spec, defaultwidth) - if colfmt: - colfmt = f':{colfmt}' - else: - colfmt = f':{width}' + width = spec.resolve_width(defaultwidth) + colfmt = spec.fmt + colfmt = f':{spec.fmt}' if spec.fmt else f':{width}' - header.append(f' {{:^{width}}} '.format(label)) + header.append(f' {{:^{width}}} '.format(spec.label)) div.append('-' * (width + 2)) - rowfmt.append(f' {{{field}{colfmt}}} ') + rowfmt.append(f' {{{spec.field}{colfmt}}} ') return ( sep.join(header), sep.join(div), diff --git a/Tools/c-analyzer/cpython/__main__.py b/Tools/c-analyzer/cpython/__main__.py index be331d5..2b9e423 100644 --- a/Tools/c-analyzer/cpython/__main__.py +++ b/Tools/c-analyzer/cpython/__main__.py @@ -20,7 +20,7 @@ import c_parser.__main__ as c_parser import c_analyzer.__main__ as c_analyzer import c_analyzer as _c_analyzer from c_analyzer.info import UNKNOWN -from . import _analyzer, _capi, _files, _parser, REPO_ROOT +from . import _analyzer, _builtin_types, _capi, _files, _parser, REPO_ROOT logger = logging.getLogger(__name__) @@ -325,6 +325,47 @@ def cmd_capi(filenames=None, *, print(line) +def _cli_builtin_types(parser): + parser.add_argument('--format', dest='fmt', default='table') +# parser.add_argument('--summary', dest='format', +# action='store_const', const='summary') + def process_format(args, *, argv=None): + orig = args.fmt + args.fmt = _builtin_types.resolve_format(args.fmt) + if isinstance(args.fmt, str): + if args.fmt not in _builtin_types._FORMATS: + parser.error(f'unsupported format {orig!r}') + + parser.add_argument('--include-modules', dest='showmodules', + action='store_true') + def process_modules(args, *, argv=None): + pass + + return [ + process_format, + process_modules, + ] + + +def cmd_builtin_types(fmt, *, + showmodules=False, + verbosity=VERBOSITY, + ): + render = _builtin_types.get_renderer(fmt) + types = _builtin_types.iter_builtin_types() + match = _builtin_types.resolve_matcher(showmodules) + if match: + types = (t for t in types if match(t, log=lambda msg: logger.log(1, msg))) + + lines = render( + types, +# verbose=verbosity > VERBOSITY, + ) + print() + for line in lines: + print(line) + + # We do not define any other cmd_*() handlers here, # favoring those defined elsewhere. @@ -354,6 +395,11 @@ COMMANDS = { [_cli_capi], cmd_capi, ), + 'builtin-types': ( + 'show the builtin types', + [_cli_builtin_types], + cmd_builtin_types, + ), } diff --git a/Tools/c-analyzer/cpython/_builtin_types.py b/Tools/c-analyzer/cpython/_builtin_types.py new file mode 100644 index 0000000..faa0b7a --- /dev/null +++ b/Tools/c-analyzer/cpython/_builtin_types.py @@ -0,0 +1,365 @@ +from collections import namedtuple +import os.path +import re +import textwrap + +from c_common import tables +from . import REPO_ROOT +from ._files import iter_header_files, iter_filenames + + +CAPI_PREFIX = os.path.join('Include', '') +INTERNAL_PREFIX = os.path.join('Include', 'internal', '') + +REGEX = re.compile(textwrap.dedent(rf''' + (?: + ^ + (?: + (?: + (?: + (?: + (?: + ( static ) # <static> + \s+ + | + ( extern ) # <extern> + \s+ + )? + PyTypeObject \s+ + ) + | + (?: + ( PyAPI_DATA ) # <capi> + \s* [(] \s* PyTypeObject \s* [)] \s* + ) + ) + (\w+) # <name> + \s* + (?: + (?: + ( = \s* {{ ) # <def> + $ + ) + | + ( ; ) # <decl> + ) + ) + | + (?: + # These are specific to Objects/exceptions.c: + (?: + SimpleExtendsException + | + MiddlingExtendsException + | + ComplexExtendsException + ) + \( \w+ \s* , \s* + ( \w+ ) # <excname> + \s* , + ) + ) + ) +'''), re.VERBOSE) + + +def _parse_line(line): + m = re.match(REGEX, line) + if not m: + return None + (static, extern, capi, + name, + def_, decl, + excname, + ) = m.groups() + if def_: + isdecl = False + if extern or capi: + raise NotImplementedError(line) + kind = 'static' if static else None + elif excname: + name = f'_PyExc_{excname}' + isdecl = False + kind = 'static' + else: + isdecl = True + if static: + kind = 'static' + elif extern: + kind = 'extern' + elif capi: + kind = 'capi' + else: + kind = None + return name, isdecl, kind + + +class BuiltinTypeDecl(namedtuple('BuiltinTypeDecl', 'file lno name kind')): + + KINDS = { + 'static', + 'extern', + 'capi', + 'forward', + } + + @classmethod + def from_line(cls, line, filename, lno): + # This is similar to ._capi.CAPIItem.from_line(). + parsed = _parse_line(line) + if not parsed: + return None + name, isdecl, kind = parsed + if not isdecl: + return None + return cls.from_parsed(name, kind, filename, lno) + + @classmethod + def from_parsed(cls, name, kind, filename, lno): + if not kind: + kind = 'forward' + return cls.from_values(filename, lno, name, kind) + + @classmethod + def from_values(cls, filename, lno, name, kind): + if kind not in cls.KINDS: + raise ValueError(f'unsupported kind {kind!r}') + self = cls(filename, lno, name, kind) + if self.kind not in ('extern', 'capi') and self.api: + raise NotImplementedError(self) + elif self.kind == 'capi' and not self.api: + raise NotImplementedError(self) + return self + + @property + def relfile(self): + return self.file[len(REPO_ROOT) + 1:] + + @property + def api(self): + return self.relfile.startswith(CAPI_PREFIX) + + @property + def internal(self): + return self.relfile.startswith(INTERNAL_PREFIX) + + @property + def private(self): + if not self.name.startswith('_'): + return False + return self.api and not self.internal + + @property + def public(self): + if self.kind != 'capi': + return False + return not self.internal and not self.private + + +class BuiltinTypeInfo(namedtuple('BuiltinTypeInfo', 'file lno name static decl')): + + @classmethod + def from_line(cls, line, filename, lno, *, decls=None): + parsed = _parse_line(line) + if not parsed: + return None + name, isdecl, kind = parsed + if isdecl: + return None + return cls.from_parsed(name, kind, filename, lno, decls=decls) + + @classmethod + def from_parsed(cls, name, kind, filename, lno, *, decls=None): + if not kind: + static = False + elif kind == 'static': + static = True + else: + raise NotImplementedError((filename, line, kind)) + decl = decls.get(name) if decls else None + return cls(filename, lno, name, static, decl) + + @property + def relfile(self): + return self.file[len(REPO_ROOT) + 1:] + + @property + def exported(self): + return not self.static + + @property + def api(self): + if not self.decl: + return False + return self.decl.api + + @property + def internal(self): + if not self.decl: + return False + return self.decl.internal + + @property + def private(self): + if not self.decl: + return False + return self.decl.private + + @property + def public(self): + if not self.decl: + return False + return self.decl.public + + @property + def inmodule(self): + return self.relfile.startswith('Modules' + os.path.sep) + + def render_rowvalues(self, kinds): + row = { + 'name': self.name, + **{k: '' for k in kinds}, + 'filename': f'{self.relfile}:{self.lno}', + } + if self.static: + kind = 'static' + else: + if self.internal: + kind = 'internal' + elif self.private: + kind = 'private' + elif self.public: + kind = 'public' + else: + kind = 'global' + row['kind'] = kind + row[kind] = kind + return row + + +def _ensure_decl(decl, decls): + prev = decls.get(decl.name) + if prev: + if decl.kind == 'forward': + return None + if prev.kind != 'forward': + if decl.kind == prev.kind and decl.file == prev.file: + assert decl.lno != prev.lno, (decl, prev) + return None + raise NotImplementedError(f'duplicate {decl} (was {prev}') + decls[decl.name] = decl + + +def iter_builtin_types(filenames=None): + decls = {} + seen = set() + for filename in iter_header_files(): + seen.add(filename) + with open(filename) as infile: + for lno, line in enumerate(infile, 1): + decl = BuiltinTypeDecl.from_line(line, filename, lno) + if not decl: + continue + _ensure_decl(decl, decls) + srcfiles = [] + for filename in iter_filenames(): + if filename.endswith('.c'): + srcfiles.append(filename) + continue + if filename in seen: + continue + with open(filename) as infile: + for lno, line in enumerate(infile, 1): + decl = BuiltinTypeDecl.from_line(line, filename, lno) + if not decl: + continue + _ensure_decl(decl, decls) + + for filename in srcfiles: + with open(filename) as infile: + localdecls = {} + for lno, line in enumerate(infile, 1): + parsed = _parse_line(line) + if not parsed: + continue + name, isdecl, kind = parsed + if isdecl: + decl = BuiltinTypeDecl.from_parsed(name, kind, filename, lno) + if not decl: + raise NotImplementedError((filename, line)) + _ensure_decl(decl, localdecls) + else: + builtin = BuiltinTypeInfo.from_parsed( + name, kind, filename, lno, + decls=decls if name in decls else localdecls) + if not builtin: + raise NotImplementedError((filename, line)) + yield builtin + + +def resolve_matcher(showmodules=False): + def match(info, *, log=None): + if not info.inmodule: + return True + if log is not None: + log(f'ignored {info.name!r}') + return False + return match + + +################################## +# CLI rendering + +def resolve_format(fmt): + if not fmt: + return 'table' + elif isinstance(fmt, str) and fmt in _FORMATS: + return fmt + else: + raise NotImplementedError(fmt) + + +def get_renderer(fmt): + fmt = resolve_format(fmt) + if isinstance(fmt, str): + try: + return _FORMATS[fmt] + except KeyError: + raise ValueError(f'unsupported format {fmt!r}') + else: + raise NotImplementedError(fmt) + + +def render_table(types): + types = sorted(types, key=(lambda t: t.name)) + colspecs = tables.resolve_columns( + 'name:<33 static:^ global:^ internal:^ private:^ public:^ filename:<30') + header, div, rowfmt = tables.build_table(colspecs) + leader = ' ' * sum(c.width+2 for c in colspecs[:3]) + ' ' + yield leader + f'{"API":^29}' + yield leader + '-' * 29 + yield header + yield div + kinds = [c[0] for c in colspecs[1:-1]] + counts = {k: 0 for k in kinds} + base = {k: '' for k in kinds} + for t in types: + row = t.render_rowvalues(kinds) + kind = row['kind'] + yield rowfmt.format(**row) + counts[kind] += 1 + yield '' + yield f'total: {sum(counts.values()):>3}' + for kind in kinds: + yield f' {kind:>10}: {counts[kind]:>3}' + + +def render_repr(types): + for t in types: + yield repr(t) + + +_FORMATS = { + 'table': render_table, + 'repr': render_repr, +} diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv index c92f64d..bc9d6aa 100644 --- a/Tools/c-analyzer/cpython/globals-to-fix.tsv +++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv @@ -7,7 +7,7 @@ filename funcname name reason # global objects to fix in core code #----------------------- -# static types +# exported builtin types (C-API) Objects/boolobject.c - PyBool_Type - Objects/bytearrayobject.c - PyByteArrayIter_Type - @@ -18,8 +18,6 @@ Objects/capsule.c - PyCapsule_Type - Objects/cellobject.c - PyCell_Type - Objects/classobject.c - PyInstanceMethod_Type - Objects/classobject.c - PyMethod_Type - -Objects/codeobject.c - _PyLineIterator - -Objects/codeobject.c - _PyPositionsIterator - Objects/codeobject.c - PyCode_Type - Objects/complexobject.c - PyComplex_Type - Objects/descrobject.c - PyClassMethodDescr_Type - @@ -42,16 +40,12 @@ Objects/dictobject.c - PyDictValues_Type - Objects/dictobject.c - PyDict_Type - Objects/enumobject.c - PyEnum_Type - Objects/enumobject.c - PyReversed_Type - -Objects/exceptions.c - _PyExc_BaseExceptionGroup - -Objects/exceptions.c - _PyExc_EncodingWarning - Objects/fileobject.c - PyStdPrinter_Type - -Objects/floatobject.c - FloatInfoType - Objects/floatobject.c - PyFloat_Type - Objects/frameobject.c - PyFrame_Type - Objects/funcobject.c - PyClassMethod_Type - Objects/funcobject.c - PyFunction_Type - Objects/funcobject.c - PyStaticMethod_Type - -Objects/genericaliasobject.c - _Py_GenericAliasIterType - Objects/genericaliasobject.c - Py_GenericAliasType - Objects/genobject.c - PyAsyncGen_Type - Objects/genobject.c - PyCoro_Type - @@ -63,13 +57,10 @@ Objects/genobject.c - _PyCoroWrapper_Type - Objects/interpreteridobject.c - _PyInterpreterID_Type - Objects/iterobject.c - PyCallIter_Type - Objects/iterobject.c - PySeqIter_Type - -Objects/iterobject.c - _PyAnextAwaitable_Type - Objects/listobject.c - PyListIter_Type - Objects/listobject.c - PyListRevIter_Type - Objects/listobject.c - PyList_Type - -Objects/longobject.c - Int_InfoType - Objects/longobject.c - PyLong_Type - -Objects/memoryobject.c - _PyMemoryIter_Type - Objects/memoryobject.c - PyMemoryView_Type - Objects/memoryobject.c - _PyManagedBuffer_Type - Objects/methodobject.c - PyCFunction_Type - @@ -91,7 +82,6 @@ Objects/rangeobject.c - PyRange_Type - Objects/setobject.c - PyFrozenSet_Type - Objects/setobject.c - PySetIter_Type - Objects/setobject.c - PySet_Type - -Objects/setobject.c - _PySetDummy_Type - Objects/sliceobject.c - PyEllipsis_Type - Objects/sliceobject.c - PySlice_Type - Objects/tupleobject.c - PyTupleIter_Type - @@ -99,11 +89,8 @@ Objects/tupleobject.c - PyTuple_Type - Objects/typeobject.c - PyBaseObject_Type - Objects/typeobject.c - PySuper_Type - Objects/typeobject.c - PyType_Type - -Objects/unicodeobject.c - EncodingMapType - Objects/unicodeobject.c - PyUnicodeIter_Type - Objects/unicodeobject.c - PyUnicode_Type - -Objects/unionobject.c - _PyUnion_Type - -Objects/unionobject.c - _Py_UnionType - Objects/weakrefobject.c - _PyWeakref_CallableProxyType - Objects/weakrefobject.c - _PyWeakref_ProxyType - Objects/weakrefobject.c - _PyWeakref_RefType - @@ -113,8 +100,23 @@ Python/bltinmodule.c - PyZip_Type - Python/context.c - PyContextToken_Type - Python/context.c - PyContextVar_Type - Python/context.c - PyContext_Type - +Python/traceback.c - PyTraceBack_Type - + +#----------------------- +# other exported builtin types + +# Not in a .h file: +Objects/codeobject.c - _PyLineIterator - +# Not in a .h file: +Objects/codeobject.c - _PyPositionsIterator - +Objects/genericaliasobject.c - _Py_GenericAliasIterType - +# Not in a .h file: +Objects/iterobject.c - _PyAnextAwaitable_Type - +# Not in a .h file: +Objects/memoryobject.c - _PyMemoryIter_Type - +#Objects/unicodeobject.c - _PyUnicodeASCIIIter_Type - +Objects/unionobject.c - _PyUnion_Type - Python/context.c - _PyContextTokenMissing_Type - -Python/errors.c - UnraisableHookArgsType - Python/hamt.c - _PyHamtItems_Type - Python/hamt.c - _PyHamtKeys_Type - Python/hamt.c - _PyHamtValues_Type - @@ -123,17 +125,32 @@ Python/hamt.c - _PyHamt_BitmapNode_Type - Python/hamt.c - _PyHamt_CollisionNode_Type - Python/hamt.c - _PyHamt_Type - Python/symtable.c - PySTEntry_Type - + +#----------------------- +# private static builtin types + +Objects/setobject.c - _PySetDummy_Type - +Objects/unicodeobject.c - EncodingMapType - +#Objects/unicodeobject.c - PyFieldNameIter_Type - +#Objects/unicodeobject.c - PyFormatterIter_Type - + +#----------------------- +# static builtin structseq + +Objects/floatobject.c - FloatInfoType - +Objects/longobject.c - Int_InfoType - +Python/errors.c - UnraisableHookArgsType - Python/sysmodule.c - AsyncGenHooksType - Python/sysmodule.c - FlagsType - Python/sysmodule.c - Hash_InfoType - Python/sysmodule.c - VersionInfoType - Python/thread.c - ThreadInfoType - -Python/traceback.c - PyTraceBack_Type - #----------------------- # builtin exception types Objects/exceptions.c - _PyExc_BaseException - +Objects/exceptions.c - _PyExc_BaseExceptionGroup - Objects/exceptions.c - _PyExc_UnicodeEncodeError - Objects/exceptions.c - _PyExc_UnicodeDecodeError - Objects/exceptions.c - _PyExc_UnicodeTranslateError - @@ -197,9 +214,11 @@ Objects/exceptions.c - _PyExc_ImportWarning - Objects/exceptions.c - _PyExc_UnicodeWarning - Objects/exceptions.c - _PyExc_BytesWarning - Objects/exceptions.c - _PyExc_ResourceWarning - +Objects/exceptions.c - _PyExc_EncodingWarning - Objects/exceptions.c - PyExc_EnvironmentError - Objects/exceptions.c - PyExc_IOError - Objects/exceptions.c - PyExc_BaseException - +Objects/exceptions.c - PyExc_BaseExceptionGroup - Objects/exceptions.c - PyExc_Exception - Objects/exceptions.c - PyExc_TypeError - Objects/exceptions.c - PyExc_StopAsyncIteration - @@ -263,6 +282,7 @@ Objects/exceptions.c - PyExc_ImportWarning - Objects/exceptions.c - PyExc_UnicodeWarning - Objects/exceptions.c - PyExc_BytesWarning - Objects/exceptions.c - PyExc_ResourceWarning - +Objects/exceptions.c - PyExc_EncodingWarning - #----------------------- # singletons @@ -354,8 +374,6 @@ Objects/unicodeobject.c - static_strings - # other # initialized once -Objects/exceptions.c - PyExc_BaseExceptionGroup - -Objects/exceptions.c - PyExc_EncodingWarning - # XXX This should have been found by the analyzer but wasn't: Python/context.c - _token_missing - # XXX This should have been found by the analyzer but wasn't: |