Skip to content

Commit

Permalink
Merge pull request #121 from rmartin16/next-version
Browse files Browse the repository at this point in the history
qBittorrent v4.5.0 Support
  • Loading branch information
rmartin16 authored Nov 27, 2022
2 parents cba24ed + b3c2af3 commit 23c8677
Show file tree
Hide file tree
Showing 43 changed files with 1,995 additions and 978 deletions.
12 changes: 8 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,11 @@ on:
branches:
- main
pull_request:
branches:
- main
workflow_dispatch:

env:
LATEST_PYTHON_VER: "3.11"
LATEST_QBT_VER: "v4.4.5"
LATEST_QBT_VER: "v4.5.0"
SUBMIT_COVERAGE_VERSIONS: '[ "3.11" ]'
QBITTORRENTAPI_HOST: "localhost:8080"
QBITTORRENTAPI_PASSWORD: "adminadmin"
Expand Down Expand Up @@ -49,6 +47,9 @@ jobs:
check-latest: true
cache-dependency-path: ${{ github.workspace }}/setup.cfg

- name: Install
run: pip install .[dev]

- name: Lint
uses: pre-commit/action@v3.0.0

Expand All @@ -64,7 +65,7 @@ jobs:
strategy:
matrix:
PYTHON_VER: [ "${{ needs.verify.outputs.python-latest-version }}" ]
QBT_VER: [ v4.4.4, v4.3.9, v4.3.5, v4.3.4.1, v4.3.3, v4.3.2, v4.3.1, v4.3.0.1, v4.2.5, v4.2.0, v4.1.6, v4.1.0 ]
QBT_VER: [ v4.5.0, v4.4.4, v4.3.9, v4.3.5, v4.3.4.1, v4.3.3, v4.3.2, v4.3.1, v4.3.0.1, v4.2.5, v4.2.0, v4.1.6, v4.1.0 ]
include:
# test all python versions against latest qBittorrent
- PYTHON_VER: "3.12-dev"
Expand Down Expand Up @@ -95,6 +96,9 @@ jobs:
- QBT_VER: "master"
IS_QBT_DEV: true
PYTHON_VER: ${{ needs.verify.outputs.python-latest-version }}
- QBT_VER: "v4_5_x"
IS_QBT_DEV: true
PYTHON_VER: ${{ needs.verify.outputs.python-latest-version }}
- QBT_VER: "v4_4_x"
IS_QBT_DEV: true
PYTHON_VER: ${{ needs.verify.outputs.python-latest-version }}
Expand Down
35 changes: 32 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
repos:

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.3.0
rev: v4.4.0
hooks:
- id: check-toml
- id: check-yaml
Expand All @@ -17,7 +17,7 @@ repos:
additional_dependencies: [toml]

- repo: https://github.com/asottile/pyupgrade
rev: v2.38.4 # DO NOT UPGRADE THIS - v3 drops python 2 support
rev: v2.38.4 # DO NOT UPGRADE THIS - use v2.38.4 - v3 drops Python 2 support
hooks:
- id: pyupgrade

Expand All @@ -37,4 +37,33 @@ repos:
rev: 5.0.4
hooks:
- id: flake8
additional_dependencies: [flake8-eradicate~=1.4]
additional_dependencies: [flake8-eradicate]

- repo: https://github.com/pre-commit/mirrors-mypy
rev: v0.991
hooks:
- id: mypy
files: '.*\.pyi'
additional_dependencies: ["types-requests", "types-six"]
args:
- "--strict"
- "--disallow-any-unimported"
- "--disallow-any-expr"
- "--disallow-any-decorated"
- "--warn-unreachable"
- "--warn-unused-ignores"
- "--warn-redundant-casts"
- "--strict-optional"

- repo: local
hooks:
- id: stubtest
name: mypy.stubtest
language: system
entry: stubtest
args: [ "qbittorrentapi", "--allowlist=tests/resources/mypy_stubtest_allowlist.txt" ]
pass_filenames: false
types_or:
- python
- text
files: '.*\.pyi?'
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
Change log
==========
### v2022.11.40 (27 nov 2022)
- Support qBittorrent v4.5.0 release
- Add support for ``torrents/export``
- Implement new ``transfer/setSpeedLimitsMode`` in place of existing ``transfer/toggleSpeedLimitsMode``
- Add support for ``stopCondition`` in ``torrents/add``
- Update typing to be complete, accurate, and shipped with the package

