isolate 0.26.0__tar.gz → 0.26.2__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.2/.github/workflows/test.yml +91 -0
- {isolate-0.26.0 → isolate-0.26.2}/PKG-INFO +1 -1
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/_isolate_version.py +3 -3
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/backends/_base.py +5 -10
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/backends/remote.py +4 -3
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/connections/grpc/_base.py +6 -8
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/connections/grpc/agent.py +64 -16
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/connections/grpc/definitions/agent.proto +1 -1
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/connections/grpc/definitions/agent_pb2.py +7 -7
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/connections/grpc/definitions/agent_pb2.pyi +5 -3
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/connections/grpc/definitions/agent_pb2_grpc.py +0 -1
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/server/definitions/server.proto +1 -1
- isolate-0.26.2/src/isolate/server/definitions/server_pb2.py +56 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/server/definitions/server_pb2.pyi +5 -3
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/server/definitions/server_pb2_grpc.py +0 -1
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/server/server.py +2 -2
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate.egg-info/PKG-INFO +1 -1
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate.egg-info/SOURCES.txt +1 -0
- isolate-0.26.2/tests/test_agent_backward_compatibility.py +228 -0
- {isolate-0.26.0 → isolate-0.26.2}/tests/test_server.py +189 -2
- isolate-0.26.0/.github/workflows/test.yml +0 -67
- isolate-0.26.0/src/isolate/server/definitions/server_pb2.py +0 -56
- {isolate-0.26.0 → isolate-0.26.2}/.github/workflows/claude-code-review.yml +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/.github/workflows/claude.yml +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/.github/workflows/lint.yml +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/.github/workflows/release.yml +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/.gitignore +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/.pre-commit-config.yaml +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/LICENSE +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/README.md +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/pyproject.toml +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/setup.cfg +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/__init__.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/_version.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/backends/__init__.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/backends/common.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/backends/conda.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/backends/container.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/backends/local.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/backends/pyenv.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/backends/settings.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/backends/virtualenv.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/common/__init__.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/common/timestamp.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/connections/__init__.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/connections/_local/__init__.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/connections/_local/_base.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/connections/_local/agent_startup.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/connections/common.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/connections/grpc/__init__.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/connections/grpc/configuration.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/connections/grpc/definitions/__init__.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/connections/grpc/definitions/common.proto +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/connections/grpc/definitions/common_pb2.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/connections/grpc/definitions/common_pb2.pyi +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/connections/grpc/definitions/common_pb2_grpc.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/connections/grpc/interface.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/connections/ipc/__init__.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/connections/ipc/_base.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/connections/ipc/agent.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/logger.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/logs.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/py.typed +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/registry.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/server/__init__.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/server/definitions/__init__.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/server/health/__init__.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/server/health/health.proto +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/server/health/health_pb2.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/server/health/health_pb2.pyi +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/server/health/health_pb2_grpc.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/server/health_server.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate/server/interface.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate.egg-info/dependency_links.txt +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate.egg-info/entry_points.txt +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate.egg-info/requires.txt +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/src/isolate.egg-info/top_level.txt +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/tests/__init__.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/tests/conftest.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/tests/test_backends.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/tests/test_concurrency.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/tests/test_connections.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/tests/test_connections_grpc_base.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/tests/test_isolate.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/tests/test_log.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/tests/test_log_masking.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/tests/test_logger.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/tests/test_serialization.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/tests/test_shutdown.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/tools/Dockerfile +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/tools/agent_requirements.txt +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/tools/isolate_client.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/tools/protobuf-requirements.txt +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/tools/regen_grpc.py +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/tools/requirements.txt +0 -0
- {isolate-0.26.0 → isolate-0.26.2}/tools/test_agent_requirements.txt +0 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
pull_request:
|
|
8
|
+
branches:
|
|
9
|
+
schedule:
|
|
10
|
+
- cron: "30 5 * * *" # every day at 5:30 UTC
|
|
11
|
+
|
|
12
|
+
concurrency:
|
|
13
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
14
|
+
cancel-in-progress: true
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
test:
|
|
18
|
+
runs-on: ${{ matrix.os }}
|
|
19
|
+
timeout-minutes: 45
|
|
20
|
+
strategy:
|
|
21
|
+
fail-fast: false
|
|
22
|
+
|
|
23
|
+
matrix:
|
|
24
|
+
os: [ubuntu-latest]
|
|
25
|
+
python: ["3.8", "3.9", "3.10", "3.11"]
|
|
26
|
+
include:
|
|
27
|
+
- os: macos-15-intel
|
|
28
|
+
python: "3.8"
|
|
29
|
+
- os: macos-15-intel
|
|
30
|
+
python: "3.11"
|
|
31
|
+
steps:
|
|
32
|
+
- uses: actions/checkout@v3
|
|
33
|
+
|
|
34
|
+
- uses: actions/setup-python@v3
|
|
35
|
+
with:
|
|
36
|
+
python-version: ${{ matrix.python }}
|
|
37
|
+
|
|
38
|
+
- name: Install mamba
|
|
39
|
+
uses: mamba-org/setup-micromamba@v1
|
|
40
|
+
with:
|
|
41
|
+
environment-name: ci
|
|
42
|
+
create-args: >-
|
|
43
|
+
python=${{ matrix.python }}
|
|
44
|
+
condarc: |
|
|
45
|
+
channels:
|
|
46
|
+
- anaconda
|
|
47
|
+
- conda-forge
|
|
48
|
+
- pytorch
|
|
49
|
+
|
|
50
|
+
- uses: actions/checkout@v3
|
|
51
|
+
with:
|
|
52
|
+
repository: pyenv/pyenv
|
|
53
|
+
ref: v2.3.6
|
|
54
|
+
path: pyenv
|
|
55
|
+
|
|
56
|
+
- name: Install dependencies
|
|
57
|
+
run: |
|
|
58
|
+
python -m pip install -e ".[test]"
|
|
59
|
+
|
|
60
|
+
- name: Install uv
|
|
61
|
+
run: |
|
|
62
|
+
python -m pip install uv
|
|
63
|
+
|
|
64
|
+
- name: Test
|
|
65
|
+
run: |
|
|
66
|
+
export ISOLATE_PYENV_EXECUTABLE=pyenv/bin/pyenv
|
|
67
|
+
python -m pytest -vvv --ignore=tests/test_agent_backward_compatibility.py
|
|
68
|
+
|
|
69
|
+
backward-compat:
|
|
70
|
+
runs-on: ubuntu-latest
|
|
71
|
+
timeout-minutes: 30
|
|
72
|
+
steps:
|
|
73
|
+
- uses: actions/checkout@v3
|
|
74
|
+
with:
|
|
75
|
+
fetch-depth: 0
|
|
76
|
+
|
|
77
|
+
- uses: actions/setup-python@v3
|
|
78
|
+
with:
|
|
79
|
+
python-version: "3.11"
|
|
80
|
+
|
|
81
|
+
- name: Install dependencies
|
|
82
|
+
run: |
|
|
83
|
+
python -m pip install -e ".[test]"
|
|
84
|
+
|
|
85
|
+
- name: Install uv
|
|
86
|
+
run: |
|
|
87
|
+
python -m pip install uv
|
|
88
|
+
|
|
89
|
+
- name: Test backward compatibility
|
|
90
|
+
run: |
|
|
91
|
+
python -m pytest -vvv tests/test_agent_backward_compatibility.py
|
|
@@ -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.2'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 26, 2)
|
|
33
33
|
|
|
34
|
-
__commit_id__ = commit_id = '
|
|
34
|
+
__commit_id__ = commit_id = 'g7e1de0bc2'
|
|
@@ -2,14 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from contextlib import contextmanager
|
|
4
4
|
from dataclasses import dataclass
|
|
5
|
-
from typing import
|
|
6
|
-
Any,
|
|
7
|
-
Callable,
|
|
8
|
-
ClassVar,
|
|
9
|
-
Generic,
|
|
10
|
-
Iterator,
|
|
11
|
-
TypeVar,
|
|
12
|
-
)
|
|
5
|
+
from typing import Any, Callable, ClassVar, Generic, Iterator, Optional, TypeVar
|
|
13
6
|
|
|
14
7
|
from isolate.backends.settings import DEFAULT_SETTINGS, IsolateSettings
|
|
15
8
|
from isolate.logs import Log, LogLevel, LogSource
|
|
@@ -131,7 +124,7 @@ class EnvironmentConnection:
|
|
|
131
124
|
self,
|
|
132
125
|
entrypoint: str,
|
|
133
126
|
*,
|
|
134
|
-
run_on_main_thread: bool =
|
|
127
|
+
run_on_main_thread: Optional[bool] = None,
|
|
135
128
|
) -> CallResultType: # type: ignore[type-var]
|
|
136
129
|
"""Run a ``"module:attr"`` Python entrypoint inside the environment,
|
|
137
130
|
and return the result. If the entrypoint raises an exception, then it
|
|
@@ -139,7 +132,9 @@ class EnvironmentConnection:
|
|
|
139
132
|
|
|
140
133
|
If ``run_on_main_thread`` is True, the resolved callable is invoked on
|
|
141
134
|
the agent's main thread (and coroutines it returns are awaited on that
|
|
142
|
-
loop)
|
|
135
|
+
loop). If False, it runs on a thread pool. If None, the backend may
|
|
136
|
+
fall back to legacy callable-level hints such as
|
|
137
|
+
``_run_on_main_thread``."""
|
|
143
138
|
raise NotImplementedError
|
|
144
139
|
|
|
145
140
|
def log(
|
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import copy
|
|
4
4
|
import json
|
|
5
5
|
from dataclasses import dataclass
|
|
6
|
-
from typing import Any, ClassVar, List
|
|
6
|
+
from typing import Any, ClassVar, List, Optional
|
|
7
7
|
|
|
8
8
|
import grpc
|
|
9
9
|
|
|
@@ -120,15 +120,16 @@ class IsolateServerConnection(EnvironmentConnection):
|
|
|
120
120
|
self,
|
|
121
121
|
entrypoint: str,
|
|
122
122
|
*,
|
|
123
|
-
run_on_main_thread: bool =
|
|
123
|
+
run_on_main_thread: Optional[bool] = None,
|
|
124
124
|
) -> CallResultType: # type: ignore[type-var]
|
|
125
125
|
validate_entrypoint(entrypoint)
|
|
126
126
|
request = BoundFunction(
|
|
127
127
|
entrypoint=entrypoint,
|
|
128
128
|
environments=self.definitions,
|
|
129
129
|
stream_logs=True,
|
|
130
|
-
run_on_main_thread=run_on_main_thread,
|
|
131
130
|
)
|
|
131
|
+
if run_on_main_thread is not None:
|
|
132
|
+
request.run_on_main_thread = run_on_main_thread
|
|
132
133
|
return self._run_request(request)
|
|
133
134
|
|
|
134
135
|
def _run_request(self, request: BoundFunction) -> CallResultType: # type: ignore[type-var]
|
|
@@ -6,7 +6,7 @@ import time
|
|
|
6
6
|
from contextlib import contextmanager
|
|
7
7
|
from dataclasses import dataclass
|
|
8
8
|
from pathlib import Path
|
|
9
|
-
from typing import Any, ContextManager, Iterator, List, Tuple, Union, cast
|
|
9
|
+
from typing import Any, ContextManager, Iterator, List, Optional, Tuple, Union, cast
|
|
10
10
|
|
|
11
11
|
import grpc
|
|
12
12
|
|
|
@@ -125,15 +125,13 @@ class GRPCExecutionBase(EnvironmentConnection):
|
|
|
125
125
|
self,
|
|
126
126
|
entrypoint: str,
|
|
127
127
|
*,
|
|
128
|
-
run_on_main_thread: bool =
|
|
128
|
+
run_on_main_thread: Optional[bool] = None,
|
|
129
129
|
) -> CallResultType: # type: ignore[type-var]
|
|
130
130
|
validate_entrypoint(entrypoint)
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
),
|
|
136
|
-
)
|
|
131
|
+
function_call = definitions.FunctionCall(entrypoint=entrypoint)
|
|
132
|
+
if run_on_main_thread is not None:
|
|
133
|
+
function_call.run_on_main_thread = run_on_main_thread
|
|
134
|
+
return self._run_function_call(function_call)
|
|
137
135
|
|
|
138
136
|
def _run_function_call(
|
|
139
137
|
self, function_call: definitions.FunctionCall
|
|
@@ -26,6 +26,7 @@ from typing import (
|
|
|
26
26
|
Any,
|
|
27
27
|
AsyncIterator,
|
|
28
28
|
Iterable,
|
|
29
|
+
Optional,
|
|
29
30
|
TextIO,
|
|
30
31
|
)
|
|
31
32
|
|
|
@@ -39,12 +40,30 @@ except ImportError:
|
|
|
39
40
|
agent_version = "UNKNOWN"
|
|
40
41
|
|
|
41
42
|
from isolate.backends.common import sha256_digest_of
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
43
|
+
|
|
44
|
+
try:
|
|
45
|
+
from isolate.backends.settings import DEFAULT_SERIALIZATION_METHOD
|
|
46
|
+
except ImportError:
|
|
47
|
+
# Newer server code can run inside an older frozen agent environment
|
|
48
|
+
# that predates this exported constant. Keep the legacy default inline
|
|
49
|
+
# so version-skewed agent/server pairs remain compatible.
|
|
50
|
+
DEFAULT_SERIALIZATION_METHOD = "pickle"
|
|
51
|
+
from isolate.connections.common import SerializationError, serialize_object
|
|
52
|
+
|
|
53
|
+
try:
|
|
54
|
+
from isolate.connections.common import validate_entrypoint
|
|
55
|
+
except ImportError:
|
|
56
|
+
# Older installed isolate builds predate the shared helper. Keep the
|
|
57
|
+
# legacy syntax check inline so current agent scripts still start up
|
|
58
|
+
# under those versions.
|
|
59
|
+
def validate_entrypoint(entrypoint: str) -> None:
|
|
60
|
+
module, sep, attr = entrypoint.partition(":")
|
|
61
|
+
if not sep or not module or not attr or ":" in attr:
|
|
62
|
+
raise ValueError(
|
|
63
|
+
f"Invalid entrypoint {entrypoint!r}: expected 'module:attr'."
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
|
|
48
67
|
from isolate.connections.grpc import definitions
|
|
49
68
|
from isolate.connections.grpc.configuration import get_default_options
|
|
50
69
|
from isolate.connections.grpc.interface import from_grpc
|
|
@@ -310,18 +329,23 @@ class AgentServicer(definitions.AgentServicer):
|
|
|
310
329
|
extra_args.append(self._run_cache[cache_key])
|
|
311
330
|
|
|
312
331
|
try:
|
|
332
|
+
run_on_main_thread = (
|
|
333
|
+
request.run_on_main_thread
|
|
334
|
+
if request.HasField("run_on_main_thread")
|
|
335
|
+
else None
|
|
336
|
+
)
|
|
313
337
|
if has_entrypoint:
|
|
314
338
|
invocation = await self.execute_entrypoint(
|
|
315
339
|
request.entrypoint,
|
|
316
340
|
"function",
|
|
317
|
-
run_on_main_thread=
|
|
341
|
+
run_on_main_thread=run_on_main_thread,
|
|
318
342
|
)
|
|
319
343
|
else:
|
|
320
344
|
invocation = await self.execute_function(
|
|
321
345
|
request.function,
|
|
322
346
|
"function",
|
|
323
347
|
extra_args=extra_args,
|
|
324
|
-
run_on_main_thread=
|
|
348
|
+
run_on_main_thread=run_on_main_thread,
|
|
325
349
|
)
|
|
326
350
|
result, was_it_raised, stringized_tb = invocation
|
|
327
351
|
yield self.send_object(
|
|
@@ -340,7 +364,7 @@ class AgentServicer(definitions.AgentServicer):
|
|
|
340
364
|
function_kind: str,
|
|
341
365
|
*,
|
|
342
366
|
extra_args: Iterable[Any] = (),
|
|
343
|
-
run_on_main_thread: bool =
|
|
367
|
+
run_on_main_thread: Optional[bool] = None,
|
|
344
368
|
) -> tuple[Any, bool, str | None]:
|
|
345
369
|
if function.was_it_raised:
|
|
346
370
|
raise AbortException(
|
|
@@ -370,16 +394,37 @@ class AgentServicer(definitions.AgentServicer):
|
|
|
370
394
|
entrypoint: str,
|
|
371
395
|
function_kind: str,
|
|
372
396
|
*,
|
|
373
|
-
run_on_main_thread: bool =
|
|
397
|
+
run_on_main_thread: Optional[bool] = None,
|
|
374
398
|
) -> tuple[Any, bool, str | None]:
|
|
375
399
|
# Resolve lazily so import / attribute errors surface through the
|
|
376
400
|
# regular exception capture in _invoke_callable and reach the client
|
|
377
|
-
# as a raised result, matching the pickle error path.
|
|
378
|
-
|
|
379
|
-
|
|
401
|
+
# as a raised result, matching the pickle error path. The wrapper also
|
|
402
|
+
# mirrors the resolved callable's legacy `_run_on_main_thread` flag so
|
|
403
|
+
# absent RPC fields keep the old fallback behavior for entrypoints.
|
|
404
|
+
unresolved = object()
|
|
405
|
+
|
|
406
|
+
class ResolvedEntrypoint:
|
|
407
|
+
def __init__(self, value: str):
|
|
408
|
+
self._entrypoint = value
|
|
409
|
+
self._resolved: Any = unresolved
|
|
410
|
+
|
|
411
|
+
def _resolve(self) -> Any:
|
|
412
|
+
if self._resolved is unresolved:
|
|
413
|
+
self._resolved = _resolve_entrypoint(self._entrypoint)
|
|
414
|
+
return self._resolved
|
|
415
|
+
|
|
416
|
+
@property
|
|
417
|
+
def _run_on_main_thread(self) -> bool:
|
|
418
|
+
try:
|
|
419
|
+
return getattr(self._resolve(), "_run_on_main_thread", False)
|
|
420
|
+
except Exception:
|
|
421
|
+
return False
|
|
422
|
+
|
|
423
|
+
def __call__(self) -> Any:
|
|
424
|
+
return self._resolve()()
|
|
380
425
|
|
|
381
426
|
return await self._invoke_callable(
|
|
382
|
-
|
|
427
|
+
ResolvedEntrypoint(entrypoint),
|
|
383
428
|
function_kind,
|
|
384
429
|
run_on_main_thread=run_on_main_thread,
|
|
385
430
|
)
|
|
@@ -390,7 +435,7 @@ class AgentServicer(definitions.AgentServicer):
|
|
|
390
435
|
function_kind: str,
|
|
391
436
|
extra_args: Iterable[Any] = (),
|
|
392
437
|
*,
|
|
393
|
-
run_on_main_thread: bool =
|
|
438
|
+
run_on_main_thread: Optional[bool] = None,
|
|
394
439
|
) -> tuple[Any, bool, str | None]:
|
|
395
440
|
if not callable(function):
|
|
396
441
|
raise AbortException(
|
|
@@ -411,7 +456,10 @@ class AgentServicer(definitions.AgentServicer):
|
|
|
411
456
|
# called from a running event loop" error and stay backward
|
|
412
457
|
# compatible, we offload those unflagged functions to a thread pool.
|
|
413
458
|
|
|
414
|
-
if run_on_main_thread
|
|
459
|
+
if run_on_main_thread is None:
|
|
460
|
+
run_on_main_thread = getattr(function, "_run_on_main_thread", False)
|
|
461
|
+
|
|
462
|
+
if run_on_main_thread:
|
|
415
463
|
result = function(*extra_args)
|
|
416
464
|
else:
|
|
417
465
|
result = self._thread_pool.submit(function, *extra_args).result()
|
|
@@ -17,7 +17,7 @@ message FunctionCall {
|
|
|
17
17
|
// event loop, useful for async callables) instead of a thread pool. The
|
|
18
18
|
// agent also honors `_run_on_main_thread` set on the callable itself,
|
|
19
19
|
// for backward compatibility with older clients.
|
|
20
|
-
bool run_on_main_thread = 4;
|
|
20
|
+
optional bool run_on_main_thread = 4;
|
|
21
21
|
// Exactly one of the following must be set.
|
|
22
22
|
oneof callable {
|
|
23
23
|
// A serialized callable to execute.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
|
3
3
|
# source: agent.proto
|
|
4
|
-
# Protobuf Python Version:
|
|
4
|
+
# Protobuf Python Version: 5.26.1
|
|
5
5
|
"""Generated protocol buffer code."""
|
|
6
6
|
from google.protobuf import descriptor as _descriptor
|
|
7
7
|
from google.protobuf import descriptor_pool as _descriptor_pool
|
|
@@ -15,15 +15,15 @@ _sym_db = _symbol_database.Default()
|
|
|
15
15
|
from isolate.connections.grpc.definitions import common_pb2 as common__pb2
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0b\x61gent.proto\x1a\x0c\x63ommon.proto\"\
|
|
18
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0b\x61gent.proto\x1a\x0c\x63ommon.proto\"\xca\x01\n\x0c\x46unctionCall\x12*\n\nsetup_func\x18\x02 \x01(\x0b\x32\x11.SerializedObjectH\x01\x88\x01\x01\x12\x1f\n\x12run_on_main_thread\x18\x04 \x01(\x08H\x02\x88\x01\x01\x12%\n\x08\x66unction\x18\x01 \x01(\x0b\x32\x11.SerializedObjectH\x00\x12\x14\n\nentrypoint\x18\x03 \x01(\tH\x00\x42\n\n\x08\x63\x61llableB\r\n\x0b_setup_funcB\x15\n\x13_run_on_main_thread24\n\x05\x41gent\x12+\n\x03Run\x12\r.FunctionCall\x1a\x11.PartialRunResult\"\x00\x30\x01\x62\x06proto3')
|
|
19
19
|
|
|
20
20
|
_globals = globals()
|
|
21
21
|
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
22
22
|
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'agent_pb2', _globals)
|
|
23
|
-
if _descriptor._USE_C_DESCRIPTORS
|
|
24
|
-
DESCRIPTOR.
|
|
23
|
+
if not _descriptor._USE_C_DESCRIPTORS:
|
|
24
|
+
DESCRIPTOR._loaded_options = None
|
|
25
25
|
_globals['_FUNCTIONCALL']._serialized_start=30
|
|
26
|
-
_globals['_FUNCTIONCALL']._serialized_end=
|
|
27
|
-
_globals['_AGENT']._serialized_start=
|
|
28
|
-
_globals['_AGENT']._serialized_end=
|
|
26
|
+
_globals['_FUNCTIONCALL']._serialized_end=232
|
|
27
|
+
_globals['_AGENT']._serialized_start=234
|
|
28
|
+
_globals['_AGENT']._serialized_end=286
|
|
29
29
|
# @@protoc_insertion_point(module_scope)
|
|
@@ -49,12 +49,14 @@ class FunctionCall(google.protobuf.message.Message):
|
|
|
49
49
|
self,
|
|
50
50
|
*,
|
|
51
51
|
setup_func: common_pb2.SerializedObject | None = ...,
|
|
52
|
-
run_on_main_thread: builtins.bool = ...,
|
|
52
|
+
run_on_main_thread: builtins.bool | None = ...,
|
|
53
53
|
function: common_pb2.SerializedObject | None = ...,
|
|
54
54
|
entrypoint: builtins.str = ...,
|
|
55
55
|
) -> None: ...
|
|
56
|
-
def HasField(self, field_name: typing_extensions.Literal["_setup_func", b"_setup_func", "callable", b"callable", "entrypoint", b"entrypoint", "function", b"function", "setup_func", b"setup_func"]) -> builtins.bool: ...
|
|
57
|
-
def ClearField(self, field_name: typing_extensions.Literal["_setup_func", b"_setup_func", "callable", b"callable", "entrypoint", b"entrypoint", "function", b"function", "run_on_main_thread", b"run_on_main_thread", "setup_func", b"setup_func"]) -> None: ...
|
|
56
|
+
def HasField(self, field_name: typing_extensions.Literal["_run_on_main_thread", b"_run_on_main_thread", "_setup_func", b"_setup_func", "callable", b"callable", "entrypoint", b"entrypoint", "function", b"function", "run_on_main_thread", b"run_on_main_thread", "setup_func", b"setup_func"]) -> builtins.bool: ...
|
|
57
|
+
def ClearField(self, field_name: typing_extensions.Literal["_run_on_main_thread", b"_run_on_main_thread", "_setup_func", b"_setup_func", "callable", b"callable", "entrypoint", b"entrypoint", "function", b"function", "run_on_main_thread", b"run_on_main_thread", "setup_func", b"setup_func"]) -> None: ...
|
|
58
|
+
@typing.overload
|
|
59
|
+
def WhichOneof(self, oneof_group: typing_extensions.Literal["_run_on_main_thread", b"_run_on_main_thread"]) -> typing_extensions.Literal["run_on_main_thread"] | None: ...
|
|
58
60
|
@typing.overload
|
|
59
61
|
def WhichOneof(self, oneof_group: typing_extensions.Literal["_setup_func", b"_setup_func"]) -> typing_extensions.Literal["setup_func"] | None: ...
|
|
60
62
|
@typing.overload
|
|
@@ -29,7 +29,7 @@ message BoundFunction {
|
|
|
29
29
|
// event loop, useful for async callables) instead of a thread pool. The
|
|
30
30
|
// agent also honors `_run_on_main_thread` set on the callable itself,
|
|
31
31
|
// for backward compatibility with older clients.
|
|
32
|
-
bool run_on_main_thread = 6;
|
|
32
|
+
optional bool run_on_main_thread = 6;
|
|
33
33
|
// Exactly one of the following must be set.
|
|
34
34
|
oneof callable {
|
|
35
35
|
// A serialized callable to run.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
|
3
|
+
# source: server.proto
|
|
4
|
+
# Protobuf Python Version: 5.26.1
|
|
5
|
+
"""Generated protocol buffer code."""
|
|
6
|
+
from google.protobuf import descriptor as _descriptor
|
|
7
|
+
from google.protobuf import descriptor_pool as _descriptor_pool
|
|
8
|
+
from google.protobuf import symbol_database as _symbol_database
|
|
9
|
+
from google.protobuf.internal import builder as _builder
|
|
10
|
+
# @@protoc_insertion_point(imports)
|
|
11
|
+
|
|
12
|
+
_sym_db = _symbol_database.Default()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
from isolate.connections.grpc.definitions import common_pb2 as common__pb2
|
|
16
|
+
from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0cserver.proto\x1a\x0c\x63ommon.proto\x1a\x1cgoogle/protobuf/struct.proto\"\x8e\x02\n\rBoundFunction\x12,\n\x0c\x65nvironments\x18\x01 \x03(\x0b\x32\x16.EnvironmentDefinition\x12*\n\nsetup_func\x18\x03 \x01(\x0b\x32\x11.SerializedObjectH\x01\x88\x01\x01\x12\x13\n\x0bstream_logs\x18\x04 \x01(\x08\x12\x1f\n\x12run_on_main_thread\x18\x06 \x01(\x08H\x02\x88\x01\x01\x12%\n\x08\x66unction\x18\x02 \x01(\x0b\x32\x11.SerializedObjectH\x00\x12\x14\n\nentrypoint\x18\x05 \x01(\tH\x00\x42\n\n\x08\x63\x61llableB\r\n\x0b_setup_funcB\x15\n\x13_run_on_main_thread\"d\n\x15\x45nvironmentDefinition\x12\x0c\n\x04kind\x18\x01 \x01(\t\x12.\n\rconfiguration\x18\x02 \x01(\x0b\x32\x17.google.protobuf.Struct\x12\r\n\x05\x66orce\x18\x03 \x01(\x08\"R\n\rSubmitRequest\x12 \n\x08\x66unction\x18\x01 \x01(\x0b\x32\x0e.BoundFunction\x12\x1f\n\x08metadata\x18\x02 \x01(\x0b\x32\r.TaskMetadata\"{\n\x0cTaskMetadata\x12\x36\n\rlogger_labels\x18\x01 \x03(\x0b\x32\x1f.TaskMetadata.LoggerLabelsEntry\x1a\x33\n\x11LoggerLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"!\n\x0eSubmitResponse\x12\x0f\n\x07task_id\x18\x01 \x01(\t\"F\n\x12SetMetadataRequest\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x1f\n\x08metadata\x18\x02 \x01(\x0b\x32\r.TaskMetadata\"\x15\n\x13SetMetadataResponse\"\r\n\x0bListRequest\"\x1b\n\x08TaskInfo\x12\x0f\n\x07task_id\x18\x01 \x01(\t\"(\n\x0cListResponse\x12\x18\n\x05tasks\x18\x01 \x03(\x0b\x32\t.TaskInfo\" \n\rCancelRequest\x12\x0f\n\x07task_id\x18\x01 \x01(\t\"\x10\n\x0e\x43\x61ncelResponse2\xf4\x01\n\x07Isolate\x12,\n\x03Run\x12\x0e.BoundFunction\x1a\x11.PartialRunResult\"\x00\x30\x01\x12+\n\x06Submit\x12\x0e.SubmitRequest\x1a\x0f.SubmitResponse\"\x00\x12:\n\x0bSetMetadata\x12\x13.SetMetadataRequest\x1a\x14.SetMetadataResponse\"\x00\x12%\n\x04List\x12\x0c.ListRequest\x1a\r.ListResponse\"\x00\x12+\n\x06\x43\x61ncel\x12\x0e.CancelRequest\x1a\x0f.CancelResponse\"\x00\x62\x06proto3')
|
|
20
|
+
|
|
21
|
+
_globals = globals()
|
|
22
|
+
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
23
|
+
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'server_pb2', _globals)
|
|
24
|
+
if not _descriptor._USE_C_DESCRIPTORS:
|
|
25
|
+
DESCRIPTOR._loaded_options = None
|
|
26
|
+
_globals['_TASKMETADATA_LOGGERLABELSENTRY']._loaded_options = None
|
|
27
|
+
_globals['_TASKMETADATA_LOGGERLABELSENTRY']._serialized_options = b'8\001'
|
|
28
|
+
_globals['_BOUNDFUNCTION']._serialized_start=61
|
|
29
|
+
_globals['_BOUNDFUNCTION']._serialized_end=331
|
|
30
|
+
_globals['_ENVIRONMENTDEFINITION']._serialized_start=333
|
|
31
|
+
_globals['_ENVIRONMENTDEFINITION']._serialized_end=433
|
|
32
|
+
_globals['_SUBMITREQUEST']._serialized_start=435
|
|
33
|
+
_globals['_SUBMITREQUEST']._serialized_end=517
|
|
34
|
+
_globals['_TASKMETADATA']._serialized_start=519
|
|
35
|
+
_globals['_TASKMETADATA']._serialized_end=642
|
|
36
|
+
_globals['_TASKMETADATA_LOGGERLABELSENTRY']._serialized_start=591
|
|
37
|
+
_globals['_TASKMETADATA_LOGGERLABELSENTRY']._serialized_end=642
|
|
38
|
+
_globals['_SUBMITRESPONSE']._serialized_start=644
|
|
39
|
+
_globals['_SUBMITRESPONSE']._serialized_end=677
|
|
40
|
+
_globals['_SETMETADATAREQUEST']._serialized_start=679
|
|
41
|
+
_globals['_SETMETADATAREQUEST']._serialized_end=749
|
|
42
|
+
_globals['_SETMETADATARESPONSE']._serialized_start=751
|
|
43
|
+
_globals['_SETMETADATARESPONSE']._serialized_end=772
|
|
44
|
+
_globals['_LISTREQUEST']._serialized_start=774
|
|
45
|
+
_globals['_LISTREQUEST']._serialized_end=787
|
|
46
|
+
_globals['_TASKINFO']._serialized_start=789
|
|
47
|
+
_globals['_TASKINFO']._serialized_end=816
|
|
48
|
+
_globals['_LISTRESPONSE']._serialized_start=818
|
|
49
|
+
_globals['_LISTRESPONSE']._serialized_end=858
|
|
50
|
+
_globals['_CANCELREQUEST']._serialized_start=860
|
|
51
|
+
_globals['_CANCELREQUEST']._serialized_end=892
|
|
52
|
+
_globals['_CANCELRESPONSE']._serialized_start=894
|
|
53
|
+
_globals['_CANCELRESPONSE']._serialized_end=910
|
|
54
|
+
_globals['_ISOLATE']._serialized_start=913
|
|
55
|
+
_globals['_ISOLATE']._serialized_end=1157
|
|
56
|
+
# @@protoc_insertion_point(module_scope)
|
|
@@ -54,12 +54,14 @@ class BoundFunction(google.protobuf.message.Message):
|
|
|
54
54
|
environments: collections.abc.Iterable[global___EnvironmentDefinition] | None = ...,
|
|
55
55
|
setup_func: common_pb2.SerializedObject | None = ...,
|
|
56
56
|
stream_logs: builtins.bool = ...,
|
|
57
|
-
run_on_main_thread: builtins.bool = ...,
|
|
57
|
+
run_on_main_thread: builtins.bool | None = ...,
|
|
58
58
|
function: common_pb2.SerializedObject | None = ...,
|
|
59
59
|
entrypoint: builtins.str = ...,
|
|
60
60
|
) -> None: ...
|
|
61
|
-
def HasField(self, field_name: typing_extensions.Literal["_setup_func", b"_setup_func", "callable", b"callable", "entrypoint", b"entrypoint", "function", b"function", "setup_func", b"setup_func"]) -> builtins.bool: ...
|
|
62
|
-
def ClearField(self, field_name: typing_extensions.Literal["_setup_func", b"_setup_func", "callable", b"callable", "entrypoint", b"entrypoint", "environments", b"environments", "function", b"function", "run_on_main_thread", b"run_on_main_thread", "setup_func", b"setup_func", "stream_logs", b"stream_logs"]) -> None: ...
|
|
61
|
+
def HasField(self, field_name: typing_extensions.Literal["_run_on_main_thread", b"_run_on_main_thread", "_setup_func", b"_setup_func", "callable", b"callable", "entrypoint", b"entrypoint", "function", b"function", "run_on_main_thread", b"run_on_main_thread", "setup_func", b"setup_func"]) -> builtins.bool: ...
|
|
62
|
+
def ClearField(self, field_name: typing_extensions.Literal["_run_on_main_thread", b"_run_on_main_thread", "_setup_func", b"_setup_func", "callable", b"callable", "entrypoint", b"entrypoint", "environments", b"environments", "function", b"function", "run_on_main_thread", b"run_on_main_thread", "setup_func", b"setup_func", "stream_logs", b"stream_logs"]) -> None: ...
|
|
63
|
+
@typing.overload
|
|
64
|
+
def WhichOneof(self, oneof_group: typing_extensions.Literal["_run_on_main_thread", b"_run_on_main_thread"]) -> typing_extensions.Literal["run_on_main_thread"] | None: ...
|
|
63
65
|
@typing.overload
|
|
64
66
|
def WhichOneof(self, oneof_group: typing_extensions.Literal["_setup_func", b"_setup_func"]) -> typing_extensions.Literal["setup_func"] | None: ...
|
|
65
67
|
@typing.overload
|
|
@@ -330,16 +330,16 @@ class IsolateServicer(definitions.IsolateServicer):
|
|
|
330
330
|
if has_entrypoint:
|
|
331
331
|
function_call = definitions.FunctionCall(
|
|
332
332
|
entrypoint=task.request.entrypoint,
|
|
333
|
-
run_on_main_thread=task.request.run_on_main_thread,
|
|
334
333
|
)
|
|
335
334
|
else:
|
|
336
335
|
function_call = definitions.FunctionCall(
|
|
337
336
|
function=task.request.function,
|
|
338
337
|
setup_func=task.request.setup_func,
|
|
339
|
-
run_on_main_thread=task.request.run_on_main_thread,
|
|
340
338
|
)
|
|
341
339
|
if not task.request.HasField("setup_func"):
|
|
342
340
|
function_call.ClearField("setup_func")
|
|
341
|
+
if task.request.HasField("run_on_main_thread"):
|
|
342
|
+
function_call.run_on_main_thread = task.request.run_on_main_thread
|
|
343
343
|
|
|
344
344
|
future = local_pool.submit(
|
|
345
345
|
_proxy_to_queue,
|