Skip to content

Commit 357171e

Browse files
authored
Merge pull request #5 from pollockjj/pr4
PR4: SHM leak fixes, sandbox detection, 0.9.1 release prep
2 parents efdbc61 + 495c7f0 commit 357171e

22 files changed

Lines changed: 426 additions & 149 deletions

.coderabbit.yaml

Lines changed: 0 additions & 81 deletions
This file was deleted.

.github/workflows/ci.yml

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,6 @@ jobs:
5757
fail-fast: false
5858
matrix:
5959
include:
60-
- container: debian:11
61-
python-install: |
62-
apt-get update && apt-get install -y python3 python3-pip python3-venv git curl bubblewrap
63-
extras: "dev,test"
6460
- container: debian:12
6561
python-install: |
6662
apt-get update && apt-get install -y python3 python3-pip python3-venv git curl bubblewrap
@@ -73,10 +69,6 @@ jobs:
7369
python-install: |
7470
dnf install -y python3 python3-pip git curl bubblewrap
7571
extras: "dev,test"
76-
- container: rockylinux:9
77-
python-install: |
78-
dnf install -y python3 python3-pip git bubblewrap
79-
extras: "dev,test"
8072

8173
container: ${{ matrix.container }}
8274

@@ -92,7 +84,7 @@ jobs:
9284
9385
- name: Install package
9486
run: |
95-
$HOME/.local/bin/uv venv
87+
$HOME/.local/bin/uv venv --python python3
9688
. .venv/bin/activate
9789
$HOME/.local/bin/uv pip install -e ".[${{ matrix.extras }}]"
9890

.github/workflows/docs.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,10 @@ jobs:
4848
url: ${{ steps.deployment.outputs.page_url }}
4949
runs-on: ubuntu-latest
5050
needs: build
51-
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
51+
if: >-
52+
github.repository == 'Comfy-Org/pyisolate' &&
53+
github.event_name == 'push' &&
54+
github.ref == 'refs/heads/main'
5255
steps:
5356
- name: Deploy to GitHub Pages
5457
id: deployment

.github/workflows/pytorch.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ jobs:
4141
- name: Run tests
4242
run: |
4343
source .venv/bin/activate
44-
pytest tests/test_integration.py -v -k "torch"
44+
pytest tests/integration_v2/test_tensors.py tests/test_torch_optional_contract.py tests/test_torch_utils_additional.py -v
4545
4646
- name: Test example with PyTorch
4747
run: |
@@ -100,7 +100,7 @@ jobs:
100100
- name: Run tests
101101
run: |
102102
source .venv/bin/activate
103-
pytest tests/test_integration.py -v -k "torch"
103+
pytest tests/integration_v2/test_tensors.py tests/test_torch_optional_contract.py tests/test_torch_utils_additional.py -v
104104
105105
- name: Test example with PyTorch
106106
run: |

.github/workflows/windows.yml

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ jobs:
5050
strategy:
5151
fail-fast: false
5252
matrix:
53-
pytorch-version: ['2.1.0', '2.3.0']
53+
pytorch-version: ['2.1.0']
5454

5555
steps:
5656
- uses: actions/checkout@v4
@@ -78,8 +78,4 @@ jobs:
7878
- name: Run PyTorch tests
7979
run: |
8080
.venv\Scripts\activate
81-
python tests/test_integration.py -v
82-
python tests/test_edge_cases.py -v
83-
python tests/test_normalization_integration.py -v
84-
python tests/test_security.py -v
85-
python tests/test_torch_tensor_integration.py -v
81+
pytest tests/integration_v2/test_tensors.py tests/test_torch_optional_contract.py tests/test_torch_utils_additional.py -v

MANIFEST.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@ include README.md
33
include pyproject.toml
44
recursive-include pyisolate *.py
55
recursive-include tests *.py
6+
prune tests/.test_temps
67
recursive-exclude * __pycache__
78
recursive-exclude * *.py[co]

docs/conf.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
copyright = "2026, Jacob Segal"
1616
author = "Jacob Segal"
1717

18-
version = "0.9.0"
19-
release = "0.9.0"
18+
version = "0.9.1"
19+
release = "0.9.1"
2020

2121
# -- General configuration ---------------------------------------------------
2222
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration

example/host.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import argparse
22
import asyncio
3+
import inspect
34
import logging
45
import os
56
import sys
@@ -9,6 +10,7 @@
910
from shared import DatabaseSingleton, ExampleExtensionBase
1011

1112
import pyisolate
13+
from pyisolate._internal.sandbox_detect import detect_sandbox_capability
1214

1315

1416
# ANSI color codes for terminal output (using 256-color mode for better compatibility)
@@ -47,6 +49,16 @@ async def async_main():
4749
config = pyisolate.ExtensionManagerConfig(venv_root_path=os.path.join(base_path, "extension-venvs"))
4850
manager = pyisolate.ExtensionManager(ExampleExtensionBase, config)
4951

52+
sandbox_mode = pyisolate.SandboxMode.REQUIRED
53+
if sys.platform == "linux":
54+
cap = detect_sandbox_capability()
55+
if not cap.available:
56+
sandbox_mode = pyisolate.SandboxMode.DISABLED
57+
logger.warning(
58+
"Sandbox unavailable in example environment (%s); using sandbox_mode=disabled",
59+
cap.restriction_model,
60+
)
61+
5062
extensions: list[ExampleExtensionBase] = []
5163
extension_dir = os.path.join(base_path, "extensions")
5264
for extension in os.listdir(extension_dir):
@@ -85,6 +97,7 @@ class CustomConfig(TypedDict):
8597
dependencies=manifest["dependencies"] + pyisolate_install,
8698
apis=[DatabaseSingleton],
8799
share_torch=manifest["share_torch"],
100+
sandbox_mode=sandbox_mode,
88101
)
89102

