an.library.registry#
The machine’s memory of its libraries: every root ever written, and every statement ever made (an#249).
The rights floor (an.library.floor) must read every statement any
library on this machine makes about a blob, not only those it can discover
from today’s environment. Discovery finds the package roots under the CURRENT
data folder (which follows XDG_DATA_HOME) and the CURRENTLY set
<PKG>_HOME roots. A library written at an explicit root= / --root,
or under an environment that has since changed, is invisible to discovery, and
its private bytes would then publish as free anywhere else.
So this module keeps two records, side by side, at a location that depends on
nothing in the environment: the account’s home folder as the operating
system records it (the password database on POSIX, never $HOME), under the
core package’s default data folder — ~/.local/share/an/registry/ on Linux
and macOS, whatever XDG_DATA_HOME, AN_HOME or <PKG>_HOME say. (On
Windows the account’s home is Path.home(), which follows USERPROFILE:
there the location is as stable as that variable.)
The registry of roots (
library_roots.jsonl): the first write to any on-disk library records its root, and the floor reads each registered root’s own index. JSON Lines, append-only: an append of one short line is atomic, so racing publishers cannot lose each other’s registration, and a line torn by a crash is skipped (the next append starts on a fresh line). A root that no longer exists is skipped — which is why the second record exists.The memory of statements (
statements/<aa>/<sha256>/…json): every statement a version makes about a blob, written at publish beside the library’s own index. The floor reads it in addition to the libraries, so a library that is moved, renamed, unmounted or deleted can never relax a statement it once made: a missing root relaxes nothing. One small file per (blob, library root, asset), replaced only by a later version of the same asset at the same root — so a relicence there still speaks, as in the library’s own index. A file that cannot be parsed counts asunknown.The record of generated bytes (
generated/<aa>/<sha256>/…json): the digests the character factory drew on this machine, written only at the end ofnew_character, for the folder it created empty in that call (record_generated(), deliberately not exported) — never by the public stamping functions, which stamp whatever bytes they are pointed at. It verifies a factory stamp: such bytes are the factory’scc0work whatever an older, UNLABELLED asset holding the same bytes fails to say (an#269). It relaxes onlyunknown, never a statement anyone made.
Deleting the registry folder wholesale deletes that memory with it — nothing
left on disk tells a deleted registry from a first use — so whenever the
registry is created from nothing, the first write warns
(RegistryWarning). Prune it; never delete it.
Both are read fail-closed: a registry or memory that exists but cannot be
read raises RegistryError — a floor that silently read less would let
private bytes out. Libraries with injected stores (no root on disk: an S3 or
in-memory mall) are in neither record; their statements reach the floor only
while they are on the search path.
Neither record is a search path: a registered library’s assets are never
found, resolved or checked out through them — reads still go through the
explicit search path (an.library.federation.search_path()).
Tests and doctests are redirected by the repository’s root conftest.py,
which points _account_home() into a temporary folder. A test that runs
an in a SUBPROCESS cannot be redirected that way and must not publish.
>>> import tempfile, pathlib
>>> with tempfile.TemporaryDirectory() as d:
... reg = pathlib.Path(d) / "roots.jsonl"
... first = register_root("cutan", pathlib.Path(d) / "study", registry=reg)
... again = register_root("cutan", pathlib.Path(d) / "study", registry=reg)
... (first, again), [(p, r.name) for p, r in registered_roots(registry=reg)]
((True, False), [('cutan', 'study')])
Module Attributes
The sub-folder of the core package's default data root holding the registry (a root holds one sub-folder per kind of data, never files at the top). |
|
JSON Lines, one |
|
The folder of remembered statements, beside the registry file. |
|
The folder of the machine's record of bytes a GENERATOR drew here (an#269). |
Functions
The folder holding the registry and the statement memory (independent of the environment). |
|
Where this machine's registry of library roots lives. |
|
|
Record |
|
|
|
Remember |
|
|
|
|
|
The generators this machine recorded as having drawn the bytes |
Exceptions
The machine's registry or statement memory cannot be read or written; nothing proceeds. |
- an.library.registry.GENERATED_DIRNAME: str = 'generated'#
The folder of the machine’s record of bytes a GENERATOR drew here (an#269).
- an.library.registry.REGISTRY_DIRNAME: str = 'registry'#
The sub-folder of the core package’s default data root holding the registry (a root holds one sub-folder per kind of data, never files at the top).
- an.library.registry.REGISTRY_FILENAME: str = 'library_roots.jsonl'#
JSON Lines, one
{"package", "root", "registered"}per line.- Type:
The registry file
- exception an.library.registry.RegistryError[source]#
Bases:
OSErrorThe machine’s registry or statement memory cannot be read or written; nothing proceeds.
- an.library.registry.STATEMENTS_DIRNAME: str = 'statements'#
The folder of remembered statements, beside the registry file.
- an.library.registry.generated_by(digest)[source]#
The generators this machine recorded as having drawn the bytes
digest.Read fail-safe for rights: anything unreadable counts as not recorded, so the stamp it would verify is not verified (the stricter reading).
- an.library.registry.machine_registry_dir()[source]#
The folder holding the registry and the statement memory (independent of the environment).
- Return type:
>>> machine_registry_dir().name 'registry'
- an.library.registry.machine_registry_path()[source]#
Where this machine’s registry of library roots lives.
- Return type:
>>> machine_registry_path().name 'library_roots.jsonl'
- an.library.registry.register_root(package, root, *, registry=None)[source]#
Record
root(package’s library root) in the registry;Trueif it was new.Idempotent. Raises
RegistryErrorwhen the registry cannot be read or written: a library the floor cannot find later must not be written to.- Return type:
- an.library.registry.registered_roots(*, registry=None)[source]#
(package, root)for every root ever registered, oldest first, each once.A line that does not parse (a torn append) is skipped; existence is the caller’s to check. A registry that exists but cannot be read raises
RegistryError.
- an.library.registry.remember_statements(root, statements)[source]#
Remember
(digest, asset_key, statement)made by the library atroot.One file per (digest, root, asset), replaced only by a statement of a later (or the same) version of that asset — the same rule as a library’s own index. Raises
RegistryErrorwhen it cannot be written.- Return type:
- an.library.registry.remembered_statements(digest)[source]#
(asset_key, statement)for every statement this machine ever recorded aboutdigest.A remembered file that cannot be parsed counts as an
unknownstatement (it said something; what is no longer known). A memory that exists but cannot be listed raisesRegistryError.