Skip to content

Commit 2287b7e

Browse files
committed
Python >= 3.12. Excised ast_Identifier, which changed many functions and methods from "_Identifier" to "Identifier". factory3 is online. Excised dead comments and code.
1 parent dff1b4d commit 2287b7e

23 files changed

Lines changed: 261 additions & 1022 deletions

README.md

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -140,32 +140,32 @@ print(ast.unparse(tree))
140140
This example shows a more complex transformation inspired by the mapFolding package:
141141

142142
```python
143-
from astToolkit import ast_Identifier, Be, DOT, Grab, IfThis as astToolkit_IfThis, Make, NodeChanger, Then
143+
from astToolkit import str, Be, DOT, Grab, IfThis as astToolkit_IfThis, Make, NodeChanger, Then
144144
import ast
145145

146146
# Define custom predicates by extending IfThis
147147
class IfThis(astToolkit_IfThis):
148148
@staticmethod
149-
def isAttributeNamespace_IdentifierGreaterThan0(
150-
namespace: ast_Identifier,
151-
identifier: ast_Identifier
149+
def isAttributeNamespaceIdentifierGreaterThan0(
150+
namespace: str,
151+
identifier: str
152152
) -> Callable[[ast.AST], TypeGuard[ast.Compare] | bool]:
153153

154154
return lambda node: (
155155
Be.Compare(node)
156-
and IfThis.isAttributeNamespace_Identifier(namespace, identifier)(DOT.left(node))
156+
and IfThis.isAttributeNamespaceIdentifier(namespace, identifier)(DOT.left(node))
157157
and Be.Gt(node.ops[0])
158158
and IfThis.isConstant_value(0)(node.comparators[0]))
159159

160160
@staticmethod
161-
def isWhileAttributeNamespace_IdentifierGreaterThan0(
162-
namespace: ast_Identifier,
163-
identifier: ast_Identifier
161+
def isWhileAttributeNamespaceIdentifierGreaterThan0(
162+
namespace: str,
163+
identifier: str
164164
) -> Callable[[ast.AST], TypeGuard[ast.While] | bool]:
165165

166166
return lambda node: (
167167
Be.While(node)
168-
and IfThis.isAttributeNamespace_IdentifierGreaterThan0(namespace, identifier)(DOT.test(node)))
168+
and IfThis.isAttributeNamespaceIdentifierGreaterThan0(namespace, identifier)(DOT.test(node)))
169169

170170
# Parse some code
171171
code = """
@@ -176,7 +176,7 @@ while claude.counter > 0:
176176
tree = ast.parse(code)
177177

178178
# Find the while loop with our custom predicate
179-
find_while_loop = IfThis.isWhileAttributeNamespace_IdentifierGreaterThan0("claude", "counter")
179+
find_while_loop = IfThis.isWhileAttributeNamespaceIdentifierGreaterThan0("claude", "counter")
180180

181181
# Replace counter > 0 with counter > 1
182182
change_condition = Grab.testAttribute(
@@ -212,7 +212,7 @@ module_ast = parseLogicalPath2astModule("my_package.source_module")
212212
# Extract a function and track its imports
213213
function_name = "target_function"
214214
function_def = NodeTourist(
215-
IfThis.isFunctionDef_Identifier(function_name),
215+
IfThis.isFunctionDefIdentifier(function_name),
216216
Then.extractIt
217217
).captureLastMatch(module_ast)
218218

@@ -247,34 +247,34 @@ if function_def:
247247
To create specialized patterns for your codebase, extend the core classes:
248248

249249
```python
250-
from astToolkit import ast_Identifier, Be, IfThis as astToolkit_IfThis
250+
from astToolkit import str, Be, IfThis as astToolkit_IfThis
251251
from collections.abc import Callable
252252
from typing import TypeGuard
253253
import ast
254254