90103
extension = manager.load_extension(config)
@@ -118,12 +131,7 @@ class CustomConfig(TypedDict):
118131

119132
# Test Extension 2
120133
ext2_result = await db.get_value("extension2_result")
121-
if (
122-
ext2_result
123-
and ext2_result.get("extension") == "extension2"
124-
and ext2_result.get("array_sum") == 17.5
125-
and ext2_result.get("numpy_version").startswith("2.")
126-
):
134+
if ext2_result and ext2_result.get("extension") == "extension2" and ext2_result.get("array_sum") == 17.5:
127135
test_results.append(("Extension2", "PASSED", "Array processing with numpy 2.x"))
128136
logger.debug(f"Extension2 result: {ext2_result}")
129137
else:
@@ -169,7 +177,9 @@ class CustomConfig(TypedDict):
169177
# Shutdown extensions
170178
logger.debug("Shutting down extensions...")
171179
for extension in extensions:
172-
await extension.stop()
180+
stop_result = extension.stop()
181+
if inspect.isawaitable(stop_result):
182+
await stop_result
173183

174184
# Exit with appropriate code
175185
if failed_tests > 0:

pyisolate/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,14 @@
3636

3737
from ._internal.rpc_protocol import ProxiedSingleton, local_execution
3838
from ._internal.singleton_context import singleton_scope
39+
from ._internal.tensor_serializer import flush_tensor_keeper, purge_orphan_sender_shm_files
3940
from .config import ExtensionConfig, ExtensionManagerConfig, SandboxMode
4041
from .host import ExtensionBase, ExtensionManager
4142

4243
if TYPE_CHECKING:
4344
from .interfaces import IsolationAdapter
4445

45-
__version__ = "0.9.0"
46+
__version__ = "0.9.1"
4647

4748
__all__ = [
4849
"ExtensionBase",
@@ -53,6 +54,8 @@
5354
"ProxiedSingleton",
5455
"local_execution",
5556
"singleton_scope",
57+
"flush_tensor_keeper",
58+
"purge_orphan_sender_shm_files",
5659
"register_adapter",
5760
"get_adapter",
5861
]

pyisolate/_internal/environment.py

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -173,9 +173,20 @@ def exclude_satisfied_requirements(
173173
"""
174174
from packaging.requirements import Requirement
175175

176-
result = subprocess.run( # noqa: S603 # Trusted: system pip executable
177-
[str(python_exe), "-m", "pip", "list", "--format", "json"], capture_output=True, text=True, check=True
178-
)
176+
try:
177+
result = subprocess.run( # noqa: S603 # Trusted: system pip executable
178+
[str(python_exe), "-m", "pip", "list", "--format", "json"],
179+
capture_output=True,
180+
text=True,
181+
check=True,
182+
)
183+
except subprocess.CalledProcessError as exc:
184+
# Newer uv versions can create venvs without pip unless seeded.
185+
# If pip is unavailable, skip filtering and install requested deps.
186+
if "No module named pip" in (exc.stderr or ""):
187+
logger.debug("pip unavailable in %s; skipping satisfied-requirement filter", python_exe)
188+
return requirements
189+
raise
179190
installed = {pkg["name"].lower(): pkg["version"] for pkg in json.loads(result.stdout)}
180191
torch_ecosystem = get_torch_ecosystem_packages()
181192

@@ -227,6 +238,7 @@ def create_venv(venv_path: Path, config: ExtensionConfig) -> None:
227238
uv_path,
228239
"venv",
229240
str(venv_path),
241+
"--seed",
230242
"--python",
231243
sys.executable,
232244
]
@@ -337,7 +349,34 @@ def install_dependencies(venv_path: Path, config: ExtensionConfig, name: str) ->
337349
except Exception as exc:
338350
logger.debug("Dependency cache read failed: %s", exc)
339351

340-
cmd = cmd_prefix + safe_deps + common_args
352+
install_targets: list[str] = []
353+
i = 0
354+
while i < len(safe_deps):
355+
dep = safe_deps[i]
356+
dep_stripped = dep.strip()
357+
358+
# Support split editable args from existing callers:
359+
# ["-e", "/path/to/pkg"].
360+
if dep_stripped == "-e":
361+
if i + 1 >= len(safe_deps):
362+
raise ValueError("Editable dependency '-e' must include a path or URL")
363+
editable_target = safe_deps[i + 1].strip()
364+
if not editable_target:
365+
raise ValueError("Editable dependency '-e' must include a path or URL")
366+
install_targets.extend(["-e", editable_target])
367+
i += 2
368+
continue
369+
370+
if dep_stripped.startswith("-e "):
371+
editable_target = dep_stripped[3:].strip()
372+
if not editable_target:
373+
raise ValueError("Editable dependency must include a path or URL after '-e'")
374+
install_targets.extend(["-e", editable_target])
375+
else:
376+
install_targets.append(dep)
377+
i += 1
378+
379+
cmd = cmd_prefix + install_targets + common_args
341380

342381
with subprocess.Popen( # noqa: S603 # Trusted: validated pip/uv install cmd
343382
cmd,

0 commit comments

Comments
 (0)