experimaestro 1.6.2__py3-none-any.whl → 1.7.0rc1__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.

Files changed (71) hide show
  1. experimaestro/__init__.py +3 -1
  2. experimaestro/annotations.py +13 -3
  3. experimaestro/cli/filter.py +3 -3
  4. experimaestro/cli/jobs.py +1 -1
  5. experimaestro/connectors/__init__.py +17 -8
  6. experimaestro/connectors/local.py +8 -3
  7. experimaestro/core/arguments.py +26 -3
  8. experimaestro/core/objects.py +90 -6
  9. experimaestro/core/objects.pyi +7 -1
  10. experimaestro/core/types.py +33 -2
  11. experimaestro/generators.py +6 -1
  12. experimaestro/ipc.py +4 -1
  13. experimaestro/launcherfinder/registry.py +18 -4
  14. experimaestro/notifications.py +1 -1
  15. experimaestro/run.py +1 -1
  16. experimaestro/scheduler/base.py +94 -10
  17. experimaestro/scheduler/dynamic_outputs.py +184 -0
  18. experimaestro/server/data/016b4a6cdced82ab3aa1.ttf +0 -0
  19. experimaestro/server/data/0c35d18bf06992036b69.woff2 +0 -0
  20. experimaestro/server/data/1815e00441357e01619e.ttf +0 -0
  21. experimaestro/server/data/219aa9140e099e6c72ed.woff2 +0 -0
  22. experimaestro/server/data/2463b90d9a316e4e5294.woff2 +0 -0
  23. experimaestro/server/data/2582b0e4bcf85eceead0.ttf +0 -0
  24. experimaestro/server/data/3a4004a46a653d4b2166.woff +0 -0
  25. experimaestro/server/data/3baa5b8f3469222b822d.woff +0 -0
  26. experimaestro/server/data/4d73cb90e394b34b7670.woff +0 -0
  27. experimaestro/server/data/4ef4218c522f1eb6b5b1.woff2 +0 -0
  28. experimaestro/server/data/50701fbb8177c2dde530.ttf +0 -0
  29. experimaestro/server/data/5d681e2edae8c60630db.woff +0 -0
  30. experimaestro/server/data/6f420cf17cc0d7676fad.woff2 +0 -0
  31. experimaestro/server/data/878f31251d960bd6266f.woff2 +0 -0
  32. experimaestro/server/data/89999bdf5d835c012025.woff2 +0 -0
  33. experimaestro/server/data/914997e1bdfc990d0897.ttf +0 -0
  34. experimaestro/server/data/b041b1fa4fe241b23445.woff2 +0 -0
  35. experimaestro/server/data/b6879d41b0852f01ed5b.woff2 +0 -0
  36. experimaestro/server/data/c210719e60948b211a12.woff2 +0 -0
  37. experimaestro/server/data/c380809fd3677d7d6903.woff2 +0 -0
  38. experimaestro/server/data/d75e3fd1eb12e9bd6655.ttf +0 -0
  39. experimaestro/server/data/f882956fd323fd322f31.woff +0 -0
  40. experimaestro/server/data/favicon.ico +0 -0
  41. experimaestro/server/data/index.css +22963 -0
  42. experimaestro/server/data/index.css.map +1 -0
  43. experimaestro/server/data/index.html +27 -0
  44. experimaestro/server/data/index.js +101770 -0
  45. experimaestro/server/data/index.js.map +1 -0
  46. experimaestro/server/data/login.html +22 -0
  47. experimaestro/server/data/manifest.json +15 -0
  48. experimaestro/taskglobals.py +7 -2
  49. experimaestro/tests/definitions_types.py +5 -3
  50. experimaestro/tests/launchers/bin/sbatch +18 -5
  51. experimaestro/tests/launchers/common.py +11 -3
  52. experimaestro/tests/restart.py +6 -3
  53. experimaestro/tests/tasks/all.py +16 -10
  54. experimaestro/tests/tasks/foreign.py +2 -4
  55. experimaestro/tests/test_forward.py +5 -5
  56. experimaestro/tests/test_identifier.py +61 -66
  57. experimaestro/tests/test_instance.py +3 -6
  58. experimaestro/tests/test_param.py +40 -22
  59. experimaestro/tests/test_tags.py +5 -11
  60. experimaestro/tests/test_tokens.py +3 -2
  61. experimaestro/tests/test_types.py +17 -14
  62. experimaestro/tests/test_validation.py +48 -91
  63. experimaestro/tokens.py +16 -5
  64. experimaestro/typingutils.py +7 -0
  65. experimaestro/utils/asyncio.py +6 -2
  66. experimaestro/utils/resources.py +7 -3
  67. {experimaestro-1.6.2.dist-info → experimaestro-1.7.0rc1.dist-info}/METADATA +3 -4
  68. {experimaestro-1.6.2.dist-info → experimaestro-1.7.0rc1.dist-info}/RECORD +71 -40
  69. {experimaestro-1.6.2.dist-info → experimaestro-1.7.0rc1.dist-info}/WHEEL +1 -1
  70. {experimaestro-1.6.2.dist-info → experimaestro-1.7.0rc1.dist-info}/LICENSE +0 -0
  71. {experimaestro-1.6.2.dist-info → experimaestro-1.7.0rc1.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,22 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta
6
+ name="viewport"
7
+ content="width=device-width, initial-scale=1, shrink-to-fit=no"
8
+ />
9
+ <meta name="theme-color" content="#000000" />
10
+ <title>Experimaestro</title>
11
+ </head>
12
+ <body>
13
+ <h1>Experimaestro</h1>
14
+ <form action="/auth" method="GET">
15
+ <div>
16
+ Token
17
+ <input type="text" name="xpm-token" />
18
+ <input type="submit" value="submit" />
19
+ </div>
20
+ </form>
21
+ </body>
22
+ </html>
@@ -0,0 +1,15 @@
1
+ {
2
+ "short_name": "Experimaestro",
3
+ "name": "Experimaestro Client",
4
+ "icons": [
5
+ {
6
+ "src": "favicon.ico",
7
+ "sizes": "64x64 32x32 24x24 16x16",
8
+ "type": "image/x-icon"
9
+ }
10
+ ],
11
+ "start_url": "./index.html",
12
+ "display": "standalone",
13
+ "theme_color": "#000000",
14
+ "background_color": "#ffffff"
15
+ }
@@ -1,7 +1,6 @@
1
+ from functools import cached_property
1
2
  from pathlib import Path
2
3
  from typing import Optional
3
- import os
4
- import logging
5
4
 
6
5
 
7
6
  class Env:
@@ -18,6 +17,12 @@ class Env:
18
17
  # - no progress report
19
18
  slave: bool = False
20
19
 
20
+ @cached_property
21
+ def xpm_path(self):
22
+ path = self.taskpath / ".experimaestro"
23
+ path.mkdir(exist_ok=True)
24
+ return path
25
+
21
26
  @staticmethod
22
27
  def instance():
23
28
  if Env._instance is None:
@@ -1,15 +1,17 @@
1
- from experimaestro import argument, Task
1
+ from experimaestro import Param, Task
2
2
 
3
3
 
4
- @argument("value", type=int)
5
4
  class IntegerTask(Task):
5
+ value: Param[int]
6
+
6
7
  def execute(self):
7
8
  if not isinstance(self.value, int):
8
9
  raise AssertionError("Not an integer")
9
10
 
10
11
 
11
- @argument("value", type=float)
12
12
  class FloatTask(Task):
13
+ value: Param[float]
14
+
13
15
  def execute(self):
14
16
  if not isinstance(self.value, float):
15
17
  raise AssertionError("Not a float but %s" % type(self.value))
@@ -10,7 +10,17 @@ if ! test -d "$XPM_SLURM_DIR"; then
10
10
  fi
11
11
 
12
12
  mkdir -p "$XPM_SLURM_DIR/jobs"
13
- echo "Slurm directory: $XPM_SLURM_DIR" >&2
13
+ echo "Slurm directory: $XPM_SLURM_DIR" >&2
14
+
15
+ RED='\033[0;31m'
16
+ NC='\033[0m' # No Color
17
+
18
+
19
+ if ! which flock > /dev/null; then
20
+ echo -e "[${RED}ERROR${NC}] flock is not installed on this system" 1>&2
21
+ exit 1
22
+ fi
23
+
14
24
 
15
25
  lockpath() {
16
26
  fid="$1"
@@ -18,7 +28,7 @@ lockpath() {
18
28
 
19
29
  echo "Locking $path..." 1>&2
20
30
  eval exec "$fid<>" $path
21
- if ! flock --timeout 2 $fid; then
31
+ if ! flock --timeout 2 $fid; then
22
32
  echo Could not lock "$path" - stopping 1>&2
23
33
  exit 017
24
34
  fi
@@ -37,12 +47,15 @@ while true; do
37
47
  -o) shift; stdout="$1"; shift;;
38
48
  -e) shift; stderr="$1"; shift;;
39
49
  --*) args+=("$1"); shift;;
