fix: resolve two ValueError bugs in config_loader._get_explicit_cli_args#3
Conversation
Bug 1: positional arguments passed dest both as first arg and as kwarg, raising "dest supplied twice for positional argument". Bug 2: store_true actions have nargs=0, which was unconditionally passed to add_argument, raising "nargs for store actions must be != 0". Fix: only add dest to kwargs for optional args; detect store_true, store_false, store_const, and count actions via isinstance and preserve them with action= instead of nargs=0. Closes QuantumNoLab#1 Signed-off-by: thc1006 <84045975+thc1006@users.noreply.github.com>
pyyaml is in the "configs" extra, not "dev". CI installs .[dev,pyscf] so yaml would be missing, causing a collection error. importorskip gracefully skips the module when yaml is unavailable. Signed-off-by: thc1006 <84045975+thc1006@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Fixes experiment startup crashes by correcting argparse “probe parser” reconstruction in experiments/config_loader.py, and adds regression tests to ensure explicit-CLI detection and config-merge precedence behave as intended.
Changes:
- Reworks
_get_explicit_cli_argsto avoidargparseValueErrors for positional args (duplicatedest) andstore_*flags (nargs=0misuse). - Adds a new
tests/test_config_loader.pytest suite covering the reported regressions and merge precedence (CLI > YAML > defaults).
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
experiments/config_loader.py |
Fixes argparse probe-parser construction to prevent startup crashes and correctly detect explicit CLI args. |
tests/test_config_loader.py |
Adds regression + precedence tests for _get_explicit_cli_args and load_config. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| kwargs: dict[str, Any] = {"default": sentinel} | ||
|
|
||
| # Actions with nargs=0 (store_true, store_false, store_const, count) | ||
| # cannot pass nargs as a kwarg — preserve them via action= instead. | ||
| if isinstance(action, argparse._StoreTrueAction): # noqa: SLF001 | ||
| kwargs["action"] = "store_true" | ||
| elif isinstance(action, argparse._StoreFalseAction): # noqa: SLF001 | ||
| kwargs["action"] = "store_false" | ||
| elif isinstance(action, argparse._StoreConstAction): # noqa: SLF001 | ||
| kwargs["action"] = "store_const" | ||
| kwargs["const"] = action.const | ||
| elif isinstance(action, argparse._CountAction): # noqa: SLF001 | ||
| kwargs["action"] = "count" | ||
| else: |
There was a problem hiding this comment.
action='count' cannot use a non-None sentinel default: argparse increments the existing value, so when the flag is provided it will attempt sentinel + 1 and raise TypeError. This means _get_explicit_cli_args will currently break for any parser that includes a count flag. Consider handling _CountAction separately by using a safe default (e.g. None or 0) and updating the explicit-detection logic accordingly (e.g. treat None/0 as “not provided” for count flags).
| import pytest | ||
|
|
||
| # config_loader requires pyyaml, which lives in the "configs" extra | ||
| pytest.importorskip("yaml") | ||
|
|
There was a problem hiding this comment.
This test module imports config_loader, which imports yaml (PyYAML). CI installs deps via pip install -e ".[dev,pyscf]", and pyyaml isn’t included in those extras, so these tests will raise ModuleNotFoundError: yaml and fail. Either add PyYAML to the dev/test dependencies, or guard these tests with an early pytest.importorskip("yaml") (before importing config_loader) if YAML support is intentionally optional.
- Add structured logging (debug: explicit args, merged config; info: YAML file loaded; debug: empty YAML) - Add 5 new tests: _load_yaml error paths (FileNotFoundError, empty YAML, non-dict YAML, valid YAML), namespace sync - Total: 18 tests covering all code paths in config_loader.py Signed-off-by: thc1006 <84045975+thc1006@users.noreply.github.com>
action="count" increments default+1, so sentinel (object) would raise TypeError. No experiment script uses count, so remove the branch and document the limitation. Addresses Copilot review on PR QuantumNoLab#3. Signed-off-by: thc1006 <84045975+thc1006@users.noreply.github.com>
- Add store_const detected/not-detected tests (covers line 191-193) - Strengthen defaults test to verify all 3 _DEFAULTS keys - Total: 20 tests, all code paths in config_loader.py now covered Signed-off-by: thc1006 <84045975+thc1006@users.noreply.github.com>
Critical fixes: - #1/#2: Use persistent prev_coeffs/prev_batch_configs for PT2 scoring (was using best_coeffs before it was defined in current iteration) - QuantumNoLab#5: Eviction checks cumulative_basis size (was checking best_batch_configs) - QuantumNoLab#7: Convert numpy indices to torch.LongTensor before indexing CUDA tensor - QuantumNoLab#8: Default energy_weight=0.0, entropy_weight=0.0 (was 0.1/0.05, silently changing existing behavior) Lower priority fixes: - QuantumNoLab#6: CIPSI docstring mentions build_sparse_hamiltonian requirement - QuantumNoLab#9: Warn when energy_weight>0 but hamiltonian=None Not applicable (won't fix): - QuantumNoLab#3/QuantumNoLab#4: config_integer_hash returns tuple for n_sites>=64; our CAS max is 58Q (<64), so int cast is safe Co-authored-by: leo07010 <leo07010@gmail.com>
Copilot fixes: - #1: top_idx on same device as unique_new (CUDA compat) - #2: use prev_energy (consistent with prev_coeffs eigenvector) - QuantumNoLab#3: eviction log only when eviction actually occurred - QuantumNoLab#4: remove dead test code, clarify as smoke test New: - 64+Q hash support (remove int() casts, use hash values directly) - Cr₂-CAS(12,32) @ 64Q and Cr₂-CAS(12,36) @ 72Q registry entries - Both MOLECULE_REGISTRY and _MOLECULE_INFO_REGISTRY synced (26 total) Co-authored-by: leo07010 <leo07010@gmail.com>
TLDR
Fixes two bugs in
experiments/config_loader.pythat crash all experiment scripts on startup.Closes #1
What changed
_get_explicit_cli_argsuses a sentinel-based probe parser to detect which CLI arguments were explicitly provided. Two argparse API misuses caused immediateValueErroron any experiment script invocation:Bug 1 -- positional arg with duplicate dest
Fix: only add
destto kwargs for optional arguments (those withoption_strings). Positional arguments infer dest from their name.Bug 2 -- store_true with nargs=0
Fix: detect
store_true,store_false,store_const, andcountactions viaisinstanceand preserve them withaction=kwarg instead of passingnargs=0.Test plan
tests/test_config_loader.pystore_trueflag detection (present / absent)store_falseflag detection (present / absent)load_configmerge precedence: CLI > YAML > defaultsruff check+ruff formatclean