Skip to content

Commit 1304976

Browse files
committed
Merge branch 'conda-clash'
This prevents problematic environment variables from propagating to the worker process, to avoid the wrong Python environment being used. See: https://imagesc.zulipchat.com/#narrow/channel/377693-Appose/topic/Python.20worker.20runs.20in.20wrong.20environment/with/583449746
2 parents ef9436a + 812c016 commit 1304976

4 files changed

Lines changed: 40 additions & 5 deletions

File tree

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "appose"
7-
version = "0.11.1.dev0"
7+
version = "0.12.0.dev0"
88
description = "Appose: multi-language interprocess cooperation with shared memory."
99
license = "BSD-2-Clause"
1010
authors = [{name = "Appose developers"}]

src/appose/environment.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,22 @@ def python(self, *args) -> Service:
146146
"-c",
147147
"import appose.python_worker; appose.python_worker.main()",
148148
]
149-
return self.service(python_exes, *python_args).syntax(PythonSyntax())
149+
# NB: Unset conda/mamba variables so they don't bleed into the worker
150+
# process and cause the wrong Python interpreter to be resolved.
151+
# Only clear variables not explicitly set by the caller via env().
152+
conda_vars = (
153+
"CONDA_PREFIX",
154+
"CONDA_DEFAULT_ENV",
155+
"CONDA_SHLVL",
156+
"PYTHONEXECUTABLE",
157+
)
158+
explicit = self.env_vars()
159+
conda_unset = {var: None for var in conda_vars if var not in explicit}
160+
return (
161+
self.service(python_exes, *python_args)
162+
.syntax(PythonSyntax())
163+
.env(**conda_unset)
164+
)
150165

151166
def groovy(
152167
self,

src/appose/service.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,12 @@ class Service:
4747
_service_count: int = 0
4848

4949
def __init__(
50-
self, cwd: str | Path, env_vars: dict[str, str] | None = None, *args: str
50+
self, cwd: str | Path, env_vars: dict[str, str | None] | None = None, *args: str
5151
) -> None:
5252
self._cwd: Path = Path(cwd)
53-
self._env_vars: dict[str, str] = env_vars.copy() if env_vars is not None else {}
53+
self._env_vars: dict[str, str | None] = (
54+
env_vars.copy() if env_vars is not None else {}
55+
)
5456
self._args: list[str] = list(args)
5557
self._tasks: dict[str, "Task"] = {}
5658
self._service_id: int = Service._service_count
@@ -102,6 +104,20 @@ def init(self, script: str) -> "Service":
102104
self._init_script = script
103105
return self
104106

107+
def env(self, **vars: str | None) -> "Service":
108+
"""
109+
Set environment variables to pass to the worker process.
110+
111+
Args:
112+
**vars: Key/value pairs to add to the worker's environment.
113+
A value of None causes the variable to be unset in the worker.
114+
115+
Returns:
116+
This service object, for chaining method calls.
117+
"""
118+
self._env_vars.update(vars)
119+
return self
120+
105121
def start(self) -> "Service":
106122
"""
107123
Explicitly launch the worker process associated with this service.

src/appose/util/process.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,11 @@ def builder(
3333
"""
3434
env = os.environ.copy()
3535
if env_vars:
36-
env.update(env_vars)
36+
for key, value in env_vars.items():
37+
if value is None:
38+
env.pop(key, None)
39+
else:
40+
env[key] = value
3741

3842
cwd = str(working_dir) if working_dir else None
3943

0 commit comments

Comments
 (0)