]> kaliko git repositories - python-musicpdaio.git/commitdiff
Add Sphinx documentation
authorkaliko <kaliko@azylum.org>
Tue, 5 Mar 2024 16:35:07 +0000 (17:35 +0100)
committerkaliko <kaliko@azylum.org>
Tue, 5 Mar 2024 16:59:00 +0000 (17:59 +0100)
doc/Makefile [new file with mode: 0644]
doc/source/conf.py [new file with mode: 0644]
doc/source/explanations.rst [new file with mode: 0644]
doc/source/index.rst [new file with mode: 0644]
doc/source/reference.rst [new file with mode: 0644]
doc/source/tutorial.rst [new file with mode: 0644]
doc/source/tutorial/mpdaio [new symlink]
doc/source/tutorial/tutorial-00.py [new file with mode: 0644]
doc/source/tutorial/tutorial-01.py [new file with mode: 0644]

diff --git a/doc/Makefile b/doc/Makefile
new file mode 100644 (file)
index 0000000..d0c3cbf
--- /dev/null
@@ -0,0 +1,20 @@
+# Minimal makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line, and also
+# from the environment for the first two.
+SPHINXOPTS    ?=
+SPHINXBUILD   ?= sphinx-build
+SOURCEDIR     = source
+BUILDDIR      = build
+
+# Put it first so that "make" without argument is like "make help".
+help:
+       @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+.PHONY: help Makefile
+
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).
+%: Makefile
+       @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
diff --git a/doc/source/conf.py b/doc/source/conf.py
new file mode 100644 (file)
index 0000000..6377b03
--- /dev/null
@@ -0,0 +1,42 @@
+# 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 = 'musicpdaio'
+copyright = '2024, kaliko'
+author = 'kaliko'
+release = '0.0.1'
+
+# -- General configuration ---------------------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
+
+extensions = [
+    'sphinx.ext.autodoc',
+    'sphinx.ext.intersphinx',
+    'sphinx.ext.viewcode',
+    'sphinx.ext.todo',
+]
+
+templates_path = ['_templates']
+exclude_patterns = []
+
+# -- 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']
+html_theme_options = {
+    'page_width' : '1024px',
+    'fixed_sidebar': 'true',
+    }
+
+# -- Options for intersphinx extension ---------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/extensions/intersphinx.html#configuration
+
+intersphinx_mapping = {
+    'python': ('https://docs.python.org/3', None),
+}
diff --git a/doc/source/explanations.rst b/doc/source/explanations.rst
new file mode 100644 (file)
index 0000000..48724bf
--- /dev/null
@@ -0,0 +1,82 @@
+.. _explanations:
+
+Explanations
+============
+
+What is musicpdaio?
+-------------------
+
+ |  « Concurrency is about dealing with lots of things at once. »
+ |  Concurrency is not Parallelism -- Rob Pike
+
+**musicpdaio** is the asyncio_ port of python-musicpd_.
+
+The goal of this project is to keep python-musicpd_ simplicity and provide
+asyncio_ support.
+
+Should I use it?
+----------------
+
+ * If you need a plain MPD client to manage you MPD server, then stick with
+   no-ansynio module python-musicpd_
+ * If you're building a interactive client, concurrent access to MPD or plugin
+   into another asyncio project then use musicpdaio.
+
+
+Using the client library
+-------------------------
+
+The client library can be used as follows:
+
+.. code-block:: python
+
+    client = mpdaio.MPDClient()       # create client object
+    await client.ping()               # test the connection, using default host/port, cf. Reference
+    print(client.version)             # print the MPD protocol version
+    await client.setvol('42')         # sets the volume
+    await client.close()              # disconnect from the server
+
+The MPD command protocol exchanges line-based text records. The client emits a
+command with optional arguments. In the example above the client sends a
+`setvol` command with the string argument `42`.
+
+MPD commands are exposed as :py:class:`mpdaio.MPDClient` methods. Methods
+**arguments are python strings**. Some commands are composed of more than one word
+(ie "**tagtypes [disable|enable|all]**"), for these use a `snake case`_ style to
+access the method. Then **"tagtypes enable"** command is called with
+**"tagtypes_enable"**.
+
+Remember MPD protocol is text based, then all MPD command arguments are UTF-8
+strings. In the example above, an integer can be used as argument for the
+`setvol` command, but it is then evaluated as a string when the command is
+written to the socket. To avoid confusion use regular string instead of relying
+on object string representation.
+
+:py:class:`mpdaio.MPDClient` methods returns different kinds of objects
+depending on the command. Could be :py:obj:`None`, a single object as a
+:py:obj:`str` or a :py:obj:`dict`, a list of :py:obj:`dict`.
+
+Then :py:class:`mpdaio.MPDClient` **methods signatures** are not hard coded
+within this module since the protocol is handled on the server side. Please
+refer to the protocol and MPD commands in `MPD protocol documentation`_ to
+learn how to call commands and what kind of arguments they expect.
+
+Some examples are provided for the most common cases, see :ref:`tutorial`.
+
+For a list of currently supported commands in this python module see
+:ref:`commands`.
+
+**musicpdaio** tries to come with sane defaults, then running
+:py:class:`mpdaio.MPDClient` with no explicit argument will try defaults values
+to connect to MPD. Cf. :ref:`reference` for more about defaults.
+
+
+.. _environment_variables:
+
+
+.. _snake case: https://en.wikipedia.org/wiki/Snake_case
+.. _MPD protocol documentation: http://www.musicpd.org/doc/protocol/
+.. _asyncio: https://docs.python.org/3/library/asyncio.html
+.. _python-musicpd: https://kaliko.gitlab.io/python-musicpd
+
+.. vim: spell spelllang=en
diff --git a/doc/source/index.rst b/doc/source/index.rst
new file mode 100644 (file)
index 0000000..0c20408
--- /dev/null
@@ -0,0 +1,25 @@
+Welcome to musicpdaio's documentation!
+======================================
+
+The documentation is structured by following the `Diátaxis`_ principles:
+tutorials and explanation are mainly useful to discover and learn, howtos and
+reference are more useful when you are familiar with musicpdaio already and you
+have some specific action to perform or goal to achieve.
+
+.. toctree::
+   :maxdepth: 2
+
+   tutorial
+   explanations
+   reference
+
+
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+
+.. _Diátaxis: https://diataxis.fr/
diff --git a/doc/source/reference.rst b/doc/source/reference.rst
new file mode 100644 (file)
index 0000000..f71444c
--- /dev/null
@@ -0,0 +1,53 @@
+.. _reference:
+
+Reference
+=========
+
+Environment variables
+---------------------
+
+:py:class:`mpdaio.MPDClient` honors the following environment variables:
+
+.. envvar:: MPD_HOST
+
+   MPD host (:abbr:`FQDN (fully qualified domain name)`, IP, socket path or abstract socket) and password.
+
+    | To define a **password** set :envvar:`MPD_HOST` to "*password@host*" (password only "*password@*")
+    | For **abstract socket** use "@" as prefix : "*@socket*" and then with a password  "*pass@@socket*"
+    | Regular **unix socket** are set with an absolute path: "*/run/mpd/socket*"
+
+.. envvar:: MPD_PORT
+
+   MPD port, relevant for TCP socket only
+
+.. envvar:: MPD_TIMEOUT
+
+   socket timeout when connecting to MPD and waiting for MPD’s response (in seconds)
+
+.. envvar:: XDG_RUNTIME_DIR
+
+   path to look for potential socket
+
+.. _default_settings:
+
+Default settings
+----------------
+
+Default host:
+ * use :envvar:`MPD_HOST` environment variable if set, extract password if present,
+ * else looks for an existing file in :envvar:`${XDG_RUNTIME_DIR:-/run/}/mpd/socket`
+ * else set host to ``localhost``
+
+Default port:
+ * use :envvar:`MPD_PORT` environment variable is set
+ * else use ``6600``
+
+Default timeout:
+ * use :envvar:`MPD_TIMEOUT` is set
+ * else use :py:obj:`mpdaio.CONNECTION_TIMEOUT`
+
+
+Changelog
+---------
+
+No release yet
diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst
new file mode 100644 (file)
index 0000000..31cbde9
--- /dev/null
@@ -0,0 +1,36 @@
+.. _tutorial:
+
+Tutorials
+=========
+
+Install
+-------
+
+For now the code is in early development stage. No releases are made.
+
+.. code:: bash
+
+   # Use a virtualenv
+   python -m venv .../path/to/my/venv
+   . .../path/to/my/venv/bin/activate
+   pip install git+https://codeberg.org/MusicPlayerDaemon/python-musicpdaio.git@main
+
+
+.. todo::
+
+   Updating a previous installation via `pip install git+https`.
+
+Getting started
+----------------
+
+
+.. literalinclude:: tutorial/tutorial-00.py
+
+
+Concurrency
+-----------
+
+.. literalinclude:: tutorial/tutorial-01.py
+
+
+.. vim: spell spelllang=en
diff --git a/doc/source/tutorial/mpdaio b/doc/source/tutorial/mpdaio
new file mode 120000 (symlink)
index 0000000..7af2e50
--- /dev/null
@@ -0,0 +1 @@
+../../../mpdaio
\ No newline at end of file
diff --git a/doc/source/tutorial/tutorial-00.py b/doc/source/tutorial/tutorial-00.py
new file mode 100644 (file)
index 0000000..dea5826
--- /dev/null
@@ -0,0 +1,45 @@
+import asyncio
+import logging
+
+from mpdaio.client import MPDClient
+
+# Configure loggers
+logging.basicConfig(level=logging.INFO, format='%(levelname)-8s %(message)s')
+logging.getLogger("asyncio").setLevel(logging.WARNING)
+# debug level level will show where defaults settings come from
+log = logging.getLogger('mpdaio.client')
+log.setLevel(logging.DEBUG)
+
+
+async def run():
+    # Explicit host declaration
+    #client = MPDClient(host='example.org', port='6601')
+
+    # Use defaults
+    client = MPDClient()
+    # MPDClient use MPD_HOST/MPD_PORT env var if set
+    # else test ${XDG_RUNTIME_DIR}/mpd/socket for existence
+    # finnally fallback to localhost:6600
+
+    # Make an initial connection to MPD server
+    # The connection is kept open an reused for later commands
+    await client.ping()
+
+    status = await client.status()
+    if status.get('state') == 'play':
+        current_song_id = status.get('songid')
+        current_song = await client.playlistid(current_song_id)
+        log.info(f'Playing   : {current_song[0].get("file")}')
+        next_song_id = status.get('nextsongid', None)
+        if next_song_id:
+            next_song = await client.playlistid(next_song_id)
+            log.info(f'Next song : {next_song[0].get("file")}')
+    else:
+        log.info('Not playing')
+
+    # Closes any remaining connections to MPD server
+    await client.close()
+
+
+if __name__ == '__main__':
+    asyncio.run(run())
diff --git a/doc/source/tutorial/tutorial-01.py b/doc/source/tutorial/tutorial-01.py
new file mode 100644 (file)
index 0000000..1ef066c
--- /dev/null
@@ -0,0 +1,30 @@
+import asyncio
+import logging
+
+from mpdaio.client import MPDClient
+
+# Configure loggers
+logging.basicConfig(level=logging.INFO, format='%(levelname)-8s %(message)s')
+logging.getLogger("asyncio").setLevel(logging.WARNING)
+# debug level level will show where defaults settings come from
+log = logging.getLogger('mpdaio.client')
+log.setLevel(logging.DEBUG)
+
+
+async def run():
+    # Use defaults to access MPD server
+    client = MPDClient()
+
+    # Make an initial connection to MPD server
+    # The connection is kept open an reused for later commands
+    await client.ping()
+
+    # Each task gathered here will run with it's own connection
+    await asyncio.gather(...)
+
+    # Closes all connections to MPD server
+    await client.close()
+
+
+if __name__ == '__main__':
+    asyncio.run(run())