experimaestro 1.7.0rc3__py3-none-any.whl → 1.8.0rc0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of experimaestro might be problematic. Click here for more details.

experimaestro/__init__.py CHANGED
@@ -55,8 +55,9 @@ from .core.context import SerializationContext
55
55
  from .core.serializers import SerializationLWTask, PathSerializationLWTask
56
56
  from .core.types import Any, SubmitHook
57
57
  from .launchers import Launcher
58
- from .scheduler.workspace import Workspace, RunMode
59
58
  from .scheduler import Scheduler, experiment, FailedExperiment
59
+ from .scheduler.workspace import Workspace, RunMode
60
+ from .scheduler.state import get_experiment
60
61
  from .notifications import progress, tqdm
61
62
  from .checkers import Choices
62
63
  from .xpmutils import DirectoryContext
@@ -1,22 +1,16 @@
1
1
  from contextlib import contextmanager
2
- from pathlib import Path
2
+ from pathlib import Path, UnsupportedOperation
3
3
  import shutil
4
4
  from typing import List, Optional, Protocol, Set, Union
5
5
  import os
6
- import sys
7
-
8
- has_hardlink_to = sys.version_info.major == 3 and sys.version_info.minor >= 10
9
6
 
10
7
 
11
8
  def shallow_copy(src_path: Path, dest_path: Path):
12
9
  """Copy a directory or file, trying to use hard links if possible"""
13
10
  if src_path.is_file():
14
11
  try:
15
- if has_hardlink_to:
16
- dest_path.hardlink_to(src_path)
17
- else:
18
- dest_path.link_to(src_path)
19
- except OSError:
12
+ dest_path.hardlink_to(src_path)
13
+ except (NotImplementedError, UnsupportedOperation, OSError):
20
14
  shutil.copy(src_path, dest_path)
21
15
  else:
22
16
  if dest_path.exists():
@@ -1079,7 +1079,7 @@ class ConfigInformation:
1079
1079
  if value is None:
1080
1080
  return None
1081
1081
 
1082
- elif isinstance(value, list):
1082
+ elif isinstance(value, (list, tuple)):
1083
1083
  return [ConfigInformation._outputjsonvalue(el, context) for el in value]
1084
1084
 
1085
1085
  elif isinstance(value, dict):
@@ -1196,7 +1196,7 @@ class ConfigInformation:
1196
1196
  configurations if necessary"""
1197
1197
  if isinstance(value, Config):
1198
1198
  value.__xpm__.__get_objects__(objects, context)
1199
- elif isinstance(value, list):
1199
+ elif isinstance(value, (list, tuple)):
1200
1200
  for el in value:
1201
1201
  ConfigInformation.__collect_objects__(el, objects, context)
1202
1202
  elif isinstance(value, dict):
@@ -1,6 +1,6 @@
1
1
  import json
2
2
  from pathlib import Path
3
- from typing import Any, Dict, List, Tuple, Union, TYPE_CHECKING
3
+ from typing import Any, Dict, List, Optional, Tuple, Union, TYPE_CHECKING
4
4
  from experimaestro.core.context import (
5
5
  SerializationContext,
6
6
  SerializedPath,
@@ -41,17 +41,20 @@ def state_dict(context: SerializationContext, obj: Any):
41
41
  return {"objects": objects, "data": data}
42
42
 
43
43
 
44
- def save(obj: Any, save_directory: Path):
44
+ def save_definition(obj: Any, context: SerializationContext, path: Path):
45
+ data = state_dict(context, obj)
46
+ with path.open("wt") as out:
47
+ json.dump(data, out)
48
+
49
+
50
+ def save(obj: Any, save_directory: Optional[Path]):
45
51
  """Saves an object into a disk file
46
52
 
47
53
  :param save_directory: The directory in which the object and its data will
48
54
  be saved (by default, the object is saved in "definition.json")
