Skip to content
Open
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
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,15 @@ pythonCWMS -m pip install package-name

Packages included in releases are defined by [base requirements](requirements/base_requirements.txt) and [supplemental requirements](requirements/supplemental_requirements.txt), then resolved into the hash-pinned [Windows lock](requirements/locked.txt).

## RTS and HEC-DSS scripts
## RTS scripts

Jython is still used as a launcher inside RTS and HEC-DSS. Edit `python_script_path` and `args` in [example_python_script_launcher.py](jython_scripts/example_python_script_launcher.py). Set `args` to `None` or an empty string when no arguments are needed; multiple arguments are split before launching CPython.
Jython is still used inside RTS to launch external CPython processes. Configure
the `SCRIPTS` list in
[example_python_script_launcher.py](jython_scripts/example_python_script_launcher.py)
to provide a script menu, editable arguments, optional CDA credentials, and an optional snapshot of the active RTS forecast context. The launcher is
RTS-specific and does not run in HEC-DSSVue.

See the [RTS launcher guide](jython_scripts/README.md#rts-cpython-launcher) for configuration, child-process environment variables, security considerations, and troubleshooting.

Do not use the former Jython `install_python.py` workflow to install Python CWMS. The file remains as a compatibility notice for old bookmarks, while the signed Windows installer is documented in the [Jython migration guide](jython_scripts/README.md). Saved copies of the old installer are also stopped by the retirement document at the root of `main`.

Expand Down
168 changes: 164 additions & 4 deletions jython_scripts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,167 @@ Install-PythonCWMS.cmd -InstallRoot "D:\Tools\pythonCWMS"

For an unattended replacement, use `Install-PythonCWMS.cmd -Force`.

The remaining Jython script in this directory is only a launcher for running
CPython scripts from RTS or HEC-DSSVue. See
[`example_python_script_launcher.py`](example_python_script_launcher.py) for
its configuration.
## RTS CPython launcher

[`example_python_script_launcher.py`](example_python_script_launcher.py) is a
Jython 2.7 launcher for running external CPython scripts from RTS. It provides:

- A menu of configured scripts with editable command-line arguments.
- Live, combined standard output and error output in a Swing window.
- Optional CDA endpoint, office, and OAuth credentials from the active RTS
connection.
- An optional snapshot of the active watershed, forecast, run, and forecast
time window.

The launcher uses RTS-specific classes and is not compatible with HEC-DSSVue.
It runs one child process at a time. Closing the output window does not stop a
running child process.

### Prerequisites

1. Install Python CWMS using the instructions above.
2. Restart RTS after installation so it sees the new `PYTHON_CWMS_HOME` user
environment variable.
3. Confirm that `%PYTHON_CWMS_HOME%\python.exe` exists.
4. Log in to a CDA connection in RTS before running an entry configured with
`CDA_AUTH`.

### Configure scripts

Edit the `SCRIPTS` list near the top of the launcher. Each entry requires
`name`, `path`, and `args`. The `cda` and `rts_context` options default to
`CDA_NONE` and `False`.

```python
SCRIPTS = [
{
"name": "Local DSS Utility",
"path": r"C:\code\tools\local_dss_utility.py",
"args": r'--file "C:\data\forecast.dss"',
"cda": CDA_NONE,
"rts_context": True,
},
{
"name": "Authenticated CDA Job",
"path": r"C:\code\jobs\store_data.py",
"args": "--dry-run",
"cda": CDA_AUTH,
"rts_context": False,
},
]
```

Use an empty string for `args` when a script takes no arguments. The launcher
splits the argument text using Windows-style quoting and passes an argument
list directly to CPython without invoking a shell. The launch dialog lets the
operator edit arguments for that run without changing the configured default.

Each child starts with its script directory as the working directory and uses
`%PYTHON_CWMS_HOME%\python.exe -u`. Standard error is merged into standard
output and streamed to the output window.

### CDA access

Choose the least-privileged CDA mode needed by each script:

| Mode | Child environment | RTS requirement |
| --- | --- | --- |
| `CDA_NONE` | No CDA variables supplied by the launcher | None |
| `CDA_ENDPOINT` | `CDA_API_ROOT` and `OFFICE` | Active RTS CDA connection |
| `CDA_AUTH` | Endpoint and office plus `CDA_ACCESS_TOKEN`, `CDA_REFRESH_TOKEN`, `CDA_TOKEN_URL`, and `CDA_CLIENT_ID` | Authenticated OpenID RTS CDA connection |

For `CDA_AUTH`, the launcher refreshes the cached RTS OAuth token immediately
before starting CPython. The CPython script is responsible for reading the
environment and initializing its CDA client. For example:

```python
import os

import cwms

cwms.init_session(
api_root=os.environ["CDA_API_ROOT"],
token=os.environ.get("CDA_ACCESS_TOKEN"),
)

office_id = os.environ["OFFICE"]
```

Before constructing a child environment, the launcher removes all CDA and RTS
variables that it manages. It then adds only the capabilities requested by the selected entry, preventing a `CDA_NONE` or `CDA_ENDPOINT` script from
accidentally inheriting credentials from RTS.

`CDA_AUTH` gives the selected script and any processes it starts access to the current user's OAuth credentials. Configure only trusted scripts, and do not print tokens or a complete copy of the child environment. The launcher reports token lifetimes but does not display token values.

### RTS context

Set `rts_context` to `True` to provide `RTS_CONTEXT_JSON`, a versioned JSON
snapshot with this shape:

```json
{
"version": 1,
"watershed": {
"name": "Example Watershed",
"directory": "C:\\watersheds\\example",
"time_zone": "America/Chicago"
},
"current_module": "Forecast",
"active_forecast": {
"name": "Example Forecast",
"directory": "C:\\watersheds\\example\\forecast\\example",
"dss_file": "C:\\watersheds\\example\\forecast\\example\\forecast.dss"
},
"active_run": {
"name": "Run 1",
"key": "..."
},
"time_window": {
"startTime": "2026-11-01T00:00:00-05:00",
"extractStartTime": "2026-11-01T06:00:00-06:00",
"forecastTime": "2026-11-02T06:00:00-06:00",
"endTime": "2026-11-05T06:00:00-06:00"
}
}
```

Unavailable values remain `null`. Forecast, run, and time-window values are
only populated when the current RTS module is a forecast tab.

The same available values are also exported individually:

| Context | Environment variables |
| --- | --- |
| Watershed | `RTS_WATERSHED_NAME`, `RTS_WATERSHED_DIRECTORY`, `RTS_WATERSHED_TIME_ZONE` |
| Module | `RTS_CURRENT_MODULE` |
| Forecast | `RTS_ACTIVE_FORECAST`, `RTS_ACTIVE_FORECAST_DIRECTORY`, `RTS_ACTIVE_FORECAST_DSS` |
| Run | `RTS_ACTIVE_RUN`, `RTS_ACTIVE_RUN_KEY` |
| Time window | `RTS_START_TIME`, `RTS_EXTRACT_START_TIME`, `RTS_FORECAST_TIME`, `RTS_END_TIME` |

Times are ISO-8601 values with a UTC offset in the watershed time zone. A
CPython script can load the full snapshot with:

```python
import json
import os

context = json.loads(os.environ["RTS_CONTEXT_JSON"])
```

### Troubleshooting

- `PYTHON_CWMS_HOME environment variable is not set`: restart RTS after
installing Python CWMS, or verify the user environment variable.
- `Python executable not found`: verify that `PYTHON_CWMS_HOME` points to the
directory containing `python.exe`, normally
`C:\hec\python\pythonCWMS\python`.
- `This script requires an active RTS CDA connection`: select a CDA connection
in RTS or change the entry to `CDA_NONE`.
- Token or authentication errors: log out of CDA in RTS, log back in, and
launch the script again.
- `Python script not found`: correct the absolute `path` in the selected
`SCRIPTS` entry.

The authenticated mode reads RTS's cached token provider through Java
reflection to avoid opening another interactive login. That implementation
detail may need updating when moving the launcher to a different RTS release.
Loading
Loading