q8s 0.7.0__tar.gz → 0.8.0.dev2__tar.gz
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.
- {q8s-0.7.0 → q8s-0.8.0.dev2}/PKG-INFO +5 -1
- {q8s-0.7.0 → q8s-0.8.0.dev2}/README.md +4 -0
- {q8s-0.7.0 → q8s-0.8.0.dev2}/pyproject.toml +1 -1
- {q8s-0.7.0 → q8s-0.8.0.dev2}/q8s/cli.py +8 -1
- {q8s-0.7.0 → q8s-0.8.0.dev2}/q8s/execution.py +1 -1
- {q8s-0.7.0 → q8s-0.8.0.dev2}/q8s/multifiles.py +9 -6
- {q8s-0.7.0 → q8s-0.8.0.dev2}/q8s/plugins/cpu_job.py +9 -5
- {q8s-0.7.0 → q8s-0.8.0.dev2}/q8s/plugins/cuda_job.py +9 -5
- {q8s-0.7.0 → q8s-0.8.0.dev2}/q8s/plugins/job_template_spec.py +1 -4
- q8s-0.8.0.dev2/q8s/workload.py +167 -0
- {q8s-0.7.0 → q8s-0.8.0.dev2}/q8s.egg-info/PKG-INFO +5 -1
- q8s-0.7.0/q8s/workload.py +0 -82
- {q8s-0.7.0 → q8s-0.8.0.dev2}/LICENSE +0 -0
- {q8s-0.7.0 → q8s-0.8.0.dev2}/q8s/__init__.py +0 -0
- {q8s-0.7.0 → q8s-0.8.0.dev2}/q8s/__main__.py +0 -0
- {q8s-0.7.0 → q8s-0.8.0.dev2}/q8s/constants.py +0 -0
- {q8s-0.7.0 → q8s-0.8.0.dev2}/q8s/deps/__init__.py +0 -0
- {q8s-0.7.0 → q8s-0.8.0.dev2}/q8s/deps/code_analyzer.py +0 -0
- {q8s-0.7.0 → q8s-0.8.0.dev2}/q8s/deps/parser.py +0 -0
- {q8s-0.7.0 → q8s-0.8.0.dev2}/q8s/enums.py +0 -0
- {q8s-0.7.0 → q8s-0.8.0.dev2}/q8s/install.py +0 -0
- {q8s-0.7.0 → q8s-0.8.0.dev2}/q8s/kernel.py +0 -0
- {q8s-0.7.0 → q8s-0.8.0.dev2}/q8s/matplotlib/backend.py +0 -0
- {q8s-0.7.0 → q8s-0.8.0.dev2}/q8s/plugins/__init__.py +0 -0
- {q8s-0.7.0 → q8s-0.8.0.dev2}/q8s/project.py +0 -0
- {q8s-0.7.0 → q8s-0.8.0.dev2}/q8s/utils.py +0 -0
- {q8s-0.7.0 → q8s-0.8.0.dev2}/q8s.egg-info/SOURCES.txt +0 -0
- {q8s-0.7.0 → q8s-0.8.0.dev2}/q8s.egg-info/dependency_links.txt +0 -0
- {q8s-0.7.0 → q8s-0.8.0.dev2}/q8s.egg-info/entry_points.txt +0 -0
- {q8s-0.7.0 → q8s-0.8.0.dev2}/q8s.egg-info/requires.txt +0 -0
- {q8s-0.7.0 → q8s-0.8.0.dev2}/q8s.egg-info/top_level.txt +0 -0
- {q8s-0.7.0 → q8s-0.8.0.dev2}/setup.cfg +0 -0
- {q8s-0.7.0 → q8s-0.8.0.dev2}/tests/__init__.py +0 -0
- {q8s-0.7.0 → q8s-0.8.0.dev2}/tests/fixtures/cache/app.py +0 -0
- {q8s-0.7.0 → q8s-0.8.0.dev2}/tests/fixtures/simple/qiskit.py +0 -0
- {q8s-0.7.0 → q8s-0.8.0.dev2}/tests/test_backend.py +0 -0
- {q8s-0.7.0 → q8s-0.8.0.dev2}/tests/test_deps.py +0 -0
- {q8s-0.7.0 → q8s-0.8.0.dev2}/tests/test_job_template_spec.py +0 -0
- {q8s-0.7.0 → q8s-0.8.0.dev2}/tests/test_kernel.py +0 -0
- {q8s-0.7.0 → q8s-0.8.0.dev2}/tests/test_multifiles.py +0 -0
- {q8s-0.7.0 → q8s-0.8.0.dev2}/tests/test_project.py +0 -0
- {q8s-0.7.0 → q8s-0.8.0.dev2}/tests/test_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: q8s
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.0.dev2
|
|
4
4
|
Summary: Kernel extension for executing quantum programs in simulators on q8s clusters
|
|
5
5
|
Author-email: Vlad Stirbu <vstirbu@gmail.com>
|
|
6
6
|
License: Apache License
|
|
@@ -234,6 +234,10 @@ Dynamic: license-file
|
|
|
234
234
|
|
|
235
235
|
# q8s
|
|
236
236
|
|
|
237
|
+
[](https://pypi.org/project/q8s/)
|
|
238
|
+
[](https://pypi.org/project/q8s/)
|
|
239
|
+
[](https://pepy.tech/projects/q8s)
|
|
240
|
+
|
|
237
241
|
Toolset for executing quantum jobs on [Qubernetes](https://www.qubernetes.dev).
|
|
238
242
|
|
|
239
243
|
## Installation
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# q8s
|
|
2
2
|
|
|
3
|
+
[](https://pypi.org/project/q8s/)
|
|
4
|
+
[](https://pypi.org/project/q8s/)
|
|
5
|
+
[](https://pepy.tech/projects/q8s)
|
|
6
|
+
|
|
3
7
|
Toolset for executing quantum jobs on [Qubernetes](https://www.qubernetes.dev).
|
|
4
8
|
|
|
5
9
|
## Installation
|
|
@@ -71,7 +71,12 @@ def build(
|
|
|
71
71
|
project.update_images_cache()
|
|
72
72
|
|
|
73
73
|
|
|
74
|
-
@app.command(
|
|
74
|
+
@app.command(
|
|
75
|
+
context_settings={
|
|
76
|
+
"allow_extra_args": True,
|
|
77
|
+
"ignore_unknown_options": True,
|
|
78
|
+
}
|
|
79
|
+
)
|
|
75
80
|
def execute(
|
|
76
81
|
file: Annotated[Path, typer.Argument(help="Python file to be executed")],
|
|
77
82
|
target: Annotated[
|
|
@@ -88,6 +93,7 @@ def execute(
|
|
|
88
93
|
envvar="REGISTRY_PAT",
|
|
89
94
|
),
|
|
90
95
|
] = None,
|
|
96
|
+
args: Annotated[list[str], typer.Argument(help="Additional arguments")] = None,
|
|
91
97
|
):
|
|
92
98
|
project = Project()
|
|
93
99
|
|
|
@@ -117,6 +123,7 @@ def execute(
|
|
|
117
123
|
k8s_context.set_registry_pat(registry_pat)
|
|
118
124
|
|
|
119
125
|
workload = Workload.from_entry_script(entry_script=file)
|
|
126
|
+
workload.set_args(args or [])
|
|
120
127
|
|
|
121
128
|
output, stream_name = k8s_context.execute_workload(workload=workload)
|
|
122
129
|
|
|
@@ -136,7 +136,7 @@ class K8sContext:
|
|
|
136
136
|
self.__progress.console.print("Job created")
|
|
137
137
|
|
|
138
138
|
self.__create_config_map_object_from_workload(job, workload=workload)
|
|
139
|
-
self.__progress.console.print("Application code
|
|
139
|
+
self.__progress.console.print("Application code attached")
|
|
140
140
|
self.__create_environment_secret()
|
|
141
141
|
self.__progress.console.print("Environment variables created")
|
|
142
142
|
|
|
@@ -9,16 +9,17 @@ GLOBAL = getattr(sys, "base_prefix", sys.prefix)
|
|
|
9
9
|
LOCAL = sys.prefix
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
def _resolve_spec(modname: str, package: str | None = None):
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
def _resolve_spec(modname: str, package: str | None = None, is_project: bool = False):
|
|
13
|
+
"""Resolve a module spec, temporarily adjusting sys.path for project layout."""
|
|
14
|
+
cwd = Path(os.getcwd()) / "src" if is_project else Path(os.getcwd())
|
|
15
|
+
sys.path.insert(0, str(cwd))
|
|
15
16
|
|
|
16
17
|
try:
|
|
17
18
|
return importlib.util.find_spec(modname, package=package)
|
|
18
19
|
except Exception:
|
|
19
20
|
return None
|
|
20
21
|
finally:
|
|
21
|
-
sys.path.remove(cwd)
|
|
22
|
+
sys.path.remove(str(cwd))
|
|
22
23
|
|
|
23
24
|
|
|
24
25
|
def _spec_origin_files(spec: ModuleSpec):
|
|
@@ -106,7 +107,9 @@ def pkg_name_for_file(fpath: Path | str):
|
|
|
106
107
|
return ".".join(reversed(parts)) if parts else None
|
|
107
108
|
|
|
108
109
|
|
|
109
|
-
def collect_imported_files(
|
|
110
|
+
def collect_imported_files(
|
|
111
|
+
entry_script: str | Path, is_project: bool = True
|
|
112
|
+
) -> set[Path]:
|
|
110
113
|
"""
|
|
111
114
|
Return a set of file paths transitively imported by entry_script
|
|
112
115
|
except pip-installed and global interpreter packages.
|
|
@@ -136,7 +139,7 @@ def collect_imported_files(entry_script: str | Path):
|
|
|
136
139
|
continue
|
|
137
140
|
|
|
138
141
|
# Explore the resolved module/package
|
|
139
|
-
spec = _resolve_spec(target)
|
|
142
|
+
spec = _resolve_spec(target, is_project=is_project)
|
|
140
143
|
if not spec:
|
|
141
144
|
continue
|
|
142
145
|
|
|
@@ -16,10 +16,7 @@ class CPUJobTemplatePlugin:
|
|
|
16
16
|
registry_credentials_secret_name: str,
|
|
17
17
|
container_image: str,
|
|
18
18
|
workload: Workload,
|
|
19
|
-
env:
|
|
20
|
-
str,
|
|
21
|
-
str | None,
|
|
22
|
-
],
|
|
19
|
+
env: list[client.V1EnvVar],
|
|
23
20
|
target: Target,
|
|
24
21
|
) -> client.V1PodTemplateSpec:
|
|
25
22
|
|
|
@@ -28,12 +25,19 @@ class CPUJobTemplatePlugin:
|
|
|
28
25
|
|
|
29
26
|
volume_name = f"app-volume-{name}"
|
|
30
27
|
|
|
28
|
+
if workload.is_src_project:
|
|
29
|
+
env.append(client.V1EnvVar(name="PYTHONPATH", value=f"{WORKSPACE}/src"))
|
|
30
|
+
|
|
31
31
|
container = client.V1Container(
|
|
32
32
|
name="quantum-routine",
|
|
33
33
|
image=container_image,
|
|
34
34
|
env=env,
|
|
35
35
|
command=["python"],
|
|
36
|
-
args=
|
|
36
|
+
args=(
|
|
37
|
+
["-m", workload.entry_module] + workload.args
|
|
38
|
+
if workload.is_src_project
|
|
39
|
+
else [f"{WORKSPACE}/{workload.entry_script}"] + workload.args
|
|
40
|
+
),
|
|
37
41
|
image_pull_policy="Always",
|
|
38
42
|
volume_mounts=[
|
|
39
43
|
client.V1VolumeMount(
|
|
@@ -22,10 +22,7 @@ class CUDAJobTemplatePlugin:
|
|
|
22
22
|
registry_credentials_secret_name: str,
|
|
23
23
|
container_image: str,
|
|
24
24
|
workload: Workload,
|
|
25
|
-
env:
|
|
26
|
-
str,
|
|
27
|
-
str | None,
|
|
28
|
-
],
|
|
25
|
+
env: list[client.V1EnvVar],
|
|
29
26
|
target: Target,
|
|
30
27
|
) -> client.V1PodTemplateSpec:
|
|
31
28
|
|
|
@@ -34,12 +31,19 @@ class CUDAJobTemplatePlugin:
|
|
|
34
31
|
|
|
35
32
|
volume_name = f"app-volume-{name}"
|
|
36
33
|
|
|
34
|
+
if workload.is_src_project:
|
|
35
|
+
env.append(client.V1EnvVar(name="PYTHONPATH", value=f"{WORKSPACE}/src"))
|
|
36
|
+
|
|
37
37
|
container = client.V1Container(
|
|
38
38
|
name="quantum-routine",
|
|
39
39
|
image=container_image,
|
|
40
40
|
env=env,
|
|
41
41
|
command=["python"],
|
|
42
|
-
args=
|
|
42
|
+
args=(
|
|
43
|
+
["-m", workload.entry_module] + workload.args
|
|
44
|
+
if workload.is_src_project
|
|
45
|
+
else [f"{WORKSPACE}/{workload.entry_script}"] + workload.args
|
|
46
|
+
),
|
|
43
47
|
image_pull_policy="Always",
|
|
44
48
|
resources=(
|
|
45
49
|
client.V1ResourceRequirements(
|
|
@@ -34,10 +34,7 @@ class JobTemplatePluginSpec:
|
|
|
34
34
|
registry_credentials_secret_name: str,
|
|
35
35
|
container_image: str,
|
|
36
36
|
workload: Workload,
|
|
37
|
-
env:
|
|
38
|
-
str,
|
|
39
|
-
str | None,
|
|
40
|
-
],
|
|
37
|
+
env: list[client.V1EnvVar],
|
|
41
38
|
target: Target,
|
|
42
39
|
) -> client.V1PodTemplateSpec:
|
|
43
40
|
return None
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
import configparser
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
from .multifiles import collect_imported_files
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Workload:
|
|
9
|
+
"""
|
|
10
|
+
Represents a mutifile workload consisting of an entry script and its imported files
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
__pyproject_root: Path | None = None
|
|
14
|
+
__args: list[str] = []
|
|
15
|
+
|
|
16
|
+
def __init__(self, entry_script: Path | str = None, code: str = None):
|
|
17
|
+
if entry_script is not None:
|
|
18
|
+
|
|
19
|
+
if self.__is_src_layout():
|
|
20
|
+
self.__entry_script = Path(os.path.abspath(entry_script))
|
|
21
|
+
self.__base_path = self.__pyproject_root
|
|
22
|
+
|
|
23
|
+
self.__files = collect_imported_files(
|
|
24
|
+
self.__entry_script, is_project=True
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
else:
|
|
28
|
+
self.__entry_script = Path(os.path.abspath(entry_script))
|
|
29
|
+
self.__base_path = self.__entry_script.parent
|
|
30
|
+
|
|
31
|
+
self.__files = collect_imported_files(
|
|
32
|
+
self.__entry_script, is_project=False
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
self.__data = {
|
|
36
|
+
self.__path_mapping(f): open(f, "r").read() for f in self.__files
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
elif code is not None:
|
|
40
|
+
self.__entry_script = Path(os.path.abspath("main.py"))
|
|
41
|
+
self.__base_path = os.getcwd()
|
|
42
|
+
self.__files = [Path(self.__entry_script)]
|
|
43
|
+
|
|
44
|
+
self.__data = {self.__path_mapping(self.__entry_script): code}
|
|
45
|
+
|
|
46
|
+
else:
|
|
47
|
+
raise ValueError("Either entry_script or code must be provided.")
|
|
48
|
+
|
|
49
|
+
@classmethod
|
|
50
|
+
def from_code(cls, code: str):
|
|
51
|
+
"""
|
|
52
|
+
Create a Workload from code string
|
|
53
|
+
"""
|
|
54
|
+
return cls(code=code)
|
|
55
|
+
|
|
56
|
+
@classmethod
|
|
57
|
+
def from_entry_script(cls, entry_script: Path | str):
|
|
58
|
+
"""
|
|
59
|
+
Create a Workload from an entry script file path
|
|
60
|
+
"""
|
|
61
|
+
return cls(entry_script=entry_script)
|
|
62
|
+
|
|
63
|
+
@property
|
|
64
|
+
def files(self) -> list[Path]:
|
|
65
|
+
"""
|
|
66
|
+
List of all files in the workload
|
|
67
|
+
"""
|
|
68
|
+
return self.__files
|
|
69
|
+
|
|
70
|
+
@property
|
|
71
|
+
def entry_script(self) -> Path:
|
|
72
|
+
"""
|
|
73
|
+
Entry script path relative to base path
|
|
74
|
+
"""
|
|
75
|
+
return self.__relative_path(self.__entry_script)
|
|
76
|
+
|
|
77
|
+
@property
|
|
78
|
+
def is_src_project(self) -> bool:
|
|
79
|
+
"""
|
|
80
|
+
Whether the project uses a src/ layout
|
|
81
|
+
"""
|
|
82
|
+
return self.__pyproject_root is not None
|
|
83
|
+
|
|
84
|
+
@property
|
|
85
|
+
def entry_module(self) -> str:
|
|
86
|
+
"""
|
|
87
|
+
Entry script module name
|
|
88
|
+
"""
|
|
89
|
+
return self.entry_script.replace("/", ".")[:-3] # strip .py
|
|
90
|
+
|
|
91
|
+
@property
|
|
92
|
+
def data(self) -> dict[str, str]:
|
|
93
|
+
"""
|
|
94
|
+
Dictionary mapping file paths to their contents
|
|
95
|
+
"""
|
|
96
|
+
return self.__data
|
|
97
|
+
|
|
98
|
+
@property
|
|
99
|
+
def mappings(self):
|
|
100
|
+
"""
|
|
101
|
+
Dictionary mapping relative file paths to their unique path mappings
|
|
102
|
+
"""
|
|
103
|
+
return {self.__path_mapping(f): self.__relative_path(f) for f in self.__files}
|
|
104
|
+
|
|
105
|
+
@property
|
|
106
|
+
def args(self) -> list[str]:
|
|
107
|
+
"""
|
|
108
|
+
Additional arguments for the workload
|
|
109
|
+
"""
|
|
110
|
+
return self.__args
|
|
111
|
+
|
|
112
|
+
def set_args(self, args: list[str]) -> None:
|
|
113
|
+
"""
|
|
114
|
+
Set additional arguments for the workload
|
|
115
|
+
"""
|
|
116
|
+
self.__args = args
|
|
117
|
+
|
|
118
|
+
def __relative_path(self, file: Path | str) -> str:
|
|
119
|
+
"""
|
|
120
|
+
Get the relative path of a file with respect to the base path
|
|
121
|
+
"""
|
|
122
|
+
return os.path.relpath(os.path.abspath(file), self.__base_path)
|
|
123
|
+
|
|
124
|
+
def __path_mapping(self, file: Path | str) -> str:
|
|
125
|
+
"""
|
|
126
|
+
Get the unique path mapping for a file
|
|
127
|
+
"""
|
|
128
|
+
return self.__relative_path(file).replace("/", "__")
|
|
129
|
+
|
|
130
|
+
def __pyproject_root(self, start: Path | None = None) -> Path | None:
|
|
131
|
+
"""
|
|
132
|
+
Find the project root by looking for setup.cfg or pyproject.toml
|
|
133
|
+
"""
|
|
134
|
+
|
|
135
|
+
if (
|
|
136
|
+
Path(os.path.join(os.getcwd(), "setup.cfg")).exists()
|
|
137
|
+
or Path(os.path.join(os.getcwd(), "pyproject.toml")).exists()
|
|
138
|
+
):
|
|
139
|
+
return Path(os.getcwd()).resolve()
|
|
140
|
+
|
|
141
|
+
return None
|
|
142
|
+
|
|
143
|
+
def __is_src_layout(self) -> bool:
|
|
144
|
+
"""
|
|
145
|
+
Determine if the project uses a src/ layout
|
|
146
|
+
"""
|
|
147
|
+
root = self.__pyproject_root()
|
|
148
|
+
|
|
149
|
+
if root is None:
|
|
150
|
+
return False
|
|
151
|
+
|
|
152
|
+
cfg_path = root / "setup.cfg"
|
|
153
|
+
if not cfg_path.exists():
|
|
154
|
+
return False
|
|
155
|
+
|
|
156
|
+
config = configparser.ConfigParser()
|
|
157
|
+
config.read(cfg_path)
|
|
158
|
+
|
|
159
|
+
# Very simple heuristic: [options.packages.find] where = src
|
|
160
|
+
if config.has_section("options.packages.find"):
|
|
161
|
+
where = config.get("options.packages.find", "where", fallback="").strip()
|
|
162
|
+
if where == "src":
|
|
163
|
+
self.__pyproject_root = root
|
|
164
|
+
return True
|
|
165
|
+
|
|
166
|
+
# You could add similar checks for pyproject.toml if you use that
|
|
167
|
+
return False
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: q8s
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.0.dev2
|
|
4
4
|
Summary: Kernel extension for executing quantum programs in simulators on q8s clusters
|
|
5
5
|
Author-email: Vlad Stirbu <vstirbu@gmail.com>
|
|
6
6
|
License: Apache License
|
|
@@ -234,6 +234,10 @@ Dynamic: license-file
|
|
|
234
234
|
|
|
235
235
|
# q8s
|
|
236
236
|
|
|
237
|
+
[](https://pypi.org/project/q8s/)
|
|
238
|
+
[](https://pypi.org/project/q8s/)
|
|
239
|
+
[](https://pepy.tech/projects/q8s)
|
|
240
|
+
|
|
237
241
|
Toolset for executing quantum jobs on [Qubernetes](https://www.qubernetes.dev).
|
|
238
242
|
|
|
239
243
|
## Installation
|
q8s-0.7.0/q8s/workload.py
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
from pathlib import Path
|
|
2
|
-
import os
|
|
3
|
-
|
|
4
|
-
from .multifiles import collect_imported_files
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class Workload:
|
|
8
|
-
"""
|
|
9
|
-
Represents a mutifile workload consisting of an entry script and its imported files
|
|
10
|
-
"""
|
|
11
|
-
|
|
12
|
-
def __init__(self, entry_script: Path | str = None, code: str = None):
|
|
13
|
-
if entry_script is not None:
|
|
14
|
-
self.__entry_script = Path(os.path.abspath(entry_script))
|
|
15
|
-
self.__base_path = self.__entry_script.parent
|
|
16
|
-
|
|
17
|
-
self.__files = collect_imported_files(self.__entry_script)
|
|
18
|
-
self.__data = {
|
|
19
|
-
self.__path_mapping(f): open(f, "r").read() for f in self.__files
|
|
20
|
-
}
|
|
21
|
-
elif code is not None:
|
|
22
|
-
self.__entry_script = Path(os.path.abspath("main.py"))
|
|
23
|
-
self.__base_path = os.getcwd()
|
|
24
|
-
self.__files = [Path(self.__entry_script)]
|
|
25
|
-
|
|
26
|
-
self.__data = {self.__path_mapping(self.__entry_script): code}
|
|
27
|
-
else:
|
|
28
|
-
raise ValueError("Either entry_script or code must be provided.")
|
|
29
|
-
|
|
30
|
-
@classmethod
|
|
31
|
-
def from_code(cls, code: str):
|
|
32
|
-
"""
|
|
33
|
-
Create a Workload from code string
|
|
34
|
-
"""
|
|
35
|
-
return cls(code=code)
|
|
36
|
-
|
|
37
|
-
@classmethod
|
|
38
|
-
def from_entry_script(cls, entry_script: Path | str):
|
|
39
|
-
"""
|
|
40
|
-
Create a Workload from an entry script file path
|
|
41
|
-
"""
|
|
42
|
-
return cls(entry_script=entry_script)
|
|
43
|
-
|
|
44
|
-
@property
|
|
45
|
-
def files(self) -> list[Path]:
|
|
46
|
-
"""
|
|
47
|
-
List of all files in the workload
|
|
48
|
-
"""
|
|
49
|
-
return self.__files
|
|
50
|
-
|
|
51
|
-
@property
|
|
52
|
-
def entry_script(self) -> Path:
|
|
53
|
-
"""
|
|
54
|
-
Entry script path relative to base path
|
|
55
|
-
"""
|
|
56
|
-
return self.__relative_path(self.__entry_script)
|
|
57
|
-
|
|
58
|
-
@property
|
|
59
|
-
def data(self) -> dict[str, str]:
|
|
60
|
-
"""
|
|
61
|
-
Dictionary mapping file paths to their contents
|
|
62
|
-
"""
|
|
63
|
-
return self.__data
|
|
64
|
-
|
|
65
|
-
@property
|
|
66
|
-
def mappings(self):
|
|
67
|
-
"""
|
|
68
|
-
Dictionary mapping relative file paths to their unique path mappings
|
|
69
|
-
"""
|
|
70
|
-
return {self.__path_mapping(f): self.__relative_path(f) for f in self.__files}
|
|
71
|
-
|
|
72
|
-
def __relative_path(self, file: Path | str) -> str:
|
|
73
|
-
"""
|
|
74
|
-
Get the relative path of a file with respect to the base path
|
|
75
|
-
"""
|
|
76
|
-
return os.path.relpath(os.path.abspath(file), self.__base_path)
|
|
77
|
-
|
|
78
|
-
def __path_mapping(self, file: Path | str) -> str:
|
|
79
|
-
"""
|
|
80
|
-
Get the unique path mapping for a file
|
|
81
|
-
"""
|
|
82
|
-
return self.__relative_path(file).replace("/", "__")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|