Repository navigation
Give every load model one package layout and stop models sharing code - #15
Open
TimThacker wants to merge 6 commits into
Open
TimThacker wants to merge 6 commits into
TimThacker wants to merge 6 commits into
Conversation
Each model package exposes CON_NAMES, DEFAULT_CONS and DISPLAY_FIELDS from cons.py, build_<id>_record/parse_<id>_record/is_<id>_record from dyr.py, simulate_<id>_response from simulation.py, and cons_for_preset/preset_gaps from presets.py. __init__.py only wires MODEL. Adds a contract test and a Package layout section to ADDING_A_LOAD_MODEL.md.
…wn package Remove load_models/common.py and every cross-model import. flag_on, preset_bundle and the simulator time grid are copied into each model that uses them; perc2_dll carries its own PERC1-record CON layout, defaults, display rows, .dyr parser and simulator; perc2_standard carries its own .dyr helpers. CON names, defaults, .dyr text and simulated responses are unchanged. Add a test that fails if a model package imports another, and update the developer docs and CHANGELOG.
Every cons/dyr/presets/simulation file opens with a docstring and ends with an exact __all__. cons.py defines CON_NAMES, then DEFAULT_CONS, then DISPLAY_FIELDS; flag_on lives only in cons.py. Every dyr.py starts with the same header constants (FAMILY, MODEL_CODE, N_ICON, N_CON, N_STATE, N_VAR, N_RESERVED_ICON) and defines strip_comments and _SCOPE_BY_SUFFIX. perc2_dll's simulator internals are renamed to match the others. Tests check all of it; CON names, defaults, .dyr text and simulated responses are unchanged.
A complete step-trip model in the package layout, one block per file. The test writes the doc's blocks to a package and runs the layout and behaviour checks on it, so the example cannot drift from the rules.
…d-model layout tests/fixtures/extra_models/step_trip/ has the same files, names and ..base imports as a built-in model, supports record scopes with aliases, and is the model the end-to-end tests register. The worked example in ADDING_A_LOAD_MODEL.md is generated from those files, and a test fails if a doc block differs from its file. Removes example_load_model.py.
…model tests/test_model_regression.py compares every registered model with a golden file in tests/golden/ (CON names and defaults, display rows, the .dyr record, and a digest of the simulated response over a grid of voltage and frequency events for the defaults and every preset) and the main window's exported .dyr for four models. The golden files were generated from release 1.2.1, before the load models were restructured; UPDATE_GOLDEN=1 regenerates them. The developer-loop tests (case, export, mock run, sweep, CLI) now run on every real model that can mock-run. The step-trip test fixture package is removed; the worked example in ADDING_A_LOAD_MODEL.md stays, checked by a small test that writes its blocks to a temporary package.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this change?
Gives every built-in load model the same structure and stops the models sharing code. It is a refactor: no CON name, default,
.dyrrecord or simulated response changes. A new golden-file test pins that.src/load_models/<id>/with the same files and public names:cons.py(CON_NAMES,DEFAULT_CONS,DISPLAY_FIELDS),dyr.py(build_<id>_record,parse_<id>_record,parse_<id>_records,is_<id>_record),simulation.py(simulate_<id>_response,simulate_<id>_frequency_response) andpresets.py(cons_for_preset,preset_gaps).__init__.pyonly wiresMODEL.perc1_dll's preset code moves out of__init__.pyinto a newpresets.py.load_models/common.pyis deleted.flag_on, the preset bundle lookup and the simulator time grid are copied into each model that uses them.perc2_dllcarries its own copy of the PERC1 DLL CON layout, defaults, display rows,.dyrparser and simulator, andperc2_standardcarries its own copy of the PERC1 standard.dyrhelpers. A model imports only..base.cons/dyr/presets/simulationfile opens with a docstring and ends with an exact__all__.cons.pydefinesCON_NAMES, thenDEFAULT_CONS, thenDISPLAY_FIELDS, andflag_onlives only there. Everydyr.pystarts with the same header constants (FAMILY,MODEL_CODE,N_ICON,N_CON,N_STATE,N_VAR,N_RESERVED_ICON) and definesstrip_comments, so the writers and parsers no longer use header literals.perc2_dll's simulator internals are renamed to match the others.PERC1_CON_ORDER,PERC1_DEFAULT_CONS,PERC1_DISPLAY_FIELDS,CLOD_DISPLAY_FIELDS,build_perc1_dyr_block,parse_perc1_dyr_block,simulate_perc1_response,clod_recordand their PERC2 counterparts now follow the layout above. Callers inexport/,editor/,preview/,ui/,presets/and the tests are updated.tests/test_model_regression.pycompares every registered model with a golden file intests/golden/: CON names and defaults, display rows, the.dyrrecord (in full for the defaults, a digest for every preset and block), and a digest of the simulated response over a grid of voltage and frequency events, for the defaults and every preset (and with momentary cessation on for the PERC2 DLL). It also compares the full.dyrfile the main window exports for the four PERC models. The golden files were generated from release 1.2.1 (c5ab482), before the restructuring.UPDATE_GOLDEN=1 uv run pytest tests/test_model_regression.pyregenerates them for a deliberate change.example_load_model.pyis removed. The developer-loop tests (case, export, mock run, sweep, CLI) now run on every real model that can mock-run. New tests check the layout, the import rule and the file shape.ADDING_A_LOAD_MODEL.mddefines the layout and rules, has a worked example (a small step-trip model, checked by a test that writes its code blocks to a temporary package), and explains the golden files.ARCHITECTURE.md,PERC2_DLL_MODEL.mdand the CHANGELOG are updated.Why?
The four PERC models and CLOD had grown different structures (different names for the same thing,
perc1_dll's preset code inline in__init__.py,perc2_dllimporting the PERC1 DLL's internals), so there was no pattern to follow when adding a model. PSS/E can treat a CON of the same name differently in each model, so sharing code between models risks a change for one silently changing another. Each model is now defined in full in its own files, tests enforce the layout, and the golden files guard each model's behavior.How was it tested?
Test counts (
uv run pytest -q): 909 passed, 2 skipped (the golden-file regenerator, which only runs withUPDATE_GOLDEN=1, and one skip that was already there).uv run ruff checkis clean. Run on the branch rebased onto currentmain, with pytest 9.2.0 and ruff 0.17.3.Model behavior is unchanged:
c5ab482, before any of this refactoring: 5 models, 2,090 simulated responses and every preset and block..dyrheader code and a changed momentary-cessation delay in the simulator each failed it and named what moved. I then reverted them..dyrinputs (short and long records, bad headers, placeholder and unquoted ids, PERC1 and PERC2 records together) gave the same results from the old and newperc2_dllparser. This was a one-off comparison and is not in the suite..dyrequals that ofc5ab482apart from the generation timestamp. The test above keeps four of those as golden files.This does not change model behavior, so no new PSS/E run was needed. I did not run PSS/E.
What was not done?
perc2_dll's copy of the PERC1 DLL simulator) is now kept in sync by hand. A fix to the PERC1 DLL simulator needs the same fix inperc2_dll. The golden files will show if the copies diverge in the cases they cover.presets/ridethrough.py,editor/model_ui.py,editor/dyr_import.pyandpreview/perc2_dll.pystill import PERC1 DLL pieces. They are application code, not model definitions, and the preset library is written in PERC1 DLL terms.DYR_LAYOUTand the standard models withConSpec, since the vendor formats differ.validate_consstays optional:perc1_dlland CLOD have none.Checklist