49
55
  """
50
56
  context = SerializationContext(save_directory=save_directory)
51
-
52
- data = state_dict(context, obj)
53
- with (save_directory / "definition.json").open("wt") as out:
54
- json.dump(data, out)
57
+ save_definition(obj, context, save_directory / "definition.json")
55
58
 
56
59
 
57
60
  def get_data_loader(path: Union[str, Path, SerializedPathLoader]):
@@ -1,4 +1,3 @@
1
- import imp
2
1
  import importlib
3
2
  import inspect
4
3
  import json
@@ -60,6 +59,7 @@ class ConfigurationLoader:
60
59
  def __init__(self):
61
60
  self.yamls = []
62
61
  self.python_path = set()
62
+ self.yaml_module_file: None | Path = None
63
63
 
64
64
  def load(self, yaml_file: Path):
65
65
  """Loads a YAML file, and parents one if they exist"""
@@ -68,6 +68,16 @@ class ConfigurationLoader:
68
68
 
69
69
  with yaml_file.open("rt") as fp:
70
70
  _data = yaml.full_load(fp)
71
+
72
+ if "file" in _data:
73
+ path = Path(_data["file"])
74
+ if not path.is_absolute():
75
+ _data["file"] = str((yaml_file.parent / path).resolve())
76
+
77
+ if "module" in _data:
78
+ # Keeps track of the YAML file where the module was defined
79
+ self.yaml_module_file = yaml_file
80
+
71
81
  if parent := _data.get("parent", None):
72
82
  self.load(yaml_file.parent / parent)
73
83
 
@@ -116,7 +126,10 @@ class ConfigurationLoader:
116
126
  help="Port for monitoring (can be defined in the settings.yaml file)",
117
127
  )
118
128
  @click.option(
119
- "--file", "xp_file", help="The file containing the main experimental code"
129
+ "--file",
130
+ "xp_file",
131
+ type=Path,
132
+ help="The file containing the main experimental code",
120
133
  )
121
134
  @click.option(
122
135
  "--module-name", "module_name", help="Module containing the experimental code"
@@ -193,12 +206,10 @@ def experiments_cli( # noqa: C901
193
206
  ), "Module name and experiment file are mutually exclusive options"
194
207
  xp_file = Path(xp_file)
195
208
  if not python_path:
196
- python_path.append(xp_file.parent)
209
+ python_path.append(xp_file.parent.absolute())
197
210
  logging.info(
198
211
  "Using python path: %s", ", ".join(str(s) for s in python_path)
199
212
  )
200
- else:
201
- xp_file = Path(xp_file)
202
213
 
203
214
  assert (
204
215
  module_name or xp_file
@@ -216,18 +227,29 @@ def experiments_cli( # noqa: C901
216
227
  for path in python_path:
217
228
  sys.path.append(str(path))
218
229
 
230
+ # --- Adds automatically the experiment module if not found
231
+ if module_name and conf_loader.yaml_module_file:
232
+ try:
233
+ importlib.import_module(module_name)
234
+ except ModuleNotFoundError:
235
+ # Try to setup a path
236
+ path = conf_loader.yaml_module_file.resolve()
237
+ for _ in range(len(module_name.split("."))):
238
+ path = path.parent
239
+
240
+ logging.info("Appending %s to python path", path)
241
+ sys.path.append(str(path))
242
+
219
243
  if xp_file:
220
244
  if not xp_file.exists() and xp_file.suffix != ".py":
221
245
  xp_file = xp_file.with_suffix(".py")
222
246
  xp_file: Path = Path(yaml_file).parent / xp_file
223
- with open(xp_file) as src:
224
- module_name = xp_file.with_suffix("").name
225
- mod = imp.load_module(
226
- module_name,
227
- src,
228
- str(xp_file.absolute()),
229
- (".py", "r", imp.PY_SOURCE),
230
- )
247
+ module_name = xp_file.with_suffix("").name
248
+ spec = importlib.util.spec_from_file_location(
249
+ module_name, str(xp_file.absolute())
250
+ )
251
+ mod = importlib.util.module_from_spec(spec)
252
+ spec.loader.exec_module(mod)
231
253
  else:
232
254
  # Module
233
255
  try:
@@ -240,17 +262,20 @@ def experiments_cli( # noqa: C901
240
262
 
241
263
  # --- ... and runs it
242
264
  if helper is None:
243
- raise ValueError(f"Could not find run function in {xp_file}")
265
+ raise click.ClickException(
266
+ f"Could not find run function in {xp_file if xp_file else module_name}"
267
+ )
244
268
 
245
269
  if not isinstance(helper, ExperimentHelper):
246
270
  helper = ExperimentHelper(helper)
247
271
 
248
272
  parameters = inspect.signature(helper.callable).parameters
249
273
  list_parameters = list(parameters.values())
250
- assert len(list_parameters) == 2, (
251
- "Callable function should only "
252
- f"have two arguments (got {len(list_parameters)})"
253
- )
274
+ if len(list_parameters) != 2:
275
+ raise click.ClickException(
276
+ f"run in {xp_file if xp_file else module_name} function should only "
277
+ f"have two arguments (got {len(list_parameters)}), "
278
+ )
254
279
 
255
280
  schema = list_parameters[1].annotation
256
281
  omegaconf_schema = OmegaConf.structured(schema())
@@ -260,7 +285,7 @@ def experiments_cli( # noqa: C901
260
285
  configuration = OmegaConf.merge(omegaconf_schema, configuration)
261
286
  except omegaconf.errors.ConfigKeyError as e:
262
287
  cprint(f"Error in configuration:\n\n{e}", "red", file=sys.stderr)
263
- sys.exit(1)
288
+ raise click.ClickException("Error in configuration")
264
289
 
265
290
  if show:
266
291
  print(json.dumps(OmegaConf.to_container(configuration))) # noqa: T201
@@ -1057,6 +1057,15 @@ class experiment:
1057
1057
  logger.info("Stopping web server")
1058
1058
  self.server.stop()
1059
1059
 
1060
+ if self.workspace.run_mode == RunMode.NORMAL:
1061
+ # Write the state
1062
+ logging.info("Saving the experiment state")
1063
+ from experimaestro.scheduler.state import ExperimentState
1064
+
1065
+ ExperimentState.save(
1066
+ self.workdir / "state.json", self.scheduler.jobs.values()
1067
+ )
1068
+
1060
1069
  async def update_task_output_count(self, delta: int):
1061
1070
  """Change in the number of task outputs to process"""
1062
1071
  async with self.central.exitCondition:
@@ -0,0 +1,75 @@
1
+ from dataclasses import dataclass, field
2
+ import json
3
+ from pathlib import Path
4
+ from typing import Iterable, Optional, Type
5
+ from experimaestro import Task
6
+
7
+ from experimaestro.core.context import SerializationContext
8
+ from experimaestro.scheduler.base import Job, JobDependency
9
+ from experimaestro.settings import find_workspace
10
+ from experimaestro.core.serialization import from_state_dict, save_definition
11
+
12
+
13
+ @dataclass
14
+ class JobInformation:
15
+ id: str
16
+ path: Path
17
+ task: Task
18
+ tags: dict[str, str]
19
+ depends_on: list["JobInformation"] = field(default_factory=list)
20
+
21
+ def __post_init__(self):
22
+ self.path = Path(self.path)
23
+
24
+
25
+ class ExperimentState:
26
+ def __init__(self, workdir: Path, name: str):
27
+ path = workdir / "xp" / name / "state.json"
28
+ with path.open("rt") as fh:
29
+ content = json.load(fh)
30
+
31
+ self.states: dict[str, JobInformation] = {
32
+ state_dict["id"]: JobInformation(**state_dict)
33
+ for state_dict in from_state_dict(content, as_instance=False)
34
+ }
35
+
36
+ for state in self.states.values():
37
+ state.depends_on = [self.states[key] for key in state.depends_on]
38
+
39
+ def get_jobs(self, task_class: Type[Task]) -> list[JobInformation]:
40
+ if task_class is None:
41
+ return list(self.data.values())
42
+
43
+ tasks = []
44
+ for job_state in self.states.values():
45
+ if isinstance(job_state.task, task_class):
46
+ tasks.append(job_state)
47
+ return tasks
48
+
49
+ @staticmethod
50
+ def save(path: Path, jobs: Iterable[Job]):
51
+ save_definition(
52
+ [
53
+ {
54
+ "id": job.identifier,
55
+ "path": str(job.path),
56
+ "task": job.config,
57
+ "tags": job.config.__xpm__.tags(),
58
+ "depends_on": list(
59
+ dep.origin.identifier
60
+ for dep in job.dependencies
61
+ if isinstance(dep, JobDependency)
62
+ ),
63
+ }
64
+ for job in jobs
65
+ ],
66
+ SerializationContext(),
67
+ path,
68
+ )
69
+
70
+
71
+ def get_experiment(
72
+ name: str, *, workspace: Optional[str] = None, workdir: Optional[Path] = None
73
+ ) -> ExperimentState:
74
+ ws = find_workspace(workspace=workspace, workdir=workdir)
75
+ return ExperimentState(ws.path, name)
@@ -12,11 +12,8 @@ from sphinx import addnodes
12
12
  from sphinx.ext.autodoc import ClassDocumenter, Documenter, restify
13
13
  from sphinx.locale import _
14
14
  from sphinx.util import inspect, logging
15
- from sphinx.domains.python import (
16
- PyClasslike,
17
- PyAttribute,
18
- directives, # noqa: F401
19
- )
15
+ from sphinx.domains.python import PyClasslike, PyAttribute, directives
16
+ from sphinx.domains.python import PyObject # noqa: F401
20
17
  from sphinx.addnodes import desc_signature
21
18
  from sphinx.util.typing import OptionSpec
22
19
  from docutils.statemachine import StringList
@@ -63,9 +63,9 @@ while IFS= read -r line; do
63
63
  esac
64
64
  done < "$1"
65
65
 
66
+ cd "$chdir"
66
67
  echo "Starting $@ ${args[@]} > $stdout 2> $stderr" >&2
67
68
  (
68
- if test "$chdir"; then cd "$chdir"; fi
69
69
  export PATH="${CURDIR}/bin:$PATH"
70
70
  eval "$@" "${args[@]}"
71
71
  echo $? > "$XPM_SLURM_DIR/jobs/$$.status"
@@ -0,0 +1,50 @@
1
+ from experimaestro import Task, Param, get_experiment, tag
2
+ from experimaestro.tests.utils import TemporaryDirectory, TemporaryExperiment
3
+
4
+
5
+ class TaskA(Task):
6
+ def execute(self):
7
+ pass
8
+
9
+
10
+ class TaskB(Task):
11
+ task_a: Param[TaskA]
12
+ x: Param[int]
13
+
14
+ def execute(self):
15
+ pass
16
+
17
+
18
+ # xp = get_experiment(id="my-xp-1")
19
+
20
+ # # Returns a list of tasks which were submitted and successful
21
+ # tasks = xp.get_tasks(myxps.evaluation.Evaluation, status=Job.DONE)
22
+
23
+ # for task in tasks:
24
+ # # Look at the tags
25
+ # print(task.tags)
26
+
27
+ # # Get some information
28
+ # print("Task ran in {task.workdir}")
29
+
30
+ # # Look at the parent jobs
31
+ # print(task.depends_on)
32
+
33
+ # # Look at the dependant
34
+ # print(task.dependents)
35
+
36
+
37
+ def test_experiment_history():
38
+ """Test retrieving experiment history"""
39
+ with TemporaryDirectory() as workdir:
40
+ with TemporaryExperiment("experiment", workdir=workdir):
41
+ task_a = TaskA().submit()
42
+ TaskB(task_a=task_a, x=tag(1)).submit()
43
+
44
+ # Look at the experiment
45
+ xp = get_experiment("experiment", workdir=workdir)
46
+
47
+ (task_a_info,) = xp.get_jobs(TaskA)
48
+ (task_b_info,) = xp.get_jobs(TaskB)
49
+ assert task_b_info.tags == {"x": 1}
50
+ assert task_b_info.depends_on == [task_a_info]
@@ -8,14 +8,7 @@ if sys.version_info.major == 3:
8
8
  else:
9
9
  from typing import _collect_parameters
10
10
 
11
- if sys.version_info.minor < 9:
12
- from typing_extensions import (
13
- _AnnotatedAlias as AnnotatedAlias,
14
- get_args,
15
- get_origin,
16
- )
17
- else:
18
- from typing import _AnnotatedAlias as AnnotatedAlias, get_args, get_origin
11
+ from typing import _AnnotatedAlias as AnnotatedAlias, get_args, get_origin
19
12
 
20
13
  GenericAlias = typing._GenericAlias
21
14
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: experimaestro
3
- Version: 1.7.0rc3
3
+ Version: 1.8.0rc0
4
4
  Summary: "Experimaestro is a computer science experiment manager"
5
5
  License: GPL-3
6
6
  Keywords: experiment manager
@@ -1,4 +1,4 @@
1
- experimaestro/__init__.py,sha256=qZXkir1sdCNkJ72W0OwpfH0c_Xk0OFczHrxZ1ORiWN8,1548
1
+ experimaestro/__init__.py,sha256=7ZR4dfOm70olFdhyOuQJnVa4a7NwoMFehGTkaFsX_7A,1592
2
2
  experimaestro/__main__.py,sha256=Dv9lFl03yt1dswd0Xb9NIJRgHpA5_IwH4RfQPEHyFz0,158
3
3
  experimaestro/annotations.py,sha256=wyVmPlkXuoT6IxJ-ti8bFo6HxhGY1BYBxM5-pib6shU,8773
4
4
  experimaestro/checkers.py,sha256=ZCMbnE_GFC5compWjt-fuHhPImi9fCPjImF8Ow9NqK8,696
@@ -13,16 +13,16 @@ experimaestro/connectors/local.py,sha256=348akOw69t7LgiTBMPG5McCg821I8qfR5GvYNU1
13
13
  experimaestro/connectors/ssh.py,sha256=5giqvv1y0QQKF-GI0IFUzI_Z5H8Bj9EuL_Szpvk899Q,8600
14
14
  experimaestro/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
15
  experimaestro/core/arguments.py,sha256=7hpkU1f8LJ7JL8kQaD514h9CFSfMotYLsVfMsMmdpWk,6487
16
- experimaestro/core/context.py,sha256=Q8_ngiHRBZ0laavXRJNiDvdCprrnROVTWaHfrwMdlG4,2638
17
- experimaestro/core/objects.py,sha256=6LDQzdH55n10Yck_6yee2rJzNICaiTNYl_yZY5dtbAg,67344
16
+ experimaestro/core/context.py,sha256=sw2Z8ijnVHirhmbzluFixJaSC2ovS2yQ-F-3Fywh0R4,2516
17
+ experimaestro/core/objects.py,sha256=G0_PjcUPmbrQi8lxaxwdTq0dIw2cTCJUHduQ4XEbfFw,67362
18
18
  experimaestro/core/objects.pyi,sha256=NElf7J-1rL2l9Td6fQofRj-UQTtt7d0tlO7NUyewqYI,7283
19
- experimaestro/core/serialization.py,sha256=9tg5ebLF3YeZ_zG9DiTHPLthppvo7io710ohD_dcLTo,3836
19
+ experimaestro/core/serialization.py,sha256=vYFbeNSgc7Icl9wgmnjZvESCehpfvlweyI_QyldA_CQ,3969
20
20
  experimaestro/core/serializers.py,sha256=R_CAMyjjfU1oi-eHU6VlEUixJpFayGqEPaYu7VsD9xA,1197
21
21
  experimaestro/core/types.py,sha256=gSLv9F1HszVxI8jla6e-aVVS7q3KBwSzG1MImUHdGMg,21158
22
22
  experimaestro/core/utils.py,sha256=JfC3qGUS9b6FUHc2VxIYUI9ysNpXSQ1LjOBkjfZ8n7o,495
23
23
  experimaestro/exceptions.py,sha256=cUy83WHM3GeynxmMk6QRr5xsnpqUAdAoc-m3KQVrE2o,44
24
24
  experimaestro/experiments/__init__.py,sha256=GcpDUIbCvhnv6rxFdAp4wTffCVNTv-InY6fbQAlTy-o,159
25
- experimaestro/experiments/cli.py,sha256=fvHz2aih7Aw1DK3GoVkeaVtG3r1tU6qbnwIv-uD0eVI,8697
25
+ experimaestro/experiments/cli.py,sha256=iQrUjY6mmJpT-tj-Ek1QPbzNs27x4jsKjciCMgaTKZw,9722
26
26
  experimaestro/experiments/configuration.py,sha256=cFDiUHnUGblJsctAUxAqx0jlM7_Ja_527lzk-4G-44k,1368
27
27
  experimaestro/generators.py,sha256=DQsEgdMwRUud9suWr-QGxI3vCO5sywP6MVGZWRNQXkk,1372
28
28
  experimaestro/huggingface.py,sha256=gnVlr6SZnbutYz4PLH0Q77n1TRF-uk-dR-3UFzFqAY0,2956
@@ -49,10 +49,11 @@ experimaestro/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
49
  experimaestro/rpyc.py,sha256=ZRKol-3tVoeoUITLNFenLF4dhWBLW_FvSV_GvsypmeI,3605
50
50
  experimaestro/run.py,sha256=58ZlIZ2dQ7a0un2iGiyHJhK14zc18BnpEFDis7OyTPA,5222
51
51
  experimaestro/scheduler/__init__.py,sha256=ERmmOxz_9mUkIuccNbzUa5Y6gVLLVDdyc4cCxbCCUbY,20
52
- experimaestro/scheduler/base.py,sha256=R40hKI_2cpyZ8F4GTwEulTWczPAaGYi1UaaELh9etGM,35368
52
+ experimaestro/scheduler/base.py,sha256=9Vh6S3SVEr6VF_Zp3fCf8Jl_ygnEJPVElu4ghOuSapc,35702
53
53
  experimaestro/scheduler/dependencies.py,sha256=n9XegwrmjayOIxt3xhuTEBVEBGSq4oeVdzz-FviDGXo,1994
54
54
  experimaestro/scheduler/dynamic_outputs.py,sha256=yYPL98I0nSgDjlE3Sk9dtvovh2PZ6rUDnKjDNnAg1dc,5732
55
55
  experimaestro/scheduler/services.py,sha256=aCKkNZMULlceabqf-kOs_-C7KPINnjU3Q-I00o5x6iY,2189
56
+ experimaestro/scheduler/state.py,sha256=szTgnI_hAVqU2OWrrIXsZrO3VsrJlHryXUU0r95w_sw,2367
56
57
  experimaestro/scheduler/workspace.py,sha256=KNdxPBwUk7gO8h2utMCrlIVKB-f2Ylqg_IxLc4okp_8,2320
57
58
  experimaestro/scriptbuilder.py,sha256=6GKUkgixLqSEy41sNr-_HNcrjKb8uxaoQ65DywRYsC0,5027
58
59
  experimaestro/server/__init__.py,sha256=F2bzLf2q29Haj2OIbPA26r5WVbaipBNylIozg-As758,10854
@@ -87,7 +88,7 @@ experimaestro/server/data/index.js.map,sha256=cv7KF28Uq5dy7Ux3yRnoSVztrOFVid359f
87
88
  experimaestro/server/data/login.html,sha256=4dvhSOn6DHp_tbmzqIKrqq2uAo0sAUbgLVD0lTnPp4s,511
88
89
  experimaestro/server/data/manifest.json,sha256=EpzHQZzrGh9c1Kf63nrqvI33H1cm0nLYfdh5lDm8ijI,318
89
90
  experimaestro/settings.py,sha256=U6gTVBL5Z4Rk0_7BAVoavVJKN2sQNRpspE-601Elfys,3170
90
- experimaestro/sphinx/__init__.py,sha256=xac4NmlxvciVONXfr3CChHH7AxZeAuQoC1MYL4Hwu3g,9440
91
+ experimaestro/sphinx/__init__.py,sha256=HAofa65lCLAUOShgWwJIGEEOPKzu4VEs5LZd46V_Bng,9466
91
92
  experimaestro/sphinx/static/experimaestro.css,sha256=0rEgt1LoDdD-a_R5rVfWZ19zD1gR-1L7q3f4UibIB58,294
92
93
  experimaestro/taskglobals.py,sha256=Lp0bqobVLndR7fOtF9qPI7utTKQXXwTdVN6l5Av9Dc4,660
93
94
  experimaestro/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -98,7 +99,7 @@ experimaestro/tests/connectors/utils.py,sha256=9sM3Pwy2nRfSr7pwQoOoSCDhBrEcDsEEl
98
99
  experimaestro/tests/definitions_types.py,sha256=nMoQxZxhTJAYV87Ce9F2dAITxXGHf7Uw5j-MKsZ3LmQ,399
99
100
  experimaestro/tests/launchers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
100
101
  experimaestro/tests/launchers/bin/sacct,sha256=9mmRAYCE4RBSBOf7aanhFw9hzujOUlcw3OJmZJ3K-Wc,639
101
- experimaestro/tests/launchers/bin/sbatch,sha256=MGzCDw6ywc973nMViPijwLzJcAW-ghJynMJA00h9AoQ,1746
102
+ experimaestro/tests/launchers/bin/sbatch,sha256=KgG4xUiIpELHBWLjnM7IUBu5jKiIGnILS9HfHE5eVFk,1715
102
103
  experimaestro/tests/launchers/bin/srun,sha256=3oE3qq0UFpVtTvXfR1kH3tovFYX74fp1Fk-o8zgsaJA,47
103
104
  experimaestro/tests/launchers/bin/test.py,sha256=MbxdAd2Sf7T-Hj3ldmrtngbQuBdNOkXjMcICJTf39wI,477
104
105
  experimaestro/tests/launchers/common.py,sha256=E09KhrQfNQNZbaeVkXBgHk2906DvaCEU7CqEQvLbZTE,2994
@@ -116,6 +117,7 @@ experimaestro/tests/tasks/all.py,sha256=OMkHsWZkErCmTajiNO7hNhvnk9eKzJC-VatWgabW
116
117
  experimaestro/tests/tasks/foreign.py,sha256=uhXDOcWozkcm26ybbeEU9RElJpbhjC-zdzmlSKfPcdY,122
117
118
  experimaestro/tests/test_checkers.py,sha256=Kg5frDNRE3pvWVmmYzyk0tJFNO885KOrK48lSu-NlYA,403
118
119
  experimaestro/tests/test_dependencies.py,sha256=xfWrSkvjT45G4FSCL535m1huLT2ghmyW7kvP_XvvCJQ,2005
120
+ experimaestro/tests/test_experiment.py,sha256=MXpVsWZpxINBianuTQ8vJ5iwmpIUq-GcS7YwSjLJUxM,1260
119
121
  experimaestro/tests/test_findlauncher.py,sha256=8tjpR8bLMi6Gjs7KpY2t64izZso6bmY7vIivMflm-Bc,2965
120
122
  experimaestro/tests/test_forward.py,sha256=9y1zYm7hT_Lx5citxnK7n20cMZ2WJbsaEeY5irCZ9U4,735
121
123
  experimaestro/tests/test_identifier.py,sha256=L-r0S0dI9ErOZSmqGOPbbUZBvWJ-uzc3sijoyTPyMYU,13680
@@ -139,7 +141,7 @@ experimaestro/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSu
139
141
  experimaestro/tools/diff.py,sha256=FBCwupPrSwkEOcqYu0NWe7LTkuOW6r-_btoCel2_k_I,3436
140
142
  experimaestro/tools/documentation.py,sha256=O2UzjzodPqGot3YSe6NYlK7S42XpplakUdqxFpvjqHQ,9184
141
143
  experimaestro/tools/jobs.py,sha256=63bXhJ7RGdczLU_nxu2skGn-9dwgr4r5pD23qH4WeBA,3516
142
- experimaestro/typingutils.py,sha256=XjEljfizrUeVedWVmtnYFpeTEJ2I8zU1xj3CxkZ8mJ8,3572
144
+ experimaestro/typingutils.py,sha256=NiHx62CQs1pJ6SwuZLxzlLXhxZUIe_cCgotLCHO9dhE,3380
143
145
  experimaestro/utils/__init__.py,sha256=BdYguxAbR1jOQPV36OgGA31itaMvBJ6WVPV6b4Jn4xw,2434
144
146
  experimaestro/utils/asyncio.py,sha256=9r_vFQs6T6tqmymC_DbHVFhY9YVRO6X48uEuyL_ugP8,726
145
147
  experimaestro/utils/jobs.py,sha256=42FAdKcn_v_-M6hcQZPUBr9kbDt1eVsk3a4E8Gc4eu8,2394
@@ -147,8 +149,8 @@ experimaestro/utils/jupyter.py,sha256=JcEo2yQK7x3Cr1tNl5FqGMZOICxCv9DwMvL5xsWdQP
147
149
  experimaestro/utils/resources.py,sha256=j-nvsTFwmgENMoVGOD2Ap-UD3WU85WkI0IgeSszMCX4,1328
148
150
  experimaestro/utils/settings.py,sha256=jpFMqF0DLL4_P1xGal0zVR5cOrdD8O0Y2IOYvnRgN3k,793
149
151
  experimaestro/xpmutils.py,sha256=S21eMbDYsHfvmZ1HmKpq5Pz5O-1HnCLYxKbyTBbASyQ,638
150
- experimaestro-1.7.0rc3.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
151
- experimaestro-1.7.0rc3.dist-info/METADATA,sha256=-fuyq-zQ7nqyCb4NJ0fbTWp5YTZKgFDk6o26noSDrJQ,6162
152
- experimaestro-1.7.0rc3.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
153
- experimaestro-1.7.0rc3.dist-info/entry_points.txt,sha256=TppTNiz5qm5xm1fhAcdLKdCLMrlL-eQggtCrCI00D9c,446
154
- experimaestro-1.7.0rc3.dist-info/RECORD,,
152
+ experimaestro-1.8.0rc0.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
153
+ experimaestro-1.8.0rc0.dist-info/METADATA,sha256=lIhCOBnO2j7MDVoEc5wNHw-rzUKcCkcR-y-yBFgx6vA,6162
154
+ experimaestro-1.8.0rc0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
155
+ experimaestro-1.8.0rc0.dist-info/entry_points.txt,sha256=TppTNiz5qm5xm1fhAcdLKdCLMrlL-eQggtCrCI00D9c,446
156
+ experimaestro-1.8.0rc0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.1.2
2
+ Generator: poetry-core 2.1.3
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any