40
- *) break 2;;
50
+ *) break 2;;
41
51
  esac
42
52
  done
43
53
 
44
54
  echo "Starting $@ ${args[@]} > $stdout" >&2
45
- (eval "$@" "${args[@]}"; echo $? > "$XPM_SLURM_DIR/jobs/$$.status") > $stdout 2> $stderr &
55
+ (
56
+ eval "$@" "${args[@]}"
57
+ echo $? > "$XPM_SLURM_DIR/jobs/$$.status"
58
+ ) > $stdout 2> $stderr &
46
59
  JOBID="$$"
47
60
  date > "$XPM_SLURM_DIR/jobs/$JOBID.start"
48
61
  disown
@@ -51,4 +64,4 @@ if test "$parsable" == 0; then
51
64
  echo "Submitted batch job ${JOBID}"
52
65
  else
53
66
  echo "${JOBID};cluster"
54
- fi
67
+ fi
@@ -68,24 +68,32 @@ class WaitUntilTouched(Task):
68
68
 
69
69
 
70
70
  def takeback(launcher, datapath, txp1, txp2):
71
+ """Launch two times the same task (with two experiments)
72
+
73
+ :param launcher: The launcher
74
+ :param datapath: The path containing the two files that control the task, namely (1) touching which is created by the task when starting, (2) waiting which is controlled here
75
+ :param txp1: The first experiment
76
+ :param txp2: The second experiment
77
+ """
71
78
  datapath.mkdir()
