Summary
Define and document the "optional peer" integration pattern that
dazzle_filekit.data (sub-issue #N+1) uses to compose with unctools
and preservelib without making them hard dependencies.
This is the architectural contract that keeps the primitives layer
(v0.2.x filekit) decoupled from the workflow layer (v0.3.x) even though
they share a package namespace.
The pattern
# Inside dazzle_filekit/data/__init__.py or a helper module
# --- Detection -----------------------------------------------------
try:
import unctools
HAS_UNCTOOLS = True
except ImportError:
HAS_UNCTOOLS = False
try:
from preservelib import manifest as _pl_manifest
HAS_PRESERVELIB = True
except ImportError:
HAS_PRESERVELIB = False
# --- Guards --------------------------------------------------------
def _require_preservelib(feature: str):
if not HAS_PRESERVELIB:
raise RuntimeError(
f"{feature} requires preservelib. Install it with:\n"
f" pip install 'dazzle-filekit[preservelib]'\n"
f"or install preservelib directly alongside filekit."
)
# --- Use at the call site ------------------------------------------
def copy(src, dst, *, manifest=False, ...):
if manifest:
_require_preservelib("manifest=True")
# ... use _pl_manifest ...
else:
# fall back to filekit's atomic_write_json with a minimal schema
...
Invariants
import dazzle_filekit must never fail because unctools or
preservelib are missing. The top-level package imports only its
own submodules.
import dazzle_filekit.data must never fail because peers are
missing. The data submodule sets HAS_UNCTOOLS / HAS_PRESERVELIB
at import time but doesn't fail.
- Feature-gated calls raise a clear
RuntimeError with an install
hint, never a confusing ImportError or AttributeError from
deep in the composition chain.
- Default behavior degrades to filekit-only primitives when peers
are missing. For example, manifest=False is the default so the
common case works without preservelib.
- No monkey-patching. If a user installs preservelib after
importing filekit, they need to reimport filekit to pick up the
new features. (Document this.)
pyproject.toml extras
[project.optional-dependencies]
unctools = ["unctools>=0.1.0"]
preservelib = ["preservelib>=0.5.0"]
full = ["unctools>=0.1.0", "preservelib>=0.5.0"]
dev = [
"pytest>=7.0.0",
"pytest-cov>=3.0.0",
"flake8>=3.8.0",
"black>=20.8b1",
]
Install variants:
pip install dazzle-filekit -- primitives only
pip install 'dazzle-filekit[unctools]' -- primitives + UNC translation
pip install 'dazzle-filekit[preservelib]' -- primitives + manifest support
pip install 'dazzle-filekit[full]' -- the whole seamless experience
Acceptance criteria
Dependencies
- Blocks: #N+1 (data submodule), #N+2 (DataRef), and all other
Layer 1 work that composes the peers
Non-goals
- Actually refactoring unctools or preservelib to make them more
filekit-friendly -- those are separate tracks in their own repos
Summary
Define and document the "optional peer" integration pattern that
dazzle_filekit.data(sub-issue #N+1) uses to compose withunctoolsand
preservelibwithout making them hard dependencies.This is the architectural contract that keeps the primitives layer
(v0.2.x filekit) decoupled from the workflow layer (v0.3.x) even though
they share a package namespace.
The pattern
Invariants
import dazzle_filekitmust never fail because unctools orpreservelib are missing. The top-level package imports only its
own submodules.
import dazzle_filekit.datamust never fail because peers aremissing. The
datasubmodule setsHAS_UNCTOOLS/HAS_PRESERVELIBat import time but doesn't fail.
RuntimeErrorwith an installhint, never a confusing
ImportErrororAttributeErrorfromdeep in the composition chain.
are missing. For example,
manifest=Falseis the default so thecommon case works without preservelib.
importing filekit, they need to reimport filekit to pick up the
new features. (Document this.)
pyproject.toml extras
Install variants:
pip install dazzle-filekit-- primitives onlypip install 'dazzle-filekit[unctools]'-- primitives + UNC translationpip install 'dazzle-filekit[preservelib]'-- primitives + manifest supportpip install 'dazzle-filekit[full]'-- the whole seamless experienceAcceptance criteria
HAS_UNCTOOLS/HAS_PRESERVELIBmodule-level flags exist indazzle_filekit.data_require_unctools()/_require_preservelib()helpers raiseclear errors with install hints
pyproject.tomlhasunctools,preservelib, andfullextrasdocs/optional-peers.mddocuments the pattern for downstreamtool authors
HAS_UNCTOOLS = Falsein a test fixture)Dependencies
Layer 1 work that composes the peers
Non-goals
filekit-friendly -- those are separate tracks in their own repos