nucli 0.4.0__tar.gz → 0.5.1__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: nucli
3
- Version: 0.4.0
3
+ Version: 0.5.1
4
4
  Summary: The `nu` command line: doctor, demos, telemetry. Ships alongside the nucore kernel and the nustd fabrics.
5
5
  Project-URL: Repository, https://github.com/nustackdev/nu
6
6
  Author-email: Gor Arakelyan <gorarkln@gmail.com>
@@ -16,7 +16,7 @@ Classifier: Programming Language :: Python :: 3.12
16
16
  Classifier: Programming Language :: Python :: 3.13
17
17
  Requires-Python: >=3.10
18
18
  Requires-Dist: click>=8.0
19
- Requires-Dist: nustd>=0.4.0
19
+ Requires-Dist: nustd>=0.5.1
20
20
  Requires-Dist: rich-click>=1.6
21
21
  Requires-Dist: rich>=10.7
22
22
  Description-Content-Type: text/markdown
@@ -34,10 +34,10 @@ nu demo movies # run a packaged demo app
34
34
  nu telemetry # see / change telemetry settings
35
35
  ```
36
36
 
37
- It ships `nu._cli` into the `nu.` namespace and depends on
37
+ It imports as `nucli`, installs the `nu` command, and depends on
38
38
  [`nustd`](https://pypi.org/project/nustd/) (which pulls the
39
39
  [`nucore`](https://pypi.org/project/nucore/) kernel) because the
40
- packaged demos run on `nu.ui` and `nu.kv` at runtime.
40
+ packaged demos run on `nustd.ui` and `nustd.kv` at runtime.
41
41
 
42
42
  You normally do not install this directly - `pip install "nustd[all]" nucli`
43
43
  brings it along. Released in lockstep with the kernel. Docs at
@@ -11,10 +11,10 @@ nu demo movies # run a packaged demo app
11
11
  nu telemetry # see / change telemetry settings
12
12
  ```
13
13
 