72
79
  touching = datapath / "touching"
73
80
  waiting = datapath / "waiting"
74
81
 
75
- with txp1 as xp1: # flake8: noqa: F841
82
+ with txp1:
76
83
  WaitUntilTouched(touching=touching, waiting=waiting).submit(launcher=launcher)
77
84
 
78
85
  logger.debug("Waiting for task to create 'touching' file")
79
86
  while not touching.is_file():
80
87
  time.sleep(0.01)
81
88
 
82
- with txp2 as xp2: # flake8: noqa: F841
89
+ with txp2:
83
90
  result = WaitUntilTouched(touching=touching, waiting=waiting).submit(
84
91
  launcher=launcher
85
92
  )
86
93
 
87
- logger.debug("Waiting for job to be in running mode")
94
+ logger.debug("Waiting for job to be running (scheduler)")
88
95
  while result.__xpm__.job.state != JobState.RUNNING:
89
96
  time.sleep(0.1)
90
97
 
98
+ logger.debug("OK, no we can notify the task")
91
99
  waiting.touch()
@@ -1,12 +1,14 @@
1
1
  import time
2
+ from pathlib import Path
2
3
  import sys
3
4
  from typing import Callable
4
- from experimaestro import Task, pathoption
5
+ from experimaestro import Task, Meta, field, PathGenerator
5
6
  import psutil
6
7
  import logging
7
8
  import subprocess
8
9
  import json
9
10
  import signal
11
+
10
12
  from experimaestro.scheduler.workspace import RunMode
11
13
  from experimaestro.tests.utils import TemporaryExperiment, is_posix
12
14
  from experimaestro.scheduler import JobState
@@ -26,9 +28,10 @@ if is_posix():
26
28
  TERMINATES_FUNC.append(sigint)
27
29
 
28
30
 
29
- @pathoption("touch", "touch")
30
- @pathoption("wait", "wait")
31
31
  class Restart(Task):
32
+ touch: Meta[Path] = field(default_factory=PathGenerator("touch"))
33
+ wait: Meta[Path] = field(default_factory=PathGenerator("wait"))
34
+
32
35
  def execute(self):
