experimaestro 1.12.0__py3-none-any.whl → 1.13.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.

@@ -122,11 +122,11 @@ class ConfigInformation:
122
122
  def __init__(self, pyobject: "ConfigMixin"):
123
123
  # The underlying pyobject and XPM type
124
124
  self.pyobject = pyobject
125
- self.xpmtype = pyobject.__xpmtype__ # type: ObjectType
125
+ self.xpmtype: "ObjectType" = pyobject.__xpmtype__
126
126
  self.values = {}
127
127
 
128
128
  # Meta-informations
129
- self._tags = {}
129
+ self._tags: dict[str, Any] = {}
130
130
  self._initinfo = ""
131
131
 
132
132
  self._taskoutput = None
@@ -142,7 +142,7 @@ class ConfigInformation:
142
142
  #: True when this configuration was loaded from disk
143
143
  self.loaded = False
144
144
 
145
- # Explicitely added dependencies
145
+ # Explicitly added dependencies
146
146
  self.dependencies = []
147
147
 
148
148
  # Concrete type variables resolutions
@@ -170,6 +170,11 @@ class ConfigInformation:
170
170
  self._sealed = False
171
171
  self._meta = None
172
172
 
173
+ #: This flags is True when a value in this configuration,
174
+ #: or any sub-configuration, is generated. This prevents problem
175
+ #: when a configuration with generated values is re-used
176
+ self._has_generated_value = False
177
+
173
178
  def set_meta(self, value: Optional[bool]):
174
179
  """Sets the meta flag"""
175
180
  assert not self._sealed, "Configuration is sealed"
@@ -198,6 +203,20 @@ class ConfigInformation:
198
203
  if self._sealed and not bypass:
199
204
  raise AttributeError(f"Object is read-only (trying to set {k})")
200
205
 
206
+ if not isinstance(v, ConfigMixin) and isinstance(v, Config):
207
+ raise AttributeError(
208
+ "Configuration (and not objects) should be used. Consider using .C(...)"
209
+ )
210
+
211
+ if (
212
+ isinstance(v, ConfigMixin)
213
+ and v.__xpm__._has_generated_value
214
+ and v.__xpm__.task is None
215
+ ):
216
+ raise AttributeError(
217
+ f"Cannot set {k} to a configuration with generated values"
218
+ )
219
+
201
220
  try:
202
221
  argument = self.xpmtype.arguments.get(k, None)
203
222
  if argument:
@@ -328,10 +347,10 @@ class ConfigInformation:
328
347
  """
329
348
 
330
349
  class Sealer(ConfigWalk):
331
- def preprocess(self, config: Config):
350
+ def preprocess(self, config: ConfigMixin):
332
351
  return not config.__xpm__._sealed, config
333
352
 
334
- def postprocess(self, stub, config: Config, values):
353
+ def postprocess(self, stub, config: ConfigMixin, values):
335
354
  # Generate values
336
355
  from experimaestro.generators import Generator
337
356
 
@@ -344,6 +363,7 @@ class ConfigInformation:
344
363
  continue
345
364
  value = argument.generator()
346
365
  else:
366
+ # Generate a value
347
367
  sig = inspect.signature(argument.generator)
348
368
  if len(sig.parameters) == 0:
349
369
  value = argument.generator()
@@ -354,12 +374,23 @@ class ConfigInformation:
354
374
  False
355
375
  ), "generator has either two parameters (context and config), or none"
356
376
  config.__xpm__.set(k, value, bypass=True)
377
+ config.__xpm__._has_generated_value = True
378
+ else:
379
+ value = config.__xpm__.values.get(k)
357
380
  except Exception:
358
381
  logger.error(
359
382
  "While setting %s of %s", argument.name, config.__xpmtype__
360
383
  )
361
384
  raise
362
385
 
386
+ # Propagate the generated value flag
387
+ if (
388
+ (value is not None)
389
+ and isinstance(value, ConfigMixin)
390
+ and value.__xpm__._has_generated_value
391
+ ):
392
+ self._has_generated_value = True
393
+
363
394
  config.__xpm__._sealed = True
364
395
 
365
396
  Sealer(context, recurse_task=True)(self.pyobject)
@@ -657,13 +688,6 @@ class ConfigInformation:
657
688
 
658
689
  print(file=sys.stderr) # noqa: T201
659
690
 
660
- # Handle an output configuration # FIXME: remove
661
- def mark_output(config: "Config"):
662
- """Sets a dependency on the job"""
663
- assert not isinstance(config, Task), "Cannot set a dependency on a task"
664
- config.__xpm__.task = self.pyobject
665
- return config
666
-
667
691
  # Mark this configuration also
668
692
  self.task = self.pyobject
669
693
 
@@ -1242,6 +1266,9 @@ def clone(v):
1242
1266
  if isinstance(v, Enum):
1243
1267
  return v
1244
1268
 
1269
+ if isinstance(v, tuple):
1270
+ return tuple(clone(x) for x in v)
1271
+
1245
1272
  if isinstance(v, Config):
1246
1273
  # Create a new instance
1247
1274
  kwargs = {
@@ -1260,6 +1287,11 @@ class ConfigMixin:
1260
1287
  """Class for configuration objects"""
1261
1288
 
1262
1289
  __xpmtype__: ObjectType
1290
+ """The associated XPM type"""
1291
+
1292
+ __xpm__: ConfigInformation
1293
+ """The __xpm__ object contains all instance specific information about a
1294
+ configuration/task"""
1263
1295
 
1264
1296
  def __init__(self, **kwargs):
1265
1297
  """Initialize the configuration with the given parameters"""
@@ -1441,10 +1473,6 @@ class Config:
1441
1473
  """The object type holds all the information about a specific subclass
