pypeline-runner 1.15.0__py3-none-any.whl → 1.16.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pypeline/__init__.py +1 -1
- pypeline/bootstrap/run.py +3 -126
- pypeline/inputs_parser.py +25 -15
- pypeline/steps/create_venv.py +70 -22
- {pypeline_runner-1.15.0.dist-info → pypeline_runner-1.16.0.dist-info}/METADATA +1 -1
- {pypeline_runner-1.15.0.dist-info → pypeline_runner-1.16.0.dist-info}/RECORD +9 -9
- {pypeline_runner-1.15.0.dist-info → pypeline_runner-1.16.0.dist-info}/LICENSE +0 -0
- {pypeline_runner-1.15.0.dist-info → pypeline_runner-1.16.0.dist-info}/WHEEL +0 -0
- {pypeline_runner-1.15.0.dist-info → pypeline_runner-1.16.0.dist-info}/entry_points.txt +0 -0
pypeline/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "1.
|
|
1
|
+
__version__ = "1.16.0"
|
pypeline/bootstrap/run.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import argparse
|
|
2
2
|
import configparser
|
|
3
3
|
import ensurepip
|
|
4
|
-
import hashlib
|
|
5
4
|
import json
|
|
6
5
|
import logging
|
|
7
6
|
import os
|
|
@@ -12,7 +11,6 @@ import tempfile
|
|
|
12
11
|
import venv
|
|
13
12
|
from abc import ABC, abstractmethod
|
|
14
13
|
from dataclasses import dataclass
|
|
15
|
-
from enum import Enum
|
|
16
14
|
from functools import total_ordering
|
|
17
15
|
from pathlib import Path
|
|
18
16
|
from typing import List, Optional, Tuple
|
|
@@ -153,106 +151,6 @@ class PyPiSourceParser:
|
|
|
153
151
|
return sections
|
|
154
152
|
|
|
155
153
|
|
|
156
|
-
class Runnable(ABC):
|
|
157
|
-
@abstractmethod
|
|
158
|
-
def run(self) -> int:
|
|
159
|
-
"""Run stage."""
|
|
160
|
-
|
|
161
|
-
@abstractmethod
|
|
162
|
-
def get_name(self) -> str:
|
|
163
|
-
"""Get stage name."""
|
|
164
|
-
|
|
165
|
-
@abstractmethod
|
|
166
|
-
def get_inputs(self) -> List[Path]:
|
|
167
|
-
"""Get stage dependencies."""
|
|
168
|
-
|
|
169
|
-
@abstractmethod
|
|
170
|
-
def get_outputs(self) -> List[Path]:
|
|
171
|
-
"""Get stage outputs."""
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
class RunInfoStatus(Enum):
|
|
175
|
-
MATCH = (False, "Nothing has changed, previous execution information matches.")
|
|
176
|
-
NO_INFO = (True, "No previous execution information found.")
|
|
177
|
-
FILE_CHANGED = (True, "Dependencies have been changed.")
|
|
178
|
-
|
|
179
|
-
def __init__(self, should_run: bool, message: str) -> None:
|
|
180
|
-
self.should_run = should_run
|
|
181
|
-
self.message = message
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
class Executor:
|
|
185
|
-
"""
|
|
186
|
-
Accepts Runnable objects and executes them.
|
|
187
|
-
|
|
188
|
-
It create a file with the same name as the runnable's name
|
|
189
|
-
and stores the inputs and outputs with their hashes.
|
|
190
|
-
If the file exists, it checks the hashes of the inputs and outputs
|
|
191
|
-
and if they match, it skips the execution.
|
|
192
|
-
"""
|
|
193
|
-
|
|
194
|
-
RUN_INFO_FILE_EXTENSION = ".deps.json"
|
|
195
|
-
|
|
196
|
-
def __init__(self, cache_dir: Path) -> None:
|
|
197
|
-
self.cache_dir = cache_dir
|
|
198
|
-
|
|
199
|
-
@staticmethod
|
|
200
|
-
def get_file_hash(path: Path) -> str:
|
|
201
|
-
"""
|
|
202
|
-
Get the hash of a file.
|
|
203
|
-
|
|
204
|
-
Returns an empty string if the file does not exist.
|
|
205
|
-
"""
|
|
206
|
-
if path.is_file():
|
|
207
|
-
with open(path, "rb") as file:
|
|
208
|
-
bytes = file.read()
|
|
209
|
-
readable_hash = hashlib.sha256(bytes).hexdigest()
|
|
210
|
-
return readable_hash
|
|
211
|
-
else:
|
|
212
|
-
return ""
|
|
213
|
-
|
|
214
|
-
def store_run_info(self, runnable: Runnable) -> None:
|
|
215
|
-
file_info = {
|
|
216
|
-
"inputs": {str(path): self.get_file_hash(path) for path in runnable.get_inputs()},
|
|
217
|
-
"outputs": {str(path): self.get_file_hash(path) for path in runnable.get_outputs()},
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
run_info_path = self.get_runnable_run_info_file(runnable)
|
|
221
|
-
run_info_path.parent.mkdir(parents=True, exist_ok=True)
|
|
222
|
-
with run_info_path.open("w") as f:
|
|
223
|
-
# pretty print the json file
|
|
224
|
-
json.dump(file_info, f, indent=4)
|
|
225
|
-
|
|
226
|
-
def get_runnable_run_info_file(self, runnable: Runnable) -> Path:
|
|
227
|
-
return self.cache_dir / f"{runnable.get_name()}{self.RUN_INFO_FILE_EXTENSION}"
|
|
228
|
-
|
|
229
|
-
def previous_run_info_matches(self, runnable: Runnable) -> RunInfoStatus:
|
|
230
|
-
run_info_path = self.get_runnable_run_info_file(runnable)
|
|
231
|
-
if not run_info_path.exists():
|
|
232
|
-
return RunInfoStatus.NO_INFO
|
|
233
|
-
|
|
234
|
-
with run_info_path.open() as f:
|
|
235
|
-
previous_info = json.load(f)
|
|
236
|
-
|
|
237
|
-
for file_type in ["inputs", "outputs"]:
|
|
238
|
-
for path_str, previous_hash in previous_info[file_type].items():
|
|
239
|
-
path = Path(path_str)
|
|
240
|
-
if self.get_file_hash(path) != previous_hash:
|
|
241
|
-
return RunInfoStatus.FILE_CHANGED
|
|
242
|
-
return RunInfoStatus.MATCH
|
|
243
|
-
|
|
244
|
-
def execute(self, runnable: Runnable) -> int:
|
|
245
|
-
run_info_status = self.previous_run_info_matches(runnable)
|
|
246
|
-
if run_info_status.should_run:
|
|
247
|
-
logger.info(f"Runnable '{runnable.get_name()}' must run. {run_info_status.message}")
|
|
248
|
-
exit_code = runnable.run()
|
|
249
|
-
self.store_run_info(runnable)
|
|
250
|
-
return exit_code
|
|
251
|
-
logger.info(f"Runnable '{runnable.get_name()}' execution skipped. {run_info_status.message}")
|
|
252
|
-
|
|
253
|
-
return 0
|
|
254
|
-
|
|
255
|
-
|
|
256
154
|
class UserNotificationException(Exception):
|
|
257
155
|
pass
|
|
258
156
|
|
|
@@ -399,7 +297,7 @@ class UnixVirtualEnvironment(VirtualEnvironment):
|
|
|
399
297
|
os.remove(temp_script_path)
|
|
400
298
|
|
|
401
299
|
|
|
402
|
-
class CreateVirtualEnvironment
|
|
300
|
+
class CreateVirtualEnvironment:
|
|
403
301
|
def __init__(self, root_dir: Path, package_manager: str) -> None:
|
|
404
302
|
self.root_dir = root_dir
|
|
405
303
|
self.venv_dir = self.root_dir / ".venv"
|
|
@@ -422,9 +320,7 @@ class CreateVirtualEnvironment(Runnable):
|
|
|
422
320
|
return "install"
|
|
423
321
|
|
|
424
322
|
def run(self) -> int:
|
|
425
|
-
|
|
426
|
-
if not self.virtual_env.pip_path().exists():
|
|
427
|
-
self.virtual_env.create()
|
|
323
|
+
self.virtual_env.create()
|
|
428
324
|
|
|
429
325
|
# Get the PyPi source from pyproject.toml or Pipfile if it is defined
|
|
430
326
|
pypi_source = PyPiSourceParser.from_pyproject(self.root_dir)
|
|
@@ -454,24 +350,6 @@ class CreateVirtualEnvironment(Runnable):
|
|
|
454
350
|
else:
|
|
455
351
|
raise UserNotificationException(f"Unsupported operating system: {sys.platform}")
|
|
456
352
|
|
|
457
|
-
def get_name(self) -> str:
|
|
458
|
-
return "create-virtual-environment"
|
|
459
|
-
|
|
460
|
-
def get_inputs(self) -> List[Path]:
|
|
461
|
-
venv_relevant_files = [
|
|
462
|
-
"uv.lock",
|
|
463
|
-
"poetry.lock",
|
|
464
|
-
"poetry.toml",
|
|
465
|
-
"pyproject.toml",
|
|
466
|
-
".env",
|
|
467
|
-
"Pipfile",
|
|
468
|
-
"Pipfile.lock",
|
|
469
|
-
]
|
|
470
|
-
return [self.root_dir / file for file in venv_relevant_files] + [get_bootstrap_script()]
|
|
471
|
-
|
|
472
|
-
def get_outputs(self) -> List[Path]:
|
|
473
|
-
return []
|
|
474
|
-
|
|
475
353
|
|
|
476
354
|
def print_environment_info() -> None:
|
|
477
355
|
str_bar = "".join(["-" for _ in range(80)])
|
|
@@ -501,8 +379,7 @@ def main() -> int:
|
|
|
501
379
|
)
|
|
502
380
|
args = parser.parse_args()
|
|
503
381
|
|
|
504
|
-
|
|
505
|
-
Executor(creator.venv_dir).execute(creator)
|
|
382
|
+
CreateVirtualEnvironment(args.project_dir, package_manager=args.package_manager).run()
|
|
506
383
|
except UserNotificationException as e:
|
|
507
384
|
logger.error(e)
|
|
508
385
|
return 1
|
pypeline/inputs_parser.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import argparse
|
|
2
|
-
import distutils.util
|
|
3
2
|
from typing import Any, Dict, List
|
|
4
3
|
|
|
5
4
|
from py_app_dev.core.exceptions import UserNotificationException
|
|
@@ -13,7 +12,7 @@ def _map_type_for_argparse(input_type: InputType) -> Any:
|
|
|
13
12
|
elif input_type == "integer":
|
|
14
13
|
return int
|
|
15
14
|
elif input_type == "boolean":
|
|
16
|
-
return
|
|
15
|
+
return argparse.BooleanOptionalAction # Use BooleanOptionalAction for boolean arguments
|
|
17
16
|
else:
|
|
18
17
|
raise ValueError(f"Unsupported input type specified: {input_type}")
|
|
19
18
|
|
|
@@ -37,14 +36,23 @@ def create_argument_parser_from_definitions(
|
|
|
37
36
|
help_text += f", Default: {definition.default}"
|
|
38
37
|
help_text += ")"
|
|
39
38
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
39
|
+
if definition.type == "boolean":
|
|
40
|
+
parser.add_argument(
|
|
41
|
+
f"--{name}",
|
|
42
|
+
dest=name, # Attribute name in the parsed namespace
|
|
43
|
+
help=help_text,
|
|
44
|
+
action=arg_type, # Use BooleanOptionalAction for boolean arguments
|
|
45
|
+
default=definition.default or False,
|
|
46
|
+
)
|
|
47
|
+
else:
|
|
48
|
+
parser.add_argument(
|
|
49
|
+
f"--{name}",
|
|
50
|
+
dest=name,
|
|
51
|
+
help=help_text,
|
|
52
|
+
type=arg_type,
|
|
53
|
+
required=definition.required,
|
|
54
|
+
default=definition.default,
|
|
55
|
+
)
|
|
48
56
|
|
|
49
57
|
return parser
|
|
50
58
|
|
|
@@ -69,11 +77,13 @@ class InputsParser:
|
|
|
69
77
|
try:
|
|
70
78
|
args = []
|
|
71
79
|
for item in inputs:
|
|
72
|
-
if "="
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
80
|
+
if "=" in item:
|
|
81
|
+
name, value = item.split("=", 1)
|
|
82
|
+
args.append(f"--{name}")
|
|
83
|
+
if value:
|
|
84
|
+
args.append(value)
|
|
85
|
+
else:
|
|
86
|
+
args.append(f"--{item}")
|
|
77
87
|
|
|
78
88
|
parsed_namespace = self.parser.parse_args(args)
|
|
79
89
|
return vars(parsed_namespace)
|
pypeline/steps/create_venv.py
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import re
|
|
1
2
|
from dataclasses import dataclass
|
|
3
|
+
from enum import Enum, auto
|
|
2
4
|
from pathlib import Path
|
|
3
|
-
from typing import Any, Dict, List, Optional
|
|
5
|
+
from typing import Any, ClassVar, Dict, List, Optional
|
|
4
6
|
|
|
5
7
|
from mashumaro import DataClassDictMixin
|
|
8
|
+
from py_app_dev.core.exceptions import UserNotificationException
|
|
6
9
|
from py_app_dev.core.logging import logger
|
|
7
10
|
|
|
8
11
|
from pypeline.bootstrap.run import get_bootstrap_script
|
|
@@ -13,50 +16,95 @@ from ..domain.pipeline import PipelineStep
|
|
|
13
16
|
|
|
14
17
|
@dataclass
|
|
15
18
|
class CreateVEnvConfig(DataClassDictMixin):
|
|
16
|
-
bootstrap_script: str =
|
|
17
|
-
python_executable: str =
|
|
19
|
+
bootstrap_script: Optional[str] = None
|
|
20
|
+
python_executable: Optional[str] = None
|
|
18
21
|
package_manager: Optional[str] = None
|
|
19
22
|
|
|
20
23
|
|
|
24
|
+
class BootstrapScriptType(Enum):
|
|
25
|
+
CUSTOM = auto()
|
|
26
|
+
INTERNAL = auto()
|
|
27
|
+
|
|
28
|
+
|
|
21
29
|
class CreateVEnv(PipelineStep[ExecutionContext]):
|
|
30
|
+
DEFAULT_PACKAGE_MANAGER = "uv>=0.6"
|
|
31
|
+
DEFAULT_PYTHON_EXECUTABLE = "python311"
|
|
32
|
+
SUPPORTED_PACKAGE_MANAGERS: ClassVar[Dict[str, List[str]]] = {
|
|
33
|
+
"uv": ["uv.lock", "pyproject.toml"],
|
|
34
|
+
"pipenv": ["Pipfile", "Pipfile.lock"],
|
|
35
|
+
"poetry": ["pyproject.toml", "poetry.lock"],
|
|
36
|
+
}
|
|
37
|
+
|
|
22
38
|
def __init__(self, execution_context: ExecutionContext, group_name: str, config: Optional[Dict[str, Any]] = None) -> None:
|
|
39
|
+
self.user_config = CreateVEnvConfig.from_dict(config) if config else CreateVEnvConfig()
|
|
40
|
+
self.bootstrap_script_type = BootstrapScriptType.CUSTOM if self.user_config.bootstrap_script else BootstrapScriptType.INTERNAL
|
|
23
41
|
super().__init__(execution_context, group_name, config)
|
|
24
42
|
self.logger = logger.bind()
|
|
43
|
+
self.bootstrap_script = get_bootstrap_script()
|
|
44
|
+
self.package_manager = self.user_config.package_manager if self.user_config.package_manager else self.DEFAULT_PACKAGE_MANAGER
|
|
45
|
+
self.python_executable = self.user_config.python_executable if self.user_config.python_executable else self.DEFAULT_PYTHON_EXECUTABLE
|
|
46
|
+
self.venv_dir = self.project_root_dir / ".venv"
|
|
25
47
|
|
|
26
48
|
@property
|
|
27
49
|
def install_dirs(self) -> List[Path]:
|
|
28
50
|
return [self.project_root_dir / dir for dir in [".venv/Scripts", ".venv/bin"] if (self.project_root_dir / dir).exists()]
|
|
29
51
|
|
|
52
|
+
@property
|
|
53
|
+
def package_manager_name(self) -> str:
|
|
54
|
+
match = re.match(r"^([a-zA-Z0-9_-]+)", self.package_manager)
|
|
55
|
+
if match:
|
|
56
|
+
result = match.group(1)
|
|
57
|
+
if result in self.SUPPORTED_PACKAGE_MANAGERS:
|
|
58
|
+
return result
|
|
59
|
+
else:
|
|
60
|
+
raise UserNotificationException(f"Package manager {result} is not supported. Supported package managers are: {', '.join(self.SUPPORTED_PACKAGE_MANAGERS)}")
|
|
61
|
+
else:
|
|
62
|
+
raise UserNotificationException(f"Could not extract the package manager name from {self.package_manager}")
|
|
63
|
+
|
|
30
64
|
def get_name(self) -> str:
|
|
31
65
|
return self.__class__.__name__
|
|
32
66
|
|
|
33
67
|
def run(self) -> int:
|
|
34
68
|
self.logger.debug(f"Run {self.get_name()} step. Output dir: {self.output_dir}")
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
69
|
+
|
|
70
|
+
if self.user_config.bootstrap_script:
|
|
71
|
+
bootstrap_script = self.project_root_dir / self.user_config.bootstrap_script
|
|
72
|
+
if not bootstrap_script.exists():
|
|
73
|
+
raise UserNotificationException(f"Bootstrap script {bootstrap_script} does not exist.")
|
|
74
|
+
self.execution_context.create_process_executor(
|
|
75
|
+
[self.python_executable, bootstrap_script.as_posix()],
|
|
76
|
+
cwd=self.project_root_dir,
|
|
77
|
+
).execute()
|
|
78
|
+
else:
|
|
79
|
+
# The internal bootstrap script supports arguments.
|
|
80
|
+
bootstrap_args = [
|
|
81
|
+
"--project-dir",
|
|
82
|
+
self.project_root_dir.as_posix(),
|
|
83
|
+
"--package-manager",
|
|
84
|
+
f'"{self.package_manager}"',
|
|
85
|
+
]
|
|
86
|
+
self.execution_context.create_process_executor(
|
|
87
|
+
[self.python_executable, self.bootstrap_script.as_posix(), *bootstrap_args],
|
|
88
|
+
cwd=self.project_root_dir,
|
|
89
|
+
).execute()
|
|
50
90
|
return 0
|
|
51
91
|
|
|
52
92
|
def get_inputs(self) -> List[Path]:
|
|
53
|
-
|
|
93
|
+
package_manager_relevant_file = self.SUPPORTED_PACKAGE_MANAGERS.get(self.package_manager_name, [])
|
|
94
|
+
return [self.project_root_dir / file for file in package_manager_relevant_file] + [self.bootstrap_script]
|
|
54
95
|
|
|
55
96
|
def get_outputs(self) -> List[Path]:
|
|
56
|
-
return []
|
|
97
|
+
return [self.venv_dir]
|
|
98
|
+
|
|
99
|
+
def get_config(self) -> Optional[dict[str, str]]:
|
|
100
|
+
return {
|
|
101
|
+
"bootstrap_script": self.bootstrap_script.as_posix(),
|
|
102
|
+
"python_executable": self.python_executable,
|
|
103
|
+
"package_manager": self.package_manager,
|
|
104
|
+
}
|
|
57
105
|
|
|
58
106
|
def update_execution_context(self) -> None:
|
|
59
|
-
|
|
107
|
+
self.execution_context.add_install_dirs(self.install_dirs)
|
|
60
108
|
|
|
61
109
|
def get_needs_dependency_management(self) -> bool:
|
|
62
|
-
return False
|
|
110
|
+
return False if self.bootstrap_script_type == BootstrapScriptType.CUSTOM else True
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
pypeline/__init__.py,sha256=
|
|
1
|
+
pypeline/__init__.py,sha256=zXjo5icgcGx5X40awUvUOk5_ohh0Pz1N3VFKYCfYEcM,23
|
|
2
2
|
pypeline/__run.py,sha256=TCdaX05Qm3g8T4QYryKB25Xxf0L5Km7hFOHe1mK9vI0,350
|
|
3
3
|
pypeline/bootstrap/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
pypeline/bootstrap/run.py,sha256=
|
|
4
|
+
pypeline/bootstrap/run.py,sha256=iZS-VZGk2KnMRVOb3QuYPrTeINQqVdWkvgjEDpl8oQA,15927
|
|
5
5
|
pypeline/domain/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
6
|
pypeline/domain/artifacts.py,sha256=5k7cVfHhLmvWXNuHKxXb9ca4Lxu0JytGQqazENCeKEU,1404
|
|
7
7
|
pypeline/domain/config.py,sha256=6vWdHi7B6MA7NGi9wWXQE-YhSg1COSRmc3b1ji6AdAk,2053
|
|
8
8
|
pypeline/domain/execution_context.py,sha256=cDdUOU32hKg2Mv6FNXCG1co8GUrBf5QOVKhaKO-xVxI,1848
|
|
9
9
|
pypeline/domain/pipeline.py,sha256=2BsN2lw2znUxLH--Novyqe6SubVKs6XeHQSQf9yxirw,7788
|
|
10
10
|
pypeline/domain/project_slurper.py,sha256=64aqgVsrLgAK-c5QOM2N0wGCkOM1uNMio8yKjO2zDLU,1069
|
|
11
|
-
pypeline/inputs_parser.py,sha256=
|
|
11
|
+
pypeline/inputs_parser.py,sha256=tGQRfZMsDAXbir455kxNXPNLN_hwGmSisS41GqYrh1A,3745
|
|
12
12
|
pypeline/kickstart/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
13
|
pypeline/kickstart/create.py,sha256=iaB8MMC7PinpPBwRmz3rWZuE-DRbsLh2NtvczYaVgi0,2133
|
|
14
14
|
pypeline/kickstart/templates/project/.gitignore,sha256=y8GJoVvRPez1LBokf1NaDOt2X1XtGwKFMF5yjA8AVS0,24
|
|
@@ -21,12 +21,12 @@ pypeline/main.py,sha256=2mC2BDB1OWIXhaijBXG6Y1vfT8_yMZ4Dj55w5u7g7-w,4158
|
|
|
21
21
|
pypeline/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
22
22
|
pypeline/pypeline.py,sha256=-mquLfFlEvESk-HORhvjRMESIzdlVAgBLPjwUDOPLqg,7452
|
|
23
23
|
pypeline/steps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
24
|
-
pypeline/steps/create_venv.py,sha256=
|
|
24
|
+
pypeline/steps/create_venv.py,sha256=NeS2Q0a0USwEc-PpcqDxOOCGEDRENlnzAxI0OjTL3N4,4861
|
|
25
25
|
pypeline/steps/env_setup_script.py,sha256=u08A6pvMccFQbcnU0xruFvpU30PbDrttnbOjl1gDqog,2340
|
|
26
26
|
pypeline/steps/scoop_install.py,sha256=DDXBD-5TVaT-u6Yf7A85uWoCgBVmLvj9nPGrZ8OQCz0,3853
|
|
27
27
|
pypeline/steps/west_install.py,sha256=hPyr28ksdKsQ0tv0gMNytzupgk1IgjN9CpmaBdX5zps,1947
|
|
28
|
-
pypeline_runner-1.
|
|
29
|
-
pypeline_runner-1.
|
|
30
|
-
pypeline_runner-1.
|
|
31
|
-
pypeline_runner-1.
|
|
32
|
-
pypeline_runner-1.
|
|
28
|
+
pypeline_runner-1.16.0.dist-info/LICENSE,sha256=sKxdoqSmW9ezvPvt0ZGJbneyA0SBcm0GiqzTv2jN230,1066
|
|
29
|
+
pypeline_runner-1.16.0.dist-info/METADATA,sha256=LdGV3SefgqFcV2tki0BBK2pr4wNzIBCOZ7Ws7Dx-Jew,7553
|
|
30
|
+
pypeline_runner-1.16.0.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
|
|
31
|
+
pypeline_runner-1.16.0.dist-info/entry_points.txt,sha256=pe1u0uuhPI_yeQ0KjEw6jK-EvQfPcZwBSajgbAdKz1o,47
|
|
32
|
+
pypeline_runner-1.16.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|