33
36
  # Write the file "touch" to notify that we started
34
37
  with open(self.touch, "w") as out:
@@ -1,11 +1,13 @@
1
+ from pathlib import Path
1
2
  import time
2
3
  from typing import List
3
4
  from experimaestro import (
4
- param,
5
+ Meta,
5
6
  Param,
7
+ field,
6
8
  Task,
9
+ PathGenerator,
7
10
  Config,
8
- pathoption,
9
11
  STDOUT,
10
12
  cache,
11
13
  )
@@ -18,8 +20,8 @@ class SimpleTask(Task):
18
20
  print(self.x) # noqa: T201
19
21
 
20
22
 
21
- @pathoption("out", STDOUT)
22
23
  class Say(Task):
24
+ out: Meta[Path] = field(default_factory=PathGenerator(STDOUT))
23
25
  word: Param[str]
24
26
 
25
27
  def execute(self):
@@ -38,19 +40,20 @@ class Concat(Task):
38
40
  print(" ".join(says)) # noqa: T201
39
41
 
40
42
 
41
- @param("x", type=int)
42
43
  class ForeignClassB1(Config):
43
- pass
44
+ x: Param[int]
44
45
 
45
46
 
46
- @param("b", type=ForeignClassB1)
47
47
  class ForeignTaskA(Task):
48
+ b: Param[ForeignClassB1]
49
+
48
50
  def execute(self):
49
51
  print(self.b.x) # noqa: T201
50
52
 
51
53
 
52
- @pathoption("wait", "wait")
53
54
  class Fail(Task):
55
+ wait: Meta[Path] = field(default_factory=PathGenerator("wait"))
56
+
54
57
  def execute(self):
55
58
  while not self.wait.is_file():
56
59
  time.sleep(0.01)
@@ -64,14 +67,16 @@ class Fail(Task):
64
67
  out.write("hello")
65
68
 
66
69
 
67
- @param("fail", Fail)
68
70
  class FailConsumer(Task):
71
+ fail: Param[Fail]
72
+
69
73
  def execute(self):
70
74
  return True
71
75
 
72
76
 
73
- @param("a", int)
74
77
  class Method(Task):
78
+ a: Param[int]
79
+
75
80
  def execute(self):
76
81
  assert self.a == 1
77
82
 
@@ -92,7 +97,8 @@ class CacheConfig(Config):
92
97
  return path.read_text()
93
98
 
94
99
 
95
- @param("data", type=CacheConfig)
96
100
  class CacheConfigTask(Task):
101
+ data: Param[CacheConfig]
102
+
97
103
  def execute(self):
98
104
  assert self.data.get() == "hello"
@@ -1,8 +1,6 @@
1
- from experimaestro import param, config
1
+ from experimaestro import Param
2
2
  from .all import ForeignClassB1
3
3
 
4
4
 
5
- @param("y", type=int)
6
- @config()
7
5
  class ForeignClassB2(ForeignClassB1):
8
- pass
6
+ y: Param[int]
@@ -1,12 +1,12 @@
1
- from experimaestro import argument, Config
1
+ from experimaestro import Param, Config
2
2
  from experimaestro.click import forwardoption
3
3
  import click
4
4
 
5
5
 
6
6
  def test_main():
7
- @argument("epochs", type=int, default=100, help="Number of learning epochs")
8
7
  class MyModel(Config):
9
- pass
8
+ epochs: Param[int] = 100
9
+ """Number of learning epochs"""
10
10
 
11
11
  @forwardoption.epochs(MyModel)
12
12
  @click.command()
@@ -18,9 +18,9 @@ def test_main():
18
18
 
19
19
 
20
20
  def test_rename():
21
- @argument("epochs", type=int, default=100, help="Number of learning epochs")
22
21
  class MyModel(Config):
23
- pass
22
+ epochs: Param[int] = 100
23
+ """Number of learning epochs"""
24
24
 
25
25
  @forwardoption.epochs(MyModel, "my-epochs")
26
26
  @click.command()
@@ -4,16 +4,14 @@ import json
4
4
  from pathlib import Path
5
5
  from typing import Dict, List, Optional
