experimaestro 1.14.0__tar.gz → 1.15.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.
Potentially problematic release.
This version of experimaestro might be problematic. Click here for more details.
- {experimaestro-1.14.0 → experimaestro-1.15.0}/PKG-INFO +1 -1
- {experimaestro-1.14.0 → experimaestro-1.15.0}/pyproject.toml +2 -2
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/core/identifier.py +11 -6
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/core/objects/config.py +16 -165
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/core/objects/config_walk.py +1 -5
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/core/objects.pyi +2 -6
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/core/serializers.py +1 -8
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/test_dependencies.py +0 -6
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/test_identifier.py +87 -76
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/test_instance.py +0 -12
- experimaestro-1.15.0/src/experimaestro/tests/test_serializers.py +54 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/test_tasks.py +0 -20
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/test_types.py +2 -2
- experimaestro-1.14.0/src/experimaestro/tests/test_serializers.py +0 -113
- {experimaestro-1.14.0 → experimaestro-1.15.0}/LICENSE +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/README.md +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/__init__.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/__main__.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/annotations.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/checkers.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/cli/__init__.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/cli/filter.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/cli/jobs.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/click.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/commandline.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/compat.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/connectors/__init__.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/connectors/local.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/connectors/ssh.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/core/__init__.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/core/arguments.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/core/callbacks.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/core/context.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/core/objects/__init__.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/core/objects/config_utils.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/core/serialization.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/core/types.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/core/utils.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/exceptions.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/experiments/__init__.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/experiments/cli.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/experiments/configuration.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/generators.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/huggingface.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/ipc.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/launcherfinder/__init__.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/launcherfinder/base.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/launcherfinder/parser.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/launcherfinder/registry.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/launcherfinder/specs.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/launchers/__init__.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/launchers/direct.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/launchers/oar.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/launchers/slurm/__init__.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/launchers/slurm/base.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/locking.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/mkdocs/__init__.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/mkdocs/annotations.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/mkdocs/base.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/mkdocs/metaloader.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/mkdocs/style.css +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/mypy.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/notifications.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/py.typed +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/rpyc.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/run.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/scheduler/__init__.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/scheduler/base.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/scheduler/dependencies.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/scheduler/dynamic_outputs.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/scheduler/services.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/scheduler/state.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/scheduler/workspace.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/scriptbuilder.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/server/__init__.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/server/data/0c35d18bf06992036b69.woff2 +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/server/data/1815e00441357e01619e.ttf +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/server/data/219aa9140e099e6c72ed.woff2 +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/server/data/2463b90d9a316e4e5294.woff2 +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/server/data/2582b0e4bcf85eceead0.ttf +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/server/data/3a4004a46a653d4b2166.woff +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/server/data/3baa5b8f3469222b822d.woff +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/server/data/4d73cb90e394b34b7670.woff +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/server/data/4ef4218c522f1eb6b5b1.woff2 +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/server/data/5d681e2edae8c60630db.woff +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/server/data/6f420cf17cc0d7676fad.woff2 +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/server/data/89999bdf5d835c012025.woff2 +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/server/data/914997e1bdfc990d0897.ttf +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/server/data/c210719e60948b211a12.woff2 +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/server/data/c380809fd3677d7d6903.woff2 +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/server/data/f882956fd323fd322f31.woff +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/server/data/favicon.ico +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/server/data/index.css +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/server/data/index.css.map +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/server/data/index.html +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/server/data/index.js +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/server/data/index.js.map +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/server/data/login.html +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/server/data/manifest.json +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/settings.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/sphinx/__init__.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/sphinx/static/experimaestro.css +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/taskglobals.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/__init__.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/conftest.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/connectors/bin/executable.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/connectors/test_local.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/connectors/utils.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/core/__init__.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/core/test_generics.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/definitions_types.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/launchers/__init__.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/launchers/bin/sacct +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/launchers/bin/sbatch +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/launchers/bin/srun +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/launchers/bin/test.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/launchers/common.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/launchers/config_slurm/__init__.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/launchers/config_slurm/launchers.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/launchers/test_local.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/launchers/test_slurm.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/restart.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/restart_main.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/scripts/notifyandwait.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/scripts/waitforfile.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/task_tokens.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/tasks/__init__.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/tasks/all.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/tasks/foreign.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/test_checkers.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/test_experiment.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/test_findlauncher.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/test_forward.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/test_generators.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/test_objects.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/test_outputs.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/test_param.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/test_progress.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/test_snippets.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/test_ssh.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/test_tags.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/test_tokens.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/test_validation.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/token_reschedule.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tests/utils.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tokens.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tools/__init__.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tools/diff.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tools/documentation.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/tools/jobs.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/typingutils.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/utils/__init__.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/utils/asyncio.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/utils/jobs.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/utils/jupyter.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/utils/multiprocessing.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/utils/resources.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/utils/settings.py +0 -0
- {experimaestro-1.14.0 → experimaestro-1.15.0}/src/experimaestro/xpmutils.py +0 -0
|
@@ -48,7 +48,7 @@ dependencies = [
|
|
|
48
48
|
"typing-extensions >=4.2; python_version < \"3.12\"",
|
|
49
49
|
"watchdog >=2"
|
|
50
50
|
]
|
|
51
|
-
version = "1.
|
|
51
|
+
version = "1.15.0"
|
|
52
52
|
|
|
53
53
|
[tool.poetry-dynamic-versioning]
|
|
54
54
|
enable = false
|
|
@@ -140,7 +140,7 @@ warn_unused_ignores = true
|
|
|
140
140
|
|
|
141
141
|
[tool.commitizen]
|
|
142
142
|
name = "cz_conventional_commits"
|
|
143
|
-
version = "1.
|
|
143
|
+
version = "1.15.0"
|
|
144
144
|
changelog_start_rev = "v1.0.0"
|
|
145
145
|
tag_format = "v$major.$minor.$patch$prerelease"
|
|
146
146
|
# update_changelog_on_bump = true
|
|
@@ -6,7 +6,7 @@ import logging
|
|
|
6
6
|
import os
|
|
7
7
|
import struct
|
|
8
8
|
from typing import Optional
|
|
9
|
-
from experimaestro.core.objects import Config
|
|
9
|
+
from experimaestro.core.objects import Config, ConfigMixin
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class ConfigPath:
|
|
@@ -116,7 +116,7 @@ class IdentifierComputer:
|
|
|
116
116
|
CYCLE_REFERENCE = b"\x0b"
|
|
117
117
|
INIT_TASKS = b"\x0c"
|
|
118
118
|
|
|
119
|
-
def __init__(self, config: "
|
|
119
|
+
def __init__(self, config: "ConfigMixin", config_path: ConfigPath, *, version=None):
|
|
120
120
|
# Hasher for parameters
|
|
121
121
|
self._hasher = hashlib.sha256()
|
|
122
122
|
self.config = config
|
|
@@ -170,7 +170,7 @@ class IdentifierComputer:
|
|
|
170
170
|
self._hashupdate(IdentifierComputer.ENUM_ID)
|
|
171
171
|
k = value.__class__
|
|
172
172
|
self._hashupdate(
|
|
173
|
-
f"{k.__module__}.{k.__qualname__
|
|
173
|
+
f"{k.__module__}.{k.__qualname__}:{value.name}".encode("utf-8"),
|
|
174
174
|
)
|
|
175
175
|
elif isinstance(value, dict):
|
|
176
176
|
self._hashupdate(IdentifierComputer.DICT_ID)
|
|
@@ -183,7 +183,7 @@ class IdentifierComputer:
|
|
|
183
183
|
self.update(value)
|
|
184
184
|
|
|
185
185
|
# Handles configurations
|
|
186
|
-
elif isinstance(value,
|
|
186
|
+
elif isinstance(value, ConfigMixin):
|
|
187
187
|
# Encodes the identifier
|
|
188
188
|
self._hashupdate(IdentifierComputer.OBJECT_ID)
|
|
189
189
|
|
|
@@ -264,12 +264,17 @@ class IdentifierComputer:
|
|
|
264
264
|
self._hashupdate(IdentifierComputer.NAME_ID)
|
|
265
265
|
self.update(argvalue)
|
|
266
266
|
|
|
267
|
+
# Add init tasks
|
|
268
|
+
if value.__xpm__.init_tasks:
|
|
269
|
+
self._hashupdate(IdentifierComputer.INIT_TASKS)
|
|
270
|
+
for init_task in value.__xpm__.init_tasks:
|
|
271
|
+
self.update(init_task)
|
|
267
272
|
else:
|
|
268
273
|
raise NotImplementedError("Cannot compute hash of type %s" % type(value))
|
|
269
274
|
|
|
270
275
|
@staticmethod
|
|
271
276
|
def compute(
|
|
272
|
-
config: "
|
|
277
|
+
config: "ConfigMixin", config_path: ConfigPath | None = None, version=None
|
|
273
278
|
) -> Identifier:
|
|
274
279
|
"""Compute the identifier for a configuration
|
|
275
280
|
|
|
@@ -281,7 +286,7 @@ class IdentifierComputer:
|
|
|
281
286
|
# Try to use the cached value first
|
|
282
287
|
# (if there are no loops)
|
|
283
288
|
if config.__xpm__._sealed:
|
|
284
|
-
identifier = config.__xpm__.
|
|
289
|
+
identifier = config.__xpm__._identifier
|
|
285
290
|
if identifier is not None and not identifier.has_loops:
|
|
286
291
|
return identifier
|
|
287
292
|
|
|
@@ -9,7 +9,6 @@ from experimaestro import taskglobals
|
|
|
9
9
|
|
|
10
10
|
from termcolor import cprint
|
|
11
11
|
from pathlib import Path
|
|
12
|
-
import hashlib
|
|
13
12
|
import logging
|
|
14
13
|
import io
|
|
15
14
|
from enum import Enum
|
|
@@ -20,7 +19,6 @@ from typing import (
|
|
|
20
19
|
Callable,
|
|
21
20
|
ClassVar,
|
|
22
21
|
Dict,
|
|
23
|
-
Iterator,
|
|
24
22
|
List,
|
|
25
23
|
Optional,
|
|
26
24
|
Set,
|
|
@@ -49,7 +47,6 @@ from .config_walk import ConfigWalk, ConfigWalkContext
|
|
|
49
47
|
from .config_utils import (
|
|
50
48
|
getqualattr,
|
|
51
49
|
add_to_path,
|
|
52
|
-
SealedError,
|
|
53
50
|
TaggedValue,
|
|
54
51
|
ObjectStore,
|
|
55
52
|
classproperty,
|
|
@@ -149,9 +146,6 @@ class ConfigInformation:
|
|
|
149
146
|
# This is used to check typevars coherence
|
|
150
147
|
self.concrete_typevars: Dict[TypeVar, type] = {}
|
|
151
148
|
|
|
152
|
-
# Lightweight tasks
|
|
153
|
-
self.pre_tasks: List["LightweightTask"] = []
|
|
154
|
-
|
|
155
149
|
# Initialization tasks
|
|
156
150
|
self.init_tasks: List["LightweightTask"] = []
|
|
157
151
|
|
|
@@ -160,11 +154,8 @@ class ConfigInformation:
|
|
|
160
154
|
|
|
161
155
|
# Cached information
|
|
162
156
|
|
|
163
|
-
self.
|
|
164
|
-
"""The
|
|
165
|
-
|
|
166
|
-
self._raw_identifier = None
|
|
167
|
-
"""The identifier without taking into account pre-tasks"""
|
|
157
|
+
self._identifier = None
|
|
158
|
+
"""The configuration identifier (cached when sealed)"""
|
|
168
159
|
|
|
169
160
|
self._validated = False
|
|
170
161
|
self._sealed = False
|
|
@@ -367,10 +358,6 @@ class ConfigInformation:
|
|
|
367
358
|
% (k, self.xpmtype, self._initinfo)
|
|
368
359
|
)
|
|
369
360
|
|
|
370
|
-
# Validate pre-tasks
|
|
371
|
-
for pre_task in self.pre_tasks:
|
|
372
|
-
pre_task.__xpm__.validate()
|
|
373
|
-
|
|
374
361
|
# Validate init tasks
|
|
375
362
|
for init_task in self.init_tasks:
|
|
376
363
|
init_task.__xpm__.validate()
|
|
@@ -460,90 +447,29 @@ class ConfigInformation:
|
|
|
460
447
|
context = ConfigWalkContext()
|
|
461
448
|
|
|
462
449
|
class Unsealer(ConfigWalk):
|
|
463
|
-
def preprocess(self, config:
|
|
450
|
+
def preprocess(self, config: ConfigMixin):
|
|
464
451
|
return config.__xpm__._sealed, config
|
|
465
452
|
|
|
466
|
-
def postprocess(self, stub, config:
|
|
453
|
+
def postprocess(self, stub, config: ConfigMixin, values):
|
|
467
454
|
config.__xpm__._sealed = False
|
|
468
455
|
config.__xpm__._identifier = None
|
|
469
456
|
|
|
470
457
|
Unsealer(context, recurse_task=True)(self.pyobject)
|
|
471
458
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
pre_tasks: Dict[int, "Config"] = {}
|
|
475
|
-
|
|
476
|
-
class PreTaskCollect(ConfigWalk):
|
|
477
|
-
def preprocess(self, config: Config):
|
|
478
|
-
# Do not cross tasks
|
|
479
|
-
return not isinstance(config.__xpm__, Task), config
|
|
480
|
-
|
|
481
|
-
def postprocess(self, stub, config: Config, values):
|
|
482
|
-
pre_tasks.update(
|
|
483
|
-
{id(pre_task): pre_task for pre_task in config.__xpm__.pre_tasks}
|
|
484
|
-
)
|
|
485
|
-
|
|
486
|
-
PreTaskCollect(context, recurse_task=True)(self.pyobject)
|
|
487
|
-
return pre_tasks.values()
|
|
488
|
-
|
|
489
|
-
def identifiers(self, only_raw: bool):
|
|
459
|
+
@property
|
|
460
|
+
def identifier(self):
|
|
490
461
|
"""Computes the unique identifier"""
|
|
491
|
-
from ..identifier import IdentifierComputer
|
|
492
|
-
|
|
493
|
-
raw_identifier = self._raw_identifier
|
|
494
|
-
full_identifier = self._full_identifier
|
|
462
|
+
from ..identifier import IdentifierComputer
|
|
495
463
|
|
|
496
464
|
# Computes raw identifier if needed
|
|
497
|
-
if
|
|
498
|
-
|
|
499
|
-
raw_identifier = IdentifierComputer.compute(self.pyobject)
|
|
500
|
-
if self._sealed:
|
|
501
|
-
self._raw_identifier = raw_identifier
|
|
502
|
-
|
|
503
|
-
if only_raw:
|
|
504
|
-
return raw_identifier, full_identifier
|
|
505
|
-
|
|
506
|
-
# OK, let's compute the full identifier
|
|
507
|
-
if full_identifier is None or not self._sealed:
|
|
508
|
-
# Compute the full identifier by including the pre-tasks
|
|
509
|
-
hasher = hashlib.sha256()
|
|
510
|
-
hasher.update(raw_identifier.all)
|
|
511
|
-
pre_tasks_ids = [
|
|
512
|
-
pre_task.__xpm__.raw_identifier.all
|
|
513
|
-
for pre_task in self.collect_pre_tasks()
|
|
514
|
-
]
|
|
515
|
-
for task_id in sorted(pre_tasks_ids):
|
|
516
|
-
hasher.update(task_id)
|
|
517
|
-
|
|
518
|
-
# Adds init tasks
|
|
519
|
-
if self.init_tasks:
|
|
520
|
-
hasher.update(IdentifierComputer.INIT_TASKS)
|
|
521
|
-
for init_task in self.init_tasks:
|
|
522
|
-
hasher.update(init_task.__xpm__.raw_identifier.all)
|
|
523
|
-
|
|
524
|
-
full_identifier = Identifier(hasher.digest())
|
|
525
|
-
full_identifier.has_loops = raw_identifier.has_loops
|
|
526
|
-
|
|
527
|
-
# Only cache the identifier if sealed
|
|
528
|
-
if self._sealed:
|
|
529
|
-
self._full_identifier = full_identifier
|
|
530
|
-
|
|
531
|
-
return raw_identifier, full_identifier
|
|
532
|
-
|
|
533
|
-
@property
|
|
534
|
-
def raw_identifier(self) -> "Identifier":
|
|
535
|
-
"""Computes the unique identifier (without task modifiers)"""
|
|
536
|
-
raw_identifier, _ = self.identifiers(True)
|
|
537
|
-
return raw_identifier
|
|
538
|
-
|
|
539
|
-
@property
|
|
540
|
-
def full_identifier(self) -> "Identifier":
|
|
541
|
-
"""Computes the unique identifier (with task modifiers)"""
|
|
542
|
-
_, full_identifier = self.identifiers(False)
|
|
543
|
-
return full_identifier
|
|
465
|
+
if self._identifier is not None:
|
|
466
|
+
return self._identifier
|
|
544
467
|
|
|
545
|
-
|
|
546
|
-
|
|
468
|
+
# Get the main identifier
|
|
469
|
+
identifier = IdentifierComputer.compute(self.pyobject)
|
|
470
|
+
if self._sealed:
|
|
471
|
+
self._identifier = identifier
|
|
472
|
+
return identifier
|
|
547
473
|
|
|
548
474
|
def dependency(self):
|
|
549
475
|
"""Returns a dependency"""
|
|
@@ -558,12 +484,6 @@ class ConfigInformation:
|
|
|
558
484
|
path: List[str],
|
|
559
485
|
taskids: Set[int],
|
|
560
486
|
):
|
|
561
|
-
# Add pre-tasks
|
|
562
|
-
for pre_task in self.pre_tasks:
|
|
563
|
-
pre_task.__xpm__.updatedependencies(
|
|
564
|
-
dependencies, path + ["__pre_tasks__"], taskids
|
|
565
|
-
)
|
|
566
|
-
|
|
567
487
|
# Add initialization tasks
|
|
568
488
|
for init_task in self.init_tasks:
|
|
569
489
|
init_task.__xpm__.updatedependencies(
|
|
@@ -833,9 +753,6 @@ class ConfigInformation:
|
|
|
833
753
|
if self.task is not None and self.task is not self:
|
|
834
754
|
ConfigInformation.__collect_objects__(self.task, objects, context)
|
|
835
755
|
|
|
836
|
-
# Serialize pre-tasks
|
|
837
|
-
ConfigInformation.__collect_objects__(self.pre_tasks, objects, context)
|
|
838
|
-
|
|
839
756
|
# Serialize initialization tasks
|
|
840
757
|
ConfigInformation.__collect_objects__(self.init_tasks, objects, context)
|
|
841
758
|
|
|
@@ -849,8 +766,6 @@ class ConfigInformation:
|
|
|
849
766
|
}
|
|
850
767
|
|
|
851
768
|
# Add pre/init tasks
|
|
852
|
-
if self.pre_tasks:
|
|
853
|
-
state_dict["pre-tasks"] = [id(pre_task) for pre_task in self.pre_tasks]
|
|
854
769
|
if self.init_tasks:
|
|
855
770
|
state_dict["init-tasks"] = [id(init_task) for init_task in self.init_tasks]
|
|
856
771
|
|
|
@@ -1182,12 +1097,6 @@ class ConfigInformation:
|
|
|
1182
1097
|
o.__post_init__()
|
|
1183
1098
|
|
|
1184
1099
|
else:
|
|
1185
|
-
# Sets pre-tasks
|
|
1186
|
-
o.__xpm__.pre_tasks = [
|
|
1187
|
-
objects[pre_task_id]
|
|
1188
|
-
for pre_task_id in definition.get("pre-tasks", [])
|
|
1189
|
-
]
|
|
1190
|
-
|
|
1191
1100
|
if task_id := definition.get("task", None):
|
|
1192
1101
|
o.__xpm__.task = objects[task_id]
|
|
1193
1102
|
|
|
@@ -1221,15 +1130,6 @@ class ConfigInformation:
|
|
|
1221
1130
|
|
|
1222
1131
|
# Run pre-task (or returns them)
|
|
1223
1132
|
if as_instance or return_tasks:
|
|
1224
|
-
# Collect pre-tasks (just once)
|
|
1225
|
-
completed_pretasks = set()
|
|
1226
|
-
pre_tasks = []
|
|
1227
|
-
for definition in definitions:
|
|
1228
|
-
for pre_task_id in definition.get("pre-tasks", []):
|
|
1229
|
-
if pre_task_id not in completed_pretasks:
|
|
1230
|
-
completed_pretasks.add(pre_task_id)
|
|
1231
|
-
pre_tasks.append(objects[pre_task_id])
|
|
1232
|
-
|
|
1233
1133
|
# Collect init tasks
|
|
1234
1134
|
init_tasks = []
|
|
1235
1135
|
for init_task_id in definitions[-1].get("init-tasks", []):
|
|
@@ -1237,14 +1137,11 @@ class ConfigInformation:
|
|
|
1237
1137
|
init_tasks.append(init_task)
|
|
1238
1138
|
|
|
1239
1139
|
if as_instance:
|
|
1240
|
-
for pre_task in pre_tasks:
|
|
1241
|
-
logger.info("Executing pre-task %s", type(pre_task))
|
|
1242
|
-
pre_task.execute()
|
|
1243
1140
|
for init_task in init_tasks:
|
|
1244
1141
|
logger.info("Executing init task %s", type(init_task))
|
|
1245
1142
|
init_task.execute()
|
|
1246
1143
|
else:
|
|
1247
|
-
return o,
|
|
1144
|
+
return o, init_tasks
|
|
1248
1145
|
|
|
1249
1146
|
return o
|
|
1250
1147
|
|
|
@@ -1252,7 +1149,6 @@ class ConfigInformation:
|
|
|
1252
1149
|
def __init__(self, context: ConfigWalkContext, *, objects: ObjectStore = None):
|
|
1253
1150
|
super().__init__(context)
|
|
1254
1151
|
self.objects = ObjectStore() if objects is None else objects
|
|
1255
|
-
self.pre_tasks = {}
|
|
1256
1152
|
|
|
1257
1153
|
def preprocess(self, config: "Config"):
|
|
1258
1154
|
if self.objects.is_constructed(id(config)):
|
|
@@ -1279,10 +1175,6 @@ class ConfigInformation:
|
|
|
1279
1175
|
# Call __post_init__
|
|
1280
1176
|
stub.__post_init__()
|
|
1281
1177
|
|
|
1282
|
-
# Gather pre-tasks
|
|
1283
|
-
for pre_task in config.__xpm__.pre_tasks:
|
|
1284
|
-
self.pre_tasks[id(pre_task)] = self.stub(pre_task)
|
|
1285
|
-
|
|
1286
1178
|
self.objects.set_constructed(id(config))
|
|
1287
1179
|
return stub
|
|
1288
1180
|
|
|
@@ -1296,10 +1188,6 @@ class ConfigInformation:
|
|
|
1296
1188
|
processor = ConfigInformation.FromPython(context, objects=objects)
|
|
1297
1189
|
last_object = processor(self.pyobject)
|
|
1298
1190
|
|
|
1299
|
-
# Execute pre-tasks
|
|
1300
|
-
for pre_task in processor.pre_tasks.values():
|
|
1301
|
-
pre_task.execute()
|
|
1302
|
-
|
|
1303
1191
|
return last_object
|
|
1304
1192
|
|
|
1305
1193
|
def add_dependencies(self, *dependencies):
|
|
@@ -1485,29 +1373,7 @@ class ConfigMixin:
|
|
|
1485
1373
|
attributes)"""
|
|
1486
1374
|
return clone(self)
|
|
1487
1375
|
|
|
1488
|
-
def
|
|
1489
|
-
assert all(
|
|
1490
|
-
[isinstance(task, LightweightTask) for task in tasks]
|
|
1491
|
-
), "One of the pre-tasks are not lightweight tasks"
|
|
1492
|
-
if self.__xpm__._sealed:
|
|
1493
|
-
raise SealedError("Cannot add pre-tasks to a sealed configuration")
|
|
1494
|
-
self.__xpm__.pre_tasks.extend(tasks)
|
|
1495
|
-
return self
|
|
1496
|
-
|
|
1497
|
-
def add_pretasks_from(self, *configs: "Config"):
|
|
1498
|
-
assert all(
|
|
1499
|
-
[isinstance(config, ConfigMixin) for config in configs]
|
|
1500
|
-
), "One of the parameters is not a configuration object"
|
|
1501
|
-
for config in configs:
|
|
1502
|
-
self.add_pretasks(*config.__xpm__.pre_tasks)
|
|
1503
|
-
return self
|
|
1504
|
-
|
|
1505
|
-
@property
|
|
1506
|
-
def pre_tasks(self) -> List["LightweightTask"]:
|
|
1507
|
-
"""Access pre-tasks"""
|
|
1508
|
-
return self.__xpm__.pre_tasks
|
|
1509
|
-
|
|
1510
|
-
def copy_dependencies(self, other: "Config"):
|
|
1376
|
+
def copy_dependencies(self, other: "ConfigMixin"):
|
|
1511
1377
|
"""Add all the dependencies from other configuration"""
|
|
1512
1378
|
|
|
1513
1379
|
# Add task dependency
|
|
@@ -1644,27 +1510,12 @@ class Config:
|
|
|
1644
1510
|
def __identifier__(self) -> "Identifier":
|
|
1645
1511
|
return self.__xpm__.full_identifier
|
|
1646
1512
|
|
|
1647
|
-
def add_pretasks(self, *tasks: "LightweightTask"):
|
|
1648
|
-
"""Add pre-tasks"""
|
|
1649
|
-
raise AssertionError("This method can only be used during configuration")
|
|
1650
|
-
|
|
1651
|
-
def add_pretasks_from(self, *configs: "Config"):
|
|
1652
|
-
"""Add pre-tasks from the listed configurations"""
|
|
1653
|
-
raise AssertionError(
|
|
1654
|
-
"The 'add_pretasks_from' can only be used during configuration"
|
|
1655
|
-
)
|
|
1656
|
-
|
|
1657
1513
|
def copy_dependencies(self, other: "Config"):
|
|
1658
1514
|
"""Add pre-tasks from the listed configurations"""
|
|
1659
1515
|
raise AssertionError(
|
|
1660
1516
|
"The 'copy_dependencies' method can only be used during configuration"
|
|
1661
1517
|
)
|
|
1662
1518
|
|
|
1663
|
-
@property
|
|
1664
|
-
def pre_tasks(self) -> List["LightweightTask"]:
|
|
1665
|
-
"""Access pre-tasks"""
|
|
1666
|
-
raise AssertionError("Pre-tasks can be accessed only during configuration")
|
|
1667
|
-
|
|
1668
1519
|
def register_task_output(self, method, *args, **kwargs):
|
|
1669
1520
|
# Determine the path for this...
|
|
1670
1521
|
path = taskglobals.Env.instance().xpm_path / "task-outputs.jsonl"
|
|
@@ -109,11 +109,7 @@ class ConfigWalk:
|
|
|
109
109
|
else:
|
|
110
110
|
result[arg.name] = None
|
|
111
111
|
|
|
112
|
-
# Deals with
|
|
113
|
-
if info.pre_tasks:
|
|
114
|
-
with self.map("__pre_tasks__"):
|
|
115
|
-
self(info.pre_tasks)
|
|
116
|
-
|
|
112
|
+
# Deals with init tasks
|
|
117
113
|
if info.init_tasks:
|
|
118
114
|
with self.map("__init_tasks__"):
|
|
119
115
|
self(info.init_tasks)
|
|
@@ -168,7 +168,7 @@ class ConfigMixin:
|
|
|
168
168
|
*,
|
|
169
169
|
workspace: Incomplete | None = ...,
|
|
170
170
|
launcher: Incomplete | None = ...,
|
|
171
|
-
run_mode: RunMode =
|
|
171
|
+
run_mode: RunMode = ...,
|
|
172
172
|
): ...
|
|
173
173
|
def stdout(self): ...
|
|
174
174
|
def stderr(self): ...
|
|
@@ -195,11 +195,7 @@ class Config:
|
|
|
195
195
|
def __post_init__(self) -> None: ...
|
|
196
196
|
def __json__(self): ...
|
|
197
197
|
def __identifier__(self) -> Identifier: ...
|
|
198
|
-
def add_pretasks(self, *tasks: "LightweightTask"): ...
|
|
199
|
-
def add_pretasks_from(self, configs: "Config"): ...
|
|
200
198
|
def copy_dependencies(self, other: "Config"): ...
|
|
201
|
-
@property
|
|
202
|
-
def pre_tasks(self) -> List["LightweightTask"]: ...
|
|
203
199
|
|
|
204
200
|
class LightweightTask(Config):
|
|
205
201
|
def execute(self) -> None: ...
|
|
@@ -213,7 +209,7 @@ class Task(LightweightTask):
|
|
|
213
209
|
workspace: Incomplete | None = ...,
|
|
214
210
|
launcher: Incomplete | None = ...,
|
|
215
211
|
run_mode: RunMode = ...,
|
|
216
|
-
init_tasks: List["LightweightTask"] = []
|
|
212
|
+
init_tasks: List["LightweightTask"] = [],
|
|
217
213
|
): ...
|
|
218
214
|
def task_outputs(self, dep: Callable[[Config], None]) -> Any: ...
|
|
219
215
|
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
from typing import List, TypeVar
|
|
2
|
-
from pathlib import Path
|
|
1
|
+
from typing import List, TypeVar
|
|
3
2
|
from experimaestro import Param
|
|
4
3
|
|
|
5
4
|
from .objects import Config, LightweightTask
|
|
6
5
|
from .arguments import DataPath
|
|
7
|
-
from experimaestro import copyconfig
|
|
8
6
|
|
|
9
7
|
|
|
10
8
|
class SerializationLWTask(LightweightTask):
|
|
@@ -39,8 +37,3 @@ class PathSerializationLWTask(SerializationLWTask):
|
|
|
39
37
|
|
|
40
38
|
path: DataPath
|
|
41
39
|
"""Path containing the data"""
|
|
42
|
-
|
|
43
|
-
@classmethod
|
|
44
|
-
def construct(cls, value: T, path: Path, dep: Callable[[Config], Any]) -> T:
|
|
45
|
-
value = copyconfig(value)
|
|
46
|
-
return value.add_pretasks(dep(cls(value=value, path=path)))
|
|
@@ -85,9 +85,3 @@ def test_dependencies_inner_task_output(xp):
|
|
|
85
85
|
a = task_a.submit()
|
|
86
86
|
b = Inner_TaskB(param_a=a).submit()
|
|
87
87
|
check_dependencies(b, task_a)
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
def test_dependencies_pre_task(xp):
|
|
91
|
-
a = TaskA().submit()
|
|
92
|
-
a2 = TaskA().add_pretasks(a).submit()
|
|
93
|
-
check_dependencies(a2, a)
|