isolate 0.14.2__tar.gz → 0.15.0__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.14.2 → isolate-0.15.0}/.github/workflows/test.yml +1 -1
- {isolate-0.14.2 → isolate-0.15.0}/.pre-commit-config.yaml +4 -1
- {isolate-0.14.2 → isolate-0.15.0}/PKG-INFO +1 -1
- {isolate-0.14.2 → isolate-0.15.0}/pyproject.toml +4 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/_isolate_version.py +2 -2
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/backends/settings.py +32 -2
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/connections/_local/_base.py +3 -1
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/connections/grpc/_base.py +3 -1
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/connections/ipc/_base.py +3 -1
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/logger.py +4 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate.egg-info/PKG-INFO +1 -1
- {isolate-0.14.2 → isolate-0.15.0}/tests/test_backends.py +41 -0
- {isolate-0.14.2 → isolate-0.15.0}/tests/test_server.py +5 -3
- {isolate-0.14.2 → isolate-0.15.0}/.github/workflows/release.yml +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/.gitignore +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/LICENSE +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/README.md +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/setup.cfg +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/__init__.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/_version.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/backends/__init__.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/backends/_base.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/backends/common.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/backends/conda.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/backends/container.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/backends/local.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/backends/pyenv.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/backends/remote.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/backends/virtualenv.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/common/__init__.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/common/timestamp.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/connections/__init__.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/connections/_local/__init__.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/connections/_local/agent_startup.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/connections/common.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/connections/grpc/__init__.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/connections/grpc/agent.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/connections/grpc/configuration.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/connections/grpc/definitions/__init__.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/connections/grpc/definitions/agent.proto +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/connections/grpc/definitions/agent_pb2.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/connections/grpc/definitions/agent_pb2.pyi +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/connections/grpc/definitions/agent_pb2_grpc.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/connections/grpc/definitions/common.proto +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/connections/grpc/definitions/common_pb2.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/connections/grpc/definitions/common_pb2.pyi +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/connections/grpc/definitions/common_pb2_grpc.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/connections/grpc/interface.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/connections/ipc/__init__.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/connections/ipc/agent.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/logs.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/py.typed +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/registry.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/server/__init__.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/server/definitions/__init__.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/server/definitions/server.proto +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/server/definitions/server_pb2.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/server/definitions/server_pb2.pyi +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/server/definitions/server_pb2_grpc.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/server/health/__init__.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/server/health/health.proto +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/server/health/health_pb2.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/server/health/health_pb2.pyi +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/server/health/health_pb2_grpc.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/server/health_server.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/server/interface.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate/server/server.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate.egg-info/SOURCES.txt +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate.egg-info/dependency_links.txt +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate.egg-info/entry_points.txt +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate.egg-info/requires.txt +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/src/isolate.egg-info/top_level.txt +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/tests/__init__.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/tests/conftest.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/tests/test_concurrency.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/tests/test_connections.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/tests/test_isolate.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/tests/test_log.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/tests/test_logger.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/tests/test_serialization.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/tools/Dockerfile +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/tools/agent_requirements.txt +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/tools/protobuf-requirements.txt +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/tools/regen_grpc.py +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/tools/requirements.txt +0 -0
- {isolate-0.14.2 → isolate-0.15.0}/tools/test_agent_requirements.txt +0 -0
|
@@ -3,7 +3,10 @@ repos:
|
|
|
3
3
|
rev: 'v0.3.4'
|
|
4
4
|
hooks:
|
|
5
5
|
- id: ruff
|
|
6
|
-
args:
|
|
6
|
+
args:
|
|
7
|
+
- --fix
|
|
8
|
+
- --exit-non-zero-on-fix
|
|
9
|
+
- --exclude=UP007
|
|
7
10
|
exclude: ".*(_pb2.py|_pb2.pyi|_pb2_grpc.py)$"
|
|
8
11
|
- id: ruff-format
|
|
9
12
|
exclude: ".*(_pb2.py|_pb2.pyi|_pb2_grpc.py)$"
|
|
@@ -67,5 +67,9 @@ dev = [
|
|
|
67
67
|
target-version = "py38"
|
|
68
68
|
exclude = ["*_pb2.py", "*_pb2.pyi", "*_pb2_grpc.py"]
|
|
69
69
|
|
|
70
|
+
[tool.ruff.lint.pyupgrade]
|
|
71
|
+
# Preserve types, even if a file imports `from __future__ import annotations`.
|
|
72
|
+
keep-runtime-typing = true
|
|
73
|
+
|
|
70
74
|
[tool.ruff.lint]
|
|
71
75
|
select = ["E", "F", "W", "PLC", "PLE", "PLW", "I", "UP"]
|
|
@@ -11,7 +11,7 @@ from typing import TYPE_CHECKING, Callable, Iterator
|
|
|
11
11
|
from platformdirs import user_cache_dir
|
|
12
12
|
|
|
13
13
|
from isolate.backends.common import lock_build_path
|
|
14
|
-
from isolate.logs import Log
|
|
14
|
+
from isolate.logs import Log, LogLevel, LogSource
|
|
15
15
|
|
|
16
16
|
if TYPE_CHECKING:
|
|
17
17
|
from isolate.backends import BaseEnvironment
|
|
@@ -28,7 +28,37 @@ class IsolateSettings:
|
|
|
28
28
|
strict_cache: bool = _STRICT_CACHE
|
|
29
29
|
|
|
30
30
|
def log(self, log: Log) -> None:
|
|
31
|
-
self.log_hook(log)
|
|
31
|
+
self.log_hook(self._infer_log_level(log))
|
|
32
|
+
|
|
33
|
+
def _infer_log_level(self, log: Log) -> Log:
|
|
34
|
+
"""Infer the log level if it's correctly set."""
|
|
35
|
+
if log.level not in (LogLevel.STDOUT, LogLevel.STDERR):
|
|
36
|
+
# We should only infer the log level for stdout/stderr logs.
|
|
37
|
+
return log
|
|
38
|
+
|
|
39
|
+
if log.source in (LogSource.BUILDER, LogSource.BRIDGE):
|
|
40
|
+
return replace(log, level=LogLevel.TRACE)
|
|
41
|
+
|
|
42
|
+
line = log.message.lower()
|
|
43
|
+
|
|
44
|
+
if "[error]" in line:
|
|
45
|
+
return replace(log, level=LogLevel.ERROR)
|
|
46
|
+
if "[warning]" in line:
|
|
47
|
+
return replace(log, level=LogLevel.WARNING)
|
|
48
|
+
if "[warn]" in line:
|
|
49
|
+
return replace(log, level=LogLevel.WARNING)
|
|
50
|
+
if "[info]" in line:
|
|
51
|
+
return replace(log, level=LogLevel.INFO)
|
|
52
|
+
if "[debug]" in line:
|
|
53
|
+
return replace(log, level=LogLevel.DEBUG)
|
|
54
|
+
if "[trace]" in line:
|
|
55
|
+
return replace(log, level=LogLevel.TRACE)
|
|
56
|
+
|
|
57
|
+
if log.level == LogLevel.STDERR:
|
|
58
|
+
return replace(log, level=LogLevel.ERROR)
|
|
59
|
+
|
|
60
|
+
# Default to INFO level
|
|
61
|
+
return replace(log, level=LogLevel.INFO)
|
|
32
62
|
|
|
33
63
|
def _get_temp_base(self) -> Path:
|
|
34
64
|
"""Return the base path for creating temporary files/directories.
|
|
@@ -173,7 +173,9 @@ class PythonExecutionBase(Generic[ConnectionType]):
|
|
|
173
173
|
"""Return the command to run the agent process with."""
|
|
174
174
|
raise NotImplementedError
|
|
175
175
|
|
|
176
|
-
def handle_agent_log(
|
|
176
|
+
def handle_agent_log(
|
|
177
|
+
self, line: str, *, level: LogLevel, source: LogSource
|
|
178
|
+
) -> None:
|
|
177
179
|
"""Handle a log line emitted by the agent process. The level will be either
|
|
178
180
|
STDOUT or STDERR."""
|
|
179
181
|
raise NotImplementedError
|
|
@@ -147,5 +147,7 @@ class LocalPythonGRPC(PythonExecutionBase[str], GRPCExecutionBase):
|
|
|
147
147
|
str(log_fd),
|
|
148
148
|
]
|
|
149
149
|
|
|
150
|
-
def handle_agent_log(
|
|
150
|
+
def handle_agent_log(
|
|
151
|
+
self, line: str, *, level: LogLevel, source: LogSource
|
|
152
|
+
) -> None:
|
|
151
153
|
self.log(line, level=level, source=source)
|
|
@@ -219,5 +219,7 @@ class PythonIPC(PythonExecutionBase[AgentListener], IsolatedProcessConnection):
|
|
|
219
219
|
str(log_fd),
|
|
220
220
|
]
|
|
221
221
|
|
|
222
|
-
def handle_agent_log(
|
|
222
|
+
def handle_agent_log(
|
|
223
|
+
self, line: str, *, level: LogLevel, source: LogSource
|
|
224
|
+
) -> None:
|
|
223
225
|
self.log(line, level=level, source=source)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import os
|
|
3
|
+
from datetime import datetime, timezone
|
|
3
4
|
from typing import Dict
|
|
4
5
|
|
|
5
6
|
from isolate.logs import LogLevel, LogSource
|
|
@@ -16,6 +17,9 @@ class IsolateLogger:
|
|
|
16
17
|
|
|
17
18
|
def log(self, level: LogLevel, message: str, source: LogSource) -> None:
|
|
18
19
|
record = {
|
|
20
|
+
# Set the timestamp from source so we can be sure no buffering or
|
|
21
|
+
# latency is affecting the timestamp.
|
|
22
|
+
"logged_at": datetime.now(tz=timezone.utc).isoformat(),
|
|
19
23
|
"isolate_source": source.name,
|
|
20
24
|
"level": level.name,
|
|
21
25
|
"message": message,
|
|
@@ -16,6 +16,7 @@ from isolate.backends.pyenv import PyenvEnvironment, _get_pyenv_executable
|
|
|
16
16
|
from isolate.backends.remote import IsolateServer
|
|
17
17
|
from isolate.backends.settings import IsolateSettings
|
|
18
18
|
from isolate.backends.virtualenv import VirtualPythonEnvironment
|
|
19
|
+
from isolate.logs import LogLevel, LogSource
|
|
19
20
|
|
|
20
21
|
|
|
21
22
|
class GenericEnvironmentTests:
|
|
@@ -660,6 +661,46 @@ def test_isolate_server_logs(isolate_server):
|
|
|
660
661
|
assert "hello!!!" in [log.message for log in collected_logs]
|
|
661
662
|
|
|
662
663
|
|
|
664
|
+
def test_isolate_server_logs_level_inference(isolate_server):
|
|
665
|
+
collected_logs = []
|
|
666
|
+
environment = IsolateServer(
|
|
667
|
+
host=isolate_server,
|
|
668
|
+
target_environments=[
|
|
669
|
+
{
|
|
670
|
+
"kind": "virtualenv",
|
|
671
|
+
"configuration": {"requirements": ["pyjokes==0.5.0"]},
|
|
672
|
+
}
|
|
673
|
+
],
|
|
674
|
+
)
|
|
675
|
+
|
|
676
|
+
environment.apply_settings(IsolateSettings(log_hook=collected_logs.append))
|
|
677
|
+
|
|
678
|
+
with environment.connect() as connection:
|
|
679
|
+
connection.run(
|
|
680
|
+
partial(
|
|
681
|
+
eval,
|
|
682
|
+
"print('[debug] hello!!!') or "
|
|
683
|
+
"print('[error] bad!!!') or "
|
|
684
|
+
"print('[trace] hide!!!') or "
|
|
685
|
+
"print('[warning] warn1!!!') or "
|
|
686
|
+
"print('warn2!!! [warn]') or "
|
|
687
|
+
"print('default') or "
|
|
688
|
+
"__import__('time').sleep(0.5)",
|
|
689
|
+
)
|
|
690
|
+
)
|
|
691
|
+
|
|
692
|
+
user_logs = [log for log in collected_logs if log.source == LogSource.USER]
|
|
693
|
+
assert len(user_logs) == 6
|
|
694
|
+
assert [log.level for log in user_logs] == [
|
|
695
|
+
LogLevel.DEBUG,
|
|
696
|
+
LogLevel.ERROR,
|
|
697
|
+
LogLevel.TRACE,
|
|
698
|
+
LogLevel.WARNING,
|
|
699
|
+
LogLevel.WARNING,
|
|
700
|
+
LogLevel.INFO,
|
|
701
|
+
]
|
|
702
|
+
|
|
703
|
+
|
|
663
704
|
def test_isolate_server_demo(isolate_server):
|
|
664
705
|
from functools import partial
|
|
665
706
|
|
|
@@ -252,6 +252,7 @@ def test_user_logs_immediate(stub: definitions.IsolateStub, monkeypatch: Any) ->
|
|
|
252
252
|
import sys, pyjokes
|
|
253
253
|
print(pyjokes.__version__)
|
|
254
254
|
print("error error!", file=sys.stderr)
|
|
255
|
+
print("[debug] error!", file=sys.stderr)
|
|
255
256
|
"""
|
|
256
257
|
),
|
|
257
258
|
),
|
|
@@ -263,11 +264,12 @@ def test_user_logs_immediate(stub: definitions.IsolateStub, monkeypatch: Any) ->
|
|
|
263
264
|
user_logs: List[Log] = []
|
|
264
265
|
run_request(stub, request, user_logs=user_logs)
|
|
265
266
|
|
|
266
|
-
assert len(user_logs) ==
|
|
267
|
+
assert len(user_logs) == 3
|
|
267
268
|
|
|
268
269
|
by_stream = {log.level: log.message for log in user_logs}
|
|
269
|
-
assert by_stream[LogLevel.
|
|
270
|
-
assert by_stream[LogLevel.
|
|
270
|
+
assert by_stream[LogLevel.INFO] == "0.6.0"
|
|
271
|
+
assert by_stream[LogLevel.ERROR] == "error error!"
|
|
272
|
+
assert by_stream[LogLevel.DEBUG] == "[debug] error!"
|
|
271
273
|
|
|
272
274
|
|
|
273
275
|
def test_unknown_environment(stub: definitions.IsolateStub, monkeypatch: Any) -> None:
|
|
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.14.2 → isolate-0.15.0}/src/isolate/connections/grpc/definitions/agent_pb2_grpc.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{isolate-0.14.2 → isolate-0.15.0}/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
|