6
6
  from experimaestro import (
7
- config,
8
7
  Param,
9
- param,
10
8
  deprecate,
11
9
  Config,
12
10
  Constant,
13
11
  Meta,
14
12
  Option,
15
- pathgenerator,
16
- Annotated,
13
+ PathGenerator,
14
+ field,
17
15
  Task,
18
16
  LightweightTask,
19
17
  )
@@ -48,8 +46,7 @@ class Float(Config):
48
46
  value: Param[float]
49
47
 
50
48
 
51
- @config()
52
- class Values:
49
+ class Values(Config):
53
50
  value1: Param[float]
54
51
  value2: Param[float]
55
52
 
@@ -66,50 +63,50 @@ def assert_notequal(a, b, message=""):
66
63
  assert getidentifier(a) != getidentifier(b), message
67
64
 
68
65
 
69
- def test_int():
66
+ def test_param_int():
70
67
  assert_equal(A(a=1), A(a=1))
71
68
 
72
69
 
73
- def test_different_type():
70
+ def test_param_different_type():
74
71
  assert_notequal(A(a=1), B(a=1))
75
72
 
76
73
 
77
- def test_order():
74
+ def test_param_order():
78
75
  assert_equal(Values(value1=1, value2=2), Values(value2=2, value1=1))
79
76
 
80
77
 
81
- def test_default():
78
+ def test_param_default():
82
79
  assert_equal(C(a=1, b=2), C(b=2))
83
80
 
84
81
 
85
- def test_inner_eq():
82
+ def test_param_inner_eq():
86
83
  assert_equal(D(a=A(a=1)), D(a=A(a=1)))
87
84
 
88
85
 
89
- def test_float():
86
+ def test_param_float():
90
87
  assert_equal(Float(value=1), Float(value=1))
91
88
 
92
89
 
93
- def test_float2():
90
+ def test_param_float2():
94
91
  assert_equal(Float(value=1.0), Float(value=1))
95
92
 
96
93
 
97
94
  # --- Argument name
98
95
 
99
96
 
100
- def test_name():
97
+ def test_param_name():
101
98
  """The identifier fully determines the hash code"""
102
99
 
103
- @config("test.identifier.argumentname")
104
- class Config0:
100
+ class Config0(Config):
101
+ __xpmid__ = "test.identifier.argumentname"
105
102
  a: Param[int]
106
103
 
107
- @config("test.identifier.argumentname")
108
- class Config1:
104
+ class Config1(Config):
105
+ __xpmid__ = "test.identifier.argumentname"
109
106
  b: Param[int]
110
107
 
111
- @config("test.identifier.argumentname")
112
- class Config3:
108
+ class Config3(Config):
109
+ __xpmid__ = "test.identifier.argumentname"
113
110
  a: Param[int]
114
111
 
115
112
  assert_notequal(Config0(a=2), Config1(b=2))
@@ -119,9 +116,9 @@ def test_name():
119
116
  # --- Test option
120
117
 
121
118
 
122
- def test_option():
123
- @config("test.identifier.option")
124
- class OptionConfig:
119
+ def test_param_option():
120
+ class OptionConfig(Config):
121
+ __xpmid__ = "test.identifier.option"
125
122
  a: Param[int]
126
123
  b: Option[int] = 1
127
124
 
@@ -133,7 +130,7 @@ def test_option():
133
130
  # --- Dictionnary
134
131
 
135
132
 
136
- def test_identifier_dict():
133
+ def test_param_identifier_dict():
137
134
  """Test identifiers of dictionary structures"""
138
135
 
139
136
  class B(Config):
@@ -152,13 +149,12 @@ def test_identifier_dict():
152
149
  # --- Ignore paths
153
150
 
154
151
 
155
- @config()
156
- class TypeWithPath:
152
+ class TypeWithPath(Config):
157
153
  a: Param[int]
158
154
  path: Param[Path]
159
155
 
160
156
 
161
- def test_path():
157
+ def test_param_identifier_path():
162
158
  """Path should be ignored"""
163
159
  assert_equal(TypeWithPath(a=1, path="/a/b"), TypeWithPath(a=1, path="/c/d"))
164
160
  assert_notequal(TypeWithPath(a=2, path="/a/b"), TypeWithPath(a=1, path="/c/d"))
@@ -167,23 +163,23 @@ def test_path():
167
163
  # --- Test with added arguments
168
164
 
169
165
 
