Skip to content

Commit

Permalink
Add support for torrents/setTags (#512)
Browse files Browse the repository at this point in the history
  • Loading branch information
rmartin16 authored Jan 25, 2025
1 parent 8b68ca2 commit 1242182
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 10 deletions.
8 changes: 4 additions & 4 deletions docs/source/apidoc/torrents.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@ Torrents
.. autoclass:: qbittorrentapi.torrents.TorrentsAPIMixIn
:members:
:undoc-members:
:exclude-members: torrents, torrent_categories, torrent_tags, torrents_pieceStates, torrents_pieceHashes, torrents_addTrackers, torrents_editTracker, torrents_removeTrackers, torrents_filePrio, torrents_renameFile, torrents_renameFolder, torrents_increasePrio, torrents_decreasePrio, torrents_topPrio, torrents_bottomPrio, torrents_downloadLimit, torrents_setDownloadLimit, torrents_setShareLimits, torrents_uploadLimit, torrents_setUploadLimit, torrents_setLocation, torrents_setCategory, torrents_setAutoManagement, torrents_toggleSequentialDownload, torrents_toggleFirstLastPiecePrio, torrents_setForceStart, torrents_setSuperSeeding, torrents_addPeers, torrents_createCategory, torrents_editCategory, torrents_removeCategories, torrents_addTags, torrents_removeTags, torrents_createTags, torrents_deleteTags, torrents_setDownloadPath, torrents_setSavePath, torrents_addWebSeeds, torrents_editWebSeed, torrents_removeWebSeeds
:exclude-members: torrents, torrent_categories, torrent_tags, torrents_pieceStates, torrents_pieceHashes, torrents_addTrackers, torrents_editTracker, torrents_removeTrackers, torrents_filePrio, torrents_renameFile, torrents_renameFolder, torrents_increasePrio, torrents_decreasePrio, torrents_topPrio, torrents_bottomPrio, torrents_downloadLimit, torrents_setDownloadLimit, torrents_setShareLimits, torrents_uploadLimit, torrents_setUploadLimit, torrents_setLocation, torrents_setCategory, torrents_setAutoManagement, torrents_toggleSequentialDownload, torrents_toggleFirstLastPiecePrio, torrents_setForceStart, torrents_setSuperSeeding, torrents_addPeers, torrents_createCategory, torrents_editCategory, torrents_removeCategories, torrents_addTags, torrents_removeTags, torrents_createTags, torrents_deleteTags, torrents_setDownloadPath, torrents_setSavePath, torrents_addWebSeeds, torrents_editWebSeed, torrents_removeWebSeeds, torrents_setTags
:show-inheritance:

.. autoclass:: qbittorrentapi.torrents.Torrents
:members:
:undoc-members:
:exclude-members: pieceStates, pieceHashes, addTrackers, editTracker, removeTrackers, filePrio, renameFile, renameFolder, increasePrio, decreasePrio, topPrio, bottomPrio, downloadLimit, setDownloadLimit, setShareLimits, uploadLimit, setUploadLimit, setLocation, setCategory, setAutoManagement, toggleSequentialDownload, toggleFirstLastPiecePrio, setForceStart, setSuperSeeding, addPeers, createCategory, editCategory, removeCategories, addTags, removeTags, createTags, deleteTags, setDownloadPath, setSavePath, addWebSeeds, editWebSeed, removeWebSeeds
:exclude-members: pieceStates, pieceHashes, addTrackers, editTracker, removeTrackers, filePrio, renameFile, renameFolder, increasePrio, decreasePrio, topPrio, bottomPrio, downloadLimit, setDownloadLimit, setShareLimits, uploadLimit, setUploadLimit, setLocation, setCategory, setAutoManagement, toggleSequentialDownload, toggleFirstLastPiecePrio, setForceStart, setSuperSeeding, addPeers, createCategory, editCategory, removeCategories, addTags, removeTags, createTags, deleteTags, setDownloadPath, setSavePath, addWebSeeds, editWebSeed, removeWebSeeds, setTags

.. autoclass:: qbittorrentapi.torrents.TorrentDictionary
:members:
:undoc-members:
:exclude-members: pieceStates, pieceHashes, addTrackers, editTracker, removeTrackers, filePrio, renameFile, renameFolder, increasePrio, decreasePrio, topPrio, bottomPrio, downloadLimit, setDownloadLimit, setShareLimits, uploadLimit, setUploadLimit, setLocation, setCategory, setAutoManagement, toggleSequentialDownload, toggleFirstLastPiecePrio, setForceStart, setSuperSeeding, addPeers, createCategory, editCategory, removeCategories, addTags, removeTags, createTags, deleteTags, filePriority, setDownloadPath, setSavePath, addWebSeeds, editWebSeed, removeWebSeeds
:exclude-members: pieceStates, pieceHashes, addTrackers, editTracker, removeTrackers, filePrio, renameFile, renameFolder, increasePrio, decreasePrio, topPrio, bottomPrio, downloadLimit, setDownloadLimit, setShareLimits, uploadLimit, setUploadLimit, setLocation, setCategory, setAutoManagement, toggleSequentialDownload, toggleFirstLastPiecePrio, setForceStart, setSuperSeeding, addPeers, createCategory, editCategory, removeCategories, addTags, removeTags, createTags, deleteTags, filePriority, setDownloadPath, setSavePath, addWebSeeds, editWebSeed, removeWebSeeds, setTags
:show-inheritance:

.. autoclass:: qbittorrentapi.torrents.TorrentCategories
Expand All @@ -27,7 +27,7 @@ Torrents
.. autoclass:: qbittorrentapi.torrents.TorrentTags
:members:
:undoc-members:
:exclude-members: addTags, removeTags, createTags, deleteTags
:exclude-members: addTags, removeTags, createTags, deleteTags, setTags
:show-inheritance:

.. autoclass:: qbittorrentapi.torrents.TorrentPropertiesDictionary
Expand Down
1 change: 1 addition & 0 deletions docs/source/spelling_wordlist
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pem
Reannounce
ResponseT
str
Upsert
untagged
Untrusted
untrusted
Expand Down
60 changes: 60 additions & 0 deletions src/qbittorrentapi/torrents.py
Original file line number Diff line number Diff line change
Expand Up @@ -1777,6 +1777,37 @@ def torrents_add_tags(

torrents_addTags = torrents_add_tags

def torrents_set_tags(
self,
tags: str | Iterable[str] | None = None,
torrent_hashes: str | Iterable[str] | None = None,
**kwargs: APIKwargsT,
) -> None:
"""
Upsert one or more tags to one or more torrents.
Note: Tags that do not exist will be created on-the-fly.
This method was introduced with qBittorrent v5.1.0 (Web API v2.11.4).
:param tags: tag name or list of tags
:param torrent_hashes: single torrent hash or list of torrent hashes.
Or ``all`` for all torrents.
"""
data = {
"hashes": self._list2string(torrent_hashes, "|"),
"tags": self._list2string(tags, ","),
}
self._post(
_name=APINames.Torrents,
_method="setTags",
data=data,
version_introduced="2.11.4",
**kwargs,
)

torrents_setTags = torrents_set_tags

def torrents_remove_tags(
self,
tags: str | Iterable[str] | None = None,
Expand Down Expand Up @@ -2409,6 +2440,20 @@ def add_tags(

addTags = add_tags

def set_tags(
self,
tags: str | Iterable[str] | None = None,
**kwargs: APIKwargsT,
) -> None:
"""Implements :meth:`~TorrentsAPIMixIn.torrents_set_tags`."""
self._client.torrents_set_tags(
torrent_hashes=self._torrent_hash,
tags=tags,
**kwargs,
)

setTags = set_tags

def remove_tags(
self,
tags: str | Iterable[str] | None = None,
Expand Down Expand Up @@ -3358,6 +3403,21 @@ def add_tags(

addTags = add_tags

def set_tags(
self,
tags: str | Iterable[str] | None = None,
torrent_hashes: str | Iterable[str] | None = None,
**kwargs: APIKwargsT,
) -> None:
"""Implements :meth:`~TorrentsAPIMixIn.torrents_set_tags`."""
self._client.torrents_set_tags(
tags=tags,
torrent_hashes=torrent_hashes,
**kwargs,
)

setTags = set_tags

def remove_tags(
self,
tags: str | Iterable[str] | None = None,
Expand Down
32 changes: 26 additions & 6 deletions tests/test_torrent.py
Original file line number Diff line number Diff line change
Expand Up @@ -577,13 +577,14 @@ def test_rename(new_torrent, name):
)
@pytest.mark.parametrize("tags", ["tag 1", ["tag 2", "tag 3"]])
def test_add_remove_tags(client, orig_torrent, add_tags_func, remove_tags_func, tags):
orig_torrent.func(add_tags_func)(tags=tags)
check(lambda: orig_torrent.info.tags, tags, reverse=True)
try:
orig_torrent.func(add_tags_func)(tags=tags)
check(lambda: orig_torrent.info.tags, tags, reverse=True)

orig_torrent.func(remove_tags_func)(tags=tags)
check(lambda: orig_torrent.info.tags, tags, reverse=True, negate=True)

client.torrents_delete_tags(tags=tags)
orig_torrent.func(remove_tags_func)(tags=tags)
check(lambda: orig_torrent.info.tags, tags, reverse=True, negate=True)
finally:
client.torrents_delete_tags(tags=tags)


@pytest.mark.skipif_after_api_version("2.3.0")
Expand All @@ -598,3 +599,22 @@ def test_add_remove_tags_not_implemented(
orig_torrent.func(add_tags_func)()
with pytest.raises(NotImplementedError):
orig_torrent.func(remove_tags_func)()


@pytest.mark.skipif_before_api_version("2.11.4")
@pytest.mark.parametrize("set_tags_func", ["set_tags", "setTags"])
@pytest.mark.parametrize("tags", ["tag 1", ["tag 2", "tag 3"]])
def test_set_tags(client, orig_torrent, set_tags_func, tags):
try:
orig_torrent.add_tags(tags="extra-tag")
orig_torrent.func(set_tags_func)(tags=tags)
check(lambda: orig_torrent.info.tags, tags, reverse=True)
finally:
client.torrents_delete_tags(tags=tags)


@pytest.mark.skipif_after_api_version("2.11.4")
@pytest.mark.parametrize("set_tags_func", ["set_tags", "setTags"])
def test_set_tags_not_implemented(client, orig_torrent, set_tags_func):
with pytest.raises(NotImplementedError):
orig_torrent.func(set_tags_func)()
35 changes: 35 additions & 0 deletions tests/test_torrents.py
Original file line number Diff line number Diff line change
Expand Up @@ -1636,6 +1636,41 @@ def test_add_tags_not_implemented(client, add_tags_func):
client.func(add_tags_func)()


@pytest.mark.skipif_before_api_version("2.11.4")
@pytest.mark.parametrize(
"set_tags_func",
[
"torrents_set_tags",
"torrents_setTags",
"torrent_tags.set_tags",
"torrent_tags.setTags",
],
)
@pytest.mark.parametrize("tags", [["tag1"], ["tag1", "tag 2"]])
def test_set_tags(client, orig_torrent, set_tags_func, tags):
try:
client.torrents_add_tags(tags="extra-tag", torrent_hashes=orig_torrent.hash)
client.func(set_tags_func)(tags=tags, torrent_hashes=orig_torrent.hash)
check(lambda: orig_torrent.info.tags, tags, reverse=True)
finally:
client.torrents_delete_tags(tags=tags)


@pytest.mark.skipif_after_api_version("2.11.4")
@pytest.mark.parametrize(
"set_tags_func",
[
"torrents_set_tags",
"torrents_setTags",
"torrent_tags.set_tags",
"torrent_tags.setTags",
],
)
def test_set_tags_not_implemented(client, set_tags_func):
with pytest.raises(NotImplementedError):
client.func(set_tags_func)()


@pytest.mark.skipif_before_api_version("2.3.0")
@pytest.mark.parametrize(
"remove_tags_func",
Expand Down

0 comments on commit 1242182

Please sign in to comment.