isolate 0.26.6__tar.gz → 0.26.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {isolate-0.26.6 → isolate-0.26.7}/.github/workflows/test.yml +2 -2
- {isolate-0.26.6/src/isolate.egg-info → isolate-0.26.7}/PKG-INFO +1 -1
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/_isolate_version.py +3 -3
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/connections/common.py +32 -11
- {isolate-0.26.6 → isolate-0.26.7/src/isolate.egg-info}/PKG-INFO +1 -1
- {isolate-0.26.6 → isolate-0.26.7}/tests/test_backends.py +1 -0
- {isolate-0.26.6 → isolate-0.26.7}/tests/test_serialization.py +36 -0
- {isolate-0.26.6 → isolate-0.26.7}/.github/workflows/claude-code-review.yml +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/.github/workflows/claude.yml +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/.github/workflows/lint.yml +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/.github/workflows/release.yml +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/.gitignore +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/.pre-commit-config.yaml +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/LICENSE +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/README.md +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/pyproject.toml +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/setup.cfg +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/__init__.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/_version.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/backends/__init__.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/backends/_base.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/backends/common.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/backends/conda.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/backends/container.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/backends/local.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/backends/pyenv.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/backends/remote.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/backends/settings.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/backends/virtualenv.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/common/__init__.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/common/timestamp.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/connections/__init__.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/connections/_local/__init__.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/connections/_local/_base.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/connections/_local/agent_startup.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/connections/grpc/__init__.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/connections/grpc/_base.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/connections/grpc/agent.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/connections/grpc/configuration.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/connections/grpc/definitions/__init__.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/connections/grpc/definitions/agent.proto +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/connections/grpc/definitions/agent_pb2.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/connections/grpc/definitions/agent_pb2.pyi +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/connections/grpc/definitions/agent_pb2_grpc.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/connections/grpc/definitions/common.proto +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/connections/grpc/definitions/common_pb2.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/connections/grpc/definitions/common_pb2.pyi +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/connections/grpc/definitions/common_pb2_grpc.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/connections/grpc/interface.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/connections/ipc/__init__.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/connections/ipc/_base.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/connections/ipc/agent.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/logger.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/logs.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/py.typed +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/registry.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/server/__init__.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/server/definitions/__init__.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/server/definitions/server.proto +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/server/definitions/server_pb2.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/server/definitions/server_pb2.pyi +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/server/definitions/server_pb2_grpc.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/server/health/__init__.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/server/health/health.proto +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/server/health/health_pb2.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/server/health/health_pb2.pyi +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/server/health/health_pb2_grpc.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/server/health_server.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/server/interface.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate/server/server.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate.egg-info/SOURCES.txt +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate.egg-info/dependency_links.txt +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate.egg-info/entry_points.txt +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate.egg-info/requires.txt +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/src/isolate.egg-info/top_level.txt +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/tests/__init__.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/tests/conftest.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/tests/test_agent_backward_compatibility.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/tests/test_concurrency.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/tests/test_connections.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/tests/test_connections_grpc_base.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/tests/test_isolate.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/tests/test_log.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/tests/test_log_masking.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/tests/test_logged_io_pipe.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/tests/test_logger.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/tests/test_server.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/tests/test_shutdown.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/tools/Dockerfile +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/tools/agent_requirements.txt +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/tools/isolate_client.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/tools/protobuf-requirements.txt +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/tools/regen_grpc.py +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/tools/requirements.txt +0 -0
- {isolate-0.26.6 → isolate-0.26.7}/tools/test_agent_requirements.txt +0 -0
|
@@ -22,12 +22,12 @@ jobs:
|
|
|
22
22
|
|
|
23
23
|
matrix:
|
|
24
24
|
os: [ubuntu-latest]
|
|
25
|
-
python: ["3.8", "3.9", "3.10", "3.11"]
|
|
25
|
+
python: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
|
|
26
26
|
include:
|
|
27
27
|
- os: macos-15-intel
|
|
28
28
|
python: "3.8"
|
|
29
29
|
- os: macos-15-intel
|
|
30
|
-
python: "3.
|
|
30
|
+
python: "3.14"
|
|
31
31
|
steps:
|
|
32
32
|
- uses: actions/checkout@v3
|
|
33
33
|
|
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '0.26.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 26,
|
|
31
|
+
__version__ = version = '0.26.7'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 26, 7)
|
|
33
33
|
|
|
34
|
-
__commit_id__ = commit_id = '
|
|
34
|
+
__commit_id__ = commit_id = 'g9b3604b86'
|
|
@@ -4,6 +4,7 @@ import importlib
|
|
|
4
4
|
import os
|
|
5
5
|
from contextlib import contextmanager
|
|
6
6
|
from dataclasses import dataclass
|
|
7
|
+
from types import TracebackType
|
|
7
8
|
from typing import TYPE_CHECKING, Any, Iterator, cast
|
|
8
9
|
|
|
9
10
|
from tblib import Traceback, TracebackParseError
|
|
@@ -28,6 +29,14 @@ class SerializationError(Exception):
|
|
|
28
29
|
message: str
|
|
29
30
|
|
|
30
31
|
|
|
32
|
+
@dataclass
|
|
33
|
+
class ExceptionDeserializationError(SerializationError):
|
|
34
|
+
"""Raised when a remote exception cannot be deserialized locally (e.g. the
|
|
35
|
+
module that defines its type isn't importable here)."""
|
|
36
|
+
|
|
37
|
+
original_traceback: TracebackType | None
|
|
38
|
+
|
|
39
|
+
|
|
31
40
|
# NOTE: tblib's install() will search for BaseException subclasses,
|
|
32
41
|
# so we have to call it after the SerializationError is defined.
|
|
33
42
|
tblib_install()
|
|
@@ -77,8 +86,19 @@ def load_serialized_object(
|
|
|
77
86
|
importlib.import_module(serialization_method)
|
|
78
87
|
)
|
|
79
88
|
|
|
80
|
-
|
|
81
|
-
|
|
89
|
+
try:
|
|
90
|
+
with _step("deserializing the given object"):
|
|
91
|
+
result = serialization_backend.loads(raw_object)
|
|
92
|
+
except SerializationError as exc:
|
|
93
|
+
if was_it_raised:
|
|
94
|
+
# We were trying to reconstruct a remote exception but its type
|
|
95
|
+
# isn't importable here, so loads() failed. Surface the genuine
|
|
96
|
+
# local cause along with the remote traceback.
|
|
97
|
+
raise ExceptionDeserializationError(
|
|
98
|
+
exc.message,
|
|
99
|
+
original_traceback=_prepare_traceback(stringized_traceback),
|
|
100
|
+
) from exc.__cause__
|
|
101
|
+
raise
|
|
82
102
|
|
|
83
103
|
if was_it_raised:
|
|
84
104
|
raise prepare_exc(result, stringized_traceback=stringized_traceback)
|
|
@@ -111,18 +131,19 @@ def validate_entrypoint(entrypoint: str) -> None:
|
|
|
111
131
|
raise ValueError(f"Invalid entrypoint {entrypoint!r}: expected 'module:attr'.")
|
|
112
132
|
|
|
113
133
|
|
|
134
|
+
def _prepare_traceback(stringized_traceback: str | None) -> TracebackType | None:
|
|
135
|
+
if stringized_traceback:
|
|
136
|
+
try:
|
|
137
|
+
return Traceback.from_string(stringized_traceback).as_traceback()
|
|
138
|
+
except TracebackParseError:
|
|
139
|
+
pass
|
|
140
|
+
return None
|
|
141
|
+
|
|
142
|
+
|
|
114
143
|
def prepare_exc(
|
|
115
144
|
exc: BaseException,
|
|
116
145
|
*,
|
|
117
146
|
stringized_traceback: str | None = None,
|
|
118
147
|
) -> BaseException:
|
|
119
|
-
|
|
120
|
-
try:
|
|
121
|
-
traceback = Traceback.from_string(stringized_traceback).as_traceback()
|
|
122
|
-
except TracebackParseError:
|
|
123
|
-
traceback = None
|
|
124
|
-
else:
|
|
125
|
-
traceback = None
|
|
126
|
-
|
|
127
|
-
exc.__traceback__ = traceback
|
|
148
|
+
exc.__traceback__ = _prepare_traceback(stringized_traceback)
|
|
128
149
|
return exc
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
import importlib
|
|
2
|
+
import sys
|
|
3
|
+
import traceback
|
|
1
4
|
from functools import partial
|
|
2
5
|
|
|
3
6
|
import pytest
|
|
4
7
|
from isolate.connections.common import (
|
|
8
|
+
ExceptionDeserializationError,
|
|
5
9
|
SerializationError,
|
|
6
10
|
load_serialized_object,
|
|
7
11
|
serialize_object,
|
|
@@ -37,6 +41,38 @@ def test_deserialize_raised_exception():
|
|
|
37
41
|
assert exc_info.value.args == ("some error",)
|
|
38
42
|
|
|
39
43
|
|
|
44
|
+
def test_deserialize_raised_exception_with_unimportable_type_preserves_traceback(
|
|
45
|
+
tmp_path,
|
|
46
|
+
monkeypatch,
|
|
47
|
+
):
|
|
48
|
+
module_name = "remote_only_exc_for_isolate_test"
|
|
49
|
+
module_path = tmp_path / f"{module_name}.py"
|
|
50
|
+
module_path.write_text("class RemoteOnlyError(Exception):\n pass\n")
|
|
51
|
+
monkeypatch.syspath_prepend(str(tmp_path))
|
|
52
|
+
remote_module = importlib.import_module(module_name)
|
|
53
|
+
|
|
54
|
+
try:
|
|
55
|
+
raise remote_module.RemoteOnlyError("remote boom")
|
|
56
|
+
except remote_module.RemoteOnlyError as exc:
|
|
57
|
+
serialized = serialize_object("pickle", exc)
|
|
58
|
+
stringized_traceback = traceback.format_exc()
|
|
59
|
+
|
|
60
|
+
sys.modules.pop(module_name, None)
|
|
61
|
+
sys.path.remove(str(tmp_path))
|
|
62
|
+
|
|
63
|
+
with pytest.raises(ExceptionDeserializationError) as exc_info:
|
|
64
|
+
load_serialized_object(
|
|
65
|
+
"pickle",
|
|
66
|
+
serialized,
|
|
67
|
+
was_it_raised=True,
|
|
68
|
+
stringized_traceback=stringized_traceback,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
assert exc_info.value.message == "Error while deserializing the given object"
|
|
72
|
+
assert exc_info.value.original_traceback is not None
|
|
73
|
+
assert isinstance(exc_info.value.__cause__, ModuleNotFoundError)
|
|
74
|
+
|
|
75
|
+
|
|
40
76
|
def error_while_serializing():
|
|
41
77
|
anon = lambda: 2 + 2 # anonymous functions are not # noqa: E731
|
|
42
78
|
# serializable by pickle
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{isolate-0.26.6 → isolate-0.26.7}/src/isolate/connections/grpc/definitions/agent_pb2_grpc.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{isolate-0.26.6 → isolate-0.26.7}/src/isolate/connections/grpc/definitions/common_pb2_grpc.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|