170
- def test_pathoption():
166
+ def test_param_identifier_pathoption():
171
167
  """Path arguments should be ignored"""
172
168
 
173
- @config("pathoption_test")
174
- class A_with_path:
169
+ class A_with_path(Config):
170
+ __xpmid__ = "pathoption_test"
175
171
  a: Param[int]
176
- path: Annotated[Path, pathgenerator("path")]
172
+ path: Meta[Path] = field(default_factory=PathGenerator("path"))
177
173
 
178
- @config("pathoption_test")
179
- class A_without_path:
174
+ class A_without_path(Config):
175
+ __xpmid__ = "pathoption_test"
180
176
  a: Param[int]
181
177
 
182
178
  assert_equal(A_with_path(a=1), A_without_path(a=1))
183
179
 
184
180
 
185
- def test_identifier_enum():
186
- """Path arguments should be ignored"""
181
+ def test_param_identifier_enum():
182
+ """test enum parameters"""
187
183
  from enum import Enum
188
184
 
189
185
  class EnumParam(Enum):
@@ -197,7 +193,7 @@ def test_identifier_enum():
197
193
  assert_equal(EnumConfig(a=EnumParam.FIRST), EnumConfig(a=EnumParam.FIRST))
198
194
 
199
195
 
200
- def test_identifier_addnone():
196
+ def test_param_identifier_addnone():
201
197
  """Test the case of new parameter (with None default)"""
202
198
 
203
199
  class B(Config):
@@ -214,25 +210,24 @@ def test_identifier_addnone():
214
210
  assert_notequal(A_with_b(b=B(x=1)), A())
215
211
 
216
212
 
217
- def test_defaultnew():
213
+ def test_param_defaultnew():
218
214
  """Path arguments should be ignored"""
219
215
 
220
- @param("b", type=int, default=1)
221
- @param(name="a", type=int)
222
- @config("defaultnew")
223
- class A_with_b:
224
- pass
216
+ class A_with_b(Config):
217
+ __xpmid__ = "defaultnew"
225
218
 
226
- @param(name="a", type=int)
227
- @config("defaultnew")
228
- class A:
229
- pass
219
+ a: Param[int]
220
+ b: Param[int] = 1
221
+
222
+ class A(Config):
223
+ __xpmid__ = "defaultnew"
224
+ a: Param[int]
230
225
 
231
226
  assert_equal(A_with_b(a=1, b=1), A(a=1))
232
227
  assert_equal(A_with_b(a=1), A(a=1))
233
228
 
234
229
 
235
- def test_taskconfigidentifier():
230
+ def test_param_taskconfigidentifier():
236
231
  """Test whether the embedded task arguments make the configuration different"""
237
232
 
238
233
  class MyConfig(Config):
@@ -254,27 +249,27 @@ def test_taskconfigidentifier():
254
249
  )
255
250
 
256
251
 
257
- def test_constant():
252
+ def test_param_constant():
258
253
  """Test if constants are taken into account for signature computation"""
259
254
 
260
- @config("test.constant")
261
- class A1:
255
+ class A1(Config):
256
+ __xpmid__ = "test.constant"
262
257
  version: Constant[int] = 1
263
258
 
264
- @config("test.constant")
265
- class A1bis:
259
+ class A1bis(Config):
260
+ __xpmid__ = "test.constant"
266
261
  version: Constant[int] = 1
267
262
 
268
263
  assert_equal(A1(), A1bis())
269
264
 
270
- @config("test.constant")
271
- class A2:
265
+ class A2(Config):
266
+ __xpmid__ = "test.constant"
272
267
  version: Constant[int] = 2
273
268
 
274
269
  assert_notequal(A1(), A2())
275
270
 
276
271
 
277
- def test_identifier_deprecated_class():
272
+ def test_param_identifier_deprecated_class():
278
273
  """Test that when submitting the task, the computed identifier is the one of
279
274
  the new class"""
280
275
 
@@ -296,7 +291,7 @@ def test_identifier_deprecated_class():
296
291
  )
297
292
 
298
293
 
299
- def test_identifier_deprecated_attribute():
294
+ def test_param_identifier_deprecated_attribute():
300
295
  class Values(Config):
301
296
  values: Param[List[int]] = []
302
297
 
