isolate 0.26.6__tar.gz → 0.26.8__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.
Files changed (95) hide show
  1. {isolate-0.26.6 → isolate-0.26.8}/.github/workflows/test.yml +2 -2
  2. {isolate-0.26.6/src/isolate.egg-info → isolate-0.26.8}/PKG-INFO +1 -1
  3. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/_isolate_version.py +3 -3
  4. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/connections/common.py +36 -11
  5. {isolate-0.26.6 → isolate-0.26.8/src/isolate.egg-info}/PKG-INFO +1 -1
  6. {isolate-0.26.6 → isolate-0.26.8}/tests/test_backends.py +1 -0
  7. {isolate-0.26.6 → isolate-0.26.8}/tests/test_serialization.py +37 -0
  8. {isolate-0.26.6 → isolate-0.26.8}/.github/workflows/claude-code-review.yml +0 -0
  9. {isolate-0.26.6 → isolate-0.26.8}/.github/workflows/claude.yml +0 -0
  10. {isolate-0.26.6 → isolate-0.26.8}/.github/workflows/lint.yml +0 -0
  11. {isolate-0.26.6 → isolate-0.26.8}/.github/workflows/release.yml +0 -0
  12. {isolate-0.26.6 → isolate-0.26.8}/.gitignore +0 -0
  13. {isolate-0.26.6 → isolate-0.26.8}/.pre-commit-config.yaml +0 -0
  14. {isolate-0.26.6 → isolate-0.26.8}/LICENSE +0 -0
  15. {isolate-0.26.6 → isolate-0.26.8}/README.md +0 -0
  16. {isolate-0.26.6 → isolate-0.26.8}/pyproject.toml +0 -0
  17. {isolate-0.26.6 → isolate-0.26.8}/setup.cfg +0 -0
  18. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/__init__.py +0 -0
  19. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/_version.py +0 -0
  20. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/backends/__init__.py +0 -0
  21. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/backends/_base.py +0 -0
  22. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/backends/common.py +0 -0
  23. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/backends/conda.py +0 -0
  24. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/backends/container.py +0 -0
  25. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/backends/local.py +0 -0
  26. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/backends/pyenv.py +0 -0
  27. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/backends/remote.py +0 -0
  28. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/backends/settings.py +0 -0
  29. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/backends/virtualenv.py +0 -0
  30. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/common/__init__.py +0 -0
  31. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/common/timestamp.py +0 -0
  32. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/connections/__init__.py +0 -0
  33. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/connections/_local/__init__.py +0 -0
  34. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/connections/_local/_base.py +0 -0
  35. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/connections/_local/agent_startup.py +0 -0
  36. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/connections/grpc/__init__.py +0 -0
  37. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/connections/grpc/_base.py +0 -0
  38. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/connections/grpc/agent.py +0 -0
  39. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/connections/grpc/configuration.py +0 -0
  40. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/connections/grpc/definitions/__init__.py +0 -0
  41. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/connections/grpc/definitions/agent.proto +0 -0
  42. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/connections/grpc/definitions/agent_pb2.py +0 -0
  43. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/connections/grpc/definitions/agent_pb2.pyi +0 -0
  44. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/connections/grpc/definitions/agent_pb2_grpc.py +0 -0
  45. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/connections/grpc/definitions/common.proto +0 -0
  46. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/connections/grpc/definitions/common_pb2.py +0 -0
  47. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/connections/grpc/definitions/common_pb2.pyi +0 -0
  48. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/connections/grpc/definitions/common_pb2_grpc.py +0 -0
  49. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/connections/grpc/interface.py +0 -0
  50. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/connections/ipc/__init__.py +0 -0
  51. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/connections/ipc/_base.py +0 -0
  52. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/connections/ipc/agent.py +0 -0
  53. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/logger.py +0 -0
  54. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/logs.py +0 -0
  55. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/py.typed +0 -0
  56. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/registry.py +0 -0
  57. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/server/__init__.py +0 -0
  58. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/server/definitions/__init__.py +0 -0
  59. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/server/definitions/server.proto +0 -0
  60. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/server/definitions/server_pb2.py +0 -0
  61. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/server/definitions/server_pb2.pyi +0 -0
  62. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/server/definitions/server_pb2_grpc.py +0 -0
  63. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/server/health/__init__.py +0 -0
  64. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/server/health/health.proto +0 -0
  65. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/server/health/health_pb2.py +0 -0
  66. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/server/health/health_pb2.pyi +0 -0
  67. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/server/health/health_pb2_grpc.py +0 -0
  68. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/server/health_server.py +0 -0
  69. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/server/interface.py +0 -0
  70. {isolate-0.26.6 → isolate-0.26.8}/src/isolate/server/server.py +0 -0
  71. {isolate-0.26.6 → isolate-0.26.8}/src/isolate.egg-info/SOURCES.txt +0 -0
  72. {isolate-0.26.6 → isolate-0.26.8}/src/isolate.egg-info/dependency_links.txt +0 -0
  73. {isolate-0.26.6 → isolate-0.26.8}/src/isolate.egg-info/entry_points.txt +0 -0
  74. {isolate-0.26.6 → isolate-0.26.8}/src/isolate.egg-info/requires.txt +0 -0
  75. {isolate-0.26.6 → isolate-0.26.8}/src/isolate.egg-info/top_level.txt +0 -0
  76. {isolate-0.26.6 → isolate-0.26.8}/tests/__init__.py +0 -0
  77. {isolate-0.26.6 → isolate-0.26.8}/tests/conftest.py +0 -0
  78. {isolate-0.26.6 → isolate-0.26.8}/tests/test_agent_backward_compatibility.py +0 -0
  79. {isolate-0.26.6 → isolate-0.26.8}/tests/test_concurrency.py +0 -0
  80. {isolate-0.26.6 → isolate-0.26.8}/tests/test_connections.py +0 -0
  81. {isolate-0.26.6 → isolate-0.26.8}/tests/test_connections_grpc_base.py +0 -0
  82. {isolate-0.26.6 → isolate-0.26.8}/tests/test_isolate.py +0 -0
  83. {isolate-0.26.6 → isolate-0.26.8}/tests/test_log.py +0 -0
  84. {isolate-0.26.6 → isolate-0.26.8}/tests/test_log_masking.py +0 -0
  85. {isolate-0.26.6 → isolate-0.26.8}/tests/test_logged_io_pipe.py +0 -0
  86. {isolate-0.26.6 → isolate-0.26.8}/tests/test_logger.py +0 -0
  87. {isolate-0.26.6 → isolate-0.26.8}/tests/test_server.py +0 -0
  88. {isolate-0.26.6 → isolate-0.26.8}/tests/test_shutdown.py +0 -0
  89. {isolate-0.26.6 → isolate-0.26.8}/tools/Dockerfile +0 -0
  90. {isolate-0.26.6 → isolate-0.26.8}/tools/agent_requirements.txt +0 -0
  91. {isolate-0.26.6 → isolate-0.26.8}/tools/isolate_client.py +0 -0
  92. {isolate-0.26.6 → isolate-0.26.8}/tools/protobuf-requirements.txt +0 -0
  93. {isolate-0.26.6 → isolate-0.26.8}/tools/regen_grpc.py +0 -0
  94. {isolate-0.26.6 → isolate-0.26.8}/tools/requirements.txt +0 -0
  95. {isolate-0.26.6 → isolate-0.26.8}/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.11"
