splime 0.1.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.
- spl/__init__.py +14 -0
- spl/client.py +1364 -0
- spl/core/__init__.py +23 -0
- spl/core/common.py +350 -0
- spl/core/entities/__init__.py +0 -0
- spl/core/entities/adapter.py +210 -0
- spl/core/entities/artifact.py +141 -0
- spl/core/entities/control.py +45 -0
- spl/core/entities/distribution.py +65 -0
- spl/core/entities/function.py +254 -0
- spl/core/entities/local_function.py +286 -0
- spl/core/entities/misc.py +14 -0
- spl/core/entities/module.py +88 -0
- spl/core/entities/node.py +286 -0
- spl/core/entities/node_function.py +79 -0
- spl/core/entities/node_remote.py +295 -0
- spl/core/entities/pipeline.py +436 -0
- spl/core/entities/scalar.py +55 -0
- spl/core/ir/__init__.py +0 -0
- spl/core/ir/common.py +34 -0
- spl/core/ir/parse.py +79 -0
- spl/core/ir/unparse.py +29 -0
- spl/core/ir/utils.py +163 -0
- spl/daemon/__init__.py +23 -0
- spl/daemon/__main__.py +11 -0
- spl/daemon/cli.py +582 -0
- spl/daemon/client.py +43 -0
- spl/daemon/docker_environment.py +329 -0
- spl/daemon/docker_pool.py +516 -0
- spl/daemon/environment.py +228 -0
- spl/daemon/environment_base.py +479 -0
- spl/daemon/heartbeat_service.py +119 -0
- spl/daemon/metadata.py +427 -0
- spl/daemon/remote_client.py +457 -0
- spl/daemon/repositories/__init__.py +17 -0
- spl/daemon/repositories/env.py +323 -0
- spl/daemon/repositories/library.py +181 -0
- spl/daemon/repositories/object.py +997 -0
- spl/daemon/repositories/run.py +279 -0
- spl/daemon/repositories/server_connection.py +657 -0
- spl/daemon/repositories/sync_event.py +129 -0
- spl/daemon/routes/__init__.py +1 -0
- spl/daemon/routes/_helpers.py +147 -0
- spl/daemon/routes/artifacts.py +77 -0
- spl/daemon/routes/diagnostics.py +114 -0
- spl/daemon/routes/envs.py +82 -0
- spl/daemon/routes/libraries.py +129 -0
- spl/daemon/routes/objects.py +174 -0
- spl/daemon/routes/remote.py +56 -0
- spl/daemon/routes/runs.py +96 -0
- spl/daemon/routes/server_connections.py +86 -0
- spl/daemon/runtime_backend.py +368 -0
- spl/daemon/runtime_config.py +133 -0
- spl/daemon/runtime_dependencies.py +459 -0
- spl/daemon/secret_store.py +187 -0
- spl/daemon/server.py +2224 -0
- spl/daemon/server_connection.py +267 -0
- spl/daemon/services/__init__.py +1 -0
- spl/daemon/services/sync.py +76 -0
- spl/daemon/signature.py +376 -0
- spl/daemon/storage_base.py +542 -0
- spl/daemon/store.py +436 -0
- spl/daemon/worker.py +526 -0
- spl/daemon_client.py +945 -0
- spl/pipeline_widget.py +1452 -0
- spl/py.typed +0 -0
- spl/server_client.py +787 -0
- splime-0.1.2.dist-info/METADATA +189 -0
- splime-0.1.2.dist-info/RECORD +74 -0
- splime-0.1.2.dist-info/WHEEL +5 -0
- splime-0.1.2.dist-info/entry_points.txt +2 -0
- splime-0.1.2.dist-info/licenses/LICENSE +201 -0
- splime-0.1.2.dist-info/licenses/NOTICE +8 -0
- splime-0.1.2.dist-info/top_level.txt +1 -0
spl/core/ir/utils.py
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
from itertools import chain, repeat
|
|
3
|
+
from operator import itemgetter
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
import yaml
|
|
8
|
+
|
|
9
|
+
from spl.core.entities.adapter import DAdapter
|
|
10
|
+
from spl.core.entities.artifact import DArtifactRef
|
|
11
|
+
from spl.core.entities.control import DSPLImport, DSPLSelfImport
|
|
12
|
+
from spl.core.entities.distribution import DDistribution, validate_distributions
|
|
13
|
+
from spl.core.entities.function import DFunction
|
|
14
|
+
from spl.core.entities.local_function import DLocalAlias
|
|
15
|
+
from spl.core.entities.module import DImport, DImportFrom
|
|
16
|
+
from spl.core.entities.node import (
|
|
17
|
+
DFormattedOutputRef,
|
|
18
|
+
DNodeInputRef,
|
|
19
|
+
DNodeOutputRef,
|
|
20
|
+
InputPort,
|
|
21
|
+
OutputPort,
|
|
22
|
+
)
|
|
23
|
+
from spl.core.entities.node_function import DNodeFunction
|
|
24
|
+
from spl.core.entities.node_remote import DNodeRemote
|
|
25
|
+
from spl.core.entities.pipeline import DPipeline
|
|
26
|
+
from spl.core.entities.scalar import DScalar
|
|
27
|
+
from spl.core.ir.parse import get_top_level_deps
|
|
28
|
+
from spl.core.ir.unparse import mk_top_level_ast
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class SPLSafeLoader(yaml.SafeLoader):
|
|
32
|
+
pass
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _construct_dataclass(cls):
|
|
36
|
+
def _construct(loader, node):
|
|
37
|
+
return cls(**loader.construct_mapping(node, deep = True))
|
|
38
|
+
return _construct
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _construct_dfunction(loader, node):
|
|
42
|
+
data = loader.construct_mapping(node, deep = True)
|
|
43
|
+
return DFunction(
|
|
44
|
+
name = data['name'],
|
|
45
|
+
body = data['body'],
|
|
46
|
+
inputs = [
|
|
47
|
+
InputPort(
|
|
48
|
+
name = x['name'],
|
|
49
|
+
typ_ = x['type'],
|
|
50
|
+
default = x.get('default'))
|
|
51
|
+
for x in data['inputs']],
|
|
52
|
+
outputs = None if data['outputs'] is None else [
|
|
53
|
+
OutputPort(
|
|
54
|
+
name = x['name'],
|
|
55
|
+
typ_ = x['type'])
|
|
56
|
+
for x in data['outputs']])
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
SPL_YAML_CONSTRUCTORS = {
|
|
60
|
+
'!DSPLSelfImport': _construct_dataclass(DSPLSelfImport),
|
|
61
|
+
'!DSPLImport': _construct_dataclass(DSPLImport),
|
|
62
|
+
'!DDistribution': _construct_dataclass(DDistribution),
|
|
63
|
+
'!DFunction': _construct_dfunction,
|
|
64
|
+
'!DLocalAlias': _construct_dataclass(DLocalAlias),
|
|
65
|
+
'!DImport': _construct_dataclass(DImport),
|
|
66
|
+
'!DImportFrom': _construct_dataclass(DImportFrom),
|
|
67
|
+
'!DFormattedOutputRef': _construct_dataclass(DFormattedOutputRef),
|
|
68
|
+
'!DNodeInputRef': _construct_dataclass(DNodeInputRef),
|
|
69
|
+
'!DNodeOutputRef': _construct_dataclass(DNodeOutputRef),
|
|
70
|
+
'!DNodeFunction': _construct_dataclass(DNodeFunction),
|
|
71
|
+
'!DNodeRemote': _construct_dataclass(DNodeRemote),
|
|
72
|
+
'!DPipeline': _construct_dataclass(DPipeline),
|
|
73
|
+
'!DScalar': _construct_dataclass(DScalar),
|
|
74
|
+
'!DArtifactRef': _construct_dataclass(DArtifactRef),
|
|
75
|
+
'!DAdapter': _construct_dataclass(DAdapter),
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
for _tag, _constructor in SPL_YAML_CONSTRUCTORS.items():
|
|
80
|
+
SPLSafeLoader.add_constructor(_tag, _constructor)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def spl_export_to_file(fname: Path, xs: list[Any]):
|
|
84
|
+
top_level_deps = get_top_level_deps(2, xs)
|
|
85
|
+
|
|
86
|
+
mapping = {
|
|
87
|
+
root: DSPLSelfImport(name = root.name)
|
|
88
|
+
for (root, _) in top_level_deps
|
|
89
|
+
if hasattr(root, 'name')}
|
|
90
|
+
|
|
91
|
+
top_level_deps = {
|
|
92
|
+
root: [mapping.get(x, x) for x in dependencies]
|
|
93
|
+
for root, dependencies in top_level_deps}
|
|
94
|
+
|
|
95
|
+
fname.write_text(yaml.dump_all(
|
|
96
|
+
[[root, *dependencies] for root, dependencies in top_level_deps.items()],
|
|
97
|
+
sort_keys = False,
|
|
98
|
+
allow_unicode = True))
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def spl_export_to_dir(dname: Path, xs: list[Any]):
|
|
102
|
+
top_level_deps = get_top_level_deps(2, xs)
|
|
103
|
+
mapping = {
|
|
104
|
+
root: DSPLImport(
|
|
105
|
+
path = './{}.yaml'.format(root.name),
|
|
106
|
+
name = root.name)
|
|
107
|
+
for (root, _) in top_level_deps}
|
|
108
|
+
|
|
109
|
+
top_level_deps = {
|
|
110
|
+
root: [mapping.get(x, x) for x in dependencies]
|
|
111
|
+
for root, dependencies in top_level_deps}
|
|
112
|
+
|
|
113
|
+
for root, dependencies in top_level_deps.items():
|
|
114
|
+
fname = dname / '{}.yaml'.format(root.name)
|
|
115
|
+
fname.write_text(yaml.dump(
|
|
116
|
+
[root, *dependencies],
|
|
117
|
+
sort_keys = False,
|
|
118
|
+
allow_unicode = True))
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def mk_top_level_deps_closure(fnames):
|
|
122
|
+
top_level_deps = []
|
|
123
|
+
imports = set(map(Path.absolute, fnames))
|
|
124
|
+
queue = list(imports)
|
|
125
|
+
|
|
126
|
+
while len(queue) > 0:
|
|
127
|
+
fname, *queue = queue
|
|
128
|
+
|
|
129
|
+
top_level_deps_new = [
|
|
130
|
+
(root, dependencies)
|
|
131
|
+
for (root, *dependencies) in yaml.load_all(fname.read_text(), SPLSafeLoader)]
|
|
132
|
+
|
|
133
|
+
top_level_deps = [
|
|
134
|
+
*top_level_deps,
|
|
135
|
+
*zip(repeat(fname), top_level_deps_new, strict = False)]
|
|
136
|
+
|
|
137
|
+
# TODO: filter by x.name
|
|
138
|
+
new_imports = sorted(set([
|
|
139
|
+
(fname.parent / x.path).absolute()
|
|
140
|
+
for x in chain.from_iterable([dependencies for (_, dependencies) in top_level_deps_new])
|
|
141
|
+
if isinstance(x, DSPLImport)]) - imports)
|
|
142
|
+
|
|
143
|
+
imports = set([*imports, *new_imports])
|
|
144
|
+
queue = [*queue, *new_imports]
|
|
145
|
+
|
|
146
|
+
return top_level_deps
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def spl_import_from_file(fname: Path, globals: dict[str, Any] | None = None):
|
|
150
|
+
if globals is None:
|
|
151
|
+
globals = sys._getframe(1).f_globals
|
|
152
|
+
|
|
153
|
+
top_level_deps = mk_top_level_deps_closure([fname])
|
|
154
|
+
|
|
155
|
+
validate_distributions(
|
|
156
|
+
list(map(itemgetter(1), top_level_deps)),
|
|
157
|
+
str(fname.absolute()))
|
|
158
|
+
|
|
159
|
+
for fname, (root, dependencies) in top_level_deps[::-1]:
|
|
160
|
+
expr = mk_top_level_ast((root, dependencies), fname)
|
|
161
|
+
eval( # noqa: S307
|
|
162
|
+
compile(expr, str(fname), mode = 'exec'),
|
|
163
|
+
globals = globals)
|
spl/daemon/__init__.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""Minimal local daemon runtime for SPL objects.
|
|
2
|
+
|
|
3
|
+
This package is intentionally kept outside ``spl.core``. The current core
|
|
4
|
+
already knows how to describe functions and pipelines as SPL/YAML; the daemon
|
|
5
|
+
adds only the missing local runtime pieces:
|
|
6
|
+
|
|
7
|
+
* a SQLite registry for environments, serialized objects, versions, and runs;
|
|
8
|
+
* a local HTTP API available from other Python environments;
|
|
9
|
+
* a worker subprocess that executes the object with its registered Python.
|
|
10
|
+
|
|
11
|
+
The public entry point is the module CLI:
|
|
12
|
+
|
|
13
|
+
python -m spl.daemon serve
|
|
14
|
+
|
|
15
|
+
The package does not import ``spl.core`` here on purpose. The daemon process
|
|
16
|
+
can start and manage its registry even if a particular target environment is
|
|
17
|
+
missing the dependencies required by an object; those errors belong to the
|
|
18
|
+
worker process and are reported per run.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from spl.daemon.client import Client
|
|
22
|
+
|
|
23
|
+
__all__ = ["Client"]
|
spl/daemon/__main__.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"""Command line entry point for ``python -m spl.daemon``.
|
|
2
|
+
|
|
3
|
+
Keeping this file tiny makes the module invocation predictable: all argument
|
|
4
|
+
parsing lives in ``cli.py`` and this file simply delegates to it.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from spl.daemon.cli import main
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
if __name__ == "__main__":
|
|
11
|
+
raise SystemExit(main())
|