Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .codex/skills/regi-python-bridge-maintenance/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
name: regi-python-bridge-maintenance
description: Maintain the regi_python JPype bridge, JVM lifecycle, logging bridge, and wheel packaging. Use when editing regi_python.py, regi_python_logging.py, buildPythonWheel behavior, or troubleshooting JVM startup, classpath, shutdown, or logging issues.
---

# Regi Python Bridge Maintenance

Read `docs/agent-guides/regi-python-bridge-maintenance.md` and keep the bridge behavior aligned with the wheel tests.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
interface:
display_name: "REGI Python Bridge Maintenance"
short_description: "Maintain the JPype bridge layer"
default_prompt: "Use $regi-python-bridge-maintenance to update or troubleshoot the regi_python JPype bridge and runtime."
50 changes: 50 additions & 0 deletions .github/workflows/build-wheel.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Build Python Wheel

on:
workflow_call:
inputs:
ref:
description: Git ref to check out
required: false
type: string
default: ""

jobs:
build-wheel:
name: Build Python wheel
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v7
with:
fetch-depth: 0
ref: ${{ inputs.ref || github.ref }}

- name: Set up Java
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: 21

- name: Set up Gradle
uses: gradle/actions/setup-gradle@v6

- name: Make Gradle wrapper executable
run: chmod +x ./gradlew

- name: Build and test
run: ./gradlew clean build buildPythonWheel

- name: Collect wheel
run: |
mkdir -p dist
find . -path "*/build/install/*/dist/*.whl" -exec cp {} dist/ \;

