Skip to content

Commit 3a1be67

Browse files
committed
adding Buildtests step
1 parent fd3ecb5 commit 3a1be67

3 files changed

Lines changed: 174 additions & 30 deletions

File tree

builder-tool/pack.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,18 @@
11
from src.builderTool import BaseBuilder, Logger, PYTHON, NULL_TARGET #this file use the module to build itself
2-
import shutil
32

43

54
class Builder(BaseBuilder):
65
def Setup(self):
7-
Logger.debug('Copying sources')
8-
shutil.copytree('src', self.tempDir + '/src', ignore=shutil.ignore_patterns('*.pyc', '*.pyo', '__pycache__'))
9-
Logger.debug('Copying pyproject.toml')
10-
self.CopyAndReplaceByPackageVersion('pyproject.toml', self.tempDir + '/pyproject.toml')
11-
Logger.debug('Copying requirements.txt')
12-
shutil.copy('requirements.txt', self.tempDir + '/requirements.txt')
13-
Logger.debug('Copying readme.md')
14-
self.CopyAndReplaceByPackageVersion('readme.md', self.tempDir + '/readme.md')
6+
self.addDirectory('src')
7+
self.addAndReplaceByPackageVersion('pyproject.toml', self.tempDir + '/pyproject.toml')
8+
self.addFile("requirements.txt")
9+
self.addAndReplaceByPackageVersion('readme.md', self.tempDir + '/readme.md')
1510

1611

1712
def Build(self):
1813
self.runCommand(f'{PYTHON} -m build --outdir {self.distDir} {self.tempDir} > {NULL_TARGET}')
19-
14+
15+
def Publish(self):
16+
Logger.info("Publishing package")
2017

2118
BaseBuilder.execute()

builder-tool/src/builderTool.py

Lines changed: 81 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
os.system(f'{sys.executable} -m pip install https://github.com/GamuNetwork/logger/releases/download/2.0.0-alpha.4/gamu_logger-2.0.0a4-py3-none-any.whl > {NULL_TARGET} 2> {NULL_TARGET}')
1616
print("done")
1717
from gamuLogger import Logger, LEVELS, debugFunc
18+
19+
Logger.setModule('Builder')
1820

