diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 00000000..e69de29b diff --git a/index.html b/index.html new file mode 100644 index 00000000..17ade5bc --- /dev/null +++ b/index.html @@ -0,0 +1,11 @@ + + + + SPDL + + +

Redirecting to the main document.

+ + diff --git a/main/_sources/api.rst.txt b/main/_sources/api.rst.txt new file mode 100644 index 00000000..11e22c3b --- /dev/null +++ b/main/_sources/api.rst.txt @@ -0,0 +1,13 @@ +API Reference +============= + +.. autosummary:: + :toctree: generated + :template: _custom_autosummary_module.rst + :caption: API Reference + :recursive: + + spdl.io + spdl.pipeline + spdl.dataloader + spdl.utils diff --git a/main/_sources/best_practice.rst.txt b/main/_sources/best_practice.rst.txt new file mode 100644 index 00000000..64d2d8b7 --- /dev/null +++ b/main/_sources/best_practice.rst.txt @@ -0,0 +1,133 @@ +Best Practices +============== + +Avoid creating intermediate tensors +----------------------------------- + +For efficient and performant data processing, it is advised to not create +an intermediate Tensor for each individual media object (such as single image), +instead create a batch Tensor directly. + +We recommend decoding individual frames, then using :py:func:`spdl.io.convert_frames` +to create a batch Tensor directly without creating an intermediate Tensors. + +If you are decoding a batch of images, and you have pre-determined set of images +that should go together into a same batch, use +:py:func:`spdl.io.load_image_batch` (or its async variant +:py:func:`spdl.io.async_load_image_batch`). + +Otherwise, demux, decode and pre-process multiple media, then combine them with +:py:func:`spdl.io.convert_frames` (or :py:func:`spdl.io.async_convert_frames`). +For example, the following functions implement decoding and tensor creation +separately. + +.. code-block:: + + import spdl.io + from spdl.io import ImageFrames + + def decode_image(src: str) -> ImageFrames: + packets = spdl.io.async_demux_image(src) + return spdl.io.async_decode_packets(packets) + + def batchify(frames: list[ImageFrames]) -> ImageFrames: + buffer = spdl.io.convert_frames(frames) + return spdl.io.to_torch(buffer) + +They can be combined in :py:class:`~spdl.pipeline.Pipeline`, which automatically +discards the items failed to process (for example due to invalid data), and +keep the batch size consistent by using other items successfully processed. + +.. code-block:: + + from spdl.pipeline import PipelineBuilder + + pipeline = ( + PipelineBuilder() + .add_source(...) + .pipe(decode_image, concurrency=...) + .aggregate(32) + .pipe(batchify) + .add_sink(3) + .build(num_threads=...) + ) + +.. seealso:: + + :py:mod:`multi_thread_preprocessing` + +Make Dataset class composable +----------------------------- + +If you are publishing a dataset and providing an implementation of +`Dataset` class, we recommend to make it composable. + +That is, in addition to the conventional ``Dataset`` class that +returns Tensors, make the components of the ``Dataset`` +implementation available by breaking down the implementation into + +* Iterator (or map) interface that returns paths instead of Tensors. +* A helper function that loads the source path into Tensor. + +For example, the interface of a ``Dataset`` for image classification +might look like the following. + +.. code-block:: + + class Dataset: + def __getitem__(self, key: int) -> tuple[Tensor, int]: + ... + +We recommend to separate the source and process and make them additional +public interface. +(Also, as described above, we recommend to not convert each item into +``Tensor`` for the performance reasons.) + +.. code-block:: + + class Source: + def __getitem__(self, key: int) -> tuple[str, int]: + ... + + def load(data: tuple[str, int]) -> tuple[ImageFrames, int]: + ... + +and if the processing is composed of stages with different bounding +factor, then split them further into primitive functions. + +.. code-block:: + + def download(src: tuple[str, int]) -> tuple[bytes, int]: + ... + + def decode_and_preprocess(data: tuple[bytes, int]) -> tuple[ImageFrames, int]: + ... + +then the original ``Dataset`` can be implemented as a composition + +.. code-block:: + + class Dataset: + def __init__(self, ...): + self._src = Source(...) + + def __getitem__(self, key:int) -> tuple[str, int]: + metadata = self._src[key] + item = download(metadata) + frames, cls = decode_and_preprocess(item) + tensor = spdl.io.to_torch(frames) + return tensor, cls + +Such decomposition makes the dataset compatible with SPDL's Pipeline, +and allows users to run them more efficiently + +.. code-block:: + + pipeline = ( + PipelineBuilder() + .add_source(Source(...)) + .pipe(download, concurrency=8) + .pipe(decode_and_preprocess, concurrency=4) + ... + .build(...) + ) diff --git a/main/_sources/cpp.rst.txt b/main/_sources/cpp.rst.txt new file mode 100644 index 00000000..91f63ac6 --- /dev/null +++ b/main/_sources/cpp.rst.txt @@ -0,0 +1,9 @@ +API References (C++) +==================== + +.. toctree:: + :caption: API References (C++) + + Class List + File List + API diff --git a/main/_sources/examples.rst.txt b/main/_sources/examples.rst.txt new file mode 100644 index 00000000..bcdb1a7d --- /dev/null +++ b/main/_sources/examples.rst.txt @@ -0,0 +1,13 @@ +Examples +======== + +.. autosummary:: + :toctree: generated + :template: _custom_autosummary_example.rst + :caption: Examples + :recursive: + + image_dataloading + video_dataloading + imagenet_classification + multi_thread_preprocessing diff --git a/main/_sources/faq.rst.txt b/main/_sources/faq.rst.txt new file mode 100644 index 00000000..40d23530 --- /dev/null +++ b/main/_sources/faq.rst.txt @@ -0,0 +1,112 @@ +Frequently Asked Questions +========================== + +How to work around GIL? +----------------------- + +In Python, GIL (Global Interpreter Lock) practically prevents the use of multi-threading, however extension modules that are written in low-level languages, such as C, C++ and Rust, can release GIL when executing operations that do not interact with Python interpreter. + +Many libraries used for data loading release the GIL. To name a few; + +- Pillow +- OpenCV +- Decord +- tiktoken + +Typically, the bottleneck of model training in loading and pre-processing the media data. +So even though there are still parts of pipelines that are constrained by GIL, +by taking advantage of pre-processing functions that release GIL, +we can achieve high throughput. + +What if a function does not release GIL? +---------------------------------------- + +In case you need to use a function that takes long time to execute (e.g. network utilities) +but it does not release GIL, you can delegate the stage to sub-process. + +:py:meth:`spdl.pipeline.PipelineBuilder.pipe` method takes an optional ``executor`` argument. +The default behavior of the ``Pipeline`` is to use the thread pool shared among all stages. +You can pass an instance of :py:class:`concurrent.futures.ProcessPoolExecutor`, +and that stage will execute the function in the sub-process. + +.. code-block:: + + executor = ProcessPoolExecutor(max_workers=num_processes) + + pipeline = ( + PipelineBuilder() + .add_source(src) + .pipe(stage1, executor=executor, concurrency=num_processes) + .pipe(stage2, ...) + .pipe(stage3, ...) + .add_sink(1) + .build() + ) + +This will build pipeline like the following. + +.. include:: ./plots/faq_subprocess_chart.txt + +.. note:: + + Along with the function arguments and return values, the function itself is also + serialized and passed to the sub-process. Therefore, the function to be executed + must be a plain function. Closures and class methods cannot be passed. + +.. tip:: + + If you need to perform one-time initialization in sub-process, you can use + ``initializer`` and ``initargs`` arguments. + + The values passed as ``initializer`` and ``initargs`` must be picklable. + If constructing an object in a process that does not support picke, then + you can pass constructor arguments instead and store the resulting object + in global scope. See also https://stackoverflow.com/a/68783184/3670924. + + Example + + .. code-block:: + + def init_resource(*args): + global rsc + rsc = ResourceClass(*args) + + def process_with_resource(item): + global rsc + + return rsc.process(item) + + executor = ProcessPoolExecutor( + max_workers=4, + mp_context=None, + initializer=init_resource, + initargs=(...), + ) + + pipeline = ( + PipelineBuilder() + .add_source() + .pipe( + process_with_resource, + executor=executor, + concurrency=4, + ) + .add_sink(3) + .build() + ) + +Which functions hold the GIL? +----------------------------- + +The following is the list of functions that we are aware that they hold the GIL. So it is advised to use them with ``ProcessPoolExecutor`` or avoid using them in SPDL. + +* `np.load `_ + +Why Async IO? +------------- + +When training a model with large amount of data, the data are retrieved from remote locations. Network utilities often provide APIs based on Async I/O. + +The Async I/O allows to easily build complex data pre-processing pipeline and execute them while automatically parallelizing parts of the pipeline, achieving high throughput. + +Synchronous operations that release GIL can be converted to async operations easily by running them in a thread pool. So by converting the synchronous pre-processing functions that release GIL into asynchronous operations, the entire data pre-processing pipeline can be executed in async event loop. The event loop handles the scheduling of data processing functions, and execute them concurrently. diff --git a/main/_sources/generated/image_dataloading.rst.txt b/main/_sources/generated/image_dataloading.rst.txt new file mode 100644 index 00000000..4541bfa7 --- /dev/null +++ b/main/_sources/generated/image_dataloading.rst.txt @@ -0,0 +1,121 @@ +.. + Custom template for our custom_autosummary. + The purpose of using custom_autosummary is list the entries on + the right side bar instead of the left side bar. + This is achieved with the combination of custom directive, template and CSS. + + The `custom_autosummary` directive functions mostly like `autosummary`. We + pass `:toctree:` option to generate a doc page for each entry, but we use + our custom `:hide_from_toctree:` option so as not to attach them in ToC tree. + + This template inserts a section header for each entry, so that they show up + in the right-side bar. The headers are hidden by CSS. + + Because each entry will have its own table and their borders no longer match, + table borders are hidden by CSS and instead we use horizontal line. + +.. raw:: html + +
+ +image\_dataloading +================== + +.. automodule:: image_dataloading + +.. + ############################################################################ + Source + ############################################################################ + +Source +------ + +.. rubric:: Source + +.. raw:: html + +
+ Click here to see the source. + +.. literalinclude:: ../../../examples/image_dataloading.py + :linenos: + +.. raw:: html + +
+ +.. + ############################################################################ + Functions + ############################################################################ + + + + +Functions +--------- +.. rubric:: Functions + + + +.. autofunction:: image_dataloading.entrypoint + + + +.. autofunction:: image_dataloading.worker_entrypoint + + + +.. autofunction:: image_dataloading.benchmark + + + +.. autofunction:: image_dataloading.source + + + +.. autofunction:: image_dataloading.batch_decode + + + +.. autofunction:: image_dataloading.get_pipeline + + + + + +.. + ############################################################################ + Attributes + ############################################################################ + + + + + +.. + ############################################################################ + Classes + ############################################################################ + + + + +Classes +------- + +.. rubric:: Classes + + + +.. autoclass:: image_dataloading.PerfResult + :members: + + + + + +.. raw:: html + +
\ No newline at end of file diff --git a/main/_sources/generated/imagenet_classification.rst.txt b/main/_sources/generated/imagenet_classification.rst.txt new file mode 100644 index 00000000..73a882d4 --- /dev/null +++ b/main/_sources/generated/imagenet_classification.rst.txt @@ -0,0 +1,139 @@ +.. + Custom template for our custom_autosummary. + The purpose of using custom_autosummary is list the entries on + the right side bar instead of the left side bar. + This is achieved with the combination of custom directive, template and CSS. + + The `custom_autosummary` directive functions mostly like `autosummary`. We + pass `:toctree:` option to generate a doc page for each entry, but we use + our custom `:hide_from_toctree:` option so as not to attach them in ToC tree. + + This template inserts a section header for each entry, so that they show up + in the right-side bar. The headers are hidden by CSS. + + Because each entry will have its own table and their borders no longer match, + table borders are hidden by CSS and instead we use horizontal line. + +.. raw:: html + +
+ +imagenet\_classification +======================== + +.. automodule:: imagenet_classification + +.. + ############################################################################ + Source + ############################################################################ + +Source +------ + +.. rubric:: Source + +.. raw:: html + +
+ Click here to see the source. + +.. literalinclude:: ../../../examples/imagenet_classification.py + :linenos: + +.. raw:: html + +
+ +.. + ############################################################################ + Functions + ############################################################################ + + + + +Functions +--------- +.. rubric:: Functions + + + +.. autofunction:: imagenet_classification.entrypoint + + + +.. autofunction:: imagenet_classification.benchmark + + + +.. autofunction:: imagenet_classification.source + + + +.. autofunction:: imagenet_classification.get_decode_func + + + +.. autofunction:: imagenet_classification.get_dataloader + + + +.. autofunction:: imagenet_classification.get_model + + + +.. autofunction:: imagenet_classification.get_mappings + + + +.. autofunction:: imagenet_classification.parse_wnid + + + + + +.. + ############################################################################ + Attributes + ############################################################################ + + + + + +.. + ############################################################################ + Classes + ############################################################################ + + + + +Classes +------- + +.. rubric:: Classes + + + +.. autoclass:: imagenet_classification.ModelBundle + :members: + + + +.. autoclass:: imagenet_classification.Classification + :members: + + + +.. autoclass:: imagenet_classification.Preprocessing + :members: + + + + + +.. raw:: html + +
\ No newline at end of file diff --git a/main/_sources/generated/libspdl/classspdl_1_1core_1_1CPUStorage.rst.txt b/main/_sources/generated/libspdl/classspdl_1_1core_1_1CPUStorage.rst.txt new file mode 100644 index 00000000..93480174 --- /dev/null +++ b/main/_sources/generated/libspdl/classspdl_1_1core_1_1CPUStorage.rst.txt @@ -0,0 +1,26 @@ +.. _exhale_class_classspdl_1_1core_1_1CPUStorage: + +Class CPUStorage +================ + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_storage.h` + + +Inheritance Relationships +------------------------- + +Base Type +********* + +- ``public spdl::core::Storage`` (:ref:`exhale_struct_structspdl_1_1core_1_1Storage`) + + +Class Documentation +------------------- + + +.. doxygenclass:: spdl::core::CPUStorage + :project: libspdl + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/main/_sources/generated/libspdl/classspdl_1_1core_1_1CUDAStorage.rst.txt b/main/_sources/generated/libspdl/classspdl_1_1core_1_1CUDAStorage.rst.txt new file mode 100644 index 00000000..36b5744c --- /dev/null +++ b/main/_sources/generated/libspdl/classspdl_1_1core_1_1CUDAStorage.rst.txt @@ -0,0 +1,26 @@ +.. _exhale_class_classspdl_1_1core_1_1CUDAStorage: + +Class CUDAStorage +================= + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_storage.h` + + +Inheritance Relationships +------------------------- + +Base Type +********* + +- ``public spdl::core::Storage`` (:ref:`exhale_struct_structspdl_1_1core_1_1Storage`) + + +Class Documentation +------------------- + + +.. doxygenclass:: spdl::core::CUDAStorage + :project: libspdl + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/main/_sources/generated/libspdl/classspdl_1_1core_1_1DemuxedPackets.rst.txt b/main/_sources/generated/libspdl/classspdl_1_1core_1_1DemuxedPackets.rst.txt new file mode 100644 index 00000000..8fcaee85 --- /dev/null +++ b/main/_sources/generated/libspdl/classspdl_1_1core_1_1DemuxedPackets.rst.txt @@ -0,0 +1,17 @@ +.. _exhale_class_classspdl_1_1core_1_1DemuxedPackets: + +Template Class DemuxedPackets +============================= + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_packets.h` + + +Class Documentation +------------------- + + +.. doxygenclass:: spdl::core::DemuxedPackets + :project: libspdl + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/main/_sources/generated/libspdl/classspdl_1_1core_1_1Demuxer.rst.txt b/main/_sources/generated/libspdl/classspdl_1_1core_1_1Demuxer.rst.txt new file mode 100644 index 00000000..d39e9868 --- /dev/null +++ b/main/_sources/generated/libspdl/classspdl_1_1core_1_1Demuxer.rst.txt @@ -0,0 +1,17 @@ +.. _exhale_class_classspdl_1_1core_1_1Demuxer: + +Class Demuxer +============= + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_demuxing.h` + + +Class Documentation +------------------- + + +.. doxygenclass:: spdl::core::Demuxer + :project: libspdl + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/main/_sources/generated/libspdl/classspdl_1_1core_1_1FFmpegFrames.rst.txt b/main/_sources/generated/libspdl/classspdl_1_1core_1_1FFmpegFrames.rst.txt new file mode 100644 index 00000000..329579a9 --- /dev/null +++ b/main/_sources/generated/libspdl/classspdl_1_1core_1_1FFmpegFrames.rst.txt @@ -0,0 +1,17 @@ +.. _exhale_class_classspdl_1_1core_1_1FFmpegFrames: + +Template Class FFmpegFrames +=========================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_frames.h` + + +Class Documentation +------------------- + + +.. doxygenclass:: spdl::core::FFmpegFrames + :project: libspdl + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/main/_sources/generated/libspdl/classspdl_1_1core_1_1InternalError.rst.txt b/main/_sources/generated/libspdl/classspdl_1_1core_1_1InternalError.rst.txt new file mode 100644 index 00000000..fc196c77 --- /dev/null +++ b/main/_sources/generated/libspdl/classspdl_1_1core_1_1InternalError.rst.txt @@ -0,0 +1,26 @@ +.. _exhale_class_classspdl_1_1core_1_1InternalError: + +Class InternalError +=================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_types.h` + + +Inheritance Relationships +------------------------- + +Base Type +********* + +- ``public std::logic_error`` + + +Class Documentation +------------------- + + +.. doxygenclass:: spdl::core::InternalError + :project: libspdl + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/main/_sources/generated/libspdl/classspdl_1_1core_1_1TracingSession.rst.txt b/main/_sources/generated/libspdl/classspdl_1_1core_1_1TracingSession.rst.txt new file mode 100644 index 00000000..39bf4223 --- /dev/null +++ b/main/_sources/generated/libspdl/classspdl_1_1core_1_1TracingSession.rst.txt @@ -0,0 +1,17 @@ +.. _exhale_class_classspdl_1_1core_1_1TracingSession: + +Class TracingSession +==================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_utils.h` + + +Class Documentation +------------------- + + +.. doxygenclass:: spdl::core::TracingSession + :project: libspdl + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/main/_sources/generated/libspdl/define_frames_8h_1a9beaa64113e413112d43491ba5c13670.rst.txt b/main/_sources/generated/libspdl/define_frames_8h_1a9beaa64113e413112d43491ba5c13670.rst.txt new file mode 100644 index 00000000..28f6ebe8 --- /dev/null +++ b/main/_sources/generated/libspdl/define_frames_8h_1a9beaa64113e413112d43491ba5c13670.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_define_frames_8h_1a9beaa64113e413112d43491ba5c13670: + +Define _IS_VIDEO +================ + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_frames.h` + + +Define Documentation +-------------------- + + +.. doxygendefine:: _IS_VIDEO + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/define_frames_8h_1ac2ad95ac922a100ec27340436eb94940.rst.txt b/main/_sources/generated/libspdl/define_frames_8h_1ac2ad95ac922a100ec27340436eb94940.rst.txt new file mode 100644 index 00000000..230c68bf --- /dev/null +++ b/main/_sources/generated/libspdl/define_frames_8h_1ac2ad95ac922a100ec27340436eb94940.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_define_frames_8h_1ac2ad95ac922a100ec27340436eb94940: + +Define _IS_AUDIO +================ + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_frames.h` + + +Define Documentation +-------------------- + + +.. doxygendefine:: _IS_AUDIO + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/define_frames_8h_1ac99c83df576500933a3691deb137be6d.rst.txt b/main/_sources/generated/libspdl/define_frames_8h_1ac99c83df576500933a3691deb137be6d.rst.txt new file mode 100644 index 00000000..5321fe06 --- /dev/null +++ b/main/_sources/generated/libspdl/define_frames_8h_1ac99c83df576500933a3691deb137be6d.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_define_frames_8h_1ac99c83df576500933a3691deb137be6d: + +Define _IS_IMAGE +================ + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_frames.h` + + +Define Documentation +-------------------- + + +.. doxygendefine:: _IS_IMAGE + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/define_types_8h_1a3a6c4d7f842d451acf8717ce734385f2.rst.txt b/main/_sources/generated/libspdl/define_types_8h_1a3a6c4d7f842d451acf8717ce734385f2.rst.txt new file mode 100644 index 00000000..f65dff19 --- /dev/null +++ b/main/_sources/generated/libspdl/define_types_8h_1a3a6c4d7f842d451acf8717ce734385f2.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_define_types_8h_1a3a6c4d7f842d451acf8717ce734385f2: + +Define SPDL_DEFAULT_BUFFER_SIZE +=============================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_types.h` + + +Define Documentation +-------------------- + + +.. doxygendefine:: SPDL_DEFAULT_BUFFER_SIZE + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/dir__home_runner_work_spdl_spdl_src.rst.txt b/main/_sources/generated/libspdl/dir__home_runner_work_spdl_spdl_src.rst.txt new file mode 100644 index 00000000..d7ca988c --- /dev/null +++ b/main/_sources/generated/libspdl/dir__home_runner_work_spdl_spdl_src.rst.txt @@ -0,0 +1,16 @@ +.. _dir__home_runner_work_spdl_spdl_src: + + +Directory src +============= + + +*Directory path:* ``/home/runner/work/spdl/spdl/src`` + +Subdirectories +-------------- + +- :ref:`dir__home_runner_work_spdl_spdl_src_libspdl` + + + diff --git a/main/_sources/generated/libspdl/dir__home_runner_work_spdl_spdl_src_libspdl.rst.txt b/main/_sources/generated/libspdl/dir__home_runner_work_spdl_spdl_src_libspdl.rst.txt new file mode 100644 index 00000000..2459eb26 --- /dev/null +++ b/main/_sources/generated/libspdl/dir__home_runner_work_spdl_spdl_src_libspdl.rst.txt @@ -0,0 +1,21 @@ +.. _dir__home_runner_work_spdl_spdl_src_libspdl: + + +Directory libspdl +================= + + +|exhale_lsh| :ref:`Parent directory ` (``/home/runner/work/spdl/spdl/src``) + +.. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS + + +*Directory path:* ``/home/runner/work/spdl/spdl/src/libspdl`` + +Subdirectories +-------------- + +- :ref:`dir__home_runner_work_spdl_spdl_src_libspdl_core` + + + diff --git a/main/_sources/generated/libspdl/dir__home_runner_work_spdl_spdl_src_libspdl_core.rst.txt b/main/_sources/generated/libspdl/dir__home_runner_work_spdl_spdl_src_libspdl_core.rst.txt new file mode 100644 index 00000000..10d83cf7 --- /dev/null +++ b/main/_sources/generated/libspdl/dir__home_runner_work_spdl_spdl_src_libspdl_core.rst.txt @@ -0,0 +1,32 @@ +.. _dir__home_runner_work_spdl_spdl_src_libspdl_core: + + +Directory core +============== + + +|exhale_lsh| :ref:`Parent directory ` (``/home/runner/work/spdl/spdl/src/libspdl``) + +.. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS + + +*Directory path:* ``/home/runner/work/spdl/spdl/src/libspdl/core`` + + +Files +----- + +- :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_adaptor.h` +- :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_buffer.h` +- :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_conversion.h` +- :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_decoding.h` +- :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_demuxing.h` +- :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_encoding.h` +- :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_frames.h` +- :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_packets.h` +- :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_storage.h` +- :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_transfer.h` +- :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_types.h` +- :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_utils.h` + + diff --git a/main/_sources/generated/libspdl/enum_types_8h_1ac22438cfd069f0b1b6a736e73e8d244c.rst.txt b/main/_sources/generated/libspdl/enum_types_8h_1ac22438cfd069f0b1b6a736e73e8d244c.rst.txt new file mode 100644 index 00000000..92adb8b1 --- /dev/null +++ b/main/_sources/generated/libspdl/enum_types_8h_1ac22438cfd069f0b1b6a736e73e8d244c.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_enum_types_8h_1ac22438cfd069f0b1b6a736e73e8d244c: + +Enum MediaType +============== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_types.h` + + +Enum Documentation +------------------ + + +.. doxygenenum:: spdl::core::MediaType + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/enum_types_8h_1adb4e1adb2b3a59148c2797f903ead06f.rst.txt b/main/_sources/generated/libspdl/enum_types_8h_1adb4e1adb2b3a59148c2797f903ead06f.rst.txt new file mode 100644 index 00000000..44275c43 --- /dev/null +++ b/main/_sources/generated/libspdl/enum_types_8h_1adb4e1adb2b3a59148c2797f903ead06f.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_enum_types_8h_1adb4e1adb2b3a59148c2797f903ead06f: + +Enum ElemClass +============== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_types.h` + + +Enum Documentation +------------------ + + +.. doxygenenum:: spdl::core::ElemClass + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/file__home_runner_work_spdl_spdl_src_libspdl_core_adaptor.h.rst.txt b/main/_sources/generated/libspdl/file__home_runner_work_spdl_spdl_src_libspdl_core_adaptor.h.rst.txt new file mode 100644 index 00000000..1d13b03c --- /dev/null +++ b/main/_sources/generated/libspdl/file__home_runner_work_spdl_spdl_src_libspdl_core_adaptor.h.rst.txt @@ -0,0 +1,72 @@ + +.. _file__home_runner_work_spdl_spdl_src_libspdl_core_adaptor.h: + +File adaptor.h +============== + +|exhale_lsh| :ref:`Parent directory ` (``/home/runner/work/spdl/spdl/src/libspdl/core``) + +.. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS + +Definition (``/home/runner/work/spdl/spdl/src/libspdl/core/adaptor.h``) +----------------------------------------------------------------------- + + +.. toctree:: + :maxdepth: 1 + + program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_adaptor.h.rst + + + + + +Includes +-------- + + +- ``libspdl/core/types.h`` (:ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_types.h`) + +- ``memory`` + +- ``string`` + +- ``string_view`` + + + +Included By +----------- + + +- :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_demuxing.h` + + + + +Namespaces +---------- + + +- :ref:`namespace_spdl` + +- :ref:`namespace_spdl__core` + + +Classes +------- + + +- :ref:`exhale_struct_structspdl_1_1core_1_1BytesAdaptor` + +- :ref:`exhale_struct_structspdl_1_1core_1_1DataInterface` + +- :ref:`exhale_struct_structspdl_1_1core_1_1SourceAdaptor` + + +Typedefs +-------- + + +- :ref:`exhale_typedef_adaptor_8h_1aeea90ffba3c9156c91a3f9cea6b1526c` + diff --git a/main/_sources/generated/libspdl/file__home_runner_work_spdl_spdl_src_libspdl_core_buffer.h.rst.txt b/main/_sources/generated/libspdl/file__home_runner_work_spdl_spdl_src_libspdl_core_buffer.h.rst.txt new file mode 100644 index 00000000..344b5ad8 --- /dev/null +++ b/main/_sources/generated/libspdl/file__home_runner_work_spdl_spdl_src_libspdl_core_buffer.h.rst.txt @@ -0,0 +1,87 @@ + +.. _file__home_runner_work_spdl_spdl_src_libspdl_core_buffer.h: + +File buffer.h +============= + +|exhale_lsh| :ref:`Parent directory ` (``/home/runner/work/spdl/spdl/src/libspdl/core``) + +.. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS + +Definition (``/home/runner/work/spdl/spdl/src/libspdl/core/buffer.h``) +---------------------------------------------------------------------- + + +.. toctree:: + :maxdepth: 1 + + program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_buffer.h.rst + + + + + +Includes +-------- + + +- ``cstddef`` + +- ``libspdl/core/storage.h`` (:ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_storage.h`) + +- ``libspdl/core/types.h`` (:ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_types.h`) + +- ``memory`` + +- ``vector`` + + + +Included By +----------- + + +- :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_transfer.h` + +- :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_frames.h` + +- :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_conversion.h` + + + + +Namespaces +---------- + + +- :ref:`namespace_spdl` + +- :ref:`namespace_spdl__core` + + +Classes +------- + + +- :ref:`exhale_struct_structspdl_1_1core_1_1Buffer` + +- :ref:`exhale_struct_structspdl_1_1core_1_1CPUBuffer` + +- :ref:`exhale_struct_structspdl_1_1core_1_1CUDABuffer` + + +Functions +--------- + + +- :ref:`exhale_function_buffer_8h_1abb668d9a68635211e5e07bd5038df4aa` + + +Typedefs +-------- + + +- :ref:`exhale_typedef_buffer_8h_1aa53ca0dad3d74ed660c4f0ae55bb3ca3` + +- :ref:`exhale_typedef_buffer_8h_1a295ea6cb7bed7deb39f245f91beff04b` + diff --git a/main/_sources/generated/libspdl/file__home_runner_work_spdl_spdl_src_libspdl_core_conversion.h.rst.txt b/main/_sources/generated/libspdl/file__home_runner_work_spdl_spdl_src_libspdl_core_conversion.h.rst.txt new file mode 100644 index 00000000..03015cc8 --- /dev/null +++ b/main/_sources/generated/libspdl/file__home_runner_work_spdl_spdl_src_libspdl_core_conversion.h.rst.txt @@ -0,0 +1,57 @@ + +.. _file__home_runner_work_spdl_spdl_src_libspdl_core_conversion.h: + +File conversion.h +================= + +|exhale_lsh| :ref:`Parent directory ` (``/home/runner/work/spdl/spdl/src/libspdl/core``) + +.. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS + +Definition (``/home/runner/work/spdl/spdl/src/libspdl/core/conversion.h``) +-------------------------------------------------------------------------- + + +.. toctree:: + :maxdepth: 1 + + program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_conversion.h.rst + + + + + +Includes +-------- + + +- ``libspdl/core/buffer.h`` (:ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_buffer.h`) + +- ``libspdl/core/frames.h`` (:ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_frames.h`) + +- ``libspdl/core/types.h`` (:ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_types.h`) + +- ``vector`` + + + + + + +Namespaces +---------- + + +- :ref:`namespace_spdl` + +- :ref:`namespace_spdl__core` + + +Functions +--------- + + +- :ref:`exhale_function_conversion_8h_1a0545c3f2ca11c468e1a0ee74f57e2b02` + +- :ref:`exhale_function_conversion_8h_1a99743466504068e22a728f0ed8ae97bd` + diff --git a/main/_sources/generated/libspdl/file__home_runner_work_spdl_spdl_src_libspdl_core_decoding.h.rst.txt b/main/_sources/generated/libspdl/file__home_runner_work_spdl_spdl_src_libspdl_core_decoding.h.rst.txt new file mode 100644 index 00000000..01304cee --- /dev/null +++ b/main/_sources/generated/libspdl/file__home_runner_work_spdl_spdl_src_libspdl_core_decoding.h.rst.txt @@ -0,0 +1,76 @@ + +.. _file__home_runner_work_spdl_spdl_src_libspdl_core_decoding.h: + +File decoding.h +=============== + +|exhale_lsh| :ref:`Parent directory ` (``/home/runner/work/spdl/spdl/src/libspdl/core``) + +.. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS + +Definition (``/home/runner/work/spdl/spdl/src/libspdl/core/decoding.h``) +------------------------------------------------------------------------ + + +.. toctree:: + :maxdepth: 1 + + program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_decoding.h.rst + + + + + +Includes +-------- + + +- ``libspdl/core/frames.h`` (:ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_frames.h`) + +- ``libspdl/core/packets.h`` (:ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_packets.h`) + +- ``libspdl/core/types.h`` (:ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_types.h`) + +- ``optional`` + +- ``string`` + + + + + + +Namespaces +---------- + + +- :ref:`namespace_spdl` + +- :ref:`namespace_spdl__core` + + +Functions +--------- + + +- :ref:`exhale_function_decoding_8h_1a5b067f8b056f584a1f95ca9da44d875d` + +- :ref:`exhale_function_decoding_8h_1a343df1b3a19c73067200a302d052babd` + +- :ref:`exhale_function_decoding_8h_1a893795bd114529bcaa15e4abb4d6fb48` + +- :ref:`exhale_function_decoding_8h_1a2f5317d512083631645da5d55406ebb3` + +- :ref:`exhale_function_decoding_8h_1a6367f6b6ca933fc62638615e96a48fa0` + +- :ref:`exhale_function_decoding_8h_1a14676d89d3d27991a7d54346b0815f87` + +- :ref:`exhale_function_decoding_8h_1ad4f30cd883e8316d581e9af50c91ea9a` + + +Typedefs +-------- + + +- :ref:`exhale_typedef_decoding_8h_1a8fd65cf6184acafacace029e6a2e20b8` + diff --git a/main/_sources/generated/libspdl/file__home_runner_work_spdl_spdl_src_libspdl_core_demuxing.h.rst.txt b/main/_sources/generated/libspdl/file__home_runner_work_spdl_spdl_src_libspdl_core_demuxing.h.rst.txt new file mode 100644 index 00000000..0a9f4cb1 --- /dev/null +++ b/main/_sources/generated/libspdl/file__home_runner_work_spdl_spdl_src_libspdl_core_demuxing.h.rst.txt @@ -0,0 +1,77 @@ + +.. _file__home_runner_work_spdl_spdl_src_libspdl_core_demuxing.h: + +File demuxing.h +=============== + +|exhale_lsh| :ref:`Parent directory ` (``/home/runner/work/spdl/spdl/src/libspdl/core``) + +.. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS + +Definition (``/home/runner/work/spdl/spdl/src/libspdl/core/demuxing.h``) +------------------------------------------------------------------------ + + +.. toctree:: + :maxdepth: 1 + + program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_demuxing.h.rst + + + + + +Includes +-------- + + +- ``libspdl/core/adaptor.h`` (:ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_adaptor.h`) + +- ``libspdl/core/packets.h`` (:ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_packets.h`) + +- ``libspdl/core/types.h`` (:ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_types.h`) + +- ``optional`` + +- ``string_view`` + +- ``tuple`` + + + + + + +Namespaces +---------- + + +- :ref:`namespace_spdl` + +- :ref:`namespace_spdl__core` + + +Classes +------- + + +- :ref:`exhale_class_classspdl_1_1core_1_1Demuxer` + + +Functions +--------- + + +- :ref:`exhale_function_demuxing_8h_1a657f0fb3b23804653ed6c19e96d2b2e9` + +- :ref:`exhale_function_demuxing_8h_1a590baa95f8eeb6bc0092c723ff060dd4` + +- :ref:`exhale_function_demuxing_8h_1ad3fdb02bd04d231cd7238e034c27711f` + + +Typedefs +-------- + + +- :ref:`exhale_typedef_demuxing_8h_1a77c7c5e3c314e95c84755ff4be0c7382` + diff --git a/main/_sources/generated/libspdl/file__home_runner_work_spdl_spdl_src_libspdl_core_encoding.h.rst.txt b/main/_sources/generated/libspdl/file__home_runner_work_spdl_spdl_src_libspdl_core_encoding.h.rst.txt new file mode 100644 index 00000000..cf1cc12d --- /dev/null +++ b/main/_sources/generated/libspdl/file__home_runner_work_spdl_spdl_src_libspdl_core_encoding.h.rst.txt @@ -0,0 +1,53 @@ + +.. _file__home_runner_work_spdl_spdl_src_libspdl_core_encoding.h: + +File encoding.h +=============== + +|exhale_lsh| :ref:`Parent directory ` (``/home/runner/work/spdl/spdl/src/libspdl/core``) + +.. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS + +Definition (``/home/runner/work/spdl/spdl/src/libspdl/core/encoding.h``) +------------------------------------------------------------------------ + + +.. toctree:: + :maxdepth: 1 + + program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_encoding.h.rst + + + + + +Includes +-------- + + +- ``libspdl/core/types.h`` (:ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_types.h`) + +- ``string`` + +- ``vector`` + + + + + + +Namespaces +---------- + + +- :ref:`namespace_spdl` + +- :ref:`namespace_spdl__core` + + +Functions +--------- + + +- :ref:`exhale_function_encoding_8h_1aa2406e658aea82791bca3e4eddbbd7e0` + diff --git a/main/_sources/generated/libspdl/file__home_runner_work_spdl_spdl_src_libspdl_core_frames.h.rst.txt b/main/_sources/generated/libspdl/file__home_runner_work_spdl_spdl_src_libspdl_core_frames.h.rst.txt new file mode 100644 index 00000000..76379af0 --- /dev/null +++ b/main/_sources/generated/libspdl/file__home_runner_work_spdl_spdl_src_libspdl_core_frames.h.rst.txt @@ -0,0 +1,100 @@ + +.. _file__home_runner_work_spdl_spdl_src_libspdl_core_frames.h: + +File frames.h +============= + +|exhale_lsh| :ref:`Parent directory ` (``/home/runner/work/spdl/spdl/src/libspdl/core``) + +.. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS + +Definition (``/home/runner/work/spdl/spdl/src/libspdl/core/frames.h``) +---------------------------------------------------------------------- + + +.. toctree:: + :maxdepth: 1 + + program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_frames.h.rst + + + + + +Includes +-------- + + +- ``libspdl/core/buffer.h`` (:ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_buffer.h`) + +- ``libspdl/core/types.h`` (:ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_types.h`) + +- ``memory`` + +- ``vector`` + + + +Included By +----------- + + +- :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_decoding.h` + +- :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_conversion.h` + + + + +Namespaces +---------- + + +- :ref:`namespace_spdl` + +- :ref:`namespace_spdl__core` + + +Classes +------- + + +- :ref:`exhale_class_classspdl_1_1core_1_1FFmpegFrames` + + +Functions +--------- + + +- :ref:`exhale_function_frames_8h_1a90f0a97dc78248324bcf95c89ed16aa1` + + +Defines +------- + + +- :ref:`exhale_define_frames_8h_1ac2ad95ac922a100ec27340436eb94940` + +- :ref:`exhale_define_frames_8h_1ac99c83df576500933a3691deb137be6d` + +- :ref:`exhale_define_frames_8h_1a9beaa64113e413112d43491ba5c13670` + + +Typedefs +-------- + + +- :ref:`exhale_typedef_frames_8h_1a6f38c02e59d9bde7760a9662ec20d4f6` + +- :ref:`exhale_typedef_frames_8h_1aaa34b66b95f4cc27c8e9333bc20eb179` + +- :ref:`exhale_typedef_frames_8h_1af53bca5467cae4ea8c56a12f0c281d7d` + +- :ref:`exhale_typedef_frames_8h_1afcf5acc7119e9f97078aa93aba49bdf9` + +- :ref:`exhale_typedef_frames_8h_1a35f2f4ff658c5bf990288f605b286514` + +- :ref:`exhale_typedef_frames_8h_1ac65015b0c2d25150472229b1af78398a` + +- :ref:`exhale_typedef_frames_8h_1a37b07a783dc120ebfbf2bc1df02f63c9` + diff --git a/main/_sources/generated/libspdl/file__home_runner_work_spdl_spdl_src_libspdl_core_packets.h.rst.txt b/main/_sources/generated/libspdl/file__home_runner_work_spdl_spdl_src_libspdl_core_packets.h.rst.txt new file mode 100644 index 00000000..727e2e5d --- /dev/null +++ b/main/_sources/generated/libspdl/file__home_runner_work_spdl_spdl_src_libspdl_core_packets.h.rst.txt @@ -0,0 +1,93 @@ + +.. _file__home_runner_work_spdl_spdl_src_libspdl_core_packets.h: + +File packets.h +============== + +|exhale_lsh| :ref:`Parent directory ` (``/home/runner/work/spdl/spdl/src/libspdl/core``) + +.. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS + +Definition (``/home/runner/work/spdl/spdl/src/libspdl/core/packets.h``) +----------------------------------------------------------------------- + + +.. toctree:: + :maxdepth: 1 + + program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_packets.h.rst + + + + + +Includes +-------- + + +- ``libspdl/core/types.h`` (:ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_types.h`) + +- ``memory`` + +- ``string`` + +- ``tuple`` + +- ``vector`` + + + +Included By +----------- + + +- :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_decoding.h` + +- :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_demuxing.h` + + + + +Namespaces +---------- + + +- :ref:`namespace_spdl` + +- :ref:`namespace_spdl__core` + + +Classes +------- + + +- :ref:`exhale_class_classspdl_1_1core_1_1DemuxedPackets` + + +Functions +--------- + + +- :ref:`exhale_function_packets_8h_1aac1ec6808da374fe1f4c47869a6f8300` + +- :ref:`exhale_function_packets_8h_1a0b623fad072c5d9b6eec4e7039519d41` + + +Typedefs +-------- + + +- :ref:`exhale_typedef_packets_8h_1ac32cc3efe73a9e4d350dea50de9bfc1a` + +- :ref:`exhale_typedef_packets_8h_1a7d8aab12ea6bbedd5f5ac3a61ca35052` + +- :ref:`exhale_typedef_packets_8h_1a9f1d8f8a824887584d6c7afeef0db0ba` + +- :ref:`exhale_typedef_packets_8h_1a40b9e72f2c5acbf57523f3147b49b4d7` + +- :ref:`exhale_typedef_packets_8h_1ad0bca8953615860b5cd7c018711defd2` + +- :ref:`exhale_typedef_packets_8h_1a491d9af92f6473307b62089e5fd58655` + +- :ref:`exhale_typedef_packets_8h_1ae3f1d293e78dbd0c27d6b9607cc7658e` + diff --git a/main/_sources/generated/libspdl/file__home_runner_work_spdl_spdl_src_libspdl_core_storage.h.rst.txt b/main/_sources/generated/libspdl/file__home_runner_work_spdl_spdl_src_libspdl_core_storage.h.rst.txt new file mode 100644 index 00000000..16c9c525 --- /dev/null +++ b/main/_sources/generated/libspdl/file__home_runner_work_spdl_spdl_src_libspdl_core_storage.h.rst.txt @@ -0,0 +1,67 @@ + +.. _file__home_runner_work_spdl_spdl_src_libspdl_core_storage.h: + +File storage.h +============== + +|exhale_lsh| :ref:`Parent directory ` (``/home/runner/work/spdl/spdl/src/libspdl/core``) + +.. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS + +Definition (``/home/runner/work/spdl/spdl/src/libspdl/core/storage.h``) +----------------------------------------------------------------------- + + +.. toctree:: + :maxdepth: 1 + + program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_storage.h.rst + + + + + +Includes +-------- + + +- ``cstddef`` + +- ``cstdint`` + +- ``functional`` + +- ``libspdl/core/types.h`` (:ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_types.h`) + +- ``optional`` + + + +Included By +----------- + + +- :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_buffer.h` + + + + +Namespaces +---------- + + +- :ref:`namespace_spdl` + +- :ref:`namespace_spdl__core` + + +Classes +------- + + +- :ref:`exhale_struct_structspdl_1_1core_1_1Storage` + +- :ref:`exhale_class_classspdl_1_1core_1_1CPUStorage` + +- :ref:`exhale_class_classspdl_1_1core_1_1CUDAStorage` + diff --git a/main/_sources/generated/libspdl/file__home_runner_work_spdl_spdl_src_libspdl_core_transfer.h.rst.txt b/main/_sources/generated/libspdl/file__home_runner_work_spdl_spdl_src_libspdl_core_transfer.h.rst.txt new file mode 100644 index 00000000..6886bac8 --- /dev/null +++ b/main/_sources/generated/libspdl/file__home_runner_work_spdl_spdl_src_libspdl_core_transfer.h.rst.txt @@ -0,0 +1,59 @@ + +.. _file__home_runner_work_spdl_spdl_src_libspdl_core_transfer.h: + +File transfer.h +=============== + +|exhale_lsh| :ref:`Parent directory ` (``/home/runner/work/spdl/spdl/src/libspdl/core``) + +.. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS + +Definition (``/home/runner/work/spdl/spdl/src/libspdl/core/transfer.h``) +------------------------------------------------------------------------ + + +.. toctree:: + :maxdepth: 1 + + program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_transfer.h.rst + + + + + +Includes +-------- + + +- ``libspdl/core/buffer.h`` (:ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_buffer.h`) + +- ``libspdl/core/types.h`` (:ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_types.h`) + +- ``vector`` + + + + + + +Namespaces +---------- + + +- :ref:`namespace_spdl` + +- :ref:`namespace_spdl__core` + + +Functions +--------- + + +- :ref:`exhale_function_transfer_8h_1a3a7e98772b85103f03f154dd591295cc` + +- :ref:`exhale_function_transfer_8h_1adf8f9d7df9379f5a27403fa4f1d495d8` + +- :ref:`exhale_function_transfer_8h_1a37b4ea250aff54e99c9cb5d56350fcfb` + +- :ref:`exhale_function_transfer_8h_1a46f014da74eb97abf0c4af96c2de6e39` + diff --git a/main/_sources/generated/libspdl/file__home_runner_work_spdl_spdl_src_libspdl_core_types.h.rst.txt b/main/_sources/generated/libspdl/file__home_runner_work_spdl_spdl_src_libspdl_core_types.h.rst.txt new file mode 100644 index 00000000..6400fe17 --- /dev/null +++ b/main/_sources/generated/libspdl/file__home_runner_work_spdl_spdl_src_libspdl_core_types.h.rst.txt @@ -0,0 +1,124 @@ + +.. _file__home_runner_work_spdl_spdl_src_libspdl_core_types.h: + +File types.h +============ + +|exhale_lsh| :ref:`Parent directory ` (``/home/runner/work/spdl/spdl/src/libspdl/core``) + +.. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS + +Definition (``/home/runner/work/spdl/spdl/src/libspdl/core/types.h``) +--------------------------------------------------------------------- + + +.. toctree:: + :maxdepth: 1 + + program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_types.h.rst + + + + + +Includes +-------- + + +- ``functional`` + +- ``map`` + +- ``optional`` + +- ``stdexcept`` + +- ``string`` + + + +Included By +----------- + + +- :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_buffer.h` + +- :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_utils.h` + +- :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_packets.h` + +- :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_transfer.h` + +- :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_adaptor.h` + +- :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_frames.h` + +- :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_decoding.h` + +- :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_encoding.h` + +- :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_demuxing.h` + +- :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_conversion.h` + +- :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_storage.h` + + + + +Namespaces +---------- + + +- :ref:`namespace_spdl` + +- :ref:`namespace_spdl__core` + + +Classes +------- + + +- :ref:`exhale_struct_structspdl_1_1core_1_1CropArea` + +- :ref:`exhale_struct_structspdl_1_1core_1_1CUDAConfig` + +- :ref:`exhale_struct_structspdl_1_1core_1_1DecodeConfig` + +- :ref:`exhale_struct_structspdl_1_1core_1_1DemuxConfig` + +- :ref:`exhale_struct_structspdl_1_1core_1_1EncodeConfig` + +- :ref:`exhale_struct_structspdl_1_1core_1_1Rational` + +- :ref:`exhale_class_classspdl_1_1core_1_1InternalError` + + +Enums +----- + + +- :ref:`exhale_enum_types_8h_1adb4e1adb2b3a59148c2797f903ead06f` + +- :ref:`exhale_enum_types_8h_1ac22438cfd069f0b1b6a736e73e8d244c` + + +Defines +------- + + +- :ref:`exhale_define_types_8h_1a3a6c4d7f842d451acf8717ce734385f2` + + +Typedefs +-------- + + +- :ref:`exhale_typedef_types_8h_1a58ee8c8a06f6695125b423a1a8532efc` + +- :ref:`exhale_typedef_types_8h_1a4b013fc972e599fc717bd1afd978b083` + +- :ref:`exhale_typedef_types_8h_1a8429006d88afae24621607926baef99e` + +- :ref:`exhale_typedef_types_8h_1a2e4149a86d8a55df8a689a1d40855fa8` + diff --git a/main/_sources/generated/libspdl/file__home_runner_work_spdl_spdl_src_libspdl_core_utils.h.rst.txt b/main/_sources/generated/libspdl/file__home_runner_work_spdl_spdl_src_libspdl_core_utils.h.rst.txt new file mode 100644 index 00000000..b1d25861 --- /dev/null +++ b/main/_sources/generated/libspdl/file__home_runner_work_spdl_spdl_src_libspdl_core_utils.h.rst.txt @@ -0,0 +1,84 @@ + +.. _file__home_runner_work_spdl_spdl_src_libspdl_core_utils.h: + +File utils.h +============ + +|exhale_lsh| :ref:`Parent directory ` (``/home/runner/work/spdl/spdl/src/libspdl/core``) + +.. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS + +Definition (``/home/runner/work/spdl/spdl/src/libspdl/core/utils.h``) +--------------------------------------------------------------------- + + +.. toctree:: + :maxdepth: 1 + + program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_utils.h.rst + + + + + +Includes +-------- + + +- ``libspdl/core/types.h`` (:ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_types.h`) + +- ``memory`` + +- ``optional`` + +- ``string`` + +- ``tuple`` + + + + + + +Namespaces +---------- + + +- :ref:`namespace_spdl` + +- :ref:`namespace_spdl__core` + + +Classes +------- + + +- :ref:`exhale_class_classspdl_1_1core_1_1TracingSession` + + +Functions +--------- + + +- :ref:`exhale_function_utils_8h_1ab585293c73cc47b15afd22e733622ab2` + +- :ref:`exhale_function_utils_8h_1ae1a3d30b33d837c39c40190e681d37c8` + +- :ref:`exhale_function_utils_8h_1af82c781c7484afbad6cbac32ff925793` + +- :ref:`exhale_function_utils_8h_1aeafeca6d5325f292073ef63f114ae16d` + +- :ref:`exhale_function_utils_8h_1afa70a317592db745d0573211a10f98c8` + +- :ref:`exhale_function_utils_8h_1a95f92b9fa38af9ecb328983679dc9cf4` + +- :ref:`exhale_function_utils_8h_1aa1e91130e5d71e8c2a104e4f72296ff3` + +- :ref:`exhale_function_utils_8h_1a9b6c16227a1a8445319b487cacb0cd1d` + +- :ref:`exhale_function_utils_8h_1a893d39670b4169063d8f6e3723f4bc11` + +- :ref:`exhale_function_utils_8h_1ae27a1cc3e5bfd9997090eb40711cc6c6` + +- :ref:`exhale_function_utils_8h_1a8f29c25b417b77e9dfb5a769b418c169` + diff --git a/main/_sources/generated/libspdl/function_buffer_8h_1abb668d9a68635211e5e07bd5038df4aa.rst.txt b/main/_sources/generated/libspdl/function_buffer_8h_1abb668d9a68635211e5e07bd5038df4aa.rst.txt new file mode 100644 index 00000000..89270b09 --- /dev/null +++ b/main/_sources/generated/libspdl/function_buffer_8h_1abb668d9a68635211e5e07bd5038df4aa.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_function_buffer_8h_1abb668d9a68635211e5e07bd5038df4aa: + +Function spdl::core::cpu_buffer +=============================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_buffer.h` + + +Function Documentation +---------------------- + + +.. doxygenfunction:: spdl::core::cpu_buffer(const std::vector&, ElemClass, size_t, std::shared_ptr) + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/function_conversion_8h_1a0545c3f2ca11c468e1a0ee74f57e2b02.rst.txt b/main/_sources/generated/libspdl/function_conversion_8h_1a0545c3f2ca11c468e1a0ee74f57e2b02.rst.txt new file mode 100644 index 00000000..6d56afcc --- /dev/null +++ b/main/_sources/generated/libspdl/function_conversion_8h_1a0545c3f2ca11c468e1a0ee74f57e2b02.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_function_conversion_8h_1a0545c3f2ca11c468e1a0ee74f57e2b02: + +Template Function spdl::core::convert_frames(const FFmpegFrames \*, std::shared_ptr) +============================================================================================================ + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_conversion.h` + + +Function Documentation +---------------------- + + +.. doxygenfunction:: spdl::core::convert_frames(const FFmpegFrames *, std::shared_ptr) + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/function_conversion_8h_1a99743466504068e22a728f0ed8ae97bd.rst.txt b/main/_sources/generated/libspdl/function_conversion_8h_1a99743466504068e22a728f0ed8ae97bd.rst.txt new file mode 100644 index 00000000..b2cf6c9c --- /dev/null +++ b/main/_sources/generated/libspdl/function_conversion_8h_1a99743466504068e22a728f0ed8ae97bd.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_function_conversion_8h_1a99743466504068e22a728f0ed8ae97bd: + +Template Function spdl::core::convert_frames(const std::vector \*>&, std::shared_ptr) +================================================================================================================================ + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_conversion.h` + + +Function Documentation +---------------------- + + +.. doxygenfunction:: spdl::core::convert_frames(const std::vector *>&, std::shared_ptr) + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/function_decoding_8h_1a14676d89d3d27991a7d54346b0815f87.rst.txt b/main/_sources/generated/libspdl/function_decoding_8h_1a14676d89d3d27991a7d54346b0815f87.rst.txt new file mode 100644 index 00000000..06e46652 --- /dev/null +++ b/main/_sources/generated/libspdl/function_decoding_8h_1a14676d89d3d27991a7d54346b0815f87.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_function_decoding_8h_1a14676d89d3d27991a7d54346b0815f87: + +Template Function spdl::core::make_decoder +========================================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_decoding.h` + + +Function Documentation +---------------------- + + +.. doxygenfunction:: spdl::core::make_decoder(PacketsPtr, const std::optional&, const std::optional&) + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/function_decoding_8h_1a2f5317d512083631645da5d55406ebb3.rst.txt b/main/_sources/generated/libspdl/function_decoding_8h_1a2f5317d512083631645da5d55406ebb3.rst.txt new file mode 100644 index 00000000..eb1f7b38 --- /dev/null +++ b/main/_sources/generated/libspdl/function_decoding_8h_1a2f5317d512083631645da5d55406ebb3.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_function_decoding_8h_1a2f5317d512083631645da5d55406ebb3: + +Template Function spdl::core::decode_packets_nvdec(PacketsPtr, const CUDAConfig&, const CropArea&, int, int, const std::optional&) +=========================================================================================================================================================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_decoding.h` + + +Function Documentation +---------------------- + + +.. doxygenfunction:: spdl::core::decode_packets_nvdec(PacketsPtr, const CUDAConfig&, const CropArea&, int, int, const std::optional&) + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/function_decoding_8h_1a343df1b3a19c73067200a302d052babd.rst.txt b/main/_sources/generated/libspdl/function_decoding_8h_1a343df1b3a19c73067200a302d052babd.rst.txt new file mode 100644 index 00000000..0cc6d635 --- /dev/null +++ b/main/_sources/generated/libspdl/function_decoding_8h_1a343df1b3a19c73067200a302d052babd.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_function_decoding_8h_1a343df1b3a19c73067200a302d052babd: + +Function spdl::core::decode_image_nvjpeg(const std::vector&, const CUDAConfig&, int, int, const std::string&) +=============================================================================================================================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_decoding.h` + + +Function Documentation +---------------------- + + +.. doxygenfunction:: spdl::core::decode_image_nvjpeg(const std::vector&, const CUDAConfig&, int, int, const std::string&) + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/function_decoding_8h_1a5b067f8b056f584a1f95ca9da44d875d.rst.txt b/main/_sources/generated/libspdl/function_decoding_8h_1a5b067f8b056f584a1f95ca9da44d875d.rst.txt new file mode 100644 index 00000000..568930a6 --- /dev/null +++ b/main/_sources/generated/libspdl/function_decoding_8h_1a5b067f8b056f584a1f95ca9da44d875d.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_function_decoding_8h_1a5b067f8b056f584a1f95ca9da44d875d: + +Function spdl::core::decode_image_nvjpeg(const std::string_view&, const CUDAConfig&, int, int, const std::string&) +================================================================================================================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_decoding.h` + + +Function Documentation +---------------------- + + +.. doxygenfunction:: spdl::core::decode_image_nvjpeg(const std::string_view&, const CUDAConfig&, int, int, const std::string&) + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/function_decoding_8h_1a6367f6b6ca933fc62638615e96a48fa0.rst.txt b/main/_sources/generated/libspdl/function_decoding_8h_1a6367f6b6ca933fc62638615e96a48fa0.rst.txt new file mode 100644 index 00000000..f11e20c9 --- /dev/null +++ b/main/_sources/generated/libspdl/function_decoding_8h_1a6367f6b6ca933fc62638615e96a48fa0.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_function_decoding_8h_1a6367f6b6ca933fc62638615e96a48fa0: + +Function spdl::core::decode_packets_nvdec(std::vector&&, const CUDAConfig&, const CropArea&, int, int, const std::optional&, bool) +================================================================================================================================================================ + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_decoding.h` + + +Function Documentation +---------------------- + + +.. doxygenfunction:: spdl::core::decode_packets_nvdec(std::vector&&, const CUDAConfig&, const CropArea&, int, int, const std::optional&, bool) + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/function_decoding_8h_1a893795bd114529bcaa15e4abb4d6fb48.rst.txt b/main/_sources/generated/libspdl/function_decoding_8h_1a893795bd114529bcaa15e4abb4d6fb48.rst.txt new file mode 100644 index 00000000..193e688a --- /dev/null +++ b/main/_sources/generated/libspdl/function_decoding_8h_1a893795bd114529bcaa15e4abb4d6fb48.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_function_decoding_8h_1a893795bd114529bcaa15e4abb4d6fb48: + +Template Function spdl::core::decode_packets_ffmpeg +=================================================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_decoding.h` + + +Function Documentation +---------------------- + + +.. doxygenfunction:: spdl::core::decode_packets_ffmpeg(PacketsPtr, const std::optional&, const std::optional&) + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/function_decoding_8h_1ad4f30cd883e8316d581e9af50c91ea9a.rst.txt b/main/_sources/generated/libspdl/function_decoding_8h_1ad4f30cd883e8316d581e9af50c91ea9a.rst.txt new file mode 100644 index 00000000..0ebb0342 --- /dev/null +++ b/main/_sources/generated/libspdl/function_decoding_8h_1ad4f30cd883e8316d581e9af50c91ea9a.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_function_decoding_8h_1ad4f30cd883e8316d581e9af50c91ea9a: + +Template Function spdl::core::requires +====================================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_decoding.h` + + +Function Documentation +---------------------- + + +.. doxygenfunction:: spdl::core::requires(media_type !) + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/function_demuxing_8h_1a590baa95f8eeb6bc0092c723ff060dd4.rst.txt b/main/_sources/generated/libspdl/function_demuxing_8h_1a590baa95f8eeb6bc0092c723ff060dd4.rst.txt new file mode 100644 index 00000000..1af71df1 --- /dev/null +++ b/main/_sources/generated/libspdl/function_demuxing_8h_1a590baa95f8eeb6bc0092c723ff060dd4.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_function_demuxing_8h_1a590baa95f8eeb6bc0092c723ff060dd4: + +Function spdl::core::make_demuxer(const std::string_view, const std::optional&) +============================================================================================ + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_demuxing.h` + + +Function Documentation +---------------------- + + +.. doxygenfunction:: spdl::core::make_demuxer(const std::string_view, const std::optional&) + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/function_demuxing_8h_1a657f0fb3b23804653ed6c19e96d2b2e9.rst.txt b/main/_sources/generated/libspdl/function_demuxing_8h_1a657f0fb3b23804653ed6c19e96d2b2e9.rst.txt new file mode 100644 index 00000000..9421cce1 --- /dev/null +++ b/main/_sources/generated/libspdl/function_demuxing_8h_1a657f0fb3b23804653ed6c19e96d2b2e9.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_function_demuxing_8h_1a657f0fb3b23804653ed6c19e96d2b2e9: + +Function spdl::core::apply_bsf +============================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_demuxing.h` + + +Function Documentation +---------------------- + + +.. doxygenfunction:: spdl::core::apply_bsf(VideoPacketsPtr) + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/function_demuxing_8h_1ad3fdb02bd04d231cd7238e034c27711f.rst.txt b/main/_sources/generated/libspdl/function_demuxing_8h_1ad3fdb02bd04d231cd7238e034c27711f.rst.txt new file mode 100644 index 00000000..0a28c9d5 --- /dev/null +++ b/main/_sources/generated/libspdl/function_demuxing_8h_1ad3fdb02bd04d231cd7238e034c27711f.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_function_demuxing_8h_1ad3fdb02bd04d231cd7238e034c27711f: + +Function spdl::core::make_demuxer(const std::string&, const SourceAdaptorPtr&, const std::optional&) +================================================================================================================= + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_demuxing.h` + + +Function Documentation +---------------------- + + +.. doxygenfunction:: spdl::core::make_demuxer(const std::string&, const SourceAdaptorPtr&, const std::optional&) + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/function_encoding_8h_1aa2406e658aea82791bca3e4eddbbd7e0.rst.txt b/main/_sources/generated/libspdl/function_encoding_8h_1aa2406e658aea82791bca3e4eddbbd7e0.rst.txt new file mode 100644 index 00000000..a535aa7b --- /dev/null +++ b/main/_sources/generated/libspdl/function_encoding_8h_1aa2406e658aea82791bca3e4eddbbd7e0.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_function_encoding_8h_1aa2406e658aea82791bca3e4eddbbd7e0: + +Function spdl::core::encode_image +================================= + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_encoding.h` + + +Function Documentation +---------------------- + + +.. doxygenfunction:: spdl::core::encode_image(std::string, void *, std::vector, int, const std::string&, const std::optional&) + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/function_frames_8h_1a90f0a97dc78248324bcf95c89ed16aa1.rst.txt b/main/_sources/generated/libspdl/function_frames_8h_1a90f0a97dc78248324bcf95c89ed16aa1.rst.txt new file mode 100644 index 00000000..0d841f69 --- /dev/null +++ b/main/_sources/generated/libspdl/function_frames_8h_1a90f0a97dc78248324bcf95c89ed16aa1.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_function_frames_8h_1a90f0a97dc78248324bcf95c89ed16aa1: + +Template Function spdl::core::clone(const FFmpegFrames&) +==================================================================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_frames.h` + + +Function Documentation +---------------------- + + +.. doxygenfunction:: spdl::core::clone(const FFmpegFrames&) + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/function_packets_8h_1a0b623fad072c5d9b6eec4e7039519d41.rst.txt b/main/_sources/generated/libspdl/function_packets_8h_1a0b623fad072c5d9b6eec4e7039519d41.rst.txt new file mode 100644 index 00000000..86e24a8c --- /dev/null +++ b/main/_sources/generated/libspdl/function_packets_8h_1a0b623fad072c5d9b6eec4e7039519d41.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_function_packets_8h_1a0b623fad072c5d9b6eec4e7039519d41: + +Function spdl::core::extract_packets_at_indices +=============================================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_packets.h` + + +Function Documentation +---------------------- + + +.. doxygenfunction:: spdl::core::extract_packets_at_indices(const VideoPacketsPtr&, std::vector) + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/function_packets_8h_1aac1ec6808da374fe1f4c47869a6f8300.rst.txt b/main/_sources/generated/libspdl/function_packets_8h_1aac1ec6808da374fe1f4c47869a6f8300.rst.txt new file mode 100644 index 00000000..3e37d4df --- /dev/null +++ b/main/_sources/generated/libspdl/function_packets_8h_1aac1ec6808da374fe1f4c47869a6f8300.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_function_packets_8h_1aac1ec6808da374fe1f4c47869a6f8300: + +Template Function spdl::core::clone(const DemuxedPackets&) +====================================================================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_packets.h` + + +Function Documentation +---------------------- + + +.. doxygenfunction:: spdl::core::clone(const DemuxedPackets&) + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/function_transfer_8h_1a37b4ea250aff54e99c9cb5d56350fcfb.rst.txt b/main/_sources/generated/libspdl/function_transfer_8h_1a37b4ea250aff54e99c9cb5d56350fcfb.rst.txt new file mode 100644 index 00000000..615f985c --- /dev/null +++ b/main/_sources/generated/libspdl/function_transfer_8h_1a37b4ea250aff54e99c9cb5d56350fcfb.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_function_transfer_8h_1a37b4ea250aff54e99c9cb5d56350fcfb: + +Function spdl::core::transfer_buffer(const std::vector&, ElemClass, size_t, const void \*) +================================================================================================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_transfer.h` + + +Function Documentation +---------------------- + + +.. doxygenfunction:: spdl::core::transfer_buffer(const std::vector&, ElemClass, size_t, const void *) + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/function_transfer_8h_1a3a7e98772b85103f03f154dd591295cc.rst.txt b/main/_sources/generated/libspdl/function_transfer_8h_1a3a7e98772b85103f03f154dd591295cc.rst.txt new file mode 100644 index 00000000..d8246612 --- /dev/null +++ b/main/_sources/generated/libspdl/function_transfer_8h_1a3a7e98772b85103f03f154dd591295cc.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_function_transfer_8h_1a3a7e98772b85103f03f154dd591295cc: + +Function spdl::core::cp_to_cpu +============================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_transfer.h` + + +Function Documentation +---------------------- + + +.. doxygenfunction:: spdl::core::cp_to_cpu(const void *, const std::vector&) + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/function_transfer_8h_1a46f014da74eb97abf0c4af96c2de6e39.rst.txt b/main/_sources/generated/libspdl/function_transfer_8h_1a46f014da74eb97abf0c4af96c2de6e39.rst.txt new file mode 100644 index 00000000..7825eed2 --- /dev/null +++ b/main/_sources/generated/libspdl/function_transfer_8h_1a46f014da74eb97abf0c4af96c2de6e39.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_function_transfer_8h_1a46f014da74eb97abf0c4af96c2de6e39: + +Function spdl::core::transfer_buffer(CPUBufferPtr, const CUDAConfig&) +===================================================================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_transfer.h` + + +Function Documentation +---------------------- + + +.. doxygenfunction:: spdl::core::transfer_buffer(CPUBufferPtr, const CUDAConfig&) + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/function_transfer_8h_1adf8f9d7df9379f5a27403fa4f1d495d8.rst.txt b/main/_sources/generated/libspdl/function_transfer_8h_1adf8f9d7df9379f5a27403fa4f1d495d8.rst.txt new file mode 100644 index 00000000..edbded87 --- /dev/null +++ b/main/_sources/generated/libspdl/function_transfer_8h_1adf8f9d7df9379f5a27403fa4f1d495d8.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_function_transfer_8h_1adf8f9d7df9379f5a27403fa4f1d495d8: + +Function spdl::core::transfer_buffer(const std::vector&, ElemClass, size_t, void \*, const CUDAConfig&) +=============================================================================================================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_transfer.h` + + +Function Documentation +---------------------- + + +.. doxygenfunction:: spdl::core::transfer_buffer(const std::vector&, ElemClass, size_t, void *, const CUDAConfig&) + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/function_utils_8h_1a893d39670b4169063d8f6e3723f4bc11.rst.txt b/main/_sources/generated/libspdl/function_utils_8h_1a893d39670b4169063d8f6e3723f4bc11.rst.txt new file mode 100644 index 00000000..b773d29f --- /dev/null +++ b/main/_sources/generated/libspdl/function_utils_8h_1a893d39670b4169063d8f6e3723f4bc11.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_function_utils_8h_1a893d39670b4169063d8f6e3723f4bc11: + +Template Function spdl::core::trace_counter +=========================================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_utils.h` + + +Function Documentation +---------------------- + + +.. doxygenfunction:: spdl::core::trace_counter(int, Number) + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/function_utils_8h_1a8f29c25b417b77e9dfb5a769b418c169.rst.txt b/main/_sources/generated/libspdl/function_utils_8h_1a8f29c25b417b77e9dfb5a769b418c169.rst.txt new file mode 100644 index 00000000..a2dd8682 --- /dev/null +++ b/main/_sources/generated/libspdl/function_utils_8h_1a8f29c25b417b77e9dfb5a769b418c169.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_function_utils_8h_1a8f29c25b417b77e9dfb5a769b418c169: + +Function spdl::core::trace_event_end +==================================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_utils.h` + + +Function Documentation +---------------------- + + +.. doxygenfunction:: spdl::core::trace_event_end() + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/function_utils_8h_1a95f92b9fa38af9ecb328983679dc9cf4.rst.txt b/main/_sources/generated/libspdl/function_utils_8h_1a95f92b9fa38af9ecb328983679dc9cf4.rst.txt new file mode 100644 index 00000000..d7074dfa --- /dev/null +++ b/main/_sources/generated/libspdl/function_utils_8h_1a95f92b9fa38af9ecb328983679dc9cf4.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_function_utils_8h_1a95f92b9fa38af9ecb328983679dc9cf4: + +Function spdl::core::is_nvcodec_available +========================================= + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_utils.h` + + +Function Documentation +---------------------- + + +.. doxygenfunction:: spdl::core::is_nvcodec_available() + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/function_utils_8h_1a9b6c16227a1a8445319b487cacb0cd1d.rst.txt b/main/_sources/generated/libspdl/function_utils_8h_1a9b6c16227a1a8445319b487cacb0cd1d.rst.txt new file mode 100644 index 00000000..2ecd7f72 --- /dev/null +++ b/main/_sources/generated/libspdl/function_utils_8h_1a9b6c16227a1a8445319b487cacb0cd1d.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_function_utils_8h_1a9b6c16227a1a8445319b487cacb0cd1d: + +Function spdl::core::set_ffmpeg_log_level +========================================= + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_utils.h` + + +Function Documentation +---------------------- + + +.. doxygenfunction:: spdl::core::set_ffmpeg_log_level(int) + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/function_utils_8h_1aa1e91130e5d71e8c2a104e4f72296ff3.rst.txt b/main/_sources/generated/libspdl/function_utils_8h_1aa1e91130e5d71e8c2a104e4f72296ff3.rst.txt new file mode 100644 index 00000000..2a8f7e58 --- /dev/null +++ b/main/_sources/generated/libspdl/function_utils_8h_1aa1e91130e5d71e8c2a104e4f72296ff3.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_function_utils_8h_1aa1e91130e5d71e8c2a104e4f72296ff3: + +Function spdl::core::register_avdevices +======================================= + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_utils.h` + + +Function Documentation +---------------------- + + +.. doxygenfunction:: spdl::core::register_avdevices() + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/function_utils_8h_1ab585293c73cc47b15afd22e733622ab2.rst.txt b/main/_sources/generated/libspdl/function_utils_8h_1ab585293c73cc47b15afd22e733622ab2.rst.txt new file mode 100644 index 00000000..9e18b018 --- /dev/null +++ b/main/_sources/generated/libspdl/function_utils_8h_1ab585293c73cc47b15afd22e733622ab2.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_function_utils_8h_1ab585293c73cc47b15afd22e733622ab2: + +Function spdl::core::get_ffmpeg_filters +======================================= + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_utils.h` + + +Function Documentation +---------------------- + + +.. doxygenfunction:: spdl::core::get_ffmpeg_filters() + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/function_utils_8h_1ae1a3d30b33d837c39c40190e681d37c8.rst.txt b/main/_sources/generated/libspdl/function_utils_8h_1ae1a3d30b33d837c39c40190e681d37c8.rst.txt new file mode 100644 index 00000000..353ce30b --- /dev/null +++ b/main/_sources/generated/libspdl/function_utils_8h_1ae1a3d30b33d837c39c40190e681d37c8.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_function_utils_8h_1ae1a3d30b33d837c39c40190e681d37c8: + +Function spdl::core::get_ffmpeg_log_level +========================================= + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_utils.h` + + +Function Documentation +---------------------- + + +.. doxygenfunction:: spdl::core::get_ffmpeg_log_level() + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/function_utils_8h_1ae27a1cc3e5bfd9997090eb40711cc6c6.rst.txt b/main/_sources/generated/libspdl/function_utils_8h_1ae27a1cc3e5bfd9997090eb40711cc6c6.rst.txt new file mode 100644 index 00000000..b38255f1 --- /dev/null +++ b/main/_sources/generated/libspdl/function_utils_8h_1ae27a1cc3e5bfd9997090eb40711cc6c6.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_function_utils_8h_1ae27a1cc3e5bfd9997090eb40711cc6c6: + +Function spdl::core::trace_event_begin +====================================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_utils.h` + + +Function Documentation +---------------------- + + +.. doxygenfunction:: spdl::core::trace_event_begin(const std::string&) + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/function_utils_8h_1aeafeca6d5325f292073ef63f114ae16d.rst.txt b/main/_sources/generated/libspdl/function_utils_8h_1aeafeca6d5325f292073ef63f114ae16d.rst.txt new file mode 100644 index 00000000..8435095b --- /dev/null +++ b/main/_sources/generated/libspdl/function_utils_8h_1aeafeca6d5325f292073ef63f114ae16d.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_function_utils_8h_1aeafeca6d5325f292073ef63f114ae16d: + +Function spdl::core::init_tracing +================================= + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_utils.h` + + +Function Documentation +---------------------- + + +.. doxygenfunction:: spdl::core::init_tracing() + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/function_utils_8h_1af82c781c7484afbad6cbac32ff925793.rst.txt b/main/_sources/generated/libspdl/function_utils_8h_1af82c781c7484afbad6cbac32ff925793.rst.txt new file mode 100644 index 00000000..61ac84ff --- /dev/null +++ b/main/_sources/generated/libspdl/function_utils_8h_1af82c781c7484afbad6cbac32ff925793.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_function_utils_8h_1af82c781c7484afbad6cbac32ff925793: + +Function spdl::core::init_glog +============================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_utils.h` + + +Function Documentation +---------------------- + + +.. doxygenfunction:: spdl::core::init_glog(const char *) + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/function_utils_8h_1afa70a317592db745d0573211a10f98c8.rst.txt b/main/_sources/generated/libspdl/function_utils_8h_1afa70a317592db745d0573211a10f98c8.rst.txt new file mode 100644 index 00000000..ef3b28e5 --- /dev/null +++ b/main/_sources/generated/libspdl/function_utils_8h_1afa70a317592db745d0573211a10f98c8.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_function_utils_8h_1afa70a317592db745d0573211a10f98c8: + +Function spdl::core::is_cuda_available +====================================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_utils.h` + + +Function Documentation +---------------------- + + +.. doxygenfunction:: spdl::core::is_cuda_available() + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/libspdl_api.rst.txt b/main/_sources/generated/libspdl/libspdl_api.rst.txt new file mode 100644 index 00000000..adc4091f --- /dev/null +++ b/main/_sources/generated/libspdl/libspdl_api.rst.txt @@ -0,0 +1 @@ +.. include:: unabridged_api.rst.include diff --git a/main/_sources/generated/libspdl/libspdl_class.rst.txt b/main/_sources/generated/libspdl/libspdl_class.rst.txt new file mode 100644 index 00000000..e4132962 --- /dev/null +++ b/main/_sources/generated/libspdl/libspdl_class.rst.txt @@ -0,0 +1 @@ +.. include:: class_view_hierarchy.rst.include diff --git a/main/_sources/generated/libspdl/libspdl_file.rst.txt b/main/_sources/generated/libspdl/libspdl_file.rst.txt new file mode 100644 index 00000000..fb87cf09 --- /dev/null +++ b/main/_sources/generated/libspdl/libspdl_file.rst.txt @@ -0,0 +1 @@ +.. include:: file_view_hierarchy.rst.include diff --git a/main/_sources/generated/libspdl/namespace_spdl.rst.txt b/main/_sources/generated/libspdl/namespace_spdl.rst.txt new file mode 100644 index 00000000..6ee05cd3 --- /dev/null +++ b/main/_sources/generated/libspdl/namespace_spdl.rst.txt @@ -0,0 +1,13 @@ + +.. _namespace_spdl: + +Namespace spdl +============== + + + +Namespaces +---------- + + +- :ref:`namespace_spdl__core` diff --git a/main/_sources/generated/libspdl/namespace_spdl__core.rst.txt b/main/_sources/generated/libspdl/namespace_spdl__core.rst.txt new file mode 100644 index 00000000..b03c4606 --- /dev/null +++ b/main/_sources/generated/libspdl/namespace_spdl__core.rst.txt @@ -0,0 +1,180 @@ + +.. _namespace_spdl__core: + +Namespace spdl::core +==================== + + + +Classes +------- + + +- :ref:`exhale_struct_structspdl_1_1core_1_1Buffer` + +- :ref:`exhale_struct_structspdl_1_1core_1_1BytesAdaptor` + +- :ref:`exhale_struct_structspdl_1_1core_1_1CPUBuffer` + +- :ref:`exhale_struct_structspdl_1_1core_1_1CropArea` + +- :ref:`exhale_struct_structspdl_1_1core_1_1CUDABuffer` + +- :ref:`exhale_struct_structspdl_1_1core_1_1CUDAConfig` + +- :ref:`exhale_struct_structspdl_1_1core_1_1DataInterface` + +- :ref:`exhale_struct_structspdl_1_1core_1_1DecodeConfig` + +- :ref:`exhale_struct_structspdl_1_1core_1_1DemuxConfig` + +- :ref:`exhale_struct_structspdl_1_1core_1_1EncodeConfig` + +- :ref:`exhale_struct_structspdl_1_1core_1_1Rational` + +- :ref:`exhale_struct_structspdl_1_1core_1_1SourceAdaptor` + +- :ref:`exhale_struct_structspdl_1_1core_1_1Storage` + +- :ref:`exhale_class_classspdl_1_1core_1_1CPUStorage` + +- :ref:`exhale_class_classspdl_1_1core_1_1CUDAStorage` + +- :ref:`exhale_class_classspdl_1_1core_1_1DemuxedPackets` + +- :ref:`exhale_class_classspdl_1_1core_1_1Demuxer` + +- :ref:`exhale_class_classspdl_1_1core_1_1FFmpegFrames` + +- :ref:`exhale_class_classspdl_1_1core_1_1InternalError` + +- :ref:`exhale_class_classspdl_1_1core_1_1TracingSession` + + +Enums +----- + + +- :ref:`exhale_enum_types_8h_1adb4e1adb2b3a59148c2797f903ead06f` + +- :ref:`exhale_enum_types_8h_1ac22438cfd069f0b1b6a736e73e8d244c` + + +Functions +--------- + + +- :ref:`exhale_function_demuxing_8h_1a657f0fb3b23804653ed6c19e96d2b2e9` + +- :ref:`exhale_function_packets_8h_1aac1ec6808da374fe1f4c47869a6f8300` + +- :ref:`exhale_function_frames_8h_1a90f0a97dc78248324bcf95c89ed16aa1` + +- :ref:`exhale_function_conversion_8h_1a99743466504068e22a728f0ed8ae97bd` + +- :ref:`exhale_function_conversion_8h_1a0545c3f2ca11c468e1a0ee74f57e2b02` + +- :ref:`exhale_function_transfer_8h_1a3a7e98772b85103f03f154dd591295cc` + +- :ref:`exhale_function_buffer_8h_1abb668d9a68635211e5e07bd5038df4aa` + +- :ref:`exhale_function_decoding_8h_1a5b067f8b056f584a1f95ca9da44d875d` + +- :ref:`exhale_function_decoding_8h_1a343df1b3a19c73067200a302d052babd` + +- :ref:`exhale_function_decoding_8h_1a893795bd114529bcaa15e4abb4d6fb48` + +- :ref:`exhale_function_decoding_8h_1a2f5317d512083631645da5d55406ebb3` + +- :ref:`exhale_function_decoding_8h_1a6367f6b6ca933fc62638615e96a48fa0` + +- :ref:`exhale_function_encoding_8h_1aa2406e658aea82791bca3e4eddbbd7e0` + +- :ref:`exhale_function_packets_8h_1a0b623fad072c5d9b6eec4e7039519d41` + +- :ref:`exhale_function_utils_8h_1ab585293c73cc47b15afd22e733622ab2` + +- :ref:`exhale_function_utils_8h_1ae1a3d30b33d837c39c40190e681d37c8` + +- :ref:`exhale_function_utils_8h_1af82c781c7484afbad6cbac32ff925793` + +- :ref:`exhale_function_utils_8h_1aeafeca6d5325f292073ef63f114ae16d` + +- :ref:`exhale_function_utils_8h_1afa70a317592db745d0573211a10f98c8` + +- :ref:`exhale_function_utils_8h_1a95f92b9fa38af9ecb328983679dc9cf4` + +- :ref:`exhale_function_decoding_8h_1a14676d89d3d27991a7d54346b0815f87` + +- :ref:`exhale_function_demuxing_8h_1ad3fdb02bd04d231cd7238e034c27711f` + +- :ref:`exhale_function_demuxing_8h_1a590baa95f8eeb6bc0092c723ff060dd4` + +- :ref:`exhale_function_utils_8h_1aa1e91130e5d71e8c2a104e4f72296ff3` + +- :ref:`exhale_function_decoding_8h_1ad4f30cd883e8316d581e9af50c91ea9a` + +- :ref:`exhale_function_utils_8h_1a9b6c16227a1a8445319b487cacb0cd1d` + +- :ref:`exhale_function_utils_8h_1a893d39670b4169063d8f6e3723f4bc11` + +- :ref:`exhale_function_utils_8h_1ae27a1cc3e5bfd9997090eb40711cc6c6` + +- :ref:`exhale_function_utils_8h_1a8f29c25b417b77e9dfb5a769b418c169` + +- :ref:`exhale_function_transfer_8h_1a46f014da74eb97abf0c4af96c2de6e39` + +- :ref:`exhale_function_transfer_8h_1adf8f9d7df9379f5a27403fa4f1d495d8` + +- :ref:`exhale_function_transfer_8h_1a37b4ea250aff54e99c9cb5d56350fcfb` + + +Typedefs +-------- + + +- :ref:`exhale_typedef_packets_8h_1ac32cc3efe73a9e4d350dea50de9bfc1a` + +- :ref:`exhale_typedef_packets_8h_1a7d8aab12ea6bbedd5f5ac3a61ca35052` + +- :ref:`exhale_typedef_buffer_8h_1aa53ca0dad3d74ed660c4f0ae55bb3ca3` + +- :ref:`exhale_typedef_types_8h_1a58ee8c8a06f6695125b423a1a8532efc` + +- :ref:`exhale_typedef_types_8h_1a4b013fc972e599fc717bd1afd978b083` + +- :ref:`exhale_typedef_types_8h_1a8429006d88afae24621607926baef99e` + +- :ref:`exhale_typedef_buffer_8h_1a295ea6cb7bed7deb39f245f91beff04b` + +- :ref:`exhale_typedef_decoding_8h_1a8fd65cf6184acafacace029e6a2e20b8` + +- :ref:`exhale_typedef_demuxing_8h_1a77c7c5e3c314e95c84755ff4be0c7382` + +- :ref:`exhale_typedef_frames_8h_1a6f38c02e59d9bde7760a9662ec20d4f6` + +- :ref:`exhale_typedef_frames_8h_1aaa34b66b95f4cc27c8e9333bc20eb179` + +- :ref:`exhale_typedef_frames_8h_1af53bca5467cae4ea8c56a12f0c281d7d` + +- :ref:`exhale_typedef_frames_8h_1afcf5acc7119e9f97078aa93aba49bdf9` + +- :ref:`exhale_typedef_frames_8h_1a35f2f4ff658c5bf990288f605b286514` + +- :ref:`exhale_typedef_frames_8h_1ac65015b0c2d25150472229b1af78398a` + +- :ref:`exhale_typedef_frames_8h_1a37b07a783dc120ebfbf2bc1df02f63c9` + +- :ref:`exhale_typedef_packets_8h_1a9f1d8f8a824887584d6c7afeef0db0ba` + +- :ref:`exhale_typedef_packets_8h_1a40b9e72f2c5acbf57523f3147b49b4d7` + +- :ref:`exhale_typedef_types_8h_1a2e4149a86d8a55df8a689a1d40855fa8` + +- :ref:`exhale_typedef_packets_8h_1ad0bca8953615860b5cd7c018711defd2` + +- :ref:`exhale_typedef_adaptor_8h_1aeea90ffba3c9156c91a3f9cea6b1526c` + +- :ref:`exhale_typedef_packets_8h_1a491d9af92f6473307b62089e5fd58655` + +- :ref:`exhale_typedef_packets_8h_1ae3f1d293e78dbd0c27d6b9607cc7658e` diff --git a/main/_sources/generated/libspdl/namespace_std.rst.txt b/main/_sources/generated/libspdl/namespace_std.rst.txt new file mode 100644 index 00000000..9a86580a --- /dev/null +++ b/main/_sources/generated/libspdl/namespace_std.rst.txt @@ -0,0 +1,6 @@ + +.. _namespace_std: + +Namespace std +============= + diff --git a/main/_sources/generated/libspdl/program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_adaptor.h.rst.txt b/main/_sources/generated/libspdl/program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_adaptor.h.rst.txt new file mode 100644 index 00000000..a6e9c25c --- /dev/null +++ b/main/_sources/generated/libspdl/program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_adaptor.h.rst.txt @@ -0,0 +1,71 @@ + +.. _program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_adaptor.h: + +Program Listing for File adaptor.h +================================== + +|exhale_lsh| :ref:`Return to documentation for file ` (``/home/runner/work/spdl/spdl/src/libspdl/core/adaptor.h``) + +.. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS + +.. code-block:: cpp + + /* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + + #pragma once + + #include + + #include + #include + #include + + struct AVFormatContext; + + namespace spdl::core { + + struct SourceAdaptor; + + using SourceAdaptorPtr = std::shared_ptr; + + // DataInterface + + // DataInterface serves two purposes: + // 1. It encapsulates the AVFormatContext, AVIOContext and other + // objects so that their lifetimes are aligned. + // These are consumed in demuxer functions. + // 2. Abstract away the difference between the interfaces. Each + // interface can require additional/specific implementation to + // talk to the actual data source. Such things are distilled to + // merely AVFormatContext*. + struct DataInterface { + virtual ~DataInterface() = default; + virtual AVFormatContext* get_fmt_ctx() = 0; + virtual std::string get_src() const = 0; + }; + + // Adaptor + // Adaptor optionally modifies the intput resource indicator, and create + // DataInterface from the result. + struct SourceAdaptor { + virtual ~SourceAdaptor() = default; + + virtual std::unique_ptr get_interface( + std::string_view url, + const DemuxConfig& dmx_cfg) const; + }; + + // Bytes + struct BytesAdaptor : public SourceAdaptor { + std::unique_ptr get_interface( + std::string_view data, + const DemuxConfig& dmx_cfg) const override; + }; + + } // namespace spdl::core diff --git a/main/_sources/generated/libspdl/program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_buffer.h.rst.txt b/main/_sources/generated/libspdl/program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_buffer.h.rst.txt new file mode 100644 index 00000000..fd202983 --- /dev/null +++ b/main/_sources/generated/libspdl/program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_buffer.h.rst.txt @@ -0,0 +1,98 @@ + +.. _program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_buffer.h: + +Program Listing for File buffer.h +================================= + +|exhale_lsh| :ref:`Return to documentation for file ` (``/home/runner/work/spdl/spdl/src/libspdl/core/buffer.h``) + +.. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS + +.. code-block:: cpp + + /* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + + #pragma once + + #include + #include + + #include + #include + #include + + namespace spdl::core { + // Buffer + + struct Buffer; + struct CPUBuffer; + struct CUDABuffer; + + using CPUBufferPtr = std::unique_ptr; + using CUDABufferPtr = std::unique_ptr; + + struct Buffer { + std::vector shape; + ElemClass elem_class = ElemClass::UInt; + size_t depth = sizeof(uint8_t); + + Buffer(std::vector shape, ElemClass elem_class, size_t depth); + virtual ~Buffer() = default; + + virtual void* data() = 0; + }; + + struct CPUBuffer : public Buffer { + std::shared_ptr storage; + + CPUBuffer( + const std::vector& shape, + ElemClass elem_class, + size_t depth, + std::shared_ptr storage); + + void* data() override; + }; + + struct CUDABuffer : Buffer { + #ifdef SPDL_USE_CUDA + std::shared_ptr storage; + int device_index; + + CUDABuffer( + std::vector shape, + ElemClass elem_class, + size_t depth, + std::shared_ptr storage, + int device_index); + + void* data() override; + + uintptr_t get_cuda_stream() const; + + #endif + }; + + // Factory functions + + CPUBufferPtr cpu_buffer( + const std::vector& shape, + ElemClass elem_class = ElemClass::UInt, + size_t depth = sizeof(uint8_t), + std::shared_ptr storage = nullptr); + + #ifdef SPDL_USE_CUDA + CUDABufferPtr cuda_buffer( + const std::vector& shape, + const CUDAConfig& cfg, + ElemClass elem_class = ElemClass::UInt, + size_t depth = sizeof(uint8_t)); + #endif + + } // namespace spdl::core diff --git a/main/_sources/generated/libspdl/program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_conversion.h.rst.txt b/main/_sources/generated/libspdl/program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_conversion.h.rst.txt new file mode 100644 index 00000000..66245a93 --- /dev/null +++ b/main/_sources/generated/libspdl/program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_conversion.h.rst.txt @@ -0,0 +1,47 @@ + +.. _program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_conversion.h: + +Program Listing for File conversion.h +===================================== + +|exhale_lsh| :ref:`Return to documentation for file ` (``/home/runner/work/spdl/spdl/src/libspdl/core/conversion.h``) + +.. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS + +.. code-block:: cpp + + /* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + + #pragma once + #include + #include + #include + + #include + + namespace spdl::core { + + // The actual implementation is found in + // detail/ffmpeg/conversion.cpp + template + CPUBufferPtr convert_frames( + const std::vector*>& batch, + std::shared_ptr storage = nullptr); + + template + CPUBufferPtr convert_frames( + const FFmpegFrames* frames, + std::shared_ptr storage = nullptr) { + const std::vector*> batch{frames}; + // Use the same impl as batch conversion + auto ret = convert_frames(batch, std::move(storage)); + ret->shape.erase(ret->shape.begin()); // Trim the batch dim + return ret; + } + } // namespace spdl::core diff --git a/main/_sources/generated/libspdl/program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_decoding.h.rst.txt b/main/_sources/generated/libspdl/program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_decoding.h.rst.txt new file mode 100644 index 00000000..689b7100 --- /dev/null +++ b/main/_sources/generated/libspdl/program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_decoding.h.rst.txt @@ -0,0 +1,99 @@ + +.. _program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_decoding.h: + +Program Listing for File decoding.h +=================================== + +|exhale_lsh| :ref:`Return to documentation for file ` (``/home/runner/work/spdl/spdl/src/libspdl/core/decoding.h``) + +.. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS + +.. code-block:: cpp + + /* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + + #pragma once + + #include + #include + #include + + #include + #include + + namespace spdl::core { + + template + requires(media_type != MediaType::Image) + struct StreamingDecoder; + + template + using DecoderPtr = std::unique_ptr>; + + template + requires(media_type != MediaType::Image) + struct StreamingDecoder { + struct Impl; + Impl* pImpl; + + explicit StreamingDecoder( + PacketsPtr packets, + const std::optional& cfg = std::nullopt, + const std::optional& filter_desc = std::nullopt); + + ~StreamingDecoder(); + + std::optional> decode(int num_frames); + }; + + template + DecoderPtr make_decoder( + PacketsPtr packets, + const std::optional& decode_cfg, + const std::optional& filter_desc); + + template + FFmpegFramesPtr decode_packets_ffmpeg( + PacketsPtr packets, + const std::optional& cfg = std::nullopt, + const std::optional& filter_desc = std::nullopt); + + template + CUDABufferPtr decode_packets_nvdec( + PacketsPtr packets, + const CUDAConfig& cuda_config, + const CropArea& crop, + int width, + int height, + const std::optional& pix_fmt); + + CUDABufferPtr decode_packets_nvdec( + std::vector&& packets, + const CUDAConfig& cuda_config, + const CropArea& crop, + int width, + int height, + const std::optional& pix_fmt, + bool strict); + + CUDABufferPtr decode_image_nvjpeg( + const std::string_view& data, + const CUDAConfig& cuda_config, + int scale_width, + int scale_height, + const std::string& pix_fmt); + + CUDABufferPtr decode_image_nvjpeg( + const std::vector& data, + const CUDAConfig& cuda_config, + int scale_width, + int scale_height, + const std::string& pix_fmt); + + } // namespace spdl::core diff --git a/main/_sources/generated/libspdl/program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_demuxing.h.rst.txt b/main/_sources/generated/libspdl/program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_demuxing.h.rst.txt new file mode 100644 index 00000000..f1197d9c --- /dev/null +++ b/main/_sources/generated/libspdl/program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_demuxing.h.rst.txt @@ -0,0 +1,71 @@ + +.. _program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_demuxing.h: + +Program Listing for File demuxing.h +=================================== + +|exhale_lsh| :ref:`Return to documentation for file ` (``/home/runner/work/spdl/spdl/src/libspdl/core/demuxing.h``) + +.. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS + +.. code-block:: cpp + + /* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + + #pragma once + + #include + #include + #include + + #include + #include + #include + + struct AVFormatContext; + struct AVStream; + + namespace spdl::core { + + class Demuxer; + + using DemuxerPtr = std::unique_ptr; + + class Demuxer { + std::unique_ptr di; + AVFormatContext* fmt_ctx; + + public: + explicit Demuxer(std::unique_ptr di); + + ~Demuxer(); + + bool has_audio(); + + template + PacketsPtr demux_window( + const std::optional>& window = std::nullopt, + const std::optional& bsf = std::nullopt); + }; + + // Create a demuxer from an URI (file path, http, etc.) + DemuxerPtr make_demuxer( + const std::string& src, + const SourceAdaptorPtr& adaptor = nullptr, + const std::optional& dmx_cfg = std::nullopt); + + // Create a demuxer from an externally managed in-memory data + DemuxerPtr make_demuxer( + const std::string_view data, + const std::optional& dmx_cfg = std::nullopt); + + // Apply bitstream filter for NVDEC video decoding + VideoPacketsPtr apply_bsf(VideoPacketsPtr packets); + + } // namespace spdl::core diff --git a/main/_sources/generated/libspdl/program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_encoding.h.rst.txt b/main/_sources/generated/libspdl/program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_encoding.h.rst.txt new file mode 100644 index 00000000..ce2505c2 --- /dev/null +++ b/main/_sources/generated/libspdl/program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_encoding.h.rst.txt @@ -0,0 +1,36 @@ + +.. _program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_encoding.h: + +Program Listing for File encoding.h +=================================== + +|exhale_lsh| :ref:`Return to documentation for file ` (``/home/runner/work/spdl/spdl/src/libspdl/core/encoding.h``) + +.. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS + +.. code-block:: cpp + + /* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + + #include + + #include + #include + + namespace spdl::core { + + void encode_image( + std::string uri, + void* data, + std::vector shape, + int bit_depth, + const std::string& src_pix_fmt, + const std::optional& enc_cfg); + + } // namespace spdl::core diff --git a/main/_sources/generated/libspdl/program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_frames.h.rst.txt b/main/_sources/generated/libspdl/program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_frames.h.rst.txt new file mode 100644 index 00000000..ddb000a4 --- /dev/null +++ b/main/_sources/generated/libspdl/program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_frames.h.rst.txt @@ -0,0 +1,131 @@ + +.. _program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_frames.h: + +Program Listing for File frames.h +================================= + +|exhale_lsh| :ref:`Return to documentation for file ` (``/home/runner/work/spdl/spdl/src/libspdl/core/frames.h``) + +.. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS + +.. code-block:: cpp + + /* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + + #pragma once + + #include + #include + + #include + #include + + struct AVFrame; + + namespace spdl::core { + + // FFmpeg Frames + + template + class FFmpegFrames; + + using FFmpegAudioFrames = FFmpegFrames; + using FFmpegVideoFrames = FFmpegFrames; + using FFmpegImageFrames = FFmpegFrames; + + template + using FFmpegFramesPtr = std::unique_ptr>; + + using FFmpegAudioFramesPtr = FFmpegFramesPtr; + using FFmpegVideoFramesPtr = FFmpegFramesPtr; + using FFmpegImageFramesPtr = FFmpegFramesPtr; + + #define _IS_AUDIO (media_type == MediaType::Audio) + #define _IS_VIDEO (media_type == MediaType::Video) + #define _IS_IMAGE (media_type == MediaType::Image) + + template + class FFmpegFrames { + private: + uint64_t id{0}; + + public: + Rational time_base; + + private: + std::vector frames{}; + + public: + FFmpegFrames(uint64_t id, Rational time_base); + + FFmpegFrames(const FFmpegFrames&) = delete; + FFmpegFrames& operator=(const FFmpegFrames&) = delete; + FFmpegFrames(FFmpegFrames&&) noexcept; + FFmpegFrames& operator=(FFmpegFrames&&) noexcept; + ~FFmpegFrames(); + + uint64_t get_id() const; + + const std::vector& get_frames() const; + + // Common + + const char* get_media_format_name() const; + + OptionDict get_metadata() const; + + int get_num_frames() const; + // the behavior is different for audio + + void push_back(AVFrame* frame); + // the behavior is different for image + + // Audio specific + + int get_sample_rate() const + requires _IS_AUDIO; + + int get_num_channels() const + requires _IS_AUDIO; + + // Common to Audio/Video + Rational get_time_base() const + requires(_IS_AUDIO || _IS_VIDEO); + + // Common to Image/Video + + int get_num_planes() const + requires(_IS_IMAGE || _IS_VIDEO); + + int get_width() const + requires(_IS_IMAGE || _IS_VIDEO); + + int get_height() const + requires(_IS_IMAGE || _IS_VIDEO); + + // Video specific + + FFmpegVideoFramesPtr slice(int start, int stop, int step) const + requires _IS_VIDEO; + + FFmpegVideoFramesPtr slice(const std::vector& index) const + requires _IS_VIDEO; + + FFmpegImageFramesPtr slice(int64_t index) const + requires _IS_VIDEO; + }; + + template + FFmpegFramesPtr clone(const FFmpegFrames& src); + + #undef _IS_AUDIO + #undef _IS_VIDEO + #undef _IS_IMAGE + + } // namespace spdl::core diff --git a/main/_sources/generated/libspdl/program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_packets.h.rst.txt b/main/_sources/generated/libspdl/program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_packets.h.rst.txt new file mode 100644 index 00000000..8054d2b3 --- /dev/null +++ b/main/_sources/generated/libspdl/program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_packets.h.rst.txt @@ -0,0 +1,115 @@ + +.. _program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_packets.h: + +Program Listing for File packets.h +================================== + +|exhale_lsh| :ref:`Return to documentation for file ` (``/home/runner/work/spdl/spdl/src/libspdl/core/packets.h``) + +.. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS + +.. code-block:: cpp + + /* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + + #pragma once + + #include + + #include + #include + #include + #include + + struct AVCodecParameters; + struct AVPacket; + + namespace spdl::core { + + template + class DemuxedPackets; + + using AudioPackets = DemuxedPackets; + using VideoPackets = DemuxedPackets; + using ImagePackets = DemuxedPackets; + + template + using PacketsPtr = std::unique_ptr>; + + using AudioPacketsPtr = PacketsPtr; + using VideoPacketsPtr = PacketsPtr; + using ImagePacketsPtr = PacketsPtr; + + // Struct passed from IO thread pool to decoder thread pool. + // Similar to FFmpegFrames, AVFrame pointers are bulk released. + // It contains suffiient information to build decoder via AVStream*. + template + class DemuxedPackets { + public: + uint64_t id; + // Source information + std::string src; + std::optional> timestamp; + + // + AVCodecParameters* codecpar = nullptr; + Rational time_base = {0, 1}; + + // frame rate for video + Rational frame_rate = {0, 1}; + + private: + // Sliced raw packets + std::vector packets = {}; + + public: + DemuxedPackets( + std::string src, + std::tuple timestamp, + AVCodecParameters* codecpar, + Rational time_base); + + DemuxedPackets( + std::string src, + AVCodecParameters* codecpar, + Rational time_base); + + // Destructor releases AVPacket* resources + ~DemuxedPackets(); + // No copy/move constructors + DemuxedPackets(const DemuxedPackets&) = delete; + DemuxedPackets& operator=(const DemuxedPackets&) = delete; + DemuxedPackets(DemuxedPackets&& other) noexcept = delete; + DemuxedPackets& operator=(DemuxedPackets&& other) noexcept = delete; + + void push(AVPacket*); + const std::vector& get_packets() const; + const char* get_media_format_name() const; + + int get_width() const; + int get_height() const; + Rational get_frame_rate() const; + + // Get the number of valid packets, that is, the number of frames returned + // by decoding function when decoded. + // This is different from `packets.size()` when timestamp is set. + // This is the number of packets visible to users. + size_t num_packets() const + requires(media_type == MediaType::Video || media_type == MediaType::Image); + }; + + template + PacketsPtr clone(const DemuxedPackets& src); + + std::vector>> + extract_packets_at_indices( + const VideoPacketsPtr& src, + std::vector indices); + + } // namespace spdl::core diff --git a/main/_sources/generated/libspdl/program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_storage.h.rst.txt b/main/_sources/generated/libspdl/program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_storage.h.rst.txt new file mode 100644 index 00000000..afca22e2 --- /dev/null +++ b/main/_sources/generated/libspdl/program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_storage.h.rst.txt @@ -0,0 +1,92 @@ + +.. _program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_storage.h: + +Program Listing for File storage.h +================================== + +|exhale_lsh| :ref:`Return to documentation for file ` (``/home/runner/work/spdl/spdl/src/libspdl/core/storage.h``) + +.. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS + +.. code-block:: cpp + + /* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + + #pragma once + + #include + + #include + #include + #include + #include + + #ifdef SPDL_USE_CUDA + #include + #endif + + namespace spdl::core { + + struct Storage { + virtual void* data() const = 0; + virtual ~Storage() = default; + }; + + class CPUStorage : public Storage { + public: + size_t size; + // So far, we only need this in CPUStorage. So we are not adding it + // in CUDAStorage. If we need to add that to CUDAStorage, revisit + // the interface/abstraction. (Is virtual `get_size` better?) + private: + void* data_ = nullptr; + bool memory_pinned = false; + + public: + void* data() const override; + bool is_pinned() const; + + CPUStorage() = default; + explicit CPUStorage(size_t size, bool pin_memory = false); + + CPUStorage(const CPUStorage&) = delete; + CPUStorage& operator=(const CPUStorage&) = delete; + + CPUStorage(CPUStorage&&) noexcept; + CPUStorage& operator=(CPUStorage&&) noexcept; + + ~CPUStorage() override; + }; + + class CUDAStorage : public Storage { + #ifdef SPDL_USE_CUDA + void* data_ = nullptr; + + public: + CUstream stream = nullptr; + + cuda_deleter_fn deleter; + + void* data() const override; + + CUDAStorage() = default; + CUDAStorage(size_t size, int device, CUstream stream); + CUDAStorage(size_t size, const CUDAConfig& cfg); + + CUDAStorage(const CUDAStorage&) = delete; + CUDAStorage& operator=(const CUDAStorage&) = delete; + + CUDAStorage(CUDAStorage&&) noexcept; + CUDAStorage& operator=(CUDAStorage&&) noexcept; + + ~CUDAStorage() override; + #endif + }; + + } // namespace spdl::core diff --git a/main/_sources/generated/libspdl/program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_transfer.h.rst.txt b/main/_sources/generated/libspdl/program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_transfer.h.rst.txt new file mode 100644 index 00000000..9651d271 --- /dev/null +++ b/main/_sources/generated/libspdl/program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_transfer.h.rst.txt @@ -0,0 +1,47 @@ + +.. _program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_transfer.h: + +Program Listing for File transfer.h +=================================== + +|exhale_lsh| :ref:`Return to documentation for file ` (``/home/runner/work/spdl/spdl/src/libspdl/core/transfer.h``) + +.. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS + +.. code-block:: cpp + + /* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + + #pragma once + #include + #include + + #include + + namespace spdl::core { + + // CPU -> CUDA + CUDABufferPtr transfer_buffer(CPUBufferPtr buffer, const CUDAConfig& cfg); + // For transfering generic arrays like NumPy. + CUDABufferPtr transfer_buffer( + const std::vector& shape, + ElemClass elem_class, + size_t depth, + void* ptr, + const CUDAConfig& cfg); + + // CUDA -> CPU + CPUBufferPtr transfer_buffer( + const std::vector& shape, + ElemClass elem_class, + size_t depth, + const void* ptr); + + CPUStorage cp_to_cpu(const void* src, const std::vector& shape); + } // namespace spdl::core diff --git a/main/_sources/generated/libspdl/program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_types.h.rst.txt b/main/_sources/generated/libspdl/program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_types.h.rst.txt new file mode 100644 index 00000000..6d726072 --- /dev/null +++ b/main/_sources/generated/libspdl/program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_types.h.rst.txt @@ -0,0 +1,118 @@ + +.. _program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_types.h: + +Program Listing for File types.h +================================ + +|exhale_lsh| :ref:`Return to documentation for file ` (``/home/runner/work/spdl/spdl/src/libspdl/core/types.h``) + +.. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS + +.. code-block:: cpp + + /* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + + #pragma once + + #include + #include + #include + #include + #include + + #define SPDL_DEFAULT_BUFFER_SIZE 8096 + + namespace spdl::core { + + using OptionDict = std::map; + + // alternative for AVRational so that we can avoid exposing FFmpeg headers + struct Rational { + int num = 0; + int den = 1; + }; + + // simplified version of AVMediaType so that public headers do not + // include ffmpeg headers + enum class MediaType { Audio, Video, Image }; + + struct DemuxConfig { + std::optional format = std::nullopt; + std::optional format_options = std::nullopt; + int buffer_size = SPDL_DEFAULT_BUFFER_SIZE; + }; + + struct DecodeConfig { + std::optional decoder = std::nullopt; + std::optional decoder_options = std::nullopt; + }; + + using cuda_allocator_fn = std::function; + using cuda_deleter_fn = std::function; + using cuda_allocator = std::pair; + + struct CUDAConfig { + int device_index; + uintptr_t stream = 0; + std::optional allocator; + }; + + // Used to construct Dtype when converting buffer to array + enum class ElemClass { Int, UInt, Float }; + + struct CropArea { + short left = 0; + short top = 0; + short right = 0; + short bottom = 0; + }; + + struct EncodeConfig { + // Muxer format or device name + std::optional muxer = std::nullopt; + // Options for muxer + std::optional muxer_options = std::nullopt; + + // Encoder + std::optional encoder = std::nullopt; + // Encoder options + std::optional encoder_options = std::nullopt; + + // Pixel/sample format used for encoding + std::optional format = std::nullopt; + + // Rescale options + int width = -1; + int height = -1; + std::optional scale_algo = std::nullopt; + + // Optional filter desc + std::optional filter_desc = std::nullopt; + + int bit_rate = -1; + int compression_level = -1; + + // qscale corresponds to ffmpeg CLI's qscale. + // Example: MP3 + // https://trac.ffmpeg.org/wiki/Encode/MP3 + // This should be set like + // https://github.com/FFmpeg/FFmpeg/blob/n4.3.2/fftools/ffmpeg_opt.c#L1550 + int qscale = -1; + + // video + int gop_size = -1; + int max_b_frames = -1; + }; + + // Thrown when unexpected internal error occurs. + class InternalError : public std::logic_error { + using std::logic_error::logic_error; + }; + + } // namespace spdl::core diff --git a/main/_sources/generated/libspdl/program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_utils.h.rst.txt b/main/_sources/generated/libspdl/program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_utils.h.rst.txt new file mode 100644 index 00000000..ee1def34 --- /dev/null +++ b/main/_sources/generated/libspdl/program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_utils.h.rst.txt @@ -0,0 +1,90 @@ + +.. _program_listing_file__home_runner_work_spdl_spdl_src_libspdl_core_utils.h: + +Program Listing for File utils.h +================================ + +|exhale_lsh| :ref:`Return to documentation for file ` (``/home/runner/work/spdl/spdl/src/libspdl/core/utils.h``) + +.. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS + +.. code-block:: cpp + + /* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + + #pragma once + + #include + + #include + #include + #include + #include + + namespace spdl::core { + + constexpr bool is_cuda_available() { + return + #ifdef SPDL_USE_CUDA + true + #else + false + #endif + ; + } + + constexpr bool is_nvcodec_available() { + return + #ifdef SPDL_USE_NVCODEC + true + #else + false + #endif + ; + } + + // Utilities for FFmpeg + int get_ffmpeg_log_level(); + + void set_ffmpeg_log_level(int); + + void register_avdevices(); + + std::vector get_ffmpeg_filters(); + + // Utilities for Glog + void init_glog(const char* name); + + // Utilities for tracing + class TracingSession { + void* sess = nullptr; + + public: + explicit TracingSession(void* sess = nullptr); + TracingSession(const TracingSession&) = delete; + TracingSession& operator=(const TracingSession&) = delete; + TracingSession(TracingSession&& other) noexcept; + TracingSession& operator=(TracingSession&& other) noexcept; + ~TracingSession(); + + void init(); + void config(const std::string& process_name); + void start(int fd, int buffer_size_in_kb); + void stop(); + }; + + std::unique_ptr init_tracing(); + + // These utilities are for adding custom tracing on Python side + template + void trace_counter(int i, Number counter); + void trace_event_begin(const std::string& name); + void trace_event_end(); + + } // namespace spdl::core diff --git a/main/_sources/generated/libspdl/root.rst.txt b/main/_sources/generated/libspdl/root.rst.txt new file mode 100644 index 00000000..7a2b5f7a --- /dev/null +++ b/main/_sources/generated/libspdl/root.rst.txt @@ -0,0 +1,10 @@ +=========== +Libspdl API +=========== + +.. include:: class_view_hierarchy.rst.include + +.. include:: file_view_hierarchy.rst.include + +.. include:: unabridged_api.rst.include + diff --git a/main/_sources/generated/libspdl/structspdl_1_1core_1_1Buffer.rst.txt b/main/_sources/generated/libspdl/structspdl_1_1core_1_1Buffer.rst.txt new file mode 100644 index 00000000..c7beda42 --- /dev/null +++ b/main/_sources/generated/libspdl/structspdl_1_1core_1_1Buffer.rst.txt @@ -0,0 +1,27 @@ +.. _exhale_struct_structspdl_1_1core_1_1Buffer: + +Struct Buffer +============= + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_buffer.h` + + +Inheritance Relationships +------------------------- + +Derived Types +************* + +- ``public spdl::core::CPUBuffer`` (:ref:`exhale_struct_structspdl_1_1core_1_1CPUBuffer`) +- ``public spdl::core::CUDABuffer`` (:ref:`exhale_struct_structspdl_1_1core_1_1CUDABuffer`) + + +Struct Documentation +-------------------- + + +.. doxygenstruct:: spdl::core::Buffer + :project: libspdl + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/main/_sources/generated/libspdl/structspdl_1_1core_1_1BytesAdaptor.rst.txt b/main/_sources/generated/libspdl/structspdl_1_1core_1_1BytesAdaptor.rst.txt new file mode 100644 index 00000000..87d19a6b --- /dev/null +++ b/main/_sources/generated/libspdl/structspdl_1_1core_1_1BytesAdaptor.rst.txt @@ -0,0 +1,26 @@ +.. _exhale_struct_structspdl_1_1core_1_1BytesAdaptor: + +Struct BytesAdaptor +=================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_adaptor.h` + + +Inheritance Relationships +------------------------- + +Base Type +********* + +- ``public spdl::core::SourceAdaptor`` (:ref:`exhale_struct_structspdl_1_1core_1_1SourceAdaptor`) + + +Struct Documentation +-------------------- + + +.. doxygenstruct:: spdl::core::BytesAdaptor + :project: libspdl + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/main/_sources/generated/libspdl/structspdl_1_1core_1_1CPUBuffer.rst.txt b/main/_sources/generated/libspdl/structspdl_1_1core_1_1CPUBuffer.rst.txt new file mode 100644 index 00000000..360f7753 --- /dev/null +++ b/main/_sources/generated/libspdl/structspdl_1_1core_1_1CPUBuffer.rst.txt @@ -0,0 +1,26 @@ +.. _exhale_struct_structspdl_1_1core_1_1CPUBuffer: + +Struct CPUBuffer +================ + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_buffer.h` + + +Inheritance Relationships +------------------------- + +Base Type +********* + +- ``public spdl::core::Buffer`` (:ref:`exhale_struct_structspdl_1_1core_1_1Buffer`) + + +Struct Documentation +-------------------- + + +.. doxygenstruct:: spdl::core::CPUBuffer + :project: libspdl + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/main/_sources/generated/libspdl/structspdl_1_1core_1_1CUDABuffer.rst.txt b/main/_sources/generated/libspdl/structspdl_1_1core_1_1CUDABuffer.rst.txt new file mode 100644 index 00000000..ffe0c167 --- /dev/null +++ b/main/_sources/generated/libspdl/structspdl_1_1core_1_1CUDABuffer.rst.txt @@ -0,0 +1,26 @@ +.. _exhale_struct_structspdl_1_1core_1_1CUDABuffer: + +Struct CUDABuffer +================= + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_buffer.h` + + +Inheritance Relationships +------------------------- + +Base Type +********* + +- ``public spdl::core::Buffer`` (:ref:`exhale_struct_structspdl_1_1core_1_1Buffer`) + + +Struct Documentation +-------------------- + + +.. doxygenstruct:: spdl::core::CUDABuffer + :project: libspdl + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/main/_sources/generated/libspdl/structspdl_1_1core_1_1CUDAConfig.rst.txt b/main/_sources/generated/libspdl/structspdl_1_1core_1_1CUDAConfig.rst.txt new file mode 100644 index 00000000..8858a67a --- /dev/null +++ b/main/_sources/generated/libspdl/structspdl_1_1core_1_1CUDAConfig.rst.txt @@ -0,0 +1,17 @@ +.. _exhale_struct_structspdl_1_1core_1_1CUDAConfig: + +Struct CUDAConfig +================= + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_types.h` + + +Struct Documentation +-------------------- + + +.. doxygenstruct:: spdl::core::CUDAConfig + :project: libspdl + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/main/_sources/generated/libspdl/structspdl_1_1core_1_1CropArea.rst.txt b/main/_sources/generated/libspdl/structspdl_1_1core_1_1CropArea.rst.txt new file mode 100644 index 00000000..840d921b --- /dev/null +++ b/main/_sources/generated/libspdl/structspdl_1_1core_1_1CropArea.rst.txt @@ -0,0 +1,17 @@ +.. _exhale_struct_structspdl_1_1core_1_1CropArea: + +Struct CropArea +=============== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_types.h` + + +Struct Documentation +-------------------- + + +.. doxygenstruct:: spdl::core::CropArea + :project: libspdl + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/main/_sources/generated/libspdl/structspdl_1_1core_1_1DataInterface.rst.txt b/main/_sources/generated/libspdl/structspdl_1_1core_1_1DataInterface.rst.txt new file mode 100644 index 00000000..742518cd --- /dev/null +++ b/main/_sources/generated/libspdl/structspdl_1_1core_1_1DataInterface.rst.txt @@ -0,0 +1,17 @@ +.. _exhale_struct_structspdl_1_1core_1_1DataInterface: + +Struct DataInterface +==================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_adaptor.h` + + +Struct Documentation +-------------------- + + +.. doxygenstruct:: spdl::core::DataInterface + :project: libspdl + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/main/_sources/generated/libspdl/structspdl_1_1core_1_1DecodeConfig.rst.txt b/main/_sources/generated/libspdl/structspdl_1_1core_1_1DecodeConfig.rst.txt new file mode 100644 index 00000000..11b73644 --- /dev/null +++ b/main/_sources/generated/libspdl/structspdl_1_1core_1_1DecodeConfig.rst.txt @@ -0,0 +1,17 @@ +.. _exhale_struct_structspdl_1_1core_1_1DecodeConfig: + +Struct DecodeConfig +=================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_types.h` + + +Struct Documentation +-------------------- + + +.. doxygenstruct:: spdl::core::DecodeConfig + :project: libspdl + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/main/_sources/generated/libspdl/structspdl_1_1core_1_1DemuxConfig.rst.txt b/main/_sources/generated/libspdl/structspdl_1_1core_1_1DemuxConfig.rst.txt new file mode 100644 index 00000000..9d3f1ac8 --- /dev/null +++ b/main/_sources/generated/libspdl/structspdl_1_1core_1_1DemuxConfig.rst.txt @@ -0,0 +1,17 @@ +.. _exhale_struct_structspdl_1_1core_1_1DemuxConfig: + +Struct DemuxConfig +================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_types.h` + + +Struct Documentation +-------------------- + + +.. doxygenstruct:: spdl::core::DemuxConfig + :project: libspdl + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/main/_sources/generated/libspdl/structspdl_1_1core_1_1EncodeConfig.rst.txt b/main/_sources/generated/libspdl/structspdl_1_1core_1_1EncodeConfig.rst.txt new file mode 100644 index 00000000..32d903fc --- /dev/null +++ b/main/_sources/generated/libspdl/structspdl_1_1core_1_1EncodeConfig.rst.txt @@ -0,0 +1,17 @@ +.. _exhale_struct_structspdl_1_1core_1_1EncodeConfig: + +Struct EncodeConfig +=================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_types.h` + + +Struct Documentation +-------------------- + + +.. doxygenstruct:: spdl::core::EncodeConfig + :project: libspdl + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/main/_sources/generated/libspdl/structspdl_1_1core_1_1Rational.rst.txt b/main/_sources/generated/libspdl/structspdl_1_1core_1_1Rational.rst.txt new file mode 100644 index 00000000..5bcac4d4 --- /dev/null +++ b/main/_sources/generated/libspdl/structspdl_1_1core_1_1Rational.rst.txt @@ -0,0 +1,17 @@ +.. _exhale_struct_structspdl_1_1core_1_1Rational: + +Struct Rational +=============== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_types.h` + + +Struct Documentation +-------------------- + + +.. doxygenstruct:: spdl::core::Rational + :project: libspdl + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/main/_sources/generated/libspdl/structspdl_1_1core_1_1SourceAdaptor.rst.txt b/main/_sources/generated/libspdl/structspdl_1_1core_1_1SourceAdaptor.rst.txt new file mode 100644 index 00000000..13f141db --- /dev/null +++ b/main/_sources/generated/libspdl/structspdl_1_1core_1_1SourceAdaptor.rst.txt @@ -0,0 +1,26 @@ +.. _exhale_struct_structspdl_1_1core_1_1SourceAdaptor: + +Struct SourceAdaptor +==================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_adaptor.h` + + +Inheritance Relationships +------------------------- + +Derived Type +************ + +- ``public spdl::core::BytesAdaptor`` (:ref:`exhale_struct_structspdl_1_1core_1_1BytesAdaptor`) + + +Struct Documentation +-------------------- + + +.. doxygenstruct:: spdl::core::SourceAdaptor + :project: libspdl + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/main/_sources/generated/libspdl/structspdl_1_1core_1_1Storage.rst.txt b/main/_sources/generated/libspdl/structspdl_1_1core_1_1Storage.rst.txt new file mode 100644 index 00000000..8fbf65d7 --- /dev/null +++ b/main/_sources/generated/libspdl/structspdl_1_1core_1_1Storage.rst.txt @@ -0,0 +1,27 @@ +.. _exhale_struct_structspdl_1_1core_1_1Storage: + +Struct Storage +============== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_storage.h` + + +Inheritance Relationships +------------------------- + +Derived Types +************* + +- ``public spdl::core::CPUStorage`` (:ref:`exhale_class_classspdl_1_1core_1_1CPUStorage`) +- ``public spdl::core::CUDAStorage`` (:ref:`exhale_class_classspdl_1_1core_1_1CUDAStorage`) + + +Struct Documentation +-------------------- + + +.. doxygenstruct:: spdl::core::Storage + :project: libspdl + :members: + :protected-members: + :undoc-members: \ No newline at end of file diff --git a/main/_sources/generated/libspdl/typedef_adaptor_8h_1aeea90ffba3c9156c91a3f9cea6b1526c.rst.txt b/main/_sources/generated/libspdl/typedef_adaptor_8h_1aeea90ffba3c9156c91a3f9cea6b1526c.rst.txt new file mode 100644 index 00000000..30c9d76c --- /dev/null +++ b/main/_sources/generated/libspdl/typedef_adaptor_8h_1aeea90ffba3c9156c91a3f9cea6b1526c.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_typedef_adaptor_8h_1aeea90ffba3c9156c91a3f9cea6b1526c: + +Typedef spdl::core::SourceAdaptorPtr +==================================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_adaptor.h` + + +Typedef Documentation +--------------------- + + +.. doxygentypedef:: spdl::core::SourceAdaptorPtr + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/typedef_buffer_8h_1a295ea6cb7bed7deb39f245f91beff04b.rst.txt b/main/_sources/generated/libspdl/typedef_buffer_8h_1a295ea6cb7bed7deb39f245f91beff04b.rst.txt new file mode 100644 index 00000000..5cab0008 --- /dev/null +++ b/main/_sources/generated/libspdl/typedef_buffer_8h_1a295ea6cb7bed7deb39f245f91beff04b.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_typedef_buffer_8h_1a295ea6cb7bed7deb39f245f91beff04b: + +Typedef spdl::core::CUDABufferPtr +================================= + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_buffer.h` + + +Typedef Documentation +--------------------- + + +.. doxygentypedef:: spdl::core::CUDABufferPtr + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/typedef_buffer_8h_1aa53ca0dad3d74ed660c4f0ae55bb3ca3.rst.txt b/main/_sources/generated/libspdl/typedef_buffer_8h_1aa53ca0dad3d74ed660c4f0ae55bb3ca3.rst.txt new file mode 100644 index 00000000..6306fd48 --- /dev/null +++ b/main/_sources/generated/libspdl/typedef_buffer_8h_1aa53ca0dad3d74ed660c4f0ae55bb3ca3.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_typedef_buffer_8h_1aa53ca0dad3d74ed660c4f0ae55bb3ca3: + +Typedef spdl::core::CPUBufferPtr +================================ + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_buffer.h` + + +Typedef Documentation +--------------------- + + +.. doxygentypedef:: spdl::core::CPUBufferPtr + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/typedef_decoding_8h_1a8fd65cf6184acafacace029e6a2e20b8.rst.txt b/main/_sources/generated/libspdl/typedef_decoding_8h_1a8fd65cf6184acafacace029e6a2e20b8.rst.txt new file mode 100644 index 00000000..3afdc366 --- /dev/null +++ b/main/_sources/generated/libspdl/typedef_decoding_8h_1a8fd65cf6184acafacace029e6a2e20b8.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_typedef_decoding_8h_1a8fd65cf6184acafacace029e6a2e20b8: + +Typedef spdl::core::DecoderPtr +============================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_decoding.h` + + +Typedef Documentation +--------------------- + + +.. doxygentypedef:: spdl::core::DecoderPtr + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/typedef_demuxing_8h_1a77c7c5e3c314e95c84755ff4be0c7382.rst.txt b/main/_sources/generated/libspdl/typedef_demuxing_8h_1a77c7c5e3c314e95c84755ff4be0c7382.rst.txt new file mode 100644 index 00000000..a1802c02 --- /dev/null +++ b/main/_sources/generated/libspdl/typedef_demuxing_8h_1a77c7c5e3c314e95c84755ff4be0c7382.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_typedef_demuxing_8h_1a77c7c5e3c314e95c84755ff4be0c7382: + +Typedef spdl::core::DemuxerPtr +============================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_demuxing.h` + + +Typedef Documentation +--------------------- + + +.. doxygentypedef:: spdl::core::DemuxerPtr + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/typedef_frames_8h_1a35f2f4ff658c5bf990288f605b286514.rst.txt b/main/_sources/generated/libspdl/typedef_frames_8h_1a35f2f4ff658c5bf990288f605b286514.rst.txt new file mode 100644 index 00000000..fbe9814c --- /dev/null +++ b/main/_sources/generated/libspdl/typedef_frames_8h_1a35f2f4ff658c5bf990288f605b286514.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_typedef_frames_8h_1a35f2f4ff658c5bf990288f605b286514: + +Typedef spdl::core::FFmpegImageFramesPtr +======================================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_frames.h` + + +Typedef Documentation +--------------------- + + +.. doxygentypedef:: spdl::core::FFmpegImageFramesPtr + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/typedef_frames_8h_1a37b07a783dc120ebfbf2bc1df02f63c9.rst.txt b/main/_sources/generated/libspdl/typedef_frames_8h_1a37b07a783dc120ebfbf2bc1df02f63c9.rst.txt new file mode 100644 index 00000000..0ef51ab8 --- /dev/null +++ b/main/_sources/generated/libspdl/typedef_frames_8h_1a37b07a783dc120ebfbf2bc1df02f63c9.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_typedef_frames_8h_1a37b07a783dc120ebfbf2bc1df02f63c9: + +Typedef spdl::core::FFmpegVideoFramesPtr +======================================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_frames.h` + + +Typedef Documentation +--------------------- + + +.. doxygentypedef:: spdl::core::FFmpegVideoFramesPtr + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/typedef_frames_8h_1a6f38c02e59d9bde7760a9662ec20d4f6.rst.txt b/main/_sources/generated/libspdl/typedef_frames_8h_1a6f38c02e59d9bde7760a9662ec20d4f6.rst.txt new file mode 100644 index 00000000..98a7496f --- /dev/null +++ b/main/_sources/generated/libspdl/typedef_frames_8h_1a6f38c02e59d9bde7760a9662ec20d4f6.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_typedef_frames_8h_1a6f38c02e59d9bde7760a9662ec20d4f6: + +Typedef spdl::core::FFmpegAudioFrames +===================================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_frames.h` + + +Typedef Documentation +--------------------- + + +.. doxygentypedef:: spdl::core::FFmpegAudioFrames + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/typedef_frames_8h_1aaa34b66b95f4cc27c8e9333bc20eb179.rst.txt b/main/_sources/generated/libspdl/typedef_frames_8h_1aaa34b66b95f4cc27c8e9333bc20eb179.rst.txt new file mode 100644 index 00000000..07510d9e --- /dev/null +++ b/main/_sources/generated/libspdl/typedef_frames_8h_1aaa34b66b95f4cc27c8e9333bc20eb179.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_typedef_frames_8h_1aaa34b66b95f4cc27c8e9333bc20eb179: + +Typedef spdl::core::FFmpegAudioFramesPtr +======================================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_frames.h` + + +Typedef Documentation +--------------------- + + +.. doxygentypedef:: spdl::core::FFmpegAudioFramesPtr + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/typedef_frames_8h_1ac65015b0c2d25150472229b1af78398a.rst.txt b/main/_sources/generated/libspdl/typedef_frames_8h_1ac65015b0c2d25150472229b1af78398a.rst.txt new file mode 100644 index 00000000..8a7b2b20 --- /dev/null +++ b/main/_sources/generated/libspdl/typedef_frames_8h_1ac65015b0c2d25150472229b1af78398a.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_typedef_frames_8h_1ac65015b0c2d25150472229b1af78398a: + +Typedef spdl::core::FFmpegVideoFrames +===================================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_frames.h` + + +Typedef Documentation +--------------------- + + +.. doxygentypedef:: spdl::core::FFmpegVideoFrames + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/typedef_frames_8h_1af53bca5467cae4ea8c56a12f0c281d7d.rst.txt b/main/_sources/generated/libspdl/typedef_frames_8h_1af53bca5467cae4ea8c56a12f0c281d7d.rst.txt new file mode 100644 index 00000000..51dcebae --- /dev/null +++ b/main/_sources/generated/libspdl/typedef_frames_8h_1af53bca5467cae4ea8c56a12f0c281d7d.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_typedef_frames_8h_1af53bca5467cae4ea8c56a12f0c281d7d: + +Typedef spdl::core::FFmpegFramesPtr +=================================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_frames.h` + + +Typedef Documentation +--------------------- + + +.. doxygentypedef:: spdl::core::FFmpegFramesPtr + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/typedef_frames_8h_1afcf5acc7119e9f97078aa93aba49bdf9.rst.txt b/main/_sources/generated/libspdl/typedef_frames_8h_1afcf5acc7119e9f97078aa93aba49bdf9.rst.txt new file mode 100644 index 00000000..64c2cf68 --- /dev/null +++ b/main/_sources/generated/libspdl/typedef_frames_8h_1afcf5acc7119e9f97078aa93aba49bdf9.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_typedef_frames_8h_1afcf5acc7119e9f97078aa93aba49bdf9: + +Typedef spdl::core::FFmpegImageFrames +===================================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_frames.h` + + +Typedef Documentation +--------------------- + + +.. doxygentypedef:: spdl::core::FFmpegImageFrames + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/typedef_packets_8h_1a40b9e72f2c5acbf57523f3147b49b4d7.rst.txt b/main/_sources/generated/libspdl/typedef_packets_8h_1a40b9e72f2c5acbf57523f3147b49b4d7.rst.txt new file mode 100644 index 00000000..83c3e8e0 --- /dev/null +++ b/main/_sources/generated/libspdl/typedef_packets_8h_1a40b9e72f2c5acbf57523f3147b49b4d7.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_typedef_packets_8h_1a40b9e72f2c5acbf57523f3147b49b4d7: + +Typedef spdl::core::ImagePacketsPtr +=================================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_packets.h` + + +Typedef Documentation +--------------------- + + +.. doxygentypedef:: spdl::core::ImagePacketsPtr + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/typedef_packets_8h_1a491d9af92f6473307b62089e5fd58655.rst.txt b/main/_sources/generated/libspdl/typedef_packets_8h_1a491d9af92f6473307b62089e5fd58655.rst.txt new file mode 100644 index 00000000..36c6a558 --- /dev/null +++ b/main/_sources/generated/libspdl/typedef_packets_8h_1a491d9af92f6473307b62089e5fd58655.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_typedef_packets_8h_1a491d9af92f6473307b62089e5fd58655: + +Typedef spdl::core::VideoPackets +================================ + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_packets.h` + + +Typedef Documentation +--------------------- + + +.. doxygentypedef:: spdl::core::VideoPackets + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/typedef_packets_8h_1a7d8aab12ea6bbedd5f5ac3a61ca35052.rst.txt b/main/_sources/generated/libspdl/typedef_packets_8h_1a7d8aab12ea6bbedd5f5ac3a61ca35052.rst.txt new file mode 100644 index 00000000..fe090401 --- /dev/null +++ b/main/_sources/generated/libspdl/typedef_packets_8h_1a7d8aab12ea6bbedd5f5ac3a61ca35052.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_typedef_packets_8h_1a7d8aab12ea6bbedd5f5ac3a61ca35052: + +Typedef spdl::core::AudioPacketsPtr +=================================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_packets.h` + + +Typedef Documentation +--------------------- + + +.. doxygentypedef:: spdl::core::AudioPacketsPtr + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/typedef_packets_8h_1a9f1d8f8a824887584d6c7afeef0db0ba.rst.txt b/main/_sources/generated/libspdl/typedef_packets_8h_1a9f1d8f8a824887584d6c7afeef0db0ba.rst.txt new file mode 100644 index 00000000..b185cf34 --- /dev/null +++ b/main/_sources/generated/libspdl/typedef_packets_8h_1a9f1d8f8a824887584d6c7afeef0db0ba.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_typedef_packets_8h_1a9f1d8f8a824887584d6c7afeef0db0ba: + +Typedef spdl::core::ImagePackets +================================ + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_packets.h` + + +Typedef Documentation +--------------------- + + +.. doxygentypedef:: spdl::core::ImagePackets + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/typedef_packets_8h_1ac32cc3efe73a9e4d350dea50de9bfc1a.rst.txt b/main/_sources/generated/libspdl/typedef_packets_8h_1ac32cc3efe73a9e4d350dea50de9bfc1a.rst.txt new file mode 100644 index 00000000..4b3e2575 --- /dev/null +++ b/main/_sources/generated/libspdl/typedef_packets_8h_1ac32cc3efe73a9e4d350dea50de9bfc1a.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_typedef_packets_8h_1ac32cc3efe73a9e4d350dea50de9bfc1a: + +Typedef spdl::core::AudioPackets +================================ + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_packets.h` + + +Typedef Documentation +--------------------- + + +.. doxygentypedef:: spdl::core::AudioPackets + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/typedef_packets_8h_1ad0bca8953615860b5cd7c018711defd2.rst.txt b/main/_sources/generated/libspdl/typedef_packets_8h_1ad0bca8953615860b5cd7c018711defd2.rst.txt new file mode 100644 index 00000000..f20992d8 --- /dev/null +++ b/main/_sources/generated/libspdl/typedef_packets_8h_1ad0bca8953615860b5cd7c018711defd2.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_typedef_packets_8h_1ad0bca8953615860b5cd7c018711defd2: + +Typedef spdl::core::PacketsPtr +============================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_packets.h` + + +Typedef Documentation +--------------------- + + +.. doxygentypedef:: spdl::core::PacketsPtr + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/typedef_packets_8h_1ae3f1d293e78dbd0c27d6b9607cc7658e.rst.txt b/main/_sources/generated/libspdl/typedef_packets_8h_1ae3f1d293e78dbd0c27d6b9607cc7658e.rst.txt new file mode 100644 index 00000000..790670ff --- /dev/null +++ b/main/_sources/generated/libspdl/typedef_packets_8h_1ae3f1d293e78dbd0c27d6b9607cc7658e.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_typedef_packets_8h_1ae3f1d293e78dbd0c27d6b9607cc7658e: + +Typedef spdl::core::VideoPacketsPtr +=================================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_packets.h` + + +Typedef Documentation +--------------------- + + +.. doxygentypedef:: spdl::core::VideoPacketsPtr + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/typedef_types_8h_1a2e4149a86d8a55df8a689a1d40855fa8.rst.txt b/main/_sources/generated/libspdl/typedef_types_8h_1a2e4149a86d8a55df8a689a1d40855fa8.rst.txt new file mode 100644 index 00000000..a970622a --- /dev/null +++ b/main/_sources/generated/libspdl/typedef_types_8h_1a2e4149a86d8a55df8a689a1d40855fa8.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_typedef_types_8h_1a2e4149a86d8a55df8a689a1d40855fa8: + +Typedef spdl::core::OptionDict +============================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_types.h` + + +Typedef Documentation +--------------------- + + +.. doxygentypedef:: spdl::core::OptionDict + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/typedef_types_8h_1a4b013fc972e599fc717bd1afd978b083.rst.txt b/main/_sources/generated/libspdl/typedef_types_8h_1a4b013fc972e599fc717bd1afd978b083.rst.txt new file mode 100644 index 00000000..1b2b95c0 --- /dev/null +++ b/main/_sources/generated/libspdl/typedef_types_8h_1a4b013fc972e599fc717bd1afd978b083.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_typedef_types_8h_1a4b013fc972e599fc717bd1afd978b083: + +Typedef spdl::core::cuda_allocator_fn +===================================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_types.h` + + +Typedef Documentation +--------------------- + + +.. doxygentypedef:: spdl::core::cuda_allocator_fn + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/typedef_types_8h_1a58ee8c8a06f6695125b423a1a8532efc.rst.txt b/main/_sources/generated/libspdl/typedef_types_8h_1a58ee8c8a06f6695125b423a1a8532efc.rst.txt new file mode 100644 index 00000000..6bf51be0 --- /dev/null +++ b/main/_sources/generated/libspdl/typedef_types_8h_1a58ee8c8a06f6695125b423a1a8532efc.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_typedef_types_8h_1a58ee8c8a06f6695125b423a1a8532efc: + +Typedef spdl::core::cuda_allocator +================================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_types.h` + + +Typedef Documentation +--------------------- + + +.. doxygentypedef:: spdl::core::cuda_allocator + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/typedef_types_8h_1a8429006d88afae24621607926baef99e.rst.txt b/main/_sources/generated/libspdl/typedef_types_8h_1a8429006d88afae24621607926baef99e.rst.txt new file mode 100644 index 00000000..27501d1c --- /dev/null +++ b/main/_sources/generated/libspdl/typedef_types_8h_1a8429006d88afae24621607926baef99e.rst.txt @@ -0,0 +1,14 @@ +.. _exhale_typedef_types_8h_1a8429006d88afae24621607926baef99e: + +Typedef spdl::core::cuda_deleter_fn +=================================== + +- Defined in :ref:`file__home_runner_work_spdl_spdl_src_libspdl_core_types.h` + + +Typedef Documentation +--------------------- + + +.. doxygentypedef:: spdl::core::cuda_deleter_fn + :project: libspdl \ No newline at end of file diff --git a/main/_sources/generated/libspdl/unabridged_orphan.rst.txt b/main/_sources/generated/libspdl/unabridged_orphan.rst.txt new file mode 100644 index 00000000..39131ef5 --- /dev/null +++ b/main/_sources/generated/libspdl/unabridged_orphan.rst.txt @@ -0,0 +1,88 @@ +:orphan: + + +Full API +======== + +Directories +*********** + + +.. toctree:: + :maxdepth: 5 + + dir__home_runner_work_spdl_spdl_src.rst + +.. toctree:: + :maxdepth: 5 + + dir__home_runner_work_spdl_spdl_src_libspdl.rst + +.. toctree:: + :maxdepth: 5 + + dir__home_runner_work_spdl_spdl_src_libspdl_core.rst + +Files +***** + + +.. toctree:: + :maxdepth: 5 + + file__home_runner_work_spdl_spdl_src_libspdl_core_adaptor.h.rst + +.. toctree:: + :maxdepth: 5 + + file__home_runner_work_spdl_spdl_src_libspdl_core_buffer.h.rst + +.. toctree:: + :maxdepth: 5 + + file__home_runner_work_spdl_spdl_src_libspdl_core_conversion.h.rst + +.. toctree:: + :maxdepth: 5 + + file__home_runner_work_spdl_spdl_src_libspdl_core_decoding.h.rst + +.. toctree:: + :maxdepth: 5 + + file__home_runner_work_spdl_spdl_src_libspdl_core_demuxing.h.rst + +.. toctree:: + :maxdepth: 5 + + file__home_runner_work_spdl_spdl_src_libspdl_core_encoding.h.rst + +.. toctree:: + :maxdepth: 5 + + file__home_runner_work_spdl_spdl_src_libspdl_core_frames.h.rst + +.. toctree:: + :maxdepth: 5 + + file__home_runner_work_spdl_spdl_src_libspdl_core_packets.h.rst + +.. toctree:: + :maxdepth: 5 + + file__home_runner_work_spdl_spdl_src_libspdl_core_storage.h.rst + +.. toctree:: + :maxdepth: 5 + + file__home_runner_work_spdl_spdl_src_libspdl_core_transfer.h.rst + +.. toctree:: + :maxdepth: 5 + + file__home_runner_work_spdl_spdl_src_libspdl_core_types.h.rst + +.. toctree:: + :maxdepth: 5 + + file__home_runner_work_spdl_spdl_src_libspdl_core_utils.h.rst diff --git a/main/_sources/generated/multi_thread_preprocessing.rst.txt b/main/_sources/generated/multi_thread_preprocessing.rst.txt new file mode 100644 index 00000000..10ab6aa5 --- /dev/null +++ b/main/_sources/generated/multi_thread_preprocessing.rst.txt @@ -0,0 +1,100 @@ +.. + Custom template for our custom_autosummary. + The purpose of using custom_autosummary is list the entries on + the right side bar instead of the left side bar. + This is achieved with the combination of custom directive, template and CSS. + + The `custom_autosummary` directive functions mostly like `autosummary`. We + pass `:toctree:` option to generate a doc page for each entry, but we use + our custom `:hide_from_toctree:` option so as not to attach them in ToC tree. + + This template inserts a section header for each entry, so that they show up + in the right-side bar. The headers are hidden by CSS. + + Because each entry will have its own table and their borders no longer match, + table borders are hidden by CSS and instead we use horizontal line. + +.. raw:: html + +
+ +multi\_thread\_preprocessing +============================ + +.. automodule:: multi_thread_preprocessing + +.. + ############################################################################ + Source + ############################################################################ + +Source +------ + +.. rubric:: Source + +.. raw:: html + +
+ Click here to see the source. + +.. literalinclude:: ../../../examples/multi_thread_preprocessing.py + :linenos: + +.. raw:: html + +
+ +.. + ############################################################################ + Functions + ############################################################################ + + + + +Functions +--------- +.. rubric:: Functions + + + +.. autofunction:: multi_thread_preprocessing.entrypoint + + + +.. autofunction:: multi_thread_preprocessing.exp_torch + + + +.. autofunction:: multi_thread_preprocessing.exp_spdl + + + +.. autofunction:: multi_thread_preprocessing.run_dataloader + + + + + +.. + ############################################################################ + Attributes + ############################################################################ + + + + + +.. + ############################################################################ + Classes + ############################################################################ + + + + + +.. raw:: html + +
\ No newline at end of file diff --git a/main/_sources/generated/spdl.dataloader.DataLoader.rst.txt b/main/_sources/generated/spdl.dataloader.DataLoader.rst.txt new file mode 100644 index 00000000..45747e53 --- /dev/null +++ b/main/_sources/generated/spdl.dataloader.DataLoader.rst.txt @@ -0,0 +1,7 @@ +spdl.dataloader.DataLoader +========================== + +.. currentmodule:: spdl.dataloader + +.. autoclass:: DataLoader + :members: \ No newline at end of file diff --git a/main/_sources/generated/spdl.dataloader.MergeIterator.rst.txt b/main/_sources/generated/spdl.dataloader.MergeIterator.rst.txt new file mode 100644 index 00000000..57040603 --- /dev/null +++ b/main/_sources/generated/spdl.dataloader.MergeIterator.rst.txt @@ -0,0 +1,7 @@ +spdl.dataloader.MergeIterator +============================= + +.. currentmodule:: spdl.dataloader + +.. autoclass:: MergeIterator + :members: \ No newline at end of file diff --git a/main/_sources/generated/spdl.dataloader.rst.txt b/main/_sources/generated/spdl.dataloader.rst.txt new file mode 100644 index 00000000..7dea760b --- /dev/null +++ b/main/_sources/generated/spdl.dataloader.rst.txt @@ -0,0 +1,123 @@ +.. + Custom template for our custom_autosummary. + The purpose of using custom_autosummary is list the entries on + the right side bar instead of the left side bar. + This is achieved with the combination of custom directive, template and CSS. + + The `custom_autosummary` directive functions mostly like `autosummary`. We + pass `:toctree:` option to generate a doc page for each entry, but we use + our custom `:hide_from_toctree:` option so as not to attach them in ToC tree. + + This template inserts a section header for each entry, so that they show up + in the right-side bar. The headers are hidden by CSS. + + Because each entry will have its own table and their borders no longer match, + table borders are hidden by CSS and instead we use horizontal line. + +.. raw:: html + +
+ +spdl.dataloader +=============== + +.. automodule:: spdl.dataloader + +.. + ############################################################################ + Functions + ############################################################################ + + + +.. rubric:: Functions + + +run\_in\_subprocess +------------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.dataloader.run_in_subprocess + + + + + +.. + ############################################################################ + Attributes + ############################################################################ + + + + + +.. + ############################################################################ + Classes + ############################################################################ + + + +.. rubric:: Classes + + +DataLoader +---------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + :template: _custom_autosummary_class.rst + + ~spdl.dataloader.DataLoader + + +MergeIterator +------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + :template: _custom_autosummary_class.rst + + ~spdl.dataloader.MergeIterator + + + + + +.. + ############################################################################ + Exceptions + ############################################################################ + + + + + +.. + ############################################################################ + Sub modules + ############################################################################ + + + + + +.. + ############################################################################ + Others + ############################################################################ + + + + + + +.. raw:: html + +
\ No newline at end of file diff --git a/main/_sources/generated/spdl.dataloader.run_in_subprocess.rst.txt b/main/_sources/generated/spdl.dataloader.run_in_subprocess.rst.txt new file mode 100644 index 00000000..3f8892cd --- /dev/null +++ b/main/_sources/generated/spdl.dataloader.run_in_subprocess.rst.txt @@ -0,0 +1,6 @@ +spdl.dataloader.run\_in\_subprocess +=================================== + +.. currentmodule:: spdl.dataloader + +.. autofunction:: run_in_subprocess \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.AudioFrames.rst.txt b/main/_sources/generated/spdl.io.AudioFrames.rst.txt new file mode 100644 index 00000000..506e80f1 --- /dev/null +++ b/main/_sources/generated/spdl.io.AudioFrames.rst.txt @@ -0,0 +1,20 @@ +spdl.io.AudioFrames +=================== + +.. currentmodule:: spdl.io + +.. autoclass:: AudioFrames + :members: + + .. rubric:: Methods + + .. autosummary:: + ~AudioFrames.clone + + .. rubric:: Attributes + + .. autosummary:: + ~AudioFrames.num_channels + ~AudioFrames.num_frames + ~AudioFrames.sample_fmt + ~AudioFrames.sample_rate \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.AudioPackets.rst.txt b/main/_sources/generated/spdl.io.AudioPackets.rst.txt new file mode 100644 index 00000000..d13e92e0 --- /dev/null +++ b/main/_sources/generated/spdl.io.AudioPackets.rst.txt @@ -0,0 +1,19 @@ +spdl.io.AudioPackets +==================== + +.. currentmodule:: spdl.io + +.. autoclass:: AudioPackets + :members: + + .. rubric:: Methods + + .. autosummary:: + ~AudioPackets.clone + + .. rubric:: Attributes + + .. autosummary:: + ~AudioPackets.num_channels + ~AudioPackets.sample_rate + ~AudioPackets.timestamp \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.CPUBuffer.rst.txt b/main/_sources/generated/spdl.io.CPUBuffer.rst.txt new file mode 100644 index 00000000..409191d8 --- /dev/null +++ b/main/_sources/generated/spdl.io.CPUBuffer.rst.txt @@ -0,0 +1,7 @@ +spdl.io.CPUBuffer +================= + +.. currentmodule:: spdl.io + +.. autoclass:: CPUBuffer + :members: \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.CPUStorage.rst.txt b/main/_sources/generated/spdl.io.CPUStorage.rst.txt new file mode 100644 index 00000000..f4ae1283 --- /dev/null +++ b/main/_sources/generated/spdl.io.CPUStorage.rst.txt @@ -0,0 +1,7 @@ +spdl.io.CPUStorage +================== + +.. currentmodule:: spdl.io + +.. autoclass:: CPUStorage + :members: \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.CUDABuffer.rst.txt b/main/_sources/generated/spdl.io.CUDABuffer.rst.txt new file mode 100644 index 00000000..a6d12428 --- /dev/null +++ b/main/_sources/generated/spdl.io.CUDABuffer.rst.txt @@ -0,0 +1,12 @@ +spdl.io.CUDABuffer +================== + +.. currentmodule:: spdl.io + +.. autoclass:: CUDABuffer + :members: + + .. rubric:: Attributes + + .. autosummary:: + ~CUDABuffer.device_index \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.CUDAConfig.rst.txt b/main/_sources/generated/spdl.io.CUDAConfig.rst.txt new file mode 100644 index 00000000..b426bb1a --- /dev/null +++ b/main/_sources/generated/spdl.io.CUDAConfig.rst.txt @@ -0,0 +1,7 @@ +spdl.io.CUDAConfig +================== + +.. currentmodule:: spdl.io + +.. autoclass:: CUDAConfig + :members: \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.DecodeConfig.rst.txt b/main/_sources/generated/spdl.io.DecodeConfig.rst.txt new file mode 100644 index 00000000..33f8a77e --- /dev/null +++ b/main/_sources/generated/spdl.io.DecodeConfig.rst.txt @@ -0,0 +1,7 @@ +spdl.io.DecodeConfig +==================== + +.. currentmodule:: spdl.io + +.. autoclass:: DecodeConfig + :members: \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.DemuxConfig.rst.txt b/main/_sources/generated/spdl.io.DemuxConfig.rst.txt new file mode 100644 index 00000000..a64ab358 --- /dev/null +++ b/main/_sources/generated/spdl.io.DemuxConfig.rst.txt @@ -0,0 +1,7 @@ +spdl.io.DemuxConfig +=================== + +.. currentmodule:: spdl.io + +.. autoclass:: DemuxConfig + :members: \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.Demuxer.rst.txt b/main/_sources/generated/spdl.io.Demuxer.rst.txt new file mode 100644 index 00000000..36639b6b --- /dev/null +++ b/main/_sources/generated/spdl.io.Demuxer.rst.txt @@ -0,0 +1,15 @@ +spdl.io.Demuxer +=============== + +.. currentmodule:: spdl.io + +.. autoclass:: Demuxer + :members: + + .. rubric:: Methods + + .. autosummary:: + ~Demuxer.demux_audio + ~Demuxer.demux_image + ~Demuxer.demux_video + ~Demuxer.has_audio \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.EncodeConfig.rst.txt b/main/_sources/generated/spdl.io.EncodeConfig.rst.txt new file mode 100644 index 00000000..d1e0a25c --- /dev/null +++ b/main/_sources/generated/spdl.io.EncodeConfig.rst.txt @@ -0,0 +1,7 @@ +spdl.io.EncodeConfig +==================== + +.. currentmodule:: spdl.io + +.. autoclass:: EncodeConfig + :members: \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.Frames.rst.txt b/main/_sources/generated/spdl.io.Frames.rst.txt new file mode 100644 index 00000000..ac46a468 --- /dev/null +++ b/main/_sources/generated/spdl.io.Frames.rst.txt @@ -0,0 +1,7 @@ +spdl.io.Frames +============== + +.. currentmodule:: spdl.io + +.. autoclass:: Frames + :members: \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.ImageFrames.rst.txt b/main/_sources/generated/spdl.io.ImageFrames.rst.txt new file mode 100644 index 00000000..fa21a17e --- /dev/null +++ b/main/_sources/generated/spdl.io.ImageFrames.rst.txt @@ -0,0 +1,22 @@ +spdl.io.ImageFrames +=================== + +.. currentmodule:: spdl.io + +.. autoclass:: ImageFrames + :members: + + .. rubric:: Methods + + .. autosummary:: + ~ImageFrames.clone + + .. rubric:: Attributes + + .. autosummary:: + ~ImageFrames.height + ~ImageFrames.metadata + ~ImageFrames.num_planes + ~ImageFrames.pix_fmt + ~ImageFrames.pts + ~ImageFrames.width \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.ImagePackets.rst.txt b/main/_sources/generated/spdl.io.ImagePackets.rst.txt new file mode 100644 index 00000000..1bfd04a9 --- /dev/null +++ b/main/_sources/generated/spdl.io.ImagePackets.rst.txt @@ -0,0 +1,19 @@ +spdl.io.ImagePackets +==================== + +.. currentmodule:: spdl.io + +.. autoclass:: ImagePackets + :members: + + .. rubric:: Methods + + .. autosummary:: + ~ImagePackets.clone + + .. rubric:: Attributes + + .. autosummary:: + ~ImagePackets.height + ~ImagePackets.pix_fmt + ~ImagePackets.width \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.NpzFile.rst.txt b/main/_sources/generated/spdl.io.NpzFile.rst.txt new file mode 100644 index 00000000..2d519284 --- /dev/null +++ b/main/_sources/generated/spdl.io.NpzFile.rst.txt @@ -0,0 +1,16 @@ +spdl.io.NpzFile +=============== + +.. currentmodule:: spdl.io + +.. autoclass:: NpzFile + :members: + + .. rubric:: Methods + + .. autosummary:: + ~NpzFile.close + ~NpzFile.get + ~NpzFile.items + ~NpzFile.keys + ~NpzFile.values \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.Packets.rst.txt b/main/_sources/generated/spdl.io.Packets.rst.txt new file mode 100644 index 00000000..2c839887 --- /dev/null +++ b/main/_sources/generated/spdl.io.Packets.rst.txt @@ -0,0 +1,7 @@ +spdl.io.Packets +=============== + +.. currentmodule:: spdl.io + +.. autoclass:: Packets + :members: \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.VideoFrames.rst.txt b/main/_sources/generated/spdl.io.VideoFrames.rst.txt new file mode 100644 index 00000000..42c87a49 --- /dev/null +++ b/main/_sources/generated/spdl.io.VideoFrames.rst.txt @@ -0,0 +1,21 @@ +spdl.io.VideoFrames +=================== + +.. currentmodule:: spdl.io + +.. autoclass:: VideoFrames + :members: + + .. rubric:: Methods + + .. autosummary:: + ~VideoFrames.clone + + .. rubric:: Attributes + + .. autosummary:: + ~VideoFrames.height + ~VideoFrames.num_frames + ~VideoFrames.num_planes + ~VideoFrames.pix_fmt + ~VideoFrames.width \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.VideoPackets.rst.txt b/main/_sources/generated/spdl.io.VideoPackets.rst.txt new file mode 100644 index 00000000..9e27e421 --- /dev/null +++ b/main/_sources/generated/spdl.io.VideoPackets.rst.txt @@ -0,0 +1,21 @@ +spdl.io.VideoPackets +==================== + +.. currentmodule:: spdl.io + +.. autoclass:: VideoPackets + :members: + + .. rubric:: Methods + + .. autosummary:: + ~VideoPackets.clone + + .. rubric:: Attributes + + .. autosummary:: + ~VideoPackets.frame_rate + ~VideoPackets.height + ~VideoPackets.pix_fmt + ~VideoPackets.timestamp + ~VideoPackets.width \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.async_convert_array.rst.txt b/main/_sources/generated/spdl.io.async_convert_array.rst.txt new file mode 100644 index 00000000..c017c1e8 --- /dev/null +++ b/main/_sources/generated/spdl.io.async_convert_array.rst.txt @@ -0,0 +1,6 @@ +spdl.io.async\_convert\_array +============================= + +.. currentmodule:: spdl.io + +.. autofunction:: async_convert_array \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.async_convert_frames.rst.txt b/main/_sources/generated/spdl.io.async_convert_frames.rst.txt new file mode 100644 index 00000000..2ba6c988 --- /dev/null +++ b/main/_sources/generated/spdl.io.async_convert_frames.rst.txt @@ -0,0 +1,6 @@ +spdl.io.async\_convert\_frames +============================== + +.. currentmodule:: spdl.io + +.. autofunction:: async_convert_frames \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.async_decode_image_nvjpeg.rst.txt b/main/_sources/generated/spdl.io.async_decode_image_nvjpeg.rst.txt new file mode 100644 index 00000000..3036dc91 --- /dev/null +++ b/main/_sources/generated/spdl.io.async_decode_image_nvjpeg.rst.txt @@ -0,0 +1,6 @@ +spdl.io.async\_decode\_image\_nvjpeg +==================================== + +.. currentmodule:: spdl.io + +.. autofunction:: async_decode_image_nvjpeg \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.async_decode_packets.rst.txt b/main/_sources/generated/spdl.io.async_decode_packets.rst.txt new file mode 100644 index 00000000..993d09a9 --- /dev/null +++ b/main/_sources/generated/spdl.io.async_decode_packets.rst.txt @@ -0,0 +1,6 @@ +spdl.io.async\_decode\_packets +============================== + +.. currentmodule:: spdl.io + +.. autofunction:: async_decode_packets \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.async_decode_packets_nvdec.rst.txt b/main/_sources/generated/spdl.io.async_decode_packets_nvdec.rst.txt new file mode 100644 index 00000000..49aeefaa --- /dev/null +++ b/main/_sources/generated/spdl.io.async_decode_packets_nvdec.rst.txt @@ -0,0 +1,6 @@ +spdl.io.async\_decode\_packets\_nvdec +===================================== + +.. currentmodule:: spdl.io + +.. autofunction:: async_decode_packets_nvdec \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.async_demux_audio.rst.txt b/main/_sources/generated/spdl.io.async_demux_audio.rst.txt new file mode 100644 index 00000000..c9b08c90 --- /dev/null +++ b/main/_sources/generated/spdl.io.async_demux_audio.rst.txt @@ -0,0 +1,6 @@ +spdl.io.async\_demux\_audio +=========================== + +.. currentmodule:: spdl.io + +.. autofunction:: async_demux_audio \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.async_demux_image.rst.txt b/main/_sources/generated/spdl.io.async_demux_image.rst.txt new file mode 100644 index 00000000..c68ba227 --- /dev/null +++ b/main/_sources/generated/spdl.io.async_demux_image.rst.txt @@ -0,0 +1,6 @@ +spdl.io.async\_demux\_image +=========================== + +.. currentmodule:: spdl.io + +.. autofunction:: async_demux_image \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.async_demux_video.rst.txt b/main/_sources/generated/spdl.io.async_demux_video.rst.txt new file mode 100644 index 00000000..47c2c1a7 --- /dev/null +++ b/main/_sources/generated/spdl.io.async_demux_video.rst.txt @@ -0,0 +1,6 @@ +spdl.io.async\_demux\_video +=========================== + +.. currentmodule:: spdl.io + +.. autofunction:: async_demux_video \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.async_encode_image.rst.txt b/main/_sources/generated/spdl.io.async_encode_image.rst.txt new file mode 100644 index 00000000..0ecfc6dc --- /dev/null +++ b/main/_sources/generated/spdl.io.async_encode_image.rst.txt @@ -0,0 +1,6 @@ +spdl.io.async\_encode\_image +============================ + +.. currentmodule:: spdl.io + +.. autofunction:: async_encode_image \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.async_load_audio.rst.txt b/main/_sources/generated/spdl.io.async_load_audio.rst.txt new file mode 100644 index 00000000..9ab840f5 --- /dev/null +++ b/main/_sources/generated/spdl.io.async_load_audio.rst.txt @@ -0,0 +1,6 @@ +spdl.io.async\_load\_audio +========================== + +.. currentmodule:: spdl.io + +.. autofunction:: async_load_audio \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.async_load_image.rst.txt b/main/_sources/generated/spdl.io.async_load_image.rst.txt new file mode 100644 index 00000000..990116da --- /dev/null +++ b/main/_sources/generated/spdl.io.async_load_image.rst.txt @@ -0,0 +1,6 @@ +spdl.io.async\_load\_image +========================== + +.. currentmodule:: spdl.io + +.. autofunction:: async_load_image \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.async_load_image_batch.rst.txt b/main/_sources/generated/spdl.io.async_load_image_batch.rst.txt new file mode 100644 index 00000000..7b35ab3c --- /dev/null +++ b/main/_sources/generated/spdl.io.async_load_image_batch.rst.txt @@ -0,0 +1,6 @@ +spdl.io.async\_load\_image\_batch +================================= + +.. currentmodule:: spdl.io + +.. autofunction:: async_load_image_batch \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.async_load_image_batch_nvdec.rst.txt b/main/_sources/generated/spdl.io.async_load_image_batch_nvdec.rst.txt new file mode 100644 index 00000000..ca441d45 --- /dev/null +++ b/main/_sources/generated/spdl.io.async_load_image_batch_nvdec.rst.txt @@ -0,0 +1,6 @@ +spdl.io.async\_load\_image\_batch\_nvdec +======================================== + +.. currentmodule:: spdl.io + +.. autofunction:: async_load_image_batch_nvdec \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.async_load_image_batch_nvjpeg.rst.txt b/main/_sources/generated/spdl.io.async_load_image_batch_nvjpeg.rst.txt new file mode 100644 index 00000000..e75f33c5 --- /dev/null +++ b/main/_sources/generated/spdl.io.async_load_image_batch_nvjpeg.rst.txt @@ -0,0 +1,6 @@ +spdl.io.async\_load\_image\_batch\_nvjpeg +========================================= + +.. currentmodule:: spdl.io + +.. autofunction:: async_load_image_batch_nvjpeg \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.async_load_video.rst.txt b/main/_sources/generated/spdl.io.async_load_video.rst.txt new file mode 100644 index 00000000..229a0080 --- /dev/null +++ b/main/_sources/generated/spdl.io.async_load_video.rst.txt @@ -0,0 +1,6 @@ +spdl.io.async\_load\_video +========================== + +.. currentmodule:: spdl.io + +.. autofunction:: async_load_video \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.async_sample_decode_video.rst.txt b/main/_sources/generated/spdl.io.async_sample_decode_video.rst.txt new file mode 100644 index 00000000..339d6c82 --- /dev/null +++ b/main/_sources/generated/spdl.io.async_sample_decode_video.rst.txt @@ -0,0 +1,6 @@ +spdl.io.async\_sample\_decode\_video +==================================== + +.. currentmodule:: spdl.io + +.. autofunction:: async_sample_decode_video \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.async_streaming_decode_packets.rst.txt b/main/_sources/generated/spdl.io.async_streaming_decode_packets.rst.txt new file mode 100644 index 00000000..f2a900e3 --- /dev/null +++ b/main/_sources/generated/spdl.io.async_streaming_decode_packets.rst.txt @@ -0,0 +1,6 @@ +spdl.io.async\_streaming\_decode\_packets +========================================= + +.. currentmodule:: spdl.io + +.. autofunction:: async_streaming_decode_packets \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.async_transfer_buffer.rst.txt b/main/_sources/generated/spdl.io.async_transfer_buffer.rst.txt new file mode 100644 index 00000000..25bea4d8 --- /dev/null +++ b/main/_sources/generated/spdl.io.async_transfer_buffer.rst.txt @@ -0,0 +1,6 @@ +spdl.io.async\_transfer\_buffer +=============================== + +.. currentmodule:: spdl.io + +.. autofunction:: async_transfer_buffer \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.async_transfer_buffer_cpu.rst.txt b/main/_sources/generated/spdl.io.async_transfer_buffer_cpu.rst.txt new file mode 100644 index 00000000..197654e3 --- /dev/null +++ b/main/_sources/generated/spdl.io.async_transfer_buffer_cpu.rst.txt @@ -0,0 +1,6 @@ +spdl.io.async\_transfer\_buffer\_cpu +==================================== + +.. currentmodule:: spdl.io + +.. autofunction:: async_transfer_buffer_cpu \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.convert_array.rst.txt b/main/_sources/generated/spdl.io.convert_array.rst.txt new file mode 100644 index 00000000..2cf481b0 --- /dev/null +++ b/main/_sources/generated/spdl.io.convert_array.rst.txt @@ -0,0 +1,6 @@ +spdl.io.convert\_array +====================== + +.. currentmodule:: spdl.io + +.. autofunction:: convert_array \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.convert_frames.rst.txt b/main/_sources/generated/spdl.io.convert_frames.rst.txt new file mode 100644 index 00000000..12901ec5 --- /dev/null +++ b/main/_sources/generated/spdl.io.convert_frames.rst.txt @@ -0,0 +1,6 @@ +spdl.io.convert\_frames +======================= + +.. currentmodule:: spdl.io + +.. autofunction:: convert_frames \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.cpu_storage.rst.txt b/main/_sources/generated/spdl.io.cpu_storage.rst.txt new file mode 100644 index 00000000..6ec467f1 --- /dev/null +++ b/main/_sources/generated/spdl.io.cpu_storage.rst.txt @@ -0,0 +1,6 @@ +spdl.io.cpu\_storage +==================== + +.. currentmodule:: spdl.io + +.. autofunction:: cpu_storage \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.cuda_config.rst.txt b/main/_sources/generated/spdl.io.cuda_config.rst.txt new file mode 100644 index 00000000..3c0e711a --- /dev/null +++ b/main/_sources/generated/spdl.io.cuda_config.rst.txt @@ -0,0 +1,6 @@ +spdl.io.cuda\_config +==================== + +.. currentmodule:: spdl.io + +.. autofunction:: cuda_config \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.decode_config.rst.txt b/main/_sources/generated/spdl.io.decode_config.rst.txt new file mode 100644 index 00000000..47014f18 --- /dev/null +++ b/main/_sources/generated/spdl.io.decode_config.rst.txt @@ -0,0 +1,6 @@ +spdl.io.decode\_config +====================== + +.. currentmodule:: spdl.io + +.. autofunction:: decode_config \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.decode_image_nvjpeg.rst.txt b/main/_sources/generated/spdl.io.decode_image_nvjpeg.rst.txt new file mode 100644 index 00000000..f581a93b --- /dev/null +++ b/main/_sources/generated/spdl.io.decode_image_nvjpeg.rst.txt @@ -0,0 +1,6 @@ +spdl.io.decode\_image\_nvjpeg +============================= + +.. currentmodule:: spdl.io + +.. autofunction:: decode_image_nvjpeg \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.decode_packets.rst.txt b/main/_sources/generated/spdl.io.decode_packets.rst.txt new file mode 100644 index 00000000..a40c4bfd --- /dev/null +++ b/main/_sources/generated/spdl.io.decode_packets.rst.txt @@ -0,0 +1,6 @@ +spdl.io.decode\_packets +======================= + +.. currentmodule:: spdl.io + +.. autofunction:: decode_packets \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.decode_packets_nvdec.rst.txt b/main/_sources/generated/spdl.io.decode_packets_nvdec.rst.txt new file mode 100644 index 00000000..e7e389f8 --- /dev/null +++ b/main/_sources/generated/spdl.io.decode_packets_nvdec.rst.txt @@ -0,0 +1,6 @@ +spdl.io.decode\_packets\_nvdec +============================== + +.. currentmodule:: spdl.io + +.. autofunction:: decode_packets_nvdec \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.demux_audio.rst.txt b/main/_sources/generated/spdl.io.demux_audio.rst.txt new file mode 100644 index 00000000..a1939463 --- /dev/null +++ b/main/_sources/generated/spdl.io.demux_audio.rst.txt @@ -0,0 +1,6 @@ +spdl.io.demux\_audio +==================== + +.. currentmodule:: spdl.io + +.. autofunction:: demux_audio \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.demux_config.rst.txt b/main/_sources/generated/spdl.io.demux_config.rst.txt new file mode 100644 index 00000000..d6737a05 --- /dev/null +++ b/main/_sources/generated/spdl.io.demux_config.rst.txt @@ -0,0 +1,6 @@ +spdl.io.demux\_config +===================== + +.. currentmodule:: spdl.io + +.. autofunction:: demux_config \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.demux_image.rst.txt b/main/_sources/generated/spdl.io.demux_image.rst.txt new file mode 100644 index 00000000..b0f85210 --- /dev/null +++ b/main/_sources/generated/spdl.io.demux_image.rst.txt @@ -0,0 +1,6 @@ +spdl.io.demux\_image +==================== + +.. currentmodule:: spdl.io + +.. autofunction:: demux_image \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.demux_video.rst.txt b/main/_sources/generated/spdl.io.demux_video.rst.txt new file mode 100644 index 00000000..ec3996e4 --- /dev/null +++ b/main/_sources/generated/spdl.io.demux_video.rst.txt @@ -0,0 +1,6 @@ +spdl.io.demux\_video +==================== + +.. currentmodule:: spdl.io + +.. autofunction:: demux_video \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.encode_config.rst.txt b/main/_sources/generated/spdl.io.encode_config.rst.txt new file mode 100644 index 00000000..797e9b99 --- /dev/null +++ b/main/_sources/generated/spdl.io.encode_config.rst.txt @@ -0,0 +1,6 @@ +spdl.io.encode\_config +====================== + +.. currentmodule:: spdl.io + +.. autofunction:: encode_config \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.encode_image.rst.txt b/main/_sources/generated/spdl.io.encode_image.rst.txt new file mode 100644 index 00000000..08ed5ea8 --- /dev/null +++ b/main/_sources/generated/spdl.io.encode_image.rst.txt @@ -0,0 +1,6 @@ +spdl.io.encode\_image +===================== + +.. currentmodule:: spdl.io + +.. autofunction:: encode_image \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.get_audio_filter_desc.rst.txt b/main/_sources/generated/spdl.io.get_audio_filter_desc.rst.txt new file mode 100644 index 00000000..cc86dc78 --- /dev/null +++ b/main/_sources/generated/spdl.io.get_audio_filter_desc.rst.txt @@ -0,0 +1,6 @@ +spdl.io.get\_audio\_filter\_desc +================================ + +.. currentmodule:: spdl.io + +.. autofunction:: get_audio_filter_desc \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.get_filter_desc.rst.txt b/main/_sources/generated/spdl.io.get_filter_desc.rst.txt new file mode 100644 index 00000000..c3a7d885 --- /dev/null +++ b/main/_sources/generated/spdl.io.get_filter_desc.rst.txt @@ -0,0 +1,6 @@ +spdl.io.get\_filter\_desc +========================= + +.. currentmodule:: spdl.io + +.. autofunction:: get_filter_desc \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.get_video_filter_desc.rst.txt b/main/_sources/generated/spdl.io.get_video_filter_desc.rst.txt new file mode 100644 index 00000000..8879290c --- /dev/null +++ b/main/_sources/generated/spdl.io.get_video_filter_desc.rst.txt @@ -0,0 +1,6 @@ +spdl.io.get\_video\_filter\_desc +================================ + +.. currentmodule:: spdl.io + +.. autofunction:: get_video_filter_desc \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.load_audio.rst.txt b/main/_sources/generated/spdl.io.load_audio.rst.txt new file mode 100644 index 00000000..778e9e27 --- /dev/null +++ b/main/_sources/generated/spdl.io.load_audio.rst.txt @@ -0,0 +1,6 @@ +spdl.io.load\_audio +=================== + +.. currentmodule:: spdl.io + +.. autofunction:: load_audio \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.load_image.rst.txt b/main/_sources/generated/spdl.io.load_image.rst.txt new file mode 100644 index 00000000..4f52c3ac --- /dev/null +++ b/main/_sources/generated/spdl.io.load_image.rst.txt @@ -0,0 +1,6 @@ +spdl.io.load\_image +=================== + +.. currentmodule:: spdl.io + +.. autofunction:: load_image \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.load_image_batch_nvjpeg.rst.txt b/main/_sources/generated/spdl.io.load_image_batch_nvjpeg.rst.txt new file mode 100644 index 00000000..34ecb2c1 --- /dev/null +++ b/main/_sources/generated/spdl.io.load_image_batch_nvjpeg.rst.txt @@ -0,0 +1,6 @@ +spdl.io.load\_image\_batch\_nvjpeg +================================== + +.. currentmodule:: spdl.io + +.. autofunction:: load_image_batch_nvjpeg \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.load_npz.rst.txt b/main/_sources/generated/spdl.io.load_npz.rst.txt new file mode 100644 index 00000000..620e7b84 --- /dev/null +++ b/main/_sources/generated/spdl.io.load_npz.rst.txt @@ -0,0 +1,6 @@ +spdl.io.load\_npz +================= + +.. currentmodule:: spdl.io + +.. autofunction:: load_npz \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.load_video.rst.txt b/main/_sources/generated/spdl.io.load_video.rst.txt new file mode 100644 index 00000000..5582a89b --- /dev/null +++ b/main/_sources/generated/spdl.io.load_video.rst.txt @@ -0,0 +1,6 @@ +spdl.io.load\_video +=================== + +.. currentmodule:: spdl.io + +.. autofunction:: load_video \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.rst.txt b/main/_sources/generated/spdl.io.rst.txt new file mode 100644 index 00000000..9b7d0068 --- /dev/null +++ b/main/_sources/generated/spdl.io.rst.txt @@ -0,0 +1,842 @@ +.. + Custom template for our custom_autosummary. + The purpose of using custom_autosummary is list the entries on + the right side bar instead of the left side bar. + This is achieved with the combination of custom directive, template and CSS. + + The `custom_autosummary` directive functions mostly like `autosummary`. We + pass `:toctree:` option to generate a doc page for each entry, but we use + our custom `:hide_from_toctree:` option so as not to attach them in ToC tree. + + This template inserts a section header for each entry, so that they show up + in the right-side bar. The headers are hidden by CSS. + + Because each entry will have its own table and their borders no longer match, + table borders are hidden by CSS and instead we use horizontal line. + +.. raw:: html + +
+ +spdl.io +======= + +.. automodule:: spdl.io + +.. + ############################################################################ + Functions + ############################################################################ + + + +.. rubric:: Functions + + +async\_convert\_array +--------------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.async_convert_array + + +async\_convert\_frames +---------------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.async_convert_frames + + +async\_decode\_image\_nvjpeg +---------------------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.async_decode_image_nvjpeg + + +async\_decode\_packets +---------------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.async_decode_packets + + +async\_decode\_packets\_nvdec +----------------------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.async_decode_packets_nvdec + + +async\_demux\_audio +------------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.async_demux_audio + + +async\_demux\_image +------------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.async_demux_image + + +async\_demux\_video +------------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.async_demux_video + + +async\_encode\_image +-------------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.async_encode_image + + +async\_load\_audio +------------------ +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.async_load_audio + + +async\_load\_image +------------------ +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.async_load_image + + +async\_load\_image\_batch +------------------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.async_load_image_batch + + +async\_load\_image\_batch\_nvdec +-------------------------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.async_load_image_batch_nvdec + + +async\_load\_image\_batch\_nvjpeg +--------------------------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.async_load_image_batch_nvjpeg + + +async\_load\_video +------------------ +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.async_load_video + + +async\_sample\_decode\_video +---------------------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.async_sample_decode_video + + +async\_streaming\_decode\_packets +--------------------------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.async_streaming_decode_packets + + +async\_transfer\_buffer +----------------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.async_transfer_buffer + + +async\_transfer\_buffer\_cpu +---------------------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.async_transfer_buffer_cpu + + +convert\_array +-------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.convert_array + + +convert\_frames +--------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.convert_frames + + +cpu\_storage +------------ +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.cpu_storage + + +cuda\_config +------------ +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.cuda_config + + +decode\_config +-------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.decode_config + + +decode\_image\_nvjpeg +--------------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.decode_image_nvjpeg + + +decode\_packets +--------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.decode_packets + + +decode\_packets\_nvdec +---------------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.decode_packets_nvdec + + +demux\_audio +------------ +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.demux_audio + + +demux\_config +------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.demux_config + + +demux\_image +------------ +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.demux_image + + +demux\_video +------------ +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.demux_video + + +encode\_config +-------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.encode_config + + +encode\_image +------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.encode_image + + +get\_audio\_filter\_desc +------------------------ +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.get_audio_filter_desc + + +get\_filter\_desc +----------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.get_filter_desc + + +get\_video\_filter\_desc +------------------------ +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.get_video_filter_desc + + +load\_audio +----------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.load_audio + + +load\_image +----------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.load_image + + +load\_image\_batch\_nvjpeg +-------------------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.load_image_batch_nvjpeg + + +load\_npz +--------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.load_npz + + +load\_video +----------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.load_video + + +run\_async +---------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.run_async + + +sample\_decode\_video +--------------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.sample_decode_video + + +streaming\_decode\_packets +-------------------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.streaming_decode_packets + + +to\_jax +------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.to_jax + + +to\_numba +--------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.to_numba + + +to\_numpy +--------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.to_numpy + + +to\_torch +--------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.to_torch + + +transfer\_buffer +---------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.transfer_buffer + + +transfer\_buffer\_cpu +--------------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.io.transfer_buffer_cpu + + + + + +.. + ############################################################################ + Attributes + ############################################################################ + + + + + +.. + ############################################################################ + Classes + ############################################################################ + + + +.. rubric:: Classes + + +AudioFrames +----------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + :template: _custom_autosummary_class.rst + + ~spdl.io.AudioFrames + + +AudioPackets +------------ +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + :template: _custom_autosummary_class.rst + + ~spdl.io.AudioPackets + + +CPUBuffer +--------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + :template: _custom_autosummary_class.rst + + ~spdl.io.CPUBuffer + + +CPUStorage +---------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + :template: _custom_autosummary_class.rst + + ~spdl.io.CPUStorage + + +CUDABuffer +---------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + :template: _custom_autosummary_class.rst + + ~spdl.io.CUDABuffer + + +CUDAConfig +---------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + :template: _custom_autosummary_class.rst + + ~spdl.io.CUDAConfig + + +DecodeConfig +------------ +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + :template: _custom_autosummary_class.rst + + ~spdl.io.DecodeConfig + + +DemuxConfig +----------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + :template: _custom_autosummary_class.rst + + ~spdl.io.DemuxConfig + + +Demuxer +------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + :template: _custom_autosummary_class.rst + + ~spdl.io.Demuxer + + +EncodeConfig +------------ +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + :template: _custom_autosummary_class.rst + + ~spdl.io.EncodeConfig + + +Frames +------ +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + :template: _custom_autosummary_class.rst + + ~spdl.io.Frames + + +ImageFrames +----------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + :template: _custom_autosummary_class.rst + + ~spdl.io.ImageFrames + + +ImagePackets +------------ +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + :template: _custom_autosummary_class.rst + + ~spdl.io.ImagePackets + + +NpzFile +------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + :template: _custom_autosummary_class.rst + + ~spdl.io.NpzFile + + +Packets +------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + :template: _custom_autosummary_class.rst + + ~spdl.io.Packets + + +VideoFrames +----------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + :template: _custom_autosummary_class.rst + + ~spdl.io.VideoFrames + + +VideoPackets +------------ +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + :template: _custom_autosummary_class.rst + + ~spdl.io.VideoPackets + + + + + +.. + ############################################################################ + Exceptions + ############################################################################ + + + + + +.. + ############################################################################ + Sub modules + ############################################################################ + + + + + +.. + ############################################################################ + Others + ############################################################################ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +.. raw:: html + +
\ No newline at end of file diff --git a/main/_sources/generated/spdl.io.run_async.rst.txt b/main/_sources/generated/spdl.io.run_async.rst.txt new file mode 100644 index 00000000..cb8e46e8 --- /dev/null +++ b/main/_sources/generated/spdl.io.run_async.rst.txt @@ -0,0 +1,6 @@ +spdl.io.run\_async +================== + +.. currentmodule:: spdl.io + +.. autofunction:: run_async \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.sample_decode_video.rst.txt b/main/_sources/generated/spdl.io.sample_decode_video.rst.txt new file mode 100644 index 00000000..acc0c03f --- /dev/null +++ b/main/_sources/generated/spdl.io.sample_decode_video.rst.txt @@ -0,0 +1,6 @@ +spdl.io.sample\_decode\_video +============================= + +.. currentmodule:: spdl.io + +.. autofunction:: sample_decode_video \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.streaming_decode_packets.rst.txt b/main/_sources/generated/spdl.io.streaming_decode_packets.rst.txt new file mode 100644 index 00000000..fda2c4c7 --- /dev/null +++ b/main/_sources/generated/spdl.io.streaming_decode_packets.rst.txt @@ -0,0 +1,6 @@ +spdl.io.streaming\_decode\_packets +================================== + +.. currentmodule:: spdl.io + +.. autofunction:: streaming_decode_packets \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.to_jax.rst.txt b/main/_sources/generated/spdl.io.to_jax.rst.txt new file mode 100644 index 00000000..f9bdd6cc --- /dev/null +++ b/main/_sources/generated/spdl.io.to_jax.rst.txt @@ -0,0 +1,6 @@ +spdl.io.to\_jax +=============== + +.. currentmodule:: spdl.io + +.. autofunction:: to_jax \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.to_numba.rst.txt b/main/_sources/generated/spdl.io.to_numba.rst.txt new file mode 100644 index 00000000..e06531b8 --- /dev/null +++ b/main/_sources/generated/spdl.io.to_numba.rst.txt @@ -0,0 +1,6 @@ +spdl.io.to\_numba +================= + +.. currentmodule:: spdl.io + +.. autofunction:: to_numba \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.to_numpy.rst.txt b/main/_sources/generated/spdl.io.to_numpy.rst.txt new file mode 100644 index 00000000..ca69d04c --- /dev/null +++ b/main/_sources/generated/spdl.io.to_numpy.rst.txt @@ -0,0 +1,6 @@ +spdl.io.to\_numpy +================= + +.. currentmodule:: spdl.io + +.. autofunction:: to_numpy \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.to_torch.rst.txt b/main/_sources/generated/spdl.io.to_torch.rst.txt new file mode 100644 index 00000000..fcd17240 --- /dev/null +++ b/main/_sources/generated/spdl.io.to_torch.rst.txt @@ -0,0 +1,6 @@ +spdl.io.to\_torch +================= + +.. currentmodule:: spdl.io + +.. autofunction:: to_torch \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.transfer_buffer.rst.txt b/main/_sources/generated/spdl.io.transfer_buffer.rst.txt new file mode 100644 index 00000000..eeed0daf --- /dev/null +++ b/main/_sources/generated/spdl.io.transfer_buffer.rst.txt @@ -0,0 +1,6 @@ +spdl.io.transfer\_buffer +======================== + +.. currentmodule:: spdl.io + +.. autofunction:: transfer_buffer \ No newline at end of file diff --git a/main/_sources/generated/spdl.io.transfer_buffer_cpu.rst.txt b/main/_sources/generated/spdl.io.transfer_buffer_cpu.rst.txt new file mode 100644 index 00000000..418d52d7 --- /dev/null +++ b/main/_sources/generated/spdl.io.transfer_buffer_cpu.rst.txt @@ -0,0 +1,6 @@ +spdl.io.transfer\_buffer\_cpu +============================= + +.. currentmodule:: spdl.io + +.. autofunction:: transfer_buffer_cpu \ No newline at end of file diff --git a/main/_sources/generated/spdl.pipeline.Pipeline.rst.txt b/main/_sources/generated/spdl.pipeline.Pipeline.rst.txt new file mode 100644 index 00000000..a4007770 --- /dev/null +++ b/main/_sources/generated/spdl.pipeline.Pipeline.rst.txt @@ -0,0 +1,16 @@ +spdl.pipeline.Pipeline +====================== + +.. currentmodule:: spdl.pipeline + +.. autoclass:: Pipeline + :members: + + .. rubric:: Methods + + .. autosummary:: + ~Pipeline.auto_stop + ~Pipeline.get_item + ~Pipeline.get_iterator + ~Pipeline.start + ~Pipeline.stop \ No newline at end of file diff --git a/main/_sources/generated/spdl.pipeline.PipelineBuilder.rst.txt b/main/_sources/generated/spdl.pipeline.PipelineBuilder.rst.txt new file mode 100644 index 00000000..86cd13f2 --- /dev/null +++ b/main/_sources/generated/spdl.pipeline.PipelineBuilder.rst.txt @@ -0,0 +1,17 @@ +spdl.pipeline.PipelineBuilder +============================= + +.. currentmodule:: spdl.pipeline + +.. autoclass:: PipelineBuilder + :members: + + .. rubric:: Methods + + .. autosummary:: + ~PipelineBuilder.add_sink + ~PipelineBuilder.add_source + ~PipelineBuilder.aggregate + ~PipelineBuilder.build + ~PipelineBuilder.disaggregate + ~PipelineBuilder.pipe \ No newline at end of file diff --git a/main/_sources/generated/spdl.pipeline.PipelineFailure.rst.txt b/main/_sources/generated/spdl.pipeline.PipelineFailure.rst.txt new file mode 100644 index 00000000..4fd507a0 --- /dev/null +++ b/main/_sources/generated/spdl.pipeline.PipelineFailure.rst.txt @@ -0,0 +1,6 @@ +spdl.pipeline.PipelineFailure +============================= + +.. currentmodule:: spdl.pipeline + +.. autoexception:: PipelineFailure \ No newline at end of file diff --git a/main/_sources/generated/spdl.pipeline.PipelineHook.rst.txt b/main/_sources/generated/spdl.pipeline.PipelineHook.rst.txt new file mode 100644 index 00000000..163fe6de --- /dev/null +++ b/main/_sources/generated/spdl.pipeline.PipelineHook.rst.txt @@ -0,0 +1,13 @@ +spdl.pipeline.PipelineHook +========================== + +.. currentmodule:: spdl.pipeline + +.. autoclass:: PipelineHook + :members: + + .. rubric:: Methods + + .. autosummary:: + ~PipelineHook.stage_hook + ~PipelineHook.task_hook \ No newline at end of file diff --git a/main/_sources/generated/spdl.pipeline.TaskStatsHook.rst.txt b/main/_sources/generated/spdl.pipeline.TaskStatsHook.rst.txt new file mode 100644 index 00000000..d9bffbe0 --- /dev/null +++ b/main/_sources/generated/spdl.pipeline.TaskStatsHook.rst.txt @@ -0,0 +1,13 @@ +spdl.pipeline.TaskStatsHook +=========================== + +.. currentmodule:: spdl.pipeline + +.. autoclass:: TaskStatsHook + :members: + + .. rubric:: Methods + + .. autosummary:: + ~TaskStatsHook.stage_hook + ~TaskStatsHook.task_hook \ No newline at end of file diff --git a/main/_sources/generated/spdl.pipeline.create_task.rst.txt b/main/_sources/generated/spdl.pipeline.create_task.rst.txt new file mode 100644 index 00000000..699103eb --- /dev/null +++ b/main/_sources/generated/spdl.pipeline.create_task.rst.txt @@ -0,0 +1,6 @@ +spdl.pipeline.create\_task +========================== + +.. currentmodule:: spdl.pipeline + +.. autofunction:: create_task \ No newline at end of file diff --git a/main/_sources/generated/spdl.pipeline.rst.txt b/main/_sources/generated/spdl.pipeline.rst.txt new file mode 100644 index 00000000..992eb2bd --- /dev/null +++ b/main/_sources/generated/spdl.pipeline.rst.txt @@ -0,0 +1,162 @@ +.. + Custom template for our custom_autosummary. + The purpose of using custom_autosummary is list the entries on + the right side bar instead of the left side bar. + This is achieved with the combination of custom directive, template and CSS. + + The `custom_autosummary` directive functions mostly like `autosummary`. We + pass `:toctree:` option to generate a doc page for each entry, but we use + our custom `:hide_from_toctree:` option so as not to attach them in ToC tree. + + This template inserts a section header for each entry, so that they show up + in the right-side bar. The headers are hidden by CSS. + + Because each entry will have its own table and their borders no longer match, + table borders are hidden by CSS and instead we use horizontal line. + +.. raw:: html + +
+ +spdl.pipeline +============= + +.. automodule:: spdl.pipeline + +.. + ############################################################################ + Functions + ############################################################################ + + + +.. rubric:: Functions + + +create\_task +------------ +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.pipeline.create_task + + + + + +.. + ############################################################################ + Attributes + ############################################################################ + + + + + +.. + ############################################################################ + Classes + ############################################################################ + + + +.. rubric:: Classes + + +Pipeline +-------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + :template: _custom_autosummary_class.rst + + ~spdl.pipeline.Pipeline + + +PipelineBuilder +--------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + :template: _custom_autosummary_class.rst + + ~spdl.pipeline.PipelineBuilder + + +PipelineHook +------------ +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + :template: _custom_autosummary_class.rst + + ~spdl.pipeline.PipelineHook + + +TaskStatsHook +------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + :template: _custom_autosummary_class.rst + + ~spdl.pipeline.TaskStatsHook + + + + + +.. + ############################################################################ + Exceptions + ############################################################################ + + + +.. rubric:: Exceptions + + +PipelineFailure +--------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.pipeline.PipelineFailure + + + + + +.. + ############################################################################ + Sub modules + ############################################################################ + + + + + +.. + ############################################################################ + Others + ############################################################################ + + + + + + + + + +.. raw:: html + +
\ No newline at end of file diff --git a/main/_sources/generated/spdl.utils.get_ffmpeg_filters.rst.txt b/main/_sources/generated/spdl.utils.get_ffmpeg_filters.rst.txt new file mode 100644 index 00000000..3482289a --- /dev/null +++ b/main/_sources/generated/spdl.utils.get_ffmpeg_filters.rst.txt @@ -0,0 +1,6 @@ +spdl.utils.get\_ffmpeg\_filters +=============================== + +.. currentmodule:: spdl.utils + +.. autofunction:: get_ffmpeg_filters \ No newline at end of file diff --git a/main/_sources/generated/spdl.utils.get_ffmpeg_log_level.rst.txt b/main/_sources/generated/spdl.utils.get_ffmpeg_log_level.rst.txt new file mode 100644 index 00000000..32ecddb1 --- /dev/null +++ b/main/_sources/generated/spdl.utils.get_ffmpeg_log_level.rst.txt @@ -0,0 +1,6 @@ +spdl.utils.get\_ffmpeg\_log\_level +================================== + +.. currentmodule:: spdl.utils + +.. autofunction:: get_ffmpeg_log_level \ No newline at end of file diff --git a/main/_sources/generated/spdl.utils.is_cuda_available.rst.txt b/main/_sources/generated/spdl.utils.is_cuda_available.rst.txt new file mode 100644 index 00000000..a498462e --- /dev/null +++ b/main/_sources/generated/spdl.utils.is_cuda_available.rst.txt @@ -0,0 +1,6 @@ +spdl.utils.is\_cuda\_available +============================== + +.. currentmodule:: spdl.utils + +.. autofunction:: is_cuda_available \ No newline at end of file diff --git a/main/_sources/generated/spdl.utils.is_nvcodec_available.rst.txt b/main/_sources/generated/spdl.utils.is_nvcodec_available.rst.txt new file mode 100644 index 00000000..58c2e330 --- /dev/null +++ b/main/_sources/generated/spdl.utils.is_nvcodec_available.rst.txt @@ -0,0 +1,6 @@ +spdl.utils.is\_nvcodec\_available +================================= + +.. currentmodule:: spdl.utils + +.. autofunction:: is_nvcodec_available \ No newline at end of file diff --git a/main/_sources/generated/spdl.utils.rst.txt b/main/_sources/generated/spdl.utils.rst.txt new file mode 100644 index 00000000..c8aa99e8 --- /dev/null +++ b/main/_sources/generated/spdl.utils.rst.txt @@ -0,0 +1,183 @@ +.. + Custom template for our custom_autosummary. + The purpose of using custom_autosummary is list the entries on + the right side bar instead of the left side bar. + This is achieved with the combination of custom directive, template and CSS. + + The `custom_autosummary` directive functions mostly like `autosummary`. We + pass `:toctree:` option to generate a doc page for each entry, but we use + our custom `:hide_from_toctree:` option so as not to attach them in ToC tree. + + This template inserts a section header for each entry, so that they show up + in the right-side bar. The headers are hidden by CSS. + + Because each entry will have its own table and their borders no longer match, + table borders are hidden by CSS and instead we use horizontal line. + +.. raw:: html + +
+ +spdl.utils +========== + +.. automodule:: spdl.utils + +.. + ############################################################################ + Functions + ############################################################################ + + + +.. rubric:: Functions + + +get\_ffmpeg\_filters +-------------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.utils.get_ffmpeg_filters + + +get\_ffmpeg\_log\_level +----------------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.utils.get_ffmpeg_log_level + + +is\_cuda\_available +------------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.utils.is_cuda_available + + +is\_nvcodec\_available +---------------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.utils.is_nvcodec_available + + +set\_ffmpeg\_log\_level +----------------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.utils.set_ffmpeg_log_level + + +trace\_counter +-------------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.utils.trace_counter + + +trace\_event +------------ +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.utils.trace_event + + +trace\_gc +--------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.utils.trace_gc + + +tracing +------- +.. autosummary:: + :toctree: + :nosignatures: + :hide_from_toctree: + + ~spdl.utils.tracing + + + + + +.. + ############################################################################ + Attributes + ############################################################################ + + + + + +.. + ############################################################################ + Classes + ############################################################################ + + + + + +.. + ############################################################################ + Exceptions + ############################################################################ + + + + + +.. + ############################################################################ + Sub modules + ############################################################################ + + + + + +.. + ############################################################################ + Others + ############################################################################ + + + + + + + + + + + + +.. raw:: html + +
\ No newline at end of file diff --git a/main/_sources/generated/spdl.utils.set_ffmpeg_log_level.rst.txt b/main/_sources/generated/spdl.utils.set_ffmpeg_log_level.rst.txt new file mode 100644 index 00000000..d1b282d5 --- /dev/null +++ b/main/_sources/generated/spdl.utils.set_ffmpeg_log_level.rst.txt @@ -0,0 +1,6 @@ +spdl.utils.set\_ffmpeg\_log\_level +================================== + +.. currentmodule:: spdl.utils + +.. autofunction:: set_ffmpeg_log_level \ No newline at end of file diff --git a/main/_sources/generated/spdl.utils.trace_counter.rst.txt b/main/_sources/generated/spdl.utils.trace_counter.rst.txt new file mode 100644 index 00000000..e8a481ff --- /dev/null +++ b/main/_sources/generated/spdl.utils.trace_counter.rst.txt @@ -0,0 +1,6 @@ +spdl.utils.trace\_counter +========================= + +.. currentmodule:: spdl.utils + +.. autofunction:: trace_counter \ No newline at end of file diff --git a/main/_sources/generated/spdl.utils.trace_event.rst.txt b/main/_sources/generated/spdl.utils.trace_event.rst.txt new file mode 100644 index 00000000..41e9d851 --- /dev/null +++ b/main/_sources/generated/spdl.utils.trace_event.rst.txt @@ -0,0 +1,6 @@ +spdl.utils.trace\_event +======================= + +.. currentmodule:: spdl.utils + +.. autofunction:: trace_event \ No newline at end of file diff --git a/main/_sources/generated/spdl.utils.trace_gc.rst.txt b/main/_sources/generated/spdl.utils.trace_gc.rst.txt new file mode 100644 index 00000000..d395789d --- /dev/null +++ b/main/_sources/generated/spdl.utils.trace_gc.rst.txt @@ -0,0 +1,6 @@ +spdl.utils.trace\_gc +==================== + +.. currentmodule:: spdl.utils + +.. autofunction:: trace_gc \ No newline at end of file diff --git a/main/_sources/generated/spdl.utils.tracing.rst.txt b/main/_sources/generated/spdl.utils.tracing.rst.txt new file mode 100644 index 00000000..dd7a253d --- /dev/null +++ b/main/_sources/generated/spdl.utils.tracing.rst.txt @@ -0,0 +1,6 @@ +spdl.utils.tracing +================== + +.. currentmodule:: spdl.utils + +.. autofunction:: tracing \ No newline at end of file diff --git a/main/_sources/generated/video_dataloading.rst.txt b/main/_sources/generated/video_dataloading.rst.txt new file mode 100644 index 00000000..ea4e8e4b --- /dev/null +++ b/main/_sources/generated/video_dataloading.rst.txt @@ -0,0 +1,125 @@ +.. + Custom template for our custom_autosummary. + The purpose of using custom_autosummary is list the entries on + the right side bar instead of the left side bar. + This is achieved with the combination of custom directive, template and CSS. + + The `custom_autosummary` directive functions mostly like `autosummary`. We + pass `:toctree:` option to generate a doc page for each entry, but we use + our custom `:hide_from_toctree:` option so as not to attach them in ToC tree. + + This template inserts a section header for each entry, so that they show up + in the right-side bar. The headers are hidden by CSS. + + Because each entry will have its own table and their borders no longer match, + table borders are hidden by CSS and instead we use horizontal line. + +.. raw:: html + +
+ +video\_dataloading +================== + +.. automodule:: video_dataloading + +.. + ############################################################################ + Source + ############################################################################ + +Source +------ + +.. rubric:: Source + +.. raw:: html + +
+ Click here to see the source. + +.. literalinclude:: ../../../examples/video_dataloading.py + :linenos: + +.. raw:: html + +
+ +.. + ############################################################################ + Functions + ############################################################################ + + + + +Functions +--------- +.. rubric:: Functions + + + +.. autofunction:: video_dataloading.entrypoint + + + +.. autofunction:: video_dataloading.worker_entrypoint + + + +.. autofunction:: video_dataloading.benchmark + + + +.. autofunction:: video_dataloading.source + + + +.. autofunction:: video_dataloading.decode_video + + + +.. autofunction:: video_dataloading.decode_video_nvdec + + + +.. autofunction:: video_dataloading.get_pipeline + + + + + +.. + ############################################################################ + Attributes + ############################################################################ + + + + + +.. + ############################################################################ + Classes + ############################################################################ + + + + +Classes +------- + +.. rubric:: Classes + + + +.. autoclass:: video_dataloading.PerfResult + :members: + + + + + +.. raw:: html + +
\ No newline at end of file diff --git a/main/_sources/getting_started/concurrency.rst.txt b/main/_sources/getting_started/concurrency.rst.txt new file mode 100644 index 00000000..34780a9e --- /dev/null +++ b/main/_sources/getting_started/concurrency.rst.txt @@ -0,0 +1,130 @@ +Concurrency +=========== + +.. py:currentmodule:: spdl.dataloader + +The pipelines we looked at so far process data sequentially. +Now let's introduce concurrency to the pipeline so that it finishes jobs faster. + +There are two parameters that affects the pipeline performance. + +1. Stage concurrency +2. Thread pool size + +Stage Concurrency +----------------- + +The stage concurrency can be configured with ``concurrency`` argument in the :py:meth:`PipelineBuilder.pipe` method. + +This argument determines at most how many operations of the stage the event loop would schedule at a given time. + +.. important:: + + Please note that **scheduling multiple tasks concurrently does not necessarily mean + all of them are executed concurrently.** The execution of scheduled tasks is subject to + the availability of resources required for the execution. + + See the :ref:`Thread Pool Size` for the detail. + +For example, let's say we have a pipeline that downloads data and pre-process them, and we implement it like the following. + +.. code-block:: + + pipeline = ( + PipelineBuilder() + .add_source(url_generator) + .pipe(download, concurrency=4) + .pipe(preprocess, concurrency=2) + .add_sink(3) + .build() + ) + +The ``download`` stage will schedule 4 tasks, and wait for any of the tasks to complete. When a task is completed, the stage will schedule another task with new input data. + +Similarly, ``preprocess`` stage will schedule 2 tasks and when a task is completed, it will schedule another task. + +The following diagram illustrates this. + +.. mermaid:: + + flowchart TD + A[url_generator] + subgraph B[download] + b1[download 1] + b2[download 2] + b3[download 3] + b4[download 4] + end + subgraph C[preprocess] + c1[preprocess 1] + c2[preprocess 2] + end + subgraph D[sink] + d1[result 1] + d2[result 2] + d3[result 3] + end + A --> B + B --> C + C --> D + +.. note:: + + When the stage concurrency is bigger than 1, the results of the operations are, + by default, put to the output queue in the order of task completion. + Therefore the order of the processed items can change. + + This behavior can be changed by specifying ``output_order="input"`` in + :py:meth:`PipelineBuilder.pipe` method, so that the order of the output is same + as the input. + +Thread Pool Size +---------------- + +Async event loop uses :py:class:`~concurrent.futures.ThreadPoolExecutor` to execute +synchronous functions as async functions. + +When executing functions that are synchronous, the event loop can offload +its execution to the thread pool and wait for its completion. +This is what :py:meth:`~asyncio.loop.run_in_executor` does and it is a primal +way to execute synchronous functions in async event loop. + +The majority of operations performed in ML data loading are synchronous, so we need to +use this mechanism to run them in asynchronous context. +Or in an alternative view, the event loop acts as a surrogate who manages the thread pool +and does all the scheduling and inter/intra op parallelization. + +The size of thread pool can be specified with ``num_threads`` argument in the +:py:meth:`PipelineBuilder.build` method. + +The size of the thread pool serves as the capacity that pipeline can execute synchronous +functions concurrently. Therefore, if concurrently scheduling multiple tasks of +synchronous operations, the size of thread pool must be bigger than the number of +the concurrency. + +The following code snippet illustrates this. + +.. code-block:: + + def preprocess(data): + """A hypothetical preprocessing function. (not async)""" + ... + + pipeline = ( + PipelineBuilder() + .add_source(source) + .pipe(preprocess, concurrency=3) + # Run at most 3 `preprocess` functions concurrently. + .add_sink(3) + .build(num_threads=3) + # Use 3 threads in the thread pool to accommodate 3 async_preprocess + ) + +.. note:: + + Note that there are cases where the stage concurrency and + thread pool size are irrelevant. + + For example, some libraries implement thread-based parallelism in + low-level language like C++. When using such libraries the concurrency + is constraint by the resource managed by the library. diff --git a/main/_sources/getting_started/index.rst.txt b/main/_sources/getting_started/index.rst.txt new file mode 100644 index 00000000..ddc3bdba --- /dev/null +++ b/main/_sources/getting_started/index.rst.txt @@ -0,0 +1,8 @@ +Getting Started +=============== + +.. toctree:: + + intro + stages + concurrency diff --git a/main/_sources/getting_started/intro.rst.txt b/main/_sources/getting_started/intro.rst.txt new file mode 100644 index 00000000..381fd0ca --- /dev/null +++ b/main/_sources/getting_started/intro.rst.txt @@ -0,0 +1,63 @@ +Building and Running Pipeline +============================= + +.. py:currentmodule:: spdl.dataloader + +First, let's look at how easy it is to build the pipeline in SPDL. + +The following snippet demonstrates how one can construct a +:py:class:`Pipeline` object using a :py:class:`PipelineBuilder` object. + +.. code-block:: + + >>> from spdl.dataloader import PipelineBuilder + >>> + >>> pipeline = ( + ... PipelineBuilder() + ... .add_source(range(12)) + ... .pipe(lambda x: 2 * x) + ... .pipe(lambda x: x + 1) + ... .aggregate(3) + ... .add_sink(3) + ... .build() + ... ) + + +The resulting :py:class:`Pipeline` object contains all the logic to +perform the operations in an async event loop in the background thread. + +To run the pipeline, call :py:meth:`Pipeline.start`. +Once the pipeline starts executing, you can iterate on the pipeline. +Finally call :py:meth:`Pipeline.stop` to stop the background thread. + +.. code-block:: + + >>> pipeline.start() + >>> + >>> for item in pipeline: + ... print(item) + [1, 3, 5] + [7, 9, 11] + [13, 15, 17] + [19, 21, 23] + >>> pipeline.stop() + +It is important to call :py:meth:`Pipeline.stop`. +Forgetting to do so will leave the background thread running, +leading to the situation where Python interpreter gets stuck at exit. + +In practice, there is always a chance that data processing raises an error, +so there is a context manager :py:meth:`Pipeline.auto_stop` to make sure that +pipeline is stopped. + +.. code-block:: + + >>> with pipeline.auto_stop(): + ... for item in pipeline: + ... print(item) + +.. note:: + + Once :py:meth:`Pipeline.stop` method is called, the ``Pipeline`` object is unusable. + To pause and resume the execution, simply keep the reference around until the + next use. diff --git a/main/_sources/getting_started/stages.rst.txt b/main/_sources/getting_started/stages.rst.txt new file mode 100644 index 00000000..433eea0c --- /dev/null +++ b/main/_sources/getting_started/stages.rst.txt @@ -0,0 +1,136 @@ +Pipeline Stages +=============== + +.. py:currentmodule:: spdl.dataloader + +:py:class:`Pipeline` is composed of multiple stages. +There are mainly three kind of stages. + +- Source +- Processing +- Sink (buffer) + +Source +------ + +Source specifies where the data are located. This is typically file paths or URLs. +The source can be set with :py:meth:`PipelineBuilder.add_source` +method. The only requirement for the source object is that it must implement +:py:class:`~collections.abc.Iterable` or :py:class:`~collections.abc.AsyncIterable` +interface. + +For example + +- Load a list of paths from a file. + +.. code-block:: + + def load_path_from_file(input_path: str): + with open(input_path, "r") as f: + for line in f: + if path := line.strip(): + yield path + +- Files in directories + +.. code-block:: + + def find_files(path: Path, ext: str): + yield from path.glob(f'**/*{ext}') + +- Asynchronously list files in remote storage + +.. code-block:: + + # Using some imaginary client + async def list_bucket(bucket: str) -> AsyncIterator[str]: + client = client.connect() + async for route in client.list_bucket(bucket): + yield route + +.. note:: + + Since the source object is executed in async event loop, if the source is + ``Iterable`` (synchronous iterator), the source object must be lightweight + and refrain from performing blocking operation. + + Running a blocking operation in async event loop can, in turn, prevent the + loop from scheduling callbacks, prevent tasks from being canceled, and + prevent the background thread from joining. + +Processing +---------- + +Pre-processing is where a variety of operations are applied to the items passed +from the previous stages. + +You can define processing stage by passing an operator function (callable) to +:py:meth:`~PipelineBuilder.pipe`. (Also there is :py:meth:`~PipelineBuilder.aggregate` +method, which can be used to stack multiple items.) + +The operator can be either async function or synchronous function. Either way, +the operator must take exactly one argument†, which is an output from the earlier +stage. + +.. note:: + + † If you need to pass multiple objects between stages, use tuple or define a + protocol using :py:class:`~dataclasses.dataclass`. + +The following diagram illustrates a pipeline that fetch images from remote +locations, batch decode and send data to GPU. + +.. mermaid:: + + flowchart TD + A[Source] --> B(Acquire data) + B --> C(Batch) + C --> D(Decode & Pre-process &Transfer to GPU & Convert to Tensor) + D --> E[Sink] + +An implementation could look like this. +It uses :py:func:`spdl.io.async_load_image_batch`, which can decode and resize images +and send the decoded frames to GPU in asynchronously. + +.. code-block:: + + >>> import spdl.io + >>> from spdl.dataloader import PipelineBuilder + >>> + >>> def source() -> Iterator[str]: + ... """Returns the list of URLs to fetch data from""" + ... ... + >>> + >>> async def download(url: str) -> bytes: + ... """Download data from the given URL""" + ... ... + >>> + >>> async def process(data: list[bytes]) -> Tensor: + ... """Given raw image data, decode, resize, batch and transfer data to GPU""" + ... buffer = spdl.io.async_load_image_batch( + ... data, + ... width=224, + ... height=224, + ... cuda_config=spdl.io.cuda_config(device_index=0), + ... ) + ... return spdl.io.to_torch(buffer) + >>> + >>> pipeline = ( + ... PipelineBuiler() + ... .add_source(source()) + ... .pipe(download) + ... .aggregate(32) + ... .pipe(process) + ... .add_sink(4) + ... .build() + ... ) + >>> + >>> + + +Sink +---- + +Sink is a buffer where the results of the pipeline is accumulated. +A sink can be attached to pipeline with :py:meth:`PipelineBuilder.add_sink` method. +You can specify how many items can be buffered in the sink. diff --git a/main/_sources/index.rst.txt b/main/_sources/index.rst.txt new file mode 100644 index 00000000..40edee05 --- /dev/null +++ b/main/_sources/index.rst.txt @@ -0,0 +1,43 @@ +.. SPDL documentation master file, created by + sphinx-quickstart on Fri Jun 14 19:39:36 2024. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +SPDL +==== + +SPDL (Scalable and Performant Data Loading) + +.. toctree:: + :hidden: + + Home + +.. toctree:: + :maxdepth: 2 + :caption: Contents + + overview + installation + getting_started/index + performance_analysis/index + migration/index + best_practice + examples + fb/examples + faq + +.. toctree:: + :maxdepth: 2 + :caption: API References + + API Reference + API Reference (Meta) + API Reference (C++) + API Index + +.. toctree:: + :maxdepth: 2 + :caption: Development Notes + + notes/index diff --git a/main/_sources/installation.rst.txt b/main/_sources/installation.rst.txt new file mode 100644 index 00000000..77360563 --- /dev/null +++ b/main/_sources/installation.rst.txt @@ -0,0 +1,147 @@ +Installation +============ + +From source +----------- + +The following command will build and install `spdl` Python package. + +.. note:: + + Make sure to use `-v` to see the log from the actual build process. + +**Regular installation** + +.. code-block:: + + pip install . -v + +**Development installation** + +.. code-block:: + + pip install -e . -v + +The build process first downloads/builds/installs some third-party +dependencies, then it builds SPDL and its binding code. + +Build can be customized through the environment variables; + +- ``SPDL_USE_CUDA=1``: Enable CUDA integration, such as background data transfer. +- ``SPDL_USE_NVCODEC=1``: Enable + `NVIDIA VIDEO CODEC `_ + integration, i.e. GPU video decoder and direct CUDA memory placement +- ``SPDL_USE_TRACING=1``: Enable `Perfetto `_ + integration for performance profiling. +- ``SPDL_USE_FFMPEG_VERSION``: Specify the version of FFmpeg you want to use + to reduce the build time. By default, SPDL compiles against FFmpeg 4, 5, 6 and 7, + and pick available one at run time. +- ``SPDL_RELASE_GIL=0``: I/O module does not release GIL. This is intended to be used for + experimenting with free-threaded Python (3.13+). + +See `setup.py `_ for the up-to-date available options. + +Trouble Shooting +---------------- + +If you hit an error like the following, ``--no-build-isolation`` can help. + +.. code-block:: text + + Installing collected packages: ninja, wheel, setuptools, cmake + Creating /tmp/pip-build-env-1ac3bsc_/overlay/bin + changing mode of /tmp/pip-build-env-1ac3bsc_/overlay/bin/ninja to 775 + changing mode of /tmp/pip-build-env-1ac3bsc_/overlay/bin/wheel to 775 + changing mode of /tmp/pip-build-env-1ac3bsc_/overlay/bin/cmake to 775 + changing mode of /tmp/pip-build-env-1ac3bsc_/overlay/bin/cpack to 775 + changing mode of /tmp/pip-build-env-1ac3bsc_/overlay/bin/ctest to 775 + Successfully installed cmake-3.30.5 ninja-1.11.1.1 setuptools-75.2.0 wheel-0.44.0 + + ... + + CMake Error at CMakeLists.txt:3 (project): + Running + + '/tmp/pip-build-env-xic7ygls/overlay/bin/ninja' '--version' + + failed with: + + no such file or directory + +This happens because, somehow ``cmake`` command is not pointing the ``ninja`` installed +by ``pip``. + +One workaround is to use ``--no-build-isolation`` option. +e.g. ``TMPDIR="${PWD}/build" pip install . -v --no-build-isolation`` + + +Requirements +------------ + +* Supported OS: Linux, macOS + +* Build requirements + - C++20 compiler (Tested on GCC 11 and Clang 15) + - CMake, Ninja + - (Optional) CUDA Toolkit + +* Runtime Requirements and dependencies + - Python 3.10+ + - NumPy + - (Optional) PyTorch + - (Optional) Numba + - (Optional) CUDA runtime + +Dependencies +------------ + +The libspdl uses the following third party libraries, which are fetched and built automatically during the build process. + +* `{fmt} `_ (`MIT `_) +* `gflags `_ (`BSD-3 `_) +* `glog `_ (`BSD-3 `_) +* `libzip `_ (`BSD-3 `_) +* `nanobind `_ (`BSD-3 `_) and its dependency `robin-map `_ (`MIT `_) +* `FFmpeg `_ (`LGPL `_ †) + +.. note:: + + **†** FFmpeg is a dual-licensed software. One can choose LGPL or GPL. + + When building ``libspdl``, pre-built LGPL version of FFmpeg library files are + downloaded and linked against ``libspdl``. + These FFmpeg library files are compiled in a way that no GPL component is used + and runtime search path is not hard-coded. + Therefore, the resulting ``libspdl`` is not obliged to be GPL, and + users can (need to) provide own FFmpeg library files. + + Users are free to dynamically link GPL or non-distributable version of + FFmpeg libraries. However, please note that linking a non-LGPL binary might + change the condition for redistribution of your application. + + +Optional Dependencies +--------------------- + +* `Perfetto `_ (`Apache 2.0 `_) +* `CUDA Toolkit `_ †† (`CUDA Toolkit EULA `_) and the following family of libraries covered by the same EULA + * `nvJPEG `_ + * `NPP `_ +* The header files of `Video Codec SDK `_ †† + + The header files of video codec SDK (``nvcuvid.h`` and ``cuviddec.h``), + which are distributed under MIT license, is used when compiling SPDL with + hardware video decoder enabled. + +.. note:: + + **††** This software contains source code provided by NVIDIA Corporation. + +Building with Free-Threaded Python +---------------------------------- + +To build SPDL with Free-Threaded Python, the following manual changes are required. +We intend to incorporate these changes in build process, once Python 3.13 and +FT-aware nanobind is released. + +1. Add ``FREE_THREADED`` to ``nanobind_add_module``. Please refer to `the doc `_. diff --git a/main/_sources/migration/index.rst.txt b/main/_sources/migration/index.rst.txt new file mode 100644 index 00000000..bc59a56d --- /dev/null +++ b/main/_sources/migration/index.rst.txt @@ -0,0 +1,8 @@ +Usage Guide +=========== + +.. toctree:: + + why + paradigm_shift + pytorch diff --git a/main/_sources/migration/paradigm_shift.rst.txt b/main/_sources/migration/paradigm_shift.rst.txt new file mode 100644 index 00000000..0d6f0bfe --- /dev/null +++ b/main/_sources/migration/paradigm_shift.rst.txt @@ -0,0 +1,55 @@ +Paradigm Shift +============== + +Concurrency Structure +--------------------- + +When using SPDL, it is important to understand the difference in how SPDL structure +the concurrency, compared against common process-based data loaders. + +In process-based data loading, each process runs the entire pipeline. +The pipeline is implemented as DataSet. + +.. mermaid:: + + flowchart + subgraph P1[Process 3] + direction TB + S10[src] --> S11[Stage 1] --> S12[Stage 2] + end + subgraph P2[Process 2] + direction TB + S20[src] --> S21[Stage 1] --> S22[Stage 2] + end + subgraph P3[Process 1] + direction TB + S30[src] --> S31[Stage 1] --> S32[Stage 2] + end + +Whereas SPDL parallelizes the the pipeline stage-by-stage, using different concurrency. +This approach is better fit for achieving higher throughput. + +.. mermaid:: + + flowchart + subgraph P1[Stage 1] + direction TB + T11[Task 1] + T12[Task 2] + T13[Task 3] + end + subgraph P2[Stage 2] + direction TB + T21[Task 1] + T22[Task 2] + end + subgraph P3[Stage 3] + direction TB + T31[Task 1] + end + src --> P1 --> P2 --> P3 + +It is worth noting that in this setup, there is no equivalent of Dataset class. + +This paradigm shift makes it difficult to achieve mechanical update (such as +one-line-change or swap-the-class type of update) to SPDL. diff --git a/main/_sources/migration/pytorch.rst.txt b/main/_sources/migration/pytorch.rst.txt new file mode 100644 index 00000000..22395865 --- /dev/null +++ b/main/_sources/migration/pytorch.rst.txt @@ -0,0 +1,353 @@ +Practical Example +================= + +If you are using :py:class:`torch.utils.data.DataLoader` and decided to +use to SPDL, there are couple of conceptual differences +you want to be aware of. + +There are three distinguished components in PyTorch's DataLoader. + +1. Sampler - Generates keys. +2. Dataset - Map an input key to a Tensor. +3. Collate function - Merge multiple Tensors into one batch Tensor. + +One notable thing about this composition is that dataset contains the logic +to convert the data source to Tensor, and it directly maps keys to Tensors. +It prohibits the access to the data source or data itself, and it does not +distinguish the steps for data acquisition, decoding and pre-processing nor +expose them. + +So as to achieve high throughput, it is important to separate the operations of +different natures and configure them, but there is no native support for +that in :py:class:`torch.utils.data.Dataset`. + +Now let's look into a task of image loading for classification task, using +TorchVision's :py:class:`torchvision.datasets.ImageNet`. + +Here is the base dataset instance we are going to use. + +.. code-block:: + + from torchvision.datasets import ImageNet + from torchvision.transforms import Compose, PILToTensor, Resize + + dataset = ImageNet( + "dataset_directory", + transform=Compose([Resize((224, 224)), PILToTensor()]), + ) + +The images are decoded in +:py:class:`torchvision.datasets.ImageNet.__getitem__` method, then +resized and converted to Tensor through :py:class:`~torchvision.transforms.Resize` +and :py:class:`~torchvision.transforms.PILToTensor` transforms. + +Decoding images in threads +-------------------------- + +When using SPDL before free-threaded (a.k.a no-GIL) Python becomes available +and stable, we need to check whether the dataset instance can be used +in threaded environment in a performant manner. + +- Does the internal loading logic release GIL? +- Is the dataset instance thread-safe? + +If the answer to both questions is yes, then we can start by reusing +the dataset logic as-is in :py:class:`spdl.dataloader.Pipeline`. + +TorchVision's dataset implementations meet these requirements. +By default, TorchVision uses Pillow to load images, and +Pillow releases GIL. The dataset is thread-safe. + +The following code snippets show how one can use PyTorch +:py:class:`~torch.utils.data.DataLoader` to load images without batching. + +.. code-block:: + + import torch + + dataloader = torch.utils.data.DataLoader( + dataset, + batch_size=None, + num_workers=num_workers, + ) + + for batch, classes in dataloader: + ... + + +The following is an equivalent implementation using SPDL +:py:class:`~spdl.dataloader.Pipeline`. + +.. code-block:: + + from spdl.dataloader import PipelineBuilder + + pipeline = ( + PipelineBuilder() + .add_source(range(len(dataset))) + .pipe( + dataset.__getitem__, + concurrency=num_workers, + output_order="input", + ) + .add_sink(prefetch_factor) + .build(num_threads=num_workers) + ) + + with pipeline.auto_stop(): + for batch, classes in dataloader: + ... + +Running them with different concurrency, we get the following +performance. + +.. include:: ../plots/migration_1.txt + +SPDL Pipeline is faster than PyTorch DataLoader at all stages, +which suggests that the operations executed here +(Image decoding, resizing and Tensor conversions) all release GIL. + +Many PyTorch operators (and also NumPy operators) release GIL, +so there is a good chance that they work fine in thread-based pipeline. + +Batching images +--------------- + +Now we know that the basic loading operation works, we add batching. +In PyTorch DataLoader, providing `batch_size` enables batching +internally. + +By default, it uses :py:func:`torch.utils.data.default_collate` +function. + +.. code-block:: + + dataloader = torch.utils.data.DataLoader( + dataset, + batch_size=32, + # ^^^^^^^^^^^^ + num_workers=num_workers, + ) + + for batch, classes in dataloader: + ... + +In SPDL, we use :py:meth:`~spdl.dataloader.PipelineBuilder.aggregate` +method to buffer the results coming from upstream into a list. + +The the buffered items need to be passed to collate function explicitly. + +.. code-block:: + + pipeline = ( + PipelineBuilder() + .add_source(range(len(dataset))) + .pipe( + dataset.__getitem__, + concurrency=num_workers, + output_order="input", + ) + .aggregate(32) + # ^^^^^^^^^^^^ + .pipe(torch.utils.data.default_collate) + # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + .add_sink(prefetch_factor) + .build(num_threads=num_workers) + ) + +Running this, we get the following result. + +.. include:: ../plots/migration_2.txt + +The batching gives huge boost to PyTorch DataLoader pipeline, while +SPDL becomes slightly slower than before. +Now, PyTorch DataLoader is faster than SPDL Pipeline. + +This means that, simply running the existing data loading pipeline, which +is designed for multi-processing, does not improve the performance. + +This might change with free-threaded, but that's the current state, and +also the reason why SPDL cannot provide a simple drop-in replacement of +PyTorch DataLoader class. + +To understand how to workaround this, let's see how both pipelines scale. + +Understanding the Performance Trend +----------------------------------- + +We run the same pipeline while changing the batch size from 32 to 256 and see +how they scale. + +.. include:: ../plots/migration_3.txt + +.. include:: ../plots/migration_4.txt + +We can make the following observations. + +1. PyTorch DataLoader does not scale well beyond 8-16 workers, + while SPDL Pipeline can achieve similar or higher throughput. +2. As the batch size increases, PyTorch DataLoader's peak throughput drops, + while SPDL Pipeline sustain similar or even higher throughput. +3. The way SPDL Pipeline's performance scale is consistent for different batch sizes. + +Why does the performance of PyTorch DataLoader drops as the batch size increase? +And why it's not the case for SPDL Pipeline? + +Since they use the same operations, we can deduce that the difference is coming from +process and thread. +One of the major difference between process-based and thread-based data preparation +is the treatment of the batch after its creation. + +The following figure shows in detail how images are prepared when using PyTorch +DataLoader. + +.. include:: ../plots/multi_thread_preprocessing_chart_torch.txt + +The batch created in a background process is serialized into byte string and written to +the memory space shared between the main process and the background process. +The main process then deserialize the byte string and re-create the batch. + +This means that the batch tensor is at least copied twice after its creation. + +So as the size of the batch tensor grows, the main process needs to allocate and copy more +memory to fetch the batch. + +In SPDL Pipeline, this is not the case because it uses threads to execute works concurrently. +Threads, unlike processes, share the memory space, so the batch tensor created by the background +thread can be directly used by the main thread. There is no need to copy it. + +Switching to SPDL I/O +--------------------- + +In addition to the redundant memory copy originated from inter-process communication, there +are few more memory-related inefficiency in the pipelines. + +The image data coming out of :py:class:`~torchvision.datasets.ImageNet` is Tensor, which is +contiguous memory format. In media processing, the data are more often represented as +non-contiguous memories regions (like separate image planes), +and usually they are not in the size. +For example, YUV420 format, which is one of the most commonly used format uses 12 bits per +pixel to store data, while RGB tensors uses 24 bits per pixel of contiguous memory. + +Loading JPEG files using Pillow converts the data to RGB. +This RGB data is then resized to the target resolution, and converted to a Tensor representing +a single image. Finally, image tensors are copied into batch Tensor. + +This process adds multiple of redundant memory allocations and copying. + +Let's do a back-of-the-envelope calculation to see how wasteful this can be. +Suppose we want to create a batch of 32 images at 224x224 and all the source images are +720x480 YUV420 format. + +One decoded image kept at YUV420 format occupies 720x480x12 = 4147200 bits ~= 0.52 MB. +When this images is converted to RGB, then it occupies twice the size of YUV420, 1.04 MB. +So converting images to RGB after loading consumes extra 32x0.52 = 16 MB of memory. + +Next, once the image is resized to 224x224 RGB format, TorchVision/Pillow convert the data +to Tensors of single images. That is, 32 of contiguous 224x224x3 bytes ~= 4.8 MB is +allocated, copied but discarded when batch tensor is created. + +Therefore, when using Pillow and TorchVision, creating a batch of 32 images at 224x224 +(which is 4.8 MB) allocates, copies and discards redundant memory of about 20MB. + +When this data is transferred from sub-process to the main process, 2x4.8 MB extra copies +are created. + +In SPDL, we implemented the I/O module, which avoids these redundant memory allocations and +copying, and converts the data to contiguous format only when batching the resulted images. + +The following figure illustrates the SPDL pipeline with this SPDL I/O module at the same +level of abstraction as the previous PyTorch DataLoader figure. + +.. include:: ../plots/multi_thread_preprocessing_chart_spdl.txt + +The image processing part has fewer steps than PyTorch DataLoader equivalent. + +Let's swap the image decoding part and see how it helps. + +We change the image decoding part (which was happening inside of +:py:class:`~torchvision.datasets.ImageNet` class) as follow. + +First, we implement the function that decodes an image, but does not convert it to Tensor yet. +The result of :py:func:`spdl.io.decode_packets` is :py:class:`~spdl.io.ImageFrames`, which holds +the frame data decoded by FFmpeg as-is. + +.. code-block:: + + filter_desc = spdl.io.get_video_filter_desc( + scale_width=224, + scale_height=224, + ) + + def decode_image(path: str) -> ImageFrames: + packets = spdl.io.demux_image(path) + return spdl.io.decode_packets(packets, filter_desc=filter_desc) + +Then we swap the image decoding function. + +.. code-block:: + + dataset = ImageNet( + "dataset_directory", + loader = decode_image, + # ^^^^^^^^^^^^^^^^^^^ + ) + +Then we implement a batching function, which is somewhat equivalent to collate function, but +its inputs are not Tensor. +The :py:func:`spdl.io.convert_frames` function receives multiple Frame objects and create one +contiguous memory and copies the data from the Frames. +The result is a :py:class:`spdl.io.CPUBuffer` instance, which implements +`NumPy Array Interface `_, so it +can be converted to PyTorch Tensor without copying data. +:py:func:`spdl.io.to_torch` function performs this operation. + +.. code-block:: + + def convert(items): + frames, clsses = list(zip(*items)) + buffer = spdl.io.convert_frames(frames) + tensor = spdl.io.to_torch(buffer).permute(0, 3, 1, 2) + return tensor, clsses + +Then we put them together to build the Pipeline. + +.. code-block:: + + pipeline = ( + PipelineBuilder() + .add_source(range(len(dataset))) + .pipe( + dataset.__getitem__, + concurrency=num_workers, + output_order="input", + ) + .aggregate(batch_size) + .pipe(convert) + .add_sink(prefetch_factor) + .build(num_threads=num_workers) + ) + +Running the pipeline with different number of threads, we get the following result. + +.. include:: ../plots/migration_5.txt + +The new pipeline is faster than PyTorch DataLoader at all the level of concurrency +and the size of the batch tensor. + +Summary +------- + +We looked at how one can replace PyTorch DataLoader with SPDL Pipeline while +improving the performance of data loading. + +The initial step can be mechanically applied, but to ensure that the resulting +pipeline is more performant, it is necessary to benchmark and adjust parts of the +pipeline. + +We recommend to use :py:mod:`spdl.io` module for processing media data. It is +designed for scaling throughput and has small memory footprint. + +For more complete performance analysis on the SPDL-based pipeline, please refer +to :py:mod:`multi_thread_preprocessing`. +This example measures the pipeline with more processing and GPU data transfer. diff --git a/main/_sources/migration/why.rst.txt b/main/_sources/migration/why.rst.txt new file mode 100644 index 00000000..e75b2195 --- /dev/null +++ b/main/_sources/migration/why.rst.txt @@ -0,0 +1,63 @@ +Why try SPDL? +============= + +When trying SPDL, you should ask why you want to do that, +and what's the benefit and what's the drawback? + +Here are the pros and cons of SPDL. + +Pros +---- + +1. *Performance* + When switching to SPDL, it is not uncommon to see x3 throughput in data loading. + The improvement is not directly reflected to model training performance, + but considering how ubiquitous the data loading bottleneck is, + there is a good chance using SPDL increases the model training performance. +2. *Efficiency* + Switching to SPDL essentially means to switching from sub-process-based parallelism to + thread-based parallelism. + Thread-based parallelism uses smaller compute resource to achieve the same throughput + as sub process-based parallelism. + This leaves spare capacity for increased data loading demand in the future. +3. *Tunability* + The :py:class:`spdl.dataloader.Pipeline` allows to configure the concurrency stage by stage. + This makes the pipeline flexible to fit different environments that the pipeline is running. + You can adjust them based on the network bandwidth and CPU capacity independently. +4. *Flexibility* + The :py:class:`spdl.dataloader.Pipeline` executes the functions you provide. SPDL + does not put any restriction on what data can go through the pipeline. Stages can + aggregate/disaggregate data along the way. +5. *Debuggability* + As we have seen in :ref:`Performance Analysis` section, SPDL's + pipeline abstraction gives insights of stage-wise runtime performance, which makes it + easier to understand how the data loading is performing and how to optimize the pipeline. + +Cons +---- + +1. *Onboarding Cost* + Although we are working to make the onboarding easier, since SPDL involves paradigm shift + (from sub-process-based parallelism to thread-based parallelism, and from object-oriented + composition to functional composition), it is inevitable to require some changes on the + model training code. + +2. *Requires functions that release GIL* + Until free-threaded (a.k.a no-GIL) Python becomes available, to achieve high throughput + with :py:class:`spdl.dataloader.Pipeline`, one must use functions that are thread-safe + and release GIL. + + Since SPDL comes with multimedia submodule which supports audio/video/image, and + `OpenAI's tiktoken `_ and + `HuggingFace's Tokenizers `_ † release GIL, + we believe that the major modalities from popular ML models are covered. + + † The tokenizers is not thread-safe so it requires + `a workaround `_. + (note: You can use `thread local storage `_.) + +3. *New library* + SPDL is a new attempt in data loading. Although the development team is making every + efforts to make sure that the code works in intended way and easy to use, unseen + issues would arise. We make our best efforts to resolve them, but initially some + instability is expected. diff --git a/main/_sources/notes/index.rst.txt b/main/_sources/notes/index.rst.txt new file mode 100644 index 00000000..dbb79f55 --- /dev/null +++ b/main/_sources/notes/index.rst.txt @@ -0,0 +1,6 @@ +Development Notes +================= + +.. toctree:: + + pipeline_impl diff --git a/main/_sources/notes/pipeline_impl.rst.txt b/main/_sources/notes/pipeline_impl.rst.txt new file mode 100644 index 00000000..3b8effdc --- /dev/null +++ b/main/_sources/notes/pipeline_impl.rst.txt @@ -0,0 +1,134 @@ +Implementation detail of Pipeline +================================= + +.. py:currentmodule:: spdl.dataloader + +Simply put, the data processing pipeline is an async functions executed in a background thread, and the foreground fetches the processed data from the sink. + +When implementing foreground/background components, it turned out that a subtle design choice in one part constraints the design choices of other parts of the system, and there are multiple constraints that must be met at the same time. + +This note is a memorandum of the design trade offs and their consequences encountered during the implementation of the :py:class:`Pipeline`. + +Async IO +-------- + +The Pipeline is composed of async functions. This is to make it easy to integrate the network utilities which are often async functions. Also executing the data processing functions in async context makes it easy to realize inter-op and intra-op parallelism. + +Queue vs Async Queue as Buffer +------------------------------ + +The sink of the Pipeline is where the processed data are buffered. Pipeline runs in the background thread, so that the data are written to the sink in the background thread. They are fetched by the foreground thread. Therefore, the access to the sink must be thread-safe. In addition, pipeline is executed in async event loop, so it is ideal that the sink buffer supports async accessor natively. + +Python has two types of queues. One is thread-safe :py:class:`queue.Queue` (sync queue) and the other is its async variant :py:class:`asyncio.Queue` (async queue). + +The accessors of sync queue, :py:meth:`queue.Queue.get` and :py:meth:`queue.Queue.put`, are thread-safe, and they support blocking operations with timeout. +The accessors of async queue, :py:meth:`asyncio.Queue.get` and :py:meth:`asyncio.Queue.put`, are not thread-safe. They return coroutine which can be awaited. For the foreground thread to actually fetch the values from the queue, these coroutinues must be executed by the same async event loop that's running the pipeline. There are synchronous variant of these accessors, :py:meth:`asyncio.Queue.get_nowait` and :py:meth:`asyncio.Queue.put_nowait`, which can work without an event loop, but since they are not thread-safe, they can only be used when the pipeline is not running. + +If we choose sync queue, reading from the foreground is straightforward because the its accessors are thread-safe, but writing to the queue can block the event loop. +If we choose async queue, writing to the queue is straightforward in an event loop, but reading from the foreground is convoluted, because the access must be thread-safe, and if the loop is running and the Pipeline is still writing the queue, then the read access must use async operation as well. + +From the perspective of the apparent code simplicity, :py:class:`queue.Queue` requires less code to write, however, having the blocking :py:meth:`queue.Queue.put` call in event loop makes it impossible to cleanly stop the background thread. This is because the synchronous blocking call blocks the event loop, and prevents the loop from processing cancellation request. + +For this reason, we use :py:class:`asyncio.Queue` in the :py:class:`Pipeline`. As a result, the implementation of :py:meth:`Pipeline.get_item` becomes a bit convoluted. The next section explains why it is the case. + +Thread, loop and task +--------------------- + +In implementing :py:class:`Pipeline`, there are several object states that need to be carefully managed. They are + +- The state of the background thread which runs the event loop. +- The state of the async event loop managed by the background thread. +- The state of the pipeline task, which process data and puts in the sink buffer. + +When the foreground thread attempts to fetch data from sink buffer, which is an async queue, it must use the different API (sync vs async accessor) to get the data, depending on the state of the state of the pipeline execution. This is because when the pipeline is running, the pipeline puts data in the async queue, and the event loop controls its execution. To access the async queue in cooperative manner, the foreground has to issue a request to run fetch coroutine (:py:meth:`asyncio.Queue.get`) to the background thread and wait for the result. However if the event loop is not running, then this request to run the fetch coroutine will never be fulfilled. Therefore, if the event loop is not running, the foreground must use sync accessor (:py:meth:`asyncio.Queue.get_nowait`). + +Another thing to consider is how to run the event loop. The foreground attempts to fetch data, the fetch request must be made via :py:func:`asyncio.run_coroutine_threadsafe`, so the system needs access to the loop object. In general, however, it is recommended not to manage loop object explicitly i.e. :py:meth:`asyncio.loop.run_forever` or :py:meth:`asyncio.loop.run_until_complete`). Instead it is encouraged to use :py:func:`asyncio.run`. But if we simply pass the pipeline coroutine to the :py:func:`asyncio.run` function, as soon as the task completes, the event loop is stopped and closed. We would like to encapsulate the event loop in the background thread and abstract away from the foreground thread. But this way, the foreground thread cannot know if the loop is running or not. + +Following the above considerations, the implementation of the pipeline executions follows the following constraints. + +- 1. To make the state management simpler, overlap the life cycle of the background thread and the event loop. + + - a. When the thread is started, the control flow is not returned to the foreground thread until the event loop is initialized. + - b. The thread is stopped when the event loop is stopped. + +- 2. Detach the life cycle of pipeline task from that of the event loop. + + - a. Keep the event loop alive after the pipeline task is completed. + - b. Wait for the explicit request to stop the loop. + +- 3. The event loop signals the object that manages the background thread that the task is completed. + +Following the above constraints, the foreground can decide whether it should use sync or async accessor. + +- If the background thread is not started. -> Fail +- If the task is completed. -> Use sync API +- Otherwise, the task is running. -> use async API. + +The following sequence diagram summarizes the interaction between the foreground thread, the background thread, the event loop and the pipeline task. + +.. mermaid:: + + sequenceDiagram + FG Thread ->>+ BG Thread: Start BG Thread + + create participant Event Loop + BG Thread ->> Event Loop: Start Event loop + Event Loop ->> BG Thread: Event loop initialized + BG Thread ->>- FG Thread: Return + + create participant Task + Event Loop ->> Task: Start Task + FG Thread --)+ BG Thread: Q: "Is task started?" + BG Thread --)- FG Thread: A: "Not yet." + Event Loop -->> BG Thread: Signal task start + FG Thread --)+ BG Thread: Q: "Is task started?" + BG Thread --)- FG Thread: A: "Yes it is started." + FG Thread --)+ BG Thread: Q: "Is task completed?" + BG Thread --)- FG Thread: A: "Not yet." + + destroy Task + Task ->> Event Loop: Task completed + Event Loop -->> BG Thread: Signal task completion + FG Thread --)+ BG Thread: Q: "Is task completed?" + BG Thread --)- FG Thread: A: "Yes it is completed." + Event Loop ->> Event Loop: Keep event loop alive + FG Thread ->>+ BG Thread: Request stop event loop + BG Thread -->> Event Loop: Signal Stop + BG Thread ->>- FG Thread: Return without waiting for the loop stop + + destroy Event Loop + Event Loop ->> BG Thread: Loop Stopped + FG Thread ->>+ BG Thread: Join thread + BG Thread ->>- FG Thread: Return + +If the foreground thread decides to stop the pipeline before its completion, the +event loop will cancel the pipeline task, (in turn the pipeline task will cancel +tasks correspond to pipeline stages) then the foreground thread will wait for the +background thread to complete the loop and join. + + +.. mermaid:: + + sequenceDiagram + FG Thread ->>+ BG Thread: Start BG Thread + + create participant Event Loop + BG Thread ->> Event Loop: Start Event Loop + Event Loop ->> BG Thread: Event loop initialized + BG Thread ->>- FG Thread: Return + + create participant Task + Event Loop ->> Task: Start Task + Event Loop -->> BG Thread: Signal task start + FG Thread ->>+ BG Thread: Request stop event loop + BG Thread -->> Event Loop: Signal Stop + BG Thread ->>- FG Thread: Return without waiting for the loop stop + Event Loop -->> Task: Signal Stop + + destroy Task + Task ->> Event Loop: Task cancelled + + destroy Event Loop + Event Loop ->> BG Thread: Loop Stopped + FG Thread ->>+ BG Thread: Join thread + BG Thread ->>- FG Thread: Return diff --git a/main/_sources/overview.rst.txt b/main/_sources/overview.rst.txt new file mode 100644 index 00000000..a25aa39a --- /dev/null +++ b/main/_sources/overview.rst.txt @@ -0,0 +1,84 @@ +Overview +======== + +What is SPDL? +------------- + +SPDL (Scalable and Performant Data Loading) is a research project to explore +the design of fast data loading for ML training with free-threaded (a.k.a no-GIL) Python, +but brings its benefits to the current ML systems. + +SPDL implements an abstraction that facilitates building performant data processing +pipelines that utilizes multi-threading. + +Oftentimes, the bottleneck of data loading is in media decoding and pre-processing. +So, in addition to the pipeline abstraction, SPDL also provides an I/O module for +multimedia (audio, video and image) processing. +This I/O module was designed from scratch to achieve high performance and high throughput. + +There are three main components in SPDL. + +1. Task execution engine. (The pipeline abstraction) +2. Utilities to build the data processing pipelines with the task execution engine. +3. Efficient media processing operations that are thread-safe. + +SPDL provides many ways to tune the performance. Some of them are explicit, +such as stage-wise concurrency and the size of thread pool. +Others are implicit and subtle, such as the choice of sync and async functions +and structuring and ordering of the pre-processing. +The pipelines built with SPDL provide various insights about its performance. +This makes it easy to diagnose the performance and optimize the performance, + +What SPDL is NOT +---------------- + +* SPDL is not a drop-in replacement of existing data loading solutions. +* SPDL does not guarantee automagical performance improvement. + +SPDL is an attempt and an experimental evidence that thread-based parallelism can +achieve higher throughput than common process-based parallelism, +even under the constraint of GIL. + +SPDL does not claim to be the fastest solution out there, nor it aims to be the +fastest. The goal of SPDL is to pave the way for to take advantage of free-threaded +Python in Machine Learning, by first solving the bottleneck (media decoding) +in data loading, then later performing other parts of pre-processing within +multi-threading paradigm. + +When to use SPDL? +----------------- + +SPDL is highly flexible. You can use it in variety of ways. + +1. As a new end-to-end data loading pipeline. + The primal goal of SPDL is to build performant data loading solutions for ML. + The project mostly talk about the performance in end-to-end (from data storage + to GPUs) context. + Using SPDL as a replacement for existing data loading solution is what the + development team intends. +2. As a replacement for media processor. + SPDL uses multi-threading for fast data processing. It is possible to use it in + sub-processes. If your current data loading pipeline is elaborated, and it is not + ideal to replace the whole data loading pipeline, you can start adopting SPDL + by replacing the media processing part. This should allow reducing the number of + sub-processes, improving the overall performance. +3. As a research tool in free-threaded Python and high-performance computing. + SPDL's task execute engine uses async event loop at its core. Async event loop + itself is single-threaded. Only the functions passed to the executors are + executed concurrently. This makes SPDL an ideal test bed for experimenting with + free-threaded Python and high-performance computing. + SPDL provides option to enable GIL in its I/O module when building from source. + The ability to enable/disable GIL helps performing controlled experiments. + Please check out the `Installation <./installation.html>`_ for how to customize the build. + +Expectations for OSS Support +---------------------------- + +We can't commit to providing active support, including fixing external bug reports +or reviewing pull requests. +We made SPDL publicly available to facilitate communicating our insights on +free threading for data loading. +While we do use it in production, if you choose to do so, you are on your own. +We make sure SPDL is sufficiently stable and fast for our production workloads, +but we make no assurances about its stability or +correctness or performance for any external workloads or use-cases. diff --git a/main/_sources/performance_analysis/bottleneck.rst.txt b/main/_sources/performance_analysis/bottleneck.rst.txt new file mode 100644 index 00000000..97b40959 --- /dev/null +++ b/main/_sources/performance_analysis/bottleneck.rst.txt @@ -0,0 +1,115 @@ +Is data loading bottleneck? +=========================== + +.. py:currentmodule:: spdl.dataloader + +When optimizing ML training pipeline, it is important to determine if data loading is +the bottleneck. + +The sink stage of :py:class:`Pipeline` is the interface between the data processing pipeline +running in the background thread and the model training running in the foreground thread. + +The sink is responsible for fetching data produced by the pipeline upstream stages and +putting them in the buffer, which is accessed by the foreground thread. + +If the pipeline upstream is not producing data fast enough, the sink gets blocked on the input +data. +Similarly, if the foreground thread is not consuming the data fast enough, the buffer gets full +and the sink gets gets blocked on the output buffer. + +Therefore, by monitoring the time sink gets blocked on each end of the buffer, +we can determine if the training is bound by data loading or model training. + +We look at this with some toy examples. + +Baseline +-------- + +The following snippet constructs a Pipeline without any processing. + +.. code-block:: + + >>> pipeline = ( + ... PipelineBuilder() + ... .add_source(range(100)) + ... .add_sink(1) + ... .build() + ... ) + +We execute it as following. There is no bottleneck in the execution. + +.. code-block:: + + >>> with pipeline.auto_stop(): + ... for item in pipeline: + ... pass + +Executing the above code gives a log like the following. + +.. code-block:: + + [sink] Processed 100 items in 7.0900 [ms ]. QPS: 14104.37. Average wait time: Upstream: 0.0674 [ms ], Downstream: 0.0007 [ms ]. + +The ``Upstream`` in the log is the time that sink waited on the production of data, and the ``Downstream`` is the time that sink waited for the buffer space to become available. + +In the above case, there is no bottleneck and both are quit fast. + +Bottleneck is in training loop +------------------------------ + +Now, we introduce an artificial delay in the foreground thread to see how the average time changes. +We change the way the pipeline is executed as following. + +.. code-block:: + + >>> with pipeline.auto_stop(): + ... for item in pipeline: + ... time.sleep(100) + +.. code-block:: + + [sink] Processed 100 items in 10.2294 [sec]. QPS: 9.78. Average wait time: Upstream: 0.0157 [ms ], Downstream: 102.2399 [ms ]. + +We see that the average time that sink waited on the downstream buffer increased from less than 1 millisecond to over 100 milliseconds, which corresponds to the delay we introduced. + +Bottleneck is in data loading +----------------------------- + +Next, we modify the pipeline as follow to introduce an artificial delay in the data loading pipeline. + +.. code-block:: + + >>> async def delay(item): + ... await asyncio.sleep(0.1) + ... return item + ... + >>> + >>> pipeline = ( + ... PipelineBuilder() + ... .add_source(range(100)) + ... .pipe(delay) + ... .add_sink(1) + ... .build() + ... ) + +We execute the pipeline, like the first time without any delay in the foreground thread. + +.. code-block:: + + >>> with pipeline.auto_stop(): + ... for item in pipeline: + ... pass + +Executing the above, we obtain the following log. + +.. code-block:: + + [delay] Completed 100 tasks ( 0 failed) in 10.1984 [sec]. QPS: 9.81 (Concurrency: 1). Average task time: 101.3354 [ ms]. + [sink] Processed 100 items in 10.1938 [sec]. QPS: 9.81. Average wait time: Upstream: 100.8673 [ms ], Downstream: 0.0167 [ms ]. + +The average upstream wait time is increased to 100 millisecond. + +Summary +------- + +Using :py:class:`Pipeline`, it becomes easy to determine if the bottleneck is in data loading or not. When the data loading is the bottleneck, the sink stage gets blocked on the input queue. So if the upstream wait time is larger than that of downstream, the data loading is the bottleneck. diff --git a/main/_sources/performance_analysis/index.rst.txt b/main/_sources/performance_analysis/index.rst.txt new file mode 100644 index 00000000..63e0a0a6 --- /dev/null +++ b/main/_sources/performance_analysis/index.rst.txt @@ -0,0 +1,13 @@ +Performance Analysis +==================== + +When optimizing ML model pipeline, it is important to determine if data loading is bottleneck. +SPDL facilitates the pipeline performance analysis. + +:py:class:`Pipeline` records runtime statistics and report them at the end of the execution. +In this section, we look at how to analyze the pipeline performance and optimize the pipeline. + +.. toctree:: + + bottleneck + stage_stats diff --git a/main/_sources/performance_analysis/stage_stats.rst.txt b/main/_sources/performance_analysis/stage_stats.rst.txt new file mode 100644 index 00000000..35ad6310 --- /dev/null +++ b/main/_sources/performance_analysis/stage_stats.rst.txt @@ -0,0 +1,227 @@ +Which stage is the bottleneck? +============================== + +.. py:currentmodule:: spdl.dataloader + +By default, when a pipe stage is created, :py:class:`TaskStatsHook` is attached to the stage. +This hook collects runtime statistics of the stage and report them at the end. +We can use this report to determine which stage in the pipeline is being the bottleneck +thus requires improvement. + +Task Stats and QPS +------------------ + +Let's say, we have a pipeline that downloads data from remote storage system and process the data. + +.. code-block:: + + >>> pipeline = ( + ... PipelineBuilder() + ... .add_source(sample_list) + ... .pipe(download, concurrency=32) + ... .pipe(process, concurrency=128) + ... .add_sink(3) + ... .build(num_threads=128) + ... ) + +We execute the pipeline without downstream load, and we obtain the following log. + +.. code-block:: + + >>> with pipeline.auto_stop(): + ... for data in pipeline: + ... pass + +.. code-block:: + + [download] Completed 2559 tasks (163 failed) in 17.3974 [sec]. QPS: 137.72 (Concurrency: 32). Average task time: 128.7163 [ ms]. + [process] Completed 2396 tasks ( 0 failed) in 18.9318 [sec]. QPS: 126.56 (Concurrency: 128). Average task time: 896.3629 [ ms]. + +:py:class:`TaskStatsHook` collects the number of tasks (items processed by the stage), the average task execution time and the time elapsed between the start and the end of the stage. + +.. note:: + + The average task time does not include the failed tasks, however, + the total duration of the stage include everything from task execution + to the time it waited on input/output queues. + +``QPS`` (queries per second, though it is not query) is the number of tasks successfully completed, divided by the duration of the stage. It is an indication of how fast the stage is processing items. + +From source to the sink, ``QPS`` can only decrease, as it is impossible for downstream stages to process items faster than upstream stages. +If a downstream stage is fast enough to catch up its upstream stage, then the QPS values are roughly the same between these stages. +If a downstream stage is not as fast as its upstream stage, then the QPS value of the downstream stage is smaller than that of the upstream stage. + +Therefore, by locating the stage at which QPS drops significantly, we can determine the stage which is the bottleneck within the pipeline. + +In the above example, QPS drops from 137 to 126 in the ``process`` stage. This indicates that data processing is not up to the speed of data acquisition. To optimize the pipeline throughput, one needs to improve the performance of the ``process`` stage. Increasing the throughput of the ``download`` stage does not help. How to optimize the ``process`` stage depends on the other factors. For example if the machine executing the pipeline has spare computation resource, then increasing the concurrency and the number of threads can help. + +Tuning Pipeline Performance +--------------------------- + +Let's look at another example. + +This time, we download images from the remote source, decode, batch and send them to GPU device. We create decoding/pre-processing and batch stage using :py:mod:`spdl.io`. + +.. code-block:: + + >>> def decode(width=224, height=224, pix_fmt="rgb24") -> Callable: + ... """Decode and resize image from byte string""" + ... filter_desc = spdl.io.get_video_filter_desc( + ... scale_width=width, scale_height=height, pix_fmt=pix_fmt + ... ) + ... + ... async def decode(data: bytes) -> FFmpegFrames: + ... packets = await spdl.io.async_demux_image(data) + ... frames = await spdl.io.async_decode_packets(packets, filter_desc=filter_desc) + ... return frames + ... + ... return decode + +.. code-block:: + + >>> async def batchify(frames: list[FFmpegFrames]) -> torch.Tensor: + ... """Create a batch from image frames, send them to GPU and create Torch tensor""" + ... cfg = spdl.io.cuda_config(device_index=0) + ... cpu_buffer = await spdl.io.async_convert_frames(frames) + ... cuda_buffer = await spdl.io.async_transfer_buffer(cpu_buffer, cuda_config=cfg) + ... + ... return routes, spdl.io.to_torch(cuda_buffer) + +.. code-block:: + + >>> def run_pipeline(dl_concurrency, decode_concurrency): + ... pipeline = ( + ... PipelineBuilder() + ... .add_source(src) + ... .pipe(download, concurrency=dl_concurrency) + ... .pipe(decode(), concurrency=decode_concurrency) + ... .aggregate(32) + ... .pipe(batchify) + ... .add_sink(10) + ... .build(num_threads=decode_concurrency) + ... ) + ... with pipeline.auto_stop(): + ... for item in pipeline: + ... pass + + +Now we run the pipeline with different concurrency values for downloading and decoding. +(You can skip the raw result and go to the summary table bellow.) + +.. code-block:: + + >>> run_pipeline(64, 4) + +.. code-block:: + + [download] Completed 1600 tasks ( 0 failed) in 6.2723 [sec]. QPS: 255.09 (Concurrency: 64). Average task time: 240.2614 [ ms]. + [decode_image] Completed 1600 tasks ( 0 failed) in 6.2763 [sec]. QPS: 254.93 (Concurrency: 4). Average task time: 3.8516 [ ms]. + [aggregate(32, drop_last=False)] Completed 1601 tasks ( 0 failed) in 6.2786 [sec]. QPS: 254.99 (Concurrency: 1). Average task time: 0.0038 [ ms]. + [batchify] Completed 50 tasks ( 0 failed) in 6.2790 [sec]. QPS: 7.96 (Concurrency: 1). Average task time: 1.6127 [ ms]. + [sink] Processed 50 items in 6.2799 [sec]. QPS: 7.96. Average wait time: Upstream: 123.1203 [ms ], Downstream: 0.0043 [ms ]. + +.. code-block:: + + >>> run_pipeline(128, 4) + +.. code-block:: + + [download] Completed 1600 tasks ( 0 failed) in 2.0347 [sec]. QPS: 786.36 (Concurrency: 128). Average task time: 139.2847 [ ms]. + [decode_image] Completed 1600 tasks ( 0 failed) in 2.0385 [sec]. QPS: 784.89 (Concurrency: 4). Average task time: 4.1260 [ ms]. + [aggregate(32, drop_last=False)] Completed 1601 tasks ( 0 failed) in 2.0477 [sec]. QPS: 781.87 (Concurrency: 1). Average task time: 0.0039 [ ms]. + [batchify] Completed 50 tasks ( 0 failed) in 2.0522 [sec]. QPS: 24.36 (Concurrency: 1). Average task time: 2.6672 [ ms]. + [sink] Processed 50 items in 2.0529 [sec]. QPS: 24.36. Average wait time: Upstream: 40.2405 [ms ], Downstream: 0.0040 [ms ]. + +.. code-block:: + + >>> run_pipeline(256, 4) + +.. code-block:: + + [download] Completed 1600 tasks ( 0 failed) in 1.8855 [sec]. QPS: 848.57 (Concurrency: 256). Average task time: 146.4174 [ ms]. + [decode_image] Completed 1600 tasks ( 0 failed) in 1.8907 [sec]. QPS: 846.25 (Concurrency: 4). Average task time: 4.3023 [ ms]. + [aggregate(32, drop_last=False)] Completed 1601 tasks ( 0 failed) in 1.8935 [sec]. QPS: 845.52 (Concurrency: 1). Average task time: 0.0038 [ ms]. + [batchify] Completed 50 tasks ( 0 failed) in 1.8942 [sec]. QPS: 26.40 (Concurrency: 1). Average task time: 2.6016 [ ms]. + [sink] Processed 50 items in 1.8945 [sec]. QPS: 26.39. Average wait time: Upstream: 37.1349 [ms ], Downstream: 0.0039 [ms ]. + +.. code-block:: + + >>> run_pipeline(512, 4) + +.. code-block:: + + [download] Completed 1600 tasks ( 0 failed) in 1.9942 [sec]. QPS: 802.31 (Concurrency: 512). Average task time: 151.8697 [ ms]. + [decode_image] Completed 1600 tasks ( 0 failed) in 1.9986 [sec]. QPS: 800.55 (Concurrency: 4). Average task time: 4.5500 [ ms]. + [aggregate(32, drop_last=False)] Completed 1601 tasks ( 0 failed) in 2.0021 [sec]. QPS: 799.67 (Concurrency: 1). Average task time: 0.0038 [ ms]. + [batchify] Completed 50 tasks ( 0 failed) in 2.0029 [sec]. QPS: 24.96 (Concurrency: 1). Average task time: 3.1626 [ ms]. + [sink] Processed 50 items in 2.0037 [sec]. QPS: 24.95. Average wait time: Upstream: 39.2747 [ms ], Downstream: 0.0044 [ms ]. + +.. code-block:: + + >>> run_pipeline(256, 8) + +.. code-block:: + + [download] Completed 1600 tasks ( 0 failed) in 1.3731 [sec]. QPS: 1165.27 (Concurrency: 256). Average task time: 152.5442 [ ms]. + [decode_image] Completed 1600 tasks ( 0 failed) in 1.3768 [sec]. QPS: 1162.10 (Concurrency: 8). Average task time: 5.4827 [ ms]. + [aggregate(32, drop_last=False)] Completed 1601 tasks ( 0 failed) in 1.3794 [sec]. QPS: 1160.61 (Concurrency: 1). Average task time: 0.0038 [ ms]. + [batchify] Completed 50 tasks ( 0 failed) in 1.3806 [sec]. QPS: 36.22 (Concurrency: 1). Average task time: 3.1528 [ ms]. + [sink] Processed 50 items in 1.3814 [sec]. QPS: 36.20. Average wait time: Upstream: 27.0740 [ms ], Downstream: 0.0041 [ms ]. + +.. code-block:: + + >>> run_pipeline(256, 16) + +.. code-block:: + + [download] Completed 1600 tasks ( 0 failed) in 2.2429 [sec]. QPS: 713.36 (Concurrency: 256). Average task time: 154.0344 [ ms]. + [decode_image] Completed 1600 tasks ( 0 failed) in 2.2661 [sec]. QPS: 706.06 (Concurrency: 16). Average task time: 14.4060 [ ms]. + [aggregate(32, drop_last=False)] Completed 1601 tasks ( 0 failed) in 2.3514 [sec]. QPS: 680.86 (Concurrency: 1). Average task time: 0.0039 [ ms]. + [batchify] Completed 50 tasks ( 0 failed) in 2.3610 [sec]. QPS: 21.18 (Concurrency: 1). Average task time: 15.5912 [ ms]. + [sink] Processed 50 items in 2.3622 [sec]. QPS: 21.17. Average wait time: Upstream: 46.3030 [ms ], Downstream: 0.0041 [ms ]. + +.. code-block:: + + >>> run_pipeline(256, 32) + +.. code-block:: + + [download] Completed 1600 tasks ( 0 failed) in 1.6766 [sec]. QPS: 954.30 (Concurrency: 256). Average task time: 156.4433 [ ms]. + [decode_image] Completed 1600 tasks ( 0 failed) in 1.6815 [sec]. QPS: 951.55 (Concurrency: 32). Average task time: 18.5734 [ ms]. + [aggregate(32, drop_last=False)] Completed 1601 tasks ( 0 failed) in 1.6862 [sec]. QPS: 949.48 (Concurrency: 1). Average task time: 0.0039 [ ms]. + [batchify] Completed 50 tasks ( 0 failed) in 1.6866 [sec]. QPS: 29.64 (Concurrency: 1). Average task time: 15.2163 [ ms]. + [sink] Processed 50 items in 1.6913 [sec]. QPS: 29.56. Average wait time: Upstream: 33.1498 [ms ], Downstream: 0.0041 [ms ]. + +The following table summarizes the above result. + +.. table:: + :class: right-align + + === ==================== ================== ============ ============ ===================== + Run Download Concurrency Decode Concurrency Download QPS Decoding QPS Sink QPS (normalized) + === ==================== ================== ============ ============ ===================== + 1 64 4 255.09 254.93 254.72 + 2 128 4 786.36 784.89 779.52 + 3 256 4 848.57 846.25 844.48 + 4 512 4 802.31 800.55 798.40 + 5 256 8 1165.27 1162.10 1158.40 + 6 256 16 713.36 706.06 677.44 + 7 256 32 954.30 951.55 945.92 + === ==================== ================== ============ ============ ===================== + +Looking at the first pipeline (``Run 1``), we do not see a significant QPS drop in the stages. +It is around 241 at the beginning and the at the end of the pipeline. +This suggests that the first stage (download) is dominating the QPS of the whole pipeline. +So we increase the download concurrency. + +As we increase the concurrency of download (``Run 2 - 4``), QPS increases, but QPS is saturated +around 800. +Because the pipeline is automatically blocked according to the performance of the downstream, +we tweak the concurrency of decoding. +Increasing the decode concurrency from 4 to 8 (``Run 5``), the QPS increases further more, but +it drops again beyond 16 (``Run 6, 7``). + +Summary +------- + +When running :py:class:`Pipeline`, :py:class:`TaskStatsHook`: provides runtime statistics of stages. This information is helpful when determining which part of the pipeline should be optimized. diff --git a/main/_static/basic.css b/main/_static/basic.css new file mode 100644 index 00000000..f316efcb --- /dev/null +++ b/main/_static/basic.css @@ -0,0 +1,925 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 360px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +a:visited { + color: #551A8B; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} + +nav.contents, +aside.topic, +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ + +nav.contents, +aside.topic, +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +nav.contents > :last-child, +aside.topic > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +nav.contents::after, +aside.topic::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +aside.footnote > span, +div.citation > span { + float: left; +} +aside.footnote > span:last-of-type, +div.citation > span:last-of-type { + padding-right: 0.5em; +} +aside.footnote > p { + margin-left: 2em; +} +div.citation > p { + margin-left: 4em; +} +aside.footnote > p:last-of-type, +div.citation > p:last-of-type { + margin-bottom: 0em; +} +aside.footnote > p:last-of-type:after, +div.citation > p:last-of-type:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +.sig dd { + margin-top: 0px; + margin-bottom: 0px; +} + +.sig dl { + margin-top: 0px; + margin-bottom: 0px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +.translated { + background-color: rgba(207, 255, 207, 0.2) +} + +.untranslated { + background-color: rgba(255, 207, 207, 0.2) +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; + white-space: nowrap; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/main/_static/collapsible-lists/LICENSE.md b/main/_static/collapsible-lists/LICENSE.md new file mode 100644 index 00000000..21859bfd --- /dev/null +++ b/main/_static/collapsible-lists/LICENSE.md @@ -0,0 +1,16 @@ +This code is the fruit of Kate Morley's labor, taken from here: + +- http://code.iamkate.com/javascript/collapsible-lists/ + +which has been updated here: + +- https://iamkate.com/code/tree-views/ + +and there is a strong desire for this folder to update accordingly, when +possible: + +- https://github.com/svenevs/exhale/issues/180 + +She includes a generous CC0 1.0 license for all materials on her site: + +- https://iamkate.com/code/ diff --git a/main/_static/collapsible-lists/css/button-closed.png b/main/_static/collapsible-lists/css/button-closed.png new file mode 100644 index 00000000..417eb2fc Binary files /dev/null and b/main/_static/collapsible-lists/css/button-closed.png differ diff --git a/main/_static/collapsible-lists/css/button-open.png b/main/_static/collapsible-lists/css/button-open.png new file mode 100644 index 00000000..ac4a6ef3 Binary files /dev/null and b/main/_static/collapsible-lists/css/button-open.png differ diff --git a/main/_static/collapsible-lists/css/button.png b/main/_static/collapsible-lists/css/button.png new file mode 100644 index 00000000..631d734d Binary files /dev/null and b/main/_static/collapsible-lists/css/button.png differ diff --git a/main/_static/collapsible-lists/css/list-item-contents.png b/main/_static/collapsible-lists/css/list-item-contents.png new file mode 100644 index 00000000..bc082929 Binary files /dev/null and b/main/_static/collapsible-lists/css/list-item-contents.png differ diff --git a/main/_static/collapsible-lists/css/list-item-last-open.png b/main/_static/collapsible-lists/css/list-item-last-open.png new file mode 100644 index 00000000..cf4cf9bd Binary files /dev/null and b/main/_static/collapsible-lists/css/list-item-last-open.png differ diff --git a/main/_static/collapsible-lists/css/list-item-last.png b/main/_static/collapsible-lists/css/list-item-last.png new file mode 100644 index 00000000..1eb1c64a Binary files /dev/null and b/main/_static/collapsible-lists/css/list-item-last.png differ diff --git a/main/_static/collapsible-lists/css/list-item-open.png b/main/_static/collapsible-lists/css/list-item-open.png new file mode 100644 index 00000000..0889c801 Binary files /dev/null and b/main/_static/collapsible-lists/css/list-item-open.png differ diff --git a/main/_static/collapsible-lists/css/list-item-root.png b/main/_static/collapsible-lists/css/list-item-root.png new file mode 100644 index 00000000..87441710 Binary files /dev/null and b/main/_static/collapsible-lists/css/list-item-root.png differ diff --git a/main/_static/collapsible-lists/css/list-item.png b/main/_static/collapsible-lists/css/list-item.png new file mode 100644 index 00000000..81934f9b Binary files /dev/null and b/main/_static/collapsible-lists/css/list-item.png differ diff --git a/main/_static/collapsible-lists/css/tree_view.css b/main/_static/collapsible-lists/css/tree_view.css new file mode 100644 index 00000000..fa21ac4e --- /dev/null +++ b/main/_static/collapsible-lists/css/tree_view.css @@ -0,0 +1,61 @@ +/* Source taken directly from: + * view-source:http://code.iamkate.com/javascript/collapsible-lists/ + * + * Kate Morley's license for this code is CC0: + * Created by [Kate Morley](http://iamkate.com/). Except where explicitly + * stated otherwise, all content is released under the terms of the + * [CC0 1.0 Universal legal code](http://creativecommons.org/publicdomain/zero/1.0/legalcode). + */ +.treeView{ + -moz-user-select:none; + position:relative; +} + +.treeView ul{ + margin:0 0 0 -1.5em ! important; + padding:0 0 0 1.5em ! important; +} + +.treeView ul ul{ + background:url('list-item-contents.png') repeat-y left ! important; +} + +.treeView li.lastChild > ul{ + background-image:none ! important; +} + +.treeView li{ + margin:0 ! important; + padding:0 ! important; + background:url('list-item-root.png') no-repeat top left ! important; + list-style-position:inside ! important; + list-style-image:url('button.png') ! important; + cursor:auto; +} + +.treeView li.collapsibleListOpen{ + list-style-image:url('button-open.png') ! important; + cursor:pointer; +} + +.treeView li.collapsibleListClosed{ + list-style-image:url('button-closed.png') ! important; + cursor:pointer; +} + +.treeView li li{ + background-image:url('list-item.png') ! important; + padding-left:1.5em ! important; +} + +.treeView li.lastChild{ + background-image:url('list-item-last.png') ! important; +} + +.treeView li.collapsibleListOpen{ + background-image:url('list-item-open.png') ! important; +} + +.treeView li.collapsibleListOpen.lastChild{ + background-image:url('list-item-last-open.png') ! important; +} diff --git a/main/_static/collapsible-lists/js/CollapsibleLists.compressed.js b/main/_static/collapsible-lists/js/CollapsibleLists.compressed.js new file mode 100644 index 00000000..429406cf --- /dev/null +++ b/main/_static/collapsible-lists/js/CollapsibleLists.compressed.js @@ -0,0 +1,83 @@ +/* + +CollapsibleLists.js + +An object allowing lists to dynamically expand and collapse + +Created by Kate Morley - http://code.iamkate.com/ - and released under +the terms of the CC0 1.0 Universal legal code: + +http://creativecommons.org/publicdomain/zero/1.0/legalcode + +*/ + +var CollapsibleLists=new function(){ +this.apply=function(_1){ +var _2=document.getElementsByTagName("ul"); +for(var _3=0;_3<_2.length;_3++){ +if(_2[_3].className.match(/(^| )collapsibleList( |$)/)){ +this.applyTo(_2[_3],true); +if(!_1){ +var _4=_2[_3].getElementsByTagName("ul"); +for(var _5=0;_5<_4.length;_5++){ +_4[_5].className+=" collapsibleList"; +} +} +} +} +}; +this.applyTo=function(_6,_7){ +var _8=_6.getElementsByTagName("li"); +for(var _9=0;_9<_8.length;_9++){ +if(!_7||_6==_8[_9].parentNode){ +if(_8[_9].addEventListener){ +_8[_9].addEventListener("mousedown",function(e){ +e.preventDefault(); +},false); +}else{ +_8[_9].attachEvent("onselectstart",function(){ +event.returnValue=false; +}); +} +if(_8[_9].addEventListener){ +_8[_9].addEventListener("click",_a(_8[_9]),false); +}else{ +_8[_9].attachEvent("onclick",_a(_8[_9])); +} +_b(_8[_9]); +} +} +}; +function _a(_c){ +return function(e){ +if(!e){ +e=window.event; +} +var _d=(e.target?e.target:e.srcElement); +while(_d.nodeName!="LI"){ +_d=_d.parentNode; +} +if(_d==_c){ +_b(_c); +} +}; +}; +function _b(_e){ +var _f=_e.className.match(/(^| )collapsibleListClosed( |$)/); +var uls=_e.getElementsByTagName("ul"); +for(var _10=0;_100){ +_e.className+=" collapsibleList"+(_f?"Open":"Closed"); +} +}; +}(); + diff --git a/main/_static/collapsible-lists/js/apply-collapsible-lists.js b/main/_static/collapsible-lists/js/apply-collapsible-lists.js new file mode 100644 index 00000000..e848bb98 --- /dev/null +++ b/main/_static/collapsible-lists/js/apply-collapsible-lists.js @@ -0,0 +1,3 @@ +$(document).ready(function() { + CollapsibleLists.apply(); +}); diff --git a/main/_static/css/custom.css b/main/_static/css/custom.css new file mode 100644 index 00000000..9e4838fb --- /dev/null +++ b/main/_static/css/custom.css @@ -0,0 +1,45 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +/* + */ +div.custom_autosummary h2 { + color: #c95362; + display: none; + height: 0; + margin: 0; + border: 0; + padding: 0; +} +div.document div.custom_autosummary section section { + margin: 0; +} +div.custom_autosummary table.docutils { + margin-left: 0; + box-shadow: none; +} + +div.custom_autosummary table.docutils tbody tr td { + border-color: transparent; +} + +dl.py.function > dt.sig.sig-object.py { + margin-bottom: 1em; +} + +table.right-align > tbody > tr { + text-align: right +} + +/* For details in source code of Example sections */ + section > details { + margin-bottom: 1rem; + padding: .8em; + background: #f8f8f8; + border-radius: 20px +} diff --git a/main/_static/debug.css b/main/_static/debug.css new file mode 100644 index 00000000..74d4aec3 --- /dev/null +++ b/main/_static/debug.css @@ -0,0 +1,69 @@ +/* + This CSS file should be overridden by the theme authors. It's + meant for debugging and developing the skeleton that this theme provides. +*/ +body { + font-family: -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, + "Apple Color Emoji", "Segoe UI Emoji"; + background: lavender; +} +.sb-announcement { + background: rgb(131, 131, 131); +} +.sb-announcement__inner { + background: black; + color: white; +} +.sb-header { + background: lightskyblue; +} +.sb-header__inner { + background: royalblue; + color: white; +} +.sb-header-secondary { + background: lightcyan; +} +.sb-header-secondary__inner { + background: cornflowerblue; + color: white; +} +.sb-sidebar-primary { + background: lightgreen; +} +.sb-main { + background: blanchedalmond; +} +.sb-main__inner { + background: antiquewhite; +} +.sb-header-article { + background: lightsteelblue; +} +.sb-article-container { + background: snow; +} +.sb-article-main { + background: white; +} +.sb-footer-article { + background: lightpink; +} +.sb-sidebar-secondary { + background: lightgoldenrodyellow; +} +.sb-footer-content { + background: plum; +} +.sb-footer-content__inner { + background: palevioletred; +} +.sb-footer { + background: pink; +} +.sb-footer__inner { + background: salmon; +} +.sb-article { + background: white; +} diff --git a/main/_static/doctools.js b/main/_static/doctools.js new file mode 100644 index 00000000..4d67807d --- /dev/null +++ b/main/_static/doctools.js @@ -0,0 +1,156 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Base JavaScript utilities for all Sphinx HTML documentation. + * + * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ +"use strict"; + +const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ + "TEXTAREA", + "INPUT", + "SELECT", + "BUTTON", +]); + +const _ready = (callback) => { + if (document.readyState !== "loading") { + callback(); + } else { + document.addEventListener("DOMContentLoaded", callback); + } +}; + +/** + * Small JavaScript module for the documentation. + */ +const Documentation = { + init: () => { + Documentation.initDomainIndexTable(); + Documentation.initOnKeyListeners(); + }, + + /** + * i18n support + */ + TRANSLATIONS: {}, + PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), + LOCALE: "unknown", + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext: (string) => { + const translated = Documentation.TRANSLATIONS[string]; + switch (typeof translated) { + case "undefined": + return string; // no translation + case "string": + return translated; // translation exists + default: + return translated[0]; // (singular, plural) translation tuple exists + } + }, + + ngettext: (singular, plural, n) => { + const translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated !== "undefined") + return translated[Documentation.PLURAL_EXPR(n)]; + return n === 1 ? singular : plural; + }, + + addTranslations: (catalog) => { + Object.assign(Documentation.TRANSLATIONS, catalog.messages); + Documentation.PLURAL_EXPR = new Function( + "n", + `return (${catalog.plural_expr})` + ); + Documentation.LOCALE = catalog.locale; + }, + + /** + * helper function to focus on search bar + */ + focusSearchBar: () => { + document.querySelectorAll("input[name=q]")[0]?.focus(); + }, + + /** + * Initialise the domain index toggle buttons + */ + initDomainIndexTable: () => { + const toggler = (el) => { + const idNumber = el.id.substr(7); + const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); + if (el.src.substr(-9) === "minus.png") { + el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; + toggledRows.forEach((el) => (el.style.display = "none")); + } else { + el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; + toggledRows.forEach((el) => (el.style.display = "")); + } + }; + + const togglerElements = document.querySelectorAll("img.toggler"); + togglerElements.forEach((el) => + el.addEventListener("click", (event) => toggler(event.currentTarget)) + ); + togglerElements.forEach((el) => (el.style.display = "")); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); + }, + + initOnKeyListeners: () => { + // only install a listener if it is really needed + if ( + !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && + !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS + ) + return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.altKey || event.ctrlKey || event.metaKey) return; + + if (!event.shiftKey) { + switch (event.key) { + case "ArrowLeft": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const prevLink = document.querySelector('link[rel="prev"]'); + if (prevLink && prevLink.href) { + window.location.href = prevLink.href; + event.preventDefault(); + } + break; + case "ArrowRight": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const nextLink = document.querySelector('link[rel="next"]'); + if (nextLink && nextLink.href) { + window.location.href = nextLink.href; + event.preventDefault(); + } + break; + } + } + + // some keyboard layouts may need Shift to get / + switch (event.key) { + case "/": + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; + Documentation.focusSearchBar(); + event.preventDefault(); + } + }); + }, +}; + +// quick alias for translations +const _ = Documentation.gettext; + +_ready(Documentation.init); diff --git a/main/_static/documentation_options.js b/main/_static/documentation_options.js new file mode 100644 index 00000000..bdfe451b --- /dev/null +++ b/main/_static/documentation_options.js @@ -0,0 +1,13 @@ +const DOCUMENTATION_OPTIONS = { + VERSION: '0.0.6', + LANGUAGE: 'en', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: true, + SHOW_SEARCH_SUMMARY: true, + ENABLE_SEARCH_SHORTCUTS: true, +}; \ No newline at end of file diff --git a/main/_static/file.png b/main/_static/file.png new file mode 100644 index 00000000..a858a410 Binary files /dev/null and b/main/_static/file.png differ diff --git a/main/_static/js/custom.js b/main/_static/js/custom.js new file mode 100644 index 00000000..e53e1449 --- /dev/null +++ b/main/_static/js/custom.js @@ -0,0 +1,85 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +/** + * We add extra br tags to the autodoc output, so each parameter is shown on + * its own line. + */ +function setupAutodocPy() { + const paramElements = document.querySelectorAll('.py .sig-param') + + Array(...paramElements).forEach((element) => { + let brElement = document.createElement('br') + element.parentNode.insertBefore(brElement, element) + }) + + const lastParamElements = document.querySelectorAll('.py em.sig-param:last-of-type') + + Array(...lastParamElements).forEach((element) => { + let brElement = document.createElement('br') + element.after(brElement) + }) +} + +function setupAutodocCpp() { + const highlightableElements = document.querySelectorAll(".c dt.sig-object, .cpp dt.sig-object") + + Array(...highlightableElements).forEach((element) => { + element.classList.add("highlight"); + }) + + const documentables = document.querySelectorAll("dt.sig-object.c,dt.sig-object.cpp"); + + Array(...documentables).forEach((element) => { + element.classList.add("highlight"); + + var parens = element.querySelectorAll(".sig-paren"); + var commas = Array(...element.childNodes).filter(e => e.textContent == ", ") + + if (parens.length != 2) return; + + commas.forEach(c => { + if (c.compareDocumentPosition(parens[0]) == Node.DOCUMENT_POSITION_PRECEDING && + c.compareDocumentPosition(parens[1]) == Node.DOCUMENT_POSITION_FOLLOWING + ) { + let brElement = document.createElement('br') + let spanElement = document.createElement('span') + spanElement.className = "sig-indent" + c.after(brElement) + brElement.after(spanElement) + } + }); + + if (parens[0].nextSibling != parens[1]) { + // not an empty argument list + let brElement = document.createElement('br') + let spanElement = document.createElement('span') + spanElement.className = "sig-indent" + parens[0].after(brElement) + brElement.after(spanElement) + let brElement1 = document.createElement('br') + parens[1].parentNode.insertBefore(brElement1, parens[1]); + } + }) +} + +/* Append `target="_blank"` to source link + */ +function updateSourceLink() { + const sourceLinks = document.querySelectorAll("a.reference.external") + console.log(sourceLinks) + sourceLinks.forEach(c => { + c.setAttribute('target', '_blank') + }) +} + +document.addEventListener("DOMContentLoaded", function() { + setupAutodocPy() + setupAutodocCpp() + updateSourceLink() +}) diff --git a/main/_static/language_data.js b/main/_static/language_data.js new file mode 100644 index 00000000..367b8ed8 --- /dev/null +++ b/main/_static/language_data.js @@ -0,0 +1,199 @@ +/* + * language_data.js + * ~~~~~~~~~~~~~~~~ + * + * This script contains the language-specific data used by searchtools.js, + * namely the list of stopwords, stemmer, scorer and splitter. + * + * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +var stopwords = ["a", "and", "are", "as", "at", "be", "but", "by", "for", "if", "in", "into", "is", "it", "near", "no", "not", "of", "on", "or", "such", "that", "the", "their", "then", "there", "these", "they", "this", "to", "was", "will", "with"]; + + +/* Non-minified version is copied as a separate JS file, if available */ + +/** + * Porter Stemmer + */ +var Stemmer = function() { + + var step2list = { + ational: 'ate', + tional: 'tion', + enci: 'ence', + anci: 'ance', + izer: 'ize', + bli: 'ble', + alli: 'al', + entli: 'ent', + eli: 'e', + ousli: 'ous', + ization: 'ize', + ation: 'ate', + ator: 'ate', + alism: 'al', + iveness: 'ive', + fulness: 'ful', + ousness: 'ous', + aliti: 'al', + iviti: 'ive', + biliti: 'ble', + logi: 'log' + }; + + var step3list = { + icate: 'ic', + ative: '', + alize: 'al', + iciti: 'ic', + ical: 'ic', + ful: '', + ness: '' + }; + + var c = "[^aeiou]"; // consonant + var v = "[aeiouy]"; // vowel + var C = c + "[^aeiouy]*"; // consonant sequence + var V = v + "[aeiou]*"; // vowel sequence + + var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 + var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 + var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 + var s_v = "^(" + C + ")?" + v; // vowel in stem + + this.stemWord = function (w) { + var stem; + var suffix; + var firstch; + var origword = w; + + if (w.length < 3) + return w; + + var re; + var re2; + var re3; + var re4; + + firstch = w.substr(0,1); + if (firstch == "y") + w = firstch.toUpperCase() + w.substr(1); + + // Step 1a + re = /^(.+?)(ss|i)es$/; + re2 = /^(.+?)([^s])s$/; + + if (re.test(w)) + w = w.replace(re,"$1$2"); + else if (re2.test(w)) + w = w.replace(re2,"$1$2"); + + // Step 1b + re = /^(.+?)eed$/; + re2 = /^(.+?)(ed|ing)$/; + if (re.test(w)) { + var fp = re.exec(w); + re = new RegExp(mgr0); + if (re.test(fp[1])) { + re = /.$/; + w = w.replace(re,""); + } + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1]; + re2 = new RegExp(s_v); + if (re2.test(stem)) { + w = stem; + re2 = /(at|bl|iz)$/; + re3 = new RegExp("([^aeiouylsz])\\1$"); + re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re2.test(w)) + w = w + "e"; + else if (re3.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + else if (re4.test(w)) + w = w + "e"; + } + } + + // Step 1c + re = /^(.+?)y$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(s_v); + if (re.test(stem)) + w = stem + "i"; + } + + // Step 2 + re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step2list[suffix]; + } + + // Step 3 + re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step3list[suffix]; + } + + // Step 4 + re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; + re2 = /^(.+?)(s|t)(ion)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + if (re.test(stem)) + w = stem; + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1] + fp[2]; + re2 = new RegExp(mgr1); + if (re2.test(stem)) + w = stem; + } + + // Step 5 + re = /^(.+?)e$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + re2 = new RegExp(meq1); + re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) + w = stem; + } + re = /ll$/; + re2 = new RegExp(mgr1); + if (re.test(w) && re2.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + + // and turn initial Y back to y + if (firstch == "y") + w = firstch.toLowerCase() + w.substr(1); + return w; + } +} + diff --git a/main/_static/minus.png b/main/_static/minus.png new file mode 100644 index 00000000..d96755fd Binary files /dev/null and b/main/_static/minus.png differ diff --git a/main/_static/plus.png b/main/_static/plus.png new file mode 100644 index 00000000..7107cec9 Binary files /dev/null and b/main/_static/plus.png differ diff --git a/main/_static/pygments.css b/main/_static/pygments.css new file mode 100644 index 00000000..02b4b128 --- /dev/null +++ b/main/_static/pygments.css @@ -0,0 +1,258 @@ +.highlight pre { line-height: 125%; } +.highlight td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +.highlight span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +.highlight td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +.highlight span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +.highlight .hll { background-color: #ffffcc } +.highlight { background: #f8f8f8; } +.highlight .c { color: #8f5902; font-style: italic } /* Comment */ +.highlight .err { color: #a40000; border: 1px solid #ef2929 } /* Error */ +.highlight .g { color: #000000 } /* Generic */ +.highlight .k { color: #204a87; font-weight: bold } /* Keyword */ +.highlight .l { color: #000000 } /* Literal */ +.highlight .n { color: #000000 } /* Name */ +.highlight .o { color: #ce5c00; font-weight: bold } /* Operator */ +.highlight .x { color: #000000 } /* Other */ +.highlight .p { color: #000000; font-weight: bold } /* Punctuation */ +.highlight .ch { color: #8f5902; font-style: italic } /* Comment.Hashbang */ +.highlight .cm { color: #8f5902; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #8f5902; font-style: italic } /* Comment.Preproc */ +.highlight .cpf { color: #8f5902; font-style: italic } /* Comment.PreprocFile */ +.highlight .c1 { color: #8f5902; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #8f5902; font-style: italic } /* Comment.Special */ +.highlight .gd { color: #a40000 } /* Generic.Deleted */ +.highlight .ge { color: #000000; font-style: italic } /* Generic.Emph */ +.highlight .ges { color: #000000; font-weight: bold; font-style: italic } /* Generic.EmphStrong */ +.highlight .gr { color: #ef2929 } /* Generic.Error */ +.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight .gi { color: #00A000 } /* Generic.Inserted */ +.highlight .go { color: #000000; font-style: italic } /* Generic.Output */ +.highlight .gp { color: #8f5902 } /* Generic.Prompt */ +.highlight .gs { color: #000000; font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight .gt { color: #a40000; font-weight: bold } /* Generic.Traceback */ +.highlight .kc { color: #204a87; font-weight: bold } /* Keyword.Constant */ +.highlight .kd { color: #204a87; font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { color: #204a87; font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { color: #204a87; font-weight: bold } /* Keyword.Pseudo */ +.highlight .kr { color: #204a87; font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #204a87; font-weight: bold } /* Keyword.Type */ +.highlight .ld { color: #000000 } /* Literal.Date */ +.highlight .m { color: #0000cf; font-weight: bold } /* Literal.Number */ +.highlight .s { color: #4e9a06 } /* Literal.String */ +.highlight .na { color: #c4a000 } /* Name.Attribute */ +.highlight .nb { color: #204a87 } /* Name.Builtin */ +.highlight .nc { color: #000000 } /* Name.Class */ +.highlight .no { color: #000000 } /* Name.Constant */ +.highlight .nd { color: #5c35cc; font-weight: bold } /* Name.Decorator */ +.highlight .ni { color: #ce5c00 } /* Name.Entity */ +.highlight .ne { color: #cc0000; font-weight: bold } /* Name.Exception */ +.highlight .nf { color: #000000 } /* Name.Function */ +.highlight .nl { color: #f57900 } /* Name.Label */ +.highlight .nn { color: #000000 } /* Name.Namespace */ +.highlight .nx { color: #000000 } /* Name.Other */ +.highlight .py { color: #000000 } /* Name.Property */ +.highlight .nt { color: #204a87; font-weight: bold } /* Name.Tag */ +.highlight .nv { color: #000000 } /* Name.Variable */ +.highlight .ow { color: #204a87; font-weight: bold } /* Operator.Word */ +.highlight .pm { color: #000000; font-weight: bold } /* Punctuation.Marker */ +.highlight .w { color: #f8f8f8 } /* Text.Whitespace */ +.highlight .mb { color: #0000cf; font-weight: bold } /* Literal.Number.Bin */ +.highlight .mf { color: #0000cf; font-weight: bold } /* Literal.Number.Float */ +.highlight .mh { color: #0000cf; font-weight: bold } /* Literal.Number.Hex */ +.highlight .mi { color: #0000cf; font-weight: bold } /* Literal.Number.Integer */ +.highlight .mo { color: #0000cf; font-weight: bold } /* Literal.Number.Oct */ +.highlight .sa { color: #4e9a06 } /* Literal.String.Affix */ +.highlight .sb { color: #4e9a06 } /* Literal.String.Backtick */ +.highlight .sc { color: #4e9a06 } /* Literal.String.Char */ +.highlight .dl { color: #4e9a06 } /* Literal.String.Delimiter */ +.highlight .sd { color: #8f5902; font-style: italic } /* Literal.String.Doc */ +.highlight .s2 { color: #4e9a06 } /* Literal.String.Double */ +.highlight .se { color: #4e9a06 } /* Literal.String.Escape */ +.highlight .sh { color: #4e9a06 } /* Literal.String.Heredoc */ +.highlight .si { color: #4e9a06 } /* Literal.String.Interpol */ +.highlight .sx { color: #4e9a06 } /* Literal.String.Other */ +.highlight .sr { color: #4e9a06 } /* Literal.String.Regex */ +.highlight .s1 { color: #4e9a06 } /* Literal.String.Single */ +.highlight .ss { color: #4e9a06 } /* Literal.String.Symbol */ +.highlight .bp { color: #3465a4 } /* Name.Builtin.Pseudo */ +.highlight .fm { color: #000000 } /* Name.Function.Magic */ +.highlight .vc { color: #000000 } /* Name.Variable.Class */ +.highlight .vg { color: #000000 } /* Name.Variable.Global */ +.highlight .vi { color: #000000 } /* Name.Variable.Instance */ +.highlight .vm { color: #000000 } /* Name.Variable.Magic */ +.highlight .il { color: #0000cf; font-weight: bold } /* Literal.Number.Integer.Long */ +@media not print { +body[data-theme="dark"] .highlight pre { line-height: 125%; } +body[data-theme="dark"] .highlight td.linenos .normal { color: #aaaaaa; background-color: transparent; padding-left: 5px; padding-right: 5px; } +body[data-theme="dark"] .highlight span.linenos { color: #aaaaaa; background-color: transparent; padding-left: 5px; padding-right: 5px; } +body[data-theme="dark"] .highlight td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +body[data-theme="dark"] .highlight span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +body[data-theme="dark"] .highlight .hll { background-color: #404040 } +body[data-theme="dark"] .highlight { background: #202020; color: #d0d0d0 } +body[data-theme="dark"] .highlight .c { color: #ababab; font-style: italic } /* Comment */ +body[data-theme="dark"] .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ +body[data-theme="dark"] .highlight .esc { color: #d0d0d0 } /* Escape */ +body[data-theme="dark"] .highlight .g { color: #d0d0d0 } /* Generic */ +body[data-theme="dark"] .highlight .k { color: #6ebf26; font-weight: bold } /* Keyword */ +body[data-theme="dark"] .highlight .l { color: #d0d0d0 } /* Literal */ +body[data-theme="dark"] .highlight .n { color: #d0d0d0 } /* Name */ +body[data-theme="dark"] .highlight .o { color: #d0d0d0 } /* Operator */ +body[data-theme="dark"] .highlight .x { color: #d0d0d0 } /* Other */ +body[data-theme="dark"] .highlight .p { color: #d0d0d0 } /* Punctuation */ +body[data-theme="dark"] .highlight .ch { color: #ababab; font-style: italic } /* Comment.Hashbang */ +body[data-theme="dark"] .highlight .cm { color: #ababab; font-style: italic } /* Comment.Multiline */ +body[data-theme="dark"] .highlight .cp { color: #ff3a3a; font-weight: bold } /* Comment.Preproc */ +body[data-theme="dark"] .highlight .cpf { color: #ababab; font-style: italic } /* Comment.PreprocFile */ +body[data-theme="dark"] .highlight .c1 { color: #ababab; font-style: italic } /* Comment.Single */ +body[data-theme="dark"] .highlight .cs { color: #e50808; font-weight: bold; background-color: #520000 } /* Comment.Special */ +body[data-theme="dark"] .highlight .gd { color: #ff3a3a } /* Generic.Deleted */ +body[data-theme="dark"] .highlight .ge { color: #d0d0d0; font-style: italic } /* Generic.Emph */ +body[data-theme="dark"] .highlight .ges { color: #d0d0d0; font-weight: bold; font-style: italic } /* Generic.EmphStrong */ +body[data-theme="dark"] .highlight .gr { color: #ff3a3a } /* Generic.Error */ +body[data-theme="dark"] .highlight .gh { color: #ffffff; font-weight: bold } /* Generic.Heading */ +body[data-theme="dark"] .highlight .gi { color: #589819 } /* Generic.Inserted */ +body[data-theme="dark"] .highlight .go { color: #cccccc } /* Generic.Output */ +body[data-theme="dark"] .highlight .gp { color: #aaaaaa } /* Generic.Prompt */ +body[data-theme="dark"] .highlight .gs { color: #d0d0d0; font-weight: bold } /* Generic.Strong */ +body[data-theme="dark"] .highlight .gu { color: #ffffff; text-decoration: underline } /* Generic.Subheading */ +body[data-theme="dark"] .highlight .gt { color: #ff3a3a } /* Generic.Traceback */ +body[data-theme="dark"] .highlight .kc { color: #6ebf26; font-weight: bold } /* Keyword.Constant */ +body[data-theme="dark"] .highlight .kd { color: #6ebf26; font-weight: bold } /* Keyword.Declaration */ +body[data-theme="dark"] .highlight .kn { color: #6ebf26; font-weight: bold } /* Keyword.Namespace */ +body[data-theme="dark"] .highlight .kp { color: #6ebf26 } /* Keyword.Pseudo */ +body[data-theme="dark"] .highlight .kr { color: #6ebf26; font-weight: bold } /* Keyword.Reserved */ +body[data-theme="dark"] .highlight .kt { color: #6ebf26; font-weight: bold } /* Keyword.Type */ +body[data-theme="dark"] .highlight .ld { color: #d0d0d0 } /* Literal.Date */ +body[data-theme="dark"] .highlight .m { color: #51b2fd } /* Literal.Number */ +body[data-theme="dark"] .highlight .s { color: #ed9d13 } /* Literal.String */ +body[data-theme="dark"] .highlight .na { color: #bbbbbb } /* Name.Attribute */ +body[data-theme="dark"] .highlight .nb { color: #2fbccd } /* Name.Builtin */ +body[data-theme="dark"] .highlight .nc { color: #71adff; text-decoration: underline } /* Name.Class */ +body[data-theme="dark"] .highlight .no { color: #40ffff } /* Name.Constant */ +body[data-theme="dark"] .highlight .nd { color: #ffa500 } /* Name.Decorator */ +body[data-theme="dark"] .highlight .ni { color: #d0d0d0 } /* Name.Entity */ +body[data-theme="dark"] .highlight .ne { color: #bbbbbb } /* Name.Exception */ +body[data-theme="dark"] .highlight .nf { color: #71adff } /* Name.Function */ +body[data-theme="dark"] .highlight .nl { color: #d0d0d0 } /* Name.Label */ +body[data-theme="dark"] .highlight .nn { color: #71adff; text-decoration: underline } /* Name.Namespace */ +body[data-theme="dark"] .highlight .nx { color: #d0d0d0 } /* Name.Other */ +body[data-theme="dark"] .highlight .py { color: #d0d0d0 } /* Name.Property */ +body[data-theme="dark"] .highlight .nt { color: #6ebf26; font-weight: bold } /* Name.Tag */ +body[data-theme="dark"] .highlight .nv { color: #40ffff } /* Name.Variable */ +body[data-theme="dark"] .highlight .ow { color: #6ebf26; font-weight: bold } /* Operator.Word */ +body[data-theme="dark"] .highlight .pm { color: #d0d0d0 } /* Punctuation.Marker */ +body[data-theme="dark"] .highlight .w { color: #666666 } /* Text.Whitespace */ +body[data-theme="dark"] .highlight .mb { color: #51b2fd } /* Literal.Number.Bin */ +body[data-theme="dark"] .highlight .mf { color: #51b2fd } /* Literal.Number.Float */ +body[data-theme="dark"] .highlight .mh { color: #51b2fd } /* Literal.Number.Hex */ +body[data-theme="dark"] .highlight .mi { color: #51b2fd } /* Literal.Number.Integer */ +body[data-theme="dark"] .highlight .mo { color: #51b2fd } /* Literal.Number.Oct */ +body[data-theme="dark"] .highlight .sa { color: #ed9d13 } /* Literal.String.Affix */ +body[data-theme="dark"] .highlight .sb { color: #ed9d13 } /* Literal.String.Backtick */ +body[data-theme="dark"] .highlight .sc { color: #ed9d13 } /* Literal.String.Char */ +body[data-theme="dark"] .highlight .dl { color: #ed9d13 } /* Literal.String.Delimiter */ +body[data-theme="dark"] .highlight .sd { color: #ed9d13 } /* Literal.String.Doc */ +body[data-theme="dark"] .highlight .s2 { color: #ed9d13 } /* Literal.String.Double */ +body[data-theme="dark"] .highlight .se { color: #ed9d13 } /* Literal.String.Escape */ +body[data-theme="dark"] .highlight .sh { color: #ed9d13 } /* Literal.String.Heredoc */ +body[data-theme="dark"] .highlight .si { color: #ed9d13 } /* Literal.String.Interpol */ +body[data-theme="dark"] .highlight .sx { color: #ffa500 } /* Literal.String.Other */ +body[data-theme="dark"] .highlight .sr { color: #ed9d13 } /* Literal.String.Regex */ +body[data-theme="dark"] .highlight .s1 { color: #ed9d13 } /* Literal.String.Single */ +body[data-theme="dark"] .highlight .ss { color: #ed9d13 } /* Literal.String.Symbol */ +body[data-theme="dark"] .highlight .bp { color: #2fbccd } /* Name.Builtin.Pseudo */ +body[data-theme="dark"] .highlight .fm { color: #71adff } /* Name.Function.Magic */ +body[data-theme="dark"] .highlight .vc { color: #40ffff } /* Name.Variable.Class */ +body[data-theme="dark"] .highlight .vg { color: #40ffff } /* Name.Variable.Global */ +body[data-theme="dark"] .highlight .vi { color: #40ffff } /* Name.Variable.Instance */ +body[data-theme="dark"] .highlight .vm { color: #40ffff } /* Name.Variable.Magic */ +body[data-theme="dark"] .highlight .il { color: #51b2fd } /* Literal.Number.Integer.Long */ +@media (prefers-color-scheme: dark) { +body:not([data-theme="light"]) .highlight pre { line-height: 125%; } +body:not([data-theme="light"]) .highlight td.linenos .normal { color: #aaaaaa; background-color: transparent; padding-left: 5px; padding-right: 5px; } +body:not([data-theme="light"]) .highlight span.linenos { color: #aaaaaa; background-color: transparent; padding-left: 5px; padding-right: 5px; } +body:not([data-theme="light"]) .highlight td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +body:not([data-theme="light"]) .highlight span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +body:not([data-theme="light"]) .highlight .hll { background-color: #404040 } +body:not([data-theme="light"]) .highlight { background: #202020; color: #d0d0d0 } +body:not([data-theme="light"]) .highlight .c { color: #ababab; font-style: italic } /* Comment */ +body:not([data-theme="light"]) .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ +body:not([data-theme="light"]) .highlight .esc { color: #d0d0d0 } /* Escape */ +body:not([data-theme="light"]) .highlight .g { color: #d0d0d0 } /* Generic */ +body:not([data-theme="light"]) .highlight .k { color: #6ebf26; font-weight: bold } /* Keyword */ +body:not([data-theme="light"]) .highlight .l { color: #d0d0d0 } /* Literal */ +body:not([data-theme="light"]) .highlight .n { color: #d0d0d0 } /* Name */ +body:not([data-theme="light"]) .highlight .o { color: #d0d0d0 } /* Operator */ +body:not([data-theme="light"]) .highlight .x { color: #d0d0d0 } /* Other */ +body:not([data-theme="light"]) .highlight .p { color: #d0d0d0 } /* Punctuation */ +body:not([data-theme="light"]) .highlight .ch { color: #ababab; font-style: italic } /* Comment.Hashbang */ +body:not([data-theme="light"]) .highlight .cm { color: #ababab; font-style: italic } /* Comment.Multiline */ +body:not([data-theme="light"]) .highlight .cp { color: #ff3a3a; font-weight: bold } /* Comment.Preproc */ +body:not([data-theme="light"]) .highlight .cpf { color: #ababab; font-style: italic } /* Comment.PreprocFile */ +body:not([data-theme="light"]) .highlight .c1 { color: #ababab; font-style: italic } /* Comment.Single */ +body:not([data-theme="light"]) .highlight .cs { color: #e50808; font-weight: bold; background-color: #520000 } /* Comment.Special */ +body:not([data-theme="light"]) .highlight .gd { color: #ff3a3a } /* Generic.Deleted */ +body:not([data-theme="light"]) .highlight .ge { color: #d0d0d0; font-style: italic } /* Generic.Emph */ +body:not([data-theme="light"]) .highlight .ges { color: #d0d0d0; font-weight: bold; font-style: italic } /* Generic.EmphStrong */ +body:not([data-theme="light"]) .highlight .gr { color: #ff3a3a } /* Generic.Error */ +body:not([data-theme="light"]) .highlight .gh { color: #ffffff; font-weight: bold } /* Generic.Heading */ +body:not([data-theme="light"]) .highlight .gi { color: #589819 } /* Generic.Inserted */ +body:not([data-theme="light"]) .highlight .go { color: #cccccc } /* Generic.Output */ +body:not([data-theme="light"]) .highlight .gp { color: #aaaaaa } /* Generic.Prompt */ +body:not([data-theme="light"]) .highlight .gs { color: #d0d0d0; font-weight: bold } /* Generic.Strong */ +body:not([data-theme="light"]) .highlight .gu { color: #ffffff; text-decoration: underline } /* Generic.Subheading */ +body:not([data-theme="light"]) .highlight .gt { color: #ff3a3a } /* Generic.Traceback */ +body:not([data-theme="light"]) .highlight .kc { color: #6ebf26; font-weight: bold } /* Keyword.Constant */ +body:not([data-theme="light"]) .highlight .kd { color: #6ebf26; font-weight: bold } /* Keyword.Declaration */ +body:not([data-theme="light"]) .highlight .kn { color: #6ebf26; font-weight: bold } /* Keyword.Namespace */ +body:not([data-theme="light"]) .highlight .kp { color: #6ebf26 } /* Keyword.Pseudo */ +body:not([data-theme="light"]) .highlight .kr { color: #6ebf26; font-weight: bold } /* Keyword.Reserved */ +body:not([data-theme="light"]) .highlight .kt { color: #6ebf26; font-weight: bold } /* Keyword.Type */ +body:not([data-theme="light"]) .highlight .ld { color: #d0d0d0 } /* Literal.Date */ +body:not([data-theme="light"]) .highlight .m { color: #51b2fd } /* Literal.Number */ +body:not([data-theme="light"]) .highlight .s { color: #ed9d13 } /* Literal.String */ +body:not([data-theme="light"]) .highlight .na { color: #bbbbbb } /* Name.Attribute */ +body:not([data-theme="light"]) .highlight .nb { color: #2fbccd } /* Name.Builtin */ +body:not([data-theme="light"]) .highlight .nc { color: #71adff; text-decoration: underline } /* Name.Class */ +body:not([data-theme="light"]) .highlight .no { color: #40ffff } /* Name.Constant */ +body:not([data-theme="light"]) .highlight .nd { color: #ffa500 } /* Name.Decorator */ +body:not([data-theme="light"]) .highlight .ni { color: #d0d0d0 } /* Name.Entity */ +body:not([data-theme="light"]) .highlight .ne { color: #bbbbbb } /* Name.Exception */ +body:not([data-theme="light"]) .highlight .nf { color: #71adff } /* Name.Function */ +body:not([data-theme="light"]) .highlight .nl { color: #d0d0d0 } /* Name.Label */ +body:not([data-theme="light"]) .highlight .nn { color: #71adff; text-decoration: underline } /* Name.Namespace */ +body:not([data-theme="light"]) .highlight .nx { color: #d0d0d0 } /* Name.Other */ +body:not([data-theme="light"]) .highlight .py { color: #d0d0d0 } /* Name.Property */ +body:not([data-theme="light"]) .highlight .nt { color: #6ebf26; font-weight: bold } /* Name.Tag */ +body:not([data-theme="light"]) .highlight .nv { color: #40ffff } /* Name.Variable */ +body:not([data-theme="light"]) .highlight .ow { color: #6ebf26; font-weight: bold } /* Operator.Word */ +body:not([data-theme="light"]) .highlight .pm { color: #d0d0d0 } /* Punctuation.Marker */ +body:not([data-theme="light"]) .highlight .w { color: #666666 } /* Text.Whitespace */ +body:not([data-theme="light"]) .highlight .mb { color: #51b2fd } /* Literal.Number.Bin */ +body:not([data-theme="light"]) .highlight .mf { color: #51b2fd } /* Literal.Number.Float */ +body:not([data-theme="light"]) .highlight .mh { color: #51b2fd } /* Literal.Number.Hex */ +body:not([data-theme="light"]) .highlight .mi { color: #51b2fd } /* Literal.Number.Integer */ +body:not([data-theme="light"]) .highlight .mo { color: #51b2fd } /* Literal.Number.Oct */ +body:not([data-theme="light"]) .highlight .sa { color: #ed9d13 } /* Literal.String.Affix */ +body:not([data-theme="light"]) .highlight .sb { color: #ed9d13 } /* Literal.String.Backtick */ +body:not([data-theme="light"]) .highlight .sc { color: #ed9d13 } /* Literal.String.Char */ +body:not([data-theme="light"]) .highlight .dl { color: #ed9d13 } /* Literal.String.Delimiter */ +body:not([data-theme="light"]) .highlight .sd { color: #ed9d13 } /* Literal.String.Doc */ +body:not([data-theme="light"]) .highlight .s2 { color: #ed9d13 } /* Literal.String.Double */ +body:not([data-theme="light"]) .highlight .se { color: #ed9d13 } /* Literal.String.Escape */ +body:not([data-theme="light"]) .highlight .sh { color: #ed9d13 } /* Literal.String.Heredoc */ +body:not([data-theme="light"]) .highlight .si { color: #ed9d13 } /* Literal.String.Interpol */ +body:not([data-theme="light"]) .highlight .sx { color: #ffa500 } /* Literal.String.Other */ +body:not([data-theme="light"]) .highlight .sr { color: #ed9d13 } /* Literal.String.Regex */ +body:not([data-theme="light"]) .highlight .s1 { color: #ed9d13 } /* Literal.String.Single */ +body:not([data-theme="light"]) .highlight .ss { color: #ed9d13 } /* Literal.String.Symbol */ +body:not([data-theme="light"]) .highlight .bp { color: #2fbccd } /* Name.Builtin.Pseudo */ +body:not([data-theme="light"]) .highlight .fm { color: #71adff } /* Name.Function.Magic */ +body:not([data-theme="light"]) .highlight .vc { color: #40ffff } /* Name.Variable.Class */ +body:not([data-theme="light"]) .highlight .vg { color: #40ffff } /* Name.Variable.Global */ +body:not([data-theme="light"]) .highlight .vi { color: #40ffff } /* Name.Variable.Instance */ +body:not([data-theme="light"]) .highlight .vm { color: #40ffff } /* Name.Variable.Magic */ +body:not([data-theme="light"]) .highlight .il { color: #51b2fd } /* Literal.Number.Integer.Long */ +} +} \ No newline at end of file diff --git a/main/_static/scripts/furo-extensions.js b/main/_static/scripts/furo-extensions.js new file mode 100644 index 00000000..e69de29b diff --git a/main/_static/scripts/furo.js b/main/_static/scripts/furo.js new file mode 100644 index 00000000..0abb2afa --- /dev/null +++ b/main/_static/scripts/furo.js @@ -0,0 +1,3 @@ +/*! For license information please see furo.js.LICENSE.txt */ +(()=>{var t={856:function(t,e,n){var o,r;r=void 0!==n.g?n.g:"undefined"!=typeof window?window:this,o=function(){return function(t){"use strict";var e={navClass:"active",contentClass:"active",nested:!1,nestedClass:"active",offset:0,reflow:!1,events:!0},n=function(t,e,n){if(n.settings.events){var o=new CustomEvent(t,{bubbles:!0,cancelable:!0,detail:n});e.dispatchEvent(o)}},o=function(t){var e=0;if(t.offsetParent)for(;t;)e+=t.offsetTop,t=t.offsetParent;return e>=0?e:0},r=function(t){t&&t.sort((function(t,e){return o(t.content)=Math.max(document.body.scrollHeight,document.documentElement.scrollHeight,document.body.offsetHeight,document.documentElement.offsetHeight,document.body.clientHeight,document.documentElement.clientHeight)},l=function(t,e){var n=t[t.length-1];if(function(t,e){return!(!s()||!c(t.content,e,!0))}(n,e))return n;for(var o=t.length-1;o>=0;o--)if(c(t[o].content,e))return t[o]},a=function(t,e){if(e.nested&&t.parentNode){var n=t.parentNode.closest("li");n&&(n.classList.remove(e.nestedClass),a(n,e))}},i=function(t,e){if(t){var o=t.nav.closest("li");o&&(o.classList.remove(e.navClass),t.content.classList.remove(e.contentClass),a(o,e),n("gumshoeDeactivate",o,{link:t.nav,content:t.content,settings:e}))}},u=function(t,e){if(e.nested){var n=t.parentNode.closest("li");n&&(n.classList.add(e.nestedClass),u(n,e))}};return function(o,c){var s,a,d,f,m,v={setup:function(){s=document.querySelectorAll(o),a=[],Array.prototype.forEach.call(s,(function(t){var e=document.getElementById(decodeURIComponent(t.hash.substr(1)));e&&a.push({nav:t,content:e})})),r(a)},detect:function(){var t=l(a,m);t?d&&t.content===d.content||(i(d,m),function(t,e){if(t){var o=t.nav.closest("li");o&&(o.classList.add(e.navClass),t.content.classList.add(e.contentClass),u(o,e),n("gumshoeActivate",o,{link:t.nav,content:t.content,settings:e}))}}(t,m),d=t):d&&(i(d,m),d=null)}},h=function(e){f&&t.cancelAnimationFrame(f),f=t.requestAnimationFrame(v.detect)},g=function(e){f&&t.cancelAnimationFrame(f),f=t.requestAnimationFrame((function(){r(a),v.detect()}))};return v.destroy=function(){d&&i(d,m),t.removeEventListener("scroll",h,!1),m.reflow&&t.removeEventListener("resize",g,!1),a=null,s=null,d=null,f=null,m=null},m=function(){var t={};return Array.prototype.forEach.call(arguments,(function(e){for(var n in e){if(!e.hasOwnProperty(n))return;t[n]=e[n]}})),t}(e,c||{}),v.setup(),v.detect(),t.addEventListener("scroll",h,!1),m.reflow&&t.addEventListener("resize",g,!1),v}}(r)}.apply(e,[]),void 0===o||(t.exports=o)}},e={};function n(o){var r=e[o];if(void 0!==r)return r.exports;var c=e[o]={exports:{}};return t[o].call(c.exports,c,c.exports,n),c.exports}n.n=t=>{var e=t&&t.__esModule?()=>t.default:()=>t;return n.d(e,{a:e}),e},n.d=(t,e)=>{for(var o in e)n.o(e,o)&&!n.o(t,o)&&Object.defineProperty(t,o,{enumerable:!0,get:e[o]})},n.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(t){if("object"==typeof window)return window}}(),n.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),(()=>{"use strict";var t=n(856),e=n.n(t),o=null,r=null,c=document.documentElement.scrollTop;const s=64;function l(){const t=localStorage.getItem("theme")||"auto";var e;"light"!==(e=window.matchMedia("(prefers-color-scheme: dark)").matches?"auto"===t?"light":"light"==t?"dark":"auto":"auto"===t?"dark":"dark"==t?"light":"auto")&&"dark"!==e&&"auto"!==e&&(console.error(`Got invalid theme mode: ${e}. Resetting to auto.`),e="auto"),document.body.dataset.theme=e,localStorage.setItem("theme",e),console.log(`Changed to ${e} mode.`)}function a(){!function(){const t=document.getElementsByClassName("theme-toggle");Array.from(t).forEach((t=>{t.addEventListener("click",l)}))}(),function(){let t=0,e=!1;window.addEventListener("scroll",(function(n){t=window.scrollY,e||(window.requestAnimationFrame((function(){var n;(function(t){const e=Math.floor(r.getBoundingClientRect().top);console.log(`headerTop: ${e}`),0==e&&t!=e?r.classList.add("scrolled"):r.classList.remove("scrolled")})(n=t),function(t){tc&&document.documentElement.classList.remove("show-back-to-top"),c=t}(n),function(t){null!==o&&(0==t?o.scrollTo(0,0):Math.ceil(t)>=Math.floor(document.documentElement.scrollHeight-window.innerHeight)?o.scrollTo(0,o.scrollHeight):document.querySelector(".scroll-current"))}(n),e=!1})),e=!0)})),window.scroll()}(),null!==o&&new(e())(".toc-tree a",{reflow:!0,recursive:!0,navClass:"scroll-current",offset:()=>{let t=parseFloat(getComputedStyle(document.documentElement).fontSize);return r.getBoundingClientRect().height+2.5*t+1}})}document.addEventListener("DOMContentLoaded",(function(){document.body.parentNode.classList.remove("no-js"),r=document.querySelector("header"),o=document.querySelector(".toc-scroll"),a()}))})()})(); +//# sourceMappingURL=furo.js.map \ No newline at end of file diff --git a/main/_static/scripts/furo.js.LICENSE.txt b/main/_static/scripts/furo.js.LICENSE.txt new file mode 100644 index 00000000..1632189c --- /dev/null +++ b/main/_static/scripts/furo.js.LICENSE.txt @@ -0,0 +1,7 @@ +/*! + * gumshoejs v5.1.2 (patched by @pradyunsg) + * A simple, framework-agnostic scrollspy script. + * (c) 2019 Chris Ferdinandi + * MIT License + * http://github.com/cferdinandi/gumshoe + */ diff --git a/main/_static/scripts/furo.js.map b/main/_static/scripts/furo.js.map new file mode 100644 index 00000000..80ea12b8 --- /dev/null +++ b/main/_static/scripts/furo.js.map @@ -0,0 +1 @@ +{"version":3,"file":"scripts/furo.js","mappings":";iCAAA,MAQWA,SAWS,IAAX,EAAAC,EACH,EAAAA,EACkB,oBAAXC,OACLA,OACAC,KAbO,EAAF,WACP,OAaJ,SAAUD,GACR,aAMA,IAAIE,EAAW,CAEbC,SAAU,SACVC,aAAc,SAGdC,QAAQ,EACRC,YAAa,SAGbC,OAAQ,EACRC,QAAQ,EAGRC,QAAQ,GA6BNC,EAAY,SAAUC,EAAMC,EAAMC,GAEpC,GAAKA,EAAOC,SAASL,OAArB,CAGA,IAAIM,EAAQ,IAAIC,YAAYL,EAAM,CAChCM,SAAS,EACTC,YAAY,EACZL,OAAQA,IAIVD,EAAKO,cAAcJ,EAVgB,CAWrC,EAOIK,EAAe,SAAUR,GAC3B,IAAIS,EAAW,EACf,GAAIT,EAAKU,aACP,KAAOV,GACLS,GAAYT,EAAKW,UACjBX,EAAOA,EAAKU,aAGhB,OAAOD,GAAY,EAAIA,EAAW,CACpC,EAMIG,EAAe,SAAUC,GACvBA,GACFA,EAASC,MAAK,SAAUC,EAAOC,GAG7B,OAFcR,EAAaO,EAAME,SACnBT,EAAaQ,EAAMC,UACF,EACxB,CACT,GAEJ,EAwCIC,EAAW,SAAUlB,EAAME,EAAUiB,GACvC,IAAIC,EAASpB,EAAKqB,wBACd1B,EAnCU,SAAUO,GAExB,MAA+B,mBAApBA,EAASP,OACX2B,WAAWpB,EAASP,UAItB2B,WAAWpB,EAASP,OAC7B,CA2Be4B,CAAUrB,GACvB,OAAIiB,EAEAK,SAASJ,EAAOD,OAAQ,KACvB/B,EAAOqC,aAAeC,SAASC,gBAAgBC,cAG7CJ,SAASJ,EAAOS,IAAK,KAAOlC,CACrC,EAMImC,EAAa,WACf,OACEC,KAAKC,KAAK5C,EAAOqC,YAAcrC,EAAO6C,cAnCjCF,KAAKG,IACVR,SAASS,KAAKC,aACdV,SAASC,gBAAgBS,aACzBV,SAASS,KAAKE,aACdX,SAASC,gBAAgBU,aACzBX,SAASS,KAAKP,aACdF,SAASC,gBAAgBC,aAkC7B,EAmBIU,EAAY,SAAUzB,EAAUX,GAClC,IAAIqC,EAAO1B,EAASA,EAAS2B,OAAS,GACtC,GAbgB,SAAUC,EAAMvC,GAChC,SAAI4B,MAAgBZ,EAASuB,EAAKxB,QAASf,GAAU,GAEvD,CAUMwC,CAAYH,EAAMrC,GAAW,OAAOqC,EACxC,IAAK,IAAII,EAAI9B,EAAS2B,OAAS,EAAGG,GAAK,EAAGA,IACxC,GAAIzB,EAASL,EAAS8B,GAAG1B,QAASf,GAAW,OAAOW,EAAS8B,EAEjE,EAOIC,EAAmB,SAAUC,EAAK3C,GAEpC,GAAKA,EAAST,QAAWoD,EAAIC,WAA7B,CAGA,IAAIC,EAAKF,EAAIC,WAAWE,QAAQ,MAC3BD,IAGLA,EAAGE,UAAUC,OAAOhD,EAASR,aAG7BkD,EAAiBG,EAAI7C,GAV0B,CAWjD,EAOIiD,EAAa,SAAUC,EAAOlD,GAEhC,GAAKkD,EAAL,CAGA,IAAIL,EAAKK,EAAMP,IAAIG,QAAQ,MACtBD,IAGLA,EAAGE,UAAUC,OAAOhD,EAASX,UAC7B6D,EAAMnC,QAAQgC,UAAUC,OAAOhD,EAASV,cAGxCoD,EAAiBG,EAAI7C,GAGrBJ,EAAU,oBAAqBiD,EAAI,CACjCM,KAAMD,EAAMP,IACZ5B,QAASmC,EAAMnC,QACff,SAAUA,IAjBM,CAmBpB,EAOIoD,EAAiB,SAAUT,EAAK3C,GAElC,GAAKA,EAAST,OAAd,CAGA,IAAIsD,EAAKF,EAAIC,WAAWE,QAAQ,MAC3BD,IAGLA,EAAGE,UAAUM,IAAIrD,EAASR,aAG1B4D,EAAeP,EAAI7C,GAVS,CAW9B,EA6LA,OA1JkB,SAAUsD,EAAUC,GAKpC,IACIC,EAAU7C,EAAU8C,EAASC,EAAS1D,EADtC2D,EAAa,CAUjBA,MAAmB,WAEjBH,EAAWhC,SAASoC,iBAAiBN,GAGrC3C,EAAW,GAGXkD,MAAMC,UAAUC,QAAQC,KAAKR,GAAU,SAAUjB,GAE/C,IAAIxB,EAAUS,SAASyC,eACrBC,mBAAmB3B,EAAK4B,KAAKC,OAAO,KAEjCrD,GAGLJ,EAAS0D,KAAK,CACZ1B,IAAKJ,EACLxB,QAASA,GAEb,IAGAL,EAAaC,EACf,EAKAgD,OAAoB,WAElB,IAAIW,EAASlC,EAAUzB,EAAUX,GAG5BsE,EASDb,GAAWa,EAAOvD,UAAY0C,EAAQ1C,UAG1CkC,EAAWQ,EAASzD,GAzFT,SAAUkD,EAAOlD,GAE9B,GAAKkD,EAAL,CAGA,IAAIL,EAAKK,EAAMP,IAAIG,QAAQ,MACtBD,IAGLA,EAAGE,UAAUM,IAAIrD,EAASX,UAC1B6D,EAAMnC,QAAQgC,UAAUM,IAAIrD,EAASV,cAGrC8D,EAAeP,EAAI7C,GAGnBJ,EAAU,kBAAmBiD,EAAI,CAC/BM,KAAMD,EAAMP,IACZ5B,QAASmC,EAAMnC,QACff,SAAUA,IAjBM,CAmBpB,CAqEIuE,CAASD,EAAQtE,GAGjByD,EAAUa,GAfJb,IACFR,EAAWQ,EAASzD,GACpByD,EAAU,KAchB,GAMIe,EAAgB,SAAUvE,GAExByD,GACFxE,EAAOuF,qBAAqBf,GAI9BA,EAAUxE,EAAOwF,sBAAsBf,EAAWgB,OACpD,EAMIC,EAAgB,SAAU3E,GAExByD,GACFxE,EAAOuF,qBAAqBf,GAI9BA,EAAUxE,EAAOwF,uBAAsB,WACrChE,EAAaC,GACbgD,EAAWgB,QACb,GACF,EAkDA,OA7CAhB,EAAWkB,QAAU,WAEfpB,GACFR,EAAWQ,EAASzD,GAItBd,EAAO4F,oBAAoB,SAAUN,GAAe,GAChDxE,EAASN,QACXR,EAAO4F,oBAAoB,SAAUF,GAAe,GAItDjE,EAAW,KACX6C,EAAW,KACXC,EAAU,KACVC,EAAU,KACV1D,EAAW,IACb,EAOEA,EA3XS,WACX,IAAI+E,EAAS,CAAC,EAOd,OANAlB,MAAMC,UAAUC,QAAQC,KAAKgB,WAAW,SAAUC,GAChD,IAAK,IAAIC,KAAOD,EAAK,CACnB,IAAKA,EAAIE,eAAeD,GAAM,OAC9BH,EAAOG,GAAOD,EAAIC,EACpB,CACF,IACOH,CACT,CAkXeK,CAAOhG,EAAUmE,GAAW,CAAC,GAGxCI,EAAW0B,QAGX1B,EAAWgB,SAGXzF,EAAOoG,iBAAiB,SAAUd,GAAe,GAC7CxE,EAASN,QACXR,EAAOoG,iBAAiB,SAAUV,GAAe,GAS9CjB,CACT,CAOF,CArcW4B,CAAQvG,EAChB,UAFM,SAEN,uBCXDwG,EAA2B,CAAC,EAGhC,SAASC,EAAoBC,GAE5B,IAAIC,EAAeH,EAAyBE,GAC5C,QAAqBE,IAAjBD,EACH,OAAOA,EAAaE,QAGrB,IAAIC,EAASN,EAAyBE,GAAY,CAGjDG,QAAS,CAAC,GAOX,OAHAE,EAAoBL,GAAU1B,KAAK8B,EAAOD,QAASC,EAAQA,EAAOD,QAASJ,GAGpEK,EAAOD,OACf,CCrBAJ,EAAoBO,EAAKF,IACxB,IAAIG,EAASH,GAAUA,EAAOI,WAC7B,IAAOJ,EAAiB,QACxB,IAAM,EAEP,OADAL,EAAoBU,EAAEF,EAAQ,CAAEG,EAAGH,IAC5BA,CAAM,ECLdR,EAAoBU,EAAI,CAACN,EAASQ,KACjC,IAAI,IAAInB,KAAOmB,EACXZ,EAAoBa,EAAED,EAAYnB,KAASO,EAAoBa,EAAET,EAASX,IAC5EqB,OAAOC,eAAeX,EAASX,EAAK,CAAEuB,YAAY,EAAMC,IAAKL,EAAWnB,IAE1E,ECNDO,EAAoBxG,EAAI,WACvB,GAA0B,iBAAf0H,WAAyB,OAAOA,WAC3C,IACC,OAAOxH,MAAQ,IAAIyH,SAAS,cAAb,EAChB,CAAE,MAAOC,GACR,GAAsB,iBAAX3H,OAAqB,OAAOA,MACxC,CACA,CAPuB,GCAxBuG,EAAoBa,EAAI,CAACrB,EAAK6B,IAAUP,OAAOzC,UAAUqB,eAAenB,KAAKiB,EAAK6B,4CCK9EC,EAAY,KACZC,EAAS,KACTC,EAAgBzF,SAASC,gBAAgByF,UAC7C,MAAMC,EAAmB,GA8EzB,SAASC,IACP,MAAMC,EAAeC,aAAaC,QAAQ,UAAY,OAZxD,IAAkBC,EACH,WADGA,EAaItI,OAAOuI,WAAW,gCAAgCC,QAI/C,SAAjBL,EACO,QACgB,SAAhBA,EACA,OAEA,OAIU,SAAjBA,EACO,OACgB,QAAhBA,EACA,QAEA,SA9BoB,SAATG,GAA4B,SAATA,IACzCG,QAAQC,MAAM,2BAA2BJ,yBACzCA,EAAO,QAGThG,SAASS,KAAK4F,QAAQC,MAAQN,EAC9BF,aAAaS,QAAQ,QAASP,GAC9BG,QAAQK,IAAI,cAAcR,UA0B5B,CAkDA,SAASnC,KART,WAEE,MAAM4C,EAAUzG,SAAS0G,uBAAuB,gBAChDrE,MAAMsE,KAAKF,GAASlE,SAASqE,IAC3BA,EAAI9C,iBAAiB,QAAS8B,EAAe,GAEjD,CAGEiB,GA9CF,WAEE,IAAIC,EAA6B,EAC7BC,GAAU,EAEdrJ,OAAOoG,iBAAiB,UAAU,SAAUuB,GAC1CyB,EAA6BpJ,OAAOsJ,QAE/BD,IACHrJ,OAAOwF,uBAAsB,WAzDnC,IAAuB+D,GAxDvB,SAAgCA,GAC9B,MAAMC,EAAY7G,KAAK8G,MAAM3B,EAAO7F,wBAAwBQ,KAE5DgG,QAAQK,IAAI,cAAcU,KACT,GAAbA,GAAkBD,GAAaC,EACjC1B,EAAOjE,UAAUM,IAAI,YAErB2D,EAAOjE,UAAUC,OAAO,WAE5B,EAgDE4F,CADqBH,EA0DDH,GAvGtB,SAAmCG,GAC7BA,EAAYtB,EACd3F,SAASC,gBAAgBsB,UAAUC,OAAO,oBAEtCyF,EAAYxB,EACdzF,SAASC,gBAAgBsB,UAAUM,IAAI,oBAC9BoF,EAAYxB,GACrBzF,SAASC,gBAAgBsB,UAAUC,OAAO,oBAG9CiE,EAAgBwB,CAClB,CAoCEI,CAA0BJ,GAlC5B,SAA6BA,GACT,OAAd1B,IAKa,GAAb0B,EACF1B,EAAU+B,SAAS,EAAG,GAGtBjH,KAAKC,KAAK2G,IACV5G,KAAK8G,MAAMnH,SAASC,gBAAgBS,aAAehD,OAAOqC,aAE1DwF,EAAU+B,SAAS,EAAG/B,EAAU7E,cAGhBV,SAASuH,cAAc,mBAc3C,CAKEC,CAAoBP,GAwDdF,GAAU,CACZ,IAEAA,GAAU,EAEd,IACArJ,OAAO+J,QACT,CA6BEC,GA1BkB,OAAdnC,GAKJ,IAAI,IAAJ,CAAY,cAAe,CACzBrH,QAAQ,EACRyJ,WAAW,EACX9J,SAAU,iBACVI,OAAQ,KACN,IAAI2J,EAAMhI,WAAWiI,iBAAiB7H,SAASC,iBAAiB6H,UAChE,OAAOtC,EAAO7F,wBAAwBoI,OAAS,IAAMH,EAAM,CAAC,GAiBlE,CAcA5H,SAAS8D,iBAAiB,oBAT1B,WACE9D,SAASS,KAAKW,WAAWG,UAAUC,OAAO,SAE1CgE,EAASxF,SAASuH,cAAc,UAChChC,EAAYvF,SAASuH,cAAc,eAEnC1D,GACF","sources":["webpack:///./src/furo/assets/scripts/gumshoe-patched.js","webpack:///webpack/bootstrap","webpack:///webpack/runtime/compat get default export","webpack:///webpack/runtime/define property getters","webpack:///webpack/runtime/global","webpack:///webpack/runtime/hasOwnProperty shorthand","webpack:///./src/furo/assets/scripts/furo.js"],"sourcesContent":["/*!\n * gumshoejs v5.1.2 (patched by @pradyunsg)\n * A simple, framework-agnostic scrollspy script.\n * (c) 2019 Chris Ferdinandi\n * MIT License\n * http://github.com/cferdinandi/gumshoe\n */\n\n(function (root, factory) {\n if (typeof define === \"function\" && define.amd) {\n define([], function () {\n return factory(root);\n });\n } else if (typeof exports === \"object\") {\n module.exports = factory(root);\n } else {\n root.Gumshoe = factory(root);\n }\n})(\n typeof global !== \"undefined\"\n ? global\n : typeof window !== \"undefined\"\n ? window\n : this,\n function (window) {\n \"use strict\";\n\n //\n // Defaults\n //\n\n var defaults = {\n // Active classes\n navClass: \"active\",\n contentClass: \"active\",\n\n // Nested navigation\n nested: false,\n nestedClass: \"active\",\n\n // Offset & reflow\n offset: 0,\n reflow: false,\n\n // Event support\n events: true,\n };\n\n //\n // Methods\n //\n\n /**\n * Merge two or more objects together.\n * @param {Object} objects The objects to merge together\n * @returns {Object} Merged values of defaults and options\n */\n var extend = function () {\n var merged = {};\n Array.prototype.forEach.call(arguments, function (obj) {\n for (var key in obj) {\n if (!obj.hasOwnProperty(key)) return;\n merged[key] = obj[key];\n }\n });\n return merged;\n };\n\n /**\n * Emit a custom event\n * @param {String} type The event type\n * @param {Node} elem The element to attach the event to\n * @param {Object} detail Any details to pass along with the event\n */\n var emitEvent = function (type, elem, detail) {\n // Make sure events are enabled\n if (!detail.settings.events) return;\n\n // Create a new event\n var event = new CustomEvent(type, {\n bubbles: true,\n cancelable: true,\n detail: detail,\n });\n\n // Dispatch the event\n elem.dispatchEvent(event);\n };\n\n /**\n * Get an element's distance from the top of the Document.\n * @param {Node} elem The element\n * @return {Number} Distance from the top in pixels\n */\n var getOffsetTop = function (elem) {\n var location = 0;\n if (elem.offsetParent) {\n while (elem) {\n location += elem.offsetTop;\n elem = elem.offsetParent;\n }\n }\n return location >= 0 ? location : 0;\n };\n\n /**\n * Sort content from first to last in the DOM\n * @param {Array} contents The content areas\n */\n var sortContents = function (contents) {\n if (contents) {\n contents.sort(function (item1, item2) {\n var offset1 = getOffsetTop(item1.content);\n var offset2 = getOffsetTop(item2.content);\n if (offset1 < offset2) return -1;\n return 1;\n });\n }\n };\n\n /**\n * Get the offset to use for calculating position\n * @param {Object} settings The settings for this instantiation\n * @return {Float} The number of pixels to offset the calculations\n */\n var getOffset = function (settings) {\n // if the offset is a function run it\n if (typeof settings.offset === \"function\") {\n return parseFloat(settings.offset());\n }\n\n // Otherwise, return it as-is\n return parseFloat(settings.offset);\n };\n\n /**\n * Get the document element's height\n * @private\n * @returns {Number}\n */\n var getDocumentHeight = function () {\n return Math.max(\n document.body.scrollHeight,\n document.documentElement.scrollHeight,\n document.body.offsetHeight,\n document.documentElement.offsetHeight,\n document.body.clientHeight,\n document.documentElement.clientHeight,\n );\n };\n\n /**\n * Determine if an element is in view\n * @param {Node} elem The element\n * @param {Object} settings The settings for this instantiation\n * @param {Boolean} bottom If true, check if element is above bottom of viewport instead\n * @return {Boolean} Returns true if element is in the viewport\n */\n var isInView = function (elem, settings, bottom) {\n var bounds = elem.getBoundingClientRect();\n var offset = getOffset(settings);\n if (bottom) {\n return (\n parseInt(bounds.bottom, 10) <\n (window.innerHeight || document.documentElement.clientHeight)\n );\n }\n return parseInt(bounds.top, 10) <= offset;\n };\n\n /**\n * Check if at the bottom of the viewport\n * @return {Boolean} If true, page is at the bottom of the viewport\n */\n var isAtBottom = function () {\n if (\n Math.ceil(window.innerHeight + window.pageYOffset) >=\n getDocumentHeight()\n )\n return true;\n return false;\n };\n\n /**\n * Check if the last item should be used (even if not at the top of the page)\n * @param {Object} item The last item\n * @param {Object} settings The settings for this instantiation\n * @return {Boolean} If true, use the last item\n */\n var useLastItem = function (item, settings) {\n if (isAtBottom() && isInView(item.content, settings, true)) return true;\n return false;\n };\n\n /**\n * Get the active content\n * @param {Array} contents The content areas\n * @param {Object} settings The settings for this instantiation\n * @return {Object} The content area and matching navigation link\n */\n var getActive = function (contents, settings) {\n var last = contents[contents.length - 1];\n if (useLastItem(last, settings)) return last;\n for (var i = contents.length - 1; i >= 0; i--) {\n if (isInView(contents[i].content, settings)) return contents[i];\n }\n };\n\n /**\n * Deactivate parent navs in a nested navigation\n * @param {Node} nav The starting navigation element\n * @param {Object} settings The settings for this instantiation\n */\n var deactivateNested = function (nav, settings) {\n // If nesting isn't activated, bail\n if (!settings.nested || !nav.parentNode) return;\n\n // Get the parent navigation\n var li = nav.parentNode.closest(\"li\");\n if (!li) return;\n\n // Remove the active class\n li.classList.remove(settings.nestedClass);\n\n // Apply recursively to any parent navigation elements\n deactivateNested(li, settings);\n };\n\n /**\n * Deactivate a nav and content area\n * @param {Object} items The nav item and content to deactivate\n * @param {Object} settings The settings for this instantiation\n */\n var deactivate = function (items, settings) {\n // Make sure there are items to deactivate\n if (!items) return;\n\n // Get the parent list item\n var li = items.nav.closest(\"li\");\n if (!li) return;\n\n // Remove the active class from the nav and content\n li.classList.remove(settings.navClass);\n items.content.classList.remove(settings.contentClass);\n\n // Deactivate any parent navs in a nested navigation\n deactivateNested(li, settings);\n\n // Emit a custom event\n emitEvent(\"gumshoeDeactivate\", li, {\n link: items.nav,\n content: items.content,\n settings: settings,\n });\n };\n\n /**\n * Activate parent navs in a nested navigation\n * @param {Node} nav The starting navigation element\n * @param {Object} settings The settings for this instantiation\n */\n var activateNested = function (nav, settings) {\n // If nesting isn't activated, bail\n if (!settings.nested) return;\n\n // Get the parent navigation\n var li = nav.parentNode.closest(\"li\");\n if (!li) return;\n\n // Add the active class\n li.classList.add(settings.nestedClass);\n\n // Apply recursively to any parent navigation elements\n activateNested(li, settings);\n };\n\n /**\n * Activate a nav and content area\n * @param {Object} items The nav item and content to activate\n * @param {Object} settings The settings for this instantiation\n */\n var activate = function (items, settings) {\n // Make sure there are items to activate\n if (!items) return;\n\n // Get the parent list item\n var li = items.nav.closest(\"li\");\n if (!li) return;\n\n // Add the active class to the nav and content\n li.classList.add(settings.navClass);\n items.content.classList.add(settings.contentClass);\n\n // Activate any parent navs in a nested navigation\n activateNested(li, settings);\n\n // Emit a custom event\n emitEvent(\"gumshoeActivate\", li, {\n link: items.nav,\n content: items.content,\n settings: settings,\n });\n };\n\n /**\n * Create the Constructor object\n * @param {String} selector The selector to use for navigation items\n * @param {Object} options User options and settings\n */\n var Constructor = function (selector, options) {\n //\n // Variables\n //\n\n var publicAPIs = {};\n var navItems, contents, current, timeout, settings;\n\n //\n // Methods\n //\n\n /**\n * Set variables from DOM elements\n */\n publicAPIs.setup = function () {\n // Get all nav items\n navItems = document.querySelectorAll(selector);\n\n // Create contents array\n contents = [];\n\n // Loop through each item, get it's matching content, and push to the array\n Array.prototype.forEach.call(navItems, function (item) {\n // Get the content for the nav item\n var content = document.getElementById(\n decodeURIComponent(item.hash.substr(1)),\n );\n if (!content) return;\n\n // Push to the contents array\n contents.push({\n nav: item,\n content: content,\n });\n });\n\n // Sort contents by the order they appear in the DOM\n sortContents(contents);\n };\n\n /**\n * Detect which content is currently active\n */\n publicAPIs.detect = function () {\n // Get the active content\n var active = getActive(contents, settings);\n\n // if there's no active content, deactivate and bail\n if (!active) {\n if (current) {\n deactivate(current, settings);\n current = null;\n }\n return;\n }\n\n // If the active content is the one currently active, do nothing\n if (current && active.content === current.content) return;\n\n // Deactivate the current content and activate the new content\n deactivate(current, settings);\n activate(active, settings);\n\n // Update the currently active content\n current = active;\n };\n\n /**\n * Detect the active content on scroll\n * Debounced for performance\n */\n var scrollHandler = function (event) {\n // If there's a timer, cancel it\n if (timeout) {\n window.cancelAnimationFrame(timeout);\n }\n\n // Setup debounce callback\n timeout = window.requestAnimationFrame(publicAPIs.detect);\n };\n\n /**\n * Update content sorting on resize\n * Debounced for performance\n */\n var resizeHandler = function (event) {\n // If there's a timer, cancel it\n if (timeout) {\n window.cancelAnimationFrame(timeout);\n }\n\n // Setup debounce callback\n timeout = window.requestAnimationFrame(function () {\n sortContents(contents);\n publicAPIs.detect();\n });\n };\n\n /**\n * Destroy the current instantiation\n */\n publicAPIs.destroy = function () {\n // Undo DOM changes\n if (current) {\n deactivate(current, settings);\n }\n\n // Remove event listeners\n window.removeEventListener(\"scroll\", scrollHandler, false);\n if (settings.reflow) {\n window.removeEventListener(\"resize\", resizeHandler, false);\n }\n\n // Reset variables\n contents = null;\n navItems = null;\n current = null;\n timeout = null;\n settings = null;\n };\n\n /**\n * Initialize the current instantiation\n */\n var init = function () {\n // Merge user options into defaults\n settings = extend(defaults, options || {});\n\n // Setup variables based on the current DOM\n publicAPIs.setup();\n\n // Find the currently active content\n publicAPIs.detect();\n\n // Setup event listeners\n window.addEventListener(\"scroll\", scrollHandler, false);\n if (settings.reflow) {\n window.addEventListener(\"resize\", resizeHandler, false);\n }\n };\n\n //\n // Initialize and return the public APIs\n //\n\n init();\n return publicAPIs;\n };\n\n //\n // Return the Constructor\n //\n\n return Constructor;\n },\n);\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","import Gumshoe from \"./gumshoe-patched.js\";\n\n////////////////////////////////////////////////////////////////////////////////\n// Scroll Handling\n////////////////////////////////////////////////////////////////////////////////\nvar tocScroll = null;\nvar header = null;\nvar lastScrollTop = document.documentElement.scrollTop;\nconst GO_TO_TOP_OFFSET = 64;\n\nfunction scrollHandlerForHeader(positionY) {\n const headerTop = Math.floor(header.getBoundingClientRect().top);\n\n console.log(`headerTop: ${headerTop}`);\n if (headerTop == 0 && positionY != headerTop) {\n header.classList.add(\"scrolled\");\n } else {\n header.classList.remove(\"scrolled\");\n }\n}\n\nfunction scrollHandlerForBackToTop(positionY) {\n if (positionY < GO_TO_TOP_OFFSET) {\n document.documentElement.classList.remove(\"show-back-to-top\");\n } else {\n if (positionY < lastScrollTop) {\n document.documentElement.classList.add(\"show-back-to-top\");\n } else if (positionY > lastScrollTop) {\n document.documentElement.classList.remove(\"show-back-to-top\");\n }\n }\n lastScrollTop = positionY;\n}\n\nfunction scrollHandlerForTOC(positionY) {\n if (tocScroll === null) {\n return;\n }\n\n // top of page.\n if (positionY == 0) {\n tocScroll.scrollTo(0, 0);\n } else if (\n // bottom of page.\n Math.ceil(positionY) >=\n Math.floor(document.documentElement.scrollHeight - window.innerHeight)\n ) {\n tocScroll.scrollTo(0, tocScroll.scrollHeight);\n } else {\n // somewhere in the middle.\n const current = document.querySelector(\".scroll-current\");\n if (current == null) {\n return;\n }\n\n // https://github.com/pypa/pip/issues/9159 This breaks scroll behaviours.\n // // scroll the currently \"active\" heading in toc, into view.\n // const rect = current.getBoundingClientRect();\n // if (0 > rect.top) {\n // current.scrollIntoView(true); // the argument is \"alignTop\"\n // } else if (rect.bottom > window.innerHeight) {\n // current.scrollIntoView(false);\n // }\n }\n}\n\nfunction scrollHandler(positionY) {\n scrollHandlerForHeader(positionY);\n scrollHandlerForBackToTop(positionY);\n scrollHandlerForTOC(positionY);\n}\n\n////////////////////////////////////////////////////////////////////////////////\n// Theme Toggle\n////////////////////////////////////////////////////////////////////////////////\nfunction setTheme(mode) {\n if (mode !== \"light\" && mode !== \"dark\" && mode !== \"auto\") {\n console.error(`Got invalid theme mode: ${mode}. Resetting to auto.`);\n mode = \"auto\";\n }\n\n document.body.dataset.theme = mode;\n localStorage.setItem(\"theme\", mode);\n console.log(`Changed to ${mode} mode.`);\n}\n\nfunction cycleThemeOnce() {\n const currentTheme = localStorage.getItem(\"theme\") || \"auto\";\n const prefersDark = window.matchMedia(\"(prefers-color-scheme: dark)\").matches;\n\n if (prefersDark) {\n // Auto (dark) -> Light -> Dark\n if (currentTheme === \"auto\") {\n setTheme(\"light\");\n } else if (currentTheme == \"light\") {\n setTheme(\"dark\");\n } else {\n setTheme(\"auto\");\n }\n } else {\n // Auto (light) -> Dark -> Light\n if (currentTheme === \"auto\") {\n setTheme(\"dark\");\n } else if (currentTheme == \"dark\") {\n setTheme(\"light\");\n } else {\n setTheme(\"auto\");\n }\n }\n}\n\n////////////////////////////////////////////////////////////////////////////////\n// Setup\n////////////////////////////////////////////////////////////////////////////////\nfunction setupScrollHandler() {\n // Taken from https://developer.mozilla.org/en-US/docs/Web/API/Document/scroll_event\n let last_known_scroll_position = 0;\n let ticking = false;\n\n window.addEventListener(\"scroll\", function (e) {\n last_known_scroll_position = window.scrollY;\n\n if (!ticking) {\n window.requestAnimationFrame(function () {\n scrollHandler(last_known_scroll_position);\n ticking = false;\n });\n\n ticking = true;\n }\n });\n window.scroll();\n}\n\nfunction setupScrollSpy() {\n if (tocScroll === null) {\n return;\n }\n\n // Scrollspy -- highlight table on contents, based on scroll\n new Gumshoe(\".toc-tree a\", {\n reflow: true,\n recursive: true,\n navClass: \"scroll-current\",\n offset: () => {\n let rem = parseFloat(getComputedStyle(document.documentElement).fontSize);\n return header.getBoundingClientRect().height + 2.5 * rem + 1;\n },\n });\n}\n\nfunction setupTheme() {\n // Attach event handlers for toggling themes\n const buttons = document.getElementsByClassName(\"theme-toggle\");\n Array.from(buttons).forEach((btn) => {\n btn.addEventListener(\"click\", cycleThemeOnce);\n });\n}\n\nfunction setup() {\n setupTheme();\n setupScrollHandler();\n setupScrollSpy();\n}\n\n////////////////////////////////////////////////////////////////////////////////\n// Main entrypoint\n////////////////////////////////////////////////////////////////////////////////\nfunction main() {\n document.body.parentNode.classList.remove(\"no-js\");\n\n header = document.querySelector(\"header\");\n tocScroll = document.querySelector(\".toc-scroll\");\n\n setup();\n}\n\ndocument.addEventListener(\"DOMContentLoaded\", main);\n"],"names":["root","g","window","this","defaults","navClass","contentClass","nested","nestedClass","offset","reflow","events","emitEvent","type","elem","detail","settings","event","CustomEvent","bubbles","cancelable","dispatchEvent","getOffsetTop","location","offsetParent","offsetTop","sortContents","contents","sort","item1","item2","content","isInView","bottom","bounds","getBoundingClientRect","parseFloat","getOffset","parseInt","innerHeight","document","documentElement","clientHeight","top","isAtBottom","Math","ceil","pageYOffset","max","body","scrollHeight","offsetHeight","getActive","last","length","item","useLastItem","i","deactivateNested","nav","parentNode","li","closest","classList","remove","deactivate","items","link","activateNested","add","selector","options","navItems","current","timeout","publicAPIs","querySelectorAll","Array","prototype","forEach","call","getElementById","decodeURIComponent","hash","substr","push","active","activate","scrollHandler","cancelAnimationFrame","requestAnimationFrame","detect","resizeHandler","destroy","removeEventListener","merged","arguments","obj","key","hasOwnProperty","extend","setup","addEventListener","factory","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","exports","module","__webpack_modules__","n","getter","__esModule","d","a","definition","o","Object","defineProperty","enumerable","get","globalThis","Function","e","prop","tocScroll","header","lastScrollTop","scrollTop","GO_TO_TOP_OFFSET","cycleThemeOnce","currentTheme","localStorage","getItem","mode","matchMedia","matches","console","error","dataset","theme","setItem","log","buttons","getElementsByClassName","from","btn","setupTheme","last_known_scroll_position","ticking","scrollY","positionY","headerTop","floor","scrollHandlerForHeader","scrollHandlerForBackToTop","scrollTo","querySelector","scrollHandlerForTOC","scroll","setupScrollHandler","recursive","rem","getComputedStyle","fontSize","height"],"sourceRoot":""} \ No newline at end of file diff --git a/main/_static/searchtools.js b/main/_static/searchtools.js new file mode 100644 index 00000000..b08d58c9 --- /dev/null +++ b/main/_static/searchtools.js @@ -0,0 +1,620 @@ +/* + * searchtools.js + * ~~~~~~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for the full-text search. + * + * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ +"use strict"; + +/** + * Simple result scoring code. + */ +if (typeof Scorer === "undefined") { + var Scorer = { + // Implement the following function to further tweak the score for each result + // The function takes a result array [docname, title, anchor, descr, score, filename] + // and returns the new score. + /* + score: result => { + const [docname, title, anchor, descr, score, filename] = result + return score + }, + */ + + // query matches the full name of an object + objNameMatch: 11, + // or matches in the last dotted part of the object name + objPartialMatch: 6, + // Additive scores depending on the priority of the object + objPrio: { + 0: 15, // used to be importantResults + 1: 5, // used to be objectResults + 2: -5, // used to be unimportantResults + }, + // Used when the priority is not in the mapping. + objPrioDefault: 0, + + // query found in title + title: 15, + partialTitle: 7, + // query found in terms + term: 5, + partialTerm: 2, + }; +} + +const _removeChildren = (element) => { + while (element && element.lastChild) element.removeChild(element.lastChild); +}; + +/** + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping + */ +const _escapeRegExp = (string) => + string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string + +const _displayItem = (item, searchTerms, highlightTerms) => { + const docBuilder = DOCUMENTATION_OPTIONS.BUILDER; + const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX; + const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX; + const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY; + const contentRoot = document.documentElement.dataset.content_root; + + const [docName, title, anchor, descr, score, _filename] = item; + + let listItem = document.createElement("li"); + let requestUrl; + let linkUrl; + if (docBuilder === "dirhtml") { + // dirhtml builder + let dirname = docName + "/"; + if (dirname.match(/\/index\/$/)) + dirname = dirname.substring(0, dirname.length - 6); + else if (dirname === "index/") dirname = ""; + requestUrl = contentRoot + dirname; + linkUrl = requestUrl; + } else { + // normal html builders + requestUrl = contentRoot + docName + docFileSuffix; + linkUrl = docName + docLinkSuffix; + } + let linkEl = listItem.appendChild(document.createElement("a")); + linkEl.href = linkUrl + anchor; + linkEl.dataset.score = score; + linkEl.innerHTML = title; + if (descr) { + listItem.appendChild(document.createElement("span")).innerHTML = + " (" + descr + ")"; + // highlight search terms in the description + if (SPHINX_HIGHLIGHT_ENABLED) // set in sphinx_highlight.js + highlightTerms.forEach((term) => _highlightText(listItem, term, "highlighted")); + } + else if (showSearchSummary) + fetch(requestUrl) + .then((responseData) => responseData.text()) + .then((data) => { + if (data) + listItem.appendChild( + Search.makeSearchSummary(data, searchTerms, anchor) + ); + // highlight search terms in the summary + if (SPHINX_HIGHLIGHT_ENABLED) // set in sphinx_highlight.js + highlightTerms.forEach((term) => _highlightText(listItem, term, "highlighted")); + }); + Search.output.appendChild(listItem); +}; +const _finishSearch = (resultCount) => { + Search.stopPulse(); + Search.title.innerText = _("Search Results"); + if (!resultCount) + Search.status.innerText = Documentation.gettext( + "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories." + ); + else + Search.status.innerText = _( + "Search finished, found ${resultCount} page(s) matching the search query." + ).replace('${resultCount}', resultCount); +}; +const _displayNextItem = ( + results, + resultCount, + searchTerms, + highlightTerms, +) => { + // results left, load the summary and display it + // this is intended to be dynamic (don't sub resultsCount) + if (results.length) { + _displayItem(results.pop(), searchTerms, highlightTerms); + setTimeout( + () => _displayNextItem(results, resultCount, searchTerms, highlightTerms), + 5 + ); + } + // search finished, update title and status message + else _finishSearch(resultCount); +}; +// Helper function used by query() to order search results. +// Each input is an array of [docname, title, anchor, descr, score, filename]. +// Order the results by score (in opposite order of appearance, since the +// `_displayNextItem` function uses pop() to retrieve items) and then alphabetically. +const _orderResultsByScoreThenName = (a, b) => { + const leftScore = a[4]; + const rightScore = b[4]; + if (leftScore === rightScore) { + // same score: sort alphabetically + const leftTitle = a[1].toLowerCase(); + const rightTitle = b[1].toLowerCase(); + if (leftTitle === rightTitle) return 0; + return leftTitle > rightTitle ? -1 : 1; // inverted is intentional + } + return leftScore > rightScore ? 1 : -1; +}; + +/** + * Default splitQuery function. Can be overridden in ``sphinx.search`` with a + * custom function per language. + * + * The regular expression works by splitting the string on consecutive characters + * that are not Unicode letters, numbers, underscores, or emoji characters. + * This is the same as ``\W+`` in Python, preserving the surrogate pair area. + */ +if (typeof splitQuery === "undefined") { + var splitQuery = (query) => query + .split(/[^\p{Letter}\p{Number}_\p{Emoji_Presentation}]+/gu) + .filter(term => term) // remove remaining empty strings +} + +/** + * Search Module + */ +const Search = { + _index: null, + _queued_query: null, + _pulse_status: -1, + + htmlToText: (htmlString, anchor) => { + const htmlElement = new DOMParser().parseFromString(htmlString, 'text/html'); + for (const removalQuery of [".headerlink", "script", "style"]) { + htmlElement.querySelectorAll(removalQuery).forEach((el) => { el.remove() }); + } + if (anchor) { + const anchorContent = htmlElement.querySelector(`[role="main"] ${anchor}`); + if (anchorContent) return anchorContent.textContent; + + console.warn( + `Anchored content block not found. Sphinx search tries to obtain it via DOM query '[role=main] ${anchor}'. Check your theme or template.` + ); + } + + // if anchor not specified or not found, fall back to main content + const docContent = htmlElement.querySelector('[role="main"]'); + if (docContent) return docContent.textContent; + + console.warn( + "Content block not found. Sphinx search tries to obtain it via DOM query '[role=main]'. Check your theme or template." + ); + return ""; + }, + + init: () => { + const query = new URLSearchParams(window.location.search).get("q"); + document + .querySelectorAll('input[name="q"]') + .forEach((el) => (el.value = query)); + if (query) Search.performSearch(query); + }, + + loadIndex: (url) => + (document.body.appendChild(document.createElement("script")).src = url), + + setIndex: (index) => { + Search._index = index; + if (Search._queued_query !== null) { + const query = Search._queued_query; + Search._queued_query = null; + Search.query(query); + } + }, + + hasIndex: () => Search._index !== null, + + deferQuery: (query) => (Search._queued_query = query), + + stopPulse: () => (Search._pulse_status = -1), + + startPulse: () => { + if (Search._pulse_status >= 0) return; + + const pulse = () => { + Search._pulse_status = (Search._pulse_status + 1) % 4; + Search.dots.innerText = ".".repeat(Search._pulse_status); + if (Search._pulse_status >= 0) window.setTimeout(pulse, 500); + }; + pulse(); + }, + + /** + * perform a search for something (or wait until index is loaded) + */ + performSearch: (query) => { + // create the required interface elements + const searchText = document.createElement("h2"); + searchText.textContent = _("Searching"); + const searchSummary = document.createElement("p"); + searchSummary.classList.add("search-summary"); + searchSummary.innerText = ""; + const searchList = document.createElement("ul"); + searchList.classList.add("search"); + + const out = document.getElementById("search-results"); + Search.title = out.appendChild(searchText); + Search.dots = Search.title.appendChild(document.createElement("span")); + Search.status = out.appendChild(searchSummary); + Search.output = out.appendChild(searchList); + + const searchProgress = document.getElementById("search-progress"); + // Some themes don't use the search progress node + if (searchProgress) { + searchProgress.innerText = _("Preparing search..."); + } + Search.startPulse(); + + // index already loaded, the browser was quick! + if (Search.hasIndex()) Search.query(query); + else Search.deferQuery(query); + }, + + _parseQuery: (query) => { + // stem the search terms and add them to the correct list + const stemmer = new Stemmer(); + const searchTerms = new Set(); + const excludedTerms = new Set(); + const highlightTerms = new Set(); + const objectTerms = new Set(splitQuery(query.toLowerCase().trim())); + splitQuery(query.trim()).forEach((queryTerm) => { + const queryTermLower = queryTerm.toLowerCase(); + + // maybe skip this "word" + // stopwords array is from language_data.js + if ( + stopwords.indexOf(queryTermLower) !== -1 || + queryTerm.match(/^\d+$/) + ) + return; + + // stem the word + let word = stemmer.stemWord(queryTermLower); + // select the correct list + if (word[0] === "-") excludedTerms.add(word.substr(1)); + else { + searchTerms.add(word); + highlightTerms.add(queryTermLower); + } + }); + + if (SPHINX_HIGHLIGHT_ENABLED) { // set in sphinx_highlight.js + localStorage.setItem("sphinx_highlight_terms", [...highlightTerms].join(" ")) + } + + // console.debug("SEARCH: searching for:"); + // console.info("required: ", [...searchTerms]); + // console.info("excluded: ", [...excludedTerms]); + + return [query, searchTerms, excludedTerms, highlightTerms, objectTerms]; + }, + + /** + * execute search (requires search index to be loaded) + */ + _performSearch: (query, searchTerms, excludedTerms, highlightTerms, objectTerms) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + const allTitles = Search._index.alltitles; + const indexEntries = Search._index.indexentries; + + // Collect multiple result groups to be sorted separately and then ordered. + // Each is an array of [docname, title, anchor, descr, score, filename]. + const normalResults = []; + const nonMainIndexResults = []; + + _removeChildren(document.getElementById("search-progress")); + + const queryLower = query.toLowerCase().trim(); + for (const [title, foundTitles] of Object.entries(allTitles)) { + if (title.toLowerCase().trim().includes(queryLower) && (queryLower.length >= title.length/2)) { + for (const [file, id] of foundTitles) { + const score = Math.round(Scorer.title * queryLower.length / title.length); + const boost = titles[file] === title ? 1 : 0; // add a boost for document titles + normalResults.push([ + docNames[file], + titles[file] !== title ? `${titles[file]} > ${title}` : title, + id !== null ? "#" + id : "", + null, + score + boost, + filenames[file], + ]); + } + } + } + + // search for explicit entries in index directives + for (const [entry, foundEntries] of Object.entries(indexEntries)) { + if (entry.includes(queryLower) && (queryLower.length >= entry.length/2)) { + for (const [file, id, isMain] of foundEntries) { + const score = Math.round(100 * queryLower.length / entry.length); + const result = [ + docNames[file], + titles[file], + id ? "#" + id : "", + null, + score, + filenames[file], + ]; + if (isMain) { + normalResults.push(result); + } else { + nonMainIndexResults.push(result); + } + } + } + } + + // lookup as object + objectTerms.forEach((term) => + normalResults.push(...Search.performObjectSearch(term, objectTerms)) + ); + + // lookup as search terms in fulltext + normalResults.push(...Search.performTermsSearch(searchTerms, excludedTerms)); + + // let the scorer override scores with a custom scoring function + if (Scorer.score) { + normalResults.forEach((item) => (item[4] = Scorer.score(item))); + nonMainIndexResults.forEach((item) => (item[4] = Scorer.score(item))); + } + + // Sort each group of results by score and then alphabetically by name. + normalResults.sort(_orderResultsByScoreThenName); + nonMainIndexResults.sort(_orderResultsByScoreThenName); + + // Combine the result groups in (reverse) order. + // Non-main index entries are typically arbitrary cross-references, + // so display them after other results. + let results = [...nonMainIndexResults, ...normalResults]; + + // remove duplicate search results + // note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept + let seen = new Set(); + results = results.reverse().reduce((acc, result) => { + let resultStr = result.slice(0, 4).concat([result[5]]).map(v => String(v)).join(','); + if (!seen.has(resultStr)) { + acc.push(result); + seen.add(resultStr); + } + return acc; + }, []); + + return results.reverse(); + }, + + query: (query) => { + const [searchQuery, searchTerms, excludedTerms, highlightTerms, objectTerms] = Search._parseQuery(query); + const results = Search._performSearch(searchQuery, searchTerms, excludedTerms, highlightTerms, objectTerms); + + // for debugging + //Search.lastresults = results.slice(); // a copy + // console.info("search results:", Search.lastresults); + + // print the results + _displayNextItem(results, results.length, searchTerms, highlightTerms); + }, + + /** + * search for object names + */ + performObjectSearch: (object, objectTerms) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const objects = Search._index.objects; + const objNames = Search._index.objnames; + const titles = Search._index.titles; + + const results = []; + + const objectSearchCallback = (prefix, match) => { + const name = match[4] + const fullname = (prefix ? prefix + "." : "") + name; + const fullnameLower = fullname.toLowerCase(); + if (fullnameLower.indexOf(object) < 0) return; + + let score = 0; + const parts = fullnameLower.split("."); + + // check for different match types: exact matches of full name or + // "last name" (i.e. last dotted part) + if (fullnameLower === object || parts.slice(-1)[0] === object) + score += Scorer.objNameMatch; + else if (parts.slice(-1)[0].indexOf(object) > -1) + score += Scorer.objPartialMatch; // matches in last name + + const objName = objNames[match[1]][2]; + const title = titles[match[0]]; + + // If more than one term searched for, we require other words to be + // found in the name/title/description + const otherTerms = new Set(objectTerms); + otherTerms.delete(object); + if (otherTerms.size > 0) { + const haystack = `${prefix} ${name} ${objName} ${title}`.toLowerCase(); + if ( + [...otherTerms].some((otherTerm) => haystack.indexOf(otherTerm) < 0) + ) + return; + } + + let anchor = match[3]; + if (anchor === "") anchor = fullname; + else if (anchor === "-") anchor = objNames[match[1]][1] + "-" + fullname; + + const descr = objName + _(", in ") + title; + + // add custom score for some objects according to scorer + if (Scorer.objPrio.hasOwnProperty(match[2])) + score += Scorer.objPrio[match[2]]; + else score += Scorer.objPrioDefault; + + results.push([ + docNames[match[0]], + fullname, + "#" + anchor, + descr, + score, + filenames[match[0]], + ]); + }; + Object.keys(objects).forEach((prefix) => + objects[prefix].forEach((array) => + objectSearchCallback(prefix, array) + ) + ); + return results; + }, + + /** + * search for full-text terms in the index + */ + performTermsSearch: (searchTerms, excludedTerms) => { + // prepare search + const terms = Search._index.terms; + const titleTerms = Search._index.titleterms; + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + + const scoreMap = new Map(); + const fileMap = new Map(); + + // perform the search on the required terms + searchTerms.forEach((word) => { + const files = []; + const arr = [ + { files: terms[word], score: Scorer.term }, + { files: titleTerms[word], score: Scorer.title }, + ]; + // add support for partial matches + if (word.length > 2) { + const escapedWord = _escapeRegExp(word); + if (!terms.hasOwnProperty(word)) { + Object.keys(terms).forEach((term) => { + if (term.match(escapedWord)) + arr.push({ files: terms[term], score: Scorer.partialTerm }); + }); + } + if (!titleTerms.hasOwnProperty(word)) { + Object.keys(titleTerms).forEach((term) => { + if (term.match(escapedWord)) + arr.push({ files: titleTerms[term], score: Scorer.partialTitle }); + }); + } + } + + // no match but word was a required one + if (arr.every((record) => record.files === undefined)) return; + + // found search word in contents + arr.forEach((record) => { + if (record.files === undefined) return; + + let recordFiles = record.files; + if (recordFiles.length === undefined) recordFiles = [recordFiles]; + files.push(...recordFiles); + + // set score for the word in each file + recordFiles.forEach((file) => { + if (!scoreMap.has(file)) scoreMap.set(file, {}); + scoreMap.get(file)[word] = record.score; + }); + }); + + // create the mapping + files.forEach((file) => { + if (!fileMap.has(file)) fileMap.set(file, [word]); + else if (fileMap.get(file).indexOf(word) === -1) fileMap.get(file).push(word); + }); + }); + + // now check if the files don't contain excluded terms + const results = []; + for (const [file, wordList] of fileMap) { + // check if all requirements are matched + + // as search terms with length < 3 are discarded + const filteredTermCount = [...searchTerms].filter( + (term) => term.length > 2 + ).length; + if ( + wordList.length !== searchTerms.size && + wordList.length !== filteredTermCount + ) + continue; + + // ensure that none of the excluded terms is in the search result + if ( + [...excludedTerms].some( + (term) => + terms[term] === file || + titleTerms[term] === file || + (terms[term] || []).includes(file) || + (titleTerms[term] || []).includes(file) + ) + ) + break; + + // select one (max) score for the file. + const score = Math.max(...wordList.map((w) => scoreMap.get(file)[w])); + // add result to the result list + results.push([ + docNames[file], + titles[file], + "", + null, + score, + filenames[file], + ]); + } + return results; + }, + + /** + * helper function to return a node containing the + * search summary for a given text. keywords is a list + * of stemmed words. + */ + makeSearchSummary: (htmlText, keywords, anchor) => { + const text = Search.htmlToText(htmlText, anchor); + if (text === "") return null; + + const textLower = text.toLowerCase(); + const actualStartPosition = [...keywords] + .map((k) => textLower.indexOf(k.toLowerCase())) + .filter((i) => i > -1) + .slice(-1)[0]; + const startWithContext = Math.max(actualStartPosition - 120, 0); + + const top = startWithContext === 0 ? "" : "..."; + const tail = startWithContext + 240 < text.length ? "..." : ""; + + let summary = document.createElement("p"); + summary.classList.add("context"); + summary.textContent = top + text.substr(startWithContext, 240).trim() + tail; + + return summary; + }, +}; + +_ready(Search.init); diff --git a/main/_static/skeleton.css b/main/_static/skeleton.css new file mode 100644 index 00000000..467c878c --- /dev/null +++ b/main/_static/skeleton.css @@ -0,0 +1,296 @@ +/* Some sane resets. */ +html { + height: 100%; +} + +body { + margin: 0; + min-height: 100%; +} + +/* All the flexbox magic! */ +body, +.sb-announcement, +.sb-content, +.sb-main, +.sb-container, +.sb-container__inner, +.sb-article-container, +.sb-footer-content, +.sb-header, +.sb-header-secondary, +.sb-footer { + display: flex; +} + +/* These order things vertically */ +body, +.sb-main, +.sb-article-container { + flex-direction: column; +} + +/* Put elements in the center */ +.sb-header, +.sb-header-secondary, +.sb-container, +.sb-content, +.sb-footer, +.sb-footer-content { + justify-content: center; +} +/* Put elements at the ends */ +.sb-article-container { + justify-content: space-between; +} + +/* These elements grow. */ +.sb-main, +.sb-content, +.sb-container, +article { + flex-grow: 1; +} + +/* Because padding making this wider is not fun */ +article { + box-sizing: border-box; +} + +/* The announcements element should never be wider than the page. */ +.sb-announcement { + max-width: 100%; +} + +.sb-sidebar-primary, +.sb-sidebar-secondary { + flex-shrink: 0; + width: 17rem; +} + +.sb-announcement__inner { + justify-content: center; + + box-sizing: border-box; + height: 3rem; + + overflow-x: auto; + white-space: nowrap; +} + +/* Sidebars, with checkbox-based toggle */ +.sb-sidebar-primary, +.sb-sidebar-secondary { + position: fixed; + height: 100%; + top: 0; +} + +.sb-sidebar-primary { + left: -17rem; + transition: left 250ms ease-in-out; +} +.sb-sidebar-secondary { + right: -17rem; + transition: right 250ms ease-in-out; +} + +.sb-sidebar-toggle { + display: none; +} +.sb-sidebar-overlay { + position: fixed; + top: 0; + width: 0; + height: 0; + + transition: width 0ms ease 250ms, height 0ms ease 250ms, opacity 250ms ease; + + opacity: 0; + background-color: rgba(0, 0, 0, 0.54); +} + +#sb-sidebar-toggle--primary:checked + ~ .sb-sidebar-overlay[for="sb-sidebar-toggle--primary"], +#sb-sidebar-toggle--secondary:checked + ~ .sb-sidebar-overlay[for="sb-sidebar-toggle--secondary"] { + width: 100%; + height: 100%; + opacity: 1; + transition: width 0ms ease, height 0ms ease, opacity 250ms ease; +} + +#sb-sidebar-toggle--primary:checked ~ .sb-container .sb-sidebar-primary { + left: 0; +} +#sb-sidebar-toggle--secondary:checked ~ .sb-container .sb-sidebar-secondary { + right: 0; +} + +/* Full-width mode */ +.drop-secondary-sidebar-for-full-width-content + .hide-when-secondary-sidebar-shown { + display: none !important; +} +.drop-secondary-sidebar-for-full-width-content .sb-sidebar-secondary { + display: none !important; +} + +/* Mobile views */ +.sb-page-width { + width: 100%; +} + +.sb-article-container, +.sb-footer-content__inner, +.drop-secondary-sidebar-for-full-width-content .sb-article, +.drop-secondary-sidebar-for-full-width-content .match-content-width { + width: 100vw; +} + +.sb-article, +.match-content-width { + padding: 0 1rem; + box-sizing: border-box; +} + +@media (min-width: 32rem) { + .sb-article, + .match-content-width { + padding: 0 2rem; + } +} + +/* Tablet views */ +@media (min-width: 42rem) { + .sb-article-container { + width: auto; + } + .sb-footer-content__inner, + .drop-secondary-sidebar-for-full-width-content .sb-article, + .drop-secondary-sidebar-for-full-width-content .match-content-width { + width: 42rem; + } + .sb-article, + .match-content-width { + width: 42rem; + } +} +@media (min-width: 46rem) { + .sb-footer-content__inner, + .drop-secondary-sidebar-for-full-width-content .sb-article, + .drop-secondary-sidebar-for-full-width-content .match-content-width { + width: 46rem; + } + .sb-article, + .match-content-width { + width: 46rem; + } +} +@media (min-width: 50rem) { + .sb-footer-content__inner, + .drop-secondary-sidebar-for-full-width-content .sb-article, + .drop-secondary-sidebar-for-full-width-content .match-content-width { + width: 50rem; + } + .sb-article, + .match-content-width { + width: 50rem; + } +} + +/* Tablet views */ +@media (min-width: 59rem) { + .sb-sidebar-secondary { + position: static; + } + .hide-when-secondary-sidebar-shown { + display: none !important; + } + .sb-footer-content__inner, + .drop-secondary-sidebar-for-full-width-content .sb-article, + .drop-secondary-sidebar-for-full-width-content .match-content-width { + width: 59rem; + } + .sb-article, + .match-content-width { + width: 42rem; + } +} +@media (min-width: 63rem) { + .sb-footer-content__inner, + .drop-secondary-sidebar-for-full-width-content .sb-article, + .drop-secondary-sidebar-for-full-width-content .match-content-width { + width: 63rem; + } + .sb-article, + .match-content-width { + width: 46rem; + } +} +@media (min-width: 67rem) { + .sb-footer-content__inner, + .drop-secondary-sidebar-for-full-width-content .sb-article, + .drop-secondary-sidebar-for-full-width-content .match-content-width { + width: 67rem; + } + .sb-article, + .match-content-width { + width: 50rem; + } +} + +/* Desktop views */ +@media (min-width: 76rem) { + .sb-sidebar-primary { + position: static; + } + .hide-when-primary-sidebar-shown { + display: none !important; + } + .sb-footer-content__inner, + .drop-secondary-sidebar-for-full-width-content .sb-article, + .drop-secondary-sidebar-for-full-width-content .match-content-width { + width: 59rem; + } + .sb-article, + .match-content-width { + width: 42rem; + } +} + +/* Full desktop views */ +@media (min-width: 80rem) { + .sb-article, + .match-content-width { + width: 46rem; + } + .sb-footer-content__inner, + .drop-secondary-sidebar-for-full-width-content .sb-article, + .drop-secondary-sidebar-for-full-width-content .match-content-width { + width: 63rem; + } +} + +@media (min-width: 84rem) { + .sb-article, + .match-content-width { + width: 50rem; + } + .sb-footer-content__inner, + .drop-secondary-sidebar-for-full-width-content .sb-article, + .drop-secondary-sidebar-for-full-width-content .match-content-width { + width: 67rem; + } +} + +@media (min-width: 88rem) { + .sb-footer-content__inner, + .drop-secondary-sidebar-for-full-width-content .sb-article, + .drop-secondary-sidebar-for-full-width-content .match-content-width { + width: 67rem; + } + .sb-page-width { + width: 88rem; + } +} diff --git a/main/_static/sphinx_highlight.js b/main/_static/sphinx_highlight.js new file mode 100644 index 00000000..8a96c69a --- /dev/null +++ b/main/_static/sphinx_highlight.js @@ -0,0 +1,154 @@ +/* Highlighting utilities for Sphinx HTML documentation. */ +"use strict"; + +const SPHINX_HIGHLIGHT_ENABLED = true + +/** + * highlight a given string on a node by wrapping it in + * span elements with the given class name. + */ +const _highlight = (node, addItems, text, className) => { + if (node.nodeType === Node.TEXT_NODE) { + const val = node.nodeValue; + const parent = node.parentNode; + const pos = val.toLowerCase().indexOf(text); + if ( + pos >= 0 && + !parent.classList.contains(className) && + !parent.classList.contains("nohighlight") + ) { + let span; + + const closestNode = parent.closest("body, svg, foreignObject"); + const isInSVG = closestNode && closestNode.matches("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.classList.add(className); + } + + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + const rest = document.createTextNode(val.substr(pos + text.length)); + parent.insertBefore( + span, + parent.insertBefore( + rest, + node.nextSibling + ) + ); + node.nodeValue = val.substr(0, pos); + /* There may be more occurrences of search term in this node. So call this + * function recursively on the remaining fragment. + */ + _highlight(rest, addItems, text, className); + + if (isInSVG) { + const rect = document.createElementNS( + "http://www.w3.org/2000/svg", + "rect" + ); + const bbox = parent.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute("class", className); + addItems.push({ parent: parent, target: rect }); + } + } + } else if (node.matches && !node.matches("button, select, textarea")) { + node.childNodes.forEach((el) => _highlight(el, addItems, text, className)); + } +}; +const _highlightText = (thisNode, text, className) => { + let addItems = []; + _highlight(thisNode, addItems, text, className); + addItems.forEach((obj) => + obj.parent.insertAdjacentElement("beforebegin", obj.target) + ); +}; + +/** + * Small JavaScript module for the documentation. + */ +const SphinxHighlight = { + + /** + * highlight the search words provided in localstorage in the text + */ + highlightSearchWords: () => { + if (!SPHINX_HIGHLIGHT_ENABLED) return; // bail if no highlight + + // get and clear terms from localstorage + const url = new URL(window.location); + const highlight = + localStorage.getItem("sphinx_highlight_terms") + || url.searchParams.get("highlight") + || ""; + localStorage.removeItem("sphinx_highlight_terms") + url.searchParams.delete("highlight"); + window.history.replaceState({}, "", url); + + // get individual terms from highlight string + const terms = highlight.toLowerCase().split(/\s+/).filter(x => x); + if (terms.length === 0) return; // nothing to do + + // There should never be more than one element matching "div.body" + const divBody = document.querySelectorAll("div.body"); + const body = divBody.length ? divBody[0] : document.querySelector("body"); + window.setTimeout(() => { + terms.forEach((term) => _highlightText(body, term, "highlighted")); + }, 10); + + const searchBox = document.getElementById("searchbox"); + if (searchBox === null) return; + searchBox.appendChild( + document + .createRange() + .createContextualFragment( + '" + ) + ); + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords: () => { + document + .querySelectorAll("#searchbox .highlight-link") + .forEach((el) => el.remove()); + document + .querySelectorAll("span.highlighted") + .forEach((el) => el.classList.remove("highlighted")); + localStorage.removeItem("sphinx_highlight_terms") + }, + + initEscapeListener: () => { + // only install a listener if it is really needed + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return; + if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) { + SphinxHighlight.hideSearchWords(); + event.preventDefault(); + } + }); + }, +}; + +_ready(() => { + /* Do not call highlightSearchWords() when we are on the search page. + * It will highlight words from the *previous* search query. + */ + if (typeof Search === "undefined") SphinxHighlight.highlightSearchWords(); + SphinxHighlight.initEscapeListener(); +}); diff --git a/main/_static/styles/furo-extensions.css b/main/_static/styles/furo-extensions.css new file mode 100644 index 00000000..82295876 --- /dev/null +++ b/main/_static/styles/furo-extensions.css @@ -0,0 +1,2 @@ +#furo-sidebar-ad-placement{padding:var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal)}#furo-sidebar-ad-placement .ethical-sidebar{background:var(--color-background-secondary);border:none;box-shadow:none}#furo-sidebar-ad-placement .ethical-sidebar:hover{background:var(--color-background-hover)}#furo-sidebar-ad-placement .ethical-sidebar a{color:var(--color-foreground-primary)}#furo-sidebar-ad-placement .ethical-callout a{color:var(--color-foreground-secondary)!important}#furo-readthedocs-versions{background:transparent;display:block;position:static;width:100%}#furo-readthedocs-versions .rst-versions{background:#1a1c1e}#furo-readthedocs-versions .rst-current-version{background:var(--color-sidebar-item-background);cursor:unset}#furo-readthedocs-versions .rst-current-version:hover{background:var(--color-sidebar-item-background)}#furo-readthedocs-versions .rst-current-version .fa-book{color:var(--color-foreground-primary)}#furo-readthedocs-versions>.rst-other-versions{padding:0}#furo-readthedocs-versions>.rst-other-versions small{opacity:1}#furo-readthedocs-versions .injected .rst-versions{position:unset}#furo-readthedocs-versions:focus-within,#furo-readthedocs-versions:hover{box-shadow:0 0 0 1px var(--color-sidebar-background-border)}#furo-readthedocs-versions:focus-within .rst-current-version,#furo-readthedocs-versions:hover .rst-current-version{background:#1a1c1e;font-size:inherit;height:auto;line-height:inherit;padding:12px;text-align:right}#furo-readthedocs-versions:focus-within .rst-current-version .fa-book,#furo-readthedocs-versions:hover .rst-current-version .fa-book{color:#fff;float:left}#furo-readthedocs-versions:focus-within .fa-caret-down,#furo-readthedocs-versions:hover .fa-caret-down{display:none}#furo-readthedocs-versions:focus-within .injected,#furo-readthedocs-versions:focus-within .rst-current-version,#furo-readthedocs-versions:focus-within .rst-other-versions,#furo-readthedocs-versions:hover .injected,#furo-readthedocs-versions:hover .rst-current-version,#furo-readthedocs-versions:hover .rst-other-versions{display:block}#furo-readthedocs-versions:focus-within>.rst-current-version,#furo-readthedocs-versions:hover>.rst-current-version{display:none}.highlight:hover button.copybtn{color:var(--color-code-foreground)}.highlight button.copybtn{align-items:center;background-color:var(--color-code-background);border:none;color:var(--color-background-item);cursor:pointer;height:1.25em;right:.5rem;top:.625rem;transition:color .3s,opacity .3s;width:1.25em}.highlight button.copybtn:hover{background-color:var(--color-code-background);color:var(--color-brand-content)}.highlight button.copybtn:after{background-color:transparent;color:var(--color-code-foreground);display:none}.highlight button.copybtn.success{color:#22863a;transition:color 0ms}.highlight button.copybtn.success:after{display:block}.highlight button.copybtn svg{padding:0}body{--sd-color-primary:var(--color-brand-primary);--sd-color-primary-highlight:var(--color-brand-content);--sd-color-primary-text:var(--color-background-primary);--sd-color-shadow:rgba(0,0,0,.05);--sd-color-card-border:var(--color-card-border);--sd-color-card-border-hover:var(--color-brand-content);--sd-color-card-background:var(--color-card-background);--sd-color-card-text:var(--color-foreground-primary);--sd-color-card-header:var(--color-card-marginals-background);--sd-color-card-footer:var(--color-card-marginals-background);--sd-color-tabs-label-active:var(--color-brand-content);--sd-color-tabs-label-hover:var(--color-foreground-muted);--sd-color-tabs-label-inactive:var(--color-foreground-muted);--sd-color-tabs-underline-active:var(--color-brand-content);--sd-color-tabs-underline-hover:var(--color-foreground-border);--sd-color-tabs-underline-inactive:var(--color-background-border);--sd-color-tabs-overline:var(--color-background-border);--sd-color-tabs-underline:var(--color-background-border)}.sd-tab-content{box-shadow:0 -2px var(--sd-color-tabs-overline),0 1px var(--sd-color-tabs-underline)}.sd-card{box-shadow:0 .1rem .25rem var(--sd-color-shadow),0 0 .0625rem rgba(0,0,0,.1)}.sd-shadow-sm{box-shadow:0 .1rem .25rem var(--sd-color-shadow),0 0 .0625rem rgba(0,0,0,.1)!important}.sd-shadow-md{box-shadow:0 .3rem .75rem var(--sd-color-shadow),0 0 .0625rem rgba(0,0,0,.1)!important}.sd-shadow-lg{box-shadow:0 .6rem 1.5rem var(--sd-color-shadow),0 0 .0625rem rgba(0,0,0,.1)!important}.sd-card-hover:hover{transform:none}.sd-cards-carousel{gap:.25rem;padding:.25rem}body{--tabs--label-text:var(--color-foreground-muted);--tabs--label-text--hover:var(--color-foreground-muted);--tabs--label-text--active:var(--color-brand-content);--tabs--label-text--active--hover:var(--color-brand-content);--tabs--label-background:transparent;--tabs--label-background--hover:transparent;--tabs--label-background--active:transparent;--tabs--label-background--active--hover:transparent;--tabs--padding-x:0.25em;--tabs--margin-x:1em;--tabs--border:var(--color-background-border);--tabs--label-border:transparent;--tabs--label-border--hover:var(--color-foreground-muted);--tabs--label-border--active:var(--color-brand-content);--tabs--label-border--active--hover:var(--color-brand-content)}[role=main] .container{max-width:none;padding-left:0;padding-right:0}.shadow.docutils{border:none;box-shadow:0 .2rem .5rem rgba(0,0,0,.05),0 0 .0625rem rgba(0,0,0,.1)!important}.sphinx-bs .card{background-color:var(--color-background-secondary);color:var(--color-foreground)} +/*# sourceMappingURL=furo-extensions.css.map*/ \ No newline at end of file diff --git a/main/_static/styles/furo-extensions.css.map b/main/_static/styles/furo-extensions.css.map new file mode 100644 index 00000000..c26eac7f --- /dev/null +++ b/main/_static/styles/furo-extensions.css.map @@ -0,0 +1 @@ +{"version":3,"file":"styles/furo-extensions.css","mappings":"AAGA,2BACE,oFACA,4CAKE,6CAHA,YACA,eAEA,CACA,kDACE,yCAEF,8CACE,sCAEJ,8CACE,kDAEJ,2BAGE,uBACA,cAHA,gBACA,UAEA,CAGA,yCACE,mBAEF,gDAEE,gDADA,YACA,CACA,sDACE,gDACF,yDACE,sCAEJ,+CACE,UACA,qDACE,UAGF,mDACE,eAEJ,yEAEE,4DAEA,mHASE,mBAPA,kBAEA,YADA,oBAGA,aADA,gBAIA,CAEA,qIAEE,WADA,UACA,CAEJ,uGACE,aAEF,iUAGE,cAEF,mHACE,aC1EJ,gCACE,mCAEF,0BAEE,mBAUA,8CACA,YAFA,mCAKA,eAZA,cAIA,YADA,YAYA,iCAdA,YAcA,CAEA,gCAEE,8CADA,gCACA,CAEF,gCAGE,6BADA,mCADA,YAEA,CAEF,kCAEE,cADA,oBACA,CACA,wCACE,cAEJ,8BACE,UCzCN,KAEE,6CAA8C,CAC9C,uDAAwD,CACxD,uDAAwD,CAGxD,iCAAsC,CAGtC,+CAAgD,CAChD,uDAAwD,CACxD,uDAAwD,CACxD,oDAAqD,CACrD,6DAA8D,CAC9D,6DAA8D,CAG9D,uDAAwD,CACxD,yDAA0D,CAC1D,4DAA6D,CAC7D,2DAA4D,CAC5D,8DAA+D,CAC/D,iEAAkE,CAClE,uDAAwD,CACxD,wDAAyD,CAG3D,gBACE,qFAGF,SACE,6EAEF,cACE,uFAEF,cACE,uFAEF,cACE,uFAGF,qBACE,eAEF,mBACE,WACA,eChDF,KACE,gDAAiD,CACjD,uDAAwD,CACxD,qDAAsD,CACtD,4DAA6D,CAC7D,oCAAqC,CACrC,2CAA4C,CAC5C,4CAA6C,CAC7C,mDAAoD,CACpD,wBAAyB,CACzB,oBAAqB,CACrB,6CAA8C,CAC9C,gCAAiC,CACjC,yDAA0D,CAC1D,uDAAwD,CACxD,8DAA+D,CCbjE,uBACE,eACA,eACA,gBAGF,iBACE,YACA,+EAGF,iBACE,mDACA","sources":["webpack:///./src/furo/assets/styles/extensions/_readthedocs.sass","webpack:///./src/furo/assets/styles/extensions/_copybutton.sass","webpack:///./src/furo/assets/styles/extensions/_sphinx-design.sass","webpack:///./src/furo/assets/styles/extensions/_sphinx-inline-tabs.sass","webpack:///./src/furo/assets/styles/extensions/_sphinx-panels.sass"],"sourcesContent":["// This file contains the styles used for tweaking how ReadTheDoc's embedded\n// contents would show up inside the theme.\n\n#furo-sidebar-ad-placement\n padding: var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal)\n .ethical-sidebar\n // Remove the border and box-shadow.\n border: none\n box-shadow: none\n // Manage the background colors.\n background: var(--color-background-secondary)\n &:hover\n background: var(--color-background-hover)\n // Ensure the text is legible.\n a\n color: var(--color-foreground-primary)\n\n .ethical-callout a\n color: var(--color-foreground-secondary) !important\n\n#furo-readthedocs-versions\n position: static\n width: 100%\n background: transparent\n display: block\n\n // Make the background color fit with the theme's aesthetic.\n .rst-versions\n background: rgb(26, 28, 30)\n\n .rst-current-version\n cursor: unset\n background: var(--color-sidebar-item-background)\n &:hover\n background: var(--color-sidebar-item-background)\n .fa-book\n color: var(--color-foreground-primary)\n\n > .rst-other-versions\n padding: 0\n small\n opacity: 1\n\n .injected\n .rst-versions\n position: unset\n\n &:hover,\n &:focus-within\n box-shadow: 0 0 0 1px var(--color-sidebar-background-border)\n\n .rst-current-version\n // Undo the tweaks done in RTD's CSS\n font-size: inherit\n line-height: inherit\n height: auto\n text-align: right\n padding: 12px\n\n // Match the rest of the body\n background: #1a1c1e\n\n .fa-book\n float: left\n color: white\n\n .fa-caret-down\n display: none\n\n .rst-current-version,\n .rst-other-versions,\n .injected\n display: block\n\n > .rst-current-version\n display: none\n",".highlight\n &:hover button.copybtn\n color: var(--color-code-foreground)\n\n button.copybtn\n // Align things correctly\n align-items: center\n\n height: 1.25em\n width: 1.25em\n\n top: 0.625rem // $code-spacing-vertical\n right: 0.5rem\n\n // Make it look better\n color: var(--color-background-item)\n background-color: var(--color-code-background)\n border: none\n\n // Change to cursor to make it obvious that you can click on it\n cursor: pointer\n\n // Transition smoothly, for aesthetics\n transition: color 300ms, opacity 300ms\n\n &:hover\n color: var(--color-brand-content)\n background-color: var(--color-code-background)\n\n &::after\n display: none\n color: var(--color-code-foreground)\n background-color: transparent\n\n &.success\n transition: color 0ms\n color: #22863a\n &::after\n display: block\n\n svg\n padding: 0\n","body\n // Colors\n --sd-color-primary: var(--color-brand-primary)\n --sd-color-primary-highlight: var(--color-brand-content)\n --sd-color-primary-text: var(--color-background-primary)\n\n // Shadows\n --sd-color-shadow: rgba(0, 0, 0, 0.05)\n\n // Cards\n --sd-color-card-border: var(--color-card-border)\n --sd-color-card-border-hover: var(--color-brand-content)\n --sd-color-card-background: var(--color-card-background)\n --sd-color-card-text: var(--color-foreground-primary)\n --sd-color-card-header: var(--color-card-marginals-background)\n --sd-color-card-footer: var(--color-card-marginals-background)\n\n // Tabs\n --sd-color-tabs-label-active: var(--color-brand-content)\n --sd-color-tabs-label-hover: var(--color-foreground-muted)\n --sd-color-tabs-label-inactive: var(--color-foreground-muted)\n --sd-color-tabs-underline-active: var(--color-brand-content)\n --sd-color-tabs-underline-hover: var(--color-foreground-border)\n --sd-color-tabs-underline-inactive: var(--color-background-border)\n --sd-color-tabs-overline: var(--color-background-border)\n --sd-color-tabs-underline: var(--color-background-border)\n\n// Tabs\n.sd-tab-content\n box-shadow: 0 -2px var(--sd-color-tabs-overline), 0 1px var(--sd-color-tabs-underline)\n\n// Shadows\n.sd-card // Have a shadow by default\n box-shadow: 0 0.1rem 0.25rem var(--sd-color-shadow), 0 0 0.0625rem rgba(0, 0, 0, 0.1)\n\n.sd-shadow-sm\n box-shadow: 0 0.1rem 0.25rem var(--sd-color-shadow), 0 0 0.0625rem rgba(0, 0, 0, 0.1) !important\n\n.sd-shadow-md\n box-shadow: 0 0.3rem 0.75rem var(--sd-color-shadow), 0 0 0.0625rem rgba(0, 0, 0, 0.1) !important\n\n.sd-shadow-lg\n box-shadow: 0 0.6rem 1.5rem var(--sd-color-shadow), 0 0 0.0625rem rgba(0, 0, 0, 0.1) !important\n\n// Cards\n.sd-card-hover:hover // Don't change scale on hover\n transform: none\n\n.sd-cards-carousel // Have a bit of gap in the carousel by default\n gap: 0.25rem\n padding: 0.25rem\n","// This file contains styles to tweak sphinx-inline-tabs to work well with Furo.\n\nbody\n --tabs--label-text: var(--color-foreground-muted)\n --tabs--label-text--hover: var(--color-foreground-muted)\n --tabs--label-text--active: var(--color-brand-content)\n --tabs--label-text--active--hover: var(--color-brand-content)\n --tabs--label-background: transparent\n --tabs--label-background--hover: transparent\n --tabs--label-background--active: transparent\n --tabs--label-background--active--hover: transparent\n --tabs--padding-x: 0.25em\n --tabs--margin-x: 1em\n --tabs--border: var(--color-background-border)\n --tabs--label-border: transparent\n --tabs--label-border--hover: var(--color-foreground-muted)\n --tabs--label-border--active: var(--color-brand-content)\n --tabs--label-border--active--hover: var(--color-brand-content)\n","// This file contains styles to tweak sphinx-panels to work well with Furo.\n\n// sphinx-panels includes Bootstrap 4, which uses .container which can conflict\n// with docutils' `.. container::` directive.\n[role=\"main\"] .container\n max-width: initial\n padding-left: initial\n padding-right: initial\n\n// Make the panels look nicer!\n.shadow.docutils\n border: none\n box-shadow: 0 0.2rem 0.5rem rgba(0, 0, 0, 0.05), 0 0 0.0625rem rgba(0, 0, 0, 0.1) !important\n\n// Make panel colors respond to dark mode\n.sphinx-bs .card\n background-color: var(--color-background-secondary)\n color: var(--color-foreground)\n"],"names":[],"sourceRoot":""} \ No newline at end of file diff --git a/main/_static/styles/furo.css b/main/_static/styles/furo.css new file mode 100644 index 00000000..21836d6a --- /dev/null +++ b/main/_static/styles/furo.css @@ -0,0 +1,2 @@ +/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}[hidden],template{display:none}@media print{.content-icon-container,.headerlink,.mobile-header,.related-pages{display:none!important}.highlight{border:.1pt solid var(--color-foreground-border)}a,blockquote,dl,ol,pre,table,ul{page-break-inside:avoid}caption,figure,h1,h2,h3,h4,h5,h6,img{page-break-after:avoid;page-break-inside:avoid}dl,ol,ul{page-break-before:avoid}}.visually-hidden{height:1px!important;margin:-1px!important;overflow:hidden!important;padding:0!important;position:absolute!important;width:1px!important;clip:rect(0,0,0,0)!important;background:var(--color-background-primary);border:0!important;color:var(--color-foreground-primary);white-space:nowrap!important}:-moz-focusring{outline:auto}body{--font-stack:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji;--font-stack--monospace:"SFMono-Regular",Menlo,Consolas,Monaco,Liberation Mono,Lucida Console,monospace;--font-stack--headings:var(--font-stack);--font-size--normal:100%;--font-size--small:87.5%;--font-size--small--2:81.25%;--font-size--small--3:75%;--font-size--small--4:62.5%;--sidebar-caption-font-size:var(--font-size--small--2);--sidebar-item-font-size:var(--font-size--small);--sidebar-search-input-font-size:var(--font-size--small);--toc-font-size:var(--font-size--small--3);--toc-font-size--mobile:var(--font-size--normal);--toc-title-font-size:var(--font-size--small--4);--admonition-font-size:0.8125rem;--admonition-title-font-size:0.8125rem;--code-font-size:var(--font-size--small--2);--api-font-size:var(--font-size--small);--header-height:calc(var(--sidebar-item-line-height) + var(--sidebar-item-spacing-vertical)*4);--header-padding:0.5rem;--sidebar-tree-space-above:1.5rem;--sidebar-caption-space-above:1rem;--sidebar-item-line-height:1rem;--sidebar-item-spacing-vertical:0.5rem;--sidebar-item-spacing-horizontal:1rem;--sidebar-item-height:calc(var(--sidebar-item-line-height) + var(--sidebar-item-spacing-vertical)*2);--sidebar-expander-width:var(--sidebar-item-height);--sidebar-search-space-above:0.5rem;--sidebar-search-input-spacing-vertical:0.5rem;--sidebar-search-input-spacing-horizontal:0.5rem;--sidebar-search-input-height:1rem;--sidebar-search-icon-size:var(--sidebar-search-input-height);--toc-title-padding:0.25rem 0;--toc-spacing-vertical:1.5rem;--toc-spacing-horizontal:1.5rem;--toc-item-spacing-vertical:0.4rem;--toc-item-spacing-horizontal:1rem;--icon-search:url('data:image/svg+xml;charset=utf-8,');--icon-pencil:url('data:image/svg+xml;charset=utf-8,');--icon-abstract:url('data:image/svg+xml;charset=utf-8,');--icon-info:url('data:image/svg+xml;charset=utf-8,');--icon-flame:url('data:image/svg+xml;charset=utf-8,');--icon-question:url('data:image/svg+xml;charset=utf-8,');--icon-warning:url('data:image/svg+xml;charset=utf-8,');--icon-failure:url('data:image/svg+xml;charset=utf-8,');--icon-spark:url('data:image/svg+xml;charset=utf-8,');--color-admonition-title--caution:#ff9100;--color-admonition-title-background--caution:rgba(255,145,0,.2);--color-admonition-title--warning:#ff9100;--color-admonition-title-background--warning:rgba(255,145,0,.2);--color-admonition-title--danger:#ff5252;--color-admonition-title-background--danger:rgba(255,82,82,.2);--color-admonition-title--attention:#ff5252;--color-admonition-title-background--attention:rgba(255,82,82,.2);--color-admonition-title--error:#ff5252;--color-admonition-title-background--error:rgba(255,82,82,.2);--color-admonition-title--hint:#00c852;--color-admonition-title-background--hint:rgba(0,200,82,.2);--color-admonition-title--tip:#00c852;--color-admonition-title-background--tip:rgba(0,200,82,.2);--color-admonition-title--important:#00bfa5;--color-admonition-title-background--important:rgba(0,191,165,.2);--color-admonition-title--note:#00b0ff;--color-admonition-title-background--note:rgba(0,176,255,.2);--color-admonition-title--seealso:#448aff;--color-admonition-title-background--seealso:rgba(68,138,255,.2);--color-admonition-title--admonition-todo:grey;--color-admonition-title-background--admonition-todo:hsla(0,0%,50%,.2);--color-admonition-title:#651fff;--color-admonition-title-background:rgba(101,31,255,.2);--icon-admonition-default:var(--icon-abstract);--color-topic-title:#14b8a6;--color-topic-title-background:rgba(20,184,166,.2);--icon-topic-default:var(--icon-pencil);--color-problematic:#b30000;--color-foreground-primary:#000;--color-foreground-secondary:#5a5c63;--color-foreground-muted:#6b6f76;--color-foreground-border:#878787;--color-background-primary:#fff;--color-background-secondary:#f8f9fb;--color-background-hover:#efeff4;--color-background-hover--transparent:#efeff400;--color-background-border:#eeebee;--color-background-item:#ccc;--color-announcement-background:#000000dd;--color-announcement-text:#eeebee;--color-brand-primary:#0a4bff;--color-brand-content:#2757dd;--color-brand-visited:#872ee0;--color-api-background:var(--color-background-hover--transparent);--color-api-background-hover:var(--color-background-hover);--color-api-overall:var(--color-foreground-secondary);--color-api-name:var(--color-problematic);--color-api-pre-name:var(--color-problematic);--color-api-paren:var(--color-foreground-secondary);--color-api-keyword:var(--color-foreground-primary);--color-api-added:#21632c;--color-api-added-border:#38a84d;--color-api-changed:#046172;--color-api-changed-border:#06a1bc;--color-api-deprecated:#605706;--color-api-deprecated-border:#f0d90f;--color-api-removed:#b30000;--color-api-removed-border:#ff5c5c;--color-highlight-on-target:#ffc;--color-inline-code-background:var(--color-background-secondary);--color-highlighted-background:#def;--color-highlighted-text:var(--color-foreground-primary);--color-guilabel-background:#ddeeff80;--color-guilabel-border:#bedaf580;--color-guilabel-text:var(--color-foreground-primary);--color-admonition-background:transparent;--color-table-header-background:var(--color-background-secondary);--color-table-border:var(--color-background-border);--color-card-border:var(--color-background-secondary);--color-card-background:transparent;--color-card-marginals-background:var(--color-background-secondary);--color-header-background:var(--color-background-primary);--color-header-border:var(--color-background-border);--color-header-text:var(--color-foreground-primary);--color-sidebar-background:var(--color-background-secondary);--color-sidebar-background-border:var(--color-background-border);--color-sidebar-brand-text:var(--color-foreground-primary);--color-sidebar-caption-text:var(--color-foreground-muted);--color-sidebar-link-text:var(--color-foreground-secondary);--color-sidebar-link-text--top-level:var(--color-brand-primary);--color-sidebar-item-background:var(--color-sidebar-background);--color-sidebar-item-background--current:var( --color-sidebar-item-background );--color-sidebar-item-background--hover:linear-gradient(90deg,var(--color-background-hover--transparent) 0%,var(--color-background-hover) var(--sidebar-item-spacing-horizontal),var(--color-background-hover) 100%);--color-sidebar-item-expander-background:transparent;--color-sidebar-item-expander-background--hover:var( --color-background-hover );--color-sidebar-search-text:var(--color-foreground-primary);--color-sidebar-search-background:var(--color-background-secondary);--color-sidebar-search-background--focus:var(--color-background-primary);--color-sidebar-search-border:var(--color-background-border);--color-sidebar-search-icon:var(--color-foreground-muted);--color-toc-background:var(--color-background-primary);--color-toc-title-text:var(--color-foreground-muted);--color-toc-item-text:var(--color-foreground-secondary);--color-toc-item-text--hover:var(--color-foreground-primary);--color-toc-item-text--active:var(--color-brand-primary);--color-content-foreground:var(--color-foreground-primary);--color-content-background:transparent;--color-link:var(--color-brand-content);--color-link-underline:var(--color-background-border);--color-link--hover:var(--color-brand-content);--color-link-underline--hover:var(--color-foreground-border);--color-link--visited:var(--color-brand-visited);--color-link-underline--visited:var(--color-background-border);--color-link--visited--hover:var(--color-brand-visited);--color-link-underline--visited--hover:var(--color-foreground-border)}.only-light{display:block!important}html body .only-dark{display:none!important}@media not print{body[data-theme=dark]{--color-problematic:#ee5151;--color-foreground-primary:#cfd0d0;--color-foreground-secondary:#9ca0a5;--color-foreground-muted:#81868d;--color-foreground-border:#666;--color-background-primary:#131416;--color-background-secondary:#1a1c1e;--color-background-hover:#1e2124;--color-background-hover--transparent:#1e212400;--color-background-border:#303335;--color-background-item:#444;--color-announcement-background:#000000dd;--color-announcement-text:#eeebee;--color-brand-primary:#3d94ff;--color-brand-content:#5ca5ff;--color-brand-visited:#b27aeb;--color-highlighted-background:#083563;--color-guilabel-background:#08356380;--color-guilabel-border:#13395f80;--color-api-keyword:var(--color-foreground-secondary);--color-highlight-on-target:#330;--color-api-added:#3db854;--color-api-added-border:#267334;--color-api-changed:#09b0ce;--color-api-changed-border:#056d80;--color-api-deprecated:#b1a10b;--color-api-deprecated-border:#6e6407;--color-api-removed:#ff7575;--color-api-removed-border:#b03b3b;--color-admonition-background:#18181a;--color-card-border:var(--color-background-secondary);--color-card-background:#18181a;--color-card-marginals-background:var(--color-background-hover)}html body[data-theme=dark] .only-light{display:none!important}body[data-theme=dark] .only-dark{display:block!important}@media(prefers-color-scheme:dark){body:not([data-theme=light]){--color-problematic:#ee5151;--color-foreground-primary:#cfd0d0;--color-foreground-secondary:#9ca0a5;--color-foreground-muted:#81868d;--color-foreground-border:#666;--color-background-primary:#131416;--color-background-secondary:#1a1c1e;--color-background-hover:#1e2124;--color-background-hover--transparent:#1e212400;--color-background-border:#303335;--color-background-item:#444;--color-announcement-background:#000000dd;--color-announcement-text:#eeebee;--color-brand-primary:#3d94ff;--color-brand-content:#5ca5ff;--color-brand-visited:#b27aeb;--color-highlighted-background:#083563;--color-guilabel-background:#08356380;--color-guilabel-border:#13395f80;--color-api-keyword:var(--color-foreground-secondary);--color-highlight-on-target:#330;--color-api-added:#3db854;--color-api-added-border:#267334;--color-api-changed:#09b0ce;--color-api-changed-border:#056d80;--color-api-deprecated:#b1a10b;--color-api-deprecated-border:#6e6407;--color-api-removed:#ff7575;--color-api-removed-border:#b03b3b;--color-admonition-background:#18181a;--color-card-border:var(--color-background-secondary);--color-card-background:#18181a;--color-card-marginals-background:var(--color-background-hover)}html body:not([data-theme=light]) .only-light{display:none!important}body:not([data-theme=light]) .only-dark{display:block!important}}}body[data-theme=auto] .theme-toggle svg.theme-icon-when-auto-light{display:block}@media(prefers-color-scheme:dark){body[data-theme=auto] .theme-toggle svg.theme-icon-when-auto-dark{display:block}body[data-theme=auto] .theme-toggle svg.theme-icon-when-auto-light{display:none}}body[data-theme=dark] .theme-toggle svg.theme-icon-when-dark,body[data-theme=light] .theme-toggle svg.theme-icon-when-light{display:block}body{font-family:var(--font-stack)}code,kbd,pre,samp{font-family:var(--font-stack--monospace)}body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}article{line-height:1.5}h1,h2,h3,h4,h5,h6{border-radius:.5rem;font-family:var(--font-stack--headings);font-weight:700;line-height:1.25;margin:.5rem -.5rem;padding-left:.5rem;padding-right:.5rem}h1+p,h2+p,h3+p,h4+p,h5+p,h6+p{margin-top:0}h1{font-size:2.5em;margin-bottom:1rem}h1,h2{margin-top:1.75rem}h2{font-size:2em}h3{font-size:1.5em}h4{font-size:1.25em}h5{font-size:1.125em}h6{font-size:1em}small{font-size:80%;opacity:75%}p{margin-bottom:.75rem;margin-top:.5rem}hr.docutils{background-color:var(--color-background-border);border:0;height:1px;margin:2rem 0;padding:0}.centered{text-align:center}a{color:var(--color-link);text-decoration:underline;text-decoration-color:var(--color-link-underline)}a:visited{color:var(--color-link--visited);text-decoration-color:var(--color-link-underline--visited)}a:visited:hover{color:var(--color-link--visited--hover);text-decoration-color:var(--color-link-underline--visited--hover)}a:hover{color:var(--color-link--hover);text-decoration-color:var(--color-link-underline--hover)}a.muted-link{color:inherit}a.muted-link:hover{color:var(--color-link--hover);text-decoration-color:var(--color-link-underline--hover)}a.muted-link:hover:visited{color:var(--color-link--visited--hover);text-decoration-color:var(--color-link-underline--visited--hover)}html{overflow-x:hidden;overflow-y:scroll;scroll-behavior:smooth}.sidebar-scroll,.toc-scroll,article[role=main] *{scrollbar-color:var(--color-foreground-border) transparent;scrollbar-width:thin}.sidebar-scroll::-webkit-scrollbar,.toc-scroll::-webkit-scrollbar,article[role=main] ::-webkit-scrollbar{height:.25rem;width:.25rem}.sidebar-scroll::-webkit-scrollbar-thumb,.toc-scroll::-webkit-scrollbar-thumb,article[role=main] ::-webkit-scrollbar-thumb{background-color:var(--color-foreground-border);border-radius:.125rem}body,html{height:100%}.skip-to-content,body,html{background:var(--color-background-primary);color:var(--color-foreground-primary)}.skip-to-content{border-radius:1rem;left:.25rem;padding:1rem;position:fixed;top:.25rem;transform:translateY(-200%);transition:transform .3s ease-in-out;z-index:40}.skip-to-content:focus-within{transform:translateY(0)}article{background:var(--color-content-background);color:var(--color-content-foreground);overflow-wrap:break-word}.page{display:flex;min-height:100%}.mobile-header{background-color:var(--color-header-background);border-bottom:1px solid var(--color-header-border);color:var(--color-header-text);display:none;height:var(--header-height);width:100%;z-index:10}.mobile-header.scrolled{border-bottom:none;box-shadow:0 0 .2rem rgba(0,0,0,.1),0 .2rem .4rem rgba(0,0,0,.2)}.mobile-header .header-center a{color:var(--color-header-text);text-decoration:none}.main{display:flex;flex:1}.sidebar-drawer{background:var(--color-sidebar-background);border-right:1px solid var(--color-sidebar-background-border);box-sizing:border-box;display:flex;justify-content:flex-end;min-width:15em;width:calc(50% - 26em)}.sidebar-container,.toc-drawer{box-sizing:border-box;width:15em}.toc-drawer{background:var(--color-toc-background);padding-right:1rem}.sidebar-sticky,.toc-sticky{display:flex;flex-direction:column;height:min(100%,100vh);height:100vh;position:sticky;top:0}.sidebar-scroll,.toc-scroll{flex-grow:1;flex-shrink:1;overflow:auto;scroll-behavior:smooth}.content{display:flex;flex-direction:column;justify-content:space-between;padding:0 3em;width:46em}.icon{display:inline-block;height:1rem;width:1rem}.icon svg{height:100%;width:100%}.announcement{align-items:center;background-color:var(--color-announcement-background);color:var(--color-announcement-text);display:flex;height:var(--header-height);overflow-x:auto}.announcement+.page{min-height:calc(100% - var(--header-height))}.announcement-content{box-sizing:border-box;min-width:100%;padding:.5rem;text-align:center;white-space:nowrap}.announcement-content a{color:var(--color-announcement-text);text-decoration-color:var(--color-announcement-text)}.announcement-content a:hover{color:var(--color-announcement-text);text-decoration-color:var(--color-link--hover)}.no-js .theme-toggle-container{display:none}.theme-toggle-container{display:flex}.theme-toggle{background:transparent;border:none;cursor:pointer;display:flex;padding:0}.theme-toggle svg{color:var(--color-foreground-primary);display:none;height:1.25rem;width:1.25rem}.theme-toggle-header{align-items:center;display:flex;justify-content:center}.nav-overlay-icon,.toc-overlay-icon{cursor:pointer;display:none}.nav-overlay-icon .icon,.toc-overlay-icon .icon{color:var(--color-foreground-secondary);height:1.5rem;width:1.5rem}.nav-overlay-icon,.toc-header-icon{align-items:center;justify-content:center}.toc-content-icon{height:1.5rem;width:1.5rem}.content-icon-container{display:flex;float:right;gap:.5rem;margin-bottom:1rem;margin-left:1rem;margin-top:1.5rem}.content-icon-container .edit-this-page svg,.content-icon-container .view-this-page svg{color:inherit;height:1.25rem;width:1.25rem}.sidebar-toggle{display:none;position:absolute}.sidebar-toggle[name=__toc]{left:20px}.sidebar-toggle:checked{left:40px}.overlay{background-color:rgba(0,0,0,.54);height:0;opacity:0;position:fixed;top:0;transition:width 0ms,height 0ms,opacity .25s ease-out;width:0}.sidebar-overlay{z-index:20}.toc-overlay{z-index:40}.sidebar-drawer{transition:left .25s ease-in-out;z-index:30}.toc-drawer{transition:right .25s ease-in-out;z-index:50}#__navigation:checked~.sidebar-overlay{height:100%;opacity:1;width:100%}#__navigation:checked~.page .sidebar-drawer{left:0;top:0}#__toc:checked~.toc-overlay{height:100%;opacity:1;width:100%}#__toc:checked~.page .toc-drawer{right:0;top:0}.back-to-top{background:var(--color-background-primary);border-radius:1rem;box-shadow:0 .2rem .5rem rgba(0,0,0,.05),0 0 1px 0 hsla(220,9%,46%,.502);display:none;font-size:.8125rem;left:0;margin-left:50%;padding:.5rem .75rem .5rem .5rem;position:fixed;text-decoration:none;top:1rem;transform:translateX(-50%);z-index:10}.back-to-top svg{height:1rem;width:1rem;fill:currentColor;display:inline-block}.back-to-top span{margin-left:.25rem}.show-back-to-top .back-to-top{align-items:center;display:flex}@media(min-width:97em){html{font-size:110%}}@media(max-width:82em){.toc-content-icon{display:flex}.toc-drawer{border-left:1px solid var(--color-background-muted);height:100vh;position:fixed;right:-15em;top:0}.toc-tree{border-left:none;font-size:var(--toc-font-size--mobile)}.sidebar-drawer{width:calc(50% - 18.5em)}}@media(max-width:67em){.nav-overlay-icon{display:flex}.sidebar-drawer{height:100vh;left:-15em;position:fixed;top:0;width:15em}.theme-toggle-header,.toc-header-icon{display:flex}.theme-toggle-content,.toc-content-icon{display:none}.mobile-header{align-items:center;display:flex;justify-content:space-between;position:sticky;top:0}.mobile-header .header-left,.mobile-header .header-right{display:flex;height:var(--header-height);padding:0 var(--header-padding)}.mobile-header .header-left label,.mobile-header .header-right label{height:100%;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:100%}.nav-overlay-icon .icon,.theme-toggle svg{height:1.5rem;width:1.5rem}:target{scroll-margin-top:calc(var(--header-height) + 2.5rem)}.back-to-top{top:calc(var(--header-height) + .5rem)}.page{flex-direction:column;justify-content:center}.content{margin-left:auto;margin-right:auto}}@media(max-width:52em){.content{overflow-x:auto;width:100%}}@media(max-width:46em){.content{padding:0 1em}article aside.sidebar{float:none;margin:1rem 0;width:100%}}.admonition,.topic{background:var(--color-admonition-background);border-radius:.2rem;box-shadow:0 .2rem .5rem rgba(0,0,0,.05),0 0 .0625rem rgba(0,0,0,.1);font-size:var(--admonition-font-size);margin:1rem auto;overflow:hidden;padding:0 .5rem .5rem;page-break-inside:avoid}.admonition>:nth-child(2),.topic>:nth-child(2){margin-top:0}.admonition>:last-child,.topic>:last-child{margin-bottom:0}.admonition p.admonition-title,p.topic-title{font-size:var(--admonition-title-font-size);font-weight:500;line-height:1.3;margin:0 -.5rem .5rem;padding:.4rem .5rem .4rem 2rem;position:relative}.admonition p.admonition-title:before,p.topic-title:before{content:"";height:1rem;left:.5rem;position:absolute;width:1rem}p.admonition-title{background-color:var(--color-admonition-title-background)}p.admonition-title:before{background-color:var(--color-admonition-title);-webkit-mask-image:var(--icon-admonition-default);mask-image:var(--icon-admonition-default);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat}p.topic-title{background-color:var(--color-topic-title-background)}p.topic-title:before{background-color:var(--color-topic-title);-webkit-mask-image:var(--icon-topic-default);mask-image:var(--icon-topic-default);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat}.admonition{border-left:.2rem solid var(--color-admonition-title)}.admonition.caution{border-left-color:var(--color-admonition-title--caution)}.admonition.caution>.admonition-title{background-color:var(--color-admonition-title-background--caution)}.admonition.caution>.admonition-title:before{background-color:var(--color-admonition-title--caution);-webkit-mask-image:var(--icon-spark);mask-image:var(--icon-spark)}.admonition.warning{border-left-color:var(--color-admonition-title--warning)}.admonition.warning>.admonition-title{background-color:var(--color-admonition-title-background--warning)}.admonition.warning>.admonition-title:before{background-color:var(--color-admonition-title--warning);-webkit-mask-image:var(--icon-warning);mask-image:var(--icon-warning)}.admonition.danger{border-left-color:var(--color-admonition-title--danger)}.admonition.danger>.admonition-title{background-color:var(--color-admonition-title-background--danger)}.admonition.danger>.admonition-title:before{background-color:var(--color-admonition-title--danger);-webkit-mask-image:var(--icon-spark);mask-image:var(--icon-spark)}.admonition.attention{border-left-color:var(--color-admonition-title--attention)}.admonition.attention>.admonition-title{background-color:var(--color-admonition-title-background--attention)}.admonition.attention>.admonition-title:before{background-color:var(--color-admonition-title--attention);-webkit-mask-image:var(--icon-warning);mask-image:var(--icon-warning)}.admonition.error{border-left-color:var(--color-admonition-title--error)}.admonition.error>.admonition-title{background-color:var(--color-admonition-title-background--error)}.admonition.error>.admonition-title:before{background-color:var(--color-admonition-title--error);-webkit-mask-image:var(--icon-failure);mask-image:var(--icon-failure)}.admonition.hint{border-left-color:var(--color-admonition-title--hint)}.admonition.hint>.admonition-title{background-color:var(--color-admonition-title-background--hint)}.admonition.hint>.admonition-title:before{background-color:var(--color-admonition-title--hint);-webkit-mask-image:var(--icon-question);mask-image:var(--icon-question)}.admonition.tip{border-left-color:var(--color-admonition-title--tip)}.admonition.tip>.admonition-title{background-color:var(--color-admonition-title-background--tip)}.admonition.tip>.admonition-title:before{background-color:var(--color-admonition-title--tip);-webkit-mask-image:var(--icon-info);mask-image:var(--icon-info)}.admonition.important{border-left-color:var(--color-admonition-title--important)}.admonition.important>.admonition-title{background-color:var(--color-admonition-title-background--important)}.admonition.important>.admonition-title:before{background-color:var(--color-admonition-title--important);-webkit-mask-image:var(--icon-flame);mask-image:var(--icon-flame)}.admonition.note{border-left-color:var(--color-admonition-title--note)}.admonition.note>.admonition-title{background-color:var(--color-admonition-title-background--note)}.admonition.note>.admonition-title:before{background-color:var(--color-admonition-title--note);-webkit-mask-image:var(--icon-pencil);mask-image:var(--icon-pencil)}.admonition.seealso{border-left-color:var(--color-admonition-title--seealso)}.admonition.seealso>.admonition-title{background-color:var(--color-admonition-title-background--seealso)}.admonition.seealso>.admonition-title:before{background-color:var(--color-admonition-title--seealso);-webkit-mask-image:var(--icon-info);mask-image:var(--icon-info)}.admonition.admonition-todo{border-left-color:var(--color-admonition-title--admonition-todo)}.admonition.admonition-todo>.admonition-title{background-color:var(--color-admonition-title-background--admonition-todo)}.admonition.admonition-todo>.admonition-title:before{background-color:var(--color-admonition-title--admonition-todo);-webkit-mask-image:var(--icon-pencil);mask-image:var(--icon-pencil)}.admonition-todo>.admonition-title{text-transform:uppercase}dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) dd{margin-left:2rem}dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) dd>:first-child{margin-top:.125rem}dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .field-list,dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) dd>:last-child{margin-bottom:.75rem}dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .field-list>dt{font-size:var(--font-size--small);text-transform:uppercase}dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .field-list dd:empty{margin-bottom:.5rem}dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .field-list dd>ul{margin-left:-1.2rem}dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .field-list dd>ul>li>p:nth-child(2){margin-top:0}dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .field-list dd>ul>li>p+p:last-child:empty{margin-bottom:0;margin-top:0}dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple)>dt{color:var(--color-api-overall)}.sig:not(.sig-inline){background:var(--color-api-background);border-radius:.25rem;font-family:var(--font-stack--monospace);font-size:var(--api-font-size);font-weight:700;margin-left:-.25rem;margin-right:-.25rem;padding:.25rem .5rem .25rem 3em;text-indent:-2.5em;transition:background .1s ease-out}.sig:not(.sig-inline):hover{background:var(--color-api-background-hover)}.sig:not(.sig-inline) a.reference .viewcode-link{font-weight:400;width:4.25rem}em.property{font-style:normal}em.property:first-child{color:var(--color-api-keyword)}.sig-name{color:var(--color-api-name)}.sig-prename{color:var(--color-api-pre-name);font-weight:400}.sig-paren{color:var(--color-api-paren)}.sig-param{font-style:normal}div.deprecated,div.versionadded,div.versionchanged,div.versionremoved{border-left:.1875rem solid;border-radius:.125rem;padding-left:.75rem}div.deprecated p,div.versionadded p,div.versionchanged p,div.versionremoved p{margin-bottom:.125rem;margin-top:.125rem}div.versionadded{border-color:var(--color-api-added-border)}div.versionadded .versionmodified{color:var(--color-api-added)}div.versionchanged{border-color:var(--color-api-changed-border)}div.versionchanged .versionmodified{color:var(--color-api-changed)}div.deprecated{border-color:var(--color-api-deprecated-border)}div.deprecated .versionmodified{color:var(--color-api-deprecated)}div.versionremoved{border-color:var(--color-api-removed-border)}div.versionremoved .versionmodified{color:var(--color-api-removed)}.viewcode-back,.viewcode-link{float:right;text-align:right}.line-block{margin-bottom:.75rem;margin-top:.5rem}.line-block .line-block{margin-bottom:0;margin-top:0;padding-left:1rem}.code-block-caption,article p.caption,table>caption{font-size:var(--font-size--small);text-align:center}.toctree-wrapper.compound .caption,.toctree-wrapper.compound :not(.caption)>.caption-text{font-size:var(--font-size--small);margin-bottom:0;text-align:initial;text-transform:uppercase}.toctree-wrapper.compound>ul{margin-bottom:0;margin-top:0}.sig-inline,code.literal{background:var(--color-inline-code-background);border-radius:.2em;font-size:var(--font-size--small--2);padding:.1em .2em}pre.literal-block .sig-inline,pre.literal-block code.literal{font-size:inherit;padding:0}p .sig-inline,p code.literal{border:1px solid var(--color-background-border)}.sig-inline{font-family:var(--font-stack--monospace)}div[class*=" highlight-"],div[class^=highlight-]{display:flex;margin:1em 0}div[class*=" highlight-"] .table-wrapper,div[class^=highlight-] .table-wrapper,pre{margin:0;padding:0}pre{overflow:auto}article[role=main] .highlight pre{line-height:1.5}.highlight pre,pre.literal-block{font-size:var(--code-font-size);padding:.625rem .875rem}pre.literal-block{background-color:var(--color-code-background);border-radius:.2rem;color:var(--color-code-foreground);margin-bottom:1rem;margin-top:1rem}.highlight{border-radius:.2rem;width:100%}.highlight .gp,.highlight span.linenos{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}.highlight .hll{display:block;margin-left:-.875rem;margin-right:-.875rem;padding-left:.875rem;padding-right:.875rem}.code-block-caption{background-color:var(--color-code-background);border-bottom:1px solid;border-radius:.25rem;border-bottom-left-radius:0;border-bottom-right-radius:0;border-color:var(--color-background-border);color:var(--color-code-foreground);display:flex;font-weight:300;padding:.625rem .875rem}.code-block-caption+div[class]{margin-top:0}.code-block-caption+div[class] pre{border-top-left-radius:0;border-top-right-radius:0}.highlighttable{display:block;width:100%}.highlighttable tbody{display:block}.highlighttable tr{display:flex}.highlighttable td.linenos{background-color:var(--color-code-background);border-bottom-left-radius:.2rem;border-top-left-radius:.2rem;color:var(--color-code-foreground);padding:.625rem 0 .625rem .875rem}.highlighttable .linenodiv{box-shadow:-.0625rem 0 var(--color-foreground-border) inset;font-size:var(--code-font-size);padding-right:.875rem}.highlighttable td.code{display:block;flex:1;overflow:hidden;padding:0}.highlighttable td.code .highlight{border-bottom-left-radius:0;border-top-left-radius:0}.highlight span.linenos{box-shadow:-.0625rem 0 var(--color-foreground-border) inset;display:inline-block;margin-right:.875rem;padding-left:0;padding-right:.875rem}.footnote-reference{font-size:var(--font-size--small--4);vertical-align:super}dl.footnote.brackets{color:var(--color-foreground-secondary);display:grid;font-size:var(--font-size--small);grid-template-columns:max-content auto}dl.footnote.brackets dt{margin:0}dl.footnote.brackets dt>.fn-backref{margin-left:.25rem}dl.footnote.brackets dt:after{content:":"}dl.footnote.brackets dt .brackets:before{content:"["}dl.footnote.brackets dt .brackets:after{content:"]"}dl.footnote.brackets dd{margin:0;padding:0 1rem}aside.footnote{color:var(--color-foreground-secondary);font-size:var(--font-size--small)}aside.footnote>span,div.citation>span{float:left;font-weight:500;padding-right:.25rem}aside.footnote>:not(span),div.citation>p{margin-left:2rem}img{box-sizing:border-box;height:auto;max-width:100%}article .figure,article figure{border-radius:.2rem;margin:0}article .figure :last-child,article figure :last-child{margin-bottom:0}article .align-left{clear:left;float:left;margin:0 1rem 1rem}article .align-right{clear:right;float:right;margin:0 1rem 1rem}article .align-center,article .align-default{display:block;margin-left:auto;margin-right:auto;text-align:center}article table.align-default{display:table;text-align:initial}.domainindex-jumpbox,.genindex-jumpbox{border-bottom:1px solid var(--color-background-border);border-top:1px solid var(--color-background-border);padding:.25rem}.domainindex-section h2,.genindex-section h2{margin-bottom:.5rem;margin-top:.75rem}.domainindex-section ul,.genindex-section ul{margin-bottom:0;margin-top:0}ol,ul{margin-bottom:1rem;margin-top:1rem;padding-left:1.2rem}ol li>p:first-child,ul li>p:first-child{margin-bottom:.25rem;margin-top:.25rem}ol li>p:last-child,ul li>p:last-child{margin-top:.25rem}ol li>ol,ol li>ul,ul li>ol,ul li>ul{margin-bottom:.5rem;margin-top:.5rem}ol.arabic{list-style:decimal}ol.loweralpha{list-style:lower-alpha}ol.upperalpha{list-style:upper-alpha}ol.lowerroman{list-style:lower-roman}ol.upperroman{list-style:upper-roman}.simple li>ol,.simple li>ul,.toctree-wrapper li>ol,.toctree-wrapper li>ul{margin-bottom:0;margin-top:0}.field-list dt,.option-list dt,dl.footnote dt,dl.glossary dt,dl.simple dt,dl:not([class]) dt{font-weight:500;margin-top:.25rem}.field-list dt+dt,.option-list dt+dt,dl.footnote dt+dt,dl.glossary dt+dt,dl.simple dt+dt,dl:not([class]) dt+dt{margin-top:0}.field-list dt .classifier:before,.option-list dt .classifier:before,dl.footnote dt .classifier:before,dl.glossary dt .classifier:before,dl.simple dt .classifier:before,dl:not([class]) dt .classifier:before{content:":";margin-left:.2rem;margin-right:.2rem}.field-list dd ul,.field-list dd>p:first-child,.option-list dd ul,.option-list dd>p:first-child,dl.footnote dd ul,dl.footnote dd>p:first-child,dl.glossary dd ul,dl.glossary dd>p:first-child,dl.simple dd ul,dl.simple dd>p:first-child,dl:not([class]) dd ul,dl:not([class]) dd>p:first-child{margin-top:.125rem}.field-list dd ul,.option-list dd ul,dl.footnote dd ul,dl.glossary dd ul,dl.simple dd ul,dl:not([class]) dd ul{margin-bottom:.125rem}.math-wrapper{overflow-x:auto;width:100%}div.math{position:relative;text-align:center}div.math .headerlink,div.math:focus .headerlink{display:none}div.math:hover .headerlink{display:inline-block}div.math span.eqno{position:absolute;right:.5rem;top:50%;transform:translateY(-50%);z-index:1}abbr[title]{cursor:help}.problematic{color:var(--color-problematic)}kbd:not(.compound){background-color:var(--color-background-secondary);border:1px solid var(--color-foreground-border);border-radius:.2rem;box-shadow:0 .0625rem 0 rgba(0,0,0,.2),inset 0 0 0 .125rem var(--color-background-primary);color:var(--color-foreground-primary);display:inline-block;font-size:var(--font-size--small--3);margin:0 .2rem;padding:0 .2rem;vertical-align:text-bottom}blockquote{background:var(--color-background-secondary);border-left:4px solid var(--color-background-border);margin-left:0;margin-right:0;padding:.5rem 1rem}blockquote .attribution{font-weight:600;text-align:right}blockquote.highlights,blockquote.pull-quote{font-size:1.25em}blockquote.epigraph,blockquote.pull-quote{border-left-width:0;border-radius:.5rem}blockquote.highlights{background:transparent;border-left-width:0}p .reference img{vertical-align:middle}p.rubric{font-size:1.125em;font-weight:700;line-height:1.25}dd p.rubric{font-size:var(--font-size--small);font-weight:inherit;line-height:inherit;text-transform:uppercase}article .sidebar{background-color:var(--color-background-secondary);border:1px solid var(--color-background-border);border-radius:.2rem;clear:right;float:right;margin-left:1rem;margin-right:0;width:30%}article .sidebar>*{padding-left:1rem;padding-right:1rem}article .sidebar>ol,article .sidebar>ul{padding-left:2.2rem}article .sidebar .sidebar-title{border-bottom:1px solid var(--color-background-border);font-weight:500;margin:0;padding:.5rem 1rem}.table-wrapper{margin-bottom:.5rem;margin-top:1rem;overflow-x:auto;padding:.2rem .2rem .75rem;width:100%}table.docutils{border-collapse:collapse;border-radius:.2rem;border-spacing:0;box-shadow:0 .2rem .5rem rgba(0,0,0,.05),0 0 .0625rem rgba(0,0,0,.1)}table.docutils th{background:var(--color-table-header-background)}table.docutils td,table.docutils th{border-bottom:1px solid var(--color-table-border);border-left:1px solid var(--color-table-border);border-right:1px solid var(--color-table-border);padding:0 .25rem}table.docutils td p,table.docutils th p{margin:.25rem}table.docutils td:first-child,table.docutils th:first-child{border-left:none}table.docutils td:last-child,table.docutils th:last-child{border-right:none}table.docutils td.text-left,table.docutils th.text-left{text-align:left}table.docutils td.text-right,table.docutils th.text-right{text-align:right}table.docutils td.text-center,table.docutils th.text-center{text-align:center}:target{scroll-margin-top:2.5rem}@media(max-width:67em){:target{scroll-margin-top:calc(2.5rem + var(--header-height))}section>span:target{scroll-margin-top:calc(2.8rem + var(--header-height))}}.headerlink{font-weight:100;-webkit-user-select:none;-moz-user-select:none;user-select:none}.code-block-caption>.headerlink,dl dt>.headerlink,figcaption p>.headerlink,h1>.headerlink,h2>.headerlink,h3>.headerlink,h4>.headerlink,h5>.headerlink,h6>.headerlink,p.caption>.headerlink,table>caption>.headerlink{margin-left:.5rem;visibility:hidden}.code-block-caption:hover>.headerlink,dl dt:hover>.headerlink,figcaption p:hover>.headerlink,h1:hover>.headerlink,h2:hover>.headerlink,h3:hover>.headerlink,h4:hover>.headerlink,h5:hover>.headerlink,h6:hover>.headerlink,p.caption:hover>.headerlink,table>caption:hover>.headerlink{visibility:visible}.code-block-caption>.toc-backref,dl dt>.toc-backref,figcaption p>.toc-backref,h1>.toc-backref,h2>.toc-backref,h3>.toc-backref,h4>.toc-backref,h5>.toc-backref,h6>.toc-backref,p.caption>.toc-backref,table>caption>.toc-backref{color:inherit;text-decoration-line:none}figure:hover>figcaption>p>.headerlink,table:hover>caption>.headerlink{visibility:visible}:target>h1:first-of-type,:target>h2:first-of-type,:target>h3:first-of-type,:target>h4:first-of-type,:target>h5:first-of-type,:target>h6:first-of-type,span:target~h1:first-of-type,span:target~h2:first-of-type,span:target~h3:first-of-type,span:target~h4:first-of-type,span:target~h5:first-of-type,span:target~h6:first-of-type{background-color:var(--color-highlight-on-target)}:target>h1:first-of-type code.literal,:target>h2:first-of-type code.literal,:target>h3:first-of-type code.literal,:target>h4:first-of-type code.literal,:target>h5:first-of-type code.literal,:target>h6:first-of-type code.literal,span:target~h1:first-of-type code.literal,span:target~h2:first-of-type code.literal,span:target~h3:first-of-type code.literal,span:target~h4:first-of-type code.literal,span:target~h5:first-of-type code.literal,span:target~h6:first-of-type code.literal{background-color:transparent}.literal-block-wrapper:target .code-block-caption,.this-will-duplicate-information-and-it-is-still-useful-here li :target,figure:target,table:target>caption{background-color:var(--color-highlight-on-target)}dt:target{background-color:var(--color-highlight-on-target)!important}.footnote-reference:target,.footnote>dt:target+dd{background-color:var(--color-highlight-on-target)}.guilabel{background-color:var(--color-guilabel-background);border:1px solid var(--color-guilabel-border);border-radius:.5em;color:var(--color-guilabel-text);font-size:.9em;padding:0 .3em}footer{display:flex;flex-direction:column;font-size:var(--font-size--small);margin-top:2rem}.bottom-of-page{align-items:center;border-top:1px solid var(--color-background-border);color:var(--color-foreground-secondary);display:flex;justify-content:space-between;line-height:1.5;margin-top:1rem;padding-bottom:1rem;padding-top:1rem}@media(max-width:46em){.bottom-of-page{flex-direction:column-reverse;gap:.25rem;text-align:center}}.bottom-of-page .left-details{font-size:var(--font-size--small)}.bottom-of-page .right-details{display:flex;flex-direction:column;gap:.25rem;text-align:right}.bottom-of-page .icons{display:flex;font-size:1rem;gap:.25rem;justify-content:flex-end}.bottom-of-page .icons a{text-decoration:none}.bottom-of-page .icons img,.bottom-of-page .icons svg{font-size:1.125rem;height:1em;width:1em}.related-pages a{align-items:center;display:flex;text-decoration:none}.related-pages a:hover .page-info .title{color:var(--color-link);text-decoration:underline;text-decoration-color:var(--color-link-underline)}.related-pages a svg.furo-related-icon,.related-pages a svg.furo-related-icon>use{color:var(--color-foreground-border);flex-shrink:0;height:.75rem;margin:0 .5rem;width:.75rem}.related-pages a.next-page{clear:right;float:right;max-width:50%;text-align:right}.related-pages a.prev-page{clear:left;float:left;max-width:50%}.related-pages a.prev-page svg{transform:rotate(180deg)}.page-info{display:flex;flex-direction:column;overflow-wrap:anywhere}.next-page .page-info{align-items:flex-end}.page-info .context{align-items:center;color:var(--color-foreground-muted);display:flex;font-size:var(--font-size--small);padding-bottom:.1rem;text-decoration:none}ul.search{list-style:none;padding-left:0}ul.search li{border-bottom:1px solid var(--color-background-border);padding:1rem 0}[role=main] .highlighted{background-color:var(--color-highlighted-background);color:var(--color-highlighted-text)}.sidebar-brand{display:flex;flex-direction:column;flex-shrink:0;padding:var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal);text-decoration:none}.sidebar-brand-text{color:var(--color-sidebar-brand-text);font-size:1.5rem;overflow-wrap:break-word}.sidebar-brand-text,.sidebar-logo-container{margin:var(--sidebar-item-spacing-vertical) 0}.sidebar-logo{display:block;margin:0 auto;max-width:100%}.sidebar-search-container{align-items:center;background:var(--color-sidebar-search-background);display:flex;margin-top:var(--sidebar-search-space-above);position:relative}.sidebar-search-container:focus-within,.sidebar-search-container:hover{background:var(--color-sidebar-search-background--focus)}.sidebar-search-container:before{background-color:var(--color-sidebar-search-icon);content:"";height:var(--sidebar-search-icon-size);left:var(--sidebar-item-spacing-horizontal);-webkit-mask-image:var(--icon-search);mask-image:var(--icon-search);position:absolute;width:var(--sidebar-search-icon-size)}.sidebar-search{background:transparent;border:none;border-bottom:1px solid var(--color-sidebar-search-border);border-top:1px solid var(--color-sidebar-search-border);box-sizing:border-box;color:var(--color-sidebar-search-foreground);padding:var(--sidebar-search-input-spacing-vertical) var(--sidebar-search-input-spacing-horizontal) var(--sidebar-search-input-spacing-vertical) calc(var(--sidebar-item-spacing-horizontal) + var(--sidebar-search-input-spacing-horizontal) + var(--sidebar-search-icon-size));width:100%;z-index:10}.sidebar-search:focus{outline:none}.sidebar-search::-moz-placeholder{font-size:var(--sidebar-search-input-font-size)}.sidebar-search::placeholder{font-size:var(--sidebar-search-input-font-size)}#searchbox .highlight-link{margin:0;padding:var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal) 0;text-align:center}#searchbox .highlight-link a{color:var(--color-sidebar-search-icon);font-size:var(--font-size--small--2)}.sidebar-tree{font-size:var(--sidebar-item-font-size);margin-bottom:var(--sidebar-item-spacing-vertical);margin-top:var(--sidebar-tree-space-above)}.sidebar-tree ul{display:flex;flex-direction:column;list-style:none;margin-bottom:0;margin-top:0;padding:0}.sidebar-tree li{margin:0;position:relative}.sidebar-tree li>ul{margin-left:var(--sidebar-item-spacing-horizontal)}.sidebar-tree .icon,.sidebar-tree .reference{color:var(--color-sidebar-link-text)}.sidebar-tree .reference{box-sizing:border-box;display:inline-block;height:100%;line-height:var(--sidebar-item-line-height);overflow-wrap:anywhere;padding:var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal);text-decoration:none;width:100%}.sidebar-tree .reference:hover{background:var(--color-sidebar-item-background--hover);color:var(--color-sidebar-link-text)}.sidebar-tree .reference.external:after{color:var(--color-sidebar-link-text);content:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23607D8B' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' viewBox='0 0 24 24'%3E%3Cpath stroke='none' d='M0 0h24v24H0z'/%3E%3Cpath d='M11 7H6a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h9a2 2 0 0 0 2-2v-5M10 14 20 4M15 4h5v5'/%3E%3C/svg%3E");margin:0 .25rem;vertical-align:middle}.sidebar-tree .current-page>.reference{font-weight:700}.sidebar-tree label{align-items:center;cursor:pointer;display:flex;height:var(--sidebar-item-height);justify-content:center;position:absolute;right:0;top:0;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:var(--sidebar-expander-width)}.sidebar-tree .caption,.sidebar-tree :not(.caption)>.caption-text{color:var(--color-sidebar-caption-text);font-size:var(--sidebar-caption-font-size);font-weight:700;margin:var(--sidebar-caption-space-above) 0 0 0;padding:var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal);text-transform:uppercase}.sidebar-tree li.has-children>.reference{padding-right:var(--sidebar-expander-width)}.sidebar-tree .toctree-l1>.reference,.sidebar-tree .toctree-l1>label .icon{color:var(--color-sidebar-link-text--top-level)}.sidebar-tree label{background:var(--color-sidebar-item-expander-background)}.sidebar-tree label:hover{background:var(--color-sidebar-item-expander-background--hover)}.sidebar-tree .current>.reference{background:var(--color-sidebar-item-background--current)}.sidebar-tree .current>.reference:hover{background:var(--color-sidebar-item-background--hover)}.toctree-checkbox{display:none;position:absolute}.toctree-checkbox~ul{display:none}.toctree-checkbox~label .icon svg{transform:rotate(90deg)}.toctree-checkbox:checked~ul{display:block}.toctree-checkbox:checked~label .icon svg{transform:rotate(-90deg)}.toc-title-container{padding:var(--toc-title-padding);padding-top:var(--toc-spacing-vertical)}.toc-title{color:var(--color-toc-title-text);font-size:var(--toc-title-font-size);padding-left:var(--toc-spacing-horizontal);text-transform:uppercase}.no-toc{display:none}.toc-tree-container{padding-bottom:var(--toc-spacing-vertical)}.toc-tree{border-left:1px solid var(--color-background-border);font-size:var(--toc-font-size);line-height:1.3;padding-left:calc(var(--toc-spacing-horizontal) - var(--toc-item-spacing-horizontal))}.toc-tree>ul>li:first-child{padding-top:0}.toc-tree>ul>li:first-child>ul{padding-left:0}.toc-tree>ul>li:first-child>a{display:none}.toc-tree ul{list-style-type:none;margin-bottom:0;margin-top:0;padding-left:var(--toc-item-spacing-horizontal)}.toc-tree li{padding-top:var(--toc-item-spacing-vertical)}.toc-tree li.scroll-current>.reference{color:var(--color-toc-item-text--active);font-weight:700}.toc-tree a.reference{color:var(--color-toc-item-text);overflow-wrap:anywhere;text-decoration:none}.toc-scroll{max-height:100vh;overflow-y:scroll}.contents:not(.this-will-duplicate-information-and-it-is-still-useful-here){background:rgba(255,0,0,.25);color:var(--color-problematic)}.contents:not(.this-will-duplicate-information-and-it-is-still-useful-here):before{content:"ERROR: Adding a table of contents in Furo-based documentation is unnecessary, and does not work well with existing styling. Add a 'this-will-duplicate-information-and-it-is-still-useful-here' class, if you want an escape hatch."}.text-align\:left>p{text-align:left}.text-align\:center>p{text-align:center}.text-align\:right>p{text-align:right} +/*# sourceMappingURL=furo.css.map*/ \ No newline at end of file diff --git a/main/_static/styles/furo.css.map b/main/_static/styles/furo.css.map new file mode 100644 index 00000000..0ee3acbe --- /dev/null +++ b/main/_static/styles/furo.css.map @@ -0,0 +1 @@ +{"version":3,"file":"styles/furo.css","mappings":"AAAA,2EAA2E,CAU3E,KACE,gBAAiB,CACjB,6BACF,CASA,KACE,QACF,CAMA,KACE,aACF,CAOA,GACE,aAAc,CACd,cACF,CAUA,GACE,sBAAuB,CACvB,QAAS,CACT,gBACF,CAOA,IACE,+BAAiC,CACjC,aACF,CASA,EACE,4BACF,CAOA,YACE,kBAAmB,CACnB,yBAA0B,CAC1B,gCACF,CAMA,SAEE,kBACF,CAOA,cAGE,+BAAiC,CACjC,aACF,CAeA,QAEE,aAAc,CACd,aAAc,CACd,iBAAkB,CAClB,uBACF,CAEA,IACE,aACF,CAEA,IACE,SACF,CASA,IACE,iBACF,CAUA,sCAKE,mBAAoB,CACpB,cAAe,CACf,gBAAiB,CACjB,QACF,CAOA,aAEE,gBACF,CAOA,cAEE,mBACF,CAMA,gDAIE,yBACF,CAMA,wHAIE,iBAAkB,CAClB,SACF,CAMA,4GAIE,6BACF,CAMA,SACE,0BACF,CASA,OACE,qBAAsB,CACtB,aAAc,CACd,aAAc,CACd,cAAe,CACf,SAAU,CACV,kBACF,CAMA,SACE,uBACF,CAMA,SACE,aACF,CAOA,6BAEE,qBAAsB,CACtB,SACF,CAMA,kFAEE,WACF,CAOA,cACE,4BAA6B,CAC7B,mBACF,CAMA,yCACE,uBACF,CAOA,6BACE,yBAA0B,CAC1B,YACF,CASA,QACE,aACF,CAMA,QACE,iBACF,CAiBA,kBACE,YACF,CCvVA,aAcE,kEACE,uBAOF,WACE,iDAMF,gCACE,wBAEF,qCAEE,uBADA,uBACA,CAEF,SACE,wBAtBA,CCpBJ,iBAGE,qBAEA,sBACA,0BAFA,oBAHA,4BACA,oBAKA,6BAIA,2CAFA,mBACA,sCAFA,4BAGA,CAEF,gBACE,aCTF,KCGE,mHAEA,wGAEA,wCAAyC,CAEzC,wBAAyB,CACzB,wBAAyB,CACzB,4BAA6B,CAC7B,yBAA0B,CAC1B,2BAA4B,CAG5B,sDAAuD,CACvD,gDAAiD,CACjD,wDAAyD,CAGzD,0CAA2C,CAC3C,gDAAiD,CACjD,gDAAiD,CAKjD,gCAAiC,CACjC,sCAAuC,CAGvC,2CAA4C,CAG5C,uCAAwC,CCjCxC,+FAGA,uBAAwB,CAGxB,iCAAkC,CAClC,kCAAmC,CAEnC,+BAAgC,CAChC,sCAAuC,CACvC,sCAAuC,CACvC,qGAIA,mDAAoD,CAEpD,mCAAoC,CACpC,8CAA+C,CAC/C,gDAAiD,CACjD,kCAAmC,CACnC,6DAA8D,CAG9D,6BAA8B,CAC9B,6BAA8B,CAC9B,+BAAgC,CAChC,kCAAmC,CACnC,kCAAmC,CCPjC,+jBCYA,iqCAZF,iaCVA,8KAOA,4SAWA,4SAUA,0CACA,gEAGA,0CAGA,gEAGA,yCACA,+DAIA,4CACA,kEAGA,wCAUA,8DACA,uCAGA,4DACA,sCACA,2DAGA,4CACA,kEACA,uCAGA,6DACA,2GAGA,sHAEA,yFAEA,+CACA,+EAGA,4MAOA,gCACA,sHAIA,kCACA,uEACA,gEACA,4DACA,kEAGA,2DACA,sDACA,0CACA,8CACA,wGAGA,0BACA,iCAGA,+DACA,+BACA,sCACA,+DAEA,kGACA,oCACA,yDACA,sCL7HF,kCAEA,sDAIA,0CK2HE,kEAIA,oDACA,sDAGA,oCACA,oEAEA,0DACA,qDAIA,oDACA,6DAIA,iEAIA,2DAIA,2DAGA,4DACA,gEAIA,gEAEA,gFAEA,oNASA,qDLxKE,gFAGE,4DAIF,oEKkHF,yEAEA,6DAGA,0DAEA,uDACA,qDACA,wDAIA,6DAIA,yDACA,2DAIA,uCAGA,wCACA,sDAGA,+CAGA,6DAEA,iDACA,+DAEA,wDAEA,sEAMA,0DACA,sBACA,mEL9JI,wEAEA,iCACE,+BAMN,wEAGA,iCACE,kFAEA,uEAIF,gEACE,8BAGF,qEMvDA,sCAKA,wFAKA,iCAIA,0BAWA,iCACA,4BACA,mCAGA,+BAEA,sCACA,4BAEA,mCAEA,sCAKA,sDAIA,gCAEA,gEAQF,wCAME,sBACA,kCAKA,uBAEA,gEAIA,2BAIA,mCAEA,qCACA,iCAGE,+BACA,wEAEE,iCACA,kFAGF,6BACA,0CACF,kCAEE,8BACE,8BACA,qEAEE,sCACA,wFCnFN,iCAGF,2DAEE,4BACA,oCAGA,mIAGA,4HACE,gEAMJ,+CAGE,sBACA,yCAEF,uBAEE,sEAKA,gDACA,kEAGA,iFAGE,YAGF,EACA,4HAQF,mBACE,6BACA,mBACA,wCACA,wCACA,2CAIA,eAGA,mBAKE,mBAGA,CAJA,uCACA,iBAFF,gBACE,CAKE,mBACA,mBAGJ,oBAIF,+BAGE,kDACA,OADA,kBAGA,CAFA,gBAEA,mBACA,oBAEA,sCACA,OAGF,cAHE,WAGF,GAEE,oBACA,CAHF,gBAGE,CC9Gc,YDiHd,+CAIF,SAEE,CAPF,UACE,wBAMA,4BAEA,GAGA,uBACA,CAJA,yBAGA,CACA,iDAKA,2CAGA,2DAQA,iBACA,uCAGA,kEAKE,SAKJ,8BACE,yDACA,2BAEA,oBACA,8BAEA,yDAEE,4BAEJ,uCACE,CACA,iEAGA,CAEA,wCACE,uBACA,kDAEA,0DAEE,CAJF,oBAIE,0GAWN,aACE,CAHA,YAGA,4HASA,+CAGF,sBACE,WACA,WAQA,4BAFF,0CAEE,CARA,qCAsBA,CAdA,iBAEA,kBACE,aADF,4BACE,WAMF,2BAGF,qCAEE,CAXE,UAWF,+BAGA,uBAEA,SAEA,0CAIE,CANF,qCAEA,CAIE,2DACE,gBAIN,+CAIA,CAEA,kDAKE,CAPF,8BAEA,CAOE,YACA,CAjBI,2BAGN,CAHM,WAcJ,UAGA,CAEA,2GAIF,iCAGE,8BAIA,qBACA,oBACF,uBAOI,0CAIA,CATF,6DAKE,CALF,sBASE,qCAKF,CACE,cACA,CAFF,sBAEE,CACA,+BAEA,qBAEE,WAKN,aACE,sCAGA,mBAEA,6BAMA,kCACA,CAJA,sBACA,aAEA,CAJA,eACA,MAIA,2FAEA,UAGA,YACA,sBACE,8BAEA,CALF,aACA,WAIE,OACA,oBAEF,uBACE,WAEF,YAFE,UAEF,eAgBA,kBACE,CAhBA,qDAQF,qCAGF,CAGI,YACF,CAJF,2BAGI,CAEA,eACA,qBAGA,mEAEA,qBACA,8BAIA,kBADF,kBACE,yBAEJ,oCAGI,qDAGA,CACA,8BAMF,oCACE,+CACF,gCAIA,YACE,yBAGA,2BAGA,mCAFA,cAEA,CAHA,YACA,CAEA,4BAIE,qCACA,cAFA,4BAEA,wCACE,CADF,aACE,sBAEA,mDAEN,CAFM,YAEN,iDAEE,uCAKA,+DAIA,kBAIA,CAJA,sBAIA,mBACA,0BACF,yBAEE,YAEJ,CAFI,YAQJ,UAFI,kBAEJ,CAJE,gBAEE,CAJJ,iBAMA,yFAOI,aEjbJ,eACE,cACA,iBAEA,aAFA,iBAEA,6BAEA,kCACA,mBAKA,gCAGA,CARA,QAEA,CAGA,UALA,qBAEA,qDAGA,CALA,OAQA,4BACE,cAGF,2BACE,gCAEJ,CAHE,UAGF,8CAGE,CAHF,UAGE,wCAGA,qBACA,CAFA,UAEA,6CAGA,yCAIA,sBAHA,UAGA,kCACE,OACA,CADA,KACA,cASA,2CAFF,kBACA,CACE,wEACA,CARA,YACA,CAKF,mBAFF,MACE,CAIE,gBAJF,iCADF,eALI,oBACA,CAKF,SAIE,2BADA,UACA,kBAEJ,WACE,kDACA,mBACE,kDACA,0EACA,uDAKJ,aACE,mDAII,CAJJ,6CAII,2BACA,uCACE,kEACA,+CACE,aACA,WADA,oBACA,CADA,UACA,4FALJ,4BAEE,mBADF,0CACE,CAFF,eACA,MACE,0DACA,wCACE,sGACA,WANN,yBACE,uCACA,CAFF,UAEE,2CACE,wFACA,cACE,kEACA,mEANN,yBACE,4DACA,sBACE,+EAEE,iEACA,qEANN,sCACE,CAGE,iBAHF,gBAGE,qBACE,CAJJ,uBACA,gDACE,wDACA,6DAHF,2CACA,CADA,gBACA,eACE,CAGE,sBANN,8BACE,CAII,iBAFF,4DACA,WACE,YADF,uCACE,6EACA,2BANN,8CACE,kDACA,0CACE,8BACA,yFACE,sBACA,sFALJ,mEACA,sBACE,kEACA,6EACE,uCACA,kEALJ,qGAEE,kEACA,6EACE,uCACA,kEALJ,8CACA,uDACE,sEACA,2EACE,sCACA,iEALJ,mGACA,qCACE,oDACA,0DACE,6GACA,gDAGR,yDCrEA,sEACE,CACA,6GACE,gEACF,iGAIF,wFACE,qDAGA,mGAEE,2CAEF,4FACE,gCACF,wGACE,8DAEE,6FAIA,iJAKN,6GACE,gDAKF,yDACA,qCAGA,6BACA,kBACA,qDAKA,oCAEA,+DAGA,2CAGE,oDAIA,oEAEE,qBAGJ,wDAEE,uCAEF,kEAGA,8CAEA,uDAIF,gEAIE,6BACA,gEAIA,+CACE,0EAIF,sDAEE,+DAGF,sCACA,8BACE,oCAEJ,wBACE,4FAEE,gBAEJ,yGAGI,kBAGJ,CCnHE,2MCFF,oBAGE,wGAKA,iCACE,CADF,wBACE,8GAQA,mBCjBJ,2GAIE,mBACA,6HAMA,YACE,mIAYF,eACA,CAHF,YAGE,4FAGE,8BAKF,uBAkBE,sCACA,CADA,qBAbA,wCAIA,CALF,8BACE,CADF,gBAKE,wCACA,CAOA,kDACA,CACA,kCAKF,6BAGA,4CACE,kDACA,eAGF,cACE,aACA,iBACA,yBACA,8BACA,WAGJ,2BACE,cAGA,+BACA,CAHA,eAGA,wCACA,YACA,iBACA,uEAGA,0BACA,2CAEA,8EAGI,qBACA,CAFF,kBAEE,kBAGN,0CAGE,mCAGA,4BAIA,gEACE,qCACA,8BAEA,gBACA,+CACA,iCAEF,iCAEE,gEACA,qCAGF,8BAEE,+BAIA,yCAEE,qBADA,gBACA,yBAKF,eACA,CAFF,YACE,CACA,iBACA,qDAEA,mDCvIJ,2FAOE,iCACA,CAEA,eACA,CAHA,kBAEA,CAFA,wBAGA,8BACA,eACE,CAFF,YAEE,0BACA,8CAGA,oBACE,oCAGA,kBACE,8DAEA,iBAEN,UACE,8BAIJ,+CAEE,qDAEF,kDAIE,YAEF,CAFE,YAEF,CCpCE,mFADA,kBAKE,CAJF,IAGA,aACE,mCAGA,iDACE,+BAEJ,wBAEE,mBAMA,6CAEF,CAJE,mBAEA,CAEF,kCAGE,CARF,kBACE,CAHA,eAUA,YACA,mBACA,CADA,UACA,wCC9BF,oBDkCE,wBCnCJ,uCACE,+BACA,+DACA,sBAGA,qBCDA,6CAIE,CAPF,uBAGA,CDGE,oBACF,yDAEE,CCDE,2CAGF,CAJA,kCACE,CDJJ,YACE,CAIA,eCTF,CDKE,uBCMA,gCACE,YAEF,oCAEE,wBACA,0BAIF,iBAEA,cADF,UACE,uBAEA,iCAEA,wCAEA,6CAMA,CAYF,gCATI,4BASJ,CAZE,mCAEE,iCAUJ,4BAGE,4DADA,+BACA,CAHF,qBAGE,sCACE,OAEF,iBAHA,SAGA,iHACE,2DAKF,CANA,8EAMA,uSAEE,kBAEF,+FACE,yCCjEJ,WACA,yBAGA,uBACA,gBAEA,uCAIA,CAJA,iCAIA,uCAGA,UACE,gBACA,qBAEA,0CClBJ,gBACE,KAGF,qBACE,YAGF,CAHE,cAGF,gCAEE,mBACA,iEAEA,oCACA,wCAEA,sBACA,WAEA,CAFA,YAEA,8EAEA,mCAFA,iBAEA,6BAIA,wEAKA,sDAIE,CARF,mDAIA,CAIE,cAEF,8CAIA,oBAFE,iBAEF,8CAGE,eAEF,CAFE,YAEF,OAEE,kBAGJ,CAJI,eACA,CAFF,mBAKF,yCCjDE,oBACA,CAFA,iBAEA,uCAKE,iBACA,qCAGA,mBCZJ,CDWI,gBCXJ,6BAEE,eACA,sBAGA,eAEA,sBACA,oDACA,iGAMA,gBAFE,YAEF,8FAME,iJClBF,YACA,gNAUE,6BAEF,oTAcI,kBACF,gHAIA,qBACE,eACF,qDACE,kBACF,6DACE,4BCxCJ,oBAEF,qCAEI,+CAGF,uBACE,uDAGJ,oBAiBI,kDACF,CAhBA,+CAaA,CAbA,oBAaA,0FAEE,CAFF,gGAdA,cACA,iBAaA,0BAGA,mQAIA,oNAEE,iBAGJ,CAHI,gBAFF,gBAKF,8CAYI,CAZJ,wCAYI,sVACE,iCAGA,uEAHA,QAGA,qXAKJ,iDAGF,CARM,+CACE,iDAIN,CALI,gBAQN,mHACE,gBAGF,2DACE,0EAOA,0EAGF,gBAEE,6DC/EA,kDACA,gCACA,qDAGA,qBACA,qDCFA,cACA,eAEA,yBAGF,sBAEE,iBACA,sNAWA,iBACE,kBACA,wRAgBA,kBAEA,iOAgBA,uCACE,uEAEA,kBAEF,qUAuBE,iDAIJ,CACA,geCxFF,4BAEE,CAQA,6JACA,iDAIA,sEAGA,mDAOF,iDAGE,4DAIA,8CACA,qDAEE,eAFF,cAEE,oBAEF,uBAFE,kCAGA,eACA,iBACA,mBAIA,mDACA,CAHA,uCAEA,CAJA,0CACA,CAIA,gBAJA,gBACA,oBADA,gBAIA,wBAEJ,gBAGE,6BACA,YAHA,iBAGA,gCACA,iEAEA,6CACA,sDACA,0BADA,wBACA,0BACA,oIAIA,mBAFA,YAEA,qBACA,0CAIE,uBAEF,CAHA,yBACE,CAEF,iDACE,mFAKJ,oCACE,CANE,aAKJ,CACE,qEAIA,YAFA,WAEA,CAHA,aACA,CAEA,gBACE,4BACA,sBADA,aACA,gCAMF,oCACA,yDACA,2CAEA,qBAGE,kBAEA,CACA,mCAIF,CARE,YACA,CAOF,iCAEE,CAPA,oBACA,CAQA,oBACE,uDAEJ,sDAGA,CAHA,cAGA,0BACE,oDAIA,oCACA,4BACA,sBAGA,cAEA,oFAGA,sBAEA,yDACE,CAIF,iBAJE,wBAIF,6CAHE,6CAKA,eACA,aACA,CADA,cACA,yCAGJ,kBACE,CAKA,iDAEA,CARF,aACE,4CAGA,kBAIA,wEAGA,wDAGA,kCAOA,iDAGA,CAPF,WAEE,sCAEA,CAJF,2CACE,CAMA,qCACA,+BARF,kBACE,qCAOA,iBAsBA,sBACE,CAvBF,WAKA,CACE,0DAIF,CALA,uDACE,CANF,sBAqBA,4CACA,CALA,gRAIA,YAEE,6CAEN,mCAEE,+CASA,6EAIA,4BChNA,SDmNA,qFCnNA,gDACA,sCAGA,qCACA,sDACA,CAKA,kDAGA,CARA,0CAQA,kBAGA,YACA,sBACA,iBAFA,gBADF,YACE,CAHA,SAKA,kBAEA,SAFA,iBAEA,uEAGA,CAEE,6CAFF,oCAgBI,CAdF,yBACE,qBACF,CAGF,oBACE,CAIF,WACE,CALA,2CAGA,uBACF,CACE,mFAGE,CALF,qBAEA,UAGE,gCAIF,sDAEA,CALE,oCAKF,yCC7CJ,oCACE,CD+CA,yXAQE,sCCrDJ,wCAGA,oCACE","sources":["webpack:///./node_modules/normalize.css/normalize.css","webpack:///./src/furo/assets/styles/base/_print.sass","webpack:///./src/furo/assets/styles/base/_screen-readers.sass","webpack:///./src/furo/assets/styles/base/_theme.sass","webpack:///./src/furo/assets/styles/variables/_fonts.scss","webpack:///./src/furo/assets/styles/variables/_spacing.scss","webpack:///./src/furo/assets/styles/variables/_icons.scss","webpack:///./src/furo/assets/styles/variables/_admonitions.scss","webpack:///./src/furo/assets/styles/variables/_colors.scss","webpack:///./src/furo/assets/styles/base/_typography.sass","webpack:///./src/furo/assets/styles/_scaffold.sass","webpack:///./src/furo/assets/styles/variables/_layout.scss","webpack:///./src/furo/assets/styles/content/_admonitions.sass","webpack:///./src/furo/assets/styles/content/_api.sass","webpack:///./src/furo/assets/styles/content/_blocks.sass","webpack:///./src/furo/assets/styles/content/_captions.sass","webpack:///./src/furo/assets/styles/content/_code.sass","webpack:///./src/furo/assets/styles/content/_footnotes.sass","webpack:///./src/furo/assets/styles/content/_images.sass","webpack:///./src/furo/assets/styles/content/_indexes.sass","webpack:///./src/furo/assets/styles/content/_lists.sass","webpack:///./src/furo/assets/styles/content/_math.sass","webpack:///./src/furo/assets/styles/content/_misc.sass","webpack:///./src/furo/assets/styles/content/_rubrics.sass","webpack:///./src/furo/assets/styles/content/_sidebar.sass","webpack:///./src/furo/assets/styles/content/_tables.sass","webpack:///./src/furo/assets/styles/content/_target.sass","webpack:///./src/furo/assets/styles/content/_gui-labels.sass","webpack:///./src/furo/assets/styles/components/_footer.sass","webpack:///./src/furo/assets/styles/components/_sidebar.sass","webpack:///./src/furo/assets/styles/components/_table_of_contents.sass","webpack:///./src/furo/assets/styles/_shame.sass"],"sourcesContent":["/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */\n\n/* Document\n ========================================================================== */\n\n/**\n * 1. Correct the line height in all browsers.\n * 2. Prevent adjustments of font size after orientation changes in iOS.\n */\n\nhtml {\n line-height: 1.15; /* 1 */\n -webkit-text-size-adjust: 100%; /* 2 */\n}\n\n/* Sections\n ========================================================================== */\n\n/**\n * Remove the margin in all browsers.\n */\n\nbody {\n margin: 0;\n}\n\n/**\n * Render the `main` element consistently in IE.\n */\n\nmain {\n display: block;\n}\n\n/**\n * Correct the font size and margin on `h1` elements within `section` and\n * `article` contexts in Chrome, Firefox, and Safari.\n */\n\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\n\n/* Grouping content\n ========================================================================== */\n\n/**\n * 1. Add the correct box sizing in Firefox.\n * 2. Show the overflow in Edge and IE.\n */\n\nhr {\n box-sizing: content-box; /* 1 */\n height: 0; /* 1 */\n overflow: visible; /* 2 */\n}\n\n/**\n * 1. Correct the inheritance and scaling of font size in all browsers.\n * 2. Correct the odd `em` font sizing in all browsers.\n */\n\npre {\n font-family: monospace, monospace; /* 1 */\n font-size: 1em; /* 2 */\n}\n\n/* Text-level semantics\n ========================================================================== */\n\n/**\n * Remove the gray background on active links in IE 10.\n */\n\na {\n background-color: transparent;\n}\n\n/**\n * 1. Remove the bottom border in Chrome 57-\n * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.\n */\n\nabbr[title] {\n border-bottom: none; /* 1 */\n text-decoration: underline; /* 2 */\n text-decoration: underline dotted; /* 2 */\n}\n\n/**\n * Add the correct font weight in Chrome, Edge, and Safari.\n */\n\nb,\nstrong {\n font-weight: bolder;\n}\n\n/**\n * 1. Correct the inheritance and scaling of font size in all browsers.\n * 2. Correct the odd `em` font sizing in all browsers.\n */\n\ncode,\nkbd,\nsamp {\n font-family: monospace, monospace; /* 1 */\n font-size: 1em; /* 2 */\n}\n\n/**\n * Add the correct font size in all browsers.\n */\n\nsmall {\n font-size: 80%;\n}\n\n/**\n * Prevent `sub` and `sup` elements from affecting the line height in\n * all browsers.\n */\n\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\n\nsub {\n bottom: -0.25em;\n}\n\nsup {\n top: -0.5em;\n}\n\n/* Embedded content\n ========================================================================== */\n\n/**\n * Remove the border on images inside links in IE 10.\n */\n\nimg {\n border-style: none;\n}\n\n/* Forms\n ========================================================================== */\n\n/**\n * 1. Change the font styles in all browsers.\n * 2. Remove the margin in Firefox and Safari.\n */\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n font-family: inherit; /* 1 */\n font-size: 100%; /* 1 */\n line-height: 1.15; /* 1 */\n margin: 0; /* 2 */\n}\n\n/**\n * Show the overflow in IE.\n * 1. Show the overflow in Edge.\n */\n\nbutton,\ninput { /* 1 */\n overflow: visible;\n}\n\n/**\n * Remove the inheritance of text transform in Edge, Firefox, and IE.\n * 1. Remove the inheritance of text transform in Firefox.\n */\n\nbutton,\nselect { /* 1 */\n text-transform: none;\n}\n\n/**\n * Correct the inability to style clickable types in iOS and Safari.\n */\n\nbutton,\n[type=\"button\"],\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button;\n}\n\n/**\n * Remove the inner border and padding in Firefox.\n */\n\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n border-style: none;\n padding: 0;\n}\n\n/**\n * Restore the focus styles unset by the previous rule.\n */\n\nbutton:-moz-focusring,\n[type=\"button\"]:-moz-focusring,\n[type=\"reset\"]:-moz-focusring,\n[type=\"submit\"]:-moz-focusring {\n outline: 1px dotted ButtonText;\n}\n\n/**\n * Correct the padding in Firefox.\n */\n\nfieldset {\n padding: 0.35em 0.75em 0.625em;\n}\n\n/**\n * 1. Correct the text wrapping in Edge and IE.\n * 2. Correct the color inheritance from `fieldset` elements in IE.\n * 3. Remove the padding so developers are not caught out when they zero out\n * `fieldset` elements in all browsers.\n */\n\nlegend {\n box-sizing: border-box; /* 1 */\n color: inherit; /* 2 */\n display: table; /* 1 */\n max-width: 100%; /* 1 */\n padding: 0; /* 3 */\n white-space: normal; /* 1 */\n}\n\n/**\n * Add the correct vertical alignment in Chrome, Firefox, and Opera.\n */\n\nprogress {\n vertical-align: baseline;\n}\n\n/**\n * Remove the default vertical scrollbar in IE 10+.\n */\n\ntextarea {\n overflow: auto;\n}\n\n/**\n * 1. Add the correct box sizing in IE 10.\n * 2. Remove the padding in IE 10.\n */\n\n[type=\"checkbox\"],\n[type=\"radio\"] {\n box-sizing: border-box; /* 1 */\n padding: 0; /* 2 */\n}\n\n/**\n * Correct the cursor style of increment and decrement buttons in Chrome.\n */\n\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n/**\n * 1. Correct the odd appearance in Chrome and Safari.\n * 2. Correct the outline style in Safari.\n */\n\n[type=\"search\"] {\n -webkit-appearance: textfield; /* 1 */\n outline-offset: -2px; /* 2 */\n}\n\n/**\n * Remove the inner padding in Chrome and Safari on macOS.\n */\n\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n/**\n * 1. Correct the inability to style clickable types in iOS and Safari.\n * 2. Change font properties to `inherit` in Safari.\n */\n\n::-webkit-file-upload-button {\n -webkit-appearance: button; /* 1 */\n font: inherit; /* 2 */\n}\n\n/* Interactive\n ========================================================================== */\n\n/*\n * Add the correct display in Edge, IE 10+, and Firefox.\n */\n\ndetails {\n display: block;\n}\n\n/*\n * Add the correct display in all browsers.\n */\n\nsummary {\n display: list-item;\n}\n\n/* Misc\n ========================================================================== */\n\n/**\n * Add the correct display in IE 10+.\n */\n\ntemplate {\n display: none;\n}\n\n/**\n * Add the correct display in IE 10.\n */\n\n[hidden] {\n display: none;\n}\n","// This file contains styles for managing print media.\n\n////////////////////////////////////////////////////////////////////////////////\n// Hide elements not relevant to print media.\n////////////////////////////////////////////////////////////////////////////////\n@media print\n // Hide icon container.\n .content-icon-container\n display: none !important\n\n // Hide showing header links if hovering over when printing.\n .headerlink\n display: none !important\n\n // Hide mobile header.\n .mobile-header\n display: none !important\n\n // Hide navigation links.\n .related-pages\n display: none !important\n\n////////////////////////////////////////////////////////////////////////////////\n// Tweaks related to decolorization.\n////////////////////////////////////////////////////////////////////////////////\n@media print\n // Apply a border around code which no longer have a color background.\n .highlight\n border: 0.1pt solid var(--color-foreground-border)\n\n////////////////////////////////////////////////////////////////////////////////\n// Avoid page break in some relevant cases.\n////////////////////////////////////////////////////////////////////////////////\n@media print\n ul, ol, dl, a, table, pre, blockquote\n page-break-inside: avoid\n\n h1, h2, h3, h4, h5, h6, img, figure, caption\n page-break-inside: avoid\n page-break-after: avoid\n\n ul, ol, dl\n page-break-before: avoid\n",".visually-hidden\n position: absolute !important\n width: 1px !important\n height: 1px !important\n padding: 0 !important\n margin: -1px !important\n overflow: hidden !important\n clip: rect(0,0,0,0) !important\n white-space: nowrap !important\n border: 0 !important\n color: var(--color-foreground-primary)\n background: var(--color-background-primary)\n\n:-moz-focusring\n outline: auto\n","// This file serves as the \"skeleton\" of the theming logic.\n//\n// This contains the bulk of the logic for handling dark mode, color scheme\n// toggling and the handling of color-scheme-specific hiding of elements.\n\nbody\n @include fonts\n @include spacing\n @include icons\n @include admonitions\n @include default-admonition(#651fff, \"abstract\")\n @include default-topic(#14B8A6, \"pencil\")\n\n @include colors\n\n.only-light\n display: block !important\nhtml body .only-dark\n display: none !important\n\n// Ignore dark-mode hints if print media.\n@media not print\n // Enable dark-mode, if requested.\n body[data-theme=\"dark\"]\n @include colors-dark\n\n html & .only-light\n display: none !important\n .only-dark\n display: block !important\n\n // Enable dark mode, unless explicitly told to avoid.\n @media (prefers-color-scheme: dark)\n body:not([data-theme=\"light\"])\n @include colors-dark\n\n html & .only-light\n display: none !important\n .only-dark\n display: block !important\n\n//\n// Theme toggle presentation\n//\nbody[data-theme=\"auto\"]\n .theme-toggle svg.theme-icon-when-auto-light\n display: block\n\n @media (prefers-color-scheme: dark)\n .theme-toggle svg.theme-icon-when-auto-dark\n display: block\n .theme-toggle svg.theme-icon-when-auto-light\n display: none\n\nbody[data-theme=\"dark\"]\n .theme-toggle svg.theme-icon-when-dark\n display: block\n\nbody[data-theme=\"light\"]\n .theme-toggle svg.theme-icon-when-light\n display: block\n","// Fonts used by this theme.\n//\n// There are basically two things here -- using the system font stack and\n// defining sizes for various elements in %ages. We could have also used `em`\n// but %age is easier to reason about for me.\n\n@mixin fonts {\n // These are adapted from https://systemfontstack.com/\n --font-stack: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial,\n sans-serif, Apple Color Emoji, Segoe UI Emoji;\n --font-stack--monospace: \"SFMono-Regular\", Menlo, Consolas, Monaco,\n Liberation Mono, Lucida Console, monospace;\n --font-stack--headings: var(--font-stack);\n\n --font-size--normal: 100%;\n --font-size--small: 87.5%;\n --font-size--small--2: 81.25%;\n --font-size--small--3: 75%;\n --font-size--small--4: 62.5%;\n\n // Sidebar\n --sidebar-caption-font-size: var(--font-size--small--2);\n --sidebar-item-font-size: var(--font-size--small);\n --sidebar-search-input-font-size: var(--font-size--small);\n\n // Table of Contents\n --toc-font-size: var(--font-size--small--3);\n --toc-font-size--mobile: var(--font-size--normal);\n --toc-title-font-size: var(--font-size--small--4);\n\n // Admonitions\n //\n // These aren't defined in terms of %ages, since nesting these is permitted.\n --admonition-font-size: 0.8125rem;\n --admonition-title-font-size: 0.8125rem;\n\n // Code\n --code-font-size: var(--font-size--small--2);\n\n // API\n --api-font-size: var(--font-size--small);\n}\n","// Spacing for various elements on the page\n//\n// If the user wants to tweak things in a certain way, they are permitted to.\n// They also have to deal with the consequences though!\n\n@mixin spacing {\n // Header!\n --header-height: calc(\n var(--sidebar-item-line-height) + 4 * #{var(--sidebar-item-spacing-vertical)}\n );\n --header-padding: 0.5rem;\n\n // Sidebar\n --sidebar-tree-space-above: 1.5rem;\n --sidebar-caption-space-above: 1rem;\n\n --sidebar-item-line-height: 1rem;\n --sidebar-item-spacing-vertical: 0.5rem;\n --sidebar-item-spacing-horizontal: 1rem;\n --sidebar-item-height: calc(\n var(--sidebar-item-line-height) + 2 *#{var(--sidebar-item-spacing-vertical)}\n );\n\n --sidebar-expander-width: var(--sidebar-item-height); // be square\n\n --sidebar-search-space-above: 0.5rem;\n --sidebar-search-input-spacing-vertical: 0.5rem;\n --sidebar-search-input-spacing-horizontal: 0.5rem;\n --sidebar-search-input-height: 1rem;\n --sidebar-search-icon-size: var(--sidebar-search-input-height);\n\n // Table of Contents\n --toc-title-padding: 0.25rem 0;\n --toc-spacing-vertical: 1.5rem;\n --toc-spacing-horizontal: 1.5rem;\n --toc-item-spacing-vertical: 0.4rem;\n --toc-item-spacing-horizontal: 1rem;\n}\n","// Expose theme icons as CSS variables.\n\n$icons: (\n // Adapted from tabler-icons\n // url: https://tablericons.com/\n \"search\":\n url('data:image/svg+xml;charset=utf-8,'),\n // Factored out from mkdocs-material on 24-Aug-2020.\n // url: https://squidfunk.github.io/mkdocs-material/reference/admonitions/\n \"pencil\":\n url('data:image/svg+xml;charset=utf-8,'),\n \"abstract\":\n url('data:image/svg+xml;charset=utf-8,'),\n \"info\":\n url('data:image/svg+xml;charset=utf-8,'),\n \"flame\":\n url('data:image/svg+xml;charset=utf-8,'),\n \"question\":\n url('data:image/svg+xml;charset=utf-8,'),\n \"warning\":\n url('data:image/svg+xml;charset=utf-8,'),\n \"failure\":\n url('data:image/svg+xml;charset=utf-8,'),\n \"spark\":\n url('data:image/svg+xml;charset=utf-8,')\n);\n\n@mixin icons {\n @each $name, $glyph in $icons {\n --icon-#{$name}: #{$glyph};\n }\n}\n","// Admonitions\n\n// Structure of these is:\n// admonition-class: color \"icon-name\";\n//\n// The colors are translated into CSS variables below. The icons are\n// used directly in the main declarations to set the `mask-image` in\n// the title.\n\n// prettier-ignore\n$admonitions: (\n // Each of these has an reST directives for it.\n \"caution\": #ff9100 \"spark\",\n \"warning\": #ff9100 \"warning\",\n \"danger\": #ff5252 \"spark\",\n \"attention\": #ff5252 \"warning\",\n \"error\": #ff5252 \"failure\",\n \"hint\": #00c852 \"question\",\n \"tip\": #00c852 \"info\",\n \"important\": #00bfa5 \"flame\",\n \"note\": #00b0ff \"pencil\",\n \"seealso\": #448aff \"info\",\n \"admonition-todo\": #808080 \"pencil\"\n);\n\n@mixin default-admonition($color, $icon-name) {\n --color-admonition-title: #{$color};\n --color-admonition-title-background: #{rgba($color, 0.2)};\n\n --icon-admonition-default: var(--icon-#{$icon-name});\n}\n\n@mixin default-topic($color, $icon-name) {\n --color-topic-title: #{$color};\n --color-topic-title-background: #{rgba($color, 0.2)};\n\n --icon-topic-default: var(--icon-#{$icon-name});\n}\n\n@mixin admonitions {\n @each $name, $values in $admonitions {\n --color-admonition-title--#{$name}: #{nth($values, 1)};\n --color-admonition-title-background--#{$name}: #{rgba(\n nth($values, 1),\n 0.2\n )};\n }\n}\n","// Colors used throughout this theme.\n//\n// The aim is to give the user more control. Thus, instead of hard-coding colors\n// in various parts of the stylesheet, the approach taken is to define all\n// colors as CSS variables and reusing them in all the places.\n//\n// `colors-dark` depends on `colors` being included at a lower specificity.\n\n@mixin colors {\n --color-problematic: #b30000;\n\n // Base Colors\n --color-foreground-primary: black; // for main text and headings\n --color-foreground-secondary: #5a5c63; // for secondary text\n --color-foreground-muted: #6b6f76; // for muted text\n --color-foreground-border: #878787; // for content borders\n\n --color-background-primary: white; // for content\n --color-background-secondary: #f8f9fb; // for navigation + ToC\n --color-background-hover: #efeff4ff; // for navigation-item hover\n --color-background-hover--transparent: #efeff400;\n --color-background-border: #eeebee; // for UI borders\n --color-background-item: #ccc; // for \"background\" items (eg: copybutton)\n\n // Announcements\n --color-announcement-background: #000000dd;\n --color-announcement-text: #eeebee;\n\n // Brand colors\n --color-brand-primary: #0a4bff;\n --color-brand-content: #2757dd;\n --color-brand-visited: #872ee0;\n\n // API documentation\n --color-api-background: var(--color-background-hover--transparent);\n --color-api-background-hover: var(--color-background-hover);\n --color-api-overall: var(--color-foreground-secondary);\n --color-api-name: var(--color-problematic);\n --color-api-pre-name: var(--color-problematic);\n --color-api-paren: var(--color-foreground-secondary);\n --color-api-keyword: var(--color-foreground-primary);\n\n --color-api-added: #21632c;\n --color-api-added-border: #38a84d;\n --color-api-changed: #046172;\n --color-api-changed-border: #06a1bc;\n --color-api-deprecated: #605706;\n --color-api-deprecated-border: #f0d90f;\n --color-api-removed: #b30000;\n --color-api-removed-border: #ff5c5c;\n\n --color-highlight-on-target: #ffffcc;\n\n // Inline code background\n --color-inline-code-background: var(--color-background-secondary);\n\n // Highlighted text (search)\n --color-highlighted-background: #ddeeff;\n --color-highlighted-text: var(--color-foreground-primary);\n\n // GUI Labels\n --color-guilabel-background: #ddeeff80;\n --color-guilabel-border: #bedaf580;\n --color-guilabel-text: var(--color-foreground-primary);\n\n // Admonitions!\n --color-admonition-background: transparent;\n\n //////////////////////////////////////////////////////////////////////////////\n // Everything below this should be one of:\n // - var(...)\n // - *-gradient(...)\n // - special literal values (eg: transparent, none)\n //////////////////////////////////////////////////////////////////////////////\n\n // Tables\n --color-table-header-background: var(--color-background-secondary);\n --color-table-border: var(--color-background-border);\n\n // Cards\n --color-card-border: var(--color-background-secondary);\n --color-card-background: transparent;\n --color-card-marginals-background: var(--color-background-secondary);\n\n // Header\n --color-header-background: var(--color-background-primary);\n --color-header-border: var(--color-background-border);\n --color-header-text: var(--color-foreground-primary);\n\n // Sidebar (left)\n --color-sidebar-background: var(--color-background-secondary);\n --color-sidebar-background-border: var(--color-background-border);\n\n --color-sidebar-brand-text: var(--color-foreground-primary);\n --color-sidebar-caption-text: var(--color-foreground-muted);\n --color-sidebar-link-text: var(--color-foreground-secondary);\n --color-sidebar-link-text--top-level: var(--color-brand-primary);\n\n --color-sidebar-item-background: var(--color-sidebar-background);\n --color-sidebar-item-background--current: var(\n --color-sidebar-item-background\n );\n --color-sidebar-item-background--hover: linear-gradient(\n 90deg,\n var(--color-background-hover--transparent) 0%,\n var(--color-background-hover) var(--sidebar-item-spacing-horizontal),\n var(--color-background-hover) 100%\n );\n\n --color-sidebar-item-expander-background: transparent;\n --color-sidebar-item-expander-background--hover: var(\n --color-background-hover\n );\n\n --color-sidebar-search-text: var(--color-foreground-primary);\n --color-sidebar-search-background: var(--color-background-secondary);\n --color-sidebar-search-background--focus: var(--color-background-primary);\n --color-sidebar-search-border: var(--color-background-border);\n --color-sidebar-search-icon: var(--color-foreground-muted);\n\n // Table of Contents (right)\n --color-toc-background: var(--color-background-primary);\n --color-toc-title-text: var(--color-foreground-muted);\n --color-toc-item-text: var(--color-foreground-secondary);\n --color-toc-item-text--hover: var(--color-foreground-primary);\n --color-toc-item-text--active: var(--color-brand-primary);\n\n // Actual page contents\n --color-content-foreground: var(--color-foreground-primary);\n --color-content-background: transparent;\n\n // Links\n --color-link: var(--color-brand-content);\n --color-link-underline: var(--color-background-border);\n --color-link--hover: var(--color-brand-content);\n --color-link-underline--hover: var(--color-foreground-border);\n\n --color-link--visited: var(--color-brand-visited);\n --color-link-underline--visited: var(--color-background-border);\n --color-link--visited--hover: var(--color-brand-visited);\n --color-link-underline--visited--hover: var(--color-foreground-border);\n}\n\n@mixin colors-dark {\n --color-problematic: #ee5151;\n\n // Base Colors\n --color-foreground-primary: #cfd0d0; // for main text and headings\n --color-foreground-secondary: #9ca0a5; // for secondary text\n --color-foreground-muted: #81868d; // for muted text\n --color-foreground-border: #666666; // for content borders\n\n --color-background-primary: #131416; // for content\n --color-background-secondary: #1a1c1e; // for navigation + ToC\n --color-background-hover: #1e2124ff; // for navigation-item hover\n --color-background-hover--transparent: #1e212400;\n --color-background-border: #303335; // for UI borders\n --color-background-item: #444; // for \"background\" items (eg: copybutton)\n\n // Announcements\n --color-announcement-background: #000000dd;\n --color-announcement-text: #eeebee;\n\n // Brand colors\n --color-brand-primary: #3d94ff;\n --color-brand-content: #5ca5ff;\n --color-brand-visited: #b27aeb;\n\n // Highlighted text (search)\n --color-highlighted-background: #083563;\n\n // GUI Labels\n --color-guilabel-background: #08356380;\n --color-guilabel-border: #13395f80;\n\n // API documentation\n --color-api-keyword: var(--color-foreground-secondary);\n --color-highlight-on-target: #333300;\n\n --color-api-added: #3db854;\n --color-api-added-border: #267334;\n --color-api-changed: #09b0ce;\n --color-api-changed-border: #056d80;\n --color-api-deprecated: #b1a10b;\n --color-api-deprecated-border: #6e6407;\n --color-api-removed: #ff7575;\n --color-api-removed-border: #b03b3b;\n\n // Admonitions\n --color-admonition-background: #18181a;\n\n // Cards\n --color-card-border: var(--color-background-secondary);\n --color-card-background: #18181a;\n --color-card-marginals-background: var(--color-background-hover);\n}\n","// This file contains the styling for making the content throughout the page,\n// including fonts, paragraphs, headings and spacing among these elements.\n\nbody\n font-family: var(--font-stack)\npre,\ncode,\nkbd,\nsamp\n font-family: var(--font-stack--monospace)\n\n// Make fonts look slightly nicer.\nbody\n -webkit-font-smoothing: antialiased\n -moz-osx-font-smoothing: grayscale\n\n// Line height from Bootstrap 4.1\narticle\n line-height: 1.5\n\n//\n// Headings\n//\nh1,\nh2,\nh3,\nh4,\nh5,\nh6\n line-height: 1.25\n font-family: var(--font-stack--headings)\n font-weight: bold\n\n border-radius: 0.5rem\n margin-top: 0.5rem\n margin-bottom: 0.5rem\n margin-left: -0.5rem\n margin-right: -0.5rem\n padding-left: 0.5rem\n padding-right: 0.5rem\n\n + p\n margin-top: 0\n\nh1\n font-size: 2.5em\n margin-top: 1.75rem\n margin-bottom: 1rem\nh2\n font-size: 2em\n margin-top: 1.75rem\nh3\n font-size: 1.5em\nh4\n font-size: 1.25em\nh5\n font-size: 1.125em\nh6\n font-size: 1em\n\nsmall\n opacity: 75%\n font-size: 80%\n\n// Paragraph\np\n margin-top: 0.5rem\n margin-bottom: 0.75rem\n\n// Horizontal rules\nhr.docutils\n height: 1px\n padding: 0\n margin: 2rem 0\n background-color: var(--color-background-border)\n border: 0\n\n.centered\n text-align: center\n\n// Links\na\n text-decoration: underline\n\n color: var(--color-link)\n text-decoration-color: var(--color-link-underline)\n\n &:visited\n color: var(--color-link--visited)\n text-decoration-color: var(--color-link-underline--visited)\n &:hover\n color: var(--color-link--visited--hover)\n text-decoration-color: var(--color-link-underline--visited--hover)\n\n &:hover\n color: var(--color-link--hover)\n text-decoration-color: var(--color-link-underline--hover)\n &.muted-link\n color: inherit\n &:hover\n color: var(--color-link--hover)\n text-decoration-color: var(--color-link-underline--hover)\n &:visited\n color: var(--color-link--visited--hover)\n text-decoration-color: var(--color-link-underline--visited--hover)\n","// This file contains the styles for the overall layouting of the documentation\n// skeleton, including the responsive changes as well as sidebar toggles.\n//\n// This is implemented as a mobile-last design, which isn't ideal, but it is\n// reasonably good-enough and I got pretty tired by the time I'd finished this\n// to move the rules around to fix this. Shouldn't take more than 3-4 hours,\n// if you know what you're doing tho.\n\n// HACK: Not all browsers account for the scrollbar width in media queries.\n// This results in horizontal scrollbars in the breakpoint where we go\n// from displaying everything to hiding the ToC. We accomodate for this by\n// adding a bit of padding to the TOC drawer, disabling the horizontal\n// scrollbar and allowing the scrollbars to cover the padding.\n// https://www.456bereastreet.com/archive/201301/media_query_width_and_vertical_scrollbars/\n\n// HACK: Always having the scrollbar visible, prevents certain browsers from\n// causing the content to stutter horizontally between taller-than-viewport and\n// not-taller-than-viewport pages.\n\nhtml\n overflow-x: hidden\n overflow-y: scroll\n scroll-behavior: smooth\n\n.sidebar-scroll, .toc-scroll, article[role=main] *\n // Override Firefox scrollbar style\n scrollbar-width: thin\n scrollbar-color: var(--color-foreground-border) transparent\n\n // Override Chrome scrollbar styles\n &::-webkit-scrollbar\n width: 0.25rem\n height: 0.25rem\n &::-webkit-scrollbar-thumb\n background-color: var(--color-foreground-border)\n border-radius: 0.125rem\n\n//\n// Overalls\n//\nhtml,\nbody\n height: 100%\n color: var(--color-foreground-primary)\n background: var(--color-background-primary)\n\n.skip-to-content\n position: fixed\n padding: 1rem\n border-radius: 1rem\n left: 0.25rem\n top: 0.25rem\n z-index: 40\n background: var(--color-background-primary)\n color: var(--color-foreground-primary)\n\n transform: translateY(-200%)\n transition: transform 300ms ease-in-out\n\n &:focus-within\n transform: translateY(0%)\n\narticle\n color: var(--color-content-foreground)\n background: var(--color-content-background)\n overflow-wrap: break-word\n\n.page\n display: flex\n // fill the viewport for pages with little content.\n min-height: 100%\n\n.mobile-header\n width: 100%\n height: var(--header-height)\n background-color: var(--color-header-background)\n color: var(--color-header-text)\n border-bottom: 1px solid var(--color-header-border)\n\n // Looks like sub-script/super-script have this, and we need this to\n // be \"on top\" of those.\n z-index: 10\n\n // We don't show the header on large screens.\n display: none\n\n // Add shadow when scrolled\n &.scrolled\n border-bottom: none\n box-shadow: 0 0 0.2rem rgba(0, 0, 0, 0.1), 0 0.2rem 0.4rem rgba(0, 0, 0, 0.2)\n\n .header-center\n a\n color: var(--color-header-text)\n text-decoration: none\n\n.main\n display: flex\n flex: 1\n\n// Sidebar (left) also covers the entire left portion of screen.\n.sidebar-drawer\n box-sizing: border-box\n\n border-right: 1px solid var(--color-sidebar-background-border)\n background: var(--color-sidebar-background)\n\n display: flex\n justify-content: flex-end\n // These next two lines took me two days to figure out.\n width: calc((100% - #{$full-width}) / 2 + #{$sidebar-width})\n min-width: $sidebar-width\n\n// Scroll-along sidebars\n.sidebar-container,\n.toc-drawer\n box-sizing: border-box\n width: $sidebar-width\n\n.toc-drawer\n background: var(--color-toc-background)\n // See HACK described on top of this document\n padding-right: 1rem\n\n.sidebar-sticky,\n.toc-sticky\n position: sticky\n top: 0\n height: min(100%, 100vh)\n height: 100vh\n\n display: flex\n flex-direction: column\n\n.sidebar-scroll,\n.toc-scroll\n flex-grow: 1\n flex-shrink: 1\n\n overflow: auto\n scroll-behavior: smooth\n\n// Central items.\n.content\n padding: 0 $content-padding\n width: $content-width\n\n display: flex\n flex-direction: column\n justify-content: space-between\n\n.icon\n display: inline-block\n height: 1rem\n width: 1rem\n svg\n width: 100%\n height: 100%\n\n//\n// Accommodate announcement banner\n//\n.announcement\n background-color: var(--color-announcement-background)\n color: var(--color-announcement-text)\n\n height: var(--header-height)\n display: flex\n align-items: center\n overflow-x: auto\n & + .page\n min-height: calc(100% - var(--header-height))\n\n.announcement-content\n box-sizing: border-box\n padding: 0.5rem\n min-width: 100%\n white-space: nowrap\n text-align: center\n\n a\n color: var(--color-announcement-text)\n text-decoration-color: var(--color-announcement-text)\n\n &:hover\n color: var(--color-announcement-text)\n text-decoration-color: var(--color-link--hover)\n\n////////////////////////////////////////////////////////////////////////////////\n// Toggles for theme\n////////////////////////////////////////////////////////////////////////////////\n.no-js .theme-toggle-container // don't show theme toggle if there's no JS\n display: none\n\n.theme-toggle-container\n display: flex\n\n.theme-toggle\n display: flex\n cursor: pointer\n border: none\n padding: 0\n background: transparent\n\n.theme-toggle svg\n height: 1.25rem\n width: 1.25rem\n color: var(--color-foreground-primary)\n display: none\n\n.theme-toggle-header\n display: flex\n align-items: center\n justify-content: center\n\n////////////////////////////////////////////////////////////////////////////////\n// Toggles for elements\n////////////////////////////////////////////////////////////////////////////////\n.toc-overlay-icon, .nav-overlay-icon\n display: none\n cursor: pointer\n\n .icon\n color: var(--color-foreground-secondary)\n height: 1.5rem\n width: 1.5rem\n\n.toc-header-icon, .nav-overlay-icon\n // for when we set display: flex\n justify-content: center\n align-items: center\n\n.toc-content-icon\n height: 1.5rem\n width: 1.5rem\n\n.content-icon-container\n float: right\n display: flex\n margin-top: 1.5rem\n margin-left: 1rem\n margin-bottom: 1rem\n gap: 0.5rem\n\n .edit-this-page, .view-this-page\n svg\n color: inherit\n height: 1.25rem\n width: 1.25rem\n\n.sidebar-toggle\n position: absolute\n display: none\n// \n.sidebar-toggle[name=\"__toc\"]\n left: 20px\n.sidebar-toggle:checked\n left: 40px\n// \n\n.overlay\n position: fixed\n top: 0\n width: 0\n height: 0\n\n transition: width 0ms, height 0ms, opacity 250ms ease-out\n\n opacity: 0\n background-color: rgba(0, 0, 0, 0.54)\n.sidebar-overlay\n z-index: 20\n.toc-overlay\n z-index: 40\n\n// Keep things on top and smooth.\n.sidebar-drawer\n z-index: 30\n transition: left 250ms ease-in-out\n.toc-drawer\n z-index: 50\n transition: right 250ms ease-in-out\n\n// Show the Sidebar\n#__navigation:checked\n & ~ .sidebar-overlay\n width: 100%\n height: 100%\n opacity: 1\n & ~ .page\n .sidebar-drawer\n top: 0\n left: 0\n // Show the toc sidebar\n#__toc:checked\n & ~ .toc-overlay\n width: 100%\n height: 100%\n opacity: 1\n & ~ .page\n .toc-drawer\n top: 0\n right: 0\n\n////////////////////////////////////////////////////////////////////////////////\n// Back to top\n////////////////////////////////////////////////////////////////////////////////\n.back-to-top\n text-decoration: none\n\n display: none\n position: fixed\n left: 0\n top: 1rem\n padding: 0.5rem\n padding-right: 0.75rem\n border-radius: 1rem\n font-size: 0.8125rem\n\n background: var(--color-background-primary)\n box-shadow: 0 0.2rem 0.5rem rgba(0, 0, 0, 0.05), #6b728080 0px 0px 1px 0px\n\n z-index: 10\n\n margin-left: 50%\n transform: translateX(-50%)\n svg\n height: 1rem\n width: 1rem\n fill: currentColor\n display: inline-block\n\n span\n margin-left: 0.25rem\n\n .show-back-to-top &\n display: flex\n align-items: center\n\n////////////////////////////////////////////////////////////////////////////////\n// Responsive layouting\n////////////////////////////////////////////////////////////////////////////////\n// Make things a bit bigger on bigger screens.\n@media (min-width: $full-width + $sidebar-width)\n html\n font-size: 110%\n\n@media (max-width: $full-width)\n // Collapse \"toc\" into the icon.\n .toc-content-icon\n display: flex\n .toc-drawer\n position: fixed\n height: 100vh\n top: 0\n right: -$sidebar-width\n border-left: 1px solid var(--color-background-muted)\n .toc-tree\n border-left: none\n font-size: var(--toc-font-size--mobile)\n\n // Accomodate for a changed content width.\n .sidebar-drawer\n width: calc((100% - #{$full-width - $sidebar-width}) / 2 + #{$sidebar-width})\n\n@media (max-width: $full-width - $sidebar-width)\n // Collapse \"navigation\".\n .nav-overlay-icon\n display: flex\n .sidebar-drawer\n position: fixed\n height: 100vh\n width: $sidebar-width\n\n top: 0\n left: -$sidebar-width\n\n // Swap which icon is visible.\n .toc-header-icon, .theme-toggle-header\n display: flex\n .toc-content-icon, .theme-toggle-content\n display: none\n\n // Show the header.\n .mobile-header\n position: sticky\n top: 0\n display: flex\n justify-content: space-between\n align-items: center\n\n .header-left,\n .header-right\n display: flex\n height: var(--header-height)\n padding: 0 var(--header-padding)\n label\n height: 100%\n width: 100%\n user-select: none\n\n .nav-overlay-icon .icon,\n .theme-toggle svg\n height: 1.5rem\n width: 1.5rem\n\n // Add a scroll margin for the content\n :target\n scroll-margin-top: calc(var(--header-height) + 2.5rem)\n\n // Show back-to-top below the header\n .back-to-top\n top: calc(var(--header-height) + 0.5rem)\n\n // Center the page, and accommodate for the header.\n .page\n flex-direction: column\n justify-content: center\n .content\n margin-left: auto\n margin-right: auto\n\n@media (max-width: $content-width + 2* $content-padding)\n // Content should respect window limits.\n .content\n width: 100%\n overflow-x: auto\n\n@media (max-width: $content-width)\n .content\n padding: 0 $content-padding--small\n // Don't float sidebars to the right.\n article aside.sidebar\n float: none\n width: 100%\n margin: 1rem 0\n","// Overall Layout Variables\n//\n// Because CSS variables can't be used in media queries. The fact that this\n// makes the layout non-user-configurable is a good thing.\n$content-padding: 3em;\n$content-padding--small: 1em;\n$content-width: 46em;\n$sidebar-width: 15em;\n$full-width: $content-width + 2 * ($content-padding + $sidebar-width);\n","//\n// The design here is strongly inspired by mkdocs-material.\n.admonition, .topic\n margin: 1rem auto\n padding: 0 0.5rem 0.5rem 0.5rem\n\n background: var(--color-admonition-background)\n\n border-radius: 0.2rem\n box-shadow: 0 0.2rem 0.5rem rgba(0, 0, 0, 0.05), 0 0 0.0625rem rgba(0, 0, 0, 0.1)\n\n font-size: var(--admonition-font-size)\n\n overflow: hidden\n page-break-inside: avoid\n\n // First element should have no margin, since the title has it.\n > :nth-child(2)\n margin-top: 0\n\n // Last item should have no margin, since we'll control that w/ padding\n > :last-child\n margin-bottom: 0\n\n.admonition p.admonition-title,\np.topic-title\n position: relative\n margin: 0 -0.5rem 0.5rem\n padding-left: 2rem\n padding-right: .5rem\n padding-top: .4rem\n padding-bottom: .4rem\n\n font-weight: 500\n font-size: var(--admonition-title-font-size)\n line-height: 1.3\n\n // Our fancy icon\n &::before\n content: \"\"\n position: absolute\n left: 0.5rem\n width: 1rem\n height: 1rem\n\n// Default styles\np.admonition-title\n background-color: var(--color-admonition-title-background)\n &::before\n background-color: var(--color-admonition-title)\n mask-image: var(--icon-admonition-default)\n mask-repeat: no-repeat\n\np.topic-title\n background-color: var(--color-topic-title-background)\n &::before\n background-color: var(--color-topic-title)\n mask-image: var(--icon-topic-default)\n mask-repeat: no-repeat\n\n//\n// Variants\n//\n.admonition\n border-left: 0.2rem solid var(--color-admonition-title)\n\n @each $type, $value in $admonitions\n &.#{$type}\n border-left-color: var(--color-admonition-title--#{$type})\n > .admonition-title\n background-color: var(--color-admonition-title-background--#{$type})\n &::before\n background-color: var(--color-admonition-title--#{$type})\n mask-image: var(--icon-#{nth($value, 2)})\n\n.admonition-todo > .admonition-title\n text-transform: uppercase\n","// This file stylizes the API documentation (stuff generated by autodoc). It's\n// deeply nested due to how autodoc structures the HTML without enough classes\n// to select the relevant items.\n\n// API docs!\ndl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple)\n // Tweak the spacing of all the things!\n dd\n margin-left: 2rem\n > :first-child\n margin-top: 0.125rem\n > :last-child\n margin-bottom: 0.75rem\n\n // This is used for the arguments\n .field-list\n margin-bottom: 0.75rem\n\n // \"Headings\" (like \"Parameters\" and \"Return\")\n > dt\n text-transform: uppercase\n font-size: var(--font-size--small)\n\n dd:empty\n margin-bottom: 0.5rem\n dd > ul\n margin-left: -1.2rem\n > li\n > p:nth-child(2)\n margin-top: 0\n // When the last-empty-paragraph follows a paragraph, it doesn't need\n // to augument the existing spacing.\n > p + p:last-child:empty\n margin-top: 0\n margin-bottom: 0\n\n // Colorize the elements\n > dt\n color: var(--color-api-overall)\n\n.sig:not(.sig-inline)\n font-weight: bold\n\n font-size: var(--api-font-size)\n font-family: var(--font-stack--monospace)\n\n margin-left: -0.25rem\n margin-right: -0.25rem\n padding-top: 0.25rem\n padding-bottom: 0.25rem\n padding-right: 0.5rem\n\n // These are intentionally em, to properly match the font size.\n padding-left: 3em\n text-indent: -2.5em\n\n border-radius: 0.25rem\n\n background: var(--color-api-background)\n transition: background 100ms ease-out\n\n &:hover\n background: var(--color-api-background-hover)\n\n // adjust the size of the [source] link on the right.\n a.reference\n .viewcode-link\n font-weight: normal\n width: 4.25rem\n\nem.property\n font-style: normal\n &:first-child\n color: var(--color-api-keyword)\n.sig-name\n color: var(--color-api-name)\n.sig-prename\n font-weight: normal\n color: var(--color-api-pre-name)\n.sig-paren\n color: var(--color-api-paren)\n.sig-param\n font-style: normal\n\ndiv.versionadded,\ndiv.versionchanged,\ndiv.deprecated,\ndiv.versionremoved\n border-left: 0.1875rem solid\n border-radius: 0.125rem\n\n padding-left: 0.75rem\n\n p\n margin-top: 0.125rem\n margin-bottom: 0.125rem\n\ndiv.versionadded\n border-color: var(--color-api-added-border)\n .versionmodified\n color: var(--color-api-added)\n\ndiv.versionchanged\n border-color: var(--color-api-changed-border)\n .versionmodified\n color: var(--color-api-changed)\n\ndiv.deprecated\n border-color: var(--color-api-deprecated-border)\n .versionmodified\n color: var(--color-api-deprecated)\n\ndiv.versionremoved\n border-color: var(--color-api-removed-border)\n .versionmodified\n color: var(--color-api-removed)\n\n// Align the [docs] and [source] to the right.\n.viewcode-link, .viewcode-back\n float: right\n text-align: right\n",".line-block\n margin-top: 0.5rem\n margin-bottom: 0.75rem\n .line-block\n margin-top: 0rem\n margin-bottom: 0rem\n padding-left: 1rem\n","// Captions\narticle p.caption,\ntable > caption,\n.code-block-caption\n font-size: var(--font-size--small)\n text-align: center\n\n// Caption above a TOCTree\n.toctree-wrapper.compound\n .caption, :not(.caption) > .caption-text\n font-size: var(--font-size--small)\n text-transform: uppercase\n\n text-align: initial\n margin-bottom: 0\n\n > ul\n margin-top: 0\n margin-bottom: 0\n","// Inline code\ncode.literal, .sig-inline\n background: var(--color-inline-code-background)\n border-radius: 0.2em\n // Make the font smaller, and use padding to recover.\n font-size: var(--font-size--small--2)\n padding: 0.1em 0.2em\n\n pre.literal-block &\n font-size: inherit\n padding: 0\n\n p &\n border: 1px solid var(--color-background-border)\n\n.sig-inline\n font-family: var(--font-stack--monospace)\n\n// Code and Literal Blocks\n$code-spacing-vertical: 0.625rem\n$code-spacing-horizontal: 0.875rem\n\n// Wraps every literal block + line numbers.\ndiv[class*=\" highlight-\"],\ndiv[class^=\"highlight-\"]\n margin: 1em 0\n display: flex\n\n .table-wrapper\n margin: 0\n padding: 0\n\npre\n margin: 0\n padding: 0\n overflow: auto\n\n // Needed to have more specificity than pygments' \"pre\" selector. :(\n article[role=\"main\"] .highlight &\n line-height: 1.5\n\n &.literal-block,\n .highlight &\n font-size: var(--code-font-size)\n padding: $code-spacing-vertical $code-spacing-horizontal\n\n // Make it look like all the other blocks.\n &.literal-block\n margin-top: 1rem\n margin-bottom: 1rem\n\n border-radius: 0.2rem\n background-color: var(--color-code-background)\n color: var(--color-code-foreground)\n\n// All code is always contained in this.\n.highlight\n width: 100%\n border-radius: 0.2rem\n\n // Make line numbers and prompts un-selectable.\n .gp, span.linenos\n user-select: none\n pointer-events: none\n\n // Expand the line-highlighting.\n .hll\n display: block\n margin-left: -$code-spacing-horizontal\n margin-right: -$code-spacing-horizontal\n padding-left: $code-spacing-horizontal\n padding-right: $code-spacing-horizontal\n\n/* Make code block captions be nicely integrated */\n.code-block-caption\n display: flex\n padding: $code-spacing-vertical $code-spacing-horizontal\n\n border-radius: 0.25rem\n border-bottom-left-radius: 0\n border-bottom-right-radius: 0\n font-weight: 300\n border-bottom: 1px solid\n\n background-color: var(--color-code-background)\n color: var(--color-code-foreground)\n border-color: var(--color-background-border)\n\n + div[class]\n margin-top: 0\n pre\n border-top-left-radius: 0\n border-top-right-radius: 0\n\n// When `html_codeblock_linenos_style` is table.\n.highlighttable\n width: 100%\n display: block\n tbody\n display: block\n\n tr\n display: flex\n\n // Line numbers\n td.linenos\n background-color: var(--color-code-background)\n color: var(--color-code-foreground)\n padding: $code-spacing-vertical $code-spacing-horizontal\n padding-right: 0\n border-top-left-radius: 0.2rem\n border-bottom-left-radius: 0.2rem\n\n .linenodiv\n padding-right: $code-spacing-horizontal\n font-size: var(--code-font-size)\n box-shadow: -0.0625rem 0 var(--color-foreground-border) inset\n\n // Actual code\n td.code\n padding: 0\n display: block\n flex: 1\n overflow: hidden\n\n .highlight\n border-top-left-radius: 0\n border-bottom-left-radius: 0\n\n// When `html_codeblock_linenos_style` is inline.\n.highlight\n span.linenos\n display: inline-block\n padding-left: 0\n padding-right: $code-spacing-horizontal\n margin-right: $code-spacing-horizontal\n box-shadow: -0.0625rem 0 var(--color-foreground-border) inset\n","// Inline Footnote Reference\n.footnote-reference\n font-size: var(--font-size--small--4)\n vertical-align: super\n\n// Definition list, listing the content of each note.\n// docutils <= 0.17\ndl.footnote.brackets\n font-size: var(--font-size--small)\n color: var(--color-foreground-secondary)\n\n display: grid\n grid-template-columns: max-content auto\n dt\n margin: 0\n > .fn-backref\n margin-left: 0.25rem\n\n &:after\n content: \":\"\n\n .brackets\n &:before\n content: \"[\"\n &:after\n content: \"]\"\n\n dd\n margin: 0\n padding: 0 1rem\n\n// docutils >= 0.18\naside.footnote\n font-size: var(--font-size--small)\n color: var(--color-foreground-secondary)\n\naside.footnote > span,\ndiv.citation > span\n float: left\n font-weight: 500\n padding-right: 0.25rem\n\naside.footnote > *:not(span),\ndiv.citation > p\n margin-left: 2rem\n","//\n// Figures\n//\nimg\n box-sizing: border-box\n max-width: 100%\n height: auto\n\narticle\n figure, .figure\n border-radius: 0.2rem\n\n margin: 0\n :last-child\n margin-bottom: 0\n\n .align-left\n float: left\n clear: left\n margin: 0 1rem 1rem\n\n .align-right\n float: right\n clear: right\n margin: 0 1rem 1rem\n\n .align-default,\n .align-center\n display: block\n text-align: center\n margin-left: auto\n margin-right: auto\n\n // WELL, table needs to be stylised like a table.\n table.align-default\n display: table\n text-align: initial\n",".genindex-jumpbox, .domainindex-jumpbox\n border-top: 1px solid var(--color-background-border)\n border-bottom: 1px solid var(--color-background-border)\n padding: 0.25rem\n\n.genindex-section, .domainindex-section\n h2\n margin-top: 0.75rem\n margin-bottom: 0.5rem\n ul\n margin-top: 0\n margin-bottom: 0\n","ul,\nol\n padding-left: 1.2rem\n\n // Space lists out like paragraphs\n margin-top: 1rem\n margin-bottom: 1rem\n // reduce margins within li.\n li\n > p:first-child\n margin-top: 0.25rem\n margin-bottom: 0.25rem\n\n > p:last-child\n margin-top: 0.25rem\n\n > ul,\n > ol\n margin-top: 0.5rem\n margin-bottom: 0.5rem\n\nol\n &.arabic\n list-style: decimal\n &.loweralpha\n list-style: lower-alpha\n &.upperalpha\n list-style: upper-alpha\n &.lowerroman\n list-style: lower-roman\n &.upperroman\n list-style: upper-roman\n\n// Don't space lists out when they're \"simple\" or in a `.. toctree::`\n.simple,\n.toctree-wrapper\n li\n > ul,\n > ol\n margin-top: 0\n margin-bottom: 0\n\n// Definition Lists\n.field-list,\n.option-list,\ndl:not([class]),\ndl.simple,\ndl.footnote,\ndl.glossary\n dt\n font-weight: 500\n margin-top: 0.25rem\n + dt\n margin-top: 0\n\n .classifier::before\n content: \":\"\n margin-left: 0.2rem\n margin-right: 0.2rem\n\n dd\n > p:first-child,\n ul\n margin-top: 0.125rem\n\n ul\n margin-bottom: 0.125rem\n",".math-wrapper\n width: 100%\n overflow-x: auto\n\ndiv.math\n position: relative\n text-align: center\n\n .headerlink,\n &:focus .headerlink\n display: none\n\n &:hover .headerlink\n display: inline-block\n\n span.eqno\n position: absolute\n right: 0.5rem\n top: 50%\n transform: translate(0, -50%)\n z-index: 1\n","// Abbreviations\nabbr[title]\n cursor: help\n\n// \"Problematic\" content, as identified by Sphinx\n.problematic\n color: var(--color-problematic)\n\n// Keyboard / Mouse \"instructions\"\nkbd:not(.compound)\n margin: 0 0.2rem\n padding: 0 0.2rem\n border-radius: 0.2rem\n border: 1px solid var(--color-foreground-border)\n color: var(--color-foreground-primary)\n vertical-align: text-bottom\n\n font-size: var(--font-size--small--3)\n display: inline-block\n\n box-shadow: 0 0.0625rem 0 rgba(0, 0, 0, 0.2), inset 0 0 0 0.125rem var(--color-background-primary)\n\n background-color: var(--color-background-secondary)\n\n// Blockquote\nblockquote\n border-left: 4px solid var(--color-background-border)\n background: var(--color-background-secondary)\n\n margin-left: 0\n margin-right: 0\n padding: 0.5rem 1rem\n\n .attribution\n font-weight: 600\n text-align: right\n\n &.pull-quote,\n &.highlights\n font-size: 1.25em\n\n &.epigraph,\n &.pull-quote\n border-left-width: 0\n border-radius: 0.5rem\n\n &.highlights\n border-left-width: 0\n background: transparent\n\n// Center align embedded-in-text images\np .reference img\n vertical-align: middle\n","p.rubric\n line-height: 1.25\n font-weight: bold\n font-size: 1.125em\n\n // For Numpy-style documentation that's got rubrics within it.\n // https://github.com/pradyunsg/furo/discussions/505\n dd &\n line-height: inherit\n font-weight: inherit\n\n font-size: var(--font-size--small)\n text-transform: uppercase\n","article .sidebar\n float: right\n clear: right\n width: 30%\n\n margin-left: 1rem\n margin-right: 0\n\n border-radius: 0.2rem\n background-color: var(--color-background-secondary)\n border: var(--color-background-border) 1px solid\n\n > *\n padding-left: 1rem\n padding-right: 1rem\n\n > ul, > ol // lists need additional padding, because bullets.\n padding-left: 2.2rem\n\n .sidebar-title\n margin: 0\n padding: 0.5rem 1rem\n border-bottom: var(--color-background-border) 1px solid\n\n font-weight: 500\n\n// TODO: subtitle\n// TODO: dedicated variables?\n",".table-wrapper\n width: 100%\n overflow-x: auto\n margin-top: 1rem\n margin-bottom: 0.5rem\n padding: 0.2rem 0.2rem 0.75rem\n\ntable.docutils\n border-radius: 0.2rem\n border-spacing: 0\n border-collapse: collapse\n\n box-shadow: 0 0.2rem 0.5rem rgba(0, 0, 0, 0.05), 0 0 0.0625rem rgba(0, 0, 0, 0.1)\n\n th\n background: var(--color-table-header-background)\n\n td,\n th\n // Space things out properly\n padding: 0 0.25rem\n\n // Get the borders looking just-right.\n border-left: 1px solid var(--color-table-border)\n border-right: 1px solid var(--color-table-border)\n border-bottom: 1px solid var(--color-table-border)\n\n p\n margin: 0.25rem\n\n &:first-child\n border-left: none\n &:last-child\n border-right: none\n\n // MyST-parser tables set these classes for control of column alignment\n &.text-left\n text-align: left\n &.text-right\n text-align: right\n &.text-center\n text-align: center\n",":target\n scroll-margin-top: 2.5rem\n\n@media (max-width: $full-width - $sidebar-width)\n :target\n scroll-margin-top: calc(2.5rem + var(--header-height))\n\n // When a heading is selected\n section > span:target\n scroll-margin-top: calc(2.8rem + var(--header-height))\n\n// Permalinks\n.headerlink\n font-weight: 100\n user-select: none\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\ndl dt,\np.caption,\nfigcaption p,\ntable > caption,\n.code-block-caption\n > .headerlink\n margin-left: 0.5rem\n visibility: hidden\n &:hover > .headerlink\n visibility: visible\n\n // Don't change to link-like, if someone adds the contents directive.\n > .toc-backref\n color: inherit\n text-decoration-line: none\n\n// Figure and table captions are special.\nfigure:hover > figcaption > p > .headerlink,\ntable:hover > caption > .headerlink\n visibility: visible\n\n:target >, // Regular section[id] style anchors\nspan:target ~ // Non-regular span[id] style \"extra\" anchors\n h1,\n h2,\n h3,\n h4,\n h5,\n h6\n &:nth-of-type(1)\n background-color: var(--color-highlight-on-target)\n // .headerlink\n // visibility: visible\n code.literal\n background-color: transparent\n\ntable:target > caption,\nfigure:target\n background-color: var(--color-highlight-on-target)\n\n// Inline page contents\n.this-will-duplicate-information-and-it-is-still-useful-here li :target\n background-color: var(--color-highlight-on-target)\n\n// Code block permalinks\n.literal-block-wrapper:target .code-block-caption\n background-color: var(--color-highlight-on-target)\n\n// When a definition list item is selected\n//\n// There isn't really an alternative to !important here, due to the\n// high-specificity of API documentation's selector.\ndt:target\n background-color: var(--color-highlight-on-target) !important\n\n// When a footnote reference is selected\n.footnote > dt:target + dd,\n.footnote-reference:target\n background-color: var(--color-highlight-on-target)\n",".guilabel\n background-color: var(--color-guilabel-background)\n border: 1px solid var(--color-guilabel-border)\n color: var(--color-guilabel-text)\n\n padding: 0 0.3em\n border-radius: 0.5em\n font-size: 0.9em\n","// This file contains the styles used for stylizing the footer that's shown\n// below the content.\n\nfooter\n font-size: var(--font-size--small)\n display: flex\n flex-direction: column\n\n margin-top: 2rem\n\n// Bottom of page information\n.bottom-of-page\n display: flex\n align-items: center\n justify-content: space-between\n\n margin-top: 1rem\n padding-top: 1rem\n padding-bottom: 1rem\n\n color: var(--color-foreground-secondary)\n border-top: 1px solid var(--color-background-border)\n\n line-height: 1.5\n\n @media (max-width: $content-width)\n text-align: center\n flex-direction: column-reverse\n gap: 0.25rem\n\n .left-details\n font-size: var(--font-size--small)\n\n .right-details\n display: flex\n flex-direction: column\n gap: 0.25rem\n text-align: right\n\n .icons\n display: flex\n justify-content: flex-end\n gap: 0.25rem\n font-size: 1rem\n\n a\n text-decoration: none\n\n svg,\n img\n font-size: 1.125rem\n height: 1em\n width: 1em\n\n// Next/Prev page information\n.related-pages\n a\n display: flex\n align-items: center\n\n text-decoration: none\n &:hover .page-info .title\n text-decoration: underline\n color: var(--color-link)\n text-decoration-color: var(--color-link-underline)\n\n svg.furo-related-icon,\n svg.furo-related-icon > use\n flex-shrink: 0\n\n color: var(--color-foreground-border)\n\n width: 0.75rem\n height: 0.75rem\n margin: 0 0.5rem\n\n &.next-page\n max-width: 50%\n\n float: right\n clear: right\n text-align: right\n\n &.prev-page\n max-width: 50%\n\n float: left\n clear: left\n\n svg\n transform: rotate(180deg)\n\n.page-info\n display: flex\n flex-direction: column\n overflow-wrap: anywhere\n\n .next-page &\n align-items: flex-end\n\n .context\n display: flex\n align-items: center\n\n padding-bottom: 0.1rem\n\n color: var(--color-foreground-muted)\n font-size: var(--font-size--small)\n text-decoration: none\n","// This file contains the styles for the contents of the left sidebar, which\n// contains the navigation tree, logo, search etc.\n\n////////////////////////////////////////////////////////////////////////////////\n// Brand on top of the scrollable tree.\n////////////////////////////////////////////////////////////////////////////////\n.sidebar-brand\n display: flex\n flex-direction: column\n flex-shrink: 0\n\n padding: var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal)\n text-decoration: none\n\n.sidebar-brand-text\n color: var(--color-sidebar-brand-text)\n overflow-wrap: break-word\n margin: var(--sidebar-item-spacing-vertical) 0\n font-size: 1.5rem\n\n.sidebar-logo-container\n margin: var(--sidebar-item-spacing-vertical) 0\n\n.sidebar-logo\n margin: 0 auto\n display: block\n max-width: 100%\n\n////////////////////////////////////////////////////////////////////////////////\n// Search\n////////////////////////////////////////////////////////////////////////////////\n.sidebar-search-container\n display: flex\n align-items: center\n margin-top: var(--sidebar-search-space-above)\n\n position: relative\n\n background: var(--color-sidebar-search-background)\n &:hover,\n &:focus-within\n background: var(--color-sidebar-search-background--focus)\n\n &::before\n content: \"\"\n position: absolute\n left: var(--sidebar-item-spacing-horizontal)\n width: var(--sidebar-search-icon-size)\n height: var(--sidebar-search-icon-size)\n\n background-color: var(--color-sidebar-search-icon)\n mask-image: var(--icon-search)\n\n.sidebar-search\n box-sizing: border-box\n\n border: none\n border-top: 1px solid var(--color-sidebar-search-border)\n border-bottom: 1px solid var(--color-sidebar-search-border)\n\n padding-top: var(--sidebar-search-input-spacing-vertical)\n padding-bottom: var(--sidebar-search-input-spacing-vertical)\n padding-right: var(--sidebar-search-input-spacing-horizontal)\n padding-left: calc(var(--sidebar-item-spacing-horizontal) + var(--sidebar-search-input-spacing-horizontal) + var(--sidebar-search-icon-size))\n\n width: 100%\n\n color: var(--color-sidebar-search-foreground)\n background: transparent\n z-index: 10\n\n &:focus\n outline: none\n\n &::placeholder\n font-size: var(--sidebar-search-input-font-size)\n\n//\n// Hide Search Matches link\n//\n#searchbox .highlight-link\n padding: var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal) 0\n margin: 0\n text-align: center\n\n a\n color: var(--color-sidebar-search-icon)\n font-size: var(--font-size--small--2)\n\n////////////////////////////////////////////////////////////////////////////////\n// Structure/Skeleton of the navigation tree (left)\n////////////////////////////////////////////////////////////////////////////////\n.sidebar-tree\n font-size: var(--sidebar-item-font-size)\n margin-top: var(--sidebar-tree-space-above)\n margin-bottom: var(--sidebar-item-spacing-vertical)\n\n ul\n padding: 0\n margin-top: 0\n margin-bottom: 0\n\n display: flex\n flex-direction: column\n\n list-style: none\n\n li\n position: relative\n margin: 0\n\n > ul\n margin-left: var(--sidebar-item-spacing-horizontal)\n\n .icon\n color: var(--color-sidebar-link-text)\n\n .reference\n box-sizing: border-box\n color: var(--color-sidebar-link-text)\n\n // Fill the parent.\n display: inline-block\n line-height: var(--sidebar-item-line-height)\n text-decoration: none\n\n // Don't allow long words to cause wrapping.\n overflow-wrap: anywhere\n\n height: 100%\n width: 100%\n\n padding: var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal)\n\n &:hover\n color: var(--color-sidebar-link-text)\n background: var(--color-sidebar-item-background--hover)\n\n // Add a nice little \"external-link\" arrow here.\n &.external::after\n content: url('data:image/svg+xml,')\n margin: 0 0.25rem\n vertical-align: middle\n color: var(--color-sidebar-link-text)\n\n // Make the current page reference bold.\n .current-page > .reference\n font-weight: bold\n\n label\n position: absolute\n top: 0\n right: 0\n height: var(--sidebar-item-height)\n width: var(--sidebar-expander-width)\n\n cursor: pointer\n user-select: none\n\n display: flex\n justify-content: center\n align-items: center\n\n .caption, :not(.caption) > .caption-text\n font-size: var(--sidebar-caption-font-size)\n color: var(--color-sidebar-caption-text)\n\n font-weight: bold\n text-transform: uppercase\n\n margin: var(--sidebar-caption-space-above) 0 0 0\n padding: var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal)\n\n // If it has children, add a bit more padding to wrap the content to avoid\n // overlapping with the