feat: macOS support - portable paths, solver discovery, and cross-platform runtime fixes#52
feat: macOS support - portable paths, solver discovery, and cross-platform runtime fixes#52parthdagia05 wants to merge 1 commit intoEAPD-DRB:mainfrom
Conversation
…m fixes
- Config.py: anchor all paths to PROJECT_ROOT via __file__ (CWD-independent)
- app.py: use Config.WebAPP_PATH for template/static dirs, clean startup banner
- OsemosysClass.py: 3-tier solver resolution (env var → PATH → bundled fallback)
- SyncS3.py + UploadRoute.py: replace hardcoded backslash with os.sep
- SyncS3.py + UploadRoute.py: guard against None in S3 list_objects_v2
- CustomThreadClass.py: propagate exceptions from background threads
- Base.Class.js: use window.location.origin for API URL resolution
- Osemosys.Class.js: guard null casename in getData/getResultData
- index.html: comment out missing wijmo licence.js
- Config.py: fix EmissionActivityRatio typo ('e''t' → 'e','t')
- setup.sh: cross-platform setup script (venv, deps, GLPK/CBC via Homebrew)
Closes OSeMOSYS#3, OSeMOSYS#8, OSeMOSYS#12, OSeMOSYS#25, OSeMOSYS#34, OSeMOSYS#39, #43, #45
Supersedes PRs: OSeMOSYS#11, OSeMOSYS#13, OSeMOSYS#28, OSeMOSYS#31, OSeMOSYS#32, OSeMOSYS#35, OSeMOSYS#40, #44, #46
|
Thanks for the strong cross-platform work here, @parthdagia05. This PR is very aligned with our macOS direction. For this integration track, we prefer to merge the individual focused PRs directly so review stays manageable. Because of that, could you please rebase this PR onto the latest Key items we found to address when you rebase:
I'll change this PR to draft to make it easier to track |
|
Thanks for the thorough work here @parthdagia05, this is a substantial PR. The Python-side changes have all been incorporated into the One item worth noting: your Closing as superseded by mac-port. Appreciate the effort — it covered a lot of ground. |
Summary
This PR integrates full macOS support into MUIOGO by resolving all platform-dependent
assumptions across the backend, frontend, and setup flow. It consolidates the work
planned across 9 individual PRs (#11, #13, #28, #31, #32, #35, #40, #44, #46) into
a single, tested change set.
What changed and why
Path Portability (CWD-Independent Startup)
Config.py: AllPath('WebAPP')relative paths replaced withPROJECT_ROOT / 'WebAPP'computed via
Path(__file__).resolve(). The app now starts correctly from any workingdirectory, not just the project root.
app.py: Replacedos.path.abspath('WebAPP')withConfig.WebAPP_PATH.resolve().Removed debug
print()statements, added structured startup banner showing Python path,template/static dirs, mode, and server URL.
Config.py: Addedos.makedirs(DATA_STORAGE, exist_ok=True)and wrappedos.chmodin
try/exceptto handle macOS SIP permission restrictions gracefully.Solver Discovery (GLPK/CBC)
OsemosysClass.py: Removed theif platform.system() == 'Windows'block withhardcoded Windows/x86 macOS paths. Replaced with
_resolve_solver_folder()— a portablethree-tier resolution chain:
$GLPK_PATH/$CBC_PATH)shutil.which()(finds Homebrew-installed solvers automatically)WebAPP/SOLVERs/Verified on Apple Silicon: GLPK resolves to
/opt/homebrew/Cellar/glpk/5.0/bin,CBC to
/opt/homebrew/Cellar/cbc/2.10.12/bin.Frontend & Runtime
Base.Class.js: Replaced hardcodedhttp://127.0.0.1:5002/withwindow.location.origin + "/"for local/dev mode, enabling compatibility withCodespaces and preview URLs.
Osemosys.Class.js: Addedif (!casename)guards ingetData()andgetResultData()to preventfetch('/DataStorage/null/...')calls after modeldeletion.
index.html: Commented out missingReferences/wijmo/licence.jsscript includeto prevent 404 + MIME console errors.
Backend Robustness
SyncS3.py+UploadRoute.py: Replaced all hardcoded'\\'path separatorswith
os.sep. Addedif contents:guard before iterating overlist_objects_v2response to prevent
TypeError: 'NoneType' is not iterable.CustomThreadClass.py: Background thread exceptions are now captured viasys.exc_info()inrun()and re-raised with original traceback injoin().Previously exceptions were silently swallowed.
Bug Fix
Config.py: FixedEmissionActivityRatiodimension list —'e''t'(Pythonstring concatenation =
'et') corrected to'e','t'(two separate elements).Setup & Documentation
setup.sh: New cross-platform setup script that creates a Python venv, installspip dependencies, installs GLPK/CBC via Homebrew (macOS) or apt (Linux), verifies
solver availability, and creates required directories.
Files changed (10)
API/Classes/Base/Config.pyAPI/app.pyAPI/Classes/Case/OsemosysClass.pyAPI/Classes/Base/SyncS3.pyAPI/Routes/Upload/UploadRoute.pyAPI/Classes/Base/CustomThreadClass.pyWebAPP/Classes/Base.Class.jsWebAPP/Classes/Osemosys.Class.jsWebAPP/index.htmlsetup.shValidation
python3 app.py/opt/homebrew/Cellar/glpk/5.0/binviashutil.which()/opt/homebrew/Cellar/cbc/2.10.12/binviashutil.which()http://127.0.0.1:5002/Related issues
Closes #51