experimaestro 1.5.6__tar.gz → 1.5.7__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.5.6 → experimaestro-1.5.7}/PKG-INFO +1 -1
- {experimaestro-1.5.6 → experimaestro-1.5.7}/pyproject.toml +2 -2
- experimaestro-1.5.7/src/experimaestro/__main__.py +12 -0
- experimaestro-1.5.6/src/experimaestro/__main__.py → experimaestro-1.5.7/src/experimaestro/cli/__init__.py +8 -128
- {experimaestro-1.5.6/src/experimaestro → experimaestro-1.5.7/src/experimaestro/cli}/filter.py +4 -4
- experimaestro-1.5.7/src/experimaestro/cli/jobs.py +245 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/core/objects.py +6 -3
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/experiments/cli.py +3 -22
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/launchers/slurm/base.py +3 -1
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/notifications.py +24 -8
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/run.py +0 -1
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/scheduler/base.py +0 -5
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/settings.py +29 -1
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/test_tags.py +35 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/LICENSE +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/README.md +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/__init__.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/annotations.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/checkers.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/click.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/commandline.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/compat.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/connectors/__init__.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/connectors/local.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/connectors/ssh.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/core/__init__.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/core/arguments.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/core/context.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/core/objects.pyi +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/core/serialization.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/core/serializers.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/core/types.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/core/utils.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/exceptions.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/experiments/__init__.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/experiments/configuration.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/generators.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/huggingface.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/ipc.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/launcherfinder/__init__.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/launcherfinder/base.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/launcherfinder/parser.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/launcherfinder/registry.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/launcherfinder/specs.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/launchers/__init__.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/launchers/direct.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/launchers/oar.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/launchers/slurm/__init__.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/launchers/slurm/cli.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/launchers/slurm/configuration.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/locking.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/mkdocs/__init__.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/mkdocs/annotations.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/mkdocs/base.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/mkdocs/metaloader.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/mkdocs/style.css +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/mypy.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/py.typed +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/rpyc.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/scheduler/__init__.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/scheduler/dependencies.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/scheduler/services.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/scheduler/workspace.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/scriptbuilder.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/server/__init__.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/server/data/016b4a6cdced82ab3aa1.ttf +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/server/data/0c35d18bf06992036b69.woff2 +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/server/data/219aa9140e099e6c72ed.woff2 +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/server/data/3a4004a46a653d4b2166.woff +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/server/data/3baa5b8f3469222b822d.woff +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/server/data/4d73cb90e394b34b7670.woff +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/server/data/4ef4218c522f1eb6b5b1.woff2 +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/server/data/50701fbb8177c2dde530.ttf +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/server/data/5d681e2edae8c60630db.woff +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/server/data/6f420cf17cc0d7676fad.woff2 +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/server/data/878f31251d960bd6266f.woff2 +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/server/data/b041b1fa4fe241b23445.woff2 +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/server/data/b6879d41b0852f01ed5b.woff2 +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/server/data/c380809fd3677d7d6903.woff2 +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/server/data/d75e3fd1eb12e9bd6655.ttf +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/server/data/f882956fd323fd322f31.woff +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/server/data/favicon.ico +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/server/data/index.css +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/server/data/index.css.map +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/server/data/index.html +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/server/data/index.js +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/server/data/index.js.map +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/server/data/login.html +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/server/data/manifest.json +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/sphinx/__init__.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/sphinx/static/experimaestro.css +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/taskglobals.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/__init__.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/conftest.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/connectors/bin/executable.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/connectors/test_local.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/connectors/utils.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/definitions_types.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/launchers/__init__.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/launchers/bin/sacct +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/launchers/bin/sbatch +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/launchers/bin/test.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/launchers/common.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/launchers/config_slurm/__init__.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/launchers/config_slurm/launchers.yaml +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/launchers/test_local.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/launchers/test_slurm.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/restart.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/restart_main.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/scripts/notifyandwait.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/scripts/waitforfile.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/task_tokens.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/tasks/__init__.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/tasks/all.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/tasks/foreign.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/test_checkers.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/test_dependencies.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/test_findlauncher.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/test_forward.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/test_identifier.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/test_instance.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/test_objects.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/test_outputs.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/test_param.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/test_progress.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/test_serializers.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/test_snippets.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/test_ssh.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/test_tasks.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/test_tokens.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/test_types.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/test_validation.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/token_reschedule.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tests/utils.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tokens.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tools/__init__.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tools/diff.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tools/documentation.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/tools/jobs.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/typingutils.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/utils/__init__.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/utils/asyncio.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/utils/jobs.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/utils/jupyter.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/utils/resources.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/utils/settings.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/utils/yaml.py +0 -0
- {experimaestro-1.5.6 → experimaestro-1.5.7}/src/experimaestro/xpmutils.py +0 -0
|
@@ -19,7 +19,7 @@ include = [
|
|
|
19
19
|
"src/experimaestro/sphinx/static/experimaestro.css",
|
|
20
20
|
"src/experimaestro/mkdocs/style.css"
|
|
21
21
|
]
|
|
22
|
-
version = "1.5.
|
|
22
|
+
version = "1.5.7"
|
|
23
23
|
repository = "https://github.com/experimaestro/experimaestro-python"
|
|
24
24
|
documentation = "https://experimaestro-python.readthedocs.io/"
|
|
25
25
|
|
|
@@ -123,7 +123,7 @@ warn_unused_ignores = true
|
|
|
123
123
|
|
|
124
124
|
[tool.commitizen]
|
|
125
125
|
name = "cz_conventional_commits"
|
|
126
|
-
version = "1.5.
|
|
126
|
+
version = "1.5.7"
|
|
127
127
|
changelog_start_rev = "0.15.0"
|
|
128
128
|
tag_format = "v$version"
|
|
129
129
|
update_changelog_on_bump = true
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# flake8: noqa: T201
|
|
2
2
|
import sys
|
|
3
|
-
from types import ModuleType
|
|
4
3
|
from typing import Set, Optional
|
|
5
4
|
import pkg_resources
|
|
6
5
|
from itertools import chain
|
|
@@ -10,11 +9,12 @@ import logging
|
|
|
10
9
|
from functools import cached_property, update_wrapper
|
|
11
10
|
from pathlib import Path
|
|
12
11
|
import subprocess
|
|
13
|
-
from termcolor import
|
|
12
|
+
from termcolor import cprint
|
|
14
13
|
|
|
15
14
|
import experimaestro
|
|
16
15
|
from experimaestro.experiments.cli import experiments_cli
|
|
17
16
|
import experimaestro.launcherfinder.registry as launcher_registry
|
|
17
|
+
from experimaestro.settings import find_workspace
|
|
18
18
|
|
|
19
19
|
# --- Command line main options
|
|
20
20
|
logging.basicConfig(level=logging.INFO)
|
|
@@ -175,121 +175,6 @@ def diff(path: Path):
|
|
|
175
175
|
check(".", job, new_job, set())
|
|
176
176
|
|
|
177
177
|
|
|
178
|
-
@click.argument("path", type=Path, callback=check_xp_path)
|
|
179
|
-
@click.option("--experiment", default=None, help="Restrict to this experiment")
|
|
180
|
-
@click.option("--tags", is_flag=True, help="Show tags")
|
|
181
|
-
@click.option("--ready", is_flag=True, help="Include tasks which are not yet scheduled")
|
|
182
|
-
@click.option("--filter", default="", help="Filter expression")
|
|
183
|
-
@click.option(
|
|
184
|
-
"--force",
|
|
185
|
-
is_flag=True,
|
|
186
|
-
help="Force operation even if experiment has not been completed yet",
|
|
187
|
-
)
|
|
188
|
-
@click.option("--kill", is_flag=True, help="Kill filtered tasks (when/before running)")
|
|
189
|
-
@click.option("--clean", is_flag=True, help="Remove finished tasks directories")
|
|
190
|
-
@cli.command()
|
|
191
|
-
def jobs(
|
|
192
|
-
path: Path,
|
|
193
|
-
experiment: str,
|
|
194
|
-
filter: str,
|
|
195
|
-
tags: bool,
|
|
196
|
-
ready: bool,
|
|
197
|
-
kill: bool,
|
|
198
|
-
clean: bool,
|
|
199
|
-
force: bool,
|
|
200
|
-
):
|
|
201
|
-
"""Job control: list, kill and clean
|
|
202
|
-
|
|
203
|
-
The job filter is a boolean expression where tags (alphanumeric)
|
|
204
|
-
and special job information (@state for job state, @name for job full
|
|
205
|
-
name) can be compared to a given value (using '~' for regex matching,
|
|
206
|
-
'=', 'not in', or 'in')
|
|
207
|
-
|
|
208
|
-
For instance,
|
|
209
|
-
|
|
210
|
-
model = "bm25" and mode in ["a", b"] and @state = "RUNNING"
|
|
211
|
-
|
|
212
|
-
selects jobs where the tag model is "bm25", the tag mode is either
|
|
213
|
-
"a" or "b", and the state is running.
|
|
214
|
-
|
|
215
|
-
"""
|
|
216
|
-
for p in (path / "xp").glob("*"):
|
|
217
|
-
if experiment and p.name != experiment:
|
|
218
|
-
continue
|
|
219
|
-
|
|
220
|
-
from .filter import createFilter, JobInformation
|
|
221
|
-
from experimaestro.scheduler import JobState
|
|
222
|
-
|
|
223
|
-
_filter = createFilter(filter) if filter else lambda x: True
|
|
224
|
-
|
|
225
|
-
print(f"* Experiment {p.name}")
|
|
226
|
-
if (p / "jobs.bak").is_dir():
|
|
227
|
-
cprint(" Experiment has not finished yet", "red")
|
|
228
|
-
if not force and (kill or clean):
|
|
229
|
-
cprint(" Preventing kill/clean (use --force if you want to)", "yellow")
|
|
230
|
-
kill = False
|
|
231
|
-
clean = False
|
|
232
|
-
print()
|
|
233
|
-
|
|
234
|
-
for job in p.glob("jobs/*/*"):
|
|
235
|
-
info = None
|
|
236
|
-
p = job.resolve()
|
|
237
|
-
if p.is_dir():
|
|
238
|
-
*_, scriptname = p.parent.name.rsplit(".", 1)
|
|
239
|
-
|
|
240
|
-
info = JobInformation(p, scriptname)
|
|
241
|
-
if filter:
|
|
242
|
-
if not _filter(info):
|
|
243
|
-
continue
|
|
244
|
-
|
|
245
|
-
if info.state is None:
|
|
246
|
-
print(
|
|
247
|
-
colored(f"NODIR {job.parent.name}/{job.name}", "red"), end=""
|
|
248
|
-
)
|
|
249
|
-
elif info.state.running():
|
|
250
|
-
if kill:
|
|
251
|
-
process = info.getprocess()
|
|
252
|
-
print("KILLING", process)
|
|
253
|
-
process.kill()
|
|
254
|
-
print(
|
|
255
|
-
colored(
|
|
256
|
-
f"{info.state.name:8}{job.parent.name}/{job.name}", "yellow"
|
|
257
|
-
),
|
|
258
|
-
end="",
|
|
259
|
-
)
|
|
260
|
-
elif info.state == JobState.DONE:
|
|
261
|
-
print(
|
|
262
|
-
colored(f"DONE {job.parent.name}/{job.name}", "green"),
|
|
263
|
-
end="",
|
|
264
|
-
)
|
|
265
|
-
elif info.state == JobState.ERROR:
|
|
266
|
-
print(
|
|
267
|
-
colored(f"FAIL {job.parent.name}/{job.name}", "red"), end=""
|
|
268
|
-
)
|
|
269
|
-
else:
|
|
270
|
-
print(
|
|
271
|
-
colored(
|
|
272
|
-
f"{info.state.name:8}{job.parent.name}/{job.name}", "red"
|
|
273
|
-
),
|
|
274
|
-
end="",
|
|
275
|
-
)
|
|
276
|
-
|
|
277
|
-
else:
|
|
278
|
-
if not ready:
|
|
279
|
-
continue
|
|
280
|
-
print(colored(f"READY {job.parent.name}/{job.name}", "yellow"), end="")
|
|
281
|
-
|
|
282
|
-
if tags:
|
|
283
|
-
print(f""" {" ".join(f"{k}={v}" for k, v in info.tags.items())}""")
|
|
284
|
-
else:
|
|
285
|
-
print()
|
|
286
|
-
|
|
287
|
-
if clean and info.state and info.state.finished():
|
|
288
|
-
cprint("Cleaning...", "red")
|
|
289
|
-
rmtree(p)
|
|
290
|
-
print()
|
|
291
|
-
|
|
292
|
-
|
|
293
178
|
@click.option("--show-all", is_flag=True, help="Show even not orphans")
|
|
294
179
|
@click.option(
|
|
295
180
|
"--ignore-old", is_flag=True, help="Ignore old jobs for unfinished experiments"
|
|
@@ -407,11 +292,14 @@ cli.add_command(Launchers("tokens", help="Token specific commands"))
|
|
|
407
292
|
|
|
408
293
|
|
|
409
294
|
@cli.group()
|
|
410
|
-
@click.
|
|
295
|
+
@click.option("--workdir", type=Path, default=None)
|
|
296
|
+
@click.option("--workspace", type=str, default=None)
|
|
411
297
|
@click.pass_context
|
|
412
|
-
def experiments(ctx, workdir):
|
|
298
|
+
def experiments(ctx, workdir, workspace):
|
|
413
299
|
"""Manage experiments"""
|
|
414
|
-
|
|
300
|
+
ws = find_workspace(workdir=workdir, workspace=workspace)
|
|
301
|
+
path = check_xp_path(None, None, ws.path)
|
|
302
|
+
ctx.obj = path
|
|
415
303
|
|
|
416
304
|
|
|
417
305
|
@experiments.command()
|
|
@@ -422,11 +310,3 @@ def list(workdir: Path):
|
|
|
422
310
|
cprint(f"[unfinished] {p.name}", "yellow")
|
|
423
311
|
else:
|
|
424
312
|
cprint(p.name, "cyan")
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
def main():
|
|
428
|
-
cli(obj=None)
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
if __name__ == "__main__":
|
|
432
|
-
main()
|
{experimaestro-1.5.6/src/experimaestro → experimaestro-1.5.7/src/experimaestro/cli}/filter.py
RENAMED
|
@@ -22,12 +22,12 @@ class JobInformation:
|
|
|
22
22
|
|
|
23
23
|
@cached_property
|
|
24
24
|
def state(self) -> Optional[JobState]:
|
|
25
|
-
if (self.path / f"{self.scriptname}.
|
|
26
|
-
return JobState.RUNNING
|
|
27
|
-
elif (self.path / f"{self.scriptname}.done").is_file():
|
|
25
|
+
if (self.path / f"{self.scriptname}.done").is_file():
|
|
28
26
|
return JobState.DONE
|
|
29
|
-
|
|
27
|
+
if (self.path / f"{self.scriptname}.failed").is_file():
|
|
30
28
|
return JobState.ERROR
|
|
29
|
+
if (self.path / f"{self.scriptname}.pid").is_file():
|
|
30
|
+
return JobState.RUNNING
|
|
31
31
|
else:
|
|
32
32
|
return None
|
|
33
33
|
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
# flake8: noqa: T201
|
|
2
|
+
import subprocess
|
|
3
|
+
from typing import Optional
|
|
4
|
+
from shutil import rmtree
|
|
5
|
+
import click
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from termcolor import colored, cprint
|
|
8
|
+
|
|
9
|
+
from experimaestro.settings import find_workspace
|
|
10
|
+
from . import check_xp_path, cli
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@click.option("--workspace", default="", help="Experimaestro workspace")
|
|
14
|
+
@click.option("--workdir", type=Path, default=None)
|
|
15
|
+
@cli.group()
|
|
16
|
+
@click.pass_context
|
|
17
|
+
def jobs(
|
|
18
|
+
ctx,
|
|
19
|
+
workdir: Optional[Path],
|
|
20
|
+
workspace: Optional[str],
|
|
21
|
+
):
|
|
22
|
+
"""Job control: list, kill and clean
|
|
23
|
+
|
|
24
|
+
The job filter is a boolean expression where tags (alphanumeric)
|
|
25
|
+
and special job information (@state for job state, @name for job full
|
|
26
|
+
name) can be compared to a given value (using '~' for regex matching,
|
|
27
|
+
'=', 'not in', or 'in')
|
|
28
|
+
|
|
29
|
+
For instance,
|
|
30
|
+
|
|
31
|
+
model = "bm25" and mode in ["a", b"] and @state = "RUNNING"
|
|
32
|
+
|
|
33
|
+
selects jobs where the tag model is "bm25", the tag mode is either
|
|
34
|
+
"a" or "b", and the state is running.
|
|
35
|
+
|
|
36
|
+
"""
|
|
37
|
+
ws = ctx.obj.workspace = find_workspace(workdir=workdir, workspace=workspace)
|
|
38
|
+
check_xp_path(ctx, None, ws.path)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def process(
|
|
42
|
+
workspace,
|
|
43
|
+
*,
|
|
44
|
+
experiment="",
|
|
45
|
+
tags="",
|
|
46
|
+
ready=False,
|
|
47
|
+
clean=False,
|
|
48
|
+
kill=False,
|
|
49
|
+
filter="",
|
|
50
|
+
perform=False,
|
|
51
|
+
fullpath=False,
|
|
52
|
+
):
|
|
53
|
+
path = workspace.path
|
|
54
|
+
for p in (path / "xp").glob("*"):
|
|
55
|
+
if experiment and p.name != experiment:
|
|
56
|
+
continue
|
|
57
|
+
|
|
58
|
+
from .filter import createFilter, JobInformation
|
|
59
|
+
from experimaestro.scheduler import JobState
|
|
60
|
+
|
|
61
|
+
_filter = createFilter(filter) if filter else lambda x: True
|
|
62
|
+
|
|
63
|
+
print(f"* Experiment {p.name}")
|
|
64
|
+
if (p / "jobs.bak").is_dir():
|
|
65
|
+
cprint(" Experiment has not finished yet", "red")
|
|
66
|
+
if not perform and (kill or clean):
|
|
67
|
+
cprint(" Preventing kill/clean (use --force if you want to)", "yellow")
|
|
68
|
+
kill = False
|
|
69
|
+
clean = False
|
|
70
|
+
print()
|
|
71
|
+
|
|
72
|
+
for job in p.glob("jobs/*/*"):
|
|
73
|
+
info = None
|
|
74
|
+
p = job.resolve()
|
|
75
|
+
if p.is_dir():
|
|
76
|
+
*_, scriptname = p.parent.name.rsplit(".", 1)
|
|
77
|
+
|
|
78
|
+
info = JobInformation(p, scriptname)
|
|
79
|
+
job_path = (
|
|
80
|
+
str(job.resolve()) if fullpath else f"{job.parent.name}/{job.name}"
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
if filter:
|
|
84
|
+
if not _filter(info):
|
|
85
|
+
continue
|
|
86
|
+
|
|
87
|
+
if info.state is None:
|
|
88
|
+
print(colored(f"NODIR {job_path}", "red"), end="")
|
|
89
|
+
elif info.state.running():
|
|
90
|
+
if kill:
|
|
91
|
+
if perform:
|
|
92
|
+
process = info.getprocess()
|
|
93
|
+
print("KILLING", process)
|
|
94
|
+
process.kill()
|
|
95
|
+
else:
|
|
96
|
+
print("KILLING (not performing)", process)
|
|
97
|
+
print(
|
|
98
|
+
colored(f"{info.state.name:8}{job_path}", "yellow"),
|
|
99
|
+
end="",
|
|
100
|
+
)
|
|
101
|
+
elif info.state == JobState.DONE:
|
|
102
|
+
print(
|
|
103
|
+
colored(f"DONE {job_path}", "green"),
|
|
104
|
+
end="",
|
|
105
|
+
)
|
|
106
|
+
elif info.state == JobState.ERROR:
|
|
107
|
+
print(colored(f"FAIL {job_path}", "red"), end="")
|
|
108
|
+
else:
|
|
109
|
+
print(
|
|
110
|
+
colored(f"{info.state.name:8}{job_path}", "red"),
|
|
111
|
+
end="",
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
else:
|
|
115
|
+
if not ready:
|
|
116
|
+
continue
|
|
117
|
+
print(colored(f"READY {job_path}", "yellow"), end="")
|
|
118
|
+
|
|
119
|
+
if tags:
|
|
120
|
+
print(f""" {" ".join(f"{k}={v}" for k, v in info.tags.items())}""")
|
|
121
|
+
else:
|
|
122
|
+
print()
|
|
123
|
+
|
|
124
|
+
if clean and info.state and info.state.finished():
|
|
125
|
+
if perform:
|
|
126
|
+
cprint("Cleaning...", "red")
|
|
127
|
+
rmtree(p)
|
|
128
|
+
else:
|
|
129
|
+
cprint("Cleaning... (not performed)", "red")
|
|
130
|
+
print()
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
@click.option("--experiment", default=None, help="Restrict to this experiment")
|
|
134
|
+
@click.option("--tags", is_flag=True, help="Show tags")
|
|
135
|
+
@click.option("--ready", is_flag=True, help="Include tasks which are not yet scheduled")
|
|
136
|
+
@click.option("--filter", default="", help="Filter expression")
|
|
137
|
+
@click.option("--fullpath", is_flag=True, help="Prints full paths")
|
|
138
|
+
@jobs.command()
|
|
139
|
+
@click.pass_context
|
|
140
|
+
def list(
|
|
141
|
+
ctx,
|
|
142
|
+
experiment: str,
|
|
143
|
+
filter: str,
|
|
144
|
+
tags: bool,
|
|
145
|
+
ready: bool,
|
|
146
|
+
fullpath: bool,
|
|
147
|
+
):
|
|
148
|
+
process(
|
|
149
|
+
ctx.obj.workspace,
|
|
150
|
+
experiment=experiment,
|
|
151
|
+
filter=filter,
|
|
152
|
+
tags=tags,
|
|
153
|
+
ready=ready,
|
|
154
|
+
fullpath=fullpath,
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
@click.option("--experiment", default=None, help="Restrict to this experiment")
|
|
159
|
+
@click.option("--tags", is_flag=True, help="Show tags")
|
|
160
|
+
@click.option("--ready", is_flag=True, help="Include tasks which are not yet scheduled")
|
|
161
|
+
@click.option("--filter", default="", help="Filter expression")
|
|
162
|
+
@click.option("--perform", is_flag=True, help="Really perform the killing")
|
|
163
|
+
@click.option("--fullpath", is_flag=True, help="Prints full paths")
|
|
164
|
+
@jobs.command()
|
|
165
|
+
@click.pass_context
|
|
166
|
+
def kill(
|
|
167
|
+
ctx,
|
|
168
|
+
experiment: str,
|
|
169
|
+
filter: str,
|
|
170
|
+
tags: bool,
|
|
171
|
+
ready: bool,
|
|
172
|
+
fullpath: bool,
|
|
173
|
+
perform: bool,
|
|
174
|
+
):
|
|
175
|
+
process(
|
|
176
|
+
ctx.obj.workspace,
|
|
177
|
+
experiment=experiment,
|
|
178
|
+
filter=filter,
|
|
179
|
+
tags=tags,
|
|
180
|
+
ready=ready,
|
|
181
|
+
kill=True,
|
|
182
|
+
perform=perform,
|
|
183
|
+
fullpath=fullpath,
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
@click.option("--experiment", default=None, help="Restrict to this experiment")
|
|
188
|
+
@click.option("--tags", is_flag=True, help="Show tags")
|
|
189
|
+
@click.option("--ready", is_flag=True, help="Include tasks which are not yet scheduled")
|
|
190
|
+
@click.option("--filter", default="", help="Filter expression")
|
|
191
|
+
@click.option("--perform", is_flag=True, help="Really perform the cleaning")
|
|
192
|
+
@click.option("--fullpath", is_flag=True, help="Prints full paths")
|
|
193
|
+
@jobs.command()
|
|
194
|
+
@click.pass_context
|
|
195
|
+
def clean(
|
|
196
|
+
ctx,
|
|
197
|
+
experiment: str,
|
|
198
|
+
filter: str,
|
|
199
|
+
tags: bool,
|
|
200
|
+
ready: bool,
|
|
201
|
+
fullpath: bool,
|
|
202
|
+
perform: bool,
|
|
203
|
+
):
|
|
204
|
+
process(
|
|
205
|
+
ctx.obj.workspace,
|
|
206
|
+
experiment=experiment,
|
|
207
|
+
filter=filter,
|
|
208
|
+
tags=tags,
|
|
209
|
+
ready=ready,
|
|
210
|
+
clean=True,
|
|
211
|
+
perform=perform,
|
|
212
|
+
fullpath=fullpath,
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
@click.argument("jobid", type=str)
|
|
217
|
+
@click.option(
|
|
218
|
+
"--follow", "-f", help="Use tail instead of less to follow changes", is_flag=True
|
|
219
|
+
)
|
|
220
|
+
@click.option("--std", help="Follow stdout instead of stderr", is_flag=True)
|
|
221
|
+
@jobs.command()
|
|
222
|
+
@click.pass_context
|
|
223
|
+
def log(ctx, jobid: str, follow: bool, std: bool):
|
|
224
|
+
task_name, task_hash = jobid.split("/")
|
|
225
|
+
_, name = task_name.rsplit(".", 1)
|
|
226
|
+
path = (
|
|
227
|
+
ctx.obj.workspace.path
|
|
228
|
+
/ "jobs"
|
|
229
|
+
/ task_name
|
|
230
|
+
/ task_hash
|
|
231
|
+
/ f"""{name}.{'out' if std else 'err'}"""
|
|
232
|
+
)
|
|
233
|
+
if follow:
|
|
234
|
+
subprocess.run(["tail", "-f", path])
|
|
235
|
+
else:
|
|
236
|
+
subprocess.run(["less", "-r", path])
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
@click.argument("jobid", type=str)
|
|
240
|
+
@jobs.command()
|
|
241
|
+
@click.pass_context
|
|
242
|
+
def path(ctx, jobid: str):
|
|
243
|
+
task_name, task_hash = jobid.split("/")
|
|
244
|
+
path = ctx.obj.workspace.path / "jobs" / task_name / task_hash
|
|
245
|
+
print(path)
|
|
@@ -916,14 +916,14 @@ class ConfigInformation:
|
|
|
916
916
|
|
|
917
917
|
# --- Submit the job
|
|
918
918
|
|
|
919
|
+
# Sets the init tasks
|
|
920
|
+
self.init_tasks = init_tasks
|
|
921
|
+
|
|
919
922
|
# Creates a new job
|
|
920
923
|
self.job = self.xpmtype.task(
|
|
921
924
|
self.pyobject, launcher=launcher, workspace=workspace, run_mode=run_mode
|
|
922
925
|
)
|
|
923
926
|
|
|
924
|
-
# Sets the init tasks
|
|
925
|
-
self.init_tasks = init_tasks
|
|
926
|
-
|
|
927
927
|
# Validate the object
|
|
928
928
|
job_context = JobContext(self.job)
|
|
929
929
|
self.validate_and_seal(job_context)
|
|
@@ -979,6 +979,9 @@ class ConfigInformation:
|
|
|
979
979
|
elif self.job.failedpath.is_file():
|
|
980
980
|
color = "light_red"
|
|
981
981
|
cprint(f"[failed] {s}", color, file=sys.stderr)
|
|
982
|
+
elif self.job.pidpath.is_file():
|
|
983
|
+
color = "blue"
|
|
984
|
+
cprint(f"[running] {s}", color, file=sys.stderr)
|
|
982
985
|
else:
|
|
983
986
|
color = "light_blue"
|
|
984
987
|
cprint(f"[not run] {s}", color, file=sys.stderr)
|
|
@@ -11,7 +11,7 @@ import yaml
|
|
|
11
11
|
from experimaestro import LauncherRegistry, RunMode, experiment
|
|
12
12
|
from experimaestro.experiments.configuration import ConfigurationBase
|
|
13
13
|
from experimaestro.exceptions import HandledException
|
|
14
|
-
from experimaestro.settings import
|
|
14
|
+
from experimaestro.settings import find_workspace
|
|
15
15
|
from omegaconf import OmegaConf, SCMode
|
|
16
16
|
from termcolor import cprint
|
|
17
17
|
|
|
@@ -231,27 +231,8 @@ def experiments_cli( # noqa: C901
|
|
|
231
231
|
)
|
|
232
232
|
|
|
233
233
|
# Define the workspace
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
if workspace:
|
|
237
|
-
ws_env = get_workspace(workspace)
|
|
238
|
-
if ws_env is None:
|
|
239
|
-
raise RuntimeError("No workspace named %s", workspace)
|
|
240
|
-
|
|
241
|
-
logging.info("Using workspace %s", ws_env.id)
|
|
242
|
-
if workdir:
|
|
243
|
-
# Overrides working directory
|
|
244
|
-
logging.info(" override working directory: %s", workdir)
|
|
245
|
-
ws_env.path = workdir
|
|
246
|
-
else:
|
|
247
|
-
workdir = ws_env.path
|
|
248
|
-
elif workdir:
|
|
249
|
-
logging.info("Using workdir %s", workdir)
|
|
250
|
-
ws_env = workdir
|
|
251
|
-
else:
|
|
252
|
-
ws_env = get_workspace()
|
|
253
|
-
assert ws_env is not None, "No workdir or workspace defined, and no default"
|
|
254
|
-
logging.info("Using default workspace %s", ws_env.id)
|
|
234
|
+
ws_env = find_workspace(workdir=workdir, workspace=workspace)
|
|
235
|
+
workdir = ws_env.path
|
|
255
236
|
|
|
256
237
|
logging.info("Using working directory %s", str(workdir.resolve()))
|
|
257
238
|
|
|
@@ -262,7 +262,9 @@ class SlurmProcessBuilder(ProcessBuilder):
|
|
|
262
262
|
addstream(builder.command, "-i", self.stdin)
|
|
263
263
|
|
|
264
264
|
builder.command.extend(self.command)
|
|
265
|
-
logger.info(
|
|
265
|
+
logger.info(
|
|
266
|
+
"slurm sbatch command: %s", " ".join(f'"{s}"' for s in builder.command)
|
|
267
|
+
)
|
|
266
268
|
handler = OutputCaptureHandler()
|
|
267
269
|
builder.stdout = Redirect.pipe(handler)
|
|
268
270
|
builder.stderr = Redirect.inherit()
|
|
@@ -44,6 +44,12 @@ class LevelInformation:
|
|
|
44
44
|
return f"[{self.level}] {self.desc} {int(self.progress*1000)/10}%"
|
|
45
45
|
|
|
46
46
|
|
|
47
|
+
class ListenerInformation:
|
|
48
|
+
def __init__(self, url: str):
|
|
49
|
+
self.url = url
|
|
50
|
+
self.error_count = 0
|
|
51
|
+
|
|
52
|
+
|
|
47
53
|
class Reporter(threading.Thread):
|
|
48
54
|
NOTIFICATION_FOLDER = ".notifications"
|
|
49
55
|
|
|
@@ -59,7 +65,7 @@ class Reporter(threading.Thread):
|
|
|
59
65
|
super().__init__(daemon=True)
|
|
60
66
|
self.path = path / Reporter.NOTIFICATION_FOLDER
|
|
61
67
|
self.path.mkdir(exist_ok=True)
|
|
62
|
-
self.urls: Dict[str,
|
|
68
|
+
self.urls: Dict[str, ListenerInformation] = {}
|
|
63
69
|
|
|
64
70
|
# Last check of notification URLs
|
|
65
71
|
self.lastcheck = 0
|
|
@@ -80,7 +86,7 @@ class Reporter(threading.Thread):
|
|
|
80
86
|
self.cv.notifyAll()
|
|
81
87
|
|
|
82
88
|
@staticmethod
|
|
83
|
-
def isfatal_httperror(e: Exception) -> bool:
|
|
89
|
+
def isfatal_httperror(e: Exception, info: ListenerInformation) -> bool:
|
|
84
90
|
"""Returns True if this HTTP error indicates that the server won't recover"""
|
|
85
91
|
if isinstance(e, HTTPError):
|
|
86
92
|
if e.code >= 400 and e.code < 500:
|
|
@@ -90,6 +96,13 @@ class Reporter(threading.Thread):
|
|
|
90
96
|
return True
|
|
91
97
|
if isinstance(e.reason, socket.gaierror) and e.reason.errno == -2:
|
|
92
98
|
return True
|
|
99
|
+
if isinstance(e.reason, TimeoutError):
|
|
100
|
+
info.error_count += 1
|
|
101
|
+
|
|
102
|
+
# Too many errors
|
|
103
|
+
if info.error_count > 3:
|
|
104
|
+
logger.info("Too many errors with %s", info.error_count)
|
|
105
|
+
return True
|
|
93
106
|
|
|
94
107
|
return False
|
|
95
108
|
|
|
@@ -100,8 +113,8 @@ class Reporter(threading.Thread):
|
|
|
100
113
|
mtime = os.path.getmtime(self.path)
|
|
101
114
|
if mtime > self.lastcheck:
|
|
102
115
|
for f in self.path.iterdir():
|
|
103
|
-
self.urls[f.name] = f.read_text().strip()
|
|
104
|
-
logger.info("Added new notification URL: %s", self.urls[f.name])
|
|
116
|
+
self.urls[f.name] = ListenerInformation(f.read_text().strip())
|
|
117
|
+
logger.info("Added new notification URL: %s", self.urls[f.name].url)
|
|
105
118
|
f.unlink()
|
|
106
119
|
|
|
107
120
|
self.lastcheck = os.path.getmtime(self.path)
|
|
@@ -128,7 +141,9 @@ class Reporter(threading.Thread):
|
|
|
128
141
|
params = level.report()
|
|
129
142
|
|
|
130
143
|
# Go over all URLs
|
|
131
|
-
for key,
|
|
144
|
+
for key, info in self.urls.items():
|
|
145
|
+
baseurl = info.url
|
|
146
|
+
|
|
132
147
|
url = "{}/progress?{}".format(
|
|
133
148
|
baseurl, urllib.parse.urlencode(params)
|
|
134
149
|
)
|
|
@@ -147,7 +162,7 @@ class Reporter(threading.Thread):
|
|
|
147
162
|
url,
|
|
148
163
|
e,
|
|
149
164
|
)
|
|
150
|
-
if Reporter.isfatal_httperror(e):
|
|
165
|
+
if Reporter.isfatal_httperror(e, info):
|
|
151
166
|
toremove.append(key)
|
|
152
167
|
|
|
153
168
|
# Removes unvalid URLs
|
|
@@ -165,7 +180,8 @@ class Reporter(threading.Thread):
|
|
|
165
180
|
self.check_urls()
|
|
166
181
|
if self.urls:
|
|
167
182
|
# Go over all URLs
|
|
168
|
-
for key,
|
|
183
|
+
for key, info in self.urls.items():
|
|
184
|
+
baseurl = info.url
|
|
169
185
|
url = "{}?status=eoj".format(baseurl)
|
|
170
186
|
try:
|
|
171
187
|
with urlopen(url) as _:
|
|
@@ -243,7 +259,7 @@ class xpm_tqdm(std_tqdm):
|
|
|
243
259
|
|
|
244
260
|
def update(self, n=1):
|
|
245
261
|
result = super().update(n)
|
|
246
|
-
if self.total is not None:
|
|
262
|
+
if self.total is not None and self.total > 0:
|
|
247
263
|
progress(self.n / self.total, level=self.pos, console=False)
|
|
248
264
|
return result
|
|
249
265
|
|
|
@@ -803,11 +803,6 @@ class experiment:
|
|
|
803
803
|
else None
|
|
804
804
|
)
|
|
805
805
|
|
|
806
|
-
# Copy environment variable from main (but do not
|
|
807
|
-
# override)
|
|
808
|
-
for key, value in settings.env.items():
|
|
809
|
-
self.setenv(key, value, override=False)
|
|
810
|
-
|
|
811
806
|
if os.environ.get("XPM_ENABLEFAULTHANDLER", "0") == "1":
|
|
812
807
|
import faulthandler
|
|
813
808
|
|