1921
class BaseBuilder:
2022
"""
@@ -49,20 +51,27 @@ class Status(Enum):
4951

5052
def __str__(self):
5153
return self.name
54+
55+
class RequireMode(Enum):
56+
OPTIONAL = 0
57+
REQUIRED = 1
58+
59+
def __str__(self):
60+
return self.name
5261

5362
def __init__(self):
5463
if self.__class__ == BaseBuilder:
5564
raise Exception('BaseBuilder is an abstract class and cannot be instantiated')
5665

5766
self.argumentParser = argparse.ArgumentParser(description='Builder tool')
5867

59-
loggerOptions = self.argumentParser.add_argument_group('Logger options')
68+
loggerOptions = self.argumentParser.add_mutually_exclusive_group()
6069
loggerOptions.add_argument('--debug', action='store_true', help='Enable debug messages')
70+
loggerOptions.add_argument('--deep-debug', action='store_true', help='Enable deep debug messages')
6171

6272
buildersOptions = self.argumentParser.add_argument_group('Builder options')
6373
buildersOptions.add_argument('--no-tests', action='store_true', help='Do not run tests')
6474
buildersOptions.add_argument('--no-docs', action='store_true', help='Do not generate documentation')
65-
buildersOptions.add_argument('--no-build', action='store_true', help='Do not build the package')
6675
buildersOptions.add_argument('--publish', action='store_true', help='Publish the package')
6776
buildersOptions.add_argument('--no-clean', action='store_true', help='Do not clean temporary files')
6877
buildersOptions.add_argument('--temp-dir', help='Temporary directory (used to generate the package)', type=str, default=mkdtemp())
@@ -74,27 +83,45 @@ def __init__(self):
7483
self.args = self.argumentParser.parse_args()
7584

7685
self.__steps = {
77-
"Setup": self.Status.WAITING,
78-
"Build": self.Status.DISABLED if self.args.no_build else self.Status.WAITING,
79-
"Tests": self.Status.DISABLED if self.args.no_tests else self.Status.WAITING,
80-
"Docs": self.Status.DISABLED if self.args.no_docs else self.Status.WAITING,
81-
"Publish": self.Status.WAITING if self.args.publish else self.Status.DISABLED
86+
"Setup": self.Status.WAITING,
87+
"Build": self.Status.WAITING,
88+
"Tests": self.Status.DISABLED if self.args.no_tests else self.Status.WAITING,
89+
"BuildTests" : self.Status.DISABLED if self.args.no_tests else self.Status.WAITING,
90+
"Docs": self.Status.DISABLED if self.args.no_docs else self.Status.WAITING,
91+
"Publish": self.Status.WAITING if self.args.publish else self.Status.DISABLED
8292
}
8393

8494
self.clean = not self.args.no_clean
8595

8696
self.__remainingSteps = len([step for step in self.__steps if self.__steps[step] != self.Status.DISABLED])
8797

8898
self.__stepDependencies = {
89-
"Setup": [],
90-
"Build": ["Setup"],
91-
"Docs": ["Setup"],
92-
"Tests": ["Setup", "Build"],
93-
"Publish": ["Setup", "Build", "Tests", "Docs"]
94-
}
99+
"Setup": {},
100+
"Build": {
101+
"Setup" : self.RequireMode.REQUIRED,
102+
"Tests" : self.RequireMode.OPTIONAL
103+
},
104+
"Docs": {
105+
"Setup" : self.RequireMode.REQUIRED
106+
},
107+
"Tests": {
108+
"Setup" : self.RequireMode.REQUIRED
109+
},
110+
"BuildTests": {
111+
"Setup" : self.RequireMode.REQUIRED,
112+
"Build" : self.RequireMode.REQUIRED
113+
},
114+
"Publish": {
115+
"Build" : self.RequireMode.REQUIRED,
116+
"BuildTests" : self.RequireMode.OPTIONAL,
117+
"Docs" : self.RequireMode.OPTIONAL
118+
}
119+
} #type: dict[str, dict[str, BaseBuilder.RequireMode]]
95120

96121
if self.args.debug:
97122
Logger.setLevel('stdout', LEVELS.DEBUG)
123+
elif self.args.deep_debug:
124+
Logger.setLevel('stdout', LEVELS.DEEP_DEBUG)
98125

99126

100127
Logger.debug('Using temporary directory: ' + os.path.abspath(self.args.temp_dir))
@@ -112,7 +139,8 @@ def packageVersion(self):
112139
def distDir(self):
113140
return os.path.abspath(self.args.dist_dir)
114141

115-
def CopyAndReplaceByPackageVersion(self, src, dst, versionString = "{version}"):
142+
def addAndReplaceByPackageVersion(self, src, dst, versionString = "{version}"):
143+
Logger.debug('Adding file: ' + src + ' and replacing version string by ' + self.packageVersion)
116144
with open(src, 'r') as file:
117145
content = file.read()
118146
content = content.replace(versionString, self.packageVersion)
@@ -140,6 +168,18 @@ def runCommand(self, command) -> bool:
140168
os.remove(stderrPath)
141169
return True
142170

171+
def addFile(self, path, dest = None):
172+
Logger.debug('Adding file: ' + path)
173+
if dest is None:
174+
dest = path
175+
shutil.copy(path, self.tempDir + '/' + dest)
176+
177+
def addDirectory(self, path, dest = None):
178+
Logger.debug('Adding directory: ' + path)
179+
if dest is None:
180+
dest = path
181+
shutil.copytree(path, self.tempDir + '/' + dest, ignore=shutil.ignore_patterns('*.pyc', '*.pyo', '__pycache__'))
182+
143183

144184
def __clean(self) -> bool:
145185
Logger.info('Cleaning temporary directory')
@@ -152,13 +192,32 @@ def __clean(self) -> bool:
152192
Logger.debug('Temporary directory cleaned')
153193
return True
154194

155-
195+
156196
def __canStepBeStarted(self, step):
157-
for dependency in self.__stepDependencies[step]:
158-
if self.__steps[dependency] != self.Status.FINISHED:
159-
return False
197+
# a better version of the previous function
198+
for dependency, requireMode in self.__stepDependencies[step].items():
199+
match self.__steps[dependency]:
200+
case self.Status.WAITING:
201+
Logger.deepDebug(f"The step '{step}' cannot be started because the dependency '{dependency}' is not started yet")
202+
return False
203+
case self.Status.RUNNING:
204+
Logger.deepDebug(f"The step '{step}' cannot be started because the dependency '{dependency}' is running and need to finish first")
205+
return False
206+
case self.Status.FAILED:
207+
Logger.deepDebug(f"The step '{step}' cannot be started because the dependency '{dependency}' has failed")
208+
return False
209+
case self.Status.DISABLED:
210+
if requireMode == self.RequireMode.REQUIRED:
211+
Logger.deepDebug(f"The step '{step}' cannot be started because the dependency '{dependency}' is disabled but required")
212+
return False
213+
else:
214+
Logger.deepDebug(f"The step '{step}' will run without the optional dependency '{dependency}'")
215+
continue
216+
case self.Status.FINISHED:
217+
continue
160218
return True
161219

220+
162221
def __runStep(self, step : str):
163222
'''
164223
A step is considered failed if it raises an exception, or if it returns False
@@ -177,20 +236,22 @@ def __runStep(self, step : str):
177236

178237
def __run(self, configuredSteps : list[str]):
179238
for step in self.__steps:
180-
if step not in configuredSteps and step != '__clean':
239+
if step not in configuredSteps:
181240
self.__steps[step] = self.Status.DISABLED
182241
self.__remainingSteps -= 1
183242
Logger.debug('Step "' + step + '" disabled')
184243

185244

186245
HasFailed = False
187246
while self.__remainingSteps > 0 and not HasFailed:
247+
Logger.deepDebug("Remaining steps: " + str(self.__remainingSteps))
188248
for step in self.__steps:
189249
if self.__steps[step] == self.Status.WAITING and self.__canStepBeStarted(step):
190250
Logger.info('Starting step "' + step + '"')
191251
self.__steps[step] = self.Status.RUNNING
192252

193253
hasSucceeded = self.__runStep(step)
254+
Logger.deepDebug('Step "' + step + '" returned ' + str(hasSucceeded))
194255

195256
if hasSucceeded:
196257
self.__steps[step] = self.Status.FINISHED
@@ -221,7 +282,7 @@ def execute():
221282
Logger.critical('Multiple builders found')
222283
sys.exit(1)
223284

224-
possibleSteps = ['Setup', 'Tests', 'Docs', 'Build', 'Publish']
285+
possibleSteps = ['Setup', 'Tests', 'BuildTests', 'Docs', 'Build', 'Publish']
225286
steps = [step for step in subClasses[0].__dict__ if step in possibleSteps]
226287
subClasses[0]().__run(steps)
227288

builder-tool/stepDeps.drawio

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<mxfile host="65bd71144e">
2+
<diagram id="hNHtbLPrV3ga_JxnJnNU" name="Page-1">
3+
<mxGraphModel dx="267" dy="159" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
4+
<root>
5+
<mxCell id="0"/>
6+
<mxCell id="1" parent="0"/>
7+
<mxCell id="2" value="Setup" style="html=1;points=[[0,0,0,0,0],[0,0.25,0,0,0],[0,0.5,0,0,0],[0,0.75,0,0,0],[0,1,0,0,0],[0.25,0,0,0,0],[0.33,1,0,0,0],[0.5,0,0,0,0],[0.67,1,0,0,0],[0.75,0,0,0,0],[1,0,0,0,0],[1,0.25,0,0,0],[1,0.5,0,0,0],[1,0.75,0,0,0],[1,1,0,0,0]];" vertex="1" parent="1">
8+
<mxGeometry x="360" y="80" width="120" height="40" as="geometry"/>
9+
</mxCell>
10+
<mxCell id="11" style="edgeStyle=none;html=1;exitX=0.33;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;dashed=1;exitPerimeter=0;" edge="1" parent="1" source="3" target="5">
11+
<mxGeometry relative="1" as="geometry">
12+
<Array as="points">
13+
<mxPoint x="350" y="280"/>
14+
<mxPoint x="330" y="280"/>
15+
</Array>
16+
</mxGeometry>
17+
</mxCell>
18+
<mxCell id="12" style="edgeStyle=none;html=1;exitX=0.75;exitY=0;exitDx=0;exitDy=0;entryX=0.33;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;exitPerimeter=0;" edge="1" parent="1" source="3" target="2">
19+
<mxGeometry relative="1" as="geometry">
20+
<Array as="points"/>
21+
</mxGeometry>
22+
</mxCell>
23+
<mxCell id="21" style="edgeStyle=none;html=1;exitX=0.33;exitY=1;exitDx=0;exitDy=0;entryX=0.25;entryY=0;entryDx=0;entryDy=0;startArrow=classic;startFill=1;endArrow=none;endFill=0;exitPerimeter=0;" edge="1" parent="1" source="3" target="7">
24+
<mxGeometry relative="1" as="geometry">
25+
<Array as="points">
26+
<mxPoint x="350" y="520"/>
27+
<mxPoint x="390" y="520"/>
28+
</Array>
29+
</mxGeometry>
30+
</mxCell>
31+
<mxCell id="3" value="Build" style="html=1;points=[[0,0,0,0,0],[0,0.25,0,0,0],[0,0.5,0,0,0],[0,0.75,0,0,0],[0,1,0,0,0],[0.25,0,0,0,0],[0.25,1,0,0,0],[0.75,0,0,0,0],[0.75,1,0,0,0],[1,0,0,0,0],[1,0.25,0,0,0],[1,0.5,0,0,0],[1,0.75,0,0,0],[1,1,0,0,0]];" vertex="1" parent="1">
32+
<mxGeometry x="310" y="320" width="120" height="40" as="geometry"/>
33+
</mxCell>
34+
<mxCell id="8" style="edgeStyle=none;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=1;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="4" target="2">
35+
<mxGeometry relative="1" as="geometry">
36+
<Array as="points">
37+
<mxPoint x="520" y="160"/>
38+
<mxPoint x="480" y="160"/>
39+
</Array>
40+
</mxGeometry>
41+
</mxCell>
42+
<mxCell id="4" value="Docs" style="html=1;dashed=1;" vertex="1" parent="1">
43+
<mxGeometry x="460" y="200" width="120" height="40" as="geometry"/>
44+
</mxCell>
45+
<mxCell id="9" style="edgeStyle=none;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="5" target="2">
46+
<mxGeometry relative="1" as="geometry">
47+
<Array as="points">
48+
<mxPoint x="330" y="160"/>
49+
<mxPoint x="360" y="160"/>
50+
</Array>
51+
</mxGeometry>
52+
</mxCell>
53+
<mxCell id="5" value="Tests" style="html=1;dashed=1;" vertex="1" parent="1">
54+
<mxGeometry x="270" y="200" width="120" height="40" as="geometry"/>
55+
</mxCell>
56+
<mxCell id="13" style="edgeStyle=none;html=1;exitX=0.33;exitY=0;exitDx=0;exitDy=0;entryX=0.75;entryY=1;entryDx=0;entryDy=0;exitPerimeter=0;entryPerimeter=0;" edge="1" parent="1" source="6" target="3">
57+
<mxGeometry relative="1" as="geometry"/>
58+
</mxCell>
59+
<mxCell id="14" style="edgeStyle=none;html=1;exitX=0.67;exitY=0;exitDx=0;exitDy=0;entryX=0.67;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;exitPerimeter=0;" edge="1" parent="1" source="6" target="2">
60+
<mxGeometry relative="1" as="geometry">
61+
<Array as="points"/>
62+
</mxGeometry>
63+
</mxCell>
64+
<mxCell id="19" style="edgeStyle=none;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;dashed=1;startArrow=classic;startFill=1;endArrow=none;endFill=0;" edge="1" parent="1" source="6" target="7">
65+
<mxGeometry relative="1" as="geometry">
66+
<Array as="points"/>
67+
</mxGeometry>
68+
</mxCell>
69+
<mxCell id="6" value="BuildTests" style="html=1;dashed=1;points=[[0,0,0,0,0],[0,0.25,0,0,0],[0,0.5,0,0,0],[0,0.75,0,0,0],[0,1,0,0,0],[0.25,1,0,0,0],[0.33,0,0,0,0],[0.5,1,0,0,0],[0.67,0,0,0,0],[0.75,1,0,0,0],[1,0,0,0,0],[1,0.25,0,0,0],[1,0.5,0,0,0],[1,0.75,0,0,0],[1,1,0,0,0]];" vertex="1" parent="1">
70+
<mxGeometry x="360" y="440" width="120" height="40" as="geometry"/>
71+
</mxCell>
72+
<mxCell id="17" style="edgeStyle=none;html=1;exitX=0.75;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;dashed=1;" edge="1" parent="1" source="7" target="4">
73+
<mxGeometry relative="1" as="geometry">
74+
<Array as="points">
75+
<mxPoint x="450" y="520"/>
76+
<mxPoint x="520" y="520"/>
77+
</Array>
78+
</mxGeometry>
79+
</mxCell>
80+
<mxCell id="7" value="Publish&lt;br&gt;(disabled by default)" style="html=1;dashed=1;" vertex="1" parent="1">
81+
<mxGeometry x="360" y="560" width="120" height="40" as="geometry"/>
82+
</mxCell>
83+
</root>
84+
</mxGraphModel>
85+
</diagram>
86+
</mxfile>

0 commit comments

Comments
 (0)