artefacts-cli 0.6.16__py3-none-any.whl → 0.6.17__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.
- artefacts/cli/__init__.py +1 -1
- artefacts/cli/app.py +56 -3
- artefacts/cli/app_containers.py +27 -6
- artefacts/cli/containers/__init__.py +8 -1
- artefacts/cli/containers/docker.py +18 -0
- artefacts/cli/containers/utils.py +3 -0
- artefacts/cli/version.py +2 -2
- {artefacts_cli-0.6.16.dist-info → artefacts_cli-0.6.17.dist-info}/METADATA +2 -1
- artefacts_cli-0.6.17.dist-info/RECORD +21 -0
- artefacts_cli-0.6.16.dist-info/RECORD +0 -21
- {artefacts_cli-0.6.16.dist-info → artefacts_cli-0.6.17.dist-info}/WHEEL +0 -0
- {artefacts_cli-0.6.16.dist-info → artefacts_cli-0.6.17.dist-info}/entry_points.txt +0 -0
- {artefacts_cli-0.6.16.dist-info → artefacts_cli-0.6.17.dist-info}/top_level.txt +0 -0
artefacts/cli/__init__.py
CHANGED
artefacts/cli/app.py
CHANGED
@@ -231,11 +231,64 @@ def hello(project_name):
|
|
231
231
|
is_eager=True, # Necessary for callbacks to see it.
|
232
232
|
help="Skip configuration validation, so that unsupported settings can be tried out, e.g. non-ROS settings or simulators like SAPIEN.",
|
233
233
|
)
|
234
|
+
@click.option(
|
235
|
+
"--in-container",
|
236
|
+
is_flag=True,
|
237
|
+
default=False,
|
238
|
+
help='[Experimental] Run the job inside a package container. The container image is build if it does not exist yet, with default name as "artefacts" (please use --with-image to override the image name). This option overrides (for now) --dryrun, --nosim, --noisolation and --description.',
|
239
|
+
)
|
240
|
+
@click.option(
|
241
|
+
"--with-image",
|
242
|
+
default="artefacts",
|
243
|
+
help="[Experimental] Run the job using the image name passed here. Only used when running with --in-container set.",
|
244
|
+
)
|
245
|
+
@click.option(
|
246
|
+
"--rebuild-container",
|
247
|
+
is_flag=True,
|
248
|
+
default=False,
|
249
|
+
help="[Experimental] Rebuild the container image before running. This flag guarantees that the run uses the latest code available when building the image, and usually takes more time before the run can start (time to compile and generate the image).",
|
250
|
+
)
|
251
|
+
@click.option(
|
252
|
+
"--with-gui",
|
253
|
+
is_flag=True,
|
254
|
+
default=False,
|
255
|
+
help="Show any GUI if any is created by the test runs. By default, UI elements are run but hidden---only test logs are returned. Please note GUI often assume X11 (e.g. ROS), typically with Qt, so this may not work without a appropriate environment.",
|
256
|
+
)
|
234
257
|
@click.argument("jobname")
|
258
|
+
@click.pass_context
|
235
259
|
def run(
|
236
|
-
|
260
|
+
ctx: click.Context,
|
261
|
+
config,
|
262
|
+
jobname,
|
263
|
+
dryrun,
|
264
|
+
nosim,
|
265
|
+
noisolation,
|
266
|
+
description="",
|
267
|
+
skip_validation=False,
|
268
|
+
in_container: bool = False,
|
269
|
+
with_image: str = "artefacts",
|
270
|
+
rebuild_container: bool = False,
|
271
|
+
with_gui: bool = False,
|
237
272
|
):
|
238
|
-
"""
|
273
|
+
"""
|
274
|
+
Run JOBNAME locally
|
275
|
+
|
276
|
+
* Directly in the shell by default.
|
277
|
+
* Inside a packaged container when using the --in-container option.
|
278
|
+
"""
|
279
|
+
if in_container:
|
280
|
+
if rebuild_container or not ctx.invoke(containers.check, name=with_image):
|
281
|
+
ctx.invoke(
|
282
|
+
containers.build, path=".", dockerfile="Dockerfile", name=with_image
|
283
|
+
)
|
284
|
+
return ctx.invoke(
|
285
|
+
containers.run,
|
286
|
+
image=with_image,
|
287
|
+
jobname=jobname,
|
288
|
+
config=config,
|
289
|
+
with_gui=with_gui,
|
290
|
+
)
|
291
|
+
|
239
292
|
warpconfig = read_config(config)
|
240
293
|
|
241
294
|
project_id = warpconfig["project"]
|
@@ -573,7 +626,7 @@ artefacts.add_command(config)
|
|
573
626
|
artefacts.add_command(hello)
|
574
627
|
artefacts.add_command(run)
|
575
628
|
artefacts.add_command(run_remote)
|
576
|
-
artefacts.add_command(containers.
|
629
|
+
artefacts.add_command(containers.containers)
|
577
630
|
|
578
631
|
|
579
632
|
if __name__ == "__main__":
|
artefacts/cli/app_containers.py
CHANGED
@@ -10,12 +10,12 @@ from artefacts.cli.containers.utils import ContainerMgr
|
|
10
10
|
@click.group()
|
11
11
|
@click.option("--debug/--no-debug", default=False)
|
12
12
|
@click.pass_context
|
13
|
-
def
|
13
|
+
def containers(ctx: click.Context, debug: bool):
|
14
14
|
ctx.ensure_object(dict)
|
15
15
|
ctx.obj["debug"] = debug
|
16
16
|
|
17
17
|
|
18
|
-
@
|
18
|
+
@containers.command()
|
19
19
|
@click.option(
|
20
20
|
"--path",
|
21
21
|
default=".",
|
@@ -29,13 +29,13 @@ def package(ctx: click.Context, debug: bool):
|
|
29
29
|
@click.option(
|
30
30
|
"--name",
|
31
31
|
required=False,
|
32
|
-
help="Name for the generated
|
32
|
+
help="Name for the generated container",
|
33
33
|
)
|
34
34
|
@click.pass_context
|
35
35
|
def build(ctx: click.Context, path: str, dockerfile: str, name: str):
|
36
36
|
if not os.path.exists(os.path.join(path, dockerfile)):
|
37
37
|
raise click.ClickException(
|
38
|
-
f"No {dockerfile} found here. I cannot build the
|
38
|
+
f"No {dockerfile} found here. I cannot build the container."
|
39
39
|
)
|
40
40
|
if name is None:
|
41
41
|
name = "artefacts"
|
@@ -44,7 +44,21 @@ def build(ctx: click.Context, path: str, dockerfile: str, name: str):
|
|
44
44
|
print(f"Package complete in image: {image}")
|
45
45
|
|
46
46
|
|
47
|
-
@
|
47
|
+
@containers.command()
|
48
|
+
@click.argument("name")
|
49
|
+
@click.pass_context
|
50
|
+
def check(ctx: click.Context, name: str):
|
51
|
+
if name is None:
|
52
|
+
name = "artefacts"
|
53
|
+
handler = ContainerMgr()
|
54
|
+
result = handler.check(name)
|
55
|
+
if ctx.parent is None:
|
56
|
+
# Print only if the command is called directly.
|
57
|
+
print(f"Package {name} exists and ready to use.")
|
58
|
+
return result
|
59
|
+
|
60
|
+
|
61
|
+
@containers.command()
|
48
62
|
@click.argument("image")
|
49
63
|
@click.argument("jobname")
|
50
64
|
@click.option(
|
@@ -53,8 +67,14 @@ def build(ctx: click.Context, path: str, dockerfile: str, name: str):
|
|
53
67
|
default="artefacts.yaml",
|
54
68
|
help="Artefacts config file.",
|
55
69
|
)
|
70
|
+
@click.option(
|
71
|
+
"--with-gui",
|
72
|
+
"with_gui",
|
73
|
+
default=False,
|
74
|
+
help="Show any GUI if any is created by the test runs. By default, UI elements are run but hidden---only test logs are returned. Please note GUI often assume an X11 environment, typically with Qt, so this may not work without a appropriate environment.",
|
75
|
+
)
|
56
76
|
@click.pass_context
|
57
|
-
def run(ctx: click.Context, image: str, jobname: str, config: str):
|
77
|
+
def run(ctx: click.Context, image: str, jobname: str, config: str, with_gui: bool):
|
58
78
|
try:
|
59
79
|
artefacts_config = read_config(config)
|
60
80
|
except FileNotFoundError:
|
@@ -67,6 +87,7 @@ def run(ctx: click.Context, image: str, jobname: str, config: str):
|
|
67
87
|
jobname=jobname,
|
68
88
|
# Hidden setting primarily useful to Artefacts developers
|
69
89
|
api_url=os.environ.get("ARTEFACTS_API_URL", DEFAULT_API_URL),
|
90
|
+
with_gui=with_gui,
|
70
91
|
)
|
71
92
|
container, logs = handler.run(**params)
|
72
93
|
if container:
|
@@ -15,6 +15,12 @@ class CMgr:
|
|
15
15
|
"""
|
16
16
|
raise NotImplemented()
|
17
17
|
|
18
|
+
def check(self, image: str) -> bool:
|
19
|
+
"""
|
20
|
+
Checks whether a target image exists locally.
|
21
|
+
"""
|
22
|
+
raise NotImplemented()
|
23
|
+
|
18
24
|
def run(
|
19
25
|
self,
|
20
26
|
image: str,
|
@@ -22,6 +28,7 @@ class CMgr:
|
|
22
28
|
jobname: str = None,
|
23
29
|
artefacts_dir: str = Path("~/.artefacts").expanduser(),
|
24
30
|
api_url: str = DEFAULT_API_URL,
|
31
|
+
with_gui: bool = False,
|
25
32
|
) -> Tuple[Any, Generator]:
|
26
33
|
"""
|
27
34
|
Returns a container (Any type as depends on the framework)
|
@@ -45,7 +52,7 @@ class CMgr:
|
|
45
52
|
"""
|
46
53
|
if not path:
|
47
54
|
raise Exception(
|
48
|
-
"`path` must be a string, a Path object, or
|
55
|
+
"`path` must be a string, a Path object, or excluded from the kwargs"
|
49
56
|
)
|
50
57
|
if os.environ.get("ARTEFACTS_KEY", None):
|
51
58
|
return True
|
@@ -2,6 +2,7 @@ from collections.abc import Generator
|
|
2
2
|
import json
|
3
3
|
import os
|
4
4
|
from pathlib import Path
|
5
|
+
import platform
|
5
6
|
from typing import Any, Tuple
|
6
7
|
from uuid import uuid4
|
7
8
|
|
@@ -39,6 +40,12 @@ class DockerManager(CMgr):
|
|
39
40
|
img_id = self.client.inspect_image(kwargs["tag"])["Id"]
|
40
41
|
return img_id, iter(logs)
|
41
42
|
|
43
|
+
def check(
|
44
|
+
self,
|
45
|
+
image: str,
|
46
|
+
) -> bool:
|
47
|
+
return len(self.client.images(name=image)) > 0
|
48
|
+
|
42
49
|
def run(
|
43
50
|
self,
|
44
51
|
image: str,
|
@@ -46,6 +53,7 @@ class DockerManager(CMgr):
|
|
46
53
|
jobname: str = None,
|
47
54
|
artefacts_dir: str = Path("~/.artefacts").expanduser(),
|
48
55
|
api_url: str = DEFAULT_API_URL,
|
56
|
+
with_gui: bool = False,
|
49
57
|
) -> Tuple[Any, Generator]:
|
50
58
|
if not self._valid_artefacts_api_key(project, artefacts_dir):
|
51
59
|
return None, iter(
|
@@ -60,6 +68,15 @@ class DockerManager(CMgr):
|
|
60
68
|
"ARTEFACTS_API_URL": api_url,
|
61
69
|
}
|
62
70
|
|
71
|
+
if platform.system() in ["Darwin", "Windows"]:
|
72
|
+
# Assume we run in Docker Desktop
|
73
|
+
env["DISPLAY"] = "host.docker.internal:0"
|
74
|
+
else:
|
75
|
+
env["DISPLAY"] = os.environ.get("DISPLAY", ":0")
|
76
|
+
|
77
|
+
if not with_gui:
|
78
|
+
env["QT_QPA_PLATFORM"] = "offscreen"
|
79
|
+
|
63
80
|
container = self.client.create_container(
|
64
81
|
image,
|
65
82
|
environment=env,
|
@@ -72,6 +89,7 @@ class DockerManager(CMgr):
|
|
72
89
|
"mode": "ro",
|
73
90
|
},
|
74
91
|
},
|
92
|
+
network_mode="host",
|
75
93
|
),
|
76
94
|
)
|
77
95
|
self.client.start(container=container.get("Id"))
|
@@ -50,5 +50,8 @@ class ContainerMgr:
|
|
50
50
|
def build(self, **kwargs) -> Tuple[str, Generator]:
|
51
51
|
return self.mgr.build(**kwargs)
|
52
52
|
|
53
|
+
def check(self, image: str) -> bool:
|
54
|
+
return self.mgr.check(image)
|
55
|
+
|
53
56
|
def run(self, **kwargs) -> Tuple[Any, Generator]:
|
54
57
|
return self.mgr.run(**kwargs)
|
artefacts/cli/version.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: artefacts_cli
|
3
|
-
Version: 0.6.
|
3
|
+
Version: 0.6.17
|
4
4
|
Author-email: FD <fabian@artefacts.com>, AGC <alejandro@artefacts.com>, TN <tomo@artefacts.com>, EP <eric@artefacts.com>
|
5
5
|
Project-URL: Homepage, https://github.com/art-e-fact/artefacts-client
|
6
6
|
Project-URL: Bug Tracker, https://github.com/art-e-fact/artefacts-client/issues
|
@@ -18,6 +18,7 @@ Requires-Dist: mcap-ros2-support
|
|
18
18
|
Requires-Dist: PyYAML>=6.0
|
19
19
|
Requires-Dist: requests>=2.27.1
|
20
20
|
Requires-Dist: setuptools-scm
|
21
|
+
Requires-Dist: setuptools>=74
|
21
22
|
Provides-Extra: dev
|
22
23
|
Requires-Dist: awscli; extra == "dev"
|
23
24
|
Requires-Dist: build; extra == "dev"
|
@@ -0,0 +1,21 @@
|
|
1
|
+
artefacts/cli/__init__.py,sha256=--1soc8cqq1JWhz4DuRUvJWgSeDCPGqm8mEmdqtclsI,11644
|
2
|
+
artefacts/cli/app.py,sha256=cxVVHD89_eVCHm5fqPq3ANuy6jTPfw3se-FST_7wILY,22093
|
3
|
+
artefacts/cli/app_containers.py,sha256=tHdGkxtzjexLhgcx5YXy_OOJsPcBi1jmwKZN01OAcmU,3044
|
4
|
+
artefacts/cli/bagparser.py,sha256=FE_QaztC9pg4hQzTjGSdyve6mzZbHJbyqa3wqvZSbxE,3702
|
5
|
+
artefacts/cli/constants.py,sha256=bvsVDwqkAc49IZN7j6k6IL6EG87bECHd_VINtKJqbv8,320
|
6
|
+
artefacts/cli/other.py,sha256=7NvzlspvG0zF7sryR-QznwdLupXLln1BKWxHB9VuEcc,1160
|
7
|
+
artefacts/cli/parameters.py,sha256=MDhrM7ur95wKTLDteqz2f-sLdCPcepi5wk0XjeLo6TU,788
|
8
|
+
artefacts/cli/ros1.py,sha256=RbtirCGarD9a0ikfuGK-pdpWYSXfqJhEt4rpA0uFsyU,9625
|
9
|
+
artefacts/cli/ros2.py,sha256=YaCi3HRuCdvCTjM0Ftnm-SLgMOy1OneIr0aU7KVTiAM,4476
|
10
|
+
artefacts/cli/utils.py,sha256=6yQJRzv-xaLbtcA73Tty9C9QZeV06n5pjXMYl3xsLPE,3156
|
11
|
+
artefacts/cli/utils_ros.py,sha256=pYbhAU9fK2VbnWm3nSLBwUMVBzsZuCn10SFZmVW3-Zo,2090
|
12
|
+
artefacts/cli/version.py,sha256=q7Xb4Wt4eH2VCIhiAa6149XDeUKQFfphqlwqiTFiurk,413
|
13
|
+
artefacts/cli/containers/__init__.py,sha256=y6NVB0efBfRQBlHb71xhRu1hEh7t2bkKNs2vtsLJaO8,2239
|
14
|
+
artefacts/cli/containers/docker.py,sha256=A9jqs0WU-g8umJzPpEACi0_DU5N8rglR-V3dmwxDuBA,3507
|
15
|
+
artefacts/cli/containers/utils.py,sha256=6Bw6s1ceEnTbWSdE5_1CReNW6RB29VeHsq-BAwcJ_fY,1895
|
16
|
+
artefacts/wrappers/artefacts_ros1_meta.launch,sha256=9tN7_0xLH8jW27KYFerhF3NuWDx2dED3ks_qoGVZAPw,1412
|
17
|
+
artefacts_cli-0.6.17.dist-info/METADATA,sha256=aiDZPGqyOGAS_pS3XnjIk4IAStv_vS3fUOW3qPyEH-s,3051
|
18
|
+
artefacts_cli-0.6.17.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
19
|
+
artefacts_cli-0.6.17.dist-info/entry_points.txt,sha256=nlTXRzilNjccbi53FgaRWCQPkG-pv61HRkaCkrKjlec,58
|
20
|
+
artefacts_cli-0.6.17.dist-info/top_level.txt,sha256=FdaMV1C9m36MWa-2Stm5xVODv7hss_nRYNwR83j_7ow,10
|
21
|
+
artefacts_cli-0.6.17.dist-info/RECORD,,
|
@@ -1,21 +0,0 @@
|
|
1
|
-
artefacts/cli/__init__.py,sha256=9rTAfBoS9ALJxKSqaUo32ThbDshbvNN4-EmoyUsPhRI,11643
|
2
|
-
artefacts/cli/app.py,sha256=597uPtK4A_wujvqhk5h4KkrXV_XVkDLpymedd2lZB5k,20140
|
3
|
-
artefacts/cli/app_containers.py,sha256=7OAtc4n9YeK8ZYUKvteOMbZr7lYjx_YMa6tu8Pnu9Yc,2280
|
4
|
-
artefacts/cli/bagparser.py,sha256=FE_QaztC9pg4hQzTjGSdyve6mzZbHJbyqa3wqvZSbxE,3702
|
5
|
-
artefacts/cli/constants.py,sha256=bvsVDwqkAc49IZN7j6k6IL6EG87bECHd_VINtKJqbv8,320
|
6
|
-
artefacts/cli/other.py,sha256=7NvzlspvG0zF7sryR-QznwdLupXLln1BKWxHB9VuEcc,1160
|
7
|
-
artefacts/cli/parameters.py,sha256=MDhrM7ur95wKTLDteqz2f-sLdCPcepi5wk0XjeLo6TU,788
|
8
|
-
artefacts/cli/ros1.py,sha256=RbtirCGarD9a0ikfuGK-pdpWYSXfqJhEt4rpA0uFsyU,9625
|
9
|
-
artefacts/cli/ros2.py,sha256=YaCi3HRuCdvCTjM0Ftnm-SLgMOy1OneIr0aU7KVTiAM,4476
|
10
|
-
artefacts/cli/utils.py,sha256=6yQJRzv-xaLbtcA73Tty9C9QZeV06n5pjXMYl3xsLPE,3156
|
11
|
-
artefacts/cli/utils_ros.py,sha256=pYbhAU9fK2VbnWm3nSLBwUMVBzsZuCn10SFZmVW3-Zo,2090
|
12
|
-
artefacts/cli/version.py,sha256=zbqzBVUYJbK8o4vMJuNyIN5tBM9QXVZa7XiEM2PNdR8,413
|
13
|
-
artefacts/cli/containers/__init__.py,sha256=S3DXLsb0csUdfjOZIngTfhMHrmYAaWBeu5EctLEEXbM,2057
|
14
|
-
artefacts/cli/containers/docker.py,sha256=RtUOMbtWHQumTtDRa0ALjJ29tSaa7Pp497Ah1aJ7nZ4,2964
|
15
|
-
artefacts/cli/containers/utils.py,sha256=5yUoREHM9AxnTkDNCY-DFUPSR5OWtu1rNxIVs6n5zZo,1816
|
16
|
-
artefacts/wrappers/artefacts_ros1_meta.launch,sha256=9tN7_0xLH8jW27KYFerhF3NuWDx2dED3ks_qoGVZAPw,1412
|
17
|
-
artefacts_cli-0.6.16.dist-info/METADATA,sha256=OLy7Jmo_RMo9CiktBZSKiZRN1HVILJkuhz-W24YB0RA,3021
|
18
|
-
artefacts_cli-0.6.16.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
19
|
-
artefacts_cli-0.6.16.dist-info/entry_points.txt,sha256=nlTXRzilNjccbi53FgaRWCQPkG-pv61HRkaCkrKjlec,58
|
20
|
-
artefacts_cli-0.6.16.dist-info/top_level.txt,sha256=FdaMV1C9m36MWa-2Stm5xVODv7hss_nRYNwR83j_7ow,10
|
21
|
-
artefacts_cli-0.6.16.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|