an.build.reads#
What a shot read: a read-recording view of the mall, and the digests of what it saw.
ADR 0004 decision 3: a shot’s inputs are recorded, not assumed. The mall a
keyer compiles against is wrapped in a RecordingMall, which notes
every asset entry the compile asks for — props["logo"], a get, an
in test — and every store it LISTS (iterating a store, or taking its
length, depends on all of it). Those reads become the shot’s dependency edges:
read_digests() digests exactly them, and an edit to an asset no shot
read moves no key. Before an#316 every shot depended on every asset in its
project (an.build.keys.project_assets_digest(), the first slice’s
fallback), so a one-prop edit re-rendered the whole film.
Only the asset stores (PROJECT_ASSET_STORES) are
recorded. Everything else a render reads already has a part of its own: the
scene reaches the key through each shot’s compiled document, the dialogue
audio through audio, art staged by path through textures.
An entry’s digest covers what the mapping returns AND, for a filesystem store,
the files of the entry beside it (a prop’s prop.json, its parts/ SVGs,
a relative font) — so a sidecar edited behind the mapping still moves it.
>>> mall = RecordingMall({"props": {"logo": {"text": "A"}, "intro": {}}})
>>> mall["props"]["logo"]["text"]
'A'
>>> sorted(mall.reads)
[('props', 'logo')]
>>> sorted(read_digests({"props": {"logo": {"text": "A"}}}, mall.reads))
['props/logo']
Module Attributes
The key a read of a WHOLE store is recorded under (iteration, |
Functions
|
One entry's digest: what the mapping returns, plus its files on disk. |
|
The files of entry |
|
|
Classes
|
A view of |
|
One store of a |
- class an.build.reads.RecordingMall(mall, *, recorded=('characters', 'environments', 'props', 'styles', 'voices', 'sounds'))[source]#
Bases:
MappingA view of
mallthat records which asset entries are read through it.Stores named in
recordedcome back wrapped in aRecordingStore(one per store, so identity is stable across lookups); every other store comes back as it is.readsis the set of(store, key)read so far,keybeingWHOLE_STOREfor a store that was listed.
- class an.build.reads.RecordingStore(store, name, reads)[source]#
Bases:
MutableMappingOne store of a
RecordingMall: reads are noted, writes pass through.Attribute access (
_root, a store’s own helpers) reaches the wrapped store unchanged — the compiler reads art by path through_root, and those bytes are keyed by thetexturespart, not here.bool()is NOT a read:mall.get(name) or {}asks whether the store has anything, and recording it would make every shot depend on the whole store. So a read of an EMPTY store (which that idiom replaces with{}) goes unrecorded — safe, because what the shot draws from an entry that appears later reaches its compiled document.
- an.build.reads.WHOLE_STORE: str = '*'#
The key a read of a WHOLE store is recorded under (iteration,
len): the shot depends on every entry, present and future.
- an.build.reads.entry_digest(store, key)[source]#
One entry’s digest: what the mapping returns, plus its files on disk.
- Return type:
>>> entry_digest({"a": 1}, "a") == entry_digest({"a": 1}, "a") True >>> entry_digest({"a": 1}, "a") == entry_digest({"a": 2}, "a") False >>> entry_digest({}, "a") == entry_digest({}, "a") # absent is a value too True
- an.build.reads.entry_files(store, key)[source]#
The files of entry
keyin a filesystem store (one exposing_root).Both store layouts are covered: a sidecar store’s folder
<root>/<key>/(everything under it) and a file store’s<root>/<key>.<ext>(one suffix:logo.jsonis entrylogo’s;logo.v2/andlogo.v2.jsonare entrylogo.v2’s). Operating-system clutter is never an asset (an.stores._common.is_os_junk()).
- an.build.reads.read_digests(mall, reads)[source]#
{"store/key": digest}for every recorded read — the shot’s dependency edges.A read of a store the mall does not have is recorded as
ABSENT, so the day the store appears the key moves.>>> read_digests({}, [("props", "logo")]) {'props/logo': 'absent'}