isolate 0.12.13__py3-none-any.whl → 0.12.15__py3-none-any.whl

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.

@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '0.12.13'
16
- __version_tuple__ = version_tuple = (0, 12, 13)
15
+ __version__ = version = '0.12.15'
16
+ __version_tuple__ = version_tuple = (0, 12, 15)
isolate/backends/_base.py CHANGED
@@ -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(IsolateException):
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 BaseSerializationError(IsolateException):
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
- class SerializationError(BaseSerializationError):
32
- pass
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
- class DeserializationError(BaseSerializationError):
36
- pass
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
- try:
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
- try:
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
- try:
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
- try:
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(IsolateException):
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(IsolateException):
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
- # NOTE: technically any sort of exception could be raised here, since
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 BaseException as exc:
114
- return exc, True, traceback.format_exc()
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(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: isolate
3
- Version: 0.12.13
3
+ Version: 0.12.15
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
@@ -1,14 +1,14 @@
1
1
  isolate/__init__.py,sha256=uXOKnONs7sXgARNgElwr4_A1sKoA6ACHVEvs3IDiX1M,127
2
- isolate/_isolate_version.py,sha256=rYB4wxX5D44-YwCyT1hUwPhja5ktD6OYXizpLgC8gMI,415
2
+ isolate/_isolate_version.py,sha256=VMxsT9HmXnFACz1Qv_ryjpdx94Iy2Tkd2O8BMdpck7w,415
3
3
  isolate/_version.py,sha256=05pXvy-yr5t3I1m9JMn42Ilzpg7fa8IB2J8a3G7t1cU,274
4
- isolate/exceptions.py,sha256=ki-f7khY-Yo1J8nPdy5IP-aZhQyLUP9pp3dE0moEVKw,44
5
4
  isolate/logs.py,sha256=R_AHUVYD18z_PhtK_mDWi9Gch79CxmwHY09hUDShtwg,2079
6
5
  isolate/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
6
  isolate/registry.py,sha256=hpzv4HI7iihG5I7i5r8Pb257ibhEKY18xQcG-w1-BgI,1590
8
7
  isolate/backends/__init__.py,sha256=LLrSM7UnDFW8tIT5oYlE1wVJrxKcaj_v7cFwvTjQTlc,119
9
- isolate/backends/_base.py,sha256=senNj-k2Dp2DkyxmZy7WxzsexmPfU6_DBo7bbZDqTLQ,4167
8
+ isolate/backends/_base.py,sha256=Kt5pkhDzXZblq4vxaM3DQTo-Bj-7pIRZFlqJR7OfejY,4112
10
9
  isolate/backends/common.py,sha256=ZiU0Vkz78qaPH_3ThV28OcHi8QgXie4aBrkPXCJuNBM,8321
11
10
  isolate/backends/conda.py,sha256=OIQrpt_VffW2PjPOIzp-JvonW4e7rDQ1ASHOEjyzD8E,7646
11
+ isolate/backends/container.py,sha256=Ek06tMwrCzEGFUlIQ8lIWURiwchTiuiS4HHDk-9bN9k,1567
12
12
  isolate/backends/local.py,sha256=woxe4dmXuEHxWKsGNndoRA1_sP6yG-dg6tlFZni0mZc,1360
13
13
  isolate/backends/pyenv.py,sha256=G-OIwESUOU5TqqumwsKVUhRiFQzxB1xrPn-bGm4LQoI,5428
14
14
  isolate/backends/remote.py,sha256=qUm54mpqk0kaEfbPZl962Td3_P3qcpyVcfGdKfmkJHs,4234
@@ -17,13 +17,13 @@ isolate/backends/virtualenv.py,sha256=DiBAiybOLWMxJobIRaH4AgDn9agY5VrVPaSQObQa1L
17
17
  isolate/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
18
  isolate/common/timestamp.py,sha256=seh7FrMRH4i1SCQavA8d-7z8qi0pP8lYYhd29gTPMwE,367
19
19
  isolate/connections/__init__.py,sha256=oa0PNo7ZQ0StPIDvKnJ02_CNVMyfOhxJ3M1C0VMvj9c,627
20
- isolate/connections/common.py,sha256=bmQ7qDtBIbN7wj55OUwcRtRr9fWDSuxYajY1BRnb8Xc,3655
20
+ isolate/connections/common.py,sha256=PAfBGKZNUdtFlZQlw3_nQaUCKQXTnEkxzNNRV_i4R2A,3498
21
21
  isolate/connections/_local/__init__.py,sha256=6FtCKRSFBvTvjm5LNlNA-mieKEq3J7DZZRPcXVedERo,146
22
22
  isolate/connections/_local/_base.py,sha256=qCx2M8kbxuPTruj9kH5z005LU2FaC0BkLxsgY-sXRlg,6214
23
23
  isolate/connections/_local/agent_startup.py,sha256=swCs6Q0yVkDw7w-RftizHSMyJDM7DQwuP3TB0qI1ucg,1552
24
24
  isolate/connections/grpc/__init__.py,sha256=tcesLxlC36P6wSg2lBcO2egsJWMbSKwc8zFXhWac3YU,85
25
- isolate/connections/grpc/_base.py,sha256=hfGy_kFjifpK3zHD0_OTqpTF6CTOZH6abNnET4XLwE8,5613
26
- isolate/connections/grpc/agent.py,sha256=xRBfbmsWlOU4U6pBl0g_fhMdRZgVzXoKmi4gKTM3dYQ,7747
25
+ isolate/connections/grpc/_base.py,sha256=8C1qnEZghPk4GYBlh0rjbtlx8FYB7gNvioG9re1OMD8,5558
26
+ isolate/connections/grpc/agent.py,sha256=Vne6wsu1mQQm_jZwqLbWjrtfi7DjHce0TDPzjDrN1lc,7838
27
27
  isolate/connections/grpc/configuration.py,sha256=50YvGGHA9uyKg74xU_gc73j7bsFk973uIpMhmw2HhxY,788
28
28
  isolate/connections/grpc/interface.py,sha256=yt63kytgXRXrTnjePGJVdXz4LJJVSSrNkJCF1yz6FIE,2270
29
29
  isolate/connections/grpc/definitions/__init__.py,sha256=Z0453Bbjoq-Oxm2Wfi9fae-BFf8YsZwmuh88strmvxo,459
@@ -52,9 +52,9 @@ isolate/server/health/health.proto,sha256=wE2_QD0OQAblKkEBG7sALLXEOj1mOLKG-FbC4t
52
52
  isolate/server/health/health_pb2.py,sha256=mCnDq0-frAddHopN_g_LueHddbW-sN5kOfntJDlAvUY,1783
53
53
  isolate/server/health/health_pb2.pyi,sha256=boMRHMlX770EuccQCFTeRgf_KA_VMgW7l9GZIwxvMok,2546
54
54
  isolate/server/health/health_pb2_grpc.py,sha256=JRluct2W4af83OYxwmcCn0vRc78zf04Num0vBApuPEo,4005
55
- isolate-0.12.13.dist-info/LICENSE,sha256=427vuyirL5scgBLqA9UWcdnxKrtSGc0u_JfUupk6lAA,11359
56
- isolate-0.12.13.dist-info/METADATA,sha256=OKOL9Y8v5rY-Fs9zx5HwIDSdpZjRoyyseprthtrEdQs,3154
57
- isolate-0.12.13.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
58
- isolate-0.12.13.dist-info/entry_points.txt,sha256=XQ_nl-8MR94UnekxbBJRNGlY-lZ_Qh50N4mzwFDdwV8,290
59
- isolate-0.12.13.dist-info/top_level.txt,sha256=W9QJBHcq5WXRkbOXf25bvftzFsOZZN4n1DAatdroZrs,8
60
- isolate-0.12.13.dist-info/RECORD,,
55
+ isolate-0.12.15.dist-info/LICENSE,sha256=427vuyirL5scgBLqA9UWcdnxKrtSGc0u_JfUupk6lAA,11359
56
+ isolate-0.12.15.dist-info/METADATA,sha256=9wG2gpvyozTg6s7Z_km_4SQMMscmcX6Dn3jZqVA3Oe4,3154
57
+ isolate-0.12.15.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
58
+ isolate-0.12.15.dist-info/entry_points.txt,sha256=s3prh2EERaVCbL8R45tfY5WFPZ1TsYOsz305YR7s-Pc,360
59
+ isolate-0.12.15.dist-info/top_level.txt,sha256=W9QJBHcq5WXRkbOXf25bvftzFsOZZN4n1DAatdroZrs,8
60
+ isolate-0.12.15.dist-info/RECORD,,
@@ -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
isolate/exceptions.py DELETED
@@ -1,2 +0,0 @@
1
- class IsolateException(Exception):
2
- pass