lsst-ctrl-bps 29.2025.2400__py3-none-any.whl → 29.2025.2600__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.
@@ -44,6 +44,8 @@ from lsst.daf.butler import Config
44
44
  from lsst.resources import ResourcePath
45
45
  from lsst.utils import doImport
46
46
 
47
+ from .bps_utils import bps_eval
48
+
47
49
  _LOG = logging.getLogger(__name__)
48
50
 
49
51
  # Using lsst.daf.butler.Config to resolve possible includes.
@@ -417,4 +419,63 @@ class BpsConfig(Config):
417
419
  if default != _NO_SEARCH_DEFAULT_VALUE:
418
420
  opt["default"] = default
419
421
 
422
+ # check for bpsEval
423
+ value = re.sub(
424
+ r"bpsEval\(([^,)]+), ([^)]+)\)", lambda m: str(bps_eval(m.group(1), m.group(2))), value
425
+ )
426
+ if "bpsEval" in value:
427
+ raise ValueError(f"Unparsable bpsEval in '{value}'")
428
+
420
429
  return value
430
+
431
+ def generate_config(self) -> None:
432
+ """Update config with values generated by bpsGenerateConfig
433
+ entries.
434
+ """
435
+ _LOG.debug("generate_config before: %s", self)
436
+ self._recursive_generate_config("", self)
437
+ _LOG.debug("generate_config after: %s", self)
438
+
439
+ def _recursive_generate_config(self, recursive_key: str, sub_config: Config) -> None:
440
+ """Update config with values generated by bpsGenerateConfig
441
+ entries.
442
+
443
+ Parameters
444
+ ----------
445
+ recursive_key : `str`
446
+ Corresponds to a new subconfig in which to search
447
+ and replace bpsGenerateConfig.
448
+
449
+ sub_config : `lsst.daf.butler.Config`
450
+ The nested config corresponding to the recursive_key.
451
+
452
+ Raises
453
+ ------
454
+ ValueError
455
+ If bpsGenerateConfig value isn't parseable.
456
+ ImportError
457
+ If problems importing bpsGenerateConfig's method.
458
+ """
459
+ _LOG.debug("recursive_key = '%s'", recursive_key)
460
+ genkey = "bpsGenerateConfig" # to make it easier to change
461
+
462
+ # Save to avoid dictionary changed size during iteration error.
463
+ orig_keys = list(sub_config)
464
+ for key in orig_keys:
465
+ value = Config.__getitem__(sub_config, key)
466
+ _LOG.debug("key = %s, type(value) = %s", key, type(value))
467
+ if isinstance(value, Config):
468
+ self._recursive_generate_config(f"{recursive_key}.{key}", value)
469
+ elif key == genkey:
470
+ value = self.replace_vars(value, {"searchobj": sub_config})
471
+
472
+ m = re.match(r"(\S+)\((.+)\)", value)
473
+ if m:
474
+ results = bps_eval(m.group(1), m.group(2))
475
+ del sub_config[genkey]
476
+ sub_config.update(results)
477
+ if recursive_key:
478
+ self[recursive_key] = sub_config
479
+ _LOG.debug("After config = %s", self)
480
+ else:
481
+ raise ValueError(f"Unparsable {genkey} value='{value}'")
@@ -31,6 +31,7 @@ __all__ = [
31
31
  "_dump_env_info",
32
32
  "_dump_pkg_info",
33
33
  "_make_id_link",
34
+ "bps_eval",
34
35
  "chdir",
35
36
  "create_count_summary",
36
37
  "create_job_quantum_graph_filename",
@@ -52,6 +53,7 @@ from typing import Any
52
53
 
53
54
  import yaml
54
55
 
56
+ from lsst.utils import doImport
55
57
  from lsst.utils.packages import Packages
56
58
 
57
59
  _LOG = logging.getLogger(__name__)
@@ -353,3 +355,35 @@ def subset_dimension_values(
353
355
  f"{desc_what} missing dimensions ({', '.join(sorted(missing_dims))}) required for {desc_for}"
354
356
  )
355
357
  return dim_values
358
+
359
+
360
+ def bps_eval(func: str, args: str) -> Any:
361
+ """Evaluate user provided expression/function.
362
+
363
+ Parameters
364
+ ----------
365
+ func : `str`
366
+ Importable string or built-in function name.
367
+ args : `str`
368
+ Parameters to pass to the function.
369
+
370
+ Returns
371
+ -------
372
+ results : `~typing.Any`
373
+ Results of running eval.
374
+
375
+ Raises
376
+ ------
377
+ ImportError
378
+ If problems importing.
379
+ """
380
+ if "." in func:
381
+ genfunc = doImport(func) # noqa: F841
382
+ func_reference = "genfunc"
383
+ else:
384
+ func_reference = func
385
+ eval_str = f"{func_reference}({args})"
386
+ _LOG.debug("String passed to eval: '%s'", eval_str)
387
+ results = eval(eval_str)
388
+
389
+ return results
@@ -115,6 +115,7 @@ executionButler:
115
115
  whenCreate: "NEVER"
116
116
 
117
117
  finalJob:
118
+ retryUnlessExit: 2
118
119
  updateOutputChain: "--update-output-chain"
119
120
  whenSetup: "NEVER"
120
121
  whenRun: "ALWAYS"
@@ -130,6 +130,9 @@ def init_submission(
130
130
  else:
131
131
  _LOG.debug("Skipping submission checks.")
132
132
 
133
+ # Replace all bpsGenerateConfig
134
+ config.generate_config()
135
+
133
136
  # Make submit directory to contain all outputs.
134
137
  submit_path = mkdir(config["submitPath"])
135
138
  config[".bps_defined.submitPath"] = str(submit_path)
@@ -0,0 +1,114 @@
1
+ # This file is part of ctrl_bps.
2
+ #
3
+ # Developed for the LSST Data Management System.
4
+ # This product includes software developed by the LSST Project
5
+ # (https://www.lsst.org).
6
+ # See the COPYRIGHT file at the top-level directory of this distribution
7
+ # for details of code ownership.
8
+ #
9
+ # This software is dual licensed under the GNU General Public License and also
10
+ # under a 3-clause BSD license. Recipients may choose which of these licenses
11
+ # to use; please see the files gpl-3.0.txt and/or bsd_license.txt,
12
+ # respectively. If you choose the GPL option then the following text applies
13
+ # (but note that there is still no warranty even if you opt for BSD instead):
14
+ #
15
+ # This program is free software: you can redistribute it and/or modify
16
+ # it under the terms of the GNU General Public License as published by
17
+ # the Free Software Foundation, either version 3 of the License, or
18
+ # (at your option) any later version.
19
+ #
20
+ # This program is distributed in the hope that it will be useful,
21
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
22
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23
+ # GNU General Public License for more details.
24
+ #
25
+ # You should have received a copy of the GNU General Public License
26
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
27
+ """BpsConfig-related utilities to support ctrl_bps testing."""
28
+
29
+ __all__ = ["generate_config_1", "generate_config_2", "generate_config_all"]
30
+
31
+ from typing import Any
32
+
33
+
34
+ def generate_config_1(param1: int, param2: int = -1, param3: int = -2) -> dict[str, Any]:
35
+ """Return a dictionary for updating a config in unit tests.
36
+
37
+ Parameters
38
+ ----------
39
+ param1 : `int`
40
+ First param.
41
+ param2 : `int`, optional
42
+ Second param. Defaults to -1.
43
+ param3 : `int`, optional
44
+ Third param. Defaults to -2.
45
+
46
+ Returns
47
+ -------
48
+ results : `dict` [`str`, `~typing.Any`]
49
+ The mocked results.
50
+ """
51
+ results = {"gencfg_1": param1, "gencfg_2": param2, "gencfg_3": param3, "p4": 41}
52
+ return results
53
+
54
+
55
+ def generate_config_2(param1: int, param2: int = -3, param3: int = -4) -> dict[str, Any]:
56
+ """Return a dictionary for updating a config in unit tests.
57
+
58
+ Parameters
59
+ ----------
60
+ param1 : `int`
61
+ First param.
62
+ param2 : `int`, optional
63
+ Second param. Defaults to -3.
64
+ param3 : `int`, optional
65
+ Third param. Defaults to -4.
66
+
67
+ Returns
68
+ -------
69
+ results : `dict` [`str`, `~typing.Any`]
70
+ The mocked results.
71
+ """
72
+ results = {"gencfg_4": param1, "gencfg_5": param2, "gencfg_6": param3, "p4": 42}
73
+ return results
74
+
75
+
76
+ def generate_config_all(param1: str, param2: int = -5, param3: int = -6) -> dict[str, Any]:
77
+ """Return a dictionary for updating multiple sections in a config.
78
+
79
+ Parameters
80
+ ----------
81
+ param1 : `str`
82
+ First param.
83
+ param2 : `int`, optional
84
+ Second param. Defaults to -2.
85
+ param3 : `int`, optional
86
+ Third param. Defaults to -5.
87
+
88
+ Returns
89
+ -------
90
+ results : `dict` [`str`, `~typing.Any`]
91
+ The mocked results.
92
+ """
93
+ results = {
94
+ "genall_1": param1,
95
+ "pipetask": {"ptask1": {"genall_2": param2}},
96
+ "finalJob": {"genall_3": param3},
97
+ }
98
+ return results
99
+
100
+
101
+ def generate_value_1(param1: int) -> str:
102
+ """Return a string for updating a config value in unit tests.
103
+
104
+ Parameters
105
+ ----------
106
+ param1 : `int`
107
+ First param.
108
+
109
+ Returns
110
+ -------
111
+ results : `str`
112
+ The mocked result.
113
+ """
114
+ return f"-c val2:{param1}"
lsst/ctrl/bps/version.py CHANGED
@@ -1,2 +1,2 @@
1
1
  __all__ = ["__version__"]
2
- __version__ = "29.2025.2400"
2
+ __version__ = "29.2025.2600"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lsst-ctrl-bps
3
- Version: 29.2025.2400
3
+ Version: 29.2025.2600
4
4
  Summary: Pluggable execution of workflow graphs from Rubin pipelines.
5
5
  Author-email: Rubin Observatory Data Management <dm-admin@lists.lsst.org>
6
6
  License: BSD 3-Clause License
@@ -2,17 +2,17 @@ lsst/__init__.py,sha256=Gk14M2Z1rlkmKNnIVprTMAua6WiShDHrlt32AkqTfj0,1366
2
2
  lsst/ctrl/__init__.py,sha256=Gk14M2Z1rlkmKNnIVprTMAua6WiShDHrlt32AkqTfj0,1366
3
3
  lsst/ctrl/bps/__init__.py,sha256=qNei3h4EwqUnyyCsBUkYXcRNNlSvzUzbM6Zdkd4eklE,1663
4
4
  lsst/ctrl/bps/_exceptions.py,sha256=qNftFVE8yhiRD8yvACKEf5iHhi1o2eaa69ZCBvw6lDo,1974
5
- lsst/ctrl/bps/bps_config.py,sha256=Nw7TXbBY9VHry6u1erzLodyI72uiJgklTcYoDtuIns8,16103
5
+ lsst/ctrl/bps/bps_config.py,sha256=4t1jyIBiw9leAySjkcksCaZ3CPJMOt8afxGxTEWRSyQ,18460
6
6
  lsst/ctrl/bps/bps_draw.py,sha256=Sl04jpbm6jB_5lBzfJprqnDes9t_aqQQhr0Ag5RSv-Y,1984
7
7
  lsst/ctrl/bps/bps_reports.py,sha256=j6HdAvkOBTSxSHmkx_vd04FvifToTaZVGpwfF-LIUu0,12487
8
- lsst/ctrl/bps/bps_utils.py,sha256=c7sB9DzuVI4-zdB5mpBPqFrON3ZqPRX7URzAbpXrVqs,11446
8
+ lsst/ctrl/bps/bps_utils.py,sha256=-w0HSUXKw8jgJFl28yzwJuuqLqT_UOw12_XQBELUWrE,12206
9
9
  lsst/ctrl/bps/cancel.py,sha256=mAdBi-oUpepyo-1MCqx_I34dbm6cqT0VJu3d2-y9T2Y,3317
10
10
  lsst/ctrl/bps/clustered_quantum_graph.py,sha256=mBf8s_DlTzGCFq7aAKmD1cAXq6Cqr8QxjwpgXPOQcRc,18765
11
11
  lsst/ctrl/bps/constants.py,sha256=dsnsNMqwU6Xl_ln6nQ0PmxsghlbBY9mLJWf2rlzYayQ,1733
12
12
  lsst/ctrl/bps/construct.py,sha256=a5Gb_oinowb7m9rLsk0R_hz8GFu9WGCzDd_QWbsK0Mk,4944
13
13
  lsst/ctrl/bps/drivers.py,sha256=M_zWXvzK23MBBNvqdbJCnA_9DUCoFznCjWfwQw9BO6Q,22512
14
14
  lsst/ctrl/bps/generic_workflow.py,sha256=BwEFBudncziHTZaTTknOQroY_a-33mGf-mq9PzxH8G0,53720
15
- lsst/ctrl/bps/initialize.py,sha256=mTCWHLFudfu_Kk3QVbd1tnz76UdG822K9CNWuOOgUv0,7488
15
+ lsst/ctrl/bps/initialize.py,sha256=DCQwB9ZSo_36Ncs8jMJwxKZcYCu46jjww6rzyiuMFKY,7554
16
16
  lsst/ctrl/bps/ping.py,sha256=orwTZUNFtlexMYFcNWW_48jaa7Jo1oK4_eb_HuC-p5E,2235
17
17
  lsst/ctrl/bps/pre_transform.py,sha256=mPUW1QuHwgkSgZGVK6xO4RN590z4g1zf3p4kNsx_yOg,10222
18
18
  lsst/ctrl/bps/prepare.py,sha256=Fa2OEQIo4Pa8R5WmRo0PvJgXWNjynRijATvu1x80qlw,3129
@@ -22,7 +22,7 @@ lsst/ctrl/bps/restart.py,sha256=yVwxeviLiehyIfPmwU-H3tJ9ou7OWZZcrNf8PMxjr8o,2298
22
22
  lsst/ctrl/bps/status.py,sha256=Lrt0cAqROv77B8UvYXGimCa4cDHBD1N0K2Xx7oS6fXk,3362
23
23
  lsst/ctrl/bps/submit.py,sha256=Ev-yhcoZwtBPIo5bRt_4XFJRtgQBd8JHUurEfn01HpU,2880
24
24
  lsst/ctrl/bps/transform.py,sha256=jGEA3YGIQIJiLv-4Qm00WPNW0EEKughX7lcoJRZhsKU,35600
25
- lsst/ctrl/bps/version.py,sha256=AyivLkwA4FcYO6eiFsfTA_EuqMhydgvzBupNZlQZL-E,55
25
+ lsst/ctrl/bps/version.py,sha256=eKEngRNTsqzq5yv4faNqXQ7KB1ya5wGTLTxJ1qbWG50,55
26
26
  lsst/ctrl/bps/wms_service.py,sha256=l3T6i1MG72dhHY0KXMUlBjWUpCLOfaySs7o2W8oCwhs,18891
27
27
  lsst/ctrl/bps/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
28
  lsst/ctrl/bps/cli/bps.py,sha256=CHfAL-U4mSi-FqeGKtmkX5nI5H9gkRre4XEWNVdeMRk,2559
@@ -32,15 +32,16 @@ lsst/ctrl/bps/cli/opt/__init__.py,sha256=6-bAftMGxt_uEKrQl0gtrg8dJLBNsPd_DWCApg_
32
32
  lsst/ctrl/bps/cli/opt/arguments.py,sha256=Q9nU1Ad1CRv0HgIM68bu6sqCfJT1om-ARZy7pVXGJ94,1534
33
33
  lsst/ctrl/bps/cli/opt/option_groups.py,sha256=xylZX9CmxrTg1FJQ0ziyWYF0Se6CvO6ydgAwUZFTkR4,2722
34
34
  lsst/ctrl/bps/cli/opt/options.py,sha256=pZQpjJ2Vrx6kYJGs5vVERBMFstPocwBXHffxkWkmavg,3088
35
- lsst/ctrl/bps/etc/bps_defaults.yaml,sha256=pEmaTJ-F7hHVo2rrqhSoxgLTdMuFRpm-sU7FhoX2eco,4807
35
+ lsst/ctrl/bps/etc/bps_defaults.yaml,sha256=UwKAKWl09-Xjtl6kiz-AiXA9SDczeCvPGRXOPG3fzb8,4828
36
+ lsst/ctrl/bps/tests/config_test_utils.py,sha256=WM8Vrigk4OO0TBoL1A73a6hLhf2a6-ACD20fROJ0U7A,3537
36
37
  lsst/ctrl/bps/tests/gw_test_utils.py,sha256=zVVQqzwSiQgPgk9TnqDzgR7uDnaTMeuBLYKA8vOp5RI,22452
37
- lsst_ctrl_bps-29.2025.2400.dist-info/licenses/COPYRIGHT,sha256=Lc6NoAEFQ65v_SmtS9NwfHTOuSUtC2Umbjv5zyowiQM,61
38
- lsst_ctrl_bps-29.2025.2400.dist-info/licenses/LICENSE,sha256=pRExkS03v0MQW-neNfIcaSL6aiAnoLxYgtZoFzQ6zkM,232
39
- lsst_ctrl_bps-29.2025.2400.dist-info/licenses/bsd_license.txt,sha256=7MIcv8QRX9guUtqPSBDMPz2SnZ5swI-xZMqm_VDSfxY,1606
40
- lsst_ctrl_bps-29.2025.2400.dist-info/licenses/gpl-v3.0.txt,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
41
- lsst_ctrl_bps-29.2025.2400.dist-info/METADATA,sha256=f2SkQsZUeoXJ2jUagkNzhvtrjTUaGoJBJK4PM5J3UNc,2190
42
- lsst_ctrl_bps-29.2025.2400.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
43
- lsst_ctrl_bps-29.2025.2400.dist-info/entry_points.txt,sha256=d6FhN79h7s9frdBI7YkScsGEInwpGGub49pAjXWbIbI,51
44
- lsst_ctrl_bps-29.2025.2400.dist-info/top_level.txt,sha256=eUWiOuVVm9wwTrnAgiJT6tp6HQHXxIhj2QSZ7NYZH80,5
45
- lsst_ctrl_bps-29.2025.2400.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
46
- lsst_ctrl_bps-29.2025.2400.dist-info/RECORD,,
38
+ lsst_ctrl_bps-29.2025.2600.dist-info/licenses/COPYRIGHT,sha256=Lc6NoAEFQ65v_SmtS9NwfHTOuSUtC2Umbjv5zyowiQM,61
39
+ lsst_ctrl_bps-29.2025.2600.dist-info/licenses/LICENSE,sha256=pRExkS03v0MQW-neNfIcaSL6aiAnoLxYgtZoFzQ6zkM,232
40
+ lsst_ctrl_bps-29.2025.2600.dist-info/licenses/bsd_license.txt,sha256=7MIcv8QRX9guUtqPSBDMPz2SnZ5swI-xZMqm_VDSfxY,1606
41
+ lsst_ctrl_bps-29.2025.2600.dist-info/licenses/gpl-v3.0.txt,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
42
+ lsst_ctrl_bps-29.2025.2600.dist-info/METADATA,sha256=2lLcDL1u06EDG3qahVfcgvJmJHZP_5KedjOEO4e34vI,2190
43
+ lsst_ctrl_bps-29.2025.2600.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
44
+ lsst_ctrl_bps-29.2025.2600.dist-info/entry_points.txt,sha256=d6FhN79h7s9frdBI7YkScsGEInwpGGub49pAjXWbIbI,51
45
+ lsst_ctrl_bps-29.2025.2600.dist-info/top_level.txt,sha256=eUWiOuVVm9wwTrnAgiJT6tp6HQHXxIhj2QSZ7NYZH80,5
46
+ lsst_ctrl_bps-29.2025.2600.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
47
+ lsst_ctrl_bps-29.2025.2600.dist-info/RECORD,,