30
+ python: "3.14"
31
31
  steps:
32
32
  - uses: actions/checkout@v3
33
33
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: isolate
3
- Version: 0.26.6
3
+ Version: 0.26.8
4
4
  Summary: Managed isolated environments for Python
5
5
  Author-email: Features & Labels <hello@fal.ai>
6
6
  Project-URL: Issues, https://github.com/fal-ai/isolate/issues
@@ -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.6'
32
- __version_tuple__ = version_tuple = (0, 26, 6)
31
+ __version__ = version = '0.26.8'
32
+ __version_tuple__ = version_tuple = (0, 26, 8)
33
33
 
34
- __commit_id__ = commit_id = 'g6d4ff5277'
34
+ __commit_id__ = commit_id = 'ge1f994002'
@@ -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,15 @@ 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
+ original_stringized_traceback: str | None
39
+
40
+
31
41
  # NOTE: tblib's install() will search for BaseException subclasses,
32
42
  # so we have to call it after the SerializationError is defined.
33
43
  tblib_install()
@@ -77,8 +87,22 @@ def load_serialized_object(
77
87
  importlib.import_module(serialization_method)
78
88
  )
79
89
 
80
- with _step("deserializing the given object"):
81
- result = serialization_backend.loads(raw_object)
90
+ try:
91
+ with _step("deserializing the given object"):
92
+ result = serialization_backend.loads(raw_object)
93
+ except SerializationError as exc:
94
+ if was_it_raised:
95
+ # We were trying to reconstruct a remote exception but its type
96
+ # isn't importable here, so loads() failed. Surface the genuine
97
+ # local cause along with the remote traceback.
98
+ # Keep both traceback forms: Traceback.from_string() preserves
99
+ # frames, while the string also includes the exception type/message.
100
+ raise ExceptionDeserializationError(
101
+ exc.message,
102
+ original_traceback=_prepare_traceback(stringized_traceback),
103
+ original_stringized_traceback=stringized_traceback,
104
+ ) from exc.__cause__
105
+ raise
82
106
 
83
107
  if was_it_raised:
84
108
  raise prepare_exc(result, stringized_traceback=stringized_traceback)
@@ -111,18 +135,19 @@ def validate_entrypoint(entrypoint: str) -> None:
111
135
  raise ValueError(f"Invalid entrypoint {entrypoint!r}: expected 'module:attr'.")
112
136
 
113
137
 
138
+ def _prepare_traceback(stringized_traceback: str | None) -> TracebackType | None:
139
+ if stringized_traceback:
140
+ try:
141
+ return Traceback.from_string(stringized_traceback).as_traceback()
142
+ except TracebackParseError:
143
+ pass
144
+ return None
145
+
146
+
114
147
  def prepare_exc(
115
148
  exc: BaseException,
116
149
  *,
117
150
  stringized_traceback: str | None = None,
118
151
  ) -> BaseException:
119
- if stringized_traceback:
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
152
+ exc.__traceback__ = _prepare_traceback(stringized_traceback)
128
153
  return exc
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: isolate
3
- Version: 0.26.6
3
+ Version: 0.26.8
4
4
  Summary: Managed isolated environments for Python
5
5
  Author-email: Features & Labels <hello@fal.ai>
6
6
  Project-URL: Issues, https://github.com/fal-ai/isolate/issues
@@ -555,6 +555,7 @@ class TestConda(GenericEnvironmentTests):
555
555
  "packages": [],
556
556
  },
557
557
  "black": {
558
+ "python_version": "3.11",
558
559
  "packages": ["black=22.12.0"],
559
560
  },
560
561
  "old-python": {
@@ -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,39 @@ 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 exc_info.value.original_stringized_traceback == stringized_traceback
74
+ assert isinstance(exc_info.value.__cause__, ModuleNotFoundError)
75
+
76
+
40
77
  def error_while_serializing():
41
78
  anon = lambda: 2 + 2 # anonymous functions are not # noqa: E731
42
79
  # 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