isolate 0.14.0__py3-none-any.whl → 0.14.2__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.
- isolate/_isolate_version.py +2 -2
- isolate/backends/common.py +1 -0
- isolate/logger.py +3 -0
- isolate/server/server.py +75 -25
- {isolate-0.14.0.dist-info → isolate-0.14.2.dist-info}/METADATA +1 -1
- {isolate-0.14.0.dist-info → isolate-0.14.2.dist-info}/RECORD +10 -10
- {isolate-0.14.0.dist-info → isolate-0.14.2.dist-info}/LICENSE +0 -0
- {isolate-0.14.0.dist-info → isolate-0.14.2.dist-info}/WHEEL +0 -0
- {isolate-0.14.0.dist-info → isolate-0.14.2.dist-info}/entry_points.txt +0 -0
- {isolate-0.14.0.dist-info → isolate-0.14.2.dist-info}/top_level.txt +0 -0
isolate/_isolate_version.py
CHANGED
isolate/backends/common.py
CHANGED
isolate/logger.py
CHANGED
|
@@ -9,6 +9,8 @@ from isolate.logs import LogLevel, LogSource
|
|
|
9
9
|
# but it handling `source` would be not trivial, so we are better off
|
|
10
10
|
# just keeping it simple for now.
|
|
11
11
|
class IsolateLogger:
|
|
12
|
+
extra_labels: Dict[str, str] = {}
|
|
13
|
+
|
|
12
14
|
def __init__(self, log_labels: Dict[str, str]):
|
|
13
15
|
self.log_labels = log_labels
|
|
14
16
|
|
|
@@ -18,6 +20,7 @@ class IsolateLogger:
|
|
|
18
20
|
"level": level.name,
|
|
19
21
|
"message": message,
|
|
20
22
|
**self.log_labels,
|
|
23
|
+
**self.extra_labels,
|
|
21
24
|
}
|
|
22
25
|
print(json.dumps(record))
|
|
23
26
|
|
isolate/server/server.py
CHANGED
|
@@ -36,6 +36,7 @@ from isolate.server.health_server import HealthServicer
|
|
|
36
36
|
from isolate.server.interface import from_grpc, to_grpc
|
|
37
37
|
|
|
38
38
|
EMPTY_MESSAGE_INTERVAL = float(os.getenv("ISOLATE_EMPTY_MESSAGE_INTERVAL", "600"))
|
|
39
|
+
SKIP_EMPTY_LOGS = os.getenv("ISOLATE_SKIP_EMPTY_LOGS") == "1"
|
|
39
40
|
MAX_GRPC_WAIT_TIMEOUT = float(os.getenv("ISOLATE_MAX_GRPC_WAIT_TIMEOUT", "10.0"))
|
|
40
41
|
|
|
41
42
|
# Whether to inherit all the packages from the current environment or not.
|
|
@@ -366,9 +367,7 @@ class IsolateServicer(definitions.IsolateServicer):
|
|
|
366
367
|
|
|
367
368
|
task = self.background_tasks[request.task_id]
|
|
368
369
|
|
|
369
|
-
task.logger =
|
|
370
|
-
dict(request.metadata.logger_labels)
|
|
371
|
-
)
|
|
370
|
+
task.logger.extra_labels = dict(request.metadata.logger_labels)
|
|
372
371
|
|
|
373
372
|
return definitions.SetMetadataResponse()
|
|
374
373
|
|
|
@@ -378,13 +377,19 @@ class IsolateServicer(definitions.IsolateServicer):
|
|
|
378
377
|
context: ServicerContext,
|
|
379
378
|
) -> Iterator[definitions.PartialRunResult]:
|
|
380
379
|
try:
|
|
381
|
-
|
|
380
|
+
# HACK: we can support only one task at a time for Run
|
|
381
|
+
# TODO: move away from this when we use submit for env-aware tasks
|
|
382
|
+
task = RunTask(request=request)
|
|
383
|
+
self.background_tasks["RUN"] = task
|
|
384
|
+
yield from self._run_task(task)
|
|
382
385
|
except GRPCException as exc:
|
|
383
386
|
return self.abort_with_msg(
|
|
384
387
|
exc.message,
|
|
385
388
|
context,
|
|
386
389
|
code=exc.code,
|
|
387
390
|
)
|
|
391
|
+
finally:
|
|
392
|
+
self.background_tasks.pop("RUN", None)
|
|
388
393
|
|
|
389
394
|
def List(
|
|
390
395
|
self,
|
|
@@ -464,7 +469,8 @@ class IsolateServicer(definitions.IsolateServicer):
|
|
|
464
469
|
return None
|
|
465
470
|
|
|
466
471
|
def cancel_tasks(self):
|
|
467
|
-
|
|
472
|
+
tasks_copy = self.background_tasks.copy()
|
|
473
|
+
for task in tasks_copy.values():
|
|
468
474
|
task.cancel()
|
|
469
475
|
|
|
470
476
|
|
|
@@ -484,8 +490,9 @@ class LogHandler:
|
|
|
484
490
|
task: RunTask
|
|
485
491
|
|
|
486
492
|
def handle(self, log: Log) -> None:
|
|
487
|
-
|
|
488
|
-
|
|
493
|
+
if not SKIP_EMPTY_LOGS or log.message.strip():
|
|
494
|
+
self.task.logger.log(log.level, log.message, source=log.source)
|
|
495
|
+
self._add_log_to_queue(log)
|
|
489
496
|
|
|
490
497
|
def _add_log_to_queue(self, log: Log) -> None:
|
|
491
498
|
grpc_log = cast(definitions.Log, to_grpc(log))
|
|
@@ -534,6 +541,16 @@ class SingleTaskInterceptor(ServerBoundInterceptor):
|
|
|
534
541
|
"""Sets server to terminate after the first Submit/Run task."""
|
|
535
542
|
|
|
536
543
|
_done: bool = False
|
|
544
|
+
_task_id: str | None = None
|
|
545
|
+
|
|
546
|
+
def __init__(self):
|
|
547
|
+
def terminate(request: Any, context: grpc.ServicerContext) -> Any:
|
|
548
|
+
context.abort(
|
|
549
|
+
grpc.StatusCode.RESOURCE_EXHAUSTED,
|
|
550
|
+
"Server has already served one Run/Submit task.",
|
|
551
|
+
)
|
|
552
|
+
|
|
553
|
+
self._terminator = grpc.unary_unary_rpc_method_handler(terminate)
|
|
537
554
|
|
|
538
555
|
def intercept_service(self, continuation, handler_call_details):
|
|
539
556
|
handler = continuation(handler_call_details)
|
|
@@ -542,29 +559,62 @@ class SingleTaskInterceptor(ServerBoundInterceptor):
|
|
|
542
559
|
is_run = handler_call_details.method == "/Isolate/Run"
|
|
543
560
|
is_new_task = is_submit or is_run
|
|
544
561
|
|
|
545
|
-
if is_new_task
|
|
546
|
-
raise grpc.RpcError(
|
|
547
|
-
grpc.StatusCode.UNAVAILABLE,
|
|
548
|
-
"Server has already served one Run/Submit task.",
|
|
549
|
-
)
|
|
550
|
-
elif is_new_task:
|
|
551
|
-
self._done = True
|
|
552
|
-
else:
|
|
562
|
+
if not is_new_task:
|
|
553
563
|
# Let other requests like List/Cancel/etc pass through
|
|
554
|
-
return
|
|
564
|
+
return handler
|
|
565
|
+
|
|
566
|
+
if self._done:
|
|
567
|
+
# Fail the request if the server has already served or is serving
|
|
568
|
+
# a Run/Submit task.
|
|
569
|
+
return self._terminator
|
|
570
|
+
|
|
571
|
+
self._done = True
|
|
555
572
|
|
|
556
573
|
def wrapper(method_impl):
|
|
557
574
|
@functools.wraps(method_impl)
|
|
558
|
-
def _wrapper(request, context):
|
|
559
|
-
def
|
|
560
|
-
if
|
|
561
|
-
|
|
562
|
-
|
|
575
|
+
def _wrapper(request: Any, context: grpc.ServicerContext) -> Any:
|
|
576
|
+
def termination() -> None:
|
|
577
|
+
if is_run:
|
|
578
|
+
print("Stopping server since run is finished")
|
|
579
|
+
# Stop the server after the Run task is finished
|
|
580
|
+
self.server.stop(grace=0.1)
|
|
581
|
+
|
|
582
|
+
elif is_submit:
|
|
583
|
+
# Wait until the task_id is assigned
|
|
584
|
+
while self._task_id is None:
|
|
563
585
|
time.sleep(0.1)
|
|
564
|
-
self.server.stop(grace=0.1)
|
|
565
586
|
|
|
566
|
-
|
|
567
|
-
|
|
587
|
+
# Get the task from the background tasks
|
|
588
|
+
task = self.servicer.background_tasks.get(self._task_id)
|
|
589
|
+
|
|
590
|
+
if task is not None:
|
|
591
|
+
# Wait until the task future is assigned
|
|
592
|
+
tries = 0
|
|
593
|
+
while task.future is None:
|
|
594
|
+
time.sleep(0.1)
|
|
595
|
+
tries += 1
|
|
596
|
+
if tries > 100:
|
|
597
|
+
raise RuntimeError(
|
|
598
|
+
"Task future was not assigned in time."
|
|
599
|
+
)
|
|
600
|
+
|
|
601
|
+
def _stop(*args):
|
|
602
|
+
# Small sleep to make sure the cancellation is processed
|
|
603
|
+
time.sleep(0.1)
|
|
604
|
+
print("Stopping server since the task is finished")
|
|
605
|
+
self.server.stop(grace=0.1)
|
|
606
|
+
|
|
607
|
+
# Add a callback which will stop the server
|
|
608
|
+
# after the task is finished
|
|
609
|
+
task.future.add_done_callback(_stop)
|
|
610
|
+
|
|
611
|
+
context.add_callback(termination)
|
|
612
|
+
res = method_impl(request, context)
|
|
613
|
+
|
|
614
|
+
if is_submit:
|
|
615
|
+
self._task_id = cast(definitions.SubmitResponse, res).task_id
|
|
616
|
+
|
|
617
|
+
return res
|
|
568
618
|
|
|
569
619
|
return _wrapper
|
|
570
620
|
|
|
@@ -598,7 +648,7 @@ def main(argv: list[str] | None = None) -> None:
|
|
|
598
648
|
server = grpc.server(
|
|
599
649
|
futures.ThreadPoolExecutor(max_workers=options.num_workers),
|
|
600
650
|
options=get_default_options(),
|
|
601
|
-
interceptors=interceptors,
|
|
651
|
+
interceptors=interceptors, # type: ignore
|
|
602
652
|
)
|
|
603
653
|
|
|
604
654
|
for interceptor in interceptors:
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
isolate/__init__.py,sha256=uXOKnONs7sXgARNgElwr4_A1sKoA6ACHVEvs3IDiX1M,127
|
|
2
|
-
isolate/_isolate_version.py,sha256=
|
|
2
|
+
isolate/_isolate_version.py,sha256=rlRT2sdhOGuXEsCM8RZA3pLtxwYV_87Qc0n3HT-mx2U,413
|
|
3
3
|
isolate/_version.py,sha256=05pXvy-yr5t3I1m9JMn42Ilzpg7fa8IB2J8a3G7t1cU,274
|
|
4
|
-
isolate/logger.py,sha256=
|
|
4
|
+
isolate/logger.py,sha256=gN_HzbvNkfloXw5iom6M7jL8e8VOgrMSi1Wp5I1eoX0,1522
|
|
5
5
|
isolate/logs.py,sha256=R_AHUVYD18z_PhtK_mDWi9Gch79CxmwHY09hUDShtwg,2079
|
|
6
6
|
isolate/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
7
|
isolate/registry.py,sha256=hpzv4HI7iihG5I7i5r8Pb257ibhEKY18xQcG-w1-BgI,1590
|
|
8
8
|
isolate/backends/__init__.py,sha256=LLrSM7UnDFW8tIT5oYlE1wVJrxKcaj_v7cFwvTjQTlc,119
|
|
9
9
|
isolate/backends/_base.py,sha256=Kt5pkhDzXZblq4vxaM3DQTo-Bj-7pIRZFlqJR7OfejY,4112
|
|
10
|
-
isolate/backends/common.py,sha256=
|
|
10
|
+
isolate/backends/common.py,sha256=GzmgzIkCY90elMH_7lpj-LwRNu-GLia2j4PrS6zNHwA,8567
|
|
11
11
|
isolate/backends/conda.py,sha256=S5q5bdY787AMTck2iMGtwu-LHMH4a1qCIjNHDKTkqok,7649
|
|
12
12
|
isolate/backends/container.py,sha256=MCQJbcmQvRUS-tTgTW_pKYBMKwSJO2KZsLeaBMXpPC0,1645
|
|
13
13
|
isolate/backends/local.py,sha256=woxe4dmXuEHxWKsGNndoRA1_sP6yG-dg6tlFZni0mZc,1360
|
|
@@ -42,7 +42,7 @@ isolate/connections/ipc/agent.py,sha256=hGlL4x78FhRvMZ4DkVh3dk-EmWQqxHW4LIipgyOk
|
|
|
42
42
|
isolate/server/__init__.py,sha256=7R3GuWmxuqe0q28rVqETJN9OCrP_-Svjv9h0NR1GFL0,79
|
|
43
43
|
isolate/server/health_server.py,sha256=yN7F1Q28DdX8-Zk3gef7XcQEE25XwlHwzV5GBM75aQM,1249
|
|
44
44
|
isolate/server/interface.py,sha256=nGbjdxrN0p9m1LNdeds8NIoJOwPYW2NM6ktmbhfG4_s,687
|
|
45
|
-
isolate/server/server.py,sha256=
|
|
45
|
+
isolate/server/server.py,sha256=41Y_3dtUmeJR8RuQF2VMC5x_kM_k0w1hyzPFl5uW5Do,23477
|
|
46
46
|
isolate/server/definitions/__init__.py,sha256=f_Q3pdjMuZrjgNlbM60btFKiB1Vg8cnVyKEbp0RmU0A,572
|
|
47
47
|
isolate/server/definitions/server.proto,sha256=UihlFbYG8fbwm0IUfKDRH1vNkopzP3C-wplXXcAO1c8,1761
|
|
48
48
|
isolate/server/definitions/server_pb2.py,sha256=TYBJC_z_dNf2J6FgHukY9mDyc3WBt9EPQOVFd_ayQNc,4304
|
|
@@ -53,9 +53,9 @@ isolate/server/health/health.proto,sha256=wE2_QD0OQAblKkEBG7sALLXEOj1mOLKG-FbC4t
|
|
|
53
53
|
isolate/server/health/health_pb2.py,sha256=onOdP3M4Tpqhqs2PlGcyfoKe2VVKUEDx5ALeRcObb9A,1899
|
|
54
54
|
isolate/server/health/health_pb2.pyi,sha256=AK-DPCpJzoYhU6DydD856c0Ywx84x6k-Cs4m6HpNv5A,2459
|
|
55
55
|
isolate/server/health/health_pb2_grpc.py,sha256=XgsULrnRBmYIqvKr8eI7bqs6NIea5A0kkqdOOc2JHBY,5303
|
|
56
|
-
isolate-0.14.
|
|
57
|
-
isolate-0.14.
|
|
58
|
-
isolate-0.14.
|
|
59
|
-
isolate-0.14.
|
|
60
|
-
isolate-0.14.
|
|
61
|
-
isolate-0.14.
|
|
56
|
+
isolate-0.14.2.dist-info/LICENSE,sha256=427vuyirL5scgBLqA9UWcdnxKrtSGc0u_JfUupk6lAA,11359
|
|
57
|
+
isolate-0.14.2.dist-info/METADATA,sha256=kFsnmpSczOcMgcM6idLXEuVDLWyOD8oG7MR2hV2x8KI,3191
|
|
58
|
+
isolate-0.14.2.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
|
59
|
+
isolate-0.14.2.dist-info/entry_points.txt,sha256=s3prh2EERaVCbL8R45tfY5WFPZ1TsYOsz305YR7s-Pc,360
|
|
60
|
+
isolate-0.14.2.dist-info/top_level.txt,sha256=W9QJBHcq5WXRkbOXf25bvftzFsOZZN4n1DAatdroZrs,8
|
|
61
|
+
isolate-0.14.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|