|
| 1 | +# Migrating REGI Headless District Jython Scripts to `regi_python` |
| 2 | + |
| 3 | +This guide captures the script migration pattern used in the district-scripts history, |
| 4 | +moving from old Python 2 Jython-style top-level scripts to the current JPype-based `regi_python` bridge. |
| 5 | + |
| 6 | +## Core Migration Pattern |
| 7 | + |
| 8 | +Old scripts typically: |
| 9 | + |
| 10 | +- imported Java classes at module import time |
| 11 | +- accessed global `registry` and calculation objects at top level |
| 12 | +- executed the calculation immediately when the file was loaded |
| 13 | +- relied on shell wrappers such as `RunHeadlessJython.bat` or `.sh` |
| 14 | + |
| 15 | +New scripts should: |
| 16 | + |
| 17 | +- import `regi_session` and `run_headless` from `regi_python` |
| 18 | +- move Java imports inside a callback that runs after the JVM starts |
| 19 | +- wrap the calculation logic in a function such as `run_calculations(registry)` |
| 20 | +- keep `registry.getCalculation(...)` and Java method calls unchanged |
| 21 | +- end with `if __name__ == "__main__": with regi_session(): run_headless(run_calculations)` |
| 22 | + |
| 23 | +## Before And After |
| 24 | + |
| 25 | +### Before |
| 26 | + |
| 27 | +```python |
| 28 | +from java.util import Calendar |
| 29 | +from java.util import TimeZone |
| 30 | + |
| 31 | +gateCalc = registry.getCalculation(1.0, "Gate Flow") |
| 32 | +timeZone = TimeZone.getTimeZone("US/Central") |
| 33 | +startCal = Calendar.getInstance(timeZone) |
| 34 | +endCal = Calendar.getInstance(timeZone) |
| 35 | +gateCalc.computeFlowGroup("SWT", "FOSS", startCal.getTime(), endCal.getTime(), "Flow.FOSS.Project_Total") |
| 36 | +``` |
| 37 | + |
| 38 | +### After |
| 39 | + |
| 40 | +```python |
| 41 | +from regi_python import regi_session, run_headless |
| 42 | + |
| 43 | + |
| 44 | +def run_calculations(registry): |
| 45 | + from java.util import Calendar |
| 46 | + from java.util import TimeZone |
| 47 | + |
| 48 | + gateCalc = registry.getCalculation(1.0, "Gate Flow") |
| 49 | + timeZone = TimeZone.getTimeZone("US/Central") |
| 50 | + startCal = Calendar.getInstance(timeZone) |
| 51 | + endCal = Calendar.getInstance(timeZone) |
| 52 | + gateCalc.computeFlowGroup("SWT", "FOSS", startCal.getTime(), endCal.getTime(), "Flow.FOSS.Project_Total") |
| 53 | + |
| 54 | + |
| 55 | +if __name__ == "__main__": |
| 56 | + with regi_session(): |
| 57 | + run_headless(run_calculations) |
| 58 | +``` |
| 59 | + |
| 60 | +## Translation Rules |
| 61 | + |
| 62 | +### 1. Move Java imports inside the callback |
| 63 | + |
| 64 | +JPype-backed imports should happen after the JVM starts. |
| 65 | +Put them inside `run_calculations(registry)` or a nested helper only called from that callback. |
| 66 | + |
| 67 | +This is the biggest behavioral difference from Jython scripts. |
| 68 | + |
| 69 | +### 2. Keep the registry lookup pattern |
| 70 | + |
| 71 | +The migration does not change the scriptable REGI API. Calls like these stay the same: |
| 72 | + |
| 73 | +- `registry.getNames(1.0)` |
| 74 | +- `registry.getCalculation(1.0, "Inflow")` |
| 75 | +- `registry.getCalculation(1.0, "Gate Flow")` |
| 76 | + |
| 77 | +The change is only the Python wrapper around those calls. |
| 78 | + |
| 79 | +### 3. Convert top-level execution into a callback |
| 80 | + |
| 81 | +Scripts must be converted from immediate execution to a `run_calculations()` function. |
| 82 | +That keeps import side effects out of the module. |
| 83 | + |
| 84 | +### 4. Replace Python 2 `print` statements |
| 85 | + |
| 86 | +Old scripts often contain lines like: |
| 87 | + |
| 88 | +```python |
| 89 | +print "Error Computing Flow Group" |
| 90 | +``` |
| 91 | + |
| 92 | +Update these to Python 3 syntax: |
| 93 | + |
| 94 | +```python |
| 95 | +print("Error Computing Flow Group") |
| 96 | +``` |
| 97 | + |
| 98 | +### 5. Keep optional Java-side logging calls |
| 99 | + |
| 100 | +Calls such as `LoggingOptions.setDbMessageLevel(2)` and `LoggingOptions.setMetricsEnabled(True)` still belong in the script if the district workflow depends on them. They do not move to `regi_python`; they simply live inside the callback now. |
| 101 | + |
| 102 | +### 6. Remove the shell wrapper |
| 103 | + |
| 104 | +The old `RunHeadlessJython` launchers are no longer needed. The Python file itself becomes the entry point: |
| 105 | + |
| 106 | +```python |
| 107 | +if __name__ == "__main__": |
| 108 | + with regi_session(): |
| 109 | + run_headless(run_calculations) |
| 110 | +``` |
| 111 | + |
| 112 | +## Project-Specific Examples |
| 113 | + |
| 114 | +The current district scripts show the same migration shape across several script families: |
| 115 | + |
| 116 | +- `SWF/InflowCalcComputedInflow.py` |
| 117 | +- `SWF/InflowCalcComputeEvapAsFlow.py` |
| 118 | +- `SWF/GateSettings.py` |
| 119 | +- `SWT/GateFlowGroup1.py` |
| 120 | +- `SWL/Big3-GateFlow.py` |
| 121 | + |
| 122 | +The differences between them are the calculation names, location lists, and optional logging or flow-group loops. The migration pattern itself is the same. |
0 commit comments