From d68b7e12cae187a53fc6e25715853ac2ba0f1af8 Mon Sep 17 00:00:00 2001 From: Lukasz Socha Date: Thu, 9 Dec 2021 16:04:26 +0100 Subject: [PATCH 1/2] chore!: Drop support for python 2.7 --- .travis.yml | 6 ++-- .travis/install.sh | 30 +++-------------- .travis/run.sh | 2 +- HISTORY.rst | 23 ++++++------- boxsdk/auth/cooperatively_managed_oauth2.py | 3 +- boxsdk/auth/developer_token_auth.py | 2 +- boxsdk/auth/jwt_auth.py | 2 +- boxsdk/auth/oauth2.py | 17 +++++----- boxsdk/auth/redis_managed_jwt_auth.py | 2 +- boxsdk/auth/redis_managed_oauth2.py | 5 ++- boxsdk/auth/remote_managed_oauth2.py | 3 +- boxsdk/client/client.py | 2 +- boxsdk/client/developer_token_client.py | 5 +-- boxsdk/client/logging_client.py | 2 +- boxsdk/config.py | 6 ++-- boxsdk/exception.py | 1 - boxsdk/network/default_network.py | 2 +- boxsdk/network/network_interface.py | 27 ++++++++------- boxsdk/object/api_json_object.py | 1 - boxsdk/object/base_api_json_object.py | 9 +++-- boxsdk/object/base_endpoint.py | 2 +- boxsdk/object/base_object.py | 6 ++-- boxsdk/object/cloneable.py | 2 +- boxsdk/object/collaboration.py | 4 +-- boxsdk/object/events.py | 33 +++++++++---------- boxsdk/object/file.py | 6 ++-- boxsdk/object/folder.py | 4 +-- boxsdk/object/item.py | 15 ++++----- boxsdk/object/metadata.py | 4 +-- boxsdk/object/metadata_template.py | 12 +++---- boxsdk/object/search.py | 8 ++--- boxsdk/object/upload_session.py | 2 +- boxsdk/object/user.py | 2 +- boxsdk/object/web_link.py | 6 ++-- boxsdk/pagination/box_object_collection.py | 8 ++--- .../limit_offset_based_object_collection.py | 2 +- .../marker_based_object_collection.py | 2 +- boxsdk/pagination/page.py | 2 +- boxsdk/session/box_request.py | 2 +- boxsdk/session/box_response.py | 2 +- boxsdk/session/session.py | 12 +++---- boxsdk/util/api_call_decorator.py | 4 +-- boxsdk/util/chain_map.py | 20 ----------- boxsdk/util/chunked_uploader.py | 4 +-- boxsdk/util/log.py | 2 +- boxsdk/util/lru_cache.py | 4 +-- boxsdk/util/multipart_stream.py | 2 +- boxsdk/util/translator.py | 20 +++-------- docs/source/boxsdk.util.rst | 8 ----- setup.py | 30 ++--------------- test/conftest.py | 19 +++++------ test/functional/conftest.py | 2 +- test/functional/test_recovery.py | 2 +- test/integration/mock_network.py | 2 +- test/unit/auth/test_jwt_auth.py | 2 +- test/unit/auth/test_oauth2.py | 9 ++--- test/unit/object/test_base_api_json_object.py | 4 +-- test/unit/object/test_base_item.py | 12 +++---- test/unit/object/test_device_pin.py | 2 +- test/unit/object/test_group.py | 1 - test/unit/object/test_item.py | 2 +- test/unit/object/test_legal_hold_policy.py | 4 +-- test/unit/object/test_search.py | 2 +- test/unit/object/test_terms_of_service.py | 6 ++-- .../test_terms_of_service_user_status.py | 2 +- test/unit/object/test_trash.py | 2 +- .../box_object_collection_test_base.py | 7 ++-- ...st_limit_offset_based_object_collection.py | 2 +- test/unit/session/test_session.py | 2 +- test/unit/util/test_api_call_decorator.py | 2 +- test/unit/util/test_compat.py | 4 +-- test/unit/util/test_translator.py | 8 ++--- tox.ini | 3 +- 73 files changed, 190 insertions(+), 291 deletions(-) delete mode 100644 boxsdk/util/chain_map.py diff --git a/.travis.yml b/.travis.yml index 1607d9fc7..88373f5e5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,12 +15,10 @@ before_cache: matrix: include: - - python: 2.7 + - python: 3.5 env: TOX_ENV=pycodestyle - - python: 2.7 + - python: 3.5 env: TOX_ENV=pylint - - python: 2.7 - env: TOX_ENV=py27 - python: 3.5 env: TOX_ENV=py35 - python: 3.6 diff --git a/.travis/install.sh b/.travis/install.sh index 6de2af39f..5305abd80 100755 --- a/.travis/install.sh +++ b/.travis/install.sh @@ -21,22 +21,6 @@ if [[ "$(uname -s)" == 'Darwin' ]]; then fi case "${TOX_ENV}" in - py26) - curl -O https://bootstrap.pypa.io/get-pip.py - python get-pip.py --user - ;; - py27) - curl -O https://bootstrap.pypa.io/get-pip.py - python get-pip.py --user - ;; - py33) - pyenv install 3.3.6 - pyenv global 3.3.6 - ;; - py34) - pyenv install 3.4.2 - pyenv global 3.4.2 - ;; py35) pyenv install 3.5.0 pyenv global 3.5.0 @@ -45,10 +29,15 @@ if [[ "$(uname -s)" == 'Darwin' ]]; then pyenv install 3.6.0 pyenv global 3.6.0 ;; + py37) + pyenv install 3.7.0 + pyenv global 3.7.0 + ;; pypy) pyenv install "pypy${PYPY_VERSION}" pyenv global "pypy${PYPY_VERSION}" ;; + esac pyenv rehash python -m pip install -U --user virtualenv @@ -65,15 +54,6 @@ else pip install -U virtualenv pip install --upgrade pip python -m venv $PWD/.venv - elif [[ "${TOX_ENV}" == "py27" ]] || [[ "${TOX_ENV}" == "pycodestyle" ]] || [[ "${TOX_ENV}" == "pylint" ]]; then - git clone https://github.com/yyuu/pyenv.git $PWD/.pyenv - export PYENV_ROOT="$PWD/.pyenv" - export PATH="$PYENV_ROOT/bin:$PATH" - eval "$(pyenv init --path)" - pyenv install 2.7.14 - pyenv global 2.7.14 - pip install -U virtualenv - python -m virtualenv $PWD/.venv else python -m virtualenv $PWD/.venv fi diff --git a/.travis/run.sh b/.travis/run.sh index c8e2eac41..f3a5cb8e2 100755 --- a/.travis/run.sh +++ b/.travis/run.sh @@ -10,7 +10,7 @@ set -o pipefail if [[ "$(uname -s)" == "Darwin" ]]; then eval "$(pyenv init -)" else - if [[ "${TOX_ENV}" == "pypy" ]] || [[ "${TOX_ENV}" == "py27" ]] || [[ "${TOX_ENV}" == "pycodestyle" ]] || [[ "${TOX_ENV}" == "pylint" ]]; then + if [[ "${TOX_ENV}" == "pypy" ]]; then export PYENV_ROOT="$PWD/.pyenv" export PATH="$PYENV_ROOT/bin:$PATH" eval "$(pyenv init -)" diff --git a/HISTORY.rst b/HISTORY.rst index dea81d17b..05e699596 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -4,7 +4,7 @@ Release History --------------- 2.14.0 (2021-12-08) -++++++++ +++++++++++++++++++++ **New Features and Enhancements:** @@ -14,11 +14,12 @@ Release History - Support base item operations for WebLink class (`#639 `_) **Bug Fixes:** + - Limit cryptography to version <3.5.0 (`#636 `_) - Avoid raising 404 when a thumbnail cannot be generated for a file (`#642 `_) 2.13.0 (2021-09-30) -++++++++ +++++++++++++++++++++ **New Features and Enhancements:** @@ -30,14 +31,14 @@ Release History - Upgrade cryptography to version 3 (`#620 `_) 2.12.1 (2021-06-16) -++++++++ +++++++++++++++++++++ **Bug Fixes:** - Fix bug when thumbnail representations are not found (`#597 `_) 2.12.0 (2021-04-16) -++++++++ +++++++++++++++++++++ **New Features and Enhancements:** @@ -47,14 +48,14 @@ Release History - Update `get_groups()` to use documented parameter to filter by name (`#586 `_) 2.11.0 (2021-01-11) -++++++++ +++++++++++++++++++++ **New Features and Enhancements:** - Deprecate and add method for getting a thumbnail (`#572 `_) 2.10.0 (2020-10-02) -++++++++ +++++++++++++++++++++ **New Features and Enhancements:** @@ -68,21 +69,21 @@ Release History - Allow ints to be passed in as item IDs (`#530 `_) 2.9.0 (2020-06-23) -++++++++ +++++++++++++++++++++ - Fix exception handling for OAuth - Fix path parameter sanitization 2.8.0 (2020-04-24) -++++++++ +++++++++++++++++++++ - Added support for token exchange using shared links - Added the ability to pass in a SHA1 value for file uploads 2.7.1 (2020-01-21) -++++++++ +++++++++++++++++++++ - Fixed bug in `_get_retry_request_callable` introduced in release 2.7.0 which caused chunked uploads to fail 2.7.0 (2020-01-16) -++++++++ +++++++++++++++++++++ - Fixed bug in `get_admin_events` function which caused errors when the optional `event_types` parameter was omitted. - Add marker based pagination for listing users. - Added support for more attribute parameters when uploading new files and new versions of existing files. @@ -93,7 +94,7 @@ Release History 2.6.1 (2019-10-24) ++++++++++++++++++ -- Added api_ call decorator for copy method. +- Added `api_call` decorator for copy method. 2.6.0 (2019-08-29) ++++++++++++++++++ diff --git a/boxsdk/auth/cooperatively_managed_oauth2.py b/boxsdk/auth/cooperatively_managed_oauth2.py index 9c3c32d54..835c82802 100644 --- a/boxsdk/auth/cooperatively_managed_oauth2.py +++ b/boxsdk/auth/cooperatively_managed_oauth2.py @@ -18,7 +18,7 @@ def __init__(self, retrieve_tokens=None, *args, **kwargs): """ # pylint:disable=keyword-arg-before-vararg self._retrieve_tokens = retrieve_tokens - super(CooperativelyManagedOAuth2Mixin, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def _get_tokens(self): """ @@ -33,4 +33,3 @@ class CooperativelyManagedOAuth2(CooperativelyManagedOAuth2Mixin): Allows for sharing auth tokens between multiple clients. The retrieve_tokens callback should return the current access/refresh token pair. """ - pass diff --git a/boxsdk/auth/developer_token_auth.py b/boxsdk/auth/developer_token_auth.py index 2185b2d5c..32780b490 100644 --- a/boxsdk/auth/developer_token_auth.py +++ b/boxsdk/auth/developer_token_auth.py @@ -12,7 +12,7 @@ class DeveloperTokenAuth(OAuth2): def __init__(self, get_new_token_callback=None, **kwargs): self._get_new_token = get_new_token_callback - super(DeveloperTokenAuth, self).__init__( + super().__init__( client_id=None, client_secret=None, access_token=self._refresh_developer_token(), diff --git a/boxsdk/auth/jwt_auth.py b/boxsdk/auth/jwt_auth.py index 4de959f92..533d4ef25 100644 --- a/boxsdk/auth/jwt_auth.py +++ b/boxsdk/auth/jwt_auth.py @@ -144,7 +144,7 @@ def __init__( ) del rsa_private_key_data del rsa_private_key_file_sys_path - super(JWTAuth, self).__init__( + super().__init__( client_id, client_secret, store_tokens=store_tokens, diff --git a/boxsdk/auth/oauth2.py b/boxsdk/auth/oauth2.py index 9e1d2c46a..da45c0a8f 100644 --- a/boxsdk/auth/oauth2.py +++ b/boxsdk/auth/oauth2.py @@ -9,9 +9,9 @@ import sys from threading import Lock -# pylint:disable=import-error,no-name-in-module,relative-import +# pylint:disable=import-error,no-name-in-module from six.moves.urllib.parse import urlencode, urlunsplit -# pylint:enable=import-error,no-name-in-module,relative-import +# pylint:enable=import-error,no-name-in-module import six from ..config import API @@ -38,10 +38,9 @@ class TokenScope(TextEnum): class TokenResponse(BaseAPIJSONObject): """ Represents the response for a token request. """ - pass -class OAuth2(object): +class OAuth2: """ Responsible for handling OAuth2 for the Box API. Can authenticate and refresh tokens. @@ -344,13 +343,14 @@ def _execute_token_request(self, data, access_token, expect_refresh_token=True): access_token=access_token, ) except BoxAPIException as box_api_exception: - six.raise_from(self._oauth_exception(box_api_exception.network_response, url), box_api_exception) + raise self._oauth_exception(box_api_exception.network_response, url) from box_api_exception + if not network_response.ok: raise self._oauth_exception(network_response, url) try: token_response = TokenResponse(network_response.json()) - except ValueError: - raise self._oauth_exception(network_response, url) + except ValueError as value_exception: + raise self._oauth_exception(network_response, url) from value_exception if ('access_token' not in token_response) or (expect_refresh_token and 'refresh_token' not in token_response): raise self._oauth_exception(network_response, url) @@ -426,7 +426,8 @@ def revoke(self): access_token=access_token, ) except BoxAPIException as box_api_exception: - six.raise_from(self._oauth_exception(box_api_exception.network_response, url), box_api_exception) + raise self._oauth_exception(box_api_exception.network_response, url) from box_api_exception + if not network_response.ok: raise BoxOAuthException( network_response.status_code, diff --git a/boxsdk/auth/redis_managed_jwt_auth.py b/boxsdk/auth/redis_managed_jwt_auth.py index 74edab366..22d9f19f6 100644 --- a/boxsdk/auth/redis_managed_jwt_auth.py +++ b/boxsdk/auth/redis_managed_jwt_auth.py @@ -14,4 +14,4 @@ def _auth_with_jwt(self, sub, sub_type): """ Base class override. Returns the access token in a tuple to match the OAuth2 interface. """ - return super(RedisManagedJWTAuth, self)._auth_with_jwt(sub, sub_type), None + return super()._auth_with_jwt(sub, sub_type), None diff --git a/boxsdk/auth/redis_managed_oauth2.py b/boxsdk/auth/redis_managed_oauth2.py index 3915bff55..121f51c4c 100644 --- a/boxsdk/auth/redis_managed_oauth2.py +++ b/boxsdk/auth/redis_managed_oauth2.py @@ -30,7 +30,7 @@ def __init__(self, unique_id=uuid4(), redis_server=None, *args, **kwargs): self._unique_id = unique_id self._redis_server = redis_server or StrictRedis() refresh_lock = Lock(redis=self._redis_server, name='{0}_lock'.format(self._unique_id)) - super(RedisManagedOAuth2Mixin, self).__init__(*args, refresh_lock=refresh_lock, **kwargs) + super().__init__(*args, refresh_lock=refresh_lock, **kwargs) if self._access_token is None: self._get_and_update_current_tokens() @@ -54,7 +54,7 @@ def _store_tokens(self, access_token, refresh_token): Base class override. Saves the refreshed tokens in redis. """ - super(RedisManagedOAuth2Mixin, self)._store_tokens(access_token, refresh_token) + super()._store_tokens(access_token, refresh_token) self._redis_server.hmset(self._unique_id, {'access': access_token, 'refresh': refresh_token}) @@ -62,4 +62,3 @@ class RedisManagedOAuth2(RedisManagedOAuth2Mixin): """ OAuth2 subclass which uses Redis to manage tokens. """ - pass diff --git a/boxsdk/auth/remote_managed_oauth2.py b/boxsdk/auth/remote_managed_oauth2.py index 9a8bb7ca9..62c3982f1 100644 --- a/boxsdk/auth/remote_managed_oauth2.py +++ b/boxsdk/auth/remote_managed_oauth2.py @@ -19,7 +19,7 @@ def __init__(self, retrieve_access_token=None, *args, **kwargs): """ # pylint:disable=keyword-arg-before-vararg self._retrieve_access_token = retrieve_access_token - super(RemoteOAuth2Mixin, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def _refresh(self, access_token): """ @@ -35,4 +35,3 @@ class RemoteOAuth2(RemoteOAuth2Mixin): Allows for storing auth tokens remotely. The retrieve_access_token callback should return an access token, presumably acquired from a remote server on which your auth credentials are available. """ - pass diff --git a/boxsdk/client/client.py b/boxsdk/client/client.py index cb836643a..100a28f72 100644 --- a/boxsdk/client/client.py +++ b/boxsdk/client/client.py @@ -37,7 +37,7 @@ def __init__( :type session: :class:`BoxSession` """ - super(Client, self).__init__() + super().__init__() self._oauth = oauth if session is not None: self._session = session diff --git a/boxsdk/client/developer_token_client.py b/boxsdk/client/developer_token_client.py index 2fa513665..3bdc2e3ca 100644 --- a/boxsdk/client/developer_token_client.py +++ b/boxsdk/client/developer_token_client.py @@ -11,7 +11,4 @@ class DeveloperTokenClient(Client): Box client subclass which authorizes with a developer token. """ def __init__(self, oauth=None, session=None): - super(DeveloperTokenClient, self).__init__( - oauth=oauth or DeveloperTokenAuth(), - session=session, - ) + super().__init__(oauth=oauth or DeveloperTokenAuth(), session=session) diff --git a/boxsdk/client/logging_client.py b/boxsdk/client/logging_client.py index c34c0fb2c..cab949c43 100644 --- a/boxsdk/client/logging_client.py +++ b/boxsdk/client/logging_client.py @@ -12,4 +12,4 @@ class LoggingClient(Client): """ def __init__(self, *args, **kwargs): setup_logging(None) - super(LoggingClient, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) diff --git a/boxsdk/config.py b/boxsdk/config.py index a662109c9..05734db05 100644 --- a/boxsdk/config.py +++ b/boxsdk/config.py @@ -7,7 +7,7 @@ from . import version -class API(object): +class API: """Configuration object containing the URLs for the Box API.""" BASE_API_URL = 'https://api.box.com/2.0' UPLOAD_URL = 'https://upload.box.com/api/2.0' @@ -16,7 +16,7 @@ class API(object): MAX_RETRY_ATTEMPTS = 5 -class Client(object): +class Client: """Configuration object containing the user agent string.""" VERSION = version.__version__ USER_AGENT_STRING = 'box-python-sdk-{0}'.format(VERSION) @@ -28,6 +28,6 @@ class Client(object): ) -class Proxy(object): +class Proxy: URL = None AUTH = None diff --git a/boxsdk/exception.py b/boxsdk/exception.py index e60cf9e6a..8d0e070ca 100644 --- a/boxsdk/exception.py +++ b/boxsdk/exception.py @@ -29,7 +29,6 @@ class BoxNetworkException(BoxException): """ Exception raised from the network layer. """ - pass @attr.s(repr=True, slots=True, frozen=True) diff --git a/boxsdk/network/default_network.py b/boxsdk/network/default_network.py index 9c6448bf1..2d9d7fd2d 100644 --- a/boxsdk/network/default_network.py +++ b/boxsdk/network/default_network.py @@ -22,7 +22,7 @@ class DefaultNetwork(Network): EXCEPTION_FORMAT = '\x1b[31mRequest "%(method)s %(url)s" failed with %(exc_type_name)s exception: %(exc_value)r\x1b[0m' def __init__(self): - super(DefaultNetwork, self).__init__() + super().__init__() self._session = requests.Session() self._logger = getLogger(__name__) diff --git a/boxsdk/network/network_interface.py b/boxsdk/network/network_interface.py index 388dc44b2..b476d089e 100644 --- a/boxsdk/network/network_interface.py +++ b/boxsdk/network/network_interface.py @@ -2,12 +2,10 @@ from __future__ import unicode_literals -from abc import ABCMeta, abstractmethod, abstractproperty -from six import add_metaclass +from abc import ABC, abstractmethod -@add_metaclass(ABCMeta) -class Network(object): +class Network(ABC): """ Abstract base class specifying the interface of the network layer. """ @@ -71,8 +69,7 @@ def network_response_constructor(self): return NetworkResponse -@add_metaclass(ABCMeta) -class NetworkResponse(object): +class NetworkResponse(ABC): """Abstract base class specifying the interface for a network response.""" @abstractmethod @@ -84,7 +81,8 @@ def json(self): """ raise NotImplementedError # pragma: no cover - @abstractproperty + @property + @abstractmethod def content(self): """Return the content of the response body. @@ -93,7 +91,8 @@ def content(self): """ raise NotImplementedError # pragma: no cover - @abstractproperty + @property + @abstractmethod def status_code(self): """Return the HTTP status code of the response. @@ -102,7 +101,8 @@ def status_code(self): """ raise NotImplementedError # pragma: no cover - @abstractproperty + @property + @abstractmethod def ok(self): """Return whether or not the request was successful. @@ -112,7 +112,8 @@ def ok(self): # pylint:disable=invalid-name raise NotImplementedError # pragma: no cover - @abstractproperty + @property + @abstractmethod def headers(self): """Return the response headers. @@ -121,7 +122,8 @@ def headers(self): """ raise NotImplementedError # pragma: no cover - @abstractproperty + @property + @abstractmethod def response_as_stream(self): """Return a stream containing the raw network response. @@ -130,7 +132,8 @@ def response_as_stream(self): """ raise NotImplementedError # pragma: no cover - @abstractproperty + @property + @abstractmethod def access_token_used(self): """Return the access token used to make the request. diff --git a/boxsdk/object/api_json_object.py b/boxsdk/object/api_json_object.py index 181bbffd4..f46c59072 100644 --- a/boxsdk/object/api_json_object.py +++ b/boxsdk/object/api_json_object.py @@ -19,7 +19,6 @@ class APIJSONObjectMeta(BaseAPIJSONObjectMeta, ABCMeta): Avoid conflicting metaclass definitions for APIJSONObject. http://code.activestate.com/recipes/204197-solving-the-metaclass-conflict/ """ - pass class APIJSONObject(with_metaclass(APIJSONObjectMeta, BaseAPIJSONObject, Mapping)): diff --git a/boxsdk/object/base_api_json_object.py b/boxsdk/object/base_api_json_object.py index a082e027c..52f3d7c21 100644 --- a/boxsdk/object/base_api_json_object.py +++ b/boxsdk/object/base_api_json_object.py @@ -54,14 +54,13 @@ def __init__(cls, name, bases, attrs): super(BaseAPIJSONObjectMeta, cls).__init__(name, bases, attrs) item_type = attrs.get('_item_type', None) if item_type is not None: - Translator._default_translator.register(item_type, cls) # pylint:disable=protected-access + Translator._default_translator.register(item_type, cls) # pylint:disable=protected-access,no-member # Some types have - in them instead of _ in the API. if "-" in item_type: - Translator._default_translator.register(item_type.replace("-", "_"), cls) # pylint:disable=protected-access + Translator._default_translator.register(item_type.replace("-", "_"), cls) # pylint:disable=protected-access,no-member -@six.add_metaclass(BaseAPIJSONObjectMeta) -class BaseAPIJSONObject(object): +class BaseAPIJSONObject(metaclass=BaseAPIJSONObjectMeta): """Base class containing basic logic shared between true REST objects and other objects (such as an Event)""" # :attr _item_type: @@ -84,7 +83,7 @@ def __init__(self, response_object=None, **kwargs): :type response_object: `dict` """ - super(BaseAPIJSONObject, self).__init__(**kwargs) + super().__init__(**kwargs) self._response_object = response_object or {} self.__dict__.update(self._response_object) diff --git a/boxsdk/object/base_endpoint.py b/boxsdk/object/base_endpoint.py index b87f5259d..11be8b7ca 100644 --- a/boxsdk/object/base_endpoint.py +++ b/boxsdk/object/base_endpoint.py @@ -19,7 +19,7 @@ def __init__(self, session, **kwargs): :type kwargs: `dict` """ - super(BaseEndpoint, self).__init__(**kwargs) + super().__init__(**kwargs) self._session = session @property diff --git a/boxsdk/object/base_object.py b/boxsdk/object/base_object.py index 94e6a4169..6659f4057 100644 --- a/boxsdk/object/base_object.py +++ b/boxsdk/object/base_object.py @@ -26,7 +26,7 @@ def __init__(self, session, object_id, response_object=None): :type response_object: `dict` """ - super(BaseObject, self).__init__(session=session, response_object=response_object) + super().__init__(session=session, response_object=response_object) self._object_id = object_id @property @@ -42,7 +42,7 @@ def get_url(self, *args): Return the given object's URL, appending any optional parts as specified by args. """ # pylint:disable=arguments-differ - return super(BaseObject, self).get_url('{0}s'.format(self._item_type), self._object_id, *args) + return super().get_url('{0}s'.format(self._item_type), self._object_id, *args) def get_type_url(self): """ @@ -51,7 +51,7 @@ def get_type_url(self): :rtype: `unicode` """ - return super(BaseObject, self).get_url('{0}s'.format(self._item_type)) + return super().get_url('{0}s'.format(self._item_type)) @property def object_id(self): diff --git a/boxsdk/object/cloneable.py b/boxsdk/object/cloneable.py index d08fceb15..8f617c8d6 100644 --- a/boxsdk/object/cloneable.py +++ b/boxsdk/object/cloneable.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals, absolute_import -class Cloneable(object): +class Cloneable: """ Cloneable interface to be implemented by endpoint objects that should have ability to be cloned, but with a different session member if desired. diff --git a/boxsdk/object/collaboration.py b/boxsdk/object/collaboration.py index f1b94bbf6..dc1d8ded7 100644 --- a/boxsdk/object/collaboration.py +++ b/boxsdk/object/collaboration.py @@ -59,9 +59,9 @@ def update_info(self, role=None, status=None): if status: data['status'] = status if role == CollaborationRole.OWNER: - return super(Collaboration, self).update_info(data=data, expect_json_response=False) + return super().update_info(data=data, expect_json_response=False) else: - return super(Collaboration, self).update_info(data=data) + return super().update_info(data=data) @api_call def accept(self): diff --git a/boxsdk/object/events.py b/boxsdk/object/events.py index d2b249efa..e0b0253c8 100644 --- a/boxsdk/object/events.py +++ b/boxsdk/object/events.py @@ -58,7 +58,7 @@ class Events(BaseEndpoint): def get_url(self, *args): """Base class override.""" # pylint:disable=arguments-differ - return super(Events, self).get_url('events', *args) + return super().get_url('events', *args) @api_call def get_events(self, limit=100, stream_position=0, stream_type=UserEventsStreamType.ALL): @@ -280,22 +280,21 @@ def generate_events_with_long_polling(self, stream_position=None, stream_type=Us long_poll_response = self.long_poll(options, stream_position) except Timeout: break - else: - message = long_poll_response.json()['message'] - if message == 'new_change': - next_stream_position = stream_position - for event, next_stream_position in self._get_all_events_since(stream_position, stream_type=stream_type): - try: - event_ids.get(event['event_id']) - except KeyError: - yield event - event_ids.set(event['event_id']) - stream_position = next_stream_position - break - elif message == 'reconnect': - continue - else: - break + + message = long_poll_response.json()['message'] + if message == 'new_change': + next_stream_position = stream_position + for event, next_stream_position in self._get_all_events_since(stream_position, stream_type=stream_type): + try: + event_ids.get(event['event_id']) + except KeyError: + yield event + event_ids.set(event['event_id']) + stream_position = next_stream_position + break + if message == 'reconnect': + continue + break @api_call def get_long_poll_options(self, stream_type=UserEventsStreamType.ALL): diff --git a/boxsdk/object/file.py b/boxsdk/object/file.py index c55f4d52c..bc851760b 100644 --- a/boxsdk/object/file.py +++ b/boxsdk/object/file.py @@ -126,10 +126,10 @@ def _construct_range_header(boundaries): """ if len(boundaries) == 1: return 'bytes={0}-'.format(*boundaries) - elif len(boundaries) == 2: + if len(boundaries) == 2: return 'bytes={0}-{1}'.format(*boundaries) - else: - raise ValueError('Expected a 1-tuple or 2-tuple for byte range') + + raise ValueError('Expected a 1-tuple or 2-tuple for byte range') @api_call def content(self, file_version=None, byte_range=None): diff --git a/boxsdk/object/folder.py b/boxsdk/object/folder.py index a0737fd60..4954c75e0 100644 --- a/boxsdk/object/folder.py +++ b/boxsdk/object/folder.py @@ -31,7 +31,7 @@ class _CollaborationType(TextEnum): GROUP = 'group' -class _Collaborator(object): +class _Collaborator: """This helper class represents a collaborator on Box. A Collaborator can be a User, Group, or an email address""" def __init__(self, collaborator): if isinstance(collaborator, User): @@ -607,7 +607,7 @@ def delete(self, recursive=True, etag=None): :raises: :class:`BoxAPIException` if the specified etag doesn't match the latest version of the folder. """ # pylint:disable=arguments-differ - return super(Folder, self).delete({'recursive': recursive}, etag) + return super().delete({'recursive': recursive}, etag) @api_call def get_metadata_cascade_policies(self, owner_enterprise=None, limit=None, marker=None, fields=None): diff --git a/boxsdk/object/item.py b/boxsdk/object/item.py index 8fc0cc2fa..35ca7e99b 100644 --- a/boxsdk/object/item.py +++ b/boxsdk/object/item.py @@ -128,7 +128,7 @@ def update_info(self, data, etag=None): # pylint:disable=arguments-differ self.validate_item_id(self._object_id) headers = {'If-Match': etag} if etag is not None else None - return super(Item, self).update_info(data, headers=headers) + return super().update_info(data, headers=headers) @api_call def get(self, fields=None, etag=None): @@ -152,7 +152,7 @@ def get(self, fields=None, etag=None): # pylint:disable=arguments-differ self.validate_item_id(self._object_id) headers = {'If-None-Match': etag} if etag is not None else None - return super(Item, self).get(fields=fields, headers=headers) + return super().get(fields=fields, headers=headers) @api_call def create_shared_link( @@ -215,7 +215,7 @@ def create_shared_link( :raises: :class:`BoxAPIException` if the specified etag doesn't match the latest version of the item. """ # pylint:disable=arguments-differ - return super(Item, self).create_shared_link( + return super().create_shared_link( access=access, etag=etag, unshared_at=unshared_at, @@ -283,7 +283,7 @@ def get_shared_link( :raises: :class:`BoxAPIException` if the specified etag doesn't match the latest version of the item. """ # pylint:disable=arguments-differ - return super(Item, self).get_shared_link( + return super().get_shared_link( access=access, etag=etag, unshared_at=unshared_at, @@ -311,7 +311,7 @@ def remove_shared_link(self, etag=None, **kwargs): :raises: :class:`BoxAPIException` if the specified etag doesn't match the latest version of the item. """ # pylint:disable=arguments-differ - return super(Item, self).remove_shared_link(etag=etag) + return super().remove_shared_link(etag=etag) @api_call def delete(self, params=None, etag=None): @@ -334,7 +334,7 @@ def delete(self, params=None, etag=None): # pylint:disable=arguments-differ self.validate_item_id(self._object_id) headers = {'If-Match': etag} if etag is not None else None - return super(Item, self).delete(params, headers) + return super().delete(params, headers) def metadata(self, scope='global', template='properties'): """ @@ -642,8 +642,7 @@ def get_classification(self): except BoxAPIException as err: if err.status == 404 and err.code == "instance_not_found": return None - else: - raise + raise return classification.get('Box__Security__Classification__Key', None) def remove_classification(self): diff --git a/boxsdk/object/metadata.py b/boxsdk/object/metadata.py index 4389170c1..7632fc988 100644 --- a/boxsdk/object/metadata.py +++ b/boxsdk/object/metadata.py @@ -7,7 +7,7 @@ from ..util.api_call_decorator import api_call -class MetadataUpdate(object): +class MetadataUpdate: """ Helper class for updating Box metadata. See https://developer.box.com/en/guides/metadata/instances/update/ for more details. @@ -120,7 +120,7 @@ def __init__(self, session, box_object, scope, template): :type template: `unicode` """ - super(Metadata, self).__init__(session) + super().__init__(session) self._object = box_object self._scope = scope self._template = template diff --git a/boxsdk/object/metadata_template.py b/boxsdk/object/metadata_template.py index 7440ed195..426ba471c 100644 --- a/boxsdk/object/metadata_template.py +++ b/boxsdk/object/metadata_template.py @@ -9,11 +9,11 @@ from ..util.text_enum import TextEnum -class MetadataTemplateUpdate(object): +class MetadataTemplateUpdate: """Represents a set of update operations to a metadata template.""" def __init__(self): - super(MetadataTemplateUpdate, self).__init__() + super().__init__() self._ops = [] def json(self): @@ -199,7 +199,7 @@ class MetadataFieldType(TextEnum): FLOAT = 'float' -class MetadataField(object): +class MetadataField: """Represents a metadata field when creating or updating a metadata template.""" def __init__(self, field_type, display_name, key=None, options=None): @@ -221,7 +221,7 @@ def __init__(self, field_type, display_name, key=None, options=None): :type options: `Iterable` of `unicode` """ - super(MetadataField, self).__init__() + super().__init__() self.type = field_type self.name = display_name self.key = key @@ -276,7 +276,7 @@ def __init__(self, session, object_id, response_object=None): :type response_object: `dict` or None """ - super(MetadataTemplate, self).__init__(session, object_id, response_object) + super().__init__(session, object_id, response_object) if response_object: self._scope = response_object.get('scope', None) self._template_key = response_object.get('templateKey', None) @@ -301,7 +301,7 @@ def get_url(self, *args): if self._scope and self._template_key: return self._session.get_url('metadata_templates', self._scope, self._template_key, 'schema', *args) - return super(MetadataTemplate, self).get_url(*args) + return super().get_url(*args) @staticmethod def start_update(): diff --git a/boxsdk/object/search.py b/boxsdk/object/search.py index f8f7d1c2e..fd2d72f15 100644 --- a/boxsdk/object/search.py +++ b/boxsdk/object/search.py @@ -23,7 +23,7 @@ class TrashContent(TextEnum): ONLY = 'trashed_only' -class MetadataSearchFilter(object): +class MetadataSearchFilter: """ Helper class to encapsulate a single search filter. A search filter can only search against one template, but can filter on many fields. @@ -101,7 +101,7 @@ def add_range_filter(self, field_key, gt_value=None, lt_value=None): self._field_filters.update({field_key: range_part}) -class MetadataSearchFilters(object): +class MetadataSearchFilters: """ Helper class to encapsulate a list of metadata search filter params (mdfilters API param) See https://developers.box.com/metadata-api/#search for more details @@ -145,7 +145,7 @@ def get_url(self, *args): `unicode` """ # pylint:disable=arguments-differ - return super(Search, self).get_url('search') + return super().get_url('search') @staticmethod def start_metadata_filters(): @@ -359,7 +359,7 @@ def metadata_query(self, from_template, ancestor_folder_id, query=None, query_pa :rtype: :class:`BoxObjectCollection` """ - url = super(Search, self).get_url('metadata_queries/execute_read') + url = super().get_url('metadata_queries/execute_read') data = { 'from': from_template, 'ancestor_folder_id': ancestor_folder_id diff --git a/boxsdk/object/upload_session.py b/boxsdk/object/upload_session.py index 5788b212d..469c46944 100644 --- a/boxsdk/object/upload_session.py +++ b/boxsdk/object/upload_session.py @@ -130,7 +130,7 @@ def commit(self, content_sha1, parts=None, file_attributes=None, etag=None): if parts is not None: body['parts'] = parts else: - body['parts'] = [part for part in self.get_parts()] + body['parts'] = list(self.get_parts()) headers = { 'Content-Type': 'application/json', 'Digest': 'SHA={0}'.format(base64.b64encode(content_sha1).decode('utf-8')), diff --git a/boxsdk/object/user.py b/boxsdk/object/user.py index 1438189df..20b197d51 100644 --- a/boxsdk/object/user.py +++ b/boxsdk/object/user.py @@ -212,4 +212,4 @@ def delete(self, notify=True, force=False): 'notify': notify, 'force': force, } - return super(User, self).delete(params=params) + return super().delete(params=params) diff --git a/boxsdk/object/web_link.py b/boxsdk/object/web_link.py index 49f1582f0..4a9c5be8b 100644 --- a/boxsdk/object/web_link.py +++ b/boxsdk/object/web_link.py @@ -54,7 +54,7 @@ def create_shared_link( :class:`WebLink` """ # pylint:disable=arguments-differ - return super(WebLink, self).create_shared_link( + return super().create_shared_link( access=access, unshared_at=unshared_at, password=password, @@ -103,7 +103,7 @@ def get_shared_link( `unicode` """ # pylint:disable=arguments-differ - return super(WebLink, self).get_shared_link( + return super().get_shared_link( access=access, unshared_at=unshared_at, password=password, @@ -122,4 +122,4 @@ def remove_shared_link(self, **kwargs): :rtype: `bool` """ - return super(WebLink, self).remove_shared_link() + return super().remove_shared_link() diff --git a/boxsdk/pagination/box_object_collection.py b/boxsdk/pagination/box_object_collection.py index 01f988ed5..3c48969f2 100644 --- a/boxsdk/pagination/box_object_collection.py +++ b/boxsdk/pagination/box_object_collection.py @@ -4,9 +4,8 @@ import json import sys -from abc import ABCMeta, abstractmethod +from abc import ABC, abstractmethod -from six import add_metaclass from boxsdk.pagination.page import Page @@ -16,8 +15,7 @@ from collections import Iterator # pylint:disable=no-name-in-module,import-error -@add_metaclass(ABCMeta) -class BoxObjectCollection(Iterator): +class BoxObjectCollection(Iterator, ABC): """ An iterator that represents a collection of Box objects (BaseObject). @@ -79,7 +77,7 @@ def __init__( :type use_post: `bool` """ - super(BoxObjectCollection, self).__init__() + super().__init__() self._session = session self._url = url self._limit = limit diff --git a/boxsdk/pagination/limit_offset_based_object_collection.py b/boxsdk/pagination/limit_offset_based_object_collection.py index 5cc33cfa9..89ebc1a9c 100644 --- a/boxsdk/pagination/limit_offset_based_object_collection.py +++ b/boxsdk/pagination/limit_offset_based_object_collection.py @@ -29,7 +29,7 @@ def __init__( :type offset: `int` """ - super(LimitOffsetBasedObjectCollection, self).__init__( + super().__init__( session, url, limit=limit, diff --git a/boxsdk/pagination/marker_based_object_collection.py b/boxsdk/pagination/marker_based_object_collection.py index 489977e04..3f37ef501 100644 --- a/boxsdk/pagination/marker_based_object_collection.py +++ b/boxsdk/pagination/marker_based_object_collection.py @@ -41,7 +41,7 @@ def __init__( :type use_post: `bool` """ - super(MarkerBasedObjectCollection, self).__init__( + super().__init__( session, url, limit=limit, diff --git a/boxsdk/pagination/page.py b/boxsdk/pagination/page.py index 21ee8512e..6d1745ef9 100644 --- a/boxsdk/pagination/page.py +++ b/boxsdk/pagination/page.py @@ -30,7 +30,7 @@ def __init__(self, session, response_object): :type response_object: `dict` """ - super(Page, self).__init__() + super().__init__() self._session = session self._response_object = response_object diff --git a/boxsdk/session/box_request.py b/boxsdk/session/box_request.py index 2c8493d91..20b0893dd 100644 --- a/boxsdk/session/box_request.py +++ b/boxsdk/session/box_request.py @@ -8,7 +8,7 @@ @attr.s(slots=True) -class BoxRequest(object): +class BoxRequest: """Represents a Box API request. :param url: The URL being requested. diff --git a/boxsdk/session/box_response.py b/boxsdk/session/box_response.py index b1d97e2fe..1c98067db 100644 --- a/boxsdk/session/box_response.py +++ b/boxsdk/session/box_response.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals, absolute_import -class BoxResponse(object): +class BoxResponse: """Represents a response to a Box API request.""" def __init__(self, network_response): diff --git a/boxsdk/session/session.py b/boxsdk/session/session.py index 59bae4582..eac462207 100644 --- a/boxsdk/session/session.py +++ b/boxsdk/session/session.py @@ -20,7 +20,7 @@ from ..util.translator import Translator -class Session(object): +class Session: _retry_randomization_factor = 0.5 _retry_base_interval = 1 @@ -77,7 +77,7 @@ def __init__( self._api_config = api_config or API() self._client_config = client_config or Client() self._proxy_config = proxy_config or Proxy() - super(Session, self).__init__() + super().__init__() self._network_layer = network_layer or DefaultNetwork() self._default_headers = { 'User-Agent': self._client_config.USER_AGENT_STRING, @@ -541,11 +541,11 @@ def __init__(self, oauth, **kwargs): :type session: :class:`Session` """ - super(AuthorizedSession, self).__init__(**kwargs) + super().__init__(**kwargs) self._oauth = oauth def get_constructor_kwargs(self): - kwargs = super(AuthorizedSession, self).get_constructor_kwargs() + kwargs = super().get_constructor_kwargs() kwargs['oauth'] = self._oauth return kwargs @@ -591,7 +591,7 @@ def _get_retry_request_callable(self, network_response, attempt_number, request, self._renew_session(network_response.access_token_used) request.auto_session_renewal = False return self._send_request - return super(AuthorizedSession, self)._get_retry_request_callable( + return super()._get_retry_request_callable( network_response, attempt_number, request, @@ -620,4 +620,4 @@ def _send_request(self, request, **kwargs): authorization_header = {'Authorization': 'Bearer {0}'.format(access_token)} request.headers.update(authorization_header) kwargs['access_token'] = access_token - return super(AuthorizedSession, self)._send_request(request, **kwargs) + return super()._send_request(request, **kwargs) diff --git a/boxsdk/util/api_call_decorator.py b/boxsdk/util/api_call_decorator.py index 44bab8058..2ea2656f1 100644 --- a/boxsdk/util/api_call_decorator.py +++ b/boxsdk/util/api_call_decorator.py @@ -30,10 +30,10 @@ def api_call(method): return APICallWrapper(method) -class APICallWrapper(object): +class APICallWrapper: def __init__(self, func_that_makes_an_api_call): - super(APICallWrapper, self).__init__() + super().__init__() self._func_that_makes_an_api_call = func_that_makes_an_api_call self.__name__ = func_that_makes_an_api_call.__name__ update_wrapper(self, func_that_makes_an_api_call) diff --git a/boxsdk/util/chain_map.py b/boxsdk/util/chain_map.py deleted file mode 100644 index 7df702d00..000000000 --- a/boxsdk/util/chain_map.py +++ /dev/null @@ -1,20 +0,0 @@ -# coding: utf-8 - -from __future__ import absolute_import, unicode_literals - -from functools import wraps - - -__all__ = list(map(str, ['ChainMap'])) - - -# pylint:disable=unused-import -try: - from collections import ChainMap -except ImportError: - from chainmap import ChainMap as _ChainMap - - # Make sure that `ChainMap` is a new-style class. - @wraps(_ChainMap, updated=()) - class ChainMap(_ChainMap, object): - __slots__ = () diff --git a/boxsdk/util/chunked_uploader.py b/boxsdk/util/chunked_uploader.py index 328328ec7..882868a04 100644 --- a/boxsdk/util/chunked_uploader.py +++ b/boxsdk/util/chunked_uploader.py @@ -5,7 +5,7 @@ from boxsdk.exception import BoxException -class ChunkedUploader(object): +class ChunkedUploader: def __init__(self, upload_session, content_stream, file_size): """ @@ -136,7 +136,7 @@ def _get_next_part(self): return InflightPart(offset, chunk, self._upload_session, self._file_size) -class InflightPart(object): +class InflightPart: def __init__(self, offset, chunk, upload_session, total_size): """ diff --git a/boxsdk/util/log.py b/boxsdk/util/log.py index 7d43003ed..f384f37e0 100644 --- a/boxsdk/util/log.py +++ b/boxsdk/util/log.py @@ -22,7 +22,7 @@ def emit(self, record): _no_logger = object() -class Logging(object): +class Logging: _has_setup = False KEYS_TO_SANITIZE = ( 'Authorization', diff --git a/boxsdk/util/lru_cache.py b/boxsdk/util/lru_cache.py index 0d9380ac0..faa56ff18 100644 --- a/boxsdk/util/lru_cache.py +++ b/boxsdk/util/lru_cache.py @@ -5,7 +5,7 @@ from collections import OrderedDict -class LRUCache(object): +class LRUCache: def __init__(self, capacity=512): """ :param capacity: @@ -13,7 +13,7 @@ def __init__(self, capacity=512): :type capacity: `int` """ - super(LRUCache, self).__init__() + super().__init__() self.capacity = capacity self.cache = OrderedDict() diff --git a/boxsdk/util/multipart_stream.py b/boxsdk/util/multipart_stream.py index 9a94dda78..8616d950b 100644 --- a/boxsdk/util/multipart_stream.py +++ b/boxsdk/util/multipart_stream.py @@ -19,4 +19,4 @@ def __init__(self, data, files): fields[k] = data[k] for k in files: fields[k] = files[k] - super(MultipartStream, self).__init__(fields) + super().__init__(fields) diff --git a/boxsdk/util/translator.py b/boxsdk/util/translator.py index 33a6397bc..7954be223 100644 --- a/boxsdk/util/translator.py +++ b/boxsdk/util/translator.py @@ -1,22 +1,11 @@ # coding: utf-8 from __future__ import absolute_import, unicode_literals - +from collections import ChainMap import inspect -from .chain_map import ChainMap - - __all__ = list(map(str, ['Translator'])) -# pylint: disable=invalid-name -inspect_signature = None -try: - inspect_signature = inspect.signature -except AttributeError: # pragma: no cover - import funcsigs - inspect_signature = funcsigs.signature - def _get_object_id(obj): """ @@ -105,7 +94,7 @@ def __init__(self, *translation_maps, **kwargs): translation_maps.append(self._default_translator) if new_child: translation_maps.insert(0, {}) - super(Translator, self).__init__(*translation_maps, **kwargs) + super().__init__(*translation_maps, **kwargs) def register(self, type_name, box_cls): """Associate a Box object class to handle Box API item responses with the given type name. @@ -134,10 +123,11 @@ def get(self, key, default=None): :type default: :class:`BaseAPIJSONObjectMeta` :rtype: :class:`BaseAPIJSONObjectMeta` """ + # pylint:disable=import-outside-toplevel from boxsdk.object.base_object import BaseObject if default is None: default = BaseObject - return super(Translator, self).get(key, default) + return super().get(key, default) def translate(self, session, response_object): """ @@ -185,7 +175,7 @@ def translate(self, session, response_object): 'response_object': translated_obj, 'object_id': _get_object_id(translated_obj), } - params = inspect_signature(object_class.__init__).parameters + params = inspect.signature(object_class.__init__).parameters param_values = {p: param_values[p] for p in params if p in param_values} return object_class(**param_values) diff --git a/docs/source/boxsdk.util.rst b/docs/source/boxsdk.util.rst index fb207aa12..e8a78b57a 100644 --- a/docs/source/boxsdk.util.rst +++ b/docs/source/boxsdk.util.rst @@ -12,14 +12,6 @@ boxsdk.util.api\_call\_decorator module :undoc-members: :show-inheritance: -boxsdk.util.chain\_map module ------------------------------ - -.. automodule:: boxsdk.util.chain_map - :members: - :undoc-members: - :show-inheritance: - boxsdk.util.chunked\_uploader module ------------------------------------ diff --git a/setup.py b/setup.py index e7ddc7004..fc4a79d2b 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,6 @@ from __future__ import unicode_literals from codecs import open # pylint:disable=redefined-builtin -from collections import defaultdict from os.path import dirname, join import re import sys @@ -17,8 +16,6 @@ 'Intended Audience :: Developers', 'License :: OSI Approved :: Apache Software License', 'Programming Language :: Python', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', @@ -48,6 +45,7 @@ def finalize_options(self): def run_tests(self): # Do the import here, once the eggs are loaded. + # pylint:disable=import-outside-toplevel import pytest errno = pytest.main(self.pytest_args) sys.exit(errno) @@ -61,33 +59,11 @@ def main(): 'requests-toolbelt>=0.4.0, <1.0.0', 'six>=1.9.0', 'wrapt>=1.10.1', + 'sphinx' ] redis_requires = ['redis>=2.10.3'] jwt_requires = ['pyjwt>=1.3.0', 'cryptography>=3, <3.5.0'] - extra_requires = defaultdict(list) - extra_requires.update({'jwt': jwt_requires, 'redis': redis_requires, 'all': jwt_requires + redis_requires}) - conditional_dependencies = { - # Newer versions of pip and wheel, which support PEP 426, allow - # environment markers for conditional dependencies to use operators - # such as `<` and `<=` [1]. However, older versions of pip and wheel - # only support PEP 345, which only allows operators `==` and `in` (and - # their negations) along with string constants [2]. To get the widest - # range of support, we'll only use the `==` operator, which means - # explicitly listing all supported Python versions that need the extra - # dependencies. - # - # [1] - # [2] - 'chainmap>=1.0.2': ['2.7'], # <'3.4' - 'funcsigs>=1.0.0': ['2.7'], # <'3.4' - 'enum34>=1.0.4': ['2.7'], # <'3.4' - } - for requirement, python_versions in conditional_dependencies.items(): - for python_version in python_versions: - # - python_conditional = 'python_version=="{0}"'.format(python_version) - key = ':{0}'.format(python_conditional) - extra_requires[key].append(requirement) + extra_requires = {'jwt': jwt_requires, 'redis': redis_requires, 'all': jwt_requires + redis_requires} test_requires = [ 'bottle', 'jsonpatch', diff --git a/test/conftest.py b/test/conftest.py index 7283681ca..50c4a0124 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -39,8 +39,8 @@ def _set_content_and_json_from_content(mock_response, content): @pytest.fixture() def generic_successful_request_response(): - mock_request_response = Mock(requests.Response(), headers=dict([('header{0}'.format(i), 'value{0}'.format(i)) for i in range(4)])) - _set_content_and_json_from_json(mock_request_response, json_value=dict([('key{0}'.format(i), 'value{0}'.format(i)) for i in range(8)])) + mock_request_response = Mock(requests.Response(), headers={'header{0}'.format(i): 'value{0}'.format(i) for i in range(4)}) + _set_content_and_json_from_json(mock_request_response, json_value={'key{0}'.format(i): 'value{0}'.format(i) for i in range(8)}) mock_request_response.status_code = 200 mock_request_response.ok = True mock_request_response.request = Mock() @@ -135,15 +135,15 @@ def retry_after_response_429(): def retry_after_response(retry_after_response_202, retry_after_response_429, request): if request.param == 202: return retry_after_response_202 - elif request.param == 429: + if request.param == 429: return retry_after_response_429 - else: - raise ValueError + + raise ValueError def _server_error_request_response(status_code): - mock_request_response = Mock(requests.Response(), headers=dict([('header{0}'.format(i), 'value{0}'.format(i)) for i in range(4)])) - _set_content_and_json_from_json(mock_request_response, json_value=dict([('key{0}'.format(i), 'value{0}'.format(i)) for i in range(8)])) + mock_request_response = Mock(requests.Response(), headers={'header{0}'.format(i): 'value{0}'.format(i) for i in range(4)}) + _set_content_and_json_from_json(mock_request_response, json_value={'key{0}'.format(i): 'value{0}'.format(i) for i in range(8)}) mock_request_response.status_code = status_code mock_request_response.ok = False return mock_request_response @@ -163,10 +163,9 @@ def server_error_request_response_503(): def server_error_request_response(server_error_request_response_502, server_error_request_response_503, request): if request.param == 502: return server_error_request_response_502 - elif request.param == 503: + if request.param == 503: return server_error_request_response_503 - else: - raise ValueError + raise ValueError @pytest.fixture diff --git a/test/functional/conftest.py b/test/functional/conftest.py index bd07a75fc..6d4669905 100644 --- a/test/functional/conftest.py +++ b/test/functional/conftest.py @@ -3,12 +3,12 @@ from __future__ import unicode_literals import re +from urllib import parse from mock import patch import pytest import requests import six -from six.moves.urllib import parse # pylint:disable=import-error, no-name-in-module,wrong-import-order,relative-import from boxsdk.auth.oauth2 import OAuth2 from boxsdk.config import API diff --git a/test/functional/test_recovery.py b/test/functional/test_recovery.py index 1387cf015..a7bcee89c 100644 --- a/test/functional/test_recovery.py +++ b/test/functional/test_recovery.py @@ -28,7 +28,7 @@ def should_apply(request): # Figure out how many times the call should fail. If should_apply is an int, it should fail iff should_apply == 1 # If it's a sequence, figure out the first time it will succeed. It should fail until then. if isinstance(request.param, int): - if request.param is 1: + if request.param == 1: expected_num_requests += 1 else: expected_num_requests += next( diff --git a/test/integration/mock_network.py b/test/integration/mock_network.py index 6803dd9fc..adcd0376a 100644 --- a/test/integration/mock_network.py +++ b/test/integration/mock_network.py @@ -11,7 +11,7 @@ class MockNetwork(Network): """Mock implementation of the network interface for testing purposes.""" def __init__(self): - super(MockNetwork, self).__init__() + super().__init__() self._session = Mock(requests.Session) self._retries = [] diff --git a/test/unit/auth/test_jwt_auth.py b/test/unit/auth/test_jwt_auth.py index c55c00be4..b93097442 100644 --- a/test/unit/auth/test_jwt_auth.py +++ b/test/unit/auth/test_jwt_auth.py @@ -376,7 +376,7 @@ def jwt_subclass_that_just_stores_params(): class StoreParamJWTAuth(JWTAuth): def __init__(self, **kwargs): self.kwargs = kwargs - super(StoreParamJWTAuth, self).__init__(**kwargs) + super().__init__(**kwargs) return StoreParamJWTAuth diff --git a/test/unit/auth/test_oauth2.py b/test/unit/auth/test_oauth2.py index de3140c7f..1cb81a2c5 100644 --- a/test/unit/auth/test_oauth2.py +++ b/test/unit/auth/test_oauth2.py @@ -6,13 +6,10 @@ import re from threading import Thread import uuid +from urllib import parse from mock import Mock, patch import pytest -from six.moves import range # pylint:disable=redefined-builtin -# pylint:disable=import-error,no-name-in-module,wrong-import-order,relative-import -from six.moves.urllib import parse as urlparse -# pylint:enable=import-error,no-name-in-module,wrong-import-order,relative-import from boxsdk.exception import BoxOAuthException from boxsdk.network.default_network import DefaultNetworkResponse @@ -50,7 +47,7 @@ def test_get_correct_authorization_url(redirect_url): API.OAUTH2_AUTHORIZE_URL, csrf_token, fake_client_id, - urlparse.quote_plus((redirect_url or '').encode('utf-8')), + parse.quote_plus((redirect_url or '').encode('utf-8')), ) assert re.match('^box_csrf_token_[A-Za-z0-9]{16}$', csrf_token) @@ -204,7 +201,7 @@ def token_method(request): """ Fixture that returns a partial method based on the method provided in request.param""" if request.param == OAuth2.refresh: return partial(OAuth2.refresh, access_token_to_refresh='fake_access_token') - elif request.param == OAuth2.authenticate: + if request.param == OAuth2.authenticate: return partial(OAuth2.authenticate, auth_code='fake_code') return None diff --git a/test/unit/object/test_base_api_json_object.py b/test/unit/object/test_base_api_json_object.py index 42e256b0a..6bc22711a 100644 --- a/test/unit/object/test_base_api_json_object.py +++ b/test/unit/object/test_base_api_json_object.py @@ -35,8 +35,8 @@ def test_contains(base_api_json_object): def test_iter(base_api_json_object): dictionary_response, test_object = base_api_json_object - all_test_object_keys = [key for key in test_object] - all_dictionary_response_keys = [key for key in dictionary_response] + all_test_object_keys = list(test_object) + all_dictionary_response_keys = list(dictionary_response) assert set(all_test_object_keys) == set(all_dictionary_response_keys) diff --git a/test/unit/object/test_base_item.py b/test/unit/object/test_base_item.py index c9cbff91b..114a7e279 100644 --- a/test/unit/object/test_base_item.py +++ b/test/unit/object/test_base_item.py @@ -11,7 +11,7 @@ def test_base_item_and_response( test_file, test_folder, test_web_link, mock_file_response, mock_folder_response, mock_web_link_response, request): if request.param == 'file': return test_file, mock_file_response - elif request.param == 'folder': + if request.param == 'folder': return test_folder, mock_folder_response return test_web_link, mock_web_link_response @@ -23,11 +23,11 @@ def test_collections_for_addition(mock_collection_id, request): other_collection_id = mock_collection_id + '2' if request.param == 'empty': return [], [{'id': mock_collection_id}] - elif request.param == 'same': + if request.param == 'same': # Adding a second instance of the same collection is handled correctly by the API, # so for simplicity we do not check for an existing copy of the collection and just append return [{'id': mock_collection_id}], [{'id': mock_collection_id}, {'id': mock_collection_id}] - elif request.param == 'other': + if request.param == 'other': return [{'id': other_collection_id}], [{'id': other_collection_id}, {'id': mock_collection_id}] raise NotImplementedError("Forgot to implement {}".format(request.param)) @@ -39,11 +39,11 @@ def test_collections_for_removal(mock_collection_id, request): other_collection_id = mock_collection_id + '2' if request.param == 'empty': return [], [] - elif request.param == 'only_removed': + if request.param == 'only_removed': return [{'id': mock_collection_id}], [] - elif request.param == 'only_other': + if request.param == 'only_other': return [{'id': other_collection_id}], [{'id': other_collection_id}] - elif request.param == 'other_and_removed': + if request.param == 'other_and_removed': return [{'id': mock_collection_id}, {'id': other_collection_id}], [{'id': other_collection_id}] raise NotImplementedError("Forgot to implement {}".format(request.param)) diff --git a/test/unit/object/test_device_pin.py b/test/unit/object/test_device_pin.py index 54d9d2855..e849cc033 100644 --- a/test/unit/object/test_device_pin.py +++ b/test/unit/object/test_device_pin.py @@ -19,7 +19,7 @@ def delete_device_pin_response(): def test_get(test_device_pin, mock_box_session): - created_at = '2016-05-18T17:38:03-07:00', + created_at = '2016-05-18T17:38:03-07:00' expected_url = '{0}/device_pinners/{1}'.format(API.BASE_API_URL, test_device_pin.object_id) mock_box_session.get.return_value.json.return_value = { 'type': 'device_pinner', diff --git a/test/unit/object/test_group.py b/test/unit/object/test_group.py index f0e37a5aa..f754fdbd5 100644 --- a/test/unit/object/test_group.py +++ b/test/unit/object/test_group.py @@ -8,7 +8,6 @@ from mock import Mock import pytest -from six.moves import map # pylint:disable=redefined-builtin,import-error from boxsdk.network.default_network import DefaultNetworkResponse from boxsdk.object.collaboration import Collaboration diff --git a/test/unit/object/test_item.py b/test/unit/object/test_item.py index 6bf364b4b..fb9ab55c5 100644 --- a/test/unit/object/test_item.py +++ b/test/unit/object/test_item.py @@ -534,7 +534,7 @@ def test_remove_classification(test_item_and_response, mock_box_session, make_mo mock_box_session.delete.return_value, _ = make_mock_box_request(response_ok='success') is_removed = test_item.remove_classification() mock_box_session.delete.assert_called_once_with(expected_url) - assert is_removed is 'success' + assert is_removed == 'success' def test_sanitize_item_id(test_item_and_response): diff --git a/test/unit/object/test_legal_hold_policy.py b/test/unit/object/test_legal_hold_policy.py index 92ee0deea..d7613d994 100644 --- a/test/unit/object/test_legal_hold_policy.py +++ b/test/unit/object/test_legal_hold_policy.py @@ -61,7 +61,7 @@ def legal_hold_response(legal_hold_id_1, legal_hold_id_2): def test_assign(test_legal_hold_policy, mock_box_session, test_file): assignment_id = '12345' - assigned_at = '2016-05-18T17:38:03-07:00', + assigned_at = '2016-05-18T17:38:03-07:00' expected_url = '{0}/legal_hold_policy_assignments'.format(API.BASE_API_URL) expected_body = { 'policy_id': test_legal_hold_policy.object_id, @@ -83,7 +83,7 @@ def test_assign(test_legal_hold_policy, mock_box_session, test_file): def test_get(test_legal_hold_policy, mock_box_session): - created_at = '2016-05-18T17:38:03-07:00', + created_at = '2016-05-18T17:38:03-07:00' expected_url = '{0}/legal_hold_policies/{1}'.format(API.BASE_API_URL, test_legal_hold_policy.object_id) mock_box_session.get.return_value.json.return_value = { 'type': 'legal_hold_policy', diff --git a/test/unit/object/test_search.py b/test/unit/object/test_search.py index 4602570ed..24f5552d8 100644 --- a/test/unit/object/test_search.py +++ b/test/unit/object/test_search.py @@ -150,7 +150,7 @@ def search_with_shared_links_response(): } -class Matcher(object): +class Matcher: def __init__(self, compare, some_obj): self.compare = compare self.some_obj = some_obj diff --git a/test/unit/object/test_terms_of_service.py b/test/unit/object/test_terms_of_service.py index b15371a0c..b5558de3a 100644 --- a/test/unit/object/test_terms_of_service.py +++ b/test/unit/object/test_terms_of_service.py @@ -10,7 +10,7 @@ def test_get(test_terms_of_service, mock_box_session): - created_at = '2016-05-18T17:38:03-07:00', + created_at = '2016-05-18T17:38:03-07:00' expected_url = '{0}/terms_of_services/{1}'.format(API.BASE_API_URL, test_terms_of_service.object_id) mock_box_session.get.return_value.json.return_value = { 'type': 'terms_of_service', @@ -47,7 +47,7 @@ def test_update(test_terms_of_service, mock_box_session): def test_accept_terms_of_service(test_terms_of_service, test_terms_of_service_user_status, mock_user, mock_box_session): # pylint:disable=redefined-outer-name expected_url = "{0}/terms_of_service_user_statuses".format(API.BASE_API_URL) - created_at = '2016-05-18T17:38:03-07:00', + created_at = '2016-05-18T17:38:03-07:00' value = json.dumps({ 'tos': { 'type': 'terms_of_service', @@ -75,7 +75,7 @@ def test_accept_terms_of_service(test_terms_of_service, test_terms_of_service_us def test_reject_terms_of_service(test_terms_of_service, test_terms_of_service_user_status, mock_user, mock_box_session): # pylint:disable=redefined-outer-name expected_url = "{0}/terms_of_service_user_statuses".format(API.BASE_API_URL) - created_at = '2016-05-18T17:38:03-07:00', + created_at = '2016-05-18T17:38:03-07:00' value = json.dumps({ 'tos': { 'type': 'terms_of_service', diff --git a/test/unit/object/test_terms_of_service_user_status.py b/test/unit/object/test_terms_of_service_user_status.py index c7f5e5cce..1aa68a81a 100644 --- a/test/unit/object/test_terms_of_service_user_status.py +++ b/test/unit/object/test_terms_of_service_user_status.py @@ -8,7 +8,7 @@ def test_get(test_terms_of_service_user_status, mock_box_session): - created_at = '2016-05-18T17:38:03-07:00', + created_at = '2016-05-18T17:38:03-07:00' expected_url = '{0}/terms_of_service_user_statuses/{1}'.format(API.BASE_API_URL, test_terms_of_service_user_status.object_id) mock_box_session.get.return_value.json.return_value = { 'type': 'terms_of_service_user_status', diff --git a/test/unit/object/test_trash.py b/test/unit/object/test_trash.py index ae4c0bd89..2da6655d1 100644 --- a/test/unit/object/test_trash.py +++ b/test/unit/object/test_trash.py @@ -25,7 +25,7 @@ def test_item_and_response( ): if request.param == 'file': return test_file, mock_file_response - elif request.param == 'web_link': + if request.param == 'web_link': return test_web_link, mock_web_link_response return test_folder, mock_folder_response diff --git a/test/unit/pagination/box_object_collection_test_base.py b/test/unit/pagination/box_object_collection_test_base.py index 13f01eb0f..d17ae70fd 100644 --- a/test/unit/pagination/box_object_collection_test_base.py +++ b/test/unit/pagination/box_object_collection_test_base.py @@ -1,16 +1,13 @@ # coding: utf-8 from __future__ import unicode_literals, absolute_import -from abc import ABCMeta, abstractmethod -from six import add_metaclass -from six.moves import range # pylint:disable=redefined-builtin +from abc import ABC, abstractmethod import pytest from boxsdk.util.translator import Translator -@add_metaclass(ABCMeta) -class BoxObjectCollectionTestBase(object): +class BoxObjectCollectionTestBase(ABC): NUM_ENTRIES = 25 @staticmethod diff --git a/test/unit/pagination/test_limit_offset_based_object_collection.py b/test/unit/pagination/test_limit_offset_based_object_collection.py index 5b321cebf..1ade582b4 100644 --- a/test/unit/pagination/test_limit_offset_based_object_collection.py +++ b/test/unit/pagination/test_limit_offset_based_object_collection.py @@ -92,7 +92,7 @@ def test_object_collection_sets_next_pointer_correctly(self, mock_session, retur assert object_collection.next_pointer() == page_size # Iterate to the last page, which doesn't return a full page. - [_ for _ in object_collection] # pylint:disable=pointless-statement + list(object_collection) assert object_collection.next_pointer() == self.NUM_ENTRIES def test_object_collection_raises_stop_iteration_when_starting_offset_is_too_far(self, mock_session, entries): diff --git a/test/unit/session/test_session.py b/test/unit/session/test_session.py index d17e4ab25..0836f66b2 100644 --- a/test/unit/session/test_session.py +++ b/test/unit/session/test_session.py @@ -261,7 +261,7 @@ def test_translator(box_session, translator, default_translator, original_defaul # Test that adding new registrations works. - class Foo(object): + class Foo: pass item_type = u'ƒøø' diff --git a/test/unit/util/test_api_call_decorator.py b/test/unit/util/test_api_call_decorator.py index f86778391..5a7d6aff4 100644 --- a/test/unit/util/test_api_call_decorator.py +++ b/test/unit/util/test_api_call_decorator.py @@ -67,7 +67,7 @@ def func(): def test_api_call_decorated_method_must_be_a_cloneable_method(): - class NonCloneable(object): + class NonCloneable: @api_call def func(self): pass diff --git a/test/unit/util/test_compat.py b/test/unit/util/test_compat.py index 2cad2f0aa..1e38c06c4 100644 --- a/test/unit/util/test_compat.py +++ b/test/unit/util/test_compat.py @@ -23,10 +23,10 @@ def test_total_seconds(total_seconds_data): def test_with_metaclass(): - class Class1(object): + class Class1: pass - class Class2(object): + class Class2: pass bases = (Class1, Class2) diff --git a/test/unit/util/test_translator.py b/test/unit/util/test_translator.py index 6d15ccc94..46af1a382 100644 --- a/test/unit/util/test_translator.py +++ b/test/unit/util/test_translator.py @@ -86,7 +86,7 @@ def test_default_translator(): def test_with_extend_default_translator(default_translator, extend_default_translator, new_child): item_type = 'foo' - class Foo(object): + class Foo: pass kwargs = {} @@ -100,7 +100,7 @@ class Foo(object): def test_without_extend_default_translator(new_child): item_type = 'foo' - class Foo(object): + class Foo: pass mapping = {item_type: Foo} @@ -113,7 +113,7 @@ class Foo(object): def test_with_new_child(new_child, extend_default_translator): item_type = 'foo' - class Foo(object): + class Foo: pass mapping = {item_type: Foo} @@ -140,7 +140,7 @@ class Bar(Foo): def test_without_new_child(extend_default_translator): item_type = 'foo' - class Foo(object): + class Foo: pass mapping = {item_type: Foo} diff --git a/tox.ini b/tox.ini index cdc406e2f..6d81f683c 100644 --- a/tox.ini +++ b/tox.ini @@ -7,8 +7,6 @@ envlist = pycodestyle, pylint, - py27, - py34, py35, py36, py37, @@ -58,6 +56,7 @@ passenv = TRAVIS_JOB_ID [testenv:docs] +allowlist_externals = make changedir = docs deps = -rrequirements-dev.txt From 13b21b92e9a33095c6fea84181dc5a8ed3849d1c Mon Sep 17 00:00:00 2001 From: Lukasz Socha Date: Tue, 14 Dec 2021 13:46:55 +0100 Subject: [PATCH 2/2] removed python 2 style form test and demo folders --- demo/auth.py | 2 +- demo/example.py | 3 ++- demo/music_player.py | 4 ++-- test/functional/mock_box/behavior/event_behavior.py | 2 +- test/functional/mock_box/behavior/item_behavior.py | 2 +- test/functional/mock_box/behavior/oauth2_behavior.py | 2 +- test/functional/mock_box/behavior/user_behavior.py | 2 +- test/functional/mock_box/box.py | 2 +- test/functional/mock_box/util/http_utils.py | 2 +- test/functional/mock_box/util/json_utils.py | 2 +- test/unit/util/test_compat.py | 6 +++--- 11 files changed, 15 insertions(+), 14 deletions(-) diff --git a/demo/auth.py b/demo/auth.py index 92b0227c3..c2d067240 100644 --- a/demo/auth.py +++ b/demo/auth.py @@ -18,7 +18,7 @@ def authenticate(oauth_class=OAuth2): class StoppableWSGIServer(bottle.ServerAdapter): def __init__(self, *args, **kwargs): - super(StoppableWSGIServer, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self._server = None def run(self, app): diff --git a/demo/example.py b/demo/example.py index 95318ef8b..1f53eb576 100644 --- a/demo/example.py +++ b/demo/example.py @@ -5,7 +5,7 @@ from boxsdk import Client from boxsdk.exception import BoxAPIException from boxsdk.object.collaboration import CollaborationRole -from auth import authenticate +from demo.auth import authenticate def run_user_example(client): @@ -294,5 +294,6 @@ def main(): run_examples(oauth) os._exit(0) + if __name__ == '__main__': main() diff --git a/demo/music_player.py b/demo/music_player.py index 1ba9379a9..44e48e459 100644 --- a/demo/music_player.py +++ b/demo/music_player.py @@ -8,7 +8,7 @@ from demo.auth import authenticate -class MusicPlayer(object): +class MusicPlayer: def __init__(self, folder_path): self._folder_path = folder_path self._client = self._get_client() @@ -31,7 +31,7 @@ def play(self): temp_file = tempfile.NamedTemporaryFile() temp_file.write(item.content()) item_with_name = item.get() - print item_with_name.name + print(item_with_name.name) subprocess.check_call(['afplay', temp_file.name]) diff --git a/test/functional/mock_box/behavior/event_behavior.py b/test/functional/mock_box/behavior/event_behavior.py index 3dc60f3d5..1c91a34e1 100644 --- a/test/functional/mock_box/behavior/event_behavior.py +++ b/test/functional/mock_box/behavior/event_behavior.py @@ -14,7 +14,7 @@ from test.functional.mock_box.util import json_utils as json -class EventBehavior(object): +class EventBehavior: def __init__(self, db_session): self._db_session = db_session self._subscribe_event = Event() diff --git a/test/functional/mock_box/behavior/item_behavior.py b/test/functional/mock_box/behavior/item_behavior.py index d8e8d227e..0a29f7d0e 100644 --- a/test/functional/mock_box/behavior/item_behavior.py +++ b/test/functional/mock_box/behavior/item_behavior.py @@ -7,7 +7,7 @@ from test.functional.mock_box.util import json_utils as json -class ItemBehavior(object): +class ItemBehavior: def __init__(self, db_session): self._db_session = db_session diff --git a/test/functional/mock_box/behavior/oauth2_behavior.py b/test/functional/mock_box/behavior/oauth2_behavior.py index a66465dfd..1e3127c5b 100644 --- a/test/functional/mock_box/behavior/oauth2_behavior.py +++ b/test/functional/mock_box/behavior/oauth2_behavior.py @@ -16,7 +16,7 @@ from test.functional.mock_box.util.http_utils import abort -class OAuth2Behavior(object): +class OAuth2Behavior: ACCESS_TOKEN_DURATION_SECONDS = 3600 REFRESH_TOKEN_DURATION_DAYS = 60 AUTH_CODE_DURATION_SECONDS = 30 diff --git a/test/functional/mock_box/behavior/user_behavior.py b/test/functional/mock_box/behavior/user_behavior.py index cd51fe35a..815b84b72 100644 --- a/test/functional/mock_box/behavior/user_behavior.py +++ b/test/functional/mock_box/behavior/user_behavior.py @@ -7,7 +7,7 @@ from test.functional.mock_box.util.http_utils import abort -class UserBehavior(object): +class UserBehavior: def __init__(self, db_session): self._db_session = db_session diff --git a/test/functional/mock_box/box.py b/test/functional/mock_box/box.py index ef728ca4c..7a778928c 100644 --- a/test/functional/mock_box/box.py +++ b/test/functional/mock_box/box.py @@ -44,7 +44,7 @@ TEMPLATE_PATH.insert(0, join(dirname(__file__), 'views')) -class Box(object): +class Box: """ Fake Box. Sets up 4 webservers - one for auth, one for upload, one for events, and one for the rest of the api. """ diff --git a/test/functional/mock_box/util/http_utils.py b/test/functional/mock_box/util/http_utils.py index 19dc15681..be3aa8acf 100644 --- a/test/functional/mock_box/util/http_utils.py +++ b/test/functional/mock_box/util/http_utils.py @@ -82,7 +82,7 @@ class StoppableWSGIRefServer(ServerAdapter): This is important for testing, since we don't want to "serve forever". """ def __init__(self, host='127.0.0.1', port=8080, **options): - super(StoppableWSGIRefServer, self).__init__(host, port, **options) + super().__init__(host, port, **options) self.srv = None self._thread = None diff --git a/test/functional/mock_box/util/json_utils.py b/test/functional/mock_box/util/json_utils.py index ebf80a018..519a08312 100644 --- a/test/functional/mock_box/util/json_utils.py +++ b/test/functional/mock_box/util/json_utils.py @@ -40,7 +40,7 @@ def default(self, o): if isinstance(o, FileModel): del fields['content'] return fields - return super(BoxObjectSerializer, self).default(o) + return super().default(o) return BoxObjectSerializer diff --git a/test/unit/util/test_compat.py b/test/unit/util/test_compat.py index 1e38c06c4..c80bedd9f 100644 --- a/test/unit/util/test_compat.py +++ b/test/unit/util/test_compat.py @@ -33,13 +33,13 @@ class Class2: class Meta(type): @classmethod - def __prepare__(metacls, name, this_bases, **kwds): # pylint:disable=unused-argument + def __prepare__(mcs, name, this_bases, **kwds): # pylint:disable=unused-argument assert this_bases == bases return {} - def __new__(metacls, name, this_bases, namespace, **kwds): + def __new__(mcs, name, this_bases, namespace, **kwds): assert this_bases == bases - return super(Meta, metacls).__new__(metacls, name, this_bases, namespace, **kwds) + return super(Meta, mcs).__new__(mcs, name, this_bases, namespace, **kwds) temporary_class = with_metaclass(Meta, *bases) assert isinstance(temporary_class, Meta)