embodied-first-exam 0.1.0__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.
@@ -0,0 +1,32 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ .venv/
6
+ .pytest_cache/
7
+ .ipynb_checkpoints/
8
+ # run outputs and logs
9
+ /exps/
10
+ /jobs/
11
+ *.log
12
+ nohup.out
13
+ # secrets
14
+ .env
15
+ .env.*
16
+ !.env.example
17
+ # editor, OS and merge leftovers
18
+ .DS_Store
19
+ Thumbs.db
20
+ *.swp
21
+ *~
22
+ *.bak
23
+ *.bak-*
24
+ *.orig
25
+ *.rej
26
+ *.tmp
27
+ # build contexts that scripts stage (images/<name>/BUILD_CONTEXT); images/ese/context/ is the committed snapshot
28
+ /images/*/context/
29
+ !/images/ese/context/
30
+ images/mujoco/rcb_mj/
31
+ # generated (scripts/dataset_manifest.py write)
32
+ /tasks/dataset.toml
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Kangrui Wang and Embodied First Exam contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,27 @@
1
+ Metadata-Version: 2.5
2
+ Name: embodied-first-exam
3
+ Version: 0.1.0
4
+ Summary: Embodied First Exam on Harbor: `harbor run --core|--all|--privileged|--standard|--standard-realtime`, or `efe run`
5
+ Project-URL: Homepage, https://www.embodied-first-exam.ai
6
+ Project-URL: Repository, https://github.com/mll-lab-nu/embodied-first-exam
7
+ License-Expression: MIT
8
+ License-File: LICENSE
9
+ Requires-Python: <3.15,>=3.12
10
+ Requires-Dist: harbor==0.23.0
11
+ Description-Content-Type: text/markdown
12
+
13
+ # Embodied First Exam
14
+
15
+ Code agents program robots in simulation: [embodied-first-exam.ai](https://www.embodied-first-exam.ai),
16
+ [github.com/mll-lab-nu/embodied-first-exam](https://github.com/mll-lab-nu/embodied-first-exam).
17
+
18
+ ```bash
19
+ # needs git and Docker with Compose; GPU tasks also need an NVIDIA GPU and the NVIDIA Container Toolkit
20
+ uv tool install embodied-first-exam --with-executables-from harbor
21
+ # your API keys: in the shell, or in a .env file in the working directory
22
+ # the core set; the tasks are cloned on first use (a clone you run from, or $EFE_ROOT, is used instead)
23
+ harbor run -d embodied-first-exam -a codex -m openai/gpt-6-astra
24
+ ```
25
+
26
+ This installs Harbor 0.23.0 with the benchmark's flags on `harbor run` and the `efe` command. The tasks are not in
27
+ the package: see the repository's README.
@@ -0,0 +1,49 @@
1
+ [project]
2
+ name = "embodied-first-exam"
3
+ version = "0.1.0"
4
+ description = "Embodied First Exam on Harbor: `harbor run --core|--all|--privileged|--standard|--standard-realtime`, or `efe run`"
5
+ readme = { content-type = "text/markdown", text = """
6
+ # Embodied First Exam
7
+
8
+ Code agents program robots in simulation: [embodied-first-exam.ai](https://www.embodied-first-exam.ai),
9
+ [github.com/mll-lab-nu/embodied-first-exam](https://github.com/mll-lab-nu/embodied-first-exam).
10
+
11
+ ```bash
12
+ # needs git and Docker with Compose; GPU tasks also need an NVIDIA GPU and the NVIDIA Container Toolkit
13
+ uv tool install embodied-first-exam --with-executables-from harbor
14
+ # your API keys: in the shell, or in a .env file in the working directory
15
+ # the core set; the tasks are cloned on first use (a clone you run from, or $EFE_ROOT, is used instead)
16
+ harbor run -d embodied-first-exam -a codex -m openai/gpt-6-astra
17
+ ```
18
+
19
+ This installs Harbor 0.23.0 with the benchmark's flags on `harbor run` and the `efe` command. The tasks are not in
20
+ the package: see the repository's README.
21
+ """ }
22
+ license = "MIT"
23
+ license-files = ["LICENSE"]
24
+ requires-python = ">=3.12,<3.15" # Harbor's dependency fastuuid has no wheel for newer Pythons yet
25
+ dependencies = ["harbor==0.23.0"]
26
+
27
+ [project.urls]
28
+ Homepage = "https://www.embodied-first-exam.ai"
29
+ Repository = "https://github.com/mll-lab-nu/embodied-first-exam"
30
+
31
+ [project.scripts]
32
+ efe = "efe:main"
33
+
34
+ [build-system]
35
+ requires = ["hatchling>=1.27"]
36
+ build-backend = "hatchling.build"
37
+
38
+ # The wheel: scripts/efe.py, efe_harbor_hook.py and efe-harbor.pth, nothing else (the tasks are found at run time,
39
+ # scripts/efe.py find_root). An editable install (`uv tool install -e .`) puts scripts/ on the path instead.
40
+ [tool.hatch.build.targets.wheel]
41
+ only-include = ["scripts/efe.py", "scripts/efe_harbor_hook.py"]
42
+ sources = ["scripts"]
43
+ dev-mode-dirs = ["scripts"]
44
+
45
+ [tool.hatch.build.targets.wheel.force-include]
46
+ "scripts/efe-harbor.pth" = "efe-harbor.pth"
47
+
48
+ [tool.hatch.build.targets.sdist]
49
+ only-include = ["scripts/efe.py", "scripts/efe_harbor_hook.py", "scripts/efe-harbor.pth", "LICENSE"]
@@ -0,0 +1 @@
1
+ import efe_harbor_hook
@@ -0,0 +1,294 @@
1
+ #!/usr/bin/env python3
2
+ """Embodied First Exam runs on Harbor. `uv tool install --force -e . --with-executables-from harbor` (in a clone) or
3
+ `pip install embodied-first-exam` installs `harbor` (Harbor 0.23.0, plus the flags below on `harbor run`) and `efe` (the
4
+ same, `efe run ...`). Run from anywhere. The tasks: $EFE_ROOT, else the clone that contains the working directory, else
5
+ the clone of an editable install, else a shallow clone of the release tag v<version> made on first use in
6
+ ~/.cache/embodied-first-exam/<version> (find_root).
7
+
8
+ harbor run -a codex -m openai/gpt-6-astra # core: each core task in its default mode (the default)
9
+ harbor run --core --privileged -a codex -m openai/gpt-6-astra # the core tasks in another mode (also --standard, --standard-realtime)
10
+ harbor run --all -a codex -m openai/gpt-6-astra # every task dir
11
+ harbor run --all --privileged -i 'robotwin_2_0_*' -a oracle # mode flags and -i / -x filter within the set
12
+ harbor run --benchmark roboarc -a codex -m openai/gpt-6-astra # one benchmark's core tasks
13
+ harbor run -d embodied-first-exam@core -a codex -m openai/gpt-6-astra # the same sets as a dataset: @core, @all
14
+ harbor run -p tasks/<benchmark>/<task> -a nop # one task: Harbor's own -p, untouched
15
+ harbor run -p tasks/<benchmark> -a nop # every task of one benchmark: Harbor's own -p, untouched
16
+
17
+ Set: --core (default) or --all. core = the tasks of docs/core_set.toml, each in its default_mode; with mode flags, each
18
+ core task in those modes (a task without that mode is skipped, and counted). all = every task dir; mode flags filter it.
19
+ Modes: any of --privileged, --standard, --standard-realtime.
20
+ -d embodied-first-exam[@core|@all] (also `efe`) is --core / --all (no version: core); any other -d is Harbor's.
21
+ --benchmark <name> keeps a benchmark: its README label or its folder under tasks/ (repeatable). With any of these flags,
22
+ -p <dir> (a task dir, a benchmark folder or tasks/) narrows the set to the task dirs under it, -l <n> keeps the first n of
23
+ them, and -c <file> is layered after the wrapper's job config. --list prints the task dirs and runs nothing. The tasks
24
+ are stamped in place (scripts/stamp_mtimes.py) and handed to Harbor as one dataset per benchmark folder (Harbor's
25
+ local datasets are not searched recursively). A
26
+ `harbor run` that names its own tasks (-p, -d, -t, -c) and none of these flags is Harbor's, unchanged; so is every other
27
+ subcommand."""
28
+ import fnmatch, json, os, shutil, subprocess, sys, tempfile
29
+ from pathlib import Path
30
+
31
+ # --- the task tree (board 0209): where the tasks and their scripts/ come from -------------------------------------------
32
+ REPO_URL = "https://github.com/mll-lab-nu/embodied-first-exam.git"
33
+ _ROOT: list[Path] = []
34
+
35
+
36
+ def is_tree(d: Path) -> bool:
37
+ """A checkout of this repository: the core set, the tasks and the scripts that read them."""
38
+ return (d / "docs/core_set.toml").is_file() and (d / "tasks").is_dir() and (d / "scripts/task_conventions.py").is_file()
39
+
40
+
41
+ def cache_dir() -> Path:
42
+ from importlib.metadata import PackageNotFoundError, version
43
+ try:
44
+ ver = version("embodied-first-exam")
45
+ except PackageNotFoundError:
46
+ ver = "main"
47
+ return Path(os.environ.get("XDG_CACHE_HOME") or Path.home() / ".cache") / "embodied-first-exam" / ver
48
+
49
+
50
+ def cached_clone(d: Path) -> Path:
51
+ """`git clone --depth 1` of the tag v<version> (main when there is no such tag) into d, once; SystemExit(2) on failure."""
52
+ tag = "main" if d.name == "main" else f"v{d.name}"
53
+ try:
54
+ r = subprocess.run(["git", "ls-remote", "--exit-code", "--tags", REPO_URL, f"refs/tags/{tag}"], capture_output=True)
55
+ except FileNotFoundError:
56
+ print("efe: the tasks need git (no clone here, no EFE_ROOT)", file=sys.stderr); raise SystemExit(2)
57
+ if r.returncode not in (0, 2):
58
+ print(f"efe: cannot reach {REPO_URL} (git ls-remote exit {r.returncode}); clone it and run from there, or set "
59
+ "EFE_ROOT", file=sys.stderr); raise SystemExit(2)
60
+ if tag != "main" and r.returncode == 2:
61
+ print(f"efe: {REPO_URL} has no tag {tag}: using main instead (delete {d} to clone again later)", file=sys.stderr)
62
+ tag = "main"
63
+ print(f"efe: no clone here and no EFE_ROOT: cloning the tasks ({tag}) into {d}, once", file=sys.stderr)
64
+ d.parent.mkdir(parents=True, exist_ok=True)
65
+ tmp = tempfile.mkdtemp(prefix=f".{d.name}-", dir=d.parent)
66
+ try:
67
+ if subprocess.run(["git", "clone", "--depth", "1", "--branch", tag, REPO_URL, tmp]).returncode:
68
+ print(f"efe: git clone of {tag} failed", file=sys.stderr); raise SystemExit(2)
69
+ if not is_tree(d): # else another run made it meanwhile
70
+ try:
71
+ os.rename(tmp, d)
72
+ except OSError as e:
73
+ print(f"efe: cannot place the clone at {d} ({e}); remove {d} and run again", file=sys.stderr)
74
+ raise SystemExit(2)
75
+ finally:
76
+ shutil.rmtree(tmp, ignore_errors=True)
77
+ return d
78
+
79
+
80
+ def find_root(clone: bool = True) -> Path | None:
81
+ """The task tree: $EFE_ROOT; else the checkout that contains the working directory; else the checkout this file is in
82
+ (`uv tool install -e .`); else the cached clone (made here on first use when clone; None when not)."""
83
+ if _ROOT:
84
+ return _ROOT[0]
85
+ cwd = Path.cwd().resolve()
86
+ if os.environ.get("EFE_ROOT"):
87
+ d = Path(os.environ["EFE_ROOT"]).expanduser().resolve()
88
+ if not is_tree(d):
89
+ print(f"EFE_ROOT={d}: not a checkout of {REPO_URL}", file=sys.stderr); raise SystemExit(2)
90
+ else:
91
+ d = next((p for p in (cwd, *cwd.parents, Path(__file__).resolve().parents[1], cache_dir()) if is_tree(p)), None)
92
+ if d is None and clone:
93
+ d = cached_clone(cache_dir())
94
+ if d is not None:
95
+ _ROOT.append(d)
96
+ return d
97
+
98
+
99
+ class _Scripts:
100
+ """The task tree's own scripts/<name>.py (task_conventions, stamp_mtimes), imported on first use."""
101
+ def __init__(self, name: str):
102
+ self._name = name
103
+
104
+ def __getattr__(self, attr: str):
105
+ import importlib
106
+ d = str(find_root() / "scripts")
107
+ if d not in sys.path:
108
+ sys.path.insert(0, d)
109
+ return getattr(importlib.import_module(self._name), attr)
110
+
111
+
112
+ tc = _Scripts("task_conventions")
113
+ # ------------------------------------------------------------------------------------------------------------------------
114
+
115
+ MODES = {"--privileged": "privileged", "--privilege": "privileged", "--standard": "standard",
116
+ "--standard-realtime": "standard-realtime", "--standard_realtime": "standard-realtime"}
117
+ DATASET = ("embodied-first-exam", "efe")
118
+ SOURCES = ("-p", "--path", "-d", "--dataset", "-t", "--task", "-c", "--config", "--task-git-url")
119
+
120
+
121
+ def harbor(args: list[str], app=None) -> int:
122
+ if app is None:
123
+ from harbor.cli import main as hm
124
+ app = getattr(hm.app, "__wrapped_app__", hm.app)
125
+ sys.argv = ["harbor", *args]
126
+ return app() or 0
127
+
128
+
129
+ def bench_label(name: str) -> str | None:
130
+ """A --benchmark value as its BENCHMARKS label: the label itself (any case) or its folder under tasks/."""
131
+ by = {**{lab.lower(): lab for lab in tc.BENCHMARK_DIRS}, **{f: lab for lab, f in tc.BENCHMARK_DIRS.items()}}
132
+ return by.get(name) or by.get(name.lower())
133
+
134
+
135
+ def under(paths: list[str]) -> set[str] | None:
136
+ """The task dir names under the -p paths (a task dir, a benchmark folder, tasks/; a relative path that is not one
137
+ here is taken in this clone, so `-p tasks/<benchmark>` works from anywhere); None: no -p given. SystemExit(2): a path
138
+ that is neither."""
139
+ if not paths:
140
+ return None
141
+ out: set[str] = set()
142
+ for a in paths:
143
+ d = Path(a).expanduser()
144
+ if not d.is_dir() and not d.is_absolute() and (find_root() / d).is_dir():
145
+ d = find_root() / d
146
+ if not d.is_dir():
147
+ print(f"-p {a}: no such directory (here or in {find_root()})", file=sys.stderr)
148
+ raise SystemExit(2)
149
+ d = d.resolve()
150
+ if (d / "task.toml").is_file():
151
+ out.add(d.name)
152
+ else:
153
+ out |= {t.parent.name for pat in ("*/task.toml", "*/*/task.toml") for t in d.glob(pat)}
154
+ return out
155
+
156
+
157
+ def stamp(pick: list[str]) -> bool:
158
+ """Give the picked task dirs' files their content-derived mtimes in place before Harbor builds any image from them
159
+ (scripts/stamp_mtimes.py, issue #258: a checkout's shared mtimes let BuildKit put another task's file in an image).
160
+ Files already stamped are skipped. False: a file could not be stamped."""
161
+ stamp_mtimes = _Scripts("stamp_mtimes")
162
+ err = sum(stamp_mtimes.stamp_tree(str(tc.task_dir(t)))["err"] for t in pick)
163
+ if err:
164
+ print(f"stamp_mtimes: {err} file(s) could not be stamped; no image is built from an unstamped task "
165
+ "(docs/protocol/running.md, Building task images)", file=sys.stderr)
166
+ return not err
167
+
168
+
169
+ def config_file(pick: list[str]) -> str:
170
+ """A Harbor job config (-c) with the picked task dirs: one local dataset per benchmark folder, its task_names the
171
+ picked dirs. Harbor reads it when the job is built; the caller removes it afterwards."""
172
+ by: dict[str, list[str]] = {}
173
+ for t in pick:
174
+ by.setdefault(str(tc.task_dir(t).parent), []).append(t)
175
+ cfg = {"datasets": [{"path": d, "task_names": names} for d, names in sorted(by.items())]}
176
+ fd, path = tempfile.mkstemp(prefix="efe-job-", suffix=".json")
177
+ with os.fdopen(fd, "w") as f:
178
+ json.dump(cfg, f, indent=1)
179
+ return path
180
+
181
+
182
+ def load_env() -> None:
183
+ """The working directory's and the clone's .env (cp .env.example .env) into the environment: their non-empty keys
184
+ the shell does not set (no clone is made for it)."""
185
+ from dotenv import dotenv_values
186
+ root = find_root(clone=False)
187
+ for f in dict.fromkeys([Path.cwd() / ".env", *([root / ".env"] if root else [])]):
188
+ for k, v in dotenv_values(f).items() if f.is_file() else ():
189
+ if v and not v.startswith("#") and k not in os.environ: # `KEY= # note`: dotenv reads the note as the value
190
+ os.environ[k] = v
191
+
192
+
193
+ def dataset_sets(argv: list[str]) -> list[str] | None:
194
+ """argv with -d embodied-first-exam[@core|@all] turned into --core / --all; None: an unknown version."""
195
+ out, it = [], iter(argv)
196
+ for a in it:
197
+ v = a.split("=", 1)[1] if a.startswith("--dataset=") else next(it, "") if a in ("-d", "--dataset") else None
198
+ name, _, ver = (v or "").partition("@")
199
+ if v is None or name not in DATASET:
200
+ out += [a] if v is None or a.startswith("--dataset=") else [a, v]
201
+ elif ver in ("", "core", "all"):
202
+ out.append("--" + (ver or "core"))
203
+ else:
204
+ print(f"-d {v}: the versions are {name}@core and {name}@all", file=sys.stderr)
205
+ return None
206
+ return out
207
+
208
+
209
+ def run(argv: list[str], app=None) -> int:
210
+ """`harbor run` with the set / mode / benchmark flags: picks the task dirs, then `harbor run -c <job config> ...`
211
+ (config_file: one dataset per benchmark folder)."""
212
+ argv = dataset_sets(argv)
213
+ if argv is None:
214
+ return 2
215
+ load_env()
216
+ ours = ("--core", "--all", "--benchmark", "--list")
217
+ if any(a in SOURCES or a.startswith(tuple(s + "=" for s in SOURCES if s.startswith("--"))) for a in argv):
218
+ if not any(a in MODES or a in ours or a.startswith("--benchmark=") for a in argv):
219
+ return harbor(["run", *argv], app) # the user's own task source: plain Harbor
220
+ which, modes, benches, inc, exc, paths, listing, rest = "core", set(), [], [], [], [], False, []
221
+ n_tasks = None
222
+ it = iter(argv)
223
+ for a in it:
224
+ if a in ("--all", "--core"):
225
+ which = a[2:]
226
+ elif a in MODES:
227
+ modes.add(MODES[a])
228
+ elif a == "--benchmark" or a.startswith("--benchmark="):
229
+ b = a.split("=", 1)[1] if "=" in a else next(it, "")
230
+ lab = bench_label(b)
231
+ if lab is None:
232
+ print(f"--benchmark {b!r}: not a benchmark (a README label or a folder under tasks/: "
233
+ f"{', '.join(sorted(tc.BENCHMARK_DIRS.values()))})", file=sys.stderr)
234
+ return 2
235
+ benches.append(lab)
236
+ elif a in ("-i", "--include-task-name") or a.startswith("--include-task-name="):
237
+ inc.append(a.split("=", 1)[1] if "=" in a else next(it, ""))
238
+ elif a in ("-x", "--exclude-task-name") or a.startswith("--exclude-task-name="):
239
+ exc.append(a.split("=", 1)[1] if "=" in a else next(it, ""))
240
+ elif a in ("-l", "--n-tasks") or a.startswith("--n-tasks="): # Harbor's -l: applied here, to the picked set
241
+ v = a.split("=", 1)[1] if "=" in a else next(it, "")
242
+ if not v.isdigit():
243
+ print(f"{a} {v!r}: the number of tasks to run", file=sys.stderr); return 2
244
+ n_tasks = int(v)
245
+ elif a in ("-p", "--path") or a.startswith("--path="):
246
+ paths.append(a.split("=", 1)[1] if "=" in a else next(it, ""))
247
+ elif a in ("-c", "--config"):
248
+ rest += [a, next(it, "")] # the user's config: layered after ours
249
+ elif a in SOURCES or a.startswith(tuple(s + "=" for s in SOURCES if s.startswith("--") and s != "--config")):
250
+ print(f"{a}: names its own tasks; it does not combine with {', '.join((*ours, *MODES))}", file=sys.stderr)
251
+ return 2
252
+ elif a == "--list":
253
+ listing = True
254
+ elif a in ("-h", "--help"):
255
+ print(__doc__); return harbor(["run", "--help"], app)
256
+ else:
257
+ rest.append(a)
258
+ tasks = [t.name for t in tc.iter_tasks()]
259
+ missing: dict[str, list[str]] = {}
260
+ pick = tasks if which == "all" else sorted(set(tc.core_tasks(modes, missing=missing)) & set(tasks))
261
+ for m, ts in sorted(missing.items()):
262
+ print(f"{len(ts)} core task(s) have no {m} mode: skipped", file=sys.stderr)
263
+ scope = under(paths)
264
+ pick = [t for t in pick if (scope is None or t in scope)
265
+ and (not modes or tc.mode_of(Path(t)) in modes)
266
+ and (not benches or tc.bench_of(Path(t)) in benches)
267
+ and (not inc or any(fnmatch.fnmatchcase(t, p) for p in inc))
268
+ and not any(fnmatch.fnmatchcase(t, p) for p in exc)]
269
+ pick = pick[:n_tasks] if n_tasks is not None else pick
270
+ if not pick:
271
+ print("no task matches", file=sys.stderr); return 2
272
+ print(f"{len(pick)} task(s) of " + which + (f", {', '.join(sorted(modes))}" if modes else "")
273
+ + (f", {', '.join(sorted(set(benches)))}" if benches else ""), file=sys.stderr)
274
+ if listing:
275
+ print("\n".join(pick)); return 0
276
+ if not stamp(pick):
277
+ return 2
278
+ cfg = config_file(pick)
279
+ try:
280
+ return harbor(["run", "-c", cfg, *rest], app)
281
+ finally:
282
+ os.unlink(cfg)
283
+
284
+
285
+ def main() -> int:
286
+ """The `efe` command: `efe run ...` = `harbor run ...` above, `efe` alone prints this help."""
287
+ argv = sys.argv[1:]
288
+ if not argv or argv[0] in ("-h", "--help"):
289
+ print(__doc__.replace("harbor run", "efe run")); return 0
290
+ return run(argv[1:]) if argv[0] == "run" else harbor(argv)
291
+
292
+
293
+ if __name__ == "__main__":
294
+ sys.exit(main())
@@ -0,0 +1,33 @@
1
+ """Loaded at interpreter start by efe-harbor.pth (installed with this repo: `uv tool install --force -e .`): when
2
+ Harbor's CLI module is imported, its `app` is wrapped so that `harbor run` takes --core / --all / --privileged /
3
+ --standard / --standard-realtime (scripts/efe.py). Harbor's own options and subcommands are unchanged."""
4
+ import importlib.abc, importlib.machinery, sys
5
+
6
+
7
+ class _Finder(importlib.abc.MetaPathFinder):
8
+ def find_spec(self, name, path, target=None):
9
+ if name != "harbor.cli.main":
10
+ return None
11
+ sys.meta_path.remove(self)
12
+ spec = importlib.machinery.PathFinder.find_spec(name, path)
13
+ if spec is None or spec.loader is None:
14
+ return spec
15
+ exec_module = spec.loader.exec_module
16
+
17
+ def wrapped(module):
18
+ exec_module(module)
19
+ app = module.app
20
+
21
+ def harbor_app(*a, **kw):
22
+ if not a and not kw and sys.argv[1:2] == ["run"]:
23
+ import efe
24
+ return efe.run(sys.argv[2:], app=app)
25
+ return app(*a, **kw)
26
+ harbor_app.__wrapped_app__ = app
27
+ module.app = harbor_app
28
+ spec.loader.exec_module = wrapped
29
+ return spec
30
+
31
+
32
+ if not any(isinstance(f, _Finder) for f in sys.meta_path):
33
+ sys.meta_path.insert(0, _Finder())