- name: Upload Python wheel artifact
uses: actions/upload-artifact@v4
with:
name: python-wheel
path: dist/*.whl
if-no-files-found: error
retention-days: 14
31 changes: 7 additions & 24 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,35 +9,18 @@ on:
permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
build:
build-wheel:
name: Build and test
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v7
with:
fetch-depth: 0

- name: Set up Java
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: 21

- name: Set up Gradle
uses: gradle/actions/setup-gradle@v6

- name: Make Gradle wrapper executable
run: chmod +x ./gradlew

- name: Build and test
run: ./gradlew clean build
uses: ./.github/workflows/build-wheel.yml

dependency-submission:
name: Submit Gradle dependencies
needs: build
needs: build-wheel
runs-on: ubuntu-latest
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
permissions:
Expand Down
46 changes: 46 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Release

on:
release:
types:
- published

permissions:
contents: write
actions: read

concurrency:
group: release-${{ github.event.release.id }}
cancel-in-progress: false

jobs:
build-wheel:
name: Build wheel from release tag
uses: ./.github/workflows/build-wheel.yml
with:
ref: ${{ github.event.release.tag_name }}

publish-wheel:
name: Publish Python wheel to GitHub Release
needs: build-wheel
runs-on: ubuntu-latest

steps:
- name: Download Python wheel artifact
uses: actions/download-artifact@v4
with:
name: python-wheel
path: dist

- name: Generate checksums
run: |
cd dist
sha256sum *.whl > SHA256SUMS.txt

- name: Publish wheel to GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.event.release.tag_name }}
files: |
dist/*.whl
dist/SHA256SUMS.txt
61 changes: 61 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# AGENTS.md

## Repository Overview

`regi-headless` now uses a **Python-first execution model**.

- `regi-headless/src/main/python/regi_python` is the runtime bridge. It starts the JVM with **JPype** and exposes `regi_session()` and `run_headless(calculation_callback)`.
- `district-scripts/` and the example scripts under `regi-headless/src/test/resources/...` are now Python entrypoints that call into Java through the bridge.

Treat this repo as a Python orchestration layer over REGI Java libraries.

## Current Architecture

- `regi-headless/src/main/python/regi_python/regi_python.py` is the current Python entrypoint.
- `regi_session()` owns JVM startup/shutdown.
- `run_headless()` creates the REGI domain and invokes a Python callback with a Java-backed registry.
- `regi-headless/src/main/java/...` contains the Java support layer that the Python bridge calls through JPype.
- `district-scripts/` contains active district scripts written calling Java-backed calculations inside the callback.
- `regi-headless/src/test/resources/usace/rowcps/headless/examples` contains the same pattern for example scripts used by tests.

## File Groups To Treat Differently

- `regi-headless/src/main/python/`
- python to java bridge code
- prefer modern Python style and small, testable helpers
- `district-scripts/`
- active district-owned operational scripts
- preserve behavior unless the task explicitly changes calculation results or API usage
- `regi-headless/src/test/resources/usace/rowcps/headless/examples/`
- example scripts used by tests
- keep them aligned with the district-script pattern
- `docs/`
- useful for historical context and documentation of features moving forward
- `docs/agent-guides/` is the shared source of truth for agent-facing workflow guidance

## Working Rules

- Keep edits scoped to the requested migration target.
- When a script needs a new Java method, update the Java public API and the test harness together; the script test suite validates against the Java source-defined scriptable API.
- Avoid broad refactors outside the requested script family.

## Verification

Common checks in this repo:

- `./gradlew buildPythonWheel`
- `./gradlew testPythonWheel`

The Python package is built from `regi-headless/src/main/python`, and the wheel test verifies the package metadata, importability, public API exposure, and bundled Java jars.

## Environment Notes

The Python bridge expects the Java environment to be available, and the repo documentation currently references these variables:

- `JAVA_HOME`
- `CDA_URL`
- `CDA_API_KEY`
- `OFFICE_ID`
- `REGI_LOG_LEVEL`

Use the repo's current bridge code and tests as the source of truth for behavior; use the docs for orientation, not as a strict contract. `regi-headless/src/test/python/test_district_scripts.py` is the main contract for migrated script shape and allowed API calls.
112 changes: 71 additions & 41 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,75 +1,105 @@
# REGI-Headless

> [!IMPORTANT]
> **Notice: Project Refactor in Progress**
> This project is undergoing a large refactor for [CWMS Data API](https://github.com/USACE/cwms-data-api) support.
> It will transition from a Java project consuming Jython scripts to a **Python project** that
> utilizes **JPype** to call underlying REGI Java libraries.
`regi-python` is the Python bridge over the REGI Java libraries.

`REGI-Headless` is a Java-based command-line tool and library designed to run
**REGI** calculations in a headless environment.
It allows users to execute complex hydrological calculations and manage gate settings via Jython
scripts without the need for a graphical interface.
The client-facing Python API is documented in [docs/PYTHON_API.md](docs/PYTHON_API.md).
For script migration guidance, see [docs/JYTHON_TO_JPYPE_MIGRATION.md](docs/JYTHON_TO_JPYPE_MIGRATION.md).

## Features
## What Lives Where

- **Headless Execution**: Run REGI calculations as part of automated workflows or on servers.
- **Database Integration**: Connects to CWMS data retrieval and storage.
- **Modular Calculations**: Includes support for:
- Inflow calculations (Clone, Compute, Auto-Adjust, Balance All, etc.)
- Flow Group and gate settings calculations.
- `regi-headless/src/main/python/regi_python/`
- Python bridge code
- Public entry points: `regi_session()` and `run_headless(calculation_callback)`
- `regi-headless/src/main/java/`
- Java support layer used by the bridge calling into REGI calculation and data access libraries
- `district-scripts/`
- Copy of district-owned Python scripts used as examples for smoke tests

## Project Structure
## Requirements

- `regi-headless/`: Core Java implementation, including `RegiCLI`.
- `district-scripts/`: Example scripts and district-specific configurations.
- `docs/`: Additional documentation.
- Java JDK 21 or higher
- Python 3.11 or higher

## Getting Started
### Environment variables
- `JAVA_HOME` set for JPype startup
- `CDA_URL` url for CDA instance to connect to
- `CDA_API_KEY` required for accessing and storing data in CDA
- `OFFICE_ID` session scoped office for data access
- `REGI_LOG_LEVEL` for logging verbosity
- `REGI_LOG_FORMAT` overrides the default Python log format

### Prerequisites
## Building The Wheel

- Java JDK 21 or higher.
Build the Python wheel with Gradle:

### CWMS Data API Configuration
```powershell
./gradlew buildPythonWheel
```

The wheel is written to `regi-headless/build/install/regi_python/dist/`.

The library reads the following environment variables when establishing the CWMS Data API data source:
Release tags become wheel versions and must be PEP 440 compatible. For example, use `0.0.2a0`, `0.0.2b0`, or `0.0.2rc0` instead of `0.0.2-alpha`, `0.0.2-beta`, or `0.0.2-rc`.

- `CDA_URL`: Base URL for the CWMS Data API endpoint.
- `API_KEY`: API key used for CWMS Data API authentication and authorization.
- `OFFICE_ID`: CWMS office identifier used to scope the session.
Install the built wheel into a Python environment:

```powershell
pip install regi_python-*.whl
```

The factory uses these values to authenticate, resolve the current user, and persist the connected office and time zone into the REGI project.
### Notes

### Building
- The Python package name is `regi_python`.
- The wheel metadata name is `regi-python`.
- The bundled Java jars are packaged inside `regi_python/lib/`.

## Releases

Releases are published from the GitHub repository at [USACE-WaterManagement/regi-python](https://github.com/USACE-WaterManagement/regi-python). A release build attaches the Python wheel and checksum file to the GitHub Release for the matching tag.

To consume a published wheel, download the wheel asset from the release and install it with your package manager. Use the exact wheel filename from the release asset URL.

```powershell
./gradlew build
pip install https://github.com/USACE-WaterManagement/regi-python/releases/download/<tag>/regi_python-<version>-py3-none-any.whl
```

Details TBD.
```powershell
uv pip install https://github.com/USACE-WaterManagement/regi-python/releases/download/<tag>/regi_python-<version>-py3-none-any.whl
```

## Usage
```powershell
poetry add https://github.com/USACE-WaterManagement/regi-python/releases/download/<tag>/regi_python-<version>-py3-none-any.whl
```

```powershell
pdm add https://github.com/USACE-WaterManagement/regi-python/releases/download/<tag>/regi_python-<version>-py3-none-any.whl
```

If your tool does not support direct wheel URLs, download the asset from the release page and install it from the local `.whl` file instead.

TBD
## Using The Bridge

### Command Line Options
See [docs/PYTHON_API.md](docs/PYTHON_API.md) for the full Python-facing contract.

TBD
## Verification

### Example
Run the wheel smoke tests:

TBD
```powershell
./gradlew testPythonWheel
```

Run the script/API compatibility smoke test:

## Testing
```powershell
./gradlew smokeTestDistrictScripts
```

TBD
`./gradlew check` runs both along with Java unit tests.

## Maintainers

See [MAINTAINERS.md](MAINTAINERS.md) for a list of project maintainers.
See [MAINTAINERS.md](MAINTAINERS.md).

## License

See [LICENSE](LICENSE) for licensing information.
See [LICENSE](LICENSE).
Loading
Loading