Skip to content

Commit 9b68192

Browse files
committed
level: preserve args through as_dict round-trip when only one slot is populated
Level.as_dict() used all(self.args.values()), which dropped the entire args entry whenever either 'keyword' or 'block' was empty -- the common case for users who pass only keyword args. The scheduler reconstructs the level via Level(repr=level) before handing it to the job adapter, and re-feeds job.level into run_job during trsh, so the loss surfaced as user-supplied keywords (e.g. opt=(verytight)) silently disappearing on every trsh re-run while the initial run worked correctly. Switch to any() so args is preserved when at least one slot has content; still dropped when both are empty.
1 parent a5735a6 commit 9b68192

2 files changed

Lines changed: 21 additions & 1 deletion

File tree

arc/level.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ def as_dict(self) -> dict:
187187
original_dict = self.__dict__
188188
clean_dict = {}
189189
for key, val in original_dict.items():
190-
if val is not None and key != 'args' or key == 'args' and all([v for v in self.args.values()]):
190+
if (val is not None and key != 'args') or (key == 'args' and any(v for v in self.args.values())):
191191
clean_dict[key] = val
192192
return clean_dict
193193

arc/level_test.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,26 @@ def test_build(self):
119119
"dlpno-ccsd(t)/def2-tzvp, auxiliary_basis: def2-tzvp/c, solvation_method: smd, "
120120
"solvent: water, solvation_scheme_level: 'apfd/def2-tzvp, software: gaussian', software: orca")
121121

122+
def test_as_dict_preserves_args_when_one_slot_empty(self):
123+
"""args must round-trip through as_dict() even when only 'keyword' (or only 'block') is populated.
124+
125+
Regression: as_dict() previously used ``all(self.args.values())`` which dropped args
126+
whenever either slot was empty (the common case). Trsh re-runs lost user-supplied
127+
keyword args because the scheduler reconstructs the level via ``Level(repr=level)``.
128+
"""
129+
keyword_only = Level(repr={'method': 'wb97xd', 'basis': 'def2tzvp',
130+
'args': {'keyword': {'opt': 'opt=(verytight)'}}})
131+
self.assertIn('args', keyword_only.as_dict())
132+
self.assertEqual(Level(repr=keyword_only).args, keyword_only.args)
133+
134+
block_only = Level(repr={'method': 'wb97xd', 'basis': 'def2tzvp',
135+
'args': {'block': {'1': 'extra block'}}})
136+
self.assertIn('args', block_only.as_dict())
137+
self.assertEqual(Level(repr=block_only).args, block_only.args)
138+
139+
empty_args = Level(method='wb97xd', basis='def2tzvp')
140+
self.assertNotIn('args', empty_args.as_dict())
141+
122142
def test_year_validation(self):
123143
"""Test year validation for Level"""
124144
with self.assertRaises(ValueError):

0 commit comments

Comments
 (0)