@@ -311,7 +306,7 @@ class MetaA(Config):
311
306
  x: Param[int]
312
307
 
313
308
 
314
- def test_identifier_meta():
309
+ def test_param_identifier_meta():
315
310
  """Test forced meta-parameter"""
316
311
 
317
312
  class B(Config):
@@ -350,7 +345,7 @@ def test_identifier_meta():
350
345
  )
351
346
 
352
347
 
353
- def test_identifier_meta_default_dict():
348
+ def test_param_identifier_meta_default_dict():
354
349
  class DictConfig(Config):
355
350
  params: Param[Dict[str, MetaA]] = {}
356
351
 
@@ -366,7 +361,7 @@ def test_identifier_meta_default_dict():
366
361
  )
367
362
 
368
363
 
369
- def test_identifier_meta_default_array():
364
+ def test_param_identifier_meta_default_array():
370
365
  class ArrayConfigWithDefault(Config):
371
366
  array: Param[List[MetaA]] = []
372
367
 
@@ -382,7 +377,7 @@ def test_identifier_meta_default_array():
382
377
  )
383
378
 
384
379
 
385
- def test_identifier_pre_task():
380
+ def test_param_identifier_pre_task():
386
381
  class MyConfig(Config):
387
382
  pass
388
383
 
@@ -412,7 +407,7 @@ def test_identifier_pre_task():
412
407
  assert_equal(task_with_pre, task_with_pre_3, "Pre-tasks are order-less")
413
408
 
414
409
 
415
- def test_identifier_init_task():
410
+ def test_param_identifier_init_task():
416
411
  class MyConfig(Config):
417
412
  pass
418
413
 
@@ -469,7 +464,7 @@ class IdentifierReloadConfig(Config):
469
464
  id: Param[str]
470
465
 
471
466
 
472
- def test_identifier_reload_config():
467
+ def test_param_identifier_reload_config():
473
468
  # Creates the configuration
474
469
  check_reload(IdentifierReloadConfig(id="123"))
475
470
 
@@ -485,7 +480,7 @@ class IdentifierReloadDerived(Config):
485
480
  task: Param[IdentifierReloadConfig]
486
481
 
487
482
 
488
- def test_identifier_reload_taskoutput():
483
+ def test_param_identifier_reload_taskoutput():
489
484
  """When using a task output, the identifier should not be different"""
490
485
 
491
486
  # Creates the configuration
@@ -507,7 +502,7 @@ class IdentifierReloadTaskDerived(Config):
507
502
  other: Param[IdentifierReloadTaskConfig]
508
503
 
509
504
 
510
- def test_identifier_reload_task_direct():
505
+ def test_param_identifier_reload_task_direct():
511
506
  """When using a direct task output, the identifier should not be different"""
512
507
 
513
508
  # Creates the configuration
@@ -518,7 +513,7 @@ def test_identifier_reload_task_direct():
518
513
  check_reload(config)
519
514
 
520
515
 
521
- def test_identifier_reload_meta():
516
+ def test_param_identifier_reload_meta():
522
517
  """Test identifier don't change when using meta"""
523
518
  # Creates the configuration
524
519
  task = IdentifierReloadTask(id="123").submit(run_mode=RunMode.DRY_RUN)
@@ -541,7 +536,7 @@ class LoopC(Config):
541
536
  param_b: Param["LoopB"]
542
537
 
543
538
 
544
- def test_identifier_loop():
539
+ def test_param_identifier_loop():
545
540
  c = LoopC()
546
541
  b = LoopB(param_c=c)
547
542
  a = LoopA(param_b=b)
@@ -1,21 +1,18 @@
1
1
  from typing import Optional
2
- from experimaestro import config, Param, Config
2
+ from experimaestro import Param, Config
3
3
  from experimaestro.core.objects import TypeConfig
4
4
  from experimaestro.core.serializers import SerializationLWTask
5
5
 
6
6
 
7
- @config()
8
- class A:
7
+ class A(Config):
9
8
  x: Param[int] = 1
10
9
 
11
10
 
12
- @config()
13
11
  class A1(A):
14
12
  pass
15
13
 
16
14
 
17
- @config()
18
- class B:
15
+ class B(Config):
19
16
  a: Param[A]
20
17
 
21
18