Skip to content

Commit 0dfc8bd

Browse files
ctruedenclaude
andcommitted
Strip conda/mamba activation vars from Python worker processes
When the calling process has a conda/mamba environment active, variables like CONDA_PREFIX, CONDA_DEFAULT_ENV, and CONDA_SHLVL are inherited by subprocesses. This can interfere with environment activation in tools like pixi, causing the worker to resolve the wrong Python interpreter (e.g., the caller's miniforge Python instead of the pixi-managed one). Fix by unsetting those three variables from every Python worker's environment in Environment.python(). Variables explicitly set by the caller via the builder's env() are left untouched. Infrastructure: Service gains an env(**vars: str | None) method, and process.builder() now treats a None value as a deletion request rather than a set. Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent ef9436a commit 0dfc8bd

4 files changed

Lines changed: 35 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: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,17 @@ 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 = ("CONDA_PREFIX", "CONDA_DEFAULT_ENV", "CONDA_SHLVL")
153+
explicit = self.env_vars()
154+
conda_unset = {var: None for var in conda_vars if var not in explicit}
155+
return (
156+
self.service(python_exes, *python_args)
157+
.syntax(PythonSyntax())
158+
.env(**conda_unset)
159+
)
150160

151161
def groovy(
152162
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)