splime 0.1.4__tar.gz → 0.2.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.
- {splime-0.1.4/src/splime.egg-info → splime-0.2.0}/PKG-INFO +3 -2
- {splime-0.1.4 → splime-0.2.0}/README.md +2 -1
- {splime-0.1.4 → splime-0.2.0}/pyproject.toml +1 -1
- {splime-0.1.4 → splime-0.2.0}/src/spl/__init__.py +2 -2
- splime-0.1.4/src/spl/client.py → splime-0.2.0/src/spl/_client.py +53 -278
- splime-0.2.0/src/spl/_deprecate.py +36 -0
- splime-0.2.0/src/spl/client.py +65 -0
- splime-0.2.0/src/spl/core/common.py +46 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/core/entities/node_remote.py +29 -5
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/cli.py +43 -2
- splime-0.2.0/src/spl/daemon/doctor.py +365 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/repositories/object.py +6 -2
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/routes/runs.py +6 -1
- splime-0.2.0/src/spl/daemon/run_progress.py +107 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/server.py +41 -3
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/worker.py +1 -1
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon_client.py +186 -16
- {splime-0.1.4 → splime-0.2.0/src/splime.egg-info}/PKG-INFO +3 -2
- {splime-0.1.4 → splime-0.2.0}/src/splime.egg-info/SOURCES.txt +5 -0
- {splime-0.1.4 → splime-0.2.0}/LICENSE +0 -0
- {splime-0.1.4 → splime-0.2.0}/NOTICE +0 -0
- {splime-0.1.4 → splime-0.2.0}/setup.cfg +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/core/__init__.py +0 -0
- /splime-0.1.4/src/spl/core/common.py → /splime-0.2.0/src/spl/core/_common.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/core/entities/__init__.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/core/entities/adapter.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/core/entities/artifact.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/core/entities/control.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/core/entities/distribution.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/core/entities/function.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/core/entities/local_function.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/core/entities/misc.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/core/entities/module.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/core/entities/node.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/core/entities/node_function.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/core/entities/pipeline.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/core/entities/scalar.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/core/ir/__init__.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/core/ir/common.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/core/ir/parse.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/core/ir/unparse.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/core/ir/utils.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/__init__.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/__main__.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/canonical.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/client.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/docker_environment.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/docker_pool.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/environment.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/environment_base.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/heartbeat_service.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/metadata.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/remote_client.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/repositories/__init__.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/repositories/env.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/repositories/library.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/repositories/run.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/repositories/server_connection.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/repositories/sync_event.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/routes/__init__.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/routes/_helpers.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/routes/artifacts.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/routes/diagnostics.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/routes/envs.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/routes/libraries.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/routes/objects.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/routes/remote.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/routes/server_connections.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/runtime_backend.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/runtime_config.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/runtime_dependencies.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/secret_store.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/server_connection.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/services/__init__.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/services/sync.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/signature.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/storage_base.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/daemon/store.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/pipeline_widget.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/py.typed +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/spl/server_client.py +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/splime.egg-info/dependency_links.txt +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/splime.egg-info/entry_points.txt +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/splime.egg-info/requires.txt +0 -0
- {splime-0.1.4 → splime-0.2.0}/src/splime.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: splime
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Reuse Python functions across projects without rewriting or redeploying them.
|
|
5
5
|
Author-email: Yastrebov Kirill <yastrebovks@gmail.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -105,7 +105,8 @@ client.publish(daily_total, name="daily_total")
|
|
|
105
105
|
|
|
106
106
|
result = client.call("daily_total", kwargs={"date": "2026-06-08"})
|
|
107
107
|
print(result.mode) # "local"
|
|
108
|
-
print(result.output) # 42.0 (
|
|
108
|
+
print(result.output) # 42.0 (.output always yields the plain value;
|
|
109
|
+
# for pipelines .value keeps the raw port dict)
|
|
109
110
|
```
|
|
110
111
|
|
|
111
112
|
That is the whole loop: define a function, `publish` it as a versioned node, then `call`
|
|
@@ -53,7 +53,8 @@ client.publish(daily_total, name="daily_total")
|
|
|
53
53
|
|
|
54
54
|
result = client.call("daily_total", kwargs={"date": "2026-06-08"})
|
|
55
55
|
print(result.mode) # "local"
|
|
56
|
-
print(result.output) # 42.0 (
|
|
56
|
+
print(result.output) # 42.0 (.output always yields the plain value;
|
|
57
|
+
# for pipelines .value keeps the raw port dict)
|
|
57
58
|
```
|
|
58
59
|
|
|
59
60
|
That is the whole loop: define a function, `publish` it as a versioned node, then `call`
|
|
@@ -2,9 +2,9 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
__path__ = __import__("pkgutil").extend_path(__path__, __name__)
|
|
4
4
|
|
|
5
|
-
from spl.
|
|
5
|
+
from spl._client import PublishedObject, RemoteResult, RemoteRun, SPLClient
|
|
6
6
|
from spl.core import spl_export_to_dir, spl_export_to_file, spl_import_from_file
|
|
7
|
-
from spl.core.
|
|
7
|
+
from spl.core._common import Deployment, lift
|
|
8
8
|
from spl.core.entities.distribution import DDistribution
|
|
9
9
|
from spl.core.entities.node import DEFAULT_PORT, InputPort, OutputPort
|
|
10
10
|
from spl.core.entities.node_remote import NodeRemote
|
|
@@ -4,7 +4,7 @@ This module is the thin "framework side" of the daemon integration. Code that
|
|
|
4
4
|
already uses SPL should not need to know about HTTP endpoints, run directories,
|
|
5
5
|
or worker subprocesses. The intended workflow is:
|
|
6
6
|
|
|
7
|
-
from spl
|
|
7
|
+
from spl import SPLClient
|
|
8
8
|
|
|
9
9
|
client = SPLClient()
|
|
10
10
|
client.publish(my_function, name="sum", env="default")
|
|
@@ -18,7 +18,6 @@ dependencies imported yet.
|
|
|
18
18
|
|
|
19
19
|
from __future__ import annotations
|
|
20
20
|
|
|
21
|
-
import warnings
|
|
22
21
|
from dataclasses import dataclass, field, replace
|
|
23
22
|
from html import escape
|
|
24
23
|
from pathlib import Path
|
|
@@ -31,12 +30,15 @@ from spl.daemon_client import (
|
|
|
31
30
|
DEFAULT_SERVER_URL,
|
|
32
31
|
Client,
|
|
33
32
|
ClientError,
|
|
33
|
+
RunProgressPrinter,
|
|
34
|
+
RunStateCallback,
|
|
34
35
|
)
|
|
35
36
|
from spl.server_client import SPLServerClient
|
|
36
37
|
|
|
37
38
|
OfflinePolicy = Literal["queue", "wait", "fail_fast"]
|
|
38
39
|
ObjectScope = Literal["auto", "local", "server", "all"]
|
|
39
40
|
RunSource = Literal["auto", "local"]
|
|
41
|
+
ProgressOption = bool | RunStateCallback
|
|
40
42
|
_NO_SERVER_CONNECTION_MESSAGE = "active server connection is not found"
|
|
41
43
|
|
|
42
44
|
|
|
@@ -54,15 +56,18 @@ def _is_missing_server_connection(exc: Exception) -> bool:
|
|
|
54
56
|
)
|
|
55
57
|
|
|
56
58
|
|
|
57
|
-
def
|
|
58
|
-
"""
|
|
59
|
+
def _progress_callback(progress: ProgressOption) -> RunStateCallback | None:
|
|
60
|
+
"""Turn a ``progress`` option into a wait-loop state callback.
|
|
59
61
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
62
|
+
``True`` builds a fresh stderr printer (fresh throttling state per wait),
|
|
63
|
+
``False`` disables feedback, and a callable is passed through as-is.
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
if callable(progress):
|
|
67
|
+
return progress
|
|
68
|
+
if progress:
|
|
69
|
+
return RunProgressPrinter()
|
|
70
|
+
return None
|
|
66
71
|
|
|
67
72
|
|
|
68
73
|
@dataclass(frozen=True, repr=False)
|
|
@@ -378,20 +383,30 @@ class RemoteRun:
|
|
|
378
383
|
*,
|
|
379
384
|
poll_interval: float = 0.25,
|
|
380
385
|
timeout_seconds: float | None = None,
|
|
386
|
+
progress: ProgressOption = True,
|
|
381
387
|
) -> dict[str, Any]:
|
|
382
|
-
"""Wait until the run succeeds or fails, then return final state.
|
|
388
|
+
"""Wait until the run succeeds or fails, then return final state.
|
|
389
|
+
|
|
390
|
+
``progress`` controls feedback during slow phases (first-run
|
|
391
|
+
environment builds, queued server-side runs): ``True`` prints short
|
|
392
|
+
status lines to stderr, ``False`` waits silently, and a callable
|
|
393
|
+
receives every polled state instead.
|
|
394
|
+
"""
|
|
383
395
|
|
|
396
|
+
on_state = _progress_callback(progress)
|
|
384
397
|
if self.server_side:
|
|
385
398
|
self.state = self._client._daemon.wait_remote_run(
|
|
386
399
|
self.id,
|
|
387
400
|
poll_interval=poll_interval,
|
|
388
401
|
timeout_seconds=timeout_seconds,
|
|
402
|
+
on_state=on_state,
|
|
389
403
|
)
|
|
390
404
|
else:
|
|
391
405
|
self.state = self._client._daemon.wait_run(
|
|
392
406
|
self.id,
|
|
393
407
|
poll_interval=poll_interval,
|
|
394
408
|
timeout_seconds=timeout_seconds,
|
|
409
|
+
on_state=on_state,
|
|
395
410
|
)
|
|
396
411
|
return self.state
|
|
397
412
|
|
|
@@ -437,12 +452,17 @@ class RemoteRun:
|
|
|
437
452
|
artifacts_dir: str | Path | None = None,
|
|
438
453
|
poll_interval: float = 0.25,
|
|
439
454
|
timeout_seconds: float | None = None,
|
|
455
|
+
progress: ProgressOption = True,
|
|
440
456
|
) -> RemoteResult:
|
|
441
|
-
"""Wait for completion, return result, and optionally download artifacts.
|
|
457
|
+
"""Wait for completion, return result, and optionally download artifacts.
|
|
458
|
+
|
|
459
|
+
See :meth:`wait` for the meaning of ``progress``.
|
|
460
|
+
"""
|
|
442
461
|
|
|
443
462
|
final_state = self.wait(
|
|
444
463
|
poll_interval=poll_interval,
|
|
445
464
|
timeout_seconds=timeout_seconds,
|
|
465
|
+
progress=progress,
|
|
446
466
|
)
|
|
447
467
|
if final_state["status"] != "succeeded":
|
|
448
468
|
error = final_state.get("error") or "run returned no error message"
|
|
@@ -754,139 +774,10 @@ class SPLClient:
|
|
|
754
774
|
return []
|
|
755
775
|
return self._daemon.server_libraries(include_accessible=include_accessible)
|
|
756
776
|
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
display_name: str | None = None,
|
|
762
|
-
description: str = "",
|
|
763
|
-
visibility: str = "private",
|
|
764
|
-
default_machine: str | None = None,
|
|
765
|
-
execution: dict[str, Any] | None = None,
|
|
766
|
-
) -> dict[str, Any]:
|
|
767
|
-
"""Deprecated alias of :meth:`library.create` (see docs/migration-0.2.0.md)."""
|
|
768
|
-
|
|
769
|
-
_warn_deprecated("SPLClient.create_library()", "SPLClient.library.create()")
|
|
770
|
-
return self.library.create(
|
|
771
|
-
slug,
|
|
772
|
-
display_name=display_name,
|
|
773
|
-
description=description,
|
|
774
|
-
visibility=visibility,
|
|
775
|
-
default_machine=default_machine,
|
|
776
|
-
execution=execution,
|
|
777
|
-
)
|
|
778
|
-
|
|
779
|
-
def get_library(self, ref: str) -> dict[str, Any]:
|
|
780
|
-
"""Deprecated alias of :meth:`library.get`."""
|
|
781
|
-
|
|
782
|
-
_warn_deprecated("SPLClient.get_library()", "SPLClient.library.get()")
|
|
783
|
-
return self.library.get(ref)
|
|
784
|
-
|
|
785
|
-
def update_library(
|
|
786
|
-
self,
|
|
787
|
-
ref: str,
|
|
788
|
-
*,
|
|
789
|
-
display_name: str | None = None,
|
|
790
|
-
description: str | None = None,
|
|
791
|
-
visibility: str | None = None,
|
|
792
|
-
default_machine: str | None = None,
|
|
793
|
-
execution: dict[str, Any] | None = None,
|
|
794
|
-
) -> dict[str, Any]:
|
|
795
|
-
"""Deprecated alias of :meth:`library.update`."""
|
|
796
|
-
|
|
797
|
-
_warn_deprecated("SPLClient.update_library()", "SPLClient.library.update()")
|
|
798
|
-
return self.library.update(
|
|
799
|
-
ref,
|
|
800
|
-
display_name=display_name,
|
|
801
|
-
description=description,
|
|
802
|
-
visibility=visibility,
|
|
803
|
-
default_machine=default_machine,
|
|
804
|
-
execution=execution,
|
|
805
|
-
)
|
|
806
|
-
|
|
807
|
-
def delete_library(self, ref: str) -> dict[str, Any]:
|
|
808
|
-
"""Deprecated alias of :meth:`library.delete`."""
|
|
809
|
-
|
|
810
|
-
_warn_deprecated("SPLClient.delete_library()", "SPLClient.library.delete()")
|
|
811
|
-
return self.library.delete(ref)
|
|
812
|
-
|
|
813
|
-
def grant_library(
|
|
814
|
-
self,
|
|
815
|
-
ref: str,
|
|
816
|
-
grantee: str,
|
|
817
|
-
*,
|
|
818
|
-
grantee_type: str = "user",
|
|
819
|
-
scopes: list[str] | None = None,
|
|
820
|
-
) -> dict[str, Any]:
|
|
821
|
-
"""Deprecated alias of :meth:`library.grant`."""
|
|
822
|
-
|
|
823
|
-
_warn_deprecated("SPLClient.grant_library()", "SPLClient.library.grant()")
|
|
824
|
-
return self.library.grant(
|
|
825
|
-
ref,
|
|
826
|
-
grantee,
|
|
827
|
-
grantee_type=grantee_type,
|
|
828
|
-
scopes=scopes,
|
|
829
|
-
)
|
|
830
|
-
|
|
831
|
-
def revoke_library_grant(self, ref: str, grantee: str) -> dict[str, Any]:
|
|
832
|
-
"""Deprecated alias of :meth:`library.revoke`."""
|
|
833
|
-
|
|
834
|
-
_warn_deprecated(
|
|
835
|
-
"SPLClient.revoke_library_grant()", "SPLClient.library.revoke()",
|
|
836
|
-
)
|
|
837
|
-
return self.library.revoke(ref, grantee)
|
|
838
|
-
|
|
839
|
-
def add_reference(
|
|
840
|
-
self,
|
|
841
|
-
into_library: str,
|
|
842
|
-
name: str,
|
|
843
|
-
*,
|
|
844
|
-
owner: str | None = None,
|
|
845
|
-
from_library: str = "default",
|
|
846
|
-
version: str | int | None = "latest",
|
|
847
|
-
alias: str | None = None,
|
|
848
|
-
) -> dict[str, Any]:
|
|
849
|
-
"""Deprecated alias of :meth:`library.add_reference`."""
|
|
850
|
-
|
|
851
|
-
_warn_deprecated(
|
|
852
|
-
"SPLClient.add_reference()", "SPLClient.library.add_reference()",
|
|
853
|
-
)
|
|
854
|
-
return self.library.add_reference(
|
|
855
|
-
into_library,
|
|
856
|
-
name,
|
|
857
|
-
owner=owner,
|
|
858
|
-
from_library=from_library,
|
|
859
|
-
version=version,
|
|
860
|
-
alias=alias,
|
|
861
|
-
)
|
|
862
|
-
|
|
863
|
-
def copy_object(
|
|
864
|
-
self,
|
|
865
|
-
name: str,
|
|
866
|
-
*,
|
|
867
|
-
into_library: str,
|
|
868
|
-
from_owner: str | None = None,
|
|
869
|
-
from_library: str = "default",
|
|
870
|
-
version: str | int | None = "latest",
|
|
871
|
-
new_name: str | None = None,
|
|
872
|
-
) -> dict[str, Any]:
|
|
873
|
-
"""Deprecated alias of :meth:`library.copy_object`."""
|
|
874
|
-
|
|
875
|
-
_warn_deprecated("SPLClient.copy_object()", "SPLClient.library.copy_object()")
|
|
876
|
-
return self.library.copy_object(
|
|
877
|
-
name,
|
|
878
|
-
into_library=into_library,
|
|
879
|
-
from_owner=from_owner,
|
|
880
|
-
from_library=from_library,
|
|
881
|
-
version=version,
|
|
882
|
-
new_name=new_name,
|
|
883
|
-
)
|
|
884
|
-
|
|
885
|
-
def remove_entry(self, library: str, name: str) -> dict[str, Any]:
|
|
886
|
-
"""Deprecated alias of :meth:`library.remove_entry`."""
|
|
887
|
-
|
|
888
|
-
_warn_deprecated("SPLClient.remove_entry()", "SPLClient.library.remove_entry()")
|
|
889
|
-
return self.library.remove_entry(library, name)
|
|
777
|
+
# The flat library aliases (create_library, get_library, update_library,
|
|
778
|
+
# delete_library, grant_library, revoke_library_grant, add_reference,
|
|
779
|
+
# copy_object, remove_entry) warned through 0.1.4/0.1.5 and were removed
|
|
780
|
+
# in 0.2.0 — use ``client.library.*`` (docs/migration-0.2.0.md).
|
|
890
781
|
|
|
891
782
|
def register_env(self, name: str = "default", python: str | None = None) -> dict[str, Any]:
|
|
892
783
|
"""Register a Python executable as a daemon environment.
|
|
@@ -1019,41 +910,8 @@ class SPLClient:
|
|
|
1019
910
|
raw=record,
|
|
1020
911
|
)
|
|
1021
912
|
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
_warn_deprecated("SPLClient.local_objects()", "SPLClient.objects(scope='local')")
|
|
1026
|
-
return self._object_records(self.objects(scope="local", compact=compact))
|
|
1027
|
-
|
|
1028
|
-
def server_objects(
|
|
1029
|
-
self,
|
|
1030
|
-
*,
|
|
1031
|
-
owner: str | None = None,
|
|
1032
|
-
library: str | None = None,
|
|
1033
|
-
compact: bool = False,
|
|
1034
|
-
) -> list[dict[str, Any]]:
|
|
1035
|
-
"""Deprecated alias of :meth:`objects` with ``scope='server'``."""
|
|
1036
|
-
|
|
1037
|
-
_warn_deprecated(
|
|
1038
|
-
"SPLClient.server_objects()", "SPLClient.objects(scope='server')",
|
|
1039
|
-
)
|
|
1040
|
-
return list(
|
|
1041
|
-
self.objects(
|
|
1042
|
-
scope="server",
|
|
1043
|
-
owner=owner,
|
|
1044
|
-
library=library,
|
|
1045
|
-
compact=compact,
|
|
1046
|
-
)
|
|
1047
|
-
)
|
|
1048
|
-
|
|
1049
|
-
@staticmethod
|
|
1050
|
-
def _object_records(records: dict[str, Any] | list[dict[str, Any]]) -> list[dict[str, Any]]:
|
|
1051
|
-
if isinstance(records, list):
|
|
1052
|
-
return list(records)
|
|
1053
|
-
return [
|
|
1054
|
-
dict(record) if isinstance(record, dict) else {"name": name, "value": record}
|
|
1055
|
-
for name, record in records.items()
|
|
1056
|
-
]
|
|
913
|
+
# ``local_objects()``/``server_objects()`` warned through 0.1.4/0.1.5 and
|
|
914
|
+
# were removed in 0.2.0 — use ``objects(scope='local'/'server')``.
|
|
1057
915
|
|
|
1058
916
|
@overload
|
|
1059
917
|
def objects(
|
|
@@ -1335,7 +1193,7 @@ class SPLClient:
|
|
|
1335
1193
|
pipeline = pipeline.name
|
|
1336
1194
|
|
|
1337
1195
|
if isinstance(pipeline, NodeRemote):
|
|
1338
|
-
if version is not None and pipeline.version not in {"", "latest", "current"
|
|
1196
|
+
if version is not None and pipeline.version not in {"", "latest", "current"}:
|
|
1339
1197
|
raise ValueError("pass the version either on NodeRemote or draw_pipeline(...), not both")
|
|
1340
1198
|
response = self._remote_decomposition_response(pipeline, version=version)
|
|
1341
1199
|
decomposition = response["decomposition"]
|
|
@@ -1557,11 +1415,8 @@ class SPLClient:
|
|
|
1557
1415
|
)
|
|
1558
1416
|
return RemoteRun(self, state, server_side=remote)
|
|
1559
1417
|
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
_warn_deprecated("SPLClient.start()", "SPLClient.submit()")
|
|
1564
|
-
return self._start_run(name, **kwargs)
|
|
1418
|
+
# ``start()`` warned through 0.1.4/0.1.5 and was removed in 0.2.0 — use
|
|
1419
|
+
# :meth:`submit` (same signature and behavior).
|
|
1565
1420
|
|
|
1566
1421
|
def submit(
|
|
1567
1422
|
self,
|
|
@@ -1599,38 +1454,8 @@ class SPLClient:
|
|
|
1599
1454
|
source=source,
|
|
1600
1455
|
)
|
|
1601
1456
|
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
name: str,
|
|
1605
|
-
*,
|
|
1606
|
-
args: list[Any] | None = None,
|
|
1607
|
-
kwargs: dict[str, Any] | None = None,
|
|
1608
|
-
output: str | None = None,
|
|
1609
|
-
timeout_seconds: float | None = None,
|
|
1610
|
-
target_machine: str,
|
|
1611
|
-
owner: str | None = None,
|
|
1612
|
-
library: str | None = None,
|
|
1613
|
-
function: str | None = None,
|
|
1614
|
-
source: RunSource = "auto",
|
|
1615
|
-
) -> RemoteRun:
|
|
1616
|
-
"""Deprecated alias of :meth:`submit` with ``offline_policy='queue'``."""
|
|
1617
|
-
|
|
1618
|
-
_warn_deprecated(
|
|
1619
|
-
"SPLClient.queue()", "SPLClient.submit(..., offline_policy='queue')",
|
|
1620
|
-
)
|
|
1621
|
-
return self._start_run(
|
|
1622
|
-
name,
|
|
1623
|
-
args=args,
|
|
1624
|
-
kwargs=kwargs,
|
|
1625
|
-
output=output,
|
|
1626
|
-
timeout_seconds=timeout_seconds,
|
|
1627
|
-
target_machine=target_machine,
|
|
1628
|
-
owner=owner,
|
|
1629
|
-
library=library,
|
|
1630
|
-
function=function,
|
|
1631
|
-
offline_policy="queue",
|
|
1632
|
-
source=source,
|
|
1633
|
-
)
|
|
1457
|
+
# ``queue()`` warned through 0.1.4/0.1.5 and was removed in 0.2.0 — use
|
|
1458
|
+
# ``submit(..., offline_policy='queue')``.
|
|
1634
1459
|
|
|
1635
1460
|
def call(
|
|
1636
1461
|
self,
|
|
@@ -1647,6 +1472,7 @@ class SPLClient:
|
|
|
1647
1472
|
offline_policy: OfflinePolicy | None = None,
|
|
1648
1473
|
function: str | None = None,
|
|
1649
1474
|
source: RunSource = "auto",
|
|
1475
|
+
progress: ProgressOption = True,
|
|
1650
1476
|
) -> RemoteResult:
|
|
1651
1477
|
"""Run an object, wait for completion, and return result/artifacts.
|
|
1652
1478
|
|
|
@@ -1654,6 +1480,11 @@ class SPLClient:
|
|
|
1654
1480
|
call. Passing ``target_machine``, ``owner``, or ``library`` makes it a
|
|
1655
1481
|
server-side remote run through the daemon. The returned
|
|
1656
1482
|
``RemoteResult.mode`` is therefore either ``"local"`` or ``"server"``.
|
|
1483
|
+
|
|
1484
|
+
While waiting, slow phases (a first-run environment build, a queued
|
|
1485
|
+
server-side run) print short progress lines to stderr. Pass
|
|
1486
|
+
``progress=False`` to wait silently, or a callable to receive every
|
|
1487
|
+
polled run state instead.
|
|
1657
1488
|
"""
|
|
1658
1489
|
|
|
1659
1490
|
run = self._start_run(
|
|
@@ -1672,6 +1503,7 @@ class SPLClient:
|
|
|
1672
1503
|
return run.collect(
|
|
1673
1504
|
artifacts_dir=artifacts_dir,
|
|
1674
1505
|
timeout_seconds=timeout_seconds,
|
|
1506
|
+
progress=progress,
|
|
1675
1507
|
)
|
|
1676
1508
|
|
|
1677
1509
|
def _run_node_value(
|
|
@@ -1691,66 +1523,9 @@ class SPLClient:
|
|
|
1691
1523
|
)
|
|
1692
1524
|
return response.get("value")
|
|
1693
1525
|
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
kwargs: dict[str, Any],
|
|
1698
|
-
*,
|
|
1699
|
-
timeout_seconds: float | None = None,
|
|
1700
|
-
) -> Any:
|
|
1701
|
-
"""Deprecated: run a ``NodeRemote`` directly.
|
|
1702
|
-
|
|
1703
|
-
Wire the node into a pipeline instead:
|
|
1704
|
-
``Deployment(client, lift(node)...).run(...)``.
|
|
1705
|
-
"""
|
|
1706
|
-
|
|
1707
|
-
_warn_deprecated(
|
|
1708
|
-
"SPLClient.run_node()",
|
|
1709
|
-
"Deployment(client, pipeline).run(...) with NodeRemote.locate(...)",
|
|
1710
|
-
)
|
|
1711
|
-
return self._run_node_value(node, kwargs, timeout_seconds=timeout_seconds)
|
|
1712
|
-
|
|
1713
|
-
def run_node_result(
|
|
1714
|
-
self,
|
|
1715
|
-
node: Any,
|
|
1716
|
-
*,
|
|
1717
|
-
kwargs: dict[str, Any] | None = None,
|
|
1718
|
-
timeout_seconds: float | None = None,
|
|
1719
|
-
) -> RemoteResult:
|
|
1720
|
-
"""Deprecated: run a ``NodeRemote`` and return metadata plus the value.
|
|
1721
|
-
|
|
1722
|
-
Wire the node into a pipeline instead:
|
|
1723
|
-
``Deployment(client, pipeline).run(...)``.
|
|
1724
|
-
"""
|
|
1725
|
-
|
|
1726
|
-
_warn_deprecated(
|
|
1727
|
-
"SPLClient.run_node_result()",
|
|
1728
|
-
"Deployment(client, pipeline).run(...) with NodeRemote.locate(...)",
|
|
1729
|
-
)
|
|
1730
|
-
payload = self._remote_node_payload(node)
|
|
1731
|
-
response = self._daemon.run_remote_node(
|
|
1732
|
-
payload,
|
|
1733
|
-
kwargs=kwargs or {},
|
|
1734
|
-
timeout_seconds=timeout_seconds,
|
|
1735
|
-
)
|
|
1736
|
-
value = response.get("value")
|
|
1737
|
-
raw_payload = response.get("payload")
|
|
1738
|
-
result_payload = dict(raw_payload) if isinstance(raw_payload, dict) else {}
|
|
1739
|
-
result_payload["result"] = value
|
|
1740
|
-
result_payload.setdefault("artifacts", response.get("artifacts") or {})
|
|
1741
|
-
|
|
1742
|
-
run = response.get("run")
|
|
1743
|
-
if not isinstance(run, dict):
|
|
1744
|
-
run = {
|
|
1745
|
-
"id": response.get("run_id"),
|
|
1746
|
-
"status": response.get("status") or "succeeded",
|
|
1747
|
-
}
|
|
1748
|
-
return RemoteResult(
|
|
1749
|
-
run=run,
|
|
1750
|
-
payload=result_payload,
|
|
1751
|
-
mode="server",
|
|
1752
|
-
downloaded_artifacts={},
|
|
1753
|
-
)
|
|
1526
|
+
# ``run_node()``/``run_node_result()`` warned through 0.1.4/0.1.5 and were
|
|
1527
|
+
# removed in 0.2.0 — wire the node into a pipeline instead:
|
|
1528
|
+
# ``Deployment(client, lift(NodeRemote.locate(...))...).run(...)``.
|
|
1754
1529
|
|
|
1755
1530
|
def _is_node_remote(self, value: Any) -> bool:
|
|
1756
1531
|
try:
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""Uniform deprecation warnings for the 0.2.0 API cleanup (WP-07).
|
|
2
|
+
|
|
3
|
+
Central helper so every deprecated path speaks with one voice and tests can
|
|
4
|
+
match one message shape. See ``docs/migration-0.2.0.md`` for the old → new
|
|
5
|
+
table and the removal schedule.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import warnings
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def warn_deprecated(old: str, new: str, *, stacklevel: int = 3) -> None:
|
|
14
|
+
"""Emit a uniform ``DeprecationWarning`` pointing callers to ``new``.
|
|
15
|
+
|
|
16
|
+
``stacklevel=3`` attributes the warning to the caller of the deprecated
|
|
17
|
+
API (helper frame + deprecated function frame are skipped).
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
warnings.warn(
|
|
21
|
+
f"{old} is deprecated; use {new} instead.",
|
|
22
|
+
DeprecationWarning,
|
|
23
|
+
stacklevel=stacklevel,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def warn_deprecated_import(old_module: str, new_module: str) -> None:
|
|
28
|
+
"""Emit a ``DeprecationWarning`` from a legacy import-location shim."""
|
|
29
|
+
|
|
30
|
+
warnings.warn(
|
|
31
|
+
f"importing from {old_module} is deprecated; "
|
|
32
|
+
f"import from {new_module} instead. "
|
|
33
|
+
f"The {old_module} shim will be removed in 0.3.0.",
|
|
34
|
+
DeprecationWarning,
|
|
35
|
+
stacklevel=3,
|
|
36
|
+
)
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"""Deprecated import location — the implementation lives in ``spl._client``.
|
|
2
|
+
|
|
3
|
+
``from spl.client import SPLClient`` keeps working through 0.2.x, but the
|
|
4
|
+
canonical spelling is ``from spl import SPLClient``. This shim warns once on
|
|
5
|
+
import and will be removed in 0.3.0 (see ``docs/migration-0.2.0.md``).
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
from spl import _client as _impl
|
|
13
|
+
from spl._client import ( # noqa: F401 - legacy re-exports, kept intentionally.
|
|
14
|
+
ObjectCatalog as ObjectCatalog,
|
|
15
|
+
ObjectList as ObjectList,
|
|
16
|
+
ObjectScope as ObjectScope,
|
|
17
|
+
ObjectTable as ObjectTable,
|
|
18
|
+
OfflinePolicy as OfflinePolicy,
|
|
19
|
+
ProgressOption as ProgressOption,
|
|
20
|
+
PublishedObject as PublishedObject,
|
|
21
|
+
RemoteResult as RemoteResult,
|
|
22
|
+
RemoteRun as RemoteRun,
|
|
23
|
+
RunSource as RunSource,
|
|
24
|
+
SPLClient as SPLClient,
|
|
25
|
+
build_runtime_config as build_runtime_config,
|
|
26
|
+
export_object_to_yaml as export_object_to_yaml,
|
|
27
|
+
export_objects_to_yaml as export_objects_to_yaml,
|
|
28
|
+
prepare_export_object as prepare_export_object,
|
|
29
|
+
read_yaml_input as read_yaml_input,
|
|
30
|
+
)
|
|
31
|
+
from spl._deprecate import warn_deprecated_import
|
|
32
|
+
|
|
33
|
+
# Keep ``from spl.client import *`` scoped to the curated legacy surface
|
|
34
|
+
# (without ``__all__`` the star-import would also leak ``Any`` and
|
|
35
|
+
# ``warn_deprecated_import`` into the caller's namespace).
|
|
36
|
+
__all__ = [
|
|
37
|
+
"ObjectCatalog",
|
|
38
|
+
"ObjectList",
|
|
39
|
+
"ObjectScope",
|
|
40
|
+
"ObjectTable",
|
|
41
|
+
"OfflinePolicy",
|
|
42
|
+
"ProgressOption",
|
|
43
|
+
"PublishedObject",
|
|
44
|
+
"RemoteResult",
|
|
45
|
+
"RemoteRun",
|
|
46
|
+
"RunSource",
|
|
47
|
+
"SPLClient",
|
|
48
|
+
"build_runtime_config",
|
|
49
|
+
"export_object_to_yaml",
|
|
50
|
+
"export_objects_to_yaml",
|
|
51
|
+
"prepare_export_object",
|
|
52
|
+
"read_yaml_input",
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
warn_deprecated_import("spl.client", "spl")
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def __getattr__(name: str) -> Any:
|
|
59
|
+
"""Delegate remaining lookups so legacy code keeps working unchanged."""
|
|
60
|
+
|
|
61
|
+
return getattr(_impl, name)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def __dir__() -> list[str]:
|
|
65
|
+
return sorted(set(globals()) | set(dir(_impl)))
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""Deprecated import location — the implementation lives in ``spl.core._common``.
|
|
2
|
+
|
|
3
|
+
``from spl.core.common import Deployment, lift`` keeps working through 0.2.x,
|
|
4
|
+
but the canonical spelling is ``from spl import Deployment, lift``. This shim
|
|
5
|
+
warns once on import and will be removed in 0.3.0 (see
|
|
6
|
+
``docs/migration-0.2.0.md``).
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
from spl._deprecate import warn_deprecated_import
|
|
14
|
+
from spl.core import _common as _impl
|
|
15
|
+
from spl.core._common import ( # noqa: F401 - legacy re-exports, kept intentionally.
|
|
16
|
+
Deployment as Deployment,
|
|
17
|
+
PipelineBuilder as PipelineBuilder,
|
|
18
|
+
Run as Run,
|
|
19
|
+
decode as decode,
|
|
20
|
+
encode as encode,
|
|
21
|
+
lift as lift,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
# Keep ``from spl.core.common import *`` scoped to the curated legacy surface
|
|
25
|
+
# (without ``__all__`` the star-import would also leak ``Any`` and
|
|
26
|
+
# ``warn_deprecated_import`` into the caller's namespace).
|
|
27
|
+
__all__ = [
|
|
28
|
+
"Deployment",
|
|
29
|
+
"PipelineBuilder",
|
|
30
|
+
"Run",
|
|
31
|
+
"decode",
|
|
32
|
+
"encode",
|
|
33
|
+
"lift",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
warn_deprecated_import("spl.core.common", "spl")
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def __getattr__(name: str) -> Any:
|
|
40
|
+
"""Delegate remaining lookups so legacy code keeps working unchanged."""
|
|
41
|
+
|
|
42
|
+
return getattr(_impl, name)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def __dir__() -> list[str]:
|
|
46
|
+
return sorted(set(globals()) | set(dir(_impl)))
|