an.library.rights#
Rights on every version: the most restrictive licence class wins (ADR 0005 decision 10, design §9).
The library adds no licence vocabulary. A version’s rights are rolled up from
an’s existing model (an#211): AssetSource records and
license_class()’s four classes. The roll-up reads them from
the source declared for the asset as a whole at publish, AND the descriptor’s own
source— both, never one instead of the other (an asset with neither isunknown: recorded and visible, never rejected);every part and plane that declares its own
source— gathered byan.credits.collect_credits(), the same walkan creditsruns, so thelibrary and the credits report can never disagree about what an asset holds;
every version it derives from (
derived_from) and the version it follows (previous), recursively, by the same rules: a derivative inherits the obligations of its sources, and a new version cannot relabel the old one;the source any other version records for the same file bytes (by blob digest): a file’s own recorded provenance travels with its bytes, so carved parts published again under a new id keep their obligations (
an.library.api.version_sources()walks all of it).
A version may only ever be MORE restrictive than what it inherits. Relaxing
takes an explicit, recorded relicence — who and why — on the version. Where
nobody ever said anything (a file an earlier version recorded unlabelled,
a version with no source), an explicit source with a recorded relabel —
who and why — is the first statement (an#263); it relaxes nothing anyone said.
Order, most restrictive first: private > unknown > attribution >
free. private and unknown are not publishable.
>>> from an.ir.assets import AssetSource
>>> r = roll_up([("asset", AssetSource(provider="p", license="cc0-1.0")),
... ("parts/head.png", AssetSource(provider="film", license="all-rights-reserved"))])
>>> (r.license_class, r.publishable)
('private', False)
>>> r.reasons
['parts/head.png: all-rights-reserved (private)']
Module Attributes
Licence classes, most restrictive first. |
|
The classes a video may ship with ( |
|
The classes a COMMERCIAL video may ship with (monetised, sponsored, client work). |
Functions
|
The most restrictive of |
|
The source the descriptor itself declares (or |
|
Roll labelled sources (and parents' rights) up to one |
|
Every labelled source one version holds: the asset's, the descriptor's, each part's. |
Classes
|
The rolled-up rights of one version, as stored on it. |
Exceptions
A private or unknown version would leave the user's library without an override. |
- an.library.rights.COMMERCIAL_CLASSES: frozenset[str] = frozenset({'attribution', 'free'})#
The classes a COMMERCIAL video may ship with (monetised, sponsored, client work).
- an.library.rights.LICENSE_CLASS_ORDER: tuple[Literal['attribution', 'free', 'noncommercial', 'private', 'unknown'], ...] = ('private', 'unknown', 'noncommercial', 'attribution', 'free')#
Licence classes, most restrictive first. The roll-up keeps the first that occurs.
- an.library.rights.PUBLISHABLE_CLASSES: frozenset[str] = frozenset({'attribution', 'free', 'noncommercial'})#
The classes a video may ship with (
attributionandnoncommercialwith their credit displayed;noncommercialonly in a video nobody earns from — an#373: flagged for commercial use, never blocked).
- class an.library.rights.Rights(license_class, reasons=<factory>)[source]#
Bases:
objectThe rolled-up rights of one version, as stored on it.
- exception an.library.rights.RightsRefusal[source]#
Bases:
PermissionErrorA private or unknown version would leave the user’s library without an override.
- an.library.rights.descriptor_source(doc, *, store)[source]#
The source the descriptor itself declares (or
an creditsreconstructs), if any.- Return type:
- an.library.rights.most_restrictive(classes)[source]#
The most restrictive of
classes;freefor none.- Return type:
Literal['attribution','free','noncommercial','private','unknown']
>>> most_restrictive(["free", "attribution"]), most_restrictive([]) ('attribution', 'free')
- an.library.rights.roll_up(sources, *, inherited=())[source]#
Roll labelled sources (and parents’ rights) up to one
Rights.A
Nonesource isunknown. The reasons name every contributor of the winning class, so a reader sees why a version is restricted.- Return type:
>>> roll_up([("asset", None)]).to_dict() {'license_class': 'unknown', 'publishable': False, 'reasons': ['asset: no source recorded (unknown)']}
- an.library.rights.sources_in(doc, *, store, source=None, files=None)[source]#
Every labelled source one version holds: the asset’s, the descriptor’s, each part’s.
- Return type:
list[tuple[str,AssetSource|None]]
- store: the project store this kind of document lives in (
characters, props,environments,sounds) — its sources are read byan credits’ own walk;Nonereads the top-levelsourcealone- source: a source declared for the asset as a whole (at publish, or carried
from an earlier version). It is a contributor BESIDE the descriptor’s own source, never instead of it: the roll-up takes the most restrictive, so a declared
cc0cannot mask a descriptor that says the art came from a film. The only way to relax a stricter source is an explicit, recorded relicence (an.library.api.publish()’srelicense), which bypasses this function altogether- files:
{path: sha256}of the asset’s files. With them, a factory stamp is checked against the bytes it pins (
an.credits._part_credits()): a re-carved part under a stale stamp, or a file the factory’s descriptor stamp does not pin, isunknownunless a source covers it
With no source anywhere the asset contributes
None:unknown.>>> private = {"provider": "film", "license": "all-rights-reserved"} >>> [label for label, _ in sources_in({"source": private}, store=None, ... source=AssetSource(provider="me", license="cc0-1.0"))] ['asset', 'descriptor']