experimaestro 2.0.0a1__py3-none-any.whl → 2.0.0a3__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.

@@ -80,10 +80,13 @@ class Argument:
80
80
 
81
81
  self.generator = generator
82
82
  self.default = None
83
+ self.ignore_generated = False
83
84
 
84
85
  if default is not None:
85
86
  assert self.generator is None, "generator and default are exclusive options"
86
87
  if isinstance(default, field):
88
+ self.ignore_generated = default.ignore_generated
89
+
87
90
  if default.default is not None:
88
91
  self.default = default.default
89
92
  elif default.default_factory is not None:
@@ -184,13 +187,29 @@ DataPath = Annotated[Path, dataHint]
184
187
  class field:
185
188
  """Extra information for a given experimaestro field (param or meta)"""
186
189
 
187
- def __init__(self, *, default: Any = None, default_factory: Callable = None):
190
+ def __init__(
191
+ self,
192
+ *,
193
+ default: Any = None,
194
+ default_factory: Callable = None,
195
+ ignore_generated=False,
196
+ ):
197
+ """Gives some extra per-field information
198
+
199
+ :param default: a default value, defaults to None
200
+ :param default_factory: a default factory for values, defaults to None
201
+ :param ignore_generated: True if the value is hidden – it won't be accessible in
202
+ tasks, defaults to False. The interest of hidden is to add a
203
+ configuration field that changes the identifier, but will not be
204
+ used.
205
+ """
188
206
  assert not (
189
207
  (default is not None) and (default_factory is not None)
190
208
  ), "default and default_factory are mutually exclusive options"
191
209
 
192
210
  self.default_factory = default_factory
193
211
  self.default = default
212
+ self.ignore_generated = ignore_generated
194
213
 
195
214
 
196
215
  class help(TypeAnnotation):
@@ -169,10 +169,33 @@ class ConfigInformation:
169
169
  self._sealed = False
170
170
  self._meta = None
171
171
 
172
- #: This flags is True when a value in this configuration,
173
- #: or any sub-configuration, is generated. This prevents problem
174
- #: when a configuration with generated values is re-used
175
- self._has_generated_value = False
172
+ # This contains the list of generated values (using context) in this
173
+ # configuration or any sub-configuration, is generated. This prevents
174
+ # problem when a configuration with generated values is re-used.
175
+ self._generated_values = []
176
+
177
+ def get_generated_paths(
178
+ self, path: list[str] = None, paths: list[str] = None
179
+ ) -> list[str]:
180
+ """Get the list of generated paths, useful to track down those
181
+
182
+ :param path: The current path
183
+ :param paths: The list of generated paths so far, defaults to None
184
+ :return: The full list of generated paths
185
+ """
186
+ paths = [] if paths is None else paths
187
+ path = [] if path is None else path
188
+
189
+ for key in self._generated_values:
190
+ value = self.values[key]
191
+ if isinstance(value, ConfigMixin) and value.__xpm__._generated_values:
192
+ path.append(key)
193
+ value.__xpm__.get_generated_paths(path, paths)
194
+ path.pop()
195
+ else:
196
+ paths.append(".".join(path + [key]))
197
+
198
+ return paths
176
199
 
177
200
  def set_meta(self, value: Optional[bool]):
178
201
  """Sets the meta flag"""
@@ -207,18 +230,21 @@ class ConfigInformation:
207
230
  "Configuration (and not objects) should be used. Consider using .C(...)"
208
231
  )
209
232
 
210
- if (
211
- isinstance(v, ConfigMixin)
212
- and v.__xpm__._has_generated_value
213
- and v.__xpm__.task is None
214
- ):
215
- raise AttributeError(
216
- f"Cannot set {k} to a configuration with generated values"
217
- )
218
-
219
233
  try:
220
234
  argument = self.xpmtype.arguments.get(k, None)
221
235
  if argument:
236
+ if (
237
+ isinstance(v, ConfigMixin)
238
+ and v.__xpm__._generated_values
239
+ and v.__xpm__.task is None
240
+ and not argument.ignore_generated
241
+ ):
242
+ raise AttributeError(
243
+ f"Cannot set {k} to a configuration with generated values. "
244
+ "Here is the list of paths to help you: "
245
+ f"""{', '.join(v.__xpm__.get_generated_paths([k]))}"""
246
+ )
247
+
222
248
  if not bypass and (
223
249
  (isinstance(argument.generator, Generator)) or argument.constant
224
250
  ):
@@ -344,14 +370,17 @@ class ConfigInformation:
344
370
  Arguments:
345
371
  - context: the generation context
