diff --git a/.travis.yml b/.travis.yml index be5944a2..c1a73ea7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,8 +3,8 @@ dist: xenial language: python python: - - 2.7 - - 3.4 + - 3.6 + - 3.7 - 3.8 cache: pip: true @@ -17,7 +17,7 @@ install: - python setup.py sdist before_script: - pylint synology_dsm tests - - ./scripts/check_format.sh + - black --check --fast . script: - py.test diff --git a/requirements.txt b/requirements.txt index 6ff91026..ca3f09a8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,3 @@ -requests>=2.20.0 -urllib3>=1.24.3,<1.25 -six>=1.14.0 -future>=0.18.2 -simplejson>=3.16.0 +requests>=2.24.0 +# Constrain urllib3 to ensure we deal with CVE-2019-11236 & CVE-2019-11324 +urllib3>=1.24.3 diff --git a/requirements_test.txt b/requirements_test.txt index f15a8e3d..d69693d8 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,3 +1,4 @@ pytest -pylint>=1.9.5,<=2.4.4 +pylint>=2.6.0 pylint-strict-informational==0.1 +black==20.8b1 diff --git a/scripts/check_format.sh b/scripts/check_format.sh deleted file mode 100755 index 32522cf2..00000000 --- a/scripts/check_format.sh +++ /dev/null @@ -1,16 +0,0 @@ -./scripts/common.sh - -if ! hash python3; then - echo "python3 is not installed" - exit 0 -fi - -ver=$(python3 -V 2>&1 | sed 's/.* \([0-9]\).\([0-9]\).*/\1\2/') -if [ "$ver" -lt "36" ]; then - echo "This script requires python 3.6 or greater" - exit 0 -fi - -pip install black==19.10b0 - -black --check --fast . diff --git a/setup.py b/setup.py index 058c8ccd..5f5a3411 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- +"""Synology DSM setup.""" # NOTE(ProtoThis) Guidelines for Major.Minor.Micro # - Major means an API contract change @@ -7,7 +7,6 @@ # - Micro means change of any kind (unless significant enough for a minor/major). from setuptools import setup, find_packages -from codecs import open REPO_URL = "https://github.com/ProtoThis/python-synology" VERSION = "0.9.0" @@ -25,23 +24,24 @@ download_url=REPO_URL + "/tarball/" + VERSION, description="Python API for communication with Synology DSM", long_description=long_description, - author="FG van Zeelst (ProtoThis)", + author="Quentin POLLET (Quentame) & FG van Zeelst (ProtoThis)", packages=find_packages(include=["synology_dsm*"]), install_requires=required, - python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*", + python_requires=">=3.6", license="MIT", classifiers=[ + "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", - "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.4", - "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Topic :: Software Development :: Libraries", ], keywords=["synology-dsm", "synology"], ) diff --git a/synology_dsm/api/core/security.py b/synology_dsm/api/core/security.py index 12ece8f0..fcc074c1 100644 --- a/synology_dsm/api/core/security.py +++ b/synology_dsm/api/core/security.py @@ -1,8 +1,7 @@ -# -*- coding: utf-8 -*- """DSM Security data.""" -class SynoCoreSecurity(object): +class SynoCoreSecurity: """Class containing Security data.""" API_KEY = "SYNO.Core.SecurityScan.Status" diff --git a/synology_dsm/api/core/share.py b/synology_dsm/api/core/share.py index 6e38f40c..bcc5ad56 100644 --- a/synology_dsm/api/core/share.py +++ b/synology_dsm/api/core/share.py @@ -1,9 +1,8 @@ -# -*- coding: utf-8 -*- """Shared Folders data.""" from synology_dsm.helpers import SynoFormatHelper -class SynoCoreShare(object): +class SynoCoreShare: """Class containing Share data.""" API_KEY = "SYNO.Core.Share" diff --git a/synology_dsm/api/core/utilization.py b/synology_dsm/api/core/utilization.py index d42ff874..e768c51e 100644 --- a/synology_dsm/api/core/utilization.py +++ b/synology_dsm/api/core/utilization.py @@ -1,9 +1,8 @@ -# -*- coding: utf-8 -*- """DSM Utilization data.""" from synology_dsm.helpers import SynoFormatHelper -class SynoCoreUtilization(object): +class SynoCoreUtilization: """Class containing Utilization data.""" API_KEY = "SYNO.Core.System.Utilization" diff --git a/synology_dsm/api/download_station/__init__.py b/synology_dsm/api/download_station/__init__.py index 13d7dce1..94866dd5 100644 --- a/synology_dsm/api/download_station/__init__.py +++ b/synology_dsm/api/download_station/__init__.py @@ -2,7 +2,7 @@ from .task import SynoDownloadTask -class SynoDownloadStation(object): +class SynoDownloadStation: """An implementation of a Synology DownloadStation.""" API_KEY = "SYNO.DownloadStation.*" diff --git a/synology_dsm/api/download_station/task.py b/synology_dsm/api/download_station/task.py index 7a07561b..b4b6a6cb 100644 --- a/synology_dsm/api/download_station/task.py +++ b/synology_dsm/api/download_station/task.py @@ -1,7 +1,7 @@ """DownloadStation task.""" -class SynoDownloadTask(object): +class SynoDownloadTask: """An representation of a Synology DownloadStation task.""" def __init__(self, data): diff --git a/synology_dsm/api/dsm/information.py b/synology_dsm/api/dsm/information.py index 0c3a6b24..7c73cc9e 100644 --- a/synology_dsm/api/dsm/information.py +++ b/synology_dsm/api/dsm/information.py @@ -1,8 +1,7 @@ -# -*- coding: utf-8 -*- """DSM Information data.""" -class SynoDSMInformation(object): +class SynoDSMInformation: """Class containing Information data.""" API_KEY = "SYNO.DSM.Info" diff --git a/synology_dsm/api/dsm/network.py b/synology_dsm/api/dsm/network.py index 7a214025..451d111c 100644 --- a/synology_dsm/api/dsm/network.py +++ b/synology_dsm/api/dsm/network.py @@ -1,8 +1,7 @@ -# -*- coding: utf-8 -*- """DSM Network data.""" -class SynoDSMNetwork(object): +class SynoDSMNetwork: """Class containing Network data.""" API_KEY = "SYNO.DSM.Network" diff --git a/synology_dsm/api/storage/storage.py b/synology_dsm/api/storage/storage.py index 0eb9d3b2..ed2ce661 100644 --- a/synology_dsm/api/storage/storage.py +++ b/synology_dsm/api/storage/storage.py @@ -1,11 +1,9 @@ -# -*- coding: utf-8 -*- """DSM Storage data.""" -from __future__ import division from synology_dsm.helpers import SynoFormatHelper -class SynoStorage(object): +class SynoStorage: """Class containing Storage data.""" API_KEY = "SYNO.Storage.CGI.Storage" diff --git a/synology_dsm/api/surveillance_station/__init__.py b/synology_dsm/api/surveillance_station/__init__.py index 112d3797..047284de 100644 --- a/synology_dsm/api/surveillance_station/__init__.py +++ b/synology_dsm/api/surveillance_station/__init__.py @@ -5,7 +5,7 @@ from .const import MOTION_DETECTION_BY_SURVEILLANCE, MOTION_DETECTION_DISABLED -class SynoSurveillanceStation(object): +class SynoSurveillanceStation: """An implementation of a Synology SurveillanceStation.""" API_KEY = "SYNO.SurveillanceStation.*" @@ -37,12 +37,12 @@ def update(self): )["data"] ) - live_view_data = self._dsm.get( + live_view_datas = self._dsm.get( self.CAMERA_API_KEY, "GetLiveViewPath", {"idList": ",".join(str(k) for k in self._cameras_by_id)}, )["data"] - for live_view_data in live_view_data: + for live_view_data in live_view_datas: self._cameras_by_id[live_view_data["id"]].live_view.update(live_view_data) # Global diff --git a/synology_dsm/api/surveillance_station/camera.py b/synology_dsm/api/surveillance_station/camera.py index 5096a03f..0c32812e 100644 --- a/synology_dsm/api/surveillance_station/camera.py +++ b/synology_dsm/api/surveillance_station/camera.py @@ -2,7 +2,7 @@ from .const import RECORDING_STATUS, MOTION_DETECTION_DISABLED -class SynoCamera(object): +class SynoCamera: """An representation of a Synology SurveillanceStation camera.""" def __init__(self, data, live_view_data=None): @@ -62,7 +62,7 @@ def is_recording(self): return self._data["recStatus"] in RECORDING_STATUS -class SynoCameraLiveView(object): +class SynoCameraLiveView: """An representation of a Synology SurveillanceStation camera live view.""" def __init__(self, data): diff --git a/synology_dsm/const.py b/synology_dsm/const.py index a471e452..9d4609b9 100644 --- a/synology_dsm/const.py +++ b/synology_dsm/const.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """Library constants.""" # APIs diff --git a/synology_dsm/exceptions.py b/synology_dsm/exceptions.py index 2a0c4b45..799fdc99 100644 --- a/synology_dsm/exceptions.py +++ b/synology_dsm/exceptions.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """Library exceptions.""" from .const import API_AUTH, ERROR_AUTH, ERROR_COMMON, ERROR_DOWNLOAD_SEARCH, ERROR_DOWNLOAD_TASK, ERROR_FILE, ERROR_SURVEILLANCE, ERROR_VIRTUALIZATION @@ -24,7 +23,7 @@ def __init__(self, api, code, details=None): reason = "Unknown" error_message={"api": api, "code": code, "reason": reason, "details": details} - super(SynologyDSMException, self).__init__(error_message) + super().__init__(error_message) # Request class SynologyDSMRequestException(SynologyDSMException): @@ -34,57 +33,56 @@ def __init__(self, exception): ex_reason = exception.args[0] if hasattr(exception.args[0], "reason"): ex_reason = exception.args[0].reason - message = "%s = %s" % (ex_class, ex_reason) - super(SynologyDSMRequestException, self).__init__(None, -1, message) + super().__init__(None, -1, f"{ex_class} = {ex_reason}") # API class SynologyDSMAPINotExistsException(SynologyDSMException): """API not exists exception.""" def __init__(self, api): - super(SynologyDSMAPINotExistsException, self).__init__(api, -2, "API %s does not exists" % api) + super().__init__(api, -2, f"API {api} does not exists") class SynologyDSMAPIErrorException(SynologyDSMException): """API returns an error exception.""" def __init__(self, api, code, details): - super(SynologyDSMAPIErrorException, self).__init__(api, code, details) + super().__init__(api, code, details) # Login class SynologyDSMLoginFailedException(SynologyDSMException): """Failed to login exception.""" def __init__(self, code, details=None): - super(SynologyDSMLoginFailedException, self).__init__(API_AUTH, code, details) + super().__init__(API_AUTH, code, details) class SynologyDSMLoginInvalidException(SynologyDSMLoginFailedException): """Invalid password & not admin account exception.""" def __init__(self, username): - message = "Invalid password or not admin account: %s" % username - super(SynologyDSMLoginInvalidException, self).__init__(400, message) + message = f"Invalid password or not admin account: {username}" + super().__init__(400, message) class SynologyDSMLoginDisabledAccountException(SynologyDSMLoginFailedException): """Guest & disabled account exception.""" def __init__(self, username): - message = "Guest or disabled account: %s" % username - super(SynologyDSMLoginDisabledAccountException, self).__init__(401, message) + message = f"Guest or disabled account: {username}" + super().__init__(401, message) class SynologyDSMLoginPermissionDeniedException(SynologyDSMLoginFailedException): """No access to login exception.""" def __init__(self, username): - message = "Permission denied for account: %s" % username - super(SynologyDSMLoginPermissionDeniedException, self).__init__(402, message) + message = f"Permission denied for account: {username}" + super().__init__(402, message) class SynologyDSMLogin2SARequiredException(SynologyDSMLoginFailedException): """2SA required to login exception.""" def __init__(self, username): - message = "Two-step authentication required for account: %s" % username - super(SynologyDSMLogin2SARequiredException, self).__init__(403, message) + message = f"Two-step authentication required for account: {username}" + super().__init__(403, message) class SynologyDSMLogin2SAFailedException(SynologyDSMLoginFailedException): """2SA code failed exception.""" def __init__(self): message = "Two-step authentication failed, retry with a new pass code" - super(SynologyDSMLogin2SAFailedException, self).__init__(404, message) + super().__init__(404, message) diff --git a/synology_dsm/helpers.py b/synology_dsm/helpers.py index e7647f45..8098771e 100644 --- a/synology_dsm/helpers.py +++ b/synology_dsm/helpers.py @@ -1,8 +1,7 @@ -# -*- coding: utf-8 -*- """Helpers.""" -class SynoFormatHelper(object): +class SynoFormatHelper: """Class containing various formatting functions.""" @staticmethod diff --git a/synology_dsm/synology_dsm.py b/synology_dsm/synology_dsm.py index 0e12b3e7..8ac0506a 100644 --- a/synology_dsm/synology_dsm.py +++ b/synology_dsm/synology_dsm.py @@ -1,11 +1,11 @@ -# -*- coding: utf-8 -*- """Class to interact with Synology DSM.""" +from json import JSONDecodeError +from urllib.parse import quote import socket + import urllib3 -import six from requests import Session from requests.exceptions import RequestException -from simplejson.errors import JSONDecodeError from .exceptions import ( SynologyDSMAPIErrorException, @@ -29,13 +29,8 @@ from .api.surveillance_station import SynoSurveillanceStation from .const import API_AUTH, API_INFO -if six.PY2: - from future.moves.urllib.parse import quote -else: - from urllib.parse import quote # pylint: disable=import-error,no-name-in-module - -class SynologyDSM(object): +class SynologyDSM: """Class containing the main Synology DSM functions.""" DSM_5_WEIRD_URL_API = [ @@ -44,14 +39,14 @@ class SynologyDSM(object): def __init__( self, - dsm_ip, - dsm_port, - username, - password, - use_https=False, - timeout=None, - device_token=None, - debugmode=False, + dsm_ip: str, + dsm_port: int, + username: str, + password: str, + use_https: bool = False, + timeout: int = None, + device_token: str = None, + debugmode: bool = False, ): self.username = username self._password = password @@ -86,16 +81,16 @@ def __init__( # disable SSL warnings due to the auto-genenerated cert urllib3.disable_warnings() - self._base_url = "https://%s:%s" % (dsm_ip, dsm_port) + self._base_url = f"https://{dsm_ip}:{dsm_port}" else: - self._base_url = "http://%s:%s" % (dsm_ip, dsm_port) + self._base_url = f"http://{dsm_ip}:{dsm_port}" - def _debuglog(self, message): + def _debuglog(self, message: str): """Outputs message if debug mode is enabled.""" if self._debugmode: print("DEBUG: " + message) - def _is_weird_api_url(self, api): + def _is_weird_api_url(self, api: str) -> bool: """Returns True if the API URL is not common (nas_base_url/webapi/path?params) [Only handles DSM 5 for now].""" return ( api in self.DSM_5_WEIRD_URL_API @@ -104,15 +99,12 @@ def _is_weird_api_url(self, api): and int(self._information.version) < 7321 # < DSM 6 ) - def _build_url(self, api): + def _build_url(self, api: str) -> str: if self._is_weird_api_url(api): if api == SynoStorage.API_KEY: - return ( - "%s/webman/modules/StorageManager/storagehandler.cgi?" - % self._base_url - ) + return f"{self._base_url}/webman/modules/StorageManager/storagehandler.cgi?" - return "%s/webapi/%s?" % (self._base_url, self.apis[api]["path"]) + return f"{self._base_url}/webapi/{self.apis[api]['path']}?" def discover_apis(self): """Retreives available API infos from the NAS.""" @@ -125,7 +117,7 @@ def apis(self): """Gets available API infos from the NAS.""" return self._apis - def login(self, otp_code=None): + def login(self, otp_code: str = None): """Create a logged session.""" # First reset the session self._debuglog("Creating new session") @@ -180,20 +172,26 @@ def login(self, otp_code=None): return True @property - def device_token(self): + def device_token(self) -> str: """Gets the device token to remember the 2SA access was granted on this device.""" return self._device_token - def get(self, api, method, params=None, **kwargs): + def get(self, api: str, method: str, params: dict = None, **kwargs): """Handles API GET request.""" return self._request("GET", api, method, params, **kwargs) - def post(self, api, method, params=None, **kwargs): + def post(self, api: str, method: str, params: dict = None, **kwargs): """Handles API POST request.""" return self._request("POST", api, method, params, **kwargs) def _request( - self, request_method, api, method, params=None, retry_once=True, **kwargs + self, + request_method: str, + api: str, + method: str, + params: dict = None, + retry_once: bool = True, + **kwargs ): """Handles API request.""" # Discover existing APIs @@ -252,17 +250,13 @@ def _request( return response - def _execute_request(self, method, url, params, **kwargs): + def _execute_request(self, method: str, url: str, params: dict, **kwargs): """Function to execute and handle a request.""" # Execute Request try: if method == "GET": - if six.PY2: - items = params.iteritems() - else: - items = params.items() encoded_params = "&".join( - "%s=%s" % (key, quote(str(value))) for key, value in items + f"{key}={quote(str(value))}" for key, value in params.items() ) response = self._session.get( url, params=encoded_params, timeout=self._timeout, **kwargs @@ -300,9 +294,9 @@ def _execute_request(self, method, url, params, **kwargs): raise RequestException(response) except (RequestException, JSONDecodeError) as exp: - raise SynologyDSMRequestException(exp) + raise SynologyDSMRequestException(exp) from exp - def update(self, with_information=False, with_network=False): + def update(self, with_information: bool = False, with_network: bool = False): """Updates the various instanced modules.""" if self._download: self._download.update() @@ -328,7 +322,7 @@ def update(self, with_information=False, with_network=False): if self._surveillance: self._surveillance.update() - def reset(self, api): + def reset(self, api: any) -> bool: """Reset an API to avoid fetching in on update.""" if isinstance(api, str): if api in ("information", SynoDSMInformation.API_KEY): @@ -376,56 +370,56 @@ def reset(self, api): return False @property - def download_station(self): + def download_station(self) -> SynoDownloadStation: """Gets NAS DownloadStation.""" if not self._download: self._download = SynoDownloadStation(self) return self._download @property - def information(self): + def information(self) -> SynoDSMInformation: """Gets NAS informations.""" if not self._information: self._information = SynoDSMInformation(self) return self._information @property - def network(self): + def network(self) -> SynoDSMNetwork: """Gets NAS network informations.""" if not self._network: self._network = SynoDSMNetwork(self) return self._network @property - def security(self): + def security(self) -> SynoCoreSecurity: """Gets NAS security informations.""" if not self._security: self._security = SynoCoreSecurity(self) return self._security @property - def utilisation(self): + def utilisation(self) -> SynoCoreUtilization: """Gets NAS utilisation informations.""" if not self._utilisation: self._utilisation = SynoCoreUtilization(self) return self._utilisation @property - def storage(self): + def storage(self) -> SynoStorage: """Gets NAS storage informations.""" if not self._storage: self._storage = SynoStorage(self) return self._storage @property - def share(self): + def share(self) -> SynoCoreShare: """Gets NAS shares information.""" if not self._share: self._share = SynoCoreShare(self) return self._share @property - def surveillance_station(self): + def surveillance_station(self) -> SynoSurveillanceStation: """Gets NAS SurveillanceStation.""" if not self._surveillance: self._surveillance = SynoSurveillanceStation(self) diff --git a/tests/__init__.py b/tests/__init__.py index 4c3cd9a8..a7356fbe 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,8 +1,8 @@ -# -*- coding: utf-8 -*- """Library tests.""" -import six +from json import JSONDecodeError +from urllib.parse import urlencode + from requests.exceptions import ConnectionError as ConnError, RequestException, SSLError -from simplejson.errors import JSONDecodeError from synology_dsm import SynologyDSM from synology_dsm.exceptions import SynologyDSMRequestException @@ -71,7 +71,9 @@ "DSM_INFORMATION": DSM_5_DSM_INFORMATION, "DSM_NETWORK": DSM_5_DSM_NETWORK, "CORE_UTILIZATION": DSM_5_CORE_UTILIZATION, - "STORAGE_STORAGE": {"RAID": DSM_5_STORAGE_STORAGE_DS410J_RAID5_4DISKS_1VOL,}, + "STORAGE_STORAGE": { + "RAID": DSM_5_STORAGE_STORAGE_DS410J_RAID5_4DISKS_1VOL, + }, }, 6: { "API_INFO": DSM_6_API_INFO, @@ -93,11 +95,6 @@ } -if six.PY2: - from future.moves.urllib.parse import urlencode -else: - from urllib.parse import urlencode # pylint: disable=import-error,no-name-in-module - VALID_HOST = "nas.mywebsite.me" VALID_PORT = "443" VALID_SSL = True @@ -161,7 +158,7 @@ def _execute_request(self, method, url, params, **kwargs): if VALID_PORT not in url and "https" not in url: raise SynologyDSMRequestException( - JSONDecodeError("Expecting value", "document", 0, None) + JSONDecodeError("Expecting value", "document", 0) ) if VALID_PORT not in url: diff --git a/tests/api_data/dsm_5/core/const_5_core_utilization.py b/tests/api_data/dsm_5/core/const_5_core_utilization.py index 94b201e0..9abce7da 100644 --- a/tests/api_data/dsm_5/core/const_5_core_utilization.py +++ b/tests/api_data/dsm_5/core/const_5_core_utilization.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """DSM 5 SYNO.Core.System.Utilization data.""" DSM_5_CORE_UTILIZATION = { diff --git a/tests/api_data/dsm_5/dsm/const_5_dsm_info.py b/tests/api_data/dsm_5/dsm/const_5_dsm_info.py index 453bc8cb..6fd6d059 100644 --- a/tests/api_data/dsm_5/dsm/const_5_dsm_info.py +++ b/tests/api_data/dsm_5/dsm/const_5_dsm_info.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """DSM 5 SYNO.DSM.Info data.""" DSM_5_DSM_INFORMATION_DS410J = { diff --git a/tests/api_data/dsm_5/dsm/const_5_dsm_network.py b/tests/api_data/dsm_5/dsm/const_5_dsm_network.py index 98e272bc..2ab5f3cb 100644 --- a/tests/api_data/dsm_5/dsm/const_5_dsm_network.py +++ b/tests/api_data/dsm_5/dsm/const_5_dsm_network.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """DSM 5 SYNO.DSM.Network data.""" DSM_5_DSM_NETWORK = { diff --git a/tests/api_data/dsm_5/storage/const_5_storage_storage.py b/tests/api_data/dsm_5/storage/const_5_storage_storage.py index 674fed66..9af04897 100644 --- a/tests/api_data/dsm_5/storage/const_5_storage_storage.py +++ b/tests/api_data/dsm_5/storage/const_5_storage_storage.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """DSM 5 SYNO.Storage.CGI.Storage data.""" from tests.const import UNIQUE_KEY @@ -253,10 +252,18 @@ "vol_path": "/volume1", "vspace_can_do": { "drbd": { - "resize": {"can_do": False, "errCode": 53504, "stopService": False,} + "resize": { + "can_do": False, + "errCode": 53504, + "stopService": False, + } }, "flashcache": { - "apply": {"can_do": False, "errCode": 53504, "stopService": False,}, + "apply": { + "can_do": False, + "errCode": 53504, + "stopService": False, + }, "remove": { "can_do": False, "errCode": 53504, diff --git a/tests/api_data/dsm_6/core/const_6_core_security.py b/tests/api_data/dsm_6/core/const_6_core_security.py index 10339865..e695887d 100644 --- a/tests/api_data/dsm_6/core/const_6_core_security.py +++ b/tests/api_data/dsm_6/core/const_6_core_security.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """DSM 6 SYNO.Core.SecurityScan.Status data.""" DSM_6_CORE_SECURITY = { diff --git a/tests/api_data/dsm_6/core/const_6_core_share.py b/tests/api_data/dsm_6/core/const_6_core_share.py index 08f37662..fe663582 100644 --- a/tests/api_data/dsm_6/core/const_6_core_share.py +++ b/tests/api_data/dsm_6/core/const_6_core_share.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """DSM 6 SYNO.Core.Share data.""" DSM_6_CORE_SHARE = { diff --git a/tests/api_data/dsm_6/core/const_6_core_utilization.py b/tests/api_data/dsm_6/core/const_6_core_utilization.py index 490aacfa..dac2678c 100644 --- a/tests/api_data/dsm_6/core/const_6_core_utilization.py +++ b/tests/api_data/dsm_6/core/const_6_core_utilization.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """DSM 6 SYNO.Core.System.Utilization data.""" DSM_6_CORE_UTILIZATION_ERROR_1055 = { diff --git a/tests/api_data/dsm_6/download_station/const_6_download_station_info.py b/tests/api_data/dsm_6/download_station/const_6_download_station_info.py index 9ef80a7e..5f8fadb5 100644 --- a/tests/api_data/dsm_6/download_station/const_6_download_station_info.py +++ b/tests/api_data/dsm_6/download_station/const_6_download_station_info.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """DSM 6 SYNO.DownloadStation.Info data.""" DSM_6_DOWNLOAD_STATION_INFO_INFO = { diff --git a/tests/api_data/dsm_6/download_station/const_6_download_station_stat.py b/tests/api_data/dsm_6/download_station/const_6_download_station_stat.py index b5f8c004..34a6ef61 100644 --- a/tests/api_data/dsm_6/download_station/const_6_download_station_stat.py +++ b/tests/api_data/dsm_6/download_station/const_6_download_station_stat.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """DSM 6 SYNO.DownloadStation.Statistic data.""" DSM_6_DOWNLOAD_STATION_STAT_INFO = { diff --git a/tests/api_data/dsm_6/download_station/const_6_download_station_task.py b/tests/api_data/dsm_6/download_station/const_6_download_station_task.py index 1c7b7179..180c87c8 100644 --- a/tests/api_data/dsm_6/download_station/const_6_download_station_task.py +++ b/tests/api_data/dsm_6/download_station/const_6_download_station_task.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """DSM 6 SYNO.DownloadStation.Task data.""" DSM_6_DOWNLOAD_STATION_TASK_LIST = { diff --git a/tests/api_data/dsm_6/dsm/const_6_dsm_info.py b/tests/api_data/dsm_6/dsm/const_6_dsm_info.py index c20191a0..f43f9a62 100644 --- a/tests/api_data/dsm_6/dsm/const_6_dsm_info.py +++ b/tests/api_data/dsm_6/dsm/const_6_dsm_info.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """DSM 6 SYNO.DSM.Info data.""" DSM_6_DSM_INFORMATION_DS213_PLUS = { diff --git a/tests/api_data/dsm_6/dsm/const_6_dsm_network.py b/tests/api_data/dsm_6/dsm/const_6_dsm_network.py index 48304626..38a6d05f 100644 --- a/tests/api_data/dsm_6/dsm/const_6_dsm_network.py +++ b/tests/api_data/dsm_6/dsm/const_6_dsm_network.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """DSM 6 SYNO.DSM.Network data.""" DSM_6_DSM_NETWORK = { diff --git a/tests/api_data/dsm_6/storage/const_6_storage_storage.py b/tests/api_data/dsm_6/storage/const_6_storage_storage.py index 6535b9a8..a86913e1 100644 --- a/tests/api_data/dsm_6/storage/const_6_storage_storage.py +++ b/tests/api_data/dsm_6/storage/const_6_storage_storage.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """DSM 6 SYNO.Storage.CGI.Storage data.""" from tests.const import UNIQUE_KEY @@ -1979,7 +1978,10 @@ "env": { "batchtask": {"max_task": 64, "remain_task": 64}, "bay_number": "4", - "data_scrubbing": {"sche_enabled": "0", "sche_status": "disabled",}, + "data_scrubbing": { + "sche_enabled": "0", + "sche_status": "disabled", + }, "ebox": [], "fs_acting": False, "isSyncSysPartition": False, @@ -1993,8 +1995,15 @@ "ram_size": 4, "ram_size_required": 32, "showpooltab": False, - "status": {"system_crashed": False, "system_need_repair": False,}, - "support": {"ebox": True, "raid_cross": True, "sysdef": True,}, + "status": { + "system_crashed": False, + "system_need_repair": False, + }, + "support": { + "ebox": True, + "raid_cross": True, + "sysdef": True, + }, "support_fit_fs_limit": True, "unique_key": UNIQUE_KEY, "volume_full_critical": 0.1, @@ -2040,9 +2049,21 @@ { "designedDiskCount": 3, "devices": [ - {"id": "sdc", "slot": 2, "status": "normal",}, - {"id": "sdb", "slot": 1, "status": "normal",}, - {"id": "sda", "slot": 0, "status": "normal",}, + { + "id": "sdc", + "slot": 2, + "status": "normal", + }, + { + "id": "sdb", + "slot": 1, + "status": "normal", + }, + { + "id": "sda", + "slot": 0, + "status": "normal", + }, ], "hasParity": True, "minDevSize": "4000681164800", @@ -2053,7 +2074,10 @@ } ], "scrubbingStatus": "no_action", - "size": {"total": "7991698522112", "used": "7991698522112",}, + "size": { + "total": "7991698522112", + "used": "7991698522112", + }, "space_path": "/dev/md2", "ssd_trim": {"support": "not support"}, "status": "normal", @@ -2068,9 +2092,21 @@ } }, "flashcache": { - "apply": {"can_do": True, "errCode": 0, "stopService": True,}, - "remove": {"can_do": True, "errCode": 0, "stopService": False,}, - "resize": {"can_do": True, "errCode": 0, "stopService": False,}, + "apply": { + "can_do": True, + "errCode": 0, + "stopService": True, + }, + "remove": { + "can_do": True, + "errCode": 0, + "stopService": False, + }, + "resize": { + "can_do": True, + "errCode": 0, + "stopService": False, + }, }, "snapshot": { "resize": { @@ -2142,9 +2178,21 @@ } }, "flashcache": { - "apply": {"can_do": True, "errCode": 0, "stopService": True,}, - "remove": {"can_do": True, "errCode": 0, "stopService": False,}, - "resize": {"can_do": True, "errCode": 0, "stopService": False,}, + "apply": { + "can_do": True, + "errCode": 0, + "stopService": True, + }, + "remove": { + "can_do": True, + "errCode": 0, + "stopService": False, + }, + "resize": { + "can_do": True, + "errCode": 0, + "stopService": False, + }, }, "snapshot": { "resize": { diff --git a/tests/api_data/dsm_6/surveillance_station/const_6_surveillance_station_camera.py b/tests/api_data/dsm_6/surveillance_station/const_6_surveillance_station_camera.py index e2187bd1..d39848b8 100644 --- a/tests/api_data/dsm_6/surveillance_station/const_6_surveillance_station_camera.py +++ b/tests/api_data/dsm_6/surveillance_station/const_6_surveillance_station_camera.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """DSM 6 SYNO.SurveillanceStation.Camera data.""" DSM_6_SURVEILLANCE_STATION_CAMERA_LIST = { diff --git a/tests/api_data/dsm_6/surveillance_station/const_6_surveillance_station_home_mode.py b/tests/api_data/dsm_6/surveillance_station/const_6_surveillance_station_home_mode.py index 1b7afde5..b58735bc 100644 --- a/tests/api_data/dsm_6/surveillance_station/const_6_surveillance_station_home_mode.py +++ b/tests/api_data/dsm_6/surveillance_station/const_6_surveillance_station_home_mode.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """DSM 6 SYNO.API.SurveillanceStation.HomeMode data.""" DSM_6_SURVEILLANCE_STATION_HOME_MODE_GET_INFO = { diff --git a/tests/const.py b/tests/const.py index c5466528..6e938f53 100644 --- a/tests/const.py +++ b/tests/const.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """Test constants.""" # API test data are localized in diff --git a/tests/test_synology_dsm.py b/tests/test_synology_dsm.py index 03bebbd6..87071b24 100644 --- a/tests/test_synology_dsm.py +++ b/tests/test_synology_dsm.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """Synology DSM tests.""" from unittest import TestCase import pytest diff --git a/tests/test_synology_dsm_5.py b/tests/test_synology_dsm_5.py index c1141357..ee0577c7 100644 --- a/tests/test_synology_dsm_5.py +++ b/tests/test_synology_dsm_5.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """Synology DSM tests.""" from unittest import TestCase