1442
1474
  experimaestro metadata"""
1443
1475
 
1444
- __xpm__: ConfigInformation
1445
- """The __xpm__ object contains all instance specific information about a
1446
- configuration/task"""
1447
-
1448
1476
  @classproperty
1449
1477
  def XPMConfig(cls):
1450
1478
  if issubclass(cls, ConfigMixin):
@@ -0,0 +1,33 @@
1
+ from experimaestro import Config, Task, Param, Meta, Path, field, PathGenerator
2
+ from experimaestro.scheduler.workspace import Workspace
3
+ from experimaestro.settings import Settings, WorkspaceSettings
4
+ import pytest
5
+ from experimaestro.scheduler import RunMode
6
+
7
+
8
+ class Validation(Config):
9
+ best_checkpoint: Meta[Path] = field(default_factory=PathGenerator("index"))
10
+
11
+
12
+ class Learner(Task):
13
+ validation: Param[Validation]
14
+ x: Param[int]
15
+
16
+
17
+ def test_generators_reuse():
18
+ # We have one way to select the best model
19
+ validation = Validation.C()
20
+
21
+ workspace = Workspace(
22
+ Settings(),
23
+ WorkspaceSettings("test_generators_reuse", path=Path("/tmp")),
24
+ run_mode=RunMode.DRY_RUN,
25
+ )
26
+
27
+ # OK, the path is generated depending on Learner with x=1
28
+ Learner.C(x=1, validation=validation).submit(workspace=workspace)
29
+
30
+ with pytest.raises((AttributeError)):
31
+ # Here we have a problem...
32
+ # the path is still the previous one
33
+ Learner.C(x=2, validation=validation).submit(workspace=workspace)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: experimaestro
3
- Version: 1.12.0
3
+ Version: 1.13.0
4
4
  Summary: "Experimaestro is a computer science experiment manager"
5
5
  License: GPL-3
6
6
  License-File: LICENSE
@@ -17,7 +17,7 @@ experimaestro/core/callbacks.py,sha256=59JfeUgWcCCdIQ3pvh-xNnoRp9BX8f4iOAkgm16wB
17
17
  experimaestro/core/context.py,sha256=1tLmX7WcgEKSbGw77vfziTzS8KNsoZJ02JBWMBCqqOk,2606
18
18
  experimaestro/core/identifier.py,sha256=JadBAdW2fOIgoTyMRtKI_RY9SXQP2B1vq1rUcV465Hs,10214
19
19
  experimaestro/core/objects/__init__.py,sha256=ucJY5e17QQ1Kc-GYXeL7g8GFj8rP0XB4g2vrl32uhxY,721
20
- experimaestro/core/objects/config.py,sha256=qOUgCmX1NwhRhpTVxgr2sSAqBCMYloUXb5f-NiXgV8Q,56989
20
+ experimaestro/core/objects/config.py,sha256=QDmD82NyWN9OQ_UVSV6WaPd1srKHVXeAmfcEW1Fw9Ps,58080
21
21
  experimaestro/core/objects/config_utils.py,sha256=ZLECGkeIWdzunm8vwWsQhvcSgV1e064BgXbLiZnxSEM,1288
22
22
  experimaestro/core/objects/config_walk.py,sha256=gyDMrVPbBMChn7r4em_gQXuqnxASO_JVauEbnJNO8II,4245
23
23
  experimaestro/core/objects.pyi,sha256=xvlsRj4u1xsJxbevJl5Ner_HwmxR8x1JlAeIVDJzuy0,6498
@@ -121,6 +121,7 @@ experimaestro/tests/test_dependencies.py,sha256=xfWrSkvjT45G4FSCL535m1huLT2ghmyW
121
121
  experimaestro/tests/test_experiment.py,sha256=QWF9aHewL9hepagrKKFyfikKn3iiZ_lRRXl1LLttta0,1687
122
122
  experimaestro/tests/test_findlauncher.py,sha256=KPy8ow--NXS1KFCIpxrmEJFRvjo-v-PwlVHVyoVKLPg,3134
123
123
  experimaestro/tests/test_forward.py,sha256=9y1zYm7hT_Lx5citxnK7n20cMZ2WJbsaEeY5irCZ9U4,735
124
+ experimaestro/tests/test_generators.py,sha256=Cx0jDI8JA_tFsEfg9EkV353iKxBd6j_1560p_66_oNU,1040
124
125
  experimaestro/tests/test_identifier.py,sha256=zgfpz5UumQftQTHhdw3nmr044Xd7Ntrh7e2hIAoS_PA,13862
125
126
  experimaestro/tests/test_instance.py,sha256=h-8UeoOlNsD-STWq5jbhmxw35CyiwJxtKAaUGmLPgB8,1521
126
127
  experimaestro/tests/test_objects.py,sha256=zycxjvWuJAbPR8-q2T3zuBY9xfmlhf1YvtOcrImHxnc,2431
@@ -151,8 +152,8 @@ experimaestro/utils/multiprocessing.py,sha256=am3DkHP_kmWbpynbck2c9QystCUtPBoSAC
151
152
  experimaestro/utils/resources.py,sha256=j-nvsTFwmgENMoVGOD2Ap-UD3WU85WkI0IgeSszMCX4,1328
152
153
  experimaestro/utils/settings.py,sha256=jpFMqF0DLL4_P1xGal0zVR5cOrdD8O0Y2IOYvnRgN3k,793
153
154
  experimaestro/xpmutils.py,sha256=S21eMbDYsHfvmZ1HmKpq5Pz5O-1HnCLYxKbyTBbASyQ,638
154
- experimaestro-1.12.0.dist-info/METADATA,sha256=BbLWHf4Fg1w4rkSNnAjjdRWf9S4aNx92uKlePpSacQc,5705
155
- experimaestro-1.12.0.dist-info/WHEEL,sha256=M5asmiAlL6HEcOq52Yi5mmk9KmTVjY2RDPtO4p9DMrc,88
156
- experimaestro-1.12.0.dist-info/entry_points.txt,sha256=TppTNiz5qm5xm1fhAcdLKdCLMrlL-eQggtCrCI00D9c,446
157
- experimaestro-1.12.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
158
- experimaestro-1.12.0.dist-info/RECORD,,
155
+ experimaestro-1.13.0.dist-info/METADATA,sha256=UbZQxb19lKM9jI8HI8aZli0ZmOck1UflmQmN6VHvDEI,5705
156
+ experimaestro-1.13.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
157
+ experimaestro-1.13.0.dist-info/entry_points.txt,sha256=TppTNiz5qm5xm1fhAcdLKdCLMrlL-eQggtCrCI00D9c,446
158
+ experimaestro-1.13.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
159
+ experimaestro-1.13.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.2.0
2
+ Generator: poetry-core 2.2.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any