Skip to content

Commit ca6b41f

Browse files
committed
Implement env vars
1 parent 5fdb7d8 commit ca6b41f

File tree

5 files changed

+80
-11
lines changed

5 files changed

+80
-11
lines changed

docs/backends.rst

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,27 @@ subclass implementing a remote frame-buffer. There are also some `wgpu examples
131131
canvas # Use as cell output
132132
133133
134+
135+
.. _env_vars:
136+
137+
Selecting a backend with env vars
138+
---------------------------------
139+
140+
The automatic backend selection can be influenced with the use of environment
141+
variables. This makes it possible to e.g. create examples using the
142+
auto-backend, and allow these examples to run on CI with the offscreen backend.
143+
Note that once ``rendercanvas.auto`` is imported, the selection has been made,
144+
and importing it again always yields the same backend.
145+
146+
* ``RENDERCANVAS_BACKEND``: Set the name of the backend that the auto-backend should select. Case insensituve.
147+
* ``RENDERCANVAS_FORCE_OFFSCREEN``: force the auto-backend to select the offscreen canvas, ignoring the above env var. Truethy values are '1', 'true', and 'yes'.
148+
149+
Rendercanvas also supports the following env vars for backwards compatibility, but only when the corresponding ``RENDERCANVAS_`` env var is unset or an empty string:
150+
151+
* ``WGPU_GUI_BACKEND``: legacy alias.
152+
* ``WGPU_FORCE_OFFSCREEN``: legacy alias.
153+
154+
134155
.. _interactive_use:
135156

136157
Interactive use
@@ -152,7 +173,7 @@ honor that and use Qt instead.
152173
On ``jupyter console`` and ``qtconsole``, the kernel is the same as in ``jupyter notebook``,
153174
making it (about) impossible to tell that we cannot actually use
154175
ipywidgets. So it will try to use ``jupyter_rfb``, but cannot render anything.
155-
It's therefore advised to either use ``%gui qt`` or set the ``WGPU_GUI_BACKEND`` env var
176+
It's therefore advised to either use ``%gui qt`` or set the ``RENDERCANVAS_BACKEND`` env var
156177
to "glfw". The latter option works well, because these kernels *do* have a
157178
running asyncio event loop!
158179

docs/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
ROOT_DIR = os.path.abspath(os.path.join(__file__, "..", ".."))
1818
sys.path.insert(0, ROOT_DIR)
1919

20-
os.environ["WGPU_FORCE_OFFSCREEN"] = "true"
20+
os.environ["RENDERCANVAS_FORCE_OFFSCREEN"] = "true"
2121

2222

2323
# Load wglibu so autodoc can query docstrings

rendercanvas/auto.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,19 +85,35 @@ def backends_generator():
8585

8686
def backends_by_env_vars():
8787
"""Generate backend names set via one the supported environment variables."""
88+
89+
# We also support the legacy WGPU_X env vars, but only when the
90+
# corresponding RENDERCANVAS_X is not set or set to the empty string.
91+
92+
def get_env_var(*varnames):
93+
for varname in varnames:
94+
value = os.getenv(varname, "").lower()
95+
if value:
96+
return value, varname
97+
else:
98+
return "", varnames[0]
99+
88100
# Env var intended for testing, overrules everything else
89-
if os.environ.get("WGPU_FORCE_OFFSCREEN", "").lower() in ("1", "true", "yes"):
90-
yield "offscreen", "WGPU_FORCE_OFFSCREEN is set"
101+
force_offscreen, varname = get_env_var(
102+
"RENDERCANVAS_FORCE_OFFSCREEN", "WGPU_FORCE_OFFSCREEN"
103+
)
104+
if force_offscreen and force_offscreen in ("1", "true", "yes"):
105+
yield "offscreen", f"{varname} is set"
106+
91107
# Env var to force a backend for general use
92-
backend_name = os.getenv("WGPU_GUI_BACKEND", "").lower().strip() or None
108+
backend_name, varname = get_env_var("RENDERCANVAS_BACKEND", "WGPU_GUI_BACKEND")
93109
if backend_name:
94110
if backend_name not in BACKEND_NAMES:
95111
logger.warning(
96-
f"Ignoring invalid WGPU_GUI_BACKEND '{backend_name}', must be one of {BACKEND_NAMES}"
112+
f"Ignoring invalid {varname} '{backend_name}', must be one of {BACKEND_NAMES}"
97113
)
98114
backend_name = None
99115
if backend_name:
100-
yield backend_name, "WGPU_GUI_BACKEND is set"
116+
yield backend_name, f"{varname} is set"
101117

102118

103119
def backends_by_jupyter():
@@ -116,7 +132,7 @@ def backends_by_jupyter():
116132
# whether we're in a console or notebook. Technically this kernel could be
117133
# connected to a client of each. So we assume that ipywidgets can be used.
118134
# User on jupyter console (or similar) should ``%gui qt`` or set
119-
# WGPU_GUI_BACKEND to 'glfw'.
135+
# RENDERCANVAS_BACKEND to 'glfw'.
120136

121137
# If GUI integration is enabled, we select the corresponding backend instead of jupyter
122138
app = getattr(ip.kernel, "app", None)

tests/test_offscreen.py

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,36 @@
1212
def test_offscreen_selection_using_env_var():
1313
from rendercanvas.offscreen import ManualOffscreenRenderCanvas
1414

15-
ori = os.environ.get("WGPU_FORCE_OFFSCREEN", "")
15+
ori = os.getenv("RENDERCANVAS_FORCE_OFFSCREEN")
16+
os.environ["RENDERCANVAS_FORCE_OFFSCREEN"] = "1"
17+
18+
# We only need the func, but this triggers the auto-import
19+
from rendercanvas.auto import select_backend
20+
21+
try:
22+
if not os.getenv("CI"):
23+
for value in ["", "0", "false", "False", "wut"]:
24+
os.environ["RENDERCANVAS_FORCE_OFFSCREEN"] = value
25+
module = select_backend()
26+
assert module.RenderCanvas is not ManualOffscreenRenderCanvas
27+
28+
for value in ["1", "true", "True"]:
29+
os.environ["RENDERCANVAS_FORCE_OFFSCREEN"] = value
30+
module = select_backend()
31+
assert module.RenderCanvas is ManualOffscreenRenderCanvas
32+
33+
finally:
34+
if ori is not None:
35+
os.environ["RENDERCANVAS_FORCE_OFFSCREEN"] = ori
36+
37+
38+
def test_offscreen_selection_using_legacyt_env_var():
39+
from rendercanvas.offscreen import ManualOffscreenRenderCanvas
40+
41+
ori1 = os.getenv("RENDERCANVAS_FORCE_OFFSCREEN")
42+
ori2 = os.getenv("WGPU_FORCE_OFFSCREEN")
43+
44+
os.environ.pop("RENDERCANVAS_FORCE_OFFSCREEN", None)
1645
os.environ["WGPU_FORCE_OFFSCREEN"] = "1"
1746

1847
# We only need the func, but this triggers the auto-import
@@ -31,7 +60,10 @@ def test_offscreen_selection_using_env_var():
3160
assert module.RenderCanvas is ManualOffscreenRenderCanvas
3261

3362
finally:
34-
os.environ["WGPU_FORCE_OFFSCREEN"] = ori
63+
if ori1 is not None:
64+
os.environ["RENDERCANVAS_FORCE_OFFSCREEN"] = ori1
65+
if ori2 is not None:
66+
os.environ["WGPU_FORCE_OFFSCREEN"] = ori2
3567

3668

3769
def test_offscreen_event_loop():

tests/testutils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,5 +74,5 @@ def _determine_can_use_glfw():
7474
can_use_wgpu_lib = bool(adapter_summary)
7575

7676
can_use_glfw = _determine_can_use_glfw()
77-
is_ci = bool(os.getenv("CI", None))
77+
is_ci = bool(os.getenv("CI"))
7878
is_pypy = sys.implementation.name == "pypy"

0 commit comments

Comments
 (0)