Skip to content

Commit a6ff3c6

Browse files
committed
writeClass: consolidation and convergence
1 parent faa955b commit a6ff3c6

5 files changed

Lines changed: 156 additions & 181 deletions

File tree

toolFactory/Z0Z_hardcoded.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@
1919
class FREAKOUT(Exception):
2020
pass
2121

22+
listPylanceErrors: list[str] = ['annotation', 'arg', 'args', 'body', 'keys', 'name', 'names', 'op', 'orelse', 'pattern', 'returns', 'target', 'value',]
23+
2224
# filesystem and namespace ===============================================
2325
packageName: str = 'astToolkit'
24-
moduleIdentifierPrefix: str = '_tool'
2526
keywordArgumentsIdentifier: str = 'keywordArguments'
2627

2728
pathRoot = Path('/apps') / packageName
@@ -33,6 +34,7 @@ class FREAKOUT(Exception):
3334

3435
fileExtension: str = '.py'
3536

37+
# classmethod .join() =================================================
3638
def joinOperatorExpressions(operatorClass: type[ast.operator], expressions: Iterable[ast.expr]) -> ast.expr:
3739
"""
3840
Join AST expressions with a specified operator into a nested BinOp structure.

toolFactory/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
fileExtension as fileExtension,
44
FREAKOUT as FREAKOUT,
55
keywordArgumentsIdentifier as keywordArgumentsIdentifier,
6-
moduleIdentifierPrefix as moduleIdentifierPrefix,
76
packageName as packageName,
87
pathFilenameDatabaseAST as pathFilenameDatabaseAST,
98
pathPackage as pathPackage,

toolFactory/astFactory.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
from pathlib import PurePosixPath
22
from string import ascii_letters
33
from toolFactory import fileExtension, pathPackage, str_nameDOTname, sys_version_infoTarget
4-
from toolFactory.Z0Z_hardcoded import keywordArgumentsIdentifier, listASTClassesPostPythonVersionMinimum, moduleIdentifierPrefix
4+
from toolFactory.Z0Z_hardcoded import keywordArgumentsIdentifier, listASTClassesPostPythonVersionMinimum
55
from toolFactory._snippets import astName_overload, astName_staticmethod, astName_typing_TypeAlias
66
from toolFactory.factory_annex import (
77
FunctionDefMake_Attribute,
8-
listHandmadeMethodsGrab,
8+
FunctionDefGrab_andDoAllOf,
99
listHandmadeTypeAlias_astTypes,
1010
FunctionDefMake_Import,
1111
)
1212
from toolFactory.docstrings import ClassDefDocstringDOT, ClassDefDocstringGrab, ClassDefDocstringMake, docstringWarning
1313
from typing import cast, TypedDict
1414
from Z0Z_tools import writeStringToHere
1515
import ast
16+
moduleIdentifierPrefix: str = '_tool'
17+
1618
format_asNameAttribute: str = "astDOT{nameAttribute}"
1719
astImportFromClassNewInPythonVersion: ast.ImportFrom = ast.ImportFrom('astToolkit', [], 0)
1820
listPythonVersionNewClass = [(11, ['TryStar']),
@@ -37,7 +39,7 @@
3739
conditionalTypeAlias.orelse.append(ast.AnnAssign(target=ast.Name(asNameAttribute, ast.Store()), annotation=ast.Name('typing_TypeAlias'), value=ast.Name('yourPythonIsOld'), simple=1))
3840
astImportFromClassNewInPythonVersion.names.append(ast.alias(name=asNameAttribute))
3941

40-
listHandmadeTypeAlias_astTypes.append(conditionalTypeAlias)
42+
listHandmadeTypeAlias_astTypes.append(conditionalTypeAlias) # pyright: ignore[reportArgumentType]
4143

4244

4345
"""
@@ -508,7 +510,7 @@ def list2Sequence():
508510
ClassDefGrab.body.insert(0, ClassDefDocstringGrab)
509511
ClassDefMake.body.insert(0, ClassDefDocstringMake)
510512

511-
ClassDefGrab.body.extend(listHandmadeMethodsGrab)
513+
ClassDefGrab.body.extend([FunctionDefGrab_andDoAllOf])
512514

