Add model editor app for building YAML model files#42
Conversation
…tion Create a separate Streamlit app for building and editing YAML model files: - src/epicc/editor/ package with helpers.py (pure logic) and __main__.py (UI) - editor.py entry point at repository root - Makefile 'editor' target - 29 tests covering helpers, validation, and round-trip serialization Agent-Logs-Url: https://github.com/EpiForeSITE/epicc/sessions/a4e6dd31-6c9a-4ef2-9059-59a5f3af997d Co-authored-by: gvegayon <893619+gvegayon@users.noreply.github.com>
Agent-Logs-Url: https://github.com/EpiForeSITE/epicc/sessions/a4e6dd31-6c9a-4ef2-9059-59a5f3af997d Co-authored-by: gvegayon <893619+gvegayon@users.noreply.github.com>
gvegayon
left a comment
There was a problem hiding this comment.
@copilot, I tried the new app, and it is not working as expected. The main issues I saw:
- The list of authors failed to properly load the authors of the measles model:
- The buttons to add or remove anything are not working. I tried adding/removing authors, parameters, scenarios, etc., and none worked.
- Use on_click callbacks for all add/remove buttons so state changes happen before the next render cycle (fixes buttons appearing to do nothing) - Track uploaded file identity to prevent re-processing on every rerun - Use st.rerun() after file upload to force fresh widget creation - Embed a version counter in all dynamic widget keys so structural changes (upload, add, remove) create truly new widgets that honour the value parameter from loaded data (fixes author names not loading) Agent-Logs-Url: https://github.com/EpiForeSITE/epicc/sessions/f7916fb3-4db3-4e2d-b88a-1306009dcf25 Co-authored-by: gvegayon <893619+gvegayon@users.noreply.github.com>
Agent-Logs-Url: https://github.com/EpiForeSITE/epicc/sessions/f7916fb3-4db3-4e2d-b88a-1306009dcf25 Co-authored-by: gvegayon <893619+gvegayon@users.noreply.github.com>
Fixed both issues in 93c8b1f: Authors not loading: Streamlit caches widget values by key — even after updating Add/remove buttons not working: The old code used Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
There was a problem hiding this comment.
Pull request overview
Adds a dedicated Streamlit “Model Editor” app for creating/editing EPICC YAML model files, with pure-logic helpers and accompanying tests.
Changes:
- Introduce
epicc.editorpackage with YAML↔state parsing, validation, and serialization helpers. - Add a Streamlit UI app (
epicc.editor.__main__) pluseditor.pyentrypoint to run it similarly toapp.py. - Add pytest coverage for helper logic and YAML/state round-trips.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
src/epicc/editor/helpers.py |
Implements editor helper functions (coercion/parsing, YAML→state, state→doc, validation, YAML serialization). |
src/epicc/editor/__main__.py |
Streamlit UI for editing model metadata, parameters, equations, scenarios, report blocks, and figures; supports upload/validate/download/preview. |
src/epicc/editor/__init__.py |
Declares the new epicc.editor package. |
editor.py |
Entry point to run the editor app via streamlit run editor.py. |
Makefile |
Adds make editor target for launching the editor. |
tests/epicc/test_editor.py |
Adds tests for helper functions and YAML/state/document round-trips. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Changed '\n'.join(p.get('references', [])) to '\n'.join(p.get('references') or [])
to prevent TypeError when references is null or invalid type.
…y swallowing them Agent-Logs-Url: https://github.com/EpiForeSITE/epicc/sessions/180e9200-681b-41c4-bc4b-545f4c14acc6 Co-authored-by: olivia-banks <53623746+olivia-banks@users.noreply.github.com>
…or; show structured field errors in editor UI Agent-Logs-Url: https://github.com/EpiForeSITE/epicc/sessions/a5e3de79-3ec7-4a80-8bcc-72bd03c603b5 Co-authored-by: olivia-banks <53623746+olivia-banks@users.noreply.github.com>
…_word variable for readability Agent-Logs-Url: https://github.com/EpiForeSITE/epicc/sessions/a5e3de79-3ec7-4a80-8bcc-72bd03c603b5 Co-authored-by: olivia-banks <53623746+olivia-banks@users.noreply.github.com>
Agent-Logs-Url: https://github.com/EpiForeSITE/epicc/sessions/760e0c5a-25bc-4a30-8aa6-82a77e634550 Co-authored-by: olivia-banks <53623746+olivia-banks@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| file_id = f"{uploaded.name}:{uploaded.size}" | ||
| if st.session_state.get("_uploaded_file_id") != file_id: |
| param: dict[str, Any] = { | ||
| "type": p["type"], | ||
| "label": p["label"], | ||
| "default": coerce_numeric(str(p["default"])), |
| if p["type"] == "enum" and p.get("options"): | ||
| options = parse_key_value_lines(p["options"]) | ||
| param["options"] = {str(k): str(v) for k, v in options.items()} |
| """Parse ``key: value`` lines into a dict, coercing numeric values.""" | ||
| result: dict[str, Any] = {} | ||
| for line in text.strip().splitlines(): | ||
| if ":" not in line: | ||
| continue | ||
| key, _, val = line.partition(":") | ||
| val = val.strip() | ||
| try: | ||
| result[key.strip()] = int(val) | ||
| except ValueError: | ||
| try: | ||
| result[key.strip()] = float(val) | ||
| except ValueError: | ||
| result[key.strip()] = val |
| # Authors | ||
| authors_raw = data.get("authors", []) | ||
| state["authors"] = [ | ||
| {"name": a.get("name", ""), "email": a.get("email", "")} for a in authors_raw | ||
| ] or [{"name": "", "email": ""}] |
|
@gvegayon I'm looking through the code in earnest now, and it's really not all that great. Copilot didn't really seem to read the rest of the code and emitted something that sort of exists along a tangent (e.g., the code for creating models with graphs hardcodes a bunch of information even though this is readily exposed by the block Pydantic models). I think I'm going to use some of this code as a base but then write the rest myself. Closing for now unless you think we should pursue this route. |

src/epicc/editor/__main__.pyUI strings