Source code for cutan

"""cutan: cut-out animation, as a genre package on the ``an`` core.

``an`` is the core of structured animation (scene documents, the timing kernel,
renderers, audio, storage, verification). A *genre* adds what one kind of
animation needs and registers it with the core; ``cutan`` is the first genre to
leave ``an``: rigged characters, faces and expressions, lip-sync visemes, swap
sets and views, cut-out styles and impacts (ADR 0001 in ``an``'s
``misc/docs/adr/``, tracked by an#225 under the epic an#231).

Rigged characters (``cutan.characters``), faces (``cutan.expression``), impacts
(``cutan.impacts``), the cut-out compile passes (``cutan.compile``), lip-sync
providers (``cutan.audio``), the style lint (``cutan.verify``) and the genre object
(``cutan.genre``) lived inside ``an`` until the P8 move (an#225); ``an`` keeps
warning aliases at the old import paths. Install it with ``pip install "an[cutout]"``;
``an`` finds it through the ``an.genres`` entry point.

The identifiers below are the genre's **persisted** names (ADR 0001 decision 9):
they are written into documents, stores and entry-point metadata, and none of
them changes when code moves between distributions.

>>> GENRE_NAME
'cutout_animation'
>>> ENTRY_POINT_GROUP, ENTRY_POINT_NAME
('an.genres', 'cutout_animation')
>>> RENDERER_NAME, LIBRARY_NAME
('cutout', 'cutan')
"""

#: The genre's slug: the ``an.genres`` entry-point name and the ``nw`` genre id.
GENRE_NAME: str = "cutout_animation"

#: The entry-point group ``an.genres.load()`` reads.
ENTRY_POINT_GROUP: str = "an.genres"

#: The entry-point name this distribution declares (``pyproject.toml``): the name
#: ``an`` used to declare for the in-distribution genre, so the handover was by name.
ENTRY_POINT_NAME: str = GENRE_NAME

#: Where the entry point points.
ENTRY_POINT_VALUE: str = "cutan.genre:CUTOUT"

#: The persisted renderer name of cut-out shots (``an.stage`` claims it).
RENDERER_NAME: str = "cutout"

#: The package whose data root holds the genre's asset library and projects
#: (``~/.local/share/cutan`` by default; ``CUTAN_HOME`` overrides it).
LIBRARY_NAME: str = "cutan"

#: The lowest ``an.genres.API_LEVEL`` this ``cutan`` runs against ("the lowest ``an``
#: it supports", ADR 0001 decision 8, said without a version pin: ``an``'s version is
#: assigned by CI at merge). Level 2 is the move itself: ``Genre.services``,
#: ``ActionKind.lowering``, ``EntityKind.swap_declaration`` and ``an.stage.rig``.
#: Level 3 is the public rig builder (an#338): ``an.stage.rig.build_rig_subtree``,
#: ``rig_origin``, ``RigDocument`` and ``omit_unset_rig_fields``. Level 4 is the rest
#: pose (an#339): ``register_rest_pose_migration`` and ``rig_rest_problems``. Level 5
#: is nested chains (an#340): ``build_rig_subtree(skip_slots=)``, ``slot_parent_chain``,
#: ``slot_node_paths``, ``rig_affordances``, ``RigError``.
#: Level 6: ``rest_pose_protection`` (an#407), which ``validate_character`` says aloud.
REQUIRED_AN_API_LEVEL: int = 6


[docs] def require_an() -> None: """Refuse, with an upgrade hint, to load against an ``an`` older than this ``cutan`` needs. >>> require_an() """ import an.genres level = getattr(an.genres, "API_LEVEL", 0) if level < REQUIRED_AN_API_LEVEL: raise ImportError( f"cutan needs an.genres API level {REQUIRED_AN_API_LEVEL} or higher; this an " f"provides {level}. Upgrade an: pip install -U an" )
# The named style specs (package data, cutan#4): ``cutan.style_spec("south_park")``. from cutan.styles import style_spec, style_specs # noqa: E402 __all__ = [ "ENTRY_POINT_GROUP", "ENTRY_POINT_NAME", "ENTRY_POINT_VALUE", "GENRE_NAME", "LIBRARY_NAME", "REQUIRED_AN_API_LEVEL", "RENDERER_NAME", "require_an", "style_spec", "style_specs", ]