513515
ClassDef = ClassDefClassIsAndAttribute
514516
writeModule(ast.Module(

toolFactory/factory3.py

Lines changed: 115 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,20 @@
77
astName_typing_TypeAlias,
88
fileExtension,
99
getElementsBe,
10+
getElementsDOT,
11+
getElementsGrab,
12+
getElementsMake,
1013
getElementsTypeAlias,
1114
keywordArgumentsIdentifier,
12-
moduleIdentifierPrefix,
1315
pathPackage,
1416
pythonVersionMinorMinimum,
15-
getElementsMake,
16-
getElementsDOT,
1717
)
18+
from toolFactory.Z0Z_hardcoded import listPylanceErrors
1819
from toolFactory.factory_annex import (
20+
FunctionDefGrab_andDoAllOf,
1921
FunctionDefMake_Attribute,
2022
FunctionDefMake_Import,
21-
listHandmadeMethodsGrab,
2223
listHandmadeTypeAlias_astTypes,
23-
listPylanceErrors,
2424
)
2525
from toolFactory.docstrings import ClassDefDocstringBe, ClassDefDocstringMake, docstringWarning, ClassDefDocstringDOT
2626
from typing import cast
@@ -73,73 +73,19 @@ def writeModule(astModule: ast.Module, moduleIdentifier: str) -> None:
7373
pathFilenameModule = PurePosixPath(pathPackage, moduleIdentifier + fileExtension)
7474
writeStringToHere(pythonSource, pathFilenameModule)
7575

76-
def makeTypeAlias():
77-
def Z0Z_getTypeAliasSubcategory():
78-
if len(dictionaryVersions) == 1:
79-
for versionMinor, listClassAs_astAttribute in dictionaryVersions.items():
80-
ast_stmt = ast.AnnAssign(astNameTypeAlias, astName_typing_TypeAlias, ast.BitOr.join([eval(classAs_astAttribute) for classAs_astAttribute in listClassAs_astAttribute]), 1) # pyright: ignore[reportAttributeAccessIssue]
81-
if versionMinor > pythonVersionMinorMinimum:
82-
ast_stmt = ast.If(ast.Compare(ast.Attribute(ast.Name('sys'), 'version_info')
83-
, ops=[ast.GtE()]
84-
, comparators=[ast.Tuple([ast.Constant(3),
85-
ast.Constant(versionMinor)])])
86-
, body=[ast_stmt])
87-
# This branch is the simplest case: one TypeAlias for the attribute for all Python versions
88-
astTypesModule.body.append(ast_stmt)
89-
else:
90-
# There is a smart way to do the following, but I don't see it right now. NOTE datacenter has the responsibility to aggregate all values <= pythonVersionMinorMinimum.
91-
listVersionsMinor = sorted(dictionaryVersions.keys(), reverse=False)
92-
if len(listVersionsMinor) > 2:
93-
raise NotImplementedError("Hunter's code can't handle this.")
94-
ast_stmtAtPythonMinimum = ast.AnnAssign(astNameTypeAlias, astName_typing_TypeAlias, ast.BitOr.join([eval(classAs_astAttribute) for classAs_astAttribute in dictionaryVersions[min(listVersionsMinor)]]), 1) # pyright: ignore[reportAttributeAccessIssue]
95-
ast_stmtAbovePythonMinimum = ast.AnnAssign(astNameTypeAlias, astName_typing_TypeAlias, ast.BitOr.join([eval(classAs_astAttribute) for classAs_astAttribute in sorted(chain(*dictionaryVersions.values()), key=str.lower)]), 1) # pyright: ignore[reportAttributeAccessIssue]
96-
97-
ast_stmt = ast.If(ast.Compare(ast.Attribute(ast.Name('sys'), 'version_info')
98-
, ops=[ast.GtE()]
99-
, comparators=[ast.Tuple([ast.Constant(3),
100-
ast.Constant(max(listVersionsMinor))])])
101-
, body=[ast_stmtAbovePythonMinimum]
102-
, orelse=[ast_stmtAtPythonMinimum])
103-
astTypesModule.body.append(ast_stmt)
104-
105-
astTypesModule = ast.Module(
106-
body=[docstringWarning
107-
, ast.ImportFrom('typing', [ast.alias('Any'), ast.alias('TypeAlias', 'typing_TypeAlias')], 0)
108-
, ast.Import([ast.alias('ast')])
109-
, ast.Import([ast.alias('sys')])
110-
, *listHandmadeTypeAlias_astTypes
111-
]
112-
, type_ignores=[]
113-
)
114-
115-
typeAliasData: dict[str, dict[str, dict[int, list[str]]]] = getElementsTypeAlias()
116-
117-
for attribute, dictionaryAttribute in typeAliasData.items():
118-
hasDOTIdentifier: str = 'hasDOT' + attribute
119-
hasDOTTypeAliasName_Load: ast.Name = ast.Name(hasDOTIdentifier)
120-
hasDOTTypeAliasName_Store: ast.Name = ast.Name(hasDOTIdentifier, ast.Store())
121-
122-
if len(dictionaryAttribute) == 1:
123-
astNameTypeAlias = hasDOTTypeAliasName_Store
124-
for TypeAliasSubcategory, dictionaryVersions in dictionaryAttribute.items():
125-
Z0Z_getTypeAliasSubcategory()
126-
else:
127-
# See?! Sometimes, I can see a smart way to do things. This defaultdict builds a dictionary to mimic the
128-
# process I'm already using to build the TypeAlias.
129-
attributeDictionaryVersions: dict[int, list[str]] = defaultdict(list)
130-
for TypeAliasSubcategory, dictionaryVersions in dictionaryAttribute.items():
131-
astNameTypeAlias: ast.Name = ast.Name(hasDOTIdentifier + '_' + TypeAliasSubcategory, ast.Store())
132-
if any(dictionaryVersions.keys()) <= pythonVersionMinorMinimum:
133-
attributeDictionaryVersions[min(dictionaryVersions.keys())].append(ast.dump(astNameTypeAlias))
134-
else:
135-
attributeDictionaryVersions[min(dictionaryVersions.keys())].append(ast.dump(astNameTypeAlias))
136-
attributeDictionaryVersions[max(dictionaryVersions.keys())].append(ast.dump(astNameTypeAlias))
137-
Z0Z_getTypeAliasSubcategory()
138-
astNameTypeAlias = hasDOTTypeAliasName_Store
139-
dictionaryVersions: dict[int, list[str]] = attributeDictionaryVersions
140-
Z0Z_getTypeAliasSubcategory()
141-
142-
writeModule(astTypesModule, '_astTypes')
76+
def writeClass(classIdentifier: str, list4ClassDefBody: list[ast.stmt], list4ModuleBody: list[ast.stmt], moduleIdentifierPrefix: str | None = '_tool') -> None:
77+
if moduleIdentifierPrefix:
78+
moduleIdentifier = moduleIdentifierPrefix + classIdentifier
79+
else:
80+
moduleIdentifier = classIdentifier
81+
return writeModule(ast.Module(
82+
body=[docstringWarning
83+
, *list4ModuleBody
84+
, ast.ClassDef(name=classIdentifier, bases=[], keywords=[], body=list4ClassDefBody, decorator_list=[])
85+
]
86+
, type_ignores=[]
87+
)
88+
, moduleIdentifier)
14389

14490
def makeToolBe():
14591
list4ClassDefBody: list[ast.stmt] = [ClassDefDocstringBe]
@@ -167,20 +113,13 @@ def makeToolBe():
167113

168114
list4ClassDefBody.append(ast_stmt)
169115

170-
ClassDefBe = ast.ClassDef(name='Be', bases=[], keywords=[], body=list4ClassDefBody, decorator_list=[])
116+
list4ModuleBody: list[ast.stmt] = [
117+
ast.ImportFrom('typing', [ast.alias('TypeGuard')], 0)
118+
, ast.Import([ast.alias('ast')])
119+
, ast.Import([ast.alias('sys')])
120+
]
171121

172-
ClassDef = ClassDefBe
173-
writeModule(ast.Module(
174-
body=[docstringWarning
175-
, ast.ImportFrom('typing', [ast.alias('TypeGuard')], 0)
176-
, ast.Import([ast.alias('ast')])
177-
, ast.Import([ast.alias('sys')])
178-
, ClassDef
179-
],
180-
type_ignores=[]
181-
)
182-
, moduleIdentifierPrefix + ClassDef.name)
183-
del ClassDef
122+
writeClass('Be', list4ClassDefBody, list4ModuleBody)
184123

185124
def makeToolDOT():
186125
list4ClassDefBody: list[ast.stmt] = [ClassDefDocstringDOT]
@@ -229,26 +168,33 @@ def makeToolDOT():
229168

230169
list4ClassDefBody.append(ast_stmt)
231170

232-
ClassDefDOT = ast.ClassDef(name='DOT', bases=[], keywords=[], body=list4ClassDefBody, decorator_list=[])
233-
234-
ClassDef = ClassDefDOT
235-
writeModule(ast.Module(
236-
body=[docstringWarning
171+
list4ModuleBody: list[ast.stmt] = [docstringWarning
237172
, ast.ImportFrom(module='astToolkit', names=[ast.alias(name='ast_Identifier'), ast.alias(name='ast_expr_Slice'), ast.alias(name='astDOTtype_param')], level=0)
238173
, ast.ImportFrom(module='astToolkit._astTypes', names=[ast.alias(name='*')], level=0)
239174
, ast.ImportFrom(module='collections.abc', names=[ast.alias(name='Sequence')], level=0)
240175
, ast.ImportFrom(module='typing', names=[ast.alias(name='Any'), ast.alias(name='Literal'), ast.alias(name='overload')], level=0)
241176
, ast.Import(names=[ast.alias(name='ast')])
242177
, ast.Import(names=[ast.alias(name='sys')])
243-
, ClassDef
244-
],
245-
type_ignores=[]
246-
)
247-
, moduleIdentifierPrefix + ClassDef.name)
248-
del ClassDef
178+
]
179+
180+
writeClass('DOT', list4ClassDefBody, list4ModuleBody)
249181

250182
def makeToolGrab():
251-
pass
183+
list4ClassDefBody: list[ast.stmt] = [ClassDefDocstringBe]
184+
dictionaryToolElements: dict[str, dict[str, int]] = getElementsGrab()
185+
186+
for attribute, dictionaryAttribute in dictionaryToolElements.items():
187+
hasDOTIdentifier: str = 'hasDOT' + attribute
188+
hasDOTTypeAliasName_Load: ast.Name = ast.Name(hasDOTIdentifier)
189+
hasDOTTypeAliasName_Store: ast.Name = ast.Name(hasDOTIdentifier, ast.Store())
190+
191+
list4ModuleBody: list[ast.stmt] = [
192+
ast.ImportFrom('typing', [ast.alias('TypeGuard')], 0)
193+
, ast.Import([ast.alias('ast')])
194+
, ast.Import([ast.alias('sys')])
195+
]
196+
197+
writeClass('Grab', list4ClassDefBody, list4ModuleBody)
252198

253199
def makeToolMake():
254200
list4ClassDefBody: list[ast.stmt] = [ClassDefDocstringMake]
@@ -280,22 +226,83 @@ def makeToolMake():
280226

281227
list4ClassDefBody.append(ast_stmt)
282228

283-
ClassDefMake = ast.ClassDef(name='Make', bases=[], keywords=[], body=list4ClassDefBody, decorator_list=[])
229+
list4ModuleBody: list[ast.stmt] = [
230+
ast.ImportFrom('typing', [ast.alias('TypeGuard')], 0)
231+
, ast.Import([ast.alias('ast')])
232+
, ast.Import([ast.alias('sys')])
233+
]
234+
235+
writeClass('Make', list4ClassDefBody, list4ModuleBody)
236+
237+
def makeTypeAlias():
238+
def Z0Z_getTypeAliasSubcategory():
239+
if len(dictionaryVersions) == 1:
240+
for versionMinor, listClassAs_astAttribute in dictionaryVersions.items():
241+
ast_stmt = ast.AnnAssign(astNameTypeAlias, astName_typing_TypeAlias, ast.BitOr.join([eval(classAs_astAttribute) for classAs_astAttribute in listClassAs_astAttribute]), 1) # pyright: ignore[reportAttributeAccessIssue]
242+
if versionMinor > pythonVersionMinorMinimum:
243+
ast_stmt = ast.If(ast.Compare(ast.Attribute(ast.Name('sys'), 'version_info')
244+
, ops=[ast.GtE()]
245+
, comparators=[ast.Tuple([ast.Constant(3),
246+
ast.Constant(versionMinor)])])
247+
, body=[ast_stmt])
248+
# This branch is the simplest case: one TypeAlias for the attribute for all Python versions
249+
astTypesModule.body.append(ast_stmt)
250+
else:
251+
# There is a smart way to do the following, but I don't see it right now. NOTE datacenter has the responsibility to aggregate all values <= pythonVersionMinorMinimum.
252+
listVersionsMinor = sorted(dictionaryVersions.keys(), reverse=False)
253+
if len(listVersionsMinor) > 2:
254+
raise NotImplementedError("Hunter's code can't handle this.")
255+
ast_stmtAtPythonMinimum = ast.AnnAssign(astNameTypeAlias, astName_typing_TypeAlias, ast.BitOr.join([eval(classAs_astAttribute) for classAs_astAttribute in dictionaryVersions[min(listVersionsMinor)]]), 1) # pyright: ignore[reportAttributeAccessIssue]
256+
ast_stmtAbovePythonMinimum = ast.AnnAssign(astNameTypeAlias, astName_typing_TypeAlias, ast.BitOr.join([eval(classAs_astAttribute) for classAs_astAttribute in sorted(chain(*dictionaryVersions.values()), key=str.lower)]), 1) # pyright: ignore[reportAttributeAccessIssue]
284257

285-
ClassDef = ClassDefMake
286-
writeModule(ast.Module(
258+
ast_stmt = ast.If(ast.Compare(ast.Attribute(ast.Name('sys'), 'version_info')
259+
, ops=[ast.GtE()]
260+
, comparators=[ast.Tuple([ast.Constant(3),
261+
ast.Constant(max(listVersionsMinor))])])
262+
, body=[ast_stmtAbovePythonMinimum]
263+
, orelse=[ast_stmtAtPythonMinimum])
264+
astTypesModule.body.append(ast_stmt)
265+
266+
astTypesModule = ast.Module(
287267
body=[docstringWarning
288-
, ast.ImportFrom('typing', [ast.alias('TypeGuard')], 0)
268+
, ast.ImportFrom('typing', [ast.alias('Any'), ast.alias('TypeAlias', 'typing_TypeAlias')], 0)
289269
, ast.Import([ast.alias('ast')])
290270
, ast.Import([ast.alias('sys')])
291-
, ClassDef
292-
],
293-
type_ignores=[]
271+
, *listHandmadeTypeAlias_astTypes
272+
]
273+
, type_ignores=[]
294274
)
295-
, moduleIdentifierPrefix + ClassDef.name)
296-
del ClassDef
275+
276+
dictionaryToolElements: dict[str, dict[str, dict[int, list[str]]]] = getElementsTypeAlias()
277+
278+
for attribute, dictionaryAttribute in dictionaryToolElements.items():
279+
hasDOTIdentifier: str = 'hasDOT' + attribute
280+
hasDOTTypeAliasName_Load: ast.Name = ast.Name(hasDOTIdentifier)
281+
hasDOTTypeAliasName_Store: ast.Name = ast.Name(hasDOTIdentifier, ast.Store())
282+
283+
if len(dictionaryAttribute) == 1:
284+
astNameTypeAlias = hasDOTTypeAliasName_Store
285+
for TypeAliasSubcategory, dictionaryVersions in dictionaryAttribute.items():
286+
Z0Z_getTypeAliasSubcategory()
287+
else:
288+
# See?! Sometimes, I can see a smart way to do things. This defaultdict builds a dictionary to mimic the
289+
# process I'm already using to build the TypeAlias.
290+
attributeDictionaryVersions: dict[int, list[str]] = defaultdict(list)
291+
for TypeAliasSubcategory, dictionaryVersions in dictionaryAttribute.items():
292+
astNameTypeAlias: ast.Name = ast.Name(hasDOTIdentifier + '_' + TypeAliasSubcategory, ast.Store())
293+
if any(dictionaryVersions.keys()) <= pythonVersionMinorMinimum:
294+
attributeDictionaryVersions[min(dictionaryVersions.keys())].append(ast.dump(astNameTypeAlias))
295+
else:
296+
attributeDictionaryVersions[min(dictionaryVersions.keys())].append(ast.dump(astNameTypeAlias))
297+
attributeDictionaryVersions[max(dictionaryVersions.keys())].append(ast.dump(astNameTypeAlias))
298+
Z0Z_getTypeAliasSubcategory()
299+
astNameTypeAlias = hasDOTTypeAliasName_Store
300+
dictionaryVersions: dict[int, list[str]] = attributeDictionaryVersions
301+
Z0Z_getTypeAliasSubcategory()
302+
303+
writeModule(astTypesModule, '_astTypes')
297304

298305
if __name__ == "__main__":
299-
# makeToolBe()
300-
makeToolDOT()
306+
makeToolBe()
307+
# makeToolDOT()
301308
# makeTypeAlias()

0 commit comments

Comments
 (0)