diff --git a/Makefile b/Makefile index e3007f9e7..65cf17106 100644 --- a/Makefile +++ b/Makefile @@ -181,6 +181,12 @@ doc-model: doc-model-update: @python src/py-opentimelineio/opentimelineio/console/autogen_serialized_datamodel.py -o docs/tutorials/otio-serialized-schema.md +spec: + @python src/py-opentimelineio/opentimelineio/console/autogen_core_specification.py --dryrun + +spec-update: + @python src/py-opentimelineio/opentimelineio/console/autogen_core_specification.py -o docs/spec/otio-core-specification.md + doc-plugins: @python src/py-opentimelineio/opentimelineio/console/autogen_plugin_documentation.py --dryrun diff --git a/docs/spec/core-specification-overlay.md b/docs/spec/core-specification-overlay.md new file mode 100644 index 000000000..707544b99 --- /dev/null +++ b/docs/spec/core-specification-overlay.md @@ -0,0 +1,358 @@ + + +# OpenTimelineIO Core Specification + +> **This document is generated.** It is assembled from the OpenTimelineIO code +> (schema objects, fields, types, and docstrings) and a curated prose overlay by +> `src/py-opentimelineio/opentimelineio/console/autogen_core_specification.py`. +> Run `make spec-update` to regenerate it. Do not edit this file directly. + +## Introduction + +OpenTimelineIO (OTIO) is an API and interchange format for editorial cut +information. You can think of it as a modern Edit Decision List (EDL) that also +includes an API for reading, writing, and manipulating editorial data. + +This specification describes the OTIO data model: the schema objects that make +up an OTIO document, the fields they carry, the types and default values of +those fields, and the semantic meaning and intended usage of each. It is meant +to give application integrators a precise, durable reference for the data and +mental model of OpenTimelineIO. + +OTIO supports clips, timing, tracks, transitions, markers, metadata, and more, +but it does not embed video or audio. Media is always referenced externally. + +For broader context on adopting OTIO in an application -- how to think about +your application's role in a workflow, and how to move beyond EDL-style +interchange -- see the +[Application Integrator's Guide](https://opentimelineio.readthedocs.io/). + +## Conventions + +OTIO's implementation has two layers: + +1. A serialization scheme that stores structured data along with a schema name + and version for interpreting that data. +2. A set of *schema* that define types of objects and their serialized data + fields. + +When interacting with OTIO, integrators deal almost entirely with deserialized +schema objects; the implementation handles translating between in-memory +objects and their serialized form, and provides a rich set of functionality for +querying and modifying timeline data. + +Integrators should rely on one of the implementations provided by the project +to read and write `.otio` files rather than writing their own. The core +implementation provides a great deal of subtle behavior that is time-consuming +to reproduce and easy to get subtly wrong. + +In this document, each object lists: + +- its **schema** name and version (e.g. `Clip.2`), +- the **module** that hosts the public python class, +- what it **inherits from**, and +- its **fields**, each annotated with its type, whether it is optional, and its + default value. + +### Schema are versioned + +Each object type has an independent schema version, stored as an integer that +increments each time there is a *breaking* change. Non-breaking changes, such as +the addition of a field, do not interfere with loading in older +implementations -- the new fields are simply unavailable there. + +When OTIO encounters a serialized object with an older schema, it automatically +migrates that object to the newest available schema, even up-converting data +where needed. Application implementers therefore only need to handle the latest +schema version. + +### The `metadata` dictionary + +In addition to the first-class fields defined by each schema object, every OTIO +object has a `metadata` field: an arbitrarily deep dictionary into which +applications and users may attach any data they like. This is a distinctive +feature of OTIO. Studios attach identifiers for production-tracking systems; +adapters store format-specific context about the file an OTIO was derived from; +users attach data such as source script page numbers or review notes. + +The implementation enforces no structure on `metadata`, but two conventions are +strongly recommended: + +**Use a unique "namespace" key for your data.** Place your data inside a +dictionary under a top-level key that is unlikely to collide with anyone +else's. These namespace keys act as informal sub-schema. For example: + +```json +{ + "myAnimStudio": { + "sequence": "ABC", + "shot": "ABC010", + "shot_id": "7b3aaa14-8305-4fdd-87c2-b0b9d3f9dac7" + }, + "cdl": { + "asc_sat": 0.9, + "asc_sop": { "offset": [1, -0.0122, 0.0305], "power": [1, 0, 1], "slope": [0.1, 0.2, 0.3] } + }, + "cmx_3600": { "comments": ["SOURCE FILE: ABC010.LAYOUT3.01"] } +} +``` + +Here production-tracking data, CDL color values, and a comment carried over from +an original CMX 3600 EDL coexist, separated by their namespace keys. + +**Preserve metadata you do not own.** When reading and writing OTIO, make a best +effort to round-trip `metadata` untouched, mutating only the namespaces your +application controls. This keeps upstream data flowing downstream through a +pipeline without loss. + +The `metadata` dictionary is also where new first-class schema is incubated: +valuable data not yet modeled by OTIO can be carried in `metadata` so pipelines +can begin using it, which in turn informs the design of a future first-class +field. + +### `.otio` files and root objects + +`.otio` files are the native JSON serialization of an OTIO object tree with a +single root object. Any schema object can be serialized as the root of a `.otio` +file, so implementers should check what kind of object results from reading a +file and handle it appropriately. + +In practice **most `.otio` files have either a `Timeline` or a +`SerializableCollection` as their root object.** Where an older workflow might +use an `.edl`, an `.otio` with a root `Timeline` is used; where an `.ale` was +used, an `.otio` with a root `SerializableCollection` of `Clip` objects is used. +OTIO has no dedicated "project" schema; a project is typically represented as a +`SerializableCollection` containing `Timelines`, nested `SerializableCollections` +for folder/bin structure, and `Clips` for project media. + +The following abstract objects define the fields and behavior inherited by the +concrete schema objects below. They are not usually instantiated directly. + +`SerializableObject` is the root of the OTIO type hierarchy. Every object that +can be written to and read from an `.otio` file derives from it. + +`SerializableObjectWithMetadata` adds the two fields shared by nearly every +user-facing object: a human-readable `name` and the `metadata` dictionary +described in the [Conventions](#conventions). + +`Composable` is the base class for anything that can be placed as a child inside +a `Composition` -- principally `Item` (and therefore `Clip` and `Gap`) and +`Transition`. + +`Composition` is the base class for the ordered containers `Track` and `Stack`. +It owns its children and is responsible for their ordering. + +OpenTimelineIO's schema provides objects that correlate directly to the units +editors interact with in an NLE, while also supporting advanced compositions. +This section describes the most common schema objects and how they are intended +to be used. + +When composing editorial, items have two important relationships to one another: +*sequential* presentation (clip B comes after clip A) and *simultaneous* +presentation (clip B is composited over clip A). A `Track` composes items +sequentially; a `Stack` composes items simultaneously. + +A `Timeline` represents one edit, sequence, or presentation, and is named as you +might see a sequence named in an editor's project. Its `tracks` field references +a `Stack` containing the timeline's audio, video, and other `Tracks`. + +Using an appropriate namespace key, the `metadata` field is a good place to +store timeline/sequence settings such as edit rate, video resolution, and audio +sample rate. Many of these concepts are expected to gain first-class fields in +the future. + +Use `global_start_time` for the start timecode of a sequence -- for example, to +set a start timecode of `01:00:00:00`. + +A `SerializableCollection` stores an ordered collection of other OTIO schema +objects. Collections are commonly used to represent bins or folders in a project +and can be nested to build deeper project structure. Its `name` corresponds to +the name shown for the folder or bin. + +A `Stack` composes items that are coincident in time. Commonly the only `Stack` +in an OTIO document is the `tracks` stack on a `Timeline`, which is directly +analogous to the layered timeline interface of an NLE. + +The children of a `Stack` are ordered in compositing order: the first child is +the "bottom" and the last is the "top". Visual media is assumed to use alpha +compositing (overlaying items one over another) and audio media is assumed to +use additive compositing (mixing all tracks together). If another compositing +method is used, record that under your application's namespace key in the +`Stack`'s `metadata`. + +A `Track` composes items in sequential order. In addition, a track has a `kind` +that defines what type of output media the track composes. + +`kind` is deliberately a string rather than a constrained enum. The constants +`Audio` and `Video` are provided for the most common kinds. Other values may be +used, but implementers are expected to ignore tracks of a kind they do not +understand, and some utility methods may not handle unknown kinds. As consensus +forms around new track kinds, they will be provided as additional constants. + +`Item` is the base class for the objects placed end-to-end in a track that +occupy time: `Clip` and `Gap`. Items are *single-use* -- a given instance may +appear in a composition only once, which lets each use carry its own markers, +metadata, and effects. The API provides ways to copy an item to reuse the same +media multiple times. + +One way to think of items is as strips of film spliced end-to-end in a track: a +`Gap` is clear leader of some length, and a `Clip` is film from the camera. To +use the same strip twice, you make another copy. + +The `source_range` selects the portion of the underlying time that the item +occupies and determines its duration. + +A `Clip` represents an instance of using some subsegment of media in the +timeline, directly analogous to a clip in a standard NLE. + +The clip's in and out points are set with `source_range`, which also determines +the clip's duration; `source_range` is the time range selected within the source +media's `available_range`. The `media_reference` specifies how to locate the +media assets the clip composes (see [`MediaReference`](#mediareference)). + +A `Gap` represents an absence of media: it does not contribute media to the +composition, it only offsets other items in time. A `Gap` can be thought of as +transparent or silent filler. + +A `Transition` is placed in a track between two other items to indicate that +their content is blended for some duration during presentation -- it signals an +overlap between the preceding and following items. `in_offset` specifies where, +relative to the end of the preceding item, the transition starts; `out_offset` +specifies where, relative to the start of the following item, the transition +ends. + +Set `transition_type` to a key identifying the specific effect (such as a +horizontal wipe or cross-fade); store the configuration of that effect in the +`metadata` dictionary. + +A `Marker` attaches additional information to a specific time or time range. +Markers may be added to the `markers` list on `Track`, `Stack`, `Gap`, and +`Clip` objects. They are commonly used to note chapters in a sequence, to attach +extra metadata to a clip, or to identify clips for VFX. + +`marked_range` specifies the marked range in the host item's local time +coordinates. For example, a `marked_range` of +`TimeRange(start_time=RationalTime(0, 24), duration=RationalTime(0, 24))` marks +the beginning of the clip as positioned in the timeline, not the beginning of +the source media. + +`color` describes the color the marker is drawn with in the user interface and +is commonly overloaded to convey workflow context (e.g. red for chapter markers, +blue for VFX shots). As workflows become more OTIO-aware, this overloaded use +should be phased out in favor of describing the marker's purpose explicitly in +`metadata`. + +An `Effect` models a transformation applied to the media as used in the +composition -- in common terms, a "filter". Effects may be added to the +`effects` list on `Track`, `Stack`, `Gap`, and `Clip` objects, though they are +most commonly applied to `Clip` objects. + +The `effects` list allows stacking: the media is transformed in list order. For +example, a clip could carry a 100% desaturation as its first effect and a brown +tint as its second to achieve a sepia look. + +Set `effect_name` to a key identifying the specific effect; store the +configuration of that usage in the `metadata` dictionary. Apart from the timing +effects below, all effects currently use this base `Effect` schema; in the +future, standardized effects may be defined as new schema with explicit +configuration fields. + +A `LinearTimeWarp` is a timing effect that linearly maps presentation time to +source-media time. If `time_scalar` is `2.0`, the footage plays back at double +rate. A clip's `source_range` `start_time` selects the start point in the source +media and `duration` is the duration in the presentation; the duration of source +media consumed is the clip's duration multiplied by `time_scalar`. + +> Note: a newer approach to time transformations is in active development; +> contact the OTIO developers for details. + +A `FreezeFrame` is a timing effect with a `time_scalar` of `0`, which holds the +first frame of a clip for the clip's duration. + +`TimeEffect` is the base class for timing effects -- effects that inform how +time in the clip's coordinate space (0 to the clip's duration) maps to time in +the media's coordinate space (the clip's available range). `LinearTimeWarp` and +`FreezeFrame` derive from it. + +OTIO does not embed media assets; instead it provides ways for applications to +locate the appropriate media. `MediaReference` is the base class for the +specific reference types below. + +Use the media's global start time when setting `available_range`. When the +`start_time` of the available range is the start timecode or first frame number +of the media, applications can reliably locate the correct media across a range +of situations -- especially when switching between representations trimmed with +different handles. + +An `ExternalReference` identifies an asset by URL; local files use `file://` +URLs. Use it when a specific file path or URL is available for the asset. + +An `ImageSequenceReference` identifies an asset as a set of sequentially +numbered images. Use it when the asset is a numbered image sequence rather than +a single file. + +A `MissingReference` is used when there is no specific file path for the media. +Any metadata that could help a downstream consumer relink the media (reel name, +tracking IDs, and so on) should be placed in the reference's `metadata` +dictionary. + +A `GeneratorReference` is used when a clip's media is generated programmatically +-- a solid color, color bars, tone, white noise, and the like. Use the +`parameters` dictionary to describe the generator's configuration (for example, +which color, or the frequency and wave shape of a tone). + +These value types are used by the fields of the schema objects above. Unlike the +objects above they are not, on their own, `SerializableObject`s. + +A `RationalTime` is OTIO's fundamental representation of a moment in time, as a +`value` measured in units of `1/rate` seconds. Representing time as a value over +a rate (rather than as a floating-point number of seconds) lets OTIO express +frame-accurate timing exactly and rescale cleanly between rates. + +A `TimeRange` represents a span of time as a `start_time` and a `duration`, both +`RationalTime`s. By convention the range is half-open: it includes `start_time` +and excludes `start_time + duration`. + +A `TimeTransform` represents an affine transformation of time -- an `offset` and +a `scale` applied to a `RationalTime`. + +A `Color` is an RGBA color used for user-interface elements such as marker or +clip coloring. It is not intended to describe image pixel content. + +## JSON Serialization + +`.otio` files are human-readable JSON. Every schema object serializes to a JSON +object that carries an `OTIO_SCHEMA` key naming its schema and version (for +example, `"OTIO_SCHEMA": "Clip.2"`), alongside the fields documented above. +Container objects store their children inline, so a serialized `Timeline` is a +single JSON tree rooted at one object. + +Because schema are versioned and automatically migrated on read, a file written +by one version of OTIO can be read by a newer version without special handling. +There are currently no mechanisms for downgrading the schema versions used +within an OTIO file, so keeping the OTIO implementation in your software +up-to-date maximizes read compatibility with files produced by other +applications. diff --git a/docs/spec/otio-core-specification.md b/docs/spec/otio-core-specification.md new file mode 100644 index 000000000..c89af49a1 --- /dev/null +++ b/docs/spec/otio-core-specification.md @@ -0,0 +1,820 @@ +# OpenTimelineIO Core Specification + +> **This document is generated.** It is assembled from the OpenTimelineIO code +> (schema objects, fields, types, and docstrings) and a curated prose overlay by +> `src/py-opentimelineio/opentimelineio/console/autogen_core_specification.py`. +> Run `make spec-update` to regenerate it. Do not edit this file directly. + +## Introduction + +OpenTimelineIO (OTIO) is an API and interchange format for editorial cut +information. You can think of it as a modern Edit Decision List (EDL) that also +includes an API for reading, writing, and manipulating editorial data. + +This specification describes the OTIO data model: the schema objects that make +up an OTIO document, the fields they carry, the types and default values of +those fields, and the semantic meaning and intended usage of each. It is meant +to give application integrators a precise, durable reference for the data and +mental model of OpenTimelineIO. + +OTIO supports clips, timing, tracks, transitions, markers, metadata, and more, +but it does not embed video or audio. Media is always referenced externally. + +For broader context on adopting OTIO in an application -- how to think about +your application's role in a workflow, and how to move beyond EDL-style +interchange -- see the +[Application Integrator's Guide](https://opentimelineio.readthedocs.io/). + +## Conventions + +OTIO's implementation has two layers: + +1. A serialization scheme that stores structured data along with a schema name + and version for interpreting that data. +2. A set of *schema* that define types of objects and their serialized data + fields. + +When interacting with OTIO, integrators deal almost entirely with deserialized +schema objects; the implementation handles translating between in-memory +objects and their serialized form, and provides a rich set of functionality for +querying and modifying timeline data. + +Integrators should rely on one of the implementations provided by the project +to read and write `.otio` files rather than writing their own. The core +implementation provides a great deal of subtle behavior that is time-consuming +to reproduce and easy to get subtly wrong. + +In this document, each object lists: + +- its **schema** name and version (e.g. `Clip.2`), +- the **module** that hosts the public python class, +- what it **inherits from**, and +- its **fields**, each annotated with its type, whether it is optional, and its + default value. + +### Schema are versioned + +Each object type has an independent schema version, stored as an integer that +increments each time there is a *breaking* change. Non-breaking changes, such as +the addition of a field, do not interfere with loading in older +implementations -- the new fields are simply unavailable there. + +When OTIO encounters a serialized object with an older schema, it automatically +migrates that object to the newest available schema, even up-converting data +where needed. Application implementers therefore only need to handle the latest +schema version. + +### The `metadata` dictionary + +In addition to the first-class fields defined by each schema object, every OTIO +object has a `metadata` field: an arbitrarily deep dictionary into which +applications and users may attach any data they like. This is a distinctive +feature of OTIO. Studios attach identifiers for production-tracking systems; +adapters store format-specific context about the file an OTIO was derived from; +users attach data such as source script page numbers or review notes. + +The implementation enforces no structure on `metadata`, but two conventions are +strongly recommended: + +**Use a unique "namespace" key for your data.** Place your data inside a +dictionary under a top-level key that is unlikely to collide with anyone +else's. These namespace keys act as informal sub-schema. For example: + +```json +{ + "myAnimStudio": { + "sequence": "ABC", + "shot": "ABC010", + "shot_id": "7b3aaa14-8305-4fdd-87c2-b0b9d3f9dac7" + }, + "cdl": { + "asc_sat": 0.9, + "asc_sop": { "offset": [1, -0.0122, 0.0305], "power": [1, 0, 1], "slope": [0.1, 0.2, 0.3] } + }, + "cmx_3600": { "comments": ["SOURCE FILE: ABC010.LAYOUT3.01"] } +} +``` + +Here production-tracking data, CDL color values, and a comment carried over from +an original CMX 3600 EDL coexist, separated by their namespace keys. + +**Preserve metadata you do not own.** When reading and writing OTIO, make a best +effort to round-trip `metadata` untouched, mutating only the namespaces your +application controls. This keeps upstream data flowing downstream through a +pipeline without loss. + +The `metadata` dictionary is also where new first-class schema is incubated: +valuable data not yet modeled by OTIO can be carried in `metadata` so pipelines +can begin using it, which in turn informs the design of a future first-class +field. + +### `.otio` files and root objects + +`.otio` files are the native JSON serialization of an OTIO object tree with a +single root object. Any schema object can be serialized as the root of a `.otio` +file, so implementers should check what kind of object results from reading a +file and handle it appropriately. + +In practice **most `.otio` files have either a `Timeline` or a +`SerializableCollection` as their root object.** Where an older workflow might +use an `.edl`, an `.otio` with a root `Timeline` is used; where an `.ale` was +used, an `.otio` with a root `SerializableCollection` of `Clip` objects is used. +OTIO has no dedicated "project" schema; a project is typically represented as a +`SerializableCollection` containing `Timelines`, nested `SerializableCollections` +for folder/bin structure, and `Clips` for project media. + +## Base Classes + +The following abstract objects define the fields and behavior inherited by the +concrete schema objects below. They are not usually instantiated directly. + +### SerializableObject + +- *schema*: `SerializableObject.1` +- *module*: `opentimelineio.plugins.PythonPlugin` +- *inherits from*: `SerializableObject` + +A class of plugin that is encoded in a python module, exposed via a + manifest. + +`SerializableObject` is the root of the OTIO type hierarchy. Every object that +can be written to and read from an `.otio` file derives from it. + +#### Fields + +- *filepath*: Absolute path or relative path to adapter module from location of json. +- *name*: Adapter name. + +### SerializableObjectWithMetadata + +- *schema*: `SerializableObjectWithMetadata.1` +- *module*: `opentimelineio.core.SerializableObjectWithMetadata` +- *inherits from*: `SerializableObject` + +`SerializableObjectWithMetadata` adds the two fields shared by nearly every +user-facing object: a human-readable `name` and the `metadata` dictionary +described in the [Conventions](#conventions). + +#### Fields + +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. + +### Composable + +- *schema*: `Composable.1` +- *module*: `opentimelineio.core.Composable` +- *inherits from*: `SerializableObjectWithMetadata` -> `SerializableObject` + +An object that can be composed within a `Composition` (such as `Track` or `Stack`). + +`Composable` is the base class for anything that can be placed as a child inside +a `Composition` -- principally `Item` (and therefore `Clip` and `Gap`) and +`Transition`. + +#### Fields + +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. + +### Composition + +- *schema*: `Composition.1` +- *module*: `opentimelineio.core.Composition` +- *inherits from*: `Item` -> `Composable` -> `SerializableObjectWithMetadata` -> `SerializableObject` + +Base class for an `Item` that contains `Composable`\s. + +Should be subclassed (for example by `Track` and `Stack`), not used directly. + +`Composition` is the base class for the ordered containers `Track` and `Stack`. +It owns its children and is responsible for their ordering. + +#### Fields + +- *color* (`Color`, optional): Optional color used to display this item in a user interface. +- *effects* (`Array[Effect]`, default: `[]`): Effects applied to this item's media, applied in the order they appear in the list. +- *enabled* (`Boolean`, default: `true`): If true, an Item contributes to compositions. For example, when an audio/video clip is `enabled=false` the clip is muted/hidden. +- *markers* (`Array[Marker]`, default: `[]`): Markers attached to this item, positioned in the item's local time coordinates. +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. +- *source_range* (`TimeRange`, optional): The range of the item to present, expressed in the item's own time coordinate space. This determines the item's duration. When null, the item's full `available_range` is used. + +## Object Model + +OpenTimelineIO's schema provides objects that correlate directly to the units +editors interact with in an NLE, while also supporting advanced compositions. +This section describes the most common schema objects and how they are intended +to be used. + +When composing editorial, items have two important relationships to one another: +*sequential* presentation (clip B comes after clip A) and *simultaneous* +presentation (clip B is composited over clip A). A `Track` composes items +sequentially; a `Stack` composes items simultaneously. + +### Timeline + +- *schema*: `Timeline.1` +- *module*: `opentimelineio.schema.Timeline` +- *inherits from*: `SerializableObjectWithMetadata` -> `SerializableObject` + +A `Timeline` represents one edit, sequence, or presentation, and is named as you +might see a sequence named in an editor's project. Its `tracks` field references +a `Stack` containing the timeline's audio, video, and other `Tracks`. + +Using an appropriate namespace key, the `metadata` field is a good place to +store timeline/sequence settings such as edit rate, video resolution, and audio +sample rate. Many of these concepts are expected to gain first-class fields in +the future. + +Use `global_start_time` for the start timecode of a sequence -- for example, to +set a start timecode of `01:00:00:00`. + +#### Fields + +- *global_start_time* (`RationalTime`, optional): Global offset for the start of the timeline, used to express a sequence's start timecode (for example `01:00:00:00`). +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. +- *tracks* (`Stack`): The `Stack` holding the timeline's tracks (its audio, video, and other `Track`\s). + +### SerializableCollection + +- *schema*: `SerializableCollection.1` +- *module*: `opentimelineio.schema.SerializableCollection` +- *inherits from*: `SerializableObjectWithMetadata` -> `SerializableObject` + +A container which can hold an ordered list of any serializable objects. Note that this is not a `Composition` nor is it `Composable`. + +This container approximates the concept of a bin - a collection of `SerializableObject`\s that do +not have any compositional meaning, but can serialize to/from OTIO correctly, with metadata and +a named collection. + +A `SerializableCollection` is useful for serializing multiple timelines, clips, or media references to a single file. + +A `SerializableCollection` stores an ordered collection of other OTIO schema +objects. Collections are commonly used to represent bins or folders in a project +and can be nested to build deeper project structure. Its `name` corresponds to +the name shown for the folder or bin. + +#### Fields + +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. + +### Stack + +- *schema*: `Stack.1` +- *module*: `opentimelineio.schema.Stack` +- *inherits from*: `Composition` -> `Item` -> `Composable` -> `SerializableObjectWithMetadata` -> `SerializableObject` + +A `Stack` composes items that are coincident in time. Commonly the only `Stack` +in an OTIO document is the `tracks` stack on a `Timeline`, which is directly +analogous to the layered timeline interface of an NLE. + +The children of a `Stack` are ordered in compositing order: the first child is +the "bottom" and the last is the "top". Visual media is assumed to use alpha +compositing (overlaying items one over another) and audio media is assumed to +use additive compositing (mixing all tracks together). If another compositing +method is used, record that under your application's namespace key in the +`Stack`'s `metadata`. + +#### Fields + +- *color* (`Color`, optional): Optional color used to display this item in a user interface. +- *effects* (`Array[Effect]`, default: `[]`): Effects applied to this item's media, applied in the order they appear in the list. +- *enabled* (`Boolean`, default: `true`): If true, an Item contributes to compositions. For example, when an audio/video clip is `enabled=false` the clip is muted/hidden. +- *markers* (`Array[Marker]`, default: `[]`): Markers attached to this item, positioned in the item's local time coordinates. +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. +- *source_range* (`TimeRange`, optional): The range of the item to present, expressed in the item's own time coordinate space. This determines the item's duration. When null, the item's full `available_range` is used. + +### Track + +- *schema*: `Track.1` +- *module*: `opentimelineio.schema.Track` +- *inherits from*: `Composition` -> `Item` -> `Composable` -> `SerializableObjectWithMetadata` -> `SerializableObject` + +A `Track` composes items in sequential order. In addition, a track has a `kind` +that defines what type of output media the track composes. + +`kind` is deliberately a string rather than a constrained enum. The constants +`Audio` and `Video` are provided for the most common kinds. Other values may be +used, but implementers are expected to ignore tracks of a kind they do not +understand, and some utility methods may not handle unknown kinds. As consensus +forms around new track kinds, they will be provided as additional constants. + +#### Fields + +- *color* (`Color`, optional): Optional color used to display this track in a user interface. +- *effects* (`Array[Effect]`, default: `[]`): Effects applied to this item's media, applied in the order they appear in the list. +- *enabled* (`Boolean`, default: `true`): If true, an Item contributes to compositions. For example, when an audio/video clip is `enabled=false` the clip is muted/hidden. +- *kind* (`String`, default: `"Video"`): The kind of media this track composes (for example the `Audio` or `Video` constants). A free-form string; applications are expected to ignore tracks of a kind they do not understand. +- *markers* (`Array[Marker]`, default: `[]`): Markers attached to this item, positioned in the item's local time coordinates. +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. +- *source_range* (`TimeRange`, optional): The range of the item to present, expressed in the item's own time coordinate space. This determines the item's duration. When null, the item's full `available_range` is used. + +### Item + +- *schema*: `Item.1` +- *module*: `opentimelineio.core.Item` +- *inherits from*: `Composable` -> `SerializableObjectWithMetadata` -> `SerializableObject` + +`Item` is the base class for the objects placed end-to-end in a track that +occupy time: `Clip` and `Gap`. Items are *single-use* -- a given instance may +appear in a composition only once, which lets each use carry its own markers, +metadata, and effects. The API provides ways to copy an item to reuse the same +media multiple times. + +One way to think of items is as strips of film spliced end-to-end in a track: a +`Gap` is clear leader of some length, and a `Clip` is film from the camera. To +use the same strip twice, you make another copy. + +The `source_range` selects the portion of the underlying time that the item +occupies and determines its duration. + +#### Fields + +- *color* (`Color`, optional): Optional color used to display this item in a user interface. +- *effects* (`Array[Effect]`, default: `[]`): Effects applied to this item's media, applied in the order they appear in the list. +- *enabled* (`Boolean`, default: `true`): If true, an Item contributes to compositions. For example, when an audio/video clip is `enabled=false` the clip is muted/hidden. +- *markers* (`Array[Marker]`, default: `[]`): Markers attached to this item, positioned in the item's local time coordinates. +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. +- *source_range* (`TimeRange`, optional): The range of the item to present, expressed in the item's own time coordinate space. This determines the item's duration. When null, the item's full `available_range` is used. + +### Clip + +- *schema*: `Clip.2` +- *module*: `opentimelineio.schema.Clip` +- *inherits from*: `Item` -> `Composable` -> `SerializableObjectWithMetadata` -> `SerializableObject` + +A `Clip` is a segment of editable media (usually audio or video). + +Contains a `MediaReference` and a trim on that media reference. + +A `Clip` represents an instance of using some subsegment of media in the +timeline, directly analogous to a clip in a standard NLE. + +The clip's in and out points are set with `source_range`, which also determines +the clip's duration; `source_range` is the time range selected within the source +media's `available_range`. The `media_reference` specifies how to locate the +media assets the clip composes (see [`MediaReference`](#mediareference)). + +#### Fields + +- *active_media_reference_key* (`String`, default: `"DEFAULT_MEDIA"`): Key, in `media_references`, of the media reference currently active for this clip. +- *color* (`Color`, optional): Optional color used to display this clip in a user interface. +- *effects* (`Array[Effect]`, default: `[]`): Effects applied to this item's media, applied in the order they appear in the list. +- *enabled* (`Boolean`, default: `true`): If true, an Item contributes to compositions. For example, when an audio/video clip is `enabled=false` the clip is muted/hidden. +- *markers* (`Array[Marker]`, default: `[]`): Markers attached to this item, positioned in the item's local time coordinates. +- *media_references* (`Map[String, MediaReference]`) +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. +- *source_range* (`TimeRange`, optional): The range of the item to present, expressed in the item's own time coordinate space. This determines the item's duration. When null, the item's full `available_range` is used. + +### Gap + +- *schema*: `Gap.1` +- *module*: `opentimelineio.schema.Gap` +- *inherits from*: `Item` -> `Composable` -> `SerializableObjectWithMetadata` -> `SerializableObject` + +A `Gap` represents an absence of media: it does not contribute media to the +composition, it only offsets other items in time. A `Gap` can be thought of as +transparent or silent filler. + +#### Fields + +- *color* (`Color`, optional): Optional color used to display this item in a user interface. +- *effects* (`Array[Effect]`, default: `[]`): Effects applied to this item's media, applied in the order they appear in the list. +- *enabled* (`Boolean`, default: `true`): If true, an Item contributes to compositions. For example, when an audio/video clip is `enabled=false` the clip is muted/hidden. +- *markers* (`Array[Marker]`, default: `[]`): Markers attached to this item, positioned in the item's local time coordinates. +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. +- *source_range* (`TimeRange`, optional): The range of the item to present, expressed in the item's own time coordinate space. This determines the item's duration. When null, the item's full `available_range` is used. + +### Transition + +- *schema*: `Transition.1` +- *module*: `opentimelineio.schema.Transition` +- *inherits from*: `Composable` -> `SerializableObjectWithMetadata` -> `SerializableObject` + +Represents a transition between the two adjacent items in a `Track`. For example, a cross dissolve or wipe. + +A `Transition` is placed in a track between two other items to indicate that +their content is blended for some duration during presentation -- it signals an +overlap between the preceding and following items. `in_offset` specifies where, +relative to the end of the preceding item, the transition starts; `out_offset` +specifies where, relative to the start of the following item, the transition +ends. + +Set `transition_type` to a key identifying the specific effect (such as a +horizontal wipe or cross-fade); store the configuration of that effect in the +`metadata` dictionary. + +#### Fields + +- *enabled* (`Boolean`, default: `true`): If true, a Transition contributes to compositions. For example, when a transition is `enabled=false` the transition is ignored and the adjacent clips are cut together with no transition. +- *in_offset* (`RationalTime`): Amount of the previous clip this transition overlaps, exclusive. +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. +- *out_offset* (`RationalTime`): Amount of the next clip this transition overlaps, exclusive. +- *transition_type* (`String`, default: `""`): Kind of transition, as defined by the `Type` enum. + +### Marker + +- *schema*: `Marker.2` +- *module*: `opentimelineio.schema.Marker` +- *inherits from*: `SerializableObjectWithMetadata` -> `SerializableObject` + +A marker indicates a marked range of time on an item in a timeline, usually with a name, color or other metadata. + +The marked range may have a zero duration. The marked range is in the owning item's time coordinate system. + +A `Marker` attaches additional information to a specific time or time range. +Markers may be added to the `markers` list on `Track`, `Stack`, `Gap`, and +`Clip` objects. They are commonly used to note chapters in a sequence, to attach +extra metadata to a clip, or to identify clips for VFX. + +`marked_range` specifies the marked range in the host item's local time +coordinates. For example, a `marked_range` of +`TimeRange(start_time=RationalTime(0, 24), duration=RationalTime(0, 24))` marks +the beginning of the clip as positioned in the timeline, not the beginning of +the source media. + +`color` describes the color the marker is drawn with in the user interface and +is commonly overloaded to convey workflow context (e.g. red for chapter markers, +blue for VFX shots). As workflows become more OTIO-aware, this overloaded use +should be phased out in favor of describing the marker's purpose explicitly in +`metadata`. + +#### Fields + +- *color* (`String`, default: `"RED"`): Color string for this marker (for example: 'RED'), based on the `Color` enum. +- *comment* (`String`, default: `""`): Optional comment for this marker. +- *marked_range* (`TimeRange`): Range this marker applies to, relative to the `Item` this marker is attached to (e.g. the `Clip` or `Track` that owns this marker). +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. + +### Effect + +- *schema*: `Effect.1` +- *module*: `opentimelineio.schema.Effect` +- *inherits from*: `SerializableObjectWithMetadata` -> `SerializableObject` + +An `Effect` models a transformation applied to the media as used in the +composition -- in common terms, a "filter". Effects may be added to the +`effects` list on `Track`, `Stack`, `Gap`, and `Clip` objects, though they are +most commonly applied to `Clip` objects. + +The `effects` list allows stacking: the media is transformed in list order. For +example, a clip could carry a 100% desaturation as its first effect and a brown +tint as its second to achieve a sepia look. + +Set `effect_name` to a key identifying the specific effect; store the +configuration of that usage in the `metadata` dictionary. Apart from the timing +effects below, all effects currently use this base `Effect` schema; in the +future, standardized effects may be defined as new schema with explicit +configuration fields. + +#### Fields + +- *effect_name* (`String`, default: `""`): Key identifying the specific effect applied; configuration of the effect is stored in `metadata`. +- *enabled* (`Boolean`, default: `true`): If true, the Effect is applied. If false, the Effect is omitted. +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. + +### LinearTimeWarp + +- *schema*: `LinearTimeWarp.1` +- *module*: `opentimelineio.schema.LinearTimeWarp` +- *inherits from*: `TimeEffect` -> `Effect` -> `SerializableObjectWithMetadata` -> `SerializableObject` + +A time warp that applies a linear speed up or slow down across the entire clip. + +A `LinearTimeWarp` is a timing effect that linearly maps presentation time to +source-media time. If `time_scalar` is `2.0`, the footage plays back at double +rate. A clip's `source_range` `start_time` selects the start point in the source +media and `duration` is the duration in the presentation; the duration of source +media consumed is the clip's duration multiplied by `time_scalar`. + +> Note: a newer approach to time transformations is in active development; +> contact the OTIO developers for details. + +#### Fields + +- *effect_name* (`String`, default: `"LinearTimeWarp"`): Key identifying the specific effect applied; configuration of the effect is stored in `metadata`. +- *enabled* (`Boolean`, default: `true`): If true, the Effect is applied. If false, the Effect is omitted. +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. +- *time_scalar* (`Double`, default: `1.0`): Linear time scalar applied to clip. 2.0 means the clip occupies half the time in the parent item, i.e. plays at double speed, +0.5 means the clip occupies twice the time in the parent item, i.e. plays at half speed. + +Note that adjusting the time_scalar of a `LinearTimeWarp` does not affect the duration of the item this effect is attached to. +Instead it affects the speed of the media displayed within that item. + +### FreezeFrame + +- *schema*: `FreezeFrame.1` +- *module*: `opentimelineio.schema.FreezeFrame` +- *inherits from*: `LinearTimeWarp` -> `TimeEffect` -> `Effect` -> `SerializableObjectWithMetadata` -> `SerializableObject` + +Hold the first frame of the clip for the duration of the clip. + +A `FreezeFrame` is a timing effect with a `time_scalar` of `0`, which holds the +first frame of a clip for the clip's duration. + +#### Fields + +- *effect_name* (`String`, default: `"FreezeFrame"`): Key identifying the specific effect applied; configuration of the effect is stored in `metadata`. +- *enabled* (`Boolean`, default: `true`): If true, the Effect is applied. If false, the Effect is omitted. +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. +- *time_scalar* (`Double`, default: `0.0`): Linear time scalar applied to clip. 2.0 means the clip occupies half the time in the parent item, i.e. plays at double speed, +0.5 means the clip occupies twice the time in the parent item, i.e. plays at half speed. + +Note that adjusting the time_scalar of a `LinearTimeWarp` does not affect the duration of the item this effect is attached to. +Instead it affects the speed of the media displayed within that item. + +### TimeEffect + +- *schema*: `TimeEffect.1` +- *module*: `opentimelineio.schema.TimeEffect` +- *inherits from*: `Effect` -> `SerializableObjectWithMetadata` -> `SerializableObject` + +Base class for all effects that alter the timing of an item. + +`TimeEffect` is the base class for timing effects -- effects that inform how +time in the clip's coordinate space (0 to the clip's duration) maps to time in +the media's coordinate space (the clip's available range). `LinearTimeWarp` and +`FreezeFrame` derive from it. + +#### Fields + +- *effect_name* (`String`, default: `""`): Key identifying the specific effect applied; configuration of the effect is stored in `metadata`. +- *enabled* (`Boolean`, default: `true`): If true, the Effect is applied. If false, the Effect is omitted. +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. + +### MediaReference + +- *schema*: `MediaReference.1` +- *module*: `opentimelineio.core.MediaReference` +- *inherits from*: `SerializableObjectWithMetadata` -> `SerializableObject` + +OTIO does not embed media assets; instead it provides ways for applications to +locate the appropriate media. `MediaReference` is the base class for the +specific reference types below. + +Use the media's global start time when setting `available_range`. When the +`start_time` of the available range is the start timecode or first frame number +of the media, applications can reliably locate the correct media across a range +of situations -- especially when switching between representations trimmed with +different handles. + +#### Fields + +- *available_image_bounds* (`Box2d`, optional): Optional spatial bounds of the image content of this media. +- *available_range* (`TimeRange`, optional): The range of media available in this reference, in the media's own time coordinates. When set, its `start_time` should be the media's start timecode or first frame number so consumers can reliably locate the media. +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. + +### ExternalReference + +- *schema*: `ExternalReference.1` +- *module*: `opentimelineio.schema.ExternalReference` +- *inherits from*: `MediaReference` -> `SerializableObjectWithMetadata` -> `SerializableObject` + +An `ExternalReference` identifies an asset by URL; local files use `file://` +URLs. Use it when a specific file path or URL is available for the asset. + +#### Fields + +- *available_image_bounds* (`Box2d`, optional): Optional spatial bounds of the image content of this media. +- *available_range* (`TimeRange`, optional): The range of media available in this reference, in the media's own time coordinates. When set, its `start_time` should be the media's start timecode or first frame number so consumers can reliably locate the media. +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. +- *target_url* (`String`, default: `""`): URL locating the referenced media. Local files use `file://` URLs. + +### ImageSequenceReference + +- *schema*: `ImageSequenceReference.1` +- *module*: `opentimelineio.schema.ImageSequenceReference` +- *inherits from*: `MediaReference` -> `SerializableObjectWithMetadata` -> `SerializableObject` + +An ImageSequenceReference refers to a numbered series of single-frame image files. Each file can be referred to by a URL generated by the `ImageSequenceReference`. + +Image sequences can have URLs with discontinuous frame numbers, for instance if you've only rendered every other frame in a sequence, your frame numbers may be 1, 3, 5, etc. This is configured using the `frame_step` attribute. In this case, the 0th image in the sequence is frame 1 and the 1st image in the sequence is frame 3. Because of this there are two numbering concepts in the image sequence, the image number and the frame number. + +Frame numbers are the integer numbers used in the frame file name. Image numbers are the 0-index based numbers of the frames available in the reference. Frame numbers can be discontinuous, image numbers will always be zero to the total count of frames minus 1. + +An example for 24fps media with a sample provided each frame numbered 1-1000 with a path `/show/sequence/shot/sample_image_sequence.%04d.exr` might be + +.. code-block:: json + + { + "available_range": { + "start_time": { + "value": 0, + "rate": 24 + }, + "duration": { + "value": 1000, + "rate": 24 + } + }, + "start_frame": 1, + "frame_step": 1, + "rate": 24, + "target_url_base": "file:///show/sequence/shot/", + "name_prefix": "sample_image_sequence.", + "name_suffix": ".exr" + "frame_zero_padding": 4, + } + +The same duration sequence but with only every 2nd frame available in the sequence would be + +.. code-block:: json + + { + "available_range": { + "start_time": { + "value": 0, + "rate": 24 + }, + "duration": { + "value": 1000, + "rate": 24 + } + }, + "start_frame": 1, + "frame_step": 2, + "rate": 24, + "target_url_base": "file:///show/sequence/shot/", + "name_prefix": "sample_image_sequence.", + "name_suffix": ".exr" + "frame_zero_padding": 4, + } + +A list of all the frame URLs in the sequence can be generated, regardless of frame step, with the following list comprehension + +.. code-block:: python + + [ref.target_url_for_image_number(i) for i in range(ref.number_of_images_in_sequence())] + +Negative `start_frame` is also handled. The above example with a `start_frame` of `-1` would yield the first three target urls as: + +- `file:///show/sequence/shot/sample_image_sequence.-0001.exr` +- `file:///show/sequence/shot/sample_image_sequence.0000.exr` +- `file:///show/sequence/shot/sample_image_sequence.0001.exr` + +An `ImageSequenceReference` identifies an asset as a set of sequentially +numbered images. Use it when the asset is a numbered image sequence rather than +a single file. + +#### Fields + +- *available_image_bounds* (`Box2d`, optional): Optional spatial bounds of the image content of this media. +- *available_range* (`TimeRange`, optional): The range of media available in this reference, in the media's own time coordinates. When set, its `start_time` should be the media's start timecode or first frame number so consumers can reliably locate the media. +- *frame_step* (`Integer`, default: `1`): Step between frame numbers in file names. +- *frame_zero_padding* (`Integer`, default: `0`): Number of digits to pad zeros out to in frame numbers. +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *missing_frame_policy* (`ImageSequenceReference.MissingFramePolicy`, default: `"error"`): Directive for how frames in sequence not found during playback or rendering should be handled. +- *name* (`String`, default: `""`): Human-readable name for this object. +- *name_prefix* (`String`, default: `""`): Everything in the file name leading up to the frame number. +- *name_suffix* (`String`, default: `""`): Everything after the frame number in the file name. +- *rate* (`Double`, default: `1.0`): Frame rate if every frame in the sequence were played back. +- *start_frame* (`Integer`, default: `1`): The first frame number used in file names. +- *target_url_base* (`String`, default: `""`): Everything leading up to the file name in the `target_url`. + +### MissingReference + +- *schema*: `MissingReference.1` +- *module*: `opentimelineio.schema.MissingReference` +- *inherits from*: `MediaReference` -> `SerializableObjectWithMetadata` -> `SerializableObject` + +Represents media for which a concrete reference is missing. + +Note that a `MissingReference` may have useful metadata, even if the location of the media is not known. + +A `MissingReference` is used when there is no specific file path for the media. +Any metadata that could help a downstream consumer relink the media (reel name, +tracking IDs, and so on) should be placed in the reference's `metadata` +dictionary. + +#### Fields + +- *available_image_bounds* (`Box2d`, optional): Optional spatial bounds of the image content of this media. +- *available_range* (`TimeRange`, optional): The range of media available in this reference, in the media's own time coordinates. When set, its `start_time` should be the media's start timecode or first frame number so consumers can reliably locate the media. +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. + +### GeneratorReference + +- *schema*: `GeneratorReference.1` +- *module*: `opentimelineio.schema.GeneratorReference` +- *inherits from*: `MediaReference` -> `SerializableObjectWithMetadata` -> `SerializableObject` + +A `GeneratorReference` is used when a clip's media is generated programmatically +-- a solid color, color bars, tone, white noise, and the like. Use the +`parameters` dictionary to describe the generator's configuration (for example, +which color, or the frequency and wave shape of a tone). + +#### Fields + +- *available_image_bounds* (`Box2d`, optional): Optional spatial bounds of the image content of this media. +- *available_range* (`TimeRange`, optional): The range of media available in this reference, in the media's own time coordinates. When set, its `start_time` should be the media's start timecode or first frame number so consumers can reliably locate the media. +- *generator_kind* (`String`, default: `""`): Key identifying the kind of media to generate (for example a solid color, color bars, or tone). The generator's configuration is stored in `parameters`. +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. +- *parameters* (`Map[String, Any]`, default: `{}`) + +## Datatypes + +These value types are used by the fields of the schema objects above. Unlike the +objects above they are not, on their own, `SerializableObject`s. + +### RationalTime + +- *schema*: `RationalTime.1` +- *module*: `opentimelineio.opentime.RationalTime` + +The RationalTime class represents a measure of time of `rt.value/rt.rate` seconds. +It can be rescaled into another `RationalTime`'s rate. + +A `RationalTime` is OTIO's fundamental representation of a moment in time, as a +`value` measured in units of `1/rate` seconds. Representing time as a value over +a rate (rather than as a floating-point number of seconds) lets OTIO express +frame-accurate timing exactly and rescale cleanly between rates. + +#### Fields + +- *rate* (`Double`, default: `1.0`): The rate, in units per second, in which `value` is measured (for example a frame rate). +- *value* (`Double`, default: `0.0`): The number of units of `1/rate` seconds represented by this time. + +### TimeRange + +- *schema*: `TimeRange.1` +- *module*: `opentimelineio.opentime.TimeRange` + +The TimeRange class represents a range in time. It encodes the start time and the duration, +meaning that `end_time_inclusive` (last portion of a sample in the time range) and +`end_time_exclusive` can be computed. + +A `TimeRange` represents a span of time as a `start_time` and a `duration`, both +`RationalTime`s. By convention the range is half-open: it includes `start_time` +and excludes `start_time + duration`. + +#### Fields + +- *duration* (`RationalTime`): The length of the range. The range excludes `start_time + duration`. +- *start_time* (`RationalTime`): The beginning of the range. The range is half-open: it includes `start_time`. + +### TimeTransform + +- *schema*: `TimeTransform.1` +- *module*: `opentimelineio.opentime.TimeTransform` + +1D transform for `RationalTime`. Has offset and scale. + +A `TimeTransform` represents an affine transformation of time -- an `offset` and +a `scale` applied to a `RationalTime`. + +#### Fields + +- *offset* (`RationalTime`): The time added when applying this transform. +- *rate* (`Double`, default: `-1.0`): If greater than zero, the rate the result is rescaled to after applying offset and scale. +- *scale* (`Double`, default: `1.0`): The factor applied to time when applying this transform. + +### Color + +- *schema*: `Color.1` +- *module*: `opentimelineio.core.Color` + +`Color` is a definition of red, green, blue, and alpha double floating point values, allowing conversion between different formats. To be considered interoperable, the sRGB transfer function encoded values, ranging between zero and one, are expected to be accurate to within 1/255 of the intended value. Round-trip conversions may not be guaranteed outside that. This Color class is meant for use in user interface elements, like marker or clip coloring, NOT for image pixel content. + +A `Color` is an RGBA color used for user-interface elements such as marker or +clip coloring. It is not intended to describe image pixel content. + +#### Fields + +- *a* (`Double`, default: `1.0`): Alpha component, nominally in the range 0 to 1 (1 is fully opaque). +- *b* (`Double`, default: `1.0`): Blue component, nominally in the range 0 to 1. +- *g* (`Double`, default: `1.0`): Green component, nominally in the range 0 to 1. +- *name* (`String`, default: `""`): Optional name for this color. +- *r* (`Double`, default: `1.0`): Red component, nominally in the range 0 to 1. + +## JSON Serialization + +`.otio` files are human-readable JSON. Every schema object serializes to a JSON +object that carries an `OTIO_SCHEMA` key naming its schema and version (for +example, `"OTIO_SCHEMA": "Clip.2"`), alongside the fields documented above. +Container objects store their children inline, so a serialized `Timeline` is a +single JSON tree rooted at one object. + +Because schema are versioned and automatically migrated on read, a file written +by one version of OTIO can be read by a newer version without special handling. +There are currently no mechanisms for downgrading the schema versions used +within an OTIO file, so keeping the OTIO implementation in your software +up-to-date maximizes read compatibility with files produced by other +applications. diff --git a/docs/tutorials/otio-serialized-schema-only-fields.md b/docs/tutorials/otio-serialized-schema-only-fields.md index 72ba593ce..71017da0e 100644 --- a/docs/tutorials/otio-serialized-schema-only-fields.md +++ b/docs/tutorials/otio-serialized-schema-only-fields.md @@ -27,60 +27,60 @@ changes. If it needs to be updated and this file regenerated, run: parameters: - *filepath* - *name* -- *suffixes* +- *suffixes* (`Array`) ## Module: opentimelineio.core ### Color.1 parameters: -- *a* -- *b* -- *g* -- *name* -- *r* +- *a* (`Double`) +- *b* (`Double`) +- *g* (`Double`) +- *name* (`String`) +- *r* (`Double`) ### Composable.1 parameters: -- *metadata* -- *name* +- *metadata* (`Map[String, Any]`) +- *name* (`String`) ### Composition.1 parameters: -- *color* -- *effects* -- *enabled* -- *markers* -- *metadata* -- *name* -- *source_range* +- *color* (`Color`, optional) +- *effects* (`Array[Effect]`) +- *enabled* (`Boolean`) +- *markers* (`Array[Marker]`) +- *metadata* (`Map[String, Any]`) +- *name* (`String`) +- *source_range* (`TimeRange`, optional) ### Item.1 parameters: -- *color* -- *effects* -- *enabled* -- *markers* -- *metadata* -- *name* -- *source_range* +- *color* (`Color`, optional) +- *effects* (`Array[Effect]`) +- *enabled* (`Boolean`) +- *markers* (`Array[Marker]`) +- *metadata* (`Map[String, Any]`) +- *name* (`String`) +- *source_range* (`TimeRange`, optional) ### MediaReference.1 parameters: -- *available_image_bounds* -- *available_range* -- *metadata* -- *name* +- *available_image_bounds* (`Box2d`, optional) +- *available_range* (`TimeRange`, optional) +- *metadata* (`Map[String, Any]`) +- *name* (`String`) ### SerializableObjectWithMetadata.1 parameters: -- *metadata* -- *name* +- *metadata* (`Map[String, Any]`) +- *name* (`String`) ## Module: opentimelineio.hooks @@ -103,33 +103,33 @@ parameters: ### RationalTime.1 parameters: -- *rate* -- *value* +- *rate* (`Double`) +- *value* (`Double`) ### TimeRange.1 parameters: -- *duration* -- *start_time* +- *duration* (`RationalTime`) +- *start_time* (`RationalTime`) ### TimeTransform.1 parameters: -- *offset* -- *rate* -- *scale* +- *offset* (`RationalTime`) +- *rate* (`Double`) +- *scale* (`Double`) ## Module: opentimelineio.plugins ### PluginManifest.1 parameters: -- *adapters* -- *hook_scripts* -- *hooks* -- *media_linkers* -- *schemadefs* -- *version_manifests* +- *adapters* (`Array`) +- *hook_scripts* (`Array`) +- *hooks* (`Map`) +- *media_linkers* (`Array`) +- *schemadefs* (`Array`) +- *version_manifests* (`Map`) ### SerializableObject.1 @@ -142,159 +142,159 @@ parameters: ### Clip.2 parameters: -- *active_media_reference_key* -- *color* -- *effects* -- *enabled* -- *markers* -- *media_references* -- *metadata* -- *name* -- *source_range* +- *active_media_reference_key* (`String`) +- *color* (`Color`, optional) +- *effects* (`Array[Effect]`) +- *enabled* (`Boolean`) +- *markers* (`Array[Marker]`) +- *media_references* (`Map[String, MediaReference]`) +- *metadata* (`Map[String, Any]`) +- *name* (`String`) +- *source_range* (`TimeRange`, optional) ### Effect.1 parameters: -- *effect_name* -- *enabled* -- *metadata* -- *name* +- *effect_name* (`String`) +- *enabled* (`Boolean`) +- *metadata* (`Map[String, Any]`) +- *name* (`String`) ### ExternalReference.1 parameters: -- *available_image_bounds* -- *available_range* -- *metadata* -- *name* -- *target_url* +- *available_image_bounds* (`Box2d`, optional) +- *available_range* (`TimeRange`, optional) +- *metadata* (`Map[String, Any]`) +- *name* (`String`) +- *target_url* (`String`) ### FreezeFrame.1 parameters: -- *effect_name* -- *enabled* -- *metadata* -- *name* -- *time_scalar* +- *effect_name* (`String`) +- *enabled* (`Boolean`) +- *metadata* (`Map[String, Any]`) +- *name* (`String`) +- *time_scalar* (`Double`) ### Gap.1 parameters: -- *color* -- *effects* -- *enabled* -- *markers* -- *metadata* -- *name* -- *source_range* +- *color* (`Color`, optional) +- *effects* (`Array[Effect]`) +- *enabled* (`Boolean`) +- *markers* (`Array[Marker]`) +- *metadata* (`Map[String, Any]`) +- *name* (`String`) +- *source_range* (`TimeRange`, optional) ### GeneratorReference.1 parameters: -- *available_image_bounds* -- *available_range* -- *generator_kind* -- *metadata* -- *name* -- *parameters* +- *available_image_bounds* (`Box2d`, optional) +- *available_range* (`TimeRange`, optional) +- *generator_kind* (`String`) +- *metadata* (`Map[String, Any]`) +- *name* (`String`) +- *parameters* (`Map[String, Any]`) ### ImageSequenceReference.1 parameters: -- *available_image_bounds* -- *available_range* -- *frame_step* -- *frame_zero_padding* -- *metadata* -- *missing_frame_policy* -- *name* -- *name_prefix* -- *name_suffix* -- *rate* -- *start_frame* -- *target_url_base* +- *available_image_bounds* (`Box2d`, optional) +- *available_range* (`TimeRange`, optional) +- *frame_step* (`Integer`) +- *frame_zero_padding* (`Integer`) +- *metadata* (`Map[String, Any]`) +- *missing_frame_policy* (`ImageSequenceReference.MissingFramePolicy`) +- *name* (`String`) +- *name_prefix* (`String`) +- *name_suffix* (`String`) +- *rate* (`Double`) +- *start_frame* (`Integer`) +- *target_url_base* (`String`) ### LinearTimeWarp.1 parameters: -- *effect_name* -- *enabled* -- *metadata* -- *name* -- *time_scalar* +- *effect_name* (`String`) +- *enabled* (`Boolean`) +- *metadata* (`Map[String, Any]`) +- *name* (`String`) +- *time_scalar* (`Double`) ### Marker.2 parameters: -- *color* -- *comment* -- *marked_range* -- *metadata* -- *name* +- *color* (`String`) +- *comment* (`String`) +- *marked_range* (`TimeRange`) +- *metadata* (`Map[String, Any]`) +- *name* (`String`) ### MissingReference.1 parameters: -- *available_image_bounds* -- *available_range* -- *metadata* -- *name* +- *available_image_bounds* (`Box2d`, optional) +- *available_range* (`TimeRange`, optional) +- *metadata* (`Map[String, Any]`) +- *name* (`String`) ### SerializableCollection.1 parameters: -- *metadata* -- *name* +- *metadata* (`Map[String, Any]`) +- *name* (`String`) ### Stack.1 parameters: -- *color* -- *effects* -- *enabled* -- *markers* -- *metadata* -- *name* -- *source_range* +- *color* (`Color`, optional) +- *effects* (`Array[Effect]`) +- *enabled* (`Boolean`) +- *markers* (`Array[Marker]`) +- *metadata* (`Map[String, Any]`) +- *name* (`String`) +- *source_range* (`TimeRange`, optional) ### TimeEffect.1 parameters: -- *effect_name* -- *enabled* -- *metadata* -- *name* +- *effect_name* (`String`) +- *enabled* (`Boolean`) +- *metadata* (`Map[String, Any]`) +- *name* (`String`) ### Timeline.1 parameters: -- *global_start_time* -- *metadata* -- *name* -- *tracks* +- *global_start_time* (`RationalTime`, optional) +- *metadata* (`Map[String, Any]`) +- *name* (`String`) +- *tracks* (`Stack`) ### Track.1 parameters: -- *color* -- *effects* -- *enabled* -- *kind* -- *markers* -- *metadata* -- *name* -- *source_range* +- *color* (`Color`, optional) +- *effects* (`Array[Effect]`) +- *enabled* (`Boolean`) +- *kind* (`String`) +- *markers* (`Array[Marker]`) +- *metadata* (`Map[String, Any]`) +- *name* (`String`) +- *source_range* (`TimeRange`, optional) ### Transition.1 parameters: -- *enabled* -- *in_offset* -- *metadata* -- *name* -- *out_offset* -- *transition_type* +- *enabled* (`Boolean`) +- *in_offset* (`RationalTime`) +- *metadata* (`Map[String, Any]`) +- *name* (`String`) +- *out_offset* (`RationalTime`) +- *transition_type* (`String`) ### SchemaDef.1 diff --git a/docs/tutorials/otio-serialized-schema.md b/docs/tutorials/otio-serialized-schema.md index 4fdb4e600..eccc78e5f 100644 --- a/docs/tutorials/otio-serialized-schema.md +++ b/docs/tutorials/otio-serialized-schema.md @@ -24,6 +24,8 @@ changes. If it needs to be updated and this file regenerated, run: *full module path*: `opentimelineio.adapters.Adapter` +*inherits from*: `PythonPlugin` -> `SerializableObject` + *documentation*: ``` @@ -51,7 +53,7 @@ adapter.html. # noqa parameters: - *filepath*: Absolute path or relative path to adapter module from location of json. - *name*: Adapter name. -- *suffixes*: File suffixes associated with this adapter. +- *suffixes* (`Array`, default: `[]`): File suffixes associated with this adapter. ## Module: opentimelineio.core @@ -70,16 +72,18 @@ intended value. Round-trip conversions may not be guaranteed outside that. This ``` parameters: -- *a*: -- *b*: -- *g*: -- *name*: -- *r*: +- *a* (`Double`, default: `1.0`): Alpha component, nominally in the range 0 to 1 (1 is fully opaque). +- *b* (`Double`, default: `1.0`): Blue component, nominally in the range 0 to 1. +- *g* (`Double`, default: `1.0`): Green component, nominally in the range 0 to 1. +- *name* (`String`, default: `""`): Optional name for this color. +- *r* (`Double`, default: `1.0`): Red component, nominally in the range 0 to 1. ### Composable.1 *full module path*: `opentimelineio.core.Composable` +*inherits from*: `SerializableObjectWithMetadata` -> `SerializableObject` + *documentation*: ``` @@ -88,13 +92,15 @@ An object that can be composed within a :class:`~Composition` (such as :class:`~ ``` parameters: -- *metadata*: -- *name*: +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. ### Composition.1 *full module path*: `opentimelineio.core.Composition` +*inherits from*: `Item` -> `Composable` -> `SerializableObjectWithMetadata` -> `SerializableObject` + *documentation*: ``` @@ -104,18 +110,20 @@ Should be subclassed (for example by :class:`.Track` and :class:`.Stack`), not u ``` parameters: -- *color*: -- *effects*: -- *enabled*: If true, an Item contributes to compositions. For example, when an audio/video clip is ``enabled=false`` the clip is muted/hidden. -- *markers*: -- *metadata*: -- *name*: -- *source_range*: +- *color* (`Color`, optional): Optional color used to display this item in a user interface. +- *effects* (`Array[Effect]`, default: `[]`): Effects applied to this item's media, applied in the order they appear in the list. +- *enabled* (`Boolean`, default: `true`): If true, an Item contributes to compositions. For example, when an audio/video clip is ``enabled=false`` the clip is muted/hidden. +- *markers* (`Array[Marker]`, default: `[]`): Markers attached to this item, positioned in the item's local time coordinates. +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. +- *source_range* (`TimeRange`, optional): The range of the item to present, expressed in the item's own time coordinate space. This determines the item's duration. When null, the item's full ``available_range`` is used. ### Item.1 *full module path*: `opentimelineio.core.Item` +*inherits from*: `Composable` -> `SerializableObjectWithMetadata` -> `SerializableObject` + *documentation*: ``` @@ -123,18 +131,20 @@ None ``` parameters: -- *color*: -- *effects*: -- *enabled*: If true, an Item contributes to compositions. For example, when an audio/video clip is ``enabled=false`` the clip is muted/hidden. -- *markers*: -- *metadata*: -- *name*: -- *source_range*: +- *color* (`Color`, optional): Optional color used to display this item in a user interface. +- *effects* (`Array[Effect]`, default: `[]`): Effects applied to this item's media, applied in the order they appear in the list. +- *enabled* (`Boolean`, default: `true`): If true, an Item contributes to compositions. For example, when an audio/video clip is ``enabled=false`` the clip is muted/hidden. +- *markers* (`Array[Marker]`, default: `[]`): Markers attached to this item, positioned in the item's local time coordinates. +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. +- *source_range* (`TimeRange`, optional): The range of the item to present, expressed in the item's own time coordinate space. This determines the item's duration. When null, the item's full ``available_range`` is used. ### MediaReference.1 *full module path*: `opentimelineio.core.MediaReference` +*inherits from*: `SerializableObjectWithMetadata` -> `SerializableObject` + *documentation*: ``` @@ -142,15 +152,17 @@ None ``` parameters: -- *available_image_bounds*: -- *available_range*: -- *metadata*: -- *name*: +- *available_image_bounds* (`Box2d`, optional): Optional spatial bounds of the image content of this media. +- *available_range* (`TimeRange`, optional): The range of media available in this reference, in the media's own time coordinates. When set, its ``start_time`` should be the media's start timecode or first frame number so consumers can reliably locate the media. +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. ### SerializableObjectWithMetadata.1 *full module path*: `opentimelineio.core.SerializableObjectWithMetadata` +*inherits from*: `SerializableObject` + *documentation*: ``` @@ -158,8 +170,8 @@ None ``` parameters: -- *metadata*: -- *name*: +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. ## Module: opentimelineio.hooks @@ -167,6 +179,8 @@ parameters: *full module path*: `opentimelineio.hooks.HookScript` +*inherits from*: `PythonPlugin` -> `SerializableObject` + *documentation*: ``` @@ -183,6 +197,8 @@ parameters: *full module path*: `opentimelineio.media_linker.MediaLinker` +*inherits from*: `PythonPlugin` -> `SerializableObject` + *documentation*: ``` @@ -207,8 +223,8 @@ It can be rescaled into another :class:`~RationalTime`'s rate. ``` parameters: -- *rate*: -- *value*: +- *rate* (`Double`, default: `1.0`): The rate, in units per second, in which ``value`` is measured (for example a frame rate). +- *value* (`Double`, default: `0.0`): The number of units of ``1/rate`` seconds represented by this time. ### TimeRange.1 @@ -223,8 +239,8 @@ meaning that :meth:`end_time_inclusive` (last portion of a sample in the time ra ``` parameters: -- *duration*: -- *start_time*: +- *duration* (`RationalTime`): The length of the range. The range excludes ``start_time + duration``. +- *start_time* (`RationalTime`): The beginning of the range. The range is half-open: it includes ``start_time``. ### TimeTransform.1 @@ -237,9 +253,9 @@ parameters: ``` parameters: -- *offset*: -- *rate*: -- *scale*: +- *offset* (`RationalTime`): The time added when applying this transform. +- *rate* (`Double`, default: `-1.0`): If greater than zero, the rate the result is rescaled to after applying offset and scale. +- *scale* (`Double`, default: `1.0`): The factor applied to time when applying this transform. ## Module: opentimelineio.plugins @@ -247,6 +263,8 @@ parameters: *full module path*: `opentimelineio.plugins.Manifest` +*inherits from*: `SerializableObject` + *documentation*: ``` @@ -262,17 +280,19 @@ For more information, consult the documentation. ``` parameters: -- *adapters*: Adapters this manifest describes. -- *hook_scripts*: Scripts that can be attached to hooks. -- *hooks*: Hooks that hooks scripts can be attached to. -- *media_linkers*: Media Linkers this manifest describes. -- *schemadefs*: Schemadefs this manifest describes. -- *version_manifests*: Sets of versions to downgrade schemas to. +- *adapters* (`Array`, default: `[]`): Adapters this manifest describes. +- *hook_scripts* (`Array`, default: `[]`): Scripts that can be attached to hooks. +- *hooks* (`Map`, default: `{}`): Hooks that hooks scripts can be attached to. +- *media_linkers* (`Array`, default: `[]`): Media Linkers this manifest describes. +- *schemadefs* (`Array`, default: `[]`): Schemadefs this manifest describes. +- *version_manifests* (`Map`, default: `{}`): Sets of versions to downgrade schemas to. ### SerializableObject.1 *full module path*: `opentimelineio.plugins.PythonPlugin` +*inherits from*: `SerializableObject` + *documentation*: ``` @@ -290,6 +310,8 @@ parameters: *full module path*: `opentimelineio.schema.Clip` +*inherits from*: `Item` -> `Composable` -> `SerializableObjectWithMetadata` -> `SerializableObject` + *documentation*: ``` @@ -299,20 +321,22 @@ Contains a :class:`.MediaReference` and a trim on that media reference. ``` parameters: -- *active_media_reference_key*: -- *color*: -- *effects*: -- *enabled*: If true, an Item contributes to compositions. For example, when an audio/video clip is ``enabled=false`` the clip is muted/hidden. -- *markers*: -- *media_references*: -- *metadata*: -- *name*: -- *source_range*: +- *active_media_reference_key* (`String`, default: `"DEFAULT_MEDIA"`): Key, in ``media_references``, of the media reference currently active for this clip. +- *color* (`Color`, optional): Optional color used to display this clip in a user interface. +- *effects* (`Array[Effect]`, default: `[]`): Effects applied to this item's media, applied in the order they appear in the list. +- *enabled* (`Boolean`, default: `true`): If true, an Item contributes to compositions. For example, when an audio/video clip is ``enabled=false`` the clip is muted/hidden. +- *markers* (`Array[Marker]`, default: `[]`): Markers attached to this item, positioned in the item's local time coordinates. +- *media_references* (`Map[String, MediaReference]`): +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. +- *source_range* (`TimeRange`, optional): The range of the item to present, expressed in the item's own time coordinate space. This determines the item's duration. When null, the item's full ``available_range`` is used. ### Effect.1 *full module path*: `opentimelineio.schema.Effect` +*inherits from*: `SerializableObjectWithMetadata` -> `SerializableObject` + *documentation*: ``` @@ -320,15 +344,17 @@ None ``` parameters: -- *effect_name*: -- *enabled*: If true, the Effect is applied. If false, the Effect is omitted. -- *metadata*: -- *name*: +- *effect_name* (`String`, default: `""`): Key identifying the specific effect applied; configuration of the effect is stored in ``metadata``. +- *enabled* (`Boolean`, default: `true`): If true, the Effect is applied. If false, the Effect is omitted. +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. ### ExternalReference.1 *full module path*: `opentimelineio.schema.ExternalReference` +*inherits from*: `MediaReference` -> `SerializableObjectWithMetadata` -> `SerializableObject` + *documentation*: ``` @@ -336,16 +362,18 @@ None ``` parameters: -- *available_image_bounds*: -- *available_range*: -- *metadata*: -- *name*: -- *target_url*: +- *available_image_bounds* (`Box2d`, optional): Optional spatial bounds of the image content of this media. +- *available_range* (`TimeRange`, optional): The range of media available in this reference, in the media's own time coordinates. When set, its ``start_time`` should be the media's start timecode or first frame number so consumers can reliably locate the media. +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. +- *target_url* (`String`, default: `""`): URL locating the referenced media. Local files use ``file://`` URLs. ### FreezeFrame.1 *full module path*: `opentimelineio.schema.FreezeFrame` +*inherits from*: `LinearTimeWarp` -> `TimeEffect` -> `Effect` -> `SerializableObjectWithMetadata` -> `SerializableObject` + *documentation*: ``` @@ -353,11 +381,11 @@ Hold the first frame of the clip for the duration of the clip. ``` parameters: -- *effect_name*: -- *enabled*: If true, the Effect is applied. If false, the Effect is omitted. -- *metadata*: -- *name*: -- *time_scalar*: Linear time scalar applied to clip. 2.0 means the clip occupies half the time in the parent item, i.e. plays at double speed, +- *effect_name* (`String`, default: `"FreezeFrame"`): Key identifying the specific effect applied; configuration of the effect is stored in ``metadata``. +- *enabled* (`Boolean`, default: `true`): If true, the Effect is applied. If false, the Effect is omitted. +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. +- *time_scalar* (`Double`, default: `0.0`): Linear time scalar applied to clip. 2.0 means the clip occupies half the time in the parent item, i.e. plays at double speed, 0.5 means the clip occupies twice the time in the parent item, i.e. plays at half speed. Note that adjusting the time_scalar of a :class:`~LinearTimeWarp` does not affect the duration of the item this effect is attached to. @@ -367,6 +395,8 @@ Instead it affects the speed of the media displayed within that item. *full module path*: `opentimelineio.schema.Gap` +*inherits from*: `Item` -> `Composable` -> `SerializableObjectWithMetadata` -> `SerializableObject` + *documentation*: ``` @@ -374,18 +404,20 @@ None ``` parameters: -- *color*: -- *effects*: -- *enabled*: If true, an Item contributes to compositions. For example, when an audio/video clip is ``enabled=false`` the clip is muted/hidden. -- *markers*: -- *metadata*: -- *name*: -- *source_range*: +- *color* (`Color`, optional): Optional color used to display this item in a user interface. +- *effects* (`Array[Effect]`, default: `[]`): Effects applied to this item's media, applied in the order they appear in the list. +- *enabled* (`Boolean`, default: `true`): If true, an Item contributes to compositions. For example, when an audio/video clip is ``enabled=false`` the clip is muted/hidden. +- *markers* (`Array[Marker]`, default: `[]`): Markers attached to this item, positioned in the item's local time coordinates. +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. +- *source_range* (`TimeRange`, optional): The range of the item to present, expressed in the item's own time coordinate space. This determines the item's duration. When null, the item's full ``available_range`` is used. ### GeneratorReference.1 *full module path*: `opentimelineio.schema.GeneratorReference` +*inherits from*: `MediaReference` -> `SerializableObjectWithMetadata` -> `SerializableObject` + *documentation*: ``` @@ -393,17 +425,19 @@ None ``` parameters: -- *available_image_bounds*: -- *available_range*: -- *generator_kind*: -- *metadata*: -- *name*: -- *parameters*: +- *available_image_bounds* (`Box2d`, optional): Optional spatial bounds of the image content of this media. +- *available_range* (`TimeRange`, optional): The range of media available in this reference, in the media's own time coordinates. When set, its ``start_time`` should be the media's start timecode or first frame number so consumers can reliably locate the media. +- *generator_kind* (`String`, default: `""`): Key identifying the kind of media to generate (for example a solid color, color bars, or tone). The generator's configuration is stored in ``parameters``. +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. +- *parameters* (`Map[String, Any]`, default: `{}`): ### ImageSequenceReference.1 *full module path*: `opentimelineio.schema.ImageSequenceReference` +*inherits from*: `MediaReference` -> `SerializableObjectWithMetadata` -> `SerializableObject` + *documentation*: ``` @@ -485,23 +519,25 @@ yield the first three target urls as: ``` parameters: -- *available_image_bounds*: -- *available_range*: -- *frame_step*: Step between frame numbers in file names. -- *frame_zero_padding*: Number of digits to pad zeros out to in frame numbers. -- *metadata*: -- *missing_frame_policy*: Directive for how frames in sequence not found during playback or rendering should be handled. -- *name*: -- *name_prefix*: Everything in the file name leading up to the frame number. -- *name_suffix*: Everything after the frame number in the file name. -- *rate*: Frame rate if every frame in the sequence were played back. -- *start_frame*: The first frame number used in file names. -- *target_url_base*: Everything leading up to the file name in the ``target_url``. +- *available_image_bounds* (`Box2d`, optional): Optional spatial bounds of the image content of this media. +- *available_range* (`TimeRange`, optional): The range of media available in this reference, in the media's own time coordinates. When set, its ``start_time`` should be the media's start timecode or first frame number so consumers can reliably locate the media. +- *frame_step* (`Integer`, default: `1`): Step between frame numbers in file names. +- *frame_zero_padding* (`Integer`, default: `0`): Number of digits to pad zeros out to in frame numbers. +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *missing_frame_policy* (`ImageSequenceReference.MissingFramePolicy`, default: `"error"`): Directive for how frames in sequence not found during playback or rendering should be handled. +- *name* (`String`, default: `""`): Human-readable name for this object. +- *name_prefix* (`String`, default: `""`): Everything in the file name leading up to the frame number. +- *name_suffix* (`String`, default: `""`): Everything after the frame number in the file name. +- *rate* (`Double`, default: `1.0`): Frame rate if every frame in the sequence were played back. +- *start_frame* (`Integer`, default: `1`): The first frame number used in file names. +- *target_url_base* (`String`, default: `""`): Everything leading up to the file name in the ``target_url``. ### LinearTimeWarp.1 *full module path*: `opentimelineio.schema.LinearTimeWarp` +*inherits from*: `TimeEffect` -> `Effect` -> `SerializableObjectWithMetadata` -> `SerializableObject` + *documentation*: ``` @@ -509,11 +545,11 @@ A time warp that applies a linear speed up or slow down across the entire clip. ``` parameters: -- *effect_name*: -- *enabled*: If true, the Effect is applied. If false, the Effect is omitted. -- *metadata*: -- *name*: -- *time_scalar*: Linear time scalar applied to clip. 2.0 means the clip occupies half the time in the parent item, i.e. plays at double speed, +- *effect_name* (`String`, default: `"LinearTimeWarp"`): Key identifying the specific effect applied; configuration of the effect is stored in ``metadata``. +- *enabled* (`Boolean`, default: `true`): If true, the Effect is applied. If false, the Effect is omitted. +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. +- *time_scalar* (`Double`, default: `1.0`): Linear time scalar applied to clip. 2.0 means the clip occupies half the time in the parent item, i.e. plays at double speed, 0.5 means the clip occupies twice the time in the parent item, i.e. plays at half speed. Note that adjusting the time_scalar of a :class:`~LinearTimeWarp` does not affect the duration of the item this effect is attached to. @@ -523,6 +559,8 @@ Instead it affects the speed of the media displayed within that item. *full module path*: `opentimelineio.schema.Marker` +*inherits from*: `SerializableObjectWithMetadata` -> `SerializableObject` + *documentation*: ``` @@ -534,16 +572,18 @@ system. ``` parameters: -- *color*: Color string for this marker (for example: 'RED'), based on the :class:`~Color` enum. -- *comment*: Optional comment for this marker. -- *marked_range*: Range this marker applies to, relative to the :class:`.Item` this marker is attached to (e.g. the :class:`.Clip` or :class:`.Track` that owns this marker). -- *metadata*: -- *name*: +- *color* (`String`, default: `"RED"`): Color string for this marker (for example: 'RED'), based on the :class:`~Color` enum. +- *comment* (`String`, default: `""`): Optional comment for this marker. +- *marked_range* (`TimeRange`): Range this marker applies to, relative to the :class:`.Item` this marker is attached to (e.g. the :class:`.Clip` or :class:`.Track` that owns this marker). +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. ### MissingReference.1 *full module path*: `opentimelineio.schema.MissingReference` +*inherits from*: `MediaReference` -> `SerializableObjectWithMetadata` -> `SerializableObject` + *documentation*: ``` @@ -554,15 +594,17 @@ is not known. ``` parameters: -- *available_image_bounds*: -- *available_range*: -- *metadata*: -- *name*: +- *available_image_bounds* (`Box2d`, optional): Optional spatial bounds of the image content of this media. +- *available_range* (`TimeRange`, optional): The range of media available in this reference, in the media's own time coordinates. When set, its ``start_time`` should be the media's start timecode or first frame number so consumers can reliably locate the media. +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. ### SerializableCollection.1 *full module path*: `opentimelineio.schema.SerializableCollection` +*inherits from*: `SerializableObjectWithMetadata` -> `SerializableObject` + *documentation*: ``` @@ -579,13 +621,15 @@ references to a single file. ``` parameters: -- *metadata*: -- *name*: +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. ### Stack.1 *full module path*: `opentimelineio.schema.Stack` +*inherits from*: `Composition` -> `Item` -> `Composable` -> `SerializableObjectWithMetadata` -> `SerializableObject` + *documentation*: ``` @@ -593,18 +637,20 @@ None ``` parameters: -- *color*: -- *effects*: -- *enabled*: If true, an Item contributes to compositions. For example, when an audio/video clip is ``enabled=false`` the clip is muted/hidden. -- *markers*: -- *metadata*: -- *name*: -- *source_range*: +- *color* (`Color`, optional): Optional color used to display this item in a user interface. +- *effects* (`Array[Effect]`, default: `[]`): Effects applied to this item's media, applied in the order they appear in the list. +- *enabled* (`Boolean`, default: `true`): If true, an Item contributes to compositions. For example, when an audio/video clip is ``enabled=false`` the clip is muted/hidden. +- *markers* (`Array[Marker]`, default: `[]`): Markers attached to this item, positioned in the item's local time coordinates. +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. +- *source_range* (`TimeRange`, optional): The range of the item to present, expressed in the item's own time coordinate space. This determines the item's duration. When null, the item's full ``available_range`` is used. ### TimeEffect.1 *full module path*: `opentimelineio.schema.TimeEffect` +*inherits from*: `Effect` -> `SerializableObjectWithMetadata` -> `SerializableObject` + *documentation*: ``` @@ -612,15 +658,17 @@ Base class for all effects that alter the timing of an item. ``` parameters: -- *effect_name*: -- *enabled*: If true, the Effect is applied. If false, the Effect is omitted. -- *metadata*: -- *name*: +- *effect_name* (`String`, default: `""`): Key identifying the specific effect applied; configuration of the effect is stored in ``metadata``. +- *enabled* (`Boolean`, default: `true`): If true, the Effect is applied. If false, the Effect is omitted. +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. ### Timeline.1 *full module path*: `opentimelineio.schema.Timeline` +*inherits from*: `SerializableObjectWithMetadata` -> `SerializableObject` + *documentation*: ``` @@ -628,15 +676,17 @@ None ``` parameters: -- *global_start_time*: -- *metadata*: -- *name*: -- *tracks*: +- *global_start_time* (`RationalTime`, optional): Global offset for the start of the timeline, used to express a sequence's start timecode (for example ``01:00:00:00``). +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. +- *tracks* (`Stack`): The :class:`~Stack` holding the timeline's tracks (its audio, video, and other :class:`~Track`\s). ### Track.1 *full module path*: `opentimelineio.schema.Track` +*inherits from*: `Composition` -> `Item` -> `Composable` -> `SerializableObjectWithMetadata` -> `SerializableObject` + *documentation*: ``` @@ -644,19 +694,21 @@ None ``` parameters: -- *color*: -- *effects*: -- *enabled*: If true, an Item contributes to compositions. For example, when an audio/video clip is ``enabled=false`` the clip is muted/hidden. -- *kind*: -- *markers*: -- *metadata*: -- *name*: -- *source_range*: +- *color* (`Color`, optional): Optional color used to display this track in a user interface. +- *effects* (`Array[Effect]`, default: `[]`): Effects applied to this item's media, applied in the order they appear in the list. +- *enabled* (`Boolean`, default: `true`): If true, an Item contributes to compositions. For example, when an audio/video clip is ``enabled=false`` the clip is muted/hidden. +- *kind* (`String`, default: `"Video"`): The kind of media this track composes (for example the ``Audio`` or ``Video`` constants). A free-form string; applications are expected to ignore tracks of a kind they do not understand. +- *markers* (`Array[Marker]`, default: `[]`): Markers attached to this item, positioned in the item's local time coordinates. +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. +- *source_range* (`TimeRange`, optional): The range of the item to present, expressed in the item's own time coordinate space. This determines the item's duration. When null, the item's full ``available_range`` is used. ### Transition.1 *full module path*: `opentimelineio.schema.Transition` +*inherits from*: `Composable` -> `SerializableObjectWithMetadata` -> `SerializableObject` + *documentation*: ``` @@ -665,17 +717,19 @@ dissolve or wipe. ``` parameters: -- *enabled*: If true, a Transition contributes to compositions. For example, when a transition is ``enabled=false`` the transition is ignored and the adjacent clips are cut together with no transition. -- *in_offset*: Amount of the previous clip this transition overlaps, exclusive. -- *metadata*: -- *name*: -- *out_offset*: Amount of the next clip this transition overlaps, exclusive. -- *transition_type*: Kind of transition, as defined by the :class:`Type` enum. +- *enabled* (`Boolean`, default: `true`): If true, a Transition contributes to compositions. For example, when a transition is ``enabled=false`` the transition is ignored and the adjacent clips are cut together with no transition. +- *in_offset* (`RationalTime`): Amount of the previous clip this transition overlaps, exclusive. +- *metadata* (`Map[String, Any]`, default: `{}`): Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own. +- *name* (`String`, default: `""`): Human-readable name for this object. +- *out_offset* (`RationalTime`): Amount of the next clip this transition overlaps, exclusive. +- *transition_type* (`String`, default: `""`): Kind of transition, as defined by the :class:`Type` enum. ### SchemaDef.1 *full module path*: `opentimelineio.schema.SchemaDef` +*inherits from*: `PythonPlugin` -> `SerializableObject` + *documentation*: ``` diff --git a/src/py-opentimelineio/opentime-bindings/opentime_rationalTime.cpp b/src/py-opentimelineio/opentime-bindings/opentime_rationalTime.cpp index 448d499e9..07f4bf0f0 100644 --- a/src/py-opentimelineio/opentime-bindings/opentime_rationalTime.cpp +++ b/src/py-opentimelineio/opentime-bindings/opentime_rationalTime.cpp @@ -98,8 +98,10 @@ or if the rate is less than or equal to zero. Returns true if the time is valid. The time is considered valid if the value and rate are not NaN values and the rate is greater than zero. )docstring") - .def_property_readonly("value", &RationalTime::value) - .def_property_readonly("rate", &RationalTime::rate) + .def_property_readonly("value", &RationalTime::value, + "The number of units of ``1/rate`` seconds represented by this time.") + .def_property_readonly("rate", &RationalTime::rate, + "The rate, in units per second, in which ``value`` is measured (for example a frame rate).") .def( "rescaled_to", (RationalTime (RationalTime::*)(double) const) diff --git a/src/py-opentimelineio/opentime-bindings/opentime_timeRange.cpp b/src/py-opentimelineio/opentime-bindings/opentime_timeRange.cpp index 7dc4bd79e..da4c71abd 100644 --- a/src/py-opentimelineio/opentime-bindings/opentime_timeRange.cpp +++ b/src/py-opentimelineio/opentime-bindings/opentime_timeRange.cpp @@ -60,8 +60,10 @@ duration is invalid, or if the duration is less than zero. Returns true if the time range is valid. The time range is considered valid if both the start time and duration are valid, and the duration is greater than or equal to zero. )docstring") - .def_property_readonly("start_time", &TimeRange::start_time) - .def_property_readonly("duration", &TimeRange::duration) + .def_property_readonly("start_time", &TimeRange::start_time, + "The beginning of the range. The range is half-open: it includes ``start_time``.") + .def_property_readonly("duration", &TimeRange::duration, + "The length of the range. The range excludes ``start_time + duration``.") .def("end_time_inclusive", &TimeRange::end_time_inclusive, R"docstring( The time of the last sample containing data in the time range. diff --git a/src/py-opentimelineio/opentime-bindings/opentime_timeTransform.cpp b/src/py-opentimelineio/opentime-bindings/opentime_timeTransform.cpp index ba71b9a3e..cbe114eb7 100644 --- a/src/py-opentimelineio/opentime-bindings/opentime_timeTransform.cpp +++ b/src/py-opentimelineio/opentime-bindings/opentime_timeTransform.cpp @@ -24,9 +24,12 @@ opentime_timeTransform_bindings(py::module m) "offset"_a = RationalTime(), "scale"_a = 1, "rate"_a = -1) - .def_property_readonly("offset", &TimeTransform::offset) - .def_property_readonly("scale", &TimeTransform::scale) - .def_property_readonly("rate", &TimeTransform::rate) + .def_property_readonly("offset", &TimeTransform::offset, + "The time added when applying this transform.") + .def_property_readonly("scale", &TimeTransform::scale, + "The factor applied to time when applying this transform.") + .def_property_readonly("rate", &TimeTransform::rate, + "If greater than zero, the rate the result is rescaled to after applying offset and scale.") .def( "applied_to", (TimeRange (TimeTransform::*)(TimeRange) const) diff --git a/src/py-opentimelineio/opentimelineio-bindings/otio_serializableObjects.cpp b/src/py-opentimelineio/opentimelineio-bindings/otio_serializableObjects.cpp index d2c837f60..8221081d2 100644 --- a/src/py-opentimelineio/opentimelineio-bindings/otio_serializableObjects.cpp +++ b/src/py-opentimelineio/opentimelineio-bindings/otio_serializableObjects.cpp @@ -327,11 +327,13 @@ define_bases1(py::module m) auto ptr = s->metadata().get_or_create_mutation_stamp(); return (AnyDictionaryProxy*) (ptr); }, - py::return_value_policy::take_ownership) + py::return_value_policy::take_ownership, + "Arbitrary, application-defined data attached to this object. By convention, store data under a top-level namespace key unique to your application and preserve metadata you do not own.") .def_property( "name", [](SOWithMetadata* so) { return plain_string(so->name()); }, - &SOWithMetadata::set_name); + &SOWithMetadata::set_name, + "Human-readable name for this object."); } static void @@ -355,11 +357,16 @@ define_bases2(py::module m) "b"_a = 1.0, "a"_a = 1.0, py::arg_v("name"_a = std::string())) - .def_property("r", &Color::r, &Color::set_r) - .def_property("g", &Color::g, &Color::set_g) - .def_property("b", &Color::b, &Color::set_b) - .def_property("a", &Color::a, &Color::set_a) - .def_property("name", &Color::name, &Color::set_name) + .def_property("r", &Color::r, &Color::set_r, + "Red component, nominally in the range 0 to 1.") + .def_property("g", &Color::g, &Color::set_g, + "Green component, nominally in the range 0 to 1.") + .def_property("b", &Color::b, &Color::set_b, + "Blue component, nominally in the range 0 to 1.") + .def_property("a", &Color::a, &Color::set_a, + "Alpha component, nominally in the range 0 to 1 (1 is fully opaque).") + .def_property("name", &Color::name, &Color::set_name, + "Optional name for this color.") .def("to_hex", &Color::to_hex) .def("to_rgba_int_list", &Color::to_rgba_int_list, py::arg("base") = 8) @@ -653,8 +660,13 @@ An object that can be composed within a :class:`~Composition` (such as :class:`~ .def_property( "source_range", &Item::source_range, - &Item::set_source_range) - .def_property("color", &Item::color, &Item::set_color) + &Item::set_source_range, + "The range of the item to present, expressed in the item's own time coordinate space. This determines the item's duration. When null, the item's full ``available_range`` is used.") + .def_property( + "color", + &Item::color, + &Item::set_color, + "Optional color used to display this item in a user interface.") .def( "available_range", [](Item* item) { @@ -667,10 +679,12 @@ An object that can be composed within a :class:`~Composition` (such as :class:`~ }) .def_property_readonly( "markers", - [](Item* item) { return ((MarkerVectorProxy*) &item->markers()); }) + [](Item* item) { return ((MarkerVectorProxy*) &item->markers()); }, + "Markers attached to this item, positioned in the item's local time coordinates.") .def_property_readonly( "effects", - [](Item* item) { return ((EffectVectorProxy*) &item->effects()); }) + [](Item* item) { return ((EffectVectorProxy*) &item->effects()); }, + "Effects applied to this item's media, applied in the order they appear in the list.") .def( "duration", [](Item* item) { return item->duration(ErrorStatusHandler()); }) @@ -869,7 +883,8 @@ Contains a :class:`.MediaReference` and a trim on that media reference. .def_property( "media_reference", &Clip::media_reference, - &Clip::set_media_reference) + &Clip::set_media_reference, + "The active media reference for this clip -- how to locate the media the clip composes.") .def_property( "active_media_reference_key", &Clip::active_media_reference_key, @@ -877,8 +892,13 @@ Contains a :class:`.MediaReference` and a trim on that media reference. clip->set_active_media_reference_key( new_active_key, ErrorStatusHandler()); - }) - .def_property("color", &Clip::color, &Clip::set_color) + }, + "Key, in ``media_references``, of the media reference currently active for this clip.") + .def_property( + "color", + &Clip::color, + &Clip::set_color, + "Optional color used to display this clip in a user interface.") .def("media_references", &Clip::media_references) .def( "set_media_references", @@ -1120,8 +1140,16 @@ Should be subclassed (for example by :class:`.Track` and :class:`.Stack`), not u "kind"_a = std::string(Track::Kind::video), py::arg_v("metadata"_a = py::none()), "color"_a = std::nullopt) - .def_property("kind", &Track::kind, &Track::set_kind) - .def_property("color", &Track::color, &Track::set_color) + .def_property( + "kind", + &Track::kind, + &Track::set_kind, + "The kind of media this track composes (for example the ``Audio`` or ``Video`` constants). A free-form string; applications are expected to ignore tracks of a kind they do not understand.") + .def_property( + "color", + &Track::color, + &Track::set_color, + "Optional color used to display this track in a user interface.") .def( "neighbors_of", [](Track* t, Composable* item, Track::NeighborGapPolicy policy) { @@ -1202,8 +1230,13 @@ Should be subclassed (for example by :class:`.Track` and :class:`.Stack`), not u .def_property( "global_start_time", &Timeline::global_start_time, - &Timeline::set_global_start_time) - .def_property("tracks", &Timeline::tracks, &Timeline::set_tracks) + &Timeline::set_global_start_time, + "Global offset for the start of the timeline, used to express a sequence's start timecode (for example ``01:00:00:00``).") + .def_property( + "tracks", + &Timeline::tracks, + &Timeline::set_tracks, + "The :class:`~Stack` holding the timeline's tracks (its audio, video, and other :class:`~Track`\\s).") .def( "duration", [](Timeline* t) { return t->duration(ErrorStatusHandler()); }) @@ -1265,7 +1298,8 @@ define_effects(py::module m) .def_property( "effect_name", &Effect::effect_name, - &Effect::set_effect_name) + &Effect::set_effect_name, + "Key identifying the specific effect applied; configuration of the effect is stored in ``metadata``.") .def_property( "enabled", &Effect::enabled, @@ -1361,11 +1395,13 @@ define_media_references(py::module m) .def_property( "available_range", &MediaReference::available_range, - &MediaReference::set_available_range) + &MediaReference::set_available_range, + "The range of media available in this reference, in the media's own time coordinates. When set, its ``start_time`` should be the media's start timecode or first frame number so consumers can reliably locate the media.") .def_property( "available_image_bounds", &MediaReference::available_image_bounds, - &MediaReference::set_available_image_bounds) + &MediaReference::set_available_image_bounds, + "Optional spatial bounds of the image content of this media.") .def_property_readonly( "is_missing_reference", &MediaReference::is_missing_reference); @@ -1402,7 +1438,8 @@ define_media_references(py::module m) .def_property( "generator_kind", &GeneratorReference::generator_kind, - &GeneratorReference::set_generator_kind) + &GeneratorReference::set_generator_kind, + "Key identifying the kind of media to generate (for example a solid color, color bars, or tone). The generator's configuration is stored in ``parameters``.") .def_property_readonly( "parameters", [](GeneratorReference* g) { @@ -1466,7 +1503,8 @@ Note that a :class:`~MissingReference` may have useful metadata, even if the loc .def_property( "target_url", &ExternalReference::target_url, - &ExternalReference::set_target_url); + &ExternalReference::set_target_url, + "URL locating the referenced media. Local files use ``file://`` URLs."); auto imagesequencereference_class = py::class_< ImageSequenceReference, diff --git a/src/py-opentimelineio/opentimelineio/console/autogen_core_specification.py b/src/py-opentimelineio/opentimelineio/console/autogen_core_specification.py new file mode 100644 index 000000000..e53e5ab63 --- /dev/null +++ b/src/py-opentimelineio/opentimelineio/console/autogen_core_specification.py @@ -0,0 +1,294 @@ +#!/usr/bin/env python +# +# SPDX-License-Identifier: Apache-2.0 +# Copyright Contributors to the OpenTimelineIO project + + +"""Generate the OpenTimelineIO Core Specification. + +The specification is assembled from two sources: + +1. The *code* -- every serializable schema object, its fields, field types, + default values, inheritance, and the semantic docstrings carried by the + bindings. This half is produced by reusing the model builder from + :mod:`autogen_serialized_datamodel`. + +2. A curated markdown *overlay* -- the human-authored narrative (introduction, + conventions, metadata conventions, root objects, JSON serialization) and the + per-object integrator usage guidance that does not belong in terse API + docstrings. + +The overlay declares the ordering and grouping of the object model via +HTML-comment directives, e.g.:: + + + # OpenTimelineIO Core Specification + ...narrative... + + + ...section intro... + + + ...usage guidance for Timeline... + + + ## JSON Serialization + ... + +Every data-model schema object must be referenced by exactly one ``@object`` +directive and every ``@object`` must name a real schema object; otherwise +generation fails. This keeps the specification honest: adding a new schema to +the code forces a matching entry in the overlay. + +Run with ``make spec`` (dryrun) or ``make spec-update`` (write the baseline). +The generated document is verified by the unit test suite. +""" + +import argparse +import os +import re +import sys + +from opentimelineio.console import autogen_serialized_datamodel as asd + + +# Plugin-infrastructure classes are not part of the editorial data model and +# are intentionally excluded from the specification (the spec, like the +# serialized-schema doc, omits SchemaDef plugins). +SPEC_SKIP_OBJECTS = { + "Adapter", + "HookScript", + "MediaLinker", + "PluginManifest", + "SchemaDef", +} + +# Default locations, relative to the repository root. +DEFAULT_OVERLAY = os.path.join( + "docs", "spec", "core-specification-overlay.md" +) +DEFAULT_OUTPUT = os.path.join( + "docs", "spec", "otio-core-specification.md" +) + +_DIRECTIVE_RE = re.compile(r"^\s*$") + +# RST roles that leak in from C++/python docstrings; rewrite to plain markdown +# inline code so the specification reads cleanly. +_RST_ROLE_RE = re.compile(r":[a-z:]+:`~?\.?([^`]+)`") + +# RST inline literals (``text``) -> markdown inline code (`text`). +_RST_LITERAL_RE = re.compile(r"``([^`]+)``") + + +def _parsed_args(): + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter, + ) + parser.add_argument( + "-i", + "--overlay", + default=DEFAULT_OVERLAY, + help="Path to the curated markdown overlay.", + ) + group = parser.add_mutually_exclusive_group() + group.add_argument( + "-d", + "--dryrun", + action="store_true", + default=False, + help="Print the generated specification instead of writing it.", + ) + group.add_argument( + "-o", + "--output", + type=str, + default=None, + help="Write the generated specification to this path.", + ) + return parser.parse_args() + + +def _clean_docstring(text): + """Rewrite RST inline markup to markdown: roles (``:class:`~Foo```) and + inline literals (````text````) both become `` `text` ``.""" + if not text: + return "" + text = _RST_ROLE_RE.sub(r"`\1`", text) + text = _RST_LITERAL_RE.sub(r"`\1`", text) + return text.strip() + + +def _parse_overlay(text): + """Parse the overlay into an ordered list of ``(directive, arg, body)``. + + Content appearing before the first directive is treated as a file header + (e.g. license, authoring instructions) and is not emitted. + """ + segments = [] + directive, arg, body = "header", None, [] + for line in text.splitlines(): + match = _DIRECTIVE_RE.match(line) + if match: + segments.append((directive, arg, "\n".join(body).strip())) + directive, arg = match.group(1), match.group(2) + body = [] + else: + body.append(line) + segments.append((directive, arg, "\n".join(body).strip())) + return segments + + +def _index_model(model): + """Map each schema object's base name (e.g. ``Clip``) to ``(class, entry, + module path)``.""" + index = {} + for cl, entry in model.items(): + base = entry["OTIO_SCHEMA"].rsplit(".", 1)[0] + modobj = cl.__module__ + if modobj in ("opentimelineio._opentime", "opentimelineio._otio"): + modobj = asd._remap_to_python_modules(cl) + modpath = ".".join(modobj.split(".")[:2]) + "." + cl.__name__ + index[base] = (cl, entry, modpath) + return index + + +def _render_object(name, index, prose): + """Render the reference block for a single schema object. + + Layout: heading, code-derived metadata (schema/module/inheritance), the + semantic definition (from the code docstring), the curated usage guidance + (``prose`` from the overlay), then the field reference. + """ + cl, entry, modpath = index[name] + + lines = ["### {}".format(name), ""] + lines.append("- *schema*: `{}`".format(entry["OTIO_SCHEMA"])) + lines.append("- *module*: `{}`".format(modpath)) + + chain = asd._inheritance_chain(cl) + if chain: + lines.append( + "- *inherits from*: {}".format( + " -> ".join("`{}`".format(c) for c in chain) + ) + ) + lines.append("") + + docstring = _clean_docstring(cl.__doc__) + if docstring: + lines.append(docstring) + lines.append("") + + if prose: + lines.append(prose.strip()) + lines.append("") + + fields = sorted( + (k, v) for k, v in entry.items() + if k not in asd.SKIP_KEYS and isinstance(v, dict) + ) + if fields: + lines.append("#### Fields") + lines.append("") + for key, field in fields: + typeinfo = asd._format_typeinfo(field, include_default=True) + helpstr = _clean_docstring(field["help"]) + lines.append( + "- *{key}*{typeinfo}{sep}{help}".format( + key=key, + typeinfo=typeinfo, + sep=": " if helpstr else "", + help=helpstr, + ) + ) + lines.append("") + + return "\n".join(lines) + + +def generate_specification(overlay_text): + """Assemble the full specification markdown from the overlay + the model.""" + model = asd._generate_model() + index = _index_model(model) + segments = _parse_overlay(overlay_text) + + documented = [ + arg for directive, arg, _ in segments if directive == "object" + ] + + # Validate the overlay against the code, in both directions. + unknown = [name for name in documented if name not in index] + if unknown: + raise ValueError( + "overlay documents unknown schema object(s): " + + ", ".join(sorted(unknown)) + ) + + expected = { + name for name in index + if name not in SPEC_SKIP_OBJECTS + } + missing = sorted(expected - set(documented)) + if missing: + raise ValueError( + "the following schema object(s) have no overlay @object entry " + "(add them to {} or to SPEC_SKIP_OBJECTS): {}".format( + DEFAULT_OVERLAY, ", ".join(missing) + ) + ) + + out = [] + for directive, arg, body in segments: + if directive == "header": + continue # file header / authoring instructions; not emitted + elif directive == "preamble": + if body: + out.append(body) + elif directive == "section": + out.append("## {}".format(arg)) + if body: + out.append(body) + elif directive == "object": + out.append(_render_object(arg, index, body)) + elif directive == "appendix": + if body: + out.append(body) + else: + raise ValueError( + "unknown overlay directive: @{}".format(directive) + ) + + # single trailing newline, blank line between blocks + return "\n\n".join(block.strip() for block in out if block.strip()) + "\n" + + +def generate_and_write_specification(overlay_path=None): + """Read the overlay and return the generated specification text.""" + overlay_path = overlay_path or DEFAULT_OVERLAY + with open(overlay_path) as fi: + return generate_specification(fi.read()) + + +def main(): + args = _parsed_args() + spec = generate_and_write_specification(args.overlay) + + if args.dryrun: + sys.stdout.write(spec) + return + + if not args.output: + sys.stderr.write( + "ERROR: specify --output PATH or --dryrun\n" + ) + sys.exit(1) + + with open(args.output, "w") as fo: + fo.write(spec) + print("wrote specification to {}".format(args.output)) + + +if __name__ == "__main__": + main() diff --git a/src/py-opentimelineio/opentimelineio/console/autogen_serialized_datamodel.py b/src/py-opentimelineio/opentimelineio/console/autogen_serialized_datamodel.py index 5e12b6b36..fceedc62c 100644 --- a/src/py-opentimelineio/opentimelineio/console/autogen_serialized_datamodel.py +++ b/src/py-opentimelineio/opentimelineio/console/autogen_serialized_datamodel.py @@ -9,6 +9,7 @@ import argparse import inspect import json +import re import tempfile import sys import textwrap @@ -66,7 +67,7 @@ ### {classname} *full module path*: `{modpath}` - +{inheritance} *documentation*: ``` @@ -86,11 +87,10 @@ ## Module: {modname} """ -PROP_HEADER = """- *{propkey}*: {prophelp} +PROP_HEADER = """- *{propkey}*{typeinfo}: {prophelp} """ -# @TODO: having type information here would be awesome -PROP_HEADER_NO_HELP = """- *{propkey}* +PROP_HEADER_NO_HELP = """- *{propkey}*{typeinfo} """ # three ways to try and get the property + docstring @@ -100,6 +100,176 @@ lambda cl, k: inspect.getdoc(getattr(cl(), k)) and "" or "", ) +# pybind11 prefixes the C++ module onto every type it reports; strip them so the +# documentation reads in terms of the public python schema. +_TYPE_MODULE_PREFIXES = ( + "opentimelineio._opentime.", + "opentimelineio._otio.", + "_opentime.", + "_otio.", + "opentimelineio.", +) + +# map pybind11/python primitive spellings onto the vocabulary used by the OTIO +# Core Specification. +_PRIMITIVE_REMAP = { + "str": "String", + "float": "Double", + "int": "Integer", + "bool": "Boolean", + "object": None, # the `any`-backed fields report `object`; infer from value +} + + +def _clean_type(type_str): + """Strip the internal C++ module prefixes off a pybind11 type string.""" + for prefix in _TYPE_MODULE_PREFIXES: + type_str = type_str.replace(prefix, "") + return type_str.strip() + + +def _type_from_value(value): + """Infer a spec-style type name from a serialized default value. + + Used as a fallback when the property's signature does not advertise a usable + return type (e.g. the metadata-backed `any` fields, which report `object`). + """ + # bool must be checked before int, since bool is a subclass of int + if isinstance(value, bool): + return "Boolean" + if isinstance(value, int): + return "Integer" + if isinstance(value, float): + return "Double" + if isinstance(value, str): + return "String" + if isinstance(value, list): + return "Array" + if isinstance(value, dict): + if "OTIO_SCHEMA" in value: + return value["OTIO_SCHEMA"].rsplit(".", 1)[0] + return "Map" + return None + + +def _normalize_type(raw): + """Turn a raw pybind11 return-type string into a (type, optional) pair. + + Examples: + ``Optional[...TimeRange]`` -> ("TimeRange", True) + ``...EffectVector`` -> ("Array[Effect]", False) + ``dict[str, ...MediaReference]``-> ("Map[String, MediaReference]", False) + ``AnyDictionary`` -> ("Map[String, Any]", False) + ``float`` -> ("Double", False) + """ + type_str = _clean_type(raw) + + optional = False + opt = re.match(r"Optional\[(.*)\]$", type_str) + if opt: + optional = True + type_str = opt.group(1).strip() + + vec = re.match(r"(.+)Vector$", type_str) + dct = re.match(r"[Dd]ict\[\s*str\s*,\s*(.+)\]$", type_str) + if vec: + inner = vec.group(1) + type_str = "Array[{}]".format(_PRIMITIVE_REMAP.get(inner, inner) or inner) + elif type_str == "AnyDictionary": + type_str = "Map[String, Any]" + elif dct: + inner = dct.group(1).strip() + type_str = "Map[String, {}]".format( + _PRIMITIVE_REMAP.get(inner, inner) or inner + ) + elif type_str in _PRIMITIVE_REMAP: + type_str = _PRIMITIVE_REMAP[type_str] + + return type_str, optional + + +def _signature_return_type(cl, key): + """Return the raw pybind11 return-type annotation for a field, if any. + + pybind11 records the C++ type signature in the docstring of a property's + getter (``fget``) or of a plain method (e.g. ``media_references``). + """ + try: + attr = getattr(cl, key) + except AttributeError: + return None + + doc = None + fget = getattr(attr, "fget", None) + if fget is not None: + doc = inspect.getdoc(fget) + elif callable(attr): + doc = inspect.getdoc(attr) + + if doc and "->" in doc: + return doc.rsplit("->", 1)[-1].strip() + return None + + +def _type_for_property(cl, key, value): + """Resolve the (type, optional) pair for a serialized field. + + Prefers the type advertised by the pybind11 signature, falling back to + inferring from the serialized default value when the signature is missing or + opaque (``object``). + """ + raw = _signature_return_type(cl, key) + if raw is not None: + type_str, optional = _normalize_type(raw) + if type_str: + return type_str, optional + + # fall back to inferring from the serialized default value + return _type_from_value(value), value is None + + +def _inheritance_chain(cl): + """The list of schema base-class names a class derives from, most-derived + first. Empty for types outside the SerializableObject hierarchy (e.g. + RationalTime, TimeRange, Color).""" + return [ + base.__name__ + for base in inspect.getmro(cl)[1:] + if base.__name__ not in ("object", "pybind11_object") + ] + + +def _default_repr(value): + """A compact JSON rendering of a default value, or None when it should be + omitted (null values and large/composite defaults that would add noise).""" + if value is None: + return None + try: + rendered = json.dumps(value) + except (TypeError, ValueError): + return None + if len(rendered) > 40: + return None + return rendered + + +def _format_typeinfo(entry, include_default): + """Render the parenthetical ``(`Type`, optional, default: `x`)`` annotation + for a property, or "" when the type could not be resolved (e.g. plugin + fields with no signature and a null default).""" + if not entry["type"]: + return "" + parts = ["`{}`".format(entry["type"])] + if entry["optional"]: + parts.append("optional") + if include_default: + default = _default_repr(entry["default"]) + if default is not None: + parts.append("default: `{}`".format(default)) + if not parts: + return "" + return " ({})".format(", ".join(parts)) + def _parsed_args(): """ parse commandline arguments with argparse """ @@ -176,11 +346,13 @@ def _generate_model_for_module(mod, classes, modules): if k in SKIP_KEYS: continue + value = field_dict[k] + helpstr = "" for fetcher in PROP_FETCHERS: try: # Serialized fields are almost always properties, but skip # over those that are not - model[cl][k] = fetcher(cl, k) if isinstance( + helpstr = fetcher(cl, k) if isinstance( getattr(cl, k), property) else "" break except AttributeError: @@ -188,6 +360,14 @@ def _generate_model_for_module(mod, classes, modules): else: sys.stderr.write(f"ERROR: could not fetch property: {k}") + type_str, optional = _type_for_property(cl, k, value) + model[cl][k] = { + "help": helpstr or "", + "type": type_str, + "optional": optional, + "default": value, + } + # Stashing the OTIO_SCHEMA back into the dictionary since the # documentation uses this information in its header. model[cl]["OTIO_SCHEMA"] = field_dict["OTIO_SCHEMA"] @@ -313,10 +493,19 @@ def _write_documentation(model): else: new_docstring = cl.__doc__ + chain = _inheritance_chain(cl) + if chain: + inheritance = "\n*inherits from*: {}\n".format( + " -> ".join("`{}`".format(name) for name in chain) + ) + else: + inheritance = "" + md_with_helpstrings.write( CLASS_HEADER_WITH_DOCS.format( classname=label, modpath=modname + "." + cl.__name__, + inheritance=inheritance, docstring=new_docstring ) ) @@ -326,14 +515,21 @@ def _write_documentation(model): ) ) - for key, helpstr in sorted(model[cl].items()): + for key, entry in sorted(model[cl].items()): if key in SKIP_KEYS: continue md_with_helpstrings.write( - PROP_HEADER.format(propkey=key, prophelp=helpstr) + PROP_HEADER.format( + propkey=key, + typeinfo=_format_typeinfo(entry, include_default=True), + prophelp=entry["help"], + ) ) md_only_fields.write( - PROP_HEADER_NO_HELP.format(propkey=key) + PROP_HEADER_NO_HELP.format( + propkey=key, + typeinfo=_format_typeinfo(entry, include_default=False), + ) ) return md_with_helpstrings.getvalue(), md_only_fields.getvalue() diff --git a/tests/test_serialized_schema.py b/tests/test_serialized_schema.py index 7a486f29c..c081a4f1c 100644 --- a/tests/test_serialized_schema.py +++ b/tests/test_serialized_schema.py @@ -9,7 +9,8 @@ from opentimelineio.console import ( autogen_serialized_datamodel as asd, autogen_plugin_documentation as apd, - autogen_version_map as avm + autogen_version_map as avm, + autogen_core_specification as acs ) @@ -41,6 +42,37 @@ def test_serialized_schema(self): ) +@unittest.skipIf( + os.environ.get("OTIO_DISABLE_SERIALIZED_SCHEMA_TEST"), + "Core specification test disabled because " + "$OTIO_DISABLE_SERIALIZED_SCHEMA_TEST is set to something other than ''" +) +class CoreSpecificationTester(unittest.TestCase): + def test_core_specification(self): + """Test that the generated Core Specification matches the checked-in + baseline. It is regenerated from the code (schema, types, docstrings) + and the curated overlay, so it must be updated whenever either changes. + """ + + pt = os.path.dirname(os.path.dirname(__file__)) + fp = os.path.join(pt, "docs", "spec", "otio-core-specification.md") + overlay = os.path.join(pt, "docs", "spec", + "core-specification-overlay.md") + with open(fp) as fi: + baseline_text = fi.read() + + test_text = acs.generate_and_write_specification(overlay) + + self.maxDiff = None + self.longMessage = True + self.assertMultiLineEqual( + baseline_text, + test_text, + "\n The core specification has changed and the generated document " + "in {} needs to be updated. run: `make spec-update`".format(fp) + ) + + @unittest.skipIf( os.environ.get("OTIO_DISABLE_SERIALIZED_SCHEMA_TEST"), "Plugin documentation test disabled because " diff --git a/uv.lock b/uv.lock new file mode 100644 index 000000000..43892d50c --- /dev/null +++ b/uv.lock @@ -0,0 +1,1004 @@ +version = 1 +requires-python = ">=3.7, !=3.9.0" +resolution-markers = [ + "python_full_version >= '3.9'", + "python_full_version >= '3.8.1' and python_full_version < '3.9'", + "python_full_version >= '3.8' and python_full_version < '3.8.1'", + "python_full_version < '3.8'", +] + +[[package]] +name = "build" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.8'", +] +dependencies = [ + { name = "colorama", marker = "python_full_version < '3.8' and os_name == 'nt'" }, + { name = "importlib-metadata", version = "6.7.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.8'" }, + { name = "packaging", version = "24.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.8'" }, + { name = "pyproject-hooks", marker = "python_full_version < '3.8'" }, + { name = "tomli", version = "2.0.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.8'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/55/f7/7bd626bc41b59152248087c1b56dd9f5d09c3f817b96075dc3cbda539dc7/build-1.1.1.tar.gz", hash = "sha256:8eea65bb45b1aac2e734ba2cc8dad3a6d97d97901a395bd0ed3e7b46953d2a31", size = 44711 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4f/81/4849059526d02fcc9708e19346dd740e8b9edd2f0675ea7c38302d6729df/build-1.1.1-py3-none-any.whl", hash = "sha256:8ed0851ee76e6e38adce47e4bee3b51c771d86c64cf578d0c2245567ee200e73", size = 19719 }, +] + +[[package]] +name = "build" +version = "1.2.2.post1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.9'", + "python_full_version >= '3.8.1' and python_full_version < '3.9'", + "python_full_version >= '3.8' and python_full_version < '3.8.1'", +] +dependencies = [ + { name = "colorama", marker = "python_full_version >= '3.8' and os_name == 'nt'" }, + { name = "importlib-metadata", version = "8.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.8.*'" }, + { name = "importlib-metadata", version = "8.6.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9' and python_full_version < '3.10.2'" }, + { name = "packaging", version = "25.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.8'" }, + { name = "pyproject-hooks", marker = "python_full_version >= '3.8'" }, + { name = "tomli", version = "2.2.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.8' and python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7d/46/aeab111f8e06793e4f0e421fcad593d547fb8313b50990f31681ee2fb1ad/build-1.2.2.post1.tar.gz", hash = "sha256:b36993e92ca9375a219c99e606a122ff365a760a2d4bba0caa09bd5278b608b7", size = 46701 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/c2/80633736cd183ee4a62107413def345f7e6e3c01563dbca1417363cf957e/build-1.2.2.post1-py3-none-any.whl", hash = "sha256:1d61c0887fa860c01971625baae8bdd338e517b836a2f70dd1f7aa3a6b2fc5b5", size = 22950 }, +] + +[[package]] +name = "check-manifest" +version = "0.50" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "build", version = "1.1.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.8'" }, + { name = "build", version = "1.2.2.post1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.8'" }, + { name = "setuptools", version = "68.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.8'" }, + { name = "setuptools", version = "75.3.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.8.*'" }, + { name = "setuptools", version = "79.0.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "tomli", version = "2.0.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.8'" }, + { name = "tomli", version = "2.2.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.8' and python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a8/ab/7607952f2c8d34c4124309dd3ea17c256fd3420a4ade01322daf9402b0b5/check_manifest-0.50.tar.gz", hash = "sha256:d300f9f292986aa1a30424af44eb45c5644e0a810e392e62d553b24bb3393494", size = 44827 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/71/55/92207fa9b92ac2ade5593b1280f804f2590a680b7fe96775eb26074eec6b/check_manifest-0.50-py3-none-any.whl", hash = "sha256:6ab3e3aa72a008da3314b432f4c768c9647b4d6d8032f9e1a4672a572118e48c", size = 20385 }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, +] + +[[package]] +name = "coverage" +version = "7.2.7" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.8'", +] +sdist = { url = "https://files.pythonhosted.org/packages/45/8b/421f30467e69ac0e414214856798d4bc32da1336df745e49e49ae5c1e2a8/coverage-7.2.7.tar.gz", hash = "sha256:924d94291ca674905fe9481f12294eb11f2d3d3fd1adb20314ba89e94f44ed59", size = 762575 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/01/24/be01e62a7bce89bcffe04729c540382caa5a06bee45ae42136c93e2499f5/coverage-7.2.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d39b5b4f2a66ccae8b7263ac3c8170994b65266797fb96cbbfd3fb5b23921db8", size = 200724 }, + { url = "https://files.pythonhosted.org/packages/3d/80/7060a445e1d2c9744b683dc935248613355657809d6c6b2716cdf4ca4766/coverage-7.2.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6d040ef7c9859bb11dfeb056ff5b3872436e3b5e401817d87a31e1750b9ae2fb", size = 201024 }, + { url = "https://files.pythonhosted.org/packages/b8/9d/926fce7e03dbfc653104c2d981c0fa71f0572a9ebd344d24c573bd6f7c4f/coverage-7.2.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba90a9563ba44a72fda2e85302c3abc71c5589cea608ca16c22b9804262aaeb6", size = 229528 }, + { url = "https://files.pythonhosted.org/packages/d1/3a/67f5d18f911abf96857f6f7e4df37ca840e38179e2cc9ab6c0b9c3380f19/coverage-7.2.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7d9405291c6928619403db1d10bd07888888ec1abcbd9748fdaa971d7d661b2", size = 227842 }, + { url = "https://files.pythonhosted.org/packages/b4/bd/1b2331e3a04f4cc9b7b332b1dd0f3a1261dfc4114f8479bebfcc2afee9e8/coverage-7.2.7-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31563e97dae5598556600466ad9beea39fb04e0229e61c12eaa206e0aa202063", size = 228717 }, + { url = "https://files.pythonhosted.org/packages/2b/86/3dbf9be43f8bf6a5ca28790a713e18902b2d884bc5fa9512823a81dff601/coverage-7.2.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ebba1cd308ef115925421d3e6a586e655ca5a77b5bf41e02eb0e4562a111f2d1", size = 234632 }, + { url = "https://files.pythonhosted.org/packages/91/e8/469ed808a782b9e8305a08bad8c6fa5f8e73e093bda6546c5aec68275bff/coverage-7.2.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cb017fd1b2603ef59e374ba2063f593abe0fc45f2ad9abdde5b4d83bd922a353", size = 232875 }, + { url = "https://files.pythonhosted.org/packages/29/8f/4fad1c2ba98104425009efd7eaa19af9a7c797e92d40cd2ec026fa1f58cb/coverage-7.2.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62a5c7dad11015c66fbb9d881bc4caa5b12f16292f857842d9d1871595f4495", size = 234094 }, + { url = "https://files.pythonhosted.org/packages/94/4e/d4e46a214ae857be3d7dc5de248ba43765f60daeb1ab077cb6c1536c7fba/coverage-7.2.7-cp310-cp310-win32.whl", hash = "sha256:ee57190f24fba796e36bb6d3aa8a8783c643d8fa9760c89f7a98ab5455fbf818", size = 203184 }, + { url = "https://files.pythonhosted.org/packages/1f/e9/d6730247d8dec2a3dddc520ebe11e2e860f0f98cee3639e23de6cf920255/coverage-7.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:f75f7168ab25dd93110c8a8117a22450c19976afbc44234cbf71481094c1b850", size = 204096 }, + { url = "https://files.pythonhosted.org/packages/c6/fa/529f55c9a1029c840bcc9109d5a15ff00478b7ff550a1ae361f8745f8ad5/coverage-7.2.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:06a9a2be0b5b576c3f18f1a241f0473575c4a26021b52b2a85263a00f034d51f", size = 200895 }, + { url = "https://files.pythonhosted.org/packages/67/d7/cd8fe689b5743fffac516597a1222834c42b80686b99f5b44ef43ccc2a43/coverage-7.2.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5baa06420f837184130752b7c5ea0808762083bf3487b5038d68b012e5937dbe", size = 201120 }, + { url = "https://files.pythonhosted.org/packages/8c/95/16eed713202406ca0a37f8ac259bbf144c9d24f9b8097a8e6ead61da2dbb/coverage-7.2.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdec9e8cbf13a5bf63290fc6013d216a4c7232efb51548594ca3631a7f13c3a3", size = 233178 }, + { url = "https://files.pythonhosted.org/packages/c1/49/4d487e2ad5d54ed82ac1101e467e8994c09d6123c91b2a962145f3d262c2/coverage-7.2.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:52edc1a60c0d34afa421c9c37078817b2e67a392cab17d97283b64c5833f427f", size = 230754 }, + { url = "https://files.pythonhosted.org/packages/a7/cd/3ce94ad9d407a052dc2a74fbeb1c7947f442155b28264eb467ee78dea812/coverage-7.2.7-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63426706118b7f5cf6bb6c895dc215d8a418d5952544042c8a2d9fe87fcf09cb", size = 232558 }, + { url = "https://files.pythonhosted.org/packages/8f/a8/12cc7b261f3082cc299ab61f677f7e48d93e35ca5c3c2f7241ed5525ccea/coverage-7.2.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:afb17f84d56068a7c29f5fa37bfd38d5aba69e3304af08ee94da8ed5b0865833", size = 241509 }, + { url = "https://files.pythonhosted.org/packages/04/fa/43b55101f75a5e9115259e8be70ff9279921cb6b17f04c34a5702ff9b1f7/coverage-7.2.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:48c19d2159d433ccc99e729ceae7d5293fbffa0bdb94952d3579983d1c8c9d97", size = 239924 }, + { url = "https://files.pythonhosted.org/packages/68/5f/d2bd0f02aa3c3e0311986e625ccf97fdc511b52f4f1a063e4f37b624772f/coverage-7.2.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0e1f928eaf5469c11e886fe0885ad2bf1ec606434e79842a879277895a50942a", size = 240977 }, + { url = "https://files.pythonhosted.org/packages/ba/92/69c0722882643df4257ecc5437b83f4c17ba9e67f15dc6b77bad89b6982e/coverage-7.2.7-cp311-cp311-win32.whl", hash = "sha256:33d6d3ea29d5b3a1a632b3c4e4f4ecae24ef170b0b9ee493883f2df10039959a", size = 203168 }, + { url = "https://files.pythonhosted.org/packages/b1/96/c12ed0dfd4ec587f3739f53eb677b9007853fd486ccb0e7d5512a27bab2e/coverage-7.2.7-cp311-cp311-win_amd64.whl", hash = "sha256:5b7540161790b2f28143191f5f8ec02fb132660ff175b7747b95dcb77ac26562", size = 204185 }, + { url = "https://files.pythonhosted.org/packages/ff/d5/52fa1891d1802ab2e1b346d37d349cb41cdd4fd03f724ebbf94e80577687/coverage-7.2.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f2f67fe12b22cd130d34d0ef79206061bfb5eda52feb6ce0dba0644e20a03cf4", size = 201020 }, + { url = "https://files.pythonhosted.org/packages/24/df/6765898d54ea20e3197a26d26bb65b084deefadd77ce7de946b9c96dfdc5/coverage-7.2.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a342242fe22407f3c17f4b499276a02b01e80f861f1682ad1d95b04018e0c0d4", size = 233994 }, + { url = "https://files.pythonhosted.org/packages/15/81/b108a60bc758b448c151e5abceed027ed77a9523ecbc6b8a390938301841/coverage-7.2.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:171717c7cb6b453aebac9a2ef603699da237f341b38eebfee9be75d27dc38e01", size = 231358 }, + { url = "https://files.pythonhosted.org/packages/61/90/c76b9462f39897ebd8714faf21bc985b65c4e1ea6dff428ea9dc711ed0dd/coverage-7.2.7-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49969a9f7ffa086d973d91cec8d2e31080436ef0fb4a359cae927e742abfaaa6", size = 233316 }, + { url = "https://files.pythonhosted.org/packages/04/d6/8cba3bf346e8b1a4fb3f084df7d8cea25a6b6c56aaca1f2e53829be17e9e/coverage-7.2.7-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b46517c02ccd08092f4fa99f24c3b83d8f92f739b4657b0f146246a0ca6a831d", size = 240159 }, + { url = "https://files.pythonhosted.org/packages/6e/ea/4a252dc77ca0605b23d477729d139915e753ee89e4c9507630e12ad64a80/coverage-7.2.7-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:a3d33a6b3eae87ceaefa91ffdc130b5e8536182cd6dfdbfc1aa56b46ff8c86de", size = 238127 }, + { url = "https://files.pythonhosted.org/packages/9f/5c/d9760ac497c41f9c4841f5972d0edf05d50cad7814e86ee7d133ec4a0ac8/coverage-7.2.7-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:976b9c42fb2a43ebf304fa7d4a310e5f16cc99992f33eced91ef6f908bd8f33d", size = 239833 }, + { url = "https://files.pythonhosted.org/packages/69/8c/26a95b08059db1cbb01e4b0e6d40f2e9debb628c6ca86b78f625ceaf9bab/coverage-7.2.7-cp312-cp312-win32.whl", hash = "sha256:8de8bb0e5ad103888d65abef8bca41ab93721647590a3f740100cd65c3b00511", size = 203463 }, + { url = "https://files.pythonhosted.org/packages/b7/00/14b00a0748e9eda26e97be07a63cc911108844004687321ddcc213be956c/coverage-7.2.7-cp312-cp312-win_amd64.whl", hash = "sha256:9e31cb64d7de6b6f09702bb27c02d1904b3aebfca610c12772452c4e6c21a0d3", size = 204347 }, + { url = "https://files.pythonhosted.org/packages/80/d7/67937c80b8fd4c909fdac29292bc8b35d9505312cff6bcab41c53c5b1df6/coverage-7.2.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:58c2ccc2f00ecb51253cbe5d8d7122a34590fac9646a960d1430d5b15321d95f", size = 200580 }, + { url = "https://files.pythonhosted.org/packages/7a/05/084864fa4bbf8106f44fb72a56e67e0cd372d3bf9d893be818338c81af5d/coverage-7.2.7-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d22656368f0e6189e24722214ed8d66b8022db19d182927b9a248a2a8a2f67eb", size = 226237 }, + { url = "https://files.pythonhosted.org/packages/67/a2/6fa66a50e6e894286d79a3564f42bd54a9bd27049dc0a63b26d9924f0aa3/coverage-7.2.7-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a895fcc7b15c3fc72beb43cdcbdf0ddb7d2ebc959edac9cef390b0d14f39f8a9", size = 224256 }, + { url = "https://files.pythonhosted.org/packages/e2/c0/73f139794c742840b9ab88e2e17fe14a3d4668a166ff95d812ac66c0829d/coverage-7.2.7-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e84606b74eb7de6ff581a7915e2dab7a28a0517fbe1c9239eb227e1354064dcd", size = 225550 }, + { url = "https://files.pythonhosted.org/packages/03/ec/6f30b4e0c96ce03b0e64aec46b4af2a8c49b70d1b5d0d69577add757b946/coverage-7.2.7-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:0a5f9e1dbd7fbe30196578ca36f3fba75376fb99888c395c5880b355e2875f8a", size = 232440 }, + { url = "https://files.pythonhosted.org/packages/22/c1/2f6c1b6f01a0996c9e067a9c780e1824351dbe17faae54388a4477e6d86f/coverage-7.2.7-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:419bfd2caae268623dd469eff96d510a920c90928b60f2073d79f8fe2bbc5959", size = 230897 }, + { url = "https://files.pythonhosted.org/packages/8d/d6/53e999ec1bf7498ca4bc5f3b8227eb61db39068d2de5dcc359dec5601b5a/coverage-7.2.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2aee274c46590717f38ae5e4650988d1af340fe06167546cc32fe2f58ed05b02", size = 232024 }, + { url = "https://files.pythonhosted.org/packages/e9/40/383305500d24122dbed73e505a4d6828f8f3356d1f68ab6d32c781754b81/coverage-7.2.7-cp37-cp37m-win32.whl", hash = "sha256:61b9a528fb348373c433e8966535074b802c7a5d7f23c4f421e6c6e2f1697a6f", size = 203293 }, + { url = "https://files.pythonhosted.org/packages/0e/bc/7e3a31534fabb043269f14fb64e2bb2733f85d4cf39e5bbc71357c57553a/coverage-7.2.7-cp37-cp37m-win_amd64.whl", hash = "sha256:b1c546aca0ca4d028901d825015dc8e4d56aac4b541877690eb76490f1dc8ed0", size = 204040 }, + { url = "https://files.pythonhosted.org/packages/c6/fc/be19131010930a6cf271da48202c8cc1d3f971f68c02fb2d3a78247f43dc/coverage-7.2.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:54b896376ab563bd38453cecb813c295cf347cf5906e8b41d340b0321a5433e5", size = 200689 }, + { url = "https://files.pythonhosted.org/packages/28/d7/9a8de57d87f4bbc6f9a6a5ded1eaac88a89bf71369bb935dac3c0cf2893e/coverage-7.2.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3d376df58cc111dc8e21e3b6e24606b5bb5dee6024f46a5abca99124b2229ef5", size = 200986 }, + { url = "https://files.pythonhosted.org/packages/c8/e4/e6182e4697665fb594a7f4e4f27cb3a4dd00c2e3d35c5c706765de8c7866/coverage-7.2.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e330fc79bd7207e46c7d7fd2bb4af2963f5f635703925543a70b99574b0fea9", size = 230648 }, + { url = "https://files.pythonhosted.org/packages/7b/e3/f552d5871943f747165b92a924055c5d6daa164ae659a13f9018e22f3990/coverage-7.2.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e9d683426464e4a252bf70c3498756055016f99ddaec3774bf368e76bbe02b6", size = 228511 }, + { url = "https://files.pythonhosted.org/packages/44/55/49f65ccdd4dfd6d5528e966b28c37caec64170c725af32ab312889d2f857/coverage-7.2.7-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d13c64ee2d33eccf7437961b6ea7ad8673e2be040b4f7fd4fd4d4d28d9ccb1e", size = 229852 }, + { url = "https://files.pythonhosted.org/packages/0d/31/340428c238eb506feb96d4fb5c9ea614db1149517f22cc7ab8c6035ef6d9/coverage-7.2.7-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b7aa5f8a41217360e600da646004f878250a0d6738bcdc11a0a39928d7dc2050", size = 235578 }, + { url = "https://files.pythonhosted.org/packages/dd/ce/97c1dd6592c908425622fe7f31c017d11cf0421729b09101d4de75bcadc8/coverage-7.2.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8fa03bce9bfbeeef9f3b160a8bed39a221d82308b4152b27d82d8daa7041fee5", size = 234079 }, + { url = "https://files.pythonhosted.org/packages/de/a3/5a98dc9e239d0dc5f243ef5053d5b1bdcaa1dee27a691dfc12befeccf878/coverage-7.2.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:245167dd26180ab4c91d5e1496a30be4cd721a5cf2abf52974f965f10f11419f", size = 234991 }, + { url = "https://files.pythonhosted.org/packages/4a/fb/78986d3022e5ccf2d4370bc43a5fef8374f092b3c21d32499dee8e30b7b6/coverage-7.2.7-cp38-cp38-win32.whl", hash = "sha256:d2c2db7fd82e9b72937969bceac4d6ca89660db0a0967614ce2481e81a0b771e", size = 203160 }, + { url = "https://files.pythonhosted.org/packages/c3/1c/6b3c9c363fb1433c79128e0d692863deb761b1b78162494abb9e5c328bc0/coverage-7.2.7-cp38-cp38-win_amd64.whl", hash = "sha256:2e07b54284e381531c87f785f613b833569c14ecacdcb85d56b25c4622c16c3c", size = 204085 }, + { url = "https://files.pythonhosted.org/packages/88/da/495944ebf0ad246235a6bd523810d9f81981f9b81c6059ba1f56e943abe0/coverage-7.2.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:537891ae8ce59ef63d0123f7ac9e2ae0fc8b72c7ccbe5296fec45fd68967b6c9", size = 200725 }, + { url = "https://files.pythonhosted.org/packages/ca/0c/3dfeeb1006c44b911ee0ed915350db30325d01808525ae7cc8d57643a2ce/coverage-7.2.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06fb182e69f33f6cd1d39a6c597294cff3143554b64b9825d1dc69d18cc2fff2", size = 201022 }, + { url = "https://files.pythonhosted.org/packages/61/af/5964b8d7d9a5c767785644d9a5a63cacba9a9c45cc42ba06d25895ec87be/coverage-7.2.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:201e7389591af40950a6480bd9edfa8ed04346ff80002cec1a66cac4549c1ad7", size = 229102 }, + { url = "https://files.pythonhosted.org/packages/d9/1d/cd467fceb62c371f9adb1d739c92a05d4e550246daa90412e711226bd320/coverage-7.2.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f6951407391b639504e3b3be51b7ba5f3528adbf1a8ac3302b687ecababf929e", size = 227441 }, + { url = "https://files.pythonhosted.org/packages/fe/57/e4f8ad64d84ca9e759d783a052795f62a9f9111585e46068845b1cb52c2b/coverage-7.2.7-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f48351d66575f535669306aa7d6d6f71bc43372473b54a832222803eb956fd1", size = 228265 }, + { url = "https://files.pythonhosted.org/packages/88/8b/b0d9fe727acae907fa7f1c8194ccb6fe9d02e1c3e9001ecf74c741f86110/coverage-7.2.7-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b29019c76039dc3c0fd815c41392a044ce555d9bcdd38b0fb60fb4cd8e475ba9", size = 234217 }, + { url = "https://files.pythonhosted.org/packages/66/2e/c99fe1f6396d93551aa352c75410686e726cd4ea104479b9af1af22367ce/coverage-7.2.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:81c13a1fc7468c40f13420732805a4c38a105d89848b7c10af65a90beff25250", size = 232466 }, + { url = "https://files.pythonhosted.org/packages/bb/e9/88747b40c8fb4a783b40222510ce6d66170217eb05d7f46462c36b4fa8cc/coverage-7.2.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:975d70ab7e3c80a3fe86001d8751f6778905ec723f5b110aed1e450da9d4b7f2", size = 233669 }, + { url = "https://files.pythonhosted.org/packages/b1/d5/a8e276bc005e42114468d4fe03e0a9555786bc51cbfe0d20827a46c1565a/coverage-7.2.7-cp39-cp39-win32.whl", hash = "sha256:7ee7d9d4822c8acc74a5e26c50604dff824710bc8de424904c0982e25c39c6cb", size = 203199 }, + { url = "https://files.pythonhosted.org/packages/a9/0c/4a848ae663b47f1195abcb09a951751dd61f80b503303b9b9d768e0fd321/coverage-7.2.7-cp39-cp39-win_amd64.whl", hash = "sha256:eb393e5ebc85245347950143969b241d08b52b88a3dc39479822e073a1a8eb27", size = 204109 }, + { url = "https://files.pythonhosted.org/packages/67/fb/b3b1d7887e1ea25a9608b0776e480e4bbc303ca95a31fd585555ec4fff5a/coverage-7.2.7-pp37.pp38.pp39-none-any.whl", hash = "sha256:b7b4c971f05e6ae490fef852c218b0e79d4e52f79ef0c8475566584a8fb3e01d", size = 193207 }, +] + +[[package]] +name = "coverage" +version = "7.6.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.8.1' and python_full_version < '3.9'", + "python_full_version >= '3.8' and python_full_version < '3.8.1'", +] +sdist = { url = "https://files.pythonhosted.org/packages/f7/08/7e37f82e4d1aead42a7443ff06a1e406aabf7302c4f00a546e4b320b994c/coverage-7.6.1.tar.gz", hash = "sha256:953510dfb7b12ab69d20135a0662397f077c59b1e6379a768e97c59d852ee51d", size = 798791 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/61/eb7ce5ed62bacf21beca4937a90fe32545c91a3c8a42a30c6616d48fc70d/coverage-7.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b06079abebbc0e89e6163b8e8f0e16270124c154dc6e4a47b413dd538859af16", size = 206690 }, + { url = "https://files.pythonhosted.org/packages/7d/73/041928e434442bd3afde5584bdc3f932fb4562b1597629f537387cec6f3d/coverage-7.6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cf4b19715bccd7ee27b6b120e7e9dd56037b9c0681dcc1adc9ba9db3d417fa36", size = 207127 }, + { url = "https://files.pythonhosted.org/packages/c7/c8/6ca52b5147828e45ad0242388477fdb90df2c6cbb9a441701a12b3c71bc8/coverage-7.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61c0abb4c85b095a784ef23fdd4aede7a2628478e7baba7c5e3deba61070a02", size = 235654 }, + { url = "https://files.pythonhosted.org/packages/d5/da/9ac2b62557f4340270942011d6efeab9833648380109e897d48ab7c1035d/coverage-7.6.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd21f6ae3f08b41004dfb433fa895d858f3f5979e7762d052b12aef444e29afc", size = 233598 }, + { url = "https://files.pythonhosted.org/packages/53/23/9e2c114d0178abc42b6d8d5281f651a8e6519abfa0ef460a00a91f80879d/coverage-7.6.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f59d57baca39b32db42b83b2a7ba6f47ad9c394ec2076b084c3f029b7afca23", size = 234732 }, + { url = "https://files.pythonhosted.org/packages/0f/7e/a0230756fb133343a52716e8b855045f13342b70e48e8ad41d8a0d60ab98/coverage-7.6.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a1ac0ae2b8bd743b88ed0502544847c3053d7171a3cff9228af618a068ed9c34", size = 233816 }, + { url = "https://files.pythonhosted.org/packages/28/7c/3753c8b40d232b1e5eeaed798c875537cf3cb183fb5041017c1fdb7ec14e/coverage-7.6.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e6a08c0be454c3b3beb105c0596ebdc2371fab6bb90c0c0297f4e58fd7e1012c", size = 232325 }, + { url = "https://files.pythonhosted.org/packages/57/e3/818a2b2af5b7573b4b82cf3e9f137ab158c90ea750a8f053716a32f20f06/coverage-7.6.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f5796e664fe802da4f57a168c85359a8fbf3eab5e55cd4e4569fbacecc903959", size = 233418 }, + { url = "https://files.pythonhosted.org/packages/c8/fb/4532b0b0cefb3f06d201648715e03b0feb822907edab3935112b61b885e2/coverage-7.6.1-cp310-cp310-win32.whl", hash = "sha256:7bb65125fcbef8d989fa1dd0e8a060999497629ca5b0efbca209588a73356232", size = 209343 }, + { url = "https://files.pythonhosted.org/packages/5a/25/af337cc7421eca1c187cc9c315f0a755d48e755d2853715bfe8c418a45fa/coverage-7.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:3115a95daa9bdba70aea750db7b96b37259a81a709223c8448fa97727d546fe0", size = 210136 }, + { url = "https://files.pythonhosted.org/packages/ad/5f/67af7d60d7e8ce61a4e2ddcd1bd5fb787180c8d0ae0fbd073f903b3dd95d/coverage-7.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7dea0889685db8550f839fa202744652e87c60015029ce3f60e006f8c4462c93", size = 206796 }, + { url = "https://files.pythonhosted.org/packages/e1/0e/e52332389e057daa2e03be1fbfef25bb4d626b37d12ed42ae6281d0a274c/coverage-7.6.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed37bd3c3b063412f7620464a9ac1314d33100329f39799255fb8d3027da50d3", size = 207244 }, + { url = "https://files.pythonhosted.org/packages/aa/cd/766b45fb6e090f20f8927d9c7cb34237d41c73a939358bc881883fd3a40d/coverage-7.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d85f5e9a5f8b73e2350097c3756ef7e785f55bd71205defa0bfdaf96c31616ff", size = 239279 }, + { url = "https://files.pythonhosted.org/packages/70/6c/a9ccd6fe50ddaf13442a1e2dd519ca805cbe0f1fcd377fba6d8339b98ccb/coverage-7.6.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bc572be474cafb617672c43fe989d6e48d3c83af02ce8de73fff1c6bb3c198d", size = 236859 }, + { url = "https://files.pythonhosted.org/packages/14/6f/8351b465febb4dbc1ca9929505202db909c5a635c6fdf33e089bbc3d7d85/coverage-7.6.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c0420b573964c760df9e9e86d1a9a622d0d27f417e1a949a8a66dd7bcee7bc6", size = 238549 }, + { url = "https://files.pythonhosted.org/packages/68/3c/289b81fa18ad72138e6d78c4c11a82b5378a312c0e467e2f6b495c260907/coverage-7.6.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1f4aa8219db826ce6be7099d559f8ec311549bfc4046f7f9fe9b5cea5c581c56", size = 237477 }, + { url = "https://files.pythonhosted.org/packages/ed/1c/aa1efa6459d822bd72c4abc0b9418cf268de3f60eeccd65dc4988553bd8d/coverage-7.6.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:fc5a77d0c516700ebad189b587de289a20a78324bc54baee03dd486f0855d234", size = 236134 }, + { url = "https://files.pythonhosted.org/packages/fb/c8/521c698f2d2796565fe9c789c2ee1ccdae610b3aa20b9b2ef980cc253640/coverage-7.6.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b48f312cca9621272ae49008c7f613337c53fadca647d6384cc129d2996d1133", size = 236910 }, + { url = "https://files.pythonhosted.org/packages/7d/30/033e663399ff17dca90d793ee8a2ea2890e7fdf085da58d82468b4220bf7/coverage-7.6.1-cp311-cp311-win32.whl", hash = "sha256:1125ca0e5fd475cbbba3bb67ae20bd2c23a98fac4e32412883f9bcbaa81c314c", size = 209348 }, + { url = "https://files.pythonhosted.org/packages/20/05/0d1ccbb52727ccdadaa3ff37e4d2dc1cd4d47f0c3df9eb58d9ec8508ca88/coverage-7.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:8ae539519c4c040c5ffd0632784e21b2f03fc1340752af711f33e5be83a9d6c6", size = 210230 }, + { url = "https://files.pythonhosted.org/packages/7e/d4/300fc921dff243cd518c7db3a4c614b7e4b2431b0d1145c1e274fd99bd70/coverage-7.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:95cae0efeb032af8458fc27d191f85d1717b1d4e49f7cb226cf526ff28179778", size = 206983 }, + { url = "https://files.pythonhosted.org/packages/e1/ab/6bf00de5327ecb8db205f9ae596885417a31535eeda6e7b99463108782e1/coverage-7.6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5621a9175cf9d0b0c84c2ef2b12e9f5f5071357c4d2ea6ca1cf01814f45d2391", size = 207221 }, + { url = "https://files.pythonhosted.org/packages/92/8f/2ead05e735022d1a7f3a0a683ac7f737de14850395a826192f0288703472/coverage-7.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:260933720fdcd75340e7dbe9060655aff3af1f0c5d20f46b57f262ab6c86a5e8", size = 240342 }, + { url = "https://files.pythonhosted.org/packages/0f/ef/94043e478201ffa85b8ae2d2c79b4081e5a1b73438aafafccf3e9bafb6b5/coverage-7.6.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07e2ca0ad381b91350c0ed49d52699b625aab2b44b65e1b4e02fa9df0e92ad2d", size = 237371 }, + { url = "https://files.pythonhosted.org/packages/1f/0f/c890339dd605f3ebc269543247bdd43b703cce6825b5ed42ff5f2d6122c7/coverage-7.6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c44fee9975f04b33331cb8eb272827111efc8930cfd582e0320613263ca849ca", size = 239455 }, + { url = "https://files.pythonhosted.org/packages/d1/04/7fd7b39ec7372a04efb0f70c70e35857a99b6a9188b5205efb4c77d6a57a/coverage-7.6.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:877abb17e6339d96bf08e7a622d05095e72b71f8afd8a9fefc82cf30ed944163", size = 238924 }, + { url = "https://files.pythonhosted.org/packages/ed/bf/73ce346a9d32a09cf369f14d2a06651329c984e106f5992c89579d25b27e/coverage-7.6.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3e0cadcf6733c09154b461f1ca72d5416635e5e4ec4e536192180d34ec160f8a", size = 237252 }, + { url = "https://files.pythonhosted.org/packages/86/74/1dc7a20969725e917b1e07fe71a955eb34bc606b938316bcc799f228374b/coverage-7.6.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c3c02d12f837d9683e5ab2f3d9844dc57655b92c74e286c262e0fc54213c216d", size = 238897 }, + { url = "https://files.pythonhosted.org/packages/b6/e9/d9cc3deceb361c491b81005c668578b0dfa51eed02cd081620e9a62f24ec/coverage-7.6.1-cp312-cp312-win32.whl", hash = "sha256:e05882b70b87a18d937ca6768ff33cc3f72847cbc4de4491c8e73880766718e5", size = 209606 }, + { url = "https://files.pythonhosted.org/packages/47/c8/5a2e41922ea6740f77d555c4d47544acd7dc3f251fe14199c09c0f5958d3/coverage-7.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:b5d7b556859dd85f3a541db6a4e0167b86e7273e1cdc973e5b175166bb634fdb", size = 210373 }, + { url = "https://files.pythonhosted.org/packages/8c/f9/9aa4dfb751cb01c949c990d136a0f92027fbcc5781c6e921df1cb1563f20/coverage-7.6.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a4acd025ecc06185ba2b801f2de85546e0b8ac787cf9d3b06e7e2a69f925b106", size = 207007 }, + { url = "https://files.pythonhosted.org/packages/b9/67/e1413d5a8591622a46dd04ff80873b04c849268831ed5c304c16433e7e30/coverage-7.6.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a6d3adcf24b624a7b778533480e32434a39ad8fa30c315208f6d3e5542aeb6e9", size = 207269 }, + { url = "https://files.pythonhosted.org/packages/14/5b/9dec847b305e44a5634d0fb8498d135ab1d88330482b74065fcec0622224/coverage-7.6.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0c212c49b6c10e6951362f7c6df3329f04c2b1c28499563d4035d964ab8e08c", size = 239886 }, + { url = "https://files.pythonhosted.org/packages/7b/b7/35760a67c168e29f454928f51f970342d23cf75a2bb0323e0f07334c85f3/coverage-7.6.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e81d7a3e58882450ec4186ca59a3f20a5d4440f25b1cff6f0902ad890e6748a", size = 237037 }, + { url = "https://files.pythonhosted.org/packages/f7/95/d2fd31f1d638df806cae59d7daea5abf2b15b5234016a5ebb502c2f3f7ee/coverage-7.6.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78b260de9790fd81e69401c2dc8b17da47c8038176a79092a89cb2b7d945d060", size = 239038 }, + { url = "https://files.pythonhosted.org/packages/6e/bd/110689ff5752b67924efd5e2aedf5190cbbe245fc81b8dec1abaffba619d/coverage-7.6.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a78d169acd38300060b28d600344a803628c3fd585c912cacc9ea8790fe96862", size = 238690 }, + { url = "https://files.pythonhosted.org/packages/d3/a8/08d7b38e6ff8df52331c83130d0ab92d9c9a8b5462f9e99c9f051a4ae206/coverage-7.6.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2c09f4ce52cb99dd7505cd0fc8e0e37c77b87f46bc9c1eb03fe3bc9991085388", size = 236765 }, + { url = "https://files.pythonhosted.org/packages/d6/6a/9cf96839d3147d55ae713eb2d877f4d777e7dc5ba2bce227167d0118dfe8/coverage-7.6.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6878ef48d4227aace338d88c48738a4258213cd7b74fd9a3d4d7582bb1d8a155", size = 238611 }, + { url = "https://files.pythonhosted.org/packages/74/e4/7ff20d6a0b59eeaab40b3140a71e38cf52547ba21dbcf1d79c5a32bba61b/coverage-7.6.1-cp313-cp313-win32.whl", hash = "sha256:44df346d5215a8c0e360307d46ffaabe0f5d3502c8a1cefd700b34baf31d411a", size = 209671 }, + { url = "https://files.pythonhosted.org/packages/35/59/1812f08a85b57c9fdb6d0b383d779e47b6f643bc278ed682859512517e83/coverage-7.6.1-cp313-cp313-win_amd64.whl", hash = "sha256:8284cf8c0dd272a247bc154eb6c95548722dce90d098c17a883ed36e67cdb129", size = 210368 }, + { url = "https://files.pythonhosted.org/packages/9c/15/08913be1c59d7562a3e39fce20661a98c0a3f59d5754312899acc6cb8a2d/coverage-7.6.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:d3296782ca4eab572a1a4eca686d8bfb00226300dcefdf43faa25b5242ab8a3e", size = 207758 }, + { url = "https://files.pythonhosted.org/packages/c4/ae/b5d58dff26cade02ada6ca612a76447acd69dccdbb3a478e9e088eb3d4b9/coverage-7.6.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:502753043567491d3ff6d08629270127e0c31d4184c4c8d98f92c26f65019962", size = 208035 }, + { url = "https://files.pythonhosted.org/packages/b8/d7/62095e355ec0613b08dfb19206ce3033a0eedb6f4a67af5ed267a8800642/coverage-7.6.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a89ecca80709d4076b95f89f308544ec8f7b4727e8a547913a35f16717856cb", size = 250839 }, + { url = "https://files.pythonhosted.org/packages/7c/1e/c2967cb7991b112ba3766df0d9c21de46b476d103e32bb401b1b2adf3380/coverage-7.6.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a318d68e92e80af8b00fa99609796fdbcdfef3629c77c6283566c6f02c6d6704", size = 246569 }, + { url = "https://files.pythonhosted.org/packages/8b/61/a7a6a55dd266007ed3b1df7a3386a0d760d014542d72f7c2c6938483b7bd/coverage-7.6.1-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13b0a73a0896988f053e4fbb7de6d93388e6dd292b0d87ee51d106f2c11b465b", size = 248927 }, + { url = "https://files.pythonhosted.org/packages/c8/fa/13a6f56d72b429f56ef612eb3bc5ce1b75b7ee12864b3bd12526ab794847/coverage-7.6.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4421712dbfc5562150f7554f13dde997a2e932a6b5f352edcce948a815efee6f", size = 248401 }, + { url = "https://files.pythonhosted.org/packages/75/06/0429c652aa0fb761fc60e8c6b291338c9173c6aa0f4e40e1902345b42830/coverage-7.6.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:166811d20dfea725e2e4baa71fffd6c968a958577848d2131f39b60043400223", size = 246301 }, + { url = "https://files.pythonhosted.org/packages/52/76/1766bb8b803a88f93c3a2d07e30ffa359467810e5cbc68e375ebe6906efb/coverage-7.6.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:225667980479a17db1048cb2bf8bfb39b8e5be8f164b8f6628b64f78a72cf9d3", size = 247598 }, + { url = "https://files.pythonhosted.org/packages/66/8b/f54f8db2ae17188be9566e8166ac6df105c1c611e25da755738025708d54/coverage-7.6.1-cp313-cp313t-win32.whl", hash = "sha256:170d444ab405852903b7d04ea9ae9b98f98ab6d7e63e1115e82620807519797f", size = 210307 }, + { url = "https://files.pythonhosted.org/packages/9f/b0/e0dca6da9170aefc07515cce067b97178cefafb512d00a87a1c717d2efd5/coverage-7.6.1-cp313-cp313t-win_amd64.whl", hash = "sha256:b9f222de8cded79c49bf184bdbc06630d4c58eec9459b939b4a690c82ed05657", size = 211453 }, + { url = "https://files.pythonhosted.org/packages/81/d0/d9e3d554e38beea5a2e22178ddb16587dbcbe9a1ef3211f55733924bf7fa/coverage-7.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6db04803b6c7291985a761004e9060b2bca08da6d04f26a7f2294b8623a0c1a0", size = 206674 }, + { url = "https://files.pythonhosted.org/packages/38/ea/cab2dc248d9f45b2b7f9f1f596a4d75a435cb364437c61b51d2eb33ceb0e/coverage-7.6.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f1adfc8ac319e1a348af294106bc6a8458a0f1633cc62a1446aebc30c5fa186a", size = 207101 }, + { url = "https://files.pythonhosted.org/packages/ca/6f/f82f9a500c7c5722368978a5390c418d2a4d083ef955309a8748ecaa8920/coverage-7.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a95324a9de9650a729239daea117df21f4b9868ce32e63f8b650ebe6cef5595b", size = 236554 }, + { url = "https://files.pythonhosted.org/packages/a6/94/d3055aa33d4e7e733d8fa309d9adf147b4b06a82c1346366fc15a2b1d5fa/coverage-7.6.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b43c03669dc4618ec25270b06ecd3ee4fa94c7f9b3c14bae6571ca00ef98b0d3", size = 234440 }, + { url = "https://files.pythonhosted.org/packages/e4/6e/885bcd787d9dd674de4a7d8ec83faf729534c63d05d51d45d4fa168f7102/coverage-7.6.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8929543a7192c13d177b770008bc4e8119f2e1f881d563fc6b6305d2d0ebe9de", size = 235889 }, + { url = "https://files.pythonhosted.org/packages/f4/63/df50120a7744492710854860783d6819ff23e482dee15462c9a833cc428a/coverage-7.6.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:a09ece4a69cf399510c8ab25e0950d9cf2b42f7b3cb0374f95d2e2ff594478a6", size = 235142 }, + { url = "https://files.pythonhosted.org/packages/3a/5d/9d0acfcded2b3e9ce1c7923ca52ccc00c78a74e112fc2aee661125b7843b/coverage-7.6.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:9054a0754de38d9dbd01a46621636689124d666bad1936d76c0341f7d71bf569", size = 233805 }, + { url = "https://files.pythonhosted.org/packages/c4/56/50abf070cb3cd9b1dd32f2c88f083aab561ecbffbcd783275cb51c17f11d/coverage-7.6.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0dbde0f4aa9a16fa4d754356a8f2e36296ff4d83994b2c9d8398aa32f222f989", size = 234655 }, + { url = "https://files.pythonhosted.org/packages/25/ee/b4c246048b8485f85a2426ef4abab88e48c6e80c74e964bea5cd4cd4b115/coverage-7.6.1-cp38-cp38-win32.whl", hash = "sha256:da511e6ad4f7323ee5702e6633085fb76c2f893aaf8ce4c51a0ba4fc07580ea7", size = 209296 }, + { url = "https://files.pythonhosted.org/packages/5c/1c/96cf86b70b69ea2b12924cdf7cabb8ad10e6130eab8d767a1099fbd2a44f/coverage-7.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:3f1156e3e8f2872197af3840d8ad307a9dd18e615dc64d9ee41696f287c57ad8", size = 210137 }, + { url = "https://files.pythonhosted.org/packages/19/d3/d54c5aa83268779d54c86deb39c1c4566e5d45c155369ca152765f8db413/coverage-7.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:abd5fd0db5f4dc9289408aaf34908072f805ff7792632250dcb36dc591d24255", size = 206688 }, + { url = "https://files.pythonhosted.org/packages/a5/fe/137d5dca72e4a258b1bc17bb04f2e0196898fe495843402ce826a7419fe3/coverage-7.6.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:547f45fa1a93154bd82050a7f3cddbc1a7a4dd2a9bf5cb7d06f4ae29fe94eaf8", size = 207120 }, + { url = "https://files.pythonhosted.org/packages/78/5b/a0a796983f3201ff5485323b225d7c8b74ce30c11f456017e23d8e8d1945/coverage-7.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:645786266c8f18a931b65bfcefdbf6952dd0dea98feee39bd188607a9d307ed2", size = 235249 }, + { url = "https://files.pythonhosted.org/packages/4e/e1/76089d6a5ef9d68f018f65411fcdaaeb0141b504587b901d74e8587606ad/coverage-7.6.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e0b2df163b8ed01d515807af24f63de04bebcecbd6c3bfeff88385789fdf75a", size = 233237 }, + { url = "https://files.pythonhosted.org/packages/9a/6f/eef79b779a540326fee9520e5542a8b428cc3bfa8b7c8f1022c1ee4fc66c/coverage-7.6.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:609b06f178fe8e9f89ef676532760ec0b4deea15e9969bf754b37f7c40326dbc", size = 234311 }, + { url = "https://files.pythonhosted.org/packages/75/e1/656d65fb126c29a494ef964005702b012f3498db1a30dd562958e85a4049/coverage-7.6.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:702855feff378050ae4f741045e19a32d57d19f3e0676d589df0575008ea5004", size = 233453 }, + { url = "https://files.pythonhosted.org/packages/68/6a/45f108f137941a4a1238c85f28fd9d048cc46b5466d6b8dda3aba1bb9d4f/coverage-7.6.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:2bdb062ea438f22d99cba0d7829c2ef0af1d768d1e4a4f528087224c90b132cb", size = 231958 }, + { url = "https://files.pythonhosted.org/packages/9b/e7/47b809099168b8b8c72ae311efc3e88c8d8a1162b3ba4b8da3cfcdb85743/coverage-7.6.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9c56863d44bd1c4fe2abb8a4d6f5371d197f1ac0ebdee542f07f35895fc07f36", size = 232938 }, + { url = "https://files.pythonhosted.org/packages/52/80/052222ba7058071f905435bad0ba392cc12006380731c37afaf3fe749b88/coverage-7.6.1-cp39-cp39-win32.whl", hash = "sha256:6e2cd258d7d927d09493c8df1ce9174ad01b381d4729a9d8d4e38670ca24774c", size = 209352 }, + { url = "https://files.pythonhosted.org/packages/b8/d8/1b92e0b3adcf384e98770a00ca095da1b5f7b483e6563ae4eb5e935d24a1/coverage-7.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:06a737c882bd26d0d6ee7269b20b12f14a8704807a01056c80bb881a4b2ce6ca", size = 210153 }, + { url = "https://files.pythonhosted.org/packages/a5/2b/0354ed096bca64dc8e32a7cbcae28b34cb5ad0b1fe2125d6d99583313ac0/coverage-7.6.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:e9a6e0eb86070e8ccaedfbd9d38fec54864f3125ab95419970575b42af7541df", size = 198926 }, +] + +[[package]] +name = "coverage" +version = "7.8.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.9'", +] +sdist = { url = "https://files.pythonhosted.org/packages/19/4f/2251e65033ed2ce1e68f00f91a0294e0f80c80ae8c3ebbe2f12828c4cd53/coverage-7.8.0.tar.gz", hash = "sha256:7a3d62b3b03b4b6fd41a085f3574874cf946cb4604d2b4d3e8dca8cd570ca501", size = 811872 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/01/1c5e6ee4ebaaa5e079db933a9a45f61172048c7efa06648445821a201084/coverage-7.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2931f66991175369859b5fd58529cd4b73582461877ecfd859b6549869287ffe", size = 211379 }, + { url = "https://files.pythonhosted.org/packages/e9/16/a463389f5ff916963471f7c13585e5f38c6814607306b3cb4d6b4cf13384/coverage-7.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:52a523153c568d2c0ef8826f6cc23031dc86cffb8c6aeab92c4ff776e7951b28", size = 211814 }, + { url = "https://files.pythonhosted.org/packages/b8/b1/77062b0393f54d79064dfb72d2da402657d7c569cfbc724d56ac0f9c67ed/coverage-7.8.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c8a5c139aae4c35cbd7cadca1df02ea8cf28a911534fc1b0456acb0b14234f3", size = 240937 }, + { url = "https://files.pythonhosted.org/packages/d7/54/c7b00a23150083c124e908c352db03bcd33375494a4beb0c6d79b35448b9/coverage-7.8.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5a26c0c795c3e0b63ec7da6efded5f0bc856d7c0b24b2ac84b4d1d7bc578d676", size = 238849 }, + { url = "https://files.pythonhosted.org/packages/f7/ec/a6b7cfebd34e7b49f844788fda94713035372b5200c23088e3bbafb30970/coverage-7.8.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:821f7bcbaa84318287115d54becb1915eece6918136c6f91045bb84e2f88739d", size = 239986 }, + { url = "https://files.pythonhosted.org/packages/21/8c/c965ecef8af54e6d9b11bfbba85d4f6a319399f5f724798498387f3209eb/coverage-7.8.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a321c61477ff8ee705b8a5fed370b5710c56b3a52d17b983d9215861e37b642a", size = 239896 }, + { url = "https://files.pythonhosted.org/packages/40/83/070550273fb4c480efa8381735969cb403fa8fd1626d74865bfaf9e4d903/coverage-7.8.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:ed2144b8a78f9d94d9515963ed273d620e07846acd5d4b0a642d4849e8d91a0c", size = 238613 }, + { url = "https://files.pythonhosted.org/packages/07/76/fbb2540495b01d996d38e9f8897b861afed356be01160ab4e25471f4fed1/coverage-7.8.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:042e7841a26498fff7a37d6fda770d17519982f5b7d8bf5278d140b67b61095f", size = 238909 }, + { url = "https://files.pythonhosted.org/packages/a3/7e/76d604db640b7d4a86e5dd730b73e96e12a8185f22b5d0799025121f4dcb/coverage-7.8.0-cp310-cp310-win32.whl", hash = "sha256:f9983d01d7705b2d1f7a95e10bbe4091fabc03a46881a256c2787637b087003f", size = 213948 }, + { url = "https://files.pythonhosted.org/packages/5c/a7/f8ce4aafb4a12ab475b56c76a71a40f427740cf496c14e943ade72e25023/coverage-7.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:5a570cd9bd20b85d1a0d7b009aaf6c110b52b5755c17be6962f8ccd65d1dbd23", size = 214844 }, + { url = "https://files.pythonhosted.org/packages/2b/77/074d201adb8383addae5784cb8e2dac60bb62bfdf28b2b10f3a3af2fda47/coverage-7.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e7ac22a0bb2c7c49f441f7a6d46c9c80d96e56f5a8bc6972529ed43c8b694e27", size = 211493 }, + { url = "https://files.pythonhosted.org/packages/a9/89/7a8efe585750fe59b48d09f871f0e0c028a7b10722b2172dfe021fa2fdd4/coverage-7.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bf13d564d310c156d1c8e53877baf2993fb3073b2fc9f69790ca6a732eb4bfea", size = 211921 }, + { url = "https://files.pythonhosted.org/packages/e9/ef/96a90c31d08a3f40c49dbe897df4f1fd51fb6583821a1a1c5ee30cc8f680/coverage-7.8.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5761c70c017c1b0d21b0815a920ffb94a670c8d5d409d9b38857874c21f70d7", size = 244556 }, + { url = "https://files.pythonhosted.org/packages/89/97/dcd5c2ce72cee9d7b0ee8c89162c24972fb987a111b92d1a3d1d19100c61/coverage-7.8.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5ff52d790c7e1628241ffbcaeb33e07d14b007b6eb00a19320c7b8a7024c040", size = 242245 }, + { url = "https://files.pythonhosted.org/packages/b2/7b/b63cbb44096141ed435843bbb251558c8e05cc835c8da31ca6ffb26d44c0/coverage-7.8.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d39fc4817fd67b3915256af5dda75fd4ee10621a3d484524487e33416c6f3543", size = 244032 }, + { url = "https://files.pythonhosted.org/packages/97/e3/7fa8c2c00a1ef530c2a42fa5df25a6971391f92739d83d67a4ee6dcf7a02/coverage-7.8.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b44674870709017e4b4036e3d0d6c17f06a0e6d4436422e0ad29b882c40697d2", size = 243679 }, + { url = "https://files.pythonhosted.org/packages/4f/b3/e0a59d8df9150c8a0c0841d55d6568f0a9195692136c44f3d21f1842c8f6/coverage-7.8.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8f99eb72bf27cbb167b636eb1726f590c00e1ad375002230607a844d9e9a2318", size = 241852 }, + { url = "https://files.pythonhosted.org/packages/9b/82/db347ccd57bcef150c173df2ade97976a8367a3be7160e303e43dd0c795f/coverage-7.8.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b571bf5341ba8c6bc02e0baeaf3b061ab993bf372d982ae509807e7f112554e9", size = 242389 }, + { url = "https://files.pythonhosted.org/packages/21/f6/3f7d7879ceb03923195d9ff294456241ed05815281f5254bc16ef71d6a20/coverage-7.8.0-cp311-cp311-win32.whl", hash = "sha256:e75a2ad7b647fd8046d58c3132d7eaf31b12d8a53c0e4b21fa9c4d23d6ee6d3c", size = 213997 }, + { url = "https://files.pythonhosted.org/packages/28/87/021189643e18ecf045dbe1e2071b2747901f229df302de01c998eeadf146/coverage-7.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:3043ba1c88b2139126fc72cb48574b90e2e0546d4c78b5299317f61b7f718b78", size = 214911 }, + { url = "https://files.pythonhosted.org/packages/aa/12/4792669473297f7973518bec373a955e267deb4339286f882439b8535b39/coverage-7.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bbb5cc845a0292e0c520656d19d7ce40e18d0e19b22cb3e0409135a575bf79fc", size = 211684 }, + { url = "https://files.pythonhosted.org/packages/be/e1/2a4ec273894000ebedd789e8f2fc3813fcaf486074f87fd1c5b2cb1c0a2b/coverage-7.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4dfd9a93db9e78666d178d4f08a5408aa3f2474ad4d0e0378ed5f2ef71640cb6", size = 211935 }, + { url = "https://files.pythonhosted.org/packages/f8/3a/7b14f6e4372786709a361729164125f6b7caf4024ce02e596c4a69bccb89/coverage-7.8.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f017a61399f13aa6d1039f75cd467be388d157cd81f1a119b9d9a68ba6f2830d", size = 245994 }, + { url = "https://files.pythonhosted.org/packages/54/80/039cc7f1f81dcbd01ea796d36d3797e60c106077e31fd1f526b85337d6a1/coverage-7.8.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0915742f4c82208ebf47a2b154a5334155ed9ef9fe6190674b8a46c2fb89cb05", size = 242885 }, + { url = "https://files.pythonhosted.org/packages/10/e0/dc8355f992b6cc2f9dcd5ef6242b62a3f73264893bc09fbb08bfcab18eb4/coverage-7.8.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a40fcf208e021eb14b0fac6bdb045c0e0cab53105f93ba0d03fd934c956143a", size = 245142 }, + { url = "https://files.pythonhosted.org/packages/43/1b/33e313b22cf50f652becb94c6e7dae25d8f02e52e44db37a82de9ac357e8/coverage-7.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a1f406a8e0995d654b2ad87c62caf6befa767885301f3b8f6f73e6f3c31ec3a6", size = 244906 }, + { url = "https://files.pythonhosted.org/packages/05/08/c0a8048e942e7f918764ccc99503e2bccffba1c42568693ce6955860365e/coverage-7.8.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:77af0f6447a582fdc7de5e06fa3757a3ef87769fbb0fdbdeba78c23049140a47", size = 243124 }, + { url = "https://files.pythonhosted.org/packages/5b/62/ea625b30623083c2aad645c9a6288ad9fc83d570f9adb913a2abdba562dd/coverage-7.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f2d32f95922927186c6dbc8bc60df0d186b6edb828d299ab10898ef3f40052fe", size = 244317 }, + { url = "https://files.pythonhosted.org/packages/62/cb/3871f13ee1130a6c8f020e2f71d9ed269e1e2124aa3374d2180ee451cee9/coverage-7.8.0-cp312-cp312-win32.whl", hash = "sha256:769773614e676f9d8e8a0980dd7740f09a6ea386d0f383db6821df07d0f08545", size = 214170 }, + { url = "https://files.pythonhosted.org/packages/88/26/69fe1193ab0bfa1eb7a7c0149a066123611baba029ebb448500abd8143f9/coverage-7.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:e5d2b9be5b0693cf21eb4ce0ec8d211efb43966f6657807f6859aab3814f946b", size = 214969 }, + { url = "https://files.pythonhosted.org/packages/f3/21/87e9b97b568e223f3438d93072479c2f36cc9b3f6b9f7094b9d50232acc0/coverage-7.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5ac46d0c2dd5820ce93943a501ac5f6548ea81594777ca585bf002aa8854cacd", size = 211708 }, + { url = "https://files.pythonhosted.org/packages/75/be/882d08b28a0d19c9c4c2e8a1c6ebe1f79c9c839eb46d4fca3bd3b34562b9/coverage-7.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:771eb7587a0563ca5bb6f622b9ed7f9d07bd08900f7589b4febff05f469bea00", size = 211981 }, + { url = "https://files.pythonhosted.org/packages/7a/1d/ce99612ebd58082fbe3f8c66f6d8d5694976c76a0d474503fa70633ec77f/coverage-7.8.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42421e04069fb2cbcbca5a696c4050b84a43b05392679d4068acbe65449b5c64", size = 245495 }, + { url = "https://files.pythonhosted.org/packages/dc/8d/6115abe97df98db6b2bd76aae395fcc941d039a7acd25f741312ced9a78f/coverage-7.8.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:554fec1199d93ab30adaa751db68acec2b41c5602ac944bb19187cb9a41a8067", size = 242538 }, + { url = "https://files.pythonhosted.org/packages/cb/74/2f8cc196643b15bc096d60e073691dadb3dca48418f08bc78dd6e899383e/coverage-7.8.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aaeb00761f985007b38cf463b1d160a14a22c34eb3f6a39d9ad6fc27cb73008", size = 244561 }, + { url = "https://files.pythonhosted.org/packages/22/70/c10c77cd77970ac965734fe3419f2c98665f6e982744a9bfb0e749d298f4/coverage-7.8.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:581a40c7b94921fffd6457ffe532259813fc68eb2bdda60fa8cc343414ce3733", size = 244633 }, + { url = "https://files.pythonhosted.org/packages/38/5a/4f7569d946a07c952688debee18c2bb9ab24f88027e3d71fd25dbc2f9dca/coverage-7.8.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f319bae0321bc838e205bf9e5bc28f0a3165f30c203b610f17ab5552cff90323", size = 242712 }, + { url = "https://files.pythonhosted.org/packages/bb/a1/03a43b33f50475a632a91ea8c127f7e35e53786dbe6781c25f19fd5a65f8/coverage-7.8.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:04bfec25a8ef1c5f41f5e7e5c842f6b615599ca8ba8391ec33a9290d9d2db3a3", size = 244000 }, + { url = "https://files.pythonhosted.org/packages/6a/89/ab6c43b1788a3128e4d1b7b54214548dcad75a621f9d277b14d16a80d8a1/coverage-7.8.0-cp313-cp313-win32.whl", hash = "sha256:dd19608788b50eed889e13a5d71d832edc34fc9dfce606f66e8f9f917eef910d", size = 214195 }, + { url = "https://files.pythonhosted.org/packages/12/12/6bf5f9a8b063d116bac536a7fb594fc35cb04981654cccb4bbfea5dcdfa0/coverage-7.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:a9abbccd778d98e9c7e85038e35e91e67f5b520776781d9a1e2ee9d400869487", size = 214998 }, + { url = "https://files.pythonhosted.org/packages/2a/e6/1e9df74ef7a1c983a9c7443dac8aac37a46f1939ae3499424622e72a6f78/coverage-7.8.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:18c5ae6d061ad5b3e7eef4363fb27a0576012a7447af48be6c75b88494c6cf25", size = 212541 }, + { url = "https://files.pythonhosted.org/packages/04/51/c32174edb7ee49744e2e81c4b1414ac9df3dacfcb5b5f273b7f285ad43f6/coverage-7.8.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:95aa6ae391a22bbbce1b77ddac846c98c5473de0372ba5c463480043a07bff42", size = 212767 }, + { url = "https://files.pythonhosted.org/packages/e9/8f/f454cbdb5212f13f29d4a7983db69169f1937e869a5142bce983ded52162/coverage-7.8.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e013b07ba1c748dacc2a80e69a46286ff145935f260eb8c72df7185bf048f502", size = 256997 }, + { url = "https://files.pythonhosted.org/packages/e6/74/2bf9e78b321216d6ee90a81e5c22f912fc428442c830c4077b4a071db66f/coverage-7.8.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d766a4f0e5aa1ba056ec3496243150698dc0481902e2b8559314368717be82b1", size = 252708 }, + { url = "https://files.pythonhosted.org/packages/92/4d/50d7eb1e9a6062bee6e2f92e78b0998848a972e9afad349b6cdde6fa9e32/coverage-7.8.0-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad80e6b4a0c3cb6f10f29ae4c60e991f424e6b14219d46f1e7d442b938ee68a4", size = 255046 }, + { url = "https://files.pythonhosted.org/packages/40/9e/71fb4e7402a07c4198ab44fc564d09d7d0ffca46a9fb7b0a7b929e7641bd/coverage-7.8.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b87eb6fc9e1bb8f98892a2458781348fa37e6925f35bb6ceb9d4afd54ba36c73", size = 256139 }, + { url = "https://files.pythonhosted.org/packages/49/1a/78d37f7a42b5beff027e807c2843185961fdae7fe23aad5a4837c93f9d25/coverage-7.8.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:d1ba00ae33be84066cfbe7361d4e04dec78445b2b88bdb734d0d1cbab916025a", size = 254307 }, + { url = "https://files.pythonhosted.org/packages/58/e9/8fb8e0ff6bef5e170ee19d59ca694f9001b2ec085dc99b4f65c128bb3f9a/coverage-7.8.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f3c38e4e5ccbdc9198aecc766cedbb134b2d89bf64533973678dfcf07effd883", size = 255116 }, + { url = "https://files.pythonhosted.org/packages/56/b0/d968ecdbe6fe0a863de7169bbe9e8a476868959f3af24981f6a10d2b6924/coverage-7.8.0-cp313-cp313t-win32.whl", hash = "sha256:379fe315e206b14e21db5240f89dc0774bdd3e25c3c58c2c733c99eca96f1ada", size = 214909 }, + { url = "https://files.pythonhosted.org/packages/87/e9/d6b7ef9fecf42dfb418d93544af47c940aa83056c49e6021a564aafbc91f/coverage-7.8.0-cp313-cp313t-win_amd64.whl", hash = "sha256:2e4b6b87bb0c846a9315e3ab4be2d52fac905100565f4b92f02c445c8799e257", size = 216068 }, + { url = "https://files.pythonhosted.org/packages/60/0c/5da94be095239814bf2730a28cffbc48d6df4304e044f80d39e1ae581997/coverage-7.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fa260de59dfb143af06dcf30c2be0b200bed2a73737a8a59248fcb9fa601ef0f", size = 211377 }, + { url = "https://files.pythonhosted.org/packages/d5/cb/b9e93ebf193a0bb89dbcd4f73d7b0e6ecb7c1b6c016671950e25f041835e/coverage-7.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:96121edfa4c2dfdda409877ea8608dd01de816a4dc4a0523356067b305e4e17a", size = 211803 }, + { url = "https://files.pythonhosted.org/packages/78/1a/cdbfe9e1bb14d3afcaf6bb6e1b9ba76c72666e329cd06865bbd241efd652/coverage-7.8.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b8af63b9afa1031c0ef05b217faa598f3069148eeee6bb24b79da9012423b82", size = 240561 }, + { url = "https://files.pythonhosted.org/packages/59/04/57f1223f26ac018d7ce791bfa65b0c29282de3e041c1cd3ed430cfeac5a5/coverage-7.8.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:89b1f4af0d4afe495cd4787a68e00f30f1d15939f550e869de90a86efa7e0814", size = 238488 }, + { url = "https://files.pythonhosted.org/packages/b7/b1/0f25516ae2a35e265868670384feebe64e7857d9cffeeb3887b0197e2ba2/coverage-7.8.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94ec0be97723ae72d63d3aa41961a0b9a6f5a53ff599813c324548d18e3b9e8c", size = 239589 }, + { url = "https://files.pythonhosted.org/packages/e0/a4/99d88baac0d1d5a46ceef2dd687aac08fffa8795e4c3e71b6f6c78e14482/coverage-7.8.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8a1d96e780bdb2d0cbb297325711701f7c0b6f89199a57f2049e90064c29f6bd", size = 239366 }, + { url = "https://files.pythonhosted.org/packages/ea/9e/1db89e135feb827a868ed15f8fc857160757f9cab140ffee21342c783ceb/coverage-7.8.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:f1d8a2a57b47142b10374902777e798784abf400a004b14f1b0b9eaf1e528ba4", size = 237591 }, + { url = "https://files.pythonhosted.org/packages/1b/6d/ac4d6fdfd0e201bc82d1b08adfacb1e34b40d21a22cdd62cfaf3c1828566/coverage-7.8.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:cf60dd2696b457b710dd40bf17ad269d5f5457b96442f7f85722bdb16fa6c899", size = 238572 }, + { url = "https://files.pythonhosted.org/packages/25/5e/917cbe617c230f7f1745b6a13e780a3a1cd1cf328dbcd0fd8d7ec52858cd/coverage-7.8.0-cp39-cp39-win32.whl", hash = "sha256:be945402e03de47ba1872cd5236395e0f4ad635526185a930735f66710e1bd3f", size = 213966 }, + { url = "https://files.pythonhosted.org/packages/bd/93/72b434fe550135869f9ea88dd36068af19afce666db576e059e75177e813/coverage-7.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:90e7fbc6216ecaffa5a880cdc9c77b7418c1dcb166166b78dbc630d07f278cc3", size = 214852 }, + { url = "https://files.pythonhosted.org/packages/c4/f1/1da77bb4c920aa30e82fa9b6ea065da3467977c2e5e032e38e66f1c57ffd/coverage-7.8.0-pp39.pp310.pp311-none-any.whl", hash = "sha256:b8194fb8e50d556d5849753de991d390c5a1edeeba50f68e3a9253fbd8bf8ccd", size = 203443 }, + { url = "https://files.pythonhosted.org/packages/59/f1/4da7717f0063a222db253e7121bd6a56f6fb1ba439dcc36659088793347c/coverage-7.8.0-py3-none-any.whl", hash = "sha256:dbf364b4c5e7bae9250528167dfe40219b62e2d573c854d74be213e1e52069f7", size = 203435 }, +] + +[[package]] +name = "flake8" +version = "3.9.2" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.8'", +] +dependencies = [ + { name = "importlib-metadata", version = "6.7.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.8'" }, + { name = "mccabe", version = "0.6.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.8'" }, + { name = "pycodestyle", version = "2.7.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.8'" }, + { name = "pyflakes", version = "2.3.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.8'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9e/47/15b267dfe7e03dca4c4c06e7eadbd55ef4dfd368b13a0bab36d708b14366/flake8-3.9.2.tar.gz", hash = "sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b", size = 164777 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fc/80/35a0716e5d5101e643404dabd20f07f5528a21f3ef4032d31a49c913237b/flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907", size = 73147 }, +] + +[[package]] +name = "flake8" +version = "5.0.4" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.8' and python_full_version < '3.8.1'", +] +dependencies = [ + { name = "mccabe", version = "0.7.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.8' and python_full_version < '3.8.1'" }, + { name = "pycodestyle", version = "2.9.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.8' and python_full_version < '3.8.1'" }, + { name = "pyflakes", version = "2.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.8' and python_full_version < '3.8.1'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ad/00/9808c62b2d529cefc69ce4e4a1ea42c0f855effa55817b7327ec5b75e60a/flake8-5.0.4.tar.gz", hash = "sha256:6fbe320aad8d6b95cec8b8e47bc933004678dc63095be98528b7bdd2a9f510db", size = 145862 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cf/a0/b881b63a17a59d9d07f5c0cc91a29182c8e8a9aa2bde5b3b2b16519c02f4/flake8-5.0.4-py2.py3-none-any.whl", hash = "sha256:7a1cf6b73744f5806ab95e526f6f0d8c01c66d7bbe349562d22dfca20610b248", size = 61897 }, +] + +[[package]] +name = "flake8" +version = "7.1.2" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.8.1' and python_full_version < '3.9'", +] +dependencies = [ + { name = "mccabe", version = "0.7.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.8.1' and python_full_version < '3.9'" }, + { name = "pycodestyle", version = "2.12.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.8.1' and python_full_version < '3.9'" }, + { name = "pyflakes", version = "3.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.8.1' and python_full_version < '3.9'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/58/16/3f2a0bb700ad65ac9663262905a025917c020a3f92f014d2ba8964b4602c/flake8-7.1.2.tar.gz", hash = "sha256:c586ffd0b41540951ae41af572e6790dbd49fc12b3aa2541685d253d9bd504bd", size = 48119 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/35/f8/08d37b2cd89da306e3520bd27f8a85692122b42b56c0c2c3784ff09c022f/flake8-7.1.2-py2.py3-none-any.whl", hash = "sha256:1cbc62e65536f65e6d754dfe6f1bada7f5cf392d6f5db3c2b85892466c3e7c1a", size = 57745 }, +] + +[[package]] +name = "flake8" +version = "7.2.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.9'", +] +dependencies = [ + { name = "mccabe", version = "0.7.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "pycodestyle", version = "2.13.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "pyflakes", version = "3.3.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e7/c4/5842fc9fc94584c455543540af62fd9900faade32511fab650e9891ec225/flake8-7.2.0.tar.gz", hash = "sha256:fa558ae3f6f7dbf2b4f22663e5343b6b6023620461f8d4ff2019ef4b5ee70426", size = 48177 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/5c/0627be4c9976d56b1217cb5187b7504e7fd7d3503f8bfd312a04077bd4f7/flake8-7.2.0-py2.py3-none-any.whl", hash = "sha256:93b92ba5bdb60754a6da14fa3b93a9361fd00a59632ada61fd7b130436c40343", size = 57786 }, +] + +[[package]] +name = "importlib-metadata" +version = "6.7.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.8'", +] +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.8'" }, + { name = "zipp", version = "3.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.8'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a3/82/f6e29c8d5c098b6be61460371c2c5591f4a335923639edec43b3830650a4/importlib_metadata-6.7.0.tar.gz", hash = "sha256:1aaf550d4f73e5d6783e7acb77aec43d49da8017410afae93822cc9cca98c4d4", size = 53569 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ff/94/64287b38c7de4c90683630338cf28f129decbba0a44f0c6db35a873c73c4/importlib_metadata-6.7.0-py3-none-any.whl", hash = "sha256:cb52082e659e97afc5dac71e79de97d8681de3aa07ff18578330904a9d18e5b5", size = 22934 }, +] + +[[package]] +name = "importlib-metadata" +version = "8.5.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.8.1' and python_full_version < '3.9'", + "python_full_version >= '3.8' and python_full_version < '3.8.1'", +] +dependencies = [ + { name = "zipp", version = "3.20.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.8.*'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cd/12/33e59336dca5be0c398a7482335911a33aa0e20776128f038019f1a95f1b/importlib_metadata-8.5.0.tar.gz", hash = "sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7", size = 55304 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/d9/a1e041c5e7caa9a05c925f4bdbdfb7f006d1f74996af53467bc394c97be7/importlib_metadata-8.5.0-py3-none-any.whl", hash = "sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b", size = 26514 }, +] + +[[package]] +name = "importlib-metadata" +version = "8.6.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.9'", +] +dependencies = [ + { name = "zipp", version = "3.21.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/33/08/c1395a292bb23fd03bdf572a1357c5a733d3eecbab877641ceacab23db6e/importlib_metadata-8.6.1.tar.gz", hash = "sha256:310b41d755445d74569f993ccfc22838295d9fe005425094fad953d7f15c8580", size = 55767 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/79/9d/0fb148dc4d6fa4a7dd1d8378168d9b4cd8d4560a6fbf6f0121c5fc34eb68/importlib_metadata-8.6.1-py3-none-any.whl", hash = "sha256:02a89390c1e15fdfdc0d7c6b25cb3e62650d0494005c97d6f148bf5b9787525e", size = 26971 }, +] + +[[package]] +name = "mccabe" +version = "0.6.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.8'", +] +sdist = { url = "https://files.pythonhosted.org/packages/06/18/fa675aa501e11d6d6ca0ae73a101b2f3571a565e0f7d38e062eec18a91ee/mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f", size = 8612 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/87/89/479dc97e18549e21354893e4ee4ef36db1d237534982482c3681ee6e7b57/mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", size = 8556 }, +] + +[[package]] +name = "mccabe" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.9'", + "python_full_version >= '3.8.1' and python_full_version < '3.9'", + "python_full_version >= '3.8' and python_full_version < '3.8.1'", +] +sdist = { url = "https://files.pythonhosted.org/packages/e7/ff/0ffefdcac38932a54d2b5eed4e0ba8a408f215002cd178ad1df0f2806ff8/mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325", size = 9658 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/27/1a/1f68f9ba0c207934b35b86a8ca3aad8395a3d6dd7921c0686e23853ff5a9/mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e", size = 7350 }, +] + +[[package]] +name = "opentimelineio" +version = "0.18.0.dev1" +source = { editable = "." } +dependencies = [ + { name = "importlib-metadata", version = "6.7.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.8'" }, + { name = "importlib-metadata", version = "8.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_version < '0'" }, + { name = "importlib-metadata", version = "8.6.1", source = { registry = "https://pypi.org/simple" }, marker = "python_version < '0'" }, +] + +[package.optional-dependencies] +dev = [ + { name = "check-manifest" }, + { name = "coverage", version = "7.2.7", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.8'" }, + { name = "coverage", version = "7.6.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.8.*'" }, + { name = "coverage", version = "7.8.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "flake8", version = "3.9.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.8'" }, + { name = "flake8", version = "5.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.8' and python_full_version < '3.8.1'" }, + { name = "flake8", version = "7.1.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.8.1' and python_full_version < '3.9'" }, + { name = "flake8", version = "7.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "urllib3", version = "2.0.7", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.8'" }, + { name = "urllib3", version = "2.2.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.8.*'" }, + { name = "urllib3", version = "2.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, +] +view = [ + { name = "pyside2", marker = "platform_machine == 'x86_64'" }, + { name = "pyside6", version = "6.5.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.8' and platform_machine == 'aarch64'" }, + { name = "pyside6", version = "6.6.3.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.8.*' and platform_machine == 'aarch64'" }, + { name = "pyside6", version = "6.9.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9' and platform_machine == 'aarch64'" }, +] + +[package.metadata] +requires-dist = [ + { name = "check-manifest", marker = "extra == 'dev'" }, + { name = "coverage", marker = "extra == 'dev'", specifier = ">=4.5" }, + { name = "flake8", marker = "extra == 'dev'", specifier = ">=3.5" }, + { name = "importlib-metadata", marker = "python_full_version < '3.8'", specifier = ">=1.4" }, + { name = "pyside2", marker = "platform_machine == 'x86_64' and extra == 'view'", specifier = "~=5.11" }, + { name = "pyside6", marker = "platform_machine == 'aarch64' and extra == 'view'", specifier = "~=6.2" }, + { name = "urllib3", marker = "extra == 'dev'", specifier = ">=1.24.3" }, +] + +[[package]] +name = "packaging" +version = "24.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.8'", +] +sdist = { url = "https://files.pythonhosted.org/packages/ee/b5/b43a27ac7472e1818c4bafd44430e69605baefe1f34440593e0332ec8b4d/packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9", size = 147882 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/49/df/1fceb2f8900f8639e278b056416d49134fb8d84c5942ffaa01ad34782422/packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5", size = 53488 }, +] + +[[package]] +name = "packaging" +version = "25.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.9'", + "python_full_version >= '3.8.1' and python_full_version < '3.9'", + "python_full_version >= '3.8' and python_full_version < '3.8.1'", +] +sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469 }, +] + +[[package]] +name = "pycodestyle" +version = "2.7.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.8'", +] +sdist = { url = "https://files.pythonhosted.org/packages/02/b3/c832123f2699892c715fcdfebb1a8fdeffa11bb7b2350e46ecdd76b45a20/pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef", size = 103640 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/de/cc/227251b1471f129bc35e966bb0fceb005969023926d744139642d847b7ae/pycodestyle-2.7.0-py2.py3-none-any.whl", hash = "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068", size = 41725 }, +] + +[[package]] +name = "pycodestyle" +version = "2.9.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.8' and python_full_version < '3.8.1'", +] +sdist = { url = "https://files.pythonhosted.org/packages/b6/83/5bcaedba1f47200f0665ceb07bcb00e2be123192742ee0edfb66b600e5fd/pycodestyle-2.9.1.tar.gz", hash = "sha256:2c9607871d58c76354b697b42f5d57e1ada7d261c261efac224b664affdc5785", size = 102127 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/67/e4/fc77f1039c34b3612c4867b69cbb2b8a4e569720b1f19b0637002ee03aff/pycodestyle-2.9.1-py2.py3-none-any.whl", hash = "sha256:d1735fc58b418fd7c5f658d28d943854f8a849b01a5d0a1e6f3f3fdd0166804b", size = 41493 }, +] + +[[package]] +name = "pycodestyle" +version = "2.12.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.8.1' and python_full_version < '3.9'", +] +sdist = { url = "https://files.pythonhosted.org/packages/43/aa/210b2c9aedd8c1cbeea31a50e42050ad56187754b34eb214c46709445801/pycodestyle-2.12.1.tar.gz", hash = "sha256:6838eae08bbce4f6accd5d5572075c63626a15ee3e6f842df996bf62f6d73521", size = 39232 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3a/d8/a211b3f85e99a0daa2ddec96c949cac6824bd305b040571b82a03dd62636/pycodestyle-2.12.1-py2.py3-none-any.whl", hash = "sha256:46f0fb92069a7c28ab7bb558f05bfc0110dac69a0cd23c61ea0040283a9d78b3", size = 31284 }, +] + +[[package]] +name = "pycodestyle" +version = "2.13.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.9'", +] +sdist = { url = "https://files.pythonhosted.org/packages/04/6e/1f4a62078e4d95d82367f24e685aef3a672abfd27d1a868068fed4ed2254/pycodestyle-2.13.0.tar.gz", hash = "sha256:c8415bf09abe81d9c7f872502a6eee881fbe85d8763dd5b9924bb0a01d67efae", size = 39312 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/07/be/b00116df1bfb3e0bb5b45e29d604799f7b91dd861637e4d448b4e09e6a3e/pycodestyle-2.13.0-py2.py3-none-any.whl", hash = "sha256:35863c5974a271c7a726ed228a14a4f6daf49df369d8c50cd9a6f58a5e143ba9", size = 31424 }, +] + +[[package]] +name = "pyflakes" +version = "2.3.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.8'", +] +sdist = { url = "https://files.pythonhosted.org/packages/a8/0f/0dc480da9162749bf629dca76570972dd9cce5bedc60196a3c912875c87d/pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db", size = 68567 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6c/11/2a745612f1d3cbbd9c69ba14b1b43a35a2f5c3c81cd0124508c52c64307f/pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3", size = 68805 }, +] + +[[package]] +name = "pyflakes" +version = "2.5.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.8' and python_full_version < '3.8.1'", +] +sdist = { url = "https://files.pythonhosted.org/packages/07/92/f0cb5381f752e89a598dd2850941e7f570ac3cb8ea4a344854de486db152/pyflakes-2.5.0.tar.gz", hash = "sha256:491feb020dca48ccc562a8c0cbe8df07ee13078df59813b83959cbdada312ea3", size = 66388 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/dc/13/63178f59f74e53acc2165aee4b002619a3cfa7eeaeac989a9eb41edf364e/pyflakes-2.5.0-py2.py3-none-any.whl", hash = "sha256:4579f67d887f804e67edb544428f264b7b24f435b263c4614f384135cea553d2", size = 66116 }, +] + +[[package]] +name = "pyflakes" +version = "3.2.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.8.1' and python_full_version < '3.9'", +] +sdist = { url = "https://files.pythonhosted.org/packages/57/f9/669d8c9c86613c9d568757c7f5824bd3197d7b1c6c27553bc5618a27cce2/pyflakes-3.2.0.tar.gz", hash = "sha256:1c61603ff154621fb2a9172037d84dca3500def8c8b630657d1701f026f8af3f", size = 63788 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d4/d7/f1b7db88d8e4417c5d47adad627a93547f44bdc9028372dbd2313f34a855/pyflakes-3.2.0-py2.py3-none-any.whl", hash = "sha256:84b5be138a2dfbb40689ca07e2152deb896a65c3a3e24c251c5c62489568074a", size = 62725 }, +] + +[[package]] +name = "pyflakes" +version = "3.3.2" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.9'", +] +sdist = { url = "https://files.pythonhosted.org/packages/af/cc/1df338bd7ed1fa7c317081dcf29bf2f01266603b301e6858856d346a12b3/pyflakes-3.3.2.tar.gz", hash = "sha256:6dfd61d87b97fba5dcfaaf781171ac16be16453be6d816147989e7f6e6a9576b", size = 64175 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/15/40/b293a4fa769f3b02ab9e387c707c4cbdc34f073f945de0386107d4e669e6/pyflakes-3.3.2-py2.py3-none-any.whl", hash = "sha256:5039c8339cbb1944045f4ee5466908906180f13cc99cc9949348d10f82a5c32a", size = 63164 }, +] + +[[package]] +name = "pyproject-hooks" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/82/28175b2414effca1cdac8dc99f76d660e7a4fb0ceefa4b4ab8f5f6742925/pyproject_hooks-1.2.0.tar.gz", hash = "sha256:1e859bd5c40fae9448642dd871adf459e5e2084186e8d2c2a79a824c970da1f8", size = 19228 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl", hash = "sha256:9e5c6bfa8dcc30091c74b0cf803c81fdd29d94f01992a7707bc97babb1141913", size = 10216 }, +] + +[[package]] +name = "pyside2" +version = "5.15.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "shiboken2" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/1b/1f/194ed3a9c79abe4d8e8800112d5c19d0b9d7a1aca8b10029043bb3a083d0/PySide2-5.15.2.1-5.15.2-cp35.cp36.cp37.cp38.cp39.cp310-abi3-macosx_10_13_intel.whl", hash = "sha256:a9e2e6bbcb5d2ebb421e46e72244a0f4fe0943b2288115f80a863aacc1de1f06", size = 148464754 }, + { url = "https://files.pythonhosted.org/packages/c2/9a/78ca8bada6cf4d2798e0c823c025c590517d74445837f4eb50bfddce8737/PySide2-5.15.2.1-5.15.2-cp35.cp36.cp37.cp38.cp39.cp310-abi3-manylinux1_x86_64.whl", hash = "sha256:23886c6391ebd916e835fa1b5ae66938048504fd3a2934ae3189a96cd5ac0b46", size = 164306859 }, + { url = "https://files.pythonhosted.org/packages/ed/5e/d0d540385dcc5eeda877a4288a9a4970e0e7b2282e840c2b08ce5442542e/PySide2-5.15.2.1-5.15.2-cp35.cp36.cp37.cp38.cp39.cp310-none-win_amd64.whl", hash = "sha256:af6b263fe63ba6dea7eaebae80aa7b291491fe66f4f0057c0aafe780cc83da9d", size = 137370554 }, +] + +[[package]] +name = "pyside6" +version = "6.5.3" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.8'", +] +dependencies = [ + { name = "pyside6-addons", version = "6.5.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.8'" }, + { name = "pyside6-essentials", version = "6.5.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.8'" }, + { name = "shiboken6", version = "6.5.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.8'" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/33/d1/c6b70c34058e430a50c660dd6abca52cb9a8822ad9dd9e3ac9056fa686ea/PySide6-6.5.3-cp37-abi3-macosx_11_0_universal2.whl", hash = "sha256:be53e7c64710fc4307afd33147e241a06cd97b18fae887ee611d8d4b373dbb04", size = 6696 }, + { url = "https://files.pythonhosted.org/packages/3a/38/188ab0f2bdb7ec611633a724eeecc4f2176a13257b4283a521af7f5ef50d/PySide6-6.5.3-cp37-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:48f4579ca49225cfff8f512178551bdf6aa9031198527f71799bcc061a0f2327", size = 6668 }, +] + +[[package]] +name = "pyside6" +version = "6.6.3.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.8.1' and python_full_version < '3.9'", + "python_full_version >= '3.8' and python_full_version < '3.8.1'", +] +dependencies = [ + { name = "pyside6-addons", version = "6.6.3.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.8.*'" }, + { name = "pyside6-essentials", version = "6.6.3.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.8.*'" }, + { name = "shiboken6", version = "6.6.3.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.8.*'" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/ba/9a/3483d05305701ba810192572cee5977ff884c033a1b8f96ab9582d81ccd4/PySide6-6.6.3.1-cp38-abi3-macosx_11_0_universal2.whl", hash = "sha256:3d2ebb08a7744b59e1270e57f264a9ef5b45fccdc0328a9aeb50d890d6b3f4f2", size = 512759 }, + { url = "https://files.pythonhosted.org/packages/51/3e/b77d2b9a1efcb5c90a2df4f51eb10bce45b3787c4fa16b69c599fd6620b9/PySide6-6.6.3.1-cp38-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:f7acd26fe8e1a745ef0be66b49ee49ee8ae50c2a2855d9792db262ebc7916d98", size = 513326 }, +] + +[[package]] +name = "pyside6" +version = "6.9.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.9'", +] +dependencies = [ + { name = "pyside6-addons", version = "6.9.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "pyside6-essentials", version = "6.9.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "shiboken6", version = "6.9.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/46/74/0b465aa77644cfc3bfde912bb999b5a441d92c699272cab722335e92df3e/PySide6-6.9.0-cp39-abi3-macosx_12_0_universal2.whl", hash = "sha256:b8f286a1bd143f3b2bdf08367b9362b13f469d26986c25700af9c4c68f79213e", size = 558001 }, + { url = "https://files.pythonhosted.org/packages/4b/54/41d6ab0847c043f1fd96433a87ffd09a7cf17e11f5587e91e152777ec010/PySide6-6.9.0-cp39-abi3-manylinux_2_39_aarch64.whl", hash = "sha256:1a176409dd0dd12b72d2c78b776e5051f569071ec52b7aaadd0a5b3333493c24", size = 558139 }, + { url = "https://files.pythonhosted.org/packages/e8/80/340523ecb17d2a168d7e37dfd8a7a0eebb81dcbec4870447f132f2a1a28e/PySide6-6.9.0-cp39-abi3-win_arm64.whl", hash = "sha256:846fbccf0b3501eb31cf0791a46e137615efba6ce540da2b426d79fa3e7762c4", size = 401752 }, +] + +[[package]] +name = "pyside6-addons" +version = "6.5.3" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.8'", +] +dependencies = [ + { name = "pyside6-essentials", version = "6.5.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.8'" }, + { name = "shiboken6", version = "6.5.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.8'" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/12/12/ac0cc675e2f87d2bad9cbb85c1d2d27e6621ebbf126f45314750225dbfaa/PySide6_Addons-6.5.3-cp37-abi3-macosx_11_0_universal2.whl", hash = "sha256:047162b158ee929d43c21cdc3ac48e75fec612f2e5492b317190fac98d2de5c6", size = 255695967 }, + { url = "https://files.pythonhosted.org/packages/98/50/ffada8eb16c505de785ffb7ee8eced8f2872dfd2509d9a94344000944769/PySide6_Addons-6.5.3-cp37-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:be0dcfb15d44c2973c3c122058f1df8c3c9d93abd4170534e06dbf986aa30e26", size = 111616302 }, +] + +[[package]] +name = "pyside6-addons" +version = "6.6.3.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.8.1' and python_full_version < '3.9'", + "python_full_version >= '3.8' and python_full_version < '3.8.1'", +] +dependencies = [ + { name = "pyside6-essentials", version = "6.6.3.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.8.*'" }, + { name = "shiboken6", version = "6.6.3.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.8.*'" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/5f/43/b4d9264969552450c2e889450908279302360901b530f3ec3eb1154db5bf/PySide6_Addons-6.6.3.1-cp38-abi3-macosx_11_0_universal2.whl", hash = "sha256:31135adc521ed6e3fdc8203507e7e9d72424d6b9ebd245d1189d991e90669d6a", size = 250159667 }, + { url = "https://files.pythonhosted.org/packages/9e/52/d56c3380f300b14f26be8eaf98af71a128e7e7952a2b3f4c8b24b1547e0a/PySide6_Addons-6.6.3.1-cp38-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:3abdc1e21de0c6763e5392af5ed8b2349291318ce235e7c310d84a2f9d5001a9", size = 111711166 }, +] + +[[package]] +name = "pyside6-addons" +version = "6.9.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.9'", +] +dependencies = [ + { name = "pyside6-essentials", version = "6.9.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "shiboken6", version = "6.9.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/e8/a4/211077b3f30342827b2c543f80a5f6bc483ff3af6be99766984618e68fb6/PySide6_Addons-6.9.0-cp39-abi3-macosx_12_0_universal2.whl", hash = "sha256:98f9ad4b65820736e12d49c18db2e570eac63727407fbb59a62ac753e89dc201", size = 315606763 }, + { url = "https://files.pythonhosted.org/packages/85/c3/add4948cf15648db542531a5c292f9de946ee288243730be7607499936ec/PySide6_Addons-6.9.0-cp39-abi3-manylinux_2_39_aarch64.whl", hash = "sha256:d8a650644e0b9d1e7a092f6bcd11f25a63706d12f77d442b6ace75d346ab5d30", size = 161938789 }, + { url = "https://files.pythonhosted.org/packages/29/aa/810ceb3d111fa6a0cc865520e05198dd0cad4855558c8c8309d4d3852854/PySide6_Addons-6.9.0-cp39-abi3-win_arm64.whl", hash = "sha256:260a56da59539f476c1635a3ff13591e10f1b04d92155c0617129bc53ca8b5f8", size = 26840861 }, +] + +[[package]] +name = "pyside6-essentials" +version = "6.5.3" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.8'", +] +dependencies = [ + { name = "shiboken6", version = "6.5.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.8'" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/9f/36/11fba6e89f6722dffde316b9388ba2797bbfce6f1f568d3ebe203bd2713f/PySide6_Essentials-6.5.3-cp37-abi3-macosx_11_0_universal2.whl", hash = "sha256:4d9c95ded938e557052fc67efe68d57108856df141a1b499497fd7999419e3eb", size = 144783530 }, + { url = "https://files.pythonhosted.org/packages/f9/b7/1795227e5a91dbb872661783217d54e538f25d00c351be7aed5c309d212a/PySide6_Essentials-6.5.3-cp37-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:8244bc185b0243ba7c4491033e592b247e44a63d69213e9a45ee38e87e0f1f90", size = 79277698 }, +] + +[[package]] +name = "pyside6-essentials" +version = "6.6.3.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.8.1' and python_full_version < '3.9'", + "python_full_version >= '3.8' and python_full_version < '3.8.1'", +] +dependencies = [ + { name = "shiboken6", version = "6.6.3.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.8.*'" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/47/69e1c0dd4305a30e01e54257fe08d7719da0464b1e2bd351d23831c0018c/PySide6_Essentials-6.6.3.1-cp38-abi3-macosx_11_0_universal2.whl", hash = "sha256:6c16530b63079711783796584b640cc80a347e0b2dc12651aa2877265df7a008", size = 147274572 }, + { url = "https://files.pythonhosted.org/packages/0f/2c/d6c6102a1a803f0619932996fed59c90429a09850a2b8c19f44f92dd4189/PySide6_Essentials-6.6.3.1-cp38-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:27034525fdbdd21ef21f20fcd7aaf5c2ffe26f2bcf5269a69dd9492dec7e92aa", size = 66881609 }, +] + +[[package]] +name = "pyside6-essentials" +version = "6.9.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.9'", +] +dependencies = [ + { name = "shiboken6", version = "6.9.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/98/ac/a3c8097d6fdcf414d961bdc0d532381d0ee141e4c699f5e2b881a7c3613f/PySide6_Essentials-6.9.0-cp39-abi3-macosx_12_0_universal2.whl", hash = "sha256:b18e3e01b507e8a57481fe19792eb373d5f10a23a50702ce540da1435e722f39", size = 131981893 }, + { url = "https://files.pythonhosted.org/packages/ff/f1/72e1d400017a658e271594c8bd9c447c623dfd4fb936f4e043a4f9a8c93b/PySide6_Essentials-6.9.0-cp39-abi3-manylinux_2_39_aarch64.whl", hash = "sha256:69aedfad77119c5bec0005ca31d5620e9bac8ba5ae66c7389160530cfd698ed8", size = 92102516 }, + { url = "https://files.pythonhosted.org/packages/49/a4/703e379a0979985f681cf04b9af4129f5dde20141b3cc64fc2a39d006614/PySide6_Essentials-6.9.0-cp39-abi3-win_arm64.whl", hash = "sha256:d2dc45536f2269ad111991042e81257124f1cd1c9ed5ea778d7224fd65dc9e2b", size = 49449220 }, +] + +[[package]] +name = "setuptools" +version = "68.0.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.8'", +] +sdist = { url = "https://files.pythonhosted.org/packages/dc/98/5f896af066c128669229ff1aa81553ac14cfb3e5e74b6b44594132b8540e/setuptools-68.0.0.tar.gz", hash = "sha256:baf1fdb41c6da4cd2eae722e135500da913332ab3f2f5c7d33af9b492acb5235", size = 2194111 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/42/be1c7bbdd83e1bfb160c94b9cafd8e25efc7400346cf7ccdbdb452c467fa/setuptools-68.0.0-py3-none-any.whl", hash = "sha256:11e52c67415a381d10d6b462ced9cfb97066179f0e871399e006c4ab101fc85f", size = 804037 }, +] + +[[package]] +name = "setuptools" +version = "75.3.2" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.8.1' and python_full_version < '3.9'", + "python_full_version >= '3.8' and python_full_version < '3.8.1'", +] +sdist = { url = "https://files.pythonhosted.org/packages/5c/01/771ea46cce201dd42cff043a5eea929d1c030fb3d1c2ee2729d02ca7814c/setuptools-75.3.2.tar.gz", hash = "sha256:3c1383e1038b68556a382c1e8ded8887cd20141b0eb5708a6c8d277de49364f5", size = 1354489 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/15/65/3f0dba35760d902849d39d38c0a72767794b1963227b69a587f8a336d08c/setuptools-75.3.2-py3-none-any.whl", hash = "sha256:90ab613b6583fc02d5369cbca13ea26ea0e182d1df2d943ee9cbe81d4c61add9", size = 1251198 }, +] + +[[package]] +name = "setuptools" +version = "79.0.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.9'", +] +sdist = { url = "https://files.pythonhosted.org/packages/bb/71/b6365e6325b3290e14957b2c3a804a529968c77a049b2ed40c095f749707/setuptools-79.0.1.tar.gz", hash = "sha256:128ce7b8f33c3079fd1b067ecbb4051a66e8526e7b65f6cec075dfc650ddfa88", size = 1367909 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0d/6d/b4752b044bf94cb802d88a888dc7d288baaf77d7910b7dedda74b5ceea0c/setuptools-79.0.1-py3-none-any.whl", hash = "sha256:e147c0549f27767ba362f9da434eab9c5dc0045d5304feb602a0af001089fc51", size = 1256281 }, +] + +[[package]] +name = "shiboken2" +version = "5.15.2.1" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/34/bb/7bad766088a8ccb6512c5d5d1520a51fcc9221b3ec371b134d14d1b269a5/shiboken2-5.15.2.1-5.15.2-cp35.cp36.cp37.cp38.cp39.cp310-abi3-macosx_10_13_intel.whl", hash = "sha256:ffd3d0ec3d508e592d7ee3885d27fee1f279a49989f734eb130f46d9501273a9", size = 958579 }, + { url = "https://files.pythonhosted.org/packages/a6/0e/c1953bb08f45e0f1703e7dc153e9c94ba3042c282ebcd94cada385a9cdb3/shiboken2-5.15.2.1-5.15.2-cp35.cp36.cp37.cp38.cp39.cp310-abi3-manylinux1_x86_64.whl", hash = "sha256:63debfcc531b6a2b4985aa9b71433d2ad3bac542acffc729cc0ecaa3854390c0", size = 975428 }, + { url = "https://files.pythonhosted.org/packages/26/bd/a1b31f49eb35888eae318c27327732b1036f0d921e5c8ec2e7a4276e7445/shiboken2-5.15.2.1-5.15.2-cp35.cp36.cp37.cp38.cp39.cp310-none-win_amd64.whl", hash = "sha256:a0d0fdeb12b72c8af349b9642ccc67afd783dca449309f45e78cda50272fd6b7", size = 2321148 }, +] + +[[package]] +name = "shiboken6" +version = "6.5.3" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.8'", +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/3b/24/a2827883abbe6277888c56c424d1c0bc6e434a5ae574e0a5baa89ccb85bf/shiboken6-6.5.3-cp37-abi3-macosx_11_0_universal2.whl", hash = "sha256:faaca92dcbbf26c0ae13f189746c38482e40859e0897b0ed4dee5e04f69fda71", size = 345886 }, + { url = "https://files.pythonhosted.org/packages/b1/20/c348ff897043ab5a8128b95cae35945a5d901b4b0e462c4de29270d68533/shiboken6-6.5.3-cp37-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:1bc928ca9f1c1d16ff8fe0585627738a15552bb3329c04fca2c74a443618a6b3", size = 164234 }, +] + +[[package]] +name = "shiboken6" +version = "6.6.3.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.8.1' and python_full_version < '3.9'", + "python_full_version >= '3.8' and python_full_version < '3.8.1'", +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/af/fb/183b7889168f44b19526f58c571b88e23375150abcbd5b603dd3a288ef7a/shiboken6-6.6.3.1-cp38-abi3-macosx_11_0_universal2.whl", hash = "sha256:2a8df586aa9eb629388b368d3157893083c5217ed3eb637bf182d1948c823a0f", size = 345925 }, + { url = "https://files.pythonhosted.org/packages/b9/03/e71f0f3fc35fcc90265d1345e3afa509bbd2d6bb305c6e78427a9b27efea/shiboken6-6.6.3.1-cp38-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:902d9e126ac57cc3841cdc50ba38d53948b40cf667538172f253c4ae7b2dcb2c", size = 162427 }, +] + +[[package]] +name = "shiboken6" +version = "6.9.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.9'", +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/be/85/97b36b045a233bcea9580e8c99d5c76d65cf9727dad8cb173527f6717471/shiboken6-6.9.0-cp39-abi3-macosx_12_0_universal2.whl", hash = "sha256:c4d8e3a5907154ac4789e52c77957db95bcf584238c244d7743cb39e9b66dd26", size = 407067 }, + { url = "https://files.pythonhosted.org/packages/0d/59/6a91aad272fe89bf2293b7864fb6e926822c93a2f6192611528c6945196d/shiboken6-6.9.0-cp39-abi3-manylinux_2_39_aarch64.whl", hash = "sha256:b61579b90bf9c53ecc174085a69429166dfe57a0b8b894f933d1281af9df6568", size = 202809 }, + { url = "https://files.pythonhosted.org/packages/b5/01/d59babab05786c99ebabdd152864ea3d4c500160979952c620eec68b1ff2/shiboken6-6.9.0-cp39-abi3-win_arm64.whl", hash = "sha256:24f53857458881b54798d7e35704611d07f6b6885bcdf80f13a4c8bb485b8df2", size = 1831261 }, +] + +[[package]] +name = "tomli" +version = "2.0.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.8'", +] +sdist = { url = "https://files.pythonhosted.org/packages/c0/3f/d7af728f075fb08564c5949a9c95e44352e23dee646869fa104a3b2060a3/tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f", size = 15164 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/97/75/10a9ebee3fd790d20926a90a2547f0bf78f371b2f13aa822c759680ca7b9/tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", size = 12757 }, +] + +[[package]] +name = "tomli" +version = "2.2.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.9'", + "python_full_version >= '3.8.1' and python_full_version < '3.9'", + "python_full_version >= '3.8' and python_full_version < '3.8.1'", +] +sdist = { url = "https://files.pythonhosted.org/packages/18/87/302344fed471e44a87289cf4967697d07e532f2421fdaf868a303cbae4ff/tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff", size = 17175 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/43/ca/75707e6efa2b37c77dadb324ae7d9571cb424e61ea73fad7c56c2d14527f/tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249", size = 131077 }, + { url = "https://files.pythonhosted.org/packages/c7/16/51ae563a8615d472fdbffc43a3f3d46588c264ac4f024f63f01283becfbb/tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6", size = 123429 }, + { url = "https://files.pythonhosted.org/packages/f1/dd/4f6cd1e7b160041db83c694abc78e100473c15d54620083dbd5aae7b990e/tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a", size = 226067 }, + { url = "https://files.pythonhosted.org/packages/a9/6b/c54ede5dc70d648cc6361eaf429304b02f2871a345bbdd51e993d6cdf550/tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee", size = 236030 }, + { url = "https://files.pythonhosted.org/packages/1f/47/999514fa49cfaf7a92c805a86c3c43f4215621855d151b61c602abb38091/tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e", size = 240898 }, + { url = "https://files.pythonhosted.org/packages/73/41/0a01279a7ae09ee1573b423318e7934674ce06eb33f50936655071d81a24/tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4", size = 229894 }, + { url = "https://files.pythonhosted.org/packages/55/18/5d8bc5b0a0362311ce4d18830a5d28943667599a60d20118074ea1b01bb7/tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106", size = 245319 }, + { url = "https://files.pythonhosted.org/packages/92/a3/7ade0576d17f3cdf5ff44d61390d4b3febb8a9fc2b480c75c47ea048c646/tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8", size = 238273 }, + { url = "https://files.pythonhosted.org/packages/72/6f/fa64ef058ac1446a1e51110c375339b3ec6be245af9d14c87c4a6412dd32/tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff", size = 98310 }, + { url = "https://files.pythonhosted.org/packages/6a/1c/4a2dcde4a51b81be3530565e92eda625d94dafb46dbeb15069df4caffc34/tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b", size = 108309 }, + { url = "https://files.pythonhosted.org/packages/52/e1/f8af4c2fcde17500422858155aeb0d7e93477a0d59a98e56cbfe75070fd0/tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea", size = 132762 }, + { url = "https://files.pythonhosted.org/packages/03/b8/152c68bb84fc00396b83e7bbddd5ec0bd3dd409db4195e2a9b3e398ad2e3/tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8", size = 123453 }, + { url = "https://files.pythonhosted.org/packages/c8/d6/fc9267af9166f79ac528ff7e8c55c8181ded34eb4b0e93daa767b8841573/tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192", size = 233486 }, + { url = "https://files.pythonhosted.org/packages/5c/51/51c3f2884d7bab89af25f678447ea7d297b53b5a3b5730a7cb2ef6069f07/tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222", size = 242349 }, + { url = "https://files.pythonhosted.org/packages/ab/df/bfa89627d13a5cc22402e441e8a931ef2108403db390ff3345c05253935e/tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77", size = 252159 }, + { url = "https://files.pythonhosted.org/packages/9e/6e/fa2b916dced65763a5168c6ccb91066f7639bdc88b48adda990db10c8c0b/tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6", size = 237243 }, + { url = "https://files.pythonhosted.org/packages/b4/04/885d3b1f650e1153cbb93a6a9782c58a972b94ea4483ae4ac5cedd5e4a09/tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd", size = 259645 }, + { url = "https://files.pythonhosted.org/packages/9c/de/6b432d66e986e501586da298e28ebeefd3edc2c780f3ad73d22566034239/tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e", size = 244584 }, + { url = "https://files.pythonhosted.org/packages/1c/9a/47c0449b98e6e7d1be6cbac02f93dd79003234ddc4aaab6ba07a9a7482e2/tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98", size = 98875 }, + { url = "https://files.pythonhosted.org/packages/ef/60/9b9638f081c6f1261e2688bd487625cd1e660d0a85bd469e91d8db969734/tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4", size = 109418 }, + { url = "https://files.pythonhosted.org/packages/04/90/2ee5f2e0362cb8a0b6499dc44f4d7d48f8fff06d28ba46e6f1eaa61a1388/tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7", size = 132708 }, + { url = "https://files.pythonhosted.org/packages/c0/ec/46b4108816de6b385141f082ba99e315501ccd0a2ea23db4a100dd3990ea/tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c", size = 123582 }, + { url = "https://files.pythonhosted.org/packages/a0/bd/b470466d0137b37b68d24556c38a0cc819e8febe392d5b199dcd7f578365/tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13", size = 232543 }, + { url = "https://files.pythonhosted.org/packages/d9/e5/82e80ff3b751373f7cead2815bcbe2d51c895b3c990686741a8e56ec42ab/tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281", size = 241691 }, + { url = "https://files.pythonhosted.org/packages/05/7e/2a110bc2713557d6a1bfb06af23dd01e7dde52b6ee7dadc589868f9abfac/tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272", size = 251170 }, + { url = "https://files.pythonhosted.org/packages/64/7b/22d713946efe00e0adbcdfd6d1aa119ae03fd0b60ebed51ebb3fa9f5a2e5/tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140", size = 236530 }, + { url = "https://files.pythonhosted.org/packages/38/31/3a76f67da4b0cf37b742ca76beaf819dca0ebef26d78fc794a576e08accf/tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2", size = 258666 }, + { url = "https://files.pythonhosted.org/packages/07/10/5af1293da642aded87e8a988753945d0cf7e00a9452d3911dd3bb354c9e2/tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744", size = 243954 }, + { url = "https://files.pythonhosted.org/packages/5b/b9/1ed31d167be802da0fc95020d04cd27b7d7065cc6fbefdd2f9186f60d7bd/tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec", size = 98724 }, + { url = "https://files.pythonhosted.org/packages/c7/32/b0963458706accd9afcfeb867c0f9175a741bf7b19cd424230714d722198/tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69", size = 109383 }, + { url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", size = 14257 }, +] + +[[package]] +name = "typing-extensions" +version = "4.7.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3c/8b/0111dd7d6c1478bf83baa1cab85c686426c7a6274119aceb2bd9d35395ad/typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2", size = 72876 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/6b/63cc3df74987c36fe26157ee12e09e8f9db4de771e0f3404263117e75b95/typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36", size = 33232 }, +] + +[[package]] +name = "urllib3" +version = "2.0.7" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.8'", +] +sdist = { url = "https://files.pythonhosted.org/packages/af/47/b215df9f71b4fdba1025fc05a77db2ad243fa0926755a52c5e71659f4e3c/urllib3-2.0.7.tar.gz", hash = "sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84", size = 282546 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/b2/b157855192a68541a91ba7b2bbcb91f1b4faa51f8bae38d8005c034be524/urllib3-2.0.7-py3-none-any.whl", hash = "sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e", size = 124213 }, +] + +[[package]] +name = "urllib3" +version = "2.2.3" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.8.1' and python_full_version < '3.9'", + "python_full_version >= '3.8' and python_full_version < '3.8.1'", +] +sdist = { url = "https://files.pythonhosted.org/packages/ed/63/22ba4ebfe7430b76388e7cd448d5478814d3032121827c12a2cc287e2260/urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9", size = 300677 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/d9/5f4c13cecde62396b0d3fe530a50ccea91e7dfc1ccf0e09c228841bb5ba8/urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac", size = 126338 }, +] + +[[package]] +name = "urllib3" +version = "2.4.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.9'", +] +sdist = { url = "https://files.pythonhosted.org/packages/8a/78/16493d9c386d8e60e442a35feac5e00f0913c0f4b7c217c11e8ec2ff53e0/urllib3-2.4.0.tar.gz", hash = "sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466", size = 390672 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6b/11/cc635220681e93a0183390e26485430ca2c7b5f9d33b15c74c2861cb8091/urllib3-2.4.0-py3-none-any.whl", hash = "sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813", size = 128680 }, +] + +[[package]] +name = "zipp" +version = "3.15.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.8'", +] +sdist = { url = "https://files.pythonhosted.org/packages/00/27/f0ac6b846684cecce1ee93d32450c45ab607f65c2e0255f0092032d91f07/zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b", size = 18454 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5b/fa/c9e82bbe1af6266adf08afb563905eb87cab83fde00a0a08963510621047/zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556", size = 6758 }, +] + +[[package]] +name = "zipp" +version = "3.20.2" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.8.1' and python_full_version < '3.9'", + "python_full_version >= '3.8' and python_full_version < '3.8.1'", +] +sdist = { url = "https://files.pythonhosted.org/packages/54/bf/5c0000c44ebc80123ecbdddba1f5dcd94a5ada602a9c225d84b5aaa55e86/zipp-3.20.2.tar.gz", hash = "sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29", size = 24199 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/8b/5ba542fa83c90e09eac972fc9baca7a88e7e7ca4b221a89251954019308b/zipp-3.20.2-py3-none-any.whl", hash = "sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350", size = 9200 }, +] + +[[package]] +name = "zipp" +version = "3.21.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.9'", +] +sdist = { url = "https://files.pythonhosted.org/packages/3f/50/bad581df71744867e9468ebd0bcd6505de3b275e06f202c2cb016e3ff56f/zipp-3.21.0.tar.gz", hash = "sha256:2c9958f6430a2040341a52eb608ed6dd93ef4392e02ffe219417c1b28b5dd1f4", size = 24545 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/1a/7e4798e9339adc931158c9d69ecc34f5e6791489d469f5e50ec15e35f458/zipp-3.21.0-py3-none-any.whl", hash = "sha256:ac1bbe05fd2991f160ebce24ffbac5f6d11d83dc90891255885223d42b3cd931", size = 9630 }, +]