14
- It ships `nu._cli` into the `nu.` namespace and depends on
14
+ It imports as `nucli`, installs the `nu` command, and depends on
15
15
  [`nustd`](https://pypi.org/project/nustd/) (which pulls the
16
16
  [`nucore`](https://pypi.org/project/nucore/) kernel) because the
17
- packaged demos run on `nu.ui` and `nu.kv` at runtime.
17
+ packaged demos run on `nustd.ui` and `nustd.kv` at runtime.
18
18
 
19
19
  You normally do not install this directly - `pip install "nustd[all]" nucli`
20
20
  brings it along. Released in lockstep with the kernel. Docs at
@@ -4,18 +4,18 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "nucli"
7
- version = "0.4.0"
7
+ version = "0.5.1"
8
8
  description = "The `nu` command line: doctor, demos, telemetry. Ships alongside the nucore kernel and the nustd fabrics."
9
9
  readme = "README.md"
10
10
  license = "Apache-2.0"
11
11
  authors = [{ name = "Gor Arakelyan", email = "gorarkln@gmail.com" }]
12
12
  requires-python = ">=3.10"
13
13
  # Released in lockstep with the kernel. Carries no `nu/__init__.py` -- it drops
14
- # `nu._cli` into the `nu.` namespace the kernel owns. Depends on `nustd` rather
14
+ # `nucli` into the `nu.` namespace the kernel owns. Depends on `nustd` rather
15
15
  # than the bare kernel because the packaged demos (`nu demo movies`) run on
16
- # `nu.ui` and `nu.kv` at runtime.
16
+ # `nustd.ui` and `nustd.kv` at runtime.
17
17
  dependencies = [
18
- "nustd>=0.4.0",
18
+ "nustd>=0.5.1",
19
19
  "click>=8.0",
20
20
  "rich>=10.7",
21
21
  "rich-click>=1.6",
@@ -52,9 +52,8 @@ classifiers = [
52
52
  Repository = "https://github.com/nustackdev/nu"
53
53
 
54
54
  [project.scripts]
55
- nu = "nu._cli:main"
55
+ nu = "nucli:main"
56
56
 
57
57
  [tool.hatch.build.targets.wheel]
58
- packages = ["src/nu"]
59
- # No `nu/__init__.py` here on purpose: the kernel wheel owns the package root
60
- # and the installs merge into one `site-packages/nu/`.
58
+ packages = ["src/nucli"]
59
+ # The import name is `nucli`; the command it installs is `nu`.
@@ -1,6 +1,6 @@
1
1
  """The `nu` command — entrypoint package."""
2
2
 
3
- from nu._cli.main import cli, main
3
+ from nucli.main import cli, main
4
4
 
5
5
 
6
6
  __all__ = ["cli", "main"]
@@ -0,0 +1,7 @@
1
+ """Enables `python -m nucli`."""
2
+
3
+ from nucli.main import main
4
+
5
+
6
+ if __name__ == "__main__":
7
+ main()
@@ -15,8 +15,8 @@ def nu_version() -> str:
15
15
 
16
16
 
17
17
  def demos_root() -> Path:
18
- """Locate packaged demo scripts (ships as nu._cli.demos)."""
19
- return Path(str(resources.files("nu._cli").joinpath("demos")))
18
+ """Locate packaged demo scripts (ships as nucli.demos)."""
19
+ return Path(str(resources.files("nucli").joinpath("demos")))
20
20
 
21
21
 
22
22
  def demos() -> dict[str, Path]:
@@ -12,8 +12,8 @@ from rich.console import Console
12
12
  from rich.table import Table
13
13
  from rich.text import Text
14
14
 
15
- from nu._cli._meta import demos
16
15
  from nu._config.branding import BLUE, PURPLE
16
+ from nucli._meta import demos
17
17
 
18
18
 
19
19
  if TYPE_CHECKING:
@@ -10,8 +10,8 @@ from rich.console import Console
10
10
  from rich.table import Table
11
11
  from rich.text import Text
12
12
 
13
- from nu._cli._meta import nu_version
14
13
  from nu._config.branding import BLUE, PURPLE
14
+ from nucli._meta import nu_version
15
15
 
16
16
 
17
17
  # Fabric extras (as declared in packages/nustd/pyproject.toml) and the import
@@ -3,6 +3,7 @@
3
3
  from pathlib import Path
4
4
 
5
5
  import nu
6
+ import nustd
6
7
 
7
8
 
8
9
  _DB = Path.home() / ".nu" / "demos" / "counter"
@@ -12,30 +13,30 @@ _DB.parent.mkdir(parents=True, exist_ok=True)
12
13
  class Counter(nu.Shape):
13
14
  """Persistent counter state."""
14
15
 
15
- value: nu.kv.IntRef
16
+ value: nustd.kv.IntRef
16
17
 
17
18
 
18
- class Links(nu.ui.Row):
19
- docs = nu.ui.LinkRef.slot(
19
+ class Links(nustd.ui.Row):
20
+ docs = nustd.ui.LinkRef.slot(
20
21
  label="Read the docs", href="https://nustack.dev/docs", target="_blank"
21
22
  )
22
- github = nu.ui.LinkRef.slot(
23
+ github = nustd.ui.LinkRef.slot(
23
24
  label="Star on GitHub", href="https://github.com/nustackdev/nu", target="_blank"
24
25
  )
25
- examples = nu.ui.LinkRef.slot(
26
+ examples = nustd.ui.LinkRef.slot(
26
27
  label="Browse more demos",
27
28
  href="https://github.com/nustackdev/nu/tree/main/examples",
28
29
  target="_blank",
29
30
  )
30
31
 
31
32
 
32
- class Dashboard(nu.ui.Page):
33
+ class Dashboard(nustd.ui.Page):
33
34
  """Live counter page with description and source."""
34
35
 
35
- heading = nu.ui.HeadingRef.slot(label="Persistent counter, live")
36
- count = nu.ui.StatRef.slot(label="Count")
37
- about_heading = nu.ui.HeadingRef.slot(label="How it works")
38
- about = nu.ui.MarkdownRef.slot(
36
+ heading = nustd.ui.HeadingRef.slot(label="Persistent counter, live")
37
+ count = nustd.ui.StatRef.slot(label="Count")
38
+ about_heading = nustd.ui.HeadingRef.slot(label="How it works")
39
+ about = nustd.ui.MarkdownRef.slot(
39
40
  value=(
40
41
  "- Stores counter value in rocksdb.\n"
41
42
  "- App increments the counter once a second.\n"
@@ -44,38 +45,38 @@ class Dashboard(nu.ui.Page):
44
45
  "- Same Interactions used to orchestrate storage and UI update.\n"
45
46
  ),
46
47
  )
47
- links_heading = nu.ui.HeadingRef.slot(label="Try Nu yourself")
48
- links_intro = nu.ui.TextRef.slot(
48
+ links_heading = nustd.ui.HeadingRef.slot(label="Try Nu yourself")
49
+ links_intro = nustd.ui.TextRef.slot(
49
50
  value="Persistent state, live browser, no glue. See how far the primitive goes.",
50
51
  )
51
52
  links = Links.slot(gap=4, align="center", wrap=True)
52
- source_heading = nu.ui.HeadingRef.slot(label="Source")
53
- source_intro = nu.ui.TextRef.slot(
53
+ source_heading = nustd.ui.HeadingRef.slot(label="Source")
54
+ source_intro = nustd.ui.TextRef.slot(
54
55
  value="The whole app, one file. Storage, UI, and the wires between them.",
55
56
  )
56
- source = nu.ui.CodeBlockRef.slot(
57
+ source = nustd.ui.CodeBlockRef.slot(
57
58
  code=Path(__file__).read_text(),
58
59
  language="python",
59
60
  )
60
61
 
61
62
 
62
- class App(nu.ui.Index):
63
+ class App(nustd.ui.Index):
63
64
  """UI index with one page."""
64
65
 
65
66
  home = Dashboard.slot("/")
66
67
 
67
68
 
68
69
  app = nu.With(
69
- nu.kv.rocksdb_navigator(str(_DB)),
70
- nu.ui.server(
71
- nu.kv.auto_flow_atomic(
70
+ nustd.kv.rocksdb_navigator(str(_DB)),
71
+ nustd.ui.server(
72
+ nustd.kv.auto_flow_atomic(
72
73
  nu.ReactForever(
73
74
  Counter.value.on_change(),
74
75
  App.home.count.set_value(nu.str(Counter.value)),
75
76
  ),
76
77
  ),
77
78
  ),
78
- body=nu.kv.auto_flow_atomic(
79
+ body=nustd.kv.auto_flow_atomic(
79
80
  nu.IfDo(Counter.value.missing(), Counter.value.set(0))
80
81
  >> nu.ForeverDo(
81
82
  Counter.value.inc() >> nu.Delay(1.0),
@@ -3,6 +3,7 @@
3
3
  from pathlib import Path
4
4
 
5
5
  import nu
6
+ import nustd
6
7
 
7
8
 
8
9
  _DB = Path.home() / ".nu" / "demos" / "movies"
@@ -23,16 +24,16 @@ _GENRES_WITH_ANY = [{"value": "", "label": "Any genre"}, *_GENRES]
23
24
  # ---- UI ---------------------------------------------------------------------
24
25
 
25
26
 
26
- class TitleField(nu.ui.Field):
27
- input = nu.ui.InputRef.slot(placeholder="e.g. Arrival")
27
+ class TitleField(nustd.ui.Field):
28
+ input = nustd.ui.InputRef.slot(placeholder="e.g. Arrival")
28
29
 
29
30
 
30
- class TextAreaField(nu.ui.Field):
31
- input = nu.ui.TextAreaRef.slot(placeholder="Quick thoughts...", rows=2)
31
+ class TextAreaField(nustd.ui.Field):
32
+ input = nustd.ui.TextAreaRef.slot(placeholder="Quick thoughts...", rows=2)
32
33
 
33
34
 
34
- class YearField(nu.ui.Field):
35
- input = nu.ui.NumberInputRef.slot(
35
+ class YearField(nustd.ui.Field):
36
+ input = nustd.ui.NumberInputRef.slot(
36
37
  min=1900.0,
37
38
  max=2100.0,
38
39
  step=1.0,
@@ -40,8 +41,8 @@ class YearField(nu.ui.Field):
40
41
  )
41
42
 
42
43
 
43
- class RatingField(nu.ui.Field):
44
- input = nu.ui.NumberInputRef.slot(
44
+ class RatingField(nustd.ui.Field):
45
+ input = nustd.ui.NumberInputRef.slot(
45
46
  min=1.0,
46
47
  max=10.0,
47
48
  step=0.5,
@@ -49,96 +50,96 @@ class RatingField(nu.ui.Field):
49
50
  )
50
51
 
51
52
 
52
- class GenreField(nu.ui.Field):
53
- input = nu.ui.SelectRef.slot(options=_GENRES, selected="drama")
53
+ class GenreField(nustd.ui.Field):
54
+ input = nustd.ui.SelectRef.slot(options=_GENRES, selected="drama")
54
55
 
55
56
 
56
- class SwitchField(nu.ui.Field):
57
- input = nu.ui.SwitchRef.slot(default=True)
57
+ class SwitchField(nustd.ui.Field):
58
+ input = nustd.ui.SwitchRef.slot(default=True)
58
59
 
59
60
 
60
- class DetailsFieldset(nu.ui.Fieldset):
61
+ class DetailsFieldset(nustd.ui.Fieldset):
61
62
  title = TitleField.slot(label="Title", help="Movie title", required=True)
62
63
  year = YearField.slot(label="Year")
63
64
  genre = GenreField.slot(label="Genre")
64
65
 
65
66
 
66
- class ScoreFieldset(nu.ui.Fieldset):
67
+ class ScoreFieldset(nustd.ui.Fieldset):
67
68
  rating = RatingField.slot(label="Rating", help="How much you liked it")
68
69
  watched = SwitchField.slot(label="Watched?", help="Off means still on the pile")
69
70
  notes = TextAreaField.slot(label="Notes")
70
71
 
71
72
 
72
- class AddMovieForm(nu.ui.Form):
73
+ class AddMovieForm(nustd.ui.Form):
73
74
  details = DetailsFieldset.slot(legend="Movie", gap="md")
74
75
  score = ScoreFieldset.slot(legend="Your take", gap="md")
75
- submit = nu.ui.ButtonRef.slot(label="Log it", variant="primary")
76
- feedback = nu.ui.AlertRef.slot(variant="ok", dismissible=True)
76
+ submit = nustd.ui.ButtonRef.slot(label="Log it", variant="primary")
77
+ feedback = nustd.ui.AlertRef.slot(variant="ok", dismissible=True)
77
78
 
78
79
 
79
- class MinRatingField(nu.ui.Field):
80
- input = nu.ui.NumberInputRef.slot(min=1.0, max=10.0, step=0.5, default=1.0)
80
+ class MinRatingField(nustd.ui.Field):
81
+ input = nustd.ui.NumberInputRef.slot(min=1.0, max=10.0, step=0.5, default=1.0)
81
82
 
82
83
 
83
- class FilterGenreField(nu.ui.Field):
84
- input = nu.ui.SelectRef.slot(options=_GENRES_WITH_ANY, selected="")
84
+ class FilterGenreField(nustd.ui.Field):
85
+ input = nustd.ui.SelectRef.slot(options=_GENRES_WITH_ANY, selected="")
85
86
 
86
87
 
87
- class WatchedOnlyField(nu.ui.Field):
88
- input = nu.ui.SwitchRef.slot(default=False)
88
+ class WatchedOnlyField(nustd.ui.Field):
89
+ input = nustd.ui.SwitchRef.slot(default=False)
89
90
 
90
91
 
91
- class FilterRow(nu.ui.Row):
92
+ class FilterRow(nustd.ui.Row):
92
93
  min_rating = MinRatingField.slot(label="Min rating")
93
94
  genre = FilterGenreField.slot(label="Genre")
94
95
  watched_only = WatchedOnlyField.slot(label="Already watched")
95
- apply = nu.ui.ButtonRef.slot(label="Apply", variant="secondary")
96
- clear = nu.ui.ButtonRef.slot(label="Clear", variant="ghost")
96
+ apply = nustd.ui.ButtonRef.slot(label="Apply", variant="secondary")
97
+ clear = nustd.ui.ButtonRef.slot(label="Clear", variant="ghost")
97
98
 
98
99
 
99
- class FilterCard(nu.ui.Card):
100
+ class FilterCard(nustd.ui.Card):
100
101
  body = FilterRow.slot(gap=3, align="center", wrap=True)
101
102
 
102
103
 
103
- class StatsRow(nu.ui.Row):
104
- total = nu.ui.StatRef.slot(label="Total")
105
- watched = nu.ui.StatRef.slot(label="Watched")
106
- unseen = nu.ui.StatRef.slot(label="Unseen")
107
- latest = nu.ui.TextRef.slot()
108
- health = nu.ui.BadgeRef.slot(label="Fresh", variant="ok")
104
+ class StatsRow(nustd.ui.Row):
105
+ total = nustd.ui.StatRef.slot(label="Total")
106
+ watched = nustd.ui.StatRef.slot(label="Watched")
107
+ unseen = nustd.ui.StatRef.slot(label="Unseen")
108
+ latest = nustd.ui.TextRef.slot()
109
+ health = nustd.ui.BadgeRef.slot(label="Fresh", variant="ok")
109
110
 
110
111
 
111
- class StatsCard(nu.ui.Card):
112
+ class StatsCard(nustd.ui.Card):
112
113
  body = StatsRow.slot(gap=6, align="center", wrap=True)
113
114
 
114
115
 
115
- class TableBody(nu.ui.Column):
116
- table = nu.ui.TableRef.slot(
116
+ class TableBody(nustd.ui.Column):
117
+ table = nustd.ui.TableRef.slot(
117
118
  columns=["title", "year", "genre", "rating", "watched", "notes"],
118
119
  striped=True,
119
120
  dense=True,
120
121
  clickable_rows=True,
121
122
  max_rows=200,
122
123
  )
123
- empty = nu.ui.AlertRef.slot(
124
+ empty = nustd.ui.AlertRef.slot(
124
125
  variant="info",
125
126
  body="No movies match",
126
127
  dismissible=False,
127
128
  )
128
129
 
129
130
 
130
- class TableCard(nu.ui.Card):
131
+ class TableCard(nustd.ui.Card):
131
132
  body = TableBody.slot(gap=3)
132
133
 
133
134
 
134
- class Links(nu.ui.Row):
135
- docs = nu.ui.LinkRef.slot(
135
+ class Links(nustd.ui.Row):
136
+ docs = nustd.ui.LinkRef.slot(
136
137
  label="Read the docs", href="https://nustack.dev/docs", target="_blank"
137
138
  )
138
- github = nu.ui.LinkRef.slot(
139
+ github = nustd.ui.LinkRef.slot(
139
140
  label="Star on GitHub", href="https://github.com/nustackdev/nu", target="_blank"
140
141
  )
141
- examples = nu.ui.LinkRef.slot(
142
+ examples = nustd.ui.LinkRef.slot(
142
143
  label="Browse more demos",
143
144
  href="https://github.com/nustackdev/nu/tree/main/examples",
144
145
  target="_blank",
@@ -148,13 +149,13 @@ class Links(nu.ui.Row):
148
149
  # ---- Pages ------------------------------------------------------------------
149
150
 
150
151
 
151
- class TopBar(nu.ui.Row):
152
- about = nu.ui.ButtonRef.slot(label="About this demo", variant="ghost")
152
+ class TopBar(nustd.ui.Row):
153
+ about = nustd.ui.ButtonRef.slot(label="About this demo", variant="ghost")
153
154
 
154
155
 
155
- class Movies(nu.ui.Page):
156
- heading = nu.ui.HeadingRef.slot(label="Your movies")
157
- intro = nu.ui.TextRef.slot(
156
+ class Movies(nustd.ui.Page):
157
+ heading = nustd.ui.HeadingRef.slot(label="Your movies")
158
+ intro = nustd.ui.TextRef.slot(
158
159
  value="Log what you watch. Filter the shelf, click a row for details.",
159
160
  )
160
161
  topbar = TopBar.slot(gap=3, align="center")
@@ -165,13 +166,13 @@ class Movies(nu.ui.Page):
165
166
  shelf = TableCard.slot(title="Movies")
166
167
 
167
168
 
168
- class AboutActions(nu.ui.Row):
169
- back = nu.ui.ButtonRef.slot(label="Back to app", variant="ghost")
169
+ class AboutActions(nustd.ui.Row):
170
+ back = nustd.ui.ButtonRef.slot(label="Back to app", variant="ghost")
170
171
 
171
172
 
172
- class About(nu.ui.Page):
173
- heading = nu.ui.HeadingRef.slot(label="How it works")
174
- about = nu.ui.MarkdownRef.slot(
173
+ class About(nustd.ui.Page):
174
+ heading = nustd.ui.HeadingRef.slot(label="How it works")
175
+ about = nustd.ui.MarkdownRef.slot(
175
176
  value=(
176
177
  "- Real app: form, filterable table, stats row, per-item detail page.\n"
177
178
  "- Every row lives in rocksdb. Restart, everything is still there.\n"
@@ -179,52 +180,52 @@ class About(nu.ui.Page):
179
180
  "- Same Interactions handle add, delete, filter, and page routing.\n"
180
181
  ),
181
182
  )
182
- links_heading = nu.ui.HeadingRef.slot(label="Try Nu yourself")
183
- links_intro = nu.ui.TextRef.slot(
183
+ links_heading = nustd.ui.HeadingRef.slot(label="Try Nu yourself")
184
+ links_intro = nustd.ui.TextRef.slot(
184
185
  value="Full apps, forms, routing, no glue. See how far the primitive goes.",
185
186
  )
186
187
  links = Links.slot(gap=4, align="center", wrap=True)
187
- source_heading = nu.ui.HeadingRef.slot(label="Source")
188
- source_intro = nu.ui.TextRef.slot(
188
+ source_heading = nustd.ui.HeadingRef.slot(label="Source")
189
+ source_intro = nustd.ui.TextRef.slot(
189
190
  value="The whole app, one file. Storage, UI, and the wires between them.",
190
191
  )
191
- source = nu.ui.CodeBlockRef.slot(
192
+ source = nustd.ui.CodeBlockRef.slot(
192
193
  code=Path(__file__).read_text(),
193
194
  language="python",
194
195
  )
195
196
  actions = AboutActions.slot(gap=3, align="center")
196
197
 
197
198
 
198
- class DetailRow(nu.ui.Row):
199
- year = nu.ui.StatRef.slot(label="Year")
200
- genre = nu.ui.StatRef.slot(label="Genre")
201
- rating = nu.ui.StatRef.slot(label="Rating")
202
- watched = nu.ui.BadgeRef.slot(label="Watched", variant="ok")
199
+ class DetailRow(nustd.ui.Row):
200
+ year = nustd.ui.StatRef.slot(label="Year")
201
+ genre = nustd.ui.StatRef.slot(label="Genre")
202
+ rating = nustd.ui.StatRef.slot(label="Rating")
203
+ watched = nustd.ui.BadgeRef.slot(label="Watched", variant="ok")
203
204
 
204
205
 
205
- class MetaCard(nu.ui.Card):
206
+ class MetaCard(nustd.ui.Card):
206
207
  meta = DetailRow.slot(gap=6, align="center", wrap=True)
207
208
 
208
209
 
209
- class NotesCard(nu.ui.Card):
210
- body = nu.ui.MarkdownRef.slot()
210
+ class NotesCard(nustd.ui.Card):
211
+ body = nustd.ui.MarkdownRef.slot()
211
212
 
212
213
 
213
- class DetailActions(nu.ui.Row):
214
- back = nu.ui.ButtonRef.slot(label="Back", variant="ghost")
215
- remove = nu.ui.ButtonRef.slot(label="Delete", variant="danger")
214
+ class DetailActions(nustd.ui.Row):
215
+ back = nustd.ui.ButtonRef.slot(label="Back", variant="ghost")
216
+ remove = nustd.ui.ButtonRef.slot(label="Delete", variant="danger")
216
217
 
217
218
 
218
- class MovieDetail(nu.ui.Page):
219
- heading = nu.ui.HeadingRef.slot()
219
+ class MovieDetail(nustd.ui.Page):
220
+ heading = nustd.ui.HeadingRef.slot()
220
221
  meta = MetaCard.slot(title="Details")
221
222
  notes = NotesCard.slot(title="Notes")
222
223
  actions = DetailActions.slot(gap=3, align="center")
223
224
 
224
225
 
225
- class App(nu.ui.Index):
226
- title: nu.ui.TitleRef
227
- nav: nu.ui.NavRef
226
+ class App(nustd.ui.Index):
227
+ title: nustd.ui.TitleRef
228
+ nav: nustd.ui.NavRef
228
229
  movies = Movies.slot("/")
229
230
  detail = MovieDetail.slot("/detail")
230
231
  about = About.slot("/about")
@@ -234,20 +235,20 @@ class App(nu.ui.Index):
234
235
 
235
236
 
236
237
  class Movie(nu.Shape):
237
- title = nu.kv.StrRef.slot()
238
- year = nu.kv.IntRef.slot()
239
- genre = nu.kv.StrRef.slot()
240
- rating = nu.kv.FloatRef.slot()
241
- watched = nu.kv.BoolRef.slot()
242
- notes = nu.kv.StrRef.slot()
238
+ title = nustd.kv.StrRef.slot()
239
+ year = nustd.kv.IntRef.slot()
240
+ genre = nustd.kv.StrRef.slot()
241
+ rating = nustd.kv.FloatRef.slot()
242
+ watched = nustd.kv.BoolRef.slot()
243
+ notes = nustd.kv.StrRef.slot()
243
244
 
244
245
 
245
246
  class State(nu.Shape):
246
- movies = nu.kv.ShapesListRef.slot(Movie)
247
- total = nu.kv.IntRef.slot()
248
- watched = nu.kv.IntRef.slot()
249
- latest_title = nu.kv.StrRef.slot()
250
- selected = nu.kv.IntRef.slot() # index of the movie open in MovieDetail
247
+ movies = nustd.kv.ShapesListRef.slot(Movie)
248
+ total = nustd.kv.IntRef.slot()
249
+ watched = nustd.kv.IntRef.slot()
250
+ latest_title = nustd.kv.StrRef.slot()
251
+ selected = nustd.kv.IntRef.slot() # index of the movie open in MovieDetail
251
252
 
252
253
 
253
254
  # ---- Seed ------------------------------------------------------------------
@@ -334,7 +335,7 @@ def _rows_filtered() -> nu.Nu:
334
335
  # Seed once, on a store that has never been written. A restart then keeps what
335
336
  # the user logged instead of replacing the shelf with the samples again.
336
337
  # `selected` stays unconditional: it is a cursor into the detail page, not data.
337
- init = nu.kv.Transaction(
338
+ init = nustd.kv.Transaction(
338
339
  nu.IfDo(
339
340
  State.total.missing(),
340
341
  State.total.set(len(_SEED_MOVIES))
@@ -346,7 +347,7 @@ init = nu.kv.Transaction(
346
347
  )
347
348
 
348
349
 
349
- hydrate = nu.kv.Snapshot(
350
+ hydrate = nustd.kv.Snapshot(
350
351
  App.movies.stats.body.total.set_value(nu.str(State.total))
351
352
  | App.movies.stats.body.watched.set_value(nu.str(State.watched))
352
353
  | App.movies.stats.body.unseen.set_value(nu.str(State.total - State.watched))
@@ -357,7 +358,7 @@ hydrate = nu.kv.Snapshot(
357
358
 
358
359
  on_add = nu.ReactForever(
359
360
  App.movies.form.submit.on_click(),
360
- nu.kv.Transaction(
361
+ nustd.kv.Transaction(
361
362
  State.movies.append(
362
363
  nu.Dict.of(
363
364
  title=nu.Str(App.movies.form.details.title.input),
@@ -374,7 +375,7 @@ on_add = nu.ReactForever(
374
375
  )
375
376
  | State.latest_title.set(nu.Str(App.movies.form.details.title.input)),
376
377
  )
377
- >> nu.kv.Snapshot(
378
+ >> nustd.kv.Snapshot(
378
379
  App.movies.shelf.body.table.set(_rows_form())
379
380
  | App.movies.stats.body.total.set_value(nu.str(State.total))
380
381
  | App.movies.stats.body.watched.set_value(nu.str(State.watched))
@@ -392,8 +393,8 @@ on_row_click = nu.ReactForever(
392
393
  App.movies.shelf.body.table.on_row_click(),
393
394
  nu.IfDo(
394
395
  nu.Contains(nu.DictAttrRef("row_click"), "row_index"),
395
- nu.kv.Transaction(State.selected.set(nu.DictAttrRef("row_click")["row_index"]))
396
- >> nu.kv.Snapshot(
396
+ nustd.kv.Transaction(State.selected.set(nu.DictAttrRef("row_click")["row_index"]))
397
+ >> nustd.kv.Snapshot(
397
398
  App.detail.heading.set(State.movies[State.selected].title)
398
399
  | App.detail.meta.meta.year.set_value(nu.str(State.movies[State.selected].year))
399
400
  | App.detail.meta.meta.genre.set_value(State.movies[State.selected].genre)
@@ -411,10 +412,10 @@ on_row_click = nu.ReactForever(
411
412
 
412
413
  on_delete = nu.ReactForever(
413
414
  App.detail.actions.remove.on_click(),
414
- nu.kv.Transaction(
415
+ nustd.kv.Transaction(
415
416
  State.movies.del_at(State.selected) >> State.total.set(nu.Len(State.movies)),
416
417
  )
417
- >> nu.kv.Snapshot(
418
+ >> nustd.kv.Snapshot(
418
419
  App.movies.shelf.body.table.set(_rows_form())
419
420
  | App.movies.stats.body.total.set_value(nu.str(State.total))
420
421
  | App.movies.stats.body.unseen.set_value(nu.str(State.total - State.watched))
@@ -434,13 +435,13 @@ on_about_back = nu.ReactForever(App.about.actions.back.on_click(), App.nav.set("
434
435
 
435
436
  on_filter_apply = nu.ReactForever(
436
437
  App.movies.filters.body.apply.on_click(),
437
- nu.kv.Snapshot(App.movies.shelf.body.table.set(_rows_filtered())),
438
+ nustd.kv.Snapshot(App.movies.shelf.body.table.set(_rows_filtered())),
438
439
  )
439
440
 
440
441
 
441
442
  on_filter_clear = nu.ReactForever(
442
443
  App.movies.filters.body.clear.on_click(),
443
- nu.kv.Snapshot(
444
+ nustd.kv.Snapshot(
444
445
  App.movies.filters.body.min_rating.input.set(1.0)
445
446
  | App.movies.filters.body.genre.input.set("")
446
447
  | App.movies.filters.body.watched_only.input.set(False)
@@ -466,9 +467,9 @@ ui = (
466
467
 
467
468
 
468
469
  app = nu.With(
469
- nu.kv.rocksdb_navigator(str(_DB)),
470
- nu.ui.server(nu.kv.auto_flow_atomic(ui)),
471
- body=nu.kv.auto_flow_atomic(init >> nu.ForeverDo(nu.Delay(3600))),
470
+ nustd.kv.rocksdb_navigator(str(_DB)),
471
+ nustd.ui.server(nustd.kv.auto_flow_atomic(ui)),
472
+ body=nustd.kv.auto_flow_atomic(init >> nu.ForeverDo(nu.Delay(3600))),
472
473
  )
473
474
 
474
475
 
@@ -3,6 +3,7 @@
3
3
  from pathlib import Path
4
4
 
5
5
  import nu
6
+ import nustd
6
7
 
7
8
 
8
9
  _DB = Path.home() / ".nu" / "demos" / "sampled"
@@ -12,31 +13,31 @@ _DB.parent.mkdir(parents=True, exist_ok=True)
12
13
  class State(nu.Shape):
13
14
  """Persistent series and write cursor."""
14
15
 
15
- nums = nu.kv.Kh57Ref.slot(int)
16
- cursor = nu.kv.IntRef.slot()
16
+ nums = nustd.kv.Kh57Ref.slot(int)
17
+ cursor = nustd.kv.IntRef.slot()
17
18
 
18
19
 
19
- class Links(nu.ui.Row):
20
- docs = nu.ui.LinkRef.slot(
20
+ class Links(nustd.ui.Row):
21
+ docs = nustd.ui.LinkRef.slot(
21
22
  label="Read the docs", href="https://nustack.dev/docs", target="_blank"
22
23
  )
23
- github = nu.ui.LinkRef.slot(
24
+ github = nustd.ui.LinkRef.slot(
24
25
  label="Star on GitHub", href="https://github.com/nustackdev/nu", target="_blank"
25
26
  )
26
- examples = nu.ui.LinkRef.slot(
27
+ examples = nustd.ui.LinkRef.slot(
27
28
  label="Browse more demos",
28
29
  href="https://github.com/nustackdev/nu/tree/main/examples",
29
30
  target="_blank",
30
31
  )
31
32
 
32
33
 
33
- class Dashboard(nu.ui.Page):
34
+ class Dashboard(nustd.ui.Page):
34
35
  """Live chart page with description and source."""
35
36
 
36
- heading = nu.ui.HeadingRef.slot(label="Unbounded series, instant chart")
37
- chart = nu.ui.LineChart.slot()
38
- about_heading = nu.ui.HeadingRef.slot(label="How it works")
39
- about = nu.ui.MarkdownRef.slot(
37
+ heading = nustd.ui.HeadingRef.slot(label="Unbounded series, instant chart")
38
+ chart = nustd.ui.LineChart.slot()
39
+ about_heading = nustd.ui.HeadingRef.slot(label="How it works")
40
+ about = nustd.ui.MarkdownRef.slot(
40
41
  value=(
41
42
  "- Writes 50 numbers a second into a **kh57-backed** series. Grows without limit.\n"
42
43
  "- Chart repaints from a 200-point reservoir sample. Same cost at 1k rows or 1B.\n"
@@ -45,22 +46,22 @@ class Dashboard(nu.ui.Page):
45
46
  "- Same Interactions used to orchestrate the feed and the redraw.\n"
46
47
  ),
47
48
  )
48
- links_heading = nu.ui.HeadingRef.slot(label="Try Nu yourself")
49
- links_intro = nu.ui.TextRef.slot(
49
+ links_heading = nustd.ui.HeadingRef.slot(label="Try Nu yourself")
50
+ links_intro = nustd.ui.TextRef.slot(
50
51
  value="Billion-row backends, live UIs, no glue. See how far the primitive goes.",
51
52
  )
52
53
  links = Links.slot(gap=4, align="center", wrap=True)
53
- source_heading = nu.ui.HeadingRef.slot(label="Source")
54
- source_intro = nu.ui.TextRef.slot(
54
+ source_heading = nustd.ui.HeadingRef.slot(label="Source")
55
+ source_intro = nustd.ui.TextRef.slot(
55
56
  value="The whole app, one file. Storage, UI, and the wires between them.",
56
57
  )
57
- source = nu.ui.CodeBlockRef.slot(
58
+ source = nustd.ui.CodeBlockRef.slot(
58
59
  code=Path(__file__).read_text(),
59
60
  language="python",
60
61
  )
61
62
 
62
63
 
63
- class App(nu.ui.Index):
64
+ class App(nustd.ui.Index):
64
65
  """UI index with one page."""
65
66
 
66
67
  home = Dashboard.slot("/")
@@ -81,9 +82,9 @@ feed = State.cursor.init(0) >> nu.ForeverDo(
81
82
 
82
83
  # assemble: rocksdb-backed, served over the browser
83
84
  app = nu.With(
84
- nu.kv.rocksdb_navigator(str(_DB)),
85
- nu.ui.server(nu.kv.auto_flow_atomic(ui)),
86
- body=nu.kv.auto_flow_atomic(feed),
85
+ nustd.kv.rocksdb_navigator(str(_DB)),
86
+ nustd.ui.server(nustd.kv.auto_flow_atomic(ui)),
87
+ body=nustd.kv.auto_flow_atomic(feed),
87
88
  )
88
89
 
89
90
 
@@ -4,11 +4,11 @@ from __future__ import annotations
4
4
 
5
5
  import rich_click as click
6
6
 
7
- from nu._cli._meta import nu_version
8
- from nu._cli.commands.demo import demo
9
- from nu._cli.commands.doctor import doctor
10
- from nu._cli.commands.telemetry import telemetry
11
7
  from nu._config.branding import BLUE, PURPLE, render_header
8
+ from nucli._meta import nu_version
9
+ from nucli.commands.demo import demo
10
+ from nucli.commands.doctor import doctor
11
+ from nucli.commands.telemetry import telemetry
12
12
 
13
13
 
14
14
  # Rich-click styling: strict brand duo -- purple headers, blue values.
@@ -1,7 +0,0 @@
1
- """Enables `python -m nu._cli`."""
2
-
3
- from nu._cli.main import main
4
-
5
-
6
- if __name__ == "__main__":
7
- main()
File without changes
File without changes