Skip to content

fix(powerio): out-of-service handling in PyPSA bridge + error-shape hardening#34

Closed
qian-harvard wants to merge 1 commit into
mainfrom
chore/powerio-fixes
Closed

fix(powerio): out-of-service handling in PyPSA bridge + error-shape hardening#34
qian-harvard wants to merge 1 commit into
mainfrom
chore/powerio-fixes

Conversation

@qian-harvard

Copy link
Copy Markdown
Contributor

Follow-up fixes from an adversarial review of the powerio integration.

  • PyPSA bridge: drop out-of-service branches/generators before import_from_pypower_ppc (which ignores ppc status) so switched-out elements no longer import as active; corrected the rating-0 warning; clearer write-vs-parse error. pandapower's from_ppc honors status, so it is unchanged (documented by a new test).
  • powerio server: normalize convert_case OSError to ValueError; map wrong-schema JSON to the documented parse error; fail-fast namespace-shadow guard; explicit laplacian dispatch.
  • 6 new regression tests; full suite 91 passed.

Targets 0.1.2.

?? Generated with Claude Code

…pe hardening

Addresses an adversarial review of the merged powerio integration.

PyPSA bridge (PyPSA/pypsa_mcp.py):
- Major: PyPSA's import_from_pypower_ppc ignores the ppc status columns, so
  out-of-service branches/generators imported as fully active and silently
  changed topology (an out-of-service rating-0 branch even slipped in unwarned).
  Drop status==0 branches and generators before import and report the counts;
  the rating-0 warning now sees only in-service branches. pandapower's from_ppc
  already honors status, so its bridge is unchanged (covered by a new test that
  documents the asymmetry).
- Surface a clearer message when export_to_netcdf fails (write vs. parse).

powerio server (powerio/powerio_mcp.py):
- Normalize a temp-file OSError in convert_case to ValueError (the lone
  unnormalized filesystem path).
- Broaden the JSON-transport branch in _load so wrong-schema input maps to the
  documented "parse failed" ValueError instead of an opaque error.
- Fail fast if `import powerio` binds the repo's powerio/ namespace dir instead
  of the package (dev/editable paths).
- Dispatch the "laplacian" matrix kind explicitly so _MATRIX_KINDS and the
  dispatch chain can't drift silently.

Tests: out-of-service branch dropped + warned (PyPSA), out-of-service generator
warned, pandapower honors branch status, laplacian matrix, bad-JSON ValueError,
convert_case OSError normalization. Full suite: 91 passed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@samtalki

samtalki commented Jun 10, 2026

Copy link
Copy Markdown
Member

Nice catch — import_from_pypower_ppc really does ignore the status columns, and the gencost realignment after dropping generators is a detail I'd have missed. Thanks!

Two coordination notes:

🤖 Generated with Claude Code

@qian-harvard qian-harvard deleted the chore/powerio-fixes branch June 11, 2026 02:07
@qian-harvard qian-harvard restored the chore/powerio-fixes branch June 11, 2026 02:08
@qian-harvard qian-harvard deleted the chore/powerio-fixes branch June 11, 2026 02:08
samtalki added a commit to samtalki/PowerMCP that referenced this pull request Jun 11, 2026
PyPSA bridge: drop out-of-service branches and generators before
import_from_pypower_ppc, which ignores the ppc status columns; gencost
rows are realigned after generator drops. pandapower's from_ppc honors
status so its bridge is unchanged (documented by a new test).

powerio server: shadow-import guard on startup; explicit laplacian elif
with unreachable-else guard; OSError arm in convert_case; belt-and-
braces (ValueError/KeyError/TypeError) arm in _load.

tests: 7 new cases covering OOS branch/generator drops, pandapower
status contrast, laplacian matrix, bad-JSON ValueError, and OSError
normalization.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
samtalki added a commit to eigenergy/powerio that referenced this pull request Jun 11, 2026
…pping (#93)

An unreadable case file (permissions) leaked a raw PermissionError through
convert_case and the _parse family instead of the documented ValueError; an
OSError arm now maps it. Two defensive additions from the review of the
PowerMCP copy (Power-Agent/PowerMCP#34): _load gains a wrong-schema arm (the
Rust layer already maps these to PowerIOParseError; this guards future
Python-side paths) and compute_matrix names the laplacian branch explicitly
with an unreachable-else guard. docs/languages.md codifies the read_* verb:
datasets (multi-file directories) read and write, single documents parse and
serialize.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
samtalki added a commit to samtalki/PowerMCP that referenced this pull request Jun 11, 2026
Upstream landed the error-shape hardening from the Power-Agent#34 review
(eigenergy/powerio#93, released as 0.1.1): _parse maps an unreadable
file (OSError) to the documented ValueError shape, convert_case says
"cannot read file" instead of "conversion failed" for that case, and
the defensive-arm comments came along. Ports the upstream suite's
unreadable-file and wrong-schema tests. No new powerio API, so the
>=0.1.0 floor stands.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
qian-harvard pushed a commit that referenced this pull request Jun 14, 2026
* feat: sync the powerio server with upstream 0.1.0; convert inline in memory

powerio 0.1.0 ships convert_str, so the server's inline conversion no longer
stages temp files; the _EXT/_stage/_unlink_quietly machinery is gone. The
file is now a faithful copy of the canonical powerio.mcp.server (same eight
tools, the docstring polish from its review, the save_case newline fix both
copies already shared), with the standalone header pointing at upstream. The
powerio extra pins >=0.1.0 and a regression test asserts inline conversion
never touches tempfile.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix: carry Qian's OOS fix and error hardening from PR #34

PyPSA bridge: drop out-of-service branches and generators before
import_from_pypower_ppc, which ignores the ppc status columns; gencost
rows are realigned after generator drops. pandapower's from_ppc honors
status so its bridge is unchanged (documented by a new test).

powerio server: shadow-import guard on startup; explicit laplacian elif
with unreachable-else guard; OSError arm in convert_case; belt-and-
braces (ValueError/KeyError/TypeError) arm in _load.

tests: 7 new cases covering OOS branch/generator drops, pandapower
status contrast, laplacian matrix, bad-JSON ValueError, and OSError
normalization.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* sync: refresh the powerio server copy from upstream 0.1.1

Upstream landed the error-shape hardening from the #34 review
(eigenergy/powerio#93, released as 0.1.1): _parse maps an unreadable
file (OSError) to the documented ValueError shape, convert_case says
"cannot read file" instead of "conversion failed" for that case, and
the defensive-arm comments came along. Ports the upstream suite's
unreadable-file and wrong-schema tests. No new powerio API, so the
>=0.1.0 floor stands.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat: add ANDES powerio bridge and bump version pin to 0.1.1

Adds load_network_from_json and load_network_from_any to ANDES/andes_mcp.py,
following the same pattern as the PyPSA bridge. Both tools accept a powerio
JSON transport string or any powerio-readable file (MATPOWER, PSS/E, PowerWorld
.aux, PowerModels JSON, egret JSON), convert to MATPOWER via powerio's
case.to_format("matpower"), and write the result to out_path for ANDES to
consume via run_power_flow. Bumps the powerio extra pin to >=0.1.1 to match
the 0.1.1 server already on this branch.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants