From f76afd257f810cc854bcaf029a90ff713bf03960 Mon Sep 17 00:00:00 2001 From: Trim21 Date: Tue, 9 Apr 2024 01:21:46 +0800 Subject: [PATCH 01/31] feat: support rpc version 18 --- README.md | 2 +- transmission_rpc/client.py | 18 +++++++++++++++--- transmission_rpc/constants.py | 1 + transmission_rpc/torrent.py | 11 +++++++++++ transmission_rpc/types.py | 5 +++++ 5 files changed, 33 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 5611029f..974108f8 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ hosted on GitHub at [github.com/trim21/transmission-rpc](https://github.com/trim `transmission-rpc` is a python module implementing the json-rpc client protocol for the BitTorrent client Transmission. -Support 14 <= rpc version <= 17 (2.40 <= transmission version <= 4.0.4), +Support 14 <= rpc version <= 18 (2.40 <= transmission version <= 4.1.0), should works fine with newer rpc version but some new feature may be missing. ## versioning diff --git a/transmission_rpc/client.py b/transmission_rpc/client.py index 665325b6..691e6a4a 100644 --- a/transmission_rpc/client.py +++ b/transmission_rpc/client.py @@ -594,6 +594,7 @@ def change_torrent( tracker_list: Optional[Iterable[Iterable[str]]] = None, tracker_replace: Optional[Iterable[Tuple[int, str]]] = None, tracker_remove: Optional[Iterable[int]] = None, + sequential_download: Optional[bool] = None, **kwargs: Any, ) -> None: """Change torrent parameters for the torrent(s) with the supplied id's. @@ -680,6 +681,11 @@ def change_torrent( -------- since transmission daemon 4.0.0, this argument is deprecated, use ``tracker_list`` instead. + sequential_download: + download torrent pieces sequentially + + Add in Transmission 4.1.0, rpc-version 18. + Warnings ---- ``kwargs`` is for the future features not supported yet, it's not compatibility promising. @@ -721,6 +727,7 @@ def change_torrent( "labels": list_or_none(labels), "trackerList": None if tracker_list is None else "\n".join("\n\n".join(x) for x in tracker_list), "group": group, + "sequentialDownload": sequential_download, } ) @@ -1057,13 +1064,18 @@ def blocklist_update(self, timeout: Optional[_Timeout] = None) -> Optional[int]: result = self._request(RpcMethod.BlocklistUpdate, timeout=timeout) return result.get("blocklist-size") - def port_test(self, timeout: Optional[_Timeout] = None) -> Optional[bool]: + def port_test( + self, timeout: Optional[_Timeout] = None, *, ip_protocol: Optional[Literal["ipv4", "ipv6"]] = None + ) -> dict[str, Any]: """ Tests to see if your incoming peer port is accessible from the outside world. + + return a dict with testing result + + https://github.com/transmission/transmission/blob/main/docs/rpc-spec.md#44-port-checking """ - result = self._request(RpcMethod.PortTest, timeout=timeout) - return result.get("port-is-open") + return self._request(RpcMethod.PortTest, remove_unset_value({"ipProtocol": ip_protocol}), timeout=timeout) def free_space(self, path: Union[str, pathlib.Path], timeout: Optional[_Timeout] = None) -> Optional[int]: """ diff --git a/transmission_rpc/constants.py b/transmission_rpc/constants.py index 2eb8142a..938925e8 100644 --- a/transmission_rpc/constants.py +++ b/transmission_rpc/constants.py @@ -148,6 +148,7 @@ class Type: "seedIdleMode": Args(Type.number, 10, description="Use global (0), torrent (1), or unlimited (2) limit."), "seedRatioLimit": Args(Type.double, 5, None, None, None, "Seed ratio limit."), "seedRatioMode": Args(Type.number, 5, description="Use global (0), torrent (1), or unlimited (2) limit."), + "sequentialDownload": Args(Type.boolean, 18, description="download torrent pieces sequentially"), "sizeWhenDone": Args(Type.number, 1, description="Size of the torrent download in bytes."), "startDate": Args(Type.number, 1, description="The date when the torrent was last started."), "status": Args(Type.number, 1, None, None, None, "Current status, see source"), diff --git a/transmission_rpc/torrent.py b/transmission_rpc/torrent.py index 8947f723..584e80d5 100644 --- a/transmission_rpc/torrent.py +++ b/transmission_rpc/torrent.py @@ -396,6 +396,8 @@ def get_files(self) -> List[File]: name=file["name"], completed=file["bytesCompleted"], id=id, + begin_piece=file.get("beginPiece"), + end_piece=file.get("endPiece"), ) for id, file, raw_priority, raw_selected in zip(indices, files, priorities, wanted) ) @@ -822,6 +824,15 @@ def seed_ratio_mode(self) -> RatioLimitMode: """ return RatioLimitMode(self.fields["seedRatioMode"]) + @property + def sequential_download(self) -> bool: + """ + download torrent pieces sequentially + + add in Transmission 4.1.0 (rpc-version-semver 5.4.0, rpc-version: 18) + """ + return self.fields["sequentialDownload"] + def __repr__(self) -> str: return f'' diff --git a/transmission_rpc/types.py b/transmission_rpc/types.py index 6c39597a..8b177909 100644 --- a/transmission_rpc/types.py +++ b/transmission_rpc/types.py @@ -27,6 +27,11 @@ class File(NamedTuple): selected: bool # if selected for download id: int # id of the file of this torrent, not should not be used outside the torrent scope. + # add in Transmission 4.1.0 (rpc-version-semver 5.4.0, rpc-version: 18) + begin_piece: Optional[int] = None + # add in Transmission 4.1.0 (rpc-version-semver 5.4.0, rpc-version: 18) + end_piece: Optional[int] = None + class Group(Container): @property From 52de6e250b6a0b0cd5dd7206c9464776ca42f30a Mon Sep 17 00:00:00 2001 From: Trim21 Date: Tue, 9 Apr 2024 01:24:49 +0800 Subject: [PATCH 02/31] fix --- transmission_rpc/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/transmission_rpc/client.py b/transmission_rpc/client.py index 691e6a4a..a0b4faab 100644 --- a/transmission_rpc/client.py +++ b/transmission_rpc/client.py @@ -1066,7 +1066,7 @@ def blocklist_update(self, timeout: Optional[_Timeout] = None) -> Optional[int]: def port_test( self, timeout: Optional[_Timeout] = None, *, ip_protocol: Optional[Literal["ipv4", "ipv6"]] = None - ) -> dict[str, Any]: + ) -> Dict[str, Any]: """ Tests to see if your incoming peer port is accessible from the outside world. From cd8cc02b9e9d809050d33310d50920fd75d1c48b Mon Sep 17 00:00:00 2001 From: Trim21 Date: Mon, 13 May 2024 12:30:34 +0800 Subject: [PATCH 03/31] fix --- transmission_rpc/__init__.py | 3 ++- transmission_rpc/client.py | 8 +++++--- transmission_rpc/types.py | 17 +++++++++++++++++ 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/transmission_rpc/__init__.py b/transmission_rpc/__init__.py index e072dfae..a23c6c4a 100644 --- a/transmission_rpc/__init__.py +++ b/transmission_rpc/__init__.py @@ -6,7 +6,7 @@ from transmission_rpc.error import TransmissionError from transmission_rpc.session import Session from transmission_rpc.torrent import Torrent -from transmission_rpc.types import File, Group +from transmission_rpc.types import File, Group, PortTestResult __all__ = [ "Client", @@ -21,6 +21,7 @@ "Priority", "RatioLimitMode", "IdleMode", + "PortTestResult", ] diff --git a/transmission_rpc/client.py b/transmission_rpc/client.py index 9d89d946..976dcb74 100644 --- a/transmission_rpc/client.py +++ b/transmission_rpc/client.py @@ -22,7 +22,7 @@ ) from transmission_rpc.session import Session, SessionStats from transmission_rpc.torrent import Torrent -from transmission_rpc.types import Group, _Timeout +from transmission_rpc.types import Group, PortTestResult, _Timeout from transmission_rpc.utils import _try_read_torrent, get_torrent_arguments valid_hash_char = string.digits + string.ascii_letters @@ -1097,7 +1097,7 @@ def blocklist_update(self, timeout: Optional[_Timeout] = None) -> Optional[int]: def port_test( self, timeout: Optional[_Timeout] = None, *, ip_protocol: Optional[Literal["ipv4", "ipv6"]] = None - ) -> Dict[str, Any]: + ) -> PortTestResult: """ Tests to see if your incoming peer port is accessible from the outside world. @@ -1106,7 +1106,9 @@ def port_test( https://github.com/transmission/transmission/blob/main/docs/rpc-spec.md#44-port-checking """ - return self._request(RpcMethod.PortTest, remove_unset_value({"ipProtocol": ip_protocol}), timeout=timeout) + return PortTestResult( + fields=self._request(RpcMethod.PortTest, remove_unset_value({"ipProtocol": ip_protocol}), timeout=timeout) + ) def free_space(self, path: Union[str, pathlib.Path], timeout: Optional[_Timeout] = None) -> Optional[int]: """ diff --git a/transmission_rpc/types.py b/transmission_rpc/types.py index c6989b7e..bfa4151a 100644 --- a/transmission_rpc/types.py +++ b/transmission_rpc/types.py @@ -67,3 +67,20 @@ def speed_limit_up_enabled(self) -> bool: def speed_limit_up(self) -> int: """max global upload speed (KBps)""" return self.fields["speed-limit-up"] + + +class PortTestResult(Container): + @property + def port_is_open(self) -> bool: + """available on all transmission version""" + return self.fields["port-is-open"] + + @property + def ip_protocol(self) -> str: + """ipv4 if the test was carried out on IPv4, + ipv6 if the test was carried out on IPv6, + unset if it cannot be determined + + Available in Transmission 4.1.0 (rpc-version-semver 5.4.0, rpc-version: 18) + """ + return self.fields["ipProtocol"] From 9b3b4d5d134c78e99a9e6506b071575dc5dacebb Mon Sep 17 00:00:00 2001 From: Trim21 Date: Mon, 13 May 2024 12:30:56 +0800 Subject: [PATCH 04/31] fix doc --- transmission_rpc/client.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/transmission_rpc/client.py b/transmission_rpc/client.py index 976dcb74..24ee7f72 100644 --- a/transmission_rpc/client.py +++ b/transmission_rpc/client.py @@ -1102,8 +1102,6 @@ def port_test( Tests to see if your incoming peer port is accessible from the outside world. - return a dict with testing result - https://github.com/transmission/transmission/blob/main/docs/rpc-spec.md#44-port-checking """ return PortTestResult( From beca3648b992e13f95d2acf5a6cf0cfb07639f38 Mon Sep 17 00:00:00 2001 From: Trim21 Date: Mon, 13 May 2024 12:40:19 +0800 Subject: [PATCH 05/31] fix --- transmission_rpc/client.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/transmission_rpc/client.py b/transmission_rpc/client.py index 24ee7f72..c8b532b6 100644 --- a/transmission_rpc/client.py +++ b/transmission_rpc/client.py @@ -1103,6 +1103,8 @@ def port_test( outside world. https://github.com/transmission/transmission/blob/main/docs/rpc-spec.md#44-port-checking + + :argument ip_protocol: Available in Transmission 4.1.0 (rpc-version-semver 5.4.0, rpc-version: 18) """ return PortTestResult( fields=self._request(RpcMethod.PortTest, remove_unset_value({"ipProtocol": ip_protocol}), timeout=timeout) From 0f632b0d8a469ca7dd7264ab59eabafcfda4fa4e Mon Sep 17 00:00:00 2001 From: Trim21 Date: Mon, 13 May 2024 12:44:49 +0800 Subject: [PATCH 06/31] update docs --- docs/index.rst | 1 + docs/types.rst | 11 +++++++++++ 2 files changed, 12 insertions(+) create mode 100644 docs/types.rst diff --git a/docs/index.rst b/docs/index.rst index c8330a24..ee55f13d 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -69,6 +69,7 @@ you can find rpc version by transmission version from session.rst errors.rst utils.rst + types.rst Indices and tables ================== diff --git a/docs/types.rst b/docs/types.rst new file mode 100644 index 00000000..68250528 --- /dev/null +++ b/docs/types.rst @@ -0,0 +1,11 @@ +Types +============================================ + +.. automodule:: transmission_rpc.types + :members: + +.. autoclass:: PortTestResult + +.. toctree:: + :maxdepth: 2 + :caption: Contents: From c1493f74a33b4a63cf47aaefedd3055ca261bcfa Mon Sep 17 00:00:00 2001 From: Trim21 Date: Mon, 13 May 2024 12:46:48 +0800 Subject: [PATCH 07/31] more --- docs/client.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/client.rst b/docs/client.rst index 3c9f8d26..41c60a9e 100644 --- a/docs/client.rst +++ b/docs/client.rst @@ -10,6 +10,8 @@ Many functions in Client takes torrent id. You can find torrent-ids spec in `official docs `_ +They are all supported but using SHA1 hash strings is highly recommended. + .. automodule:: transmission_rpc .. autofunction:: from_url From d7bf36d30d2dc07ed0e9e979c605a27a504321d3 Mon Sep 17 00:00:00 2001 From: Trim21 Date: Mon, 13 May 2024 12:49:33 +0800 Subject: [PATCH 08/31] fix --- docs/types.rst | 1 - transmission_rpc/types.py | 6 ++++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/types.rst b/docs/types.rst index 68250528..43c886f2 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -2,7 +2,6 @@ Types ============================================ .. automodule:: transmission_rpc.types - :members: .. autoclass:: PortTestResult diff --git a/transmission_rpc/types.py b/transmission_rpc/types.py index bfa4151a..d810dc4e 100644 --- a/transmission_rpc/types.py +++ b/transmission_rpc/types.py @@ -70,6 +70,12 @@ def speed_limit_up(self) -> int: class PortTestResult(Container): + """ + api response of ``port-test`` + + https://github.com/transmission/transmission/blob/5d159e0/docs/rpc-spec.md#44-port-checking + """ + @property def port_is_open(self) -> bool: """available on all transmission version""" From 0b3daa2cb7ccfd09f0f75b4e564217473124e05f Mon Sep 17 00:00:00 2001 From: Trim21 Date: Mon, 13 May 2024 12:51:53 +0800 Subject: [PATCH 09/31] add inline doc --- transmission_rpc/types.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/transmission_rpc/types.py b/transmission_rpc/types.py index d810dc4e..f851dc71 100644 --- a/transmission_rpc/types.py +++ b/transmission_rpc/types.py @@ -20,16 +20,17 @@ def get(self, key: str, default: Optional[T] = None) -> Any: class File(NamedTuple): - name: str # file name - size: int # file size in bytes - completed: int # bytes completed - priority: Priority - selected: bool # if selected for download - id: int # id of the file of this torrent, not should not be used outside the torrent scope. - - # add in Transmission 4.1.0 (rpc-version-semver 5.4.0, rpc-version: 18) + name: str #: file name + size: int #: file size in bytes + completed: int #: bytes completed + priority: Priority #: download priority + selected: bool #: if selected for download + id: int #: id of the file of this torrent, not should not be used outside the torrent scope. + + #: add in Transmission 4.1.0 (rpc-version-semver 5.4.0, rpc-version: 18) begin_piece: Optional[int] = None - # add in Transmission 4.1.0 (rpc-version-semver 5.4.0, rpc-version: 18) + + #: add in Transmission 4.1.0 (rpc-version-semver 5.4.0, rpc-version: 18) end_piece: Optional[int] = None From 95dda4dfe88d275e4673b92cc235757488b0c911 Mon Sep 17 00:00:00 2001 From: Trim21 Date: Mon, 13 May 2024 12:52:14 +0800 Subject: [PATCH 10/31] add inline doc --- docs/types.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/types.rst b/docs/types.rst index 43c886f2..aea2e0f6 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -2,8 +2,7 @@ Types ============================================ .. automodule:: transmission_rpc.types - -.. autoclass:: PortTestResult + :members: .. toctree:: :maxdepth: 2 From 3ddccc58623a70c55972e7095d3c81b125b80846 Mon Sep 17 00:00:00 2001 From: Trim21 Date: Mon, 13 May 2024 13:11:43 +0800 Subject: [PATCH 11/31] fix doc --- Taskfile.yaml | 6 ++++++ docs/types.rst | 2 ++ transmission_rpc/types.py | 31 +++++++++++++++++++++---------- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/Taskfile.yaml b/Taskfile.yaml index 263730d1..991a18bb 100644 --- a/Taskfile.yaml +++ b/Taskfile.yaml @@ -20,5 +20,11 @@ tasks: - poetry run pytest build:docs: + sources: + - transmission_rpc/**/*.py + - docs/**/* + - exclude: docs/dist/**/* + generates: + - docs/dist/**/* cmds: - poetry run sphinx-build ./docs/ ./docs/dist/ diff --git a/docs/types.rst b/docs/types.rst index aea2e0f6..a4f137d6 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -3,6 +3,8 @@ Types .. automodule:: transmission_rpc.types :members: + :member-order: bysource + :exclude-members: __new__, __init__ .. toctree:: :maxdepth: 2 diff --git a/transmission_rpc/types.py b/transmission_rpc/types.py index f851dc71..62082566 100644 --- a/transmission_rpc/types.py +++ b/transmission_rpc/types.py @@ -20,18 +20,29 @@ def get(self, key: str, default: Optional[T] = None) -> Any: class File(NamedTuple): - name: str #: file name - size: int #: file size in bytes - completed: int #: bytes completed - priority: Priority #: download priority - selected: bool #: if selected for download - id: int #: id of the file of this torrent, not should not be used outside the torrent scope. - - #: add in Transmission 4.1.0 (rpc-version-semver 5.4.0, rpc-version: 18) + name: str + """file name""" + + size: int + """file size in bytes""" + + completed: int + """bytes completed""" + + priority: Priority + """download priority""" + + selected: bool + """if selected for download""" + + id: int + """id of the file of this torrent, not should not be used outside the torrent scope""" + begin_piece: Optional[int] = None + """add in Transmission 4.1.0 rpc-version-semver 5.4.0, rpc-version 18""" - #: add in Transmission 4.1.0 (rpc-version-semver 5.4.0, rpc-version: 18) end_piece: Optional[int] = None + """add in Transmission 4.1.0 rpc-version-semver 5.4.0, rpc-version 18""" class Group(Container): @@ -72,7 +83,7 @@ def speed_limit_up(self) -> int: class PortTestResult(Container): """ - api response of ``port-test`` + api response of :meth:`transmission_rpc.Client.port_test` https://github.com/transmission/transmission/blob/5d159e0/docs/rpc-spec.md#44-port-checking """ From d837cfa1e597ce6f8a73d30c5eeb3d19e860e517 Mon Sep 17 00:00:00 2001 From: Trim21 Date: Mon, 13 May 2024 13:20:13 +0800 Subject: [PATCH 12/31] fix --- docs/types.rst | 1 + transmission_rpc/types.py | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/types.rst b/docs/types.rst index a4f137d6..6375fdc9 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -5,6 +5,7 @@ Types :members: :member-order: bysource :exclude-members: __new__, __init__ + :inherited-members: get .. toctree:: :maxdepth: 2 diff --git a/transmission_rpc/types.py b/transmission_rpc/types.py index 62082566..0553eb9d 100644 --- a/transmission_rpc/types.py +++ b/transmission_rpc/types.py @@ -9,7 +9,8 @@ class Container: - fields: Dict[str, Any] #: raw fields + fields: Dict[str, Any] + """raw response""" def __init__(self, *, fields: Dict[str, Any]): self.fields = fields From c144273fd89e772bb25b4812497e66eb58c33b8f Mon Sep 17 00:00:00 2001 From: Trim21 Date: Sat, 18 May 2024 06:14:29 +0800 Subject: [PATCH 13/31] Update client.rst --- docs/client.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/client.rst b/docs/client.rst index e24b7f38..96ccd58f 100644 --- a/docs/client.rst +++ b/docs/client.rst @@ -10,7 +10,6 @@ Many functions in Client takes torrent id. You can find torrent-ids spec in `official docs `_ -======= .. note:: It's recommended that you use torrent's ``info_hash`` as torrent id. The torrent's ``info_hash`` will never change. From b77eab9ab36b1693fc3efb8d1ae80fee45bdd140 Mon Sep 17 00:00:00 2001 From: Trim21 Date: Sat, 18 May 2024 06:14:45 +0800 Subject: [PATCH 14/31] Update client.rst --- docs/client.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/client.rst b/docs/client.rst index 96ccd58f..a871b62c 100644 --- a/docs/client.rst +++ b/docs/client.rst @@ -14,6 +14,7 @@ You can find torrent-ids spec in `official docs It's recommended that you use torrent's ``info_hash`` as torrent id. The torrent's ``info_hash`` will never change. + .. automodule:: transmission_rpc .. autofunction:: from_url From 3dba12d141fb56456b076c730da69030a8e95b33 Mon Sep 17 00:00:00 2001 From: Trim21 Date: Sat, 18 May 2024 07:32:42 +0800 Subject: [PATCH 15/31] chore: remove ruff from dev-deps --- .github/workflows/lint.yaml | 15 --------------- poetry.lock | 28 +--------------------------- pyproject.toml | 1 - 3 files changed, 1 insertion(+), 43 deletions(-) diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index f741d6a2..cf4d5b31 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -30,21 +30,6 @@ jobs: - name: mypy run: mypy --show-column-numbers transmission_rpc - ruff: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-python@v5 - with: - python-version: "3.10" - - - uses: trim21/setup-poetry@dist/v2 - - - uses: trim21/install-poetry-project@dist/v2 - - - run: ruff check . --output-format=github - pre-commit: runs-on: ubuntu-latest steps: diff --git a/poetry.lock b/poetry.lock index bf8a31eb..171918e9 100644 --- a/poetry.lock +++ b/poetry.lock @@ -873,32 +873,6 @@ urllib3 = ">=1.21.1,<3" socks = ["PySocks (>=1.5.6,!=1.5.7)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] -[[package]] -name = "ruff" -version = "0.4.2" -description = "An extremely fast Python linter and code formatter, written in Rust." -optional = false -python-versions = ">=3.7" -files = [ - {file = "ruff-0.4.2-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:8d14dc8953f8af7e003a485ef560bbefa5f8cc1ad994eebb5b12136049bbccc5"}, - {file = "ruff-0.4.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:24016ed18db3dc9786af103ff49c03bdf408ea253f3cb9e3638f39ac9cf2d483"}, - {file = "ruff-0.4.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e2e06459042ac841ed510196c350ba35a9b24a643e23db60d79b2db92af0c2b"}, - {file = "ruff-0.4.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3afabaf7ba8e9c485a14ad8f4122feff6b2b93cc53cd4dad2fd24ae35112d5c5"}, - {file = "ruff-0.4.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:799eb468ea6bc54b95527143a4ceaf970d5aa3613050c6cff54c85fda3fde480"}, - {file = "ruff-0.4.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:ec4ba9436a51527fb6931a8839af4c36a5481f8c19e8f5e42c2f7ad3a49f5069"}, - {file = "ruff-0.4.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6a2243f8f434e487c2a010c7252150b1fdf019035130f41b77626f5655c9ca22"}, - {file = "ruff-0.4.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8772130a063f3eebdf7095da00c0b9898bd1774c43b336272c3e98667d4fb8fa"}, - {file = "ruff-0.4.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ab165ef5d72392b4ebb85a8b0fbd321f69832a632e07a74794c0e598e7a8376"}, - {file = "ruff-0.4.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:1f32cadf44c2020e75e0c56c3408ed1d32c024766bd41aedef92aa3ca28eef68"}, - {file = "ruff-0.4.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:22e306bf15e09af45ca812bc42fa59b628646fa7c26072555f278994890bc7ac"}, - {file = "ruff-0.4.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:82986bb77ad83a1719c90b9528a9dd663c9206f7c0ab69282af8223566a0c34e"}, - {file = "ruff-0.4.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:652e4ba553e421a6dc2a6d4868bc3b3881311702633eb3672f9f244ded8908cd"}, - {file = "ruff-0.4.2-py3-none-win32.whl", hash = "sha256:7891ee376770ac094da3ad40c116258a381b86c7352552788377c6eb16d784fe"}, - {file = "ruff-0.4.2-py3-none-win_amd64.whl", hash = "sha256:5ec481661fb2fd88a5d6cf1f83403d388ec90f9daaa36e40e2c003de66751798"}, - {file = "ruff-0.4.2-py3-none-win_arm64.whl", hash = "sha256:cbd1e87c71bca14792948c4ccb51ee61c3296e164019d2d484f3eaa2d360dfaf"}, - {file = "ruff-0.4.2.tar.gz", hash = "sha256:33bcc160aee2520664bc0859cfeaebc84bb7323becff3f303b8f1f2d81cb4edc"}, -] - [[package]] name = "setuptools" version = "69.5.1" @@ -1516,4 +1490,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "6195b130a6d34f17f4732b586f9ebb4af49ada38e1041c62d0c93814822437f7" +content-hash = "07ebe0f32d2e1a37d04b6eaaa4b415def1f5494b6a7bd659704b47e034d39396" diff --git a/pyproject.toml b/pyproject.toml index 9f3cb931..c644e1ac 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,7 +46,6 @@ coverage = "==7.5.0" # linter and formatter pre-commit = { version = "==3.7.0", markers = "implementation_name != 'pypy'", python = "^3.9" } mypy = { version = "==1.10.0", markers = "implementation_name != 'pypy'", python = "^3.9" } -ruff = "0.4.2" # stubs types-requests = "==2.31.0.20240406" From fcca3a9056aaefec8435849f4ac6c10273963db3 Mon Sep 17 00:00:00 2001 From: Trim21 Date: Sat, 18 May 2024 07:35:21 +0800 Subject: [PATCH 16/31] chore: add bump to taskfile --- Taskfile.yaml | 9 +++++++++ pyproject.toml | 3 --- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Taskfile.yaml b/Taskfile.yaml index ee175647..172b5ff6 100644 --- a/Taskfile.yaml +++ b/Taskfile.yaml @@ -9,6 +9,15 @@ tasks: - task --list-all silent: true + bump: + vars: + VERSION: + sh: poetry version -s + cmds: + - git add pyproject.toml + - 'git commit -m "bump: {{.VERSION}}"' + - 'git tag "v{{.VERSION}}" -m "v{{.VERSION}}"' + lint: cmds: - poetry run ruff . diff --git a/pyproject.toml b/pyproject.toml index c644e1ac..ab71be0c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -51,9 +51,6 @@ mypy = { version = "==1.10.0", markers = "implementation_name != 'pypy'", python types-requests = "==2.31.0.20240406" sphinx-autobuild = {version = "2024.4.16", python = "^3.9"} -[tool.poetry-plugin-bump] -commit_msg = 'bump: v{version}' - [tool.isort] default_section = 'THIRDPARTY' indent = ' ' From 415acf7881acca70e89016aa12872f1f9f8dd776 Mon Sep 17 00:00:00 2001 From: Trim21 Date: Sat, 18 May 2024 07:47:47 +0800 Subject: [PATCH 17/31] chore: remove dead isort config --- pyproject.toml | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index ab71be0c..85fa6989 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -51,17 +51,6 @@ mypy = { version = "==1.10.0", markers = "implementation_name != 'pypy'", python types-requests = "==2.31.0.20240406" sphinx-autobuild = {version = "2024.4.16", python = "^3.9"} -[tool.isort] -default_section = 'THIRDPARTY' -indent = ' ' -profile = 'black' -known_first_party = 'transmission_rpc' -length_sort = true -line_length = 120 -no_lines_before = 'LOCALFOLDER' -use_parentheses = true -include_trailing_comma = true - [tool.pytest.ini_options] addopts = '-rav -Werror' From 5d8009e1cd03282781f4ec4b5980834e0498b45f Mon Sep 17 00:00:00 2001 From: Trim21 Date: Sat, 18 May 2024 08:03:36 +0800 Subject: [PATCH 18/31] style: enable mypy strict (#423) --- pyproject.toml | 1 + transmission_rpc/client.py | 6 +++--- transmission_rpc/session.py | 2 +- transmission_rpc/torrent.py | 4 ++-- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 85fa6989..53fc3f0a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -56,6 +56,7 @@ addopts = '-rav -Werror' [tool.mypy] python_version = "3.8" +strict = true disallow_untyped_defs = true ignore_missing_imports = true warn_return_any = false diff --git a/transmission_rpc/client.py b/transmission_rpc/client.py index d048ea96..798e7c62 100644 --- a/transmission_rpc/client.py +++ b/transmission_rpc/client.py @@ -141,7 +141,7 @@ def torrent_get_arguments(self) -> List[str]: @property @deprecated("do not use internal property, use `.get_session()` instead") - def raw_session(self) -> dict: + def raw_session(self) -> Dict[str, Any]: return self.__raw_session @property @@ -189,7 +189,7 @@ def timeout(self) -> None: def _http_header(self) -> Dict[str, str]: return {"x-transmission-session-id": self.__session_id} - def _http_query(self, query: dict, timeout: Optional[_Timeout] = None) -> str: + def _http_query(self, query: Dict[str, Any], timeout: Optional[_Timeout] = None) -> str: """ Query Transmission through HTTP. """ @@ -235,7 +235,7 @@ def _request( ids: Optional[_TorrentIDs] = None, require_ids: bool = False, timeout: Optional[_Timeout] = None, - ) -> dict: + ) -> Dict[str, Any]: """ Send json-rpc request to Transmission using http POST """ diff --git a/transmission_rpc/session.py b/transmission_rpc/session.py index 8fd6dae7..2d85697a 100644 --- a/transmission_rpc/session.py +++ b/transmission_rpc/session.py @@ -361,7 +361,7 @@ def version(self) -> str: return self.fields["version"] @property - def default_trackers(self) -> Optional[list]: + def default_trackers(self) -> Optional[List[str]]: """ list of default trackers to use on public torrents new at rpc-version 17 diff --git a/transmission_rpc/torrent.py b/transmission_rpc/torrent.py index d7a0cdf2..b8ff5d2f 100644 --- a/transmission_rpc/torrent.py +++ b/transmission_rpc/torrent.py @@ -633,8 +633,8 @@ def upload_ratio(self) -> float: return self.fields["uploadRatio"] @property - def wanted(self) -> List: - # TODO + def wanted(self) -> List[int]: + """if files are wanted, sorted by file index. 1 for wanted 0 for unwanted""" return self.fields["wanted"] @property From 406128ef296c7f068bd54ef25466d20cb79b888f Mon Sep 17 00:00:00 2001 From: Trim21 Date: Sat, 18 May 2024 13:23:55 +0800 Subject: [PATCH 19/31] docs: improve code (#424) --- .github/workflows/lint.yaml | 19 ++ Taskfile.yaml | 10 +- docs/conf.py | 81 +++++- docs/{const.rst => enum.rst} | 7 +- docs/index.rst | 4 +- docs/session.rst | 3 +- docs/torrent.rst | 30 ++- poetry.lock | 20 +- pyproject.toml | 3 +- transmission_rpc/__init__.py | 23 +- transmission_rpc/client.py | 507 ++++++++++++++++------------------- transmission_rpc/session.py | 5 +- transmission_rpc/torrent.py | 35 ++- transmission_rpc/types.py | 3 +- 14 files changed, 425 insertions(+), 325 deletions(-) rename docs/{const.rst => enum.rst} (59%) diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index cf4d5b31..ab1cb373 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -42,3 +42,22 @@ jobs: - uses: trim21/setup-poetry@dist/v2 - uses: trim21/install-poetry-project@dist/v2 - uses: trim21/actions/pre-commit@master + + + + sphinx: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: "3.10" + + - uses: trim21/setup-poetry@dist/v2 + + - uses: trim21/install-poetry-project@dist/v2 + with: + install_args: --with docs + + - run: sphinx-build docs/ dist/ diff --git a/Taskfile.yaml b/Taskfile.yaml index 172b5ff6..9a65b6e2 100644 --- a/Taskfile.yaml +++ b/Taskfile.yaml @@ -30,14 +30,14 @@ tasks: dev:docs: cmds: - - poetry run sphinx-autobuild ./docs/ ./docs/dist/ --watch transmission_rpc + - poetry run sphinx-autobuild --watch transmission_rpc ./docs/ ./dist/ build:docs: sources: - - transmission_rpc/**/*.py - docs/**/* - - exclude: docs/dist/**/* + - transmission_rpc/**/* generates: - - docs/dist/**/* + - dist/**/* cmds: - - poetry run sphinx-build ./docs/ ./docs/dist/ + - rm -rf dist/ + - poetry run sphinx-build ./docs/ ./dist/ diff --git a/docs/conf.py b/docs/conf.py index c8404bf2..6e94bd41 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -4,6 +4,10 @@ # This file does only contain a selection of the most common options. For a # full list see the documentation: # http://www.sphinx-doc.org/en/master/config +import importlib +import inspect +import os +import sys # -- Path setup -------------------------------------------------------------- @@ -29,11 +33,14 @@ # ones. extensions = [ "sphinx.ext.autodoc", - "sphinx.ext.viewcode", "sphinx.ext.napoleon", + "sphinx_copybutton", "furo.sphinxext", + "sphinx.ext.linkcode", ] +napoleon_numpy_docstring = False + # Add any paths that contain templates here, relative to this directory. templates_path = [] @@ -73,16 +80,27 @@ # documentation. # html_theme_options = { - "source_edit_link": "https://github.com/trim21/transmission-rpc/blob/master/docs/source/{filename}", + "source_edit_link": "https://github.com/trim21/transmission-rpc/blob/master/docs/{filename}", + # "source_view_link": "https://github.com/trim21/transmission-rpc/blob/master/{filename}", + "source_repository": "https://github.com/trim21/transmission-rpc/", + "source_branch": "master", + "source_directory": "docs/", } +html_copy_source = False + # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = [] -# autodoc_member_order = "bysource" +autodoc_member_order = "bysource" autodoc_class_signature = "separated" -autodoc_typehints = "both" +autodoc_typehints = "signature" + +autodoc_default_options = { + "special-members": "", + "exclude-members": "__new__", +} # Custom sidebar templates, must be a dictionary that maps document names # to template names. @@ -98,3 +116,58 @@ # Output file base name for HTML help builder. htmlhelp_basename = "transmission-rpc doc" + +ref = "master" + +if os.environ.get("READTHEDOCS"): + sys.path.insert(0, os.path.normpath("..")) + + if os.environ["READTHEDOCS_VERSION_TYPE"] == "tag": + ref = os.environ["READTHEDOCS_GIT_IDENTIFIER"] + else: + ref = os.environ["READTHEDOCS_GIT_COMMIT_HASH"] + + +def linkcode_resolve(domain, info): + if domain != "py": + return None + if not info["module"]: + return None + + assert domain == "py", "expected only Python objects" + + mod = importlib.import_module(info["module"]) + if "." in info["fullname"]: + objname, attrname = info["fullname"].split(".") + obj = getattr(mod, objname) + try: + # object is a method of a class + obj = getattr(obj, attrname) + except AttributeError: + # object is an attribute of a class + return None + else: + obj = getattr(mod, info["fullname"]) + + try: + file = inspect.getsourcefile(obj) + lines = inspect.getsourcelines(obj) + except TypeError: + # e.g. object is a typing.Union + return None + + file = os.path.relpath(file, os.path.abspath("..")) + + if file.startswith("transmission-rpc"): + # e.g. object is a typing.NewType + file = file.removeprefix("transmission-rpc" + os.sep) + + start = lines[1] + + return f"https://github.com/trim21/transmission-rpc/blob/{ref}/{file}#L{start}" + + if file.startswith("transmission_rpc"): + # read the docs, don't know why + start = lines[1] + + return f"https://github.com/trim21/transmission-rpc/blob/{ref}/{file}#L{start}" diff --git a/docs/const.rst b/docs/enum.rst similarity index 59% rename from docs/const.rst rename to docs/enum.rst index c1251476..3bb2de39 100644 --- a/docs/const.rst +++ b/docs/enum.rst @@ -1,7 +1,8 @@ -Const -============================================ +Enum +==== -.. automodule:: transmission_rpc.constants +.. automodule:: transmission_rpc + :no-index: .. autoclass:: RatioLimitMode :members: diff --git a/docs/index.rst b/docs/index.rst index ee55f13d..c7adbbfb 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -16,7 +16,7 @@ quick start .. seealso:: - :py:meth:`transmission_rpc.client.Client.add_torrent` + :py:meth:`transmission_rpc.Client.add_torrent` Example ======= @@ -65,7 +65,7 @@ you can find rpc version by transmission version from client.rst torrent.rst - const.rst + enum.rst session.rst errors.rst utils.rst diff --git a/docs/session.rst b/docs/session.rst index 97d9572b..f68b7185 100644 --- a/docs/session.rst +++ b/docs/session.rst @@ -1,7 +1,8 @@ Session ======= -.. automodule:: transmission_rpc.session +.. automodule:: transmission_rpc + :no-index: .. autoclass:: Session :inherited-members: get diff --git a/docs/torrent.rst b/docs/torrent.rst index 751ba24d..892ca297 100644 --- a/docs/torrent.rst +++ b/docs/torrent.rst @@ -1,22 +1,32 @@ Torrent ============================================ -.. automodule:: transmission_rpc.torrent - +.. automodule:: transmission_rpc + :no-index: .. autoclass:: Torrent :members: .. autoclass:: Status - :exclude-members: __new__, __init__ + :exclude-members: __init__, __new__ + +.. autoclass:: FileStat + :members: + :undoc-members: + :inherited-members: + :exclude-members: __init__, __new__ - .. autoattribute:: Status.stopped - .. autoattribute:: Status.check_pending - .. autoattribute:: Status.checking - .. autoattribute:: Status.download_pending - .. autoattribute:: Status.downloading - .. autoattribute:: Status.seed_pending - .. autoattribute:: Status.seeding +.. autoclass:: Tracker + :members: + :undoc-members: + :inherited-members: + :exclude-members: __init__, __new__ + +.. autoclass:: TrackerStats + :members: + :undoc-members: + :inherited-members: + :exclude-members: __init__, __new__ .. toctree:: :maxdepth: 2 diff --git a/poetry.lock b/poetry.lock index 171918e9..807ca4e2 100644 --- a/poetry.lock +++ b/poetry.lock @@ -997,6 +997,24 @@ sphinx = ">=4.0" [package.extras] docs = ["furo", "ipython", "myst-parser", "sphinx-copybutton", "sphinx-inline-tabs"] +[[package]] +name = "sphinx-copybutton" +version = "0.5.2" +description = "Add a copy button to each of your code cells." +optional = false +python-versions = ">=3.7" +files = [ + {file = "sphinx-copybutton-0.5.2.tar.gz", hash = "sha256:4cf17c82fb9646d1bc9ca92ac280813a3b605d8c421225fd9913154103ee1fbd"}, + {file = "sphinx_copybutton-0.5.2-py3-none-any.whl", hash = "sha256:fb543fd386d917746c9a2c50360c7905b605726b9355cd26e9974857afeae06e"}, +] + +[package.dependencies] +sphinx = ">=1.8" + +[package.extras] +code-style = ["pre-commit (==2.12.1)"] +rtd = ["ipython", "myst-nb", "sphinx", "sphinx-book-theme", "sphinx-examples"] + [[package]] name = "sphinxcontrib-applehelp" version = "1.0.8" @@ -1490,4 +1508,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "07ebe0f32d2e1a37d04b6eaaa4b415def1f5494b6a7bd659704b47e034d39396" +content-hash = "36548da496314e9ce1079ee05bb8b6d3db067b32b1b4bc5eb38dfe43bc141267" diff --git a/pyproject.toml b/pyproject.toml index 53fc3f0a..c14a9799 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,8 +33,9 @@ requests = "^2.23.0" typing-extensions = ">=4.5.0" [tool.poetry.group.docs.dependencies] -sphinx = { version = "^7.0.0", python = "^3.9" } +sphinx = { version = "^7.3.7", python = "^3.9" } furo = { version = "2024.5.6", python = "^3.9" } +sphinx-copybutton = { version = "^0.5.2", python = "^3.9" } [tool.poetry.group.dev.dependencies] yarl = "==1.9.4" diff --git a/transmission_rpc/__init__.py b/transmission_rpc/__init__.py index a23c6c4a..e75c35a1 100644 --- a/transmission_rpc/__init__.py +++ b/transmission_rpc/__init__.py @@ -3,20 +3,34 @@ from transmission_rpc.client import Client from transmission_rpc.constants import DEFAULT_TIMEOUT, LOGGER, IdleMode, Priority, RatioLimitMode -from transmission_rpc.error import TransmissionError -from transmission_rpc.session import Session -from transmission_rpc.torrent import Torrent +from transmission_rpc.error import ( + TransmissionAuthError, + TransmissionConnectError, + TransmissionError, + TransmissionTimeoutError, +) +from transmission_rpc.session import Session, SessionStats, Stats +from transmission_rpc.torrent import FileStat, Status, Torrent, Tracker, TrackerStats from transmission_rpc.types import File, Group, PortTestResult __all__ = [ "Client", "Group", + "Status", "DEFAULT_TIMEOUT", "LOGGER", "TransmissionError", + "TransmissionTimeoutError", + "TransmissionAuthError", + "TransmissionConnectError", "Session", + "Stats", + "SessionStats", "Torrent", "File", + "FileStat", + "Tracker", + "TrackerStats", "from_url", "Priority", "RatioLimitMode", @@ -38,8 +52,7 @@ def from_url( from_url("http://127.0.0.1") # http://127.0.0.1:80/transmission/rpc from_url("http://127.0.0.1/") # http://127.0.0.1:80/ - Warnings - -------- + Warnings: you can't ignore scheme, ``127.0.0.1:9091`` is not valid url, please use ``http://127.0.0.1:9091`` And ``from_url("http://127.0.0.1")`` is not same as ``from_url("http://127.0.0.1/")``, diff --git a/transmission_rpc/client.py b/transmission_rpc/client.py index 798e7c62..16376cf3 100644 --- a/transmission_rpc/client.py +++ b/transmission_rpc/client.py @@ -89,17 +89,15 @@ def __init__( ): """ - Parameters - ---------- - protocol - username - password - host - port - path: - rpc request target path, default ``/transmission/rpc`` - timeout - logger + Parameters: + protocol: + username: + password: + host: + port: + path: rpc request target path, default ``/transmission/rpc`` + timeout: + logger: """ if isinstance(logger, logging.Logger): self.logger = logger @@ -383,40 +381,38 @@ def add_torrent( - bytes of torrent content - ``pathlib.Path`` for local torrent file, will be read and encoded as base64. - Warnings - -------- - base64 string or ``file://`` protocol URL are not supported in v4. - - Parameters - ---------- - torrent: - torrent to add - timeout: - request timeout - bandwidthPriority: - Priority for this transfer. - cookies: - One or more HTTP cookie(s). - download_dir: - The directory where the downloaded contents will be saved in. - files_unwanted: - A list of file id's that shouldn't be downloaded. - files_wanted: - A list of file id's that should be downloaded. - paused: - If ``True``, does not start the transfer when added. - Magnet url will always start to downloading torrents. - peer_limit: - Maximum number of peers allowed. - priority_high: - A list of file id's that should have high priority. - priority_low: - A list of file id's that should have low priority. - priority_normal: - A list of file id's that should have normal priority. - labels: - Array of string labels. - Add in rpc 17. + Warnings: + base64 string or ``file://`` protocol URL are not supported in v4. + + Parameters: + torrent: + torrent to add + timeout: + request timeout + bandwidthPriority: + Priority for this transfer. + cookies: + One or more HTTP cookie(s). + download_dir: + The directory where the downloaded contents will be saved in. + files_unwanted: + A list of file id's that shouldn't be downloaded. + files_wanted: + A list of file id's that should be downloaded. + paused: + If ``True``, does not start the transfer when added. + Magnet url will always start to downloading torrents. + peer_limit: + Maximum number of peers allowed. + priority_high: + A list of file id's that should have high priority. + priority_low: + A list of file id's that should have low priority. + priority_normal: + A list of file id's that should have normal priority. + labels: + Array of string labels. + Add in rpc 17. """ if torrent is None: raise ValueError("add_torrent requires data or a URI.") @@ -511,29 +507,26 @@ def get_torrent( Returns a Torrent object with the requested fields. - Note - ---- - It's recommended that you only fetch arguments you need, - this could improve response speed. + Note: + It's recommended that you only fetch arguments you need, + this could improve response speed. - For example, fetch all fields from transmission daemon with 1500 torrents would take ~5s, - but is only ~0.2s if to fetch 6 fields. + For example, fetch all fields from transmission daemon with 1500 torrents would take ~5s, + but is only ~0.2s if to fetch 6 fields. - Parameters - ---------- - torrent_id: - torrent id can be an int or a torrent ``info_hash`` (``hashString`` property of the ``Torrent`` object). + Parameters: + torrent_id: + torrent id can be an int or a torrent ``info_hash`` (``hashString`` property of the ``Torrent`` object). - arguments: - fetched torrent arguments, in most cases you don't need to set this, - transmission-rpc will fetch all torrent fields it supported. + arguments: + fetched torrent arguments, in most cases you don't need to set this, + transmission-rpc will fetch all torrent fields it supported. - timeout: - requests timeout + timeout: + requests timeout - Raises - ------ - KeyError: torrent with given ``torrent_id`` not found + Raises: + KeyError: torrent with given ``torrent_id`` not found """ if arguments: arguments = list(set(arguments) | {"id", "hashString"}) @@ -583,12 +576,9 @@ def get_recently_active_torrents( Get information for torrents for recently active torrent. If you want to get recently-removed torrents. you should use this method. - Returns - ------- - active_torrents: List[Torrent] - List of recently active torrents - removed_torrents: List[int] - List of torrent-id of recently-removed torrents. + Returns: + active_torrents, removed_torrents + List of recently active torrents and list of torrent-id of recently-removed torrents. """ if arguments: arguments = list(set(arguments) | {"id", "hashString"}) @@ -633,98 +623,63 @@ def change_torrent( ) -> None: """Change torrent parameters for the torrent(s) with the supplied id's. - Parameters - ---------- - ids - torrent(s) to change. - timeout - requesst timeout. - honors_session_limits - true if session upload limits are honored. - location - new location of the torrent's content - peer_limit - maximum number of peers - queue_position - position of this torrent in its queue [0...n) - files_wanted - Array of file id to download. - files_unwanted - Array of file id to not download. - download_limit - maximum download speed (KBps) - download_limited - true if ``download_limit`` is honored - upload_limit - maximum upload speed (KBps) - upload_limited - true if ``upload_limit`` is honored - bandwidth_priority - Priority for this transfer. - priority_high - list of file id to set high download priority - priority_low - list of file id to set low download priority - priority_normal - list of file id to set normal download priority - seed_ratio_limit - Seed inactivity limit in minutes. - seed_ratio_mode - Torrent seed ratio mode - - Valid options are :py:class:`transmission_rpc.constants.RatioLimitMode` - seed_idle_limit - torrent-level seeding ratio - seed_idle_mode - Seed inactivity mode. - - Valid options are :py:class:`transmission_rpc.constants.IdleMode` - labels - Array of string labels. - Add in rpc 16. - group - The name of this torrent's bandwidth group. - Add in rpc 17. - - tracker_list - A ``Iterable[Iterable[str]]``, each ``Iterable[str]`` for a tracker tier. - - Add in rpc 17. - - Example: ``[['https://tracker1/announce', 'https://tracker2/announce'], - ['https://backup1.example.com/announce'], ['https://backup2.example.com/announce']]``. - - tracker_add: - Array of string with announce URLs to add. - - Warnings - -------- - since transmission daemon 4.0.0, this argument is deprecated, use ``tracker_list`` instead. - - tracker_remove: - Array of ids of trackers to remove. - - Warnings - -------- - since transmission daemon 4.0.0, this argument is deprecated, use ``tracker_list`` instead. - - tracker_replace: - Array of (id, url) tuples where the announcement URL should be replaced. - - Warnings - -------- - since transmission daemon 4.0.0, this argument is deprecated, use ``tracker_list`` instead. - - sequential_download: - download torrent pieces sequentially - - Add in Transmission 4.1.0, rpc-version 18. - - Warnings - ---- - ``kwargs`` is for the future features not supported yet, it's not compatibility promising. - - It will be bypassed to request arguments **as-is**, the underline in the key will not be replaced, so you should use kwargs like ``{'a-argument': 'value'}`` + Parameters: + ids: torrent(s) to change. + timeout: requesst timeout. + honors_session_limits: true if session upload limits are honored. + location: new location of the torrent's content + peer_limit: maximum number of peers + queue_position: position of this torrent in its queue [0...n) + files_wanted: Array of file id to download. + files_unwanted: Array of file id to not download. + download_limit: maximum download speed (KBps) + download_limited: true if ``download_limit`` is honored + upload_limit: maximum upload speed (KBps) + upload_limited: true if ``upload_limit`` is honored + bandwidth_priority: Priority for this transfer. + priority_high: list of file id to set high download priority + priority_low: list of file id to set low download priority + priority_normal: list of file id to set normal download priority + seed_ratio_limit: Seed inactivity limit in minutes. + seed_ratio_mode: Torrent seed ratio mode + Valid options are :py:class:`transmission_rpc.RatioLimitMode` + seed_idle_limit: torrent-level seeding ratio + seed_idle_mode: Seed inactivity mode. + Valid options are :py:class:`transmission_rpc.IdleMode` + labels: Array of string labels. Add in rpc 16. + group: The name of this torrent's bandwidth group. Add in rpc 17. + tracker_list: + A ``Iterable[Iterable[str]]``, each ``Iterable[str]`` for a tracker tier. + + Add in rpc 17. + + Example: ``[['https://tracker1/announce', 'https://tracker2/announce'], + ['https://backup1.example.com/announce'], ['https://backup2.example.com/announce']]``. + + tracker_add: + Array of string with announce URLs to add. + + Warnings: + since transmission daemon 4.0.0, this argument is deprecated, use ``tracker_list`` instead. + + tracker_remove: + Array of ids of trackers to remove. + + Warnings: + since transmission daemon 4.0.0, this argument is deprecated, use ``tracker_list`` instead. + + tracker_replace: + Array of (id, url) tuples where the announcement URL should be replaced. + + Warning: + since transmission daemon 4.0.0, this argument is deprecated, use ``tracker_list`` instead. + + sequential_download: + download torrent pieces sequentially. Add in Transmission 4.1.0, rpc-version 18. + + Warnings: + ``kwargs`` is for the future features not supported yet, it's not compatibility promising. + It will be bypassed to request arguments **as-is**, the underline in the key will not be replaced, so you should use kwargs like ``{'a-argument': 'value'}`` """ if labels is not None: self._rpc_version_warning(16) @@ -783,10 +738,8 @@ def move_torrent_data( """ Move torrent data to the new location. - See Also - -------- - - `RPC Spec: moving-a-torrent `_ + See Also: + `RPC Spec: moving-a-torrent `_ """ args = {"location": ensure_location_str(location), "move": bool(move)} self._request(RpcMethod.TorrentSetLocation, args, ids, True, timeout=timeout) @@ -799,17 +752,14 @@ def rename_torrent_path( timeout: Optional[_Timeout] = None, ) -> Tuple[str, str]: """ - Warnings - -------- - This method can only be called on single torrent. + Warnings: + This method can only be called on single torrent. - Warnings - -------- - This is not the method to move torrent data directory, + Warnings: + This is not the method to move torrent data directory, - See Also - -------- - `RPC Spec: renaming-a-torrents-path `_ + See Also: + `RPC Spec: renaming-a-torrents-path `_ """ self._rpc_version_warning(15) torrent_id = _parse_torrent_id(torrent_id) @@ -914,112 +864,109 @@ def set_session( """ Set session parameters. - Parameters - ---------- - timeout - request timeout - alt_speed_down: - max global download speed (KBps) - alt_speed_enabled: - true means use the alt speeds - alt_speed_time_begin: - Time when alternate speeds should be enabled. Minutes after midnight. - alt_speed_time_day: - Enables alternate speeds scheduling these days. - alt_speed_time_enabled: - Enables alternate speeds scheduling. - alt_speed_time_end: - Time when alternate speeds should be disabled. Minutes after midnight. - alt_speed_up: - Alternate session upload speed limit (in Kib/s). - blocklist_enabled: - Enables the block list - blocklist_url: - Location of the block list. Updated with blocklist-update. - cache_size_mb: - The maximum size of the disk cache in MB - default_trackers: - List of default trackers to use on public torrents. - dht_enabled: - Enables DHT. - download_dir: - Set the session download directory. - download_queue_enabled: - Enables download queue. - download_queue_size: - Number of slots in the download queue. - encryption: - Set the session encryption mode, one of ``required``, ``preferred`` or ``tolerated``. - idle_seeding_limit: - The default seed inactivity limit in minutes. - idle_seeding_limit_enabled: - Enables the default seed inactivity limit - incomplete_dir: - The path to the directory of incomplete transfer data. - incomplete_dir_enabled: - Enables the incomplete transfer data directory, - Otherwise data for incomplete transfers are stored in the download target. - lpd_enabled: - Enables local peer discovery for public torrents. - peer_limit_global: - Maximum number of peers. - peer_limit_per_torrent: - Maximum number of peers per transfer. - peer_port: - Peer port. - peer_port_random_on_start: - Enables randomized peer port on start of Transmission. - pex_enabled: - Allowing PEX in public torrents. - port_forwarding_enabled: - Enables port forwarding. - queue_stalled_enabled: - Enable tracking of stalled transfers. - queue_stalled_minutes: - Number of minutes of idle that marks a transfer as stalled. - rename_partial_files: - Appends ".part" to incomplete files - - seed_queue_enabled: - Enables upload queue. - seed_queue_size: - Number of slots in the upload queue. - seed_ratio_limit: - Seed ratio limit. 1.0 means 1:1 download and upload ratio. - seed_ratio_limited: - Enables seed ration limit. - speed_limit_down: - Download speed limit (in Kib/s). - speed_limit_down_enabled: - Enables download speed limiting. - speed_limit_up: - Upload speed limit (in Kib/s). - speed_limit_up_enabled: - Enables upload speed limiting. - start_added_torrents: - Added torrents will be started right away. - trash_original_torrent_files: - The .torrent file of added torrents will be deleted. - utp_enabled: - Enables Micro Transport Protocol (UTP). - script_torrent_done_enabled: - Whether to call the "done" script. - script_torrent_done_filename: - Filename of the script to run when the transfer is done. - script_torrent_added_filename: - filename of the script to run - script_torrent_added_enabled: - whether or not to call the ``added`` script - script_torrent_done_seeding_enabled: - whether or not to call the ``seeding-done`` script - script_torrent_done_seeding_filename: - filename of the script to run - - Warnings - ---- - ``kwargs`` is pass the arguments not supported yet future, it's not compatibility promising. - - transmission-rpc will merge ``kwargs`` in rpc arguments *as-is* + Parameters: + timeout + request timeout + alt_speed_down: + max global download speed (KBps) + alt_speed_enabled: + true means use the alt speeds + alt_speed_time_begin: + Time when alternate speeds should be enabled. Minutes after midnight. + alt_speed_time_day: + Enables alternate speeds scheduling these days. + alt_speed_time_enabled: + Enables alternate speeds scheduling. + alt_speed_time_end: + Time when alternate speeds should be disabled. Minutes after midnight. + alt_speed_up: + Alternate session upload speed limit (in Kib/s). + blocklist_enabled: + Enables the block list + blocklist_url: + Location of the block list. Updated with blocklist-update. + cache_size_mb: + The maximum size of the disk cache in MB + default_trackers: + List of default trackers to use on public torrents. + dht_enabled: + Enables DHT. + download_dir: + Set the session download directory. + download_queue_enabled: + Enables download queue. + download_queue_size: + Number of slots in the download queue. + encryption: + Set the session encryption mode, one of ``required``, ``preferred`` or ``tolerated``. + idle_seeding_limit: + The default seed inactivity limit in minutes. + idle_seeding_limit_enabled: + Enables the default seed inactivity limit + incomplete_dir: + The path to the directory of incomplete transfer data. + incomplete_dir_enabled: + Enables the incomplete transfer data directory, + Otherwise data for incomplete transfers are stored in the download target. + lpd_enabled: + Enables local peer discovery for public torrents. + peer_limit_global: + Maximum number of peers. + peer_limit_per_torrent: + Maximum number of peers per transfer. + peer_port: + Peer port. + peer_port_random_on_start: + Enables randomized peer port on start of Transmission. + pex_enabled: + Allowing PEX in public torrents. + port_forwarding_enabled: + Enables port forwarding. + queue_stalled_enabled: + Enable tracking of stalled transfers. + queue_stalled_minutes: + Number of minutes of idle that marks a transfer as stalled. + rename_partial_files: + Appends ".part" to incomplete files + + seed_queue_enabled: + Enables upload queue. + seed_queue_size: + Number of slots in the upload queue. + seed_ratio_limit: + Seed ratio limit. 1.0 means 1:1 download and upload ratio. + seed_ratio_limited: + Enables seed ration limit. + speed_limit_down: + Download speed limit (in Kib/s). + speed_limit_down_enabled: + Enables download speed limiting. + speed_limit_up: + Upload speed limit (in Kib/s). + speed_limit_up_enabled: + Enables upload speed limiting. + start_added_torrents: + Added torrents will be started right away. + trash_original_torrent_files: + The .torrent file of added torrents will be deleted. + utp_enabled: + Enables Micro Transport Protocol (UTP). + script_torrent_done_enabled: + Whether to call the "done" script. + script_torrent_done_filename: + Filename of the script to run when the transfer is done. + script_torrent_added_filename: + filename of the script to run + script_torrent_added_enabled: + whether or not to call the ``added`` script + script_torrent_done_seeding_enabled: + whether or not to call the ``seeding-done`` script + script_torrent_done_seeding_filename: + filename of the script to run + + Warnings: + ``kwargs`` is pass the arguments not supported yet future, it's not compatibility promising. + transmission-rpc will merge ``kwargs`` in rpc arguments **as-is** """ if encryption is not None and encryption not in ["required", "preferred", "tolerated"]: diff --git a/transmission_rpc/session.py b/transmission_rpc/session.py index 2d85697a..bc18abac 100644 --- a/transmission_rpc/session.py +++ b/transmission_rpc/session.py @@ -111,9 +111,8 @@ class Session(Container): https://github.com/transmission/transmission/blob/main/docs/rpc-spec.md#41-session-arguments - Warnings - -------- - setter on session's properties has been removed, please use ``Client().set_session()`` instead + Warnings: + setter on session's properties has been removed, please use :py:meth`Client.set_session` instead """ @property diff --git a/transmission_rpc/torrent.py b/transmission_rpc/torrent.py index b8ff5d2f..6a5b0197 100644 --- a/transmission_rpc/torrent.py +++ b/transmission_rpc/torrent.py @@ -35,30 +35,37 @@ class Status(str, enum.Enum): @property def stopped(self) -> bool: + """if torrent stopped""" return self == "stopped" @property def check_pending(self) -> bool: + """if torrent check pending""" return self == "check pending" @property def checking(self) -> bool: + """if torrent checking""" return self == "checking" @property def download_pending(self) -> bool: + """if download pending""" return self == "download pending" @property def downloading(self) -> bool: + """if downloading""" return self == "downloading" @property def seed_pending(self) -> bool: + """if seed pending""" return self == "seed pending" @property def seeding(self) -> bool: + """if seeding""" return self == "seeding" def __str__(self) -> str: @@ -66,6 +73,10 @@ def __str__(self) -> str: class FileStat(Container): + """ + type for :py:meth:`Torrent.file_stats` + """ + @property def bytesCompleted(self) -> int: return self.fields["bytesCompleted"] @@ -80,6 +91,10 @@ def priority(self) -> int: class Tracker(Container): + """ + type for :py:attr:`Torrent.trackers` + """ + @property def id(self) -> int: return self.fields["id"] @@ -98,6 +113,10 @@ def tier(self) -> int: class TrackerStats(Container): + """ + type for :py:attr:`Torrent.tracker_stats` + """ + @property def id(self) -> int: return self.fields["id"] @@ -211,9 +230,8 @@ class Torrent(Container): """ Torrent is a class holding the data received from Transmission regarding a bittorrent transfer. - Warnings - -------- - setter on Torrent's properties has been removed, please use ``Client().change_torrent()`` instead + Warnings: + setter on Torrent's properties has been removed, please use :py:meth:`Client.change_torrent` instead """ def __init__(self, *, fields: Dict[str, Any]): @@ -366,11 +384,9 @@ def get_files(self) -> List[File]: """ Get list of files for this torrent. - Note - ---- - + Note: The order of the files is guaranteed. The index of file object is the id of the file - when calling :py:meth:`transmission_rpc.client.Client.set_files`. + when calling :py:meth:`transmission_rpc.Client.change_torrent` .. code-block:: python @@ -378,7 +394,7 @@ def get_files(self) -> List[File]: torrent = Client().get_torrent(0) - for file in enumerate(torrent.get_files()): + for file in torrent.get_files(): print(file.id) """ @@ -406,6 +422,7 @@ def get_files(self) -> List[File]: @property def file_stats(self) -> List[FileStat]: + """file stats""" return [FileStat(fields=x) for x in self.fields["fileStats"]] @property @@ -590,6 +607,7 @@ def size_when_done(self) -> int: @property def trackers(self) -> List[Tracker]: + """trackers of torrent""" return [Tracker(fields=x) for x in self.fields["trackers"]] @property @@ -599,6 +617,7 @@ def tracker_list(self) -> List[str]: @property def tracker_stats(self) -> List[TrackerStats]: + """tracker status, for example, announce success/failure status""" return [TrackerStats(fields=x) for x in self.fields["trackerStats"]] @property diff --git a/transmission_rpc/types.py b/transmission_rpc/types.py index 0553eb9d..364b6479 100644 --- a/transmission_rpc/types.py +++ b/transmission_rpc/types.py @@ -9,8 +9,7 @@ class Container: - fields: Dict[str, Any] - """raw response""" + fields: Dict[str, Any] #: raw response data def __init__(self, *, fields: Dict[str, Any]): self.fields = fields From 9c005bb99d56dfed9cf003c91e8dff39f30ddddf Mon Sep 17 00:00:00 2001 From: Trim21 Date: Sat, 18 May 2024 13:30:29 +0800 Subject: [PATCH 20/31] update --- docs/index.rst | 1 - docs/torrent.rst | 6 ++++++ docs/types.rst | 12 ------------ 3 files changed, 6 insertions(+), 13 deletions(-) delete mode 100644 docs/types.rst diff --git a/docs/index.rst b/docs/index.rst index c7adbbfb..8f23c6ed 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -69,7 +69,6 @@ you can find rpc version by transmission version from session.rst errors.rst utils.rst - types.rst Indices and tables ================== diff --git a/docs/torrent.rst b/docs/torrent.rst index 892ca297..f7c5b41c 100644 --- a/docs/torrent.rst +++ b/docs/torrent.rst @@ -28,6 +28,12 @@ Torrent :inherited-members: :exclude-members: __init__, __new__ +.. autoclass:: PortTestResult + :members: + :undoc-members: + :inherited-members: + :exclude-members: __init__, __new__ + .. toctree:: :maxdepth: 2 :caption: Contents: diff --git a/docs/types.rst b/docs/types.rst deleted file mode 100644 index 6375fdc9..00000000 --- a/docs/types.rst +++ /dev/null @@ -1,12 +0,0 @@ -Types -============================================ - -.. automodule:: transmission_rpc.types - :members: - :member-order: bysource - :exclude-members: __new__, __init__ - :inherited-members: get - -.. toctree:: - :maxdepth: 2 - :caption: Contents: From 509083c614ecc263616a504ac6b182326350f506 Mon Sep 17 00:00:00 2001 From: Trim21 Date: Sat, 18 May 2024 13:31:06 +0800 Subject: [PATCH 21/31] update --- transmission_rpc/client.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/transmission_rpc/client.py b/transmission_rpc/client.py index 16376cf3..0d86be01 100644 --- a/transmission_rpc/client.py +++ b/transmission_rpc/client.py @@ -1054,7 +1054,8 @@ def port_test( https://github.com/transmission/transmission/blob/main/docs/rpc-spec.md#44-port-checking - :argument ip_protocol: Available in Transmission 4.1.0 (rpc-version-semver 5.4.0, rpc-version: 18) + Parameters: + ip_protocol: ``ipv4`` or ``ipv6``. Available in Transmission 4.1.0 (rpc-version-semver 5.4.0, rpc-version: 18) """ return PortTestResult( fields=self._request(RpcMethod.PortTest, remove_unset_value({"ipProtocol": ip_protocol}), timeout=timeout) From 6e98cd7abbfada339b4b16eaea45da152635cc3c Mon Sep 17 00:00:00 2001 From: Trim21 Date: Sat, 18 May 2024 13:32:51 +0800 Subject: [PATCH 22/31] update --- docs/client.rst | 5 +++++ docs/torrent.rst | 6 ------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/client.rst b/docs/client.rst index a871b62c..36fb16e4 100644 --- a/docs/client.rst +++ b/docs/client.rst @@ -22,6 +22,11 @@ You can find torrent-ids spec in `official docs .. autoclass:: Client :members: +.. autoclass:: PortTestResult + :members: + :undoc-members: + :inherited-members: + :exclude-members: __init__, __new__ Timeouts -------- diff --git a/docs/torrent.rst b/docs/torrent.rst index f7c5b41c..892ca297 100644 --- a/docs/torrent.rst +++ b/docs/torrent.rst @@ -28,12 +28,6 @@ Torrent :inherited-members: :exclude-members: __init__, __new__ -.. autoclass:: PortTestResult - :members: - :undoc-members: - :inherited-members: - :exclude-members: __init__, __new__ - .. toctree:: :maxdepth: 2 :caption: Contents: From f910072f10bb6531b9b2d4bd6b25a72b0465f725 Mon Sep 17 00:00:00 2001 From: Trim21 Date: Sat, 18 May 2024 13:34:47 +0800 Subject: [PATCH 23/31] update --- transmission_rpc/types.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/transmission_rpc/types.py b/transmission_rpc/types.py index 364b6479..414133b8 100644 --- a/transmission_rpc/types.py +++ b/transmission_rpc/types.py @@ -95,8 +95,8 @@ def port_is_open(self) -> bool: @property def ip_protocol(self) -> str: - """ipv4 if the test was carried out on IPv4, - ipv6 if the test was carried out on IPv6, + """``ipv4`` if the test was carried out on IPv4, + ``ipv6`` if the test was carried out on IPv6, unset if it cannot be determined Available in Transmission 4.1.0 (rpc-version-semver 5.4.0, rpc-version: 18) From 7804d14048a7cd90e469c3b7e50f5b86601db1a7 Mon Sep 17 00:00:00 2001 From: Trim21 Date: Sat, 18 May 2024 13:36:34 +0800 Subject: [PATCH 24/31] update --- docs/client.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/client.rst b/docs/client.rst index 36fb16e4..e9294e00 100644 --- a/docs/client.rst +++ b/docs/client.rst @@ -4,7 +4,7 @@ Client Client is the class handling the Transmission JSON-RPC client protocol. Torrent ids ------------- +----------- Many functions in Client takes torrent id. You can find torrent-ids spec in `official docs @@ -14,6 +14,8 @@ You can find torrent-ids spec in `official docs It's recommended that you use torrent's ``info_hash`` as torrent id. The torrent's ``info_hash`` will never change. +Client +------ .. automodule:: transmission_rpc From 32e426205c8f735605c5ae2596709dff57c33b70 Mon Sep 17 00:00:00 2001 From: Trim21 Date: Sat, 18 May 2024 13:39:57 +0800 Subject: [PATCH 25/31] update --- docs/conf.py | 1 + poetry.lock | 39 ++++++++++++++++++++++++++++++++++++++- pyproject.toml | 1 + 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index 6e94bd41..f2724fc0 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -37,6 +37,7 @@ "sphinx_copybutton", "furo.sphinxext", "sphinx.ext.linkcode", + "sphinx_new_tab_link", ] napoleon_numpy_docstring = False diff --git a/poetry.lock b/poetry.lock index 807ca4e2..ba9a2067 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1015,6 +1015,26 @@ sphinx = ">=1.8" code-style = ["pre-commit (==2.12.1)"] rtd = ["ipython", "myst-nb", "sphinx", "sphinx-book-theme", "sphinx-examples"] +[[package]] +name = "sphinx-new-tab-link" +version = "0.4.0" +description = "Open external links in new tabs of the browser in Sphinx HTML documents" +optional = false +python-versions = "*" +files = [ + {file = "sphinx-new-tab-link-0.4.0.tar.gz", hash = "sha256:aaefd94d5aa75c60a6c1e94b80d75c4281c3b6f95669b8e606f212744818b916"}, + {file = "sphinx_new_tab_link-0.4.0-py3-none-any.whl", hash = "sha256:2353bfd3a171fdbd9dcdf33e5f26b4447607293ff2b57e0f6a2dc18d1507598e"}, +] + +[package.dependencies] +sphinxcontrib-extdevhelper-kasane = "*" + +[package.extras] +dev = ["build", "twine", "wheel"] +lint = ["black", "flake8", "isort"] +testing = ["beautifulsoup4", "pytest"] +typecheck = ["mypy", "types-beautifulsoup"] + [[package]] name = "sphinxcontrib-applehelp" version = "1.0.8" @@ -1047,6 +1067,23 @@ lint = ["docutils-stubs", "flake8", "mypy"] standalone = ["Sphinx (>=5)"] test = ["pytest"] +[[package]] +name = "sphinxcontrib-extdevhelper-kasane" +version = "0.2.0" +description = "襲 - Provide dynamic inheritance shortcuts to make Sphinx extension development easier" +optional = false +python-versions = ">=3.8" +files = [ + {file = "sphinxcontrib-extdevhelper-kasane-0.2.0.tar.gz", hash = "sha256:4dc7b00327f33c7b421c27122b40278eeaca43f24601b572cee5616d31b206a9"}, + {file = "sphinxcontrib_extdevhelper_kasane-0.2.0-py3-none-any.whl", hash = "sha256:20f94e3b209cddec24596234458ea3887e7a7ad45b54a4d0a5bf169ff45a38f1"}, +] + +[package.dependencies] +Sphinx = "*" + +[package.extras] +dev = ["autoflake", "black", "flake8", "isort", "mypy", "pytest", "pytest-randomly", "pyupgrade", "taskipy"] + [[package]] name = "sphinxcontrib-htmlhelp" version = "2.0.5" @@ -1508,4 +1545,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "36548da496314e9ce1079ee05bb8b6d3db067b32b1b4bc5eb38dfe43bc141267" +content-hash = "d929886f8597f716cc0cf11742dba421a84e8fba474c308e0e8f6a7f9b8f36be" diff --git a/pyproject.toml b/pyproject.toml index c14a9799..1dfdaa9c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,6 +36,7 @@ typing-extensions = ">=4.5.0" sphinx = { version = "^7.3.7", python = "^3.9" } furo = { version = "2024.5.6", python = "^3.9" } sphinx-copybutton = { version = "^0.5.2", python = "^3.9" } +sphinx-new-tab-link = { version = "^0.4.0", python = "^3.9" } [tool.poetry.group.dev.dependencies] yarl = "==1.9.4" From 6d82f1ac23aeaf0b5e83459a0c98be720eafc048 Mon Sep 17 00:00:00 2001 From: Trim21 Date: Sat, 18 May 2024 13:52:21 +0800 Subject: [PATCH 26/31] update --- transmission_rpc/client.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/transmission_rpc/client.py b/transmission_rpc/client.py index 0d86be01..475b2d91 100644 --- a/transmission_rpc/client.py +++ b/transmission_rpc/client.py @@ -336,13 +336,21 @@ def _update_server_version(self) -> None: @property @deprecated("use .get_session().rpc_version_semver instead") def semver_version(self) -> Optional[int]: - """Get the Transmission daemon RPC version.""" + """Get the Transmission daemon RPC version. + + .. deprecated:: 7.0.5 + Use ``.get_session().rpc_version_semver`` instead + """ return self.__semver_version @property @deprecated("use .get_session().rpc_version instead") def rpc_version(self) -> int: - """Get the Transmission daemon RPC version.""" + """Get the Transmission daemon RPC version. + + .. deprecated:: 7.0.5 + Use ``.get_session().rpc_version`` instead + """ return self.__protocol_version def _rpc_version_warning(self, required_version: int) -> None: From 0d91d90c22cefabcd88f8f9e03abde6d23acd734 Mon Sep 17 00:00:00 2001 From: Trim21 Date: Sat, 18 May 2024 14:23:50 +0800 Subject: [PATCH 27/31] fix --- transmission_rpc/client.py | 38 +++++++++++++++----------------------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/transmission_rpc/client.py b/transmission_rpc/client.py index 475b2d91..2eda014f 100644 --- a/transmission_rpc/client.py +++ b/transmission_rpc/client.py @@ -4,7 +4,6 @@ import string import time import types -import urllib.parse from typing import Any, BinaryIO, Dict, Iterable, List, Optional, Tuple, Type, TypeVar, Union from urllib.parse import quote @@ -114,7 +113,7 @@ def __init__( if path == "/transmission/": path = "/transmission/rpc" - url = urllib.parse.urlunparse((protocol, f"{auth}{host}:{port}", path, None, None, None)) + url = f"{protocol}://{auth}{host}:{port}{path}" self._url = str(url) self._sequence = 0 self.__raw_session: Dict[str, Any] = {} @@ -620,13 +619,13 @@ def change_torrent( seed_idle_mode: Optional[int] = None, seed_ratio_limit: Optional[float] = None, seed_ratio_mode: Optional[int] = None, - tracker_add: Optional[Iterable[str]] = None, labels: Optional[Iterable[str]] = None, group: Optional[str] = None, tracker_list: Optional[Iterable[Iterable[str]]] = None, + sequential_download: Optional[bool] = None, + tracker_add: Optional[Iterable[str]] = None, tracker_replace: Optional[Iterable[Tuple[int, str]]] = None, tracker_remove: Optional[Iterable[int]] = None, - sequential_download: Optional[bool] = None, **kwargs: Any, ) -> None: """Change torrent parameters for the torrent(s) with the supplied id's. @@ -656,34 +655,27 @@ def change_torrent( Valid options are :py:class:`transmission_rpc.IdleMode` labels: Array of string labels. Add in rpc 16. group: The name of this torrent's bandwidth group. Add in rpc 17. - tracker_list: - A ``Iterable[Iterable[str]]``, each ``Iterable[str]`` for a tracker tier. + + tracker_list: A ``Iterable[Iterable[str]]``, each ``Iterable[str]`` for a tracker tier. Add in rpc 17. Example: ``[['https://tracker1/announce', 'https://tracker2/announce'], ['https://backup1.example.com/announce'], ['https://backup2.example.com/announce']]``. - tracker_add: - Array of string with announce URLs to add. - - Warnings: - since transmission daemon 4.0.0, this argument is deprecated, use ``tracker_list`` instead. - - tracker_remove: - Array of ids of trackers to remove. - - Warnings: - since transmission daemon 4.0.0, this argument is deprecated, use ``tracker_list`` instead. + sequential_download: download torrent pieces sequentially. Add in Transmission 4.1.0, rpc-version 18. - tracker_replace: - Array of (id, url) tuples where the announcement URL should be replaced. + tracker_add: Array of string with announce URLs to add. + **Deprecated** since transmission daemon 4.0.0, this argument is deprecated, + use ``tracker_list`` instead. - Warning: - since transmission daemon 4.0.0, this argument is deprecated, use ``tracker_list`` instead. + tracker_remove: Array of ids of trackers to remove. + **Deprecated** since transmission daemon 4.0.0, this argument is deprecated, + use ``tracker_list`` instead. - sequential_download: - download torrent pieces sequentially. Add in Transmission 4.1.0, rpc-version 18. + tracker_replace: Array of (id, url) tuples where the announcement URL should be replaced. + **Deprecated** since transmission daemon 4.0.0, this argument is deprecated, + use ``tracker_list`` instead. Warnings: ``kwargs`` is for the future features not supported yet, it's not compatibility promising. From bc1ee309dae4ccb3758ded70912367f46d666345 Mon Sep 17 00:00:00 2001 From: Trim21 Date: Sat, 18 May 2024 14:25:24 +0800 Subject: [PATCH 28/31] update --- transmission_rpc/client.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/transmission_rpc/client.py b/transmission_rpc/client.py index 2eda014f..49cd5505 100644 --- a/transmission_rpc/client.py +++ b/transmission_rpc/client.py @@ -679,7 +679,8 @@ def change_torrent( Warnings: ``kwargs`` is for the future features not supported yet, it's not compatibility promising. - It will be bypassed to request arguments **as-is**, the underline in the key will not be replaced, so you should use kwargs like ``{'a-argument': 'value'}`` + It will be bypassed to request arguments **as-is**, + the underline in the key will not be replaced, so you should use kwargs like ``{'a-argument': 'value'}`` """ if labels is not None: self._rpc_version_warning(16) @@ -739,7 +740,8 @@ def move_torrent_data( Move torrent data to the new location. See Also: - `RPC Spec: moving-a-torrent `_ + `RPC Spec: moving-a-torrent + `_ """ args = {"location": ensure_location_str(location), "move": bool(move)} self._request(RpcMethod.TorrentSetLocation, args, ids, True, timeout=timeout) @@ -759,7 +761,8 @@ def rename_torrent_path( This is not the method to move torrent data directory, See Also: - `RPC Spec: renaming-a-torrents-path `_ + `RPC Spec: renaming-a-torrents-path + `_ """ self._rpc_version_warning(15) torrent_id = _parse_torrent_id(torrent_id) @@ -1055,7 +1058,9 @@ def port_test( https://github.com/transmission/transmission/blob/main/docs/rpc-spec.md#44-port-checking Parameters: - ip_protocol: ``ipv4`` or ``ipv6``. Available in Transmission 4.1.0 (rpc-version-semver 5.4.0, rpc-version: 18) + ip_protocol: ``ipv4`` or ``ipv6``. + Available in Transmission 4.1.0 (rpc-version-semver 5.4.0, rpc-version: 18) + timeout: request timeout """ return PortTestResult( fields=self._request(RpcMethod.PortTest, remove_unset_value({"ipProtocol": ip_protocol}), timeout=timeout) From 34554c7099d81949b01780c81672d2a8fada42e3 Mon Sep 17 00:00:00 2001 From: Trim21 Date: Fri, 20 Sep 2024 21:36:49 +0800 Subject: [PATCH 29/31] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c8822bc6..05379592 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ `transmission-rpc` is a python wrapper on top of [transmission](https://github.com/transmission/transmission) JSON RPC protocol, hosted on GitHub at [github.com/trim21/transmission-rpc](https://github.com/trim21/transmission-rpc) -Support 2.40 (released 2011-10-05) <= transmission version <= 4.1.0 (released ...), +Support 2.40 (released 2011-10-05) <= transmission version <= 5.0.0 (released ...), should works fine with newer rpc version but some new feature may be missing. ## versioning From fc857fbde1bcbaefea42f8925b69fc0656064071 Mon Sep 17 00:00:00 2001 From: Trim21 Date: Fri, 13 Dec 2024 20:53:47 +0800 Subject: [PATCH 30/31] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 05379592..434b4916 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ `transmission-rpc` is a python wrapper on top of [transmission](https://github.com/transmission/transmission) JSON RPC protocol, hosted on GitHub at [github.com/trim21/transmission-rpc](https://github.com/trim21/transmission-rpc) -Support 2.40 (released 2011-10-05) <= transmission version <= 5.0.0 (released ...), +Support 2.40 (released 2011-10-05) <= transmission version <= 4.1.0-beta.1 (released 2024-12-13), should works fine with newer rpc version but some new feature may be missing. ## versioning From f8a5511980b76b66a35a2260dba338f65519dc9d Mon Sep 17 00:00:00 2001 From: Trim21 Date: Fri, 13 Dec 2024 20:54:49 +0800 Subject: [PATCH 31/31] merge --- transmission_rpc/__init__.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/transmission_rpc/__init__.py b/transmission_rpc/__init__.py index 52e1fb52..f0a47184 100644 --- a/transmission_rpc/__init__.py +++ b/transmission_rpc/__init__.py @@ -1,8 +1,8 @@ import logging import urllib.parse -from transmission_rpc.client import Client -from transmission_rpc.constants import DEFAULT_TIMEOUT, LOGGER, IdleMode, Priority, RatioLimitMode +from transmission_rpc.client import DEFAULT_TIMEOUT, Client +from transmission_rpc.constants import LOGGER, IdleMode, Priority, RatioLimitMode from transmission_rpc.error import ( TransmissionAuthError, TransmissionConnectError, @@ -51,6 +51,7 @@ def from_url( from_url("https://127.0.0.1/transmission/rpc") # https://127.0.0.1:443/transmission/rpc from_url("http://127.0.0.1") # http://127.0.0.1:80/transmission/rpc from_url("http://127.0.0.1/") # http://127.0.0.1:80/ + from_url("http+unix://%2Fvar%2Frun%2Ftransmission.sock/transmission/rpc") # /transmission/rpc on /var/run/transmission.sock Unix socket Warnings: you can't ignore scheme, ``127.0.0.1:9091`` is not valid url, please use ``http://127.0.0.1:9091`` @@ -62,10 +63,16 @@ def from_url( u = urllib.parse.urlparse(url) protocol = u.scheme + host = u.hostname + default_port = None if protocol == "http": default_port = 80 elif protocol == "https": default_port = 443 + elif protocol == "http+unix": + if host is None: + raise ValueError("http+unix URL is missing Unix socket path") + host = urllib.parse.unquote(host, errors="strict") else: raise ValueError(f"unknown url scheme {u.scheme}") @@ -73,7 +80,7 @@ def from_url( protocol=protocol, # type: ignore username=u.username, password=u.password, - host=u.hostname or "127.0.0.1", + host=host or "127.0.0.1", port=u.port or default_port, path=u.path or "/transmission/rpc", timeout=timeout,