acquaint.store#

Where records live and how code reaches them: the data root, Store and Entity.

Layout under the data root (one folder per entity, one entry file each):

POLICY.md                    what may be recorded
_tombstones.yaml             salted hashes of forgotten entities' identifiers
people/<slug>/PROFILE.md     the entry file (required)
people/<slug>/identities.yaml, rules.yaml, links.yaml, trust.yaml, style.md, views.md,
              sources.md, log/YYYY-MM.md, research/…   (each optional)
projects/<slug>/PROFILE.md   (and orgs/, groups/, or any other kind)

Store is a MutableMapping[str, Entity] keyed "<kind dir>/<slug>", where both parts are lowercase letters, digits and hyphens; nothing else is a key, so no reference can reach outside the data root. Underneath it is any MutableMapping[str, str] of relative paths to text: a dol files store by default, a dict in tests. That mapping is the storage seam.

When the store is on disk, an entity is a real directory whose name matches its key exactly (case included, even on case-insensitive filesystems) and is not a link. Listing, moving and removing work on those directories, so hidden files move and go with their entity. A file that is not valid UTF-8 reads with replacement characters and is reported, instead of failing every lookup. Entry files the store cannot address (a capitalised folder, a linked folder, profile.md) are listed by Store.misnamed().

>>> store = Store(files={})
>>> store["people/ada-lovelace"] = {"PROFILE.md": "---\nname: Ada Lovelace\n---\n"}
>>> list(store), store["people/ada-lovelace"].name
(['people/ada-lovelace'], 'Ada Lovelace')

Module Attributes

KIND_DIRS

see kind_dir().

UNREADABLE

What undecodable bytes read as.

Functions

config_path()

~/.config/acquaint/config.toml (honouring XDG_CONFIG_HOME; %APPDATA% on Windows).

data_dir([data_dir])

The data root: the argument, else $ACQUAINT_DATA_DIR, else data_dir in config.toml, else ~/.local/share/acquaint.

kind_dir(kind)

The folder for a kind: person/people -> people; an unknown kind is used as given, pluralised.

text_files(root)

A dol files store under root, for text.

validate_key(key)

Return key if it is <kind dir>/<slug> of lowercase letters, digits and hyphens; refuse anything else.

Classes

Entity(store, key)

One person, project, org or group: a mapping of its files (relative names to text), plus parsed views of them.

Store([data_dir, files])

MutableMapping[str, Entity] over one folder per entity, keyed "<kind dir>/<slug>".

Exceptions

AcquaintError

An expected failure with a message meant for the person or agent that asked.

exception acquaint.store.AcquaintError[source]#

Bases: Exception

An expected failure with a message meant for the person or agent that asked.

class acquaint.store.Entity(store, key)[source]#

Bases: MutableMapping

One person, project, org or group: a mapping of its files (relative names to text), plus parsed views of them.

Parsed views are recomputed on access (these are small text files), so an edit made through the mapping is never hidden behind a stale cache. Parse problems are collected in errors; they never raise.

property aka: list[str]#

Other names this entity goes by, as strings (a scalar aka is one alias, not its letters).

property body: str#

The entry file’s Markdown body.

property errors: list[str]#

Everything about the entry file and the YAML files that did not parse.

property identities: list[dict]#

{platform, value, source, status, …}.

Type:

Handles and addresses from identities.yaml

property kind: str#

person, project, org, group, or the singular of an open kind’s folder.

{to, relation, role, since, until, source}.

Type:

Affiliations from links.yaml

property meta: dict#

The entry file’s frontmatter (empty when it did not parse).

property name: str#

The display name, falling back to the id.

property ref: str#

person:ada-lovelace.

Type:

The link form other records use

property rules: list[dict]#

{when, do, set_by, source}.

Type:

Channel and communication rules from rules.yaml

property sections: dict[str, str]#

The entry file’s ## Sections, keyed by normalized title.

summary()[source]#

The identity block: frontmatter plus identities, JSON-ready.

Return type:

dict[str, Any]

property surface_forms: list[str]#

id, name, aka, name parts, handles.

