cutan.styles

The named cut-out style specs, shipped as package data (cutan#4).

A style spec is one YAML document per named look (south_park, oversimplified, kurzgesagt, gilliam, reiniger, norstein): live settings that map onto shipped an features, targets the style lint measures a render against, prosody_targets for voice acting, and guidance for what the style needs beyond them. The cutan-style skill is the procedure that applies one; this module is where the specs live, so code and agents load a spec by its name rather than through a path into a skill folder.

>>> 'south_park' in style_specs()
True
>>> spec = style_spec('south_park')
>>> spec['style'], spec['cost_class']
('south_park', 'low')
>>> style_spec_path('south_park').name
'south_park.yaml'

Each call returns a fresh dict, so a caller may change it freely:

>>> style_spec('south_park') is style_spec('south_park')
False

An unknown name is refused with the names there are (a KeyError):

>>> try:
...     style_spec('pixar')
... except KeyError as e:
...     print(e)
no style spec named 'pixar'; the specs are: gilliam, kurzgesagt, norstein, oversimplified, reiniger, south_park

A spec changes between releases (targets re-measured, roles re-cast), and whatever a production copied out of one (a StylePack, a voice document with resolved targets, a kit) is a snapshot of the version it was copied from. style_spec_digest() names that version: record it beside the copy, and compare it with the installed spec’s to know whether the copy is current.

>>> len(style_spec_digest('south_park'))
64

resolve_style_spec() is the one place a reference to a spec becomes a spec: a mapping (passed through), a path to a YAML file, or a style’s name.

python -m cutan.styles lists the specs, python -m cutan.styles NAME prints one, and python -m cutan.styles NAME --path prints its file’s path (for a tool that wants a path, such as an.verify.prosody --targets).

Module Attributes

STYLE_SPEC_SUFFIX

The file suffix of a style spec in this package.

STYLE_SPEC_SCHEMA_VERSION

bumped when a key's meaning changes, so a reader of a spec copied elsewhere knows which shape it holds.

Functions

resolve_style_spec(ref)

A style spec as a dict, from whatever refers to one.

style_spec(name)

The style spec name, parsed: a new dict on every call.

style_spec_digest(name)

The sha256 of the style spec name's file: the version a copy was made from.

style_spec_path(name)

The file of the style spec name (for a tool that reads a path).

style_spec_text(name)

The YAML text of the style spec name, comments included.

style_specs()

The names of the style specs that ship with cutan, sorted.

check_policy(policy, *[, where])

policy parsed into an an.semantic.Policy, or PolicyError naming where.

layered_policy(*[, shot, style_pack])

The policy in force: shot over style_pack (each checked).

policy_of(obj)

The policy block an object carries: a policy field (declared or extra) or key; else None.

policy_problems(policy)

What is wrong with a policy block, one sentence each (empty when it is sound).

style_pack(spec)

The StylePack a project saves for a style: its live.style_pack (a bare pack named after the style when the spec has none), its policy, and the spec it was copied from (name and digest) in metadata.

style_voice(spec, role)

The partial voice document spec casts role as (``an.audio.takes.

check_style_copies(ctx)

an validate: the style pack the scene names, and every voice its lines speak with, warn when they were copied from an older version of the shipped spec they record (cutan#19).

Exceptions

UnknownStyleError

No style spec of that name ships with cutan.

PolicyError

A policy block names an aspect or a method that does not exist, or is malformed.

exception cutan.styles.PolicyError[source]

Bases: ValueError

A policy block names an aspect or a method that does not exist, or is malformed.

cutan.styles.STYLE_SPEC_SCHEMA_VERSION: str = '0.1.0'

bumped when a key’s meaning changes, so a reader of a spec copied elsewhere knows which shape it holds.

Type:

The schema_version the shipped specs carry

cutan.styles.STYLE_SPEC_SUFFIX: str = '.yaml'

The file suffix of a style spec in this package.

exception cutan.styles.UnknownStyleError[source]

Bases: KeyError

No style spec of that name ships with cutan.

A KeyError (so a mapping or a ChainMap of spec sources falls through it), and so also a LookupError.

cutan.styles.check_policy(policy, *, where='policy')[source]

policy parsed into an an.semantic.Policy, or PolicyError naming where.

Return type:

Any

cutan.styles.check_style_copies(ctx)[source]

an validate: the style pack the scene names, and every voice its lines speak with, warn when they were copied from an older version of the shipped spec they record (cutan#19). Once per validation.

Return type:

None

cutan.styles.layered_policy(*, shot=None, style_pack=None)[source]

The policy in force: shot over style_pack (each checked).

Each argument is anything policy_of() reads (or None). The author’s explicit request is not here: the matcher puts it first (resolve(..., requested=)).

Return type:

Any

cutan.styles.policy_of(obj)[source]

The policy block an object carries: a policy field (declared or extra) or key; else None.

>>> policy_of({"policy": {"locomotion": ["loco.glide"]}})
{'locomotion': ['loco.glide']}
>>> policy_of(None) is None
True
Return type:

Any

cutan.styles.policy_problems(policy)[source]

What is wrong with a policy block, one sentence each (empty when it is sound).

Every aspect must be registered, every choice a method OF that aspect (by id: loco.bounce, not bounce), and every choice well formed (an id or {method, args, version}).

>>> policy_problems({"locomotion": ["loco.bounce", "loco.glide"]})
[]
>>> for p in policy_problems({"locomotion": ["bounce"], "dance": ["x"]}): print(p)
policy locomotion: 'bounce' is not a locomotion method id; did you mean 'loco.bounce'?
policy aspect 'dance' is not registered (aspects: expression, locomotion, speech)
Return type:

list[str]

cutan.styles.resolve_style_spec(ref)[source]

A style spec as a dict, from whatever refers to one.

  • a mapping is passed through (a deep copy);

  • a string spelled as a name (no path separator, no suffix) is looked up by name in the spec sources — today the shipped specs only — and never read from a file in the working directory (spell a local file ./south_park);

  • anything else is a path to a YAML file.

>>> resolve_style_spec('reiniger')['style']
'reiniger'
>>> resolve_style_spec({'targets': {}})
{'targets': {}}

A missing file whose stem is a shipped style says how to load that one:

>>> resolve_style_spec('oversimplified.yaml')
Traceback (most recent call last):
  ...
FileNotFoundError: no style spec file 'oversimplified.yaml' ...
Return type:

dict[str, Any]

cutan.styles.style_pack(spec)[source]

The StylePack a project saves for a style: its live.style_pack (a bare pack named after the style when the spec has none), its policy, and the spec it was copied from (name and digest) in metadata.

spec is anything cutan.styles.resolve_style_spec() takes (a style’s name, a path, a mapping). Save it as the skill’s step 3 says: mall["styles"][pack.name] = pack.model_dump(mode="json").

>>> pack = style_pack("south_park")
>>> pack.name, pack.policy, pack.metadata["style_spec"]["name"]
('south_park', {'locomotion': ['loco.bounce']}, 'south_park')
Return type:

Any

cutan.styles.style_spec(name)[source]

The style spec name, parsed: a new dict on every call.

Return type:

dict[str, Any]

cutan.styles.style_spec_digest(name)[source]

The sha256 of the style spec name’s file: the version a copy was made from.

It hashes the file’s bytes with line endings normalised to \n (a Windows checkout has the same spec as the wheel), so a comment-only edit is a new version too.

Return type:

str

cutan.styles.style_spec_path(name)[source]

The file of the style spec name (for a tool that reads a path).

Raises FileNotFoundError when cutan is imported from an archive (a zipped wheel), where the spec is not a file: use style_spec_text().

Return type:

Path

cutan.styles.style_spec_text(name)[source]

The YAML text of the style spec name, comments included.

Return type:

str

cutan.styles.style_specs()[source]

The names of the style specs that ship with cutan, sorted.

Return type:

list[str]

cutan.styles.style_voice(spec, role)[source]

The partial voice document spec casts role as (an.audio.takes. style_voice_role: target names resolved to values), with the spec it came from recorded, so a later re-measure of the style is noticed. Merge it beside a voice_id: {**style_voice("oversimplified", "eager"), "voice_id": ...}.

>>> doc = style_voice("oversimplified", "narrator")
>>> doc["metadata"]["style_spec"]["name"], "targets" in doc["takes"]["cues"]["deadpan"]
('oversimplified', True)
Return type:

dict[str, Any]

Modules

copies

Copies of a style spec, and whether they are stale (cutan#19).

policy

A style's policy: per-aspect method orders the compiler applies (ADR 0002 decision 4, cutan#9).