From e566456d822d183387b41115adee7cef3650216d Mon Sep 17 00:00:00 2001 From: Russell Martin Date: Thu, 5 Dec 2024 20:53:08 -0500 Subject: [PATCH] Add docs for async support --- docs/source/api.rst | 2 +- docs/source/apidoc/app.rst | 2 +- docs/source/apidoc/attrdict.rst | 2 +- docs/source/apidoc/auth.rst | 2 +- docs/source/apidoc/client.rst | 2 +- docs/source/apidoc/definitions.rst | 2 +- docs/source/apidoc/log.rst | 2 +- docs/source/apidoc/request.rst | 2 +- docs/source/apidoc/rss.rst | 2 +- docs/source/apidoc/search.rst | 2 +- docs/source/apidoc/sync.rst | 2 +- docs/source/apidoc/torrentcreator.rst | 2 +- docs/source/apidoc/torrents.rst | 2 +- docs/source/apidoc/transfer.rst | 2 +- docs/source/apidoc/version.rst | 2 +- docs/source/async.rst | 33 ++++++++++++++++++++++++++ docs/source/behavior&configuration.rst | 6 ++--- docs/source/index.rst | 3 ++- docs/source/introduction.rst | 14 ++++++----- docs/source/performance.rst | 14 +++++++---- pyproject.toml | 2 +- 21 files changed, 72 insertions(+), 30 deletions(-) create mode 100644 docs/source/async.rst diff --git a/docs/source/api.rst b/docs/source/api.rst index b91667a2f..fbb621843 100644 --- a/docs/source/api.rst +++ b/docs/source/api.rst @@ -1,5 +1,5 @@ API Reference -================================ +============= .. toctree:: :maxdepth: 2 diff --git a/docs/source/apidoc/app.rst b/docs/source/apidoc/app.rst index dfb2d5ef6..c4664fc4a 100644 --- a/docs/source/apidoc/app.rst +++ b/docs/source/apidoc/app.rst @@ -1,5 +1,5 @@ Application -================================ +=========== .. autoclass:: qbittorrentapi.app.AppAPIMixIn :members: diff --git a/docs/source/apidoc/attrdict.rst b/docs/source/apidoc/attrdict.rst index 444f99710..326f5a945 100644 --- a/docs/source/apidoc/attrdict.rst +++ b/docs/source/apidoc/attrdict.rst @@ -1,5 +1,5 @@ AttrDict (internal) -================================ +=================== Copyright (c) 2013 Brendan Curran-Johnson diff --git a/docs/source/apidoc/auth.rst b/docs/source/apidoc/auth.rst index 8d70daf1b..444d21d32 100644 --- a/docs/source/apidoc/auth.rst +++ b/docs/source/apidoc/auth.rst @@ -1,5 +1,5 @@ Authentication -================================ +============== .. autoclass:: qbittorrentapi.auth.AuthAPIMixIn :members: diff --git a/docs/source/apidoc/client.rst b/docs/source/apidoc/client.rst index ebef599b1..783331d5d 100644 --- a/docs/source/apidoc/client.rst +++ b/docs/source/apidoc/client.rst @@ -1,5 +1,5 @@ Client -================================ +====== .. autoclass:: qbittorrentapi.client.Client :members: diff --git a/docs/source/apidoc/definitions.rst b/docs/source/apidoc/definitions.rst index 7a0c30938..94648a7af 100644 --- a/docs/source/apidoc/definitions.rst +++ b/docs/source/apidoc/definitions.rst @@ -1,5 +1,5 @@ Definitions -================================ +=========== .. automodule:: qbittorrentapi.definitions :members: diff --git a/docs/source/apidoc/log.rst b/docs/source/apidoc/log.rst index 0596a3c5d..5e7d00683 100644 --- a/docs/source/apidoc/log.rst +++ b/docs/source/apidoc/log.rst @@ -1,5 +1,5 @@ Log -================================ +=== .. autoclass:: qbittorrentapi.log.LogAPIMixIn :members: diff --git a/docs/source/apidoc/request.rst b/docs/source/apidoc/request.rst index feaefb214..b724b5d77 100644 --- a/docs/source/apidoc/request.rst +++ b/docs/source/apidoc/request.rst @@ -1,5 +1,5 @@ Request (internal) -================================ +================== .. automodule:: qbittorrentapi.request :members: diff --git a/docs/source/apidoc/rss.rst b/docs/source/apidoc/rss.rst index 388afc94c..57822f7e1 100644 --- a/docs/source/apidoc/rss.rst +++ b/docs/source/apidoc/rss.rst @@ -1,5 +1,5 @@ RSS -================================ +==== .. autoclass:: qbittorrentapi.rss.RSSAPIMixIn :members: diff --git a/docs/source/apidoc/search.rst b/docs/source/apidoc/search.rst index 4442e64b2..dd10eeca3 100644 --- a/docs/source/apidoc/search.rst +++ b/docs/source/apidoc/search.rst @@ -1,5 +1,5 @@ Search -================================ +====== .. autoclass:: qbittorrentapi.search.SearchAPIMixIn :members: diff --git a/docs/source/apidoc/sync.rst b/docs/source/apidoc/sync.rst index 4d476dfed..dcd25e759 100644 --- a/docs/source/apidoc/sync.rst +++ b/docs/source/apidoc/sync.rst @@ -1,5 +1,5 @@ Sync -================================ +==== .. autoclass:: qbittorrentapi.sync.SyncAPIMixIn :members: diff --git a/docs/source/apidoc/torrentcreator.rst b/docs/source/apidoc/torrentcreator.rst index 97515958f..409fa912c 100644 --- a/docs/source/apidoc/torrentcreator.rst +++ b/docs/source/apidoc/torrentcreator.rst @@ -1,5 +1,5 @@ Torrent Creator -================================ +=============== .. autoclass:: qbittorrentapi.torrentcreator.TorrentCreatorAPIMixIn :members: diff --git a/docs/source/apidoc/torrents.rst b/docs/source/apidoc/torrents.rst index 3135fabcf..1a7a0be53 100644 --- a/docs/source/apidoc/torrents.rst +++ b/docs/source/apidoc/torrents.rst @@ -1,5 +1,5 @@ Torrents -================================ +======== .. autoclass:: qbittorrentapi.torrents.TorrentsAPIMixIn :members: diff --git a/docs/source/apidoc/transfer.rst b/docs/source/apidoc/transfer.rst index e37ff45d8..21367edab 100644 --- a/docs/source/apidoc/transfer.rst +++ b/docs/source/apidoc/transfer.rst @@ -1,5 +1,5 @@ Transfer -================================ +======== .. autoclass:: qbittorrentapi.transfer.TransferAPIMixIn :members: diff --git a/docs/source/apidoc/version.rst b/docs/source/apidoc/version.rst index 5667b7be7..037d5eb63 100644 --- a/docs/source/apidoc/version.rst +++ b/docs/source/apidoc/version.rst @@ -1,5 +1,5 @@ Version -================================ +======= .. autoclass:: qbittorrentapi._version_support.Version :members: diff --git a/docs/source/async.rst b/docs/source/async.rst new file mode 100644 index 000000000..d5bc71b9c --- /dev/null +++ b/docs/source/async.rst @@ -0,0 +1,33 @@ +Async Support +============= + +``qbittorrent-api`` does not support Python's ``async/await`` functionality for +asynchronous programming. However, many use-cases for this client operate within an +existing asynchronous application. Therefore, in lieu of being able to await this +client's API calls to qBittorrent, it is still possible to call them without blocking. + +Each ``asyncio`` Event Loop provides a ``ThreadPoolExecutor`` that can run blocking code +that could interfere with async applications. In Python 3.9, a simple interface was +introduced in ``asyncio`` to run synchronous code in this thread pool. + +.. code:: python + + async def fetch_torrents() -> TorrentInfoList: + return await asyncio.to_thread(qbt_client.torrents_info, category="uploaded") + +In this example, you simply specify the method to call, ``torrents_info``, as the first +argument and follow it with the arguments for the method to run in the thread. + +Below is a full example demonstrating this that can be run in the Python REPL: + +.. code:: python + + import asyncio + import qbittorrentapi + + qbt_client = qbittorrentapi.Client() + + async def fetch_qbt_info(): + return await asyncio.to_thread(qbt_client.app_build_info) + + print(asyncio.run(fetch_qbt_info())) diff --git a/docs/source/behavior&configuration.rst b/docs/source/behavior&configuration.rst index b0f8b56d0..86f460515 100644 --- a/docs/source/behavior&configuration.rst +++ b/docs/source/behavior&configuration.rst @@ -1,5 +1,5 @@ Behavior & Configuration -================================ +======================== Host, Username and Password *************************** @@ -140,8 +140,8 @@ qBittorrent Version Checking qbt_client = Client(..., RAISE_ERROR_FOR_UNSUPPORTED_QBITTORRENT_VERSIONS=True) -* Additionally, :class:`~qbittorrentapi._version_support.Version` can be used for manual introspection of - the versions. +* Additionally, :class:`~qbittorrentapi._version_support.Version` can be used for manual + introspection of the versions. .. code:: python diff --git a/docs/source/index.rst b/docs/source/index.rst index a554ceb69..fc8c2b2b5 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -1,5 +1,5 @@ qBittorrent Web API Client -================================ +========================== .. include:: introduction.rst @@ -9,6 +9,7 @@ qBittorrent Web API Client Introduction Behavior & Configuration + Async Support Performance Exceptions API Reference diff --git a/docs/source/introduction.rst b/docs/source/introduction.rst index becc2ed1e..b7d64ef67 100644 --- a/docs/source/introduction.rst +++ b/docs/source/introduction.rst @@ -1,5 +1,5 @@ Introduction -====================== +============ .. |github ci| image:: https://img.shields.io/github/checks-status/rmartin16/qbittorrent-api/main?style=flat-square :target: https://github.com/rmartin16/qbittorrent-api/actions?query=branch%3Amain @@ -22,7 +22,7 @@ Python client implementation for qBittorrent Web API. Currently supports qBittorrent `v5.0.2 `_ (Web API v2.11.2) released on Nov 17, 2024. Features ------------- +-------- - The entire qBittorrent `Web API `_ is implemented. - qBittorrent version checking for an endpoint's existence/features is automatically handled. - If the authentication cookie expires, a new one is automatically requested in line with any API call. @@ -122,7 +122,8 @@ Each Web API endpoint is implemented one-to-one as a method of the instantiated qbt_client.torrents_resume(torrent_hashes='...') # and so on -However, a more robust interface to the endpoints is available via each namespace. This is intended to provide a more seamless and intuitive interface to the Web API. +However, a more robust interface to the endpoints is available via each namespace. This +is intended to provide a more seamless and intuitive interface to the Web API. .. code:: python @@ -137,7 +138,8 @@ However, a more robust interface to the endpoints is available via each namespac qbt_client.log.main.warning() qbt_client.log.main.normal() -Finally, some of the objects returned by the client support methods of their own. This is most pronounced for torrents themselves. +Finally, some of the objects returned by the client support methods of their own. This is +most pronounced for torrents themselves. .. code:: python @@ -159,9 +161,9 @@ Here's an example: .. code:: python client = qbittorrentapi.Client() - + async def main(): for t in await asyncio.to_thread(client.torrents_info, category="uploaded"): print(t.name) - + asyncio.run(main()) diff --git a/docs/source/performance.rst b/docs/source/performance.rst index b1d020bff..a97808f22 100644 --- a/docs/source/performance.rst +++ b/docs/source/performance.rst @@ -1,11 +1,16 @@ Performance =========== -By default, complex objects are returned from some endpoints. These objects allow for accessing the response's items as attributes and include methods for contextually relevant actions (such as ``start()`` and ``stop()`` for a torrent, for example). +By default, complex objects are returned from some endpoints. These objects allow for +accessing the response's items as attributes and include methods for contextually relevant +actions (such as ``start()`` and ``stop()`` for a torrent, for example). -This comes at the cost of performance, though. Generally, this cost isn't large; however, some endpoints, such as ``torrents_files()``, may need to convert a large payload and the cost can be significant. +This comes at the cost of performance, though. Generally, this cost isn't large; however, +some endpoints, such as ``torrents_files()``, may need to convert a large payload and the +cost can be significant. -This client can be configured to always return only the simple JSON if desired. Simply set ``SIMPLE_RESPONSES=True`` when instantiating the client. +This client can be configured to always return only the simple JSON if desired. Simply +set ``SIMPLE_RESPONSES=True`` when instantiating the client. .. code:: python @@ -16,7 +21,8 @@ This client can be configured to always return only the simple JSON if desired. SIMPLE_RESPONSES=True, ) -Alternatively, ``SIMPLE_RESPONSES`` can be set to ``True`` to return the simple JSON only for an individual method call. +Alternatively, ``SIMPLE_RESPONSES`` can be set to ``True`` to return the simple JSON +only for an individual method call. .. code:: python diff --git a/pyproject.toml b/pyproject.toml index 47252186c..729070b45 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,7 +38,6 @@ dependencies = [ dev = [ "build ==1.2.2.post1", "coverage[toml] ==7.6.8", - "furo ==2024.8.6", "mypy ==1.13.0", "pre-commit ==4.0.1", "pytest ==8.3.3", @@ -49,6 +48,7 @@ dev = [ docs = [ # building docs requires Python >3.10 + "furo ==2024.8.6", "sphinx ==8.1.3", "sphinx-autobuild ==2024.10.3", "sphinx-copybutton ==0.5.2",