Type:

Every string a document might use for this entity

text(name, default='')[source]#

A file’s text, or default when the file does not exist.

Return type:

str

property trust: list[dict]#

{tier, valid_from, valid_to, review_by, recorded, source, note} (see acquaint.trust).

Type:

Disclosure tiers from trust.yaml

acquaint.store.KIND_DIRS = {'group': 'groups', 'org': 'orgs', 'person': 'people', 'project': 'projects'}#

see kind_dir().

Type:

The kinds that ship, singular -> folder. The vocabulary is open

class acquaint.store.Store(data_dir=None, *, files=None)[source]#

Bases: MutableMapping

MutableMapping[str, Entity] over one folder per entity, keyed "<kind dir>/<slug>".

>>> store = Store(files={})
>>> store["projects/example"] = {"PROFILE.md": "---\nname: Example\n---\n"}
>>> store.find("project:example"), store.find("example")
('projects/example', 'projects/example')
all_files(key)[source]#

Every file under the entity’s folder, hidden ones included.

Return type:

list[str]

append_text(key, name, text)[source]#

Append to one of an entity’s files (created if missing); a true append on disk, so concurrent writers do not erase each other.

Return type:

None

exists(key)[source]#

Whether anything is stored under the entity’s folder, with or without an entry file.

Return type:

bool

find(ref)[source]#

The store key for people/ada-lovelace, person:ada-lovelace or a bare ada-lovelace.

A bare id that names entities of two kinds is an error: say which, e.g. project:atlas. Anything that is not a valid key raises KeyError, so no reference reaches outside the data root.

Return type:

str

find_id(slug)[source]#

Every key whose id is slug, in any kind (ids are lowercase, so the lookup is too).

Return type:

list[str]

location_warning()[source]#

A warning when the data root is, or sits inside, a git repository that is not an acquaint store.

Return type:

str | None

misnamed()[source]#

Entry files on disk the store cannot address: a folder or file name not in lowercase kind/id/PROFILE.md form, or a linked folder.

Return type:

list[str]

move(src, dst)[source]#

Move an entity’s whole folder to a new key (hidden files included).

Return type:

None

path_of(key)[source]#

Where an entity lives, for a person to open: a real path when on disk, else the key.

Return type:

str

acquaint.store.UNREADABLE = '�'#

What undecodable bytes read as. A file containing it is reported as not valid UTF-8.

acquaint.store.config_path()[source]#

~/.config/acquaint/config.toml (honouring XDG_CONFIG_HOME; %APPDATA% on Windows).

Return type:

Path

acquaint.store.data_dir(data_dir=None)[source]#

The data root: the argument, else $ACQUAINT_DATA_DIR, else data_dir in config.toml, else ~/.local/share/acquaint.

An explicit argument may be relative (it is resolved now). The environment variable and the config file must hold absolute paths: a relative one would put profiles wherever the current directory happens to be.

Return type:

Path

>>> data_dir("profiles").is_absolute()
True
acquaint.store.kind_dir(kind)[source]#

The folder for a kind: person/people -> people; an unknown kind is used as given, pluralised.

Return type:

str

>>> [kind_dir(k) for k in ("person", "people", "org", "community", "teams")]
['people', 'people', 'orgs', 'communities', 'teams']
acquaint.store.text_files(root)[source]#

A dol files store under root, for text.

UTF-8 values (undecodable bytes read as U+FFFD instead of raising; a byte-order mark dropped), \n line endings, /-separated keys on every platform, folders made on write and never on read, and permanent deletes (never to a trash folder, where “forgotten” data would linger).

Return type:

MutableMapping[str, str]

acquaint.store.validate_key(key)[source]#

Return key if it is <kind dir>/<slug> of lowercase letters, digits and hyphens; refuse anything else.

Return type:

str

>>> validate_key("people/ada-lovelace")
'people/ada-lovelace'
>>> try:
...     validate_key("../outside/people/someone")
... except AcquaintError as error:
...     print(error)
not a store key: '../outside/people/someone' (expected <kind>/<id>, e.g. people/ada-lovelace)