dazzle-linklib 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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Dustin Darcy
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,106 @@
1
+ Metadata-Version: 2.4
2
+ Name: dazzle-linklib
3
+ Version: 0.1.0
4
+ Summary: Content-addressable link-record library -- the DazzleLib stack's L2 serialization layer (typed locators, content_id, export/import/rebase/scan).
5
+ Author-email: djdarcy <djdarcy@users.noreply.github.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/DazzleLib/dazzle-linklib
8
+ Project-URL: Repository, https://github.com/DazzleLib/dazzle-linklib
9
+ Project-URL: Issues, https://github.com/DazzleLib/dazzle-linklib/issues
10
+ Keywords: dazzlelib,links,symlink,junction,serialization,content-addressable,anti-link-rot,relinker,stack
11
+ Classifier: Development Status :: 2 - Pre-Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Software Development :: Libraries
22
+ Classifier: Topic :: System :: Filesystems
23
+ Requires-Python: >=3.9
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Provides-Extra: dev
27
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
28
+ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
29
+ Dynamic: license-file
30
+
31
+ # dazzle-linklib
32
+
33
+ [![PyPI](https://img.shields.io/pypi/v/dazzle-linklib?color=green)](https://pypi.org/project/dazzle-linklib/)
34
+ [![Release Date](https://img.shields.io/github/release-date/DazzleLib/dazzle-linklib?color=green)](https://github.com/DazzleLib/dazzle-linklib/releases)
35
+ [![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/)
36
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
37
+ [![Platform](https://img.shields.io/badge/platform-Windows%20%7C%20Linux%20%7C%20macOS%20%7C%20BSD-lightgrey.svg)](docs/platform-support.md)
38
+
39
+ **Content-addressable link-record library** -- the **L2** serialization layer of
40
+ the [DazzleLib stack](https://github.com/DazzleLib/.github/blob/main/docs/STACK-MAP.md).
41
+
42
+ A link record maps an **identity** to a **typed list of locators** plus
43
+ metadata, and knows how to serialize, find, and resolve itself. One model
44
+ serves three consumers:
45
+
46
+ - the **dazzlelink** filesystem CLI (the `.dazzlelink` file format),
47
+ - **preserve**'s content-hash manifest (L3), and
48
+ - **Relinker** -- a hash-addressed, decentralized anti-link-rot resolver
49
+ (`rln.kr/{hash}` -> a multi-protocol location set).
50
+
51
+ ## What this owns (and what it doesn't)
52
+
53
+ `dazzle-linklib` owns the link **record**: its schema, JSON I/O, the locator
54
+ list, `content_id`, relation edges, and the injectable target resolver. It
55
+ **delegates** the rest down the stack:
56
+
57
+ | Concern | Layer |
58
+ |---|---|
59
+ | Link record, locators, `content_id`, relations, resolve | **dazzle-linklib (L2, this lib)** |
60
+ | File/link mechanics (create/detect/read, copy, hash, metadata) | `dazzle-filekit` (L1) |
61
+ | UNC <-> drive identity, path origin classification | `unctools` (L0) |
62
+ | Shared Protocols / TypedDicts / exception root | `dazzle-lib` (B) |
63
+ | Graph **traversal** (walking the records' relation edges) | `dazzletreelib` (perpendicular) |
64
+
65
+ "Records that point at each other" live here; "walking and interpreting those
66
+ pointers" do not. (See the L2 design rationale, decision D6.)
67
+
68
+ ## Status
69
+
70
+ **0.1.0 is a name-reservation placeholder (pre-alpha).** It is published to
71
+ PyPI to claim the name, but exposes only its version -- there is no functional
72
+ content yet. The extraction of `DazzleLinkData` and the resolver from the
73
+ `dazzlelink` tool is stack phase **P2** and lands in a later release -- see the
74
+ [Roadmap](https://github.com/DazzleLib/dazzle-linklib/issues/2).
75
+
76
+ ## Installation
77
+
78
+ ```bash
79
+ pip install dazzle-linklib
80
+ ```
81
+
82
+ ### From source
83
+
84
+ ```bash
85
+ git clone https://github.com/DazzleLib/dazzle-linklib.git
86
+ cd dazzle-linklib
87
+ pip install -e ".[dev]"
88
+ ```
89
+
90
+ ## Development
91
+
92
+ ```bash
93
+ python -m venv .venv
94
+ source .venv/bin/activate # or .venv\Scripts\activate on Windows
95
+ pip install -e ".[dev]"
96
+
97
+ # Run tests
98
+ python -m pytest tests/ -v
99
+
100
+ # Install git hooks
101
+ bash scripts/install-hooks.sh
102
+ ```
103
+
104
+ ## License
105
+
106
+ MIT. See [LICENSE](LICENSE) for details.
@@ -0,0 +1,76 @@
1
+ # dazzle-linklib
2
+
3
+ [![PyPI](https://img.shields.io/pypi/v/dazzle-linklib?color=green)](https://pypi.org/project/dazzle-linklib/)
4
+ [![Release Date](https://img.shields.io/github/release-date/DazzleLib/dazzle-linklib?color=green)](https://github.com/DazzleLib/dazzle-linklib/releases)
5
+ [![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/)
6
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
7
+ [![Platform](https://img.shields.io/badge/platform-Windows%20%7C%20Linux%20%7C%20macOS%20%7C%20BSD-lightgrey.svg)](docs/platform-support.md)
8
+
9
+ **Content-addressable link-record library** -- the **L2** serialization layer of
10
+ the [DazzleLib stack](https://github.com/DazzleLib/.github/blob/main/docs/STACK-MAP.md).
11
+
12
+ A link record maps an **identity** to a **typed list of locators** plus
13
+ metadata, and knows how to serialize, find, and resolve itself. One model
14
+ serves three consumers:
15
+
16
+ - the **dazzlelink** filesystem CLI (the `.dazzlelink` file format),
17
+ - **preserve**'s content-hash manifest (L3), and
18
+ - **Relinker** -- a hash-addressed, decentralized anti-link-rot resolver
19
+ (`rln.kr/{hash}` -> a multi-protocol location set).
20
+
21
+ ## What this owns (and what it doesn't)
22
+
23
+ `dazzle-linklib` owns the link **record**: its schema, JSON I/O, the locator
24
+ list, `content_id`, relation edges, and the injectable target resolver. It
25
+ **delegates** the rest down the stack:
26
+
27
+ | Concern | Layer |
28
+ |---|---|
29
+ | Link record, locators, `content_id`, relations, resolve | **dazzle-linklib (L2, this lib)** |
30
+ | File/link mechanics (create/detect/read, copy, hash, metadata) | `dazzle-filekit` (L1) |
31
+ | UNC <-> drive identity, path origin classification | `unctools` (L0) |
32
+ | Shared Protocols / TypedDicts / exception root | `dazzle-lib` (B) |
33
+ | Graph **traversal** (walking the records' relation edges) | `dazzletreelib` (perpendicular) |
34
+
35
+ "Records that point at each other" live here; "walking and interpreting those
36
+ pointers" do not. (See the L2 design rationale, decision D6.)
37
+
38
+ ## Status
39
+
40
+ **0.1.0 is a name-reservation placeholder (pre-alpha).** It is published to
41
+ PyPI to claim the name, but exposes only its version -- there is no functional
42
+ content yet. The extraction of `DazzleLinkData` and the resolver from the
43
+ `dazzlelink` tool is stack phase **P2** and lands in a later release -- see the
44
+ [Roadmap](https://github.com/DazzleLib/dazzle-linklib/issues/2).
45
+
46
+ ## Installation
47
+
48
+ ```bash
49
+ pip install dazzle-linklib
50
+ ```
51
+
52
+ ### From source
53
+
54
+ ```bash
55
+ git clone https://github.com/DazzleLib/dazzle-linklib.git
56
+ cd dazzle-linklib
57
+ pip install -e ".[dev]"
58
+ ```
59
+
60
+ ## Development
61
+
62
+ ```bash
63
+ python -m venv .venv
64
+ source .venv/bin/activate # or .venv\Scripts\activate on Windows
65
+ pip install -e ".[dev]"
66
+
67
+ # Run tests
68
+ python -m pytest tests/ -v
69
+
70
+ # Install git hooks
71
+ bash scripts/install-hooks.sh
72
+ ```
73
+
74
+ ## License
75
+
76
+ MIT. See [LICENSE](LICENSE) for details.
@@ -0,0 +1,30 @@
1
+ """dazzle-linklib -- the DazzleLib stack's L2 link-record library.
2
+
3
+ A **content-addressable link record**: one model that maps an identity to a
4
+ typed list of locators plus metadata, and knows how to serialize, find, and
5
+ resolve itself. It is the portable-DATA layer beneath three consumers:
6
+
7
+ * the **dazzlelink** filesystem CLI (the `.dazzlelink` file format),
8
+ * **preserve**'s content-hash manifest (L3), and
9
+ * **Relinker** -- a hash-addressed, decentralized anti-link-rot resolver
10
+ (``rln.kr/{hash}`` -> a multi-protocol location set).
11
+
12
+ The boundary (STACK-MAP, layers B/L0/L1/L2/L3): this library owns the link
13
+ RECORD -- its schema, JSON I/O, locator list, ``content_id``, and relation
14
+ edges -- and the injectable target resolver. It does NOT own filesystem
15
+ mechanics (those delegate down to ``dazzle-filekit`` L1), UNC/drive identity
16
+ (``unctools`` L0), or graph TRAVERSAL (``dazzletreelib`` is the perpendicular
17
+ traversal tier). "Records that point at each other" live here; "walking and
18
+ interpreting those pointers" do not (see the L2 design DWP, decision D6).
19
+
20
+ Status: **scaffold (0.1.0, pre-alpha).** The extraction of ``DazzleLinkData``
21
+ and the resolver from the dazzlelink tool is stack phase **P2** -- tracked on
22
+ the roadmap (issue #2). Until then this package exposes only its version.
23
+
24
+ License: MIT (whole stack; STACK-MAP D11). Architecture contract:
25
+ https://github.com/DazzleLib/.github/blob/main/docs/STACK-MAP.md
26
+ """
27
+
28
+ from ._version import PIP_VERSION, __app_name__, __version__
29
+
30
+ __all__ = ["__version__", "__app_name__", "PIP_VERSION"]
@@ -0,0 +1,16 @@
1
+ """Allow running as: python -m dazzle_linklib
2
+
3
+ dazzle-linklib is a LIBRARY, not a CLI -- the `dazzlelink` command lives in the
4
+ DazzleTools/dazzlelink tool (STACK-MAP D1). Running the module just reports the
5
+ installed version.
6
+ """
7
+ from . import __app_name__, __version__
8
+
9
+
10
+ def main() -> None:
11
+ print(f"{__app_name__} {__version__}")
12
+ print("Library only -- the dazzlelink CLI lives in DazzleTools/dazzlelink.")
13
+
14
+
15
+ if __name__ == "__main__":
16
+ main()
@@ -0,0 +1,92 @@
1
+ """
2
+ Version information for dazzle-linklib.
3
+
4
+ This file is the canonical source for version numbers.
5
+ The __version__ string is automatically updated by git hooks
6
+ with build metadata (branch, build number, date, commit hash).
7
+
8
+ Format: MAJOR.MINOR.PATCH[-PHASE]_BRANCH_BUILD-YYYYMMDD-COMMITHASH
9
+ Example: 0.1.0_main_1-20260101-a1b2c3d4
10
+
11
+ Version levels:
12
+ PROJECT_PHASE: Global project maturity (prealpha -> alpha -> beta -> stable).
13
+ Changes rarely, when the overall project hits a threshold.
14
+ PHASE: Per-MINOR feature set maturity (alpha -> beta -> "" for stable).
15
+ Drops when a MINOR's feature set is complete.
16
+ """
17
+
18
+ # Version components - edit these for version bumps
19
+ MAJOR = 0
20
+ MINOR = 1
21
+ PATCH = 0
22
+ PHASE = "" # Per-MINOR feature set: "" (stable), "alpha", "beta", "rc1", etc.
23
+
24
+ # Project-level phase (independent of version phase)
25
+ PROJECT_PHASE = "" # "prealpha", "alpha", "beta", "stable", or ""
26
+
27
+ # Auto-updated by git hooks - do not edit manually
28
+ __version__ = "0.1.0_main_7-20260619-08de0656"
29
+ __app_name__ = "dazzle-linklib"
30
+
31
+
32
+ def get_version():
33
+ """Return the full version string including branch and build info."""
34
+ return __version__
35
+
36
+
37
+ def get_base_version():
38
+ """Return the semantic version string (MAJOR.MINOR.PATCH[-PHASE])."""
39
+ if "_" in __version__:
40
+ return __version__.split("_")[0]
41
+ base = f"{MAJOR}.{MINOR}.{PATCH}"
42
+ if PHASE:
43
+ base = f"{base}-{PHASE}"
44
+ return base
45
+
46
+
47
+ def get_display_version():
48
+ """Return a human-friendly version string with project phase.
49
+
50
+ Example: 'PREALPHA 0.1.0-alpha' or 'BETA 0.5.1' or '1.0.0'
51
+ """
52
+ base = get_base_version()
53
+ if PROJECT_PHASE and PROJECT_PHASE != "stable":
54
+ return f"{PROJECT_PHASE.upper()} {base}"
55
+ return base
56
+
57
+
58
+ def get_pip_version():
59
+ """
60
+ Return PEP 440 compliant version for pip/setuptools.
61
+
62
+ Converts our version format to PEP 440:
63
+ - Main branch: 0.1.0_main_3-20260404-hash -> 0.1.0
64
+ - Dev branch: 0.1.0_dev_3-20260404-hash -> 0.1.0.dev3
65
+ - Alpha: 0.1.0-alpha_main_3 -> 0.1.0a0
66
+ """
67
+ base = f"{MAJOR}.{MINOR}.{PATCH}"
68
+
69
+ # Map phase to PEP 440 pre-release segment
70
+ phase_map = {"alpha": "a0", "beta": "b0"}
71
+ if PHASE:
72
+ base += phase_map.get(PHASE, PHASE)
73
+
74
+ if "_" not in __version__:
75
+ return base
76
+
77
+ parts = __version__.split("_")
78
+ branch = parts[1] if len(parts) > 1 else "unknown"
79
+
80
+ if branch == "main":
81
+ return base
82
+ else:
83
+ build_info = "_".join(parts[2:]) if len(parts) > 2 else ""
84
+ build_num = build_info.split("-")[0] if "-" in build_info else "0"
85
+ return f"{base}.dev{build_num}"
86
+
87
+
88
+ # For convenience in imports
89
+ VERSION = get_version()
90
+ BASE_VERSION = get_base_version()
91
+ PIP_VERSION = get_pip_version()
92
+ DISPLAY_VERSION = get_display_version()
@@ -0,0 +1,106 @@
1
+ Metadata-Version: 2.4
2
+ Name: dazzle-linklib
3
+ Version: 0.1.0
4
+ Summary: Content-addressable link-record library -- the DazzleLib stack's L2 serialization layer (typed locators, content_id, export/import/rebase/scan).
5
+ Author-email: djdarcy <djdarcy@users.noreply.github.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/DazzleLib/dazzle-linklib
8
+ Project-URL: Repository, https://github.com/DazzleLib/dazzle-linklib
9
+ Project-URL: Issues, https://github.com/DazzleLib/dazzle-linklib/issues
10
+ Keywords: dazzlelib,links,symlink,junction,serialization,content-addressable,anti-link-rot,relinker,stack
11
+ Classifier: Development Status :: 2 - Pre-Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Software Development :: Libraries
22
+ Classifier: Topic :: System :: Filesystems
23
+ Requires-Python: >=3.9
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Provides-Extra: dev
27
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
28
+ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
29
+ Dynamic: license-file
30
+
31
+ # dazzle-linklib
32
+
33
+ [![PyPI](https://img.shields.io/pypi/v/dazzle-linklib?color=green)](https://pypi.org/project/dazzle-linklib/)
34
+ [![Release Date](https://img.shields.io/github/release-date/DazzleLib/dazzle-linklib?color=green)](https://github.com/DazzleLib/dazzle-linklib/releases)
35
+ [![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/)
36
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
37
+ [![Platform](https://img.shields.io/badge/platform-Windows%20%7C%20Linux%20%7C%20macOS%20%7C%20BSD-lightgrey.svg)](docs/platform-support.md)
38
+
39
+ **Content-addressable link-record library** -- the **L2** serialization layer of
40
+ the [DazzleLib stack](https://github.com/DazzleLib/.github/blob/main/docs/STACK-MAP.md).
41
+
42
+ A link record maps an **identity** to a **typed list of locators** plus
43
+ metadata, and knows how to serialize, find, and resolve itself. One model
44
+ serves three consumers:
45
+
46
+ - the **dazzlelink** filesystem CLI (the `.dazzlelink` file format),
47
+ - **preserve**'s content-hash manifest (L3), and
48
+ - **Relinker** -- a hash-addressed, decentralized anti-link-rot resolver
49
+ (`rln.kr/{hash}` -> a multi-protocol location set).
50
+
51
+ ## What this owns (and what it doesn't)
52
+
53
+ `dazzle-linklib` owns the link **record**: its schema, JSON I/O, the locator
54
+ list, `content_id`, relation edges, and the injectable target resolver. It
55
+ **delegates** the rest down the stack:
56
+
57
+ | Concern | Layer |
58
+ |---|---|
59
+ | Link record, locators, `content_id`, relations, resolve | **dazzle-linklib (L2, this lib)** |
60
+ | File/link mechanics (create/detect/read, copy, hash, metadata) | `dazzle-filekit` (L1) |
61
+ | UNC <-> drive identity, path origin classification | `unctools` (L0) |
62
+ | Shared Protocols / TypedDicts / exception root | `dazzle-lib` (B) |
63
+ | Graph **traversal** (walking the records' relation edges) | `dazzletreelib` (perpendicular) |
64
+
65
+ "Records that point at each other" live here; "walking and interpreting those
66
+ pointers" do not. (See the L2 design rationale, decision D6.)
67
+
68
+ ## Status
69
+
70
+ **0.1.0 is a name-reservation placeholder (pre-alpha).** It is published to
71
+ PyPI to claim the name, but exposes only its version -- there is no functional
72
+ content yet. The extraction of `DazzleLinkData` and the resolver from the
73
+ `dazzlelink` tool is stack phase **P2** and lands in a later release -- see the
74
+ [Roadmap](https://github.com/DazzleLib/dazzle-linklib/issues/2).
75
+
76
+ ## Installation
77
+
78
+ ```bash
79
+ pip install dazzle-linklib
80
+ ```
81
+
82
+ ### From source
83
+
84
+ ```bash
85
+ git clone https://github.com/DazzleLib/dazzle-linklib.git
86
+ cd dazzle-linklib
87
+ pip install -e ".[dev]"
88
+ ```
89
+
90
+ ## Development
91
+
92
+ ```bash
93
+ python -m venv .venv
94
+ source .venv/bin/activate # or .venv\Scripts\activate on Windows
95
+ pip install -e ".[dev]"
96
+
97
+ # Run tests
98
+ python -m pytest tests/ -v
99
+
100
+ # Install git hooks
101
+ bash scripts/install-hooks.sh
102
+ ```
103
+
104
+ ## License
105
+
106
+ MIT. See [LICENSE](LICENSE) for details.
@@ -0,0 +1,13 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ dazzle_linklib/__init__.py
5
+ dazzle_linklib/__main__.py
6
+ dazzle_linklib/_version.py
7
+ dazzle_linklib.egg-info/PKG-INFO
8
+ dazzle_linklib.egg-info/SOURCES.txt
9
+ dazzle_linklib.egg-info/dependency_links.txt
10
+ dazzle_linklib.egg-info/requires.txt
11
+ dazzle_linklib.egg-info/top_level.txt
12
+ tests/test_import_stability.py
13
+ tests/test_version.py
@@ -0,0 +1,4 @@
1
+
2
+ [dev]
3
+ pytest>=7.0.0
4
+ pytest-cov>=4.0.0
@@ -0,0 +1 @@
1
+ dazzle_linklib
@@ -0,0 +1,65 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "dazzle-linklib"
7
+ dynamic = ["version"]
8
+ description = "Content-addressable link-record library -- the DazzleLib stack's L2 serialization layer (typed locators, content_id, export/import/rebase/scan)."
9
+ readme = "README.md"
10
+ license = {text = "MIT"}
11
+ requires-python = ">=3.9"
12
+ authors = [
13
+ {name = "djdarcy", email = "djdarcy@users.noreply.github.com"},
14
+ ]
15
+ keywords = ["dazzlelib", "links", "symlink", "junction", "serialization", "content-addressable", "anti-link-rot", "relinker", "stack"]
16
+ classifiers = [
17
+ "Development Status :: 2 - Pre-Alpha",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Operating System :: OS Independent",
21
+ "Programming Language :: Python :: 3",
22
+ "Programming Language :: Python :: 3.9",
23
+ "Programming Language :: Python :: 3.10",
24
+ "Programming Language :: Python :: 3.11",
25
+ "Programming Language :: Python :: 3.12",
26
+ "Programming Language :: Python :: 3.13",
27
+ "Topic :: Software Development :: Libraries",
28
+ "Topic :: System :: Filesystems",
29
+ ]
30
+
31
+ dependencies = []
32
+
33
+ [project.optional-dependencies]
34
+ dev = [
35
+ "pytest>=7.0.0",
36
+ "pytest-cov>=4.0.0",
37
+ ]
38
+
39
+ [project.urls]
40
+ Homepage = "https://github.com/DazzleLib/dazzle-linklib"
41
+ Repository = "https://github.com/DazzleLib/dazzle-linklib"
42
+ Issues = "https://github.com/DazzleLib/dazzle-linklib/issues"
43
+
44
+ # Library-only: no console_scripts. The `dazzlelink` CLI lives in the
45
+ # DazzleTools/dazzlelink tool, which consumes this library (STACK-MAP D1).
46
+
47
+ [tool.setuptools.dynamic]
48
+ version = {attr = "dazzle_linklib._version.PIP_VERSION"}
49
+
50
+ [tool.setuptools.packages.find]
51
+ where = ["."]
52
+ include = ["dazzle_linklib", "dazzle_linklib.*"]
53
+
54
+ [tool.pytest.ini_options]
55
+ testpaths = ["tests"]
56
+ python_files = "test_*.py"
57
+ python_functions = "test_*"
58
+ python_classes = "Test*"
59
+
60
+ [tool.repokit-common]
61
+ version-source = "dazzle_linklib/_version.py"
62
+ changelog = "CHANGELOG.md"
63
+ repo-url = "https://github.com/DazzleLib/dazzle-linklib"
64
+ tag-prefix = "v"
65
+ private-patterns = ["private/", "local/", ".env"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,41 @@
1
+ """Import-stability canary (see docs/api-stability.md).
2
+
3
+ Every symbol listed here is part of the locked public API. If this test
4
+ fails, a consumer somewhere breaks: do NOT silently fix the test -- follow
5
+ the api-stability.md process (deprecate with a noisy shim, register it,
6
+ slate removal).
7
+
8
+ The locked surface is intentionally tiny at the 0.1.0 scaffold stage (version
9
+ exports only). The record model (DazzleLinkData, export/import/scan/rebase,
10
+ resolve_target) joins this canary at its P2 release.
11
+ """
12
+
13
+ import importlib
14
+
15
+ LOCKED_SURFACE = {
16
+ "dazzle_linklib": [
17
+ "__version__",
18
+ "__app_name__",
19
+ "PIP_VERSION",
20
+ ],
21
+ }
22
+
23
+
24
+ def test_locked_surface_importable():
25
+ missing = []
26
+ for module_name, symbols in LOCKED_SURFACE.items():
27
+ module = importlib.import_module(module_name)
28
+ for symbol in symbols:
29
+ if not hasattr(module, symbol):
30
+ missing.append(f"{module_name}.{symbol}")
31
+ assert not missing, (
32
+ f"Locked API symbols missing: {missing} -- see docs/api-stability.md "
33
+ f"before changing the public surface."
34
+ )
35
+
36
+
37
+ def test_package_is_importable():
38
+ """The package imports cleanly with no side effects at import time."""
39
+ mod = importlib.import_module("dazzle_linklib")
40
+ assert isinstance(mod.__version__, str)
41
+ assert mod.__app_name__ == "dazzle-linklib"
@@ -0,0 +1,50 @@
1
+ """Tests for version module."""
2
+
3
+ from dazzle_linklib._version import (
4
+ MAJOR, MINOR, PATCH, PHASE, PROJECT_PHASE,
5
+ get_version, get_base_version, get_display_version, get_pip_version,
6
+ __app_name__,
7
+ )
8
+
9
+
10
+ def test_app_name():
11
+ assert __app_name__ == "dazzle-linklib"
12
+
13
+
14
+ def test_version_components():
15
+ assert isinstance(MAJOR, int)
16
+ assert isinstance(MINOR, int)
17
+ assert isinstance(PATCH, int)
18
+
19
+
20
+ def test_phase_valid():
21
+ """PHASE is empty string (stable release) or a string like 'alpha', 'beta', 'rc1'."""
22
+ assert isinstance(PHASE, str)
23
+
24
+
25
+ def test_get_version_returns_string():
26
+ v = get_version()
27
+ assert isinstance(v, str)
28
+ assert len(v) > 0
29
+
30
+
31
+ def test_base_version_format():
32
+ base = get_base_version()
33
+ assert base.startswith(f"{MAJOR}.{MINOR}.{PATCH}")
34
+
35
+
36
+ def test_display_version_includes_project_phase():
37
+ display = get_display_version()
38
+ if PROJECT_PHASE and PROJECT_PHASE != "stable":
39
+ assert PROJECT_PHASE.upper() in display
40
+ else:
41
+ assert display == get_base_version()
42
+
43
+
44
+ def test_pip_version_pep440():
45
+ pip_v = get_pip_version()
46
+ assert "-" not in pip_v
47
+ if PHASE:
48
+ assert any(c.isalpha() for c in pip_v.split(".")[-1])
49
+ else:
50
+ assert all(c.isdigit() or c == "." for c in pip_v)