Skip to content

Test on Python 3.13 and 3.14 - #69

Closed
samtalki wants to merge 13 commits into
Power-Agent:mainfrom
samtalki:ci/python-313-314
Closed

samtalki wants to merge 13 commits into
Power-Agent:mainfrom
samtalki:ci/python-313-314

Conversation

@samtalki

Copy link
Copy Markdown
Member

Summary

  • Run the test suite on Python 3.13 and 3.14 in addition to 3.10 and 3.12, so the matrix covers the floor of requires-python and every version the classifiers claim.
  • Add the 3.13 and 3.14 classifiers; the README and the package guide state the tested range.
  • Move the checkout and setup-python steps to their current major tags.

Stacked on #67, which stacks on #64; draft until those merge.

Testing

Full suite from the branch root, no code changes needed on either new interpreter (powerio installs from its abi3 wheel):

Interpreter Result
CPython 3.12.12 390 passed, 20 skipped
CPython 3.13.14 390 passed, 20 skipped
CPython 3.14.7 390 passed, 20 skipped

🤖 Generated with Claude Code

samtalki and others added 13 commits September 15, 2026 22:55
`resolve_solver_case` resolves one file or one serialized PowerIO IR document
into a typed module, selects a collection entry by `time_index` or
`scenario_id`, and hands a writer the balanced network an operating point
states. `OperatingPoint.network` supplies that network directly, so no
MATPOWER round trip narrows the state to a representable subset.

`pio-ir` and `pio` are the format tokens PowerIO accepts; a document carrying
neither is refused on PowerIO's own terms. Diagnostics follow PowerIO's
severity vocabulary: `error` fails validation, `remark` and `note` stay out of
the user-facing warning list.

`check_diagnostics`, `operating_point_module` and `select_entry` are public
because a second server module calls them. `value_type_name` isolates the one
structural-type read PowerIO publishes no accessor for.

`powermcp.sandbox` re-exports `staged_file_write` alongside the rest of the
path policy and states powerio's containment default.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
pandapower, PyPSA, ANDES, Egret and surge accept `powerio_ir` as the primary
argument, keep `network_json` as its alias, and splice the shared response
tail: `value_type`, `selection`, `diagnostics`, `warnings`, plus the emission
fidelity and the typed-edit report for the adapters that convert into their
own model.

PowerIO 0.11.2 hands a directory writer a path that does not exist yet, so
the PyPSA CSV export and the surge table export create the staging directory
before writing into it. ANDES and Egret install their one emitted case file
through `staged_file_write`, so a write that fails part way leaves whatever
stands at the destination untouched.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Fourteen declarations now read `powerio[mcp,matrix]>=0.11.2,<0.12`. The floor
is 0.11.2 because 0.11.1 added `OperatingPoint.network` and matrix `row_ids`,
and 0.11.2 sets the path-containment default this repository documents.
`GenX/requirements.txt` gains a pin: `GenX/server.py` imports
`powermcp.sandbox`, which imports powerio.

Version 0.4.0. The sdist excludes local virtual environments and uv build
caches, and `.gitignore` covers `.venv-*/`.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
PowerIO 0.11.2 confines MCP paths to the directory the process started in when
no root variable names one. A session-scoped autouse fixture names the
repository checkout, pytest's temporary base and the system temporary
directory, so a test writing under `tmp_path` is admitted. A test that sets its
own roots still overrides it, because `allowed_roots()` reads the environment
on every call.

`_containment_status` distinguishes an explicit root list from the implicit
default, reports the default as a setting to make rather than a policy already
chosen, and reports the refusal PowerIO raises for a root variable naming no
directory. The doctor's user-visible strings carry no decorative characters.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The powerio and solver-boundary tests require powerio 0.11.2, so the matrix
tools name their axes unconditionally and a retired Package document is
asserted for what it is: not PowerIO IR.

`tests/test_transport.py` states why it exists. The SDK parses a string
argument whose text is JSON before validation, so only a real stdio session
proves a `powerio_ir` argument reaches the tool intact.

`tests/test_sdk_imports.py` covers PLEXOSDB, the one server directory it
missed. `tests/test_publish_workflow.py` asserts the sdist exclude list keeps
local virtual environments and build caches out of a release.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The PowerIO section describes the server shipped in 0.11.2, names the
arguments every adapter takes, and states the containment default: with no
root variable set, paths stay beneath the directory the server process
started in.

