We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
There was an error while loading. Please reload this page.
ClassVar
AST._field_types
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
The current annotation is broad: dict[str, Any].
dict[str, Any]
typeshed/stdlib/ast.pyi
Lines 31 to 38 in 8f5a80e
ast.Constant
ast.MatchSingleton
(.venv) C:\apps\astToolFactory>py Python 3.13.4 (tags/v3.13.4:8a526ec, Jun 3 2025, 17:46:04) [MSC v.1943 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import ast >>> ast.Constant._field_types {'value': <class 'object'>, 'kind': str | None} >>> ast.MatchSingleton._field_types {'value': <class 'object'>}
Answer: dict[str, Any]. QED; close issue.
You can play along at home!
from ast import * # pyright: ignore[reportWildcardImportFromLibrary] # noqa: F403 from ast import AST, Constant from builtins import Ellipsis as ellipsis from collections import defaultdict from itertools import chain from types import EllipsisType, GenericAlias from typing import Literal import ast import typing import typing_extensions # NOTE Settings includeDeprecated = False # Set to `True` to include deprecated AST classes. replace_class_object = True # Set to `True` to replace `class` `object` with "stdlib/ast.pyi" types. replaceLiteralBoolean = True # Set to `True` to replace `Literal[True, False]` with `bool` use_ConstantValueTypeAlias = True # Set to `True` to replace `str | bytes | bool | int | float | complex | None | ellipsis` with the TypeAlias from "stdlib/ast.pyi". listASTClasses: list[type[AST]] = [] for astClass in sorted([AST, *chain(*map(lambda c: c.__subclasses__(), [AST, Constant, *AST.__subclasses__()]))], key=lambda c: c.__name__): if not issubclass(astClass, AST): continue if not includeDeprecated: if bool(astClass.__doc__ and 'Deprecated' in astClass.__doc__): continue listASTClasses.append(astClass) listASTClassesWith_field_types: list[type[AST]] = [] for astClass in listASTClasses: try: astClass._field_types except AttributeError: continue listASTClassesWith_field_types.append(astClass) _ConstantValue: typing_extensions.TypeAlias = str | bytes | bool | int | float | complex | None | EllipsisType dictionaryAnnotations: dict[str, list[tuple[str, str]]] = defaultdict(list) for astClass in listASTClassesWith_field_types: className: str = astClass.__name__ for field in astClass._field_types: annotation_field_type = None annotationSherpa = astClass._field_types[field] if not isinstance(annotationSherpa, GenericAlias): try: annotation_field_type = annotationSherpa.__name__ if annotation_field_type == 'object' and replace_class_object: if className == Constant.__name__ and field == 'value': annotation_field_type = _ConstantValue if use_ConstantValueTypeAlias: annotation_field_type = '_ConstantValue' if className == ast.MatchSingleton.__name__ and field == 'value': annotation_field_type = Literal[True, False] if replaceLiteralBoolean: annotation_field_type = bool.__name__ except Exception: pass if not annotation_field_type: annotation_field_type = str(annotationSherpa) dictionaryAnnotations[str(annotation_field_type)].append((className, field)) # START Embarrassing, string parsing, semantically vacant code for which I don't have the health to improve. setTypesAsStr: set[str] = set() for annotation_field_type in dictionaryAnnotations.keys(): listTypesAsStr: list[str] = annotation_field_type.split('|') setTypesAsStr.update([typeAsStr.strip().replace('ast.', '') for typeAsStr in listTypesAsStr]) if use_ConstantValueTypeAlias: setConstantValueTypeAlias: set[str] = {typeAsStr.strip().replace('ast.', '') for typeAsStr in str(_ConstantValue).split('|')} setTypesAsStr = setTypesAsStr - setConstantValueTypeAlias setTypesSansSubclassesAsStr: set[str] = set() setOfClassesAST: set[type] = set() setOfListsAST: set[type] = set() for typeAsStr in setTypesAsStr: if typeAsStr.startswith('list'): typeTarget: type = eval(typeAsStr.replace('list[', '').replace(']', '')) if issubclass(typeTarget, AST): setOfListsAST.add(typeTarget) else: setTypesSansSubclassesAsStr.add(typeAsStr) else: typeTarget: type = eval(typeAsStr) if isinstance(typeTarget, type) and issubclass(typeTarget, AST): setOfClassesAST.add(typeTarget) else: setTypesSansSubclassesAsStr.add(typeAsStr) setOfClassesASTCompacted: set[type] = {classTarget for classTarget in setOfClassesAST if not any(issubclass(classTarget, otherClass) and classTarget is not otherClass for otherClass in setOfClassesAST)} setOfListsASTCompacted: set[type] = {classTarget for classTarget in setOfListsAST if not any(issubclass(classTarget, otherClass) and classTarget is not otherClass for otherClass in setOfListsAST)} print(f"{setOfClassesAST == setOfClassesASTCompacted = }") print(f"{setOfListsAST == setOfListsASTCompacted = }") setOfClassesAST.add(ast.AST) setOfListsAST.add(AST) setOfClassesASTCompacted: set[type] = {classTarget for classTarget in setOfClassesAST if not any(issubclass(classTarget, otherClass) and classTarget is not otherClass for otherClass in setOfClassesAST)} setOfListsASTCompacted: set[type] = {classTarget for classTarget in setOfListsAST if not any(issubclass(classTarget, otherClass) and classTarget is not otherClass for otherClass in setOfListsAST)} listASTisAST: list[str] = ( sorted( [classTarget.__name__ for classTarget in setOfClassesASTCompacted] + [f"list[{classTarget.__name__}]" for classTarget in setOfListsASTCompacted] + list(setTypesSansSubclassesAsStr), key=lambda string: string.lower() ) ) setOfClassesASTExpanded: set[type] = set(chain.from_iterable( [classTarget] + list(classTarget.__subclasses__()) for classTarget in setOfClassesAST )) setOfListsASTExpanded: set[type] = set(chain.from_iterable( [classTarget] + list(classTarget.__subclasses__()) for classTarget in setOfListsAST )) setOfClassesASTOverInclusive: set[type] = set(listASTClasses) - setOfClassesASTExpanded setOfListsASTOverInclusive: set[type] = set(listASTClasses) - setOfListsASTExpanded listOverInclusive: list[str] = ( sorted( [classTarget.__name__ for classTarget in setOfClassesASTOverInclusive] + [f"list[{classTarget.__name__}]" for classTarget in setOfListsASTOverInclusive], key=lambda string: string.lower() ) ) # END Embarrassing, string parsing, semantically vacant code for which I don't have the health to improve. # This is BYOp: Bring Your Own print().
includeDeprecated = False # Set to `True` to include deprecated AST classes.
arguments
ast.arg | None
ast.expr | None
ast.pattern | None
boolop
expr
expr_context
int
int | None
list[ast.alias]
list[ast.arg]
list[ast.cmpop]
list[ast.comprehension]
list[ast.excepthandler]
list[ast.expr]
list[ast.keyword]
list[ast.match_case]
list[ast.pattern]
list[ast.stmt]
list[ast.type_ignore]
list[ast.type_param]
list[ast.withitem]
list[str]
operator
pattern
str
str | None
str | bytes | bool | int | float | complex | None | ellipsis
typing.Literal[True, False]
unaryop
ast.Constant.value
ast.MatchSingleton.value
I don't know if this is haram, but I think these are valid substitutions.
Literal[True, False]
bool
typing.TypeAlias
_ConstantValue
dict[str, arg | arguments | bool | boolop | bytes | complex | ellipsis | expr | expr_context | float | int | list[alias] | list[arg] | list[cmpop] | list[comprehension] | list[excepthandler] | list[expr] | list[keyword] | list[match_case] | list[pattern] | list[stmt] | list[str] | list[type_ignore] | list[type_param] | list[withitem] | operator | pattern | str | unaryop | None]
dict[str, _ConstantValue | arg | arguments | boolop | expr | expr_context | list[alias] | list[arg] | list[cmpop] | list[comprehension] | list[excepthandler] | list[expr] | list[keyword] | list[match_case] | list[pattern] | list[stmt] | list[str] | list[type_ignore] | list[type_param] | list[withitem] | operator | pattern | unaryop]
No change!
(.venv) C:\apps\astToolFactory>Z0Z_field_types.py setOfClassesAST == setOfClassesASTCompacted = True setOfListsAST == setOfListsASTCompacted = True
ast.AST
dict[str, bool | bytes | complex | ellipsis | float | int | list[str] | str | AST | list[AST] | None]
dict[str, _ConstantValue | list[str] | AST | list[AST]]
alias | AnnAssign | Assert | Assign | AST | AsyncFor | AsyncFunctionDef | AsyncWith | AugAssign | Break | ClassDef | cmpop | comprehension | Continue | Delete | Eq | ExceptHandler | excepthandler | Expr | Expression | For | FunctionDef | FunctionType | Global | Gt | GtE | If | Import | ImportFrom | In | Interactive | Is | IsNot | keyword | list[Add] | list[And] | list[arguments] | list[AST] | list[BitAnd] | list[BitOr] | list[BitXor] | list[boolop] | list[Del] | list[Div] | list[expr_context] | list[Expression] | list[FloorDiv] | list[FunctionType] | list[Interactive] | list[Invert] | list[Load] | list[LShift] | list[MatMult] | list[mod] | list[Mod] | list[Module] | list[Mult] | list[Not] | list[operator] | list[Or] | list[Pow] | list[RShift] | list[Store] | list[Sub] | list[UAdd] | list[unaryop] | list[USub] | Lt | LtE | Match | match_case | mod | Module | Nonlocal | NotEq | NotIn | ParamSpec | Pass | Raise | Return | stmt | Try | TryStar | type_ignore | type_param | TypeAlias | TypeIgnore | TypeVar | TypeVarTuple | While | With | withitem
dict[str, None | arg | arguments | bool | boolop | bytes | complex | ellipsis | expr | expr_context | float | int | list[alias] | list[arg] | list[cmpop] | list[comprehension] | list[excepthandler] | list[expr] | list[keyword] | list[match_case] | list[pattern] | list[stmt] | list[str] | list[type_ignore] | list[type_param] | list[withitem] | operator | pattern | str | typing.Literal[True, False] | unaryop]
dict[str, None | arg | arguments | bool | boolop | bytes | complex | ellipsis | expr | expr_context | float | int | list[alias] | list[arg] | list[cmpop] | list[comprehension] | list[excepthandler] | list[expr] | list[keyword] | list[match_case] | list[pattern] | list[stmt] | list[str] | list[type_ignore] | list[type_param] | list[withitem] | operator | pattern | str | unaryop]
dict[str, AST | bool | bytes | complex | ellipsis | float | int | list[AST] | list[str] | None | str | typing.Literal[True, False]]
dict[str, AST | bool | bytes | complex | ellipsis | float | int | list[AST] | list[str] | None | str]
dict[str, _ConstantValue | AST | list[AST] | list[str]]
._field_type
from ast import * from itertools import chain ASTfield_types:dict[str, str | dict[str, str]] = {} for astClass in [C for C in [AST,*chain(*map(lambda c:c.__subclasses__(), [AST,Constant,*AST.__subclasses__()]))] if issubclass(C,AST)]: try: field_types = {k:str(v).replace("<class '",'').replace("'>",'') for k,v in astClass._field_types.items()} except Exception as ERRORmessage: field_types = ERRORmessage.__class__.__name__ ASTfield_types[astClass.__name__] = field_types print(*ASTfield_types.items(), sep='\n')
('AST', 'AttributeError') ('mod', 'AttributeError') ('stmt', 'AttributeError') ('expr', 'AttributeError') ('expr_context', 'AttributeError') ('boolop', 'AttributeError') ('operator', 'AttributeError') ('unaryop', 'AttributeError') ('cmpop', 'AttributeError') ('comprehension', {'target': 'ast.expr', 'iter': 'ast.expr', 'ifs': 'list[ast.expr]', 'is_async': 'int'}) ('excepthandler', 'AttributeError') ('arguments', {'posonlyargs': 'list[ast.arg]', 'args': 'list[ast.arg]', 'vararg': 'ast.arg | None', 'kwonlyargs': 'list[ast.arg]', 'kw_defaults': 'list[ast.expr]', 'kwarg': 'ast.arg | None', 'defaults': 'list[ast.expr]'}) ('arg', {'arg': 'str', 'annotation': 'ast.expr | None', 'type_comment': 'str | None'}) ('keyword', {'arg': 'str | None', 'value': 'ast.expr'}) ('alias', {'name': 'str', 'asname': 'str | None'}) ('withitem', {'context_expr': 'ast.expr', 'optional_vars': 'ast.expr | None'}) ('match_case', {'pattern': 'ast.pattern', 'guard': 'ast.expr | None', 'body': 'list[ast.stmt]'}) ('pattern', 'AttributeError') ('type_ignore', 'AttributeError') ('type_param', 'AttributeError') ('slice', 'AttributeError') ('Num', {'value': 'object', 'kind': 'str | None'}) ('Str', {'value': 'object', 'kind': 'str | None'}) ('Bytes', {'value': 'object', 'kind': 'str | None'}) ('NameConstant', {'value': 'object', 'kind': 'str | None'}) ('Ellipsis', {'value': 'object', 'kind': 'str | None'}) ('Module', {'body': 'list[ast.stmt]', 'type_ignores': 'list[ast.type_ignore]'}) ('Interactive', {'body': 'list[ast.stmt]'}) ('Expression', {'body': 'ast.expr'}) ('FunctionType', {'argtypes': 'list[ast.expr]', 'returns': 'ast.expr'}) ('Suite', 'AttributeError') ('FunctionDef', {'name': 'str', 'args': 'ast.arguments', 'body': 'list[ast.stmt]', 'decorator_list': 'list[ast.expr]', 'returns': 'ast.expr | None', 'type_comment': 'str | None', 'type_params': 'list[ast.type_param]'}) ('AsyncFunctionDef', {'name': 'str', 'args': 'ast.arguments', 'body': 'list[ast.stmt]', 'decorator_list': 'list[ast.expr]', 'returns': 'ast.expr | None', 'type_comment': 'str | None', 'type_params': 'list[ast.type_param]'}) ('ClassDef', {'name': 'str', 'bases': 'list[ast.expr]', 'keywords': 'list[ast.keyword]', 'body': 'list[ast.stmt]', 'decorator_list': 'list[ast.expr]', 'type_params': 'list[ast.type_param]'}) ('Return', {'value': 'ast.expr | None'}) ('Delete', {'targets': 'list[ast.expr]'}) ('Assign', {'targets': 'list[ast.expr]', 'value': 'ast.expr', 'type_comment': 'str | None'}) ('TypeAlias', {'name': 'ast.expr', 'type_params': 'list[ast.type_param]', 'value': 'ast.expr'}) ('AugAssign', {'target': 'ast.expr', 'op': 'ast.operator', 'value': 'ast.expr'}) ('AnnAssign', {'target': 'ast.expr', 'annotation': 'ast.expr', 'value': 'ast.expr | None', 'simple': 'int'}) ('For', {'target': 'ast.expr', 'iter': 'ast.expr', 'body': 'list[ast.stmt]', 'orelse': 'list[ast.stmt]', 'type_comment': 'str | None'}) ('AsyncFor', {'target': 'ast.expr', 'iter': 'ast.expr', 'body': 'list[ast.stmt]', 'orelse': 'list[ast.stmt]', 'type_comment': 'str | None'}) ('While', {'test': 'ast.expr', 'body': 'list[ast.stmt]', 'orelse': 'list[ast.stmt]'}) ('If', {'test': 'ast.expr', 'body': 'list[ast.stmt]', 'orelse': 'list[ast.stmt]'}) ('With', {'items': 'list[ast.withitem]', 'body': 'list[ast.stmt]', 'type_comment': 'str | None'}) ('AsyncWith', {'items': 'list[ast.withitem]', 'body': 'list[ast.stmt]', 'type_comment': 'str | None'}) ('Match', {'subject': 'ast.expr', 'cases': 'list[ast.match_case]'}) ('Raise', {'exc': 'ast.expr | None', 'cause': 'ast.expr | None'}) ('Try', {'body': 'list[ast.stmt]', 'handlers': 'list[ast.excepthandler]', 'orelse': 'list[ast.stmt]', 'finalbody': 'list[ast.stmt]'}) ('TryStar', {'body': 'list[ast.stmt]', 'handlers': 'list[ast.excepthandler]', 'orelse': 'list[ast.stmt]', 'finalbody': 'list[ast.stmt]'}) ('Assert', {'test': 'ast.expr', 'msg': 'ast.expr | None'}) ('Import', {'names': 'list[ast.alias]'}) ('ImportFrom', {'module': 'str | None', 'names': 'list[ast.alias]', 'level': 'int | None'}) ('Global', {'names': 'list[str]'}) ('Nonlocal', {'names': 'list[str]'}) ('Expr', {'value': 'ast.expr'}) ('Pass', {}) ('Break', {}) ('Continue', {}) ('BoolOp', {'op': 'ast.boolop', 'values': 'list[ast.expr]'}) ('NamedExpr', {'target': 'ast.expr', 'value': 'ast.expr'}) ('BinOp', {'left': 'ast.expr', 'op': 'ast.operator', 'right': 'ast.expr'}) ('UnaryOp', {'op': 'ast.unaryop', 'operand': 'ast.expr'}) ('Lambda', {'args': 'ast.arguments', 'body': 'ast.expr'}) ('IfExp', {'test': 'ast.expr', 'body': 'ast.expr', 'orelse': 'ast.expr'}) ('Dict', {'keys': 'list[ast.expr]', 'values': 'list[ast.expr]'}) ('Set', {'elts': 'list[ast.expr]'}) ('ListComp', {'elt': 'ast.expr', 'generators': 'list[ast.comprehension]'}) ('SetComp', {'elt': 'ast.expr', 'generators': 'list[ast.comprehension]'}) ('DictComp', {'key': 'ast.expr', 'value': 'ast.expr', 'generators': 'list[ast.comprehension]'}) ('GeneratorExp', {'elt': 'ast.expr', 'generators': 'list[ast.comprehension]'}) ('Await', {'value': 'ast.expr'}) ('Yield', {'value': 'ast.expr | None'}) ('YieldFrom', {'value': 'ast.expr'}) ('Compare', {'left': 'ast.expr', 'ops': 'list[ast.cmpop]', 'comparators': 'list[ast.expr]'}) ('Call', {'func': 'ast.expr', 'args': 'list[ast.expr]', 'keywords': 'list[ast.keyword]'}) ('FormattedValue', {'value': 'ast.expr', 'conversion': 'int', 'format_spec': 'ast.expr | None'}) ('JoinedStr', {'values': 'list[ast.expr]'}) ('Constant', {'value': 'object', 'kind': 'str | None'}) ('Attribute', {'value': 'ast.expr', 'attr': 'str', 'ctx': 'ast.expr_context'}) ('Subscript', {'value': 'ast.expr', 'slice': 'ast.expr', 'ctx': 'ast.expr_context'}) ('Starred', {'value': 'ast.expr', 'ctx': 'ast.expr_context'}) ('Name', {'id': 'str', 'ctx': 'ast.expr_context'}) ('List', {'elts': 'list[ast.expr]', 'ctx': 'ast.expr_context'}) ('Tuple', {'elts': 'list[ast.expr]', 'ctx': 'ast.expr_context'}) ('Slice', {'lower': 'ast.expr | None', 'upper': 'ast.expr | None', 'step': 'ast.expr | None'}) ('Load', {}) ('Store', {}) ('Del', {}) ('AugLoad', 'AttributeError') ('AugStore', 'AttributeError') ('Param', 'AttributeError') ('And', {}) ('Or', {}) ('Add', {}) ('Sub', {}) ('Mult', {}) ('MatMult', {}) ('Div', {}) ('Mod', {}) ('Pow', {}) ('LShift', {}) ('RShift', {}) ('BitOr', {}) ('BitXor', {}) ('BitAnd', {}) ('FloorDiv', {}) ('Invert', {}) ('Not', {}) ('UAdd', {}) ('USub', {}) ('Eq', {}) ('NotEq', {}) ('Lt', {}) ('LtE', {}) ('Gt', {}) ('GtE', {}) ('Is', {}) ('IsNot', {}) ('In', {}) ('NotIn', {}) ('ExceptHandler', {'type': 'ast.expr | None', 'name': 'str | None', 'body': 'list[ast.stmt]'}) ('MatchValue', {'value': 'ast.expr'}) ('MatchSingleton', {'value': 'object'}) ('MatchSequence', {'patterns': 'list[ast.pattern]'}) ('MatchMapping', {'keys': 'list[ast.expr]', 'patterns': 'list[ast.pattern]', 'rest': 'str | None'}) ('MatchClass', {'cls': 'ast.expr', 'patterns': 'list[ast.pattern]', 'kwd_attrs': 'list[str]', 'kwd_patterns': 'list[ast.pattern]'}) ('MatchStar', {'name': 'str | None'}) ('MatchAs', {'pattern': 'ast.pattern | None', 'name': 'str | None'}) ('MatchOr', {'patterns': 'list[ast.pattern]'}) ('TypeIgnore', {'lineno': 'int', 'tag': 'str'}) ('TypeVar', {'name': 'str', 'bound': 'ast.expr | None', 'default_value': 'ast.expr | None'}) ('ParamSpec', {'name': 'str', 'default_value': 'ast.expr | None'}) ('TypeVarTuple', {'name': 'str', 'default_value': 'ast.expr | None'}) ('Index', 'AttributeError') ('ExtSlice', 'AttributeError')
The text was updated successfully, but these errors were encountered:
_field_types
No branches or pull requests
My amateur analysis of the precise annotation for
ClassVar
AST._field_types
The current annotation is broad:
dict[str, Any]
.Details
typeshed/stdlib/ast.pyi
Lines 31 to 38 in 8f5a80e
If
ast.Constant
and/orast.MatchSingleton
, without "stdlib/ast.pyi", trumps everythingAnswer:
dict[str, Any]
.QED; close issue.
My code underlying the following analysis
You can play along at home!
Details
Baseline
Details
arguments
ast.arg | None
ast.expr | None
ast.pattern | None
boolop
expr
expr_context
int
int | None
list[ast.alias]
list[ast.arg]
list[ast.cmpop]
list[ast.comprehension]
list[ast.excepthandler]
list[ast.expr]
list[ast.keyword]
list[ast.match_case]
list[ast.pattern]
list[ast.stmt]
list[ast.type_ignore]
list[ast.type_param]
list[ast.withitem]
list[str]
operator
pattern
str
str | None
str | bytes | bool | int | float | complex | None | ellipsis
typing.Literal[True, False]
unaryop
Possible replacements for
ast.Constant.value
andast.MatchSingleton.value
I don't know if this is haram, but I think these are valid substitutions.
Literal[True, False]
withbool
str | bytes | bool | int | float | complex | None | ellipsis
with atyping.TypeAlias
bool
_ConstantValue
If each unique type must be listed
With a TypeAlias
Fold subclasses into their parent classes if the parent class is present
No change!
Details
Arrogantly fold
ast.AST
subclasses intoast.AST
even though it is not presentWith a TypeAlias
ast.AST
is extremely over-inclusive: 92 classes and lists of classDetails
🛑 Summary 🛑
The Brahman annotation
All true names
Like, literally all identifiers
typing.TypeAlias
"All AST look the same"
"No, like, literally the same"
Peak hubris
Annex:
._field_type
for everyast.AST
subclassCode
Details
print
Details
The text was updated successfully, but these errors were encountered: