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.
Files changed (68) hide show
  1. loom_data-0.1.0/PKG-INFO +330 -0
  2. loom_data-0.1.0/README.md +166 -0
  3. loom_data-0.1.0/packages/loom/README.md +311 -0
  4. loom_data-0.1.0/packages/loom/src/loom/__init__.py +16 -0
  5. loom_data-0.1.0/packages/loom/src/loom/__main__.py +5 -0
  6. loom_data-0.1.0/packages/loom/src/loom/chat.py +94 -0
  7. loom_data-0.1.0/packages/loom/src/loom/cli.py +4 -0
  8. loom_data-0.1.0/packages/loom/src/loom/cli_app/__init__.py +3 -0
  9. loom_data-0.1.0/packages/loom/src/loom/cli_app/config.py +10 -0
  10. loom_data-0.1.0/packages/loom/src/loom/cli_app/handlers.py +137 -0
  11. loom_data-0.1.0/packages/loom/src/loom/cli_app/main.py +48 -0
  12. loom_data-0.1.0/packages/loom/src/loom/cli_app/output.py +38 -0
  13. loom_data-0.1.0/packages/loom/src/loom/cli_app/parser.py +79 -0
  14. loom_data-0.1.0/packages/loom/src/loom/cli_app/routing.py +37 -0
  15. loom_data-0.1.0/packages/loom/src/loom/cli_app/skill.py +33 -0
  16. loom_data-0.1.0/packages/loom/src/loom/csv_profile.py +157 -0
  17. loom_data-0.1.0/packages/loom/src/loom/data.py +44 -0
  18. loom_data-0.1.0/packages/loom/src/loom/datacard.py +151 -0
  19. loom_data-0.1.0/packages/loom/src/loom/datacard_parts/__init__.py +13 -0
  20. loom_data-0.1.0/packages/loom/src/loom/datacard_parts/cards.py +66 -0
  21. loom_data-0.1.0/packages/loom/src/loom/datacard_parts/source.py +72 -0
  22. loom_data-0.1.0/packages/loom/src/loom/explore_repo.py +171 -0
  23. loom_data-0.1.0/packages/loom/src/loom/raw_cache.py +1 -0
  24. loom_data-0.1.0/packages/loom/src/loom/raw_cache_support/__init__.py +32 -0
  25. loom_data-0.1.0/packages/loom/src/loom/raw_cache_support/conflicts.py +39 -0
  26. loom_data-0.1.0/packages/loom/src/loom/raw_cache_support/ops.py +89 -0
  27. loom_data-0.1.0/packages/loom/src/loom/raw_cache_support/paths.py +26 -0
  28. loom_data-0.1.0/packages/loom/src/loom/raw_cache_support/state.py +38 -0
  29. loom_data-0.1.0/packages/loom/src/loom/raw_snapshot.py +80 -0
  30. loom_data-0.1.0/packages/loom/src/loom/scan_state.py +40 -0
  31. loom_data-0.1.0/packages/loom/src/loom/scan_support/__init__.py +13 -0
  32. loom_data-0.1.0/packages/loom/src/loom/scan_support/manifest.py +57 -0
  33. loom_data-0.1.0/packages/loom/src/loom/scan_support/state.py +22 -0
  34. loom_data-0.1.0/packages/loom/src/loom/scan_support/tree.py +17 -0
  35. loom_data-0.1.0/packages/loom/src/loom/scanner.py +120 -0
  36. loom_data-0.1.0/packages/loom/src/loom/sync_client.py +30 -0
  37. loom_data-0.1.0/packages/loom/src/loom/sync_ops/__init__.py +13 -0
  38. loom_data-0.1.0/packages/loom/src/loom/sync_ops/http.py +18 -0
  39. loom_data-0.1.0/packages/loom/src/loom/sync_ops/models.py +40 -0
  40. loom_data-0.1.0/packages/loom/src/loom/sync_ops/public.py +28 -0
  41. loom_data-0.1.0/packages/loom/src/loom/sync_ops/raw.py +81 -0
  42. loom_data-0.1.0/packages/loom/src/loom/sync_ops/state.py +24 -0
  43. loom_data-0.1.0/packages/loom/src/loom/sync_ops/workspace.py +109 -0
  44. loom_data-0.1.0/packages/loom/src/loom/sync_server.py +26 -0
  45. loom_data-0.1.0/packages/loom/src/loom/sync_service.py +26 -0
  46. loom_data-0.1.0/packages/loom/src/loom/sync_state.py +65 -0
  47. loom_data-0.1.0/packages/loom/src/loom/workspace_merge.py +168 -0
  48. loom_data-0.1.0/packages/loom/src/loom/workspace_snapshot.py +183 -0
  49. loom_data-0.1.0/packages/loom/src/loom_data.egg-info/PKG-INFO +330 -0
  50. loom_data-0.1.0/packages/loom/src/loom_data.egg-info/SOURCES.txt +66 -0
  51. loom_data-0.1.0/packages/loom/src/loom_data.egg-info/dependency_links.txt +1 -0
  52. loom_data-0.1.0/packages/loom/src/loom_data.egg-info/entry_points.txt +2 -0
  53. loom_data-0.1.0/packages/loom/src/loom_data.egg-info/top_level.txt +1 -0
  54. loom_data-0.1.0/pyproject.toml +45 -0
  55. loom_data-0.1.0/setup.cfg +4 -0
  56. loom_data-0.1.0/tests/test_chat.py +62 -0
  57. loom_data-0.1.0/tests/test_cli_workflow.py +106 -0
  58. loom_data-0.1.0/tests/test_csv_profile.py +63 -0
  59. loom_data-0.1.0/tests/test_explore_api.py +59 -0
  60. loom_data-0.1.0/tests/test_install.py +42 -0
  61. loom_data-0.1.0/tests/test_packaging_metadata.py +29 -0
  62. loom_data-0.1.0/tests/test_raw_access_cache.py +51 -0
  63. loom_data-0.1.0/tests/test_raw_access_refresh.py +58 -0
  64. loom_data-0.1.0/tests/test_scanner.py +156 -0
  65. loom_data-0.1.0/tests/test_sync_conflicts.py +62 -0
  66. loom_data-0.1.0/tests/test_sync_push_pull.py +50 -0
  67. loom_data-0.1.0/tests/test_sync_raw_history.py +37 -0
  68. loom_data-0.1.0/tests/test_sync_rebase.py +59 -0
@@ -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
+ ```