255255
class IfThis(astToolkit_IfThis):
256256
@staticmethod
257-
def isAttributeNamespace_IdentifierGreaterThan0(
258-
namespace: ast_Identifier,
259-
identifier: ast_Identifier
257+
def isAttributeNamespaceIdentifierGreaterThan0(
258+
namespace: str,
259+
identifier: str
260260
) -> Callable[[ast.AST], TypeGuard[ast.Compare] | bool]:
261261
"""Find comparisons like 'state.counter > 0'"""
262262
return lambda node: (
263263
Be.Compare(node)
264-
and IfThis.isAttributeNamespace_Identifier(namespace, identifier)(node.left)
264+
and IfThis.isAttributeNamespaceIdentifier(namespace, identifier)(node.left)
265265
and Be.Gt(node.ops[0])
266266
and IfThis.isConstant_value(0)(node.comparators[0])
267267
)
268268

269269
@staticmethod
270-
def isWhileAttributeNamespace_IdentifierGreaterThan0(
271-
namespace: ast_Identifier,
272-
identifier: ast_Identifier
270+
def isWhileAttributeNamespaceIdentifierGreaterThan0(
271+
namespace: str,
272+
identifier: str
273273
) -> Callable[[ast.AST], TypeGuard[ast.While] | bool]:
274274
"""Find while loops like 'while state.counter > 0:'"""
275275
return lambda node: (
276276
Be.While(node)
277-
and IfThis.isAttributeNamespace_IdentifierGreaterThan0(namespace, identifier)(node.test)
277+
and IfThis.isAttributeNamespaceIdentifierGreaterThan0(namespace, identifier)(node.test)
278278
)
279279
```
280280

astToolkit/__init__.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,8 @@
1-
from astToolkit._typesSpecial import (
2-
NotRequired as NotRequired,
3-
TypedDict as TypedDict,
4-
)
5-
61
from astToolkit._astTypes import * # noqa: F403
72

83
from astToolkit.theSSOT import FREAKOUT as FREAKOUT, The as The
94

105
from astToolkit._types import (
11-
ast_expr_Slice as ast_expr_Slice,
12-
ast_Identifier as ast_Identifier,
136
NodeORattribute as NodeORattribute,
147
str_nameDOTname as str_nameDOTname,
158
as ,

astToolkit/_astTypes.py

Lines changed: 10 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,9 @@
2020
hasDOTattr: typing_TypeAlias = ast.Attribute
2121
hasDOTbases: typing_TypeAlias = ast.ClassDef
2222
hasDOTbody_expr: typing_TypeAlias = ast.Expression | ast.IfExp | ast.Lambda
23-
if sys.version_info >= (3, 11):
24-
hasDOTbody_list_stmt: typing_TypeAlias = ast.AsyncFor | ast.AsyncFunctionDef | ast.AsyncWith | ast.ClassDef | ast.ExceptHandler | ast.For | ast.FunctionDef | ast.If | ast.Interactive | ast.match_case | ast.Module | ast.Try | ast.TryStar | ast.While | ast.With
25-
else:
26-
hasDOTbody_list_stmt: typing_TypeAlias = ast.AsyncFor | ast.AsyncFunctionDef | ast.AsyncWith | ast.ClassDef | ast.ExceptHandler | ast.For | ast.FunctionDef | ast.If | ast.Interactive | ast.match_case | ast.Module | ast.Try | ast.While | ast.With
23+
hasDOTbody_list_stmt: typing_TypeAlias = ast.AsyncFor | ast.AsyncFunctionDef | ast.AsyncWith | ast.ClassDef | ast.ExceptHandler | ast.For | ast.FunctionDef | ast.If | ast.Interactive | ast.match_case | ast.Module | ast.Try | ast.TryStar | ast.While | ast.With
2724
hasDOTbody: typing_TypeAlias = hasDOTbody_expr | hasDOTbody_list_stmt
28-
if sys.version_info >= (3, 12):
29-
hasDOTbound: typing_TypeAlias = ast.TypeVar
25+
hasDOTbound: typing_TypeAlias = ast.TypeVar
3026
hasDOTcases: typing_TypeAlias = ast.Match
3127
hasDOTcause: typing_TypeAlias = ast.Raise
3228
hasDOTcls: typing_TypeAlias = ast.MatchClass
@@ -41,18 +37,12 @@
4137
hasDOTelt: typing_TypeAlias = ast.GeneratorExp | ast.ListComp | ast.SetComp
4238
hasDOTelts: typing_TypeAlias = ast.List | ast.Set | ast.Tuple
4339
hasDOTexc: typing_TypeAlias = ast.Raise
44-
if sys.version_info >= (3, 11):
45-
hasDOTfinalbody: typing_TypeAlias = ast.Try | ast.TryStar
46-
else:
47-
hasDOTfinalbody: typing_TypeAlias = ast.Try
40+
hasDOTfinalbody: typing_TypeAlias = ast.Try | ast.TryStar
4841
hasDOTformat_spec: typing_TypeAlias = ast.FormattedValue
4942
hasDOTfunc: typing_TypeAlias = ast.Call
5043
hasDOTgenerators: typing_TypeAlias = ast.DictComp | ast.GeneratorExp | ast.ListComp | ast.SetComp
5144
hasDOTguard: typing_TypeAlias = ast.match_case
52-
if sys.version_info >= (3, 11):
53-
hasDOThandlers: typing_TypeAlias = ast.Try | ast.TryStar
54-
else:
55-
hasDOThandlers: typing_TypeAlias = ast.Try
45+
hasDOThandlers: typing_TypeAlias = ast.Try | ast.TryStar
5646
hasDOTid: typing_TypeAlias = ast.Name
5747
hasDOTifs: typing_TypeAlias = ast.comprehension
5848
hasDOTis_async: typing_TypeAlias = ast.comprehension
@@ -75,17 +65,10 @@
7565
hasDOTlower: typing_TypeAlias = ast.Slice
7666
hasDOTmodule: typing_TypeAlias = ast.ImportFrom
7767
hasDOTmsg: typing_TypeAlias = ast.Assert
78-
if sys.version_info >= (3, 12):
79-
hasDOTname_Name: typing_TypeAlias = ast.TypeAlias
80-
if sys.version_info >= (3, 12):
81-
hasDOTname_str: typing_TypeAlias = ast.alias | ast.AsyncFunctionDef | ast.ClassDef | ast.FunctionDef | ast.ParamSpec | ast.TypeVar | ast.TypeVarTuple
82-
else:
83-
hasDOTname_str: typing_TypeAlias = ast.alias | ast.AsyncFunctionDef | ast.ClassDef | ast.FunctionDef
68+
hasDOTname_Name: typing_TypeAlias = ast.TypeAlias
69+
hasDOTname_str: typing_TypeAlias = ast.alias | ast.AsyncFunctionDef | ast.ClassDef | ast.FunctionDef | ast.ParamSpec | ast.TypeVar | ast.TypeVarTuple
8470
hasDOTname_strOrNone: typing_TypeAlias = ast.ExceptHandler | ast.MatchAs | ast.MatchStar
85-
if sys.version_info >= (3, 12):
86-
hasDOTname: typing_TypeAlias = hasDOTname_Name | hasDOTname_str | hasDOTname_strOrNone
87-
else:
88-
hasDOTname: typing_TypeAlias = hasDOTname_str | hasDOTname_strOrNone
71+
hasDOTname: typing_TypeAlias = hasDOTname_Name | hasDOTname_str | hasDOTname_strOrNone
8972
hasDOTnames_list_alias: typing_TypeAlias = ast.Import | ast.ImportFrom
9073
hasDOTnames_list_str: typing_TypeAlias = ast.Global | ast.Nonlocal
9174
hasDOTnames: typing_TypeAlias = hasDOTnames_list_alias | hasDOTnames_list_str
@@ -97,10 +80,7 @@
9780
hasDOTops: typing_TypeAlias = ast.Compare
9881
hasDOToptional_vars: typing_TypeAlias = ast.withitem
9982
hasDOTorelse_expr: typing_TypeAlias = ast.IfExp
100-
if sys.version_info >= (3, 11):
101-
hasDOTorelse_list_stmt: typing_TypeAlias = ast.AsyncFor | ast.For | ast.If | ast.Try | ast.TryStar | ast.While
102-
else:
103-
hasDOTorelse_list_stmt: typing_TypeAlias = ast.AsyncFor | ast.For | ast.If | ast.Try | ast.While
83+
hasDOTorelse_list_stmt: typing_TypeAlias = ast.AsyncFor | ast.For | ast.If | ast.Try | ast.TryStar | ast.While
10484
hasDOTorelse: typing_TypeAlias = hasDOTorelse_expr | hasDOTorelse_list_stmt
10585
hasDOTpattern_pattern: typing_TypeAlias = ast.match_case
10686
hasDOTpattern_patternOrNone: typing_TypeAlias = ast.MatchAs
@@ -126,15 +106,11 @@
126106
hasDOTtype: typing_TypeAlias = ast.ExceptHandler
127107
hasDOTtype_comment: typing_TypeAlias = ast.arg | ast.Assign | ast.AsyncFor | ast.AsyncFunctionDef | ast.AsyncWith | ast.For | ast.FunctionDef | ast.With
128108
hasDOTtype_ignores: typing_TypeAlias = ast.Module
129-
if sys.version_info >= (3, 12):
130-
hasDOTtype_params: typing_TypeAlias = ast.AsyncFunctionDef | ast.ClassDef | ast.FunctionDef | ast.TypeAlias
109+
hasDOTtype_params: typing_TypeAlias = ast.AsyncFunctionDef | ast.ClassDef | ast.FunctionDef | ast.TypeAlias
131110
hasDOTupper: typing_TypeAlias = ast.Slice
132111
hasDOTvalue_Any: typing_TypeAlias = ast.Constant
133112
hasDOTvalue_boolOrNone: typing_TypeAlias = ast.MatchSingleton
134-
if sys.version_info >= (3, 12):
135-
hasDOTvalue_expr: typing_TypeAlias = ast.Assign | ast.Attribute | ast.AugAssign | ast.Await | ast.DictComp | ast.Expr | ast.FormattedValue | ast.keyword | ast.MatchValue | ast.NamedExpr | ast.Starred | ast.Subscript | ast.TypeAlias | ast.YieldFrom
136-
else:
137-
hasDOTvalue_expr: typing_TypeAlias = ast.Assign | ast.Attribute | ast.AugAssign | ast.Await | ast.DictComp | ast.Expr | ast.FormattedValue | ast.keyword | ast.MatchValue | ast.NamedExpr | ast.Starred | ast.Subscript | ast.YieldFrom
113+
hasDOTvalue_expr: typing_TypeAlias = ast.Assign | ast.Attribute | ast.AugAssign | ast.Await | ast.DictComp | ast.Expr | ast.FormattedValue | ast.keyword | ast.MatchValue | ast.NamedExpr | ast.Starred | ast.Subscript | ast.TypeAlias | ast.YieldFrom
138114
hasDOTvalue_exprOrNone: typing_TypeAlias = ast.AnnAssign | ast.Return | ast.Yield
139115
hasDOTvalue: typing_TypeAlias = hasDOTvalue_Any | hasDOTvalue_boolOrNone | hasDOTvalue_expr | hasDOTvalue_exprOrNone
140116
hasDOTvalues: typing_TypeAlias = ast.BoolOp | ast.Dict | ast.JoinedStr

astToolkit/_toolBe.py

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -382,11 +382,10 @@ def operator(node: ast.AST) -> TypeGuard[ast.operator]:
382382
@staticmethod
383383
def Or(node: ast.AST) -> TypeGuard[ast.Or]:
384384
return isinstance(node, ast.Or)
385-
if sys.version_info >= (3, 12):
386385

387-
@staticmethod
388-
def ParamSpec(node: ast.AST) -> TypeGuard[ast.ParamSpec]:
389-
return isinstance(node, ast.ParamSpec)
386+
@staticmethod
387+
def ParamSpec(node: ast.AST) -> TypeGuard[ast.ParamSpec]:
388+
return isinstance(node, ast.ParamSpec)
390389

391390
@staticmethod
392391
def Pass(node: ast.AST) -> TypeGuard[ast.Pass]:
@@ -447,11 +446,10 @@ def Subscript(node: ast.AST) -> TypeGuard[ast.Subscript]:
447446
@staticmethod
448447
def Try(node: ast.AST) -> TypeGuard[ast.Try]:
449448
return isinstance(node, ast.Try)
450-
if sys.version_info >= (3, 11):
451449

452-
@staticmethod
453-
def TryStar(node: ast.AST) -> TypeGuard[ast.TryStar]:
454-
return isinstance(node, ast.TryStar)
450+
@staticmethod
451+
def TryStar(node: ast.AST) -> TypeGuard[ast.TryStar]:
452+
return isinstance(node, ast.TryStar)
455453

456454
@staticmethod
457455
def Tuple(node: ast.AST) -> TypeGuard[ast.Tuple]:
@@ -460,30 +458,26 @@ def Tuple(node: ast.AST) -> TypeGuard[ast.Tuple]:
460458
@staticmethod
461459
def type_ignore(node: ast.AST) -> TypeGuard[ast.type_ignore]:
462460
return isinstance(node, ast.type_ignore)
463-
if sys.version_info >= (3, 12):
464461

465-
@staticmethod
466-
def type_param(node: ast.AST) -> TypeGuard[ast.type_param]:
467-
return isinstance(node, ast.type_param)
468-
if sys.version_info >= (3, 12):
462+
@staticmethod
463+
def type_param(node: ast.AST) -> TypeGuard[ast.type_param]:
464+
return isinstance(node, ast.type_param)
469465

470-
@staticmethod
471-
def TypeAlias(node: ast.AST) -> TypeGuard[ast.TypeAlias]:
472-
return isinstance(node, ast.TypeAlias)
466+
@staticmethod
467+
def TypeAlias(node: ast.AST) -> TypeGuard[ast.TypeAlias]:
468+
return isinstance(node, ast.TypeAlias)
473469

474470
@staticmethod
475471
def TypeIgnore(node: ast.AST) -> TypeGuard[ast.TypeIgnore]:
476472
return isinstance(node, ast.TypeIgnore)
477-
if sys.version_info >= (3, 12):
478473

479-
@staticmethod
480-
def TypeVar(node: ast.AST) -> TypeGuard[ast.TypeVar]:
481-
return isinstance(node, ast.TypeVar)
482-
if sys.version_info >= (3, 12):
474+
@staticmethod
475+
def TypeVar(node: ast.AST) -> TypeGuard[ast.TypeVar]:
476+
return isinstance(node, ast.TypeVar)
483477

484-
@staticmethod
485-
def TypeVarTuple(node: ast.AST) -> TypeGuard[ast.TypeVarTuple]:
486-
return isinstance(node, ast.TypeVarTuple)
478+
@staticmethod
479+
def TypeVarTuple(node: ast.AST) -> TypeGuard[ast.TypeVarTuple]:
480+
return isinstance(node, ast.TypeVarTuple)
487481

488482
@staticmethod
489483
def UAdd(node: ast.AST) -> TypeGuard[ast.UAdd]:

astToolkit/_toolClassIsAndAttribute.py

Lines changed: 19 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -121,14 +121,13 @@ def bodyIs(astClass: type[hasDOTbody], attributeCondition: Callable[[ast.expr],
121121
def workhorse(node: ast.AST) -> TypeGuard[hasDOTbody] | bool:
122122
return isinstance(node, astClass) and attributeCondition(node.body)
123123
return workhorse
124-
if sys.version_info >= (3, 12):
125124

126-
@staticmethod
127-
def boundIs(astClass: type[hasDOTbound], attributeCondition: Callable[[ast.expr | None], bool]) -> Callable[[ast.AST], TypeGuard[hasDOTbound] | bool]:
125+
@staticmethod
126+
def boundIs(astClass: type[hasDOTbound], attributeCondition: Callable[[ast.expr | None], bool]) -> Callable[[ast.AST], TypeGuard[hasDOTbound] | bool]:
128127

129-
def workhorse(node: ast.AST) -> TypeGuard[hasDOTbound] | bool:
130-
return isinstance(node, astClass) and node.bound is not None and attributeCondition(node.bound)
131-
return workhorse
128+
def workhorse(node: ast.AST) -> TypeGuard[hasDOTbound] | bool:
129+
return isinstance(node, astClass) and node.bound is not None and attributeCondition(node.bound)
130+
return workhorse
132131

133132
@staticmethod
134133
def casesIs(astClass: type[hasDOTcases], attributeCondition: Callable[[list[ast.match_case]], bool]) -> Callable[[ast.AST], TypeGuard[hasDOTcases] | bool]:
@@ -413,12 +412,11 @@ def msgIs(astClass: type[hasDOTmsg], attributeCondition: Callable[[ast.expr | No
413412
def workhorse(node: ast.AST) -> TypeGuard[hasDOTmsg] | bool:
414413
return isinstance(node, astClass) and node.msg is not None and attributeCondition(node.msg)
415414
return workhorse
416-
if sys.version_info >= (3, 12):
417415

418-
@staticmethod
419-
@overload
420-
def nameIs(astClass: type[hasDOTname_Name], attributeCondition: Callable[[ast.Name], bool]) -> Callable[[ast.AST], TypeGuard[hasDOTname_Name] | bool]:
421-
...
416+
@staticmethod
417+
@overload
418+
def nameIs(astClass: type[hasDOTname_Name], attributeCondition: Callable[[ast.Name], bool]) -> Callable[[ast.AST], TypeGuard[hasDOTname_Name] | bool]:
419+
...
422420

423421
@staticmethod
424422
@overload
@@ -429,22 +427,13 @@ def nameIs(astClass: type[hasDOTname_str], attributeCondition: Callable[[str], b
429427
@overload
430428
def nameIs(astClass: type[hasDOTname_strOrNone], attributeCondition: Callable[[str | None], bool]) -> Callable[[ast.AST], TypeGuard[hasDOTname_strOrNone] | bool]:
431429
...
432-
if sys.version_info >= (3, 12):
433-
434-
@staticmethod
435-
def nameIs(astClass: type[hasDOTname], attributeCondition: Callable[[ast.Name], bool] | Callable[[str], bool] | Callable[[str | None], bool]) -> Callable[[ast.AST], TypeGuard[hasDOTname] | bool]:
436430

437-
def workhorse(node: ast.AST) -> TypeGuard[hasDOTname] | bool:
438-
return isinstance(node, astClass) and node.name is not None and attributeCondition(node.name)
439-
return workhorse
440-
else:
441-
442-
@staticmethod
443-
def nameIs(astClass: type[hasDOTname], attributeCondition: Callable[[str], bool] | Callable[[str | None], bool]) -> Callable[[ast.AST], TypeGuard[hasDOTname] | bool]:
431+
@staticmethod
432+
def nameIs(astClass: type[hasDOTname], attributeCondition: Callable[[ast.Name], bool] | Callable[[str], bool] | Callable[[str | None], bool]) -> Callable[[ast.AST], TypeGuard[hasDOTname] | bool]:
444433

445-
def workhorse(node: ast.AST) -> TypeGuard[hasDOTname] | bool:
446-
return isinstance(node, astClass) and node.name is not None and attributeCondition(node.name)
447-
return workhorse
434+
def workhorse(node: ast.AST) -> TypeGuard[hasDOTname] | bool:
435+
return isinstance(node, astClass) and node.name is not None and attributeCondition(node.name)
436+
return workhorse
448437

449438
@staticmethod
450439
@overload
@@ -676,14 +665,13 @@ def type_ignoresIs(astClass: type[hasDOTtype_ignores], attributeCondition: Calla
676665
def workhorse(node: ast.AST) -> TypeGuard[hasDOTtype_ignores] | bool:
677666
return isinstance(node, astClass) and attributeCondition(node.type_ignores)
678667
return workhorse
679-
if sys.version_info >= (3, 12):
680668

681-
@staticmethod
682-
def type_paramsIs(astClass: type[hasDOTtype_params], attributeCondition: Callable[[list[ast.type_param]], bool]) -> Callable[[ast.AST], TypeGuard[hasDOTtype_params] | bool]:
669+
@staticmethod
670+
def type_paramsIs(astClass: type[hasDOTtype_params], attributeCondition: Callable[[list[ast.type_param]], bool]) -> Callable[[ast.AST], TypeGuard[hasDOTtype_params] | bool]:
683671

684-
def workhorse(node: ast.AST) -> TypeGuard[hasDOTtype_params] | bool:
685-
return isinstance(node, astClass) and attributeCondition(node.type_params)
686-
return workhorse
672+
def workhorse(node: ast.AST) -> TypeGuard[hasDOTtype_params] | bool:
673+
return isinstance(node, astClass) and attributeCondition(node.type_params)
674+
return workhorse
687675

688676
@staticmethod
689677
def upperIs(astClass: type[hasDOTupper], attributeCondition: Callable[[ast.expr | None], bool]) -> Callable[[ast.AST], TypeGuard[hasDOTupper] | bool]:

0 commit comments

Comments
 (0)