### v2022.10.39 (26 oct 2022)
- Advertise support for Python 3.11

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Python client implementation for qBittorrent Web API

</div>

Currently supports qBittorrent [v4.4.5](https://github.com/qbittorrent/qBittorrent/releases/tag/release-4.4.5) (Web API v2.8.5) released on Aug 29, 2022.
Currently supports qBittorrent [v4.5.0](https://github.com/qbittorrent/qBittorrent/releases/tag/release-4.5.0) (Web API v2.8.18) released on Nov 26, 2022.

User Guide and API Reference available on [Read the Docs](https://qbittorrent-api.readthedocs.io/).

Expand Down
2 changes: 1 addition & 1 deletion docs/source/introduction.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Introduction

Python client implementation for qBittorrent Web API.

Currently supports qBittorrent `v4.4.5 <https://github.com/qbittorrent/qBittorrent/releases/tag/release-4.4.5>`_ (Web API v2.8.5) released on Aug 29, 2022.
Currently supports qBittorrent `v4.5.0 <https://github.com/qbittorrent/qBittorrent/releases/tag/release-4.5.0>`_ (Web API v2.8.18) released on Nov 26, 2022.

Features
------------
Expand Down
23 changes: 10 additions & 13 deletions qbittorrentapi/_attrdict.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
from abc import abstractmethod
from re import match as re_match

import six

try: # python 3
from collections.abc import Mapping
from collections.abc import MutableMapping
Expand All @@ -41,11 +43,6 @@
from collections import MutableMapping
from collections import Sequence

from six import add_metaclass as six_add_metaclass
from six import binary_type as six_binary_type
from six import string_types as six_string_types
from six import u as six_u


def merge(left, right):
"""
Expand Down Expand Up @@ -85,7 +82,7 @@ def merge(left, right):
return merged


@six_add_metaclass(ABCMeta)
@six.add_metaclass(ABCMeta)
class Attr(Mapping):
"""
A mixin class for a mapping that allows for attribute-style access of
Expand Down Expand Up @@ -195,7 +192,7 @@ def _build(self, obj):
if isinstance(obj, Mapping):
obj = self._constructor(obj, self._configuration())
elif isinstance(obj, Sequence) and not isinstance(
obj, (six_string_types, six_binary_type)
obj, (six.string_types, six.binary_type)
):
sequence_type = getattr(self, "_sequence_type", None)

Expand All @@ -217,13 +214,13 @@ def _valid_name(cls, key):
'register').
"""
return (
isinstance(key, six_string_types)
isinstance(key, six.string_types)
and re_match("^[A-Za-z][A-Za-z0-9_]*$", key)
and not hasattr(cls, key)
)


@six_add_metaclass(ABCMeta)
@six.add_metaclass(ABCMeta)
class MutableAttr(Attr, MutableMapping):
"""A mixin class for a mapping that allows for attribute-style access of
values."""
Expand Down Expand Up @@ -289,7 +286,7 @@ def _configuration(self):

def __getstate__(self):
"""Serialize the object."""
return (self.copy(), self._sequence_type, self._allow_invalid_attributes)
return self.copy(), self._sequence_type, self._allow_invalid_attributes

def __setstate__(self, state):
"""Deserialize the object."""
Expand All @@ -299,7 +296,7 @@ def __setstate__(self, state):
self._setattr("_allow_invalid_attributes", allow_invalid_attributes)

def __repr__(self):
return six_u("AttrDict({contents})").format(
return six.u("AttrDict({contents})").format(
contents=super(AttrDict, self).__repr__()
)

Expand Down Expand Up @@ -369,7 +366,7 @@ def _constructor(cls, mapping, configuration):
# # sequence type seems like more trouble than it is worth.
# # If people want full serialization, they can pickle, and in
# # 99% of cases, sequence_type won't change anyway
# return six_u("AttrMap({mapping})").format(mapping=repr(self._mapping))
# return six.u("AttrMap({mapping})").format(mapping=repr(self._mapping))
#
# def __getstate__(self):
# """
Expand Down Expand Up @@ -474,7 +471,7 @@ def _constructor(cls, mapping, configuration):
# """
# Return a string representation of the object.
# """
# return six_u(
# return six.u(
# "AttrDefault({default_factory}, {pass_key}, {mapping})"
# ).format(
# default_factory=repr(self._default_factory),
Expand Down
47 changes: 33 additions & 14 deletions qbittorrentapi/_attrdict.pyi
Original file line number Diff line number Diff line change
@@ -1,18 +1,37 @@
import abc
from collections import Mapping
from collections import MutableMapping
from abc import ABCMeta
from typing import Any
from typing import Dict
from typing import Mapping
from typing import MutableMapping
from typing import Text
from typing import TypeVar

def merge(left, right): ...
K = TypeVar("K")
KOther = TypeVar("KOther")
V = TypeVar("V")
VOther = TypeVar("VOther")
KwargsT = Any

class Attr(Mapping, metaclass=abc.ABCMeta):
def __call__(self, key): ...
def __getattr__(self, key): ...
def __add__(self, other): ...
def __radd__(self, other): ...
def merge(
left: Mapping[K, V],
right: Mapping[KOther, VOther],
) -> Dict[K | KOther, V | VOther]: ...

class MutableAttr(Attr, MutableMapping, metaclass=abc.ABCMeta):
def __setattr__(self, key, value) -> None: ...
def __delattr__(self, key, force: bool = ...) -> None: ...
class Attr(Mapping[K, V], metaclass=ABCMeta):
def __call__(self, key: K) -> V: ...
def __getattr__(self, key: Text) -> V: ...
def __add__(
self,
other: Mapping[KOther, VOther],
) -> Attr[K | KOther, V | VOther]: ...
def __radd__(
self,
other: Mapping[KOther, VOther],
) -> Attr[K | KOther, V | VOther]: ...

class AttrDict(dict, MutableAttr):
def __init__(self, *args, **kwargs) -> None: ...
class MutableAttr(Attr[K, V], MutableMapping[K, V], metaclass=ABCMeta):
def __setattr__(self, key: Text, value: V) -> None: ...
def __delattr__(self, key: Text, force: bool = ...) -> None: ...

class AttrDict(Dict[K, V], MutableAttr[K, V]):
def __init__(self, *args: Any, **kwargs: KwargsT) -> None: ...
28 changes: 28 additions & 0 deletions qbittorrentapi/_types.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from typing import IO
from typing import Any
from typing import Iterable
from typing import Mapping
from typing import Sequence
from typing import Text
from typing import Tuple
from typing import Union

from qbittorrentapi.definitions import Dictionary

KwargsT = Any
# Type to define JSON
JsonValueT = Union[
None,
int,
Text,
bool,
Sequence[JsonValueT],
Mapping[Text, JsonValueT],
]
JsonDictionaryT = Dictionary[Text, JsonValueT]
# Type for inputs to build a Dictionary
DictInputT = Mapping[Text, JsonValueT]
# Type for inputs to build a List
ListInputT = Iterable[Mapping[Text, JsonValueT]]
# Type for `files` in requests.get()/post()
FilesToSendT = Mapping[Text, IO[bytes] | Tuple[Text, IO[bytes]]]
6 changes: 4 additions & 2 deletions qbittorrentapi/_version_support.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,12 @@
"v4.4.3.1": "2.8.5",
"v4.4.4": "2.8.5",
"v4.4.5": "2.8.5",
"v4.5.0beta1": "2.8.14",
"v4.5.0": "2.8.18",
}

MOST_RECENT_SUPPORTED_APP_VERSION = "v4.4.5"
MOST_RECENT_SUPPORTED_API_VERSION = "2.8.5"
MOST_RECENT_SUPPORTED_APP_VERSION = "v4.5.0"
MOST_RECENT_SUPPORTED_API_VERSION = "2.8.18"


@lru_cache(maxsize=None)
Expand Down
11 changes: 6 additions & 5 deletions qbittorrentapi/_version_support.pyi
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
from typing import Dict
from typing import Optional
from typing import Set
from typing import Text

from pkg_resources.extern.packaging.version import Version as _Version
from pkg_resources.extern.packaging.version import Version as _Version # type: ignore

MOST_RECENT_SUPPORTED_APP_VERSION: Text
MOST_RECENT_SUPPORTED_API_VERSION: Text
APP_VERSION_2_API_VERSION_MAP: Dict
APP_VERSION_2_API_VERSION_MAP: Dict[Text, Text]

def v(version: Text) -> _Version: ...
def v(version: Text) -> _Version: ... # type: ignore

class Version:
_supported_app_versions: Set = None
_supported_api_versions: Set = None
_supported_app_versions: Optional[Set[str]] = None
_supported_api_versions: Optional[Set[str]] = None
@classmethod
def supported_app_versions(cls) -> Set[str]: ...
@classmethod
Expand Down
Loading

0 comments on commit 23c8677

Please sign in to comment.