fdl-cli 0.12.1__tar.gz → 0.13.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.
- {fdl_cli-0.12.1 → fdl_cli-0.13.0}/CHANGELOG.md +11 -0
- {fdl_cli-0.12.1 → fdl_cli-0.13.0}/PKG-INFO +1 -1
- {fdl_cli-0.12.1 → fdl_cli-0.13.0}/docs/spec.md +2 -1
- {fdl_cli-0.12.1 → fdl_cli-0.13.0}/pyproject.toml +1 -1
- {fdl_cli-0.12.1 → fdl_cli-0.13.0}/src/fdl/repo.py +10 -2
- {fdl_cli-0.12.1 → fdl_cli-0.13.0}/tests/test_repo.py +12 -3
- {fdl_cli-0.12.1 → fdl_cli-0.13.0}/.github/workflows/docs.yml +0 -0
- {fdl_cli-0.12.1 → fdl_cli-0.13.0}/.github/workflows/publish.yml +0 -0
- {fdl_cli-0.12.1 → fdl_cli-0.13.0}/.github/workflows/release.yml +0 -0
- {fdl_cli-0.12.1 → fdl_cli-0.13.0}/.gitignore +0 -0
- {fdl_cli-0.12.1 → fdl_cli-0.13.0}/.python-version +0 -0
- {fdl_cli-0.12.1 → fdl_cli-0.13.0}/CLAUDE.md +0 -0
- {fdl_cli-0.12.1 → fdl_cli-0.13.0}/CONTRIBUTING.md +0 -0
- {fdl_cli-0.12.1 → fdl_cli-0.13.0}/LICENSE +0 -0
- {fdl_cli-0.12.1 → fdl_cli-0.13.0}/README.md +0 -0
- {fdl_cli-0.12.1 → fdl_cli-0.13.0}/docs/CNAME +0 -0
- {fdl_cli-0.12.1 → fdl_cli-0.13.0}/docs/cli.md +0 -0
- {fdl_cli-0.12.1 → fdl_cli-0.13.0}/docs/index.md +0 -0
- {fdl_cli-0.12.1 → fdl_cli-0.13.0}/src/fdl/__init__.py +0 -0
- {fdl_cli-0.12.1 → fdl_cli-0.13.0}/src/fdl/catalog.py +0 -0
- {fdl_cli-0.12.1 → fdl_cli-0.13.0}/src/fdl/cli.py +0 -0
- {fdl_cli-0.12.1 → fdl_cli-0.13.0}/src/fdl/layout.py +0 -0
- {fdl_cli-0.12.1 → fdl_cli-0.13.0}/src/fdl/py.typed +0 -0
- {fdl_cli-0.12.1 → fdl_cli-0.13.0}/src/fdl/refs.py +0 -0
- {fdl_cli-0.12.1 → fdl_cli-0.13.0}/src/fdl/store.py +0 -0
- {fdl_cli-0.12.1 → fdl_cli-0.13.0}/src/fdl/stores.py +0 -0
- {fdl_cli-0.12.1 → fdl_cli-0.13.0}/src/fdl/version.py +0 -0
- {fdl_cli-0.12.1 → fdl_cli-0.13.0}/tests/test_cli.py +0 -0
- {fdl_cli-0.12.1 → fdl_cli-0.13.0}/tests/test_stores.py +0 -0
- {fdl_cli-0.12.1 → fdl_cli-0.13.0}/uv.lock +0 -0
- {fdl_cli-0.12.1 → fdl_cli-0.13.0}/zensical.toml +0 -0
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
## v0.13.0 (2026-11-01)
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
- Give each repository an id in fdl.json
|
|
9
|
+
([`389ec96`](https://github.com/queria-io/fdl/commit/389ec96899d7c33fe0fbcf11d6d958de8b1fcb1a))
|
|
10
|
+
|
|
11
|
+
init writes a UUID that never changes, so a copy of a repository can tell it holds the same one.
|
|
12
|
+
Repositories started without one still read.
|
|
13
|
+
|
|
14
|
+
|
|
4
15
|
## v0.12.1 (2026-10-30)
|
|
5
16
|
|
|
6
17
|
### Bug Fixes
|
|
@@ -58,6 +58,7 @@ Paths are relative to the root, lower case, separated by `/`. The root is what a
|
|
|
58
58
|
```json
|
|
59
59
|
{
|
|
60
60
|
"fdl": "0.1",
|
|
61
|
+
"id": "5f0c8a52-6d3e-4f8e-9b1a-2c7d4e9f0a13",
|
|
61
62
|
"data_dir": "data/",
|
|
62
63
|
"catalog_formats": [
|
|
63
64
|
{ "ducklake": "1.1" },
|
|
@@ -67,6 +68,7 @@ Paths are relative to the root, lower case, separated by `/`. The root is what a
|
|
|
67
68
|
```
|
|
68
69
|
|
|
69
70
|
- `fdl` is the version of this specification. A reader must not read a major version it does not know
|
|
71
|
+
- `id` is a UUID written when the repository is started and never changed, so a copy of the repository can tell it holds the same one. A service that hosts repositories may use its own ID for the dataset here. Repositories started without one are still read
|
|
70
72
|
- `data_dir` is where data files are. The default is `data/`. A repository whose files already sit under another name declares it here instead of moving them
|
|
71
73
|
- `catalog_formats` lists the DuckLake formats published and until when (see "When the DuckLake format moves"). Without it, only `ducklake.duckdb`
|
|
72
74
|
- Files with other names may sit at the root. Readers ignore them
|
|
@@ -276,7 +278,6 @@ A push from a stale working catalog is refused on two checks:
|
|
|
276
278
|
- How to make a merge (a version with two parents)
|
|
277
279
|
- A compatibility test suite for readers and writers
|
|
278
280
|
- Withdrawal: removing past versions entirely, for example when personal data was published by mistake (`reason: withdrawn`, rewriting Parquet, and the fact that mirrors keep their copies)
|
|
279
|
-
- A repository ID: an immutable `id` in `fdl.json`, so a mirror can tell it holds the same dataset
|
|
280
281
|
- Signatures, for readers of a mirror: anyone can write a `version.json`
|
|
281
282
|
- How to declare retention defaults in `fdl.json` (versions to keep, days)
|
|
282
283
|
|
|
@@ -11,6 +11,7 @@ import hashlib
|
|
|
11
11
|
import itertools
|
|
12
12
|
import json
|
|
13
13
|
import shutil
|
|
14
|
+
import uuid
|
|
14
15
|
from dataclasses import dataclass
|
|
15
16
|
from pathlib import Path
|
|
16
17
|
from typing import Iterator
|
|
@@ -32,6 +33,9 @@ class NotFastForward(RepoError):
|
|
|
32
33
|
class Config:
|
|
33
34
|
fdl: str
|
|
34
35
|
data_dir: str
|
|
36
|
+
#: Never changes, so a copy of the repository can tell it holds the same one.
|
|
37
|
+
#: None for repositories started before it was written.
|
|
38
|
+
id: str | None = None
|
|
35
39
|
|
|
36
40
|
|
|
37
41
|
def init(store: Store, *, data_dir: str = layout.DEFAULT_DATA_DIR) -> Config:
|
|
@@ -42,7 +46,7 @@ def init(store: Store, *, data_dir: str = layout.DEFAULT_DATA_DIR) -> Config:
|
|
|
42
46
|
"""
|
|
43
47
|
if not data_dir.endswith("/"):
|
|
44
48
|
raise RepoError(f"data_dir has to end with '/': {data_dir!r}")
|
|
45
|
-
record = {"fdl": layout.FDL_VERSION, "data_dir": data_dir}
|
|
49
|
+
record = {"fdl": layout.FDL_VERSION, "id": str(uuid.uuid4()), "data_dir": data_dir}
|
|
46
50
|
try:
|
|
47
51
|
store.put(
|
|
48
52
|
layout.CONFIG,
|
|
@@ -67,7 +71,11 @@ def read_config(store: Store) -> Config:
|
|
|
67
71
|
major = str(record.get("fdl", "")).split(".")[0]
|
|
68
72
|
if major != layout.FDL_VERSION.split(".")[0]:
|
|
69
73
|
raise RepoError(f"written for fdl {record.get('fdl')}, this reads {layout.FDL_VERSION}")
|
|
70
|
-
return Config(
|
|
74
|
+
return Config(
|
|
75
|
+
fdl=record["fdl"],
|
|
76
|
+
data_dir=record.get("data_dir", layout.DEFAULT_DATA_DIR),
|
|
77
|
+
id=record.get("id"),
|
|
78
|
+
)
|
|
71
79
|
|
|
72
80
|
|
|
73
81
|
def read_version(store: Store, version_id: str) -> Version:
|
|
@@ -7,6 +7,7 @@ version that comes out the other side.
|
|
|
7
7
|
from __future__ import annotations
|
|
8
8
|
|
|
9
9
|
import json
|
|
10
|
+
import uuid
|
|
10
11
|
from pathlib import Path
|
|
11
12
|
|
|
12
13
|
import duckdb
|
|
@@ -64,11 +65,19 @@ def read_rows(store: LocalStore, version_id: str) -> list[tuple]:
|
|
|
64
65
|
|
|
65
66
|
|
|
66
67
|
def test_init_writes_the_config_and_head(remote) -> None:
|
|
67
|
-
|
|
68
|
+
config = json.loads(remote.get(layout.CONFIG))
|
|
69
|
+
assert config == {"fdl": "0.1", "id": config["id"], "data_dir": "data/"}
|
|
70
|
+
assert uuid.UUID(config["id"])
|
|
68
71
|
assert remote.get(layout.HEAD) == b"ref: refs/heads/main\n"
|
|
69
72
|
assert repo.head(remote) is None
|
|
70
|
-
# Twice is harmless.
|
|
71
|
-
assert repo.init(remote)
|
|
73
|
+
# Twice is harmless, and the id stays.
|
|
74
|
+
assert repo.init(remote) == repo.Config(fdl="0.1", data_dir="data/", id=config["id"])
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def test_a_repository_without_an_id_still_reads(tmp_path: Path) -> None:
|
|
78
|
+
store = LocalStore(tmp_path / "old")
|
|
79
|
+
store.put(layout.CONFIG, b'{"fdl": "0.1", "data_dir": "ducklake.duckdb.files/"}')
|
|
80
|
+
assert repo.read_config(store).id is None
|
|
72
81
|
|
|
73
82
|
|
|
74
83
|
def test_commit_push_and_read_back(tmp_path: Path, remote) -> None:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|