experimaestro 1.6.2__py3-none-any.whl → 1.7.0__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 +3 -1
- experimaestro/annotations.py +13 -3
- experimaestro/cli/filter.py +3 -3
- experimaestro/cli/jobs.py +1 -1
- experimaestro/commandline.py +3 -7
- experimaestro/connectors/__init__.py +22 -10
- experimaestro/connectors/local.py +17 -8
- experimaestro/connectors/ssh.py +1 -1
- experimaestro/core/arguments.py +26 -3
- experimaestro/core/objects.py +90 -6
- experimaestro/core/objects.pyi +7 -1
- experimaestro/core/types.py +33 -2
- experimaestro/experiments/cli.py +7 -3
- experimaestro/generators.py +6 -1
- experimaestro/ipc.py +4 -1
- experimaestro/launcherfinder/registry.py +23 -5
- experimaestro/launchers/slurm/base.py +47 -9
- experimaestro/notifications.py +1 -1
- experimaestro/run.py +1 -1
- experimaestro/scheduler/base.py +98 -10
- experimaestro/scheduler/dynamic_outputs.py +184 -0
- experimaestro/scriptbuilder.py +3 -1
- experimaestro/server/data/016b4a6cdced82ab3aa1.ttf +0 -0
- experimaestro/server/data/0c35d18bf06992036b69.woff2 +0 -0
- experimaestro/server/data/1815e00441357e01619e.ttf +0 -0
- experimaestro/server/data/219aa9140e099e6c72ed.woff2 +0 -0
- experimaestro/server/data/2463b90d9a316e4e5294.woff2 +0 -0
- experimaestro/server/data/2582b0e4bcf85eceead0.ttf +0 -0
- experimaestro/server/data/3a4004a46a653d4b2166.woff +0 -0
- experimaestro/server/data/3baa5b8f3469222b822d.woff +0 -0
- experimaestro/server/data/4d73cb90e394b34b7670.woff +0 -0
- experimaestro/server/data/4ef4218c522f1eb6b5b1.woff2 +0 -0
- experimaestro/server/data/50701fbb8177c2dde530.ttf +0 -0
- experimaestro/server/data/5d681e2edae8c60630db.woff +0 -0
- experimaestro/server/data/6f420cf17cc0d7676fad.woff2 +0 -0
- experimaestro/server/data/878f31251d960bd6266f.woff2 +0 -0
- experimaestro/server/data/89999bdf5d835c012025.woff2 +0 -0
- experimaestro/server/data/914997e1bdfc990d0897.ttf +0 -0
- experimaestro/server/data/b041b1fa4fe241b23445.woff2 +0 -0
- experimaestro/server/data/b6879d41b0852f01ed5b.woff2 +0 -0
- experimaestro/server/data/c210719e60948b211a12.woff2 +0 -0
- experimaestro/server/data/c380809fd3677d7d6903.woff2 +0 -0
- experimaestro/server/data/d75e3fd1eb12e9bd6655.ttf +0 -0
- experimaestro/server/data/f882956fd323fd322f31.woff +0 -0
- experimaestro/server/data/favicon.ico +0 -0
- experimaestro/server/data/index.css +22963 -0
- experimaestro/server/data/index.css.map +1 -0
- experimaestro/server/data/index.html +27 -0
- experimaestro/server/data/index.js +101770 -0
- experimaestro/server/data/index.js.map +1 -0
- experimaestro/server/data/login.html +22 -0
- experimaestro/server/data/manifest.json +15 -0
- experimaestro/sphinx/__init__.py +7 -17
- experimaestro/taskglobals.py +7 -2
- experimaestro/tests/definitions_types.py +5 -3
- experimaestro/tests/launchers/bin/sbatch +34 -7
- experimaestro/tests/launchers/bin/srun +5 -0
- experimaestro/tests/launchers/common.py +16 -4
- experimaestro/tests/restart.py +6 -3
- experimaestro/tests/tasks/all.py +16 -10
- experimaestro/tests/tasks/foreign.py +2 -4
- experimaestro/tests/test_forward.py +5 -5
- experimaestro/tests/test_identifier.py +61 -66
- experimaestro/tests/test_instance.py +3 -6
- experimaestro/tests/test_param.py +40 -22
- experimaestro/tests/test_tags.py +5 -11
- experimaestro/tests/test_tokens.py +3 -2
- experimaestro/tests/test_types.py +17 -14
- experimaestro/tests/test_validation.py +48 -91
- experimaestro/tokens.py +16 -5
- experimaestro/typingutils.py +7 -0
- experimaestro/utils/asyncio.py +6 -2
- experimaestro/utils/resources.py +7 -3
- {experimaestro-1.6.2.dist-info → experimaestro-1.7.0.dist-info}/METADATA +3 -4
- experimaestro-1.7.0.dist-info/RECORD +154 -0
- {experimaestro-1.6.2.dist-info → experimaestro-1.7.0.dist-info}/WHEEL +1 -1
- experimaestro-1.6.2.dist-info/RECORD +0 -122
- {experimaestro-1.6.2.dist-info → experimaestro-1.7.0.dist-info}/LICENSE +0 -0
- {experimaestro-1.6.2.dist-info → experimaestro-1.7.0.dist-info}/entry_points.txt +0 -0
|
@@ -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
|
-
|
|
16
|
-
|
|
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
|
-
|
|
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
|
|
66
|
+
def test_param_int():
|
|
70
67
|
assert_equal(A(a=1), A(a=1))
|
|
71
68
|
|
|
72
69
|
|
|
73
|
-
def
|
|
70
|
+
def test_param_different_type():
|
|
74
71
|
assert_notequal(A(a=1), B(a=1))
|
|
75
72
|
|
|
76
73
|
|
|
77
|
-
def
|
|
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
|
|
78
|
+
def test_param_default():
|
|
82
79
|
assert_equal(C(a=1, b=2), C(b=2))
|
|
83
80
|
|
|
84
81
|
|
|
85
|
-
def
|
|
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
|
|
86
|
+
def test_param_float():
|
|
90
87
|
assert_equal(Float(value=1), Float(value=1))
|
|
91
88
|
|
|
92
89
|
|
|
93
|
-
def
|
|
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
|
|
97
|
+
def test_param_name():
|
|
101
98
|
"""The identifier fully determines the hash code"""
|
|
102
99
|
|
|
103
|
-
|
|
104
|
-
|
|
100
|
+
class Config0(Config):
|
|
101
|
+
__xpmid__ = "test.identifier.argumentname"
|
|
105
102
|
a: Param[int]
|
|
106
103
|
|
|
107
|
-
|
|
108
|
-
|
|
104
|
+
class Config1(Config):
|
|
105
|
+
__xpmid__ = "test.identifier.argumentname"
|
|
109
106
|
b: Param[int]
|
|
110
107
|
|
|
111
|
-
|
|
112
|
-
|
|
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
|
|
123
|
-
|
|
124
|
-
|
|
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
|
|
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
|
-
|
|
156
|
-
class TypeWithPath:
|
|
152
|
+
class TypeWithPath(Config):
|
|
157
153
|
a: Param[int]
|
|
158
154
|
path: Param[Path]
|
|
159
155
|
|
|
160
156
|
|
|
161
|
-
def
|
|
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
|
|
166
|
+
def test_param_identifier_pathoption():
|
|
171
167
|
"""Path arguments should be ignored"""
|
|
172
168
|
|
|
173
|
-
|
|
174
|
-
|
|
169
|
+
class A_with_path(Config):
|
|
170
|
+
__xpmid__ = "pathoption_test"
|
|
175
171
|
a: Param[int]
|
|
176
|
-
path:
|
|
172
|
+
path: Meta[Path] = field(default_factory=PathGenerator("path"))
|
|
177
173
|
|
|
178
|
-
|
|
179
|
-
|
|
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
|
|
186
|
-
"""
|
|
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
|
|
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
|
|
213
|
+
def test_param_defaultnew():
|
|
218
214
|
"""Path arguments should be ignored"""
|
|
219
215
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
@config("defaultnew")
|
|
223
|
-
class A_with_b:
|
|
224
|
-
pass
|
|
216
|
+
class A_with_b(Config):
|
|
217
|
+
__xpmid__ = "defaultnew"
|
|
225
218
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
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
|
|
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
|
|
252
|
+
def test_param_constant():
|
|
258
253
|
"""Test if constants are taken into account for signature computation"""
|
|
259
254
|
|
|
260
|
-
|
|
261
|
-
|
|
255
|
+
class A1(Config):
|
|
256
|
+
__xpmid__ = "test.constant"
|
|
262
257
|
version: Constant[int] = 1
|
|
263
258
|
|
|
264
|
-
|
|
265
|
-
|
|
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
|
-
|
|
271
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
18
|
-
class B:
|
|
15
|
+
class B(Config):
|
|
19
16
|
a: Param[A]
|
|
20
17
|
|
|
21
18
|
|
|
@@ -13,14 +13,16 @@ from experimaestro.core.types import DictType, IntType, StrType
|
|
|
13
13
|
from enum import Enum
|
|
14
14
|
import pytest
|
|
15
15
|
from experimaestro import (
|
|
16
|
-
config,
|
|
17
16
|
Option,
|
|
18
17
|
Constant,
|
|
19
18
|
Param,
|
|
20
19
|
Task,
|
|
21
20
|
default,
|
|
21
|
+
Meta,
|
|
22
22
|
Config,
|
|
23
23
|
pathgenerator,
|
|
24
|
+
PathGenerator,
|
|
25
|
+
field,
|
|
24
26
|
Annotated,
|
|
25
27
|
)
|
|
26
28
|
import experimaestro.core.types as types
|
|
@@ -29,25 +31,24 @@ from experimaestro.xpmutils import DirectoryContext
|
|
|
29
31
|
# --- Test manual name for configuration
|
|
30
32
|
|
|
31
33
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
+
class B(Config):
|
|
35
|
+
__xpmid__ = "annotations.b"
|
|
34
36
|
pass
|
|
35
37
|
|
|
36
38
|
|
|
37
39
|
def test_fullname():
|
|
38
|
-
assert str(B.
|
|
40
|
+
assert str(B.__getxpmtype__().identifier) == "annotations.b"
|
|
39
41
|
|
|
40
42
|
|
|
41
43
|
# --- Automatic name for configuration
|
|
42
44
|
|
|
43
45
|
|
|
44
|
-
|
|
45
|
-
class A:
|
|
46
|
+
class A(Config):
|
|
46
47
|
pass
|
|
47
48
|
|
|
48
49
|
|
|
49
50
|
def test_noname():
|
|
50
|
-
assert str(A.
|
|
51
|
+
assert str(A.__getxpmtype__().identifier) == "experimaestro.tests.test_param.a"
|
|
51
52
|
|
|
52
53
|
|
|
53
54
|
def serializeCycle(config: Config):
|
|
@@ -69,8 +70,7 @@ def ArgumentValue(default=None, *, help=""):
|
|
|
69
70
|
def test_type_hinting():
|
|
70
71
|
"""Test for type hinting"""
|
|
71
72
|
|
|
72
|
-
|
|
73
|
-
class MyConfig:
|
|
73
|
+
class MyConfig(Config):
|
|
74
74
|
"""A configuration
|
|
75
75
|
|
|
76
76
|
Attributes:
|
|
@@ -89,7 +89,7 @@ def test_type_hinting():
|
|
|
89
89
|
path: Annotated[Path, pathgenerator("world")]
|
|
90
90
|
option: Option[str]
|
|
91
91
|
|
|
92
|
-
ot = MyConfig.
|
|
92
|
+
ot = MyConfig.__getxpmtype__()
|
|
93
93
|
|
|
94
94
|
# Check required parameter
|
|
95
95
|
arg_x = ot.getArgument("x")
|
|
@@ -139,7 +139,7 @@ def test_type_hinting():
|
|
|
139
139
|
|
|
140
140
|
def test_generatedpath():
|
|
141
141
|
class A(Config):
|
|
142
|
-
path:
|
|
142
|
+
path: Meta[Path] = field(default_factory=PathGenerator("test.txt"))
|
|
143
143
|
|
|
144
144
|
class B(Config):
|
|
145
145
|
a: Param[A]
|
|
@@ -179,8 +179,7 @@ def test_config_class():
|
|
|
179
179
|
|
|
180
180
|
|
|
181
181
|
def test_constant():
|
|
182
|
-
|
|
183
|
-
class A:
|
|
182
|
+
class A(Config):
|
|
184
183
|
x: Constant[int] = 2
|
|
185
184
|
|
|
186
185
|
a = A()
|
|
@@ -224,16 +223,14 @@ def test_inheritance():
|
|
|
224
223
|
|
|
225
224
|
|
|
226
225
|
def test_redefined_param():
|
|
227
|
-
|
|
228
|
-
class A:
|
|
226
|
+
class A(Config):
|
|
229
227
|
x: Param[int]
|
|
230
228
|
|
|
231
|
-
|
|
232
|
-
class B:
|
|
229
|
+
class B(Config):
|
|
233
230
|
x: Param[int] = 3
|
|
234
231
|
|
|
235
|
-
atx = A.C.
|
|
236
|
-
btx = B.C.
|
|
232
|
+
atx = A.C.__getxpmtype__().getArgument("x")
|
|
233
|
+
btx = B.C.__getxpmtype__().getArgument("x")
|
|
237
234
|
|
|
238
235
|
assert atx.required
|
|
239
236
|
|
|
@@ -258,18 +255,39 @@ def test_param_dict():
|
|
|
258
255
|
A(x={"wrong": 1.2})
|
|
259
256
|
|
|
260
257
|
|
|
258
|
+
# --- Default
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
class ConfigWithDefault(Config):
|
|
262
|
+
x: Param[int] = field(default=1)
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
def test_param_default():
|
|
266
|
+
assert ConfigWithDefault().x == 1
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
class ConfigWithDefaultFactory(Config):
|
|
270
|
+
x: Param[int] = field(default_factory=lambda: 1)
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
def test_param_default_factory():
|
|
274
|
+
value = ConfigWithDefaultFactory()
|
|
275
|
+
context = DirectoryContext(Path("/__fakepath__"))
|
|
276
|
+
value.__xpm__.seal(context)
|
|
277
|
+
assert value.x == 1
|
|
278
|
+
|
|
279
|
+
|
|
261
280
|
# --- Task annotations
|
|
262
281
|
|
|
263
282
|
|
|
264
283
|
def test_default_mismatch():
|
|
265
284
|
"""Test mismatch between default and type"""
|
|
266
285
|
|
|
267
|
-
|
|
268
|
-
class A:
|
|
286
|
+
class A(Config):
|
|
269
287
|
x: Param[int] = 0.2
|
|
270
288
|
|
|
271
289
|
with pytest.raises(TypeError):
|
|
272
|
-
A.
|
|
290
|
+
A.__getxpmtype__().getArgument("x")
|
|
273
291
|
|
|
274
292
|
|
|
275
293
|
# --- Handling help annotations
|
experimaestro/tests/test_tags.py
CHANGED
|
@@ -3,8 +3,6 @@ from pathlib import Path
|
|
|
3
3
|
from experimaestro import (
|
|
4
4
|
tag,
|
|
5
5
|
LightweightTask,
|
|
6
|
-
config,
|
|
7
|
-
argument,
|
|
8
6
|
Config,
|
|
9
7
|
Task,
|
|
10
8
|
Param,
|
|
@@ -13,17 +11,13 @@ from experimaestro.scheduler.workspace import RunMode
|
|
|
13
11
|
from experimaestro.xpmutils import DirectoryContext
|
|
14
12
|
|
|
15
13
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class Config1:
|
|
19
|
-
pass
|
|
14
|
+
class Config1(Config):
|
|
15
|
+
x: Param[int]
|
|
20
16
|
|
|
21
17
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
class Config2:
|
|
26
|
-
pass
|
|
18
|
+
class Config2(Config):
|
|
19
|
+
x: Param[int]
|
|
20
|
+
c: Param[Config1]
|
|
27
21
|
|
|
28
22
|
|
|
29
23
|
def test_tag():
|
|
@@ -7,7 +7,7 @@ import time
|
|
|
7
7
|
from pathlib import Path
|
|
8
8
|
|
|
9
9
|
import subprocess
|
|
10
|
-
from experimaestro import Task,
|
|
10
|
+
from experimaestro import Task, Param
|
|
11
11
|
from experimaestro.tokens import CounterToken, TokenFile
|
|
12
12
|
from experimaestro.scheduler import JobState
|
|
13
13
|
from .utils import (
|
|
@@ -74,8 +74,9 @@ def test_token_ok():
|
|
|
74
74
|
logging.info("Finished token_ok test")
|
|
75
75
|
|
|
76
76
|
|
|
77
|
-
@param("x", type=int)
|
|
78
77
|
class dummy_task(Task):
|
|
78
|
+
x: Param[int]
|
|
79
|
+
|
|
79
80
|
def execute(self):
|
|
80
81
|
pass
|
|
81
82
|
|
|
@@ -1,31 +1,26 @@
|
|
|
1
1
|
# --- Task and types definitions
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
-
from experimaestro import Config,
|
|
5
|
-
from
|
|
4
|
+
from experimaestro import Config, Param
|
|
5
|
+
from typing import Union
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
from experimaestro.
|
|
7
|
+
import pytest
|
|
8
|
+
from experimaestro.core.objects import TypeConfig
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
def test_multiple_inheritance():
|
|
12
|
-
|
|
13
|
-
class A:
|
|
12
|
+
class A(Config):
|
|
14
13
|
pass
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
class B:
|
|
15
|
+
class B(Config):
|
|
18
16
|
pass
|
|
19
17
|
|
|
20
|
-
@config()
|
|
21
18
|
class B1(B):
|
|
22
19
|
pass
|
|
23
20
|
|
|
24
|
-
@config()
|
|
25
21
|
class C1(B1, A):
|
|
26
22
|
pass
|
|
27
23
|
|
|
28
|
-
@config()
|
|
29
24
|
class C2(A, B1):
|
|
30
25
|
pass
|
|
31
26
|
|
|
@@ -45,14 +40,12 @@ def test_multiple_inheritance():
|
|
|
45
40
|
|
|
46
41
|
|
|
47
42
|
def test_missing_hierarchy():
|
|
48
|
-
|
|
49
|
-
class A:
|
|
43
|
+
class A(Config):
|
|
50
44
|
pass
|
|
51
45
|
|
|
52
46
|
class A1(A):
|
|
53
47
|
pass
|
|
54
48
|
|
|
55
|
-
@config()
|
|
56
49
|
class B(A1):
|
|
57
50
|
pass
|
|
58
51
|
|
|
@@ -60,3 +53,13 @@ def test_missing_hierarchy():
|
|
|
60
53
|
|
|
61
54
|
assert issubclass(B, A)
|
|
62
55
|
assert issubclass(B, A1)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def test_types_union():
|
|
59
|
+
class A(Config):
|
|
60
|
+
x: Param[Union[int, str]]
|
|
61
|
+
|
|
62
|
+
A(x=1)
|
|
63
|
+
A(x="hello")
|
|
64
|
+
with pytest.raises(ValueError):
|
|
65
|
+
A(x=[])
|