diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 9dc044fc..22a7b125 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -16,6 +16,10 @@ jobs: run: | pip install sphinx sphinx_rtd_theme myst_parser + - name: Sphinx generate structure + run: | + sphinx-apidoc -o doc src + - name: Sphinx build run: | sphinx-build doc _build diff --git a/.gitignore b/.gitignore index bafded47..0bdba649 100644 --- a/.gitignore +++ b/.gitignore @@ -20,8 +20,9 @@ config.yml # caches **cache* -# build files +# build/dev directories dist/ +.grip/ # large data & log folders _data/ diff --git a/.idea/syncify.iml b/.idea/syncify.iml index 3ee3cd4c..3c7ef020 100644 --- a/.idea/syncify.iml +++ b/.idea/syncify.iml @@ -19,6 +19,7 @@ + diff --git a/README.template.md b/README.template.md index 51d6f07c..73076dca 100644 --- a/README.template.md +++ b/README.template.md @@ -101,7 +101,7 @@ print(track1, track2, track3, album, playlist, artist) ``` 5. Add some tracks to a playlist in your library, synchronise with Spotify, and log the results - (assuming you chose to load your entire library or your just your playlists in step 3). + (assuming you chose to either load your entire library or just your playlists in step 3). ```python my_playlist = library.playlists[""] my_playlist.append(track1) diff --git a/_build/.buildinfo b/_build/.buildinfo new file mode 100644 index 00000000..208ab364 --- /dev/null +++ b/_build/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: 6f9d293138706817b2d16b1be9dff296 +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/_build/.doctrees/environment.pickle b/_build/.doctrees/environment.pickle new file mode 100644 index 00000000..d7ba34ee Binary files /dev/null and b/_build/.doctrees/environment.pickle differ diff --git a/_build/.doctrees/index.doctree b/_build/.doctrees/index.doctree new file mode 100644 index 00000000..e9ec9c2c Binary files /dev/null and b/_build/.doctrees/index.doctree differ diff --git a/_build/.doctrees/modules.doctree b/_build/.doctrees/modules.doctree new file mode 100644 index 00000000..74968bae Binary files /dev/null and b/_build/.doctrees/modules.doctree differ diff --git a/_build/.doctrees/syncify.abstract.doctree b/_build/.doctrees/syncify.abstract.doctree new file mode 100644 index 00000000..5e89fd75 Binary files /dev/null and b/_build/.doctrees/syncify.abstract.doctree differ diff --git a/_build/.doctrees/syncify.api.doctree b/_build/.doctrees/syncify.api.doctree new file mode 100644 index 00000000..9f08e129 Binary files /dev/null and b/_build/.doctrees/syncify.api.doctree differ diff --git a/_build/.doctrees/syncify.doctree b/_build/.doctrees/syncify.doctree new file mode 100644 index 00000000..7e08b4b0 Binary files /dev/null and b/_build/.doctrees/syncify.doctree differ diff --git a/_build/.doctrees/syncify.local.doctree b/_build/.doctrees/syncify.local.doctree new file mode 100644 index 00000000..0f0adc95 Binary files /dev/null and b/_build/.doctrees/syncify.local.doctree differ diff --git a/_build/.doctrees/syncify.local.library.doctree b/_build/.doctrees/syncify.local.library.doctree new file mode 100644 index 00000000..43c22d2d Binary files /dev/null and b/_build/.doctrees/syncify.local.library.doctree differ diff --git a/_build/.doctrees/syncify.local.playlist.doctree b/_build/.doctrees/syncify.local.playlist.doctree new file mode 100644 index 00000000..493add51 Binary files /dev/null and b/_build/.doctrees/syncify.local.playlist.doctree differ diff --git a/_build/.doctrees/syncify.local.track.doctree b/_build/.doctrees/syncify.local.track.doctree new file mode 100644 index 00000000..80e8c2b4 Binary files /dev/null and b/_build/.doctrees/syncify.local.track.doctree differ diff --git a/_build/.doctrees/syncify.processors.doctree b/_build/.doctrees/syncify.processors.doctree new file mode 100644 index 00000000..69dc3fad Binary files /dev/null and b/_build/.doctrees/syncify.processors.doctree differ diff --git a/_build/.doctrees/syncify.remote.doctree b/_build/.doctrees/syncify.remote.doctree new file mode 100644 index 00000000..051acc8a Binary files /dev/null and b/_build/.doctrees/syncify.remote.doctree differ diff --git a/_build/.doctrees/syncify.remote.processors.doctree b/_build/.doctrees/syncify.remote.processors.doctree new file mode 100644 index 00000000..fa5a321e Binary files /dev/null and b/_build/.doctrees/syncify.remote.processors.doctree differ diff --git a/_build/.doctrees/syncify.spotify.api.doctree b/_build/.doctrees/syncify.spotify.api.doctree new file mode 100644 index 00000000..e4bc3121 Binary files /dev/null and b/_build/.doctrees/syncify.spotify.api.doctree differ diff --git a/_build/.doctrees/syncify.spotify.doctree b/_build/.doctrees/syncify.spotify.doctree new file mode 100644 index 00000000..dbcc5456 Binary files /dev/null and b/_build/.doctrees/syncify.spotify.doctree differ diff --git a/_build/.doctrees/syncify.spotify.processors.doctree b/_build/.doctrees/syncify.spotify.processors.doctree new file mode 100644 index 00000000..683b5dc5 Binary files /dev/null and b/_build/.doctrees/syncify.spotify.processors.doctree differ diff --git a/_build/.doctrees/syncify.utils.doctree b/_build/.doctrees/syncify.utils.doctree new file mode 100644 index 00000000..135a13ff Binary files /dev/null and b/_build/.doctrees/syncify.utils.doctree differ diff --git a/_build/_sources/index.rst.txt b/_build/_sources/index.rst.txt new file mode 100644 index 00000000..fad44db0 --- /dev/null +++ b/_build/_sources/index.rst.txt @@ -0,0 +1,20 @@ +.. Syncify documentation master file, created by + sphinx-quickstart on Fri Jan 5 21:58:01 2024. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to Syncify's documentation! +=================================== + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/_build/_sources/modules.rst.txt b/_build/_sources/modules.rst.txt new file mode 100644 index 00000000..5e6c4152 --- /dev/null +++ b/_build/_sources/modules.rst.txt @@ -0,0 +1,7 @@ +src +=== + +.. toctree:: + :maxdepth: 4 + + syncify diff --git a/_build/_sources/syncify.abstract.rst.txt b/_build/_sources/syncify.abstract.rst.txt new file mode 100644 index 00000000..54196b1f --- /dev/null +++ b/_build/_sources/syncify.abstract.rst.txt @@ -0,0 +1,45 @@ +syncify.abstract package +======================== + +Submodules +---------- + +syncify.abstract.collection module +---------------------------------- + +.. automodule:: syncify.abstract.collection + :members: + :undoc-members: + :show-inheritance: + +syncify.abstract.enums module +----------------------------- + +.. automodule:: syncify.abstract.enums + :members: + :undoc-members: + :show-inheritance: + +syncify.abstract.misc module +---------------------------- + +.. automodule:: syncify.abstract.misc + :members: + :undoc-members: + :show-inheritance: + +syncify.abstract.object module +------------------------------ + +.. automodule:: syncify.abstract.object + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: syncify.abstract + :members: + :undoc-members: + :show-inheritance: diff --git a/_build/_sources/syncify.api.rst.txt b/_build/_sources/syncify.api.rst.txt new file mode 100644 index 00000000..117f61ef --- /dev/null +++ b/_build/_sources/syncify.api.rst.txt @@ -0,0 +1,21 @@ +syncify.api package +=================== + +Submodules +---------- + +syncify.api.exception module +---------------------------- + +.. automodule:: syncify.api.exception + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: syncify.api + :members: + :undoc-members: + :show-inheritance: diff --git a/_build/_sources/syncify.local.library.rst.txt b/_build/_sources/syncify.local.library.rst.txt new file mode 100644 index 00000000..50cbfe12 --- /dev/null +++ b/_build/_sources/syncify.local.library.rst.txt @@ -0,0 +1,10 @@ +syncify.local.library package +============================= + +Module contents +--------------- + +.. automodule:: syncify.local.library + :members: + :undoc-members: + :show-inheritance: diff --git a/_build/_sources/syncify.local.playlist.rst.txt b/_build/_sources/syncify.local.playlist.rst.txt new file mode 100644 index 00000000..1204319d --- /dev/null +++ b/_build/_sources/syncify.local.playlist.rst.txt @@ -0,0 +1,10 @@ +syncify.local.playlist package +============================== + +Module contents +--------------- + +.. automodule:: syncify.local.playlist + :members: + :undoc-members: + :show-inheritance: diff --git a/_build/_sources/syncify.local.rst.txt b/_build/_sources/syncify.local.rst.txt new file mode 100644 index 00000000..64ea3366 --- /dev/null +++ b/_build/_sources/syncify.local.rst.txt @@ -0,0 +1,39 @@ +syncify.local package +===================== + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + syncify.local.library + syncify.local.playlist + syncify.local.track + +Submodules +---------- + +syncify.local.collection module +------------------------------- + +.. automodule:: syncify.local.collection + :members: + :undoc-members: + :show-inheritance: + +syncify.local.exception module +------------------------------ + +.. automodule:: syncify.local.exception + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: syncify.local + :members: + :undoc-members: + :show-inheritance: diff --git a/_build/_sources/syncify.local.track.rst.txt b/_build/_sources/syncify.local.track.rst.txt new file mode 100644 index 00000000..d92ae5d7 --- /dev/null +++ b/_build/_sources/syncify.local.track.rst.txt @@ -0,0 +1,10 @@ +syncify.local.track package +=========================== + +Module contents +--------------- + +.. automodule:: syncify.local.track + :members: + :undoc-members: + :show-inheritance: diff --git a/_build/_sources/syncify.processors.rst.txt b/_build/_sources/syncify.processors.rst.txt new file mode 100644 index 00000000..45ad6c9d --- /dev/null +++ b/_build/_sources/syncify.processors.rst.txt @@ -0,0 +1,69 @@ +syncify.processors package +========================== + +Submodules +---------- + +syncify.processors.base module +------------------------------ + +.. automodule:: syncify.processors.base + :members: + :undoc-members: + :show-inheritance: + +syncify.processors.compare module +--------------------------------- + +.. automodule:: syncify.processors.compare + :members: + :undoc-members: + :show-inheritance: + +syncify.processors.exception module +----------------------------------- + +.. automodule:: syncify.processors.exception + :members: + :undoc-members: + :show-inheritance: + +syncify.processors.limit module +------------------------------- + +.. automodule:: syncify.processors.limit + :members: + :undoc-members: + :show-inheritance: + +syncify.processors.match module +------------------------------- + +.. automodule:: syncify.processors.match + :members: + :undoc-members: + :show-inheritance: + +syncify.processors.sort module +------------------------------ + +.. automodule:: syncify.processors.sort + :members: + :undoc-members: + :show-inheritance: + +syncify.processors.time module +------------------------------ + +.. automodule:: syncify.processors.time + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: syncify.processors + :members: + :undoc-members: + :show-inheritance: diff --git a/_build/_sources/syncify.remote.processors.rst.txt b/_build/_sources/syncify.remote.processors.rst.txt new file mode 100644 index 00000000..b7a3d830 --- /dev/null +++ b/_build/_sources/syncify.remote.processors.rst.txt @@ -0,0 +1,37 @@ +syncify.remote.processors package +================================= + +Submodules +---------- + +syncify.remote.processors.check module +-------------------------------------- + +.. automodule:: syncify.remote.processors.check + :members: + :undoc-members: + :show-inheritance: + +syncify.remote.processors.search module +--------------------------------------- + +.. automodule:: syncify.remote.processors.search + :members: + :undoc-members: + :show-inheritance: + +syncify.remote.processors.wrangle module +---------------------------------------- + +.. automodule:: syncify.remote.processors.wrangle + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: syncify.remote.processors + :members: + :undoc-members: + :show-inheritance: diff --git a/_build/_sources/syncify.remote.rst.txt b/_build/_sources/syncify.remote.rst.txt new file mode 100644 index 00000000..2ae1b509 --- /dev/null +++ b/_build/_sources/syncify.remote.rst.txt @@ -0,0 +1,85 @@ +syncify.remote package +====================== + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + syncify.remote.processors + +Submodules +---------- + +syncify.remote.api module +------------------------- + +.. automodule:: syncify.remote.api + :members: + :undoc-members: + :show-inheritance: + +syncify.remote.base module +-------------------------- + +.. automodule:: syncify.remote.base + :members: + :undoc-members: + :show-inheritance: + +syncify.remote.config module +---------------------------- + +.. automodule:: syncify.remote.config + :members: + :undoc-members: + :show-inheritance: + +syncify.remote.enums module +--------------------------- + +.. automodule:: syncify.remote.enums + :members: + :undoc-members: + :show-inheritance: + +syncify.remote.exception module +------------------------------- + +.. automodule:: syncify.remote.exception + :members: + :undoc-members: + :show-inheritance: + +syncify.remote.library module +----------------------------- + +.. automodule:: syncify.remote.library + :members: + :undoc-members: + :show-inheritance: + +syncify.remote.object module +---------------------------- + +.. automodule:: syncify.remote.object + :members: + :undoc-members: + :show-inheritance: + +syncify.remote.types module +--------------------------- + +.. automodule:: syncify.remote.types + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: syncify.remote + :members: + :undoc-members: + :show-inheritance: diff --git a/_build/_sources/syncify.rst.txt b/_build/_sources/syncify.rst.txt new file mode 100644 index 00000000..20915f24 --- /dev/null +++ b/_build/_sources/syncify.rst.txt @@ -0,0 +1,59 @@ +syncify package +=============== + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + syncify.abstract + syncify.api + syncify.local + syncify.processors + syncify.remote + syncify.spotify + syncify.utils + +Submodules +---------- + +syncify.config module +--------------------- + +.. automodule:: syncify.config + :members: + :undoc-members: + :show-inheritance: + +syncify.exception module +------------------------ + +.. automodule:: syncify.exception + :members: + :undoc-members: + :show-inheritance: + +syncify.fields module +--------------------- + +.. automodule:: syncify.fields + :members: + :undoc-members: + :show-inheritance: + +syncify.report module +--------------------- + +.. automodule:: syncify.report + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: syncify + :members: + :undoc-members: + :show-inheritance: diff --git a/_build/_sources/syncify.spotify.api.rst.txt b/_build/_sources/syncify.spotify.api.rst.txt new file mode 100644 index 00000000..2a754a43 --- /dev/null +++ b/_build/_sources/syncify.spotify.api.rst.txt @@ -0,0 +1,10 @@ +syncify.spotify.api package +=========================== + +Module contents +--------------- + +.. automodule:: syncify.spotify.api + :members: + :undoc-members: + :show-inheritance: diff --git a/_build/_sources/syncify.spotify.processors.rst.txt b/_build/_sources/syncify.spotify.processors.rst.txt new file mode 100644 index 00000000..bdb2a954 --- /dev/null +++ b/_build/_sources/syncify.spotify.processors.rst.txt @@ -0,0 +1,29 @@ +syncify.spotify.processors package +================================== + +Submodules +---------- + +syncify.spotify.processors.processors module +-------------------------------------------- + +.. automodule:: syncify.spotify.processors.processors + :members: + :undoc-members: + :show-inheritance: + +syncify.spotify.processors.wrangle module +----------------------------------------- + +.. automodule:: syncify.spotify.processors.wrangle + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: syncify.spotify.processors + :members: + :undoc-members: + :show-inheritance: diff --git a/_build/_sources/syncify.spotify.rst.txt b/_build/_sources/syncify.spotify.rst.txt new file mode 100644 index 00000000..4fbd5058 --- /dev/null +++ b/_build/_sources/syncify.spotify.rst.txt @@ -0,0 +1,62 @@ +syncify.spotify package +======================= + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + syncify.spotify.api + syncify.spotify.processors + +Submodules +---------- + +syncify.spotify.base module +--------------------------- + +.. automodule:: syncify.spotify.base + :members: + :undoc-members: + :show-inheritance: + +syncify.spotify.config module +----------------------------- + +.. automodule:: syncify.spotify.config + :members: + :undoc-members: + :show-inheritance: + +syncify.spotify.exception module +-------------------------------- + +.. automodule:: syncify.spotify.exception + :members: + :undoc-members: + :show-inheritance: + +syncify.spotify.library module +------------------------------ + +.. automodule:: syncify.spotify.library + :members: + :undoc-members: + :show-inheritance: + +syncify.spotify.object module +----------------------------- + +.. automodule:: syncify.spotify.object + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: syncify.spotify + :members: + :undoc-members: + :show-inheritance: diff --git a/_build/_sources/syncify.utils.rst.txt b/_build/_sources/syncify.utils.rst.txt new file mode 100644 index 00000000..e40e506f --- /dev/null +++ b/_build/_sources/syncify.utils.rst.txt @@ -0,0 +1,37 @@ +syncify.utils package +===================== + +Submodules +---------- + +syncify.utils.helpers module +---------------------------- + +.. automodule:: syncify.utils.helpers + :members: + :undoc-members: + :show-inheritance: + +syncify.utils.logger module +--------------------------- + +.. automodule:: syncify.utils.logger + :members: + :undoc-members: + :show-inheritance: + +syncify.utils.printers module +----------------------------- + +.. automodule:: syncify.utils.printers + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: syncify.utils + :members: + :undoc-members: + :show-inheritance: diff --git a/_build/_static/alabaster.css b/_build/_static/alabaster.css new file mode 100644 index 00000000..c1a69613 --- /dev/null +++ b/_build/_static/alabaster.css @@ -0,0 +1,703 @@ +@import url("basic.css"); + +/* -- page layout ----------------------------------------------------------- */ + +body { + font-family: Georgia, serif; + font-size: 17px; + background-color: #fff; + color: #000; + margin: 0; + padding: 0; +} + + +div.document { + width: 940px; + margin: 30px auto 0 auto; +} + +div.documentwrapper { + float: left; + width: 100%; +} + +div.bodywrapper { + margin: 0 0 0 220px; +} + +div.sphinxsidebar { + width: 220px; + font-size: 14px; + line-height: 1.5; +} + +hr { + border: 1px solid #B1B4B6; +} + +div.body { + background-color: #fff; + color: #3E4349; + padding: 0 30px 0 30px; +} + +div.body > .section { + text-align: left; +} + +div.footer { + width: 940px; + margin: 20px auto 30px auto; + font-size: 14px; + color: #888; + text-align: right; +} + +div.footer a { + color: #888; +} + +p.caption { + font-family: inherit; + font-size: inherit; +} + + +div.relations { + display: none; +} + + +div.sphinxsidebar a { + color: #444; + text-decoration: none; + border-bottom: 1px dotted #999; +} + +div.sphinxsidebar a:hover { + border-bottom: 1px solid #999; +} + +div.sphinxsidebarwrapper { + padding: 18px 10px; +} + +div.sphinxsidebarwrapper p.logo { + padding: 0; + margin: -10px 0 0 0px; + text-align: center; +} + +div.sphinxsidebarwrapper h1.logo { + margin-top: -10px; + text-align: center; + margin-bottom: 5px; + text-align: left; +} + +div.sphinxsidebarwrapper h1.logo-name { + margin-top: 0px; +} + +div.sphinxsidebarwrapper p.blurb { + margin-top: 0; + font-style: normal; +} + +div.sphinxsidebar h3, +div.sphinxsidebar h4 { + font-family: Georgia, serif; + color: #444; + font-size: 24px; + font-weight: normal; + margin: 0 0 5px 0; + padding: 0; +} + +div.sphinxsidebar h4 { + font-size: 20px; +} + +div.sphinxsidebar h3 a { + color: #444; +} + +div.sphinxsidebar p.logo a, +div.sphinxsidebar h3 a, +div.sphinxsidebar p.logo a:hover, +div.sphinxsidebar h3 a:hover { + border: none; +} + +div.sphinxsidebar p { + color: #555; + margin: 10px 0; +} + +div.sphinxsidebar ul { + margin: 10px 0; + padding: 0; + color: #000; +} + +div.sphinxsidebar ul li.toctree-l1 > a { + font-size: 120%; +} + +div.sphinxsidebar ul li.toctree-l2 > a { + font-size: 110%; +} + +div.sphinxsidebar input { + border: 1px solid #CCC; + font-family: Georgia, serif; + font-size: 1em; +} + +div.sphinxsidebar hr { + border: none; + height: 1px; + color: #AAA; + background: #AAA; + + text-align: left; + margin-left: 0; + width: 50%; +} + +div.sphinxsidebar .badge { + border-bottom: none; +} + +div.sphinxsidebar .badge:hover { + border-bottom: none; +} + +/* To address an issue with donation coming after search */ +div.sphinxsidebar h3.donation { + margin-top: 10px; +} + +/* -- body styles ----------------------------------------------------------- */ + +a { + color: #004B6B; + text-decoration: underline; +} + +a:hover { + color: #6D4100; + text-decoration: underline; +} + +div.body h1, +div.body h2, +div.body h3, +div.body h4, +div.body h5, +div.body h6 { + font-family: Georgia, serif; + font-weight: normal; + margin: 30px 0px 10px 0px; + padding: 0; +} + +div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; } +div.body h2 { font-size: 180%; } +div.body h3 { font-size: 150%; } +div.body h4 { font-size: 130%; } +div.body h5 { font-size: 100%; } +div.body h6 { font-size: 100%; } + +a.headerlink { + color: #DDD; + padding: 0 4px; + text-decoration: none; +} + +a.headerlink:hover { + color: #444; + background: #EAEAEA; +} + +div.body p, div.body dd, div.body li { + line-height: 1.4em; +} + +div.admonition { + margin: 20px 0px; + padding: 10px 30px; + background-color: #EEE; + border: 1px solid #CCC; +} + +div.admonition tt.xref, div.admonition code.xref, div.admonition a tt { + background-color: #FBFBFB; + border-bottom: 1px solid #fafafa; +} + +div.admonition p.admonition-title { + font-family: Georgia, serif; + font-weight: normal; + font-size: 24px; + margin: 0 0 10px 0; + padding: 0; + line-height: 1; +} + +div.admonition p.last { + margin-bottom: 0; +} + +div.highlight { + background-color: #fff; +} + +dt:target, .highlight { + background: #FAF3E8; +} + +div.warning { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.danger { + background-color: #FCC; + border: 1px solid #FAA; + -moz-box-shadow: 2px 2px 4px #D52C2C; + -webkit-box-shadow: 2px 2px 4px #D52C2C; + box-shadow: 2px 2px 4px #D52C2C; +} + +div.error { + background-color: #FCC; + border: 1px solid #FAA; + -moz-box-shadow: 2px 2px 4px #D52C2C; + -webkit-box-shadow: 2px 2px 4px #D52C2C; + box-shadow: 2px 2px 4px #D52C2C; +} + +div.caution { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.attention { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.important { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.note { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.tip { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.hint { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.seealso { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.topic { + background-color: #EEE; +} + +p.admonition-title { + display: inline; +} + +p.admonition-title:after { + content: ":"; +} + +pre, tt, code { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; + font-size: 0.9em; +} + +.hll { + background-color: #FFC; + margin: 0 -12px; + padding: 0 12px; + display: block; +} + +img.screenshot { +} + +tt.descname, tt.descclassname, code.descname, code.descclassname { + font-size: 0.95em; +} + +tt.descname, code.descname { + padding-right: 0.08em; +} + +img.screenshot { + -moz-box-shadow: 2px 2px 4px #EEE; + -webkit-box-shadow: 2px 2px 4px #EEE; + box-shadow: 2px 2px 4px #EEE; +} + +table.docutils { + border: 1px solid #888; + -moz-box-shadow: 2px 2px 4px #EEE; + -webkit-box-shadow: 2px 2px 4px #EEE; + box-shadow: 2px 2px 4px #EEE; +} + +table.docutils td, table.docutils th { + border: 1px solid #888; + padding: 0.25em 0.7em; +} + +table.field-list, table.footnote { + border: none; + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; +} + +table.footnote { + margin: 15px 0; + width: 100%; + border: 1px solid #EEE; + background: #FDFDFD; + font-size: 0.9em; +} + +table.footnote + table.footnote { + margin-top: -15px; + border-top: none; +} + +table.field-list th { + padding: 0 0.8em 0 0; +} + +table.field-list td { + padding: 0; +} + +table.field-list p { + margin-bottom: 0.8em; +} + +/* Cloned from + * https://github.com/sphinx-doc/sphinx/commit/ef60dbfce09286b20b7385333d63a60321784e68 + */ +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +table.footnote td.label { + width: .1px; + padding: 0.3em 0 0.3em 0.5em; +} + +table.footnote td { + padding: 0.3em 0.5em; +} + +dl { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding: 0; +} + +dl dd { + margin-left: 30px; +} + +blockquote { + margin: 0 0 0 30px; + padding: 0; +} + +ul, ol { + /* Matches the 30px from the narrow-screen "li > ul" selector below */ + margin: 10px 0 10px 30px; + padding: 0; +} + +pre { + background: #EEE; + padding: 7px 30px; + margin: 15px 0px; + line-height: 1.3em; +} + +div.viewcode-block:target { + background: #ffd; +} + +dl pre, blockquote pre, li pre { + margin-left: 0; + padding-left: 30px; +} + +tt, code { + background-color: #ecf0f3; + color: #222; + /* padding: 1px 2px; */ +} + +tt.xref, code.xref, a tt { + background-color: #FBFBFB; + border-bottom: 1px solid #fff; +} + +a.reference { + text-decoration: none; + border-bottom: 1px dotted #004B6B; +} + +/* Don't put an underline on images */ +a.image-reference, a.image-reference:hover { + border-bottom: none; +} + +a.reference:hover { + border-bottom: 1px solid #6D4100; +} + +a.footnote-reference { + text-decoration: none; + font-size: 0.7em; + vertical-align: top; + border-bottom: 1px dotted #004B6B; +} + +a.footnote-reference:hover { + border-bottom: 1px solid #6D4100; +} + +a:hover tt, a:hover code { + background: #EEE; +} + + +@media screen and (max-width: 870px) { + + div.sphinxsidebar { + display: none; + } + + div.document { + width: 100%; + + } + + div.documentwrapper { + margin-left: 0; + margin-top: 0; + margin-right: 0; + margin-bottom: 0; + } + + div.bodywrapper { + margin-top: 0; + margin-right: 0; + margin-bottom: 0; + margin-left: 0; + } + + ul { + margin-left: 0; + } + + li > ul { + /* Matches the 30px from the "ul, ol" selector above */ + margin-left: 30px; + } + + .document { + width: auto; + } + + .footer { + width: auto; + } + + .bodywrapper { + margin: 0; + } + + .footer { + width: auto; + } + + .github { + display: none; + } + + + +} + + + +@media screen and (max-width: 875px) { + + body { + margin: 0; + padding: 20px 30px; + } + + div.documentwrapper { + float: none; + background: #fff; + } + + div.sphinxsidebar { + display: block; + float: none; + width: 102.5%; + margin: 50px -30px -20px -30px; + padding: 10px 20px; + background: #333; + color: #FFF; + } + + div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p, + div.sphinxsidebar h3 a { + color: #fff; + } + + div.sphinxsidebar a { + color: #AAA; + } + + div.sphinxsidebar p.logo { + display: none; + } + + div.document { + width: 100%; + margin: 0; + } + + div.footer { + display: none; + } + + div.bodywrapper { + margin: 0; + } + + div.body { + min-height: 0; + padding: 0; + } + + .rtd_doc_footer { + display: none; + } + + .document { + width: auto; + } + + .footer { + width: auto; + } + + .footer { + width: auto; + } + + .github { + display: none; + } +} + + +/* misc. */ + +.revsys-inline { + display: none!important; +} + +/* Make nested-list/multi-paragraph items look better in Releases changelog + * pages. Without this, docutils' magical list fuckery causes inconsistent + * formatting between different release sub-lists. + */ +div#changelog > div.section > ul > li > p:only-child { + margin-bottom: 0; +} + +/* Hide fugly table cell borders in ..bibliography:: directive output */ +table.docutils.citation, table.docutils.citation td, table.docutils.citation th { + border: none; + /* Below needed in some edge cases; if not applied, bottom shadows appear */ + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; +} + + +/* relbar */ + +.related { + line-height: 30px; + width: 100%; + font-size: 0.9rem; +} + +.related.top { + border-bottom: 1px solid #EEE; + margin-bottom: 20px; +} + +.related.bottom { + border-top: 1px solid #EEE; +} + +.related ul { + padding: 0; + margin: 0; + list-style: none; +} + +.related li { + display: inline; +} + +nav#rellinks { + float: right; +} + +nav#rellinks li+li:before { + content: "|"; +} + +nav#breadcrumbs li+li:before { + content: "\00BB"; +} + +/* Hide certain items when printing */ +@media print { + div.related { + display: none; + } +} \ No newline at end of file diff --git a/_build/_static/basic.css b/_build/_static/basic.css new file mode 100644 index 00000000..d1901937 --- /dev/null +++ b/_build/_static/basic.css @@ -0,0 +1,925 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2023 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/_build/_static/custom.css b/_build/_static/custom.css new file mode 100644 index 00000000..2a924f1d --- /dev/null +++ b/_build/_static/custom.css @@ -0,0 +1 @@ +/* This file intentionally left blank. */ diff --git a/_build/_static/doctools.js b/_build/_static/doctools.js new file mode 100644 index 00000000..d06a71d7 --- /dev/null +++ b/_build/_static/doctools.js @@ -0,0 +1,156 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Base JavaScript utilities for all Sphinx HTML documentation. + * + * :copyright: Copyright 2007-2023 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/_build/_static/documentation_options.js b/_build/_static/documentation_options.js new file mode 100644 index 00000000..08136cae --- /dev/null +++ b/_build/_static/documentation_options.js @@ -0,0 +1,13 @@ +const DOCUMENTATION_OPTIONS = { + VERSION: '0.3', + LANGUAGE: 'en', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false, + SHOW_SEARCH_SUMMARY: true, + ENABLE_SEARCH_SHORTCUTS: true, +}; \ No newline at end of file diff --git a/_build/_static/file.png b/_build/_static/file.png new file mode 100644 index 00000000..a858a410 Binary files /dev/null and b/_build/_static/file.png differ diff --git a/_build/_static/language_data.js b/_build/_static/language_data.js new file mode 100644 index 00000000..53c120fe --- /dev/null +++ b/_build/_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-2023 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, is 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/_build/_static/minus.png b/_build/_static/minus.png new file mode 100644 index 00000000..d96755fd Binary files /dev/null and b/_build/_static/minus.png differ diff --git a/_build/_static/plus.png b/_build/_static/plus.png new file mode 100644 index 00000000..7107cec9 Binary files /dev/null and b/_build/_static/plus.png differ diff --git a/_build/_static/pygments.css b/_build/_static/pygments.css new file mode 100644 index 00000000..73b9d197 --- /dev/null +++ b/_build/_static/pygments.css @@ -0,0 +1,84 @@ +pre { line-height: 125%; } +td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +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: #004461; font-weight: bold } /* Keyword */ +.highlight .l { color: #000000 } /* Literal */ +.highlight .n { color: #000000 } /* Name */ +.highlight .o { color: #582800 } /* 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 } /* 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 } /* 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: #888888 } /* Generic.Output */ +.highlight .gp { color: #745334 } /* 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: #004461; font-weight: bold } /* Keyword.Constant */ +.highlight .kd { color: #004461; font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { color: #004461; font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { color: #004461; font-weight: bold } /* Keyword.Pseudo */ +.highlight .kr { color: #004461; font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #004461; font-weight: bold } /* Keyword.Type */ +.highlight .ld { color: #000000 } /* Literal.Date */ +.highlight .m { color: #990000 } /* Literal.Number */ +.highlight .s { color: #4e9a06 } /* Literal.String */ +.highlight .na { color: #c4a000 } /* Name.Attribute */ +.highlight .nb { color: #004461 } /* Name.Builtin */ +.highlight .nc { color: #000000 } /* Name.Class */ +.highlight .no { color: #000000 } /* Name.Constant */ +.highlight .nd { color: #888888 } /* 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: #004461; font-weight: bold } /* Name.Tag */ +.highlight .nv { color: #000000 } /* Name.Variable */ +.highlight .ow { color: #004461; font-weight: bold } /* Operator.Word */ +.highlight .pm { color: #000000; font-weight: bold } /* Punctuation.Marker */ +.highlight .w { color: #f8f8f8; text-decoration: underline } /* Text.Whitespace */ +.highlight .mb { color: #990000 } /* Literal.Number.Bin */ +.highlight .mf { color: #990000 } /* Literal.Number.Float */ +.highlight .mh { color: #990000 } /* Literal.Number.Hex */ +.highlight .mi { color: #990000 } /* Literal.Number.Integer */ +.highlight .mo { color: #990000 } /* 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: #990000 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/_build/_static/searchtools.js b/_build/_static/searchtools.js new file mode 100644 index 00000000..7918c3fa --- /dev/null +++ b/_build/_static/searchtools.js @@ -0,0 +1,574 @@ +/* + * searchtools.js + * ~~~~~~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for the full-text search. + * + * :copyright: Copyright 2007-2023 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) + ); + // 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.` + ); +}; +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); +}; + +/** + * 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) => { + const htmlElement = new DOMParser().parseFromString(htmlString, 'text/html'); + htmlElement.querySelectorAll(".headerlink").forEach((el) => { el.remove() }); + const docContent = htmlElement.querySelector('[role="main"]'); + if (docContent !== undefined) return docContent.textContent; + console.warn( + "Content block not found. Sphinx search tries to obtain it via '[role=main]'. Could you 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); + }, + + /** + * execute search (requires search index to be loaded) + */ + query: (query) => { + 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; + + // 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]); + + // array of [docname, title, anchor, descr, score, filename] + let results = []; + _removeChildren(document.getElementById("search-progress")); + + const queryLower = query.toLowerCase(); + for (const [title, foundTitles] of Object.entries(allTitles)) { + if (title.toLowerCase().includes(queryLower) && (queryLower.length >= title.length/2)) { + for (const [file, id] of foundTitles) { + let score = Math.round(100 * queryLower.length / title.length) + results.push([ + docNames[file], + titles[file] !== title ? `${titles[file]} > ${title}` : title, + id !== null ? "#" + id : "", + null, + score, + 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] of foundEntries) { + let score = Math.round(100 * queryLower.length / entry.length) + results.push([ + docNames[file], + titles[file], + id ? "#" + id : "", + null, + score, + filenames[file], + ]); + } + } + } + + // lookup as object + objectTerms.forEach((term) => + results.push(...Search.performObjectSearch(term, objectTerms)) + ); + + // lookup as search terms in fulltext + results.push(...Search.performTermsSearch(searchTerms, excludedTerms)); + + // let the scorer override scores with a custom scoring function + if (Scorer.score) results.forEach((item) => (item[4] = Scorer.score(item))); + + // now sort the results by score (in opposite order of appearance, since the + // display function below uses pop() to retrieve items) and then + // alphabetically + results.sort((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; + }); + + // 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; + }, []); + + results = results.reverse(); + + // 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); + Object.keys(terms).forEach((term) => { + if (term.match(escapedWord) && !terms[word]) + arr.push({ files: terms[term], score: Scorer.partialTerm }); + }); + Object.keys(titleTerms).forEach((term) => { + if (term.match(escapedWord) && !titleTerms[word]) + arr.push({ files: titleTerms[word], 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.get(file).indexOf(word) === -1) + fileMap.get(file).push(word); + else fileMap.set(file, [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) => { + const text = Search.htmlToText(htmlText); + 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/_build/_static/sphinx_highlight.js b/_build/_static/sphinx_highlight.js new file mode 100644 index 00000000..8a96c69a --- /dev/null +++ b/_build/_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/_build/genindex.html b/_build/genindex.html new file mode 100644 index 00000000..b10d341e --- /dev/null +++ b/_build/genindex.html @@ -0,0 +1,3039 @@ + + + + + + + Index — Syncify 0.3 documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ + +

Index

+ +
+ A + | B + | C + | D + | E + | F + | G + | H + | I + | J + | K + | L + | M + | N + | O + | P + | Q + | R + | S + | T + | U + | V + | W + | X + | Y + +
+

A

+ + + +
+ +

B

+ + + +
+ +

C

+ + + +
+ +

D

+ + + +
+ +

E

+ + + +
+ +

F

+ + + +
+ +

G

+ + + +
+ +

H

+ + + +
+ +

I

+ + + +
+ +

J

+ + +
+ +

K

+ + + +
+ +

L

+ + + +
+ +

M

+ + + +
+ +

N

+ + + +
+ +

O

+ + + +
+ +

P

+ + + +
+ +

Q

+ + + +
+ +

R

+ + + +
+ +

S

+ + + +
+ +

T

+ + + +
+ +

U

+ + + +
+ +

V

+ + + +
+ +

W

+ + + +
+ +

X

+ + +
+ +

Y

+ + + +
+ + + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/_build/index.html b/_build/index.html new file mode 100644 index 00000000..f445b36c --- /dev/null +++ b/_build/index.html @@ -0,0 +1,109 @@ + + + + + + + + Welcome to Syncify’s documentation! — Syncify 0.3 documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Welcome to Syncify’s documentation!

+
+
+
+
+

Indices and tables

+ +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/_build/modules.html b/_build/modules.html new file mode 100644 index 00000000..4a1959f3 --- /dev/null +++ b/_build/modules.html @@ -0,0 +1,418 @@ + + + + + + + + src — Syncify 0.3 documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

src

+
+ +
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/_build/objects.inv b/_build/objects.inv new file mode 100644 index 00000000..247e7dd8 Binary files /dev/null and b/_build/objects.inv differ diff --git a/_build/py-modindex.html b/_build/py-modindex.html new file mode 100644 index 00000000..8b359c64 --- /dev/null +++ b/_build/py-modindex.html @@ -0,0 +1,373 @@ + + + + + + + Python Module Index — Syncify 0.3 documentation + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ + +

Python Module Index

+ +
+ s +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 
+ s
+ syncify +
    + syncify.abstract +
    + syncify.abstract.collection +
    + syncify.abstract.enums +
    + syncify.abstract.misc +
    + syncify.abstract.object +
    + syncify.api +
    + syncify.api.exception +
    + syncify.config +
    + syncify.exception +
    + syncify.fields +
    + syncify.local +
    + syncify.local.collection +
    + syncify.local.exception +
    + syncify.local.library +
    + syncify.local.playlist +
    + syncify.local.track +
    + syncify.processors +
    + syncify.processors.base +
    + syncify.processors.compare +
    + syncify.processors.exception +
    + syncify.processors.limit +
    + syncify.processors.match +
    + syncify.processors.sort +
    + syncify.processors.time +
    + syncify.remote +
    + syncify.remote.api +
    + syncify.remote.base +
    + syncify.remote.config +
    + syncify.remote.enums +
    + syncify.remote.exception +
    + syncify.remote.library +
    + syncify.remote.object +
    + syncify.remote.processors +
    + syncify.remote.processors.check +
    + syncify.remote.processors.search +
    + syncify.remote.processors.wrangle +
    + syncify.remote.types +
    + syncify.report +
    + syncify.spotify +
    + syncify.spotify.api +
    + syncify.spotify.base +
    + syncify.spotify.config +
    + syncify.spotify.exception +
    + syncify.spotify.library +
    + syncify.spotify.object +
    + syncify.spotify.processors +
    + syncify.spotify.processors.processors +
    + syncify.spotify.processors.wrangle +
    + syncify.utils +
    + syncify.utils.helpers +
    + syncify.utils.logger +
    + syncify.utils.printers +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/_build/search.html b/_build/search.html new file mode 100644 index 00000000..f04480e9 --- /dev/null +++ b/_build/search.html @@ -0,0 +1,117 @@ + + + + + + + Search — Syncify 0.3 documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Search

+ + + + +

+ Searching for multiple words only shows matches that contain + all words. +

+ + +
+ + + +
+ + + +
+ +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/_build/searchindex.js b/_build/searchindex.js new file mode 100644 index 00000000..d9b6f155 --- /dev/null +++ b/_build/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({"docnames": ["index", "modules", "syncify", "syncify.abstract", "syncify.api", "syncify.local", "syncify.local.library", "syncify.local.playlist", "syncify.local.track", "syncify.processors", "syncify.remote", "syncify.remote.processors", "syncify.spotify", "syncify.spotify.api", "syncify.spotify.processors", "syncify.utils"], "filenames": ["index.rst", "modules.rst", "syncify.rst", "syncify.abstract.rst", "syncify.api.rst", "syncify.local.rst", "syncify.local.library.rst", "syncify.local.playlist.rst", "syncify.local.track.rst", "syncify.processors.rst", "syncify.remote.rst", "syncify.remote.processors.rst", "syncify.spotify.rst", "syncify.spotify.api.rst", "syncify.spotify.processors.rst", "syncify.utils.rst"], "titles": ["Welcome to Syncify\u2019s documentation!", "src", "syncify package", "syncify.abstract package", "syncify.api package", "syncify.local package", "syncify.local.library package", "syncify.local.playlist package", "syncify.local.track package", "syncify.processors package", "syncify.remote package", "syncify.remote.processors package", "syncify.spotify package", "syncify.spotify.api package", "syncify.spotify.processors package", "syncify.utils package"], "terms": {"index": [0, 2, 3], "modul": [0, 1], "search": [0, 2, 9, 10], "page": [0, 10], "syncifi": 1, "packag": 1, "subpackag": 1, "abstract": [1, 2, 5, 9, 10, 11], "submodul": 1, "collect": [1, 2, 9, 10, 11, 12, 14, 15], "enum": [1, 2], "misc": [1, 2], "object": [1, 2, 5, 9, 11, 14, 15], "content": 1, "api": [1, 2, 11, 12, 14], "except": [1, 3], "local": [1, 2, 10, 12], "processor": [1, 2, 5, 10, 12], "base": [1, 2, 3, 4, 5, 11, 14, 15], "compar": [1, 2], "limit": [1, 2, 3, 10, 11, 12, 15], "match": [1, 2, 3, 5, 10, 11, 15], "sort": [1, 2, 3, 15], "time": [1, 2, 15], "remot": [1, 2, 12, 14], "config": [1, 9], "librari": [1, 2, 3, 5], "type": [1, 2, 3, 5, 9, 11, 12, 14, 15], "spotifi": [1, 2], "util": [1, 2], "helper": [1, 2], "logger": [1, 2, 5, 9, 10], "printer": [1, 2], "field": [1, 3, 5, 9, 11], "report": [1, 15], "playlist": [1, 2, 3, 5, 9, 10, 11, 12], "track": [1, 2, 3, 5, 9, 10, 11, 12, 14], "check": [2, 9, 10, 14], "wrangl": [2, 10, 12], "baseconfig": [1, 2], "merg": [1, 2, 3, 5, 10, 12], "as_dict": [1, 2, 3, 5, 9, 10], "load": [1, 2, 5, 9, 10, 12], "load_log_config": [1, 2], "output_fold": [1, 2], "paus": [1, 2, 11], "reload": [1, 2, 10, 12], "configapi": [1, 2], "cache_path": [1, 2], "token_path": [1, 2], "use_cach": [1, 2, 10, 11, 12, 14], "configfilt": [1, 2], "configmatch": [1, 2], "process": [1, 2, 3, 5, 9, 11, 15], "readi": [1, 2, 3, 9], "configlibrari": [1, 2], "kind": [1, 2, 3, 5, 9, 10, 11, 12, 14], "sourc": [1, 2, 9, 10, 11, 15], "configlibrarydiffer": [1, 2], "configloc": [1, 2], "configupdatetag": [1, 2], "library_fold": [1, 2], "other_fold": [1, 2], "playlist_fold": [1, 2], "remote_wrangl": [1, 2, 5], "configmissingtag": [1, 2], "match_al": [1, 2], "tag": [1, 2, 3, 5, 9, 11], "configmusicbe": [1, 2], "musicbee_fold": [1, 2], "configplaylist": [1, 2], "configremot": [1, 2], "checker": [1, 2, 11], "searcher": [1, 2], "wrangler": [1, 2, 5], "configreportbas": [1, 2], "configreport": [1, 2], "enabl": [1, 2, 10], "configspotifi": [1, 2], "client_id": [1, 2], "client_secret": [1, 2], "scope": [1, 2], "remoteclass": [1, 2], "configerror": [1, 2], "safedict": [1, 2], "syncifyattributeerror": [1, 2], "syncifyenumerror": [1, 2], "syncifyerror": [1, 2, 4, 5, 9, 10], "syncifykeyerror": [1, 2], "syncifytypeerror": [1, 2, 3], "syncifyvalueerror": [1, 2], "albumfield": [1, 2], "album": [1, 2, 3, 5, 9, 10, 11, 12], "album_artist": [1, 2, 3, 5, 9, 12], "all": [1, 2, 3, 5, 9, 10, 11, 12, 14, 15], "artist": [1, 2, 3, 5, 9, 10, 11, 12, 14], "compil": [1, 2, 3, 5, 9, 12], "date": [1, 2, 3, 5, 9, 10, 12], "dai": [1, 2, 3, 5, 9, 12], "disc_tot": [1, 2, 3, 5, 9, 12], "genr": [1, 2, 3, 5, 9, 12], "imag": [1, 2, 3, 5, 9, 10, 12], "length": [1, 2, 3, 5, 9, 10, 11, 12, 15], "month": [1, 2, 3, 5, 9, 12], "rate": [1, 2, 3, 5, 9, 12], "track_tot": [1, 2, 3, 5, 9, 10, 12], "year": [1, 2, 3, 5, 9, 12], "artistfield": [1, 2], "folderfield": [1, 2], "folder": [1, 2, 3, 5, 9, 15], "localtrackfield": [1, 2, 5], "bit_depth": [1, 2, 3, 9], "bit_rat": [1, 2, 3, 9], "bpm": [1, 2, 3, 9, 12], "channel": [1, 2, 3, 9], "comment": [1, 2, 3, 9, 12], "date_ad": [1, 2, 3, 9, 10, 12], "date_modifi": [1, 2, 3, 9, 12], "disc": [1, 2, 3, 12], "disc_numb": [1, 2, 3, 5, 9, 12], "ext": [1, 2, 3, 9, 11, 14], "filenam": [1, 2, 3, 5, 15], "kei": [1, 2, 3, 5, 9, 10, 11, 12, 14, 15], "last_plai": [1, 2, 3, 5, 9], "path": [1, 2, 3, 5, 9, 15], "play_count": [1, 2, 3, 5, 9], "sample_r": [1, 2, 3, 9], "size": [1, 2, 3, 9, 10, 15], "titl": [1, 2, 3, 9, 10, 11, 12], "track_numb": [1, 2, 3, 5, 9, 12], "uri": [1, 2, 3, 5, 9, 10, 11, 12, 14], "playlistfield": [1, 2], "date_cr": [1, 2, 3, 9, 12], "descript": [1, 2, 3, 9, 10, 11, 12, 14], "trackfield": [1, 2], "trackfieldmixin": [1, 2], "map": [1, 2, 3, 5, 9, 10, 11, 12, 15], "report_missing_tag": [1, 2], "report_playlist_differ": [1, 2], "itemcollect": [2, 3, 5, 10, 11], "append": [2, 3, 9, 10], "clear": [2, 3, 10], "copi": [2, 3, 15], "count": [2, 3, 15], "extend": [2, 3, 9, 10, 12, 15], "insert": [2, 3], "item": [2, 3, 5, 9, 10, 11, 12, 14], "pop": [2, 3], "remov": [2, 3, 9, 10, 12, 15], "revers": [2, 3, 9], "compos": [2, 3, 9], "conductor": [2, 3, 9], "follow": [2, 3, 5, 9, 10, 11, 12], "name": [2, 3, 5, 9, 10, 11, 12, 15], "owner_id": [2, 3, 9, 10, 12], "owner_nam": [2, 3, 9, 10, 12], "publish": [2, 3, 9], "user_id": [2, 3, 9, 10], "user_nam": [2, 3, 9, 10], "syncifyenum": [2, 3, 9, 10], "from_nam": [2, 3], "from_valu": [2, 3], "tagfield": [2, 3, 5, 9, 11], "to_tag": [2, 3], "tagmap": [2, 3], "filter": [2, 3, 5, 9, 10, 15], "prettyprint": [2, 3, 9, 12], "json": [2, 3, 5, 9, 10, 11, 12, 14], "result": [2, 3, 5, 9, 10, 11], "has_imag": [2, 3, 5, 10, 12], "image_link": [2, 3, 5, 10, 12], "basiccollect": [2, 3], "get_filtered_playlist": [2, 3], "merge_playlist": [2, 3, 12], "apierror": [2, 4, 10], "requesterror": [2, 4], "localalbum": [2, 5], "localartist": [2, 5], "localcollect": [2, 5], "last_ad": [2, 5], "last_modifi": [2, 5], "log_sync_result": [2, 5], "merge_track": [2, 5], "save_track": [2, 5], "track_path": [2, 5], "localcollectionfilt": [2, 5], "localfold": [2, 5], "set_compilation_tag": [2, 5], "localgenr": [2, 5], "fielderror": [2, 5], "filedoesnotexisterror": [2, 5], "fileerror": [2, 5], "imageloaderror": [2, 5], "invalidfiletyp": [2, 5], "localcollectionerror": [2, 5], "localerror": [2, 5], "localitemerror": [2, 5], "localprocessorerror": [2, 5, 9], "musicbeeerror": [2, 5], "musicbeeiderror": [2, 5], "xmlreadererror": [2, 5], "dynamicprocessor": [2, 9], "processor_method": [2, 9], "itemprocessor": [2, 9], "musicbeeprocessor": [2, 9], "from_xml": [2, 9], "to_xml": [2, 9], "dynamicprocessormethod": [2, 9], "condit": [2, 3, 9], "expect": [2, 9], "itemcomparererror": [2, 9], "itemlimitererror": [2, 9], "itemmatchererror": [2, 9], "itemprocessorerror": [2, 9], "itemsortererror": [2, 9], "processorerror": [2, 9], "processorlookuperror": [2, 9], "timemappererror": [2, 9], "itemlimit": [2, 9], "allow": [2, 9, 10, 11, 12, 14], "limit_max": [2, 9], "limit_sort": [2, 9], "limittyp": [2, 9], "byte": [2, 9], "gigabyt": [2, 9], "hour": [2, 9], "kilobyt": [2, 9], "megabyt": [2, 9], "minut": [2, 9, 15], "second": [2, 3, 5, 9, 10, 12, 15], "terabyt": [2, 9], "week": [2, 9], "cleantagconfig": [2, 9], "preprocess": [2, 9], "split": [2, 9], "itemmatch": [2, 9, 11], "clean_tag": [2, 9], "clean_tags_config": [2, 9], "clean_tags_remove_al": [2, 9], "clean_tags_split_al": [2, 9], "karaoke_tag": [2, 9], "match_album": [2, 9], "match_artist": [2, 9], "match_length": [2, 9], "match_nam": [2, 9], "match_not_karaok": [2, 9], "match_year": [2, 9], "reduce_name_score_factor": [2, 9], "reduce_name_score_on": [2, 9], "year_rang": [2, 9], "itemsort": [2, 9], "group_by_field": [2, 9], "shuffle_bi": [2, 3, 9], "shuffle_mod": [2, 3, 9], "shuffle_weight": [2, 3, 9], "sort_by_field": [2, 9], "sort_field": [2, 9], "shufflebi": [2, 3, 9], "shufflemod": [2, 3, 9], "different_artist": [2, 9], "higher_r": [2, 9], "none": [2, 3, 4, 5, 9, 10, 11, 12, 14, 15], "random": [2, 3, 9], "recent_ad": [2, 9], "timemapp": [2, 9, 15], "remoteapi": [2, 10, 11, 12, 14], "add_to_playlist": [2, 10], "api_url_bas": [2, 10], "authoris": [2, 10, 11, 12], "clear_from_playlist": [2, 10], "collection_item_map": [2, 10], "create_playlist": [2, 10], "delete_playlist": [2, 10], "extend_item": [2, 10], "get_item": [2, 10], "get_playlist_url": [2, 10], "get_self": [2, 10], "get_track": [2, 10], "get_user_item": [2, 10], "handler": [2, 10, 15], "load_user_data": [2, 10], "print_collect": [2, 10], "print_item": [2, 10], "queri": [2, 10, 11], "user_data": [2, 10], "user_item_typ": [2, 10], "remoteitem": [2, 10, 12], "remoteobject": [2, 10, 12], "has_uri": [2, 10, 12], "id": [2, 3, 5, 10, 11, 12, 14], "refresh": [2, 10, 11, 12], "respons": [2, 4, 10, 11, 12, 14], "url": [2, 10, 11, 12, 14], "url_ext": [2, 10, 12], "remoteobjectclass": [2, 10], "remoteidtyp": [2, 10, 11, 14], "remoteobjecttyp": [2, 10, 11, 14], "audiobook": [2, 10], "chapter": [2, 10], "episod": [2, 10], "show": [2, 10], "user": [2, 3, 9, 10, 11, 12, 14, 15], "remoteerror": [2, 10, 11, 12, 14], "remoteidtypeerror": [2, 10, 11, 14], "remoteobjecttypeerror": [2, 10, 11], "remotelibrari": [2, 10, 12], "backup_playlist": [2, 10], "enrich_saved_album": [2, 10, 12], "enrich_saved_artist": [2, 10, 12], "enrich_track": [2, 10, 12], "exclud": [2, 3, 10, 11, 12, 15], "includ": [2, 3, 9, 10, 11, 12, 14, 15], "load_playlist": [2, 10], "load_saved_album": [2, 10], "load_saved_artist": [2, 10], "load_saved_track": [2, 10], "log_album": [2, 10], "log_artist": [2, 10], "log_playlist": [2, 10], "log_sync": [2, 10], "log_track": [2, 10], "restore_playlist": [2, 10], "sync": [2, 10], "remotealbum": [2, 10, 12], "remoteartist": [2, 10, 12], "remotecollect": [2, 10, 12], "remotecollectionload": [2, 10, 12], "remoteitemwranglermixin": [2, 10], "remoteplaylist": [2, 10, 12], "creat": [2, 3, 10, 11], "delet": [2, 10], "writeabl": [2, 10], "remotetrack": [2, 10, 12], "syncresultremoteplaylist": [2, 10], "ad": [2, 5, 9, 10, 11, 12], "differ": [2, 9, 10, 11], "final": [2, 9, 10, 15], "start": [2, 3, 9, 10, 15], "unchang": [2, 10], "spotifyitem": [2, 12], "spotifyobject": [2, 12], "spotifyobjectmixin": [2, 12], "spotifycollectionerror": [2, 12], "spotifyerror": [2, 12], "spotifyitemerror": [2, 12], "spotifylibrari": [2, 12], "spotifyalbum": [2, 12], "spotifyartist": [2, 12], "spotifycollect": [2, 12], "spotifycollectionload": [2, 12], "spotifyitemwranglermixin": [2, 12], "spotifyobjectloadermixin": [2, 12], "spotifyplaylist": [2, 12], "collabor": [2, 10, 12], "public": [2, 10, 12], "spotifytrack": [2, 12], "align_and_trunc": [2, 15], "correct_platform_separ": [2, 15], "flatten_nest": [2, 15], "get_max_width": [2, 15], "get_most_common_valu": [2, 15], "get_user_input": [2, 15], "limit_valu": [2, 15], "merge_map": [2, 15], "safe_format_map": [2, 15], "strip_ignore_word": [2, 15], "to_collect": [2, 15], "unique_list": [2, 15], "currenttimerotatingfilehandl": [2, 15], "rotat": [2, 15], "shouldrollov": [2, 15], "logconsolefilt": [2, 15], "logfilefilt": [2, 15], "syncifylogg": [2, 5, 9, 10, 15], "compact": [2, 15], "file_path": [2, 15], "get_progress_bar": [2, 15], "info_extra": [2, 15], "print": [2, 3, 10, 15], "stat": [2, 5, 10, 15], "stdout_handl": [2, 15], "format_full_func_nam": [2, 15], "print_lin": [2, 15], "print_logo": [2, 15], "print_tim": [2, 15], "class": [2, 3, 5, 9, 10, 11, 12, 14, 15], "set": [2, 3, 5, 9, 10, 11, 12, 15], "dict": [2, 3, 5, 9, 10, 11, 12, 15], "ani": [2, 3, 5, 9, 10, 11, 12, 14, 15], "section": 2, "repres": [2, 3, 5, 9, 10, 11, 12, 14], "block": [2, 10], "from": [2, 3, 5, 9, 10, 11, 12, 14, 15], "file": [2, 3, 5, 9, 15], "other": [2, 3, 10, 11, 12], "self": [2, 3, 9, 10, 12, 15], "overrid": 2, "bool": [2, 3, 5, 9, 10, 11, 12, 14, 15], "fals": [2, 3, 5, 9, 10, 11, 12, 14, 15], "current": [2, 3, 9, 10, 12, 15], "store": [2, 3, 5, 10, 11, 12], "valu": [2, 3, 5, 9, 10, 11, 12, 14, 15], "given": [2, 3, 5, 9, 10, 11, 12, 14, 15], "configur": [2, 9], "when": [2, 3, 4, 5, 9, 10, 11, 12, 14, 15], "i": [2, 3, 5, 9, 10, 11, 12, 14, 15], "true": [2, 3, 5, 9, 10, 11, 12, 15], "forc": 2, "overwrit": [2, 10, 15], "str": [2, 3, 4, 5, 9, 10, 11, 12, 14, 15], "yml": 2, "up": [2, 11], "provid": [2, 3, 5, 9, 10, 12, 15], "framework": 2, "initialis": [2, 9, 10, 12], "variou": [2, 5, 10, 12], "need": [2, 10, 15], "main": [2, 10, 12], "function": [2, 3, 5, 9, 10, 11, 14, 15], "program": [2, 3, 10, 11], "The": [2, 3, 4, 5, 9, 10, 11, 12, 14, 15], "option": [2, 3, 5, 9, 10, 11, 12, 14, 15], "ar": [2, 3, 5, 9, 10, 11, 12, 15], "place": [2, 3, 9, 10, 15], "default": [2, 10, 15], "found": [2, 3, 5, 9, 10, 11, 12], "us": [2, 3, 5, 9, 10, 11, 12, 15], "requir": [2, 10, 11, 12, 14], "fail": 2, "thi": [2, 3, 5, 9, 10, 11, 12, 14, 15], "onli": [2, 3, 5, 9, 10, 11, 15], "appli": [2, 3, 5, 9, 15], "call": [2, 3, 5, 9, 10, 11, 12, 15], "doe": [2, 3, 5, 10, 11, 12, 14], "case": 2, "sub": 2, "have": [2, 3, 5, 9, 10, 11, 12], "an": [2, 3, 4, 5, 9, 10, 11, 12, 14, 15], "paramet": [2, 3, 4, 5, 9, 10, 11, 12, 14, 15], "can": [2, 3, 5, 9, 10, 11, 12], "initi": 2, "present": [2, 3, 9, 15], "take": [2, 9, 15], "prioriti": 2, "By": 2, "alwai": [2, 9, 11, 14, 15], "keep": [2, 9, 15], "If": [2, 3, 5, 9, 10, 11, 12, 15], "rel": [2, 15], "root": 2, "return": [2, 3, 5, 9, 10, 11, 14, 15], "dictionari": [2, 3, 5, 9, 10], "represent": [2, 3, 5, 9, 10, 12], "attribut": [2, 3, 5, 9, 10], "produc": [2, 3, 5, 9, 10, 15], "A": [2, 3, 5, 9, 10, 11, 12, 14, 15], "string": [2, 3, 5, 9, 10, 11, 12, 14, 15], "repr": [2, 3, 5, 9, 10], "respect": 2, "rule": [2, 10], "pull": 2, "within": [2, 3, 5, 9], "parent": 2, "log": [2, 5, 10, 15], "yaml": 2, "dictconfig": 2, "valid": [2, 3, 9, 10, 11, 12, 14], "assign": [2, 9], "": [2, 3, 9, 10, 11, 12, 15], "also": [2, 9, 10, 12], "properti": [2, 3, 5, 9, 10, 11, 12, 15], "package_root": 2, "_data": 2, "output": [2, 3, 10, 11, 14], "save": [2, 5, 10, 12], "diagnost": [2, 10], "data": [2, 9, 10, 12, 15], "messag": [2, 4, 5, 10, 12], "displai": [2, 10], "tupl": [2, 3, 15], "empti": [2, 10], "either": [2, 9], "each": [2, 5, 9, 10, 11, 12, 15], "see": [2, 9, 10, 11, 12, 14, 15], "more": [2, 3, 5, 9, 10], "document": 2, "regard": 2, "oper": [2, 3, 5, 10, 11, 15], "session": 2, "api_cach": 2, "cach": [2, 10, 11, 12], "request": [2, 4, 10, 11], "client": 2, "secret": 2, "access": [2, 10, 11, 12], "where": [2, 9, 15], "possibl": [2, 3, 9], "make": [2, 4, 10, 11, 12], "granular": 2, "ha": [2, 3, 9, 10, 11, 12], "consid": [2, 9, 11], "iter": [2, 3, 5, 9, 10, 11, 12, 15], "t": [2, 3, 9, 10, 15], "list": [2, 3, 5, 9, 10, 11, 12, 14, 15], "avail": [2, 3, 10, 12], "prefix": 2, "stop": [2, 9, 11], "applic": [2, 11], "taken": [2, 5], "down": [2, 3], "identifi": [2, 9, 10], "give": [2, 9, 10, 11, 12, 14, 15], "being": [2, 9, 10], "replac": [2, 5, 15], "destruct": [2, 5, 10, 15], "updat": [2, 5, 10, 12, 15], "locallibrari": 2, "remotedatawrangl": [2, 5, 10, 11, 14], "miss": [2, 15], "musicbe": [2, 5], "configplaylistssync": 2, "synchronis": [2, 3, 10], "out": [2, 3], "everi": [2, 3], "new": [2, 10, 11, 12, 15], "after": [2, 9, 10, 11, 12], "remoteitemcheck": [2, 10, 11, 14], "remoteitemsearch": [2, 10, 11, 14], "spotifyapi": [2, 12], "could": 2, "rais": [2, 3, 4, 5, 9, 10, 11, 12, 14], "caus": [2, 5], "error": [2, 4, 5, 9, 10, 12, 15], "explan": [2, 4, 5, 10, 12], "ignor": [2, 3, 9, 10, 11, 14, 15], "format_map": [2, 15], "attributeerror": 2, "invalid": 2, "find": [2, 9, 10, 11, 12, 15], "gener": [2, 3, 5, 9, 10, 12], "relat": [2, 3, 4, 5, 9, 10, 11, 12], "keyerror": 2, "typeerror": 2, "valueerror": [2, 3], "qualnam": [2, 3, 9, 10], "1": [2, 3, 5, 9, 10, 11, 15], "boundari": [2, 3, 9, 10], "30": [2, 3, 9, 11], "31": [2, 3], "0": [2, 3, 9, 10, 11, 15], "32": [2, 3, 9, 11], "904": [2, 3], "900": [2, 3], "902": [2, 3], "54": [2, 3], "59": [2, 3], "905": [2, 3], "16": [2, 3, 11], "901": [2, 3], "75": [2, 3], "87": [2, 3], "35": [2, 3], "179": [2, 3], "support": [2, 3, 9], "localtrack": [2, 5], "183": [2, 3], "10": [2, 3, 9, 10, 11, 14], "85": [2, 3], "8": [2, 3, 9, 10, 11], "44": [2, 3], "12": [2, 3, 9], "11": [2, 3, 9], "552": 2, "52": [2, 3], "100": [2, 3, 10], "903": [2, 3], "4": [2, 3, 10], "13": [2, 3, 9], "106": [2, 3], "14": [2, 3, 9], "9": [2, 3, 10], "7": [2, 3, 10, 11], "65": [2, 3, 9, 11], "586": 2, "86": [2, 3], "941": [2, 3], "921": [2, 3], "931": [2, 3], "extra": [2, 3, 9, 12], "classmethod": [2, 3, 9, 10, 11, 12, 14], "mapper": [2, 3], "dure": [2, 3, 11], "both": 2, "unit": [2, 9], "one": [2, 3, 5, 10, 12], "which": [2, 9, 10, 11, 15], "refer": [2, 9], "between": [2, 3, 9, 10, 15], "two": [2, 3, 10], "contain": [2, 3, 5, 9, 11, 15], "unavail": [2, 10, 11, 14], "namedobjectprint": [3, 10], "mutablesequ": [3, 9, 10, 11, 14, 15], "variabl": [3, 5, 9, 10, 11, 12], "tag_sep": [3, 5], "separ": [3, 5, 15], "_itemcollection__item": 3, "allow_dupl": [3, 10], "shallow": 3, "int": [3, 5, 9, 10, 11, 12, 14, 15], "number": [3, 5, 9, 10, 11, 12, 15], "occurr": 3, "mani": [3, 9, 10, 11], "_itemcollection__start": 3, "supportsindex": 3, "_itemcollection__stop": 3, "first": [3, 9, 10, 12, 15], "_itemcollection__index": 3, "befor": [3, 9, 10, 11, 12], "order": [3, 5, 9, 10, 12, 15], "sequenc": [3, 9, 11, 15], "float": [3, 5, 9, 10, 11, 15], "shuffl": [3, 9], "otherwis": [3, 9, 11, 15], "do": [3, 5, 9, 10, 11, 12], "noth": [3, 9, 10], "mode": [3, 9], "weight": [3, 9], "automat": [3, 9], "accept": [3, 9, 11, 15], "rang": [3, 9], "instead": 3, "simpl": [3, 11], "apart": 3, "end": 3, "ensur": 3, "implement": [3, 9, 10], "same": [3, 9, 10, 11, 14, 15], "43": 3, "45": 3, "946": 3, "1000": [3, 11], "944": 3, "945": 3, "73": 3, "942": 3, "943": 3, "intenum": 3, "get": [3, 5, 9, 10, 12, 15], "fail_on_mani": 3, "than": [3, 5, 10, 15], "enumnotfounderror": 3, "correspond": 3, "cannot": [3, 5, 10, 11, 12, 14], "only_tag": 3, "those": [3, 15], "human": 3, "friendli": 3, "per": [3, 9, 10, 12], "thei": [3, 11], "id3": 3, "_": [3, 9, 10, 12, 15], "__": [3, 9, 10, 12, 15], "abc": 3, "some": [3, 9, 10, 11, 12, 14, 15], "pretti": [3, 10, 15], "inherit": 3, "gain": 3, "safe": [3, 10, 15], "deriv": 3, "join": [3, 5, 12], "frequenc": [3, 5, 10, 12], "appear": [3, 5, 10, 12], "releas": [3, 5, 12], "wa": [3, 10, 12], "highest": 3, "associ": [3, 5, 10, 11, 12], "form": [3, 5, 9, 10, 12], "link": [3, 5, 10, 12], "total": [3, 5, 10, 12, 15], "durat": [3, 5, 10, 12], "popular": [3, 12], "basic": [3, 15], "filter_tag": 3, "deep": 3, "kwarg": [3, 9, 10, 12, 15], "pars": 3, "note": 3, "datetim": [3, 5, 10, 12, 15], "last": [3, 5], "modifi": [3, 5, 9, 10, 11, 12, 15], "anoth": [3, 5, 9, 10], "metadata": [3, 10], "featur": [3, 9, 12], "tempo": [3, 12], "alphabet": [3, 12], "music": [3, 12], "notat": [3, 12], "format": [3, 10, 11, 12, 14, 15], "posit": [3, 10, 12], "__get_item__": 5, "its": [5, 9, 10, 11, 14], "uniqu": [5, 15], "most": [5, 9, 11, 12, 15], "common": [5, 15], "over": 5, "50": [5, 10, 15], "mark": [5, 11], "determin": [5, 9, 10, 11, 14, 15], "averag": 5, "singl": [5, 10, 12, 15], "timestamp": 5, "plai": 5, "syncresulttrack": 5, "perform": [5, 9], "inner": 5, "dry_run": [5, 10], "argument": 5, "run": [5, 9, 10, 11], "method": [5, 9, 10, 12], "enrich": [5, 10, 12], "drive": 5, "step": 5, "non": 5, "ascend": 5, "filenotfounderror": 5, "filetyp": 5, "recognis": [5, 10, 11, 14], "unrecognis": 5, "logic": [5, 9, 11], "persist": 5, "read": 5, "xml": [5, 9], "py": 9, "__processormethods__": 9, "altern": 9, "__dict__": 9, "callabl": 9, "point": [9, 11], "decor": 9, "you": [9, 10], "mai": [9, 10, 11, 12, 14, 15], "defin": 9, "_processor_method_fmt": 9, "transform": 9, "them": [9, 10], "frozenset": [9, 15], "export": 9, "arg": [9, 10, 12, 15], "dynam": 9, "e": [9, 10, 11, 12, 14], "g": [9, 11, 12, 14], "lessthan": 9, "inrang": 9, "convert": [9, 10, 11, 12, 14, 15], "matcher": 9, "sorter": 9, "sorted_bi": 9, "add": [9, 10], "factor": 9, "max": [9, 15], "comparison": 9, "sai": 9, "29": 9, "worth": 9, "song": [9, 10], "now": [9, 15], "whether": 9, "next": 9, "3": [9, 10], "With": 9, "howev": 9, "33": 9, "becom": 9, "40": [9, 15], "regardless": 9, "20": [9, 10], "23": 9, "21": 9, "22": [9, 10], "24": 9, "15": [9, 15], "_remov": 9, "_split": 9, "_preprocess": 9, "clean": 9, "cleaner": 9, "slice": 9, "anyth": 9, "come": 9, "unprocess": 9, "redund": 9, "word": [9, 15], "karaok": [9, 11], "score": [9, 11], "algorithm": [9, 11], "inform": [9, 10], "info": [9, 10], "reduct": 9, "against": 9, "reduc": [9, 10, 12], "_reduce_name_score_factor": 9, "combin": [9, 15], "_reduce_name_score_on": 9, "namedobject": 9, "input": [9, 10, 11, 14, 15], "better": 9, "phrase": 9, "certain": [9, 11], "part": [9, 15], "_clean_tags_config": 9, "feat": 9, "ft": 9, "v": 9, "ep": 9, "lambda": 9, "back": 9, "instrument": 9, "min_scor": [9, 10, 11], "max_scor": [9, 10, 11], "match_on": 9, "allow_karaok": [9, 10, 11, 12, 14], "abov": [9, 11, 14], "01": 9, "onc": [9, 10, 11, 15], "been": [9, 10, 11], "reach": [9, 11], "skip": [9, 10, 11, 12, 14], "best": 9, "scale": 9, "subsequ": 9, "2": [9, 10], "etc": [9, 10, 11, 12], "exact": 9, "greater": 9, "via": 9, "5": [9, 10, 11], "acoust": 9, "demo": 9, "live": 9, "_custom_sort": 9, "custom": 9, "code": 9, "group": 9, "charact": [9, 15], "convers": 9, "itemcheckresult": [10, 11], "switch": [10, 11, 12, 14], "final_skip": [10, 11, 12, 14], "final_switch": [10, 11, 12, 14], "final_unavail": [10, 11, 12, 14], "interv": [10, 11, 12, 14, 15], "playlist_name_collect": [10, 11, 12, 14], "playlist_name_url": [10, 11, 12, 14], "quit": [10, 11, 12, 14], "remain": [10, 11, 12, 14], "itemsearchresult": [10, 11], "unmatch": [10, 11], "settings_album": [10, 11], "settings_item": [10, 11], "searchset": [10, 11], "match_field": [10, 11], "result_count": [10, 11], "search_fields_1": [10, 11], "search_fields_2": [10, 11], "search_fields_3": [10, 11], "extract_id": [10, 11, 12, 14], "get_id_typ": [10, 11, 12, 14], "get_item_typ": [10, 11], "unavailable_uri_dummi": [10, 11, 12, 14], "validate_id_typ": [10, 11, 12, 14], "validate_item_typ": [10, 11], "handler_kwarg": 10, "endpoint": [10, 11, 12], "requesthandl": 10, "apiauthoris": 10, "param": 10, "pass": [10, 11], "execut": 10, "skip_dup": 10, "post": 10, "One": 10, "batch": [10, 12], "duplic": 10, "force_load": 10, "force_new": 10, "test": 10, "reauthoris": 10, "token": 10, "even": 10, "alreadi": [10, 15], "warn": [10, 12], "your": 10, "unfollow": 10, "items_block": 10, "mutablemap": [10, 11, 12, 14, 15], "across": [10, 12], "child": 10, "These": [10, 11, 14], "must": [10, 11], "OR": [10, 11], "Or": [10, 11, 14], "attempt": [10, 11, 15], "authent": [10, 12], "In": [10, 12], "update_user_data": 10, "_user_data": 10, "wrapper": [10, 15], "retriev": 10, "under": [10, 11, 12, 14], "here": 10, "prompt": [10, 11], "anywai": 10, "therefor": 10, "max_width": [10, 15], "maximum": [10, 11, 15], "width": [10, 15], "longer": [10, 15], "truncat": [10, 15], "skip_check": [10, 12], "extract": [10, 11, 12, 14], "instanti": 10, "complet": [10, 11, 12], "chang": [10, 11, 12], "manual": [10, 12], "extern": [10, 12], "6": 10, "manipul": [10, 12], "entir": [10, 12], "wish": [10, 11], "backup": 10, "purpos": 10, "element": [10, 15], "improv": 10, "coverag": 10, "_remotelibrary__item": 10, "usernam": 10, "restor": 10, "exist": [10, 11], "just": 10, "liter": 10, "reflect": 10, "build": [10, 12], "so": [10, 12], "try": [10, 12], "help": [10, 12], "made": [10, 12], "privat": 10, "edit": 10, "owner": [10, 12], "were": [10, 11], "proce": 11, "had": 11, "temporari": 11, "At": 11, "creation": 11, "correct": [11, 15], "resum": 11, "behest": 11, "how": [11, 15], "deal": 11, "remap": 11, "opt": 11, "1st": 11, "2nd": 11, "3rd": 11, "minimum": 11, "perfect": 11, "disregard": 11, "potenti": 11, "type_in": [11, 14], "type_out": [11, 14], "structur": [11, 14], "mix": [11, 14], "AND": [11, 14], "static": [11, 14, 15], "equal": [11, 14, 15], "spotifyitemcheck": [12, 14], "spotifyitemsearch": [12, 14], "spotifydatawrangl": [12, 14], "spotifyremot": [12, 14], "select": 12, "appears_on": 12, "analysi": 12, "audio": 12, "analys": 12, "technic": 12, "veri": 12, "slow": 12, "extend_artist": 12, "extend_track": 12, "extend_album": 12, "leave_bar": 12, "mixin": 12, "recent": 12, "right_align": 15, "align": 15, "space": 15, "pad": 15, "platform": 15, "nest": 15, "previou": 15, "flatten": 15, "layer": 15, "min_width": 15, "column": 15, "text": 15, "dialog": 15, "floor": 15, "ceil": 15, "recurs": 15, "begin": 15, "special": 15, "cl": 15, "turn": 15, "whilst": 15, "preserv": 15, "encod": 15, "delai": 15, "baserotatinghandl": 15, "full": 15, "open": 15, "timespan": 15, "togeth": 15, "calcul": 15, "timedelta": 15, "multipli": 15, "neg": 15, "defer": 15, "until": 15, "emit": 15, "handl": 15, "unformat": 15, "older": 15, "delta": 15, "oldest": 15, "happen": 15, "__init__": 15, "module_width": 15, "consol": 15, "record": 15, "logrecord": 15, "specifi": 15, "should": 15, "deem": 15, "appropri": 15, "level": 15, "tqdm_asyncio": 15, "tqdm": 15, "progress": 15, "bar": 15, "For": 15, "tqdm_std": 15, "msg": 15, "sever": 15, "51": 15, "line": 15, "debug": 15, "streamhandl": 15, "stdout": 15, "fulli": 15, "qualifi": 15, "letter": 15, "line_char": 15, "centr": 15, "termin": 15, "font": 15, "broadwai": 15, "chunki": 15, "doom": 15, "drpepper": 15, "epic": 15, "hollywood": 15, "isometric1": 15, "isometric2": 15, "isometric3": 15, "isometric4": 15, "larry3d": 15, "shadow": 15, "slant": 15, "speed": 15, "standard": 15, "univ": 15, "whimsi": 15, "colour": 15, "91": 15, "93": 15, "92": 15, "94": 15, "96": 15, "95": 15, "logo": 15}, "objects": {"": [[2, 0, 0, "-", "syncify"]], "syncify": [[3, 0, 0, "-", "abstract"], [4, 0, 0, "-", "api"], [2, 0, 0, "-", "config"], [2, 0, 0, "-", "exception"], [2, 0, 0, "-", "fields"], [5, 0, 0, "-", "local"], [9, 0, 0, "-", "processors"], [10, 0, 0, "-", "remote"], [2, 0, 0, "-", "report"], [12, 0, 0, "-", "spotify"], [15, 0, 0, "-", "utils"]], "syncify.abstract": [[3, 0, 0, "-", "collection"], [3, 0, 0, "-", "enums"], [3, 0, 0, "-", "misc"], [3, 0, 0, "-", "object"]], "syncify.abstract.collection": [[3, 1, 1, "", "ItemCollection"]], "syncify.abstract.collection.ItemCollection": [[3, 2, 1, "", "append"], [3, 2, 1, "", "clear"], [3, 2, 1, "", "copy"], [3, 2, 1, "", "count"], [3, 2, 1, "", "extend"], [3, 2, 1, "", "index"], [3, 2, 1, "", "insert"], [3, 3, 1, "", "items"], [3, 2, 1, "", "pop"], [3, 2, 1, "", "remove"], [3, 2, 1, "", "reverse"], [3, 2, 1, "", "sort"]], "syncify.abstract.enums": [[3, 1, 1, "", "Field"], [3, 1, 1, "", "Fields"], [3, 1, 1, "", "SyncifyEnum"], [3, 1, 1, "", "TagField"], [3, 1, 1, "", "TagFields"], [3, 1, 1, "", "TagMap"]], "syncify.abstract.enums.Fields": [[3, 4, 1, "", "ALBUM"], [3, 4, 1, "", "ALBUM_ARTIST"], [3, 4, 1, "", "ALL"], [3, 4, 1, "", "ARTIST"], [3, 4, 1, "", "BIT_DEPTH"], [3, 4, 1, "", "BIT_RATE"], [3, 4, 1, "", "BPM"], [3, 4, 1, "", "CHANNELS"], [3, 4, 1, "", "COMMENTS"], [3, 4, 1, "", "COMPILATION"], [3, 4, 1, "", "COMPOSER"], [3, 4, 1, "", "CONDUCTOR"], [3, 4, 1, "", "DATE"], [3, 4, 1, "", "DATE_ADDED"], [3, 4, 1, "", "DATE_CREATED"], [3, 4, 1, "", "DATE_MODIFIED"], [3, 4, 1, "", "DAY"], [3, 4, 1, "", "DESCRIPTION"], [3, 4, 1, "", "DISC_NUMBER"], [3, 4, 1, "", "DISC_TOTAL"], [3, 4, 1, "", "EXT"], [3, 4, 1, "", "FILENAME"], [3, 4, 1, "", "FOLDER"], [3, 4, 1, "", "FOLLOWERS"], [3, 4, 1, "", "GENRES"], [3, 4, 1, "", "IMAGES"], [3, 4, 1, "", "KEY"], [3, 4, 1, "", "KIND"], [3, 4, 1, "", "LAST_PLAYED"], [3, 4, 1, "", "LENGTH"], [3, 4, 1, "", "MONTH"], [3, 4, 1, "", "NAME"], [3, 4, 1, "", "OWNER_ID"], [3, 4, 1, "", "OWNER_NAME"], [3, 4, 1, "", "PATH"], [3, 4, 1, "", "PLAY_COUNT"], [3, 4, 1, "", "PUBLISHER"], [3, 4, 1, "", "RATING"], [3, 4, 1, "", "SAMPLE_RATE"], [3, 4, 1, "", "SIZE"], [3, 4, 1, "", "TITLE"], [3, 4, 1, "", "TRACK_NUMBER"], [3, 4, 1, "", "TRACK_TOTAL"], [3, 4, 1, "", "URI"], [3, 4, 1, "", "USER_ID"], [3, 4, 1, "", "USER_NAME"], [3, 4, 1, "", "YEAR"]], "syncify.abstract.enums.SyncifyEnum": [[3, 2, 1, "", "all"], [3, 2, 1, "", "from_name"], [3, 2, 1, "", "from_value"], [3, 2, 1, "", "map"]], "syncify.abstract.enums.TagField": [[3, 2, 1, "", "all"], [3, 2, 1, "", "to_tag"], [3, 2, 1, "", "to_tags"]], "syncify.abstract.enums.TagFields": [[3, 4, 1, "", "ALBUM"], [3, 4, 1, "", "ALBUM_ARTIST"], [3, 4, 1, "", "ALL"], [3, 4, 1, "", "ARTIST"], [3, 4, 1, "", "BIT_DEPTH"], [3, 4, 1, "", "BIT_RATE"], [3, 4, 1, "", "BPM"], [3, 4, 1, "", "CHANNELS"], [3, 4, 1, "", "COMMENTS"], [3, 4, 1, "", "COMPILATION"], [3, 4, 1, "", "COMPOSER"], [3, 4, 1, "", "CONDUCTOR"], [3, 4, 1, "", "DATE"], [3, 4, 1, "", "DATE_ADDED"], [3, 4, 1, "", "DATE_CREATED"], [3, 4, 1, "", "DATE_MODIFIED"], [3, 4, 1, "", "DAY"], [3, 4, 1, "", "DESCRIPTION"], [3, 4, 1, "", "DISC_NUMBER"], [3, 4, 1, "", "DISC_TOTAL"], [3, 4, 1, "", "EXT"], [3, 4, 1, "", "FILENAME"], [3, 4, 1, "", "FOLDER"], [3, 4, 1, "", "FOLLOWERS"], [3, 4, 1, "", "GENRES"], [3, 4, 1, "", "IMAGES"], [3, 4, 1, "", "KEY"], [3, 4, 1, "", "KIND"], [3, 4, 1, "", "LAST_PLAYED"], [3, 4, 1, "", "LENGTH"], [3, 4, 1, "", "MONTH"], [3, 4, 1, "", "NAME"], [3, 4, 1, "", "OWNER_ID"], [3, 4, 1, "", "OWNER_NAME"], [3, 4, 1, "", "PATH"], [3, 4, 1, "", "PLAY_COUNT"], [3, 4, 1, "", "PUBLISHER"], [3, 4, 1, "", "RATING"], [3, 4, 1, "", "SAMPLE_RATE"], [3, 4, 1, "", "SIZE"], [3, 4, 1, "", "TITLE"], [3, 4, 1, "", "TRACK_NUMBER"], [3, 4, 1, "", "TRACK_TOTAL"], [3, 4, 1, "", "URI"], [3, 4, 1, "", "USER_ID"], [3, 4, 1, "", "USER_NAME"], [3, 4, 1, "", "YEAR"]], "syncify.abstract.enums.TagMap": [[3, 4, 1, "", "album"], [3, 4, 1, "", "album_artist"], [3, 4, 1, "", "artist"], [3, 4, 1, "", "bpm"], [3, 4, 1, "", "comments"], [3, 4, 1, "", "compilation"], [3, 4, 1, "", "date"], [3, 4, 1, "", "day"], [3, 4, 1, "", "disc_number"], [3, 4, 1, "", "disc_total"], [3, 4, 1, "", "genres"], [3, 4, 1, "", "images"], [3, 4, 1, "", "key"], [3, 4, 1, "", "month"], [3, 4, 1, "", "title"], [3, 4, 1, "", "track_number"], [3, 4, 1, "", "track_total"], [3, 4, 1, "", "year"]], "syncify.abstract.misc": [[3, 1, 1, "", "Filter"], [3, 1, 1, "", "PrettyPrinter"], [3, 1, 1, "", "Result"]], "syncify.abstract.misc.Filter": [[3, 2, 1, "", "process"], [3, 3, 1, "", "ready"]], "syncify.abstract.misc.PrettyPrinter": [[3, 2, 1, "", "as_dict"], [3, 2, 1, "", "json"]], "syncify.abstract.object": [[3, 1, 1, "", "Album"], [3, 1, 1, "", "Artist"], [3, 1, 1, "", "BasicCollection"], [3, 1, 1, "", "Folder"], [3, 1, 1, "", "Genre"], [3, 1, 1, "", "Library"], [3, 1, 1, "", "Playlist"], [3, 1, 1, "", "Track"]], "syncify.abstract.object.Album": [[3, 3, 1, "", "album"], [3, 3, 1, "", "album_artist"], [3, 3, 1, "", "artist"], [3, 3, 1, "", "artists"], [3, 3, 1, "", "compilation"], [3, 3, 1, "", "date"], [3, 3, 1, "", "day"], [3, 3, 1, "", "disc_total"], [3, 3, 1, "", "genres"], [3, 3, 1, "", "has_image"], [3, 3, 1, "", "image_links"], [3, 3, 1, "", "items"], [3, 3, 1, "", "length"], [3, 3, 1, "", "month"], [3, 3, 1, "", "name"], [3, 3, 1, "", "rating"], [3, 3, 1, "", "track_total"], [3, 3, 1, "", "tracks"], [3, 3, 1, "", "year"]], "syncify.abstract.object.Artist": [[3, 3, 1, "", "albums"], [3, 3, 1, "", "artist"], [3, 3, 1, "", "artists"], [3, 3, 1, "", "genres"], [3, 3, 1, "", "items"], [3, 3, 1, "", "length"], [3, 3, 1, "", "name"], [3, 3, 1, "", "rating"], [3, 3, 1, "", "track_total"], [3, 3, 1, "", "tracks"]], "syncify.abstract.object.BasicCollection": [[3, 2, 1, "", "as_dict"], [3, 3, 1, "", "items"], [3, 3, 1, "", "name"]], "syncify.abstract.object.Folder": [[3, 3, 1, "", "albums"], [3, 3, 1, "", "artists"], [3, 3, 1, "", "compilation"], [3, 3, 1, "", "folder"], [3, 3, 1, "", "genres"], [3, 3, 1, "", "items"], [3, 3, 1, "", "length"], [3, 3, 1, "", "name"], [3, 3, 1, "", "track_total"], [3, 3, 1, "", "tracks"]], "syncify.abstract.object.Genre": [[3, 3, 1, "", "albums"], [3, 3, 1, "", "artists"], [3, 3, 1, "", "genre"], [3, 3, 1, "", "genres"], [3, 3, 1, "", "items"], [3, 3, 1, "", "name"], [3, 3, 1, "", "tracks"]], "syncify.abstract.object.Library": [[3, 2, 1, "", "get_filtered_playlists"], [3, 3, 1, "", "items"], [3, 2, 1, "", "merge_playlists"], [3, 3, 1, "", "name"], [3, 3, 1, "", "playlists"], [3, 3, 1, "", "track_total"], [3, 3, 1, "", "tracks"]], "syncify.abstract.object.Playlist": [[3, 3, 1, "", "date_created"], [3, 3, 1, "", "date_modified"], [3, 3, 1, "", "description"], [3, 3, 1, "", "has_image"], [3, 3, 1, "", "image_links"], [3, 3, 1, "", "items"], [3, 3, 1, "", "length"], [3, 2, 1, "", "merge"], [3, 3, 1, "", "name"], [3, 3, 1, "", "track_total"], [3, 3, 1, "", "tracks"]], "syncify.abstract.object.Track": [[3, 3, 1, "", "album"], [3, 3, 1, "", "album_artist"], [3, 3, 1, "", "artist"], [3, 3, 1, "", "artists"], [3, 3, 1, "", "bpm"], [3, 3, 1, "", "comments"], [3, 3, 1, "", "compilation"], [3, 3, 1, "", "date"], [3, 3, 1, "", "day"], [3, 3, 1, "", "disc_number"], [3, 3, 1, "", "disc_total"], [3, 3, 1, "", "genres"], [3, 3, 1, "", "has_image"], [3, 3, 1, "", "image_links"], [3, 3, 1, "", "key"], [3, 3, 1, "", "length"], [3, 3, 1, "", "month"], [3, 3, 1, "", "name"], [3, 3, 1, "", "rating"], [3, 3, 1, "", "title"], [3, 3, 1, "", "track_number"], [3, 3, 1, "", "track_total"], [3, 3, 1, "", "year"]], "syncify.api": [[4, 0, 0, "-", "exception"]], "syncify.api.exception": [[4, 5, 1, "", "APIError"], [4, 5, 1, "", "RequestError"]], "syncify.config": [[2, 1, 1, "", "BaseConfig"], [2, 1, 1, "", "Config"], [2, 1, 1, "", "ConfigAPI"], [2, 1, 1, "", "ConfigFilter"], [2, 1, 1, "", "ConfigLibrary"], [2, 1, 1, "", "ConfigLibraryDifferences"], [2, 1, 1, "", "ConfigLocal"], [2, 1, 1, "", "ConfigMissingTags"], [2, 1, 1, "", "ConfigMusicBee"], [2, 1, 1, "", "ConfigPlaylists"], [2, 1, 1, "", "ConfigRemote"], [2, 1, 1, "", "ConfigReportBase"], [2, 1, 1, "", "ConfigReports"], [2, 1, 1, "", "ConfigSpotify"], [2, 1, 1, "", "RemoteClasses"]], "syncify.config.BaseConfig": [[2, 2, 1, "", "merge"]], "syncify.config.Config": [[2, 2, 1, "", "as_dict"], [2, 2, 1, "", "load"], [2, 2, 1, "", "load_log_config"], [2, 3, 1, "", "output_folder"], [2, 3, 1, "", "pause"], [2, 3, 1, "", "reload"]], "syncify.config.ConfigAPI": [[2, 3, 1, "", "api"], [2, 2, 1, "", "as_dict"], [2, 3, 1, "", "cache_path"], [2, 3, 1, "", "token_path"], [2, 3, 1, "", "use_cache"]], "syncify.config.ConfigFilter": [[2, 1, 1, "", "ConfigMatch"], [2, 2, 1, "", "as_dict"], [2, 2, 1, "", "process"], [2, 3, 1, "", "ready"]], "syncify.config.ConfigFilter.ConfigMatch": [[2, 2, 1, "", "as_dict"], [2, 3, 1, "", "match_all"], [2, 2, 1, "", "merge"], [2, 2, 1, "", "process"], [2, 3, 1, "", "ready"], [2, 3, 1, "", "values"]], "syncify.config.ConfigLibrary": [[2, 2, 1, "", "as_dict"], [2, 3, 1, "", "kind"], [2, 3, 1, "", "library"], [2, 3, 1, "", "source"]], "syncify.config.ConfigLocal": [[2, 1, 1, "", "ConfigUpdateTags"], [2, 2, 1, "", "as_dict"], [2, 3, 1, "", "library"], [2, 3, 1, "", "library_folder"], [2, 3, 1, "", "other_folders"], [2, 3, 1, "", "playlist_folder"], [2, 3, 1, "", "remote_wrangler"], [2, 3, 1, "", "source"]], "syncify.config.ConfigLocal.ConfigUpdateTags": [[2, 2, 1, "", "as_dict"], [2, 3, 1, "", "replace"], [2, 3, 1, "", "tags"]], "syncify.config.ConfigMissingTags": [[2, 2, 1, "", "as_dict"], [2, 3, 1, "", "match_all"], [2, 3, 1, "", "tags"]], "syncify.config.ConfigMusicBee": [[2, 2, 1, "", "as_dict"], [2, 3, 1, "", "library"], [2, 3, 1, "", "musicbee_folder"], [2, 3, 1, "", "source"]], "syncify.config.ConfigRemote": [[2, 1, 1, "", "ConfigPlaylists"], [2, 2, 1, "", "as_dict"], [2, 3, 1, "", "checker"], [2, 3, 1, "", "library"], [2, 3, 1, "", "playlist"], [2, 3, 1, "", "searcher"], [2, 3, 1, "", "source"], [2, 3, 1, "", "wrangler"]], "syncify.config.ConfigRemote.ConfigPlaylists": [[2, 1, 1, "", "ConfigPlaylistsSync"], [2, 2, 1, "", "as_dict"]], "syncify.config.ConfigRemote.ConfigPlaylists.ConfigPlaylistsSync": [[2, 2, 1, "", "as_dict"], [2, 3, 1, "", "filter"], [2, 3, 1, "", "kind"], [2, 2, 1, "", "merge"], [2, 3, 1, "", "reload"]], "syncify.config.ConfigReportBase": [[2, 2, 1, "", "as_dict"]], "syncify.config.ConfigReports": [[2, 2, 1, "", "as_dict"], [2, 3, 1, "", "enabled"]], "syncify.config.ConfigSpotify": [[2, 3, 1, "", "api"], [2, 2, 1, "", "as_dict"], [2, 3, 1, "", "client_id"], [2, 3, 1, "", "client_secret"], [2, 3, 1, "", "scopes"]], "syncify.config.RemoteClasses": [[2, 4, 1, "", "api"], [2, 4, 1, "", "checker"], [2, 4, 1, "", "library"], [2, 4, 1, "", "object"], [2, 4, 1, "", "playlist"], [2, 4, 1, "", "searcher"], [2, 4, 1, "", "source"], [2, 4, 1, "", "wrangler"]], "syncify.exception": [[2, 5, 1, "", "ConfigError"], [2, 1, 1, "", "SafeDict"], [2, 5, 1, "", "SyncifyAttributeError"], [2, 5, 1, "", "SyncifyEnumError"], [2, 5, 1, "", "SyncifyError"], [2, 5, 1, "", "SyncifyKeyError"], [2, 5, 1, "", "SyncifyTypeError"], [2, 5, 1, "", "SyncifyValueError"]], "syncify.fields": [[2, 1, 1, "", "AlbumField"], [2, 1, 1, "", "ArtistField"], [2, 1, 1, "", "FolderField"], [2, 1, 1, "", "LocalTrackField"], [2, 1, 1, "", "PlaylistField"], [2, 1, 1, "", "TrackField"], [2, 1, 1, "", "TrackFieldMixin"]], "syncify.fields.AlbumField": [[2, 4, 1, "", "ALBUM"], [2, 4, 1, "", "ALBUM_ARTIST"], [2, 4, 1, "", "ALL"], [2, 4, 1, "", "ARTIST"], [2, 4, 1, "", "COMPILATION"], [2, 4, 1, "", "DATE"], [2, 4, 1, "", "DAY"], [2, 4, 1, "", "DISC_TOTAL"], [2, 4, 1, "", "GENRES"], [2, 4, 1, "", "IMAGES"], [2, 4, 1, "", "LENGTH"], [2, 4, 1, "", "MONTH"], [2, 4, 1, "", "RATING"], [2, 4, 1, "", "TRACK_TOTAL"], [2, 4, 1, "", "YEAR"]], "syncify.fields.ArtistField": [[2, 4, 1, "", "ALL"], [2, 4, 1, "", "ARTIST"], [2, 4, 1, "", "GENRES"], [2, 4, 1, "", "IMAGES"], [2, 4, 1, "", "LENGTH"], [2, 4, 1, "", "RATING"], [2, 4, 1, "", "TRACK_TOTAL"]], "syncify.fields.FolderField": [[2, 4, 1, "", "ALL"], [2, 4, 1, "", "COMPILATION"], [2, 4, 1, "", "FOLDER"], [2, 4, 1, "", "GENRES"], [2, 4, 1, "", "IMAGES"], [2, 4, 1, "", "LENGTH"], [2, 4, 1, "", "TRACK_TOTAL"]], "syncify.fields.LocalTrackField": [[2, 4, 1, "", "ALBUM"], [2, 4, 1, "", "ALBUM_ARTIST"], [2, 4, 1, "", "ALL"], [2, 4, 1, "", "ARTIST"], [2, 4, 1, "", "BIT_DEPTH"], [2, 4, 1, "", "BIT_RATE"], [2, 4, 1, "", "BPM"], [2, 4, 1, "", "CHANNELS"], [2, 4, 1, "", "COMMENTS"], [2, 4, 1, "", "COMPILATION"], [2, 4, 1, "", "DATE"], [2, 4, 1, "", "DATE_ADDED"], [2, 4, 1, "", "DATE_MODIFIED"], [2, 4, 1, "", "DAY"], [2, 4, 1, "", "DISC"], [2, 4, 1, "", "DISC_NUMBER"], [2, 4, 1, "", "DISC_TOTAL"], [2, 4, 1, "", "EXT"], [2, 4, 1, "", "FILENAME"], [2, 4, 1, "", "FOLDER"], [2, 4, 1, "", "GENRES"], [2, 4, 1, "", "IMAGES"], [2, 4, 1, "", "KEY"], [2, 4, 1, "", "KIND"], [2, 4, 1, "", "LAST_PLAYED"], [2, 4, 1, "", "LENGTH"], [2, 4, 1, "", "MONTH"], [2, 4, 1, "", "PATH"], [2, 4, 1, "", "PLAY_COUNT"], [2, 4, 1, "", "RATING"], [2, 4, 1, "", "SAMPLE_RATE"], [2, 4, 1, "", "SIZE"], [2, 4, 1, "", "TITLE"], [2, 4, 1, "", "TRACK"], [2, 4, 1, "", "TRACK_NUMBER"], [2, 4, 1, "", "TRACK_TOTAL"], [2, 4, 1, "", "URI"], [2, 4, 1, "", "YEAR"]], "syncify.fields.PlaylistField": [[2, 4, 1, "", "ALL"], [2, 4, 1, "", "DATE_CREATED"], [2, 4, 1, "", "DATE_MODIFIED"], [2, 4, 1, "", "DESCRIPTION"], [2, 4, 1, "", "IMAGES"], [2, 4, 1, "", "LENGTH"], [2, 4, 1, "", "TRACK_TOTAL"]], "syncify.fields.TrackField": [[2, 4, 1, "", "ALBUM"], [2, 4, 1, "", "ALBUM_ARTIST"], [2, 4, 1, "", "ALL"], [2, 4, 1, "", "ARTIST"], [2, 4, 1, "", "BPM"], [2, 4, 1, "", "COMMENTS"], [2, 4, 1, "", "COMPILATION"], [2, 4, 1, "", "DISC"], [2, 4, 1, "", "DISC_NUMBER"], [2, 4, 1, "", "DISC_TOTAL"], [2, 4, 1, "", "GENRES"], [2, 4, 1, "", "IMAGES"], [2, 4, 1, "", "KEY"], [2, 4, 1, "", "LENGTH"], [2, 4, 1, "", "RATING"], [2, 4, 1, "", "TITLE"], [2, 4, 1, "", "TRACK"], [2, 4, 1, "", "TRACK_NUMBER"], [2, 4, 1, "", "TRACK_TOTAL"], [2, 4, 1, "", "URI"], [2, 4, 1, "", "YEAR"]], "syncify.fields.TrackFieldMixin": [[2, 2, 1, "", "map"]], "syncify.local": [[5, 0, 0, "-", "collection"], [5, 0, 0, "-", "exception"], [6, 0, 0, "-", "library"], [7, 0, 0, "-", "playlist"], [8, 0, 0, "-", "track"]], "syncify.local.collection": [[5, 1, 1, "", "LocalAlbum"], [5, 1, 1, "", "LocalArtist"], [5, 1, 1, "", "LocalCollection"], [5, 1, 1, "", "LocalCollectionFiltered"], [5, 1, 1, "", "LocalFolder"], [5, 1, 1, "", "LocalGenres"]], "syncify.local.collection.LocalAlbum": [[5, 3, 1, "", "album_artist"], [5, 2, 1, "", "as_dict"], [5, 3, 1, "", "compilation"], [5, 3, 1, "", "date"], [5, 3, 1, "", "day"], [5, 3, 1, "", "has_image"], [5, 3, 1, "", "image_links"], [5, 4, 1, "", "logger"], [5, 3, 1, "", "month"], [5, 3, 1, "", "rating"], [5, 4, 1, "", "remote_wrangler"], [5, 3, 1, "", "year"]], "syncify.local.collection.LocalArtist": [[5, 3, 1, "", "albums"], [5, 2, 1, "", "as_dict"], [5, 4, 1, "", "logger"], [5, 3, 1, "", "rating"], [5, 4, 1, "", "remote_wrangler"]], "syncify.local.collection.LocalCollection": [[5, 3, 1, "", "artists"], [5, 2, 1, "", "as_dict"], [5, 3, 1, "", "genres"], [5, 3, 1, "", "items"], [5, 3, 1, "", "last_added"], [5, 3, 1, "", "last_modified"], [5, 3, 1, "", "last_played"], [5, 3, 1, "", "length"], [5, 2, 1, "", "log_sync_result"], [5, 4, 1, "", "logger"], [5, 2, 1, "", "merge_tracks"], [5, 3, 1, "", "play_count"], [5, 4, 1, "", "remote_wrangler"], [5, 2, 1, "", "save_tracks"], [5, 3, 1, "", "track_paths"], [5, 3, 1, "", "track_total"], [5, 3, 1, "", "tracks"]], "syncify.local.collection.LocalCollectionFiltered": [[5, 4, 1, "", "logger"], [5, 3, 1, "", "name"], [5, 4, 1, "", "remote_wrangler"], [5, 3, 1, "", "tracks"]], "syncify.local.collection.LocalFolder": [[5, 3, 1, "", "albums"], [5, 2, 1, "", "as_dict"], [5, 3, 1, "", "compilation"], [5, 4, 1, "", "logger"], [5, 4, 1, "", "remote_wrangler"], [5, 2, 1, "", "set_compilation_tags"]], "syncify.local.collection.LocalGenres": [[5, 3, 1, "", "albums"], [5, 2, 1, "", "as_dict"], [5, 4, 1, "", "logger"], [5, 4, 1, "", "remote_wrangler"]], "syncify.local.exception": [[5, 5, 1, "", "FieldError"], [5, 5, 1, "", "FileDoesNotExistError"], [5, 5, 1, "", "FileError"], [5, 5, 1, "", "ImageLoadError"], [5, 5, 1, "", "InvalidFileType"], [5, 5, 1, "", "LocalCollectionError"], [5, 5, 1, "", "LocalError"], [5, 5, 1, "", "LocalItemError"], [5, 5, 1, "", "LocalProcessorError"], [5, 5, 1, "", "MusicBeeError"], [5, 5, 1, "", "MusicBeeIDError"], [5, 5, 1, "", "XMLReaderError"]], "syncify.processors": [[9, 0, 0, "-", "base"], [9, 0, 0, "-", "compare"], [9, 0, 0, "-", "exception"], [9, 0, 0, "-", "limit"], [9, 0, 0, "-", "match"], [9, 0, 0, "-", "sort"], [9, 0, 0, "-", "time"]], "syncify.processors.base": [[9, 1, 1, "", "DynamicProcessor"], [9, 1, 1, "", "ItemProcessor"], [9, 1, 1, "", "MusicBeeProcessor"], [9, 1, 1, "", "Processor"], [9, 1, 1, "", "dynamicprocessormethod"]], "syncify.processors.base.DynamicProcessor": [[9, 3, 1, "", "processor_methods"]], "syncify.processors.base.MusicBeeProcessor": [[9, 2, 1, "", "from_xml"], [9, 2, 1, "", "to_xml"]], "syncify.processors.compare": [[9, 1, 1, "", "Comparer"]], "syncify.processors.compare.Comparer": [[9, 2, 1, "", "as_dict"], [9, 2, 1, "", "compare"], [9, 3, 1, "", "condition"], [9, 3, 1, "", "expected"], [9, 4, 1, "", "field"], [9, 2, 1, "", "from_xml"], [9, 2, 1, "", "to_xml"]], "syncify.processors.exception": [[9, 5, 1, "", "ItemComparerError"], [9, 5, 1, "", "ItemLimiterError"], [9, 5, 1, "", "ItemMatcherError"], [9, 5, 1, "", "ItemProcessorError"], [9, 5, 1, "", "ItemSorterError"], [9, 5, 1, "", "ProcessorError"], [9, 5, 1, "", "ProcessorLookupError"], [9, 5, 1, "", "TimeMapperError"]], "syncify.processors.limit": [[9, 1, 1, "", "ItemLimiter"], [9, 1, 1, "", "LimitType"]], "syncify.processors.limit.ItemLimiter": [[9, 4, 1, "", "allowance"], [9, 2, 1, "", "as_dict"], [9, 2, 1, "", "from_xml"], [9, 4, 1, "", "kind"], [9, 2, 1, "", "limit"], [9, 4, 1, "", "limit_max"], [9, 3, 1, "", "limit_sort"], [9, 2, 1, "", "to_xml"]], "syncify.processors.limit.LimitType": [[9, 4, 1, "", "ALBUMS"], [9, 4, 1, "", "BYTES"], [9, 4, 1, "", "DAYS"], [9, 4, 1, "", "GIGABYTES"], [9, 4, 1, "", "HOURS"], [9, 4, 1, "", "ITEMS"], [9, 4, 1, "", "KILOBYTES"], [9, 4, 1, "", "MEGABYTES"], [9, 4, 1, "", "MINUTES"], [9, 4, 1, "", "SECONDS"], [9, 4, 1, "", "TERABYTES"], [9, 4, 1, "", "WEEKS"]], "syncify.processors.match": [[9, 1, 1, "", "CleanTagConfig"], [9, 1, 1, "", "ItemMatcher"]], "syncify.processors.match.CleanTagConfig": [[9, 2, 1, "", "as_dict"], [9, 2, 1, "", "preprocess"], [9, 3, 1, "", "remove"], [9, 3, 1, "", "split"], [9, 4, 1, "", "tag"]], "syncify.processors.match.ItemMatcher": [[9, 2, 1, "", "as_dict"], [9, 2, 1, "", "clean_tags"], [9, 4, 1, "", "clean_tags_config"], [9, 4, 1, "", "clean_tags_remove_all"], [9, 4, 1, "", "clean_tags_split_all"], [9, 4, 1, "", "karaoke_tags"], [9, 4, 1, "", "logger"], [9, 2, 1, "", "match"], [9, 2, 1, "", "match_album"], [9, 2, 1, "", "match_artist"], [9, 2, 1, "", "match_length"], [9, 2, 1, "", "match_name"], [9, 2, 1, "", "match_not_karaoke"], [9, 2, 1, "", "match_year"], [9, 4, 1, "", "reduce_name_score_factor"], [9, 4, 1, "", "reduce_name_score_on"], [9, 4, 1, "", "year_range"]], "syncify.processors.sort": [[9, 1, 1, "", "ItemSorter"], [9, 1, 1, "", "ShuffleBy"], [9, 1, 1, "", "ShuffleMode"]], "syncify.processors.sort.ItemSorter": [[9, 2, 1, "", "as_dict"], [9, 2, 1, "", "from_xml"], [9, 2, 1, "", "group_by_field"], [9, 4, 1, "", "shuffle_by"], [9, 4, 1, "", "shuffle_mode"], [9, 4, 1, "", "shuffle_weight"], [9, 2, 1, "", "sort"], [9, 2, 1, "", "sort_by_field"], [9, 4, 1, "", "sort_fields"], [9, 2, 1, "", "to_xml"]], "syncify.processors.sort.ShuffleBy": [[9, 4, 1, "", "ALBUM"], [9, 4, 1, "", "ARTIST"], [9, 4, 1, "", "TRACK"]], "syncify.processors.sort.ShuffleMode": [[9, 4, 1, "", "DIFFERENT_ARTIST"], [9, 4, 1, "", "HIGHER_RATING"], [9, 4, 1, "", "NONE"], [9, 4, 1, "", "RANDOM"], [9, 4, 1, "", "RECENT_ADDED"]], "syncify.processors.time": [[9, 1, 1, "", "TimeMapper"]], "syncify.processors.time.TimeMapper": [[9, 2, 1, "", "as_dict"], [9, 2, 1, "", "days"], [9, 2, 1, "", "hours"], [9, 2, 1, "", "map"], [9, 2, 1, "", "minutes"], [9, 2, 1, "", "months"], [9, 2, 1, "", "seconds"], [9, 2, 1, "", "weeks"]], "syncify.remote": [[10, 0, 0, "-", "api"], [10, 0, 0, "-", "base"], [10, 0, 0, "-", "config"], [10, 0, 0, "-", "enums"], [10, 0, 0, "-", "exception"], [10, 0, 0, "-", "library"], [10, 0, 0, "-", "object"], [11, 0, 0, "-", "processors"], [10, 0, 0, "-", "types"]], "syncify.remote.api": [[10, 1, 1, "", "RemoteAPI"]], "syncify.remote.api.RemoteAPI": [[10, 2, 1, "", "add_to_playlist"], [10, 3, 1, "", "api_url_base"], [10, 2, 1, "", "authorise"], [10, 2, 1, "", "clear_from_playlist"], [10, 4, 1, "", "collection_item_map"], [10, 2, 1, "", "create_playlist"], [10, 2, 1, "", "delete_playlist"], [10, 2, 1, "", "extend_items"], [10, 2, 1, "", "get_items"], [10, 2, 1, "", "get_playlist_url"], [10, 2, 1, "", "get_self"], [10, 2, 1, "", "get_tracks"], [10, 2, 1, "", "get_user_items"], [10, 4, 1, "", "handler"], [10, 2, 1, "", "load_user_data"], [10, 4, 1, "", "logger"], [10, 2, 1, "", "print_collection"], [10, 2, 1, "", "print_item"], [10, 2, 1, "", "query"], [10, 4, 1, "", "user_data"], [10, 3, 1, "", "user_id"], [10, 4, 1, "", "user_item_types"], [10, 3, 1, "", "user_name"]], "syncify.remote.base": [[10, 1, 1, "", "RemoteItem"], [10, 1, 1, "", "RemoteObject"]], "syncify.remote.base.RemoteItem": [[10, 4, 1, "", "api"]], "syncify.remote.base.RemoteObject": [[10, 4, 1, "", "api"], [10, 2, 1, "", "as_dict"], [10, 3, 1, "", "has_uri"], [10, 3, 1, "", "id"], [10, 2, 1, "", "load"], [10, 2, 1, "", "refresh"], [10, 2, 1, "", "reload"], [10, 3, 1, "", "response"], [10, 3, 1, "", "uri"], [10, 3, 1, "", "url"], [10, 3, 1, "", "url_ext"]], "syncify.remote.config": [[10, 1, 1, "", "RemoteObjectClasses"]], "syncify.remote.config.RemoteObjectClasses": [[10, 4, 1, "", "album"], [10, 4, 1, "", "artist"], [10, 4, 1, "", "playlist"], [10, 4, 1, "", "track"]], "syncify.remote.enums": [[10, 1, 1, "", "RemoteIDType"], [10, 1, 1, "", "RemoteObjectType"]], "syncify.remote.enums.RemoteIDType": [[10, 4, 1, "", "ALL"], [10, 4, 1, "", "ID"], [10, 4, 1, "", "URI"], [10, 4, 1, "", "URL"], [10, 4, 1, "", "URL_EXT"]], "syncify.remote.enums.RemoteObjectType": [[10, 4, 1, "", "ALBUM"], [10, 4, 1, "", "ALL"], [10, 4, 1, "", "ARTIST"], [10, 4, 1, "", "AUDIOBOOK"], [10, 4, 1, "", "CHAPTER"], [10, 4, 1, "", "EPISODE"], [10, 4, 1, "", "PLAYLIST"], [10, 4, 1, "", "SHOW"], [10, 4, 1, "", "TRACK"], [10, 4, 1, "", "USER"]], "syncify.remote.exception": [[10, 5, 1, "", "RemoteError"], [10, 5, 1, "", "RemoteIDTypeError"], [10, 5, 1, "", "RemoteObjectTypeError"]], "syncify.remote.library": [[10, 1, 1, "", "RemoteLibrary"]], "syncify.remote.library.RemoteLibrary": [[10, 3, 1, "", "albums"], [10, 3, 1, "", "api"], [10, 3, 1, "", "artists"], [10, 2, 1, "", "as_dict"], [10, 2, 1, "", "backup_playlists"], [10, 2, 1, "", "enrich_saved_albums"], [10, 2, 1, "", "enrich_saved_artists"], [10, 2, 1, "", "enrich_tracks"], [10, 4, 1, "", "exclude"], [10, 2, 1, "", "extend"], [10, 3, 1, "", "id"], [10, 4, 1, "", "include"], [10, 2, 1, "", "json"], [10, 2, 1, "", "load"], [10, 2, 1, "", "load_playlists"], [10, 2, 1, "", "load_saved_albums"], [10, 2, 1, "", "load_saved_artists"], [10, 2, 1, "", "load_saved_tracks"], [10, 2, 1, "", "log_albums"], [10, 2, 1, "", "log_artists"], [10, 2, 1, "", "log_playlists"], [10, 2, 1, "", "log_sync"], [10, 2, 1, "", "log_tracks"], [10, 3, 1, "", "name"], [10, 3, 1, "", "playlists"], [10, 2, 1, "", "restore_playlists"], [10, 2, 1, "", "sync"], [10, 3, 1, "", "tracks"], [10, 4, 1, "", "use_cache"]], "syncify.remote.object": [[10, 1, 1, "", "RemoteAlbum"], [10, 1, 1, "", "RemoteArtist"], [10, 1, 1, "", "RemoteCollection"], [10, 1, 1, "", "RemoteCollectionLoader"], [10, 1, 1, "", "RemoteItemWranglerMixin"], [10, 1, 1, "", "RemotePlaylist"], [10, 1, 1, "", "RemoteTrack"], [10, 1, 1, "", "SyncResultRemotePlaylist"]], "syncify.remote.object.RemoteAlbum": [[10, 4, 1, "", "api"], [10, 3, 1, "", "artists"]], "syncify.remote.object.RemoteArtist": [[10, 3, 1, "", "albums"], [10, 4, 1, "", "api"], [10, 3, 1, "", "artists"], [10, 3, 1, "", "has_image"], [10, 3, 1, "", "image_links"], [10, 3, 1, "", "length"], [10, 3, 1, "", "track_total"], [10, 3, 1, "", "tracks"]], "syncify.remote.object.RemoteCollectionLoader": [[10, 4, 1, "", "api"], [10, 2, 1, "", "load"]], "syncify.remote.object.RemoteItemWranglerMixin": [[10, 4, 1, "", "api"]], "syncify.remote.object.RemotePlaylist": [[10, 4, 1, "", "api"], [10, 2, 1, "", "create"], [10, 3, 1, "", "date_added"], [10, 2, 1, "", "delete"], [10, 3, 1, "", "followers"], [10, 2, 1, "", "merge"], [10, 3, 1, "", "owner_id"], [10, 3, 1, "", "owner_name"], [10, 2, 1, "", "sync"], [10, 3, 1, "", "writeable"]], "syncify.remote.object.RemoteTrack": [[10, 4, 1, "", "api"]], "syncify.remote.object.SyncResultRemotePlaylist": [[10, 4, 1, "", "added"], [10, 4, 1, "", "difference"], [10, 4, 1, "", "final"], [10, 4, 1, "", "removed"], [10, 4, 1, "", "start"], [10, 4, 1, "", "unchanged"]], "syncify.remote.processors": [[11, 0, 0, "-", "check"], [11, 0, 0, "-", "search"], [11, 0, 0, "-", "wrangle"]], "syncify.remote.processors.check": [[11, 1, 1, "", "ItemCheckResult"], [11, 1, 1, "", "RemoteItemChecker"]], "syncify.remote.processors.check.ItemCheckResult": [[11, 4, 1, "", "skipped"], [11, 4, 1, "", "switched"], [11, 4, 1, "", "unavailable"]], "syncify.remote.processors.check.RemoteItemChecker": [[11, 4, 1, "", "allow_karaoke"], [11, 4, 1, "", "api"], [11, 2, 1, "", "check"], [11, 4, 1, "", "final_skipped"], [11, 4, 1, "", "final_switched"], [11, 4, 1, "", "final_unavailable"], [11, 4, 1, "", "interval"], [11, 4, 1, "", "playlist_name_collection"], [11, 4, 1, "", "playlist_name_urls"], [11, 4, 1, "", "quit"], [11, 4, 1, "", "remaining"], [11, 4, 1, "", "skip"], [11, 4, 1, "", "switched"]], "syncify.remote.processors.search": [[11, 1, 1, "", "ItemSearchResult"], [11, 1, 1, "", "RemoteItemSearcher"], [11, 1, 1, "", "SearchSettings"]], "syncify.remote.processors.search.ItemSearchResult": [[11, 4, 1, "", "matched"], [11, 4, 1, "", "skipped"], [11, 4, 1, "", "unmatched"]], "syncify.remote.processors.search.RemoteItemSearcher": [[11, 4, 1, "", "api"], [11, 2, 1, "", "search"], [11, 4, 1, "", "settings_albums"], [11, 4, 1, "", "settings_items"], [11, 4, 1, "", "use_cache"]], "syncify.remote.processors.search.SearchSettings": [[11, 4, 1, "", "allow_karaoke"], [11, 4, 1, "", "match_fields"], [11, 4, 1, "", "max_score"], [11, 4, 1, "", "min_score"], [11, 4, 1, "", "result_count"], [11, 4, 1, "", "search_fields_1"], [11, 4, 1, "", "search_fields_2"], [11, 4, 1, "", "search_fields_3"]], "syncify.remote.processors.wrangle": [[11, 1, 1, "", "RemoteDataWrangler"]], "syncify.remote.processors.wrangle.RemoteDataWrangler": [[11, 2, 1, "", "convert"], [11, 2, 1, "", "extract_ids"], [11, 2, 1, "", "get_id_type"], [11, 2, 1, "", "get_item_type"], [11, 3, 1, "", "unavailable_uri_dummy"], [11, 2, 1, "", "validate_id_type"], [11, 2, 1, "", "validate_item_type"]], "syncify.report": [[2, 6, 1, "", "report_missing_tags"], [2, 6, 1, "", "report_playlist_differences"]], "syncify.spotify": [[13, 0, 0, "-", "api"], [12, 0, 0, "-", "base"], [12, 0, 0, "-", "config"], [12, 0, 0, "-", "exception"], [12, 0, 0, "-", "library"], [12, 0, 0, "-", "object"], [14, 0, 0, "-", "processors"]], "syncify.spotify.base": [[12, 1, 1, "", "SpotifyItem"], [12, 1, 1, "", "SpotifyObject"], [12, 1, 1, "", "SpotifyObjectMixin"]], "syncify.spotify.base.SpotifyItem": [[12, 4, 1, "", "api"]], "syncify.spotify.base.SpotifyObject": [[12, 4, 1, "", "api"], [12, 3, 1, "", "has_uri"], [12, 3, 1, "", "id"], [12, 3, 1, "", "uri"], [12, 3, 1, "", "url"], [12, 3, 1, "", "url_ext"]], "syncify.spotify.base.SpotifyObjectMixin": [[12, 4, 1, "", "api"]], "syncify.spotify.exception": [[12, 5, 1, "", "SpotifyCollectionError"], [12, 5, 1, "", "SpotifyError"], [12, 5, 1, "", "SpotifyItemError"]], "syncify.spotify.library": [[12, 1, 1, "", "SpotifyLibrary"]], "syncify.spotify.library.SpotifyLibrary": [[12, 3, 1, "", "albums"], [12, 3, 1, "", "api"], [12, 3, 1, "", "artists"], [12, 2, 1, "", "enrich_saved_albums"], [12, 2, 1, "", "enrich_saved_artists"], [12, 2, 1, "", "enrich_tracks"], [12, 4, 1, "", "exclude"], [12, 4, 1, "", "include"], [12, 2, 1, "", "merge_playlists"], [12, 3, 1, "", "playlists"], [12, 4, 1, "", "use_cache"]], "syncify.spotify.object": [[12, 1, 1, "", "SpotifyAlbum"], [12, 1, 1, "", "SpotifyArtist"], [12, 1, 1, "", "SpotifyCollection"], [12, 1, 1, "", "SpotifyCollectionLoader"], [12, 1, 1, "", "SpotifyItemWranglerMixin"], [12, 1, 1, "", "SpotifyObjectLoaderMixin"], [12, 1, 1, "", "SpotifyPlaylist"], [12, 1, 1, "", "SpotifyTrack"]], "syncify.spotify.object.SpotifyAlbum": [[12, 3, 1, "", "album_artist"], [12, 3, 1, "", "artist"], [12, 3, 1, "", "artists"], [12, 3, 1, "", "compilation"], [12, 3, 1, "", "day"], [12, 3, 1, "", "genres"], [12, 3, 1, "", "has_image"], [12, 3, 1, "", "image_links"], [12, 3, 1, "", "length"], [12, 3, 1, "", "month"], [12, 3, 1, "", "name"], [12, 3, 1, "", "rating"], [12, 2, 1, "", "refresh"], [12, 2, 1, "", "reload"], [12, 3, 1, "", "track_total"], [12, 3, 1, "", "tracks"], [12, 3, 1, "", "year"]], "syncify.spotify.object.SpotifyArtist": [[12, 3, 1, "", "albums"], [12, 3, 1, "", "artist"], [12, 3, 1, "", "followers"], [12, 3, 1, "", "genres"], [12, 3, 1, "", "image_links"], [12, 3, 1, "", "items"], [12, 2, 1, "", "load"], [12, 3, 1, "", "name"], [12, 3, 1, "", "rating"], [12, 2, 1, "", "refresh"], [12, 2, 1, "", "reload"]], "syncify.spotify.object.SpotifyCollectionLoader": [[12, 4, 1, "", "api"], [12, 2, 1, "", "load"]], "syncify.spotify.object.SpotifyItemWranglerMixin": [[12, 4, 1, "", "api"]], "syncify.spotify.object.SpotifyObjectLoaderMixin": [[12, 4, 1, "", "api"]], "syncify.spotify.object.SpotifyPlaylist": [[12, 3, 1, "", "collaborative"], [12, 3, 1, "", "date_added"], [12, 3, 1, "", "date_created"], [12, 3, 1, "", "date_modified"], [12, 3, 1, "", "description"], [12, 3, 1, "", "followers"], [12, 3, 1, "", "has_image"], [12, 3, 1, "", "image_links"], [12, 3, 1, "", "name"], [12, 3, 1, "", "owner_id"], [12, 3, 1, "", "owner_name"], [12, 3, 1, "", "public"], [12, 2, 1, "", "refresh"], [12, 2, 1, "", "reload"], [12, 3, 1, "", "track_total"], [12, 3, 1, "", "tracks"]], "syncify.spotify.object.SpotifyTrack": [[12, 3, 1, "", "album"], [12, 3, 1, "", "album_artist"], [12, 3, 1, "", "artist"], [12, 3, 1, "", "artists"], [12, 3, 1, "", "bpm"], [12, 3, 1, "", "comments"], [12, 3, 1, "", "compilation"], [12, 3, 1, "", "day"], [12, 3, 1, "", "disc_number"], [12, 3, 1, "", "disc_total"], [12, 3, 1, "", "genres"], [12, 3, 1, "", "has_image"], [12, 3, 1, "", "image_links"], [12, 3, 1, "", "key"], [12, 3, 1, "", "length"], [12, 2, 1, "", "load"], [12, 3, 1, "", "month"], [12, 3, 1, "", "name"], [12, 3, 1, "", "rating"], [12, 2, 1, "", "refresh"], [12, 2, 1, "", "reload"], [12, 3, 1, "", "title"], [12, 3, 1, "", "track_number"], [12, 3, 1, "", "track_total"], [12, 3, 1, "", "year"]], "syncify.spotify.processors": [[14, 0, 0, "-", "processors"], [14, 0, 0, "-", "wrangle"]], "syncify.spotify.processors.processors": [[14, 1, 1, "", "SpotifyItemChecker"], [14, 1, 1, "", "SpotifyItemSearcher"]], "syncify.spotify.processors.processors.SpotifyItemChecker": [[14, 4, 1, "", "allow_karaoke"], [14, 4, 1, "", "api"], [14, 4, 1, "", "final_skipped"], [14, 4, 1, "", "final_switched"], [14, 4, 1, "", "final_unavailable"], [14, 4, 1, "", "interval"], [14, 4, 1, "", "playlist_name_collection"], [14, 4, 1, "", "playlist_name_urls"], [14, 4, 1, "", "quit"], [14, 4, 1, "", "remaining"], [14, 4, 1, "", "skip"], [14, 4, 1, "", "switched"]], "syncify.spotify.processors.processors.SpotifyItemSearcher": [[14, 4, 1, "", "api"], [14, 4, 1, "", "use_cache"]], "syncify.spotify.processors.wrangle": [[14, 1, 1, "", "SpotifyDataWrangler"]], "syncify.spotify.processors.wrangle.SpotifyDataWrangler": [[14, 2, 1, "", "convert"], [14, 2, 1, "", "extract_ids"], [14, 2, 1, "", "get_id_type"], [14, 4, 1, "", "unavailable_uri_dummy"], [14, 2, 1, "", "validate_id_type"]], "syncify.utils": [[15, 0, 0, "-", "helpers"], [15, 0, 0, "-", "logger"], [15, 0, 0, "-", "printers"]], "syncify.utils.helpers": [[15, 6, 1, "", "align_and_truncate"], [15, 6, 1, "", "correct_platform_separators"], [15, 6, 1, "", "flatten_nested"], [15, 6, 1, "", "get_max_width"], [15, 6, 1, "", "get_most_common_values"], [15, 6, 1, "", "get_user_input"], [15, 6, 1, "", "limit_value"], [15, 6, 1, "", "merge_maps"], [15, 6, 1, "", "safe_format_map"], [15, 6, 1, "", "strip_ignore_words"], [15, 6, 1, "", "to_collection"], [15, 6, 1, "", "unique_list"]], "syncify.utils.logger": [[15, 1, 1, "", "CurrentTimeRotatingFileHandler"], [15, 1, 1, "", "LogConsoleFilter"], [15, 1, 1, "", "LogFileFilter"], [15, 1, 1, "", "SyncifyLogger"], [15, 6, 1, "", "format_full_func_name"]], "syncify.utils.logger.CurrentTimeRotatingFileHandler": [[15, 2, 1, "", "rotator"], [15, 2, 1, "", "shouldRollover"]], "syncify.utils.logger.LogConsoleFilter": [[15, 2, 1, "", "filter"]], "syncify.utils.logger.LogFileFilter": [[15, 2, 1, "", "filter"]], "syncify.utils.logger.SyncifyLogger": [[15, 4, 1, "", "compact"], [15, 3, 1, "", "file_paths"], [15, 2, 1, "", "get_progress_bar"], [15, 2, 1, "", "info_extra"], [15, 2, 1, "", "print"], [15, 2, 1, "", "report"], [15, 2, 1, "", "stat"], [15, 3, 1, "", "stdout_handlers"]], "syncify.utils.printers": [[15, 6, 1, "", "print_line"], [15, 6, 1, "", "print_logo"], [15, 6, 1, "", "print_time"]]}, "objtypes": {"0": "py:module", "1": "py:class", "2": "py:method", "3": "py:property", "4": "py:attribute", "5": "py:exception", "6": "py:function"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "class", "Python class"], "2": ["py", "method", "Python method"], "3": ["py", "property", "Python property"], "4": ["py", "attribute", "Python attribute"], "5": ["py", "exception", "Python exception"], "6": ["py", "function", "Python function"]}, "titleterms": {"welcom": 0, "syncifi": [0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], "": 0, "document": 0, "indic": 0, "tabl": 0, "src": 1, "packag": [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], "subpackag": [2, 5, 10, 12], "submodul": [2, 3, 4, 5, 9, 10, 11, 12, 14, 15], "config": [2, 10, 12], "modul": [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], "except": [2, 4, 5, 9, 10, 12], "field": 2, "report": 2, "content": [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], "abstract": 3, "collect": [3, 5], "enum": [3, 10], "misc": 3, "object": [3, 10, 12], "api": [4, 10, 13], "local": [5, 6, 7, 8], "librari": [6, 10, 12], "playlist": 7, "track": 8, "processor": [9, 11, 14], "base": [9, 10, 12], "compar": 9, "limit": 9, "match": 9, "sort": 9, "time": 9, "remot": [10, 11], "type": 10, "check": 11, "search": 11, "wrangl": [11, 14], "spotifi": [12, 13, 14], "util": 15, "helper": 15, "logger": 15, "printer": 15}, "envversion": {"sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx": 60}, "alltitles": {"Welcome to Syncify\u2019s documentation!": [[0, "welcome-to-syncify-s-documentation"]], "Indices and tables": [[0, "indices-and-tables"]], "src": [[1, "src"]], "syncify package": [[2, "syncify-package"]], "Subpackages": [[2, "subpackages"], [5, "subpackages"], [10, "subpackages"], [12, "subpackages"]], "Submodules": [[2, "submodules"], [3, "submodules"], [4, "submodules"], [5, "submodules"], [9, "submodules"], [10, "submodules"], [11, "submodules"], [12, "submodules"], [14, "submodules"], [15, "submodules"]], "syncify.config module": [[2, "module-syncify.config"]], "syncify.exception module": [[2, "module-syncify.exception"]], "syncify.fields module": [[2, "module-syncify.fields"]], "syncify.report module": [[2, "module-syncify.report"]], "Module contents": [[2, "module-syncify"], [3, "module-syncify.abstract"], [4, "module-syncify.api"], [5, "module-syncify.local"], [6, "module-syncify.local.library"], [7, "module-syncify.local.playlist"], [8, "module-syncify.local.track"], [9, "module-syncify.processors"], [10, "module-syncify.remote"], [11, "module-syncify.remote.processors"], [12, "module-syncify.spotify"], [13, "module-syncify.spotify.api"], [14, "module-syncify.spotify.processors"], [15, "module-syncify.utils"]], "syncify.abstract package": [[3, "syncify-abstract-package"]], "syncify.abstract.collection module": [[3, "module-syncify.abstract.collection"]], "syncify.abstract.enums module": [[3, "module-syncify.abstract.enums"]], "syncify.abstract.misc module": [[3, "module-syncify.abstract.misc"]], "syncify.abstract.object module": [[3, "module-syncify.abstract.object"]], "syncify.api package": [[4, "syncify-api-package"]], "syncify.api.exception module": [[4, "module-syncify.api.exception"]], "syncify.local package": [[5, "syncify-local-package"]], "syncify.local.collection module": [[5, "module-syncify.local.collection"]], "syncify.local.exception module": [[5, "module-syncify.local.exception"]], "syncify.local.library package": [[6, "syncify-local-library-package"]], "syncify.local.playlist package": [[7, "syncify-local-playlist-package"]], "syncify.local.track package": [[8, "syncify-local-track-package"]], "syncify.processors package": [[9, "syncify-processors-package"]], "syncify.processors.base module": [[9, "module-syncify.processors.base"]], "syncify.processors.compare module": [[9, "module-syncify.processors.compare"]], "syncify.processors.exception module": [[9, "module-syncify.processors.exception"]], "syncify.processors.limit module": [[9, "module-syncify.processors.limit"]], "syncify.processors.match module": [[9, "module-syncify.processors.match"]], "syncify.processors.sort module": [[9, "module-syncify.processors.sort"]], "syncify.processors.time module": [[9, "module-syncify.processors.time"]], "syncify.remote package": [[10, "syncify-remote-package"]], "syncify.remote.api module": [[10, "module-syncify.remote.api"]], "syncify.remote.base module": [[10, "module-syncify.remote.base"]], "syncify.remote.config module": [[10, "module-syncify.remote.config"]], "syncify.remote.enums module": [[10, "module-syncify.remote.enums"]], "syncify.remote.exception module": [[10, "module-syncify.remote.exception"]], "syncify.remote.library module": [[10, "module-syncify.remote.library"]], "syncify.remote.object module": [[10, "module-syncify.remote.object"]], "syncify.remote.types module": [[10, "module-syncify.remote.types"]], "syncify.remote.processors package": [[11, "syncify-remote-processors-package"]], "syncify.remote.processors.check module": [[11, "module-syncify.remote.processors.check"]], "syncify.remote.processors.search module": [[11, "module-syncify.remote.processors.search"]], "syncify.remote.processors.wrangle module": [[11, "module-syncify.remote.processors.wrangle"]], "syncify.spotify package": [[12, "syncify-spotify-package"]], "syncify.spotify.base module": [[12, "module-syncify.spotify.base"]], "syncify.spotify.config module": [[12, "module-syncify.spotify.config"]], "syncify.spotify.exception module": [[12, "module-syncify.spotify.exception"]], "syncify.spotify.library module": [[12, "module-syncify.spotify.library"]], "syncify.spotify.object module": [[12, "module-syncify.spotify.object"]], "syncify.spotify.api package": [[13, "syncify-spotify-api-package"]], "syncify.spotify.processors package": [[14, "syncify-spotify-processors-package"]], "syncify.spotify.processors.processors module": [[14, "module-syncify.spotify.processors.processors"]], "syncify.spotify.processors.wrangle module": [[14, "module-syncify.spotify.processors.wrangle"]], "syncify.utils package": [[15, "syncify-utils-package"]], "syncify.utils.helpers module": [[15, "module-syncify.utils.helpers"]], "syncify.utils.logger module": [[15, "module-syncify.utils.logger"]], "syncify.utils.printers module": [[15, "module-syncify.utils.printers"]]}, "indexentries": {"album (syncify.fields.albumfield attribute)": [[2, "syncify.fields.AlbumField.ALBUM"]], "album (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.ALBUM"]], "album (syncify.fields.trackfield attribute)": [[2, "syncify.fields.TrackField.ALBUM"]], "album_artist (syncify.fields.albumfield attribute)": [[2, "syncify.fields.AlbumField.ALBUM_ARTIST"]], "album_artist (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.ALBUM_ARTIST"]], "album_artist (syncify.fields.trackfield attribute)": [[2, "syncify.fields.TrackField.ALBUM_ARTIST"]], "all (syncify.fields.albumfield attribute)": [[2, "syncify.fields.AlbumField.ALL"]], "all (syncify.fields.artistfield attribute)": [[2, "syncify.fields.ArtistField.ALL"]], "all (syncify.fields.folderfield attribute)": [[2, "syncify.fields.FolderField.ALL"]], "all (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.ALL"]], "all (syncify.fields.playlistfield attribute)": [[2, "syncify.fields.PlaylistField.ALL"]], "all (syncify.fields.trackfield attribute)": [[2, "syncify.fields.TrackField.ALL"]], "artist (syncify.fields.albumfield attribute)": [[2, "syncify.fields.AlbumField.ARTIST"]], "artist (syncify.fields.artistfield attribute)": [[2, "syncify.fields.ArtistField.ARTIST"]], "artist (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.ARTIST"]], "artist (syncify.fields.trackfield attribute)": [[2, "syncify.fields.TrackField.ARTIST"]], "albumfield (class in syncify.fields)": [[2, "syncify.fields.AlbumField"]], "artistfield (class in syncify.fields)": [[2, "syncify.fields.ArtistField"]], "bit_depth (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.BIT_DEPTH"]], "bit_rate (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.BIT_RATE"]], "bpm (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.BPM"]], "bpm (syncify.fields.trackfield attribute)": [[2, "syncify.fields.TrackField.BPM"]], "baseconfig (class in syncify.config)": [[2, "syncify.config.BaseConfig"]], "channels (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.CHANNELS"]], "comments (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.COMMENTS"]], "comments (syncify.fields.trackfield attribute)": [[2, "syncify.fields.TrackField.COMMENTS"]], "compilation (syncify.fields.albumfield attribute)": [[2, "syncify.fields.AlbumField.COMPILATION"]], "compilation (syncify.fields.folderfield attribute)": [[2, "syncify.fields.FolderField.COMPILATION"]], "compilation (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.COMPILATION"]], "compilation (syncify.fields.trackfield attribute)": [[2, "syncify.fields.TrackField.COMPILATION"]], "config (class in syncify.config)": [[2, "syncify.config.Config"]], "configapi (class in syncify.config)": [[2, "syncify.config.ConfigAPI"]], "configerror": [[2, "syncify.exception.ConfigError"]], "configfilter (class in syncify.config)": [[2, "syncify.config.ConfigFilter"]], "configfilter.configmatch (class in syncify.config)": [[2, "syncify.config.ConfigFilter.ConfigMatch"]], "configlibrary (class in syncify.config)": [[2, "syncify.config.ConfigLibrary"]], "configlibrarydifferences (class in syncify.config)": [[2, "syncify.config.ConfigLibraryDifferences"]], "configlocal (class in syncify.config)": [[2, "syncify.config.ConfigLocal"]], "configlocal.configupdatetags (class in syncify.config)": [[2, "syncify.config.ConfigLocal.ConfigUpdateTags"]], "configmissingtags (class in syncify.config)": [[2, "syncify.config.ConfigMissingTags"]], "configmusicbee (class in syncify.config)": [[2, "syncify.config.ConfigMusicBee"]], "configplaylists (class in syncify.config)": [[2, "syncify.config.ConfigPlaylists"]], "configremote (class in syncify.config)": [[2, "syncify.config.ConfigRemote"]], "configremote.configplaylists (class in syncify.config)": [[2, "syncify.config.ConfigRemote.ConfigPlaylists"]], "configremote.configplaylists.configplaylistssync (class in syncify.config)": [[2, "syncify.config.ConfigRemote.ConfigPlaylists.ConfigPlaylistsSync"]], "configreportbase (class in syncify.config)": [[2, "syncify.config.ConfigReportBase"]], "configreports (class in syncify.config)": [[2, "syncify.config.ConfigReports"]], "configspotify (class in syncify.config)": [[2, "syncify.config.ConfigSpotify"]], "date (syncify.fields.albumfield attribute)": [[2, "syncify.fields.AlbumField.DATE"]], "date (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.DATE"]], "date_added (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.DATE_ADDED"]], "date_created (syncify.fields.playlistfield attribute)": [[2, "syncify.fields.PlaylistField.DATE_CREATED"]], "date_modified (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.DATE_MODIFIED"]], "date_modified (syncify.fields.playlistfield attribute)": [[2, "syncify.fields.PlaylistField.DATE_MODIFIED"]], "day (syncify.fields.albumfield attribute)": [[2, "syncify.fields.AlbumField.DAY"]], "day (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.DAY"]], "description (syncify.fields.playlistfield attribute)": [[2, "syncify.fields.PlaylistField.DESCRIPTION"]], "disc (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.DISC"]], "disc (syncify.fields.trackfield attribute)": [[2, "syncify.fields.TrackField.DISC"]], "disc_number (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.DISC_NUMBER"]], "disc_number (syncify.fields.trackfield attribute)": [[2, "syncify.fields.TrackField.DISC_NUMBER"]], "disc_total (syncify.fields.albumfield attribute)": [[2, "syncify.fields.AlbumField.DISC_TOTAL"]], "disc_total (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.DISC_TOTAL"]], "disc_total (syncify.fields.trackfield attribute)": [[2, "syncify.fields.TrackField.DISC_TOTAL"]], "ext (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.EXT"]], "filename (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.FILENAME"]], "folder (syncify.fields.folderfield attribute)": [[2, "syncify.fields.FolderField.FOLDER"]], "folder (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.FOLDER"]], "folderfield (class in syncify.fields)": [[2, "syncify.fields.FolderField"]], "genres (syncify.fields.albumfield attribute)": [[2, "syncify.fields.AlbumField.GENRES"]], "genres (syncify.fields.artistfield attribute)": [[2, "syncify.fields.ArtistField.GENRES"]], "genres (syncify.fields.folderfield attribute)": [[2, "syncify.fields.FolderField.GENRES"]], "genres (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.GENRES"]], "genres (syncify.fields.trackfield attribute)": [[2, "syncify.fields.TrackField.GENRES"]], "images (syncify.fields.albumfield attribute)": [[2, "syncify.fields.AlbumField.IMAGES"]], "images (syncify.fields.artistfield attribute)": [[2, "syncify.fields.ArtistField.IMAGES"]], "images (syncify.fields.folderfield attribute)": [[2, "syncify.fields.FolderField.IMAGES"]], "images (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.IMAGES"]], "images (syncify.fields.playlistfield attribute)": [[2, "syncify.fields.PlaylistField.IMAGES"]], "images (syncify.fields.trackfield attribute)": [[2, "syncify.fields.TrackField.IMAGES"]], "key (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.KEY"]], "key (syncify.fields.trackfield attribute)": [[2, "syncify.fields.TrackField.KEY"]], "kind (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.KIND"]], "last_played (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.LAST_PLAYED"]], "length (syncify.fields.albumfield attribute)": [[2, "syncify.fields.AlbumField.LENGTH"]], "length (syncify.fields.artistfield attribute)": [[2, "syncify.fields.ArtistField.LENGTH"]], "length (syncify.fields.folderfield attribute)": [[2, "syncify.fields.FolderField.LENGTH"]], "length (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.LENGTH"]], "length (syncify.fields.playlistfield attribute)": [[2, "syncify.fields.PlaylistField.LENGTH"]], "length (syncify.fields.trackfield attribute)": [[2, "syncify.fields.TrackField.LENGTH"]], "localtrackfield (class in syncify.fields)": [[2, "syncify.fields.LocalTrackField"]], "month (syncify.fields.albumfield attribute)": [[2, "syncify.fields.AlbumField.MONTH"]], "month (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.MONTH"]], "path (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.PATH"]], "play_count (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.PLAY_COUNT"]], "playlistfield (class in syncify.fields)": [[2, "syncify.fields.PlaylistField"]], "rating (syncify.fields.albumfield attribute)": [[2, "syncify.fields.AlbumField.RATING"]], "rating (syncify.fields.artistfield attribute)": [[2, "syncify.fields.ArtistField.RATING"]], "rating (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.RATING"]], "rating (syncify.fields.trackfield attribute)": [[2, "syncify.fields.TrackField.RATING"]], "remoteclasses (class in syncify.config)": [[2, "syncify.config.RemoteClasses"]], "sample_rate (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.SAMPLE_RATE"]], "size (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.SIZE"]], "safedict (class in syncify.exception)": [[2, "syncify.exception.SafeDict"]], "syncifyattributeerror": [[2, "syncify.exception.SyncifyAttributeError"]], "syncifyenumerror": [[2, "syncify.exception.SyncifyEnumError"]], "syncifyerror": [[2, "syncify.exception.SyncifyError"]], "syncifykeyerror": [[2, "syncify.exception.SyncifyKeyError"]], "syncifytypeerror": [[2, "syncify.exception.SyncifyTypeError"]], "syncifyvalueerror": [[2, "syncify.exception.SyncifyValueError"]], "title (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.TITLE"]], "title (syncify.fields.trackfield attribute)": [[2, "syncify.fields.TrackField.TITLE"]], "track (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.TRACK"]], "track (syncify.fields.trackfield attribute)": [[2, "syncify.fields.TrackField.TRACK"]], "track_number (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.TRACK_NUMBER"]], "track_number (syncify.fields.trackfield attribute)": [[2, "syncify.fields.TrackField.TRACK_NUMBER"]], "track_total (syncify.fields.albumfield attribute)": [[2, "syncify.fields.AlbumField.TRACK_TOTAL"]], "track_total (syncify.fields.artistfield attribute)": [[2, "syncify.fields.ArtistField.TRACK_TOTAL"]], "track_total (syncify.fields.folderfield attribute)": [[2, "syncify.fields.FolderField.TRACK_TOTAL"]], "track_total (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.TRACK_TOTAL"]], "track_total (syncify.fields.playlistfield attribute)": [[2, "syncify.fields.PlaylistField.TRACK_TOTAL"]], "track_total (syncify.fields.trackfield attribute)": [[2, "syncify.fields.TrackField.TRACK_TOTAL"]], "trackfield (class in syncify.fields)": [[2, "syncify.fields.TrackField"]], "trackfieldmixin (class in syncify.fields)": [[2, "syncify.fields.TrackFieldMixin"]], "uri (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.URI"]], "uri (syncify.fields.trackfield attribute)": [[2, "syncify.fields.TrackField.URI"]], "year (syncify.fields.albumfield attribute)": [[2, "syncify.fields.AlbumField.YEAR"]], "year (syncify.fields.localtrackfield attribute)": [[2, "syncify.fields.LocalTrackField.YEAR"]], "year (syncify.fields.trackfield attribute)": [[2, "syncify.fields.TrackField.YEAR"]], "api (syncify.config.configapi property)": [[2, "syncify.config.ConfigAPI.api"]], "api (syncify.config.configspotify property)": [[2, "syncify.config.ConfigSpotify.api"]], "api (syncify.config.remoteclasses attribute)": [[2, "syncify.config.RemoteClasses.api"]], "as_dict() (syncify.config.config method)": [[2, "syncify.config.Config.as_dict"]], "as_dict() (syncify.config.configapi method)": [[2, "syncify.config.ConfigAPI.as_dict"]], "as_dict() (syncify.config.configfilter method)": [[2, "syncify.config.ConfigFilter.as_dict"]], "as_dict() (syncify.config.configfilter.configmatch method)": [[2, "syncify.config.ConfigFilter.ConfigMatch.as_dict"]], "as_dict() (syncify.config.configlibrary method)": [[2, "syncify.config.ConfigLibrary.as_dict"]], "as_dict() (syncify.config.configlocal method)": [[2, "syncify.config.ConfigLocal.as_dict"]], "as_dict() (syncify.config.configlocal.configupdatetags method)": [[2, "syncify.config.ConfigLocal.ConfigUpdateTags.as_dict"]], "as_dict() (syncify.config.configmissingtags method)": [[2, "syncify.config.ConfigMissingTags.as_dict"]], "as_dict() (syncify.config.configmusicbee method)": [[2, "syncify.config.ConfigMusicBee.as_dict"]], "as_dict() (syncify.config.configremote method)": [[2, "syncify.config.ConfigRemote.as_dict"]], "as_dict() (syncify.config.configremote.configplaylists method)": [[2, "syncify.config.ConfigRemote.ConfigPlaylists.as_dict"]], "as_dict() (syncify.config.configremote.configplaylists.configplaylistssync method)": [[2, "syncify.config.ConfigRemote.ConfigPlaylists.ConfigPlaylistsSync.as_dict"]], "as_dict() (syncify.config.configreportbase method)": [[2, "syncify.config.ConfigReportBase.as_dict"]], "as_dict() (syncify.config.configreports method)": [[2, "syncify.config.ConfigReports.as_dict"]], "as_dict() (syncify.config.configspotify method)": [[2, "syncify.config.ConfigSpotify.as_dict"]], "cache_path (syncify.config.configapi property)": [[2, "syncify.config.ConfigAPI.cache_path"]], "checker (syncify.config.configremote property)": [[2, "syncify.config.ConfigRemote.checker"]], "checker (syncify.config.remoteclasses attribute)": [[2, "syncify.config.RemoteClasses.checker"]], "client_id (syncify.config.configspotify property)": [[2, "syncify.config.ConfigSpotify.client_id"]], "client_secret (syncify.config.configspotify property)": [[2, "syncify.config.ConfigSpotify.client_secret"]], "enabled (syncify.config.configreports property)": [[2, "syncify.config.ConfigReports.enabled"]], "filter (syncify.config.configremote.configplaylists.configplaylistssync property)": [[2, "syncify.config.ConfigRemote.ConfigPlaylists.ConfigPlaylistsSync.filter"]], "kind (syncify.config.configlibrary property)": [[2, "syncify.config.ConfigLibrary.kind"]], "kind (syncify.config.configremote.configplaylists.configplaylistssync property)": [[2, "syncify.config.ConfigRemote.ConfigPlaylists.ConfigPlaylistsSync.kind"]], "library (syncify.config.configlibrary property)": [[2, "syncify.config.ConfigLibrary.library"]], "library (syncify.config.configlocal property)": [[2, "syncify.config.ConfigLocal.library"]], "library (syncify.config.configmusicbee property)": [[2, "syncify.config.ConfigMusicBee.library"]], "library (syncify.config.configremote property)": [[2, "syncify.config.ConfigRemote.library"]], "library (syncify.config.remoteclasses attribute)": [[2, "syncify.config.RemoteClasses.library"]], "library_folder (syncify.config.configlocal property)": [[2, "syncify.config.ConfigLocal.library_folder"]], "load() (syncify.config.config method)": [[2, "syncify.config.Config.load"]], "load_log_config() (syncify.config.config method)": [[2, "syncify.config.Config.load_log_config"]], "map() (syncify.fields.trackfieldmixin class method)": [[2, "syncify.fields.TrackFieldMixin.map"]], "match_all (syncify.config.configfilter.configmatch property)": [[2, "syncify.config.ConfigFilter.ConfigMatch.match_all"]], "match_all (syncify.config.configmissingtags property)": [[2, "syncify.config.ConfigMissingTags.match_all"]], "merge() (syncify.config.baseconfig method)": [[2, "syncify.config.BaseConfig.merge"]], "merge() (syncify.config.configfilter.configmatch method)": [[2, "syncify.config.ConfigFilter.ConfigMatch.merge"]], "merge() (syncify.config.configremote.configplaylists.configplaylistssync method)": [[2, "syncify.config.ConfigRemote.ConfigPlaylists.ConfigPlaylistsSync.merge"]], "module": [[2, "module-syncify"], [2, "module-syncify.config"], [2, "module-syncify.exception"], [2, "module-syncify.fields"], [2, "module-syncify.report"], [3, "module-syncify.abstract"], [3, "module-syncify.abstract.collection"], [3, "module-syncify.abstract.enums"], [3, "module-syncify.abstract.misc"], [3, "module-syncify.abstract.object"], [4, "module-syncify.api"], [4, "module-syncify.api.exception"], [5, "module-syncify.local"], [5, "module-syncify.local.collection"], [5, "module-syncify.local.exception"], [6, "module-syncify.local.library"], [7, "module-syncify.local.playlist"], [8, "module-syncify.local.track"], [9, "module-syncify.processors"], [9, "module-syncify.processors.base"], [9, "module-syncify.processors.compare"], [9, "module-syncify.processors.exception"], [9, "module-syncify.processors.limit"], [9, "module-syncify.processors.match"], [9, "module-syncify.processors.sort"], [9, "module-syncify.processors.time"], [10, "module-syncify.remote"], [10, "module-syncify.remote.api"], [10, "module-syncify.remote.base"], [10, "module-syncify.remote.config"], [10, "module-syncify.remote.enums"], [10, "module-syncify.remote.exception"], [10, "module-syncify.remote.library"], [10, "module-syncify.remote.object"], [10, "module-syncify.remote.types"], [11, "module-syncify.remote.processors"], [11, "module-syncify.remote.processors.check"], [11, "module-syncify.remote.processors.search"], [11, "module-syncify.remote.processors.wrangle"], [12, "module-syncify.spotify"], [12, "module-syncify.spotify.base"], [12, "module-syncify.spotify.config"], [12, "module-syncify.spotify.exception"], [12, "module-syncify.spotify.library"], [12, "module-syncify.spotify.object"], [13, "module-syncify.spotify.api"], [14, "module-syncify.spotify.processors"], [14, "module-syncify.spotify.processors.processors"], [14, "module-syncify.spotify.processors.wrangle"], [15, "module-syncify.utils"], [15, "module-syncify.utils.helpers"], [15, "module-syncify.utils.logger"], [15, "module-syncify.utils.printers"]], "musicbee_folder (syncify.config.configmusicbee property)": [[2, "syncify.config.ConfigMusicBee.musicbee_folder"]], "object (syncify.config.remoteclasses attribute)": [[2, "syncify.config.RemoteClasses.object"]], "other_folders (syncify.config.configlocal property)": [[2, "syncify.config.ConfigLocal.other_folders"]], "output_folder (syncify.config.config property)": [[2, "syncify.config.Config.output_folder"]], "pause (syncify.config.config property)": [[2, "syncify.config.Config.pause"]], "playlist (syncify.config.configremote property)": [[2, "syncify.config.ConfigRemote.playlist"]], "playlist (syncify.config.remoteclasses attribute)": [[2, "syncify.config.RemoteClasses.playlist"]], "playlist_folder (syncify.config.configlocal property)": [[2, "syncify.config.ConfigLocal.playlist_folder"]], "process() (syncify.config.configfilter method)": [[2, "syncify.config.ConfigFilter.process"]], "process() (syncify.config.configfilter.configmatch method)": [[2, "syncify.config.ConfigFilter.ConfigMatch.process"]], "ready (syncify.config.configfilter property)": [[2, "syncify.config.ConfigFilter.ready"]], "ready (syncify.config.configfilter.configmatch property)": [[2, "syncify.config.ConfigFilter.ConfigMatch.ready"]], "reload (syncify.config.config property)": [[2, "syncify.config.Config.reload"]], "reload (syncify.config.configremote.configplaylists.configplaylistssync property)": [[2, "syncify.config.ConfigRemote.ConfigPlaylists.ConfigPlaylistsSync.reload"]], "remote_wrangler (syncify.config.configlocal property)": [[2, "syncify.config.ConfigLocal.remote_wrangler"]], "replace (syncify.config.configlocal.configupdatetags property)": [[2, "syncify.config.ConfigLocal.ConfigUpdateTags.replace"]], "report_missing_tags() (in module syncify.report)": [[2, "syncify.report.report_missing_tags"]], "report_playlist_differences() (in module syncify.report)": [[2, "syncify.report.report_playlist_differences"]], "scopes (syncify.config.configspotify property)": [[2, "syncify.config.ConfigSpotify.scopes"]], "searcher (syncify.config.configremote property)": [[2, "syncify.config.ConfigRemote.searcher"]], "searcher (syncify.config.remoteclasses attribute)": [[2, "syncify.config.RemoteClasses.searcher"]], "source (syncify.config.configlibrary property)": [[2, "syncify.config.ConfigLibrary.source"]], "source (syncify.config.configlocal property)": [[2, "syncify.config.ConfigLocal.source"]], "source (syncify.config.configmusicbee property)": [[2, "syncify.config.ConfigMusicBee.source"]], "source (syncify.config.configremote property)": [[2, "syncify.config.ConfigRemote.source"]], "source (syncify.config.remoteclasses attribute)": [[2, "syncify.config.RemoteClasses.source"]], "syncify": [[2, "module-syncify"]], "syncify.config": [[2, "module-syncify.config"]], "syncify.exception": [[2, "module-syncify.exception"]], "syncify.fields": [[2, "module-syncify.fields"]], "syncify.report": [[2, "module-syncify.report"]], "tags (syncify.config.configlocal.configupdatetags property)": [[2, "syncify.config.ConfigLocal.ConfigUpdateTags.tags"]], "tags (syncify.config.configmissingtags property)": [[2, "syncify.config.ConfigMissingTags.tags"]], "token_path (syncify.config.configapi property)": [[2, "syncify.config.ConfigAPI.token_path"]], "use_cache (syncify.config.configapi property)": [[2, "syncify.config.ConfigAPI.use_cache"]], "values (syncify.config.configfilter.configmatch property)": [[2, "syncify.config.ConfigFilter.ConfigMatch.values"]], "wrangler (syncify.config.configremote property)": [[2, "syncify.config.ConfigRemote.wrangler"]], "wrangler (syncify.config.remoteclasses attribute)": [[2, "syncify.config.RemoteClasses.wrangler"]], "album (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.ALBUM"]], "album (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.ALBUM"]], "album_artist (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.ALBUM_ARTIST"]], "album_artist (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.ALBUM_ARTIST"]], "all (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.ALL"]], "all (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.ALL"]], "artist (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.ARTIST"]], "artist (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.ARTIST"]], "album (class in syncify.abstract.object)": [[3, "syncify.abstract.object.Album"]], "artist (class in syncify.abstract.object)": [[3, "syncify.abstract.object.Artist"]], "bit_depth (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.BIT_DEPTH"]], "bit_depth (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.BIT_DEPTH"]], "bit_rate (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.BIT_RATE"]], "bit_rate (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.BIT_RATE"]], "bpm (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.BPM"]], "bpm (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.BPM"]], "basiccollection (class in syncify.abstract.object)": [[3, "syncify.abstract.object.BasicCollection"]], "channels (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.CHANNELS"]], "channels (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.CHANNELS"]], "comments (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.COMMENTS"]], "comments (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.COMMENTS"]], "compilation (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.COMPILATION"]], "compilation (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.COMPILATION"]], "composer (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.COMPOSER"]], "composer (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.COMPOSER"]], "conductor (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.CONDUCTOR"]], "conductor (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.CONDUCTOR"]], "date (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.DATE"]], "date (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.DATE"]], "date_added (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.DATE_ADDED"]], "date_added (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.DATE_ADDED"]], "date_created (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.DATE_CREATED"]], "date_created (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.DATE_CREATED"]], "date_modified (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.DATE_MODIFIED"]], "date_modified (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.DATE_MODIFIED"]], "day (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.DAY"]], "day (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.DAY"]], "description (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.DESCRIPTION"]], "description (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.DESCRIPTION"]], "disc_number (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.DISC_NUMBER"]], "disc_number (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.DISC_NUMBER"]], "disc_total (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.DISC_TOTAL"]], "disc_total (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.DISC_TOTAL"]], "ext (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.EXT"]], "ext (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.EXT"]], "filename (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.FILENAME"]], "filename (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.FILENAME"]], "folder (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.FOLDER"]], "folder (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.FOLDER"]], "followers (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.FOLLOWERS"]], "followers (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.FOLLOWERS"]], "field (class in syncify.abstract.enums)": [[3, "syncify.abstract.enums.Field"]], "fields (class in syncify.abstract.enums)": [[3, "syncify.abstract.enums.Fields"]], "filter (class in syncify.abstract.misc)": [[3, "syncify.abstract.misc.Filter"]], "folder (class in syncify.abstract.object)": [[3, "syncify.abstract.object.Folder"]], "genres (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.GENRES"]], "genres (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.GENRES"]], "genre (class in syncify.abstract.object)": [[3, "syncify.abstract.object.Genre"]], "images (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.IMAGES"]], "images (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.IMAGES"]], "itemcollection (class in syncify.abstract.collection)": [[3, "syncify.abstract.collection.ItemCollection"]], "key (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.KEY"]], "key (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.KEY"]], "kind (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.KIND"]], "kind (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.KIND"]], "last_played (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.LAST_PLAYED"]], "last_played (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.LAST_PLAYED"]], "length (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.LENGTH"]], "length (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.LENGTH"]], "library (class in syncify.abstract.object)": [[3, "syncify.abstract.object.Library"]], "month (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.MONTH"]], "month (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.MONTH"]], "name (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.NAME"]], "name (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.NAME"]], "owner_id (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.OWNER_ID"]], "owner_id (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.OWNER_ID"]], "owner_name (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.OWNER_NAME"]], "owner_name (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.OWNER_NAME"]], "path (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.PATH"]], "path (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.PATH"]], "play_count (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.PLAY_COUNT"]], "play_count (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.PLAY_COUNT"]], "publisher (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.PUBLISHER"]], "publisher (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.PUBLISHER"]], "playlist (class in syncify.abstract.object)": [[3, "syncify.abstract.object.Playlist"]], "prettyprinter (class in syncify.abstract.misc)": [[3, "syncify.abstract.misc.PrettyPrinter"]], "rating (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.RATING"]], "rating (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.RATING"]], "result (class in syncify.abstract.misc)": [[3, "syncify.abstract.misc.Result"]], "sample_rate (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.SAMPLE_RATE"]], "sample_rate (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.SAMPLE_RATE"]], "size (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.SIZE"]], "size (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.SIZE"]], "syncifyenum (class in syncify.abstract.enums)": [[3, "syncify.abstract.enums.SyncifyEnum"]], "title (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.TITLE"]], "title (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.TITLE"]], "track_number (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.TRACK_NUMBER"]], "track_number (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.TRACK_NUMBER"]], "track_total (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.TRACK_TOTAL"]], "track_total (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.TRACK_TOTAL"]], "tagfield (class in syncify.abstract.enums)": [[3, "syncify.abstract.enums.TagField"]], "tagfields (class in syncify.abstract.enums)": [[3, "syncify.abstract.enums.TagFields"]], "tagmap (class in syncify.abstract.enums)": [[3, "syncify.abstract.enums.TagMap"]], "track (class in syncify.abstract.object)": [[3, "syncify.abstract.object.Track"]], "uri (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.URI"]], "uri (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.URI"]], "user_id (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.USER_ID"]], "user_id (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.USER_ID"]], "user_name (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.USER_NAME"]], "user_name (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.USER_NAME"]], "year (syncify.abstract.enums.fields attribute)": [[3, "syncify.abstract.enums.Fields.YEAR"]], "year (syncify.abstract.enums.tagfields attribute)": [[3, "syncify.abstract.enums.TagFields.YEAR"]], "album (syncify.abstract.enums.tagmap attribute)": [[3, "syncify.abstract.enums.TagMap.album"]], "album (syncify.abstract.object.album property)": [[3, "syncify.abstract.object.Album.album"]], "album (syncify.abstract.object.track property)": [[3, "syncify.abstract.object.Track.album"]], "album_artist (syncify.abstract.enums.tagmap attribute)": [[3, "syncify.abstract.enums.TagMap.album_artist"]], "album_artist (syncify.abstract.object.album property)": [[3, "syncify.abstract.object.Album.album_artist"]], "album_artist (syncify.abstract.object.track property)": [[3, "syncify.abstract.object.Track.album_artist"]], "albums (syncify.abstract.object.artist property)": [[3, "syncify.abstract.object.Artist.albums"]], "albums (syncify.abstract.object.folder property)": [[3, "syncify.abstract.object.Folder.albums"]], "albums (syncify.abstract.object.genre property)": [[3, "syncify.abstract.object.Genre.albums"]], "all() (syncify.abstract.enums.syncifyenum class method)": [[3, "syncify.abstract.enums.SyncifyEnum.all"]], "all() (syncify.abstract.enums.tagfield class method)": [[3, "syncify.abstract.enums.TagField.all"]], "append() (syncify.abstract.collection.itemcollection method)": [[3, "syncify.abstract.collection.ItemCollection.append"]], "artist (syncify.abstract.enums.tagmap attribute)": [[3, "syncify.abstract.enums.TagMap.artist"]], "artist (syncify.abstract.object.album property)": [[3, "syncify.abstract.object.Album.artist"]], "artist (syncify.abstract.object.artist property)": [[3, "syncify.abstract.object.Artist.artist"]], "artist (syncify.abstract.object.track property)": [[3, "syncify.abstract.object.Track.artist"]], "artists (syncify.abstract.object.album property)": [[3, "syncify.abstract.object.Album.artists"]], "artists (syncify.abstract.object.artist property)": [[3, "syncify.abstract.object.Artist.artists"]], "artists (syncify.abstract.object.folder property)": [[3, "syncify.abstract.object.Folder.artists"]], "artists (syncify.abstract.object.genre property)": [[3, "syncify.abstract.object.Genre.artists"]], "artists (syncify.abstract.object.track property)": [[3, "syncify.abstract.object.Track.artists"]], "as_dict() (syncify.abstract.misc.prettyprinter method)": [[3, "syncify.abstract.misc.PrettyPrinter.as_dict"]], "as_dict() (syncify.abstract.object.basiccollection method)": [[3, "syncify.abstract.object.BasicCollection.as_dict"]], "bpm (syncify.abstract.enums.tagmap attribute)": [[3, "syncify.abstract.enums.TagMap.bpm"]], "bpm (syncify.abstract.object.track property)": [[3, "syncify.abstract.object.Track.bpm"]], "clear() (syncify.abstract.collection.itemcollection method)": [[3, "syncify.abstract.collection.ItemCollection.clear"]], "comments (syncify.abstract.enums.tagmap attribute)": [[3, "syncify.abstract.enums.TagMap.comments"]], "comments (syncify.abstract.object.track property)": [[3, "syncify.abstract.object.Track.comments"]], "compilation (syncify.abstract.enums.tagmap attribute)": [[3, "syncify.abstract.enums.TagMap.compilation"]], "compilation (syncify.abstract.object.album property)": [[3, "syncify.abstract.object.Album.compilation"]], "compilation (syncify.abstract.object.folder property)": [[3, "syncify.abstract.object.Folder.compilation"]], "compilation (syncify.abstract.object.track property)": [[3, "syncify.abstract.object.Track.compilation"]], "copy() (syncify.abstract.collection.itemcollection method)": [[3, "syncify.abstract.collection.ItemCollection.copy"]], "count() (syncify.abstract.collection.itemcollection method)": [[3, "syncify.abstract.collection.ItemCollection.count"]], "date (syncify.abstract.enums.tagmap attribute)": [[3, "syncify.abstract.enums.TagMap.date"]], "date (syncify.abstract.object.album property)": [[3, "syncify.abstract.object.Album.date"]], "date (syncify.abstract.object.track property)": [[3, "syncify.abstract.object.Track.date"]], "date_created (syncify.abstract.object.playlist property)": [[3, "syncify.abstract.object.Playlist.date_created"]], "date_modified (syncify.abstract.object.playlist property)": [[3, "syncify.abstract.object.Playlist.date_modified"]], "day (syncify.abstract.enums.tagmap attribute)": [[3, "syncify.abstract.enums.TagMap.day"]], "day (syncify.abstract.object.album property)": [[3, "syncify.abstract.object.Album.day"]], "day (syncify.abstract.object.track property)": [[3, "syncify.abstract.object.Track.day"]], "description (syncify.abstract.object.playlist property)": [[3, "syncify.abstract.object.Playlist.description"]], "disc_number (syncify.abstract.enums.tagmap attribute)": [[3, "syncify.abstract.enums.TagMap.disc_number"]], "disc_number (syncify.abstract.object.track property)": [[3, "syncify.abstract.object.Track.disc_number"]], "disc_total (syncify.abstract.enums.tagmap attribute)": [[3, "syncify.abstract.enums.TagMap.disc_total"]], "disc_total (syncify.abstract.object.album property)": [[3, "syncify.abstract.object.Album.disc_total"]], "disc_total (syncify.abstract.object.track property)": [[3, "syncify.abstract.object.Track.disc_total"]], "extend() (syncify.abstract.collection.itemcollection method)": [[3, "syncify.abstract.collection.ItemCollection.extend"]], "folder (syncify.abstract.object.folder property)": [[3, "syncify.abstract.object.Folder.folder"]], "from_name() (syncify.abstract.enums.syncifyenum class method)": [[3, "syncify.abstract.enums.SyncifyEnum.from_name"]], "from_value() (syncify.abstract.enums.syncifyenum class method)": [[3, "syncify.abstract.enums.SyncifyEnum.from_value"]], "genre (syncify.abstract.object.genre property)": [[3, "syncify.abstract.object.Genre.genre"]], "genres (syncify.abstract.enums.tagmap attribute)": [[3, "syncify.abstract.enums.TagMap.genres"]], "genres (syncify.abstract.object.album property)": [[3, "syncify.abstract.object.Album.genres"]], "genres (syncify.abstract.object.artist property)": [[3, "syncify.abstract.object.Artist.genres"]], "genres (syncify.abstract.object.folder property)": [[3, "syncify.abstract.object.Folder.genres"]], "genres (syncify.abstract.object.genre property)": [[3, "syncify.abstract.object.Genre.genres"]], "genres (syncify.abstract.object.track property)": [[3, "syncify.abstract.object.Track.genres"]], "get_filtered_playlists() (syncify.abstract.object.library method)": [[3, "syncify.abstract.object.Library.get_filtered_playlists"]], "has_image (syncify.abstract.object.album property)": [[3, "syncify.abstract.object.Album.has_image"]], "has_image (syncify.abstract.object.playlist property)": [[3, "syncify.abstract.object.Playlist.has_image"]], "has_image (syncify.abstract.object.track property)": [[3, "syncify.abstract.object.Track.has_image"]], "image_links (syncify.abstract.object.album property)": [[3, "syncify.abstract.object.Album.image_links"]], "image_links (syncify.abstract.object.playlist property)": [[3, "syncify.abstract.object.Playlist.image_links"]], "image_links (syncify.abstract.object.track property)": [[3, "syncify.abstract.object.Track.image_links"]], "images (syncify.abstract.enums.tagmap attribute)": [[3, "syncify.abstract.enums.TagMap.images"]], "index() (syncify.abstract.collection.itemcollection method)": [[3, "syncify.abstract.collection.ItemCollection.index"]], "insert() (syncify.abstract.collection.itemcollection method)": [[3, "syncify.abstract.collection.ItemCollection.insert"]], "items (syncify.abstract.collection.itemcollection property)": [[3, "syncify.abstract.collection.ItemCollection.items"]], "items (syncify.abstract.object.album property)": [[3, "syncify.abstract.object.Album.items"]], "items (syncify.abstract.object.artist property)": [[3, "syncify.abstract.object.Artist.items"]], "items (syncify.abstract.object.basiccollection property)": [[3, "syncify.abstract.object.BasicCollection.items"]], "items (syncify.abstract.object.folder property)": [[3, "syncify.abstract.object.Folder.items"]], "items (syncify.abstract.object.genre property)": [[3, "syncify.abstract.object.Genre.items"]], "items (syncify.abstract.object.library property)": [[3, "syncify.abstract.object.Library.items"]], "items (syncify.abstract.object.playlist property)": [[3, "syncify.abstract.object.Playlist.items"]], "json() (syncify.abstract.misc.prettyprinter method)": [[3, "syncify.abstract.misc.PrettyPrinter.json"]], "key (syncify.abstract.enums.tagmap attribute)": [[3, "syncify.abstract.enums.TagMap.key"]], "key (syncify.abstract.object.track property)": [[3, "syncify.abstract.object.Track.key"]], "length (syncify.abstract.object.album property)": [[3, "syncify.abstract.object.Album.length"]], "length (syncify.abstract.object.artist property)": [[3, "syncify.abstract.object.Artist.length"]], "length (syncify.abstract.object.folder property)": [[3, "syncify.abstract.object.Folder.length"]], "length (syncify.abstract.object.playlist property)": [[3, "syncify.abstract.object.Playlist.length"]], "length (syncify.abstract.object.track property)": [[3, "syncify.abstract.object.Track.length"]], "map() (syncify.abstract.enums.syncifyenum class method)": [[3, "syncify.abstract.enums.SyncifyEnum.map"]], "merge() (syncify.abstract.object.playlist method)": [[3, "syncify.abstract.object.Playlist.merge"]], "merge_playlists() (syncify.abstract.object.library method)": [[3, "syncify.abstract.object.Library.merge_playlists"]], "month (syncify.abstract.enums.tagmap attribute)": [[3, "syncify.abstract.enums.TagMap.month"]], "month (syncify.abstract.object.album property)": [[3, "syncify.abstract.object.Album.month"]], "month (syncify.abstract.object.track property)": [[3, "syncify.abstract.object.Track.month"]], "name (syncify.abstract.object.album property)": [[3, "syncify.abstract.object.Album.name"]], "name (syncify.abstract.object.artist property)": [[3, "syncify.abstract.object.Artist.name"]], "name (syncify.abstract.object.basiccollection property)": [[3, "syncify.abstract.object.BasicCollection.name"]], "name (syncify.abstract.object.folder property)": [[3, "syncify.abstract.object.Folder.name"]], "name (syncify.abstract.object.genre property)": [[3, "syncify.abstract.object.Genre.name"]], "name (syncify.abstract.object.library property)": [[3, "syncify.abstract.object.Library.name"]], "name (syncify.abstract.object.playlist property)": [[3, "syncify.abstract.object.Playlist.name"]], "name (syncify.abstract.object.track property)": [[3, "syncify.abstract.object.Track.name"]], "playlists (syncify.abstract.object.library property)": [[3, "syncify.abstract.object.Library.playlists"]], "pop() (syncify.abstract.collection.itemcollection method)": [[3, "syncify.abstract.collection.ItemCollection.pop"]], "process() (syncify.abstract.misc.filter method)": [[3, "syncify.abstract.misc.Filter.process"]], "rating (syncify.abstract.object.album property)": [[3, "syncify.abstract.object.Album.rating"]], "rating (syncify.abstract.object.artist property)": [[3, "syncify.abstract.object.Artist.rating"]], "rating (syncify.abstract.object.track property)": [[3, "syncify.abstract.object.Track.rating"]], "ready (syncify.abstract.misc.filter property)": [[3, "syncify.abstract.misc.Filter.ready"]], "remove() (syncify.abstract.collection.itemcollection method)": [[3, "syncify.abstract.collection.ItemCollection.remove"]], "reverse() (syncify.abstract.collection.itemcollection method)": [[3, "syncify.abstract.collection.ItemCollection.reverse"]], "sort() (syncify.abstract.collection.itemcollection method)": [[3, "syncify.abstract.collection.ItemCollection.sort"]], "syncify.abstract": [[3, "module-syncify.abstract"]], "syncify.abstract.collection": [[3, "module-syncify.abstract.collection"]], "syncify.abstract.enums": [[3, "module-syncify.abstract.enums"]], "syncify.abstract.misc": [[3, "module-syncify.abstract.misc"]], "syncify.abstract.object": [[3, "module-syncify.abstract.object"]], "title (syncify.abstract.enums.tagmap attribute)": [[3, "syncify.abstract.enums.TagMap.title"]], "title (syncify.abstract.object.track property)": [[3, "syncify.abstract.object.Track.title"]], "to_tag() (syncify.abstract.enums.tagfield method)": [[3, "syncify.abstract.enums.TagField.to_tag"]], "to_tags() (syncify.abstract.enums.tagfield class method)": [[3, "syncify.abstract.enums.TagField.to_tags"]], "track_number (syncify.abstract.enums.tagmap attribute)": [[3, "syncify.abstract.enums.TagMap.track_number"]], "track_number (syncify.abstract.object.track property)": [[3, "syncify.abstract.object.Track.track_number"]], "track_total (syncify.abstract.enums.tagmap attribute)": [[3, "syncify.abstract.enums.TagMap.track_total"]], "track_total (syncify.abstract.object.album property)": [[3, "syncify.abstract.object.Album.track_total"]], "track_total (syncify.abstract.object.artist property)": [[3, "syncify.abstract.object.Artist.track_total"]], "track_total (syncify.abstract.object.folder property)": [[3, "syncify.abstract.object.Folder.track_total"]], "track_total (syncify.abstract.object.library property)": [[3, "syncify.abstract.object.Library.track_total"]], "track_total (syncify.abstract.object.playlist property)": [[3, "syncify.abstract.object.Playlist.track_total"]], "track_total (syncify.abstract.object.track property)": [[3, "syncify.abstract.object.Track.track_total"]], "tracks (syncify.abstract.object.album property)": [[3, "syncify.abstract.object.Album.tracks"]], "tracks (syncify.abstract.object.artist property)": [[3, "syncify.abstract.object.Artist.tracks"]], "tracks (syncify.abstract.object.folder property)": [[3, "syncify.abstract.object.Folder.tracks"]], "tracks (syncify.abstract.object.genre property)": [[3, "syncify.abstract.object.Genre.tracks"]], "tracks (syncify.abstract.object.library property)": [[3, "syncify.abstract.object.Library.tracks"]], "tracks (syncify.abstract.object.playlist property)": [[3, "syncify.abstract.object.Playlist.tracks"]], "year (syncify.abstract.enums.tagmap attribute)": [[3, "syncify.abstract.enums.TagMap.year"]], "year (syncify.abstract.object.album property)": [[3, "syncify.abstract.object.Album.year"]], "year (syncify.abstract.object.track property)": [[3, "syncify.abstract.object.Track.year"]], "apierror": [[4, "syncify.api.exception.APIError"]], "requesterror": [[4, "syncify.api.exception.RequestError"]], "syncify.api": [[4, "module-syncify.api"]], "syncify.api.exception": [[4, "module-syncify.api.exception"]], "fielderror": [[5, "syncify.local.exception.FieldError"]], "filedoesnotexisterror": [[5, "syncify.local.exception.FileDoesNotExistError"]], "fileerror": [[5, "syncify.local.exception.FileError"]], "imageloaderror": [[5, "syncify.local.exception.ImageLoadError"]], "invalidfiletype": [[5, "syncify.local.exception.InvalidFileType"]], "localalbum (class in syncify.local.collection)": [[5, "syncify.local.collection.LocalAlbum"]], "localartist (class in syncify.local.collection)": [[5, "syncify.local.collection.LocalArtist"]], "localcollection (class in syncify.local.collection)": [[5, "syncify.local.collection.LocalCollection"]], "localcollectionerror": [[5, "syncify.local.exception.LocalCollectionError"]], "localcollectionfiltered (class in syncify.local.collection)": [[5, "syncify.local.collection.LocalCollectionFiltered"]], "localerror": [[5, "syncify.local.exception.LocalError"]], "localfolder (class in syncify.local.collection)": [[5, "syncify.local.collection.LocalFolder"]], "localgenres (class in syncify.local.collection)": [[5, "syncify.local.collection.LocalGenres"]], "localitemerror": [[5, "syncify.local.exception.LocalItemError"]], "localprocessorerror": [[5, "syncify.local.exception.LocalProcessorError"]], "musicbeeerror": [[5, "syncify.local.exception.MusicBeeError"]], "musicbeeiderror": [[5, "syncify.local.exception.MusicBeeIDError"]], "xmlreadererror": [[5, "syncify.local.exception.XMLReaderError"]], "album_artist (syncify.local.collection.localalbum property)": [[5, "syncify.local.collection.LocalAlbum.album_artist"]], "albums (syncify.local.collection.localartist property)": [[5, "syncify.local.collection.LocalArtist.albums"]], "albums (syncify.local.collection.localfolder property)": [[5, "syncify.local.collection.LocalFolder.albums"]], "albums (syncify.local.collection.localgenres property)": [[5, "syncify.local.collection.LocalGenres.albums"]], "artists (syncify.local.collection.localcollection property)": [[5, "syncify.local.collection.LocalCollection.artists"]], "as_dict() (syncify.local.collection.localalbum method)": [[5, "syncify.local.collection.LocalAlbum.as_dict"]], "as_dict() (syncify.local.collection.localartist method)": [[5, "syncify.local.collection.LocalArtist.as_dict"]], "as_dict() (syncify.local.collection.localcollection method)": [[5, "syncify.local.collection.LocalCollection.as_dict"]], "as_dict() (syncify.local.collection.localfolder method)": [[5, "syncify.local.collection.LocalFolder.as_dict"]], "as_dict() (syncify.local.collection.localgenres method)": [[5, "syncify.local.collection.LocalGenres.as_dict"]], "compilation (syncify.local.collection.localalbum property)": [[5, "syncify.local.collection.LocalAlbum.compilation"]], "compilation (syncify.local.collection.localfolder property)": [[5, "syncify.local.collection.LocalFolder.compilation"]], "date (syncify.local.collection.localalbum property)": [[5, "syncify.local.collection.LocalAlbum.date"]], "day (syncify.local.collection.localalbum property)": [[5, "syncify.local.collection.LocalAlbum.day"]], "genres (syncify.local.collection.localcollection property)": [[5, "syncify.local.collection.LocalCollection.genres"]], "has_image (syncify.local.collection.localalbum property)": [[5, "syncify.local.collection.LocalAlbum.has_image"]], "image_links (syncify.local.collection.localalbum property)": [[5, "syncify.local.collection.LocalAlbum.image_links"]], "items (syncify.local.collection.localcollection property)": [[5, "syncify.local.collection.LocalCollection.items"]], "last_added (syncify.local.collection.localcollection property)": [[5, "syncify.local.collection.LocalCollection.last_added"]], "last_modified (syncify.local.collection.localcollection property)": [[5, "syncify.local.collection.LocalCollection.last_modified"]], "last_played (syncify.local.collection.localcollection property)": [[5, "syncify.local.collection.LocalCollection.last_played"]], "length (syncify.local.collection.localcollection property)": [[5, "syncify.local.collection.LocalCollection.length"]], "log_sync_result() (syncify.local.collection.localcollection method)": [[5, "syncify.local.collection.LocalCollection.log_sync_result"]], "logger (syncify.local.collection.localalbum attribute)": [[5, "syncify.local.collection.LocalAlbum.logger"]], "logger (syncify.local.collection.localartist attribute)": [[5, "syncify.local.collection.LocalArtist.logger"]], "logger (syncify.local.collection.localcollection attribute)": [[5, "syncify.local.collection.LocalCollection.logger"]], "logger (syncify.local.collection.localcollectionfiltered attribute)": [[5, "syncify.local.collection.LocalCollectionFiltered.logger"]], "logger (syncify.local.collection.localfolder attribute)": [[5, "syncify.local.collection.LocalFolder.logger"]], "logger (syncify.local.collection.localgenres attribute)": [[5, "syncify.local.collection.LocalGenres.logger"]], "merge_tracks() (syncify.local.collection.localcollection method)": [[5, "syncify.local.collection.LocalCollection.merge_tracks"]], "month (syncify.local.collection.localalbum property)": [[5, "syncify.local.collection.LocalAlbum.month"]], "name (syncify.local.collection.localcollectionfiltered property)": [[5, "syncify.local.collection.LocalCollectionFiltered.name"]], "play_count (syncify.local.collection.localcollection property)": [[5, "syncify.local.collection.LocalCollection.play_count"]], "rating (syncify.local.collection.localalbum property)": [[5, "syncify.local.collection.LocalAlbum.rating"]], "rating (syncify.local.collection.localartist property)": [[5, "syncify.local.collection.LocalArtist.rating"]], "remote_wrangler (syncify.local.collection.localalbum attribute)": [[5, "syncify.local.collection.LocalAlbum.remote_wrangler"]], "remote_wrangler (syncify.local.collection.localartist attribute)": [[5, "syncify.local.collection.LocalArtist.remote_wrangler"]], "remote_wrangler (syncify.local.collection.localcollection attribute)": [[5, "syncify.local.collection.LocalCollection.remote_wrangler"]], "remote_wrangler (syncify.local.collection.localcollectionfiltered attribute)": [[5, "syncify.local.collection.LocalCollectionFiltered.remote_wrangler"]], "remote_wrangler (syncify.local.collection.localfolder attribute)": [[5, "syncify.local.collection.LocalFolder.remote_wrangler"]], "remote_wrangler (syncify.local.collection.localgenres attribute)": [[5, "syncify.local.collection.LocalGenres.remote_wrangler"]], "save_tracks() (syncify.local.collection.localcollection method)": [[5, "syncify.local.collection.LocalCollection.save_tracks"]], "set_compilation_tags() (syncify.local.collection.localfolder method)": [[5, "syncify.local.collection.LocalFolder.set_compilation_tags"]], "syncify.local": [[5, "module-syncify.local"]], "syncify.local.collection": [[5, "module-syncify.local.collection"]], "syncify.local.exception": [[5, "module-syncify.local.exception"]], "track_paths (syncify.local.collection.localcollection property)": [[5, "syncify.local.collection.LocalCollection.track_paths"]], "track_total (syncify.local.collection.localcollection property)": [[5, "syncify.local.collection.LocalCollection.track_total"]], "tracks (syncify.local.collection.localcollection property)": [[5, "syncify.local.collection.LocalCollection.tracks"]], "tracks (syncify.local.collection.localcollectionfiltered property)": [[5, "syncify.local.collection.LocalCollectionFiltered.tracks"]], "year (syncify.local.collection.localalbum property)": [[5, "syncify.local.collection.LocalAlbum.year"]], "syncify.local.library": [[6, "module-syncify.local.library"]], "syncify.local.playlist": [[7, "module-syncify.local.playlist"]], "syncify.local.track": [[8, "module-syncify.local.track"]], "album (syncify.processors.sort.shuffleby attribute)": [[9, "syncify.processors.sort.ShuffleBy.ALBUM"]], "albums (syncify.processors.limit.limittype attribute)": [[9, "syncify.processors.limit.LimitType.ALBUMS"]], "artist (syncify.processors.sort.shuffleby attribute)": [[9, "syncify.processors.sort.ShuffleBy.ARTIST"]], "bytes (syncify.processors.limit.limittype attribute)": [[9, "syncify.processors.limit.LimitType.BYTES"]], "cleantagconfig (class in syncify.processors.match)": [[9, "syncify.processors.match.CleanTagConfig"]], "comparer (class in syncify.processors.compare)": [[9, "syncify.processors.compare.Comparer"]], "days (syncify.processors.limit.limittype attribute)": [[9, "syncify.processors.limit.LimitType.DAYS"]], "different_artist (syncify.processors.sort.shufflemode attribute)": [[9, "syncify.processors.sort.ShuffleMode.DIFFERENT_ARTIST"]], "dynamicprocessor (class in syncify.processors.base)": [[9, "syncify.processors.base.DynamicProcessor"]], "gigabytes (syncify.processors.limit.limittype attribute)": [[9, "syncify.processors.limit.LimitType.GIGABYTES"]], "higher_rating (syncify.processors.sort.shufflemode attribute)": [[9, "syncify.processors.sort.ShuffleMode.HIGHER_RATING"]], "hours (syncify.processors.limit.limittype attribute)": [[9, "syncify.processors.limit.LimitType.HOURS"]], "items (syncify.processors.limit.limittype attribute)": [[9, "syncify.processors.limit.LimitType.ITEMS"]], "itemcomparererror": [[9, "syncify.processors.exception.ItemComparerError"]], "itemlimiter (class in syncify.processors.limit)": [[9, "syncify.processors.limit.ItemLimiter"]], "itemlimitererror": [[9, "syncify.processors.exception.ItemLimiterError"]], "itemmatcher (class in syncify.processors.match)": [[9, "syncify.processors.match.ItemMatcher"]], "itemmatchererror": [[9, "syncify.processors.exception.ItemMatcherError"]], "itemprocessor (class in syncify.processors.base)": [[9, "syncify.processors.base.ItemProcessor"]], "itemprocessorerror": [[9, "syncify.processors.exception.ItemProcessorError"]], "itemsorter (class in syncify.processors.sort)": [[9, "syncify.processors.sort.ItemSorter"]], "itemsortererror": [[9, "syncify.processors.exception.ItemSorterError"]], "kilobytes (syncify.processors.limit.limittype attribute)": [[9, "syncify.processors.limit.LimitType.KILOBYTES"]], "limittype (class in syncify.processors.limit)": [[9, "syncify.processors.limit.LimitType"]], "megabytes (syncify.processors.limit.limittype attribute)": [[9, "syncify.processors.limit.LimitType.MEGABYTES"]], "minutes (syncify.processors.limit.limittype attribute)": [[9, "syncify.processors.limit.LimitType.MINUTES"]], "musicbeeprocessor (class in syncify.processors.base)": [[9, "syncify.processors.base.MusicBeeProcessor"]], "none (syncify.processors.sort.shufflemode attribute)": [[9, "syncify.processors.sort.ShuffleMode.NONE"]], "processor (class in syncify.processors.base)": [[9, "syncify.processors.base.Processor"]], "processorerror": [[9, "syncify.processors.exception.ProcessorError"]], "processorlookuperror": [[9, "syncify.processors.exception.ProcessorLookupError"]], "random (syncify.processors.sort.shufflemode attribute)": [[9, "syncify.processors.sort.ShuffleMode.RANDOM"]], "recent_added (syncify.processors.sort.shufflemode attribute)": [[9, "syncify.processors.sort.ShuffleMode.RECENT_ADDED"]], "seconds (syncify.processors.limit.limittype attribute)": [[9, "syncify.processors.limit.LimitType.SECONDS"]], "shuffleby (class in syncify.processors.sort)": [[9, "syncify.processors.sort.ShuffleBy"]], "shufflemode (class in syncify.processors.sort)": [[9, "syncify.processors.sort.ShuffleMode"]], "terabytes (syncify.processors.limit.limittype attribute)": [[9, "syncify.processors.limit.LimitType.TERABYTES"]], "track (syncify.processors.sort.shuffleby attribute)": [[9, "syncify.processors.sort.ShuffleBy.TRACK"]], "timemapper (class in syncify.processors.time)": [[9, "syncify.processors.time.TimeMapper"]], "timemappererror": [[9, "syncify.processors.exception.TimeMapperError"]], "weeks (syncify.processors.limit.limittype attribute)": [[9, "syncify.processors.limit.LimitType.WEEKS"]], "allowance (syncify.processors.limit.itemlimiter attribute)": [[9, "syncify.processors.limit.ItemLimiter.allowance"]], "as_dict() (syncify.processors.compare.comparer method)": [[9, "syncify.processors.compare.Comparer.as_dict"]], "as_dict() (syncify.processors.limit.itemlimiter method)": [[9, "syncify.processors.limit.ItemLimiter.as_dict"]], "as_dict() (syncify.processors.match.cleantagconfig method)": [[9, "syncify.processors.match.CleanTagConfig.as_dict"]], "as_dict() (syncify.processors.match.itemmatcher method)": [[9, "syncify.processors.match.ItemMatcher.as_dict"]], "as_dict() (syncify.processors.sort.itemsorter method)": [[9, "syncify.processors.sort.ItemSorter.as_dict"]], "as_dict() (syncify.processors.time.timemapper method)": [[9, "syncify.processors.time.TimeMapper.as_dict"]], "clean_tags() (syncify.processors.match.itemmatcher method)": [[9, "syncify.processors.match.ItemMatcher.clean_tags"]], "clean_tags_config (syncify.processors.match.itemmatcher attribute)": [[9, "syncify.processors.match.ItemMatcher.clean_tags_config"]], "clean_tags_remove_all (syncify.processors.match.itemmatcher attribute)": [[9, "syncify.processors.match.ItemMatcher.clean_tags_remove_all"]], "clean_tags_split_all (syncify.processors.match.itemmatcher attribute)": [[9, "syncify.processors.match.ItemMatcher.clean_tags_split_all"]], "compare() (syncify.processors.compare.comparer method)": [[9, "syncify.processors.compare.Comparer.compare"]], "condition (syncify.processors.compare.comparer property)": [[9, "syncify.processors.compare.Comparer.condition"]], "days() (syncify.processors.time.timemapper method)": [[9, "syncify.processors.time.TimeMapper.days"]], "dynamicprocessormethod (class in syncify.processors.base)": [[9, "syncify.processors.base.dynamicprocessormethod"]], "expected (syncify.processors.compare.comparer property)": [[9, "syncify.processors.compare.Comparer.expected"]], "field (syncify.processors.compare.comparer attribute)": [[9, "syncify.processors.compare.Comparer.field"]], "from_xml() (syncify.processors.base.musicbeeprocessor class method)": [[9, "syncify.processors.base.MusicBeeProcessor.from_xml"]], "from_xml() (syncify.processors.compare.comparer class method)": [[9, "syncify.processors.compare.Comparer.from_xml"]], "from_xml() (syncify.processors.limit.itemlimiter class method)": [[9, "syncify.processors.limit.ItemLimiter.from_xml"]], "from_xml() (syncify.processors.sort.itemsorter class method)": [[9, "syncify.processors.sort.ItemSorter.from_xml"]], "group_by_field() (syncify.processors.sort.itemsorter class method)": [[9, "syncify.processors.sort.ItemSorter.group_by_field"]], "hours() (syncify.processors.time.timemapper method)": [[9, "syncify.processors.time.TimeMapper.hours"]], "karaoke_tags (syncify.processors.match.itemmatcher attribute)": [[9, "syncify.processors.match.ItemMatcher.karaoke_tags"]], "kind (syncify.processors.limit.itemlimiter attribute)": [[9, "syncify.processors.limit.ItemLimiter.kind"]], "limit() (syncify.processors.limit.itemlimiter method)": [[9, "syncify.processors.limit.ItemLimiter.limit"]], "limit_max (syncify.processors.limit.itemlimiter attribute)": [[9, "syncify.processors.limit.ItemLimiter.limit_max"]], "limit_sort (syncify.processors.limit.itemlimiter property)": [[9, "syncify.processors.limit.ItemLimiter.limit_sort"]], "logger (syncify.processors.match.itemmatcher attribute)": [[9, "syncify.processors.match.ItemMatcher.logger"]], "map() (syncify.processors.time.timemapper method)": [[9, "syncify.processors.time.TimeMapper.map"]], "match() (syncify.processors.match.itemmatcher method)": [[9, "syncify.processors.match.ItemMatcher.match"]], "match_album() (syncify.processors.match.itemmatcher method)": [[9, "syncify.processors.match.ItemMatcher.match_album"]], "match_artist() (syncify.processors.match.itemmatcher method)": [[9, "syncify.processors.match.ItemMatcher.match_artist"]], "match_length() (syncify.processors.match.itemmatcher method)": [[9, "syncify.processors.match.ItemMatcher.match_length"]], "match_name() (syncify.processors.match.itemmatcher method)": [[9, "syncify.processors.match.ItemMatcher.match_name"]], "match_not_karaoke() (syncify.processors.match.itemmatcher method)": [[9, "syncify.processors.match.ItemMatcher.match_not_karaoke"]], "match_year() (syncify.processors.match.itemmatcher method)": [[9, "syncify.processors.match.ItemMatcher.match_year"]], "minutes() (syncify.processors.time.timemapper method)": [[9, "syncify.processors.time.TimeMapper.minutes"]], "months() (syncify.processors.time.timemapper method)": [[9, "syncify.processors.time.TimeMapper.months"]], "preprocess() (syncify.processors.match.cleantagconfig method)": [[9, "syncify.processors.match.CleanTagConfig.preprocess"]], "processor_methods (syncify.processors.base.dynamicprocessor property)": [[9, "syncify.processors.base.DynamicProcessor.processor_methods"]], "reduce_name_score_factor (syncify.processors.match.itemmatcher attribute)": [[9, "syncify.processors.match.ItemMatcher.reduce_name_score_factor"]], "reduce_name_score_on (syncify.processors.match.itemmatcher attribute)": [[9, "syncify.processors.match.ItemMatcher.reduce_name_score_on"]], "remove (syncify.processors.match.cleantagconfig property)": [[9, "syncify.processors.match.CleanTagConfig.remove"]], "seconds() (syncify.processors.time.timemapper method)": [[9, "syncify.processors.time.TimeMapper.seconds"]], "shuffle_by (syncify.processors.sort.itemsorter attribute)": [[9, "syncify.processors.sort.ItemSorter.shuffle_by"]], "shuffle_mode (syncify.processors.sort.itemsorter attribute)": [[9, "syncify.processors.sort.ItemSorter.shuffle_mode"]], "shuffle_weight (syncify.processors.sort.itemsorter attribute)": [[9, "syncify.processors.sort.ItemSorter.shuffle_weight"]], "sort() (syncify.processors.sort.itemsorter method)": [[9, "syncify.processors.sort.ItemSorter.sort"]], "sort_by_field() (syncify.processors.sort.itemsorter class method)": [[9, "syncify.processors.sort.ItemSorter.sort_by_field"]], "sort_fields (syncify.processors.sort.itemsorter attribute)": [[9, "syncify.processors.sort.ItemSorter.sort_fields"]], "split (syncify.processors.match.cleantagconfig property)": [[9, "syncify.processors.match.CleanTagConfig.split"]], "syncify.processors": [[9, "module-syncify.processors"]], "syncify.processors.base": [[9, "module-syncify.processors.base"]], "syncify.processors.compare": [[9, "module-syncify.processors.compare"]], "syncify.processors.exception": [[9, "module-syncify.processors.exception"]], "syncify.processors.limit": [[9, "module-syncify.processors.limit"]], "syncify.processors.match": [[9, "module-syncify.processors.match"]], "syncify.processors.sort": [[9, "module-syncify.processors.sort"]], "syncify.processors.time": [[9, "module-syncify.processors.time"]], "tag (syncify.processors.match.cleantagconfig attribute)": [[9, "syncify.processors.match.CleanTagConfig.tag"]], "to_xml() (syncify.processors.base.musicbeeprocessor method)": [[9, "syncify.processors.base.MusicBeeProcessor.to_xml"]], "to_xml() (syncify.processors.compare.comparer method)": [[9, "syncify.processors.compare.Comparer.to_xml"]], "to_xml() (syncify.processors.limit.itemlimiter method)": [[9, "syncify.processors.limit.ItemLimiter.to_xml"]], "to_xml() (syncify.processors.sort.itemsorter method)": [[9, "syncify.processors.sort.ItemSorter.to_xml"]], "weeks() (syncify.processors.time.timemapper method)": [[9, "syncify.processors.time.TimeMapper.weeks"]], "year_range (syncify.processors.match.itemmatcher attribute)": [[9, "syncify.processors.match.ItemMatcher.year_range"]], "album (syncify.remote.enums.remoteobjecttype attribute)": [[10, "syncify.remote.enums.RemoteObjectType.ALBUM"]], "all (syncify.remote.enums.remoteidtype attribute)": [[10, "syncify.remote.enums.RemoteIDType.ALL"]], "all (syncify.remote.enums.remoteobjecttype attribute)": [[10, "syncify.remote.enums.RemoteObjectType.ALL"]], "artist (syncify.remote.enums.remoteobjecttype attribute)": [[10, "syncify.remote.enums.RemoteObjectType.ARTIST"]], "audiobook (syncify.remote.enums.remoteobjecttype attribute)": [[10, "syncify.remote.enums.RemoteObjectType.AUDIOBOOK"]], "chapter (syncify.remote.enums.remoteobjecttype attribute)": [[10, "syncify.remote.enums.RemoteObjectType.CHAPTER"]], "episode (syncify.remote.enums.remoteobjecttype attribute)": [[10, "syncify.remote.enums.RemoteObjectType.EPISODE"]], "id (syncify.remote.enums.remoteidtype attribute)": [[10, "syncify.remote.enums.RemoteIDType.ID"]], "playlist (syncify.remote.enums.remoteobjecttype attribute)": [[10, "syncify.remote.enums.RemoteObjectType.PLAYLIST"]], "remoteapi (class in syncify.remote.api)": [[10, "syncify.remote.api.RemoteAPI"]], "remotealbum (class in syncify.remote.object)": [[10, "syncify.remote.object.RemoteAlbum"]], "remoteartist (class in syncify.remote.object)": [[10, "syncify.remote.object.RemoteArtist"]], "remotecollection (class in syncify.remote.object)": [[10, "syncify.remote.object.RemoteCollection"]], "remotecollectionloader (class in syncify.remote.object)": [[10, "syncify.remote.object.RemoteCollectionLoader"]], "remoteerror": [[10, "syncify.remote.exception.RemoteError"]], "remoteidtype (class in syncify.remote.enums)": [[10, "syncify.remote.enums.RemoteIDType"]], "remoteidtypeerror": [[10, "syncify.remote.exception.RemoteIDTypeError"]], "remoteitem (class in syncify.remote.base)": [[10, "syncify.remote.base.RemoteItem"]], "remoteitemwranglermixin (class in syncify.remote.object)": [[10, "syncify.remote.object.RemoteItemWranglerMixin"]], "remotelibrary (class in syncify.remote.library)": [[10, "syncify.remote.library.RemoteLibrary"]], "remoteobject (class in syncify.remote.base)": [[10, "syncify.remote.base.RemoteObject"]], "remoteobjectclasses (class in syncify.remote.config)": [[10, "syncify.remote.config.RemoteObjectClasses"]], "remoteobjecttype (class in syncify.remote.enums)": [[10, "syncify.remote.enums.RemoteObjectType"]], "remoteobjecttypeerror": [[10, "syncify.remote.exception.RemoteObjectTypeError"]], "remoteplaylist (class in syncify.remote.object)": [[10, "syncify.remote.object.RemotePlaylist"]], "remotetrack (class in syncify.remote.object)": [[10, "syncify.remote.object.RemoteTrack"]], "show (syncify.remote.enums.remoteobjecttype attribute)": [[10, "syncify.remote.enums.RemoteObjectType.SHOW"]], "syncresultremoteplaylist (class in syncify.remote.object)": [[10, "syncify.remote.object.SyncResultRemotePlaylist"]], "track (syncify.remote.enums.remoteobjecttype attribute)": [[10, "syncify.remote.enums.RemoteObjectType.TRACK"]], "uri (syncify.remote.enums.remoteidtype attribute)": [[10, "syncify.remote.enums.RemoteIDType.URI"]], "url (syncify.remote.enums.remoteidtype attribute)": [[10, "syncify.remote.enums.RemoteIDType.URL"]], "url_ext (syncify.remote.enums.remoteidtype attribute)": [[10, "syncify.remote.enums.RemoteIDType.URL_EXT"]], "user (syncify.remote.enums.remoteobjecttype attribute)": [[10, "syncify.remote.enums.RemoteObjectType.USER"]], "add_to_playlist() (syncify.remote.api.remoteapi method)": [[10, "syncify.remote.api.RemoteAPI.add_to_playlist"]], "added (syncify.remote.object.syncresultremoteplaylist attribute)": [[10, "syncify.remote.object.SyncResultRemotePlaylist.added"]], "album (syncify.remote.config.remoteobjectclasses attribute)": [[10, "syncify.remote.config.RemoteObjectClasses.album"]], "albums (syncify.remote.library.remotelibrary property)": [[10, "syncify.remote.library.RemoteLibrary.albums"]], "albums (syncify.remote.object.remoteartist property)": [[10, "syncify.remote.object.RemoteArtist.albums"]], "api (syncify.remote.base.remoteitem attribute)": [[10, "syncify.remote.base.RemoteItem.api"]], "api (syncify.remote.base.remoteobject attribute)": [[10, "syncify.remote.base.RemoteObject.api"]], "api (syncify.remote.library.remotelibrary property)": [[10, "syncify.remote.library.RemoteLibrary.api"]], "api (syncify.remote.object.remotealbum attribute)": [[10, "syncify.remote.object.RemoteAlbum.api"]], "api (syncify.remote.object.remoteartist attribute)": [[10, "syncify.remote.object.RemoteArtist.api"]], "api (syncify.remote.object.remotecollectionloader attribute)": [[10, "syncify.remote.object.RemoteCollectionLoader.api"]], "api (syncify.remote.object.remoteitemwranglermixin attribute)": [[10, "syncify.remote.object.RemoteItemWranglerMixin.api"]], "api (syncify.remote.object.remoteplaylist attribute)": [[10, "syncify.remote.object.RemotePlaylist.api"]], "api (syncify.remote.object.remotetrack attribute)": [[10, "syncify.remote.object.RemoteTrack.api"]], "api_url_base (syncify.remote.api.remoteapi property)": [[10, "syncify.remote.api.RemoteAPI.api_url_base"]], "artist (syncify.remote.config.remoteobjectclasses attribute)": [[10, "syncify.remote.config.RemoteObjectClasses.artist"]], "artists (syncify.remote.library.remotelibrary property)": [[10, "syncify.remote.library.RemoteLibrary.artists"]], "artists (syncify.remote.object.remotealbum property)": [[10, "syncify.remote.object.RemoteAlbum.artists"]], "artists (syncify.remote.object.remoteartist property)": [[10, "syncify.remote.object.RemoteArtist.artists"]], "as_dict() (syncify.remote.base.remoteobject method)": [[10, "syncify.remote.base.RemoteObject.as_dict"]], "as_dict() (syncify.remote.library.remotelibrary method)": [[10, "syncify.remote.library.RemoteLibrary.as_dict"]], "authorise() (syncify.remote.api.remoteapi method)": [[10, "syncify.remote.api.RemoteAPI.authorise"]], "backup_playlists() (syncify.remote.library.remotelibrary method)": [[10, "syncify.remote.library.RemoteLibrary.backup_playlists"]], "clear_from_playlist() (syncify.remote.api.remoteapi method)": [[10, "syncify.remote.api.RemoteAPI.clear_from_playlist"]], "collection_item_map (syncify.remote.api.remoteapi attribute)": [[10, "syncify.remote.api.RemoteAPI.collection_item_map"]], "create() (syncify.remote.object.remoteplaylist class method)": [[10, "syncify.remote.object.RemotePlaylist.create"]], "create_playlist() (syncify.remote.api.remoteapi method)": [[10, "syncify.remote.api.RemoteAPI.create_playlist"]], "date_added (syncify.remote.object.remoteplaylist property)": [[10, "syncify.remote.object.RemotePlaylist.date_added"]], "delete() (syncify.remote.object.remoteplaylist method)": [[10, "syncify.remote.object.RemotePlaylist.delete"]], "delete_playlist() (syncify.remote.api.remoteapi method)": [[10, "syncify.remote.api.RemoteAPI.delete_playlist"]], "difference (syncify.remote.object.syncresultremoteplaylist attribute)": [[10, "syncify.remote.object.SyncResultRemotePlaylist.difference"]], "enrich_saved_albums() (syncify.remote.library.remotelibrary method)": [[10, "syncify.remote.library.RemoteLibrary.enrich_saved_albums"]], "enrich_saved_artists() (syncify.remote.library.remotelibrary method)": [[10, "syncify.remote.library.RemoteLibrary.enrich_saved_artists"]], "enrich_tracks() (syncify.remote.library.remotelibrary method)": [[10, "syncify.remote.library.RemoteLibrary.enrich_tracks"]], "exclude (syncify.remote.library.remotelibrary attribute)": [[10, "syncify.remote.library.RemoteLibrary.exclude"]], "extend() (syncify.remote.library.remotelibrary method)": [[10, "syncify.remote.library.RemoteLibrary.extend"]], "extend_items() (syncify.remote.api.remoteapi method)": [[10, "syncify.remote.api.RemoteAPI.extend_items"]], "final (syncify.remote.object.syncresultremoteplaylist attribute)": [[10, "syncify.remote.object.SyncResultRemotePlaylist.final"]], "followers (syncify.remote.object.remoteplaylist property)": [[10, "syncify.remote.object.RemotePlaylist.followers"]], "get_items() (syncify.remote.api.remoteapi method)": [[10, "syncify.remote.api.RemoteAPI.get_items"]], "get_playlist_url() (syncify.remote.api.remoteapi method)": [[10, "syncify.remote.api.RemoteAPI.get_playlist_url"]], "get_self() (syncify.remote.api.remoteapi method)": [[10, "syncify.remote.api.RemoteAPI.get_self"]], "get_tracks() (syncify.remote.api.remoteapi method)": [[10, "syncify.remote.api.RemoteAPI.get_tracks"]], "get_user_items() (syncify.remote.api.remoteapi method)": [[10, "syncify.remote.api.RemoteAPI.get_user_items"]], "handler (syncify.remote.api.remoteapi attribute)": [[10, "syncify.remote.api.RemoteAPI.handler"]], "has_image (syncify.remote.object.remoteartist property)": [[10, "syncify.remote.object.RemoteArtist.has_image"]], "has_uri (syncify.remote.base.remoteobject property)": [[10, "syncify.remote.base.RemoteObject.has_uri"]], "id (syncify.remote.base.remoteobject property)": [[10, "syncify.remote.base.RemoteObject.id"]], "id (syncify.remote.library.remotelibrary property)": [[10, "syncify.remote.library.RemoteLibrary.id"]], "image_links (syncify.remote.object.remoteartist property)": [[10, "syncify.remote.object.RemoteArtist.image_links"]], "include (syncify.remote.library.remotelibrary attribute)": [[10, "syncify.remote.library.RemoteLibrary.include"]], "json() (syncify.remote.library.remotelibrary method)": [[10, "syncify.remote.library.RemoteLibrary.json"]], "length (syncify.remote.object.remoteartist property)": [[10, "syncify.remote.object.RemoteArtist.length"]], "load() (syncify.remote.base.remoteobject class method)": [[10, "syncify.remote.base.RemoteObject.load"]], "load() (syncify.remote.library.remotelibrary method)": [[10, "syncify.remote.library.RemoteLibrary.load"]], "load() (syncify.remote.object.remotecollectionloader class method)": [[10, "syncify.remote.object.RemoteCollectionLoader.load"]], "load_playlists() (syncify.remote.library.remotelibrary method)": [[10, "syncify.remote.library.RemoteLibrary.load_playlists"]], "load_saved_albums() (syncify.remote.library.remotelibrary method)": [[10, "syncify.remote.library.RemoteLibrary.load_saved_albums"]], "load_saved_artists() (syncify.remote.library.remotelibrary method)": [[10, "syncify.remote.library.RemoteLibrary.load_saved_artists"]], "load_saved_tracks() (syncify.remote.library.remotelibrary method)": [[10, "syncify.remote.library.RemoteLibrary.load_saved_tracks"]], "load_user_data() (syncify.remote.api.remoteapi method)": [[10, "syncify.remote.api.RemoteAPI.load_user_data"]], "log_albums() (syncify.remote.library.remotelibrary method)": [[10, "syncify.remote.library.RemoteLibrary.log_albums"]], "log_artists() (syncify.remote.library.remotelibrary method)": [[10, "syncify.remote.library.RemoteLibrary.log_artists"]], "log_playlists() (syncify.remote.library.remotelibrary method)": [[10, "syncify.remote.library.RemoteLibrary.log_playlists"]], "log_sync() (syncify.remote.library.remotelibrary method)": [[10, "syncify.remote.library.RemoteLibrary.log_sync"]], "log_tracks() (syncify.remote.library.remotelibrary method)": [[10, "syncify.remote.library.RemoteLibrary.log_tracks"]], "logger (syncify.remote.api.remoteapi attribute)": [[10, "syncify.remote.api.RemoteAPI.logger"]], "merge() (syncify.remote.object.remoteplaylist method)": [[10, "syncify.remote.object.RemotePlaylist.merge"]], "name (syncify.remote.library.remotelibrary property)": [[10, "syncify.remote.library.RemoteLibrary.name"]], "owner_id (syncify.remote.object.remoteplaylist property)": [[10, "syncify.remote.object.RemotePlaylist.owner_id"]], "owner_name (syncify.remote.object.remoteplaylist property)": [[10, "syncify.remote.object.RemotePlaylist.owner_name"]], "playlist (syncify.remote.config.remoteobjectclasses attribute)": [[10, "syncify.remote.config.RemoteObjectClasses.playlist"]], "playlists (syncify.remote.library.remotelibrary property)": [[10, "syncify.remote.library.RemoteLibrary.playlists"]], "print_collection() (syncify.remote.api.remoteapi method)": [[10, "syncify.remote.api.RemoteAPI.print_collection"]], "print_item() (syncify.remote.api.remoteapi method)": [[10, "syncify.remote.api.RemoteAPI.print_item"]], "query() (syncify.remote.api.remoteapi method)": [[10, "syncify.remote.api.RemoteAPI.query"]], "refresh() (syncify.remote.base.remoteobject method)": [[10, "syncify.remote.base.RemoteObject.refresh"]], "reload() (syncify.remote.base.remoteobject method)": [[10, "syncify.remote.base.RemoteObject.reload"]], "removed (syncify.remote.object.syncresultremoteplaylist attribute)": [[10, "syncify.remote.object.SyncResultRemotePlaylist.removed"]], "response (syncify.remote.base.remoteobject property)": [[10, "syncify.remote.base.RemoteObject.response"]], "restore_playlists() (syncify.remote.library.remotelibrary method)": [[10, "syncify.remote.library.RemoteLibrary.restore_playlists"]], "start (syncify.remote.object.syncresultremoteplaylist attribute)": [[10, "syncify.remote.object.SyncResultRemotePlaylist.start"]], "sync() (syncify.remote.library.remotelibrary method)": [[10, "syncify.remote.library.RemoteLibrary.sync"]], "sync() (syncify.remote.object.remoteplaylist method)": [[10, "syncify.remote.object.RemotePlaylist.sync"]], "syncify.remote": [[10, "module-syncify.remote"]], "syncify.remote.api": [[10, "module-syncify.remote.api"]], "syncify.remote.base": [[10, "module-syncify.remote.base"]], "syncify.remote.config": [[10, "module-syncify.remote.config"]], "syncify.remote.enums": [[10, "module-syncify.remote.enums"]], "syncify.remote.exception": [[10, "module-syncify.remote.exception"]], "syncify.remote.library": [[10, "module-syncify.remote.library"]], "syncify.remote.object": [[10, "module-syncify.remote.object"]], "syncify.remote.types": [[10, "module-syncify.remote.types"]], "track (syncify.remote.config.remoteobjectclasses attribute)": [[10, "syncify.remote.config.RemoteObjectClasses.track"]], "track_total (syncify.remote.object.remoteartist property)": [[10, "syncify.remote.object.RemoteArtist.track_total"]], "tracks (syncify.remote.library.remotelibrary property)": [[10, "syncify.remote.library.RemoteLibrary.tracks"]], "tracks (syncify.remote.object.remoteartist property)": [[10, "syncify.remote.object.RemoteArtist.tracks"]], "unchanged (syncify.remote.object.syncresultremoteplaylist attribute)": [[10, "syncify.remote.object.SyncResultRemotePlaylist.unchanged"]], "uri (syncify.remote.base.remoteobject property)": [[10, "syncify.remote.base.RemoteObject.uri"]], "url (syncify.remote.base.remoteobject property)": [[10, "syncify.remote.base.RemoteObject.url"]], "url_ext (syncify.remote.base.remoteobject property)": [[10, "syncify.remote.base.RemoteObject.url_ext"]], "use_cache (syncify.remote.library.remotelibrary attribute)": [[10, "syncify.remote.library.RemoteLibrary.use_cache"]], "user_data (syncify.remote.api.remoteapi attribute)": [[10, "syncify.remote.api.RemoteAPI.user_data"]], "user_id (syncify.remote.api.remoteapi property)": [[10, "syncify.remote.api.RemoteAPI.user_id"]], "user_item_types (syncify.remote.api.remoteapi attribute)": [[10, "syncify.remote.api.RemoteAPI.user_item_types"]], "user_name (syncify.remote.api.remoteapi property)": [[10, "syncify.remote.api.RemoteAPI.user_name"]], "writeable (syncify.remote.object.remoteplaylist property)": [[10, "syncify.remote.object.RemotePlaylist.writeable"]], "itemcheckresult (class in syncify.remote.processors.check)": [[11, "syncify.remote.processors.check.ItemCheckResult"]], "itemsearchresult (class in syncify.remote.processors.search)": [[11, "syncify.remote.processors.search.ItemSearchResult"]], "remotedatawrangler (class in syncify.remote.processors.wrangle)": [[11, "syncify.remote.processors.wrangle.RemoteDataWrangler"]], "remoteitemchecker (class in syncify.remote.processors.check)": [[11, "syncify.remote.processors.check.RemoteItemChecker"]], "remoteitemsearcher (class in syncify.remote.processors.search)": [[11, "syncify.remote.processors.search.RemoteItemSearcher"]], "searchsettings (class in syncify.remote.processors.search)": [[11, "syncify.remote.processors.search.SearchSettings"]], "allow_karaoke (syncify.remote.processors.check.remoteitemchecker attribute)": [[11, "syncify.remote.processors.check.RemoteItemChecker.allow_karaoke"]], "allow_karaoke (syncify.remote.processors.search.searchsettings attribute)": [[11, "syncify.remote.processors.search.SearchSettings.allow_karaoke"]], "api (syncify.remote.processors.check.remoteitemchecker attribute)": [[11, "syncify.remote.processors.check.RemoteItemChecker.api"]], "api (syncify.remote.processors.search.remoteitemsearcher attribute)": [[11, "syncify.remote.processors.search.RemoteItemSearcher.api"]], "check() (syncify.remote.processors.check.remoteitemchecker method)": [[11, "syncify.remote.processors.check.RemoteItemChecker.check"]], "convert() (syncify.remote.processors.wrangle.remotedatawrangler class method)": [[11, "syncify.remote.processors.wrangle.RemoteDataWrangler.convert"]], "extract_ids() (syncify.remote.processors.wrangle.remotedatawrangler class method)": [[11, "syncify.remote.processors.wrangle.RemoteDataWrangler.extract_ids"]], "final_skipped (syncify.remote.processors.check.remoteitemchecker attribute)": [[11, "syncify.remote.processors.check.RemoteItemChecker.final_skipped"]], "final_switched (syncify.remote.processors.check.remoteitemchecker attribute)": [[11, "syncify.remote.processors.check.RemoteItemChecker.final_switched"]], "final_unavailable (syncify.remote.processors.check.remoteitemchecker attribute)": [[11, "syncify.remote.processors.check.RemoteItemChecker.final_unavailable"]], "get_id_type() (syncify.remote.processors.wrangle.remotedatawrangler static method)": [[11, "syncify.remote.processors.wrangle.RemoteDataWrangler.get_id_type"]], "get_item_type() (syncify.remote.processors.wrangle.remotedatawrangler class method)": [[11, "syncify.remote.processors.wrangle.RemoteDataWrangler.get_item_type"]], "interval (syncify.remote.processors.check.remoteitemchecker attribute)": [[11, "syncify.remote.processors.check.RemoteItemChecker.interval"]], "match_fields (syncify.remote.processors.search.searchsettings attribute)": [[11, "syncify.remote.processors.search.SearchSettings.match_fields"]], "matched (syncify.remote.processors.search.itemsearchresult attribute)": [[11, "syncify.remote.processors.search.ItemSearchResult.matched"]], "max_score (syncify.remote.processors.search.searchsettings attribute)": [[11, "syncify.remote.processors.search.SearchSettings.max_score"]], "min_score (syncify.remote.processors.search.searchsettings attribute)": [[11, "syncify.remote.processors.search.SearchSettings.min_score"]], "playlist_name_collection (syncify.remote.processors.check.remoteitemchecker attribute)": [[11, "syncify.remote.processors.check.RemoteItemChecker.playlist_name_collection"]], "playlist_name_urls (syncify.remote.processors.check.remoteitemchecker attribute)": [[11, "syncify.remote.processors.check.RemoteItemChecker.playlist_name_urls"]], "quit (syncify.remote.processors.check.remoteitemchecker attribute)": [[11, "syncify.remote.processors.check.RemoteItemChecker.quit"]], "remaining (syncify.remote.processors.check.remoteitemchecker attribute)": [[11, "syncify.remote.processors.check.RemoteItemChecker.remaining"]], "result_count (syncify.remote.processors.search.searchsettings attribute)": [[11, "syncify.remote.processors.search.SearchSettings.result_count"]], "search() (syncify.remote.processors.search.remoteitemsearcher method)": [[11, "syncify.remote.processors.search.RemoteItemSearcher.search"]], "search_fields_1 (syncify.remote.processors.search.searchsettings attribute)": [[11, "syncify.remote.processors.search.SearchSettings.search_fields_1"]], "search_fields_2 (syncify.remote.processors.search.searchsettings attribute)": [[11, "syncify.remote.processors.search.SearchSettings.search_fields_2"]], "search_fields_3 (syncify.remote.processors.search.searchsettings attribute)": [[11, "syncify.remote.processors.search.SearchSettings.search_fields_3"]], "settings_albums (syncify.remote.processors.search.remoteitemsearcher attribute)": [[11, "syncify.remote.processors.search.RemoteItemSearcher.settings_albums"]], "settings_items (syncify.remote.processors.search.remoteitemsearcher attribute)": [[11, "syncify.remote.processors.search.RemoteItemSearcher.settings_items"]], "skip (syncify.remote.processors.check.remoteitemchecker attribute)": [[11, "syncify.remote.processors.check.RemoteItemChecker.skip"]], "skipped (syncify.remote.processors.check.itemcheckresult attribute)": [[11, "syncify.remote.processors.check.ItemCheckResult.skipped"]], "skipped (syncify.remote.processors.search.itemsearchresult attribute)": [[11, "syncify.remote.processors.search.ItemSearchResult.skipped"]], "switched (syncify.remote.processors.check.itemcheckresult attribute)": [[11, "syncify.remote.processors.check.ItemCheckResult.switched"]], "switched (syncify.remote.processors.check.remoteitemchecker attribute)": [[11, "syncify.remote.processors.check.RemoteItemChecker.switched"]], "syncify.remote.processors": [[11, "module-syncify.remote.processors"]], "syncify.remote.processors.check": [[11, "module-syncify.remote.processors.check"]], "syncify.remote.processors.search": [[11, "module-syncify.remote.processors.search"]], "syncify.remote.processors.wrangle": [[11, "module-syncify.remote.processors.wrangle"]], "unavailable (syncify.remote.processors.check.itemcheckresult attribute)": [[11, "syncify.remote.processors.check.ItemCheckResult.unavailable"]], "unavailable_uri_dummy (syncify.remote.processors.wrangle.remotedatawrangler property)": [[11, "syncify.remote.processors.wrangle.RemoteDataWrangler.unavailable_uri_dummy"]], "unmatched (syncify.remote.processors.search.itemsearchresult attribute)": [[11, "syncify.remote.processors.search.ItemSearchResult.unmatched"]], "use_cache (syncify.remote.processors.search.remoteitemsearcher attribute)": [[11, "syncify.remote.processors.search.RemoteItemSearcher.use_cache"]], "validate_id_type() (syncify.remote.processors.wrangle.remotedatawrangler class method)": [[11, "syncify.remote.processors.wrangle.RemoteDataWrangler.validate_id_type"]], "validate_item_type() (syncify.remote.processors.wrangle.remotedatawrangler class method)": [[11, "syncify.remote.processors.wrangle.RemoteDataWrangler.validate_item_type"]], "spotifyalbum (class in syncify.spotify.object)": [[12, "syncify.spotify.object.SpotifyAlbum"]], "spotifyartist (class in syncify.spotify.object)": [[12, "syncify.spotify.object.SpotifyArtist"]], "spotifycollection (class in syncify.spotify.object)": [[12, "syncify.spotify.object.SpotifyCollection"]], "spotifycollectionerror": [[12, "syncify.spotify.exception.SpotifyCollectionError"]], "spotifycollectionloader (class in syncify.spotify.object)": [[12, "syncify.spotify.object.SpotifyCollectionLoader"]], "spotifyerror": [[12, "syncify.spotify.exception.SpotifyError"]], "spotifyitem (class in syncify.spotify.base)": [[12, "syncify.spotify.base.SpotifyItem"]], "spotifyitemerror": [[12, "syncify.spotify.exception.SpotifyItemError"]], "spotifyitemwranglermixin (class in syncify.spotify.object)": [[12, "syncify.spotify.object.SpotifyItemWranglerMixin"]], "spotifylibrary (class in syncify.spotify.library)": [[12, "syncify.spotify.library.SpotifyLibrary"]], "spotifyobject (class in syncify.spotify.base)": [[12, "syncify.spotify.base.SpotifyObject"]], "spotifyobjectloadermixin (class in syncify.spotify.object)": [[12, "syncify.spotify.object.SpotifyObjectLoaderMixin"]], "spotifyobjectmixin (class in syncify.spotify.base)": [[12, "syncify.spotify.base.SpotifyObjectMixin"]], "spotifyplaylist (class in syncify.spotify.object)": [[12, "syncify.spotify.object.SpotifyPlaylist"]], "spotifytrack (class in syncify.spotify.object)": [[12, "syncify.spotify.object.SpotifyTrack"]], "album (syncify.spotify.object.spotifytrack property)": [[12, "syncify.spotify.object.SpotifyTrack.album"]], "album_artist (syncify.spotify.object.spotifyalbum property)": [[12, "syncify.spotify.object.SpotifyAlbum.album_artist"]], "album_artist (syncify.spotify.object.spotifytrack property)": [[12, "syncify.spotify.object.SpotifyTrack.album_artist"]], "albums (syncify.spotify.library.spotifylibrary property)": [[12, "syncify.spotify.library.SpotifyLibrary.albums"]], "albums (syncify.spotify.object.spotifyartist property)": [[12, "syncify.spotify.object.SpotifyArtist.albums"]], "api (syncify.spotify.base.spotifyitem attribute)": [[12, "syncify.spotify.base.SpotifyItem.api"]], "api (syncify.spotify.base.spotifyobject attribute)": [[12, "syncify.spotify.base.SpotifyObject.api"]], "api (syncify.spotify.base.spotifyobjectmixin attribute)": [[12, "syncify.spotify.base.SpotifyObjectMixin.api"]], "api (syncify.spotify.library.spotifylibrary property)": [[12, "syncify.spotify.library.SpotifyLibrary.api"]], "api (syncify.spotify.object.spotifycollectionloader attribute)": [[12, "syncify.spotify.object.SpotifyCollectionLoader.api"]], "api (syncify.spotify.object.spotifyitemwranglermixin attribute)": [[12, "syncify.spotify.object.SpotifyItemWranglerMixin.api"]], "api (syncify.spotify.object.spotifyobjectloadermixin attribute)": [[12, "syncify.spotify.object.SpotifyObjectLoaderMixin.api"]], "artist (syncify.spotify.object.spotifyalbum property)": [[12, "syncify.spotify.object.SpotifyAlbum.artist"]], "artist (syncify.spotify.object.spotifyartist property)": [[12, "syncify.spotify.object.SpotifyArtist.artist"]], "artist (syncify.spotify.object.spotifytrack property)": [[12, "syncify.spotify.object.SpotifyTrack.artist"]], "artists (syncify.spotify.library.spotifylibrary property)": [[12, "syncify.spotify.library.SpotifyLibrary.artists"]], "artists (syncify.spotify.object.spotifyalbum property)": [[12, "syncify.spotify.object.SpotifyAlbum.artists"]], "artists (syncify.spotify.object.spotifytrack property)": [[12, "syncify.spotify.object.SpotifyTrack.artists"]], "bpm (syncify.spotify.object.spotifytrack property)": [[12, "syncify.spotify.object.SpotifyTrack.bpm"]], "collaborative (syncify.spotify.object.spotifyplaylist property)": [[12, "syncify.spotify.object.SpotifyPlaylist.collaborative"]], "comments (syncify.spotify.object.spotifytrack property)": [[12, "syncify.spotify.object.SpotifyTrack.comments"]], "compilation (syncify.spotify.object.spotifyalbum property)": [[12, "syncify.spotify.object.SpotifyAlbum.compilation"]], "compilation (syncify.spotify.object.spotifytrack property)": [[12, "syncify.spotify.object.SpotifyTrack.compilation"]], "date_added (syncify.spotify.object.spotifyplaylist property)": [[12, "syncify.spotify.object.SpotifyPlaylist.date_added"]], "date_created (syncify.spotify.object.spotifyplaylist property)": [[12, "syncify.spotify.object.SpotifyPlaylist.date_created"]], "date_modified (syncify.spotify.object.spotifyplaylist property)": [[12, "syncify.spotify.object.SpotifyPlaylist.date_modified"]], "day (syncify.spotify.object.spotifyalbum property)": [[12, "syncify.spotify.object.SpotifyAlbum.day"]], "day (syncify.spotify.object.spotifytrack property)": [[12, "syncify.spotify.object.SpotifyTrack.day"]], "description (syncify.spotify.object.spotifyplaylist property)": [[12, "syncify.spotify.object.SpotifyPlaylist.description"]], "disc_number (syncify.spotify.object.spotifytrack property)": [[12, "syncify.spotify.object.SpotifyTrack.disc_number"]], "disc_total (syncify.spotify.object.spotifytrack property)": [[12, "syncify.spotify.object.SpotifyTrack.disc_total"]], "enrich_saved_albums() (syncify.spotify.library.spotifylibrary method)": [[12, "syncify.spotify.library.SpotifyLibrary.enrich_saved_albums"]], "enrich_saved_artists() (syncify.spotify.library.spotifylibrary method)": [[12, "syncify.spotify.library.SpotifyLibrary.enrich_saved_artists"]], "enrich_tracks() (syncify.spotify.library.spotifylibrary method)": [[12, "syncify.spotify.library.SpotifyLibrary.enrich_tracks"]], "exclude (syncify.spotify.library.spotifylibrary attribute)": [[12, "syncify.spotify.library.SpotifyLibrary.exclude"]], "followers (syncify.spotify.object.spotifyartist property)": [[12, "syncify.spotify.object.SpotifyArtist.followers"]], "followers (syncify.spotify.object.spotifyplaylist property)": [[12, "syncify.spotify.object.SpotifyPlaylist.followers"]], "genres (syncify.spotify.object.spotifyalbum property)": [[12, "syncify.spotify.object.SpotifyAlbum.genres"]], "genres (syncify.spotify.object.spotifyartist property)": [[12, "syncify.spotify.object.SpotifyArtist.genres"]], "genres (syncify.spotify.object.spotifytrack property)": [[12, "syncify.spotify.object.SpotifyTrack.genres"]], "has_image (syncify.spotify.object.spotifyalbum property)": [[12, "syncify.spotify.object.SpotifyAlbum.has_image"]], "has_image (syncify.spotify.object.spotifyplaylist property)": [[12, "syncify.spotify.object.SpotifyPlaylist.has_image"]], "has_image (syncify.spotify.object.spotifytrack property)": [[12, "syncify.spotify.object.SpotifyTrack.has_image"]], "has_uri (syncify.spotify.base.spotifyobject property)": [[12, "syncify.spotify.base.SpotifyObject.has_uri"]], "id (syncify.spotify.base.spotifyobject property)": [[12, "syncify.spotify.base.SpotifyObject.id"]], "image_links (syncify.spotify.object.spotifyalbum property)": [[12, "syncify.spotify.object.SpotifyAlbum.image_links"]], "image_links (syncify.spotify.object.spotifyartist property)": [[12, "syncify.spotify.object.SpotifyArtist.image_links"]], "image_links (syncify.spotify.object.spotifyplaylist property)": [[12, "syncify.spotify.object.SpotifyPlaylist.image_links"]], "image_links (syncify.spotify.object.spotifytrack property)": [[12, "syncify.spotify.object.SpotifyTrack.image_links"]], "include (syncify.spotify.library.spotifylibrary attribute)": [[12, "syncify.spotify.library.SpotifyLibrary.include"]], "items (syncify.spotify.object.spotifyartist property)": [[12, "syncify.spotify.object.SpotifyArtist.items"]], "key (syncify.spotify.object.spotifytrack property)": [[12, "syncify.spotify.object.SpotifyTrack.key"]], "length (syncify.spotify.object.spotifyalbum property)": [[12, "syncify.spotify.object.SpotifyAlbum.length"]], "length (syncify.spotify.object.spotifytrack property)": [[12, "syncify.spotify.object.SpotifyTrack.length"]], "load() (syncify.spotify.object.spotifyartist class method)": [[12, "syncify.spotify.object.SpotifyArtist.load"]], "load() (syncify.spotify.object.spotifycollectionloader class method)": [[12, "syncify.spotify.object.SpotifyCollectionLoader.load"]], "load() (syncify.spotify.object.spotifytrack class method)": [[12, "syncify.spotify.object.SpotifyTrack.load"]], "merge_playlists() (syncify.spotify.library.spotifylibrary method)": [[12, "syncify.spotify.library.SpotifyLibrary.merge_playlists"]], "month (syncify.spotify.object.spotifyalbum property)": [[12, "syncify.spotify.object.SpotifyAlbum.month"]], "month (syncify.spotify.object.spotifytrack property)": [[12, "syncify.spotify.object.SpotifyTrack.month"]], "name (syncify.spotify.object.spotifyalbum property)": [[12, "syncify.spotify.object.SpotifyAlbum.name"]], "name (syncify.spotify.object.spotifyartist property)": [[12, "syncify.spotify.object.SpotifyArtist.name"]], "name (syncify.spotify.object.spotifyplaylist property)": [[12, "syncify.spotify.object.SpotifyPlaylist.name"]], "name (syncify.spotify.object.spotifytrack property)": [[12, "syncify.spotify.object.SpotifyTrack.name"]], "owner_id (syncify.spotify.object.spotifyplaylist property)": [[12, "syncify.spotify.object.SpotifyPlaylist.owner_id"]], "owner_name (syncify.spotify.object.spotifyplaylist property)": [[12, "syncify.spotify.object.SpotifyPlaylist.owner_name"]], "playlists (syncify.spotify.library.spotifylibrary property)": [[12, "syncify.spotify.library.SpotifyLibrary.playlists"]], "public (syncify.spotify.object.spotifyplaylist property)": [[12, "syncify.spotify.object.SpotifyPlaylist.public"]], "rating (syncify.spotify.object.spotifyalbum property)": [[12, "syncify.spotify.object.SpotifyAlbum.rating"]], "rating (syncify.spotify.object.spotifyartist property)": [[12, "syncify.spotify.object.SpotifyArtist.rating"]], "rating (syncify.spotify.object.spotifytrack property)": [[12, "syncify.spotify.object.SpotifyTrack.rating"]], "refresh() (syncify.spotify.object.spotifyalbum method)": [[12, "syncify.spotify.object.SpotifyAlbum.refresh"]], "refresh() (syncify.spotify.object.spotifyartist method)": [[12, "syncify.spotify.object.SpotifyArtist.refresh"]], "refresh() (syncify.spotify.object.spotifyplaylist method)": [[12, "syncify.spotify.object.SpotifyPlaylist.refresh"]], "refresh() (syncify.spotify.object.spotifytrack method)": [[12, "syncify.spotify.object.SpotifyTrack.refresh"]], "reload() (syncify.spotify.object.spotifyalbum method)": [[12, "syncify.spotify.object.SpotifyAlbum.reload"]], "reload() (syncify.spotify.object.spotifyartist method)": [[12, "syncify.spotify.object.SpotifyArtist.reload"]], "reload() (syncify.spotify.object.spotifyplaylist method)": [[12, "syncify.spotify.object.SpotifyPlaylist.reload"]], "reload() (syncify.spotify.object.spotifytrack method)": [[12, "syncify.spotify.object.SpotifyTrack.reload"]], "syncify.spotify": [[12, "module-syncify.spotify"]], "syncify.spotify.base": [[12, "module-syncify.spotify.base"]], "syncify.spotify.config": [[12, "module-syncify.spotify.config"]], "syncify.spotify.exception": [[12, "module-syncify.spotify.exception"]], "syncify.spotify.library": [[12, "module-syncify.spotify.library"]], "syncify.spotify.object": [[12, "module-syncify.spotify.object"]], "title (syncify.spotify.object.spotifytrack property)": [[12, "syncify.spotify.object.SpotifyTrack.title"]], "track_number (syncify.spotify.object.spotifytrack property)": [[12, "syncify.spotify.object.SpotifyTrack.track_number"]], "track_total (syncify.spotify.object.spotifyalbum property)": [[12, "syncify.spotify.object.SpotifyAlbum.track_total"]], "track_total (syncify.spotify.object.spotifyplaylist property)": [[12, "syncify.spotify.object.SpotifyPlaylist.track_total"]], "track_total (syncify.spotify.object.spotifytrack property)": [[12, "syncify.spotify.object.SpotifyTrack.track_total"]], "tracks (syncify.spotify.object.spotifyalbum property)": [[12, "syncify.spotify.object.SpotifyAlbum.tracks"]], "tracks (syncify.spotify.object.spotifyplaylist property)": [[12, "syncify.spotify.object.SpotifyPlaylist.tracks"]], "uri (syncify.spotify.base.spotifyobject property)": [[12, "syncify.spotify.base.SpotifyObject.uri"]], "url (syncify.spotify.base.spotifyobject property)": [[12, "syncify.spotify.base.SpotifyObject.url"]], "url_ext (syncify.spotify.base.spotifyobject property)": [[12, "syncify.spotify.base.SpotifyObject.url_ext"]], "use_cache (syncify.spotify.library.spotifylibrary attribute)": [[12, "syncify.spotify.library.SpotifyLibrary.use_cache"]], "year (syncify.spotify.object.spotifyalbum property)": [[12, "syncify.spotify.object.SpotifyAlbum.year"]], "year (syncify.spotify.object.spotifytrack property)": [[12, "syncify.spotify.object.SpotifyTrack.year"]], "syncify.spotify.api": [[13, "module-syncify.spotify.api"]], "spotifydatawrangler (class in syncify.spotify.processors.wrangle)": [[14, "syncify.spotify.processors.wrangle.SpotifyDataWrangler"]], "spotifyitemchecker (class in syncify.spotify.processors.processors)": [[14, "syncify.spotify.processors.processors.SpotifyItemChecker"]], "spotifyitemsearcher (class in syncify.spotify.processors.processors)": [[14, "syncify.spotify.processors.processors.SpotifyItemSearcher"]], "allow_karaoke (syncify.spotify.processors.processors.spotifyitemchecker attribute)": [[14, "syncify.spotify.processors.processors.SpotifyItemChecker.allow_karaoke"]], "api (syncify.spotify.processors.processors.spotifyitemchecker attribute)": [[14, "syncify.spotify.processors.processors.SpotifyItemChecker.api"]], "api (syncify.spotify.processors.processors.spotifyitemsearcher attribute)": [[14, "syncify.spotify.processors.processors.SpotifyItemSearcher.api"]], "convert() (syncify.spotify.processors.wrangle.spotifydatawrangler class method)": [[14, "syncify.spotify.processors.wrangle.SpotifyDataWrangler.convert"]], "extract_ids() (syncify.spotify.processors.wrangle.spotifydatawrangler class method)": [[14, "syncify.spotify.processors.wrangle.SpotifyDataWrangler.extract_ids"]], "final_skipped (syncify.spotify.processors.processors.spotifyitemchecker attribute)": [[14, "syncify.spotify.processors.processors.SpotifyItemChecker.final_skipped"]], "final_switched (syncify.spotify.processors.processors.spotifyitemchecker attribute)": [[14, "syncify.spotify.processors.processors.SpotifyItemChecker.final_switched"]], "final_unavailable (syncify.spotify.processors.processors.spotifyitemchecker attribute)": [[14, "syncify.spotify.processors.processors.SpotifyItemChecker.final_unavailable"]], "get_id_type() (syncify.spotify.processors.wrangle.spotifydatawrangler static method)": [[14, "syncify.spotify.processors.wrangle.SpotifyDataWrangler.get_id_type"]], "interval (syncify.spotify.processors.processors.spotifyitemchecker attribute)": [[14, "syncify.spotify.processors.processors.SpotifyItemChecker.interval"]], "playlist_name_collection (syncify.spotify.processors.processors.spotifyitemchecker attribute)": [[14, "syncify.spotify.processors.processors.SpotifyItemChecker.playlist_name_collection"]], "playlist_name_urls (syncify.spotify.processors.processors.spotifyitemchecker attribute)": [[14, "syncify.spotify.processors.processors.SpotifyItemChecker.playlist_name_urls"]], "quit (syncify.spotify.processors.processors.spotifyitemchecker attribute)": [[14, "syncify.spotify.processors.processors.SpotifyItemChecker.quit"]], "remaining (syncify.spotify.processors.processors.spotifyitemchecker attribute)": [[14, "syncify.spotify.processors.processors.SpotifyItemChecker.remaining"]], "skip (syncify.spotify.processors.processors.spotifyitemchecker attribute)": [[14, "syncify.spotify.processors.processors.SpotifyItemChecker.skip"]], "switched (syncify.spotify.processors.processors.spotifyitemchecker attribute)": [[14, "syncify.spotify.processors.processors.SpotifyItemChecker.switched"]], "syncify.spotify.processors": [[14, "module-syncify.spotify.processors"]], "syncify.spotify.processors.processors": [[14, "module-syncify.spotify.processors.processors"]], "syncify.spotify.processors.wrangle": [[14, "module-syncify.spotify.processors.wrangle"]], "unavailable_uri_dummy (syncify.spotify.processors.wrangle.spotifydatawrangler attribute)": [[14, "syncify.spotify.processors.wrangle.SpotifyDataWrangler.unavailable_uri_dummy"]], "use_cache (syncify.spotify.processors.processors.spotifyitemsearcher attribute)": [[14, "syncify.spotify.processors.processors.SpotifyItemSearcher.use_cache"]], "validate_id_type() (syncify.spotify.processors.wrangle.spotifydatawrangler class method)": [[14, "syncify.spotify.processors.wrangle.SpotifyDataWrangler.validate_id_type"]], "currenttimerotatingfilehandler (class in syncify.utils.logger)": [[15, "syncify.utils.logger.CurrentTimeRotatingFileHandler"]], "logconsolefilter (class in syncify.utils.logger)": [[15, "syncify.utils.logger.LogConsoleFilter"]], "logfilefilter (class in syncify.utils.logger)": [[15, "syncify.utils.logger.LogFileFilter"]], "syncifylogger (class in syncify.utils.logger)": [[15, "syncify.utils.logger.SyncifyLogger"]], "align_and_truncate() (in module syncify.utils.helpers)": [[15, "syncify.utils.helpers.align_and_truncate"]], "compact (syncify.utils.logger.syncifylogger attribute)": [[15, "syncify.utils.logger.SyncifyLogger.compact"]], "correct_platform_separators() (in module syncify.utils.helpers)": [[15, "syncify.utils.helpers.correct_platform_separators"]], "file_paths (syncify.utils.logger.syncifylogger property)": [[15, "syncify.utils.logger.SyncifyLogger.file_paths"]], "filter() (syncify.utils.logger.logconsolefilter method)": [[15, "syncify.utils.logger.LogConsoleFilter.filter"]], "filter() (syncify.utils.logger.logfilefilter method)": [[15, "syncify.utils.logger.LogFileFilter.filter"]], "flatten_nested() (in module syncify.utils.helpers)": [[15, "syncify.utils.helpers.flatten_nested"]], "format_full_func_name() (in module syncify.utils.logger)": [[15, "syncify.utils.logger.format_full_func_name"]], "get_max_width() (in module syncify.utils.helpers)": [[15, "syncify.utils.helpers.get_max_width"]], "get_most_common_values() (in module syncify.utils.helpers)": [[15, "syncify.utils.helpers.get_most_common_values"]], "get_progress_bar() (syncify.utils.logger.syncifylogger method)": [[15, "syncify.utils.logger.SyncifyLogger.get_progress_bar"]], "get_user_input() (in module syncify.utils.helpers)": [[15, "syncify.utils.helpers.get_user_input"]], "info_extra() (syncify.utils.logger.syncifylogger method)": [[15, "syncify.utils.logger.SyncifyLogger.info_extra"]], "limit_value() (in module syncify.utils.helpers)": [[15, "syncify.utils.helpers.limit_value"]], "merge_maps() (in module syncify.utils.helpers)": [[15, "syncify.utils.helpers.merge_maps"]], "print() (syncify.utils.logger.syncifylogger method)": [[15, "syncify.utils.logger.SyncifyLogger.print"]], "print_line() (in module syncify.utils.printers)": [[15, "syncify.utils.printers.print_line"]], "print_logo() (in module syncify.utils.printers)": [[15, "syncify.utils.printers.print_logo"]], "print_time() (in module syncify.utils.printers)": [[15, "syncify.utils.printers.print_time"]], "report() (syncify.utils.logger.syncifylogger method)": [[15, "syncify.utils.logger.SyncifyLogger.report"]], "rotator() (syncify.utils.logger.currenttimerotatingfilehandler method)": [[15, "syncify.utils.logger.CurrentTimeRotatingFileHandler.rotator"]], "safe_format_map() (in module syncify.utils.helpers)": [[15, "syncify.utils.helpers.safe_format_map"]], "shouldrollover() (syncify.utils.logger.currenttimerotatingfilehandler static method)": [[15, "syncify.utils.logger.CurrentTimeRotatingFileHandler.shouldRollover"]], "stat() (syncify.utils.logger.syncifylogger method)": [[15, "syncify.utils.logger.SyncifyLogger.stat"]], "stdout_handlers (syncify.utils.logger.syncifylogger property)": [[15, "syncify.utils.logger.SyncifyLogger.stdout_handlers"]], "strip_ignore_words() (in module syncify.utils.helpers)": [[15, "syncify.utils.helpers.strip_ignore_words"]], "syncify.utils": [[15, "module-syncify.utils"]], "syncify.utils.helpers": [[15, "module-syncify.utils.helpers"]], "syncify.utils.logger": [[15, "module-syncify.utils.logger"]], "syncify.utils.printers": [[15, "module-syncify.utils.printers"]], "to_collection() (in module syncify.utils.helpers)": [[15, "syncify.utils.helpers.to_collection"]], "unique_list() (in module syncify.utils.helpers)": [[15, "syncify.utils.helpers.unique_list"]]}}) \ No newline at end of file diff --git a/_build/syncify.abstract.html b/_build/syncify.abstract.html new file mode 100644 index 00000000..f0fb788d --- /dev/null +++ b/_build/syncify.abstract.html @@ -0,0 +1,1612 @@ + + + + + + + + syncify.abstract package — Syncify 0.3 documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

syncify.abstract package

+
+

Submodules

+
+
+

syncify.abstract.collection module

+
+
+class syncify.abstract.collection.ItemCollection
+

Bases: NamedObjectPrinter, MutableSequence, Generic

+

Generic class for storing a collection of items.

+
+
Variables:
+

tag_sep – When representing a list of tags as a string, use this value as the separator.

+
+
+
+
+append(_ItemCollection__item: T, allow_duplicates: bool = True) None
+

Append one item to the items in this collection

+
+ +
+
+clear() None
+

Remove all items from this collection

+
+ +
+
+copy() list[T]
+

Return a shallow copy of the list of items in this collection

+
+ +
+
+count(_ItemCollection__item: T) int
+

Return the number of occurrences of the given Item in this collection

+
+ +
+
+extend(_ItemCollection__items: Iterable[T], allow_duplicates: bool = True) None
+

Append many items to the items in this collection

+
+ +
+
+index(_ItemCollection__item: T, _ItemCollection__start: SupportsIndex = None, _ItemCollection__stop: SupportsIndex = None) int
+

Return first index of item from items in this collection.

+
+
Raises:
+
    +
  • ValueError – If the value is not present.

  • +
  • SyncifyTypeError – If given item does not match the item type of this collection.

  • +
+
+
+
+ +
+
+insert(_ItemCollection__index: int, _ItemCollection__item: T, allow_duplicates: bool = True) None
+

Insert given Item before the given index

+
+ +
+
+abstract property items: list[T]
+

The items in this collection

+
+ +
+
+pop(_ItemCollection__item: SupportsIndex = None) T
+

Remove one item from the items in this collection and return it

+
+ +
+
+remove(_ItemCollection__item: T) None
+

Remove one item from the items in this collection

+
+ +
+
+reverse() None
+

Reverse the order of items in this collection in-place

+
+ +
+
+sort(fields: Field | None | Sequence[Field | None] | Mapping[Field | None, bool] = (), shuffle_mode: ShuffleMode = ShuffleMode.NONE, shuffle_by: ShuffleBy = ShuffleBy.TRACK, shuffle_weight: float = 1.0, key: Field | None = None, reverse: bool = False) None
+

Sort items in this collection in-place based on given conditions. +If key is given,

+
+
Parameters:
+
    +
  • fields

      +
    • When None and ShuffleMode is RANDOM, shuffle the tracks. Otherwise, do nothing.

    • +
    • List of tags/properties to sort by.

    • +
    • Map of {tag/property: reversed}. If reversed is true, sort the tag/property in reverse.

    • +
    +

  • +
  • shuffle_mode – The mode to use for shuffling.

  • +
  • shuffle_by – The field to shuffle by when shuffling.

  • +
  • shuffle_weight – The weights (between 0 and 1) to apply to shuffling modes that can use it. +This value will automatically be limited to within the accepted range 0 and 1.

  • +
  • key – Tag or property to sort on. Can be given instead of fields for a simple sort. +If set, all other fields apart from reverse are ignored. +If None, fields, shuffle_mode, shuffle_by, and shuffle_weight are used to apply sorting.

  • +
  • reverse – If true, reverse the order of the sort at the end.

  • +
+
+
+
+ +
+ +
+
+

syncify.abstract.enums module

+
+
+class syncify.abstract.enums.Field(value, names=None, *values, module=None, qualname=None, type=None, start=1, boundary=None)
+

Bases: SyncifyEnum

+

Base class for field names of an item.

+
+ +
+
+class syncify.abstract.enums.Fields(value, names=None, *values, module=None, qualname=None, type=None, start=1, boundary=None)
+

Bases: Field

+

Contains all possible Field enums in this program.

+

This is used to ensure all Field enum implementations have the same values for their enum names.

+
+
+ALBUM = 30
+
+ +
+
+ALBUM_ARTIST = 31
+
+ +
+
+ALL = 0
+
+ +
+
+ARTIST = 32
+
+ +
+
+BIT_DEPTH = 183
+
+ +
+
+BIT_RATE = 10
+
+ +
+
+BPM = 85
+
+ +
+
+CHANNELS = 8
+
+ +
+
+COMMENTS = 44
+
+ +
+
+COMPILATION = 904
+
+ +
+
+COMPOSER = 43
+
+ +
+
+CONDUCTOR = 45
+
+ +
+
+DATE = 900
+
+ +
+
+DATE_ADDED = 12
+
+ +
+
+DATE_CREATED = 921
+
+ +
+
+DATE_MODIFIED = 11
+
+ +
+
+DAY = 902
+
+ +
+
+DESCRIPTION = 931
+
+ +
+
+DISC_NUMBER = 52
+
+ +
+
+DISC_TOTAL = 54
+
+ +
+
+EXT = 100
+
+ +
+
+FILENAME = 52
+
+ +
+
+FOLDER = 179
+
+ +
+
+FOLLOWERS = 946
+
+ +
+
+GENRES = 59
+
+ +
+
+IMAGES = 905
+
+ +
+
+KEY = 903
+
+ +
+
+KIND = 4
+
+ +
+
+LAST_PLAYED = 13
+
+ +
+
+LENGTH = 16
+
+ +
+
+MONTH = 901
+
+ +
+
+NAME = 1000
+
+ +
+
+OWNER_ID = 944
+
+ +
+
+OWNER_NAME = 945
+
+ +
+
+PATH = 106
+
+ +
+
+PLAY_COUNT = 14
+
+ +
+
+PUBLISHER = 73
+
+ +
+
+RATING = 75
+
+ +
+
+SAMPLE_RATE = 9
+
+ +
+
+SIZE = 7
+
+ +
+
+TITLE = 65
+
+ +
+
+TRACK_NUMBER = 86
+
+ +
+
+TRACK_TOTAL = 87
+
+ +
+
+URI = 941
+
+ +
+
+USER_ID = 942
+
+ +
+
+USER_NAME = 943
+
+ +
+
+YEAR = 35
+
+ +
+ +
+
+class syncify.abstract.enums.SyncifyEnum(value, names=None, *values, module=None, qualname=None, type=None, start=1, boundary=None)
+

Bases: IntEnum

+

Generic class for storing IntEnums.

+
+
+classmethod all() list[Self]
+

Get all enums for this enum.

+
+ +
+
+classmethod from_name(*names: str, fail_on_many: bool = True) list[Self]
+

Returns all enums that match the given enum names

+
+
Parameters:
+

fail_on_many – If more than one enum is found, raise an exception.

+
+
Raises:
+

EnumNotFoundError – If a corresponding enum cannot be found.

+
+
+
+ +
+
+classmethod from_value(*values: int, fail_on_many: bool = True) list[Self]
+

Returns all enums that match the given enum values

+
+
Parameters:
+

fail_on_many – If more than one enum is found, raise an exception.

+
+
Raises:
+

EnumNotFoundError – If a corresponding enum cannot be found.

+
+
+
+ +
+
+classmethod map(enum: Self) list[Self]
+

“Optional mapper to apply to the enum found during all(), from_name(), +and from_value() calls

+
+ +
+ +
+
+class syncify.abstract.enums.TagField(value, names=None, *values, module=None, qualname=None, type=None, start=1, boundary=None)
+

Bases: Field

+

Applies extra functionality to the Field enum for Field types relating to Track types

+
+
+classmethod all(only_tags: bool = False) list[Self]
+

Get all enums for this enum. +When only_tags is True, returns only those enums that represent a tag for this TagField type.

+
+ +
+
+to_tag() set[str]
+

Returns all human-friendly tag names for the current enum value.

+

Applies mapper to enums before returning as per map(). +This will only return tag names if they are found in TagMap.

+
+ +
+
+classmethod to_tags(tags: Self | Iterable[Self]) set[str]
+

Returns all human-friendly tag names for the given enum value.

+

Applies mapper to enums before returning as per map(). +This will only return tag names if they are found in TagMap.

+
+ +
+ +
+
+class syncify.abstract.enums.TagFields(value, names=None, *values, module=None, qualname=None, type=None, start=1, boundary=None)
+

Bases: TagField

+

Contains all possible TagField enums in this program.

+

This is used to ensure all TagField enum implementations have the same values for their enum names.

+
+
+ALBUM = 30
+
+ +
+
+ALBUM_ARTIST = 31
+
+ +
+
+ALL = 0
+
+ +
+
+ARTIST = 32
+
+ +
+
+BIT_DEPTH = 183
+
+ +
+
+BIT_RATE = 10
+
+ +
+
+BPM = 85
+
+ +
+
+CHANNELS = 8
+
+ +
+
+COMMENTS = 44
+
+ +
+
+COMPILATION = 904
+
+ +
+
+COMPOSER = 43
+
+ +
+
+CONDUCTOR = 45
+
+ +
+
+DATE = 900
+
+ +
+
+DATE_ADDED = 12
+
+ +
+
+DATE_CREATED = 921
+
+ +
+
+DATE_MODIFIED = 11
+
+ +
+
+DAY = 902
+
+ +
+
+DESCRIPTION = 931
+
+ +
+
+DISC_NUMBER = 52
+
+ +
+
+DISC_TOTAL = 54
+
+ +
+
+EXT = 100
+
+ +
+
+FILENAME = 52
+
+ +
+
+FOLDER = 179
+
+ +
+
+FOLLOWERS = 946
+
+ +
+
+GENRES = 59
+
+ +
+
+IMAGES = 905
+
+ +
+
+KEY = 903
+
+ +
+
+KIND = 4
+
+ +
+
+LAST_PLAYED = 13
+
+ +
+
+LENGTH = 16
+
+ +
+
+MONTH = 901
+
+ +
+
+NAME = 1000
+
+ +
+
+OWNER_ID = 944
+
+ +
+
+OWNER_NAME = 945
+
+ +
+
+PATH = 106
+
+ +
+
+PLAY_COUNT = 14
+
+ +
+
+PUBLISHER = 73
+
+ +
+
+RATING = 75
+
+ +
+
+SAMPLE_RATE = 9
+
+ +
+
+SIZE = 7
+
+ +
+
+TITLE = 65
+
+ +
+
+TRACK_NUMBER = 86
+
+ +
+
+TRACK_TOTAL = 87
+
+ +
+
+URI = 941
+
+ +
+
+USER_ID = 942
+
+ +
+
+USER_NAME = 943
+
+ +
+
+YEAR = 35
+
+ +
+ +
+
+class syncify.abstract.enums.TagMap(title: Sequence[str] = (), artist: Sequence[str] = (), album: Sequence[str] = (), album_artist: Sequence[str] = (), track_number: Sequence[str] = (), track_total: Sequence[str] = (), genres: Sequence[str] = (), date: Sequence[str] = (), year: Sequence[str] = (), month: Sequence[str] = (), day: Sequence[str] = (), bpm: Sequence[str] = (), key: Sequence[str] = (), disc_number: Sequence[str] = (), disc_total: Sequence[str] = (), compilation: Sequence[str] = (), comments: Sequence[str] = (), images: Sequence[str] = ())
+

Bases: object

+

Map of human-friendly tag name to ID3 tag ids for a given file type

+
+
+album: Sequence[str] = ()
+
+ +
+
+album_artist: Sequence[str] = ()
+
+ +
+
+artist: Sequence[str] = ()
+
+ +
+
+bpm: Sequence[str] = ()
+
+ +
+
+comments: Sequence[str] = ()
+
+ +
+
+compilation: Sequence[str] = ()
+
+ +
+
+date: Sequence[str] = ()
+
+ +
+
+day: Sequence[str] = ()
+
+ +
+
+disc_number: Sequence[str] = ()
+
+ +
+
+disc_total: Sequence[str] = ()
+
+ +
+
+genres: Sequence[str] = ()
+
+ +
+
+images: Sequence[str] = ()
+
+ +
+
+key: Sequence[str] = ()
+
+ +
+
+month: Sequence[str] = ()
+
+ +
+
+title: Sequence[str] = ()
+
+ +
+
+track_number: Sequence[str] = ()
+
+ +
+
+track_total: Sequence[str] = ()
+
+ +
+
+year: Sequence[str] = ()
+
+ +
+ +
+
+

syncify.abstract.misc module

+
+
+class syncify.abstract.misc.Filter(*_, **__)
+

Bases: ABC, Collection, Generic

+

Base class for filtering down values based on some settings

+
+
+abstract process(values: Iterable) Collection
+

Filter down given values or stored available values that match this filter’s settings

+
+ +
+
+abstract property ready: bool
+

Does this filter have valid settings and can process values

+
+ +
+ +
+
+class syncify.abstract.misc.PrettyPrinter
+

Bases: ABC

+

Generic base class for pretty printing. Classes can inherit this class to gain pretty print functionality.

+
+
+abstract as_dict() dict[str, Any]
+

Return a dictionary representation of the key attributes of this object.

+
+
The results of this function are used to produce the following:
    +
  • A JSON representation of the object when calling json()

  • +
  • The string representation of the object when calling str() on the object

  • +
  • The representation of the object when calling repr() on the object

  • +
+
+
+
+ +
+
+json() dict[str, str | int | float | list | dict | bool | None]
+

Return a dictionary representation of the key attributes of this object that is safe to output to JSON

+
+ +
+ +
+
+class syncify.abstract.misc.Result
+

Bases: object

+

Stores the results of an operation within Syncify

+
+ +
+
+

syncify.abstract.object module

+
+
+class syncify.abstract.object.Album
+

Bases: ItemCollection, Generic

+

An album of items and some of their derived properties/objects.

+
+
Variables:
+

tag_sep – When representing a list of tags as a string, use this value as the separator.

+
+
+
+
+property album: str
+

The album name

+
+ +
+
+abstract property album_artist: str | None
+

The album artist for this album

+
+ +
+
+property artist: str
+

Joined string representation of all artists on this album ordered by frequency of appearance

+
+ +
+
+abstract property artists: list[str | Artist]
+

List of artists ordered by frequency of appearance on the tracks on this album

+
+ +
+
+abstract property compilation: bool
+

Is this album a compilation

+
+ +
+
+property date: date | None
+

A date object representing the release date of this album

+
+ +
+
+abstract property day: int | None
+

The day this album was released

+
+ +
+
+property disc_total: int | None
+

The highest value of disc number on this album

+
+ +
+
+abstract property genres: list[str]
+

List of genres ordered by frequency of appearance on the tracks on this album

+
+ +
+
+property has_image: bool
+

Does this album have an image

+
+ +
+ +

The images associated with this album in the form {image name: image link}

+
+ +
+
+property items
+

The tracks in this collection

+
+ +
+
+abstract property length: float | None
+

Total duration of all tracks on this album in seconds

+
+ +
+
+abstract property month: int | None
+

The month this album was released

+
+ +
+
+abstract property name: str
+

The album name

+
+ +
+
+abstract property rating: float | None
+

Rating of this album

+
+ +
+
+property track_total: int
+

The total number of tracks on this album

+
+ +
+
+abstract property tracks: list[T]
+

The tracks on this album

+
+ +
+
+abstract property year: int | None
+

The year this album was released

+
+ +
+ +
+
+class syncify.abstract.object.Artist
+

Bases: ItemCollection, Generic

+

An artist of items and some of their derived properties/objects

+
+
Variables:
+

tag_sep – When representing a list of tags as a string, use this value as the separator.

+
+
+
+
+abstract property albums: list[str | Album]
+

List of albums ordered by frequency of appearance on the tracks by this artist

+
+ +
+
+property artist: str
+

The artist name

+
+ +
+
+abstract property artists: list[str]
+

List of other artists ordered by frequency of appearance on the albums by this artist

+
+ +
+
+abstract property genres: list[str]
+

List of genres for this artist

+
+ +
+
+property items
+

The tracks in this collection

+
+ +
+
+abstract property length: float | None
+

Total duration of all tracks by this artist

+
+ +
+
+abstract property name
+

The artist name

+
+ +
+
+abstract property rating: int | None
+

The popularity of this artist

+
+ +
+
+property track_total: int
+

The total number of tracks by this artist

+
+ +
+
+abstract property tracks: list[T]
+

The tracks by this artist

+
+ +
+ +
+
+class syncify.abstract.object.BasicCollection(name: str, items: Collection[T])
+

Bases: ItemCollection, Generic

+

A basic implementation of ItemCollection for storing items with a given name.

+
+
Variables:
+

tag_sep – When representing a list of tags as a string, use this value as the separator.

+
+
Parameters:
+
    +
  • name – The name of this collection.

  • +
  • items – The items in this collection

  • +
+
+
+
+
+as_dict()
+

Return a dictionary representation of the key attributes of this object.

+
+
The results of this function are used to produce the following:
    +
  • A JSON representation of the object when calling json()

  • +
  • The string representation of the object when calling str() on the object

  • +
  • The representation of the object when calling repr() on the object

  • +
+
+
+
+ +
+
+property items: list[T]
+

The items in this collection

+
+ +
+
+property name
+

The name of this collection

+
+ +
+ +
+
+class syncify.abstract.object.Folder
+

Bases: ItemCollection, Generic

+

A folder of items and some of their derived properties/objects

+
+
Variables:
+

tag_sep – When representing a list of tags as a string, use this value as the separator.

+
+
+
+
+abstract property albums: list[str]
+

List of albums ordered by frequency of appearance on the tracks in this folder

+
+ +
+
+abstract property artists: list[str]
+

List of artists ordered by frequency of appearance on the tracks in this folder

+
+ +
+
+abstract property compilation: bool
+

Is this folder a compilation

+
+ +
+
+property folder: str
+

The folder name

+
+ +
+
+abstract property genres: list[str]
+

List of genres ordered by frequency of appearance on the tracks in this folder

+
+ +
+
+property items
+

The tracks in this collection

+
+ +
+
+abstract property length: float | None
+

Total duration of all tracks in this folder

+
+ +
+
+abstract property name
+

The folder name

+
+ +
+
+property track_total: int
+

The total number of tracks in this folder

+
+ +
+
+abstract property tracks
+

The tracks in this folder

+
+ +
+ +
+
+class syncify.abstract.object.Genre
+

Bases: ItemCollection, Generic

+

A genre of items and some of their derived properties/objects

+
+
Variables:
+

tag_sep – When representing a list of tags as a string, use this value as the separator.

+
+
+
+
+abstract property albums: list[str]
+

List of albums ordered by frequency of appearance on the tracks for this genre

+
+ +
+
+abstract property artists: list[str]
+

List of artists ordered by frequency of appearance on the tracks for this genre

+
+ +
+
+property genre: str
+

The genre

+
+ +
+
+abstract property genres: list[str]
+

List of genres ordered by frequency of appearance on the tracks for this genre

+
+ +
+
+property items
+

The tracks in this collection

+
+ +
+
+abstract property name
+

The genre

+
+ +
+
+abstract property tracks: list[T]
+

The tracks for this genre

+
+ +
+ +
+
+class syncify.abstract.object.Library
+

Bases: ItemCollection, Generic

+

A library of items and playlists

+
+
Variables:
+

tag_sep – When representing a list of tags as a string, use this value as the separator.

+
+
+
+
+get_filtered_playlists(include: Container[str] | Filter[str] | None = None, exclude: Container[str] | Filter[str] | None = None, **filter_tags: dict[str, tuple[str, ...]]) dict[str, Playlist]
+

Returns a filtered set of playlists in this library. +The playlists returned are deep copies of the playlists in the library.

+
+
Parameters:
+
    +
  • include – An optional list or Filter of playlist names to include.

  • +
  • exclude – An optional list or Filter of playlist names to exclude.

  • +
  • filter_tags – Provide optional kwargs of the tags and values of items to filter out of every playlist. +Parse a tag name as a parameter, any item matching the values given for this tag will be filtered out. +NOTE: Only string value types are currently supported.

  • +
+
+
Returns:
+

Filtered playlists.

+
+
+
+ +
+
+property items
+

The tracks in this collection

+
+ +
+
+abstract merge_playlists(playlists: Library | Collection[Playlist] | Mapping[Any, Playlist]) None
+

Merge playlists from given list/map/library to this library

+
+ +
+
+abstract property name
+

The library name

+
+ +
+
+abstract property playlists: dict[str, Playlist]
+

The playlists in this library

+
+ +
+
+property track_total: int
+

The total number of tracks in this library

+
+ +
+
+abstract property tracks
+

The tracks in this library

+
+ +
+ +
+
+class syncify.abstract.object.Playlist
+

Bases: ItemCollection, Generic

+

A playlist of items and some of their derived properties/objects.

+
+
+abstract property date_created: datetime | None
+

datetime object representing when the playlist was created

+
+ +
+
+abstract property date_modified: datetime | None
+

datetime object representing when the playlist was last modified

+
+ +
+
+abstract property description: str | None
+

Description of this playlist

+
+ +
+
+property has_image: bool
+

Does this playlist have an image

+
+ +
+ +

The images associated with this playlist in the form {image name: image link}

+
+ +
+
+property items
+

The tracks in this collection

+
+ +
+
+property length: float | None
+

Total duration of all tracks in this playlist in seconds

+
+ +
+
+abstract merge(playlist: Playlist) None
+

Merge tracks in this playlist with another playlist synchronising tracks between the two. +Only modifies this playlist.

+
+ +
+
+abstract property name
+

The name of this playlist

+
+ +
+
+property track_total: int
+

The total number of tracks in this playlist

+
+ +
+
+abstract property tracks
+

The tracks in this playlist

+
+ +
+ +
+
+class syncify.abstract.object.Track
+

Bases: Item

+

Metadata/tags associated with a track.

+
+
Variables:
+

tag_sep – When representing a list of tags as a string, use this value as the separator.

+
+
+
+
+abstract property album: str | None
+

The album this track is featured on

+
+ +
+
+abstract property album_artist: str | None
+

The artist of the album this track is featured on

+
+ +
+
+abstract property artist: str | None
+

Joined string representation of all artists featured on this track

+
+ +
+
+abstract property artists: list[str | Artist]
+

List of all artists featured on this track.

+
+ +
+
+abstract property bpm: float | None
+

The tempo of this track

+
+ +
+
+abstract property comments: list[str] | None
+

Comments associated with this track set by the user

+
+ +
+
+abstract property compilation: bool | None
+

Is the album this track is featured on a compilation

+
+ +
+
+property date: date | None
+

A date object representing the release date of this track

+
+ +
+
+abstract property day: int | None
+

The day this track was released

+
+ +
+
+abstract property disc_number: int | None
+

The number of the disc from the album this track is featured on

+
+ +
+
+abstract property disc_total: int | None
+

The total number the discs from the album this track is featured on

+
+ +
+
+abstract property genres: list[str] | None
+

List of genres associated with this track

+
+ +
+
+property has_image: bool
+

Does the album this track is associated with have an image

+
+ +
+ +

The images associated with the album this track is featured on in the form {image name: image link}

+
+ +
+
+abstract property key: str | None
+

The key of this track in alphabetical musical notation format

+
+ +
+
+abstract property length: float
+

Total duration of this track in seconds

+
+ +
+
+abstract property month: int | None
+

The month this track was released

+
+ +
+
+property name: str
+

This track’s title

+
+ +
+
+abstract property rating: float | None
+

The rating for this track

+
+ +
+
+abstract property title: str | None
+

This track’s title

+
+ +
+
+abstract property track_number: int | None
+

The position this track has on the album it is featured on

+
+ +
+
+abstract property track_total: int | None
+

The track number of tracks on the album this track is featured on

+
+ +
+
+abstract property year: int | None
+

The year this track was released

+
+ +
+ +
+
+

Module contents

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/_build/syncify.api.html b/_build/syncify.api.html new file mode 100644 index 00000000..a0ca33f5 --- /dev/null +++ b/_build/syncify.api.html @@ -0,0 +1,130 @@ + + + + + + + + syncify.api package — Syncify 0.3 documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

syncify.api package

+
+

Submodules

+
+
+

syncify.api.exception module

+
+
+exception syncify.api.exception.APIError(message: str | None = None, response: Response | None = None)
+

Bases: SyncifyError

+

Exception raised for API errors.

+
+
Parameters:
+
    +
  • message – Explanation of the error.

  • +
  • response – The Response related to the error.

  • +
+
+
+
+ +
+
+exception syncify.api.exception.RequestError(message: str | None = None, response: Response | None = None)
+

Bases: APIError

+

Exception raised for errors raised when making requests to an API.

+
+ +
+
+

Module contents

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/_build/syncify.html b/_build/syncify.html new file mode 100644 index 00000000..3577a21e --- /dev/null +++ b/_build/syncify.html @@ -0,0 +1,2551 @@ + + + + + + + + syncify package — Syncify 0.3 documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

syncify package

+
+

Subpackages

+
+ +
+
+
+

Submodules

+
+
+

syncify.config module

+
+
+class syncify.config.BaseConfig(settings: dict[Any, Any], key: Any | None = None)
+

Bases: PrettyPrinter

+

Base config section representing a config block from the file

+
+
+merge(other: Self | None, override: bool = False) None
+

Merge the currently stored config values with the config from a given other configured config object +When override is True, force overwrite any values in self with other.

+
+ +
+ +
+
+class syncify.config.Config(path: str = 'config.yml')
+

Bases: BaseConfig

+

Set up config and provide framework for initialising various objects +needed for the main functionality of the program from a given config file at path.

+

The following options are in place for configuration values:

+
    +
  • DEFAULT: When a value is not found, a default value will be used.

  • +
  • REQUIRED: The configuration will fail if this value is not given. Only applies when the key is called.

  • +
  • +
    OPTIONAL: This value does not need to be set and None will be set when this is the case.

    The configuration will not fail if this value is not given.

    +
    +
    +
  • +
+

Sub-configs have an override parameter that can be set using the override key in initial config block. +When override is True and config given, override loaded config from the file with values in config +only using loaded values when values are not present in given config. +When override is False and config given, loaded config takes priority +and given config values are only used when values are not present in the file. +By default, always keep the current settings.

+
+
Parameters:
+

path – Path of the config file to use. If relative path given, appends package root path.

+
+
+
+
+as_dict() dict[str, Any]
+

Return a dictionary representation of the key attributes of this object.

+
+
The results of this function are used to produce the following:
    +
  • A JSON representation of the object when calling json()

  • +
  • The string representation of the object when calling str() on the object

  • +
  • The representation of the object when calling repr() on the object

  • +
+
+
+
+ +
+
+load(key: str | None = None)
+

Load config from the config file at the given key respecting override rules.

+
+
Parameters:
+

key – The key to pull config from within the file. +Used as the parent key to use to pull the required configuration from the config file. +If not given, use the root values in the config file.

+
+
+
+ +
+
+load_log_config(path: str = 'logging.yml', name: str | None = None, *names: str) None
+

Load logging config from the JSON or YAML file at the given path using logging.config.dictConfig. +If relative path given, appends package root path.

+
+
Parameters:
+
    +
  • path – The path to the logger config

  • +
  • name – If the given name is a valid logger name in the config, +assign this logger’s config to the module root logger.

  • +
  • names – When given, also apply the config from name to loggers with these names.

  • +
+
+
+
+ +
+
+property output_folder: str
+

DEFAULT = ‘<package_root>/_data’ | The output folder for saving diagnostic data

+
+ +
+
+property pause: str | None
+

OPTIONAL | A message to display when pausing

+
+ +
+
+property reload: dict[str, tuple[str, ...]]
+

DEFAULT = <map of all libraries to empty tuples> | +The keys of libraries as found in either ‘local’ or ‘remote’ maps to reload +mapped to the types of data to reload for each library.

+
+ +
+ +
+
+class syncify.config.ConfigAPI(settings: dict[Any, Any])
+

Bases: BaseConfig

+

Set the settings for the remote API from a config file. +See Config for more documentation regarding operation.

+
+
Parameters:
+

settings – The loaded config from the config file.

+
+
+
+
+abstract property api: RemoteAPI
+

Set up and return a valid API session for this remote source type.

+
+ +
+
+as_dict() dict[str, Any]
+

Return a dictionary representation of the key attributes of this object.

+
+
The results of this function are used to produce the following:
    +
  • A JSON representation of the object when calling json()

  • +
  • The string representation of the object when calling str() on the object

  • +
  • The representation of the object when calling repr() on the object

  • +
+
+
+
+ +
+
+property cache_path: str
+

DEFAULT = ‘.api_cache’ | The path of the cache to use when using cached requests for the API

+
+ +
+
+property token_path: str
+

OPTIONAL | The client secret to use when authorising access to the API.

+
+ +
+
+property use_cache: bool
+

DEFAULT = True | When True, use requests cache where possible when making API calls. +When False, always make calls to the API, refreshing any cached data in the process.

+
+ +
+ +
+
+class syncify.config.ConfigFilter(settings: dict[Any, Any])
+

Bases: BaseConfig, Filter[str]

+

Set the settings for granular filtering from a config file. +See Config for more documentation regarding operation.

+
+
Parameters:
+

settings – The loaded config from the config file.

+
+
+
+
+class ConfigMatch(settings: dict[Any, Any], key: Any | None = None)
+

Bases: BaseConfig, Filter[str]

+

Set the settings for filter options from a config file. +See Config for more documentation regarding operation.

+
+
Parameters:
+
    +
  • settings – The loaded config from the config file.

  • +
  • key – The key to load filter options for. +Used as the parent key to use to pull the required configuration from the config file.

  • +
+
+
+
+
+as_dict() dict[str, Any]
+

Return a dictionary representation of the key attributes of this object.

+
+
The results of this function are used to produce the following:
    +
  • A JSON representation of the object when calling json()

  • +
  • The string representation of the object when calling str() on the object

  • +
  • The representation of the object when calling repr() on the object

  • +
+
+
+
+ +
+
+property match_all: bool
+

DEFAULT = False | When True, a value has to match all conditions +to be considered a match by the filter when processing.

+
+ +
+
+merge(other: Self | None, override: bool = False) None
+

Merge the currently stored config values with the config from a given other configured config object +When override is True, force overwrite any values in self with other.

+
+ +
+
+process(values: Iterable[T] | None = None) tuple[T, ...]
+

Returns all strings from values that match this filter’s settings

+
+ +
+
+property ready
+

Does this filter have valid settings and can process values

+
+ +
+
+property values: list[str] | None
+

DEFAULT = () | The filtered values. +Filters available values based on prefix, start, and stop as applicable. +available values are taken from the config if the config is a list of strings.

+
+ +
+ +
+
+as_dict() dict[str, Any]
+

Return a dictionary representation of the key attributes of this object.

+
+
The results of this function are used to produce the following:
    +
  • A JSON representation of the object when calling json()

  • +
  • The string representation of the object when calling str() on the object

  • +
  • The representation of the object when calling repr() on the object

  • +
+
+
+
+ +
+
+process(values: Iterable[T] | None = None) tuple[T, ...]
+

Filter down values that match this filter’s settings from

+
+ +
+
+property ready
+

Does this filter have valid settings and can process values

+
+ +
+ +
+
+class syncify.config.ConfigLibrary(settings: dict[Any, Any], key: Any | None = None)
+

Bases: BaseConfig

+

Set the settings for a library from a config file. +See Config for more documentation regarding operation.

+
+
Parameters:
+
    +
  • settings – The loaded config from the config file.

  • +
  • key – The key to load filter options for. +Used as the parent key to use to pull the required configuration from the config file.

  • +
+
+
+
+
+as_dict() dict[str, Any]
+

Return a dictionary representation of the key attributes of this object.

+
+
The results of this function are used to produce the following:
    +
  • A JSON representation of the object when calling json()

  • +
  • The string representation of the object when calling str() on the object

  • +
  • The representation of the object when calling repr() on the object

  • +
+
+
+
+ +
+
+property kind: str
+

The config identifier that gives the type of library being configured

+
+ +
+
+abstract property library: Library
+

An initialised library

+
+ +
+
+abstract property source: str
+

The name of the source currently being used for this library

+
+ +
+ +
+
+class syncify.config.ConfigLibraryDifferences(settings: dict[Any, Any])
+

Bases: ConfigReportBase

+

Set the settings for the library differences report from a config file. +See Config for more documentation regarding operation.

+
+
Parameters:
+

settings – The loaded config from the config file.

+
+
+
+ +
+
+class syncify.config.ConfigLocal(settings: dict[Any, Any])
+

Bases: ConfigLibrary

+

Set the settings for the local functionality of the program from a config file. +See Config for more documentation regarding operation.

+
+
Parameters:
+

settings – The loaded config from the config file.

+
+
+
+
+class ConfigUpdateTags(settings: dict[Any, Any])
+

Bases: BaseConfig

+

Set the settings for the playlists from a config file. +See Config for more documentation regarding operation.

+
+
Parameters:
+

settings – The loaded config from the config file.

+
+
+
+
+as_dict() dict[str, Any]
+

Return a dictionary representation of the key attributes of this object.

+
+
The results of this function are used to produce the following:
    +
  • A JSON representation of the object when calling json()

  • +
  • The string representation of the object when calling str() on the object

  • +
  • The representation of the object when calling repr() on the object

  • +
+
+
+
+ +
+
+property replace: bool
+

DEFAULT = False | Destructively replace tags in each file.

+
+ +
+
+property tags: tuple[LocalTrackField, ...]
+

DEFAULT = (<all LocalTrackFields>) | The tags to be updated.

+
+ +
+ +
+
+as_dict() dict[str, Any]
+

Return a dictionary representation of the key attributes of this object.

+
+
The results of this function are used to produce the following:
    +
  • A JSON representation of the object when calling json()

  • +
  • The string representation of the object when calling str() on the object

  • +
  • The representation of the object when calling repr() on the object

  • +
+
+
+
+ +
+
+property library: LocalLibrary
+

An initialised library

+
+ +
+
+property library_folder: str
+

REQUIRED | The path of the local library folder

+
+ +
+
+property other_folders: tuple[str, ...]
+

DEFAULT = () | The paths of other folder to use for replacement when processing local libraries

+
+ +
+
+property playlist_folder: str
+

DEFAULT = ‘Playlists’ | The path of the playlist folder.

+
+ +
+
+property remote_wrangler: RemoteDataWrangler
+

The remote wrangler to apply when initialising a library

+
+ +
+
+property source
+

The name of the source currently being used for this library

+
+ +
+ +
+
+class syncify.config.ConfigMissingTags(settings: dict[Any, Any])
+

Bases: ConfigReportBase

+

Set the settings for the missing tags report from a config file. +See Config for more documentation regarding operation.

+
+
Parameters:
+

settings – The loaded config from the config file.

+
+
+
+
+as_dict() dict[str, Any]
+

Return a dictionary representation of the key attributes of this object.

+
+
The results of this function are used to produce the following:
    +
  • A JSON representation of the object when calling json()

  • +
  • The string representation of the object when calling str() on the object

  • +
  • The representation of the object when calling repr() on the object

  • +
+
+
+
+ +
+
+property match_all: bool
+

DEFAULT = True | When True, consider a track as having missing tags only if it is missing all the given tags.

+
+ +
+
+property tags: tuple[LocalTrackField, ...]
+

DEFAULT = (<all LocalTrackFields>) | The tags to be updated.

+
+ +
+ +
+
+class syncify.config.ConfigMusicBee(settings: dict[Any, Any])
+

Bases: ConfigLocal

+

Set the settings for the local functionality of the program for a MusicBee from a config file. +See Config for more documentation regarding operation.

+
+
Parameters:
+

settings – The loaded config from the config file.

+
+
+
+
+as_dict() dict[str, Any]
+

Return a dictionary representation of the key attributes of this object.

+
+
The results of this function are used to produce the following:
    +
  • A JSON representation of the object when calling json()

  • +
  • The string representation of the object when calling str() on the object

  • +
  • The representation of the object when calling repr() on the object

  • +
+
+
+
+ +
+
+property library: MusicBee
+

An initialised library

+
+ +
+
+property musicbee_folder: str | None
+

OPTIONAL | The path of the MusicBee library folder.

+
+ +
+
+property source
+

The name of the source currently being used for this library

+
+ +
+ +
+
+class syncify.config.ConfigPlaylists(settings: dict[Any, Any])
+

Bases: ConfigFilter

+

Set the settings for the playlists from a config file. +See Config for more documentation regarding operation.

+
+
Parameters:
+

settings – The loaded config from the config file.

+
+
+
+ +
+
+class syncify.config.ConfigRemote(settings: dict[Any, Any])
+

Bases: ConfigLibrary

+

Set the settings for the remote functionality of the program from a config file. +See Config for more documentation regarding operation.

+
+
Parameters:
+

settings – The loaded config from the config file.

+
+
+
+
+class ConfigPlaylists(settings: dict[Any, Any])
+

Bases: ConfigPlaylists

+

Set the settings for processing remote playlists from a config file. +See Config for more documentation regarding operation.

+
+
Parameters:
+

settings – The loaded config from the config file.

+
+
+
+
+class ConfigPlaylistsSync(settings: dict[Any, Any])
+

Bases: BaseConfig

+

Set the settings for synchronising remote playlists from a config file. +See Config for more documentation regarding operation.

+
+
Parameters:
+

settings – The loaded config from the config file.

+
+
+
+
+as_dict() dict[str, Any]
+

Return a dictionary representation of the key attributes of this object.

+
+
The results of this function are used to produce the following:
    +
  • A JSON representation of the object when calling json()

  • +
  • The string representation of the object when calling str() on the object

  • +
  • The representation of the object when calling repr() on the object

  • +
+
+
+
+ +
+
+property filter: dict[str, tuple[str, ...]]
+

DEFAULT = {} | Tags and values of items to filter out of every playlist when synchronising

+
+ +
+
+property kind: str
+

DEFAULT = ‘new’ | Sync option for the remote playlist.

+
+ +
+
+merge(other: Self | None, override: bool = False) None
+

Merge the currently stored config values with the config from a given other configured config object +When override is True, force overwrite any values in self with other.

+
+ +
+
+property reload: bool
+

DEFAULT = True | Reload playlists after synchronisation.

+
+ +
+ +
+
+as_dict() dict[str, Any]
+

Return a dictionary representation of the key attributes of this object.

+
+
The results of this function are used to produce the following:
    +
  • A JSON representation of the object when calling json()

  • +
  • The string representation of the object when calling str() on the object

  • +
  • The representation of the object when calling repr() on the object

  • +
+
+
+
+ +
+ +
+
+as_dict() dict[str, Any]
+

Return a dictionary representation of the key attributes of this object.

+
+
The results of this function are used to produce the following:
    +
  • A JSON representation of the object when calling json()

  • +
  • The string representation of the object when calling str() on the object

  • +
  • The representation of the object when calling repr() on the object

  • +
+
+
+
+ +
+
+property checker: RemoteItemChecker
+

An initialised remote wrangler

+
+ +
+
+property library: RemoteLibrary
+

An initialised library

+
+ +
+
+property playlist: type[RemotePlaylist]
+

The RemotePlaylist class for this remote library type

+
+ +
+
+property searcher: RemoteItemSearcher
+

An initialised remote wrangler

+
+ +
+
+property source: str
+

The name of the source currently being used for this library

+
+ +
+
+property wrangler: RemoteDataWrangler
+

An initialised remote wrangler

+
+ +
+ +
+
+class syncify.config.ConfigReportBase(settings: dict[Any, Any], key: str)
+

Bases: BaseConfig

+

Base class for settings reports settings. +See Config for more documentation regarding operation.

+
+
Parameters:
+

settings – The loaded config from the config file.

+
+
+
+
+as_dict() dict[str, Any]
+

Return a dictionary representation of the key attributes of this object.

+
+
The results of this function are used to produce the following:
    +
  • A JSON representation of the object when calling json()

  • +
  • The string representation of the object when calling str() on the object

  • +
  • The representation of the object when calling repr() on the object

  • +
+
+
+
+ +
+ +
+
+class syncify.config.ConfigReports(settings: dict[Any, Any])
+

Bases: BaseConfig, Iterable[ConfigReportBase]

+

Set the settings for all reports from a config file. +See Config for more documentation regarding operation.

+
+
Parameters:
+

settings – The loaded config from the config file.

+
+
+
+
+as_dict() dict[str, Any]
+

Return a dictionary representation of the key attributes of this object.

+
+
The results of this function are used to produce the following:
    +
  • A JSON representation of the object when calling json()

  • +
  • The string representation of the object when calling str() on the object

  • +
  • The representation of the object when calling repr() on the object

  • +
+
+
+
+ +
+
+property enabled: bool
+

Are any reports configured enabled

+
+ +
+ +
+
+class syncify.config.ConfigSpotify(settings: dict[Any, Any])
+

Bases: ConfigAPI

+
+
+property api: SpotifyAPI
+

Set up and return a valid API session for this remote source type.

+
+ +
+
+as_dict() dict[str, Any]
+

Return a dictionary representation of the key attributes of this object.

+
+
The results of this function are used to produce the following:
    +
  • A JSON representation of the object when calling json()

  • +
  • The string representation of the object when calling str() on the object

  • +
  • The representation of the object when calling repr() on the object

  • +
+
+
+
+ +
+
+property client_id: str | None
+

OPTIONAL | The client ID to use when authorising access to the API.

+
+ +
+
+property client_secret: str | None
+

OPTIONAL | The client secret to use when authorising access to the API.

+
+ +
+
+property scopes: tuple[str, ...]
+

DEFAULT = () | The scopes to use when authorising access to the API.

+
+ +
+ +
+
+class syncify.config.RemoteClasses(source: str, api: type[ConfigAPI], wrangler: type[RemoteDataWrangler], object: type[RemoteObject], checker: type[RemoteItemChecker], searcher: type[RemoteItemSearcher], library: type[RemoteLibrary], playlist: type[RemotePlaylist])
+

Bases: object

+

Stores the key classes for a remote source

+
+
+api: type[ConfigAPI]
+
+ +
+
+checker: type[RemoteItemChecker]
+
+ +
+
+library: type[RemoteLibrary]
+
+ +
+
+object: type[RemoteObject]
+
+ +
+
+playlist: type[RemotePlaylist]
+
+ +
+
+searcher: type[RemoteItemSearcher]
+
+ +
+
+source: str
+
+ +
+
+wrangler: type[RemoteDataWrangler]
+
+ +
+ +
+
+

syncify.exception module

+
+
+exception syncify.exception.ConfigError(message: str = 'Could not process config', key: Any | None = None, value: Any | None = None)
+

Bases: SyncifyError

+

Exception raised when processing config gives an exception.

+
+
Parameters:
+
    +
  • key – The key that caused the error.

  • +
  • value – The value that caused the error.

  • +
  • message – Explanation of the error.

  • +
+
+
+
+ +
+
+class syncify.exception.SafeDict
+

Bases: dict

+

Extends dict to ignore missing keys when using format_map operations

+
+ +
+
+exception syncify.exception.SyncifyAttributeError
+

Bases: SyncifyError, AttributeError

+

Exception raised for invalid attributes.

+
+ +
+
+exception syncify.exception.SyncifyEnumError(value: Any, message: str = 'Could not find enum')
+

Bases: SyncifyError

+

Exception raised when searching enums gives an exception.

+
+
Parameters:
+
    +
  • value – The value that caused the error.

  • +
  • message – Explanation of the error.

  • +
+
+
+
+ +
+
+exception syncify.exception.SyncifyError
+

Bases: Exception

+

Generic base class for all Syncify-related errors

+
+ +
+
+exception syncify.exception.SyncifyKeyError
+

Bases: SyncifyError, KeyError

+

Exception raised for invalid keys.

+
+ +
+
+exception syncify.exception.SyncifyTypeError(kind: Any, message: str = 'Invalid item type given')
+

Bases: SyncifyError, TypeError

+

Exception raised for invalid item types.

+
+ +
+
+exception syncify.exception.SyncifyValueError
+

Bases: SyncifyError, ValueError

+

Exception raised for invalid values.

+
+ +
+
+

syncify.fields module

+
+
+class syncify.fields.AlbumField(value, names=None, *values, module=None, qualname=None, type=None, start=1, boundary=None)
+

Bases: Field

+
+
+ALBUM = 30
+
+ +
+
+ALBUM_ARTIST = 31
+
+ +
+
+ALL = 0
+
+ +
+
+ARTIST = 32
+
+ +
+
+COMPILATION = 904
+
+ +
+
+DATE = 900
+
+ +
+
+DAY = 902
+
+ +
+
+DISC_TOTAL = 54
+
+ +
+
+GENRES = 59
+
+ +
+
+IMAGES = 905
+
+ +
+
+LENGTH = 16
+
+ +
+
+MONTH = 901
+
+ +
+
+RATING = 75
+
+ +
+
+TRACK_TOTAL = 87
+
+ +
+
+YEAR = 35
+
+ +
+ +
+
+class syncify.fields.ArtistField(value, names=None, *values, module=None, qualname=None, type=None, start=1, boundary=None)
+

Bases: Field

+
+
+ALL = 0
+
+ +
+
+ARTIST = 32
+
+ +
+
+GENRES = 59
+
+ +
+
+IMAGES = 905
+
+ +
+
+LENGTH = 16
+
+ +
+
+RATING = 75
+
+ +
+
+TRACK_TOTAL = 87
+
+ +
+ +
+
+class syncify.fields.FolderField(value, names=None, *values, module=None, qualname=None, type=None, start=1, boundary=None)
+

Bases: Field

+
+
+ALL = 0
+
+ +
+
+COMPILATION = 904
+
+ +
+
+FOLDER = 179
+
+ +
+
+GENRES = 59
+
+ +
+
+IMAGES = 905
+
+ +
+
+LENGTH = 16
+
+ +
+
+TRACK_TOTAL = 87
+
+ +
+ +
+
+class syncify.fields.LocalTrackField(value, names=None, *values, module=None, qualname=None, type=None, start=1, boundary=None)
+

Bases: TrackFieldMixin

+

Represent all currently supported fields for objects of type LocalTrack

+
+
+ALBUM = 30
+
+ +
+
+ALBUM_ARTIST = 31
+
+ +
+
+ALL = 0
+
+ +
+
+ARTIST = 32
+
+ +
+
+BIT_DEPTH = 183
+
+ +
+
+BIT_RATE = 10
+
+ +
+
+BPM = 85
+
+ +
+
+CHANNELS = 8
+
+ +
+
+COMMENTS = 44
+
+ +
+
+COMPILATION = 904
+
+ +
+
+DATE = 900
+
+ +
+
+DATE_ADDED = 12
+
+ +
+
+DATE_MODIFIED = 11
+
+ +
+
+DAY = 902
+
+ +
+
+DISC = 552
+
+ +
+
+DISC_NUMBER = 52
+
+ +
+
+DISC_TOTAL = 54
+
+ +
+
+EXT = 100
+
+ +
+
+FILENAME = 52
+
+ +
+
+FOLDER = 179
+
+ +
+
+GENRES = 59
+
+ +
+
+IMAGES = 905
+
+ +
+
+KEY = 903
+
+ +
+
+KIND = 4
+
+ +
+
+LAST_PLAYED = 13
+
+ +
+
+LENGTH = 16
+
+ +
+
+MONTH = 901
+
+ +
+
+PATH = 106
+
+ +
+
+PLAY_COUNT = 14
+
+ +
+
+RATING = 75
+
+ +
+
+SAMPLE_RATE = 9
+
+ +
+
+SIZE = 7
+
+ +
+
+TITLE = 65
+
+ +
+
+TRACK = 586
+
+ +
+
+TRACK_NUMBER = 86
+
+ +
+
+TRACK_TOTAL = 87
+
+ +
+
+URI = 941
+
+ +
+
+YEAR = 35
+
+ +
+ +
+
+class syncify.fields.PlaylistField(value, names=None, *values, module=None, qualname=None, type=None, start=1, boundary=None)
+

Bases: Field

+
+
+ALL = 0
+
+ +
+
+DATE_CREATED = 921
+
+ +
+
+DATE_MODIFIED = 11
+
+ +
+
+DESCRIPTION = 931
+
+ +
+
+IMAGES = 905
+
+ +
+
+LENGTH = 16
+
+ +
+
+TRACK_TOTAL = 87
+
+ +
+ +
+
+class syncify.fields.TrackField(value, names=None, *values, module=None, qualname=None, type=None, start=1, boundary=None)
+

Bases: TrackFieldMixin

+

Represent all currently supported fields for objects of type Track

+
+
+ALBUM = 30
+
+ +
+
+ALBUM_ARTIST = 31
+
+ +
+
+ALL = 0
+
+ +
+
+ARTIST = 32
+
+ +
+
+BPM = 85
+
+ +
+
+COMMENTS = 44
+
+ +
+
+COMPILATION = 904
+
+ +
+
+DISC = 552
+
+ +
+
+DISC_NUMBER = 52
+
+ +
+
+DISC_TOTAL = 54
+
+ +
+
+GENRES = 59
+
+ +
+
+IMAGES = 905
+
+ +
+
+KEY = 903
+
+ +
+
+LENGTH = 16
+
+ +
+
+RATING = 75
+
+ +
+
+TITLE = 65
+
+ +
+
+TRACK = 586
+
+ +
+
+TRACK_NUMBER = 86
+
+ +
+
+TRACK_TOTAL = 87
+
+ +
+
+URI = 941
+
+ +
+
+YEAR = 35
+
+ +
+ +
+
+class syncify.fields.TrackFieldMixin(value, names=None, *values, module=None, qualname=None, type=None, start=1, boundary=None)
+

Bases: TagField

+

Applies extra functionality to the TagField enum for TagField types relating to Track types

+
+
+classmethod map(enum: Self) list[Self]
+

Mapper to apply to the enum found during from_name() and from_value() calls, +or from to_tag() and to_tags() calls

+

Applies the following mapping:

+
    +
  • TRACK returns both TRACK_NUMBER and TRACK_TOTAL enums

  • +
  • DISC returns both DISC_NUMBER and DISC_TOTAL enums

  • +
  • all other enums return the enum in a unit list

  • +
+
+ +
+ +
+
+

syncify.report module

+
+
+syncify.report.report_missing_tags(collections: LocalLibrary | Iterable[ItemCollection], tags: TagField | Iterable[TagField] = TagFields.ALL, match_all: bool = False) dict[str, dict[Item, tuple[str, ...]]]
+

Generate a report on the items with a set of collections that have missing tags.

+
+
Parameters:
+
    +
  • collections – A collection of item collections to report on. +If a local library is given, use the albums of the library as the collections to report on.

  • +
  • tags – List of tags to consider missing.

  • +
  • match_all – When True, item counts as missing tags if item is missing all of the given tags. +When False, item counts as missing tags when missing only one of the given tags.

  • +
+
+
Returns:
+

Report on collections by name which have items with missing tags.

+
+
+
+ +
+
+syncify.report.report_playlist_differences(source: Library | Iterable[Playlist], reference: Library | Iterable[Playlist]) dict[str, dict[str, tuple[Item, ...]]]
+

Generate a report on the differences between two library’s playlists.

+
+
Parameters:
+
    +
  • source – A source library object containing the source playlists, or a collection of playlists .

  • +
  • reference – A comparative library object or collection of playlists +containing the playlists to compare to the source’s playlists.

  • +
+
+
Returns:
+

Report on extra, missing, and unavailable tracks for the reference library.

+
+
+
+ +
+
+

Module contents

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/_build/syncify.local.html b/_build/syncify.local.html new file mode 100644 index 00000000..b66372b0 --- /dev/null +++ b/_build/syncify.local.html @@ -0,0 +1,763 @@ + + + + + + + + syncify.local package — Syncify 0.3 documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

syncify.local package

+
+

Subpackages

+ +
+
+

Submodules

+
+
+

syncify.local.collection module

+
+
+class syncify.local.collection.LocalAlbum(tracks: Collection[LocalTrack], name: str | None = None, remote_wrangler: RemoteDataWrangler = None)
+

Bases: LocalCollectionFiltered[LocalTrack], Album[LocalTrack]

+

Object representing a collection of tracks of an album.

+
+
Variables:
+

tag_sep – When representing a list of tags as a string, use this value as the separator.

+
+
Parameters:
+
    +
  • tracks – A list of loaded tracks.

  • +
  • name – The name of this album. +If given, the object only stores tracks that match the album name given. +If None, the list of tracks given are taken to be all the tracks for this album.

  • +
  • remote_wrangler – Optionally, provide a RemoteDataWrangler object for processing URIs on tracks. +If given, the wrangler can be used when calling __get_item__ to get an item from the collection from its URI.

  • +
+
+
Raises:
+

LocalCollectionError – If the given tracks contain more than one unique value for +album when name is None.

+
+
+
+
+property album_artist
+

The most common artist on this album

+
+ +
+
+as_dict()
+

Return a dictionary representation of the key attributes of this object.

+
+
The results of this function are used to produce the following:
    +
  • A JSON representation of the object when calling json()

  • +
  • The string representation of the object when calling str() on the object

  • +
  • The representation of the object when calling repr() on the object

  • +
+
+
+
+ +
+
+property compilation
+

Album is a compilation if over 50% of tracks are marked as compilation

+
+ +
+
+property date
+

A date object representing the release date of this album. +Determined by the most common release date of all tracks on this album.

+
+ +
+
+property day
+

The most common release day of all tracks on this album

+
+ +
+
+property has_image
+

Does this album have an image

+
+ +
+ +

The images associated with this album in the form {image name: image link}

+
+ +
+
+logger: SyncifyLogger
+
+ +
+
+property month
+

The most common release month of all tracks on this album

+
+ +
+
+property rating
+

Average rating of all tracks on this album

+
+ +
+
+remote_wrangler
+
+ +
+
+property year
+

The most common release year of all tracks on this album

+
+ +
+ +
+
+class syncify.local.collection.LocalArtist(tracks: Collection[LocalTrack], name: str | None = None, remote_wrangler: RemoteDataWrangler = None)
+

Bases: LocalCollectionFiltered[LocalTrack], Artist[LocalTrack]

+

Object representing a collection of tracks by a single artist.

+
+
Variables:
+

tag_sep – When representing a list of tags as a string, use this value as the separator.

+
+
Parameters:
+
    +
  • tracks – A list of loaded tracks.

  • +
  • name – The name of this artist. +If given, the object only stores tracks that match the artist name given. +If None, the list of tracks given are taken to be all the tracks by this artist.

  • +
  • remote_wrangler – Optionally, provide a RemoteDataWrangler object for processing URIs on tracks. +If given, the wrangler can be used when calling __get_item__ to get an item from the collection from its URI.

  • +
+
+
Raises:
+

LocalCollectionError – If the given tracks contain more than one unique value for +artist when name is None.

+
+
+
+
+property albums
+

List of albums ordered by frequency of appearance on the tracks by this artist

+
+ +
+
+as_dict()
+

Return a dictionary representation of the key attributes of this object.

+
+
The results of this function are used to produce the following:
    +
  • A JSON representation of the object when calling json()

  • +
  • The string representation of the object when calling str() on the object

  • +
  • The representation of the object when calling repr() on the object

  • +
+
+
+
+ +
+
+logger: SyncifyLogger
+
+ +
+
+property rating
+

Average rating of all tracks by this artist

+
+ +
+
+remote_wrangler
+
+ +
+ +
+
+class syncify.local.collection.LocalCollection(remote_wrangler: RemoteDataWrangler = None)
+

Bases: ItemCollection, Generic

+

Generic class for storing a collection of local tracks.

+
+
Variables:
+

tag_sep – When representing a list of tags as a string, use this value as the separator.

+
+
Parameters:
+

remote_wrangler – Optionally, provide a RemoteDataWrangler object for processing URIs on items. +If given, the wrangler can be used when calling __get_item__ to get an item from the collection from its URI.

+
+
+
+
+property artists: list[str]
+

List of artists ordered by frequency of appearance on the tracks in this collection

+
+ +
+
+as_dict()
+

Return a dictionary representation of the key attributes of this object.

+
+
The results of this function are used to produce the following:
    +
  • A JSON representation of the object when calling json()

  • +
  • The string representation of the object when calling str() on the object

  • +
  • The representation of the object when calling repr() on the object

  • +
+
+
+
+ +
+
+property genres: list[str]
+

List of genres ordered by frequency of appearance on the tracks in this collection

+
+ +
+
+property items: list[LocalTrack]
+

The tracks in this collection

+
+ +
+
+property last_added: datetime | None
+

Timestamp of the track last added to the library in this collection

+
+ +
+
+property last_modified: datetime
+

Timestamp of the last modified track in this collection

+
+ +
+
+property last_played: datetime | None
+

Timestamp of the last played track in this collection

+
+ +
+
+property length: float | None
+

Total duration of all tracks in this collection in seconds

+
+ +
+
+log_sync_result(results: Mapping[LocalTrack, SyncResultTrack]) None
+

Log stats from the results of a save_tracks operation

+
+ +
+
+logger: SyncifyLogger
+
+ +
+
+merge_tracks(tracks: Collection[Track], tags: TagField | Iterable[TagField] = Fields.ALL) None
+

Merge this collection with another collection or list of items +by performing an inner join on a given set of tags

+
+
Parameters:
+
    +
  • tracks – List of items or ItemCollection to merge with

  • +
  • tags – List of tags to merge on.

  • +
+
+
+
+ +
+
+property play_count: int
+

Total number of plays of all tracks in this collection

+
+ +
+
+remote_wrangler
+
+ +
+
+save_tracks(tags: LocalTrackField | Iterable[LocalTrackField] = LocalTrackField.ALL, replace: bool = False, dry_run: bool = True) dict[LocalTrack, SyncResultTrack]
+

Saves the tags of all tracks in this collection. Use arguments from LocalTrack.save()

+
+
Parameters:
+
    +
  • tags – Tags to be updated.

  • +
  • replace – Destructively replace tags in each file.

  • +
  • dry_run – Run function, but do not modify file at all.

  • +
+
+
Returns:
+

A map of the LocalTrack saved to its result as a SyncResultTrack object

+
+
+
+ +
+
+property track_paths: set[str]
+

Set of all unique track paths in this collection

+
+ +
+
+property track_total: int
+

The total number of tracks in this collection

+
+ +
+
+abstract property tracks: list[LocalTrack]
+

The tracks in this collection

+
+ +
+ +
+
+class syncify.local.collection.LocalCollectionFiltered(tracks: Collection[LocalTrack], name: str | None = None, remote_wrangler: RemoteDataWrangler = None)
+

Bases: LocalCollection, Generic

+

Generic class for storing and filtering on a collection of local tracks +with methods for enriching the attributes of this object from the attributes of the collection of tracks

+
+
Variables:
+

tag_sep – When representing a list of tags as a string, use this value as the separator.

+
+
Parameters:
+
    +
  • tracks – A list of loaded tracks.

  • +
  • name – The name of this collection. +If given, the object only stores tracks that match the name given on the attribute of this object. +If None, the list of tracks given are taken to be all the tracks contained in this collection.

  • +
  • remote_wrangler – Optionally, provide a RemoteDataWrangler object for processing URIs on tracks. +If given, the wrangler can be used when calling __get_item__ to get an item from the collection from its URI.

  • +
+
+
Raises:
+

LocalCollectionError – If the given tracks contain more than one unique value +for the attribute of this collection when name is None.

+
+
+
+
+logger: SyncifyLogger
+
+ +
+
+property name
+

The name of the key property of this collection

+
+ +
+
+remote_wrangler
+
+ +
+
+property tracks
+

The tracks in this collection

+
+ +
+ +
+
+class syncify.local.collection.LocalFolder(tracks: Collection[LocalTrack] = (), name: str | None = None, remote_wrangler: RemoteDataWrangler = None)
+

Bases: LocalCollectionFiltered[LocalTrack], Folder[LocalTrack]

+

Object representing a collection of tracks in a folder on the local drive

+
+
Variables:
+

tag_sep – When representing a list of tags as a string, use this value as the separator.

+
+
Parameters:
+
    +
  • tracks – A list of loaded tracks.

  • +
  • name – The name of this folder. +If given, the object only stores tracks that match the folder name given. +If None, the list of tracks given are taken to be all the tracks contained in this folder.

  • +
  • remote_wrangler – Optionally, provide a RemoteDataWrangler object for processing URIs on tracks. +If given, the wrangler can be used when calling __get_item__ to get an item from the collection from its URI.

  • +
+
+
Raises:
+

LocalCollectionError – If the given tracks contain more than one unique value for +folder when name is None.

+
+
+
+
+property albums
+

List of albums ordered by frequency of appearance on the tracks in this folder

+
+ +
+
+as_dict()
+

Return a dictionary representation of the key attributes of this object.

+
+
The results of this function are used to produce the following:
    +
  • A JSON representation of the object when calling json()

  • +
  • The string representation of the object when calling str() on the object

  • +
  • The representation of the object when calling repr() on the object

  • +
+
+
+
+ +
+
+property compilation
+

Folder is a compilation if over 50% of tracks are marked as compilation

+
+ +
+
+logger: SyncifyLogger
+
+ +
+
+remote_wrangler
+
+ +
+
+set_compilation_tags() None
+

Modify tags for tracks in the folders of this library.

+

The following steps are applied to all non-compilation folders:

+
    +
  • Set compilation to False

  • +
+

The following steps are applied to all compilation folders:

+
    +
  • Set album name to folder name

  • +
  • Set album artist to ‘Various’

  • +
  • Set track_number in ascending order by filename

  • +
  • Set track_total to the number of tracks in the folder

  • +
  • Set disc_number to 1

  • +
  • Set disc_total to 1

  • +
  • Set compilation to True

  • +
+
+ +
+ +
+
+class syncify.local.collection.LocalGenres(tracks: Collection[LocalTrack], name: str | None = None, remote_wrangler: RemoteDataWrangler = None)
+

Bases: LocalCollectionFiltered[LocalTrack], Genre[LocalTrack]

+

Object representing a collection of tracks within a genre.

+
+
Variables:
+

tag_sep – When representing a list of tags as a string, use this value as the separator.

+
+
Parameters:
+
    +
  • tracks – A list of loaded tracks.

  • +
  • name – The name of this genre. +If given, the object only stores tracks that match the genre name given. +If None, the list of tracks given are taken to be all the tracks within this genre.

  • +
  • remote_wrangler – Optionally, provide a RemoteDataWrangler object for processing URIs on tracks. +If given, the wrangler can be used when calling __get_item__ to get an item from the collection from its URI.

  • +
+
+
Raises:
+

LocalCollectionError – If the given tracks contain more than one unique value for +genre when name is None.

+
+
+
+
+property albums
+

List of albums ordered by frequency of appearance on the tracks for this genre

+
+ +
+
+as_dict()
+

Return a dictionary representation of the key attributes of this object.

+
+
The results of this function are used to produce the following:
    +
  • A JSON representation of the object when calling json()

  • +
  • The string representation of the object when calling str() on the object

  • +
  • The representation of the object when calling repr() on the object

  • +
+
+
+
+ +
+
+logger: SyncifyLogger
+
+ +
+
+remote_wrangler
+
+ +
+ +
+
+

syncify.local.exception module

+
+
+exception syncify.local.exception.FieldError(message: str | None = None, field: Any | None = None)
+

Bases: MusicBeeError

+

Exception raised for errors related to MusicBee field.

+
+
Parameters:
+

message – Explanation of the error.

+
+
+
+ +
+
+exception syncify.local.exception.FileDoesNotExistError(path: str, message: str = 'File cannot be found')
+

Bases: FileError, FileNotFoundError

+

Exception raised when a file cannot be found.

+
+
Parameters:
+
    +
  • path – The path that caused the error.

  • +
  • message – Explanation of the error.

  • +
+
+
+
+ +
+
+exception syncify.local.exception.FileError(file: str | None = None, message: str | None = None)
+

Bases: LocalError

+

Exception raised for file errors.

+
+
Parameters:
+
    +
  • file – The file type that caused the error.

  • +
  • message – Explanation of the error.

  • +
+
+
+
+ +
+
+exception syncify.local.exception.ImageLoadError(file: str | None = None, message: str | None = None)
+

Bases: FileError

+

Exception raised for errors in loading an image.

+
+ +
+
+exception syncify.local.exception.InvalidFileType(filetype: str, message: str = 'File type not recognised')
+

Bases: FileError

+

Exception raised for unrecognised file types.

+
+
Parameters:
+
    +
  • filetype – The file type that caused the error.

  • +
  • message – Explanation of the error.

  • +
+
+
+
+ +
+
+exception syncify.local.exception.LocalCollectionError(message: str | None = None, kind: str | None = None)
+

Bases: LocalError

+

Exception raised for local collection errors.

+
+
Parameters:
+
    +
  • message – Explanation of the error.

  • +
  • kind – The collection type related to the error.

  • +
+
+
+
+ +
+
+exception syncify.local.exception.LocalError(message: str | None = None)
+

Bases: SyncifyError

+

Exception raised for local errors.

+
+
Parameters:
+

message – Explanation of the error.

+
+
+
+ +
+
+exception syncify.local.exception.LocalItemError(message: str | None = None, kind: str | None = None)
+

Bases: LocalError

+

Exception raised for local item errors.

+
+
Parameters:
+
    +
  • message – Explanation of the error.

  • +
  • kind – The item type related to the error.

  • +
+
+
+
+ +
+
+exception syncify.local.exception.LocalProcessorError(message: str | None = None)
+

Bases: LocalError

+

Exception raised for errors related to track processors.

+
+ +
+
+exception syncify.local.exception.MusicBeeError(message: str | None = None)
+

Bases: LocalError

+

Exception raised for errors related to MusicBee logic.

+
+ +
+
+exception syncify.local.exception.MusicBeeIDError(message: str | None = None)
+

Bases: MusicBeeError

+

Exception raised for errors related to MusicBee a persistent ID.

+
+ +
+
+exception syncify.local.exception.XMLReaderError(message: str | None = None)
+

Bases: MusicBeeError

+

Exception raised for errors related to reading a MusicBee library XML file.

+
+ +
+
+

Module contents

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/_build/syncify.local.library.html b/_build/syncify.local.library.html new file mode 100644 index 00000000..4acdc1ca --- /dev/null +++ b/_build/syncify.local.library.html @@ -0,0 +1,102 @@ + + + + + + + + syncify.local.library package — Syncify 0.3 documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

syncify.local.library package

+
+

Module contents

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/_build/syncify.local.playlist.html b/_build/syncify.local.playlist.html new file mode 100644 index 00000000..46ce8f7f --- /dev/null +++ b/_build/syncify.local.playlist.html @@ -0,0 +1,102 @@ + + + + + + + + syncify.local.playlist package — Syncify 0.3 documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

syncify.local.playlist package

+
+

Module contents

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/_build/syncify.local.track.html b/_build/syncify.local.track.html new file mode 100644 index 00000000..199e74e6 --- /dev/null +++ b/_build/syncify.local.track.html @@ -0,0 +1,102 @@ + + + + + + + + syncify.local.track package — Syncify 0.3 documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

syncify.local.track package

+
+

Module contents

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/_build/syncify.processors.html b/_build/syncify.processors.html new file mode 100644 index 00000000..7ca411b8 --- /dev/null +++ b/_build/syncify.processors.html @@ -0,0 +1,947 @@ + + + + + + + + syncify.processors package — Syncify 0.3 documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

syncify.processors package

+
+

Submodules

+
+
+

syncify.processors.base module

+
+
+class syncify.processors.base.DynamicProcessor(*_, **__)
+

Bases: Processor

+

Base class for implementations with :py:function:`dynamicprocessormethod` methods.

+

Classes that implement this base class have a __processormethods__ class attribute +which is a list of strings of all the processor methods this class contains. +If a :py:function:`dynamicprocessormethod` has alternative method names, these names will be added +to the class’ __dict__ as callable methods which point to the decorated method.

+

Optionally, you may also define a _processor_method_fmt class method which +applies some transformation to all method names. +The transformed method name is then appended to the class’ __dict__. +The transformation is always applied before extending the class with any given +alternative method names.

+
+
Variables:
+

__processormethods__ – The set of processor methods on this processor and any alternative names for them.

+
+
+
+
+property processor_methods: frozenset[str]
+

String representation of the current processor name of this object

+
+ +
+ +
+
+class syncify.processors.base.ItemProcessor
+

Bases: Processor, PrettyPrinter

+

Base object for processing tracks in a playlist

+
+ +
+
+class syncify.processors.base.MusicBeeProcessor
+

Bases: ItemProcessor

+
+
+abstract classmethod from_xml(xml: Mapping[str, Any], **kwargs) Self
+

Initialise object from XML playlist data.

+
+
Parameters:
+

xml – The loaded XML object for this playlist.

+
+
+
+ +
+
+abstract to_xml(**kwargs) Mapping[str, Any]
+

Export this object’s settings to a map ready for export to an XML playlist file.

+
+ +
+ +
+
+class syncify.processors.base.Processor
+

Bases: object

+

Generic base class for processors

+
+ +
+
+class syncify.processors.base.dynamicprocessormethod(*args, **__)
+

Bases: object

+

Decorator for methods on a class decorated with the processor() decorator

+

This assigns the method a processor method which can be dynamically called by the processor class. +Optionally, provide a list of alternative names from which this processor method can also be called.

+
+ +
+
+

syncify.processors.compare module

+
+
+class syncify.processors.compare.Comparer(*_, **__)
+

Bases: MusicBeeProcessor, DynamicProcessor

+

Compares an item or object with another item, object or a given set of expected values to find a match.

+
+
Parameters:
+
    +
  • condition – The condition to match on e.g. Is, LessThan, InRange, Contains.

  • +
  • expected – Optional list of expected values to match on. +Types of the values in this list are automatically converted to the type of the item field’s value.

  • +
  • field – The field to match on.

  • +
+
+
+
+
+as_dict()
+

Return a dictionary representation of the key attributes of this object.

+
+
The results of this function are used to produce the following:
    +
  • A JSON representation of the object when calling json()

  • +
  • The string representation of the object when calling str() on the object

  • +
  • The representation of the object when calling repr() on the object

  • +
+
+
+
+ +
+
+compare(item: T, reference: T | None = None) bool
+

Compare a item to a reference or, +if no reference is given, to this object’s list of expected values

+
+
Returns:
+

True if a match is found, False otherwise.

+
+
Raises:
+

LocalProcessorError – If no reference given and no expected values set for this comparer.

+
+
+
+ +
+
+property condition: str
+

String representation of the current condition name of this object

+
+ +
+
+property expected: list[Any] | None
+

A list of expected values used for most conditions

+
+ +
+
+field: Field | None
+
+ +
+
+classmethod from_xml(xml: Mapping[str, Any], **__) list[Self]
+

Initialise object from XML playlist data.

+
+
Parameters:
+

xml – The loaded XML object for this playlist.

+
+
+
+ +
+
+to_xml(**kwargs) Mapping[str, Any]
+

Export this object’s settings to a map ready for export to an XML playlist file.

+
+ +
+ +
+
+

syncify.processors.exception module

+
+
+exception syncify.processors.exception.ItemComparerError
+

Bases: ItemProcessorError

+

Exception raised for errors related to item comparer settings.

+
+ +
+
+exception syncify.processors.exception.ItemLimiterError
+

Bases: ItemProcessorError

+

Exception raised for errors related to item limit settings.

+
+ +
+
+exception syncify.processors.exception.ItemMatcherError
+

Bases: ItemProcessorError

+

Exception raised for errors related to item matcher settings.

+
+ +
+
+exception syncify.processors.exception.ItemProcessorError
+

Bases: ProcessorError

+

Exception raised for errors related to ItemProcessor logic.

+
+ +
+
+exception syncify.processors.exception.ItemSorterError
+

Bases: ItemProcessorError

+

Exception raised for errors related to item sorter settings.

+
+ +
+
+exception syncify.processors.exception.ProcessorError
+

Bases: SyncifyError

+

Exception raised for errors related to processors.

+
+ +
+
+exception syncify.processors.exception.ProcessorLookupError
+

Bases: ProcessorError

+

Exception raised when processor name given is not valid.

+
+ +
+
+exception syncify.processors.exception.TimeMapperError
+

Bases: ProcessorError

+

Exception raised for errors related to TimeMapper.

+
+ +
+
+

syncify.processors.limit module

+
+
+class syncify.processors.limit.ItemLimiter(*_, **__)
+

Bases: MusicBeeProcessor, DynamicProcessor

+

Sort items in-place based on given conditions.

+
+
Parameters:
+
    +
  • limit – The number of items to limit to. A value of 0 applies no limiting.

  • +
  • on – The type to limit on e.g. items, albums, minutes.

  • +
  • sorted_by – When limiting, sort the collection of items by this function first.

  • +
  • allowance – When limiting on bytes or length, add this extra allowance factor to +the max size limit on comparison. +e.g. say the limiter currently has 29 minutes worth of songs in its final list and the max limit is 30 minutes. +The limiter has to now consider whether to include the next song it sees with length 3 minutes. +With an allowance of 0, this song will not be added. +However, with an allowance of say 1.33 it will as the max limit for this comparison becomes 30 * 1.33 = 40. +Now, with 32 minutes worth of songs in the final playlist, the limit is >30 minutes and the limiter stops +processing.

  • +
+
+
+
+
+allowance
+
+ +
+
+as_dict()
+

Return a dictionary representation of the key attributes of this object.

+
+
The results of this function are used to produce the following:
    +
  • A JSON representation of the object when calling json()

  • +
  • The string representation of the object when calling str() on the object

  • +
  • The representation of the object when calling repr() on the object

  • +
+
+
+
+ +
+
+classmethod from_xml(xml: Mapping[str, Any], **__) Self | None
+

Initialise object from XML playlist data.

+
+
Parameters:
+

xml – The loaded XML object for this playlist.

+
+
+
+ +
+
+kind
+
+ +
+
+limit(items: list[T], ignore: Collection = ()) None
+

Limit items in-place based on set conditions.

+
+
Parameters:
+
    +
  • items – The list of items to limit.

  • +
  • ignore – list of items to ignore when limiting. i.e. keep them in the list regardless.

  • +
+
+
+
+ +
+
+limit_max
+
+ +
+
+property limit_sort: str | None
+

String representation of the sorting method to use before limiting

+
+ +
+
+to_xml(**kwargs) Mapping[str, Any]
+

Export this object’s settings to a map ready for export to an XML playlist file.

+
+ +
+ +
+
+class syncify.processors.limit.LimitType(value, names=None, *values, module=None, qualname=None, type=None, start=1, boundary=None)
+

Bases: SyncifyEnum

+

Represents the possible limit types to apply when filtering a playlist.

+
+
+ALBUMS = 1
+
+ +
+
+BYTES = 20
+
+ +
+
+DAYS = 14
+
+ +
+
+GIGABYTES = 23
+
+ +
+
+HOURS = 13
+
+ +
+
+ITEMS = 0
+
+ +
+
+KILOBYTES = 21
+
+ +
+
+MEGABYTES = 22
+
+ +
+
+MINUTES = 12
+
+ +
+
+SECONDS = 11
+
+ +
+
+TERABYTES = 24
+
+ +
+
+WEEKS = 15
+
+ +
+ +
+
+

syncify.processors.match module

+
+
+class syncify.processors.match.CleanTagConfig(tag: TagField, _remove: set[str] | None = None, _split: set[str] | None = None, _preprocess: Callable[[str], str] = None)
+

Bases: PrettyPrinter

+

Config for processing string-type tag values before matching with ItemMatcher

+
+
Variables:
+
    +
  • tag – The name of the tag to clean.

  • +
  • _remove – A set of string values to remove from this tag.

  • +
  • _split – A set of string values for which the cleaner will +slice the tag on and remove anything that comes after.

  • +
  • _preprocess – A function to apply before the _remove and _split values are applied.

  • +
+
+
+
+
+as_dict() dict[str, Any]
+

Return a dictionary representation of the key attributes of this object.

+
+
The results of this function are used to produce the following:
    +
  • A JSON representation of the object when calling json()

  • +
  • The string representation of the object when calling str() on the object

  • +
  • The representation of the object when calling repr() on the object

  • +
+
+
+
+ +
+
+preprocess(value: str) str
+

Apply the preprocess function to value if given, return value unprocessed if not

+
+ +
+
+property remove: set[str]
+

Get all redundant words to be removed for this tag

+
+ +
+
+property split: set[str]
+

Get all split words for which the cleaner will only take words before this word

+
+ +
+
+tag: TagField
+
+ +
+ +
+
+class syncify.processors.match.ItemMatcher
+

Bases: ItemProcessor

+

Matches source items/collections to given result(s).

+
+
Variables:
+
    +
  • karaoke_tags – A set of words to search for in tag values that identify the item as being a karaoke item.

  • +
  • year_range – A difference in years of this value gives a score of 0 for the match_year() algorithm. +See the match_year() method for more information.

  • +
  • clean_tags_remove_all – Apply these remove settings to all tags +when processing tags as per clean_tags() method. +See also CleanTagConfig for more info on this configuration.

  • +
  • clean_tags_split_all – Apply these split settings to all tags +when processing tags as per clean_tags() method. +See also CleanTagConfig for more info on this configuration.

  • +
  • clean_tags_config – A list of configurations in the form of CleanTagConfig +to apply for each tag type. See also CleanTagConfig for more info.

  • +
  • reduce_name_score_on – A set of words to check for when applying name score reduction logic. +If a word from this list is present in the name of the result to score against +but not in the source Item, reduce the score for the name match by +the _reduce_name_score_factor. +This set is always combined with the karaoke_tags.

  • +
  • reduce_name_score_factor – The factor to reduce a name score on when a word from +_reduce_name_score_on is found in the result but not in the source Item.

  • +
+
+
+
+
+as_dict() dict[str, Any]
+

Return a dictionary representation of the key attributes of this object.

+
+
The results of this function are used to produce the following:
    +
  • A JSON representation of the object when calling json()

  • +
  • The string representation of the object when calling str() on the object

  • +
  • The representation of the object when calling repr() on the object

  • +
+
+
+
+ +
+
+clean_tags(source: NamedObject) None
+

Clean tags on the input item and assign to its clean_tags attribute. Used for better matching/searching. +Clean by removing words, and only taking phrases before a certain word e.g. ‘featuring’, ‘part’. +Cleaning config for string-type tags is set in _clean_tags_config.

+
+
Parameters:
+

source – The base object with tags to clean.

+
+
+
+ +
+
+clean_tags_config = (CleanTagConfig(tag=<TagFields.TITLE: 65>, _remove={'part'}, _split={'feat.', 'ft.', '/', 'featuring'}, _preprocess=None), CleanTagConfig(tag=<TagFields.ARTIST: 32>, _remove=None, _split={'feat.', 'vs', 'ft.', 'featuring'}, _preprocess=None), CleanTagConfig(tag=<TagFields.ALBUM: 30>, _remove={'ep'}, _split=None, _preprocess=<function ItemMatcher.<lambda>>))
+
+ +
+
+clean_tags_remove_all = {'&', 'a', 'and', 'the'}
+
+ +
+
+clean_tags_split_all = {}
+
+ +
+
+karaoke_tags = {'backing', 'instrumental', 'karaoke'}
+
+ +
+
+logger: SyncifyLogger
+
+ +
+
+match(source: T, results: Iterable, min_score: float = 0.1, max_score: float = 0.8, match_on: TagField | Iterable[TagField] = frozenset({TagFields.KIND, TagFields.SIZE, TagFields.CHANNELS, TagFields.SAMPLE_RATE, TagFields.BIT_RATE, TagFields.DATE_MODIFIED, TagFields.DATE_ADDED, TagFields.LAST_PLAYED, TagFields.PLAY_COUNT, TagFields.LENGTH, TagFields.ALBUM, TagFields.ALBUM_ARTIST, TagFields.ARTIST, TagFields.YEAR, TagFields.COMPOSER, TagFields.COMMENTS, TagFields.CONDUCTOR, TagFields.DISC_NUMBER, TagFields.DISC_TOTAL, TagFields.GENRES, TagFields.TITLE, TagFields.PUBLISHER, TagFields.RATING, TagFields.BPM, TagFields.TRACK_NUMBER, TagFields.TRACK_TOTAL, TagFields.EXT, TagFields.PATH, TagFields.FOLDER, TagFields.BIT_DEPTH, TagFields.DATE, TagFields.MONTH, TagFields.DAY, TagFields.KEY, TagFields.COMPILATION, TagFields.IMAGES, TagFields.DATE_CREATED, TagFields.DESCRIPTION, TagFields.URI, TagFields.USER_ID, TagFields.USER_NAME, TagFields.OWNER_ID, TagFields.OWNER_NAME, TagFields.FOLLOWERS, TagFields.NAME}), allow_karaoke: bool = False) T | None
+

Perform match algorithm for a given item and its results.

+
+
Parameters:
+
    +
  • source – Source item to compare against and find a match for.

  • +
  • results – Results for comparisons.

  • +
  • min_score – Only return the result as a match if the score is above this value. +Value will be limited to between 0.01 and 1.0.

  • +
  • max_score – Stop matching once this score has been reached. +Value will be limited to between 0.01 and 1.0.

  • +
  • match_on – List of tags to match on. Currently only the following fields are supported: +title, artist, album, year, length.

  • +
  • allow_karaoke – When True, items determined to be karaoke are allowed when matching added items. +Skip karaoke results otherwise. Karaoke items are identified using the karaoke_tags attribute.

  • +
+
+
Returns:
+

    +
  1. The item that matched best if found, None if no item matched conditions.

  2. +
+

+
+
+
+ +
+
+match_album(source: T, result: T) float
+

Match on album and return a score between 0-1. Score=0 when either value is None.

+
+ +
+
+match_artist(source: T, result: T) float
+

Match on artists and return a score between 0-1. Score=0 when either value is None. +When many artists are present, a scale factor is applied to the score of matches on subsequent artists. +i.e. match on artist 1 is scaled by 1, match on artist 2 is scaled by 1/2, +match on artist 3 is scaled by 1/3 etc.

+
+ +
+
+match_length(source: T, result: T) float
+

Match on length and return a score between 0-1. Score=0 when either value is None.

+
+ +
+
+match_name(source: T, result: T) float
+

Match on names and return a score between 0-1. Score=0 when either value is None.

+
+ +
+
+match_not_karaoke(source: T, result: T) int
+

Checks if a result is not a karaoke item that is either 0 when item is karaoke or 1 when not karaoke.

+
+ +
+
+match_year(source: T, result: T) float
+

Match on year and return a score between 0-1. Score=0 when either value is None. +Matches within year_range years on a 0-1 scale where 1 is the exact same year +and 0 is a difference in year greater that year_range. +User may modify this max range via the year_range class attribute.

+
+ +
+
+reduce_name_score_factor = 0.5
+
+ +
+
+reduce_name_score_on = {'acoustic', 'demo', 'live'}
+
+ +
+
+year_range = 10
+
+ +
+ +
+
+

syncify.processors.sort module

+
+
+class syncify.processors.sort.ItemSorter(fields: Field | None | Sequence[Field | None] | Mapping[Field | None, bool] = (), shuffle_mode: ShuffleMode = ShuffleMode.NONE, shuffle_by: ShuffleBy = ShuffleBy.TRACK, shuffle_weight: float = 1.0)
+

Bases: MusicBeeProcessor

+

Sort items in-place based on given conditions.

+
+
Variables:
+

_custom_sort – Settings for custom sort codes.

+
+
Parameters:
+
    +
  • fields

      +
    • When None and ShuffleMode is RANDOM, shuffle the items. Otherwise, do nothing.

    • +
    • List of tags/properties to sort by.

    • +
    • Map of {tag/property: reversed}. If reversed is true, sort the tag/property in reverse.

    • +
    +

  • +
  • shuffle_mode – The mode to use for shuffling.

  • +
  • shuffle_by – The field to shuffle by when shuffling.

  • +
  • shuffle_weight – The weights (between 0 and 1) to apply to shuffling modes that can use it. +This value will automatically be limited to within the accepted range 0 and 1.

  • +
+
+
+
+
+as_dict()
+

Return a dictionary representation of the key attributes of this object.

+
+
The results of this function are used to produce the following:
    +
  • A JSON representation of the object when calling json()

  • +
  • The string representation of the object when calling str() on the object

  • +
  • The representation of the object when calling repr() on the object

  • +
+
+
+
+ +
+
+classmethod from_xml(xml: Mapping[str, Any], **__) Self
+

Initialise object from XML playlist data.

+
+
Parameters:
+

xml – The loaded XML object for this playlist.

+
+
+
+ +
+
+classmethod group_by_field(items: T | Iterable, field: Field | None = None) dict[Any, list[T]]
+

Group items by the values of a given field.

+
+
Parameters:
+
    +
  • items – List of items to sort.

  • +
  • field – Tag or property to group by. None returns map of {None: items}.

  • +
+
+
Returns:
+

Map of grouped items.

+
+
+
+ +
+
+shuffle_by: ShuffleBy | None
+
+ +
+
+shuffle_mode: ShuffleMode | None
+
+ +
+
+shuffle_weight
+
+ +
+
+sort(items: MutableSequence[Item]) None
+

Sorts a list of items in-place.

+
+ +
+
+classmethod sort_by_field(items: list[Item], field: Field | None = None, reverse: bool = False) None
+

Sort items by the values of a given field.

+
+
Parameters:
+
    +
  • items – List of items to sort

  • +
  • field – Tag or property to sort on. If None and reverse is True, reverse the order of the list.

  • +
  • reverse – If true, reverse the order of the sort.

  • +
+
+
+
+ +
+
+sort_fields: Mapping[Field | None, bool]
+
+ +
+
+to_xml(**kwargs) Mapping[str, Any]
+

Export this object’s settings to a map ready for export to an XML playlist file.

+
+ +
+ +
+
+class syncify.processors.sort.ShuffleBy(value, names=None, *values, module=None, qualname=None, type=None, start=1, boundary=None)
+

Bases: SyncifyEnum

+

Represents the possible items/properties to shuffle by when shuffling items in a playlist.

+
+
+ALBUM = 1
+
+ +
+
+ARTIST = 2
+
+ +
+
+TRACK = 0
+
+ +
+ +
+
+class syncify.processors.sort.ShuffleMode(value, names=None, *values, module=None, qualname=None, type=None, start=1, boundary=None)
+

Bases: SyncifyEnum

+

Represents the possible shuffle modes to use when shuffling items in a playlist.

+
+
+DIFFERENT_ARTIST = 3
+
+ +
+
+HIGHER_RATING = 2
+
+ +
+
+NONE = 0
+
+ +
+
+RANDOM = 1
+
+ +
+
+RECENT_ADDED = 3
+
+ +
+ +
+
+

syncify.processors.time module

+
+
+class syncify.processors.time.TimeMapper(*_, **__)
+

Bases: DynamicProcessor, PrettyPrinter

+

Map of time character representation to it unit conversion from seconds

+
+
+as_dict() dict[str, Any]
+

Return a dictionary representation of the key attributes of this object.

+
+
The results of this function are used to produce the following:
    +
  • A JSON representation of the object when calling json()

  • +
  • The string representation of the object when calling str() on the object

  • +
  • The representation of the object when calling repr() on the object

  • +
+
+
+
+ +
+
+days(*args, **kwargs)
+

Call self as a function.

+
+ +
+
+hours(*args, **kwargs)
+

Call self as a function.

+
+ +
+
+map(value: Any)
+

Run the mapping function

+
+ +
+
+minutes(*args, **kwargs)
+

Call self as a function.

+
+ +
+
+months(*args, **kwargs)
+

Call self as a function.

+
+ +
+
+seconds(*args, **kwargs)
+

Call self as a function.

+
+ +
+
+weeks(*args, **kwargs)
+

Call self as a function.

+
+ +
+ +
+
+

Module contents

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/_build/syncify.remote.html b/_build/syncify.remote.html new file mode 100644 index 00000000..4741a111 --- /dev/null +++ b/_build/syncify.remote.html @@ -0,0 +1,1404 @@ + + + + + + + + syncify.remote package — Syncify 0.3 documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

syncify.remote package

+
+

Subpackages

+
+ +
+
+
+

Submodules

+
+
+

syncify.remote.api module

+
+
+class syncify.remote.api.RemoteAPI(**handler_kwargs)
+

Bases: RemoteDataWrangler

+

Collection of endpoints for a remote API. +See RequestHandler and APIAuthoriser +for more info on which params to pass to authorise and execute requests.

+
+
Parameters:
+

handler_kwargs – The authorisation kwargs to be passed to APIAuthoriser.

+
+
+
+
+abstract add_to_playlist(playlist: str | Mapping[str, Any], items: Collection[str], limit: int = 50, skip_dupes: bool = True) int
+

POST - Add list of tracks to a given playlist.

+
+
Parameters:
+
    +
  • playlist – One of the following to identify the playlist to clear: +- playlist URL/URI/ID, +- the name of the playlist in the current user’s playlists, +- the API response of a playlist.

  • +
  • items – List of URLs/URIs/IDs of the tracks to add.

  • +
  • limit – Size of each batch of IDs to add. This value will be limited to be between 1 and 50.

  • +
  • skip_dupes – Skip duplicates.

  • +
+
+
Returns:
+

The number of tracks added to the playlist.

+
+
Raises:
+
    +
  • RemoteIDTypeError – Raised when the input playlist does not represent +a playlist URL/URI/ID.

  • +
  • RemoteObjectTypeError – Raised when the item types of the input items +are not all tracks or IDs.

  • +
+
+
+
+ +
+
+abstract property api_url_base: str
+

The base URL for making calls to the remote API

+
+ +
+
+authorise(force_load: bool = False, force_new: bool = False) Self
+

Main method for authorisation, tests/refreshes/reauthorises as needed

+
+
Parameters:
+
    +
  • force_load – Reloads the token even if it’s already been loaded into the object. +Ignored when force_new is True.

  • +
  • force_new – Ignore saved/loaded token and generate new token.

  • +
+
+
Returns:
+

Self.

+
+
Raises:
+

APIError – If the token cannot be validated.

+
+
+
+ +
+
+abstract clear_from_playlist(playlist: str | Mapping[str, Any], items: Collection[str] | None = None, limit: int = 100) int
+

DELETE - Clear tracks from a given playlist. +WARNING: This function can destructively modify your remote playlists.

+
+
Parameters:
+
    +
  • playlist – One of the following to identify the playlist to clear: +- playlist URL/URI/ID, +- the name of the playlist in the current user’s playlists, +- the API response of a playlist.

  • +
  • items – List of URLs/URIs/IDs of the tracks to remove. If None, clear all songs from the playlist.

  • +
  • limit – Size of each batch of IDs to clear in a single request. +This value will be limited to be between 1 and 100.

  • +
+
+
Returns:
+

The number of tracks cleared from the playlist.

+
+
Raises:
+
    +
  • RemoteIDTypeError – Raised when the input playlist does not represent +a playlist URL/URI/ID.

  • +
  • RemoteObjectTypeError – Raised when the item types of the input items +are not all tracks or IDs.

  • +
+
+
+
+ +
+
+collection_item_map = {RemoteObjectType.PLAYLIST: RemoteObjectType.TRACK, RemoteObjectType.ALBUM: RemoteObjectType.TRACK, RemoteObjectType.SHOW: RemoteObjectType.EPISODE, RemoteObjectType.AUDIOBOOK: RemoteObjectType.CHAPTER}
+
+ +
+
+abstract create_playlist(name: str, *args, **kwargs) str
+

POST - Create an empty playlist for the current user with the given name.

+
+
Parameters:
+

name – Name of playlist to create.

+
+
Returns:
+

API URL for playlist.

+
+
+
+ +
+
+abstract delete_playlist(playlist: str | Mapping[str, Any]) str
+

DELETE - Unfollow/delete a given playlist. +WARNING: This function will destructively modify your remote playlists.

+
+
Parameters:
+

playlist – One of the following to identify the playlist to clear: +- playlist URL/URI/ID, +- the name of the playlist in the current user’s playlists, +- the API response of a playlist.

+
+
Returns:
+

API URL for playlist.

+
+
+
+ +
+
+abstract extend_items(items_block: MutableMapping[str, Any], kind: RemoteObjectType | str | None = None, key: RemoteObjectType | None = None, use_cache: bool = True) list[dict[str, Any]]
+

Extend the items for a given items_block API response. +The function requests each page of the collection returning a list of all items +found across all pages for this URL.

+

Updates the value of the items key in-place by extending the value of the items key with new results.

+
+
Parameters:
+
    +
  • items_block – A remote API JSON response for an items type endpoint.

  • +
  • kind – The type of response being extended. Optional, used only for logging.

  • +
  • key – The type of response of the child objects.

  • +
  • use_cache – Use the cache when calling the API endpoint. Set as False to refresh the cached response.

  • +
+
+
Returns:
+

API JSON responses for each item

+
+
+
+ +
+
+abstract get_items(values: str | MutableSequence[str] | MutableMapping[str, Any] | MutableSequence[MutableMapping[str, Any]], kind: RemoteObjectType | None = None, limit: int = 50, extend: bool = True, use_cache: bool = True) list[dict[str, Any]]
+
+

GET: /{kind}s - Get information for given values.

+
+
values may be:
    +
  • A string representing a URL/URI/ID.

  • +
  • A MutableSequence of strings representing URLs/URIs/IDs of the same type.

  • +
  • A remote API JSON response for a collection.

  • +
  • A MutableSequence of remote API JSON responses for a collection.

  • +
+
+
+

If JSON response/s given, this update each response given by merging with the new response.

+
+
param values:
+

The values representing some remote objects. See description for allowed value types. +These items must all be of the same type of item i.e. all tracks OR all artists etc.

+
+
param kind:
+

Item type if given string is ID.

+
+
param limit:
+

When requests can be batched, size of batches to request. +This value will be limited to be between 1 and 50.

+
+
param extend:
+

When True and the given kind is a collection of items, +extend the response to include all items in this collection.

+
+
+
+
+
Parameters:
+

use_cache

Use the cache when calling the API endpoint. Set as False to refresh the cached response. +:return: API JSON responses for each item. +:raise RemoteObjectTypeError: Raised when the function cannot determine the item type

+
+

of the input values. Or when it does not recognise the type of the input values parameter.

+
+

+
+
+
+ +
+
+abstract get_playlist_url(playlist: str, use_cache: bool = True) str
+

Determine the type of the given playlist and return its API URL. +If type cannot be determined, attempt to find the playlist in the +list of the currently authenticated user’s playlists.

+
+
Parameters:
+
    +
  • playlist – In URL/URI/ID form, or the name of one of the currently authenticated user’s playlists.

  • +
  • use_cache – Use the cache when calling the API endpoint. Set as False to refresh the cached response.

  • +
+
+
Returns:
+

The playlist URL.

+
+
Raises:
+

RemoteIDTypeError – Raised when the function cannot determine the item type of +the input playlist. Or when it does not recognise the type of the input playlist parameter.

+
+
+
+ +
+
+abstract get_self(update_user_data: bool = True) dict[str, Any]
+

GET - Get API response for information on current user

+
+
Parameters:
+

update_user_data – When True, update the _user_data stored in this API object.

+
+
+
+ +
+
+abstract get_tracks(values: str | MutableSequence[str] | MutableMapping[str, Any] | MutableSequence[MutableMapping[str, Any]], limit: int = 50, use_cache: bool = True, *args, **kwargs) list[dict[str, Any]]
+

Wrapper for get_items() which only returns Track type responses. +See get_items() for more info.

+
+ +
+
+abstract get_user_items(user: str | None = None, kind: RemoteObjectType = RemoteObjectType.PLAYLIST, limit: int = 50, use_cache: bool = True) list[dict[str, Any]]
+

GET - Get saved items for a given user.

+
+
Parameters:
+
    +
  • user – The ID of the user to get playlists for. If None, use the currently authenticated user.

  • +
  • kind – Item type to retrieve for the user.

  • +
  • limit – Size of each batch of items to request in the collection items request. +This value will be limited to be between 1 and 50.

  • +
  • use_cache – Use the cache when calling the API endpoint. Set as False to refresh the cached response.

  • +
+
+
Returns:
+

API JSON responses for each collection.

+
+
Raises:
+
+
+
+
+ +
+
+handler
+
+ +
+
+load_user_data() None
+

Load and store user data in this API object for the currently authorised user

+
+ +
+
+logger: SyncifyLogger
+
+ +
+
+abstract print_collection(value: str | Mapping[str, Any] | None = None, kind: RemoteIDType | None = None, limit: int = 20, use_cache: bool = True) None
+

Diagnostic function. +Print tracks from a given link in <track> - <title> | <URI> - <URL> format for a given URL/URI/ID.

+
+
value may be:
    +
  • A string representing a URL/URI/ID.

  • +
  • A remote API JSON response for a collection with a valid ID value under an id key.

  • +
+
+
+
+
Parameters:
+
    +
  • value – The value representing some remote collection. See description for allowed value types.

  • +
  • kind – When an ID is provided, give the kind of ID this is here. +If None and ID is given, user will be prompted to give the kind anyway.

  • +
  • limit – The number of results to call per request and, +therefore, the number of items in each printed block.

  • +
  • use_cache – Use the cache when calling the API endpoint. Set as False to refresh the cached response.

  • +
+
+
+
+ +
+
+print_item(i: int, name: str, uri: str, length: float = 0, total: int = 1, max_width: int = 50) None
+

Pretty print item data for displaying to the user.

+
+
Parameters:
+
    +
  • i – The position of this item in the collection.

  • +
  • name – The name of the item.

  • +
  • uri – The URI of the item.

  • +
  • length – The duration of the item in seconds.

  • +
  • total – The total number of items in the collection

  • +
  • max_width – The maximum width to print names as. Any name lengths longer than this will be truncated.

  • +
+
+
+
+ +
+
+abstract query(query: str, kind: RemoteObjectType, limit: int = 10, use_cache: bool = True) list[dict[str, Any]]
+

GET - Query for items. Modify result types returned with kind parameter

+
+
Parameters:
+
    +
  • query – Search query.

  • +
  • kind – The remote object type to search for.

  • +
  • limit – Number of results to get and return.

  • +
  • use_cache – Use the cache when calling the API endpoint. Set as False to refresh the cached response.

  • +
+
+
Returns:
+

The response from the endpoint.

+
+
+
+ +
+
+user_data: dict[str, Any]
+
+ +
+
+abstract property user_id: str | None
+

ID of the currently authorised user

+
+ +
+
+user_item_types = {RemoteObjectType.PLAYLIST, RemoteObjectType.TRACK, RemoteObjectType.ALBUM, RemoteObjectType.ARTIST, RemoteObjectType.SHOW, RemoteObjectType.EPISODE, RemoteObjectType.AUDIOBOOK}
+
+ +
+
+abstract property user_name: str | None
+

Name of the currently authorised user

+
+ +
+ +
+
+

syncify.remote.base module

+
+
+class syncify.remote.base.RemoteItem(response: dict[str, Any], api: RemoteAPI | None = None, skip_checks: bool = False)
+

Bases: RemoteObject, Item

+

Generic base class for remote items. Extracts key data from a remote API JSON response.

+
+
+api
+
+ +
+ +
+
+class syncify.remote.base.RemoteObject(response: dict[str, Any], api: RemoteAPI | None = None, skip_checks: bool = False)
+

Bases: NamedObjectPrinter, Remote

+

Generic base class for remote objects. Extracts key data from a remote API JSON response.

+
+
Parameters:
+
    +
  • response – The remote API JSON response

  • +
  • api – The instantiated and authorised API object for this source type.

  • +
+
+
+
+
+api
+
+ +
+
+as_dict()
+

Return a dictionary representation of the key attributes of this object.

+
+
The results of this function are used to produce the following:
    +
  • A JSON representation of the object when calling json()

  • +
  • The string representation of the object when calling str() on the object

  • +
  • The representation of the object when calling repr() on the object

  • +
+
+
+
+ +
+
+abstract property has_uri: bool
+

Does this item/collection have a valid URI that is not a local URI.

+
+ +
+
+abstract property id: str
+

The ID of this item/collection.

+
+ +
+
+abstract classmethod load(value: str | dict[str, Any], api: RemoteAPI, use_cache: bool = True, *args, **kwargs) Self
+

Generate a new object of this class, +calling all required endpoints to get a complete set of data for this item type.

+
+
value may be:
    +
  • A string representing a URL/URI/ID.

  • +
  • A remote API JSON response for a collection with a valid ID value under an id key.

  • +
+
+
+
+
Parameters:
+
    +
  • value – The value representing some remote object. See description for allowed value types.

  • +
  • api – An authorised API object to load the object from.

  • +
  • use_cache – Use the cache when calling the API endpoint. Set as False to refresh the cached response.

  • +
+
+
+
+ +
+
+abstract refresh(skip_checks: bool = False) None
+

Refresh this object by updating from the stored API response. +Useful for updating stored variables after making changes to the stored API response manually.

+
+ +
+
+abstract reload(use_cache: bool = True, *args, **kwargs) None
+

Reload this object from the API, calling all required endpoints +to get a complete set of data for this item type

+
+
Parameters:
+

use_cache – Use the cache when calling the API endpoint. Set as False to refresh the cached response.

+
+
+
+ +
+
+property response: dict[str, Any]
+

The API response for this object

+
+ +
+
+abstract property uri: str
+

The URI of this item/collection.

+
+ +
+
+abstract property url: str
+

The API URL of this item/collection.

+
+ +
+
+abstract property url_ext: str | None
+

The external URL of this item/collection.

+
+ +
+ +
+
+

syncify.remote.config module

+
+
+class syncify.remote.config.RemoteObjectClasses(playlist: type[RemotePlaylist], track: type[RemoteTrack], album: type[RemoteAlbum], artist: type[RemoteArtist])
+

Bases: object

+

Stores the key object classes for a remote source

+
+
+album: type[RemoteAlbum]
+
+ +
+
+artist: type[RemoteArtist]
+
+ +
+
+playlist: type[RemotePlaylist]
+
+ +
+
+track: type[RemoteTrack]
+
+ +
+ +
+
+

syncify.remote.enums module

+
+
+class syncify.remote.enums.RemoteIDType(value, names=None, *values, module=None, qualname=None, type=None, start=1, boundary=None)
+

Bases: SyncifyEnum

+

Represents remote ID type

+
+
+ALL: int = 0
+
+ +
+
+ID: int = 22
+
+ +
+
+URI: int = 3
+
+ +
+
+URL: int = 1
+
+ +
+
+URL_EXT: int = 2
+
+ +
+ +
+
+class syncify.remote.enums.RemoteObjectType(value, names=None, *values, module=None, qualname=None, type=None, start=1, boundary=None)
+

Bases: SyncifyEnum

+

Represents remote object types

+
+
+ALBUM = 3
+
+ +
+
+ALL = 0
+
+ +
+
+ARTIST = 4
+
+ +
+
+AUDIOBOOK = 8
+
+ +
+
+CHAPTER = 9
+
+ +
+
+EPISODE = 7
+
+ +
+
+PLAYLIST = 1
+
+ +
+
+SHOW = 6
+
+ +
+
+TRACK = 2
+
+ +
+
+USER = 5
+
+ +
+ +
+
+

syncify.remote.exception module

+
+
+exception syncify.remote.exception.RemoteError
+

Bases: SyncifyError

+

Exception raised for remote errors

+
+ +
+
+exception syncify.remote.exception.RemoteIDTypeError(message: str | None = None, kind: RemoteIDType | None = None, value: Any = None)
+

Bases: RemoteError

+

Exception raised for remote ID type errors.

+
+
Parameters:
+
    +
  • message – Explanation of the error.

  • +
  • kind – The ID type related to the error.

  • +
+
+
+
+ +
+
+exception syncify.remote.exception.RemoteObjectTypeError(message: str | None = None, kind: RemoteObjectType | None = None, value: Any = None)
+

Bases: RemoteError

+

Exception raised for remote object type errors.

+
+
Parameters:
+
    +
  • message – Explanation of the error.

  • +
  • kind – The item type related to the error.

  • +
+
+
+
+ +
+
+

syncify.remote.library module

+
+
+class syncify.remote.library.RemoteLibrary(api: RemoteAPI, include: Iterable[str] = (), exclude: Iterable[str] = (), use_cache: bool = True)
+

Bases: Library, RemoteCollection, Generic

+

Represents a remote library, providing various methods for manipulating +tracks and playlists across an entire remote library collection.

+
+
Parameters:
+
    +
  • api – An authorised API object for the authenticated user you wish to load the library from.

  • +
  • include – An optional list of playlist names to include when loading playlists.

  • +
  • exclude – An optional list of playlist names to exclude when loading playlists.

  • +
  • use_cache – Use the cache when calling the API endpoint. Set as False to refresh the cached response.

  • +
+
+
+
+
+property albums: list[RemoteAlbum]
+

The saved albums in this library

+
+ +
+
+property api: RemoteAPI
+

Authorised API object for making authenticated calls to a user’s library

+
+ +
+
+property artists: list[RemoteArtist]
+

The saved artists in this library

+
+ +
+
+as_dict()
+

Return a dictionary representation of the key attributes of this object.

+
+
The results of this function are used to produce the following:
    +
  • A JSON representation of the object when calling json()

  • +
  • The string representation of the object when calling str() on the object

  • +
  • The representation of the object when calling repr() on the object

  • +
+
+
+
+ +
+
+backup_playlists() dict[str, list[str]]
+

Produce a backup map of <playlist name>: [<URIs] for all playlists in this library +which can be saved to JSON for backup purposes.

+
+ +
+
+enrich_saved_albums(*_, **__) None
+

Call API to enrich elements of user’s saved album objects improving metadata coverage. +This is an optionally implementable method. Defaults to doing nothing.

+
+ +
+
+enrich_saved_artists(*_, **__) None
+

Call API to enrich elements of user’s saved artist objects improving metadata coverage. +This is an optionally implementable method. Defaults to doing nothing.

+
+ +
+
+enrich_tracks(*_, **__) None
+

Call API to enrich elements of track objects improving metadata coverage. +This is an optionally implementable method. Defaults to doing nothing.

+
+ +
+
+exclude
+
+ +
+
+extend(_RemoteLibrary__items: Iterable[Item], allow_duplicates: bool = True) None
+

Append many items to the items in this collection

+
+ +
+
+property id
+

The user ID associated with this library

+
+ +
+
+include
+
+ +
+
+json()
+

Return a dictionary representation of the key attributes of this object that is safe to output to JSON

+
+ +
+
+load() None
+

Loads all data from the remote API for this library and log results.

+
+ +
+
+load_playlists() None
+

Load all playlists from the API that match the filter rules in this library. Also loads all their tracks. +WARNING: Overwrites any currently loaded playlists.

+
+ +
+
+load_saved_albums() None
+

Load all user’s saved albums from the API. +Updates currently loaded albums in-place or appends if not already loaded.

+
+ +
+
+load_saved_artists() None
+

Load all user’s saved artists from the API. +Updates currently loaded artists in-place or appends if not already loaded.

+
+ +
+
+load_saved_tracks() None
+

Load all user’s saved tracks from the API. +Updates currently loaded tracks in-place or appends if not already loaded.

+
+ +
+
+log_albums() None
+

Log stats on currently loaded albums

+
+ +
+
+log_artists() None
+

Log stats on currently loaded artists

+
+ +
+
+log_playlists() None
+

Log stats on currently loaded playlists

+
+ +
+
+log_sync(results: Mapping[str, SyncResultRemotePlaylist]) None
+

Log stats from the results of a sync operation

+
+ +
+
+log_tracks() None
+

Log stats on currently loaded tracks

+
+ +
+
+property name
+

The username associated with this library

+
+ +
+
+property playlists: dict[str, RemotePlaylist]
+

The playlists in this library

+
+ +
+
+restore_playlists(playlists: Library | Collection[Playlist] | Mapping[str, Iterable[Track]] | Mapping[str, Iterable[str]], dry_run: bool = True) None
+

Restore playlists from a backup to loaded playlist objects.

+

This function does not sync the updated playlists with the remote library.

+

When dry_run is False, this function does create new playlists on the remote library for playlists +given that do not exist in this Library.

+
+
Parameters:
+
    +
  • playlists – Values that represent the playlists to restore from.

  • +
  • dry_run – When True, do not create playlists +and just skip any playlists that are not already currently loaded.

  • +
+
+
+
+ +
+
+sync(playlists: Library | Mapping[str, Iterable[Item]] | Collection[Playlist] | None = None, kind: Literal['new', 'refresh', 'sync'] = 'new', reload: bool = True, dry_run: bool = True) dict[str, SyncResultRemotePlaylist]
+

Synchronise this playlist object with the remote playlist it is associated with. Clear options:

+
    +
  • +
    ‘new’: Do not clear any items from the remote playlist and only add any tracks

    from this playlist object not currently in the remote playlist.

    +
    +
    +
  • +
  • ‘refresh’: Clear all items from the remote playlist first, then add all items from this playlist object.

  • +
  • +
    ‘sync’: Clear all items not currently in this object’s items list, then add all tracks

    from this playlist object not currently in the remote playlist.

    +
    +
    +
  • +
+
+
Parameters:
+
    +
  • playlists – Provide a library, map of playlist name to playlist or collection of playlists +to synchronise to the remote library. +Use the currently loaded playlists in this object if not given.

  • +
  • kind – Sync option for the remote playlist. See description.

  • +
  • reload – When True, once synchronisation is complete, reload this RemotePlaylist object +to reflect the changes on the remote playlist if enabled. Skip if False.

  • +
  • dry_run – Run function, but do not modify the remote playlists at all.

  • +
+
+
Returns:
+

Map of playlist name to the results of the sync as a SyncResultRemotePlaylist object.

+
+
+
+ +
+
+property tracks: list[T]
+

The tracks in this library

+
+ +
+
+use_cache
+
+ +
+ +
+
+

syncify.remote.object module

+
+
+class syncify.remote.object.RemoteAlbum(response: dict[str, Any], api: RemoteAPI | None = None, skip_checks: bool = False)
+

Bases: Album, RemoteCollectionLoader, Generic

+

Extracts key album data from a remote API JSON response.

+
+
+api
+
+ +
+
+abstract property artists: list[RemoteArtist]
+

List of artists ordered by frequency of appearance on the tracks on this album

+
+ +
+ +
+
+class syncify.remote.object.RemoteArtist(response: dict[str, Any], api: RemoteAPI | None = None, skip_checks: bool = False)
+

Bases: Artist, RemoteCollectionLoader, Generic

+

Extracts key artist data from a remote API JSON response.

+
+
+abstract property albums: list[RemoteAlbum]
+

List of albums ordered by frequency of appearance on the tracks by this artist

+
+ +
+
+api
+
+ +
+
+property artists
+

List of other artists ordered by frequency of appearance on the albums by this artist

+
+ +
+
+property has_image: bool
+

Does this artist have images associated with them

+
+ +
+ +

The images associated with this artist in the form {image name: image link}

+
+ +
+
+property length
+

Total duration of all tracks by this artist

+
+ +
+
+property track_total
+

The total number of tracks by this artist

+
+ +
+
+property tracks: list[RemoteTrack]
+

The tracks by this artist

+
+ +
+ +
+
+class syncify.remote.object.RemoteCollection
+

Bases: ItemCollection, RemoteDataWrangler, Generic

+

Generic class for storing a collection of remote objects.

+
+ +
+
+class syncify.remote.object.RemoteCollectionLoader(response: dict[str, Any], api: RemoteAPI | None = None, skip_checks: bool = False)
+

Bases: RemoteObject, RemoteCollection, Generic

+

Generic class for storing a collection of remote objects that can be loaded from an API response.

+
+
+api
+
+ +
+
+abstract classmethod load(value: str | Mapping[str, Any], api: RemoteAPI, use_cache: bool = True, items: Iterable[T] = (), *args, **kwargs) Self
+

Generate a new object, calling all required endpoints to get a complete set of data for this item type.

+
+
value may be:
    +
  • A string representing a URL/URI/ID.

  • +
  • A remote API JSON response for a collection with a valid ID value under an id key.

  • +
+
+
+
+
Parameters:
+
    +
  • value – The value representing some remote collection. See description for allowed value types.

  • +
  • api – An authorised API object to load the object from.

  • +
  • use_cache – Use the cache when calling the API endpoint. Set as False to refresh the cached response.

  • +
  • items – Optionally, give a list of available items to build a response for this collection. +In doing so, the method will first try to find the API responses for the items of this collection +in the given list before calling the API for any items not found there. +This helps reduce the number of API calls made on initialisation.

  • +
+
+
+
+ +
+ +
+
+class syncify.remote.object.RemoteItemWranglerMixin(response: dict[str, Any], api: RemoteAPI | None = None, skip_checks: bool = False)
+

Bases: RemoteItem, RemoteDataWrangler, Generic

+
+
+api
+
+ +
+ +
+
+class syncify.remote.object.RemotePlaylist(response: dict[str, Any], api: RemoteAPI | None = None, skip_checks: bool = False)
+

Bases: Playlist, RemoteCollectionLoader, Generic

+

Extracts key playlist data from a remote API JSON response.

+
+
+api
+
+ +
+
+classmethod create(api: RemoteAPI, name: str, public: bool = True, collaborative: bool = False) Self
+

Create an empty playlist for the current user with the given name +and initialise and return a new RemotePlaylist object from this new playlist.

+
+
Parameters:
+
    +
  • api – An API object with authorised access to a remote User to create playlists for.

  • +
  • name – Name of playlist to create.

  • +
  • public – Set playlist availability as public if True and private if False.

  • +
  • collaborative – Set playlist to collaborative i.e. other users may edit the playlist.

  • +
+
+
Returns:
+

RemotePlaylist object for the generated playlist.

+
+
+
+ +
+
+abstract property date_added: dict[str, datetime]
+

A map of {URI: date} for each item for when that item was added to the playlist

+
+ +
+
+delete() None
+

Unfollow/delete the current playlist and clear the stored response for this object. +WARNING: This function will destructively modify your remote playlists.

+
+ +
+
+abstract property followers: int
+

The number of followers this playlist has

+
+ +
+
+merge(playlist: Playlist) None
+

Merge tracks in this playlist with another playlist synchronising tracks between the two. +Only modifies this playlist.

+
+ +
+
+abstract property owner_id: str
+

The ID of the owner of this playlist

+
+ +
+
+abstract property owner_name: str
+

The name of the owner of this playlist

+
+ +
+
+sync(items: Iterable[Item] = (), kind: Literal['new', 'refresh', 'sync'] = 'new', reload: bool = True, dry_run: bool = True) SyncResultRemotePlaylist
+

Synchronise this playlist object’s items with the remote playlist it is associated with. Sync options:

+
    +
  • +
    ‘new’: Do not clear any items from the remote playlist and only add any tracks

    from this playlist object not currently in the remote playlist.

    +
    +
    +
  • +
  • ‘refresh’: Clear all items from the remote playlist first, then add all items from this playlist object.

  • +
  • +
    ‘sync’: Clear all items not currently in this object’s items list, then add all tracks

    from this playlist object not currently in the remote playlist.

    +
    +
    +
  • +
+
+
Parameters:
+
    +
  • items – Provide an item collection or list of items to synchronise to the remote playlist. +Use the currently loaded tracks in this object if not given.

  • +
  • kind – Sync option for the remote playlist. See description.

  • +
  • reload – When True, once synchronisation is complete, reload this RemotePlaylist object +to reflect the changes on the remote playlist if enabled. Skip if False.

  • +
  • dry_run – Run function, but do not modify the remote playlists at all.

  • +
+
+
Returns:
+

The results of the sync as a SyncResultRemotePlaylist object.

+
+
+
+ +
+
+property writeable: bool
+

Is this playlist writeable i.e. can this program modify it

+
+ +
+ +
+
+class syncify.remote.object.RemoteTrack(response: dict[str, Any], api: RemoteAPI | None = None, skip_checks: bool = False)
+

Bases: RemoteItemWranglerMixin, Track

+

Extracts key track data from a remote API JSON response.

+
+
+api
+
+ +
+ +
+
+class syncify.remote.object.SyncResultRemotePlaylist(start: int, added: int, removed: int, unchanged: int, difference: int, final: int)
+

Bases: Result

+

Stores the results of a sync with a remote playlist

+
+
Variables:
+
    +
  • start – The total number of tracks in the playlist before the sync.

  • +
  • added – The number of tracks added to the playlist.

  • +
  • removed – The number of tracks removed from the playlist.

  • +
  • unchanged – The number of tracks that were in the playlist before and after the sync.

  • +
  • difference – The difference between the total number tracks in the playlist from before and after the sync.

  • +
  • final – The total number of tracks in the playlist after the sync.

  • +
+
+
+
+
+added: int
+
+ +
+
+difference: int
+
+ +
+
+final: int
+
+ +
+
+removed: int
+
+ +
+
+start: int
+
+ +
+
+unchanged: int
+
+ +
+ +
+
+

syncify.remote.types module

+
+
+

Module contents

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/_build/syncify.remote.processors.html b/_build/syncify.remote.processors.html new file mode 100644 index 00000000..c0fbaa53 --- /dev/null +++ b/_build/syncify.remote.processors.html @@ -0,0 +1,579 @@ + + + + + + + + syncify.remote.processors package — Syncify 0.3 documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

syncify.remote.processors package

+
+

Submodules

+
+
+

syncify.remote.processors.check module

+
+
+class syncify.remote.processors.check.ItemCheckResult(switched: Sequence[Item] = (), unavailable: Sequence[Item] = (), skipped: Sequence[Item] = ())
+

Bases: Result

+

Stores the results of the checking proces

+
+
Variables:
+
    +
  • switched – Sequence of Items that had URIs switched during the check.

  • +
  • unavailable – Sequence of Items that were marked as unavailable.

  • +
  • skipped – Sequence of Items that were skipped from the check.

  • +
+
+
+
+
+skipped: Sequence[Item] = ()
+
+ +
+
+switched: Sequence[Item] = ()
+
+ +
+
+unavailable: Sequence[Item] = ()
+
+ +
+ +
+
+class syncify.remote.processors.check.RemoteItemChecker(api: RemoteAPI, interval: int = 10, allow_karaoke: bool = False)
+

Bases: RemoteDataWrangler, ItemMatcher

+

Runs operations for checking the URIs associated with a collection of items. +When running check(), the object will do the following:

+
    +
  • +
    Make temporary playlists for each collection up to a interval limit of playlists.

    At which point, playlist creation pauses.

    +
    +
    +
  • +
  • User can then check and modify the temporary playlists to match items to correct items or otherwise.

  • +
  • +
    When operations resume at the user’s behest, the program will search each playlist to find changes and

    attempt to match any new items to a source item.

    +
    +
    +
  • +
  • +
    If no matches are found for certain items, the program will prompt the user

    to determine how they wish to deal with these items.

    +
    +
    +
  • +
  • Operation completes once user exists or all items have an associated URI.

  • +
+
+
Parameters:
+
    +
  • api – An API object with authorised access to a remote User to create playlists for.

  • +
  • interval – Stop creating playlists after this many playlists have been created and pause for user input.

  • +
+
+
+
+
+allow_karaoke
+
+ +
+
+api
+
+ +
+
+check(collections: Collection[ItemCollection]) ItemCheckResult | None
+

Run the following operations to check a list of ItemCollections on the remote application.

+
    +
  • +
    Make temporary playlists for each collection up to a interval limit of playlists.

    At which point, playlist creation pauses.

    +
    +
    +
  • +
  • User can then check and modify the temporary playlists to match items to correct items or otherwise.

  • +
  • +
    When operations resume at the user’s behest, the program will search each playlist to find changes and

    attempt to match any new items to a source item.

    +
    +
    +
  • +
  • +
    If no matches are found for certain items, the program will prompt the user

    to determine how they wish to deal with these items.

    +
    +
    +
  • +
  • Operation completes once user exists or all items have an associated URI.

  • +
+
+
Parameters:
+

collections – A list of collections to check.

+
+
Returns:
+

A ItemCheckResult object containing the remapped items created during the check. +Return None when the user opted to quit (not skip) the checker before completion.

+
+
+
+ +
+
+final_skipped: list[Track]
+
+ +
+
+final_switched: list[Track]
+
+ +
+
+final_unavailable: list[Track]
+
+ +
+
+interval
+
+ +
+
+playlist_name_collection
+
+ +
+
+playlist_name_urls
+
+ +
+
+quit
+
+ +
+
+remaining: list[Track]
+
+ +
+
+skip
+
+ +
+
+switched: list[Track]
+
+ +
+ +
+
+

syncify.remote.processors.search module

+
+
+class syncify.remote.processors.search.ItemSearchResult(matched: Sequence[Item] = (), unmatched: Sequence[Item] = (), skipped: Sequence[Item] = ())
+

Bases: Result

+

Stores the results of the searching process

+
+
Variables:
+
    +
  • matched – Sequence of Items for which matches were found from the search.

  • +
  • unmatched – Sequence of Items for which matches were not found from the search.

  • +
  • skipped – Sequence of Items which were skipped during the search.

  • +
+
+
+
+
+matched: Sequence[Item] = ()
+
+ +
+
+skipped: Sequence[Item] = ()
+
+ +
+
+unmatched: Sequence[Item] = ()
+
+ +
+ +
+
+class syncify.remote.processors.search.RemoteItemSearcher(api: RemoteAPI, use_cache: bool = False)
+

Bases: Remote, ItemMatcher

+

Searches for remote matches for a list of item collections.

+
+
Parameters:
+
    +
  • api – An API object for calling the remote query endpoint.

  • +
  • use_cache – Use the cache when calling the API endpoint. Set as False to refresh the cached response.

  • +
+
+
+
+
+api
+
+ +
+
+search(collections: Collection[ItemCollection]) dict[str, ItemSearchResult]
+

Searches for remote matches for the given list of item collections.

+
+
Returns:
+

Map of the collection’s name to its ItemSearchResult object.

+
+
+
+ +
+
+settings_albums = SearchSettings(search_fields_1=[<TagFields.NAME: 1000>, <TagFields.ARTIST: 32>], match_fields={<TagFields.ARTIST: 32>, <TagFields.LENGTH: 16>, <TagFields.ALBUM: 30>}, result_count=5, allow_karaoke=False, min_score=0.1, max_score=0.7, search_fields_2=[<TagFields.NAME: 1000>], search_fields_3=())
+
+ +
+
+settings_items = SearchSettings(search_fields_1=[<TagFields.NAME: 1000>, <TagFields.ARTIST: 32>], match_fields={<TagFields.ARTIST: 32>, <TagFields.TITLE: 65>, <TagFields.ALBUM: 30>, <TagFields.LENGTH: 16>}, result_count=10, allow_karaoke=False, min_score=0.1, max_score=0.8, search_fields_2=[<TagFields.NAME: 1000>, <TagFields.ALBUM: 30>], search_fields_3=[<TagFields.NAME: 1000>])
+
+ +
+
+use_cache
+
+ +
+ +
+
+class syncify.remote.processors.search.SearchSettings(search_fields_1: Sequence[TagField], match_fields: TagField | Iterable[TagField], result_count: int, allow_karaoke: bool = False, min_score: float = 0.1, max_score: float = 0.8, search_fields_2: Iterable[TagField] = (), search_fields_3: Iterable[TagField] = ())
+

Bases: object

+

Key settings related to a search algorithm.

+
+
Variables:
+
    +
  • search_fields_1 – A list of the tag names to use as search fields in the 1st pass.

  • +
  • search_fields_2 – If no results are found from the tag names in search_fields_1 on the 1st pass, +an optional list of the tag names to use as search fields in the 2nd pass.

  • +
  • search_fields_3 – If no results are found from the tag names in search_fields_2 on the 2nd pass, +an optional list of the tag names to use as search fields in the 3rd pass.

  • +
  • match_fields – The fields to match results on.

  • +
  • result_count – The number of the results to request when querying the API.

  • +
  • allow_karaoke – When True, items determined to be karaoke are allowed when matching added items. +Skip karaoke results otherwise.

  • +
  • min_score – The minimum acceptable score for an item to be considered a match.

  • +
  • min_score – The maximum score for an item to be considered a perfect match. +After this score is reached by an item, any other items are disregarded as potential matches.

  • +
+
+
+
+
+allow_karaoke: bool = False
+
+ +
+
+match_fields: TagField | Iterable[TagField]
+
+ +
+
+max_score: float = 0.8
+
+ +
+
+min_score: float = 0.1
+
+ +
+
+result_count: int
+
+ +
+
+search_fields_1: Sequence[TagField]
+
+ +
+
+search_fields_2: Iterable[TagField] = ()
+
+ +
+
+search_fields_3: Iterable[TagField] = ()
+
+ +
+ +
+
+

syncify.remote.processors.wrangle module

+
+
+class syncify.remote.processors.wrangle.RemoteDataWrangler
+

Bases: Remote

+
+
+abstract classmethod convert(value: str, kind: RemoteObjectType | None = None, type_in: RemoteIDType = RemoteIDType.ALL, type_out: RemoteIDType = RemoteIDType.ID) str
+

Converts ID to required format - API URL, EXT URL, URI, or ID.

+
+
Parameters:
+
    +
  • value – URL/URI/ID to convert.

  • +
  • kind – Optionally, give the item type of the input value to skip some checks. +This is required when the given value is an ID.

  • +
  • type_in – Optionally, give the ID type of the input value to skip some checks.

  • +
  • type_out – The ID type of the output value.

  • +
+
+
Returns:
+

Formatted string.

+
+
Raises:
+

RemoteIDTypeError – Raised when the function cannot determine the item type +of the input value.

+
+
+
+ +
+
+abstract classmethod extract_ids(values: str | MutableSequence[str] | MutableMapping[str, Any] | MutableSequence[MutableMapping[str, Any]], kind: RemoteObjectType | None = None) list[str]
+

Extract a list of IDs from input values.

+
+
values may be:
    +
  • A string representing a URL/URI/ID.

  • +
  • A MutableSequence of strings representing URLs/URIs/IDs of the same type.

  • +
  • +
    A remote API JSON response for a collection including:
      +
    • a valid ID value under an id key,

    • +
    • a valid item type value under a type key if kind is None.

    • +
    +
    +
    +
  • +
  • A MutableSequence of remote API JSON responses for a collection including the same structure as above.

  • +
+
+
+
+
Parameters:
+
    +
  • values – The values representing some remote objects. See description for allowed value types. +These items may be of mixed item types e.g. some tracks AND some artists.

  • +
  • kind – Optionally, give the item type of the input value to skip some checks. +This is required when the given value is an ID.

  • +
+
+
Returns:
+

List of IDs.

+
+
Raises:
+

RemoteError – Raised when the function cannot determine the item type of the input values. +Or when it does not recognise the type of the input values parameter.

+
+
+
+ +
+
+abstract static get_id_type(value: str, kind: RemoteObjectType | None = None) RemoteIDType
+

Determine the remote ID type of the given value and return its type.

+
+
Parameters:
+
    +
  • value – URL/URI/ID to check.

  • +
  • kind – When this is equal to USER, ignore checks and always return ID as type.

  • +
+
+
Returns:
+

The RemoteIDType.

+
+
Raises:
+

RemoteIDTypeError – Raised when the function cannot determine the ID type +of the input value.

+
+
+
+ +
+
+classmethod get_item_type(values: str | MutableSequence[str] | MutableMapping[str, Any] | MutableSequence[MutableMapping[str, Any]], kind: RemoteObjectType | None = None) RemoteObjectType
+

Determine the remote object type of values.

+
+
values may be:
    +
  • A string representing a URL/URI/ID.

  • +
  • A MutableSequence of strings representing URLs/URIs/IDs of the same type.

  • +
  • A remote API JSON response for a collection including a valid item type value under a type key.

  • +
  • A MutableSequence of remote API JSON responses for a collection including the same structure as above.

  • +
+
+
+
+
Parameters:
+
    +
  • values – The values representing some remote objects. See description for allowed value types. +These items must all be of the same type of item to pass i.e. all tracks OR all artists etc.

  • +
  • kind – The RemoteObjectType if the value is found to be an ID.

  • +
+
+
Returns:
+

RemoteObjectType

+
+
Raises:
+

RemoteObjectTypeError – Raised when the function cannot determine the item type +of the input values. +Or when the list contains strings representing many differing remote object types or only IDs.

+
+
+
+ +
+
+abstract property unavailable_uri_dummy: str
+

The value to use as a URI for an item which does not have an associated remote object. +An item that has this URI value will be excluded from most remote logic.

+
+ +
+
+abstract classmethod validate_id_type(value: str, kind: RemoteIDType = RemoteIDType.ALL) bool
+

Check that the given value is a type of remote ID given by ``kind ``

+
+ +
+
+classmethod validate_item_type(values: str | MutableSequence[str] | MutableMapping[str, Any] | MutableSequence[MutableMapping[str, Any]], kind: RemoteObjectType) None
+

Check that the given values is a type of item given by ``kind `` or a simple ID.

+
+
values may be:
    +
  • A string representing a URL/URI/ID.

  • +
  • A MutableSequence of strings representing URLs/URIs/IDs of the same type.

  • +
  • A remote API JSON response for a collection including a valid item type value under a type key.

  • +
  • A MutableSequence of remote API JSON responses for a collection including the same structure as above.

  • +
+
+
+
+
Parameters:
+
    +
  • values – The values representing some remote objects. See description for allowed value types. +These items must all be of the same type of item to pass i.e. all tracks OR all artists etc.

  • +
  • kind – The remote object type to check for.

  • +
+
+
Raises:
+

RemoteObjectTypeError – Raised when the function cannot validate the item type +of the input values is of type kind or a simple ID.

+
+
+
+ +
+ +
+
+

Module contents

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/_build/syncify.spotify.api.html b/_build/syncify.spotify.api.html new file mode 100644 index 00000000..335fc408 --- /dev/null +++ b/_build/syncify.spotify.api.html @@ -0,0 +1,102 @@ + + + + + + + + syncify.spotify.api package — Syncify 0.3 documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

syncify.spotify.api package

+
+

Module contents

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/_build/syncify.spotify.html b/_build/syncify.spotify.html new file mode 100644 index 00000000..03c755a1 --- /dev/null +++ b/_build/syncify.spotify.html @@ -0,0 +1,959 @@ + + + + + + + + syncify.spotify package — Syncify 0.3 documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

syncify.spotify package

+
+

Subpackages

+ +
+
+

Submodules

+
+
+

syncify.spotify.base module

+
+
+class syncify.spotify.base.SpotifyItem(response: dict[str, Any], api: SpotifyAPI | None = None, skip_checks: bool = False)
+

Bases: RemoteItem, SpotifyObject

+

Generic base class for Spotify-stored items. Extracts key data from a Spotify API JSON response.

+
+
+api: SpotifyAPI
+
+ +
+ +
+
+class syncify.spotify.base.SpotifyObject(response: dict[str, Any], api: SpotifyAPI | None = None, skip_checks: bool = False)
+

Bases: SpotifyObjectMixin, PrettyPrinter

+

Generic base class for Spotify-stored objects. Extracts key data from a Spotify API JSON response.

+
+
+api: SpotifyAPI
+
+ +
+
+property has_uri: bool
+

Does this item/collection have a valid URI that is not a local URI.

+
+ +
+
+property id: str
+

The ID of this item/collection.

+
+ +
+
+property uri: str
+

The URI of this item/collection.

+
+ +
+
+property url: str
+

The API URL of this item/collection.

+
+ +
+
+property url_ext: str | None
+

The external URL of this item/collection.

+
+ +
+ +
+
+class syncify.spotify.base.SpotifyObjectMixin(response: dict[str, Any], api: RemoteAPI | None = None, skip_checks: bool = False)
+

Bases: RemoteObject, SpotifyRemote

+
+
+api
+
+ +
+ +
+
+

syncify.spotify.config module

+
+
+

syncify.spotify.exception module

+
+
+exception syncify.spotify.exception.SpotifyCollectionError(message: str | None = None, kind: str | None = None)
+

Bases: SpotifyError

+

Exception raised for local collection errors.

+
+
Parameters:
+
    +
  • message – Explanation of the error.

  • +
  • kind – The collection type related to the error.

  • +
+
+
+
+ +
+
+exception syncify.spotify.exception.SpotifyError(message: str | None = None)
+

Bases: RemoteError

+

Exception raised for Spotify ID errors.

+
+
Parameters:
+

message – Explanation of the error.

+
+
+
+ +
+
+exception syncify.spotify.exception.SpotifyItemError(message: str | None = None, kind: str | None = None)
+

Bases: SpotifyError

+

Exception raised for local item errors.

+
+
Parameters:
+
    +
  • message – Explanation of the error.

  • +
  • kind – The item type related to the error.

  • +
+
+
+
+ +
+
+

syncify.spotify.library module

+
+
+class syncify.spotify.library.SpotifyLibrary(api: RemoteAPI, include: Iterable[str] = (), exclude: Iterable[str] = (), use_cache: bool = True)
+

Bases: RemoteLibrary[SpotifyTrack], SpotifyCollection[SpotifyTrack]

+

Represents a Spotify library, providing various methods for manipulating +tracks and playlists across an entire Spotify library collection.

+
+
+property albums: list[SpotifyAlbum]
+

The saved albums in this library

+
+ +
+
+property api: SpotifyAPI
+

Authorised API object for making authenticated calls to a user’s library

+
+ +
+
+property artists: list[SpotifyArtist]
+

The saved artists in this library

+
+ +
+
+enrich_saved_albums() None
+

Extends the tracks data for currently loaded albums, getting all available tracks data for each album

+
+ +
+
+enrich_saved_artists(tracks: bool = False, types: Collection[str] = ()) None
+

Gets all albums for current loaded following artists.

+
+
Parameters:
+
    +
  • tracks – When True, also get all tracks for each album.

  • +
  • types – Provide a list of albums types to get to limit the types of albums loaded.

  • +
+
+
+

Select from {"album", "single", "compilation", "appears_on"}.

+
+ +
+
+enrich_tracks(features: bool = False, analysis: bool = False, albums: bool = False, artists: bool = False) None
+

Enriches the features, analysis, albums, and/or artists data for currently loaded tracks.

+
+
Parameters:
+
    +
  • features – Load all audio features (e.g. BPM, tempo, key etc.)

  • +
  • analysis – Load all audio analyses (technical audio data). +WARNING: can be very slow as calls to this endpoint cannot be batched i.e. one call per track.

  • +
  • albums – Reload albums for all tracks, adding extra album data e.g. genres, popularity

  • +
  • artists – Reload artists for all tracks, adding extra artist data e.g. genres, popularity, followers

  • +
+
+
+
+ +
+
+exclude
+
+ +
+
+include
+
+ +
+
+merge_playlists(playlists: Library | Collection[Playlist] | Mapping[Any, Playlist]) None
+

Merge playlists from given list/map/library to this library

+
+ +
+
+property playlists: dict[str, SpotifyPlaylist]
+

The playlists in this library

+
+ +
+
+use_cache
+
+ +
+ +
+
+

syncify.spotify.object module

+
+
+class syncify.spotify.object.SpotifyAlbum(response: dict[str, Any], api: SpotifyAPI | None = None, skip_checks: bool = False)
+

Bases: RemoteAlbum[SpotifyTrack], SpotifyCollectionLoader[SpotifyTrack]

+

Extracts key album data from a Spotify API JSON response.

+
+
Parameters:
+

response – The Spotify API JSON response

+
+
+
+
+property album_artist
+

The album artist for this album

+
+ +
+
+property artist
+

Joined string representation of all artists on this album ordered by frequency of appearance

+
+ +
+
+property artists: list[SpotifyArtist]
+

List of artists ordered by frequency of appearance on the tracks on this album

+
+ +
+
+property compilation
+

Is this album a compilation

+
+ +
+
+property day
+

The day this album was released

+
+ +
+
+property genres
+

List of genres ordered by frequency of appearance on the tracks on this album

+
+ +
+
+property has_image
+

Does this album have an image

+
+ +
+ +

The images associated with this album in the form {image name: image link}

+
+ +
+
+property length
+

Total duration of all tracks on this album in seconds

+
+ +
+
+property month
+

The month this album was released

+
+ +
+
+property name
+

The album name

+
+ +
+
+property rating
+

Rating of this album

+
+ +
+
+refresh(skip_checks: bool = False) None
+

Refresh this object by updating from the stored API response. +Useful for updating stored variables after making changes to the stored API response manually.

+
+ +
+
+reload(extend_artists: bool = True, extend_tracks: bool = True, use_cache: bool = True, *_, **__) None
+

Reload this object from the API, calling all required endpoints +to get a complete set of data for this item type

+
+
Parameters:
+

use_cache – Use the cache when calling the API endpoint. Set as False to refresh the cached response.

+
+
+
+ +
+
+property track_total
+

The total number of tracks on this album

+
+ +
+
+property tracks: list[SpotifyTrack]
+

The tracks on this album

+
+ +
+
+property year
+

The year this album was released

+
+ +
+ +
+
+class syncify.spotify.object.SpotifyArtist(response: dict[str, Any], api: SpotifyAPI | None = None, skip_checks: bool = False)
+

Bases: RemoteArtist[SpotifyAlbum], SpotifyCollectionLoader[SpotifyAlbum]

+

Extracts key artist data from a Spotify API JSON response.

+
+
+property albums: list[SpotifyAlbum]
+

List of albums ordered by frequency of appearance on the tracks by this artist

+
+ +
+
+property artist
+

The artist name

+
+ +
+
+property followers: int | None
+

The total number of followers for this artist

+
+ +
+
+property genres
+

List of genres for this artist

+
+ +
+ +

The images associated with this artist in the form {image name: image link}

+
+ +
+
+property items: list[SpotifyAlbum]
+

The albums this artist is featured on

+
+ +
+
+classmethod load(value: str | dict[str, Any], api: SpotifyAPI, extend_albums: bool = False, extend_tracks: bool = False, use_cache: bool = True, *_, **__) Self
+

Generate a new object, calling all required endpoints to get a complete set of data for this item type.

+
+
value may be:
    +
  • A string representing a URL/URI/ID.

  • +
  • A remote API JSON response for a collection with a valid ID value under an id key.

  • +
+
+
+
+
Parameters:
+
    +
  • value – The value representing some remote collection. See description for allowed value types.

  • +
  • api – An authorised API object to load the object from.

  • +
  • use_cache – Use the cache when calling the API endpoint. Set as False to refresh the cached response.

  • +
  • items – Optionally, give a list of available items to build a response for this collection. +In doing so, the method will first try to find the API responses for the items of this collection +in the given list before calling the API for any items not found there. +This helps reduce the number of API calls made on initialisation.

  • +
+
+
+
+ +
+
+property name
+

The artist name

+
+ +
+
+property rating
+

The popularity of this artist

+
+ +
+
+refresh(skip_checks: bool = False) None
+

Refresh this object by updating from the stored API response. +Useful for updating stored variables after making changes to the stored API response manually.

+
+ +
+
+reload(extend_albums: bool = False, extend_tracks: bool = False, use_cache: bool = True, *_, **__) None
+

Reload this object from the API, calling all required endpoints +to get a complete set of data for this item type

+
+
Parameters:
+

use_cache – Use the cache when calling the API endpoint. Set as False to refresh the cached response.

+
+
+
+ +
+ +
+
+class syncify.spotify.object.SpotifyCollection
+

Bases: RemoteCollection, SpotifyDataWrangler, Generic

+

Generic class for storing a collection of Spotify objects.

+
+ +
+
+class syncify.spotify.object.SpotifyCollectionLoader(response: dict[str, Any], api: SpotifyAPI | None = None, skip_checks: bool = False)
+

Bases: SpotifyObjectLoaderMixin, SpotifyCollection, Generic

+

Generic class for storing a collection of Spotify objects that can be loaded from an API response.

+
+
+api: SpotifyAPI
+
+ +
+
+classmethod load(value: str | MutableMapping[str, Any], api: SpotifyAPI, items: Iterable[SpotifyTrack] = (), extend_tracks: bool = False, use_cache: bool = True, leave_bar: bool = True, *args, **kwargs) Self
+

Generate a new object, calling all required endpoints to get a complete set of data for this item type.

+
+
value may be:
    +
  • A string representing a URL/URI/ID.

  • +
  • A remote API JSON response for a collection with a valid ID value under an id key.

  • +
+
+
+
+
Parameters:
+
    +
  • value – The value representing some remote collection. See description for allowed value types.

  • +
  • api – An authorised API object to load the object from.

  • +
  • use_cache – Use the cache when calling the API endpoint. Set as False to refresh the cached response.

  • +
  • items – Optionally, give a list of available items to build a response for this collection. +In doing so, the method will first try to find the API responses for the items of this collection +in the given list before calling the API for any items not found there. +This helps reduce the number of API calls made on initialisation.

  • +
+
+
+
+ +
+ +
+
+class syncify.spotify.object.SpotifyItemWranglerMixin(response: dict[str, Any], api: SpotifyAPI | None = None, skip_checks: bool = False)
+

Bases: SpotifyItem, SpotifyDataWrangler

+
+
+api: SpotifyAPI
+
+ +
+ +
+
+class syncify.spotify.object.SpotifyObjectLoaderMixin(response: dict[str, Any], api: SpotifyAPI | None = None, skip_checks: bool = False)
+

Bases: RemoteCollectionLoader, SpotifyObject, Generic

+

Mixin for RemoteCollectionLoader and SpotifyObject

+
+
+api: SpotifyAPI
+
+ +
+ +
+
+class syncify.spotify.object.SpotifyPlaylist(response: dict[str, Any], api: SpotifyAPI | None = None, skip_checks: bool = False)
+

Bases: RemotePlaylist[SpotifyTrack], SpotifyCollectionLoader[SpotifyTrack]

+

Extracts key playlist data from a Spotify API JSON response.

+
+
Parameters:
+

response – The Spotify API JSON response

+
+
+
+
+property collaborative
+

Are other users allowed to modify this playlist

+
+ +
+
+property date_added
+

A map of {URI: date} for each item for when that item was added to the playlist

+
+ +
+
+property date_created
+

datetime object representing when the first track was added to this playlist

+
+ +
+
+property date_modified
+

datetime object representing when a track was most recently added/removed

+
+ +
+
+property description
+

Description of this playlist

+
+ +
+
+property followers
+

The number of followers this playlist has

+
+ +
+
+property has_image
+

Does this playlist have an image

+
+ +
+ +

The images associated with this playlist in the form {image name: image link}

+
+ +
+
+property name
+

The name of this playlist

+
+ +
+
+property owner_id
+

The ID of the owner of this playlist

+
+ +
+
+property owner_name
+

The name of the owner of this playlist

+
+ +
+
+property public
+

Can other users access this playlist

+
+ +
+
+refresh(skip_checks: bool = False) None
+

Refresh this object by updating from the stored API response. +Useful for updating stored variables after making changes to the stored API response manually.

+
+ +
+
+reload(extend_tracks: bool = False, use_cache: bool = True, *_, **__) None
+

Reload this object from the API, calling all required endpoints +to get a complete set of data for this item type

+
+
Parameters:
+

use_cache – Use the cache when calling the API endpoint. Set as False to refresh the cached response.

+
+
+
+ +
+
+property track_total
+

The total number of tracks in this playlist

+
+ +
+
+property tracks
+

The tracks in this playlist

+
+ +
+ +
+
+class syncify.spotify.object.SpotifyTrack(response: dict[str, Any], api: SpotifyAPI | None = None, skip_checks: bool = False)
+

Bases: SpotifyItemWranglerMixin, RemoteTrack

+

Extracts key track data from a Spotify API JSON response.

+
+
Parameters:
+

response – The Spotify API JSON response.

+
+
+
+
+property album
+

The album this track is featured on

+
+ +
+
+property album_artist
+

The artist of the album this track is featured on

+
+ +
+
+property artist
+

Joined string representation of all artists featured on this track

+
+ +
+
+property artists: list[SpotifyArtist]
+

List of all artists featured on this track.

+
+ +
+
+property bpm
+

The tempo of this track

+
+ +
+
+property comments
+

Comments associated with this track set by the user

+
+ +
+
+property compilation: bool
+

Is the album this track is featured on a compilation

+
+ +
+
+property day
+

The day this track was released

+
+ +
+
+property disc_number: int
+

The number of the disc from the album this track is featured on

+
+ +
+
+property disc_total
+

The total number the discs from the album this track is featured on

+
+ +
+
+property genres
+

List of genres for the album this track is featured on. +If not found, genres from the main artist are given.

+
+ +
+
+property has_image
+

Does the album this track is associated with have an image

+
+ +
+ +

The images associated with the album this track is featured on in the form {image name: image link}

+
+ +
+
+property key
+

The key of this track in alphabetical musical notation format

+
+ +
+
+property length
+

Total duration of this track in seconds

+
+ +
+
+classmethod load(value: str | dict[str, Any], api: SpotifyAPI, features: bool = False, analysis: bool = False, extend_album: bool = False, extend_artists: bool = False, use_cache: bool = True, *_, **__) Self
+

Generate a new object of this class, +calling all required endpoints to get a complete set of data for this item type.

+
+
value may be:
    +
  • A string representing a URL/URI/ID.

  • +
  • A remote API JSON response for a collection with a valid ID value under an id key.

  • +
+
+
+
+
Parameters:
+
    +
  • value – The value representing some remote object. See description for allowed value types.

  • +
  • api – An authorised API object to load the object from.

  • +
  • use_cache – Use the cache when calling the API endpoint. Set as False to refresh the cached response.

  • +
+
+
+
+ +
+
+property month
+

The month this track was released

+
+ +
+
+property name
+

A name for this object

+
+ +
+
+property rating
+

The rating for this track

+
+ +
+
+refresh(skip_checks: bool = False) None
+

Refresh this object by updating from the stored API response. +Useful for updating stored variables after making changes to the stored API response manually.

+
+ +
+
+reload(features: bool = False, analysis: bool = False, extend_album: bool = False, extend_artists: bool = False, use_cache: bool = True, *_, **__) None
+

Reload this object from the API, calling all required endpoints +to get a complete set of data for this item type

+
+
Parameters:
+

use_cache – Use the cache when calling the API endpoint. Set as False to refresh the cached response.

+
+
+
+ +
+
+property title: str
+

This track’s title

+
+ +
+
+property track_number: int
+

The position this track has on the album it is featured on

+
+ +
+
+property track_total
+

The track number of tracks on the album this track is featured on

+
+ +
+
+property year
+

The year this track was released

+
+ +
+ +
+
+

Module contents

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/_build/syncify.spotify.processors.html b/_build/syncify.spotify.processors.html new file mode 100644 index 00000000..c7c438f3 --- /dev/null +++ b/_build/syncify.spotify.processors.html @@ -0,0 +1,294 @@ + + + + + + + + syncify.spotify.processors package — Syncify 0.3 documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

syncify.spotify.processors package

+
+

Submodules

+
+
+

syncify.spotify.processors.processors module

+
+
+class syncify.spotify.processors.processors.SpotifyItemChecker(api: RemoteAPI, interval: int = 10, allow_karaoke: bool = False)
+

Bases: SpotifyDataWrangler, RemoteItemChecker

+
+
+allow_karaoke
+
+ +
+
+api
+
+ +
+
+final_skipped: list[Track]
+
+ +
+
+final_switched: list[Track]
+
+ +
+
+final_unavailable: list[Track]
+
+ +
+
+interval
+
+ +
+
+playlist_name_collection
+
+ +
+
+playlist_name_urls
+
+ +
+
+quit
+
+ +
+
+remaining: list[Track]
+
+ +
+
+skip
+
+ +
+
+switched: list[Track]
+
+ +
+ +
+
+class syncify.spotify.processors.processors.SpotifyItemSearcher(api: RemoteAPI, use_cache: bool = False)
+

Bases: SpotifyDataWrangler, RemoteItemSearcher

+
+
+api
+
+ +
+
+use_cache
+
+ +
+ +
+
+

syncify.spotify.processors.wrangle module

+
+
+class syncify.spotify.processors.wrangle.SpotifyDataWrangler
+

Bases: RemoteDataWrangler, SpotifyRemote

+
+
+classmethod convert(value: str, kind: RemoteObjectType | None = None, type_in: RemoteIDType = RemoteIDType.ALL, type_out: RemoteIDType = RemoteIDType.ID) str
+

Converts ID to required format - API URL, EXT URL, URI, or ID.

+
+
Parameters:
+
    +
  • value – URL/URI/ID to convert.

  • +
  • kind – Optionally, give the item type of the input value to skip some checks. +This is required when the given value is an ID.

  • +
  • type_in – Optionally, give the ID type of the input value to skip some checks.

  • +
  • type_out – The ID type of the output value.

  • +
+
+
Returns:
+

Formatted string.

+
+
Raises:
+

RemoteIDTypeError – Raised when the function cannot determine the item type +of the input value.

+
+
+
+ +
+
+classmethod extract_ids(values: str | MutableSequence[str] | MutableMapping[str, Any] | MutableSequence[MutableMapping[str, Any]], kind: RemoteObjectType | None = None) list[str]
+

Extract a list of IDs from input values.

+
+
values may be:
    +
  • A string representing a URL/URI/ID.

  • +
  • A MutableSequence of strings representing URLs/URIs/IDs of the same type.

  • +
  • +
    A remote API JSON response for a collection including:
      +
    • a valid ID value under an id key,

    • +
    • a valid item type value under a type key if kind is None.

    • +
    +
    +
    +
  • +
  • A MutableSequence of remote API JSON responses for a collection including the same structure as above.

  • +
+
+
+
+
Parameters:
+
    +
  • values – The values representing some remote objects. See description for allowed value types. +These items may be of mixed item types e.g. some tracks AND some artists.

  • +
  • kind – Optionally, give the item type of the input value to skip some checks. +This is required when the given value is an ID.

  • +
+
+
Returns:
+

List of IDs.

+
+
Raises:
+

RemoteError – Raised when the function cannot determine the item type of the input values. +Or when it does not recognise the type of the input values parameter.

+
+
+
+ +
+
+static get_id_type(value: str, kind: RemoteObjectType | None = None) RemoteIDType
+

Determine the remote ID type of the given value and return its type.

+
+
Parameters:
+
    +
  • value – URL/URI/ID to check.

  • +
  • kind – When this is equal to USER, ignore checks and always return ID as type.

  • +
+
+
Returns:
+

The RemoteIDType.

+
+
Raises:
+

RemoteIDTypeError – Raised when the function cannot determine the ID type +of the input value.

+
+
+
+ +
+
+unavailable_uri_dummy = 'spotify:track:unavailable'
+
+ +
+
+classmethod validate_id_type(value: str, kind: RemoteIDType = RemoteIDType.ALL) bool
+

Check that the given value is a type of remote ID given by ``kind ``

+
+ +
+ +
+
+

Module contents

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/_build/syncify.utils.html b/_build/syncify.utils.html new file mode 100644 index 00000000..7e6eafc4 --- /dev/null +++ b/_build/syncify.utils.html @@ -0,0 +1,359 @@ + + + + + + + + syncify.utils package — Syncify 0.3 documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

syncify.utils package

+
+

Submodules

+
+
+

syncify.utils.helpers module

+
+
+syncify.utils.helpers.align_and_truncate(value: Any, max_width: int = 0, right_align: bool = False) str
+

Align string with space padding. Truncate any string longer than max width with …

+
+ +
+
+syncify.utils.helpers.correct_platform_separators(path: str | None) str | None
+

Correct separators in the given path to match those used by the current platform

+
+ +
+
+syncify.utils.helpers.flatten_nested(nested: MutableMapping, previous: MutableSequence | None = None) list[T]
+

Flatten the final layers of the values of a nested map to a single list

+
+ +
+
+syncify.utils.helpers.get_max_width(values: Collection[Any], min_width: int = 15, max_width: int = 50) int
+

Get max width of given list of values for column-aligned logging

+
+ +
+
+syncify.utils.helpers.get_most_common_values(values: Iterable[Any]) list[Any]
+

Get an ordered list of the most common values for a given collection of values

+
+ +
+
+syncify.utils.helpers.get_user_input(text: str | None = None) str
+

Print formatted dialog with optional text and get the user’s input.

+
+ +
+
+syncify.utils.helpers.limit_value(value: int | float, floor: int | float = 1, ceil: int | float = 50) int | float
+

Limit a given value to always be between some floor and ceil

+
+ +
+
+syncify.utils.helpers.merge_maps(source: T, new: Mapping, extend: bool = True, overwrite: bool = False) T
+

Recursively update a given source map in place with a new map.

+
+
Parameters:
+
    +
  • source – The source map.

  • +
  • new – The new map with values to update for the source map.

  • +
  • extend – When a value is a list and a list is already present in the source map, extend the list when True. +When False, only replace the list if overwrite is True.

  • +
  • overwrite – When True, overwrite any value in the source list destructively.

  • +
+
+
Returns:
+

The updated dict.

+
+
+
+ +
+
+syncify.utils.helpers.safe_format_map(value: T, format_map: Mapping[str, Any]) T
+

Apply a format_map to a given value ignoring missing keys. +If value is a map, apply the format_map recursively.

+
+ +
+
+syncify.utils.helpers.strip_ignore_words(value: str, words: Iterable[str] | None = frozenset({'A', 'The'})) tuple[bool, str]
+

Remove ignorable words from the beginning of a string. +Useful for sorting collections strings with ignorable start words and/or special characters. +Only removes the first word it finds at the start of the string.

+
+
Returns:
+

Tuple of (True if the string starts with some special character, the formatted string)

+
+
+
+ +
+
+syncify.utils.helpers.to_collection(data: ~typing.Any, cls: type[T] = <class 'tuple'>) T | None
+

Safely turn any object into a collection of a given type T. +Strings are converted to collections of size 1 where the first element is the string. +Returns None if value is None.

+
+ +
+
+syncify.utils.helpers.unique_list(value: Iterable[Any]) list[Any]
+

Returns a copy of the given value that contains only unique elements. +Useful for producing unique lists whilst preserving order.

+
+ +
+
+

syncify.utils.logger module

+
+
+class syncify.utils.logger.CurrentTimeRotatingFileHandler(filename: str | None = None, encoding: str | None = None, when: str | None = None, interval: int | None = None, count: int | None = None, delay: bool = False, errors: str | None = None)
+

Bases: BaseRotatingHandler

+
+
Parameters:
+
    +
  • filename – The full path to the log file. +Optionally, include a ‘{}’ part in the path to format in the current datetime. +When None, defaults to ‘{}.log’

  • +
  • encoding – When not None, it is used to open the file with that encoding.

  • +
  • when – The timespan for ‘interval’ which is used together to calculate the timedelta. +Accepts same values as TimeMapper.

  • +
  • interval – The multiplier for when. +When combined with when, gives the negative timedelta relative to now +which is the maximum datetime to keep logs for.

  • +
  • count – The maximum number of files to keep.

  • +
  • delay – When True, the file opening is deferred until the first call to emit().

  • +
  • errors – Used to determine how encoding errors are handled.

  • +
+
+
+
+
+rotator(unformatted: str, formatted: str)
+

Rotates the files in the folder on the given unformatted path. +Removes files older than self.delta and the oldest files when number of files >= count +until number of files <= count. formatted path is excluded from processing.

+
+ +
+
+static shouldRollover(*_, **__) bool
+

Always returns False. Rotation happens on __init__ and only needs to happen once.

+
+ +
+ +
+
+class syncify.utils.logger.LogConsoleFilter(name: str = '', module_width: int = 40)
+

Bases: Filter

+

Filter for logging to the console.

+
+
+filter(record: LogRecord) LogRecord | None
+

Determine if the specified record is to be logged.

+

Returns True if the record should be logged, or False otherwise. +If deemed appropriate, the record may be modified in-place.

+
+ +
+ +
+
+class syncify.utils.logger.LogFileFilter(name: str = '', module_width: int = 40)
+

Bases: Filter

+

Filter for logging to a file.

+
+
+filter(record: LogRecord) LogRecord
+

Determine if the specified record is to be logged.

+

Returns True if the record should be logged, or False otherwise. +If deemed appropriate, the record may be modified in-place.

+
+ +
+ +
+
+class syncify.utils.logger.SyncifyLogger(name: str, level: int | str = 0)
+

Bases: Logger

+

The logger for all logging operations in Syncify.

+
+
+compact: bool = False
+
+ +
+
+property file_paths: list[str]
+

Get a list of the paths of all file handlers for this logger

+
+ +
+
+get_progress_bar(iterable: Iterable | None = None, total: T | int | None = None, **kwargs) tqdm_asyncio | Iterable
+

Wrapper for tqdm progress bar. For kwargs, see tqdm_std

+
+ +
+
+info_extra(msg, *args, **kwargs) None
+

Log ‘msg % args’ with severity ‘INFO_EXTRA’.

+
+ +
+
+print(level: int = 51) None
+

Print a new line only when DEBUG < logger level <= level for all console handlers

+
+ +
+
+report(msg, *args, **kwargs) None
+

Log ‘msg % args’ with severity ‘REPORT’.

+
+ +
+
+stat(msg, *args, **kwargs) None
+

Log ‘msg % args’ with severity ‘STAT’.

+
+ +
+
+property stdout_handlers: list[StreamHandler]
+

Get a list of all logging.StreamHandler handlers that log to stdout

+
+ +
+ +
+
+syncify.utils.logger.format_full_func_name(record: LogRecord, width: int = 40) None
+

Set fully qualified path name to function including class name to the given record. +Optionally, provide a max width to attempt to truncate the path name to +by taking only the first letter of each part of the path until the length is equal to width.

+
+ +
+
+

syncify.utils.printers module

+
+
+syncify.utils.printers.print_line(text: str = '', line_char: str = '-') None
+

Print an aligned line with the given text in the centre of the terminal

+
+ +
+ +

Pretty print the Syncify logo in the centre of the terminal

+
+ +
+
+syncify.utils.printers.print_time(seconds: float) None
+

Print the time in minutes and seconds in the centre of the terminal

+
+ +
+
+

Module contents

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/doc/conf.py b/doc/conf.py new file mode 100644 index 00000000..aa36a322 --- /dev/null +++ b/doc/conf.py @@ -0,0 +1,28 @@ +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information + +project = 'Syncify' +copyright = '2024, geo-martino' +author = 'geo-martino' +release = '0.3' + +# -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration + +extensions = ['sphinx.ext.autodoc'] + +templates_path = ['_templates'] +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + + + +# -- Options for HTML output ------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output + +html_theme = 'alabaster' +html_static_path = ['_static'] diff --git a/doc/index.rst b/doc/index.rst new file mode 100644 index 00000000..fad44db0 --- /dev/null +++ b/doc/index.rst @@ -0,0 +1,20 @@ +.. Syncify documentation master file, created by + sphinx-quickstart on Fri Jan 5 21:58:01 2024. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to Syncify's documentation! +=================================== + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/pyproject.toml b/pyproject.toml index 99225f57..70c52bbe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,6 +41,14 @@ test = [ "pycountry~=23.12", "requests-mock~=1.11", ] +dev = [ + "grip~=4.6", +] +docs = [ + "sphinx~=7.2", + "sphinx_rtd_theme~=2.0", + "myst_parser~=2.0", +] [project.urls] "Source code" = "https://github.com/geo-martino/syncify" diff --git a/src/syncify/spotify/object.py b/src/syncify/spotify/object.py index 3c66fa1b..d59e8903 100644 --- a/src/syncify/spotify/object.py +++ b/src/syncify/spotify/object.py @@ -699,9 +699,9 @@ def reload( self._check_for_api() response = self.api.handler.get(url=self.url, use_cache=use_cache, log_pad=self._url_pad) - if extend_albums or extend_tracks: + if extend_albums: self.api.get_artist_albums(response, use_cache=use_cache) - if extend_tracks: + if extend_albums and extend_tracks: kind = RemoteObjectType.ALBUM key = self.api.collection_item_map[kind] for album in response["albums"]["items"]: diff --git a/tests/spotify/library/test_spotify_track.py b/tests/spotify/library/test_spotify_track.py index 1faab9a3..69b955df 100644 --- a/tests/spotify/library/test_spotify_track.py +++ b/tests/spotify/library/test_spotify_track.py @@ -188,7 +188,7 @@ def test_reload(self, response_valid: dict[str, Any], api: SpotifyAPI): assert not track.bpm track.api = api - track.reload() + track.reload(features=True) assert track.album if track.response["audio_features"]["key"] > -1: assert track.key