nuspace 0.6.2__tar.gz → 0.6.3__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.
- {nuspace-0.6.2 → nuspace-0.6.3}/CHANGELOG.md +10 -2
- {nuspace-0.6.2 → nuspace-0.6.3}/PKG-INFO +6 -6
- {nuspace-0.6.2 → nuspace-0.6.3}/pyproject.toml +6 -6
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/content/kind.py +2 -1
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/content/search.py +12 -2
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/host/space.py +4 -2
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/ops/__init__.py +2 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/ops/cell.py +1 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/ops/kernel.py +18 -7
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/ops/read.py +7 -5
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/ops/state.py +2 -1
- nuspace-0.6.3/src/nuspace/ops/stores.py +51 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/ops/tree.py +2 -2
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/ops/utils.py +18 -8
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/backends/base.py +4 -5
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/devices/web/utils.py +1 -1
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/kernel/body.py +1 -1
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/kernel/envs.py +1 -1
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/kernel/out.py +4 -5
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/kernel/reconcile.py +8 -18
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/kernel/runs.py +4 -2
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/services/bootstrap.py +2 -2
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/services/init.py +14 -14
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/services/nav.py +1 -1
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/services/reactions.py +4 -4
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/services/supervisor.py +3 -15
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/ui/home.py +1 -1
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/ui/search.py +3 -3
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/ui/seed.py +1 -1
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/utils.py +2 -2
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/ui.py +1 -1
- {nuspace-0.6.2 → nuspace-0.6.3}/tests/conftest.py +6 -2
- {nuspace-0.6.2 → nuspace-0.6.3}/tests/nuspace/test_content.py +1 -1
- {nuspace-0.6.2 → nuspace-0.6.3}/tests/nuspace/test_host.py +12 -3
- {nuspace-0.6.2 → nuspace-0.6.3}/tests/nuspace/test_kernel.py +1 -1
- {nuspace-0.6.2 → nuspace-0.6.3}/tests/nuspace/test_ops_state.py +1 -1
- {nuspace-0.6.2 → nuspace-0.6.3}/tests/nuspace/test_reactions.py +3 -2
- {nuspace-0.6.2 → nuspace-0.6.3}/tests/nuspace/test_search.py +1 -1
- {nuspace-0.6.2 → nuspace-0.6.3}/tests/nuspace/test_services.py +3 -2
- {nuspace-0.6.2 → nuspace-0.6.3}/tests/nuspace/test_shapes.py +2 -2
- {nuspace-0.6.2 → nuspace-0.6.3}/tests/nuspace/test_web.py +2 -1
- {nuspace-0.6.2 → nuspace-0.6.3}/.gitignore +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/.pre-commit-config.yaml +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/LICENSE.md +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/Makefile +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/README.md +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/examples/space.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/pkgs/ts/nuspace-ui/python/nuspace_ui/build +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/__init__.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/_branding/__init__.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/_branding/header.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/_branding/logo.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/_branding/palette.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/_cli/__init__.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/_cli/__main__.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/_cli/_installed.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/_cli/_meta.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/_cli/commands/__init__.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/_cli/commands/init.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/_cli/commands/run.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/_cli/commands/telemetry.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/_cli/commands/verse.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/_cli/main.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/_telemetry/__init__.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/_telemetry/config.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/_telemetry/send.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/content/__init__.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/ext/__init__.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/ext/registry.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/ext/specs.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/host/__init__.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/host/presets.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/ops/extend.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/ops/pin.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/ops/plane.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/ops/usage.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/shapes/__init__.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/shapes/cell.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/shapes/connection.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/shapes/contents.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/shapes/kernel.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/shapes/plane.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/shapes/reroot.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/shapes/space.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/shapes/state.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/shapes/states.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/__init__.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/backends/__init__.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/backends/async_.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/backends/mp.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/backends/pool.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/devices/__init__.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/devices/web/__init__.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/devices/web/device.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/devices/web/env.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/devices/web/session.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/devices/web/shell.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/devices/web/sidebar/__init__.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/devices/web/sidebar/feed.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/devices/web/sidebar/interactions.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/devices/web/sidebar/ref.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/devices/web/viewer/__init__.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/devices/web/viewer/feed.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/devices/web/viewer/interactions.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/devices/web/viewer/ref.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/info.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/kernel/__init__.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/kernel/dispatch.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/kernel/kernel.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/kernel/space.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/kernel/utils.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/services/__init__.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/services/reload.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/ui/__init__.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/src/nuspace/system/ui/settings.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/tests/_ext/nuspace_testing/__init__.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/tests/_ext/pyproject.toml +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/tests/_lib/_support/__init__.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/tests/_lib/_support/actions.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/tests/_lib/_support/contents.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/tests/_lib/_support/kernel.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/tests/_lib/_support/kernel_envs.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/tests/_lib/_support/made.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/tests/_lib/_support/probe.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/tests/_lib/_support/specs.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/tests/nuspace/test_cli.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/tests/nuspace/test_home.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/tests/nuspace/test_ops_kernel.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/tests/nuspace/test_ops_structure.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/tests/nuspace/test_packaging.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/tests/nuspace/test_session_pipe.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/tests/nuspace/test_settings.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/tests/nuspace/test_telemetry.py +0 -0
- {nuspace-0.6.2 → nuspace-0.6.3}/tests/nuspace/test_ui.py +0 -0
|
@@ -2,13 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
## Packages shipped from this repo
|
|
4
4
|
|
|
5
|
-
- **nuspace** (the runtime, the `nuspace` command) — 0.6.
|
|
6
|
-
- **nuspace-ui** (the compiled web bundle) — 0.
|
|
5
|
+
- **nuspace** (the runtime, the `nuspace` command) — 0.6.3
|
|
6
|
+
- **nuspace-ui** (the compiled web bundle) — 0.6.3
|
|
7
7
|
|
|
8
8
|
Below is the changelog for **nuspace** - the full commit stream. Newest first.
|
|
9
9
|
The `nuspace-ui` wheel is the same source tree's vite output and is not tracked
|
|
10
10
|
separately here.
|
|
11
11
|
|
|
12
|
+
## 0.6.3 - 2026-11-05
|
|
13
|
+
|
|
14
|
+
- Release nuspace and nuspace-ui 0.6.3 on nu 0.7.0 and virtuals 0.2.0
|
|
15
|
+
- Reads of containers that may never exist give empty instead of failing
|
|
16
|
+
- A space creates every fixed store container at open, so reads find them
|
|
17
|
+
- Kernel, supervisor and boot list create their containers up front at open
|
|
18
|
+
- Move onto nu's NULL model: absent reads checked by existence, safe defaults
|
|
19
|
+
|
|
12
20
|
## 0.6.2 — 2026-10-30
|
|
13
21
|
|
|
14
22
|
- Release nuspace 0.6.2 on nu 0.6.8 and nuverse 0.3.5
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: nuspace
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.3
|
|
4
4
|
Summary: Computational space for your data and tools.
|
|
5
5
|
Project-URL: Repository, https://github.com/nustackdev/nuspace
|
|
6
6
|
Author-email: Gor Arakelyan <gorarkln@gmail.com>
|
|
@@ -17,16 +17,16 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
17
17
|
Requires-Python: >=3.10
|
|
18
18
|
Requires-Dist: certifi>=2023.7.22
|
|
19
19
|
Requires-Dist: click>=8.0
|
|
20
|
-
Requires-Dist: nucore>=0.
|
|
21
|
-
Requires-Dist: nuspace-ui>=0.
|
|
22
|
-
Requires-Dist: nustd[kv,mp-pool,proxy,ui,valkey]>=0.
|
|
20
|
+
Requires-Dist: nucore>=0.7.0
|
|
21
|
+
Requires-Dist: nuspace-ui>=0.6.3
|
|
22
|
+
Requires-Dist: nustd[kv,mp-pool,proxy,ui,valkey]>=0.7.0
|
|
23
23
|
Requires-Dist: nuverse>=0.3.5
|
|
24
24
|
Requires-Dist: rich-click>=1.6
|
|
25
25
|
Requires-Dist: rich>=10.7
|
|
26
26
|
Requires-Dist: typing-extensions>=4.7.0
|
|
27
|
-
Requires-Dist: virtuals-py[redis]>=0.
|
|
27
|
+
Requires-Dist: virtuals-py[redis]>=0.2.0
|
|
28
28
|
Provides-Extra: all
|
|
29
|
-
Requires-Dist: nustd[all]>=0.
|
|
29
|
+
Requires-Dist: nustd[all]>=0.7.0; extra == 'all'
|
|
30
30
|
Description-Content-Type: text/markdown
|
|
31
31
|
|
|
32
32
|
<div align="center">
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "nuspace"
|
|
7
|
-
version = "0.6.
|
|
7
|
+
version = "0.6.3"
|
|
8
8
|
description = "Computational space for your data and tools."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "AGPL-3.0-or-later"
|
|
@@ -14,14 +14,14 @@ dependencies = [
|
|
|
14
14
|
# The fabrics a space runs on, nothing more: kv for the store, valkey for
|
|
15
15
|
# its change notifications, ui for the browser, mp_pool for the workers,
|
|
16
16
|
# proxy (invisibles) for the worker's session.
|
|
17
|
-
"nucore>=0.
|
|
18
|
-
"nustd[kv,ui,valkey,mp_pool,proxy]>=0.
|
|
17
|
+
"nucore>=0.7.0",
|
|
18
|
+
"nustd[kv,ui,valkey,mp_pool,proxy]>=0.7.0",
|
|
19
19
|
# The store's change notifications run over virtuals' redis backend.
|
|
20
|
-
"virtuals-py[redis]>=0.
|
|
20
|
+
"virtuals-py[redis]>=0.2.0",
|
|
21
21
|
# The compiled web bundle. A separate distribution only because PyPI caps
|
|
22
22
|
# project size and a SPA rebuilt on every UI tweak would eat the quota --
|
|
23
23
|
# not optional. `pip install nuspace` gives you the browser.
|
|
24
|
-
"nuspace-ui>=0.
|
|
24
|
+
"nuspace-ui>=0.6.3",
|
|
25
25
|
# The everyday Planes and Cells. A plugin like any other, found through
|
|
26
26
|
# its entry point, but every space ships with it.
|
|
27
27
|
"nuverse>=0.3.5",
|
|
@@ -55,7 +55,7 @@ classifiers = [
|
|
|
55
55
|
[project.optional-dependencies]
|
|
56
56
|
# Every nustd fabric and kv backend, for cells that reach past the defaults.
|
|
57
57
|
all = [
|
|
58
|
-
"nustd[all]>=0.
|
|
58
|
+
"nustd[all]>=0.7.0",
|
|
59
59
|
]
|
|
60
60
|
|
|
61
61
|
[project.urls]
|
|
@@ -304,7 +304,8 @@ class Content(Generic[S]):
|
|
|
304
304
|
``items(scope)[id]`` is :meth:`at`. The mapping is the store's own, so
|
|
305
305
|
``keys``, ``len``, ``contains`` and ``on_children_change`` read and
|
|
306
306
|
watch storage, a write lands an item and ``items(scope)[id].erase()``
|
|
307
|
-
removes one.
|
|
307
|
+
removes one. A scope no item ever landed in has no mapping yet:
|
|
308
|
+
``exists()`` is False and ``len`` or ``keys`` raise. Not relative: name the running cell as
|
|
308
309
|
``(CELL, ops.Here.cell)``.
|
|
309
310
|
|
|
310
311
|
Args:
|
|
@@ -31,6 +31,15 @@ if TYPE_CHECKING:
|
|
|
31
31
|
__all__ = ["asked", "matched", "scopes", "walk"]
|
|
32
32
|
|
|
33
33
|
|
|
34
|
+
def _ids(held: nu.Nu) -> nu.List:
|
|
35
|
+
"""A mapping's keys, ``[]`` when it was never written.
|
|
36
|
+
|
|
37
|
+
A kind's level, or one scope of it, exists only once an item landed
|
|
38
|
+
there: a kind never written in a plane has no ``planes`` to list.
|
|
39
|
+
"""
|
|
40
|
+
return nu.list(nu.If(held.exists(), nu.list(held.keys()), []))
|
|
41
|
+
|
|
42
|
+
|
|
34
43
|
def scopes(kind: type[Content[Any]], level: str) -> nu.List:
|
|
35
44
|
"""The ids of the scopes at ``level`` holding items of ``kind``: cells or planes. A bare read.
|
|
36
45
|
|
|
@@ -41,7 +50,8 @@ def scopes(kind: type[Content[Any]], level: str) -> nu.List:
|
|
|
41
50
|
if level not in SLOTS:
|
|
42
51
|
msg = f"scope level {level!r} is none of {tuple(SLOTS)}"
|
|
43
52
|
raise ValueError(msg)
|
|
44
|
-
|
|
53
|
+
held = getattr(States.contents[kind_name(kind)], SLOTS[level])
|
|
54
|
+
return _ids(held)
|
|
45
55
|
|
|
46
56
|
|
|
47
57
|
def matched(
|
|
@@ -59,7 +69,7 @@ def matched(
|
|
|
59
69
|
"""
|
|
60
70
|
held = kind.items(scope)
|
|
61
71
|
return (
|
|
62
|
-
|
|
72
|
+
_ids(held)
|
|
63
73
|
.iter()
|
|
64
74
|
.filter(lambda found: kind.match(kind.at(scope, nu.Str(found)), **question))
|
|
65
75
|
)
|
|
@@ -26,7 +26,8 @@ planes are sure to exist on a first open, so the start is sequenced here
|
|
|
26
26
|
instead (the same term, same ``by``).
|
|
27
27
|
|
|
28
28
|
:func:`init_space` is steps 1 and 2 alone, in the store's brackets only: the
|
|
29
|
-
space directory made
|
|
29
|
+
space directory made, its containers created (as reconcile does at open)
|
|
30
|
+
and seeded, and closed again, nothing run.
|
|
30
31
|
|
|
31
32
|
Workers import :mod:`nuspace`, and so this module: the web device, which
|
|
32
33
|
pulls in the web server, is imported only when a space serves.
|
|
@@ -39,6 +40,7 @@ from typing import TYPE_CHECKING
|
|
|
39
40
|
|
|
40
41
|
import nu
|
|
41
42
|
from nuspace.ext import RegistryWarning, space_registry
|
|
43
|
+
from nuspace.ops import init_stores
|
|
42
44
|
from nuspace.ops.usage import opened
|
|
43
45
|
from nuspace.system.info import write_info
|
|
44
46
|
from nuspace.system.kernel import DEFAULT_SPARES, init_start, open_kernel, store
|
|
@@ -92,7 +94,7 @@ def init_space(path: str) -> nu.With:
|
|
|
92
94
|
Raises:
|
|
93
95
|
NotASpace: ``path`` holds something other than a space.
|
|
94
96
|
"""
|
|
95
|
-
return nu.With(store(path), body=seed_space())
|
|
97
|
+
return nu.With(store(path), body=init_stores() >> seed_space())
|
|
96
98
|
|
|
97
99
|
|
|
98
100
|
def open_space(
|
|
@@ -84,6 +84,7 @@ from .state import (
|
|
|
84
84
|
plane_state,
|
|
85
85
|
sibling,
|
|
86
86
|
)
|
|
87
|
+
from .stores import init_stores
|
|
87
88
|
from .tree import move_plane
|
|
88
89
|
from .usage import track
|
|
89
90
|
from .utils import atomic, atomic_state, mint_ordered_id, snapshot
|
|
@@ -114,6 +115,7 @@ __all__ = [
|
|
|
114
115
|
"create_cell",
|
|
115
116
|
"create_plane",
|
|
116
117
|
"env",
|
|
118
|
+
"init_stores",
|
|
117
119
|
"latest",
|
|
118
120
|
"mint_ordered_id",
|
|
119
121
|
"move_pin",
|
|
@@ -24,7 +24,7 @@ import nustd.kv
|
|
|
24
24
|
from nuspace.shapes import Space
|
|
25
25
|
|
|
26
26
|
from .read import cell_plane, cells, plane_exists
|
|
27
|
-
from .utils import MintId, atomic
|
|
27
|
+
from .utils import MintId, atomic, listed
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
if TYPE_CHECKING:
|
|
@@ -48,6 +48,7 @@ __all__ = [
|
|
|
48
48
|
"off_running",
|
|
49
49
|
"plane_interrupt",
|
|
50
50
|
"plane_kill",
|
|
51
|
+
"plane_live",
|
|
51
52
|
"plane_run",
|
|
52
53
|
"plane_stop",
|
|
53
54
|
"run",
|
|
@@ -76,6 +77,15 @@ STOP_GRACE = 10.0
|
|
|
76
77
|
_kernel = Space.kernel
|
|
77
78
|
|
|
78
79
|
|
|
80
|
+
def plane_live(plane_id: nu.StrArg) -> nu.List:
|
|
81
|
+
"""A plane's live plane run ids, ``[]`` when it has none. Bare read.
|
|
82
|
+
|
|
83
|
+
Its ``planes_running`` entry is there only while it has live runs (the
|
|
84
|
+
last run out takes it away), so a plane with none has no set to read.
|
|
85
|
+
"""
|
|
86
|
+
return listed(_kernel.planes_running[plane_id].runs)
|
|
87
|
+
|
|
88
|
+
|
|
79
89
|
def _snap(term: nu.Nu) -> nu.Nu:
|
|
80
90
|
return nustd.kv.Snapshot(term, scope=Space)
|
|
81
91
|
|
|
@@ -134,10 +144,11 @@ def add_plane_run(
|
|
|
134
144
|
>> row.by.set(by)
|
|
135
145
|
>> row.envs.set(_envs(envs))
|
|
136
146
|
>> row.termination_requested.set(False)
|
|
137
|
-
>> row.cells.init(
|
|
138
|
-
>> row.cells_running.init(
|
|
139
|
-
>> row.latest.init(
|
|
140
|
-
>> row.workers.init(
|
|
147
|
+
>> row.cells.init(nu.Dict.create())
|
|
148
|
+
>> row.cells_running.init(nu.Set.create())
|
|
149
|
+
>> row.latest.init(nu.Dict.create())
|
|
150
|
+
>> row.workers.init(nu.Set.create())
|
|
151
|
+
>> row.workers_running.init(nu.Set.create())
|
|
141
152
|
>> nu.ForEachDo(
|
|
142
153
|
cells(plane_id),
|
|
143
154
|
lambda cell: nu.let(
|
|
@@ -291,7 +302,7 @@ def off_running(run_id: nu.StrArg) -> nu.Nu:
|
|
|
291
302
|
|
|
292
303
|
def live_runs_of(plane_id: nu.StrArg, body: Callable[[nu.Str], nu.Nu]) -> nu.Nu:
|
|
293
304
|
"""``body(run_id)`` for every live plane run of the plane. No bracket."""
|
|
294
|
-
live =
|
|
305
|
+
live = plane_live(plane_id)
|
|
295
306
|
return nu.ForEachDo(live, lambda rid: body(nu.Str(rid)))
|
|
296
307
|
|
|
297
308
|
|
|
@@ -378,7 +389,7 @@ def runs(plane: nu.StrArg | None = None) -> nu.List:
|
|
|
378
389
|
A run's cell runs are :func:`cell_runs`; an ended run is read by id with
|
|
379
390
|
:func:`run`.
|
|
380
391
|
"""
|
|
381
|
-
live = _kernel.running if plane is None else
|
|
392
|
+
live = _kernel.running if plane is None else plane_live(plane)
|
|
382
393
|
return nu.sorted(live).iter().map(lambda rid: _run_row(nu.Str(rid))).to_list()
|
|
383
394
|
|
|
384
395
|
|
|
@@ -14,6 +14,8 @@ from __future__ import annotations
|
|
|
14
14
|
import nu
|
|
15
15
|
from nuspace.shapes import Space
|
|
16
16
|
|
|
17
|
+
from .utils import listed
|
|
18
|
+
|
|
17
19
|
|
|
18
20
|
__all__ = [
|
|
19
21
|
"cell_exists",
|
|
@@ -53,7 +55,7 @@ def plane_title(plane_id: nu.StrArg) -> nu.Str:
|
|
|
53
55
|
|
|
54
56
|
def cells(plane_id: nu.StrArg) -> nu.List:
|
|
55
57
|
"""A plane's cell ids, in order. ``[]`` for a plane never written."""
|
|
56
|
-
return
|
|
58
|
+
return listed(Space.planes[plane_id].cells)
|
|
57
59
|
|
|
58
60
|
|
|
59
61
|
def cell_exists(cell_id: nu.StrArg) -> nu.Bool:
|
|
@@ -66,7 +68,7 @@ def cell_named(plane_id: nu.StrArg, name: nu.StrArg) -> nu.Str:
|
|
|
66
68
|
named = (
|
|
67
69
|
cells(plane_id).iter().filter(lambda c: Space.cells[nu.Str(c)].name.fallback("") == name)
|
|
68
70
|
)
|
|
69
|
-
return nu.str(nu.First(named
|
|
71
|
+
return nu.str(nu.First(named, ""))
|
|
70
72
|
|
|
71
73
|
|
|
72
74
|
def cell_plane(cell_id: nu.StrArg) -> nu.Str:
|
|
@@ -79,7 +81,7 @@ def children(plane_id: nu.StrArg = "") -> nu.List:
|
|
|
79
81
|
|
|
80
82
|
``[]`` for a plane never written.
|
|
81
83
|
"""
|
|
82
|
-
under =
|
|
84
|
+
under = listed(Space.planes[plane_id].children)
|
|
83
85
|
return nu.List(nu.If(nu.Str(plane_id) == "", nu.list(Space.top), under))
|
|
84
86
|
|
|
85
87
|
|
|
@@ -90,7 +92,7 @@ def parent(plane_id: nu.StrArg) -> nu.Str:
|
|
|
90
92
|
|
|
91
93
|
def prog(cell_id: nu.StrArg) -> nu.Str:
|
|
92
94
|
"""A cell's source, ``""`` where there is none."""
|
|
93
|
-
return nu.str(Space.cells[cell_id].prog
|
|
95
|
+
return nu.str(Space.cells[cell_id].prog.fallback(""))
|
|
94
96
|
|
|
95
97
|
|
|
96
98
|
def plane_rows() -> nu.List:
|
|
@@ -132,7 +134,7 @@ def cell_rows(plane_id: nu.StrArg) -> nu.List:
|
|
|
132
134
|
return nu.Dict.of(
|
|
133
135
|
id=at,
|
|
134
136
|
name=cell.name.fallback(""),
|
|
135
|
-
prog=nu.str(cell.prog
|
|
137
|
+
prog=nu.str(cell.prog.fallback("")),
|
|
136
138
|
props=nu.Dict.of(
|
|
137
139
|
made_by=cell.props.made_by.fallback(""), has_ui=cell.props.has_ui.fallback(True)
|
|
138
140
|
),
|
|
@@ -174,7 +174,8 @@ def drop_items(level: str, scope_id: nu.StrArg) -> nu.Nu:
|
|
|
174
174
|
|
|
175
175
|
def drop(kind: nu.Attr) -> nu.Nu:
|
|
176
176
|
held = getattr(States.contents[nu.Str(kind)], level)
|
|
177
|
-
|
|
177
|
+
there = nu.IfDo(held.contains(scope_id), held.del_item(scope_id))
|
|
178
|
+
return nu.IfDo(held.exists(), there)
|
|
178
179
|
|
|
179
180
|
return nu.ForEachDo(nu.list(States.contents.keys()), drop)
|
|
180
181
|
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""The stores' fixed containers, made real once at open.
|
|
2
|
+
|
|
3
|
+
A container never written is absent, and reading one (its length, its
|
|
4
|
+
keys, whether it holds an id) raises. The top level of both stores is fixed
|
|
5
|
+
by their root shapes, so each container there is created up front, before
|
|
6
|
+
anything reads it. ``init`` writes only where one is missing, so this is
|
|
7
|
+
safe on every open of an existing space. A plane's or a cell's own
|
|
8
|
+
containers are made with the row, by the op that adds it.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import nu
|
|
14
|
+
from nuspace.shapes import Space, States
|
|
15
|
+
|
|
16
|
+
from .utils import atomic, atomic_state
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
__all__ = ["init_stores"]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _space() -> nu.Nu:
|
|
23
|
+
"""Space's top level: structure, devices, the space's own state, the kernel's indexes."""
|
|
24
|
+
return (
|
|
25
|
+
Space.planes.init(nu.Dict.create())
|
|
26
|
+
>> Space.cells.init(nu.Dict.create())
|
|
27
|
+
>> Space.top.init(nu.List.create())
|
|
28
|
+
>> Space.pinned.init(nu.List.create())
|
|
29
|
+
>> Space.connections.init(nu.Dict.create())
|
|
30
|
+
>> Space.state.recents.init(nu.List.create())
|
|
31
|
+
>> Space.state.made.init(nu.Dict.create())
|
|
32
|
+
>> Space.kernel.runs.init(nu.Dict.create())
|
|
33
|
+
>> Space.kernel.running.init(nu.Set.create())
|
|
34
|
+
>> Space.kernel.workers.init(nu.Dict.create())
|
|
35
|
+
>> Space.kernel.workers_running.init(nu.Set.create())
|
|
36
|
+
>> Space.kernel.planes_running.init(nu.Dict.create())
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _states() -> nu.Nu:
|
|
41
|
+
"""States' top level: every plane's state, every cell's, every kind's items."""
|
|
42
|
+
return (
|
|
43
|
+
States.planes.init(nu.Dict.create())
|
|
44
|
+
>> States.cells.init(nu.Dict.create())
|
|
45
|
+
>> States.contents.init(nu.Dict.create())
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def init_stores() -> nu.Nu:
|
|
50
|
+
"""Every fixed top level container of both stores, made where missing. Two commits, Space first."""
|
|
51
|
+
return atomic(_space()) >> atomic_state(_states())
|
|
@@ -19,7 +19,7 @@ import nu
|
|
|
19
19
|
from nuspace.shapes import Space
|
|
20
20
|
|
|
21
21
|
from .read import plane_exists
|
|
22
|
-
from .utils import atomic
|
|
22
|
+
from .utils import atomic, listed
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
if TYPE_CHECKING:
|
|
@@ -49,7 +49,7 @@ def subtree(plane_id: nu.StrArg, body: Callable[[nu.Nu], nu.Nu]) -> nu.Nu:
|
|
|
49
49
|
cycle written by hand ends rather than going round forever.
|
|
50
50
|
"""
|
|
51
51
|
going, edge = nu.List(_Walk.going), nu.List(_Walk.edge)
|
|
52
|
-
below = nu.Flatten(nu.Map(edge, lambda p:
|
|
52
|
+
below = nu.Flatten(nu.Map(edge, lambda p: listed(Space.planes[nu.Str(p)].children)))
|
|
53
53
|
step = nu.List(nu.Collect(nu.Filter(nu.Unique(below), lambda p: going.contains(p).not_())))
|
|
54
54
|
walk = nu.WhileDo(edge.len() > 0, _Walk.going.set(going + edge) >> _Walk.edge.set(step))
|
|
55
55
|
return nu.Frame(_Walk, walk >> body(_Walk.going), going=[], edge=nu.List.of(plane_id))
|
|
@@ -37,8 +37,7 @@ from typing import TYPE_CHECKING
|
|
|
37
37
|
|
|
38
38
|
import nu
|
|
39
39
|
import nustd.kv
|
|
40
|
-
from nu.lang import ScalarQuery
|
|
41
|
-
from nu.lang.sentinels import EMPTY
|
|
40
|
+
from nu.lang import ScalarQuery, is_null
|
|
42
41
|
from nuspace.shapes import Space, States
|
|
43
42
|
|
|
44
43
|
|
|
@@ -54,6 +53,7 @@ __all__ = [
|
|
|
54
53
|
"atomic_state",
|
|
55
54
|
"field_str",
|
|
56
55
|
"keep_order",
|
|
56
|
+
"listed",
|
|
57
57
|
"mint_ordered_id",
|
|
58
58
|
"snapshot",
|
|
59
59
|
]
|
|
@@ -87,7 +87,7 @@ class MintId(ScalarQuery):
|
|
|
87
87
|
prefix: The id's prefix.
|
|
88
88
|
|
|
89
89
|
Yields:
|
|
90
|
-
The id, a str.
|
|
90
|
+
The id, a str. NULL when the prefix is NULL.
|
|
91
91
|
"""
|
|
92
92
|
|
|
93
93
|
def _compile(self, nid: int, children: tuple[Callable, ...]) -> Callable:
|
|
@@ -95,8 +95,8 @@ class MintId(ScalarQuery):
|
|
|
95
95
|
|
|
96
96
|
def thunk(rt: Runtime) -> object:
|
|
97
97
|
p = prefix(rt)
|
|
98
|
-
if p
|
|
99
|
-
return
|
|
98
|
+
if is_null(p):
|
|
99
|
+
return p
|
|
100
100
|
return mint_ordered_id(p)
|
|
101
101
|
|
|
102
102
|
return thunk
|
|
@@ -106,8 +106,8 @@ class MintId(ScalarQuery):
|
|
|
106
106
|
|
|
107
107
|
async def athunk(rt: Runtime) -> object:
|
|
108
108
|
p = await prefix(rt)
|
|
109
|
-
if p
|
|
110
|
-
return
|
|
109
|
+
if is_null(p):
|
|
110
|
+
return p
|
|
111
111
|
return mint_ordered_id(p)
|
|
112
112
|
|
|
113
113
|
return athunk
|
|
@@ -159,10 +159,20 @@ def snapshot(term: nu.Nu) -> nu.Nu:
|
|
|
159
159
|
return nustd.kv.Snapshot(nustd.kv.Snapshot(term, scope=States), scope=Space)
|
|
160
160
|
|
|
161
161
|
|
|
162
|
+
def listed(ref: nu.Nu) -> nu.List:
|
|
163
|
+
"""A list or set container's members as a list, ``[]`` when it was never written. Bare read.
|
|
164
|
+
|
|
165
|
+
For containers that may legitimately be absent, eg a plane's ``cells``
|
|
166
|
+
asked about a plane that is not there. A fixed container is made at open
|
|
167
|
+
instead (:func:`~nuspace.ops.init_stores`) and read as is.
|
|
168
|
+
"""
|
|
169
|
+
return nu.list(nu.If(ref.exists(), nu.list(ref), []))
|
|
170
|
+
|
|
171
|
+
|
|
162
172
|
def field_str(row: nu.Nu, field: str) -> nu.Str:
|
|
163
173
|
"""One string field off a dict, a row or a browser event: ``""`` when absent.
|
|
164
174
|
|
|
165
|
-
Total on purpose, so a field left out hands an op a string, not
|
|
175
|
+
Total on purpose, so a field left out hands an op a string, not NULL.
|
|
166
176
|
"""
|
|
167
177
|
return nu.str(nu.Dict(row).get_item(field, ""))
|
|
168
178
|
|
|
@@ -33,8 +33,7 @@ import nu
|
|
|
33
33
|
import nustd.time
|
|
34
34
|
from nu.context import FabricRef
|
|
35
35
|
from nu.engine.structure import Declared
|
|
36
|
-
from nu.lang import ScalarAction
|
|
37
|
-
from nu.lang.sentinels import EMPTY
|
|
36
|
+
from nu.lang import ScalarAction, is_null
|
|
38
37
|
from nuspace.ops.utils import atomic
|
|
39
38
|
from nuspace.shapes import EXIT_FAILED, Space
|
|
40
39
|
|
|
@@ -165,7 +164,7 @@ def require_backend(value: object) -> Backend:
|
|
|
165
164
|
if isinstance(value, Backend):
|
|
166
165
|
return value
|
|
167
166
|
name = value.name if isinstance(value, _Named) else value
|
|
168
|
-
if name
|
|
167
|
+
if is_null(name) or name == "":
|
|
169
168
|
msg = "The plane names no backend: every plane must name one, eg mp or async"
|
|
170
169
|
raise UnknownBackendError(msg)
|
|
171
170
|
msg = f"No backend registered as {name!r}"
|
|
@@ -268,7 +267,7 @@ def _made(backend: nu.StrArg, run_id: nu.StrArg, made: nu.Nu) -> nu.Nu:
|
|
|
268
267
|
>> row.handle.set(nu.str(pair[1]))
|
|
269
268
|
>> row.started_at.set(nustd.time.time())
|
|
270
269
|
>> run.workers.add(wid)
|
|
271
|
-
>> nu.IfDo(row.terminated_at.
|
|
270
|
+
>> nu.IfDo(row.terminated_at.exists().not_(), live)
|
|
272
271
|
)
|
|
273
272
|
|
|
274
273
|
return nu.ForEachDo(nu.List(made), record)
|
|
@@ -283,7 +282,7 @@ def ended(worker_id: nu.StrArg, exit_: nu.StrArg, error: nu.StrArg = "") -> nu.N
|
|
|
283
282
|
run = _kernel.runs[row.run.fallback("")]
|
|
284
283
|
return (
|
|
285
284
|
nu.IfDo(
|
|
286
|
-
row.terminated_at.
|
|
285
|
+
row.terminated_at.exists().not_(),
|
|
287
286
|
row.terminated_at.set(nustd.time.time()) >> row.exit.set(exit_) >> row.error.set(error),
|
|
288
287
|
)
|
|
289
288
|
>> run.workers_running.remove(worker_id, missing_ok=True)
|
|
@@ -246,7 +246,7 @@ class Arms:
|
|
|
246
246
|
# --- Reading one event's fields ---------------------------------------------
|
|
247
247
|
#
|
|
248
248
|
# Total on purpose: a field the browser left out reads as its default, not as
|
|
249
|
-
#
|
|
249
|
+
# NULL, so an op is handed what it wants. A string field is
|
|
250
250
|
# :func:`~nuspace.ops.utils.field_str`, shared with the rows the ops read.
|
|
251
251
|
|
|
252
252
|
|
|
@@ -106,7 +106,7 @@ def end_cell_run(
|
|
|
106
106
|
if out is not None:
|
|
107
107
|
writes = cr.out.set(out) >> writes
|
|
108
108
|
writes = writes >> cr.terminated_at.set(nustd.time.time())
|
|
109
|
-
return nu.IfDo(cr.terminated_at.
|
|
109
|
+
return nu.IfDo(cr.terminated_at.exists().not_(), writes) >> row.cells_running.remove(
|
|
110
110
|
cell_run_id, missing_ok=True
|
|
111
111
|
)
|
|
112
112
|
|
|
@@ -30,8 +30,7 @@ from typing import TYPE_CHECKING
|
|
|
30
30
|
from nu.context import FabricRef
|
|
31
31
|
from nu.core.spans.bracket import _LifecycleBracket
|
|
32
32
|
from nu.engine.structure import Declared
|
|
33
|
-
from nu.lang import ScalarAction, ScalarQuery
|
|
34
|
-
from nu.lang.sentinels import EMPTY
|
|
33
|
+
from nu.lang import ScalarAction, ScalarQuery, is_null
|
|
35
34
|
|
|
36
35
|
|
|
37
36
|
if TYPE_CHECKING:
|
|
@@ -117,7 +116,7 @@ class RunOut:
|
|
|
117
116
|
|
|
118
117
|
|
|
119
118
|
class RunOutRef(FabricRef):
|
|
120
|
-
"""The :class:`RunOut` bound on the context.
|
|
119
|
+
"""The :class:`RunOut` bound on the context. NULL outside a run."""
|
|
121
120
|
|
|
122
121
|
fabric = RunOut
|
|
123
122
|
|
|
@@ -177,7 +176,7 @@ class Captured(_LifecycleBracket):
|
|
|
177
176
|
|
|
178
177
|
|
|
179
178
|
def _value(v: object, default: object) -> object:
|
|
180
|
-
return default if v
|
|
179
|
+
return default if is_null(v) or v is None else v
|
|
181
180
|
|
|
182
181
|
|
|
183
182
|
class _Pure(ScalarQuery):
|
|
@@ -214,7 +213,7 @@ class TakeOut(ScalarAction):
|
|
|
214
213
|
|
|
215
214
|
Args:
|
|
216
215
|
extra: Text appended first as one stderr entry, eg a traceback.
|
|
217
|
-
|
|
216
|
+
NULL or "" appends nothing.
|
|
218
217
|
final: Take unfinished lines too.
|
|
219
218
|
|
|
220
219
|
Yields:
|
|
@@ -4,14 +4,16 @@ A plane run in ``running`` or a worker in ``workers_running`` belongs to a
|
|
|
4
4
|
process that is gone, since workers die with the host. Ending each
|
|
5
5
|
``killed``, its live cell runs with it, makes the records true again before
|
|
6
6
|
anything else reads them, the narrower indexes (by plane, by run) emptied
|
|
7
|
-
with them. Only the indexes are walked, never history. It
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
with them. Only the indexes are walked, never history. It runs first, so it
|
|
8
|
+
also makes both stores' fixed containers real up front, the kernel's
|
|
9
|
+
included: every read after it (the walks here, ``running.contains``, a
|
|
10
|
+
run's lookups, the planes listed) finds a container, never an absent one.
|
|
10
11
|
"""
|
|
11
12
|
|
|
12
13
|
from __future__ import annotations
|
|
13
14
|
|
|
14
15
|
import nu
|
|
16
|
+
from nuspace.ops import init_stores
|
|
15
17
|
from nuspace.ops.utils import atomic
|
|
16
18
|
from nuspace.shapes import EXIT_KILLED, Space
|
|
17
19
|
from nuspace.system import backends
|
|
@@ -25,22 +27,10 @@ __all__ = ["reconcile"]
|
|
|
25
27
|
_kernel = Space.kernel
|
|
26
28
|
|
|
27
29
|
|
|
28
|
-
def _containers() -> nu.Nu:
|
|
29
|
-
"""Every kernel container made real, so a subscription on it resolves."""
|
|
30
|
-
return (
|
|
31
|
-
_kernel.runs.init(nu.Dict.create())
|
|
32
|
-
>> _kernel.running.init(nu.Set.create())
|
|
33
|
-
>> _kernel.workers.init(nu.Dict.create())
|
|
34
|
-
>> _kernel.workers_running.init(nu.Set.create())
|
|
35
|
-
>> _kernel.planes_running.init(nu.Dict.create())
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
|
|
39
30
|
def reconcile() -> nu.Nu:
|
|
40
|
-
"""
|
|
41
|
-
return atomic(
|
|
42
|
-
|
|
43
|
-
>> nu.ForEachDo(
|
|
31
|
+
"""The stores' containers made, then every live run and worker ended ``killed``, indexes emptied."""
|
|
32
|
+
return init_stores() >> atomic(
|
|
33
|
+
nu.ForEachDo(
|
|
44
34
|
nu.list(_kernel.workers_running), lambda wid: backends.ended(nu.Str(wid), EXIT_KILLED)
|
|
45
35
|
)
|
|
46
36
|
>> nu.ForEachDo(nu.list(_kernel.running), lambda rid: end_run(nu.Str(rid), EXIT_KILLED))
|
|
@@ -89,7 +89,9 @@ def end_run(run_id: nu.StrArg, exit_: nu.StrArg, error: nu.StrArg | None = None)
|
|
|
89
89
|
nu.list(row.cells_running),
|
|
90
90
|
lambda cr: end_cell_run(run_id, nu.Str(cr), exit_, error),
|
|
91
91
|
)
|
|
92
|
-
>> nu.IfDo(
|
|
92
|
+
>> nu.IfDo(
|
|
93
|
+
row.terminated_at.exists().not_(), own >> row.terminated_at.set(nustd.time.time())
|
|
94
|
+
)
|
|
93
95
|
>> backends.released(run_id, workers)
|
|
94
96
|
>> off_running(run_id)
|
|
95
97
|
)
|
|
@@ -135,7 +137,7 @@ def _cell_arm(run_id: nu.StrArg, cell_run_id: nu.StrArg, backend: nu.StrArg) ->
|
|
|
135
137
|
|
|
136
138
|
run = nu.let(RunCell(backend, run_id, cell_run_id), lost)
|
|
137
139
|
go = nu.IfDo(
|
|
138
|
-
snap(cr.worker.
|
|
140
|
+
snap(cr.worker.exists().not_()),
|
|
139
141
|
nu.TryCatch(place >> run, catch=lambda err: nu.let(ErrorText(err), failed)),
|
|
140
142
|
failed(_ORPHAN),
|
|
141
143
|
)
|
|
@@ -45,8 +45,8 @@ def _service(plane_id: str, cell_id: str, shim: str) -> nu.Nu:
|
|
|
45
45
|
prog (eg written by hand). The cell's ``has_ui`` is worked out first,
|
|
46
46
|
outside the bracket, and only when the cell is missing.
|
|
47
47
|
"""
|
|
48
|
-
no_plane = Space.planes[plane_id].
|
|
49
|
-
no_cell = Space.cells[cell_id].
|
|
48
|
+
no_plane = Space.planes[plane_id].name.exists().not_()
|
|
49
|
+
no_cell = Space.cells[cell_id].prog.exists().not_()
|
|
50
50
|
made = nu.IfDo(no_plane, plane_writes(plane_id, backend="mp", name=plane_id, system=True))
|
|
51
51
|
|
|
52
52
|
def both(ui: nu.ObjectRef) -> nu.Nu:
|