346
372
  """
347
- subconfigs = [
348
- v.__xpm__
349
- for v in self.values.values()
350
- if isinstance(v, Config) and v.__xpm__.task is None
351
- ]
352
-
353
- if any(v._has_generated_value for v in subconfigs):
354
- raise AttributeError("Cannot seal a configuration with generated values")
373
+ if generated_keys := [
374
+ k
375
+ for k, v in self.values.items()
376
+ if isinstance(v, Config)
377
+ and v.__xpm__.task is None
378
+ and v.__xpm__._generated_values
379
+ ]:
380
+ raise AttributeError(
381
+ "Cannot seal a configuration with generated values:"
382
+ f"""{",".join(generated_keys)} in {context.currentpath}"""
383
+ )
355
384
 
356
385
  class Sealer(ConfigWalk):
357
386
  def preprocess(self, config: ConfigMixin):
@@ -375,13 +404,18 @@ class ConfigInformation:
375
404
  if len(sig.parameters) == 0:
376
405
  value = argument.generator()
377
406
  elif len(sig.parameters) == 2:
407
+ # Only in that case do we need to flag this configuration
408
+ # as containing generated values
409
+ if not argument.ignore_generated:
410
+ config.__xpm__._generated_values.append(k)
411
+ else:
412
+ logging.warning("Ignoring %s", k)
378
413
  value = argument.generator(self.context, config)
379
414
  else:
380
415
  assert (
381
416
  False
382
417
  ), "generator has either two parameters (context and config), or none"
383
418
  config.__xpm__.set(k, value, bypass=True)
384
- config.__xpm__._has_generated_value = True
385
419
  else:
386
420
  value = config.__xpm__.values.get(k)
387
421
  except Exception:
@@ -392,11 +426,14 @@ class ConfigInformation:
392
426
 
393
427
  # Propagate the generated value flag
394
428
  if (
395
- (value is not None)
429
+ value is not None
396
430
  and isinstance(value, ConfigMixin)
397
- and value.__xpm__._has_generated_value
431
+ and value.__xpm__._generated_values
398
432
  ):
399
- self._has_generated_value = True
433
+ if not argument.ignore_generated:
434
+ config.__xpm__._generated_values.append(k)
435
+ else:
436
+ logging.warning("Ignoring %s", k)
400
437
 
401
438
  config.__xpm__._sealed = True
402
439
 
@@ -71,6 +71,7 @@ class ConfigWalk:
71
71
  return self.context.push(str(i))
72
72
 
73
73
  def map(self, k: str):
74
+ """Provides a path context when processing a tree"""
74
75
  return self.context.push(k)
75
76
 
76
77
  def stub(self, config):
@@ -123,7 +124,8 @@ class ConfigWalk:
123
124
  and self.recurse_task
124
125
  and x.__xpm__.task is not x
125
126
  ):
126
- self(x.__xpm__.task)
127
+ with self.map("__task__"):
128
+ self(x.__xpm__.task)
127
129
 
128
130
  processed = self.postprocess(stub, x, result)
129
131
  self.visited[xid] = processed
@@ -14,6 +14,10 @@ class Learner(Task):
14
14
  x: Param[int]
15
15
 
16
16
 
17
+ class ModuleLoader(Task):
18
+ validation: Param[Validation] = field(ignore_generated=True)
19
+
20
+
17
21
  def test_generators_reuse_on_submit():
18
22
  # We have one way to select the best model
19
23
  validation = Validation.C()
@@ -59,3 +63,6 @@ def test_generators_reuse_on_set():
59
63
  # We should not be able to *create* a second task with the same validation,
60
64
  # even without submitting it
61
65
  Learner.C(x=2, validation=validation)
66
+
67
+ # This should run OK
68
+ ModuleLoader.C(validation=validation)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: experimaestro
3
- Version: 2.0.0a1
3
+ Version: 2.0.0a3
4
4
  Summary: "Experimaestro is a computer science experiment manager"
5
5
  License: GPL-3
6
6
  Keywords: experiment manager
@@ -13,14 +13,14 @@ experimaestro/connectors/__init__.py,sha256=UKhDU3uv9jFH37oUb0JiejrekA85xtEirn79
13
13
  experimaestro/connectors/local.py,sha256=lCGIubqmUJZ1glLtLRXOgakTMfEaEmFtNkEcw9qV5vw,6143
14
14
  experimaestro/connectors/ssh.py,sha256=5giqvv1y0QQKF-GI0IFUzI_Z5H8Bj9EuL_Szpvk899Q,8600
15
15
  experimaestro/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
- experimaestro/core/arguments.py,sha256=7hpkU1f8LJ7JL8kQaD514h9CFSfMotYLsVfMsMmdpWk,6487
16
+ experimaestro/core/arguments.py,sha256=gB0Kq9XL0_mYbm9WHL-mDx2tUGHI1pvsu1ahMaDxIY0,7170
17
17
  experimaestro/core/callbacks.py,sha256=59JfeUgWcCCdIQ3pvh-xNnoRp9BX8f4iOAkgm16wBzE,1660
18
18
  experimaestro/core/context.py,sha256=1tLmX7WcgEKSbGw77vfziTzS8KNsoZJ02JBWMBCqqOk,2606
19
19
  experimaestro/core/identifier.py,sha256=d-DczyKvQhqyGD9I1ndHrPoOFRDcBHNzeqQx6EOrDPo,10552
20
20
  experimaestro/core/objects/__init__.py,sha256=ucJY5e17QQ1Kc-GYXeL7g8GFj8rP0XB4g2vrl32uhxY,721
21
- experimaestro/core/objects/config.py,sha256=VUdkAup9jcHhl53pfeNDvuqc6KTnvr4yrGktnaR8aRw,56574
21
+ experimaestro/core/objects/config.py,sha256=jgaGYBiT3V3yEUgVxcpOdX3mozylL78eYSC0woy0664,58308
22
22
  experimaestro/core/objects/config_utils.py,sha256=ZLECGkeIWdzunm8vwWsQhvcSgV1e064BgXbLiZnxSEM,1288
23
- experimaestro/core/objects/config_walk.py,sha256=gyDMrVPbBMChn7r4em_gQXuqnxASO_JVauEbnJNO8II,4245
23
+ experimaestro/core/objects/config_walk.py,sha256=b8u6oohf1gXyva4Y_Cyyl_3BNivzI2y-I2B6MUPV2aU,4353
24
24
  experimaestro/core/objects.pyi,sha256=xvlsRj4u1xsJxbevJl5Ner_HwmxR8x1JlAeIVDJzuy0,6498
25
25
  experimaestro/core/serialization.py,sha256=CSPEwOzlDsgAz6V2og-TgyU0RXDtzt_nXaoXFZleDZE,5775
26
26
  experimaestro/core/serializers.py,sha256=R_CAMyjjfU1oi-eHU6VlEUixJpFayGqEPaYu7VsD9xA,1197
@@ -125,7 +125,7 @@ experimaestro/tests/test_file_progress.py,sha256=uNUUq-ptcnxu56zRvUUZ5EYM9ZIQbUm
125
125
  experimaestro/tests/test_file_progress_integration.py,sha256=ejXASpdnpi6HUy569Q5Vx5F8SV_RDU-4o3yuQka6vS4,16751
126
126
  experimaestro/tests/test_findlauncher.py,sha256=KPy8ow--NXS1KFCIpxrmEJFRvjo-v-PwlVHVyoVKLPg,3134
127
127
  experimaestro/tests/test_forward.py,sha256=9y1zYm7hT_Lx5citxnK7n20cMZ2WJbsaEeY5irCZ9U4,735
128
- experimaestro/tests/test_generators.py,sha256=GDPNaB7-ZNTOe5hyC5E54jzq8a4XNRNszJkxCO0BR_s,2011
128
+ experimaestro/tests/test_generators.py,sha256=rj4oQBxcW_UXeyykQ37QetKora-bxDJEY5AGkBaWEWI,2172
129
129
  experimaestro/tests/test_identifier.py,sha256=PfUK-IYXCTyK1YMrsphkQx4BmsST5Z3bWSNgu-ZameU,14284
130
130
  experimaestro/tests/test_instance.py,sha256=QaJAxZzyUQiEwx5lmfJKDw4vg1p6ASPhR6QJPXWjhnw,1705
131
131
  experimaestro/tests/test_objects.py,sha256=hGku35h1qkNMIdgP_gWM7HeviaqW7jrZDffOsCJh-_Q,1787
@@ -156,8 +156,8 @@ experimaestro/utils/multiprocessing.py,sha256=am3DkHP_kmWbpynbck2c9QystCUtPBoSAC
156
156
  experimaestro/utils/resources.py,sha256=j-nvsTFwmgENMoVGOD2Ap-UD3WU85WkI0IgeSszMCX4,1328
157
157
  experimaestro/utils/settings.py,sha256=jpFMqF0DLL4_P1xGal0zVR5cOrdD8O0Y2IOYvnRgN3k,793
158
158
  experimaestro/xpmutils.py,sha256=S21eMbDYsHfvmZ1HmKpq5Pz5O-1HnCLYxKbyTBbASyQ,638
159
- experimaestro-2.0.0a1.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
160
- experimaestro-2.0.0a1.dist-info/METADATA,sha256=65IJsCiXen3sKUqSzV4vBL_1l8JziDkI2ytAp3lDLmU,5690
161
- experimaestro-2.0.0a1.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
162
- experimaestro-2.0.0a1.dist-info/entry_points.txt,sha256=TppTNiz5qm5xm1fhAcdLKdCLMrlL-eQggtCrCI00D9c,446
163
- experimaestro-2.0.0a1.dist-info/RECORD,,
159
+ experimaestro-2.0.0a3.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
160
+ experimaestro-2.0.0a3.dist-info/METADATA,sha256=rdyvmeG6mIEMPcvZARoSrXDuBt2NX6bEPUufnfyRzhE,5690
161
+ experimaestro-2.0.0a3.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
162
+ experimaestro-2.0.0a3.dist-info/entry_points.txt,sha256=TppTNiz5qm5xm1fhAcdLKdCLMrlL-eQggtCrCI00D9c,446
163
+ experimaestro-2.0.0a3.dist-info/RECORD,,