isolate 0.12.13__tar.gz → 0.12.15__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.
Potentially problematic release.
This version of isolate might be problematic. Click here for more details.
- {isolate-0.12.13 → isolate-0.12.15}/PKG-INFO +1 -1
- {isolate-0.12.13 → isolate-0.12.15}/pyproject.toml +1 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/_isolate_version.py +2 -2
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/backends/_base.py +1 -2
- isolate-0.12.15/src/isolate/backends/container.py +49 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/connections/common.py +17 -28
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/connections/grpc/_base.py +1 -2
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/connections/grpc/agent.py +7 -5
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate.egg-info/PKG-INFO +1 -1
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate.egg-info/SOURCES.txt +1 -1
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate.egg-info/entry_points.txt +1 -0
- isolate-0.12.13/src/isolate/exceptions.py +0 -2
- {isolate-0.12.13 → isolate-0.12.15}/.github/workflows/release.yml +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/.github/workflows/test.yml +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/.gitignore +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/.pre-commit-config.yaml +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/LICENSE +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/README.md +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/setup.cfg +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/__init__.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/_version.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/backends/__init__.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/backends/common.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/backends/conda.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/backends/local.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/backends/pyenv.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/backends/remote.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/backends/settings.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/backends/virtualenv.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/common/__init__.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/common/timestamp.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/connections/__init__.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/connections/_local/__init__.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/connections/_local/_base.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/connections/_local/agent_startup.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/connections/grpc/__init__.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/connections/grpc/configuration.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/connections/grpc/definitions/__init__.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/connections/grpc/definitions/agent.proto +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/connections/grpc/definitions/agent_pb2.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/connections/grpc/definitions/agent_pb2.pyi +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/connections/grpc/definitions/agent_pb2_grpc.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/connections/grpc/definitions/common.proto +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/connections/grpc/definitions/common_pb2.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/connections/grpc/definitions/common_pb2.pyi +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/connections/grpc/definitions/common_pb2_grpc.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/connections/grpc/interface.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/connections/ipc/__init__.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/connections/ipc/_base.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/connections/ipc/agent.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/logs.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/py.typed +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/registry.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/server/__init__.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/server/definitions/__init__.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/server/definitions/server.proto +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/server/definitions/server_pb2.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/server/definitions/server_pb2.pyi +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/server/definitions/server_pb2_grpc.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/server/health/__init__.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/server/health/health.proto +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/server/health/health_pb2.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/server/health/health_pb2.pyi +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/server/health/health_pb2_grpc.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/server/health_server.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/server/interface.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate/server/server.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate.egg-info/dependency_links.txt +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate.egg-info/requires.txt +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/src/isolate.egg-info/top_level.txt +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/tests/__init__.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/tests/conftest.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/tests/test_backends.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/tests/test_concurrency.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/tests/test_connections.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/tests/test_isolate.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/tests/test_log.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/tests/test_serialization.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/tests/test_server.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/tools/Dockerfile +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/tools/agent_requirements.txt +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/tools/protobuf-requirements.txt +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/tools/regen_grpc.py +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/tools/requirements.txt +0 -0
- {isolate-0.12.13 → isolate-0.12.15}/tools/test_agent_requirements.txt +0 -0
|
@@ -56,6 +56,7 @@ dev = [
|
|
|
56
56
|
"virtualenv" = "isolate.backends.virtualenv:VirtualPythonEnvironment"
|
|
57
57
|
"conda" = "isolate.backends.conda:CondaEnvironment"
|
|
58
58
|
"local" = "isolate.backends.local:LocalPythonEnvironment"
|
|
59
|
+
"container" = "isolate.backends.container:ContainerizedPythonEnvironment"
|
|
59
60
|
"isolate-server" = "isolate.backends.remote:IsolateServer"
|
|
60
61
|
"pyenv" = "isolate.backends.pyenv:PyenvEnvironment"
|
|
61
62
|
|
|
@@ -12,7 +12,6 @@ from typing import (
|
|
|
12
12
|
)
|
|
13
13
|
|
|
14
14
|
from isolate.backends.settings import DEFAULT_SETTINGS, IsolateSettings
|
|
15
|
-
from isolate.exceptions import IsolateException
|
|
16
15
|
from isolate.logs import Log, LogLevel, LogSource
|
|
17
16
|
|
|
18
17
|
__all__ = [
|
|
@@ -28,7 +27,7 @@ CallResultType = TypeVar("CallResultType")
|
|
|
28
27
|
BasicCallable = Callable[[], CallResultType]
|
|
29
28
|
|
|
30
29
|
|
|
31
|
-
class EnvironmentCreationError(
|
|
30
|
+
class EnvironmentCreationError(Exception):
|
|
32
31
|
"""Raised when the environment cannot be created."""
|
|
33
32
|
|
|
34
33
|
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
from dataclasses import dataclass, field
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any, ClassVar
|
|
7
|
+
|
|
8
|
+
from isolate.backends import BaseEnvironment
|
|
9
|
+
from isolate.backends.common import sha256_digest_of
|
|
10
|
+
from isolate.backends.settings import DEFAULT_SETTINGS, IsolateSettings
|
|
11
|
+
from isolate.connections import PythonIPC
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass
|
|
15
|
+
class ContainerizedPythonEnvironment(BaseEnvironment[Path]):
|
|
16
|
+
BACKEND_NAME: ClassVar[str] = "container"
|
|
17
|
+
|
|
18
|
+
image: dict[str, Any] = field(default_factory=dict)
|
|
19
|
+
python_version: str | None = None
|
|
20
|
+
tags: list[str] = field(default_factory=list)
|
|
21
|
+
|
|
22
|
+
@classmethod
|
|
23
|
+
def from_config(
|
|
24
|
+
cls,
|
|
25
|
+
config: dict[str, Any],
|
|
26
|
+
settings: IsolateSettings = DEFAULT_SETTINGS,
|
|
27
|
+
) -> BaseEnvironment:
|
|
28
|
+
environment = cls(**config)
|
|
29
|
+
environment.apply_settings(settings)
|
|
30
|
+
return environment
|
|
31
|
+
|
|
32
|
+
@property
|
|
33
|
+
def key(self) -> str:
|
|
34
|
+
# dockerfile_str is always there, but the validation is handled by the
|
|
35
|
+
# controller.
|
|
36
|
+
dockerfile_str = self.image.get("dockerfile_str", "")
|
|
37
|
+
return sha256_digest_of(dockerfile_str, *sorted(self.tags))
|
|
38
|
+
|
|
39
|
+
def create(self, *, force: bool = False) -> Path:
|
|
40
|
+
return Path(sys.exec_prefix)
|
|
41
|
+
|
|
42
|
+
def destroy(self, connection_key: Path) -> None:
|
|
43
|
+
raise NotImplementedError("ContainerizedPythonEnvironment cannot be destroyed")
|
|
44
|
+
|
|
45
|
+
def exists(self) -> bool:
|
|
46
|
+
return True
|
|
47
|
+
|
|
48
|
+
def open_connection(self, connection_key: Path) -> PythonIPC:
|
|
49
|
+
return PythonIPC(self, connection_key)
|
|
@@ -2,13 +2,12 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import importlib
|
|
4
4
|
import os
|
|
5
|
+
from contextlib import contextmanager
|
|
5
6
|
from dataclasses import dataclass
|
|
6
|
-
from typing import TYPE_CHECKING, Any, cast
|
|
7
|
+
from typing import TYPE_CHECKING, Any, Iterator, cast
|
|
7
8
|
|
|
8
9
|
from tblib import Traceback, TracebackParseError
|
|
9
10
|
|
|
10
|
-
from isolate.exceptions import IsolateException
|
|
11
|
-
|
|
12
11
|
if TYPE_CHECKING:
|
|
13
12
|
from typing import Protocol
|
|
14
13
|
|
|
@@ -22,18 +21,23 @@ AGENT_SIGNATURE = "IS_ISOLATE_AGENT"
|
|
|
22
21
|
|
|
23
22
|
|
|
24
23
|
@dataclass
|
|
25
|
-
class
|
|
24
|
+
class SerializationError(Exception):
|
|
26
25
|
"""An error that happened during the serialization process."""
|
|
27
26
|
|
|
28
27
|
message: str
|
|
29
28
|
|
|
30
29
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
@contextmanager
|
|
31
|
+
def _step(message: str) -> Iterator[None]:
|
|
32
|
+
"""A context manager to capture every expression
|
|
33
|
+
underneath it and if any of them fails for any reason
|
|
34
|
+
then it will raise a SerializationError with the
|
|
35
|
+
given message."""
|
|
34
36
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
+
try:
|
|
38
|
+
yield
|
|
39
|
+
except BaseException as exception:
|
|
40
|
+
raise SerializationError("Error while " + message) from exception
|
|
37
41
|
|
|
38
42
|
|
|
39
43
|
def as_serialization_method(backend: Any) -> SerializationBackend:
|
|
@@ -62,22 +66,13 @@ def load_serialized_object(
|
|
|
62
66
|
flag is set to true, then the given object will be raised as an exception (instead
|
|
63
67
|
of being returned)."""
|
|
64
68
|
|
|
65
|
-
|
|
69
|
+
with _step(f"preparing the serialization backend ({serialization_method})"):
|
|
66
70
|
serialization_backend = as_serialization_method(
|
|
67
71
|
importlib.import_module(serialization_method)
|
|
68
72
|
)
|
|
69
|
-
except BaseException as exc:
|
|
70
|
-
raise DeserializationError(
|
|
71
|
-
"Error while preparing the serialization backend "
|
|
72
|
-
f"({serialization_method})"
|
|
73
|
-
) from exc
|
|
74
73
|
|
|
75
|
-
|
|
74
|
+
with _step("deserializing the given object"):
|
|
76
75
|
result = serialization_backend.loads(raw_object)
|
|
77
|
-
except BaseException as exc:
|
|
78
|
-
raise DeserializationError(
|
|
79
|
-
"Error while deserializing the given object"
|
|
80
|
-
) from exc
|
|
81
76
|
|
|
82
77
|
if was_it_raised:
|
|
83
78
|
raise prepare_exc(result, stringized_traceback=stringized_traceback)
|
|
@@ -89,19 +84,13 @@ def serialize_object(serialization_method: str, object: Any) -> bytes:
|
|
|
89
84
|
"""Serialize the given object using the given serialization method. If
|
|
90
85
|
anything fails, then a SerializationError will be raised."""
|
|
91
86
|
|
|
92
|
-
|
|
87
|
+
with _step(f"preparing the serialization backend ({serialization_method})"):
|
|
93
88
|
serialization_backend = as_serialization_method(
|
|
94
89
|
importlib.import_module(serialization_method)
|
|
95
90
|
)
|
|
96
|
-
except BaseException as exc:
|
|
97
|
-
raise SerializationError(
|
|
98
|
-
f"Error while preparing the serialization backend ({serialization_method})"
|
|
99
|
-
) from exc
|
|
100
91
|
|
|
101
|
-
|
|
92
|
+
with _step("serializing the given object"):
|
|
102
93
|
return serialization_backend.dumps(object)
|
|
103
|
-
except BaseException as exc:
|
|
104
|
-
raise SerializationError("Error while serializing the given object") from exc
|
|
105
94
|
|
|
106
95
|
|
|
107
96
|
def is_agent() -> bool:
|
|
@@ -16,11 +16,10 @@ from isolate.connections.common import serialize_object
|
|
|
16
16
|
from isolate.connections.grpc import agent, definitions
|
|
17
17
|
from isolate.connections.grpc.configuration import get_default_options
|
|
18
18
|
from isolate.connections.grpc.interface import from_grpc
|
|
19
|
-
from isolate.exceptions import IsolateException
|
|
20
19
|
from isolate.logs import LogLevel, LogSource
|
|
21
20
|
|
|
22
21
|
|
|
23
|
-
class AgentError(
|
|
22
|
+
class AgentError(Exception):
|
|
24
23
|
"""An internal problem caused by (most probably) the agent."""
|
|
25
24
|
|
|
26
25
|
|
|
@@ -22,12 +22,11 @@ from isolate.connections.common import SerializationError, serialize_object
|
|
|
22
22
|
from isolate.connections.grpc import definitions
|
|
23
23
|
from isolate.connections.grpc.configuration import get_default_options
|
|
24
24
|
from isolate.connections.grpc.interface import from_grpc, to_grpc
|
|
25
|
-
from isolate.exceptions import IsolateException
|
|
26
25
|
from isolate.logs import Log, LogLevel, LogSource
|
|
27
26
|
|
|
28
27
|
|
|
29
28
|
@dataclass
|
|
30
|
-
class AbortException(
|
|
29
|
+
class AbortException(Exception):
|
|
31
30
|
message: str
|
|
32
31
|
|
|
33
32
|
|
|
@@ -107,11 +106,14 @@ class AgentServicer(definitions.AgentServicer):
|
|
|
107
106
|
)
|
|
108
107
|
|
|
109
108
|
try:
|
|
110
|
-
#
|
|
109
|
+
# TODO: technically any sort of exception could be raised here, since
|
|
111
110
|
# depickling is basically involves code execution from the *user*.
|
|
112
111
|
function = from_grpc(function)
|
|
113
|
-
except
|
|
114
|
-
|
|
112
|
+
except SerializationError:
|
|
113
|
+
yield from self.log(traceback.format_exc(), level=LogLevel.ERROR)
|
|
114
|
+
raise AbortException(
|
|
115
|
+
f"The {function_kind} function could not be deserialized."
|
|
116
|
+
)
|
|
115
117
|
|
|
116
118
|
if not callable(function):
|
|
117
119
|
raise AbortException(
|
|
@@ -8,7 +8,6 @@ pyproject.toml
|
|
|
8
8
|
src/isolate/__init__.py
|
|
9
9
|
src/isolate/_isolate_version.py
|
|
10
10
|
src/isolate/_version.py
|
|
11
|
-
src/isolate/exceptions.py
|
|
12
11
|
src/isolate/logs.py
|
|
13
12
|
src/isolate/py.typed
|
|
14
13
|
src/isolate/registry.py
|
|
@@ -22,6 +21,7 @@ src/isolate/backends/__init__.py
|
|
|
22
21
|
src/isolate/backends/_base.py
|
|
23
22
|
src/isolate/backends/common.py
|
|
24
23
|
src/isolate/backends/conda.py
|
|
24
|
+
src/isolate/backends/container.py
|
|
25
25
|
src/isolate/backends/local.py
|
|
26
26
|
src/isolate/backends/pyenv.py
|
|
27
27
|
src/isolate/backends/remote.py
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
[isolate.backends]
|
|
2
2
|
conda = isolate.backends.conda:CondaEnvironment
|
|
3
|
+
container = isolate.backends.container:ContainerizedPythonEnvironment
|
|
3
4
|
isolate-server = isolate.backends.remote:IsolateServer
|
|
4
5
|
local = isolate.backends.local:LocalPythonEnvironment
|
|
5
6
|
pyenv = isolate.backends.pyenv:PyenvEnvironment
|
|
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.12.13 → isolate-0.12.15}/src/isolate/connections/grpc/definitions/agent_pb2_grpc.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{isolate-0.12.13 → isolate-0.12.15}/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
|