Per-server READMEs describe what the import tools accept, which is serialized
PowerIO IR or one selected entry of a collection. The retired `Package`,
`model-json`, `package_json` and package `study_commit` formats keep their
migration note: re-parse the original case and pass its `powerio_ir`.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
stdout carries JSON-RPC once a server runs, so the ANDES startup notes go to
its logger, which writes to stderr, and the two PowerWorld error reports go to
stderr explicitly.

`GenX/server.py` keeps the repository root on `sys.path` for the process
lifetime and says why: GenX carries no `__init__.py`, so its namespace
`__path__` is recomputed from `sys.path` on every attribute lookup and the
lazy `GenX.tool_logic` imports would fail without it.

PLEXOSDB's notes on its shared import name say what the module is: a
re-export of the `plexosdb-mcp` server object under that same name. The
install picker's instruction line and the `powermcp` package docstring carry
no decorative characters.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
powerio 0.11.2 ships a cp39-abi3 manylinux wheel serving Python 3.9 through
3.14, and the only other Rust dependency, surge-py, lives in an opt-in extra
CI never installs. Without the toolchain step a future wheel gap fails loudly
instead of building from an sdist.

The suite spawns roughly forty subprocesses per job with 60 second timeouts,
so stacked pushes on a busy runner turn a timeout into a failure. The
concurrency group cancels superseded pull request runs and leaves pushes to
main alone.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
powermcp/tellegen.py exchanges PowerIO IR with the tellegen binary over stdin
and stdout: the powerio server parses, Tellegen solves, and the solution comes
back as a PowerIO module every other tool reads. The tools are capabilities,
contract, solve, solve_module, plan and the Study family. Applying a Study
proposal binds a recommendation to the Study and stays a human action, so
study_run refuses it.

The binary resolves from POWERMCP_TELLEGEN_BINARY, then the tellegen.binary
config key, then PATH. A multiconductor value and a module PowerIO marks with
an error are both refused before the process starts. The tellegen extra is
empty because the CLI is a Rust binary rather than a pip package.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The binary is not a Python package, so the import probe says nothing about it.
The doctor runs the configured executable's capabilities subcommand and reports
green only when it exits zero and prints JSON. Output decodes as UTF-8 with
replacement so a non-UTF-8 console cannot raise UnicodeDecodeError.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
tests/data/fake_tellegen.py stands in for the compiled binary and speaks the
same JSON protocol, so CI needs no Rust toolchain. One test runs against a real
build and skips unless TELLEGEN_BIN names one.

The checked-arguments table in tests/test_sandbox.py lists the three helpers
every tellegen tool reaches the filesystem through, and test_windows_only_flags
names tellegen among the servers that run everywhere.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
powermcp/TELLEGEN.md covers configuration, the Study bundle format, revision
binding and cancellation. The README section states how to build the CLI, point
PowerMCP at it, and read the response tail, and the PowerIO section names
Tellegen as a consumer of the same IR.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The matrix now covers the floor of requires-python and every version the
classifiers claim, so a regression on a newer interpreter fails the run
instead of reaching users through a claim the tests never check. The full
suite passes unchanged on both added versions: powerio ships abi3 wheels,
and the core tests substitute fakes for the vendor engines.

The checkout and setup-python steps move to their current major tags.

README and the package guide state the tested range rather than an open
floor, matching the classifiers.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@qian-harvard

Copy link
Copy Markdown
Contributor

Landed on main as 19c1e9b, and CI is green on all four: py3.10, py3.12, py3.13, py3.14 all success.

I cherry-picked your commit (2ce0b77, with -x and your authorship preserved) rather than merging the branch. The reason is that this PR is stacked on #67, so merging it would have pulled the whole Tellegen server in with it, and #67 is a separate call for you and @qian-harvard to make — I've left a note there. Your commit is self-contained (workflow matrix, action versions, two classifiers, README wording), so it lifted out cleanly with no conflicts.

One thing worth checking, which I deliberately did not silently 'fix' for you: the three-way merge of your branch would have kept main's test step, but your commit's own diff was written against a parent where the step was still pytest tests/ -q. c41c525 (which came in with #64) had since widened it to include the PowerFactory suites. The cherry-pick touches only the matrix and the action versions, so that widening is intact on main — but if you rebase the rest of the stack, watch that Run tests step doesn't get reverted.

Also flagging a small pre-existing inconsistency, since your commit comment now reads "every version the classifiers claim": 3.11 is in the classifiers but not in the matrix. Not introduced here, and I left it alone.

Closing as merged-by-cherry-pick — reopen if you'd rather land it as the branch once #67 resolves.

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