Skip to content

temporal: add test for tgis.init() across a session change - #7445

Merged
petrasovaa merged 4 commits into
OSGeo:mainfrom
petrasovaa:fix-tgis-init-session-change
Jun 3, 2026
Merged

petrasovaa merged 4 commits into
OSGeo:mainfrom
petrasovaa:fix-tgis-init-session-change

Conversation

@petrasovaa

@petrasovaa petrasovaa commented May 30, 2026 •

Copy link
Copy Markdown
Contributor

I noticed in other PRs that pytests don't work with tgis - switching to a different project between two tgis.init() calls in the same Python process must respawn the C-library subprocess. This PR contains a test reproducing the problem, fix in tgis.init() function AND changes the way pytest import tests. The fix in the init function fixes the test for linux and the pytest import change makes it work on other platforms. The change in pytest imports impacts all tests, but seems harmless.

AI summary and explanation below:

Problem

tgis.init() spawns message and C-library subprocesses that capture GISRC at spawn time. When a process
switches to a different project and calls tgis.init() again, those subprocesses stayed bound to the previous
session's GISRC (which may have been deleted), causing failures like No active GRASS session.

Fix

tgis.init() now detects a mapset/location/gisdbase change and stops the stale message and C-library
interfaces so they are respawned in the current environment.

Test

Adds a regression test that runs tgis.init() across two projects and asserts the C-library interface is
replaced and usable in the second session. The test fails on main (all platforms) and passes with the fix.

Why the import-mode change is included

The test exercises the multiprocessing subprocesses, which use spawn on macOS/Windows. Under pytest's default
prepend import mode, the GRASS source python/ dir lands at sys.path[0], ahead of the installed tree. A
spawned child then re-imports grass from source, where grass.lib (compiled ctypes bindings) doesn't exist →
ModuleNotFoundError: No module named 'grass.lib', killing the RPC server. Setting --import-mode=importlib
(which doesn't mutate sys.path) resolves this. Verified with no regressions across the python/grass suite
(501 tests identical in both modes).

This is required for any pytest that drives temporal/pygrass RPC subprocesses on macOS/Windows.

@github-actions github-actions Bot added Python Related code is in Python libraries tests Related to Test Suite labels May 30, 2026
@petrasovaa
petrasovaa marked this pull request as draft May 30, 2026 03:23
@petrasovaa

Copy link
Copy Markdown
Contributor Author

Another attempt - using pytest with importlib option. Waiting for CI to confirm it helps.

Here is AI summary:

The failure is the first tgis.init(), before any session change. The temporal/pygrass RPC servers run as multiprocessing subprocesses. On macOS/Windows the default start method is spawn, which re-imports grass in a fresh interpreter from sys.path. Under pytest's default prepend import mode, the GRASS source python/ dir gets inserted at sys.path[0], ahead of the installed etc/python. The source tree has grass/init.py but no compiled grass/lib/ (ctypes bindings are generated only into the install tree), so the child's import grass.lib.gis fails with ModuleNotFoundError: No module named 'grass.lib', killing the RPC server (Bad file descriptor / FatalError). Linux uses fork, which inherits the already-imported install modules and never re-imports, so it passed there.

The change in core.py may still be needed.

@petrasovaa

Copy link
Copy Markdown
Contributor Author

All tests passed, so I am pretty confident this fixes it. @echoix any opinion on the changes in pytest import?

@petrasovaa
petrasovaa marked this pull request as ready for review June 3, 2026 02:58
@petrasovaa
petrasovaa requested review from echoix and ninsbl June 3, 2026 02:58
@petrasovaa
petrasovaa merged commit 41d63e5 into OSGeo:main Jun 3, 2026
30 of 32 checks passed
@petrasovaa
petrasovaa deleted the fix-tgis-init-session-change branch June 3, 2026 13:52
@github-actions github-actions Bot added this to the 8.6.0 milestone Jun 3, 2026
ninsbl pushed a commit to ninsbl/grass that referenced this pull request Jul 7, 2026
tgis.init() spawns message and C-library subprocesses that capture GISRC at spawn time. When a process
switches to a different project and calls tgis.init() again, those subprocesses stayed bound to the previous
session's GISRC (which may have been deleted), causing failures like No active GRASS session.
tgis.init() now detects a mapset/location/gisdbase change and stops the stale message and C-library
interfaces so they are respawned in the current environment.
The test exercises the multiprocessing subprocesses, which use spawn on macOS/Windows. Under pytest's default prepend import mode, the GRASS source python/ dir lands at sys.path[0], ahead of the installed tree. A
spawned child then re-imports grass from source, where grass.lib (compiled ctypes bindings) doesn't exist →
ModuleNotFoundError: No module named 'grass.lib', killing the RPC server. Setting --import-mode=importlib
(which doesn't mutate sys.path) resolves this. Verified with no regressions across the python/grass suite
(501 tests identical in both modes).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

libraries Python Related code is in Python tests Related to Test Suite

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants