loom-data 0.1.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.
- loom_data-0.1.0/PKG-INFO +330 -0
- loom_data-0.1.0/README.md +166 -0
- loom_data-0.1.0/packages/loom/README.md +311 -0
- loom_data-0.1.0/packages/loom/src/loom/__init__.py +16 -0
- loom_data-0.1.0/packages/loom/src/loom/__main__.py +5 -0
- loom_data-0.1.0/packages/loom/src/loom/chat.py +94 -0
- loom_data-0.1.0/packages/loom/src/loom/cli.py +4 -0
- loom_data-0.1.0/packages/loom/src/loom/cli_app/__init__.py +3 -0
- loom_data-0.1.0/packages/loom/src/loom/cli_app/config.py +10 -0
- loom_data-0.1.0/packages/loom/src/loom/cli_app/handlers.py +137 -0
- loom_data-0.1.0/packages/loom/src/loom/cli_app/main.py +48 -0
- loom_data-0.1.0/packages/loom/src/loom/cli_app/output.py +38 -0
- loom_data-0.1.0/packages/loom/src/loom/cli_app/parser.py +79 -0
- loom_data-0.1.0/packages/loom/src/loom/cli_app/routing.py +37 -0
- loom_data-0.1.0/packages/loom/src/loom/cli_app/skill.py +33 -0
- loom_data-0.1.0/packages/loom/src/loom/csv_profile.py +157 -0
- loom_data-0.1.0/packages/loom/src/loom/data.py +44 -0
- loom_data-0.1.0/packages/loom/src/loom/datacard.py +151 -0
- loom_data-0.1.0/packages/loom/src/loom/datacard_parts/__init__.py +13 -0
- loom_data-0.1.0/packages/loom/src/loom/datacard_parts/cards.py +66 -0
- loom_data-0.1.0/packages/loom/src/loom/datacard_parts/source.py +72 -0
- loom_data-0.1.0/packages/loom/src/loom/explore_repo.py +171 -0
- loom_data-0.1.0/packages/loom/src/loom/raw_cache.py +1 -0
- loom_data-0.1.0/packages/loom/src/loom/raw_cache_support/__init__.py +32 -0
- loom_data-0.1.0/packages/loom/src/loom/raw_cache_support/conflicts.py +39 -0
- loom_data-0.1.0/packages/loom/src/loom/raw_cache_support/ops.py +89 -0
- loom_data-0.1.0/packages/loom/src/loom/raw_cache_support/paths.py +26 -0
- loom_data-0.1.0/packages/loom/src/loom/raw_cache_support/state.py +38 -0
- loom_data-0.1.0/packages/loom/src/loom/raw_snapshot.py +80 -0
- loom_data-0.1.0/packages/loom/src/loom/scan_state.py +40 -0
- loom_data-0.1.0/packages/loom/src/loom/scan_support/__init__.py +13 -0
- loom_data-0.1.0/packages/loom/src/loom/scan_support/manifest.py +57 -0
- loom_data-0.1.0/packages/loom/src/loom/scan_support/state.py +22 -0
- loom_data-0.1.0/packages/loom/src/loom/scan_support/tree.py +17 -0
- loom_data-0.1.0/packages/loom/src/loom/scanner.py +120 -0
- loom_data-0.1.0/packages/loom/src/loom/sync_client.py +30 -0
- loom_data-0.1.0/packages/loom/src/loom/sync_ops/__init__.py +13 -0
- loom_data-0.1.0/packages/loom/src/loom/sync_ops/http.py +18 -0
- loom_data-0.1.0/packages/loom/src/loom/sync_ops/models.py +40 -0
- loom_data-0.1.0/packages/loom/src/loom/sync_ops/public.py +28 -0
- loom_data-0.1.0/packages/loom/src/loom/sync_ops/raw.py +81 -0
- loom_data-0.1.0/packages/loom/src/loom/sync_ops/state.py +24 -0
- loom_data-0.1.0/packages/loom/src/loom/sync_ops/workspace.py +109 -0
- loom_data-0.1.0/packages/loom/src/loom/sync_server.py +26 -0
- loom_data-0.1.0/packages/loom/src/loom/sync_service.py +26 -0
- loom_data-0.1.0/packages/loom/src/loom/sync_state.py +65 -0
- loom_data-0.1.0/packages/loom/src/loom/workspace_merge.py +168 -0
- loom_data-0.1.0/packages/loom/src/loom/workspace_snapshot.py +183 -0
- loom_data-0.1.0/packages/loom/src/loom_data.egg-info/PKG-INFO +330 -0
- loom_data-0.1.0/packages/loom/src/loom_data.egg-info/SOURCES.txt +66 -0
- loom_data-0.1.0/packages/loom/src/loom_data.egg-info/dependency_links.txt +1 -0
- loom_data-0.1.0/packages/loom/src/loom_data.egg-info/entry_points.txt +2 -0
- loom_data-0.1.0/packages/loom/src/loom_data.egg-info/top_level.txt +1 -0
- loom_data-0.1.0/pyproject.toml +45 -0
- loom_data-0.1.0/setup.cfg +4 -0
- loom_data-0.1.0/tests/test_chat.py +62 -0
- loom_data-0.1.0/tests/test_cli_workflow.py +106 -0
- loom_data-0.1.0/tests/test_csv_profile.py +63 -0
- loom_data-0.1.0/tests/test_explore_api.py +59 -0
- loom_data-0.1.0/tests/test_install.py +42 -0
- loom_data-0.1.0/tests/test_packaging_metadata.py +29 -0
- loom_data-0.1.0/tests/test_raw_access_cache.py +51 -0
- loom_data-0.1.0/tests/test_raw_access_refresh.py +58 -0
- loom_data-0.1.0/tests/test_scanner.py +156 -0
- loom_data-0.1.0/tests/test_sync_conflicts.py +62 -0
- loom_data-0.1.0/tests/test_sync_push_pull.py +50 -0
- loom_data-0.1.0/tests/test_sync_raw_history.py +37 -0
- loom_data-0.1.0/tests/test_sync_rebase.py +59 -0
loom_data-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: loom-data
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python client and CLI for Loom workspace data and sync workflows.
|
|
5
|
+
Project-URL: Homepage, https://github.com/yechenyan/loom
|
|
6
|
+
Project-URL: Repository, https://github.com/yechenyan/loom
|
|
7
|
+
Project-URL: Issues, https://github.com/yechenyan/loom/issues
|
|
8
|
+
Keywords: cli,data,loom,sync,workspace
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Environment :: Console
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
16
|
+
Classifier: Topic :: Utilities
|
|
17
|
+
Requires-Python: >=3.12
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
# loom-data
|
|
21
|
+
|
|
22
|
+
`loom-data` publishes the `loom` Python package and the `loom` CLI.
|
|
23
|
+
|
|
24
|
+
It is used to:
|
|
25
|
+
|
|
26
|
+
- read raw Loom data with a local cache
|
|
27
|
+
- scan `loom_raw` datasets into summarized `loom_explore` outputs
|
|
28
|
+
- review and confirm local workspace changes
|
|
29
|
+
- push and pull workspaces against a Loom sync server
|
|
30
|
+
|
|
31
|
+
The install name is `loom-data`, but the Python import stays `import loom` and the command stays `loom`.
|
|
32
|
+
|
|
33
|
+
## What Loom does
|
|
34
|
+
|
|
35
|
+
Loom turns raw datasets under `test-project/loom/loom_raw` into structured summaries under `test-project/loom/loom_explore`.
|
|
36
|
+
|
|
37
|
+
This lets agents and people read generated overviews, profiles, and data cards first, instead of opening every raw CSV directly.
|
|
38
|
+
|
|
39
|
+
## Directory layout
|
|
40
|
+
|
|
41
|
+
Loom expects this workspace layout:
|
|
42
|
+
|
|
43
|
+
- `test-project/loom/loom_raw/<topic>`: raw source datasets
|
|
44
|
+
- `test-project/loom/loom_explore/<topic>`: generated scan output
|
|
45
|
+
- `test-project/loom/.loom/raw/<workspace>`: local raw cache
|
|
46
|
+
|
|
47
|
+
In this repository:
|
|
48
|
+
|
|
49
|
+
- client package source: `packages/loom/src/loom`
|
|
50
|
+
- server package source: `packages/loom-server/src/loom_server`
|
|
51
|
+
|
|
52
|
+
## Dataset rule
|
|
53
|
+
|
|
54
|
+
If a directory contains `loom.md`, Loom treats that directory as a dataset root.
|
|
55
|
+
|
|
56
|
+
That dataset includes CSV files under the directory and its children. If a nested child directory also has its own `loom.md`, it becomes a separate dataset and is not folded into the parent dataset scan.
|
|
57
|
+
|
|
58
|
+
## Install
|
|
59
|
+
|
|
60
|
+
Install from PyPI:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
pip install loom-data
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
For local development in this repository:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
uv sync
|
|
70
|
+
uv pip install -e .
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
If you also want the FastAPI sync server and `loom-server` CLI:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
uv pip install -e packages/loom-server
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Initial setup
|
|
80
|
+
|
|
81
|
+
Run this once in a workspace to install the local Codex skill and initialize `loom_explore` as a separate git repository:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
loom install
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Or, if you want to be explicit:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
loom install --workspace-root /path/to/workspace
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
This setup is what enables the scan workflow to show pending changes and later confirm them into the `loom_explore` git history.
|
|
94
|
+
|
|
95
|
+
## Python API
|
|
96
|
+
|
|
97
|
+
Read one raw file and make sure it exists in the local raw cache:
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
import loom
|
|
101
|
+
|
|
102
|
+
local_path = loom.get("energy/technology-data/costs.csv")
|
|
103
|
+
print(local_path)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Refresh a workspace raw cache:
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
import loom
|
|
110
|
+
|
|
111
|
+
loom.pull("energy")
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Parse chat text into a Loom request:
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
import loom
|
|
118
|
+
|
|
119
|
+
request = loom.parse_chat_request("loom scan energy")
|
|
120
|
+
print(request)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## CLI overview
|
|
124
|
+
|
|
125
|
+
Main commands:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
loom install
|
|
129
|
+
loom scan <topic>
|
|
130
|
+
loom route "<message>"
|
|
131
|
+
loom get <workspace/path/to/file>
|
|
132
|
+
loom pull-raw [workspace]
|
|
133
|
+
loom status [workspace]
|
|
134
|
+
loom confirm [workspace]
|
|
135
|
+
loom push [workspace]
|
|
136
|
+
loom pull [workspace]
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
If `workspace` is omitted for `push`, `pull`, or `pull-raw`, Loom uses all available top-level workspaces where that behavior is supported.
|
|
140
|
+
|
|
141
|
+
## Scan a topic
|
|
142
|
+
|
|
143
|
+
Run a local scan:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
loom scan energy
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
This scan is local Python logic only. It will:
|
|
150
|
+
|
|
151
|
+
- inspect `test-project/loom/loom_raw/energy`
|
|
152
|
+
- find dataset roots via `loom.md`
|
|
153
|
+
- read CSV files
|
|
154
|
+
- generate dataset summaries and cards
|
|
155
|
+
- write outputs to `test-project/loom/loom_explore/energy`
|
|
156
|
+
- print the resulting pending changes
|
|
157
|
+
|
|
158
|
+
You can also test whether a chat message would route into a Loom action:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
loom route "loom scan energy"
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Review and confirm scan output
|
|
165
|
+
|
|
166
|
+
After a scan:
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
loom status energy
|
|
170
|
+
loom confirm energy
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
`loom status` shows pending files plus sync metadata.
|
|
174
|
+
|
|
175
|
+
`loom confirm` creates a commit inside the separate `loom_explore` git repository so the workspace has a local confirmed state before syncing.
|
|
176
|
+
|
|
177
|
+
## Read raw data
|
|
178
|
+
|
|
179
|
+
Use the CLI:
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
loom get energy/technology-data/costs.csv
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Use the Python API:
|
|
186
|
+
|
|
187
|
+
```python
|
|
188
|
+
import loom
|
|
189
|
+
|
|
190
|
+
path = loom.get("energy/technology-data/costs.csv")
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Lookup behavior:
|
|
194
|
+
|
|
195
|
+
- Loom first checks `test-project/loom/.loom/raw/...`
|
|
196
|
+
- if the file is already cached locally, that path is reused
|
|
197
|
+
- if a matching file already exists under `test-project/loom/loom_raw/...` or `.raw_data/...`, Loom links it into `.loom/raw`
|
|
198
|
+
- otherwise Loom fetches the latest version from the Loom sync server
|
|
199
|
+
|
|
200
|
+
Repeated reads reuse the local cache.
|
|
201
|
+
|
|
202
|
+
## Refresh raw cache
|
|
203
|
+
|
|
204
|
+
Refresh one workspace:
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
loom pull-raw energy --server-url http://127.0.0.1:8765
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Or in Python:
|
|
211
|
+
|
|
212
|
+
```python
|
|
213
|
+
import loom
|
|
214
|
+
|
|
215
|
+
loom.pull("energy")
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
`loom pull-raw` and `loom.pull(...)` compare the remote raw manifest by `path + sha256` and only refresh changed or deleted files.
|
|
219
|
+
|
|
220
|
+
## Push and pull workspaces
|
|
221
|
+
|
|
222
|
+
Push one workspace:
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
loom push energy --server-url http://127.0.0.1:8765
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Pull one workspace:
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
loom pull energy --server-url http://127.0.0.1:8765
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Pull all workspaces:
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
loom pull --server-url http://127.0.0.1:8765
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Current sync behavior is rebase-oriented:
|
|
241
|
+
|
|
242
|
+
- `push` auto-confirms pending local changes before sending
|
|
243
|
+
- if the remote has advanced, `push` rebases local confirmed work first, then continues
|
|
244
|
+
- `pull` fast-forwards when possible
|
|
245
|
+
- if local confirmed commits exist, `pull` rebases them on top of the latest remote revision
|
|
246
|
+
- rebase conflicts return a non-zero exit code and keep conflict markers in `loom_explore`
|
|
247
|
+
|
|
248
|
+
After resolving a conflict, run:
|
|
249
|
+
|
|
250
|
+
```bash
|
|
251
|
+
loom confirm <workspace>
|
|
252
|
+
loom push <workspace>
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## Optional server commands
|
|
256
|
+
|
|
257
|
+
The published `loom-data` package focuses on client workflows. Server commands require the separate `loom-server` package.
|
|
258
|
+
|
|
259
|
+
Install it first:
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
pip install loom-server
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
Or in this repository:
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
uv pip install -e packages/loom-server
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
Then you can use:
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
loom server-init-db
|
|
275
|
+
loom server-run
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
Default server URL:
|
|
279
|
+
|
|
280
|
+
```text
|
|
281
|
+
http://127.0.0.1:8765
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
Default database URL:
|
|
285
|
+
|
|
286
|
+
```text
|
|
287
|
+
postgresql+psycopg2://loom@127.0.0.1:5432/loom
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
Initialize the server database:
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
loom server-init-db
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
Run the server:
|
|
297
|
+
|
|
298
|
+
```bash
|
|
299
|
+
loom server-run --storage-root /tmp/loom-server-storage
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
## Scan outputs
|
|
303
|
+
|
|
304
|
+
After scanning, Loom writes files such as:
|
|
305
|
+
|
|
306
|
+
- `README.md`: topic-level entry file
|
|
307
|
+
- `overview.md`: dataset overview
|
|
308
|
+
- `profile.json`: dataset-level machine-readable summary
|
|
309
|
+
- `*.card.md`: per-CSV data card
|
|
310
|
+
- `*.profile.json`: per-CSV machine-readable profile
|
|
311
|
+
|
|
312
|
+
## Release
|
|
313
|
+
|
|
314
|
+
Build distributions:
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
uv build
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
Upload to TestPyPI first:
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
uv publish --publish-url https://test.pypi.org/legacy/
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
Upload to PyPI:
|
|
327
|
+
|
|
328
|
+
```bash
|
|
329
|
+
uv publish
|
|
330
|
+
```
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# loom workspace
|
|
2
|
+
|
|
3
|
+
This repository is configured as a `uv` workspace.
|
|
4
|
+
|
|
5
|
+
## Quick start
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
uv sync
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Install the client package in editable mode if you want both the Python API and the `loom` CLI on your shell path:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
uv pip install -e .
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
For PyPI installs, use the published project name `loom-data`:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pip install loom-data
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Install the service package separately when you want the FastAPI sync service and the `loom-server` CLI:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
uv pip install -e packages/loom-server
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Then you can use either form:
|
|
30
|
+
|
|
31
|
+
```python
|
|
32
|
+
import loom
|
|
33
|
+
|
|
34
|
+
path = loom.get("energy/technology-data/costs.csv")
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
loom get energy/technology-data/costs.csv
|
|
39
|
+
loom pull-raw energy
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Raw cache and local Loom state now live under:
|
|
43
|
+
|
|
44
|
+
```text
|
|
45
|
+
test-project/loom/.loom/
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Raw access behavior:
|
|
49
|
+
|
|
50
|
+
- `loom.get("workspace/path/to/file")` first checks `test-project/loom/.loom/raw/...`
|
|
51
|
+
- if the file is already available locally, Loom reuses it
|
|
52
|
+
- if a matching local raw source exists under `test-project/loom/loom_raw` or `.raw_data`, Loom links that file into `.loom/raw`
|
|
53
|
+
- otherwise Loom fetches only the missing latest file from the sync server
|
|
54
|
+
- `loom.pull(...)` and `loom pull-raw ...` compare the remote raw manifest by path and hash, then refresh only changed or deleted cache entries
|
|
55
|
+
|
|
56
|
+
## Install Loom Scan Fast Path
|
|
57
|
+
|
|
58
|
+
Run this once to install the local Codex skill for `loom scan <topic>` and initialize the `loom_explore` git repo:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
uv run python scripts/loom.py install
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
After that, Codex can recognize chat inputs like `loom scan energy` faster and route them to the scan flow directly.
|
|
65
|
+
|
|
66
|
+
You can also run the scanner manually:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
uv run python scripts/loom.py scan energy
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
After scanning, review changes and confirm them into the local `loom_explore` history:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
uv run python scripts/loom.py status energy
|
|
76
|
+
uv run python scripts/loom.py confirm energy
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Sync Server
|
|
80
|
+
|
|
81
|
+
The sync server now lives in the separate `packages/loom-server` package. It uses FastAPI for the API layer and PostgreSQL for revision metadata.
|
|
82
|
+
|
|
83
|
+
By default, Loom expects a local PostgreSQL instance at:
|
|
84
|
+
|
|
85
|
+
```text
|
|
86
|
+
postgresql+psycopg2://loom@127.0.0.1:5432/loom
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
`loom-server init-db` and `loom-server run` will automatically create the `loom` database if the local PostgreSQL server is reachable and the database does not exist yet.
|
|
90
|
+
|
|
91
|
+
Initialize the server schema:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
uv run python scripts/loom-server.py init-db
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Run the server:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
uv run python scripts/loom-server.py run --storage-root .loom-server-storage
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Push and pull workspaces:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
uv run python scripts/loom.py push energy --server-url http://127.0.0.1:8765
|
|
107
|
+
uv run python scripts/loom.py pull energy --server-url http://127.0.0.1:8765
|
|
108
|
+
uv run python scripts/loom.py pull-raw energy --server-url http://127.0.0.1:8765
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Push and pull now use rebase-style workspace sync:
|
|
112
|
+
|
|
113
|
+
- `push` will auto-confirm local pending changes, pull the latest remote revision when needed, rebase local confirmed work onto it, then continue the incremental push
|
|
114
|
+
- `pull` will fast-forward when possible, or rebase local confirmed work onto the latest remote revision instead of blindly overwriting it
|
|
115
|
+
- if a rebase conflict happens, Loom keeps conflict markers in `loom_explore`, returns a non-zero exit code, and asks you to resolve the files, run `loom confirm <workspace>`, then `loom push <workspace>`
|
|
116
|
+
- normal `pull` / `push` raw refresh only updates files already present under `test-project/loom/.loom/raw/<workspace>/...`
|
|
117
|
+
- `pull-raw` and `loom.pull(...)` still support intentional full raw cache refresh for a workspace
|
|
118
|
+
- if local `test-project/loom/loom_raw/...` files disagree with the remote raw manifest, Loom will not overwrite them and will write `loom.raw-conflict.md` next to the nearest `loom.md`
|
|
119
|
+
|
|
120
|
+
## Web App
|
|
121
|
+
|
|
122
|
+
A React web app lives in [web/package.json](/Users/maxiao/Documents/code2/loom/web/package.json) and reads dataset summaries from the FastAPI server.
|
|
123
|
+
|
|
124
|
+
Install and run it with `pnpm`:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
cd /Users/maxiao/Documents/code2/loom/web
|
|
128
|
+
pnpm install
|
|
129
|
+
pnpm dev --host 127.0.0.1
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Then open:
|
|
133
|
+
|
|
134
|
+
```text
|
|
135
|
+
http://127.0.0.1:4173
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
The Vite dev server proxies `/api` requests to the Loom FastAPI server on `http://127.0.0.1:8765`.
|
|
139
|
+
|
|
140
|
+
## Workspace layout
|
|
141
|
+
|
|
142
|
+
- Root workspace config: `pyproject.toml`
|
|
143
|
+
- Client package source: `packages/loom/src/loom`
|
|
144
|
+
- Service package source: `packages/loom-server/src/loom_server`
|
|
145
|
+
|
|
146
|
+
## Publishing `loom-data`
|
|
147
|
+
|
|
148
|
+
The import package remains `loom`, but the PyPI project name is `loom-data`.
|
|
149
|
+
|
|
150
|
+
Build distributions:
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
uv build
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Upload to TestPyPI first:
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
uv publish --publish-url https://test.pypi.org/legacy/
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Upload to PyPI:
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
uv publish
|
|
166
|
+
```
|