From ba64d0a173f3e413a90bb9abd150017e4cf9978d Mon Sep 17 00:00:00 2001 From: Michael <35783820+mib1185@users.noreply.github.com> Date: Mon, 19 Oct 2020 23:57:58 +0200 Subject: [PATCH 01/33] Add parameter verify_ssl (#76) * add parameter ssl_validation * add parameter ssl_validation * rename to verify_ssl * rename to verify_ssl * object property use_https not needed * black * VALID_SSL_VERIFICATION --> VALID_SSL_VERIFY * disable_warnings on urllib only if not verify_ssl * VALID_SSL_VERIFY --> VALID_VERIFY_SSL * VALID_SSL --> VALID_HTTPS * Add test * black again * Add test Co-authored-by: Quentin POLLET --- README.rst | 1 + synology_dsm/api/core/system.py | 36 +-- synology_dsm/synology_dsm.py | 13 +- tests/__init__.py | 34 ++- tests/api_data/dsm_6/__init__.py | 5 + .../dsm_6/core/const_6_core_system.py | 140 +++++++++--- .../dsm_6/core/const_6_core_upgrade.py | 9 +- tests/test_synology_dsm.py | 211 ++++++++++++++---- tests/test_synology_dsm_5.py | 74 +++++- 9 files changed, 392 insertions(+), 131 deletions(-) diff --git a/README.rst b/README.rst index ddba2dc3..83465a88 100644 --- a/README.rst +++ b/README.rst @@ -47,6 +47,7 @@ Constructor username, password, use_https=False, + verify_ssl=False, timeout=None, device_token=None, debugmode=False, diff --git a/synology_dsm/api/core/system.py b/synology_dsm/api/core/system.py index af9faa51..4af5870b 100644 --- a/synology_dsm/api/core/system.py +++ b/synology_dsm/api/core/system.py @@ -20,82 +20,82 @@ def update(self): @property def cpu_clock_speed(self): """Gets System CPU clock speed.""" - return self._data.get('cpu_clock_speed') + return self._data.get("cpu_clock_speed") @property def cpu_cores(self): """Gets System CPU cores.""" - return self._data.get('cpu_cores') + return self._data.get("cpu_cores") @property def cpu_family(self): """Gets System CPU family.""" - return self._data.get('cpu_family') + return self._data.get("cpu_family") @property def cpu_series(self): """Gets System CPU series.""" - return self._data.get('cpu_series') + return self._data.get("cpu_series") @property def enabled_ntp(self): """Gets System NTP state.""" - return self._data.get('enabled_ntp') + return self._data.get("enabled_ntp") @property def ntp_server(self): """Gets System NTP server.""" - return self._data.get('ntp_server') + return self._data.get("ntp_server") @property def firmware_ver(self): """Gets System firmware version.""" - return self._data.get('firmware_ver') + return self._data.get("firmware_ver") @property def model(self): """Gets System model.""" - return self._data.get('model') + return self._data.get("model") @property def ram_size(self): """Gets System ram size.""" - return self._data.get('ram_size') + return self._data.get("ram_size") @property def serial(self): """Gets System serial number.""" - return self._data.get('serial') + return self._data.get("serial") @property def sys_temp(self): """Gets System temperature.""" - return self._data.get('sys_temp') + return self._data.get("sys_temp") @property def time(self): """Gets System time.""" - return self._data.get('time') + return self._data.get("time") @property def time_zone(self): """Gets System time zone.""" - return self._data.get('time_zone') + return self._data.get("time_zone") @property def time_zone_desc(self): """Gets System time zone description.""" - return self._data.get('time_zone_desc') + return self._data.get("time_zone_desc") @property def up_time(self): """Gets System uptime.""" - return self._data.get('up_time') + return self._data.get("up_time") @property def usb_dev(self): """Gets System connected usb devices.""" - return self._data.get('usb_dev', []) + return self._data.get("usb_dev", []) ### do system actions def shutdown(self): @@ -103,7 +103,7 @@ def shutdown(self): res = self._dsm.get( self.API_KEY, "shutdown", - max_version=1, # shutdown method is only available on api version 1 + max_version=1, # shutdown method is only available on api version 1 ) return res @@ -112,6 +112,6 @@ def reboot(self): res = self._dsm.get( self.API_KEY, "reboot", - max_version=1, # reboot method is only available on api version 1 + max_version=1, # reboot method is only available on api version 1 ) return res diff --git a/synology_dsm/synology_dsm.py b/synology_dsm/synology_dsm.py index 87f09d54..81299fbf 100644 --- a/synology_dsm/synology_dsm.py +++ b/synology_dsm/synology_dsm.py @@ -46,6 +46,7 @@ def __init__( username: str, password: str, use_https: bool = False, + verify_ssl: bool = False, timeout: int = None, device_token: str = None, debugmode: bool = False, @@ -54,10 +55,11 @@ def __init__( self._password = password self._timeout = timeout or 10 self._debugmode = debugmode + self._verify = verify_ssl & use_https # Session self._session = Session() - self._session.verify = False + self._session.verify = self._verify # Login self._session_id = None @@ -81,9 +83,10 @@ def __init__( # Build variables if use_https: - # https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings - # disable SSL warnings due to the auto-genenerated cert - urllib3.disable_warnings() + if not verify_ssl: + # https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings + # disable SSL warnings due to the auto-genenerated cert + urllib3.disable_warnings() self._base_url = f"https://{dsm_ip}:{dsm_port}" else: @@ -126,7 +129,7 @@ def login(self, otp_code: str = None): # First reset the session self._debuglog("Creating new session") self._session = Session() - self._session.verify = False + self._session.verify = self._verify params = { "account": self.username, diff --git a/tests/__init__.py b/tests/__init__.py index a7356fbe..066b4f33 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -7,12 +7,14 @@ from synology_dsm import SynologyDSM from synology_dsm.exceptions import SynologyDSMRequestException from synology_dsm.api.core.security import SynoCoreSecurity +from synology_dsm.api.core.share import SynoCoreShare +from synology_dsm.api.core.system import SynoCoreSystem from synology_dsm.api.core.utilization import SynoCoreUtilization +from synology_dsm.api.core.upgrade import SynoCoreUpgrade from synology_dsm.api.dsm.information import SynoDSMInformation from synology_dsm.api.dsm.network import SynoDSMNetwork from synology_dsm.api.download_station import SynoDownloadStation from synology_dsm.api.storage.storage import SynoStorage -from synology_dsm.api.core.share import SynoCoreShare from synology_dsm.api.surveillance_station import SynoSurveillanceStation from synology_dsm.const import API_AUTH, API_INFO @@ -34,6 +36,8 @@ DSM_6_CORE_UTILIZATION_ERROR_1055, DSM_6_CORE_SECURITY, DSM_6_CORE_SECURITY_UPDATE_OUTOFDATE, + DSM_6_CORE_SYSTEM_DS918_PLUS, + DSM_6_CORE_UPGRADE, DSM_6_STORAGE_STORAGE_DS213_PLUS_SHR1_2DISKS_2VOLS, DSM_6_STORAGE_STORAGE_DS918_PLUS_RAID5_3DISKS_1VOL, DSM_6_STORAGE_STORAGE_DS1819_PLUS_SHR2_8DISKS_1VOL, @@ -83,8 +87,10 @@ "DSM_INFORMATION": DSM_6_DSM_INFORMATION, "DSM_NETWORK": DSM_6_DSM_NETWORK, "CORE_SECURITY": DSM_6_CORE_SECURITY, - "CORE_UTILIZATION": DSM_6_CORE_UTILIZATION, "CORE_SHARE": DSM_6_CORE_SHARE, + "CORE_SYSTEM": DSM_6_CORE_SYSTEM_DS918_PLUS, + "CORE_UTILIZATION": DSM_6_CORE_UTILIZATION, + "CORE_UPGRADE": DSM_6_CORE_UPGRADE, "STORAGE_STORAGE": { "RAID": DSM_6_STORAGE_STORAGE_DS918_PLUS_RAID5_3DISKS_1VOL, "SHR1": DSM_6_STORAGE_STORAGE_DS213_PLUS_SHR1_2DISKS_2VOLS, @@ -97,7 +103,8 @@ VALID_HOST = "nas.mywebsite.me" VALID_PORT = "443" -VALID_SSL = True +VALID_HTTPS = True +VALID_VERIFY_SSL = True VALID_USER = "valid_user" VALID_USER_2SA = "valid_user_2sa" VALID_PASSWORD = "valid_password" @@ -118,6 +125,7 @@ def __init__( username, password, use_https=False, + verify_ssl=False, timeout=None, device_token=None, debugmode=False, @@ -129,11 +137,13 @@ def __init__( username, password, use_https, + verify_ssl, timeout, device_token, debugmode, ) + self.verify_ssl = verify_ssl self.dsm_version = 6 # 5 or 6 self.disks_redundancy = "RAID" # RAID or SHR[number][_EXPANSION] self.error = False @@ -171,6 +181,11 @@ def _execute_request(self, method, url, params, **kwargs): if "https" not in url: raise SynologyDSMRequestException(RequestException("Bad request")) + if not self.verify_ssl: + raise SynologyDSMRequestException( + SSLError(f"hostname '192.168.0.35' doesn't match '{VALID_HOST}'") + ) + if API_INFO in url: if self.with_surveillance: return DSM_6_API_INFO_SURVEILLANCE_STATION @@ -209,10 +224,15 @@ def _execute_request(self, method, url, params, **kwargs): if SynoCoreShare.API_KEY in url: return API_SWITCHER[self.dsm_version]["CORE_SHARE"] - if SynoCoreUtilization.API_KEY in url: - if self.error: - return DSM_6_CORE_UTILIZATION_ERROR_1055 - return API_SWITCHER[self.dsm_version]["CORE_UTILIZATION"] + if SynoCoreSystem.API_KEY in url: + if SynoCoreUtilization.API_KEY in url: + if self.error: + return DSM_6_CORE_UTILIZATION_ERROR_1055 + return API_SWITCHER[self.dsm_version]["CORE_UTILIZATION"] + return API_SWITCHER[self.dsm_version]["CORE_SYSTEM"] + + if SynoCoreUpgrade.API_KEY in url: + return API_SWITCHER[self.dsm_version]["CORE_UPGRADE"] if SynoDSMInformation.API_KEY in url: return API_SWITCHER[self.dsm_version]["DSM_INFORMATION"] diff --git a/tests/api_data/dsm_6/__init__.py b/tests/api_data/dsm_6/__init__.py index b74f9e37..062f664d 100644 --- a/tests/api_data/dsm_6/__init__.py +++ b/tests/api_data/dsm_6/__init__.py @@ -13,6 +13,11 @@ DSM_6_CORE_SECURITY, DSM_6_CORE_SECURITY_UPDATE_OUTOFDATE, ) +from .core.const_6_core_system import ( + DSM_6_CORE_SYSTEM_DS918_PLUS, + DSM_6_CORE_SYSTEM_DS218_PLAY, +) +from .core.const_6_core_upgrade import DSM_6_CORE_UPGRADE from .download_station.const_6_download_station_info import ( DSM_6_DOWNLOAD_STATION_INFO_INFO, DSM_6_DOWNLOAD_STATION_INFO_CONFIG, diff --git a/tests/api_data/dsm_6/core/const_6_core_system.py b/tests/api_data/dsm_6/core/const_6_core_system.py index 2073e436..74247090 100644 --- a/tests/api_data/dsm_6/core/const_6_core_system.py +++ b/tests/api_data/dsm_6/core/const_6_core_system.py @@ -1,38 +1,108 @@ """DSM 6 SYNO.Core.System data.""" -DSM_6_CORE_SYSTEM = { - "data":{ - "cpu_clock_speed":1400, - "cpu_cores":"4", - "cpu_family":"RTD1296", - "cpu_series":"SoC", - "cpu_vendor":"Realtek", - "enabled_ntp":True, - "firmware_date":"2020/07/14", - "firmware_ver":"DSM 6.2.3-25426 Update 2", - "model":"DS218play", - "ntp_server":"pool.ntp.org", - "ram_size":1024, - "serial":"123456abcdefg", - "support_esata":"no", - "sys_temp":40, - "sys_tempwarn":False, - "systempwarn":False, - "temperature_warning":False, - "time":"2020-10-16 20:26:58", - "time_zone":"Amsterdam", - "time_zone_desc":"(GMT+01:00) Amsterdam, Berlin, Rome, Stockholm, Vienna", - "up_time":"289:31:54", - "usb_dev":[ - { - "cls":"disk", - "pid":"2621", - "producer":"Western Digital Technologies, Inc.", - "product":"Elements 2621", - "rev":"10.26", - "vid":"1058" - } - ] - }, - "success":True +DSM_6_CORE_SYSTEM_DS918_PLUS = { + "data": { + "cpu_clock_speed": 1500, + "cpu_cores": "4", + "cpu_family": "Celeron", + "cpu_series": "J3455", + "cpu_vendor": "INTEL", + "enabled_ntp": True, + "firmware_date": "2020/07/08", + "firmware_ver": "DSM 6.2.3-25426 Update 2", + "model": "DS918+", + "ntp_server": "time.google.com", + "ram_size": 4096, + "sata_dev": [], + "serial": "1920PDN001501", + "support_esata": "yes", + "sys_temp": 40, + "sys_tempwarn": False, + "systempwarn": False, + "temperature_warning": False, + "time": "2020-10-19 23:33:52", + "time_zone": "Brussels", + "time_zone_desc": "(GMT+01:00) Brussels, Copenhagen, Madrid, Paris", + "up_time": "75:12:9", + "usb_dev": [ + { + "cls": "hub", + "pid": "0612", + "producer": "Genesys Logic, Inc.", + "product": "Hub", + "rev": "92.23", + "vid": "05e3", + }, + { + "cls": "other", + "pid": "1790", + "producer": "ASIX Electronics Corp.", + "product": "AX88179 Gigabit Ethernet", + "rev": "1.00", + "vid": "0b95", + }, + { + "cls": "hub", + "pid": "0610", + "producer": "Genesys Logic, Inc.", + "product": "4-port hub", + "rev": "92.23", + "vid": "05e3", + }, + { + "cls": "other", + "pid": "0200", + "producer": "Sigma Designs, Inc.", + "product": "Aeotec Z-Stick Gen5 (ZW090) - UZB", + "rev": "0.00", + "vid": "0658", + }, + { + "cls": "ups", + "pid": "0002", + "producer": "American Power Conversion", + "product": "Uninterruptible Power Supply", + "rev": "1.06", + "vid": "051d", + }, + ], + }, + "success": True, +} + +DSM_6_CORE_SYSTEM_DS218_PLAY = { + "data": { + "cpu_clock_speed": 1400, + "cpu_cores": "4", + "cpu_family": "RTD1296", + "cpu_series": "SoC", + "cpu_vendor": "Realtek", + "enabled_ntp": True, + "firmware_date": "2020/07/14", + "firmware_ver": "DSM 6.2.3-25426 Update 2", + "model": "DS218play", + "ntp_server": "pool.ntp.org", + "ram_size": 1024, + "serial": "123456abcdefg", + "support_esata": "no", + "sys_temp": 40, + "sys_tempwarn": False, + "systempwarn": False, + "temperature_warning": False, + "time": "2020-10-16 20:26:58", + "time_zone": "Amsterdam", + "time_zone_desc": "(GMT+01:00) Amsterdam, Berlin, Rome, Stockholm, Vienna", + "up_time": "289:31:54", + "usb_dev": [ + { + "cls": "disk", + "pid": "2621", + "producer": "Western Digital Technologies, Inc.", + "product": "Elements 2621", + "rev": "10.26", + "vid": "1058", + } + ], + }, + "success": True, } diff --git a/tests/api_data/dsm_6/core/const_6_core_upgrade.py b/tests/api_data/dsm_6/core/const_6_core_upgrade.py index 8b393ed0..aaf83c60 100644 --- a/tests/api_data/dsm_6/core/const_6_core_upgrade.py +++ b/tests/api_data/dsm_6/core/const_6_core_upgrade.py @@ -1,10 +1,3 @@ """DSM 6 SYNO.Core.Upgrade data.""" -DSM_6_CORE_SYSTEM = { - "data":{ - "update":{ - "available":False - } - }, - "success":True -} +DSM_6_CORE_UPGRADE = {"data": {"update": {"available": False}}, "success": True} diff --git a/tests/test_synology_dsm.py b/tests/test_synology_dsm.py index 87071b24..78f0220a 100644 --- a/tests/test_synology_dsm.py +++ b/tests/test_synology_dsm.py @@ -19,7 +19,8 @@ SynologyDSMMock, VALID_HOST, VALID_PORT, - VALID_SSL, + VALID_HTTPS, + VALID_VERIFY_SSL, VALID_OTP, VALID_PASSWORD, VALID_USER, @@ -38,7 +39,12 @@ class TestSynologyDSM(TestCase): def setUp(self): self.api = SynologyDSMMock( - VALID_HOST, VALID_PORT, VALID_USER, VALID_PASSWORD, VALID_SSL + VALID_HOST, + VALID_PORT, + VALID_USER, + VALID_PASSWORD, + VALID_HTTPS, + VALID_VERIFY_SSL, ) def test_init(self): @@ -53,7 +59,12 @@ def test_connection_failed(self): """Test failed connection.""" # No internet api = SynologyDSMMock( - "no_internet", VALID_PORT, VALID_USER, VALID_PASSWORD, VALID_SSL + "no_internet", + VALID_PORT, + VALID_USER, + VALID_PASSWORD, + VALID_HTTPS, + VALID_VERIFY_SSL, ) with pytest.raises(SynologyDSMRequestException) as error: api.login() @@ -70,7 +81,14 @@ def test_connection_failed(self): assert not api._session_id # Wrong host - api = SynologyDSMMock("host", VALID_PORT, VALID_USER, VALID_PASSWORD, VALID_SSL) + api = SynologyDSMMock( + "host", + VALID_PORT, + VALID_USER, + VALID_PASSWORD, + VALID_HTTPS, + VALID_VERIFY_SSL, + ) with pytest.raises(SynologyDSMRequestException) as error: api.login() error_value = error.value.args[0] @@ -86,7 +104,9 @@ def test_connection_failed(self): assert not api._session_id # Wrong port - api = SynologyDSMMock(VALID_HOST, 0, VALID_USER, VALID_PASSWORD, VALID_SSL) + api = SynologyDSMMock( + VALID_HOST, 0, VALID_USER, VALID_PASSWORD, VALID_HTTPS, VALID_VERIFY_SSL + ) with pytest.raises(SynologyDSMRequestException) as error: api.login() error_value = error.value.args[0] @@ -101,8 +121,15 @@ def test_connection_failed(self): assert not api.apis.get(API_AUTH) assert not api._session_id - # Wrong SSL - api = SynologyDSMMock(VALID_HOST, VALID_PORT, VALID_USER, VALID_PASSWORD, False) + # Wrong HTTPS + api = SynologyDSMMock( + VALID_HOST, + VALID_PORT, + VALID_USER, + VALID_PASSWORD, + False, + VALID_VERIFY_SSL, + ) with pytest.raises(SynologyDSMRequestException) as error: api.login() error_value = error.value.args[0] @@ -114,6 +141,29 @@ def test_connection_failed(self): assert not api.apis.get(API_AUTH) assert not api._session_id + # Wrong SSL + api = SynologyDSMMock( + VALID_HOST, + VALID_PORT, + VALID_USER, + VALID_PASSWORD, + VALID_HTTPS, + False, + ) + with pytest.raises(SynologyDSMRequestException) as error: + api.login() + error_value = error.value.args[0] + assert not error_value["api"] + assert error_value["code"] == -1 + assert error_value["reason"] == "Unknown" + assert ( + error_value["details"] + == f"SSLError = hostname '192.168.0.35' doesn't match '{VALID_HOST}'" + ) + + assert not api.apis.get(API_AUTH) + assert not api._session_id + def test_login(self): """Test login.""" assert self.api.login() @@ -123,7 +173,14 @@ def test_login(self): def test_login_failed(self): """Test failed login.""" - api = SynologyDSMMock(VALID_HOST, VALID_PORT, "user", VALID_PASSWORD, VALID_SSL) + api = SynologyDSMMock( + VALID_HOST, + VALID_PORT, + "user", + VALID_PASSWORD, + VALID_HTTPS, + VALID_VERIFY_SSL, + ) with pytest.raises(SynologyDSMLoginInvalidException) as error: api.login() error_value = error.value.args[0] @@ -135,7 +192,14 @@ def test_login_failed(self): assert api.apis.get(API_AUTH) assert not api._session_id - api = SynologyDSMMock(VALID_HOST, VALID_PORT, VALID_USER, "pass", VALID_SSL) + api = SynologyDSMMock( + VALID_HOST, + VALID_PORT, + VALID_USER, + "pass", + VALID_HTTPS, + VALID_VERIFY_SSL, + ) with pytest.raises(SynologyDSMLoginInvalidException) as error: api.login() error_value = error.value.args[0] @@ -153,7 +217,12 @@ def test_login_failed(self): def test_login_2sa(self): """Test login with 2SA.""" api = SynologyDSMMock( - VALID_HOST, VALID_PORT, VALID_USER_2SA, VALID_PASSWORD, VALID_SSL + VALID_HOST, + VALID_PORT, + VALID_USER_2SA, + VALID_PASSWORD, + VALID_HTTPS, + VALID_VERIFY_SSL, ) with pytest.raises(SynologyDSMLogin2SARequiredException) as error: @@ -181,7 +250,8 @@ def test_login_2sa_new_session(self): VALID_PORT, VALID_USER_2SA, VALID_PASSWORD, - VALID_SSL, + VALID_HTTPS, + VALID_VERIFY_SSL, device_token=DEVICE_TOKEN, ) assert api.login() @@ -194,7 +264,12 @@ def test_login_2sa_new_session(self): def test_login_2sa_failed(self): """Test failed login with 2SA.""" api = SynologyDSMMock( - VALID_HOST, VALID_PORT, VALID_USER_2SA, VALID_PASSWORD, VALID_SSL + VALID_HOST, + VALID_PORT, + VALID_USER_2SA, + VALID_PASSWORD, + VALID_HTTPS, + VALID_VERIFY_SSL, ) with pytest.raises(SynologyDSMLogin2SARequiredException) as error: @@ -226,7 +301,12 @@ def test_login_2sa_failed(self): def test_login_basic_failed(self): """Test basic failed login.""" api = SynologyDSMMock( - VALID_HOST, VALID_PORT, USER_MAX_TRY, VALID_PASSWORD, VALID_SSL + VALID_HOST, + VALID_PORT, + USER_MAX_TRY, + VALID_PASSWORD, + VALID_HTTPS, + VALID_VERIFY_SSL, ) with pytest.raises(SynologyDSMLoginFailedException) as error: @@ -240,7 +320,13 @@ def test_login_basic_failed(self): def test_request_timeout(self): """Test request timeout.""" api = SynologyDSMMock( - VALID_HOST, VALID_PORT, VALID_USER, VALID_PASSWORD, VALID_SSL, timeout=2 + VALID_HOST, + VALID_PORT, + VALID_USER, + VALID_PASSWORD, + VALID_HTTPS, + VALID_VERIFY_SSL, + timeout=2, ) assert api._timeout == 2 @@ -428,6 +514,70 @@ def test_security_error(self): assert self.api.security.status_by_check["update"] == "outOfDate" assert self.api.security.status_by_check["userInfo"] == "safe" + def test_shares(self): + """Test shares.""" + assert self.api.share + self.api.share.update() + assert self.api.share.shares + for share_uuid in self.api.share.shares_uuids: + assert self.api.share.share_name(share_uuid) + assert self.api.share.share_path(share_uuid) + assert self.api.share.share_recycle_bin(share_uuid) is not None + assert self.api.share.share_size(share_uuid) is not None + assert self.api.share.share_size(share_uuid, human_readable=True) + + assert ( + self.api.share.share_name("2ee6c06a-8766-48b5-013d-63b18652a393") + == "test_share" + ) + assert ( + self.api.share.share_path("2ee6c06a-8766-48b5-013d-63b18652a393") + == "/volume1" + ) + assert ( + self.api.share.share_recycle_bin("2ee6c06a-8766-48b5-013d-63b18652a393") + is True + ) + assert ( + self.api.share.share_size("2ee6c06a-8766-48b5-013d-63b18652a393") + == 3.790251876432216e19 + ) + assert ( + self.api.share.share_size("2ee6c06a-8766-48b5-013d-63b18652a393", True) + == "32.9Eb" + ) + + def test_system(self): + """Test system.""" + assert self.api.system + self.api.system.update() + assert self.api.system.cpu_clock_speed + assert self.api.system.cpu_cores + assert self.api.system.cpu_family + assert self.api.system.cpu_series + assert self.api.system.firmware_ver + assert self.api.system.model + assert self.api.system.ram_size + assert self.api.system.serial + assert self.api.system.sys_temp + assert self.api.system.time + assert self.api.system.time_zone + assert self.api.system.time_zone_desc + assert self.api.system.up_time + for usb_dev in self.api.system.usb_dev: + assert usb_dev.get("cls") + assert usb_dev.get("pid") + assert usb_dev.get("producer") + assert usb_dev.get("product") + assert usb_dev.get("rev") + assert usb_dev.get("vid") + + def test_upgrade(self): + """Test upgrade.""" + assert self.api.upgrade + self.api.upgrade.update() + assert self.api.upgrade.update_available is False + def test_utilisation(self): """Test utilisation.""" assert self.api.utilisation @@ -763,36 +913,3 @@ def test_surveillance_station(self): assert self.api.surveillance_station.get_home_mode_status() assert self.api.surveillance_station.set_home_mode(False) assert self.api.surveillance_station.set_home_mode(True) - - def test_shares(self): - """Test shares.""" - assert self.api.share - self.api.share.update() - assert self.api.share.shares - for share_uuid in self.api.share.shares_uuids: - assert self.api.share.share_name(share_uuid) - assert self.api.share.share_path(share_uuid) - assert self.api.share.share_recycle_bin(share_uuid) is not None - assert self.api.share.share_size(share_uuid) is not None - assert self.api.share.share_size(share_uuid, human_readable=True) - - assert ( - self.api.share.share_name("2ee6c06a-8766-48b5-013d-63b18652a393") - == "test_share" - ) - assert ( - self.api.share.share_path("2ee6c06a-8766-48b5-013d-63b18652a393") - == "/volume1" - ) - assert ( - self.api.share.share_recycle_bin("2ee6c06a-8766-48b5-013d-63b18652a393") - is True - ) - assert ( - self.api.share.share_size("2ee6c06a-8766-48b5-013d-63b18652a393") - == 3.790251876432216e19 - ) - assert ( - self.api.share.share_size("2ee6c06a-8766-48b5-013d-63b18652a393", True) - == "32.9Eb" - ) diff --git a/tests/test_synology_dsm_5.py b/tests/test_synology_dsm_5.py index ee0577c7..b713b1fc 100644 --- a/tests/test_synology_dsm_5.py +++ b/tests/test_synology_dsm_5.py @@ -15,7 +15,8 @@ SynologyDSMMock, VALID_HOST, VALID_PORT, - VALID_SSL, + VALID_HTTPS, + VALID_VERIFY_SSL, VALID_OTP, VALID_PASSWORD, VALID_USER, @@ -31,7 +32,12 @@ class TestSynologyDSM(TestCase): def setUp(self): self.api = SynologyDSMMock( - VALID_HOST, VALID_PORT, VALID_USER, VALID_PASSWORD, VALID_SSL + VALID_HOST, + VALID_PORT, + VALID_USER, + VALID_PASSWORD, + VALID_HTTPS, + VALID_VERIFY_SSL, ) self.api.dsm_version = 5 @@ -45,7 +51,12 @@ def test_init(self): def test_connection_failed(self): """Test failed connection.""" api = SynologyDSMMock( - "no_internet", VALID_PORT, VALID_USER, VALID_PASSWORD, VALID_SSL + "no_internet", + VALID_PORT, + VALID_USER, + VALID_PASSWORD, + VALID_HTTPS, + VALID_VERIFY_SSL, ) api.dsm_version = 5 with self.assertRaises(SynologyDSMRequestException): @@ -53,21 +64,37 @@ def test_connection_failed(self): assert not api.apis.get(API_AUTH) assert not api._session_id - api = SynologyDSMMock("host", VALID_PORT, VALID_USER, VALID_PASSWORD, VALID_SSL) + api = SynologyDSMMock( + "host", + VALID_PORT, + VALID_USER, + VALID_PASSWORD, + VALID_HTTPS, + VALID_VERIFY_SSL, + ) api.dsm_version = 5 with self.assertRaises(SynologyDSMRequestException): assert not api.login() assert not api.apis.get(API_AUTH) assert not api._session_id - api = SynologyDSMMock(VALID_HOST, 0, VALID_USER, VALID_PASSWORD, VALID_SSL) + api = SynologyDSMMock( + VALID_HOST, 0, VALID_USER, VALID_PASSWORD, VALID_HTTPS, VALID_VERIFY_SSL + ) api.dsm_version = 5 with self.assertRaises(SynologyDSMRequestException): assert not api.login() assert not api.apis.get(API_AUTH) assert not api._session_id - api = SynologyDSMMock(VALID_HOST, VALID_PORT, VALID_USER, VALID_PASSWORD, False) + api = SynologyDSMMock( + VALID_HOST, + VALID_PORT, + VALID_USER, + VALID_PASSWORD, + False, + VALID_VERIFY_SSL, + ) api.dsm_version = 5 with self.assertRaises(SynologyDSMRequestException): assert not api.login() @@ -83,14 +110,28 @@ def test_login(self): def test_login_failed(self): """Test failed login.""" - api = SynologyDSMMock(VALID_HOST, VALID_PORT, "user", VALID_PASSWORD, VALID_SSL) + api = SynologyDSMMock( + VALID_HOST, + VALID_PORT, + "user", + VALID_PASSWORD, + VALID_HTTPS, + VALID_VERIFY_SSL, + ) api.dsm_version = 5 with self.assertRaises(SynologyDSMLoginInvalidException): assert not api.login() assert api.apis.get(API_AUTH) assert not api._session_id - api = SynologyDSMMock(VALID_HOST, VALID_PORT, VALID_USER, "pass", VALID_SSL) + api = SynologyDSMMock( + VALID_HOST, + VALID_PORT, + VALID_USER, + "pass", + VALID_HTTPS, + VALID_VERIFY_SSL, + ) api.dsm_version = 5 with self.assertRaises(SynologyDSMLoginInvalidException): assert not api.login() @@ -100,7 +141,12 @@ def test_login_failed(self): def test_login_2sa(self): """Test login with 2SA.""" api = SynologyDSMMock( - VALID_HOST, VALID_PORT, VALID_USER_2SA, VALID_PASSWORD, VALID_SSL + VALID_HOST, + VALID_PORT, + VALID_USER_2SA, + VALID_PASSWORD, + VALID_HTTPS, + VALID_VERIFY_SSL, ) api.dsm_version = 5 with self.assertRaises(SynologyDSMLogin2SARequiredException): @@ -119,7 +165,8 @@ def test_login_2sa_new_session(self): VALID_PORT, VALID_USER_2SA, VALID_PASSWORD, - VALID_SSL, + VALID_HTTPS, + VALID_VERIFY_SSL, device_token=DEVICE_TOKEN, ) api.dsm_version = 5 @@ -133,7 +180,12 @@ def test_login_2sa_new_session(self): def test_login_2sa_failed(self): """Test failed login with 2SA.""" api = SynologyDSMMock( - VALID_HOST, VALID_PORT, VALID_USER_2SA, VALID_PASSWORD, VALID_SSL + VALID_HOST, + VALID_PORT, + VALID_USER_2SA, + VALID_PASSWORD, + VALID_HTTPS, + VALID_VERIFY_SSL, ) api.dsm_version = 5 with self.assertRaises(SynologyDSMLogin2SARequiredException): From 3afe021a4783d4645eece77c729abfa01e3cbe0a Mon Sep 17 00:00:00 2001 From: Oncleben31 Date: Tue, 20 Oct 2020 00:31:59 +0200 Subject: [PATCH 02/33] Move python file in src folder (#77) Preparation of migration to cookiecutter-hypermodern-python template --- .travis.yml | 2 +- setup.py | 3 ++- {synology_dsm => src/synology_dsm}/__init__.py | 0 {synology_dsm => src/synology_dsm}/api/__init__.py | 0 {synology_dsm => src/synology_dsm}/api/core/__init__.py | 0 {synology_dsm => src/synology_dsm}/api/core/security.py | 0 {synology_dsm => src/synology_dsm}/api/core/share.py | 0 {synology_dsm => src/synology_dsm}/api/core/system.py | 0 {synology_dsm => src/synology_dsm}/api/core/upgrade.py | 0 {synology_dsm => src/synology_dsm}/api/core/utilization.py | 0 .../synology_dsm}/api/download_station/__init__.py | 0 .../synology_dsm}/api/download_station/task.py | 0 {synology_dsm => src/synology_dsm}/api/dsm/__init__.py | 0 {synology_dsm => src/synology_dsm}/api/dsm/information.py | 0 {synology_dsm => src/synology_dsm}/api/dsm/network.py | 0 {synology_dsm => src/synology_dsm}/api/storage/__init__.py | 0 {synology_dsm => src/synology_dsm}/api/storage/storage.py | 0 .../synology_dsm}/api/surveillance_station/__init__.py | 0 .../synology_dsm}/api/surveillance_station/camera.py | 0 .../synology_dsm}/api/surveillance_station/const.py | 0 {synology_dsm => src/synology_dsm}/const.py | 0 {synology_dsm => src/synology_dsm}/exceptions.py | 0 {synology_dsm => src/synology_dsm}/helpers.py | 0 {synology_dsm => src/synology_dsm}/synology_dsm.py | 0 24 files changed, 3 insertions(+), 2 deletions(-) rename {synology_dsm => src/synology_dsm}/__init__.py (100%) rename {synology_dsm => src/synology_dsm}/api/__init__.py (100%) rename {synology_dsm => src/synology_dsm}/api/core/__init__.py (100%) rename {synology_dsm => src/synology_dsm}/api/core/security.py (100%) rename {synology_dsm => src/synology_dsm}/api/core/share.py (100%) rename {synology_dsm => src/synology_dsm}/api/core/system.py (100%) rename {synology_dsm => src/synology_dsm}/api/core/upgrade.py (100%) rename {synology_dsm => src/synology_dsm}/api/core/utilization.py (100%) rename {synology_dsm => src/synology_dsm}/api/download_station/__init__.py (100%) rename {synology_dsm => src/synology_dsm}/api/download_station/task.py (100%) rename {synology_dsm => src/synology_dsm}/api/dsm/__init__.py (100%) rename {synology_dsm => src/synology_dsm}/api/dsm/information.py (100%) rename {synology_dsm => src/synology_dsm}/api/dsm/network.py (100%) rename {synology_dsm => src/synology_dsm}/api/storage/__init__.py (100%) rename {synology_dsm => src/synology_dsm}/api/storage/storage.py (100%) rename {synology_dsm => src/synology_dsm}/api/surveillance_station/__init__.py (100%) rename {synology_dsm => src/synology_dsm}/api/surveillance_station/camera.py (100%) rename {synology_dsm => src/synology_dsm}/api/surveillance_station/const.py (100%) rename {synology_dsm => src/synology_dsm}/const.py (100%) rename {synology_dsm => src/synology_dsm}/exceptions.py (100%) rename {synology_dsm => src/synology_dsm}/helpers.py (100%) rename {synology_dsm => src/synology_dsm}/synology_dsm.py (100%) diff --git a/.travis.yml b/.travis.yml index c1a73ea7..5181e48a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,7 @@ install: - python setup.py install - python setup.py sdist before_script: - - pylint synology_dsm tests + - pylint src tests - black --check --fast . script: - py.test diff --git a/setup.py b/setup.py index 5f5a3411..c0df8fbc 100644 --- a/setup.py +++ b/setup.py @@ -25,7 +25,8 @@ description="Python API for communication with Synology DSM", long_description=long_description, author="Quentin POLLET (Quentame) & FG van Zeelst (ProtoThis)", - packages=find_packages(include=["synology_dsm*"]), + packages=find_packages("src"), + package_dir={"": "src"}, install_requires=required, python_requires=">=3.6", license="MIT", diff --git a/synology_dsm/__init__.py b/src/synology_dsm/__init__.py similarity index 100% rename from synology_dsm/__init__.py rename to src/synology_dsm/__init__.py diff --git a/synology_dsm/api/__init__.py b/src/synology_dsm/api/__init__.py similarity index 100% rename from synology_dsm/api/__init__.py rename to src/synology_dsm/api/__init__.py diff --git a/synology_dsm/api/core/__init__.py b/src/synology_dsm/api/core/__init__.py similarity index 100% rename from synology_dsm/api/core/__init__.py rename to src/synology_dsm/api/core/__init__.py diff --git a/synology_dsm/api/core/security.py b/src/synology_dsm/api/core/security.py similarity index 100% rename from synology_dsm/api/core/security.py rename to src/synology_dsm/api/core/security.py diff --git a/synology_dsm/api/core/share.py b/src/synology_dsm/api/core/share.py similarity index 100% rename from synology_dsm/api/core/share.py rename to src/synology_dsm/api/core/share.py diff --git a/synology_dsm/api/core/system.py b/src/synology_dsm/api/core/system.py similarity index 100% rename from synology_dsm/api/core/system.py rename to src/synology_dsm/api/core/system.py diff --git a/synology_dsm/api/core/upgrade.py b/src/synology_dsm/api/core/upgrade.py similarity index 100% rename from synology_dsm/api/core/upgrade.py rename to src/synology_dsm/api/core/upgrade.py diff --git a/synology_dsm/api/core/utilization.py b/src/synology_dsm/api/core/utilization.py similarity index 100% rename from synology_dsm/api/core/utilization.py rename to src/synology_dsm/api/core/utilization.py diff --git a/synology_dsm/api/download_station/__init__.py b/src/synology_dsm/api/download_station/__init__.py similarity index 100% rename from synology_dsm/api/download_station/__init__.py rename to src/synology_dsm/api/download_station/__init__.py diff --git a/synology_dsm/api/download_station/task.py b/src/synology_dsm/api/download_station/task.py similarity index 100% rename from synology_dsm/api/download_station/task.py rename to src/synology_dsm/api/download_station/task.py diff --git a/synology_dsm/api/dsm/__init__.py b/src/synology_dsm/api/dsm/__init__.py similarity index 100% rename from synology_dsm/api/dsm/__init__.py rename to src/synology_dsm/api/dsm/__init__.py diff --git a/synology_dsm/api/dsm/information.py b/src/synology_dsm/api/dsm/information.py similarity index 100% rename from synology_dsm/api/dsm/information.py rename to src/synology_dsm/api/dsm/information.py diff --git a/synology_dsm/api/dsm/network.py b/src/synology_dsm/api/dsm/network.py similarity index 100% rename from synology_dsm/api/dsm/network.py rename to src/synology_dsm/api/dsm/network.py diff --git a/synology_dsm/api/storage/__init__.py b/src/synology_dsm/api/storage/__init__.py similarity index 100% rename from synology_dsm/api/storage/__init__.py rename to src/synology_dsm/api/storage/__init__.py diff --git a/synology_dsm/api/storage/storage.py b/src/synology_dsm/api/storage/storage.py similarity index 100% rename from synology_dsm/api/storage/storage.py rename to src/synology_dsm/api/storage/storage.py diff --git a/synology_dsm/api/surveillance_station/__init__.py b/src/synology_dsm/api/surveillance_station/__init__.py similarity index 100% rename from synology_dsm/api/surveillance_station/__init__.py rename to src/synology_dsm/api/surveillance_station/__init__.py diff --git a/synology_dsm/api/surveillance_station/camera.py b/src/synology_dsm/api/surveillance_station/camera.py similarity index 100% rename from synology_dsm/api/surveillance_station/camera.py rename to src/synology_dsm/api/surveillance_station/camera.py diff --git a/synology_dsm/api/surveillance_station/const.py b/src/synology_dsm/api/surveillance_station/const.py similarity index 100% rename from synology_dsm/api/surveillance_station/const.py rename to src/synology_dsm/api/surveillance_station/const.py diff --git a/synology_dsm/const.py b/src/synology_dsm/const.py similarity index 100% rename from synology_dsm/const.py rename to src/synology_dsm/const.py diff --git a/synology_dsm/exceptions.py b/src/synology_dsm/exceptions.py similarity index 100% rename from synology_dsm/exceptions.py rename to src/synology_dsm/exceptions.py diff --git a/synology_dsm/helpers.py b/src/synology_dsm/helpers.py similarity index 100% rename from synology_dsm/helpers.py rename to src/synology_dsm/helpers.py diff --git a/synology_dsm/synology_dsm.py b/src/synology_dsm/synology_dsm.py similarity index 100% rename from synology_dsm/synology_dsm.py rename to src/synology_dsm/synology_dsm.py From 7dda68113511697c9897324c5f9fda84954efc68 Mon Sep 17 00:00:00 2001 From: Quentame Date: Tue, 20 Oct 2020 23:40:57 +0200 Subject: [PATCH 03/33] Add logout method (#79) --- src/synology_dsm/synology_dsm.py | 10 ++++++++-- tests/api_data/dsm_6/const_6_api_auth.py | 2 ++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/synology_dsm/synology_dsm.py b/src/synology_dsm/synology_dsm.py index 81299fbf..163cb208 100644 --- a/src/synology_dsm/synology_dsm.py +++ b/src/synology_dsm/synology_dsm.py @@ -124,7 +124,7 @@ def apis(self): """Gets available API infos from the NAS.""" return self._apis - def login(self, otp_code: str = None): + def login(self, otp_code: str = None) -> bool: """Create a logged session.""" # First reset the session self._debuglog("Creating new session") @@ -176,7 +176,13 @@ def login(self, otp_code: str = None): self._information = SynoDSMInformation(self) self._information.update() - return True + return result["success"] + + def logout(self) -> bool: + """Log out of the session.""" + result = self.get(API_AUTH, "logout") + self._session = None + return result["success"] @property def device_token(self) -> str: diff --git a/tests/api_data/dsm_6/const_6_api_auth.py b/tests/api_data/dsm_6/const_6_api_auth.py index 13c6ff06..ab642ba0 100644 --- a/tests/api_data/dsm_6/const_6_api_auth.py +++ b/tests/api_data/dsm_6/const_6_api_auth.py @@ -21,3 +21,5 @@ }, "success": True, } + +DSM_6_AUTH_LOGOUT = {"success": True} From d5c3da21f1bfb84c0df7f7ae3d1153f0c669b222 Mon Sep 17 00:00:00 2001 From: Quentin POLLET Date: Wed, 21 Oct 2020 13:40:23 +0200 Subject: [PATCH 04/33] Release 1.0.0 --- scripts/clean.sh | 1 + scripts/publish.sh | 1 + setup.py | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/clean.sh b/scripts/clean.sh index 4c4325e1..f5ee09e8 100755 --- a/scripts/clean.sh +++ b/scripts/clean.sh @@ -5,3 +5,4 @@ rm -r .tox rm -r build rm -r dist rm -r python_synology.egg-info +rm -r src/python_synology.egg-info diff --git a/scripts/publish.sh b/scripts/publish.sh index c0f3ff51..7e370c81 100755 --- a/scripts/publish.sh +++ b/scripts/publish.sh @@ -14,5 +14,6 @@ python3 setup.py sdist bdist_wheel # Push to PyPi python3 -m twine upload dist/* +# python3 -m twine upload --repository testpypi dist/* # Enter credentials manually :P diff --git a/setup.py b/setup.py index c0df8fbc..64483b39 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ from setuptools import setup, find_packages REPO_URL = "https://github.com/ProtoThis/python-synology" -VERSION = "0.9.0" +VERSION = "1.0.0" with open("requirements.txt") as f: required = f.read().splitlines() From f90d14938f29651b085fdfe5129cee6951b64303 Mon Sep 17 00:00:00 2001 From: Oncleben31 Date: Wed, 21 Oct 2020 21:38:25 +0200 Subject: [PATCH 05/33] Migrate to poetry, nox and GitHub actions (#78) * Replace setup files with pyproject.toml Now we can use poetry to manage the package. poetry install to install the package in a venv poetry run ... to launch pylint, pytest or black * Add CI with GitHub Action Add a tests and release workflow Add release drafter Add dependabot * Remove old CI based on travis and pylint * Add linting configuration files Linting mainly based on flake8 and plugins. Add specific files for darglint and mypy. * Update .gitignore * Add test suite with nox and pre-commit Test suite inculde pre-commit, safety, mypy, tests, typguard and documentation checks. * Add .gitattributes * Update code coverage target to 80% * Code style update by Black * Update poetry lock file * Deactivate temporarly some linting tests * Add a contributing guide * Remove Python 3.6 in GitHub Action * Patch noxfile.py to be able to test mypy session * Rebase version to 1.0.0 --- .darglint | 2 + .flake8 | 12 + .gitattributes | 1 + .github/dependabot.yml | 18 + .github/release-drafter.yml | 29 + .github/workflows/constraints.txt | 5 + .github/workflows/release.yml | 79 + .github/workflows/tests.yml | 140 ++ .gitignore | 14 + .pre-commit-config.yaml | 51 + .travis.yml | 38 - CONTRIBUTING.rst | 121 ++ LICENSE.txt | 2 +- codecov.yml | 9 + mypy.ini | 20 + noxfile.py | 188 +++ poetry.lock | 1494 +++++++++++++++++ pylintrc | 43 - pyproject.toml | 97 +- requirements.txt | 3 - requirements_all.txt | 2 - requirements_test.txt | 4 - setup.cfg | 3 - setup.py | 48 - src/synology_dsm/api/storage/storage.py | 1 - .../api/surveillance_station/__init__.py | 3 +- .../api/surveillance_station/camera.py | 3 +- src/synology_dsm/const.py | 1 - src/synology_dsm/exceptions.py | 28 +- src/synology_dsm/synology_dsm.py | 28 +- tests/__init__.py | 106 +- tests/api_data/dsm_5/__init__.py | 8 +- tests/api_data/dsm_5/const_5_api_auth.py | 8 +- tests/api_data/dsm_6/__init__.py | 56 +- tests/api_data/dsm_6/const_6_api_auth.py | 10 +- tests/const.py | 1 - tests/test_synology_dsm.py | 47 +- tests/test_synology_dsm_5.py | 41 +- 38 files changed, 2438 insertions(+), 326 deletions(-) create mode 100644 .darglint create mode 100644 .flake8 create mode 100644 .gitattributes create mode 100644 .github/dependabot.yml create mode 100644 .github/release-drafter.yml create mode 100644 .github/workflows/constraints.txt create mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/tests.yml create mode 100644 .pre-commit-config.yaml delete mode 100644 .travis.yml create mode 100644 CONTRIBUTING.rst create mode 100644 codecov.yml create mode 100644 mypy.ini create mode 100644 noxfile.py create mode 100644 poetry.lock delete mode 100644 pylintrc delete mode 100644 requirements.txt delete mode 100644 requirements_all.txt delete mode 100644 requirements_test.txt delete mode 100644 setup.cfg delete mode 100644 setup.py diff --git a/.darglint b/.darglint new file mode 100644 index 00000000..2b03755a --- /dev/null +++ b/.darglint @@ -0,0 +1,2 @@ +[darglint] +strictness = short diff --git a/.flake8 b/.flake8 new file mode 100644 index 00000000..00bd25b2 --- /dev/null +++ b/.flake8 @@ -0,0 +1,12 @@ +[flake8] +select = B,B9,C,DAR,E,F,N,RST,S,W +# Some tests have been added to the ignore list to avoid reworking too much +# the code in this PR: D107, D403, B950, E266, C901, F401, E302. +# The error will be processed in a dedicated PR. +# targeted ignore list is: +# ignore = E203,E501,RST201,RST203,RST301,W503 +ignore = E203,E501,RST201,RST203,RST301,W503, D107, D403, B950, E266, C901, F401, E302 +max-line-length = 80 +max-complexity = 10 +docstring-convention = google +per-file-ignores = tests/*:S101 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..6313b56c --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..a0a5c735 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,18 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: "/" + schedule: + interval: daily + - package-ecosystem: pip + directory: "/.github/workflows" + schedule: + interval: daily + - package-ecosystem: pip + directory: "/docs" + schedule: + interval: daily + - package-ecosystem: pip + directory: "/" + schedule: + interval: daily diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml new file mode 100644 index 00000000..7a04410f --- /dev/null +++ b/.github/release-drafter.yml @@ -0,0 +1,29 @@ +categories: + - title: ":boom: Breaking Changes" + label: "breaking" + - title: ":rocket: Features" + label: "enhancement" + - title: ":fire: Removals and Deprecations" + label: "removal" + - title: ":beetle: Fixes" + label: "bug" + - title: ":racehorse: Performance" + label: "performance" + - title: ":rotating_light: Testing" + label: "testing" + - title: ":construction_worker: Continuous Integration" + label: "ci" + - title: ":books: Documentation" + label: "documentation" + - title: ":hammer: Refactoring" + label: "refactoring" + - title: ":lipstick: Style" + label: "style" + - title: ":package: Dependencies" + labels: + - "dependencies" + - "build" +template: | + ## Changes + + $CHANGES diff --git a/.github/workflows/constraints.txt b/.github/workflows/constraints.txt new file mode 100644 index 00000000..2937ef31 --- /dev/null +++ b/.github/workflows/constraints.txt @@ -0,0 +1,5 @@ +pip==20.2.4 +nox==2020.8.22 +nox-poetry==0.5.0 +poetry==1.0.10 +virtualenv==20.0.35 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..c325f77b --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,79 @@ +name: Release + +on: + push: + branches: + - main + - master + +jobs: + release: + name: Release + runs-on: ubuntu-latest + steps: + - name: Check out the repository + uses: actions/checkout@v2.3.3 + with: + fetch-depth: 2 + + - name: Set up Python + uses: actions/setup-python@v2.1.4 + with: + python-version: "3.9" + + - name: Upgrade pip + run: | + pip install --constraint=.github/workflows/constraints.txt pip + pip --version + + - name: Install Poetry + run: | + pip install --constraint=.github/workflows/constraints.txt poetry + poetry --version + + - name: Check if there is a parent commit + id: check-parent-commit + run: | + echo "::set-output name=sha::$(git rev-parse --verify --quiet HEAD^)" + + - name: Detect and tag new version + id: check-version + if: steps.check-parent-commit.outputs.sha + uses: salsify/action-detect-and-tag-new-version@v2.0.1 + with: + version-command: | + bash -o pipefail -c "poetry version | awk '{ print \$2 }'" + + - name: Bump version for developmental release + if: "! steps.check-version.outputs.tag" + run: | + poetry version patch && + version=$(poetry version | awk '{ print $2 }') && + poetry version $version.dev.$(date +%s) + + - name: Build package + run: | + poetry build --ansi + + - name: Publish package on PyPI + if: steps.check-version.outputs.tag + uses: pypa/gh-action-pypi-publish@v1.4.1 + with: + user: __token__ + password: ${{ secrets.PYPI_TOKEN }} + + - name: Publish package on TestPyPI + if: "! steps.check-version.outputs.tag" + uses: pypa/gh-action-pypi-publish@v1.4.1 + with: + user: __token__ + password: ${{ secrets.TEST_PYPI_TOKEN }} + repository_url: https://test.pypi.org/legacy/ + + - name: Publish release notes + uses: release-drafter/release-drafter@v5.12.0 + with: + publish: ${{ steps.check-version.outputs.tag != '' }} + tag: ${{ steps.check-version.outputs.tag }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 00000000..bda431b9 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,140 @@ +name: Tests + +on: + - push + - pull_request + +jobs: + tests: + name: ${{ matrix.session }} ${{ matrix.python-version }} / ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + # Commented session will be activated in the future + - { python-version: 3.9, os: ubuntu-latest, session: "pre-commit" } + - { python-version: 3.9, os: ubuntu-latest, session: "safety" } + # - { python-version: 3.9, os: ubuntu-latest, session: "mypy" } + # - { python-version: 3.8, os: ubuntu-latest, session: "mypy" } + # - { python-version: 3.7, os: ubuntu-latest, session: "mypy" } + - { python-version: 3.9, os: ubuntu-latest, session: "tests" } + - { python-version: 3.8, os: ubuntu-latest, session: "tests" } + - { python-version: 3.7, os: ubuntu-latest, session: "tests" } + - { python-version: 3.9, os: windows-latest, session: "tests" } + - { python-version: 3.9, os: macos-latest, session: "tests" } + # - { python-version: 3.9, os: ubuntu-latest, session: "typeguard" } + # - { python-version: 3.9, os: ubuntu-latest, session: "xdoctest" } + # - { python-version: 3.8, os: ubuntu-latest, session: "docs-build" } + + env: + NOXSESSION: ${{ matrix.session }} + + steps: + - name: Check out the repository + uses: actions/checkout@v2.3.3 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2.1.4 + with: + python-version: ${{ matrix.python-version }} + + - name: Upgrade pip + run: | + pip install --constraint=.github/workflows/constraints.txt pip + pip --version + + - name: Install Poetry + run: | + pip install --constraint=.github/workflows/constraints.txt poetry + poetry --version + + - name: Install Nox + run: | + pip install --constraint=.github/workflows/constraints.txt nox nox-poetry + nox --version + + - name: Compute pre-commit cache key + if: matrix.session == 'pre-commit' + id: pre-commit-cache + shell: python + run: | + import hashlib + import sys + + python = "py{}.{}".format(*sys.version_info[:2]) + payload = sys.version.encode() + sys.executable.encode() + digest = hashlib.sha256(payload).hexdigest() + result = "${{ runner.os }}-{}-{}-pre-commit".format(python, digest[:8]) + + print("::set-output name=result::{}".format(result)) + + - name: Restore pre-commit cache + uses: actions/cache@v2.1.2 + if: matrix.session == 'pre-commit' + with: + path: ~/.cache/pre-commit + key: ${{ steps.pre-commit-cache.outputs.result }}-${{ hashFiles('.pre-commit-config.yaml') }} + restore-keys: | + ${{ steps.pre-commit-cache.outputs.result }}- + + - name: Run Nox + run: | + nox --force-color --python=${{ matrix.python-version }} + + - name: Upload coverage data + if: always() && matrix.session == 'tests' + uses: "actions/upload-artifact@v2.2.0" + with: + name: coverage-data + path: ".coverage.*" + + - name: Upload documentation + if: matrix.session == 'docs-build' + uses: actions/upload-artifact@v2.2.0 + with: + name: docs + path: docs/_build + + coverage: + runs-on: ubuntu-latest + needs: tests + steps: + - name: Check out the repository + uses: actions/checkout@v2.3.2 + + - name: Set up Python 3.9 + uses: actions/setup-python@v2.1.4 + with: + python-version: 3.9 + + - name: Upgrade pip + run: | + pip install --constraint=.github/workflows/constraints.txt pip + pip --version + + - name: Install Poetry + run: | + pip install --constraint=.github/workflows/constraints.txt poetry + poetry --version + + - name: Install Nox + run: | + pip install --constraint=.github/workflows/constraints.txt nox nox-poetry + nox --version + + - name: Download coverage data + uses: actions/download-artifact@v2.0.5 + with: + name: coverage-data + + - name: Combine coverage data and display human readable report + run: | + nox --force-color --session=coverage + + - name: Create coverage report + run: | + nox --force-color --session=coverage -- xml + + - name: Upload coverage report + uses: codecov/codecov-action@v1.0.14 diff --git a/.gitignore b/.gitignore index f2ec26cd..d62b0712 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,17 @@ +# From cookiecutter-hypermodern-python +.mypy_cache/ +/.coverage +/.nox/ +/.python-version +/.pytype/ +/dist/ +/docs/_build/ +/src/*.egg-info/ +__pycache__/ + +# Following are kept for not anoying current developers. Could be remove in +# a future package release. + # Python *.py[cod] diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..b6652b19 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,51 @@ +repos: + - repo: local + hooks: + - id: black + name: black + entry: black + language: system + types: [python] + require_serial: true + - id: check-added-large-files + name: Check for added large files + entry: check-added-large-files + language: system + - id: check-toml + name: Check Toml + entry: check-toml + language: system + types: [toml] + - id: check-yaml + name: Check Yaml + entry: check-yaml + language: system + types: [yaml] + - id: end-of-file-fixer + name: Fix End of Files + entry: end-of-file-fixer + language: system + types: [text] + stages: [commit, push, manual] + - id: flake8 + name: flake8 + entry: flake8 + language: system + types: [python] + require_serial: true + - id: reorder-python-imports + name: Reorder python imports + entry: reorder-python-imports + language: system + types: [python] + args: [--application-directories=src] + - id: trailing-whitespace + name: Trim Trailing Whitespace + entry: trailing-whitespace-fixer + language: system + types: [text] + stages: [commit, push, manual] + - repo: https://github.com/prettier/prettier + rev: 2.1.2 + hooks: + - id: prettier diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 5181e48a..00000000 --- a/.travis.yml +++ /dev/null @@ -1,38 +0,0 @@ -os: linux -dist: xenial - -language: python -python: - - 3.6 - - 3.7 - - 3.8 -cache: - pip: true - -before_install: - - pip install -r requirements_all.txt - - pip install -e . -install: - - python setup.py install - - python setup.py sdist -before_script: - - pylint src tests - - black --check --fast . -script: - - py.test - -deploy: - - provider: pypi - user: $pypi_test_user - password: $pypi_test_pass - server: $pypi_test - on: - branch: deploy-test - python: 3.8 - - provider: pypi - user: $pypi_user - password: $pypi_pass - server: $pypi - on: - branch: deploy - python: 3.8 diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst new file mode 100644 index 00000000..a91139bb --- /dev/null +++ b/CONTRIBUTING.rst @@ -0,0 +1,121 @@ +Contributor Guide +================= + +Thank you for your interest in improving this project. +This project is open-source under the `MIT license`_ and +welcomes contributions in the form of bug reports, feature requests, and pull requests. + +Here is a list of important resources for contributors: + +- `Source Code`_ +- `Documentation`_ +- `Issue Tracker`_ +- `Code of Conduct`_ + +.. _MIT license: https://opensource.org/licenses/MIT +.. _Source Code: https://github.com/ProtoThis/python-synology +.. _Documentation: https://python-synology.readthedocs.io/ +.. _Issue Tracker: https://github.com/ProtoThis/python-synology/issues + +How to report a bug +------------------- + +Report bugs on the `Issue Tracker`_. + +When filing an issue, make sure to answer these questions: + +- Which operating system and Python version are you using? +- Which version of this project are you using? +- What did you do? +- What did you expect to see? +- What did you see instead? + +The best way to get your bug fixed is to provide a test case, +and/or steps to reproduce the issue. + + +How to request a feature +------------------------ + +Request features on the `Issue Tracker`_. + + +How to set up your development environment +------------------------------------------ + +You need Python 3.6+ and the following tools: + +- Poetry_ +- Nox_ +- nox-poetry_ + +Install the package with development requirements: + +.. code:: console + + $ poetry install + +You can now run an interactive Python session: + +.. code:: console + + $ poetry run python + +.. _Poetry: https://python-poetry.org/ +.. _Nox: https://nox.thea.codes/ +.. _nox-poetry: https://nox-poetry.readthedocs.io/ + + +How to test the project +----------------------- + +Run the full test suite: + +.. code:: console + + $ nox + +List the available Nox sessions: + +.. code:: console + + $ nox --list-sessions + +You can also run a specific Nox session. +For example, invoke the unit test suite like this: + +.. code:: console + + $ nox --session=tests + +Unit tests are located in the ``tests`` directory, +and are written using the pytest_ testing framework. + +.. _pytest: https://pytest.readthedocs.io/ + + +How to submit changes +--------------------- + +Open a `pull request`_ to submit changes to this project. + +Your pull request needs to meet the following guidelines for acceptance: + +- The Nox test suite must pass without errors and warnings. +- Include unit tests. This project maintains 100% code coverage. +- If your changes add functionality, update the documentation accordingly. + +Feel free to submit early, though—we can always iterate on this. + +To run linting and code formatting checks before commiting your change, you can install pre-commit as a Git hook by running the following command: + +.. code:: console + + $ nox --session=pre-commit -- install + +It is recommended to open an issue before starting work on anything. +This will allow a chance to talk it over with the owners and validate your approach. + +.. _pull request: https://github.com/ProtoThis/python-synology/pulls +.. github-only +.. _Code of Conduct: CODE_OF_CONDUCT.rst diff --git a/LICENSE.txt b/LICENSE.txt index cc44b79e..a45cf81c 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -5,4 +5,4 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 00000000..d3f978c9 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,9 @@ +comment: false +coverage: + status: + project: + default: + target: "80" + patch: + default: + target: "100" diff --git a/mypy.ini b/mypy.ini new file mode 100644 index 00000000..4f2123c9 --- /dev/null +++ b/mypy.ini @@ -0,0 +1,20 @@ +[mypy] +check_untyped_defs = True +disallow_any_generics = True +disallow_incomplete_defs = True +disallow_subclassing_any = True +disallow_untyped_calls = True +disallow_untyped_decorators = True +disallow_untyped_defs = True +no_implicit_optional = True +no_implicit_reexport = True +pretty = True +show_column_numbers = True +show_error_codes = True +show_error_context = True +strict_equality = True +warn_redundant_casts = True +warn_return_any = True +warn_unreachable = True +warn_unused_configs = True +warn_unused_ignores = True diff --git a/noxfile.py b/noxfile.py new file mode 100644 index 00000000..7b6894e9 --- /dev/null +++ b/noxfile.py @@ -0,0 +1,188 @@ +"""Nox sessions.""" +import shutil +import sys +from pathlib import Path +from textwrap import dedent + +import nox +import nox_poetry.patch +from nox.sessions import Session + + +package = "synology_dsm" +python_versions = ["3.9", "3.8", "3.7"] +# Comment some sessions as they need to work on the code to not fail. +# Will be activated in future release. +nox.options.sessions = ( + "pre-commit", + "safety", + # "mypy", + "tests", + # "typeguard", + # "xdoctest", + # "docs-build", +) + + +def activate_virtualenv_in_precommit_hooks(session: Session) -> None: + """Activate virtualenv in hooks installed by pre-commit. + + This function patches git hooks installed by pre-commit to activate the + session's virtual environment. This allows pre-commit to locate hooks in + that environment when invoked from git. + + Args: + session: The Session object. + """ + if session.bin is None: + return + + virtualenv = session.env.get("VIRTUAL_ENV") + if virtualenv is None: + return + + hookdir = Path(".git") / "hooks" + if not hookdir.is_dir(): + return + + for hook in hookdir.iterdir(): + if hook.name.endswith(".sample") or not hook.is_file(): + continue + + text = hook.read_text() + bindir = repr(session.bin)[1:-1] # strip quotes + if not ( + Path("A") == Path("a") and bindir.lower() in text.lower() or bindir in text + ): + continue + + lines = text.splitlines() + if not (lines[0].startswith("#!") and "python" in lines[0].lower()): + continue + + header = dedent( + f"""\ + import os + os.environ["VIRTUAL_ENV"] = {virtualenv!r} + os.environ["PATH"] = os.pathsep.join(( + {session.bin!r}, + os.environ.get("PATH", ""), + )) + """ + ) + + lines.insert(1, header) + hook.write_text("\n".join(lines)) + + +@nox.session(name="pre-commit", python="3.9") +def precommit(session: Session) -> None: + """Lint using pre-commit.""" + args = session.posargs or ["run", "--all-files", "--show-diff-on-failure"] + session.install( + "black", + "darglint", + "flake8", + "flake8-bandit", + "flake8-bugbear", + "flake8-docstrings", + "flake8-rst-docstrings", + "pep8-naming", + "pre-commit", + "pre-commit-hooks", + "reorder-python-imports", + ) + session.run("pre-commit", *args) + if args and args[0] == "install": + activate_virtualenv_in_precommit_hooks(session) + + +@nox.session(python="3.9") +def safety(session: Session) -> None: + """Scan dependencies for insecure packages.""" + requirements = nox_poetry.export_requirements(session) + session.install("safety") + session.run("safety", "check", f"--file={requirements}", "--bare") + + +@nox.session(python=python_versions) +def mypy(session: Session) -> None: + """Type-check using mypy.""" + args = session.posargs or ["src", "tests"] + session.install(".") + session.install("mypy", "pytest") + session.run("mypy", *args) + if not session.posargs: + session.run("mypy", f"--python-executable={sys.executable}", "noxfile.py") + + +@nox.session(python=python_versions) +def tests(session: Session) -> None: + """Run the test suite.""" + session.install(".") + session.install("coverage[toml]", "pytest", "pygments") + try: + session.run("coverage", "run", "--parallel", "-m", "pytest", *session.posargs) + finally: + if session.interactive: + session.notify("coverage") + + +@nox.session +def coverage(session: Session) -> None: + """Produce the coverage report.""" + # Do not use session.posargs unless this is the only session. + has_args = session.posargs and len(session._runner.manifest) == 1 + args = session.posargs if has_args else ["report"] + + session.install("coverage[toml]") + + if not has_args and any(Path().glob(".coverage.*")): + session.run("coverage", "combine") + + session.run("coverage", *args) + + +@nox.session(python=python_versions) +def typeguard(session: Session) -> None: + """Runtime type checking using Typeguard.""" + session.install(".") + session.install("pytest", "typeguard", "pygments") + session.run("pytest", f"--typeguard-packages={package}", *session.posargs) + + +@nox.session(python=python_versions) +def xdoctest(session: Session) -> None: + """Run examples with xdoctest.""" + args = session.posargs or ["all"] + session.install(".") + session.install("xdoctest[colors]") + session.run("python", "-m", "xdoctest", package, *args) + + +@nox.session(name="docs-build", python="3.8") +def docs_build(session: Session) -> None: + """Build the documentation.""" + args = session.posargs or ["docs", "docs/_build"] + session.install(".") + session.install("sphinx", "sphinx-rtd-theme") + + build_dir = Path("docs", "_build") + if build_dir.exists(): + shutil.rmtree(build_dir) + + session.run("sphinx-build", *args) + + +@nox.session(python="3.8") +def docs(session: Session) -> None: + """Build and serve the documentation with live reloading on file changes.""" + args = session.posargs or ["--open-browser", "docs", "docs/_build"] + session.install(".") + session.install("sphinx", "sphinx-autobuild", "sphinx-rtd-theme") + + build_dir = Path("docs", "_build") + if build_dir.exists(): + shutil.rmtree(build_dir) + + session.run("sphinx-autobuild", *args) diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 00000000..83b0016f --- /dev/null +++ b/poetry.lock @@ -0,0 +1,1494 @@ +[[package]] +category = "dev" +description = "A configurable sidebar-enabled Sphinx theme" +name = "alabaster" +optional = false +python-versions = "*" +version = "0.7.12" + +[[package]] +category = "dev" +description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +name = "appdirs" +optional = false +python-versions = "*" +version = "1.4.4" + +[[package]] +category = "dev" +description = "Utilities for refactoring imports in python-like syntax." +name = "aspy.refactor-imports" +optional = false +python-versions = ">=3.6.1" +version = "2.1.1" + +[package.dependencies] +cached-property = "*" + +[[package]] +category = "dev" +description = "Atomic file writes." +marker = "sys_platform == \"win32\"" +name = "atomicwrites" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "1.4.0" + +[[package]] +category = "dev" +description = "Classes Without Boilerplate" +name = "attrs" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "20.2.0" + +[package.extras] +dev = ["coverage (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "sphinx", "sphinx-rtd-theme", "pre-commit"] +docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"] +tests = ["coverage (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"] +tests_no_zope = ["coverage (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six"] + +[[package]] +category = "dev" +description = "Internationalization utilities" +name = "babel" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "2.8.0" + +[package.dependencies] +pytz = ">=2015.7" + +[[package]] +category = "dev" +description = "Security oriented static analyser for python code." +name = "bandit" +optional = false +python-versions = "*" +version = "1.6.2" + +[package.dependencies] +GitPython = ">=1.0.1" +PyYAML = ">=3.13" +colorama = ">=0.3.9" +six = ">=1.10.0" +stevedore = ">=1.20.0" + +[[package]] +category = "dev" +description = "The uncompromising code formatter." +name = "black" +optional = false +python-versions = ">=3.6" +version = "20.8b1" + +[package.dependencies] +appdirs = "*" +click = ">=7.1.2" +mypy-extensions = ">=0.4.3" +pathspec = ">=0.6,<1" +regex = ">=2020.1.8" +toml = ">=0.10.1" +typed-ast = ">=1.4.0" +typing-extensions = ">=3.7.4" + +[package.extras] +colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.3.2)", "aiohttp-cors"] + +[[package]] +category = "dev" +description = "A decorator for caching properties in classes." +name = "cached-property" +optional = false +python-versions = "*" +version = "1.5.2" + +[[package]] +category = "main" +description = "Python package for providing Mozilla's CA Bundle." +name = "certifi" +optional = false +python-versions = "*" +version = "2020.6.20" + +[[package]] +category = "dev" +description = "Validate configuration and produce human readable error messages." +name = "cfgv" +optional = false +python-versions = ">=3.6.1" +version = "3.2.0" + +[[package]] +category = "main" +description = "Universal encoding detector for Python 2 and 3" +name = "chardet" +optional = false +python-versions = "*" +version = "3.0.4" + +[[package]] +category = "dev" +description = "Composable command line interface toolkit" +name = "click" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "7.1.2" + +[[package]] +category = "dev" +description = "Cross-platform colored terminal text." +marker = "platform_system == \"Windows\" or sys_platform == \"win32\" or platform_system == \"Windows\"" +name = "colorama" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "0.4.4" + +[[package]] +category = "dev" +description = "Code coverage measurement for Python" +name = "coverage" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" +version = "5.3" + +[package.dependencies] +[package.dependencies.toml] +optional = true +version = "*" + +[package.extras] +toml = ["toml"] + +[[package]] +category = "dev" +description = "A utility for ensuring Google-style docstrings stay up to date with the source code." +name = "darglint" +optional = false +python-versions = ">=3.5,<4.0" +version = "1.5.5" + +[[package]] +category = "dev" +description = "Distribution utilities" +name = "distlib" +optional = false +python-versions = "*" +version = "0.3.1" + +[[package]] +category = "dev" +description = "Docutils -- Python Documentation Utilities" +name = "docutils" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "0.16" + +[[package]] +category = "dev" +description = "A parser for Python dependency files" +name = "dparse" +optional = false +python-versions = ">=3.5" +version = "0.5.1" + +[package.dependencies] +packaging = "*" +pyyaml = "*" +toml = "*" + +[package.extras] +pipenv = ["pipenv"] + +[[package]] +category = "dev" +description = "A platform independent file lock." +name = "filelock" +optional = false +python-versions = "*" +version = "3.0.12" + +[[package]] +category = "dev" +description = "the modular source code checker: pep8 pyflakes and co" +name = "flake8" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" +version = "3.8.4" + +[package.dependencies] +mccabe = ">=0.6.0,<0.7.0" +pycodestyle = ">=2.6.0a1,<2.7.0" +pyflakes = ">=2.2.0,<2.3.0" + +[package.dependencies.importlib-metadata] +python = "<3.8" +version = "*" + +[[package]] +category = "dev" +description = "Automated security testing with bandit and flake8." +name = "flake8-bandit" +optional = false +python-versions = "*" +version = "2.1.2" + +[package.dependencies] +bandit = "*" +flake8 = "*" +flake8-polyfill = "*" +pycodestyle = "*" + +[[package]] +category = "dev" +description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." +name = "flake8-bugbear" +optional = false +python-versions = ">=3.6" +version = "20.1.4" + +[package.dependencies] +attrs = ">=19.2.0" +flake8 = ">=3.0.0" + +[[package]] +category = "dev" +description = "Extension for flake8 which uses pydocstyle to check docstrings" +name = "flake8-docstrings" +optional = false +python-versions = "*" +version = "1.5.0" + +[package.dependencies] +flake8 = ">=3" +pydocstyle = ">=2.1" + +[[package]] +category = "dev" +description = "Polyfill package for Flake8 plugins" +name = "flake8-polyfill" +optional = false +python-versions = "*" +version = "1.0.2" + +[package.dependencies] +flake8 = "*" + +[[package]] +category = "dev" +description = "Python docstring reStructuredText (RST) validator" +name = "flake8-rst-docstrings" +optional = false +python-versions = "*" +version = "0.0.14" + +[package.dependencies] +flake8 = ">=3.0.0" +restructuredtext_lint = "*" + +[[package]] +category = "dev" +description = "Git Object Database" +name = "gitdb" +optional = false +python-versions = ">=3.4" +version = "4.0.5" + +[package.dependencies] +smmap = ">=3.0.1,<4" + +[[package]] +category = "dev" +description = "Python Git Library" +name = "gitpython" +optional = false +python-versions = ">=3.4" +version = "3.1.9" + +[package.dependencies] +gitdb = ">=4.0.1,<5" + +[[package]] +category = "dev" +description = "File identification library for Python" +name = "identify" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" +version = "1.5.6" + +[package.extras] +license = ["editdistance"] + +[[package]] +category = "main" +description = "Internationalized Domain Names in Applications (IDNA)" +name = "idna" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "2.10" + +[[package]] +category = "dev" +description = "Getting image size from png/jpeg/jpeg2000/gif file" +name = "imagesize" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "1.2.0" + +[[package]] +category = "dev" +description = "Read metadata from Python packages" +marker = "python_version < \"3.8\"" +name = "importlib-metadata" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +version = "2.0.0" + +[package.dependencies] +zipp = ">=0.5" + +[package.extras] +docs = ["sphinx", "rst.linker"] +testing = ["packaging", "pep517", "importlib-resources (>=1.3)"] + +[[package]] +category = "dev" +description = "iniconfig: brain-dead simple config-ini parsing" +name = "iniconfig" +optional = false +python-versions = "*" +version = "1.1.1" + +[[package]] +category = "dev" +description = "A very fast and expressive template engine." +name = "jinja2" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "2.11.2" + +[package.dependencies] +MarkupSafe = ">=0.23" + +[package.extras] +i18n = ["Babel (>=0.8)"] + +[[package]] +category = "dev" +description = "Python LiveReload is an awesome tool for web developers" +name = "livereload" +optional = false +python-versions = "*" +version = "2.6.3" + +[package.dependencies] +six = "*" + +[package.dependencies.tornado] +python = ">=2.8" +version = "*" + +[[package]] +category = "dev" +description = "Safely add untrusted strings to HTML/XML markup." +name = "markupsafe" +optional = false +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" +version = "1.1.1" + +[[package]] +category = "dev" +description = "McCabe checker, plugin for flake8" +name = "mccabe" +optional = false +python-versions = "*" +version = "0.6.1" + +[[package]] +category = "dev" +description = "Optional static typing for Python" +name = "mypy" +optional = false +python-versions = ">=3.5" +version = "0.782" + +[package.dependencies] +mypy-extensions = ">=0.4.3,<0.5.0" +typed-ast = ">=1.4.0,<1.5.0" +typing-extensions = ">=3.7.4" + +[package.extras] +dmypy = ["psutil (>=4.0)"] + +[[package]] +category = "dev" +description = "Experimental type system extensions for programs checked with the mypy typechecker." +name = "mypy-extensions" +optional = false +python-versions = "*" +version = "0.4.3" + +[[package]] +category = "dev" +description = "Node.js virtual environment builder" +name = "nodeenv" +optional = false +python-versions = "*" +version = "1.5.0" + +[[package]] +category = "dev" +description = "Core utilities for Python packages" +name = "packaging" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "20.4" + +[package.dependencies] +pyparsing = ">=2.0.2" +six = "*" + +[[package]] +category = "dev" +description = "Utility library for gitignore style pattern matching of file paths." +name = "pathspec" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "0.8.0" + +[[package]] +category = "dev" +description = "Python Build Reasonableness" +name = "pbr" +optional = false +python-versions = ">=2.6" +version = "5.5.1" + +[[package]] +category = "dev" +description = "Check PEP-8 naming conventions, plugin for flake8" +name = "pep8-naming" +optional = false +python-versions = "*" +version = "0.11.1" + +[package.dependencies] +flake8-polyfill = ">=1.0.2,<2" + +[[package]] +category = "dev" +description = "plugin and hook calling mechanisms for python" +name = "pluggy" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "0.13.1" + +[package.dependencies] +[package.dependencies.importlib-metadata] +python = "<3.8" +version = ">=0.12" + +[package.extras] +dev = ["pre-commit", "tox"] + +[[package]] +category = "dev" +description = "A framework for managing and maintaining multi-language pre-commit hooks." +name = "pre-commit" +optional = false +python-versions = ">=3.6.1" +version = "2.7.1" + +[package.dependencies] +cfgv = ">=2.0.0" +identify = ">=1.0.0" +nodeenv = ">=0.11.1" +pyyaml = ">=5.1" +toml = "*" +virtualenv = ">=20.0.8" + +[package.dependencies.importlib-metadata] +python = "<3.8" +version = "*" + +[[package]] +category = "dev" +description = "Some out-of-the-box hooks for pre-commit." +name = "pre-commit-hooks" +optional = false +python-versions = ">=3.6.1" +version = "3.2.0" + +[package.dependencies] +"ruamel.yaml" = ">=0.15" +toml = "*" + +[[package]] +category = "dev" +description = "library with cross-python path, ini-parsing, io, code, log facilities" +name = "py" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "1.9.0" + +[[package]] +category = "dev" +description = "Python style guide checker" +name = "pycodestyle" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "2.6.0" + +[[package]] +category = "dev" +description = "Python docstring style checker" +name = "pydocstyle" +optional = false +python-versions = ">=3.5" +version = "5.1.1" + +[package.dependencies] +snowballstemmer = "*" + +[[package]] +category = "dev" +description = "passive checker of Python programs" +name = "pyflakes" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "2.2.0" + +[[package]] +category = "dev" +description = "Pygments is a syntax highlighting package written in Python." +name = "pygments" +optional = false +python-versions = ">=3.5" +version = "2.7.1" + +[[package]] +category = "dev" +description = "Python parsing module" +name = "pyparsing" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +version = "2.4.7" + +[[package]] +category = "dev" +description = "pytest: simple powerful testing with Python" +name = "pytest" +optional = false +python-versions = ">=3.5" +version = "6.1.1" + +[package.dependencies] +atomicwrites = ">=1.0" +attrs = ">=17.4.0" +colorama = "*" +iniconfig = "*" +packaging = "*" +pluggy = ">=0.12,<1.0" +py = ">=1.8.2" +toml = "*" + +[package.dependencies.importlib-metadata] +python = "<3.8" +version = ">=0.12" + +[package.extras] +checkqa_mypy = ["mypy (0.780)"] +testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] + +[[package]] +category = "dev" +description = "World timezone definitions, modern and historical" +name = "pytz" +optional = false +python-versions = "*" +version = "2020.1" + +[[package]] +category = "dev" +description = "YAML parser and emitter for Python" +name = "pyyaml" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "5.3.1" + +[[package]] +category = "dev" +description = "Alternative regular expression module, to replace re." +name = "regex" +optional = false +python-versions = "*" +version = "2020.10.15" + +[[package]] +category = "dev" +description = "Tool for reordering python imports" +name = "reorder-python-imports" +optional = false +python-versions = ">=3.6.1" +version = "2.3.5" + +[package.dependencies] +"aspy.refactor-imports" = ">=2.1.0" + +[[package]] +category = "main" +description = "Python HTTP for Humans." +name = "requests" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "2.24.0" + +[package.dependencies] +certifi = ">=2017.4.17" +chardet = ">=3.0.2,<4" +idna = ">=2.5,<3" +urllib3 = ">=1.21.1,<1.25.0 || >1.25.0,<1.25.1 || >1.25.1,<1.26" + +[package.extras] +security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"] +socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)", "win-inet-pton"] + +[[package]] +category = "dev" +description = "reStructuredText linter" +name = "restructuredtext-lint" +optional = false +python-versions = "*" +version = "1.3.1" + +[package.dependencies] +docutils = ">=0.11,<1.0" + +[[package]] +category = "dev" +description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" +name = "ruamel.yaml" +optional = false +python-versions = "*" +version = "0.16.12" + +[package.dependencies] +[package.dependencies."ruamel.yaml.clib"] +python = "<3.9" +version = ">=0.1.2" + +[package.extras] +docs = ["ryd"] +jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"] + +[[package]] +category = "dev" +description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" +marker = "platform_python_implementation == \"CPython\" and python_version < \"3.9\"" +name = "ruamel.yaml.clib" +optional = false +python-versions = "*" +version = "0.2.2" + +[[package]] +category = "dev" +description = "Checks installed dependencies for known vulnerabilities." +name = "safety" +optional = false +python-versions = ">=3.5" +version = "1.9.0" + +[package.dependencies] +Click = ">=6.0" +dparse = ">=0.5.1" +packaging = "*" +requests = "*" +setuptools = "*" + +[[package]] +category = "dev" +description = "Python 2 and 3 compatibility utilities" +name = "six" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +version = "1.15.0" + +[[package]] +category = "dev" +description = "A pure Python implementation of a sliding window memory map manager" +name = "smmap" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "3.0.4" + +[[package]] +category = "dev" +description = "This package provides 26 stemmers for 25 languages generated from Snowball algorithms." +name = "snowballstemmer" +optional = false +python-versions = "*" +version = "2.0.0" + +[[package]] +category = "dev" +description = "Python documentation generator" +name = "sphinx" +optional = false +python-versions = ">=3.5" +version = "3.2.1" + +[package.dependencies] +Jinja2 = ">=2.3" +Pygments = ">=2.0" +alabaster = ">=0.7,<0.8" +babel = ">=1.3" +colorama = ">=0.3.5" +docutils = ">=0.12" +imagesize = "*" +packaging = "*" +requests = ">=2.5.0" +setuptools = "*" +snowballstemmer = ">=1.1" +sphinxcontrib-applehelp = "*" +sphinxcontrib-devhelp = "*" +sphinxcontrib-htmlhelp = "*" +sphinxcontrib-jsmath = "*" +sphinxcontrib-qthelp = "*" +sphinxcontrib-serializinghtml = "*" + +[package.extras] +docs = ["sphinxcontrib-websupport"] +lint = ["flake8 (>=3.5.0)", "flake8-import-order", "mypy (>=0.780)", "docutils-stubs"] +test = ["pytest", "pytest-cov", "html5lib", "typed-ast", "cython"] + +[[package]] +category = "dev" +description = "Rebuild Sphinx documentation on changes, with live-reload in the browser." +name = "sphinx-autobuild" +optional = false +python-versions = ">=3.6" +version = "2020.9.1" + +[package.dependencies] +livereload = "*" +sphinx = "*" + +[package.extras] +test = ["pytest", "pytest-cov"] + +[[package]] +category = "dev" +description = "Read the Docs theme for Sphinx" +name = "sphinx-rtd-theme" +optional = false +python-versions = "*" +version = "0.5.0" + +[package.dependencies] +sphinx = "*" + +[package.extras] +dev = ["transifex-client", "sphinxcontrib-httpdomain", "bump2version"] + +[[package]] +category = "dev" +description = "sphinxcontrib-applehelp is a sphinx extension which outputs Apple help books" +name = "sphinxcontrib-applehelp" +optional = false +python-versions = ">=3.5" +version = "1.0.2" + +[package.extras] +lint = ["flake8", "mypy", "docutils-stubs"] +test = ["pytest"] + +[[package]] +category = "dev" +description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." +name = "sphinxcontrib-devhelp" +optional = false +python-versions = ">=3.5" +version = "1.0.2" + +[package.extras] +lint = ["flake8", "mypy", "docutils-stubs"] +test = ["pytest"] + +[[package]] +category = "dev" +description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" +name = "sphinxcontrib-htmlhelp" +optional = false +python-versions = ">=3.5" +version = "1.0.3" + +[package.extras] +lint = ["flake8", "mypy", "docutils-stubs"] +test = ["pytest", "html5lib"] + +[[package]] +category = "dev" +description = "A sphinx extension which renders display math in HTML via JavaScript" +name = "sphinxcontrib-jsmath" +optional = false +python-versions = ">=3.5" +version = "1.0.1" + +[package.extras] +test = ["pytest", "flake8", "mypy"] + +[[package]] +category = "dev" +description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." +name = "sphinxcontrib-qthelp" +optional = false +python-versions = ">=3.5" +version = "1.0.3" + +[package.extras] +lint = ["flake8", "mypy", "docutils-stubs"] +test = ["pytest"] + +[[package]] +category = "dev" +description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." +name = "sphinxcontrib-serializinghtml" +optional = false +python-versions = ">=3.5" +version = "1.1.4" + +[package.extras] +lint = ["flake8", "mypy", "docutils-stubs"] +test = ["pytest"] + +[[package]] +category = "dev" +description = "Manage dynamic plugins for Python applications" +name = "stevedore" +optional = false +python-versions = ">=3.6" +version = "3.2.2" + +[package.dependencies] +pbr = ">=2.0.0,<2.1.0 || >2.1.0" + +[package.dependencies.importlib-metadata] +python = "<3.8" +version = ">=1.7.0" + +[[package]] +category = "dev" +description = "Python Library for Tom's Obvious, Minimal Language" +name = "toml" +optional = false +python-versions = "*" +version = "0.10.1" + +[[package]] +category = "dev" +description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." +marker = "python_version > \"2.7\"" +name = "tornado" +optional = false +python-versions = ">= 3.5" +version = "6.0.4" + +[[package]] +category = "dev" +description = "a fork of Python 2 and 3 ast modules with type comment support" +name = "typed-ast" +optional = false +python-versions = "*" +version = "1.4.1" + +[[package]] +category = "dev" +description = "Run-time type checker for Python" +name = "typeguard" +optional = false +python-versions = ">=3.5.3" +version = "2.10.0" + +[package.extras] +doc = ["sphinx-rtd-theme", "sphinx-autodoc-typehints (>=1.2.0)"] +test = ["pytest", "typing-extensions"] + +[[package]] +category = "dev" +description = "Backported and Experimental Type Hints for Python 3.5+" +name = "typing-extensions" +optional = false +python-versions = "*" +version = "3.7.4.3" + +[[package]] +category = "main" +description = "HTTP library with thread-safe connection pooling, file post, and more." +name = "urllib3" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" +version = "1.25.11" + +[package.extras] +brotli = ["brotlipy (>=0.6.0)"] +secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] +socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"] + +[[package]] +category = "dev" +description = "Virtual Python Environment builder" +name = "virtualenv" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" +version = "20.0.35" + +[package.dependencies] +appdirs = ">=1.4.3,<2" +distlib = ">=0.3.1,<1" +filelock = ">=3.0.0,<4" +six = ">=1.9.0,<2" + +[package.dependencies.importlib-metadata] +python = "<3.8" +version = ">=0.12,<3" + +[package.extras] +docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=19.9.0rc1)"] +testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)", "pytest-xdist (>=1.31.0)", "packaging (>=20.0)", "xonsh (>=0.9.16)"] + +[[package]] +category = "dev" +description = "A rewrite of the builtin doctest module" +name = "xdoctest" +optional = false +python-versions = "*" +version = "0.15.0" + +[package.dependencies] +six = "*" + +[package.dependencies.Pygments] +optional = true +version = "*" + +[package.dependencies.colorama] +optional = true +version = "*" + +[package.extras] +all = ["six", "pytest", "pytest-cov", "codecov", "scikit-build", "cmake", "ninja", "pybind11", "pygments", "colorama", "nbformat", "nbconvert", "jupyter-client", "ipython", "ipykernel"] +colors = ["pygments", "colorama"] +jupyter = ["nbformat", "nbconvert", "jupyter-client", "ipython", "ipykernel"] +optional = ["pygments", "colorama", "nbformat", "nbconvert", "jupyter-client", "ipython", "ipykernel"] +tests = ["pytest", "pytest-cov", "codecov", "scikit-build", "cmake", "ninja", "pybind11", "nbformat", "nbconvert", "jupyter-client", "ipython", "ipykernel"] + +[[package]] +category = "dev" +description = "Backport of pathlib-compatible object wrapper for zip files" +marker = "python_version < \"3.8\"" +name = "zipp" +optional = false +python-versions = ">=3.6" +version = "3.3.1" + +[package.extras] +docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"] +testing = ["pytest (>=3.5,<3.7.3 || >3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-cov", "jaraco.test (>=3.2.0)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"] + +[metadata] +content-hash = "b4e8b1df8bbcbfff3e4fb2353cfed0f989434715abe6675953b313facd411d01" +lock-version = "1.0" +python-versions = "^3.7.0" + +[metadata.files] +alabaster = [ + {file = "alabaster-0.7.12-py2.py3-none-any.whl", hash = "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359"}, + {file = "alabaster-0.7.12.tar.gz", hash = "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"}, +] +appdirs = [ + {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"}, + {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, +] +"aspy.refactor-imports" = [ + {file = "aspy.refactor_imports-2.1.1-py2.py3-none-any.whl", hash = "sha256:9df76bf19ef81620068b785a386740ab3c8939fcbdcebf20c4a4e0057230d782"}, + {file = "aspy.refactor_imports-2.1.1.tar.gz", hash = "sha256:eec8d1a73bedf64ffb8b589ad919a030c1fb14acf7d1ce0ab192f6eedae895c5"}, +] +atomicwrites = [ + {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, + {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, +] +attrs = [ + {file = "attrs-20.2.0-py2.py3-none-any.whl", hash = "sha256:fce7fc47dfc976152e82d53ff92fa0407700c21acd20886a13777a0d20e655dc"}, + {file = "attrs-20.2.0.tar.gz", hash = "sha256:26b54ddbbb9ee1d34d5d3668dd37d6cf74990ab23c828c2888dccdceee395594"}, +] +babel = [ + {file = "Babel-2.8.0-py2.py3-none-any.whl", hash = "sha256:d670ea0b10f8b723672d3a6abeb87b565b244da220d76b4dba1b66269ec152d4"}, + {file = "Babel-2.8.0.tar.gz", hash = "sha256:1aac2ae2d0d8ea368fa90906567f5c08463d98ade155c0c4bfedd6a0f7160e38"}, +] +bandit = [ + {file = "bandit-1.6.2-py2.py3-none-any.whl", hash = "sha256:336620e220cf2d3115877685e264477ff9d9abaeb0afe3dc7264f55fa17a3952"}, + {file = "bandit-1.6.2.tar.gz", hash = "sha256:41e75315853507aa145d62a78a2a6c5e3240fe14ee7c601459d0df9418196065"}, +] +black = [ + {file = "black-20.8b1.tar.gz", hash = "sha256:1c02557aa099101b9d21496f8a914e9ed2222ef70336404eeeac8edba836fbea"}, +] +cached-property = [ + {file = "cached-property-1.5.2.tar.gz", hash = "sha256:9fa5755838eecbb2d234c3aa390bd80fbd3ac6b6869109bfc1b499f7bd89a130"}, + {file = "cached_property-1.5.2-py2.py3-none-any.whl", hash = "sha256:df4f613cf7ad9a588cc381aaf4a512d26265ecebd5eb9e1ba12f1319eb85a6a0"}, +] +certifi = [ + {file = "certifi-2020.6.20-py2.py3-none-any.whl", hash = "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41"}, + {file = "certifi-2020.6.20.tar.gz", hash = "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3"}, +] +cfgv = [ + {file = "cfgv-3.2.0-py2.py3-none-any.whl", hash = "sha256:32e43d604bbe7896fe7c248a9c2276447dbef840feb28fe20494f62af110211d"}, + {file = "cfgv-3.2.0.tar.gz", hash = "sha256:cf22deb93d4bcf92f345a5c3cd39d3d41d6340adc60c78bbbd6588c384fda6a1"}, +] +chardet = [ + {file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"}, + {file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"}, +] +click = [ + {file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"}, + {file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"}, +] +colorama = [ + {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, +] +coverage = [ + {file = "coverage-5.3-cp27-cp27m-macosx_10_13_intel.whl", hash = "sha256:bd3166bb3b111e76a4f8e2980fa1addf2920a4ca9b2b8ca36a3bc3dedc618270"}, + {file = "coverage-5.3-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:9342dd70a1e151684727c9c91ea003b2fb33523bf19385d4554f7897ca0141d4"}, + {file = "coverage-5.3-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:63808c30b41f3bbf65e29f7280bf793c79f54fb807057de7e5238ffc7cc4d7b9"}, + {file = "coverage-5.3-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:4d6a42744139a7fa5b46a264874a781e8694bb32f1d76d8137b68138686f1729"}, + {file = "coverage-5.3-cp27-cp27m-win32.whl", hash = "sha256:86e9f8cd4b0cdd57b4ae71a9c186717daa4c5a99f3238a8723f416256e0b064d"}, + {file = "coverage-5.3-cp27-cp27m-win_amd64.whl", hash = "sha256:7858847f2d84bf6e64c7f66498e851c54de8ea06a6f96a32a1d192d846734418"}, + {file = "coverage-5.3-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:530cc8aaf11cc2ac7430f3614b04645662ef20c348dce4167c22d99bec3480e9"}, + {file = "coverage-5.3-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:381ead10b9b9af5f64646cd27107fb27b614ee7040bb1226f9c07ba96625cbb5"}, + {file = "coverage-5.3-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:71b69bd716698fa62cd97137d6f2fdf49f534decb23a2c6fc80813e8b7be6822"}, + {file = "coverage-5.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:1d44bb3a652fed01f1f2c10d5477956116e9b391320c94d36c6bf13b088a1097"}, + {file = "coverage-5.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:1c6703094c81fa55b816f5ae542c6ffc625fec769f22b053adb42ad712d086c9"}, + {file = "coverage-5.3-cp35-cp35m-win32.whl", hash = "sha256:cedb2f9e1f990918ea061f28a0f0077a07702e3819602d3507e2ff98c8d20636"}, + {file = "coverage-5.3-cp35-cp35m-win_amd64.whl", hash = "sha256:7f43286f13d91a34fadf61ae252a51a130223c52bfefb50310d5b2deb062cf0f"}, + {file = "coverage-5.3-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:c851b35fc078389bc16b915a0a7c1d5923e12e2c5aeec58c52f4aa8085ac8237"}, + {file = "coverage-5.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:aac1ba0a253e17889550ddb1b60a2063f7474155465577caa2a3b131224cfd54"}, + {file = "coverage-5.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:2b31f46bf7b31e6aa690d4c7a3d51bb262438c6dcb0d528adde446531d0d3bb7"}, + {file = "coverage-5.3-cp36-cp36m-win32.whl", hash = "sha256:c5f17ad25d2c1286436761b462e22b5020d83316f8e8fcb5deb2b3151f8f1d3a"}, + {file = "coverage-5.3-cp36-cp36m-win_amd64.whl", hash = "sha256:aef72eae10b5e3116bac6957de1df4d75909fc76d1499a53fb6387434b6bcd8d"}, + {file = "coverage-5.3-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:e8caf961e1b1a945db76f1b5fa9c91498d15f545ac0ababbe575cfab185d3bd8"}, + {file = "coverage-5.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:29a6272fec10623fcbe158fdf9abc7a5fa032048ac1d8631f14b50fbfc10d17f"}, + {file = "coverage-5.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:2d43af2be93ffbad25dd959899b5b809618a496926146ce98ee0b23683f8c51c"}, + {file = "coverage-5.3-cp37-cp37m-win32.whl", hash = "sha256:c3888a051226e676e383de03bf49eb633cd39fc829516e5334e69b8d81aae751"}, + {file = "coverage-5.3-cp37-cp37m-win_amd64.whl", hash = "sha256:9669179786254a2e7e57f0ecf224e978471491d660aaca833f845b72a2df3709"}, + {file = "coverage-5.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0203acd33d2298e19b57451ebb0bed0ab0c602e5cf5a818591b4918b1f97d516"}, + {file = "coverage-5.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:582ddfbe712025448206a5bc45855d16c2e491c2dd102ee9a2841418ac1c629f"}, + {file = "coverage-5.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:0f313707cdecd5cd3e217fc68c78a960b616604b559e9ea60cc16795c4304259"}, + {file = "coverage-5.3-cp38-cp38-win32.whl", hash = "sha256:78e93cc3571fd928a39c0b26767c986188a4118edc67bc0695bc7a284da22e82"}, + {file = "coverage-5.3-cp38-cp38-win_amd64.whl", hash = "sha256:8f264ba2701b8c9f815b272ad568d555ef98dfe1576802ab3149c3629a9f2221"}, + {file = "coverage-5.3-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:50691e744714856f03a86df3e2bff847c2acede4c191f9a1da38f088df342978"}, + {file = "coverage-5.3-cp39-cp39-manylinux1_i686.whl", hash = "sha256:9361de40701666b034c59ad9e317bae95c973b9ff92513dd0eced11c6adf2e21"}, + {file = "coverage-5.3-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:c1b78fb9700fc961f53386ad2fd86d87091e06ede5d118b8a50dea285a071c24"}, + {file = "coverage-5.3-cp39-cp39-win32.whl", hash = "sha256:cb7df71de0af56000115eafd000b867d1261f786b5eebd88a0ca6360cccfaca7"}, + {file = "coverage-5.3-cp39-cp39-win_amd64.whl", hash = "sha256:47a11bdbd8ada9b7ee628596f9d97fbd3851bd9999d398e9436bd67376dbece7"}, + {file = "coverage-5.3.tar.gz", hash = "sha256:280baa8ec489c4f542f8940f9c4c2181f0306a8ee1a54eceba071a449fb870a0"}, +] +darglint = [ + {file = "darglint-1.5.5-py3-none-any.whl", hash = "sha256:cd882c812f28ee3b5577259bfd8d6d25962386dd87fc1f3756eac24370aaa060"}, + {file = "darglint-1.5.5.tar.gz", hash = "sha256:2f12ce2ef3d8189279a8f2eb4c53fd215dbacae50e37765542a91310400a9cd6"}, +] +distlib = [ + {file = "distlib-0.3.1-py2.py3-none-any.whl", hash = "sha256:8c09de2c67b3e7deef7184574fc060ab8a793e7adbb183d942c389c8b13c52fb"}, + {file = "distlib-0.3.1.zip", hash = "sha256:edf6116872c863e1aa9d5bb7cb5e05a022c519a4594dc703843343a9ddd9bff1"}, +] +docutils = [ + {file = "docutils-0.16-py2.py3-none-any.whl", hash = "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af"}, + {file = "docutils-0.16.tar.gz", hash = "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc"}, +] +dparse = [ + {file = "dparse-0.5.1-py3-none-any.whl", hash = "sha256:e953a25e44ebb60a5c6efc2add4420c177f1d8404509da88da9729202f306994"}, + {file = "dparse-0.5.1.tar.gz", hash = "sha256:a1b5f169102e1c894f9a7d5ccf6f9402a836a5d24be80a986c7ce9eaed78f367"}, +] +filelock = [ + {file = "filelock-3.0.12-py3-none-any.whl", hash = "sha256:929b7d63ec5b7d6b71b0fa5ac14e030b3f70b75747cef1b10da9b879fef15836"}, + {file = "filelock-3.0.12.tar.gz", hash = "sha256:18d82244ee114f543149c66a6e0c14e9c4f8a1044b5cdaadd0f82159d6a6ff59"}, +] +flake8 = [ + {file = "flake8-3.8.4-py2.py3-none-any.whl", hash = "sha256:749dbbd6bfd0cf1318af27bf97a14e28e5ff548ef8e5b1566ccfb25a11e7c839"}, + {file = "flake8-3.8.4.tar.gz", hash = "sha256:aadae8761ec651813c24be05c6f7b4680857ef6afaae4651a4eccaef97ce6c3b"}, +] +flake8-bandit = [ + {file = "flake8_bandit-2.1.2.tar.gz", hash = "sha256:687fc8da2e4a239b206af2e54a90093572a60d0954f3054e23690739b0b0de3b"}, +] +flake8-bugbear = [ + {file = "flake8-bugbear-20.1.4.tar.gz", hash = "sha256:bd02e4b009fb153fe6072c31c52aeab5b133d508095befb2ffcf3b41c4823162"}, + {file = "flake8_bugbear-20.1.4-py36.py37.py38-none-any.whl", hash = "sha256:a3ddc03ec28ba2296fc6f89444d1c946a6b76460f859795b35b77d4920a51b63"}, +] +flake8-docstrings = [ + {file = "flake8-docstrings-1.5.0.tar.gz", hash = "sha256:3d5a31c7ec6b7367ea6506a87ec293b94a0a46c0bce2bb4975b7f1d09b6f3717"}, + {file = "flake8_docstrings-1.5.0-py2.py3-none-any.whl", hash = "sha256:a256ba91bc52307bef1de59e2a009c3cf61c3d0952dbe035d6ff7208940c2edc"}, +] +flake8-polyfill = [ + {file = "flake8-polyfill-1.0.2.tar.gz", hash = "sha256:e44b087597f6da52ec6393a709e7108b2905317d0c0b744cdca6208e670d8eda"}, + {file = "flake8_polyfill-1.0.2-py2.py3-none-any.whl", hash = "sha256:12be6a34ee3ab795b19ca73505e7b55826d5f6ad7230d31b18e106400169b9e9"}, +] +flake8-rst-docstrings = [ + {file = "flake8-rst-docstrings-0.0.14.tar.gz", hash = "sha256:8f8bcb18f1408b506dd8ba2c99af3eac6128f6911d4bf6ff874b94caa70182a2"}, +] +gitdb = [ + {file = "gitdb-4.0.5-py3-none-any.whl", hash = "sha256:91f36bfb1ab7949b3b40e23736db18231bf7593edada2ba5c3a174a7b23657ac"}, + {file = "gitdb-4.0.5.tar.gz", hash = "sha256:c9e1f2d0db7ddb9a704c2a0217be31214e91a4fe1dea1efad19ae42ba0c285c9"}, +] +gitpython = [ + {file = "GitPython-3.1.9-py3-none-any.whl", hash = "sha256:138016d519bf4dd55b22c682c904ed2fd0235c3612b2f8f65ce218ff358deed8"}, + {file = "GitPython-3.1.9.tar.gz", hash = "sha256:a03f728b49ce9597a6655793207c6ab0da55519368ff5961e4a74ae475b9fa8e"}, +] +identify = [ + {file = "identify-1.5.6-py2.py3-none-any.whl", hash = "sha256:3139bf72d81dfd785b0a464e2776bd59bdc725b4cc10e6cf46b56a0db931c82e"}, + {file = "identify-1.5.6.tar.gz", hash = "sha256:969d844b7a85d32a5f9ac4e163df6e846d73c87c8b75847494ee8f4bd2186421"}, +] +idna = [ + {file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"}, + {file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"}, +] +imagesize = [ + {file = "imagesize-1.2.0-py2.py3-none-any.whl", hash = "sha256:6965f19a6a2039c7d48bca7dba2473069ff854c36ae6f19d2cde309d998228a1"}, + {file = "imagesize-1.2.0.tar.gz", hash = "sha256:b1f6b5a4eab1f73479a50fb79fcf729514a900c341d8503d62a62dbc4127a2b1"}, +] +importlib-metadata = [ + {file = "importlib_metadata-2.0.0-py2.py3-none-any.whl", hash = "sha256:cefa1a2f919b866c5beb7c9f7b0ebb4061f30a8a9bf16d609b000e2dfaceb9c3"}, + {file = "importlib_metadata-2.0.0.tar.gz", hash = "sha256:77a540690e24b0305878c37ffd421785a6f7e53c8b5720d211b211de8d0e95da"}, +] +iniconfig = [ + {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, + {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, +] +jinja2 = [ + {file = "Jinja2-2.11.2-py2.py3-none-any.whl", hash = "sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035"}, + {file = "Jinja2-2.11.2.tar.gz", hash = "sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0"}, +] +livereload = [ + {file = "livereload-2.6.3.tar.gz", hash = "sha256:776f2f865e59fde56490a56bcc6773b6917366bce0c267c60ee8aaf1a0959869"}, +] +markupsafe = [ + {file = "MarkupSafe-1.1.1-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161"}, + {file = "MarkupSafe-1.1.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"}, + {file = "MarkupSafe-1.1.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183"}, + {file = "MarkupSafe-1.1.1-cp27-cp27m-win32.whl", hash = "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b"}, + {file = "MarkupSafe-1.1.1-cp27-cp27m-win_amd64.whl", hash = "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e"}, + {file = "MarkupSafe-1.1.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f"}, + {file = "MarkupSafe-1.1.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1"}, + {file = "MarkupSafe-1.1.1-cp34-cp34m-macosx_10_6_intel.whl", hash = "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5"}, + {file = "MarkupSafe-1.1.1-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1"}, + {file = "MarkupSafe-1.1.1-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735"}, + {file = "MarkupSafe-1.1.1-cp34-cp34m-win32.whl", hash = "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21"}, + {file = "MarkupSafe-1.1.1-cp34-cp34m-win_amd64.whl", hash = "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235"}, + {file = "MarkupSafe-1.1.1-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b"}, + {file = "MarkupSafe-1.1.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f"}, + {file = "MarkupSafe-1.1.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905"}, + {file = "MarkupSafe-1.1.1-cp35-cp35m-win32.whl", hash = "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1"}, + {file = "MarkupSafe-1.1.1-cp35-cp35m-win_amd64.whl", hash = "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d"}, + {file = "MarkupSafe-1.1.1-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff"}, + {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473"}, + {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e"}, + {file = "MarkupSafe-1.1.1-cp36-cp36m-win32.whl", hash = "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66"}, + {file = "MarkupSafe-1.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5"}, + {file = "MarkupSafe-1.1.1-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d"}, + {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e"}, + {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6"}, + {file = "MarkupSafe-1.1.1-cp37-cp37m-win32.whl", hash = "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2"}, + {file = "MarkupSafe-1.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c"}, + {file = "MarkupSafe-1.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15"}, + {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2"}, + {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42"}, + {file = "MarkupSafe-1.1.1-cp38-cp38-win32.whl", hash = "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b"}, + {file = "MarkupSafe-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be"}, + {file = "MarkupSafe-1.1.1.tar.gz", hash = "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b"}, +] +mccabe = [ + {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, + {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, +] +mypy = [ + {file = "mypy-0.782-cp35-cp35m-macosx_10_6_x86_64.whl", hash = "sha256:2c6cde8aa3426c1682d35190b59b71f661237d74b053822ea3d748e2c9578a7c"}, + {file = "mypy-0.782-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9c7a9a7ceb2871ba4bac1cf7217a7dd9ccd44c27c2950edbc6dc08530f32ad4e"}, + {file = "mypy-0.782-cp35-cp35m-win_amd64.whl", hash = "sha256:c05b9e4fb1d8a41d41dec8786c94f3b95d3c5f528298d769eb8e73d293abc48d"}, + {file = "mypy-0.782-cp36-cp36m-macosx_10_6_x86_64.whl", hash = "sha256:6731603dfe0ce4352c555c6284c6db0dc935b685e9ce2e4cf220abe1e14386fd"}, + {file = "mypy-0.782-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:f05644db6779387ccdb468cc47a44b4356fc2ffa9287135d05b70a98dc83b89a"}, + {file = "mypy-0.782-cp36-cp36m-win_amd64.whl", hash = "sha256:b7fbfabdbcc78c4f6fc4712544b9b0d6bf171069c6e0e3cb82440dd10ced3406"}, + {file = "mypy-0.782-cp37-cp37m-macosx_10_6_x86_64.whl", hash = "sha256:3fdda71c067d3ddfb21da4b80e2686b71e9e5c72cca65fa216d207a358827f86"}, + {file = "mypy-0.782-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:d7df6eddb6054d21ca4d3c6249cae5578cb4602951fd2b6ee2f5510ffb098707"}, + {file = "mypy-0.782-cp37-cp37m-win_amd64.whl", hash = "sha256:a4a2cbcfc4cbf45cd126f531dedda8485671545b43107ded25ce952aac6fb308"}, + {file = "mypy-0.782-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6bb93479caa6619d21d6e7160c552c1193f6952f0668cdda2f851156e85186fc"}, + {file = "mypy-0.782-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:81c7908b94239c4010e16642c9102bfc958ab14e36048fa77d0be3289dda76ea"}, + {file = "mypy-0.782-cp38-cp38-win_amd64.whl", hash = "sha256:5dd13ff1f2a97f94540fd37a49e5d255950ebcdf446fb597463a40d0df3fac8b"}, + {file = "mypy-0.782-py3-none-any.whl", hash = "sha256:e0b61738ab504e656d1fe4ff0c0601387a5489ca122d55390ade31f9ca0e252d"}, + {file = "mypy-0.782.tar.gz", hash = "sha256:eff7d4a85e9eea55afa34888dfeaccde99e7520b51f867ac28a48492c0b1130c"}, +] +mypy-extensions = [ + {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, + {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, +] +nodeenv = [ + {file = "nodeenv-1.5.0-py2.py3-none-any.whl", hash = "sha256:5304d424c529c997bc888453aeaa6362d242b6b4631e90f3d4bf1b290f1c84a9"}, + {file = "nodeenv-1.5.0.tar.gz", hash = "sha256:ab45090ae383b716c4ef89e690c41ff8c2b257b85b309f01f3654df3d084bd7c"}, +] +packaging = [ + {file = "packaging-20.4-py2.py3-none-any.whl", hash = "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181"}, + {file = "packaging-20.4.tar.gz", hash = "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8"}, +] +pathspec = [ + {file = "pathspec-0.8.0-py2.py3-none-any.whl", hash = "sha256:7d91249d21749788d07a2d0f94147accd8f845507400749ea19c1ec9054a12b0"}, + {file = "pathspec-0.8.0.tar.gz", hash = "sha256:da45173eb3a6f2a5a487efba21f050af2b41948be6ab52b6a1e3ff22bb8b7061"}, +] +pbr = [ + {file = "pbr-5.5.1-py2.py3-none-any.whl", hash = "sha256:b236cde0ac9a6aedd5e3c34517b423cd4fd97ef723849da6b0d2231142d89c00"}, + {file = "pbr-5.5.1.tar.gz", hash = "sha256:5fad80b613c402d5b7df7bd84812548b2a61e9977387a80a5fc5c396492b13c9"}, +] +pep8-naming = [ + {file = "pep8-naming-0.11.1.tar.gz", hash = "sha256:a1dd47dd243adfe8a83616e27cf03164960b507530f155db94e10b36a6cd6724"}, + {file = "pep8_naming-0.11.1-py2.py3-none-any.whl", hash = "sha256:f43bfe3eea7e0d73e8b5d07d6407ab47f2476ccaeff6937c84275cd30b016738"}, +] +pluggy = [ + {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"}, + {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, +] +pre-commit = [ + {file = "pre_commit-2.7.1-py2.py3-none-any.whl", hash = "sha256:810aef2a2ba4f31eed1941fc270e72696a1ad5590b9751839c90807d0fff6b9a"}, + {file = "pre_commit-2.7.1.tar.gz", hash = "sha256:c54fd3e574565fe128ecc5e7d2f91279772ddb03f8729645fa812fe809084a70"}, +] +pre-commit-hooks = [ + {file = "pre_commit_hooks-3.2.0-py2.py3-none-any.whl", hash = "sha256:8a174237326576c5f2279eba18ccbf2ca2a19fcaab8844db80f576c8fe76c2c2"}, + {file = "pre_commit_hooks-3.2.0.tar.gz", hash = "sha256:917bce8feb048f8271e3a4a900c6d780118d23e8ddf4557ddec9384c0d1dba79"}, +] +py = [ + {file = "py-1.9.0-py2.py3-none-any.whl", hash = "sha256:366389d1db726cd2fcfc79732e75410e5fe4d31db13692115529d34069a043c2"}, + {file = "py-1.9.0.tar.gz", hash = "sha256:9ca6883ce56b4e8da7e79ac18787889fa5206c79dcc67fb065376cd2fe03f342"}, +] +pycodestyle = [ + {file = "pycodestyle-2.6.0-py2.py3-none-any.whl", hash = "sha256:2295e7b2f6b5bd100585ebcb1f616591b652db8a741695b3d8f5d28bdc934367"}, + {file = "pycodestyle-2.6.0.tar.gz", hash = "sha256:c58a7d2815e0e8d7972bf1803331fb0152f867bd89adf8a01dfd55085434192e"}, +] +pydocstyle = [ + {file = "pydocstyle-5.1.1-py3-none-any.whl", hash = "sha256:aca749e190a01726a4fb472dd4ef23b5c9da7b9205c0a7857c06533de13fd678"}, + {file = "pydocstyle-5.1.1.tar.gz", hash = "sha256:19b86fa8617ed916776a11cd8bc0197e5b9856d5433b777f51a3defe13075325"}, +] +pyflakes = [ + {file = "pyflakes-2.2.0-py2.py3-none-any.whl", hash = "sha256:0d94e0e05a19e57a99444b6ddcf9a6eb2e5c68d3ca1e98e90707af8152c90a92"}, + {file = "pyflakes-2.2.0.tar.gz", hash = "sha256:35b2d75ee967ea93b55750aa9edbbf72813e06a66ba54438df2cfac9e3c27fc8"}, +] +pygments = [ + {file = "Pygments-2.7.1-py3-none-any.whl", hash = "sha256:307543fe65c0947b126e83dd5a61bd8acbd84abec11f43caebaf5534cbc17998"}, + {file = "Pygments-2.7.1.tar.gz", hash = "sha256:926c3f319eda178d1bd90851e4317e6d8cdb5e292a3386aac9bd75eca29cf9c7"}, +] +pyparsing = [ + {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"}, + {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"}, +] +pytest = [ + {file = "pytest-6.1.1-py3-none-any.whl", hash = "sha256:7a8190790c17d79a11f847fba0b004ee9a8122582ebff4729a082c109e81a4c9"}, + {file = "pytest-6.1.1.tar.gz", hash = "sha256:8f593023c1a0f916110285b6efd7f99db07d59546e3d8c36fc60e2ab05d3be92"}, +] +pytz = [ + {file = "pytz-2020.1-py2.py3-none-any.whl", hash = "sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed"}, + {file = "pytz-2020.1.tar.gz", hash = "sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048"}, +] +pyyaml = [ + {file = "PyYAML-5.3.1-cp27-cp27m-win32.whl", hash = "sha256:74809a57b329d6cc0fdccee6318f44b9b8649961fa73144a98735b0aaf029f1f"}, + {file = "PyYAML-5.3.1-cp27-cp27m-win_amd64.whl", hash = "sha256:240097ff019d7c70a4922b6869d8a86407758333f02203e0fc6ff79c5dcede76"}, + {file = "PyYAML-5.3.1-cp35-cp35m-win32.whl", hash = "sha256:4f4b913ca1a7319b33cfb1369e91e50354d6f07a135f3b901aca02aa95940bd2"}, + {file = "PyYAML-5.3.1-cp35-cp35m-win_amd64.whl", hash = "sha256:cc8955cfbfc7a115fa81d85284ee61147059a753344bc51098f3ccd69b0d7e0c"}, + {file = "PyYAML-5.3.1-cp36-cp36m-win32.whl", hash = "sha256:7739fc0fa8205b3ee8808aea45e968bc90082c10aef6ea95e855e10abf4a37b2"}, + {file = "PyYAML-5.3.1-cp36-cp36m-win_amd64.whl", hash = "sha256:69f00dca373f240f842b2931fb2c7e14ddbacd1397d57157a9b005a6a9942648"}, + {file = "PyYAML-5.3.1-cp37-cp37m-win32.whl", hash = "sha256:d13155f591e6fcc1ec3b30685d50bf0711574e2c0dfffd7644babf8b5102ca1a"}, + {file = "PyYAML-5.3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:73f099454b799e05e5ab51423c7bcf361c58d3206fa7b0d555426b1f4d9a3eaf"}, + {file = "PyYAML-5.3.1-cp38-cp38-win32.whl", hash = "sha256:06a0d7ba600ce0b2d2fe2e78453a470b5a6e000a985dd4a4e54e436cc36b0e97"}, + {file = "PyYAML-5.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:95f71d2af0ff4227885f7a6605c37fd53d3a106fcab511b8860ecca9fcf400ee"}, + {file = "PyYAML-5.3.1.tar.gz", hash = "sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d"}, +] +regex = [ + {file = "regex-2020.10.15-cp27-cp27m-win32.whl", hash = "sha256:e935a166a5f4c02afe3f7e4ce92ce5a786f75c6caa0c4ce09c922541d74b77e8"}, + {file = "regex-2020.10.15-cp27-cp27m-win_amd64.whl", hash = "sha256:d81be22d5d462b96a2aa5c512f741255ba182995efb0114e5a946fe254148df1"}, + {file = "regex-2020.10.15-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:6d4cdb6c20e752426b2e569128488c5046fb1b16b1beadaceea9815c36da0847"}, + {file = "regex-2020.10.15-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:25991861c6fef1e5fd0a01283cf5658c5e7f7aa644128e85243bc75304e91530"}, + {file = "regex-2020.10.15-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:6e9f72e0ee49f7d7be395bfa29e9533f0507a882e1e6bf302c0a204c65b742bf"}, + {file = "regex-2020.10.15-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:578ac6379e65eb8e6a85299b306c966c852712c834dc7eef0ba78d07a828f67b"}, + {file = "regex-2020.10.15-cp36-cp36m-win32.whl", hash = "sha256:65b6b018b07e9b3b6a05c2c3bb7710ed66132b4df41926c243887c4f1ff303d5"}, + {file = "regex-2020.10.15-cp36-cp36m-win_amd64.whl", hash = "sha256:2f60ba5c33f00ce9be29a140e6f812e39880df8ba9cb92ad333f0016dbc30306"}, + {file = "regex-2020.10.15-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:5d4a3221f37520bb337b64a0632716e61b26c8ae6aaffceeeb7ad69c009c404b"}, + {file = "regex-2020.10.15-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:26b85672275d8c7a9d4ff93dbc4954f5146efdb2ecec89ad1de49439984dea14"}, + {file = "regex-2020.10.15-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:828618f3c3439c5e6ef8621e7c885ca561bbaaba90ddbb6a7dfd9e1ec8341103"}, + {file = "regex-2020.10.15-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:aef23aed9d4017cc74d37f703d57ce254efb4c8a6a01905f40f539220348abf9"}, + {file = "regex-2020.10.15-cp37-cp37m-win32.whl", hash = "sha256:6c72adb85adecd4522a488a751e465842cdd2a5606b65464b9168bf029a54272"}, + {file = "regex-2020.10.15-cp37-cp37m-win_amd64.whl", hash = "sha256:ef3a55b16c6450574734db92e0a3aca283290889934a23f7498eaf417e3af9f0"}, + {file = "regex-2020.10.15-cp38-cp38-manylinux1_i686.whl", hash = "sha256:8958befc139ac4e3f16d44ec386c490ea2121ed8322f4956f83dd9cad8e9b922"}, + {file = "regex-2020.10.15-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:3dd952f3f8dc01b72c0cf05b3631e05c50ac65ddd2afdf26551638e97502107b"}, + {file = "regex-2020.10.15-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:608d6c05452c0e6cc49d4d7407b4767963f19c4d2230fa70b7201732eedc84f2"}, + {file = "regex-2020.10.15-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:02686a2f0b1a4be0facdd0d3ad4dc6c23acaa0f38fb5470d892ae88584ba705c"}, + {file = "regex-2020.10.15-cp38-cp38-win32.whl", hash = "sha256:137da580d1e6302484be3ef41d72cf5c3ad22a076070051b7449c0e13ab2c482"}, + {file = "regex-2020.10.15-cp38-cp38-win_amd64.whl", hash = "sha256:20cdd7e1736f4f61a5161aa30d05ac108ab8efc3133df5eb70fe1e6a23ea1ca6"}, + {file = "regex-2020.10.15-cp39-cp39-manylinux1_i686.whl", hash = "sha256:85b733a1ef2b2e7001aff0e204a842f50ad699c061856a214e48cfb16ace7d0c"}, + {file = "regex-2020.10.15-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:af1f5e997dd1ee71fb6eb4a0fb6921bf7a778f4b62f1f7ef0d7445ecce9155d6"}, + {file = "regex-2020.10.15-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:b5eeaf4b5ef38fab225429478caf71f44d4a0b44d39a1aa4d4422cda23a9821b"}, + {file = "regex-2020.10.15-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:aeac7c9397480450016bc4a840eefbfa8ca68afc1e90648aa6efbfe699e5d3bb"}, + {file = "regex-2020.10.15-cp39-cp39-win32.whl", hash = "sha256:698f8a5a2815e1663d9895830a063098ae2f8f2655ae4fdc5dfa2b1f52b90087"}, + {file = "regex-2020.10.15-cp39-cp39-win_amd64.whl", hash = "sha256:a51e51eecdac39a50ede4aeed86dbef4776e3b73347d31d6ad0bc9648ba36049"}, + {file = "regex-2020.10.15.tar.gz", hash = "sha256:d25f5cca0f3af6d425c9496953445bf5b288bb5b71afc2b8308ad194b714c159"}, +] +reorder-python-imports = [ + {file = "reorder_python_imports-2.3.5-py2.py3-none-any.whl", hash = "sha256:6e8d3baba68c409ec87242757cf579a7ad2b133d1efed498be987b97ee385ac3"}, + {file = "reorder_python_imports-2.3.5.tar.gz", hash = "sha256:7c46593d39899e3fb249248b448bde93ee7417889904f015c0c5a738c23fd0e0"}, +] +requests = [ + {file = "requests-2.24.0-py2.py3-none-any.whl", hash = "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898"}, + {file = "requests-2.24.0.tar.gz", hash = "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b"}, +] +restructuredtext-lint = [ + {file = "restructuredtext_lint-1.3.1.tar.gz", hash = "sha256:470e53b64817211a42805c3a104d2216f6f5834b22fe7adb637d1de4d6501fb8"}, +] +"ruamel.yaml" = [ + {file = "ruamel.yaml-0.16.12-py2.py3-none-any.whl", hash = "sha256:012b9470a0ea06e4e44e99e7920277edf6b46eee0232a04487ea73a7386340a5"}, + {file = "ruamel.yaml-0.16.12.tar.gz", hash = "sha256:076cc0bc34f1966d920a49f18b52b6ad559fbe656a0748e3535cf7b3f29ebf9e"}, +] +"ruamel.yaml.clib" = [ + {file = "ruamel.yaml.clib-0.2.2-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:28116f204103cb3a108dfd37668f20abe6e3cafd0d3fd40dba126c732457b3cc"}, + {file = "ruamel.yaml.clib-0.2.2-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:daf21aa33ee9b351f66deed30a3d450ab55c14242cfdfcd377798e2c0d25c9f1"}, + {file = "ruamel.yaml.clib-0.2.2-cp27-cp27m-win32.whl", hash = "sha256:30dca9bbcbb1cc858717438218d11eafb78666759e5094dd767468c0d577a7e7"}, + {file = "ruamel.yaml.clib-0.2.2-cp27-cp27m-win_amd64.whl", hash = "sha256:f6061a31880c1ed6b6ce341215336e2f3d0c1deccd84957b6fa8ca474b41e89f"}, + {file = "ruamel.yaml.clib-0.2.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:73b3d43e04cc4b228fa6fa5d796409ece6fcb53a6c270eb2048109cbcbc3b9c2"}, + {file = "ruamel.yaml.clib-0.2.2-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:53b9dd1abd70e257a6e32f934ebc482dac5edb8c93e23deb663eac724c30b026"}, + {file = "ruamel.yaml.clib-0.2.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:839dd72545ef7ba78fd2aa1a5dd07b33696adf3e68fae7f31327161c1093001b"}, + {file = "ruamel.yaml.clib-0.2.2-cp35-cp35m-win32.whl", hash = "sha256:b1e981fe1aff1fd11627f531524826a4dcc1f26c726235a52fcb62ded27d150f"}, + {file = "ruamel.yaml.clib-0.2.2-cp35-cp35m-win_amd64.whl", hash = "sha256:4e52c96ca66de04be42ea2278012a2342d89f5e82b4512fb6fb7134e377e2e62"}, + {file = "ruamel.yaml.clib-0.2.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:a873e4d4954f865dcb60bdc4914af7eaae48fb56b60ed6daa1d6251c72f5337c"}, + {file = "ruamel.yaml.clib-0.2.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:ab845f1f51f7eb750a78937be9f79baea4a42c7960f5a94dde34e69f3cce1988"}, + {file = "ruamel.yaml.clib-0.2.2-cp36-cp36m-win32.whl", hash = "sha256:e9f7d1d8c26a6a12c23421061f9022bb62704e38211fe375c645485f38df34a2"}, + {file = "ruamel.yaml.clib-0.2.2-cp36-cp36m-win_amd64.whl", hash = "sha256:2602e91bd5c1b874d6f93d3086f9830f3e907c543c7672cf293a97c3fabdcd91"}, + {file = "ruamel.yaml.clib-0.2.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:44c7b0498c39f27795224438f1a6be6c5352f82cb887bc33d962c3a3acc00df6"}, + {file = "ruamel.yaml.clib-0.2.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:8e8fd0a22c9d92af3a34f91e8a2594eeb35cba90ab643c5e0e643567dc8be43e"}, + {file = "ruamel.yaml.clib-0.2.2-cp37-cp37m-win32.whl", hash = "sha256:464e66a04e740d754170be5e740657a3b3b6d2bcc567f0c3437879a6e6087ff6"}, + {file = "ruamel.yaml.clib-0.2.2-cp37-cp37m-win_amd64.whl", hash = "sha256:52ae5739e4b5d6317b52f5b040b1b6639e8af68a5b8fd606a8b08658fbd0cab5"}, + {file = "ruamel.yaml.clib-0.2.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4df5019e7783d14b79217ad9c56edf1ba7485d614ad5a385d1b3c768635c81c0"}, + {file = "ruamel.yaml.clib-0.2.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:5254af7d8bdf4d5484c089f929cb7f5bafa59b4f01d4f48adda4be41e6d29f99"}, + {file = "ruamel.yaml.clib-0.2.2-cp38-cp38-win32.whl", hash = "sha256:74161d827407f4db9072011adcfb825b5258a5ccb3d2cd518dd6c9edea9e30f1"}, + {file = "ruamel.yaml.clib-0.2.2-cp38-cp38-win_amd64.whl", hash = "sha256:058a1cc3df2a8aecc12f983a48bda99315cebf55a3b3a5463e37bb599b05727b"}, + {file = "ruamel.yaml.clib-0.2.2.tar.gz", hash = "sha256:2d24bd98af676f4990c4d715bcdc2a60b19c56a3fb3a763164d2d8ca0e806ba7"}, +] +safety = [ + {file = "safety-1.9.0-py2.py3-none-any.whl", hash = "sha256:86c1c4a031fe35bd624fce143fbe642a0234d29f7cbf7a9aa269f244a955b087"}, + {file = "safety-1.9.0.tar.gz", hash = "sha256:23bf20690d4400edc795836b0c983c2b4cbbb922233108ff925b7dd7750f00c9"}, +] +six = [ + {file = "six-1.15.0-py2.py3-none-any.whl", hash = "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"}, + {file = "six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"}, +] +smmap = [ + {file = "smmap-3.0.4-py2.py3-none-any.whl", hash = "sha256:54c44c197c819d5ef1991799a7e30b662d1e520f2ac75c9efbeb54a742214cf4"}, + {file = "smmap-3.0.4.tar.gz", hash = "sha256:9c98bbd1f9786d22f14b3d4126894d56befb835ec90cef151af566c7e19b5d24"}, +] +snowballstemmer = [ + {file = "snowballstemmer-2.0.0-py2.py3-none-any.whl", hash = "sha256:209f257d7533fdb3cb73bdbd24f436239ca3b2fa67d56f6ff88e86be08cc5ef0"}, + {file = "snowballstemmer-2.0.0.tar.gz", hash = "sha256:df3bac3df4c2c01363f3dd2cfa78cce2840a79b9f1c2d2de9ce8d31683992f52"}, +] +sphinx = [ + {file = "Sphinx-3.2.1-py3-none-any.whl", hash = "sha256:ce6fd7ff5b215af39e2fcd44d4a321f6694b4530b6f2b2109b64d120773faea0"}, + {file = "Sphinx-3.2.1.tar.gz", hash = "sha256:321d6d9b16fa381a5306e5a0b76cd48ffbc588e6340059a729c6fdd66087e0e8"}, +] +sphinx-autobuild = [ + {file = "sphinx-autobuild-2020.9.1.tar.gz", hash = "sha256:4b184a7db893f2100bbd831991ae54ca89167a2b9ce68faea71eaa9e37716aed"}, + {file = "sphinx_autobuild-2020.9.1-py3-none-any.whl", hash = "sha256:df5c72cb8b8fc9b31279c4619780c4e95029be6de569ff60a8bb2e99d20f63dd"}, +] +sphinx-rtd-theme = [ + {file = "sphinx_rtd_theme-0.5.0-py2.py3-none-any.whl", hash = "sha256:373413d0f82425aaa28fb288009bf0d0964711d347763af2f1b65cafcb028c82"}, + {file = "sphinx_rtd_theme-0.5.0.tar.gz", hash = "sha256:22c795ba2832a169ca301cd0a083f7a434e09c538c70beb42782c073651b707d"}, +] +sphinxcontrib-applehelp = [ + {file = "sphinxcontrib-applehelp-1.0.2.tar.gz", hash = "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58"}, + {file = "sphinxcontrib_applehelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a"}, +] +sphinxcontrib-devhelp = [ + {file = "sphinxcontrib-devhelp-1.0.2.tar.gz", hash = "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4"}, + {file = "sphinxcontrib_devhelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e"}, +] +sphinxcontrib-htmlhelp = [ + {file = "sphinxcontrib-htmlhelp-1.0.3.tar.gz", hash = "sha256:e8f5bb7e31b2dbb25b9cc435c8ab7a79787ebf7f906155729338f3156d93659b"}, + {file = "sphinxcontrib_htmlhelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:3c0bc24a2c41e340ac37c85ced6dafc879ab485c095b1d65d2461ac2f7cca86f"}, +] +sphinxcontrib-jsmath = [ + {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, + {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, +] +sphinxcontrib-qthelp = [ + {file = "sphinxcontrib-qthelp-1.0.3.tar.gz", hash = "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72"}, + {file = "sphinxcontrib_qthelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"}, +] +sphinxcontrib-serializinghtml = [ + {file = "sphinxcontrib-serializinghtml-1.1.4.tar.gz", hash = "sha256:eaa0eccc86e982a9b939b2b82d12cc5d013385ba5eadcc7e4fed23f4405f77bc"}, + {file = "sphinxcontrib_serializinghtml-1.1.4-py2.py3-none-any.whl", hash = "sha256:f242a81d423f59617a8e5cf16f5d4d74e28ee9a66f9e5b637a18082991db5a9a"}, +] +stevedore = [ + {file = "stevedore-3.2.2-py3-none-any.whl", hash = "sha256:5e1ab03eaae06ef6ce23859402de785f08d97780ed774948ef16c4652c41bc62"}, + {file = "stevedore-3.2.2.tar.gz", hash = "sha256:f845868b3a3a77a2489d226568abe7328b5c2d4f6a011cc759dfa99144a521f0"}, +] +toml = [ + {file = "toml-0.10.1-py2.py3-none-any.whl", hash = "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88"}, + {file = "toml-0.10.1.tar.gz", hash = "sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f"}, +] +tornado = [ + {file = "tornado-6.0.4-cp35-cp35m-win32.whl", hash = "sha256:5217e601700f24e966ddab689f90b7ea4bd91ff3357c3600fa1045e26d68e55d"}, + {file = "tornado-6.0.4-cp35-cp35m-win_amd64.whl", hash = "sha256:c98232a3ac391f5faea6821b53db8db461157baa788f5d6222a193e9456e1740"}, + {file = "tornado-6.0.4-cp36-cp36m-win32.whl", hash = "sha256:5f6a07e62e799be5d2330e68d808c8ac41d4a259b9cea61da4101b83cb5dc673"}, + {file = "tornado-6.0.4-cp36-cp36m-win_amd64.whl", hash = "sha256:c952975c8ba74f546ae6de2e226ab3cc3cc11ae47baf607459a6728585bb542a"}, + {file = "tornado-6.0.4-cp37-cp37m-win32.whl", hash = "sha256:2c027eb2a393d964b22b5c154d1a23a5f8727db6fda837118a776b29e2b8ebc6"}, + {file = "tornado-6.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:5618f72e947533832cbc3dec54e1dffc1747a5cb17d1fd91577ed14fa0dc081b"}, + {file = "tornado-6.0.4-cp38-cp38-win32.whl", hash = "sha256:22aed82c2ea340c3771e3babc5ef220272f6fd06b5108a53b4976d0d722bcd52"}, + {file = "tornado-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:c58d56003daf1b616336781b26d184023ea4af13ae143d9dda65e31e534940b9"}, + {file = "tornado-6.0.4.tar.gz", hash = "sha256:0fe2d45ba43b00a41cd73f8be321a44936dc1aba233dee979f17a042b83eb6dc"}, +] +typed-ast = [ + {file = "typed_ast-1.4.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3"}, + {file = "typed_ast-1.4.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb"}, + {file = "typed_ast-1.4.1-cp35-cp35m-win32.whl", hash = "sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919"}, + {file = "typed_ast-1.4.1-cp35-cp35m-win_amd64.whl", hash = "sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01"}, + {file = "typed_ast-1.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75"}, + {file = "typed_ast-1.4.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652"}, + {file = "typed_ast-1.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7"}, + {file = "typed_ast-1.4.1-cp36-cp36m-win32.whl", hash = "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1"}, + {file = "typed_ast-1.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa"}, + {file = "typed_ast-1.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614"}, + {file = "typed_ast-1.4.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41"}, + {file = "typed_ast-1.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b"}, + {file = "typed_ast-1.4.1-cp37-cp37m-win32.whl", hash = "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe"}, + {file = "typed_ast-1.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355"}, + {file = "typed_ast-1.4.1-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6"}, + {file = "typed_ast-1.4.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907"}, + {file = "typed_ast-1.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d"}, + {file = "typed_ast-1.4.1-cp38-cp38-win32.whl", hash = "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c"}, + {file = "typed_ast-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4"}, + {file = "typed_ast-1.4.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34"}, + {file = "typed_ast-1.4.1.tar.gz", hash = "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b"}, +] +typeguard = [ + {file = "typeguard-2.10.0-py3-none-any.whl", hash = "sha256:a75c6d86ac9d1faf85c5ae952de473e5d26824dda6d4394ff6bc676849cfb939"}, + {file = "typeguard-2.10.0.tar.gz", hash = "sha256:d830132dcd544d3f8a2a842ea739eaa0d7c099fcebb9dcdf3802f4c9929d8191"}, +] +typing-extensions = [ + {file = "typing_extensions-3.7.4.3-py2-none-any.whl", hash = "sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f"}, + {file = "typing_extensions-3.7.4.3-py3-none-any.whl", hash = "sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918"}, + {file = "typing_extensions-3.7.4.3.tar.gz", hash = "sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c"}, +] +urllib3 = [ + {file = "urllib3-1.25.11-py2.py3-none-any.whl", hash = "sha256:f5321fbe4bf3fefa0efd0bfe7fb14e90909eb62a48ccda331726b4319897dd5e"}, + {file = "urllib3-1.25.11.tar.gz", hash = "sha256:8d7eaa5a82a1cac232164990f04874c594c9453ec55eef02eab885aa02fc17a2"}, +] +virtualenv = [ + {file = "virtualenv-20.0.35-py2.py3-none-any.whl", hash = "sha256:0ebc633426d7468664067309842c81edab11ae97fcaf27e8ad7f5748c89b431b"}, + {file = "virtualenv-20.0.35.tar.gz", hash = "sha256:2a72c80fa2ad8f4e2985c06e6fc12c3d60d060e410572f553c90619b0f6efaf3"}, +] +xdoctest = [ + {file = "xdoctest-0.15.0-py2.py3-none-any.whl", hash = "sha256:695ea04303a48cbb319709270d43f7bae7f3de3701aec73f09d90a216499992e"}, + {file = "xdoctest-0.15.0.tar.gz", hash = "sha256:7f0a184d403b69b166ebec1aadb13c98c96c59101e974ae2e4db4c3a803ec371"}, +] +zipp = [ + {file = "zipp-3.3.1-py3-none-any.whl", hash = "sha256:16522f69653f0d67be90e8baa4a46d66389145b734345d68a257da53df670903"}, + {file = "zipp-3.3.1.tar.gz", hash = "sha256:c1532a8030c32fd52ff6a288d855fe7adef5823ba1d26a29a68fd6314aa72baa"}, +] diff --git a/pylintrc b/pylintrc deleted file mode 100644 index 8fcef624..00000000 --- a/pylintrc +++ /dev/null @@ -1,43 +0,0 @@ -[MASTER] -# Use a conservative default here; 2 should speed up most setups and not hurt -# any too bad. Override on command line as appropriate. -jobs=2 -persistent=no -extension-pkg-whitelist=ciso8601 - -[BASIC] -good-names=id,i,j,k - -[MESSAGES CONTROL] -# Reasons disabled: -# format - handled by black -# duplicate-code - unavoidable -# too-many-* - are not enforced for the sake of readability -# too-few-* - same as too-many-* -# inconsistent-return-statements - doesn't handle raise -# unnecessary-pass - readability for functions which only contain pass -# useless-object-inheritance - should be removed while droping Python 2 -# wrong-import-order - isort guards this -disable= - format, - duplicate-code, - inconsistent-return-statements, - too-few-public-methods, - too-many-ancestors, - too-many-arguments, - too-many-branches, - too-many-instance-attributes, - too-many-lines, - too-many-locals, - too-many-public-methods, - too-many-return-statements, - too-many-statements, - too-many-boolean-expressions, - unnecessary-pass, - useless-object-inheritance, - -[FORMAT] -expected-line-ending-format=LF - -[EXCEPTIONS] -overgeneral-exceptions=PyiCloudException diff --git a/pyproject.toml b/pyproject.toml index 2dfcc69e..fd33d205 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,21 +1,76 @@ -[tool.black] -line-length = 88 -target-version = ["py27", "py33", "py34", "py35", "py36", "py37", "py38"] -exclude = ''' - -( - /( - \.eggs - | \.git - | \.hg - | \.mypy_cache - | \.tox - | \.venv - | _build - | buck-out - | build - | dist - )/ - | exceptions.py -) -''' +[tool.poetry] +name = "python-synology" +version = "1.0.0" +description = "Python API for communication with Synology DSM" +authors = ["Quentin POLLET (Quentame)", "FG van Zeelst (ProtoThis)"] +license = "MIT" +readme = "README.rst" +homepage = "https://github.com/ProtoThis/python-synology" +repository = "https://github.com/ProtoThis/python-synology" +documentation = "https://python-synology.readthedocs.io" +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Topic :: Software Development :: Libraries", +] +keywords=["synology-dsm", "synology"] +packages = [ + { include = "synology_dsm", from = "src" }, +] + +[tool.poetry.urls] +Changelog = "https://github.com/ProtoThis/python-synology/releases" + +[tool.poetry.dependencies] +python = "^3.7.0" +requests = "^2.24.0" +urllib3 = "^1.25.10" + +[tool.poetry.dev-dependencies] +pytest = "^6.1.1" +coverage = {extras = ["toml"], version = "^5.3"} +safety = "^1.9.0" +mypy = "^0.782" +typeguard = "^2.9.1" +xdoctest = {extras = ["colors"], version = "^0.15.0"} +sphinx = "^3.2.1" +sphinx-autobuild = "^2020.9.1" +pre-commit = "^2.7.1" +flake8 = "^3.8.4" +black = "^20.8b1" +flake8-bandit = "^2.1.2" +flake8-bugbear = "^20.1.4" +flake8-docstrings = "^1.5.0" +flake8-rst-docstrings = "^0.0.14" +pep8-naming = "^0.11.1" +darglint = "^1.5.5" +reorder-python-imports = "^2.3.5" +pre-commit-hooks = "^3.2.0" +sphinx-rtd-theme = "^0.5.0" +Pygments = "^2.7.1" + +[tool.poetry.scripts] +python-synology = "synology_dsm.__main__:main" + +[tool.coverage.paths] +source = ["src", "*/site-packages"] + +[tool.coverage.run] +branch = true +source = ["synology_dsm"] + +[tool.coverage.report] +show_missing = true +fail_under = 80 + +[build-system] +requires = ["poetry>=0.12"] +build-backend = "poetry.masonry.api" diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index ca3f09a8..00000000 --- a/requirements.txt +++ /dev/null @@ -1,3 +0,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_all.txt b/requirements_all.txt deleted file mode 100644 index daefbd08..00000000 --- a/requirements_all.txt +++ /dev/null @@ -1,2 +0,0 @@ --r requirements.txt --r requirements_test.txt diff --git a/requirements_test.txt b/requirements_test.txt deleted file mode 100644 index d69693d8..00000000 --- a/requirements_test.txt +++ /dev/null @@ -1,4 +0,0 @@ -pytest -pylint>=2.6.0 -pylint-strict-informational==0.1 -black==20.8b1 diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index b7e88a6a..00000000 --- a/setup.cfg +++ /dev/null @@ -1,3 +0,0 @@ -[tool:pytest] -testpaths = tests -norecursedirs=.git .tox build lib diff --git a/setup.py b/setup.py deleted file mode 100644 index 64483b39..00000000 --- a/setup.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env python -"""Synology DSM setup.""" - -# NOTE(ProtoThis) Guidelines for Major.Minor.Micro -# - Major means an API contract change -# - Minor means API bugfix or new functionality -# - Micro means change of any kind (unless significant enough for a minor/major). - -from setuptools import setup, find_packages - -REPO_URL = "https://github.com/ProtoThis/python-synology" -VERSION = "1.0.0" - -with open("requirements.txt") as f: - required = f.read().splitlines() - -with open("README.rst", encoding="utf-8") as f: - long_description = f.read() - -setup( - name="python-synology", - version=VERSION, - url=REPO_URL, - download_url=REPO_URL + "/tarball/" + VERSION, - description="Python API for communication with Synology DSM", - long_description=long_description, - author="Quentin POLLET (Quentame) & FG van Zeelst (ProtoThis)", - packages=find_packages("src"), - package_dir={"": "src"}, - install_requires=required, - 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 :: 3 :: Only", - "Programming Language :: Python :: 3", - "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/src/synology_dsm/api/storage/storage.py b/src/synology_dsm/api/storage/storage.py index ed2ce661..786f3d16 100644 --- a/src/synology_dsm/api/storage/storage.py +++ b/src/synology_dsm/api/storage/storage.py @@ -1,5 +1,4 @@ """DSM Storage data.""" - from synology_dsm.helpers import SynoFormatHelper diff --git a/src/synology_dsm/api/surveillance_station/__init__.py b/src/synology_dsm/api/surveillance_station/__init__.py index db0823f8..c89cd73c 100644 --- a/src/synology_dsm/api/surveillance_station/__init__.py +++ b/src/synology_dsm/api/surveillance_station/__init__.py @@ -2,7 +2,8 @@ import urllib from .camera import SynoCamera -from .const import MOTION_DETECTION_BY_SURVEILLANCE, MOTION_DETECTION_DISABLED +from .const import MOTION_DETECTION_BY_SURVEILLANCE +from .const import MOTION_DETECTION_DISABLED class SynoSurveillanceStation: diff --git a/src/synology_dsm/api/surveillance_station/camera.py b/src/synology_dsm/api/surveillance_station/camera.py index 0c32812e..c3859ace 100644 --- a/src/synology_dsm/api/surveillance_station/camera.py +++ b/src/synology_dsm/api/surveillance_station/camera.py @@ -1,5 +1,6 @@ """SurveillanceStation camera.""" -from .const import RECORDING_STATUS, MOTION_DETECTION_DISABLED +from .const import MOTION_DETECTION_DISABLED +from .const import RECORDING_STATUS class SynoCamera: diff --git a/src/synology_dsm/const.py b/src/synology_dsm/const.py index 9d4609b9..0674adfd 100644 --- a/src/synology_dsm/const.py +++ b/src/synology_dsm/const.py @@ -1,5 +1,4 @@ """Library constants.""" - # APIs API_INFO = "SYNO.API.Info" API_AUTH = "SYNO.API.Auth" diff --git a/src/synology_dsm/exceptions.py b/src/synology_dsm/exceptions.py index 799fdc99..d70998e1 100644 --- a/src/synology_dsm/exceptions.py +++ b/src/synology_dsm/exceptions.py @@ -1,8 +1,17 @@ """Library exceptions.""" -from .const import API_AUTH, ERROR_AUTH, ERROR_COMMON, ERROR_DOWNLOAD_SEARCH, ERROR_DOWNLOAD_TASK, ERROR_FILE, ERROR_SURVEILLANCE, ERROR_VIRTUALIZATION +from .const import API_AUTH +from .const import ERROR_AUTH +from .const import ERROR_COMMON +from .const import ERROR_DOWNLOAD_SEARCH +from .const import ERROR_DOWNLOAD_TASK +from .const import ERROR_FILE +from .const import ERROR_SURVEILLANCE +from .const import ERROR_VIRTUALIZATION + class SynologyDSMException(Exception): """Generic Synology DSM exception.""" + def __init__(self, api, code, details=None): reason = ERROR_COMMON.get(code) if api and not reason: @@ -21,13 +30,15 @@ def __init__(self, api, code, details=None): reason = ERROR_VIRTUALIZATION.get(code) if not reason: reason = "Unknown" - - error_message={"api": api, "code": code, "reason": reason, "details": details} + + error_message = {"api": api, "code": code, "reason": reason, "details": details} super().__init__(error_message) + # Request class SynologyDSMRequestException(SynologyDSMException): """Request exception.""" + def __init__(self, exception): ex_class = exception.__class__.__name__ ex_reason = exception.args[0] @@ -35,26 +46,33 @@ def __init__(self, exception): ex_reason = exception.args[0].reason super().__init__(None, -1, f"{ex_class} = {ex_reason}") + # API class SynologyDSMAPINotExistsException(SynologyDSMException): """API not exists exception.""" + def __init__(self, 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().__init__(api, code, details) + # Login class SynologyDSMLoginFailedException(SynologyDSMException): """Failed to login exception.""" + def __init__(self, code, details=None): super().__init__(API_AUTH, code, details) class SynologyDSMLoginInvalidException(SynologyDSMLoginFailedException): """Invalid password & not admin account exception.""" + def __init__(self, username): message = f"Invalid password or not admin account: {username}" super().__init__(400, message) @@ -62,6 +80,7 @@ def __init__(self, username): class SynologyDSMLoginDisabledAccountException(SynologyDSMLoginFailedException): """Guest & disabled account exception.""" + def __init__(self, username): message = f"Guest or disabled account: {username}" super().__init__(401, message) @@ -69,6 +88,7 @@ def __init__(self, username): class SynologyDSMLoginPermissionDeniedException(SynologyDSMLoginFailedException): """No access to login exception.""" + def __init__(self, username): message = f"Permission denied for account: {username}" super().__init__(402, message) @@ -76,6 +96,7 @@ def __init__(self, username): class SynologyDSMLogin2SARequiredException(SynologyDSMLoginFailedException): """2SA required to login exception.""" + def __init__(self, username): message = f"Two-step authentication required for account: {username}" super().__init__(403, message) @@ -83,6 +104,7 @@ def __init__(self, username): class SynologyDSMLogin2SAFailedException(SynologyDSMLoginFailedException): """2SA code failed exception.""" + def __init__(self): message = "Two-step authentication failed, retry with a new pass code" super().__init__(404, message) diff --git a/src/synology_dsm/synology_dsm.py b/src/synology_dsm/synology_dsm.py index 163cb208..f1863b8e 100644 --- a/src/synology_dsm/synology_dsm.py +++ b/src/synology_dsm/synology_dsm.py @@ -1,24 +1,12 @@ """Class to interact with Synology DSM.""" +import socket from json import JSONDecodeError from urllib.parse import quote -import socket import urllib3 from requests import Session from requests.exceptions import RequestException -from .exceptions import ( - SynologyDSMAPIErrorException, - SynologyDSMAPINotExistsException, - SynologyDSMRequestException, - SynologyDSMLoginFailedException, - SynologyDSMLoginInvalidException, - SynologyDSMLoginDisabledAccountException, - SynologyDSMLoginPermissionDeniedException, - SynologyDSMLogin2SARequiredException, - SynologyDSMLogin2SAFailedException, -) - from .api.core.security import SynoCoreSecurity from .api.core.share import SynoCoreShare from .api.core.system import SynoCoreSystem @@ -29,7 +17,17 @@ from .api.dsm.network import SynoDSMNetwork from .api.storage.storage import SynoStorage from .api.surveillance_station import SynoSurveillanceStation -from .const import API_AUTH, API_INFO +from .const import API_AUTH +from .const import API_INFO +from .exceptions import SynologyDSMAPIErrorException +from .exceptions import SynologyDSMAPINotExistsException +from .exceptions import SynologyDSMLogin2SAFailedException +from .exceptions import SynologyDSMLogin2SARequiredException +from .exceptions import SynologyDSMLoginDisabledAccountException +from .exceptions import SynologyDSMLoginFailedException +from .exceptions import SynologyDSMLoginInvalidException +from .exceptions import SynologyDSMLoginPermissionDeniedException +from .exceptions import SynologyDSMRequestException class SynologyDSM: @@ -204,7 +202,7 @@ def _request( method: str, params: dict = None, retry_once: bool = True, - **kwargs + **kwargs, ): """Handles API request.""" # Discover existing APIs diff --git a/tests/__init__.py b/tests/__init__.py index 066b4f33..a1966f24 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -2,69 +2,67 @@ from json import JSONDecodeError from urllib.parse import urlencode -from requests.exceptions import ConnectionError as ConnError, RequestException, SSLError - +from requests.exceptions import ConnectionError as ConnError +from requests.exceptions import RequestException +from requests.exceptions import SSLError + +from .api_data.dsm_5 import DSM_5_API_INFO +from .api_data.dsm_5 import DSM_5_AUTH_LOGIN +from .api_data.dsm_5 import DSM_5_AUTH_LOGIN_2SA +from .api_data.dsm_5 import DSM_5_AUTH_LOGIN_2SA_OTP +from .api_data.dsm_5 import DSM_5_CORE_UTILIZATION +from .api_data.dsm_5 import DSM_5_DSM_INFORMATION +from .api_data.dsm_5 import DSM_5_DSM_NETWORK +from .api_data.dsm_5 import DSM_5_STORAGE_STORAGE_DS410J_RAID5_4DISKS_1VOL +from .api_data.dsm_6 import DSM_6_API_INFO +from .api_data.dsm_6 import DSM_6_API_INFO_SURVEILLANCE_STATION +from .api_data.dsm_6 import DSM_6_AUTH_LOGIN +from .api_data.dsm_6 import DSM_6_AUTH_LOGIN_2SA +from .api_data.dsm_6 import DSM_6_AUTH_LOGIN_2SA_OTP +from .api_data.dsm_6 import DSM_6_CORE_SECURITY +from .api_data.dsm_6 import DSM_6_CORE_SECURITY_UPDATE_OUTOFDATE +from .api_data.dsm_6 import DSM_6_CORE_SHARE +from .api_data.dsm_6 import DSM_6_CORE_SYSTEM_DS918_PLUS +from .api_data.dsm_6 import DSM_6_CORE_UPGRADE +from .api_data.dsm_6 import DSM_6_CORE_UTILIZATION +from .api_data.dsm_6 import DSM_6_CORE_UTILIZATION_ERROR_1055 +from .api_data.dsm_6 import DSM_6_DOWNLOAD_STATION_INFO_CONFIG +from .api_data.dsm_6 import DSM_6_DOWNLOAD_STATION_INFO_INFO +from .api_data.dsm_6 import DSM_6_DOWNLOAD_STATION_STAT_INFO +from .api_data.dsm_6 import DSM_6_DOWNLOAD_STATION_TASK_LIST +from .api_data.dsm_6 import DSM_6_DSM_INFORMATION +from .api_data.dsm_6 import DSM_6_DSM_NETWORK +from .api_data.dsm_6 import ( + DSM_6_STORAGE_STORAGE_DS1515_PLUS_SHR2_10DISKS_1VOL_WITH_EXPANSION, +) +from .api_data.dsm_6 import DSM_6_STORAGE_STORAGE_DS1819_PLUS_SHR2_8DISKS_1VOL +from .api_data.dsm_6 import DSM_6_STORAGE_STORAGE_DS213_PLUS_SHR1_2DISKS_2VOLS +from .api_data.dsm_6 import DSM_6_STORAGE_STORAGE_DS918_PLUS_RAID5_3DISKS_1VOL +from .api_data.dsm_6 import DSM_6_SURVEILLANCE_STATION_CAMERA_EVENT_MD_PARAM_SAVE +from .api_data.dsm_6 import DSM_6_SURVEILLANCE_STATION_CAMERA_EVENT_MOTION_ENUM +from .api_data.dsm_6 import DSM_6_SURVEILLANCE_STATION_CAMERA_GET_LIVE_VIEW_PATH +from .api_data.dsm_6 import DSM_6_SURVEILLANCE_STATION_CAMERA_LIST +from .api_data.dsm_6 import DSM_6_SURVEILLANCE_STATION_HOME_MODE_GET_INFO +from .api_data.dsm_6 import DSM_6_SURVEILLANCE_STATION_HOME_MODE_SWITCH +from .const import DEVICE_TOKEN +from .const import ERROR_AUTH_INVALID_CREDENTIALS +from .const import ERROR_AUTH_MAX_TRIES +from .const import ERROR_AUTH_OTP_AUTHENTICATE_FAILED +from .const import ERROR_INSUFFICIENT_USER_PRIVILEGE from synology_dsm import SynologyDSM -from synology_dsm.exceptions import SynologyDSMRequestException from synology_dsm.api.core.security import SynoCoreSecurity from synology_dsm.api.core.share import SynoCoreShare from synology_dsm.api.core.system import SynoCoreSystem -from synology_dsm.api.core.utilization import SynoCoreUtilization from synology_dsm.api.core.upgrade import SynoCoreUpgrade +from synology_dsm.api.core.utilization import SynoCoreUtilization +from synology_dsm.api.download_station import SynoDownloadStation from synology_dsm.api.dsm.information import SynoDSMInformation from synology_dsm.api.dsm.network import SynoDSMNetwork -from synology_dsm.api.download_station import SynoDownloadStation from synology_dsm.api.storage.storage import SynoStorage from synology_dsm.api.surveillance_station import SynoSurveillanceStation -from synology_dsm.const import API_AUTH, API_INFO - -from .const import ( - ERROR_INSUFFICIENT_USER_PRIVILEGE, - ERROR_AUTH_INVALID_CREDENTIALS, - ERROR_AUTH_MAX_TRIES, - ERROR_AUTH_OTP_AUTHENTICATE_FAILED, - DEVICE_TOKEN, -) -from .api_data.dsm_6 import ( - DSM_6_API_INFO, - DSM_6_AUTH_LOGIN, - DSM_6_AUTH_LOGIN_2SA, - DSM_6_AUTH_LOGIN_2SA_OTP, - DSM_6_DSM_INFORMATION, - DSM_6_DSM_NETWORK, - DSM_6_CORE_UTILIZATION, - DSM_6_CORE_UTILIZATION_ERROR_1055, - DSM_6_CORE_SECURITY, - DSM_6_CORE_SECURITY_UPDATE_OUTOFDATE, - DSM_6_CORE_SYSTEM_DS918_PLUS, - DSM_6_CORE_UPGRADE, - DSM_6_STORAGE_STORAGE_DS213_PLUS_SHR1_2DISKS_2VOLS, - DSM_6_STORAGE_STORAGE_DS918_PLUS_RAID5_3DISKS_1VOL, - DSM_6_STORAGE_STORAGE_DS1819_PLUS_SHR2_8DISKS_1VOL, - DSM_6_STORAGE_STORAGE_DS1515_PLUS_SHR2_10DISKS_1VOL_WITH_EXPANSION, - DSM_6_CORE_SHARE, - DSM_6_API_INFO_SURVEILLANCE_STATION, - DSM_6_SURVEILLANCE_STATION_CAMERA_EVENT_MOTION_ENUM, - DSM_6_SURVEILLANCE_STATION_CAMERA_GET_LIVE_VIEW_PATH, - DSM_6_SURVEILLANCE_STATION_CAMERA_EVENT_MD_PARAM_SAVE, - DSM_6_SURVEILLANCE_STATION_CAMERA_LIST, - DSM_6_SURVEILLANCE_STATION_HOME_MODE_GET_INFO, - DSM_6_SURVEILLANCE_STATION_HOME_MODE_SWITCH, - DSM_6_DOWNLOAD_STATION_INFO_INFO, - DSM_6_DOWNLOAD_STATION_INFO_CONFIG, - DSM_6_DOWNLOAD_STATION_STAT_INFO, - DSM_6_DOWNLOAD_STATION_TASK_LIST, -) -from .api_data.dsm_5 import ( - DSM_5_API_INFO, - DSM_5_AUTH_LOGIN, - DSM_5_AUTH_LOGIN_2SA, - DSM_5_AUTH_LOGIN_2SA_OTP, - DSM_5_DSM_NETWORK, - DSM_5_DSM_INFORMATION, - DSM_5_CORE_UTILIZATION, - DSM_5_STORAGE_STORAGE_DS410J_RAID5_4DISKS_1VOL, -) +from synology_dsm.const import API_AUTH +from synology_dsm.const import API_INFO +from synology_dsm.exceptions import SynologyDSMRequestException API_SWITCHER = { 5: { diff --git a/tests/api_data/dsm_5/__init__.py b/tests/api_data/dsm_5/__init__.py index 56200968..63174dc3 100644 --- a/tests/api_data/dsm_5/__init__.py +++ b/tests/api_data/dsm_5/__init__.py @@ -1,10 +1,8 @@ """DSM 5 datas.""" +from .const_5_api_auth import DSM_5_AUTH_LOGIN +from .const_5_api_auth import DSM_5_AUTH_LOGIN_2SA +from .const_5_api_auth import DSM_5_AUTH_LOGIN_2SA_OTP from .const_5_api_info import DSM_5_API_INFO -from .const_5_api_auth import ( - DSM_5_AUTH_LOGIN, - DSM_5_AUTH_LOGIN_2SA, - DSM_5_AUTH_LOGIN_2SA_OTP, -) from .core.const_5_core_utilization import DSM_5_CORE_UTILIZATION from .dsm.const_5_dsm_info import DSM_5_DSM_INFORMATION from .dsm.const_5_dsm_network import DSM_5_DSM_NETWORK diff --git a/tests/api_data/dsm_5/const_5_api_auth.py b/tests/api_data/dsm_5/const_5_api_auth.py index 7f197e8e..0db2b521 100644 --- a/tests/api_data/dsm_5/const_5_api_auth.py +++ b/tests/api_data/dsm_5/const_5_api_auth.py @@ -1,9 +1,7 @@ """DSM 5 SYNO.API.Auth data.""" -from tests.const import ( - SESSION_ID, - DEVICE_TOKEN, - ERROR_AUTH_OTP_NOT_SPECIFIED, -) +from tests.const import DEVICE_TOKEN +from tests.const import ERROR_AUTH_OTP_NOT_SPECIFIED +from tests.const import SESSION_ID # No synotoken for an unknown reason DSM_5_AUTH_LOGIN = { diff --git a/tests/api_data/dsm_6/__init__.py b/tests/api_data/dsm_6/__init__.py index 062f664d..0d4ba31f 100644 --- a/tests/api_data/dsm_6/__init__.py +++ b/tests/api_data/dsm_6/__init__.py @@ -1,27 +1,22 @@ """DSM 6 datas.""" +from .const_6_api_auth import DSM_6_AUTH_LOGIN +from .const_6_api_auth import DSM_6_AUTH_LOGIN_2SA +from .const_6_api_auth import DSM_6_AUTH_LOGIN_2SA_OTP from .const_6_api_info import DSM_6_API_INFO -from .const_6_api_auth import ( - DSM_6_AUTH_LOGIN, - DSM_6_AUTH_LOGIN_2SA, - DSM_6_AUTH_LOGIN_2SA_OTP, -) -from .core.const_6_core_utilization import ( - DSM_6_CORE_UTILIZATION, - DSM_6_CORE_UTILIZATION_ERROR_1055, -) -from .core.const_6_core_security import ( - DSM_6_CORE_SECURITY, - DSM_6_CORE_SECURITY_UPDATE_OUTOFDATE, -) -from .core.const_6_core_system import ( - DSM_6_CORE_SYSTEM_DS918_PLUS, - DSM_6_CORE_SYSTEM_DS218_PLAY, -) +from .core.const_6_core_security import DSM_6_CORE_SECURITY +from .core.const_6_core_security import DSM_6_CORE_SECURITY_UPDATE_OUTOFDATE +from .core.const_6_core_share import DSM_6_CORE_SHARE +from .core.const_6_core_system import DSM_6_CORE_SYSTEM_DS218_PLAY +from .core.const_6_core_system import DSM_6_CORE_SYSTEM_DS918_PLUS from .core.const_6_core_upgrade import DSM_6_CORE_UPGRADE +from .core.const_6_core_utilization import DSM_6_CORE_UTILIZATION +from .core.const_6_core_utilization import DSM_6_CORE_UTILIZATION_ERROR_1055 from .download_station.const_6_download_station_info import ( - DSM_6_DOWNLOAD_STATION_INFO_INFO, DSM_6_DOWNLOAD_STATION_INFO_CONFIG, ) +from .download_station.const_6_download_station_info import ( + DSM_6_DOWNLOAD_STATION_INFO_INFO, +) from .download_station.const_6_download_station_stat import ( DSM_6_DOWNLOAD_STATION_STAT_INFO, ) @@ -31,22 +26,35 @@ from .dsm.const_6_dsm_info import DSM_6_DSM_INFORMATION from .dsm.const_6_dsm_network import DSM_6_DSM_NETWORK from .storage.const_6_storage_storage import ( - DSM_6_STORAGE_STORAGE_DS213_PLUS_SHR1_2DISKS_2VOLS, - DSM_6_STORAGE_STORAGE_DS918_PLUS_RAID5_3DISKS_1VOL, DSM_6_STORAGE_STORAGE_DS1515_PLUS_SHR2_10DISKS_1VOL_WITH_EXPANSION, +) +from .storage.const_6_storage_storage import ( DSM_6_STORAGE_STORAGE_DS1819_PLUS_SHR2_8DISKS_1VOL, ) +from .storage.const_6_storage_storage import ( + DSM_6_STORAGE_STORAGE_DS213_PLUS_SHR1_2DISKS_2VOLS, +) +from .storage.const_6_storage_storage import ( + DSM_6_STORAGE_STORAGE_DS918_PLUS_RAID5_3DISKS_1VOL, +) from .surveillance_station.const_6_api_info import ( DSM_6_API_INFO as DSM_6_API_INFO_SURVEILLANCE_STATION, ) from .surveillance_station.const_6_surveillance_station_camera import ( - DSM_6_SURVEILLANCE_STATION_CAMERA_LIST, - DSM_6_SURVEILLANCE_STATION_CAMERA_GET_LIVE_VIEW_PATH, - DSM_6_SURVEILLANCE_STATION_CAMERA_EVENT_MOTION_ENUM, DSM_6_SURVEILLANCE_STATION_CAMERA_EVENT_MD_PARAM_SAVE, ) -from .core.const_6_core_share import DSM_6_CORE_SHARE +from .surveillance_station.const_6_surveillance_station_camera import ( + DSM_6_SURVEILLANCE_STATION_CAMERA_EVENT_MOTION_ENUM, +) +from .surveillance_station.const_6_surveillance_station_camera import ( + DSM_6_SURVEILLANCE_STATION_CAMERA_GET_LIVE_VIEW_PATH, +) +from .surveillance_station.const_6_surveillance_station_camera import ( + DSM_6_SURVEILLANCE_STATION_CAMERA_LIST, +) from .surveillance_station.const_6_surveillance_station_home_mode import ( DSM_6_SURVEILLANCE_STATION_HOME_MODE_GET_INFO, +) +from .surveillance_station.const_6_surveillance_station_home_mode import ( DSM_6_SURVEILLANCE_STATION_HOME_MODE_SWITCH, ) diff --git a/tests/api_data/dsm_6/const_6_api_auth.py b/tests/api_data/dsm_6/const_6_api_auth.py index ab642ba0..771ed332 100644 --- a/tests/api_data/dsm_6/const_6_api_auth.py +++ b/tests/api_data/dsm_6/const_6_api_auth.py @@ -1,10 +1,8 @@ """DSM 6 SYNO.API.Auth data.""" -from tests.const import ( - SESSION_ID, - DEVICE_TOKEN, - SYNO_TOKEN, - ERROR_AUTH_OTP_NOT_SPECIFIED, -) +from tests.const import DEVICE_TOKEN +from tests.const import ERROR_AUTH_OTP_NOT_SPECIFIED +from tests.const import SESSION_ID +from tests.const import SYNO_TOKEN DSM_6_AUTH_LOGIN = { diff --git a/tests/const.py b/tests/const.py index 6e938f53..16f7e869 100644 --- a/tests/const.py +++ b/tests/const.py @@ -1,5 +1,4 @@ """Test constants.""" - # API test data are localized in # `tests/api_data/dsm_[dsm_major_version]` # Data constant names should be like : diff --git a/tests/test_synology_dsm.py b/tests/test_synology_dsm.py index 78f0220a..2284ea33 100644 --- a/tests/test_synology_dsm.py +++ b/tests/test_synology_dsm.py @@ -1,33 +1,32 @@ """Synology DSM tests.""" from unittest import TestCase + import pytest +from . import SynologyDSMMock +from . import USER_MAX_TRY +from . import VALID_HOST +from . import VALID_HTTPS +from . import VALID_OTP +from . import VALID_PASSWORD +from . import VALID_PORT +from . import VALID_USER +from . import VALID_USER_2SA +from . import VALID_VERIFY_SSL +from .const import DEVICE_TOKEN +from .const import SESSION_ID +from .const import SYNO_TOKEN from synology_dsm.api.core.security import SynoCoreSecurity from synology_dsm.api.dsm.information import SynoDSMInformation -from synology_dsm.exceptions import ( - SynologyDSMRequestException, - SynologyDSMAPINotExistsException, - SynologyDSMAPIErrorException, - SynologyDSMLoginInvalidException, - SynologyDSMLogin2SARequiredException, - SynologyDSMLogin2SAFailedException, - SynologyDSMLoginFailedException, -) -from synology_dsm.const import API_AUTH, API_INFO - -from . import ( - SynologyDSMMock, - VALID_HOST, - VALID_PORT, - VALID_HTTPS, - VALID_VERIFY_SSL, - VALID_OTP, - VALID_PASSWORD, - VALID_USER, - VALID_USER_2SA, - USER_MAX_TRY, -) -from .const import SESSION_ID, DEVICE_TOKEN, SYNO_TOKEN +from synology_dsm.const import API_AUTH +from synology_dsm.const import API_INFO +from synology_dsm.exceptions import SynologyDSMAPIErrorException +from synology_dsm.exceptions import SynologyDSMAPINotExistsException +from synology_dsm.exceptions import SynologyDSMLogin2SAFailedException +from synology_dsm.exceptions import SynologyDSMLogin2SARequiredException +from synology_dsm.exceptions import SynologyDSMLoginFailedException +from synology_dsm.exceptions import SynologyDSMLoginInvalidException +from synology_dsm.exceptions import SynologyDSMRequestException # pylint: disable=no-self-use,protected-access diff --git a/tests/test_synology_dsm_5.py b/tests/test_synology_dsm_5.py index b713b1fc..2b8d299f 100644 --- a/tests/test_synology_dsm_5.py +++ b/tests/test_synology_dsm_5.py @@ -1,28 +1,25 @@ """Synology DSM tests.""" from unittest import TestCase -from synology_dsm.exceptions import ( - SynologyDSMRequestException, - SynologyDSMAPINotExistsException, - SynologyDSMAPIErrorException, - SynologyDSMLoginInvalidException, - SynologyDSMLogin2SARequiredException, - SynologyDSMLogin2SAFailedException, -) -from synology_dsm.const import API_AUTH, API_INFO - -from . import ( - SynologyDSMMock, - VALID_HOST, - VALID_PORT, - VALID_HTTPS, - VALID_VERIFY_SSL, - VALID_OTP, - VALID_PASSWORD, - VALID_USER, - VALID_USER_2SA, -) -from .const import SESSION_ID, DEVICE_TOKEN +from . import SynologyDSMMock +from . import VALID_HOST +from . import VALID_HTTPS +from . import VALID_OTP +from . import VALID_PASSWORD +from . import VALID_PORT +from . import VALID_USER +from . import VALID_USER_2SA +from . import VALID_VERIFY_SSL +from .const import DEVICE_TOKEN +from .const import SESSION_ID +from synology_dsm.const import API_AUTH +from synology_dsm.const import API_INFO +from synology_dsm.exceptions import SynologyDSMAPIErrorException +from synology_dsm.exceptions import SynologyDSMAPINotExistsException +from synology_dsm.exceptions import SynologyDSMLogin2SAFailedException +from synology_dsm.exceptions import SynologyDSMLogin2SARequiredException +from synology_dsm.exceptions import SynologyDSMLoginInvalidException +from synology_dsm.exceptions import SynologyDSMRequestException # pylint: disable=no-self-use,protected-access,anomalous-backslash-in-string class TestSynologyDSM(TestCase): From 546c0c2807a36ce78918cbd0427088969158c416 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Oct 2020 20:20:30 +0000 Subject: [PATCH 06/33] Bump pre-commit-hooks from 3.2.0 to 3.3.0 (#83) --- poetry.lock | 597 +++++++++++++++++++++++-------------------------- pyproject.toml | 2 +- 2 files changed, 281 insertions(+), 318 deletions(-) diff --git a/poetry.lock b/poetry.lock index 83b0016f..7cc47093 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,86 +1,85 @@ [[package]] -category = "dev" -description = "A configurable sidebar-enabled Sphinx theme" name = "alabaster" +version = "0.7.12" +description = "A configurable sidebar-enabled Sphinx theme" +category = "dev" optional = false python-versions = "*" -version = "0.7.12" [[package]] -category = "dev" -description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." name = "appdirs" +version = "1.4.4" +description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +category = "dev" optional = false python-versions = "*" -version = "1.4.4" [[package]] -category = "dev" -description = "Utilities for refactoring imports in python-like syntax." name = "aspy.refactor-imports" +version = "2.1.1" +description = "Utilities for refactoring imports in python-like syntax." +category = "dev" optional = false python-versions = ">=3.6.1" -version = "2.1.1" [package.dependencies] cached-property = "*" [[package]] -category = "dev" -description = "Atomic file writes." -marker = "sys_platform == \"win32\"" name = "atomicwrites" +version = "1.4.0" +description = "Atomic file writes." +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.4.0" [[package]] -category = "dev" -description = "Classes Without Boilerplate" name = "attrs" +version = "20.2.0" +description = "Classes Without Boilerplate" +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "20.2.0" [package.extras] -dev = ["coverage (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "sphinx", "sphinx-rtd-theme", "pre-commit"] +dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "sphinx", "sphinx-rtd-theme", "pre-commit"] docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"] -tests = ["coverage (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"] -tests_no_zope = ["coverage (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six"] +tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"] +tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six"] [[package]] -category = "dev" -description = "Internationalization utilities" name = "babel" +version = "2.8.0" +description = "Internationalization utilities" +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "2.8.0" [package.dependencies] pytz = ">=2015.7" [[package]] -category = "dev" -description = "Security oriented static analyser for python code." name = "bandit" +version = "1.6.2" +description = "Security oriented static analyser for python code." +category = "dev" optional = false python-versions = "*" -version = "1.6.2" [package.dependencies] +colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""} GitPython = ">=1.0.1" PyYAML = ">=3.13" -colorama = ">=0.3.9" six = ">=1.10.0" stevedore = ">=1.20.0" [[package]] -category = "dev" -description = "The uncompromising code formatter." name = "black" +version = "20.8b1" +description = "The uncompromising code formatter." +category = "dev" optional = false python-versions = ">=3.6" -version = "20.8b1" [package.dependencies] appdirs = "*" @@ -97,101 +96,98 @@ colorama = ["colorama (>=0.4.3)"] d = ["aiohttp (>=3.3.2)", "aiohttp-cors"] [[package]] -category = "dev" -description = "A decorator for caching properties in classes." name = "cached-property" +version = "1.5.2" +description = "A decorator for caching properties in classes." +category = "dev" optional = false python-versions = "*" -version = "1.5.2" [[package]] -category = "main" -description = "Python package for providing Mozilla's CA Bundle." name = "certifi" +version = "2020.6.20" +description = "Python package for providing Mozilla's CA Bundle." +category = "main" optional = false python-versions = "*" -version = "2020.6.20" [[package]] -category = "dev" -description = "Validate configuration and produce human readable error messages." name = "cfgv" +version = "3.2.0" +description = "Validate configuration and produce human readable error messages." +category = "dev" optional = false python-versions = ">=3.6.1" -version = "3.2.0" [[package]] -category = "main" -description = "Universal encoding detector for Python 2 and 3" name = "chardet" +version = "3.0.4" +description = "Universal encoding detector for Python 2 and 3" +category = "main" optional = false python-versions = "*" -version = "3.0.4" [[package]] -category = "dev" -description = "Composable command line interface toolkit" name = "click" +version = "7.1.2" +description = "Composable command line interface toolkit" +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "7.1.2" [[package]] -category = "dev" -description = "Cross-platform colored terminal text." -marker = "platform_system == \"Windows\" or sys_platform == \"win32\" or platform_system == \"Windows\"" name = "colorama" +version = "0.4.4" +description = "Cross-platform colored terminal text." +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "0.4.4" [[package]] -category = "dev" -description = "Code coverage measurement for Python" name = "coverage" +version = "5.3" +description = "Code coverage measurement for Python" +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" -version = "5.3" [package.dependencies] -[package.dependencies.toml] -optional = true -version = "*" +toml = {version = "*", optional = true, markers = "extra == \"toml\""} [package.extras] toml = ["toml"] [[package]] -category = "dev" -description = "A utility for ensuring Google-style docstrings stay up to date with the source code." name = "darglint" +version = "1.5.5" +description = "A utility for ensuring Google-style docstrings stay up to date with the source code." +category = "dev" optional = false python-versions = ">=3.5,<4.0" -version = "1.5.5" [[package]] -category = "dev" -description = "Distribution utilities" name = "distlib" +version = "0.3.1" +description = "Distribution utilities" +category = "dev" optional = false python-versions = "*" -version = "0.3.1" [[package]] -category = "dev" -description = "Docutils -- Python Documentation Utilities" name = "docutils" +version = "0.16" +description = "Docutils -- Python Documentation Utilities" +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "0.16" [[package]] -category = "dev" -description = "A parser for Python dependency files" name = "dparse" +version = "0.5.1" +description = "A parser for Python dependency files" +category = "dev" optional = false python-versions = ">=3.5" -version = "0.5.1" [package.dependencies] packaging = "*" @@ -202,37 +198,34 @@ toml = "*" pipenv = ["pipenv"] [[package]] -category = "dev" -description = "A platform independent file lock." name = "filelock" +version = "3.0.12" +description = "A platform independent file lock." +category = "dev" optional = false python-versions = "*" -version = "3.0.12" [[package]] -category = "dev" -description = "the modular source code checker: pep8 pyflakes and co" name = "flake8" +version = "3.8.4" +description = "the modular source code checker: pep8 pyflakes and co" +category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" -version = "3.8.4" [package.dependencies] +importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} mccabe = ">=0.6.0,<0.7.0" pycodestyle = ">=2.6.0a1,<2.7.0" pyflakes = ">=2.2.0,<2.3.0" -[package.dependencies.importlib-metadata] -python = "<3.8" -version = "*" - [[package]] -category = "dev" -description = "Automated security testing with bandit and flake8." name = "flake8-bandit" +version = "2.1.2" +description = "Automated security testing with bandit and flake8." +category = "dev" optional = false python-versions = "*" -version = "2.1.2" [package.dependencies] bandit = "*" @@ -241,109 +234,108 @@ flake8-polyfill = "*" pycodestyle = "*" [[package]] -category = "dev" -description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." name = "flake8-bugbear" +version = "20.1.4" +description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." +category = "dev" optional = false python-versions = ">=3.6" -version = "20.1.4" [package.dependencies] attrs = ">=19.2.0" flake8 = ">=3.0.0" [[package]] -category = "dev" -description = "Extension for flake8 which uses pydocstyle to check docstrings" name = "flake8-docstrings" +version = "1.5.0" +description = "Extension for flake8 which uses pydocstyle to check docstrings" +category = "dev" optional = false python-versions = "*" -version = "1.5.0" [package.dependencies] flake8 = ">=3" pydocstyle = ">=2.1" [[package]] -category = "dev" -description = "Polyfill package for Flake8 plugins" name = "flake8-polyfill" +version = "1.0.2" +description = "Polyfill package for Flake8 plugins" +category = "dev" optional = false python-versions = "*" -version = "1.0.2" [package.dependencies] flake8 = "*" [[package]] -category = "dev" -description = "Python docstring reStructuredText (RST) validator" name = "flake8-rst-docstrings" +version = "0.0.14" +description = "Python docstring reStructuredText (RST) validator" +category = "dev" optional = false python-versions = "*" -version = "0.0.14" [package.dependencies] flake8 = ">=3.0.0" restructuredtext_lint = "*" [[package]] -category = "dev" -description = "Git Object Database" name = "gitdb" +version = "4.0.5" +description = "Git Object Database" +category = "dev" optional = false python-versions = ">=3.4" -version = "4.0.5" [package.dependencies] smmap = ">=3.0.1,<4" [[package]] -category = "dev" -description = "Python Git Library" name = "gitpython" +version = "3.1.9" +description = "Python Git Library" +category = "dev" optional = false python-versions = ">=3.4" -version = "3.1.9" [package.dependencies] gitdb = ">=4.0.1,<5" [[package]] -category = "dev" -description = "File identification library for Python" name = "identify" +version = "1.5.6" +description = "File identification library for Python" +category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" -version = "1.5.6" [package.extras] license = ["editdistance"] [[package]] -category = "main" -description = "Internationalized Domain Names in Applications (IDNA)" name = "idna" +version = "2.10" +description = "Internationalized Domain Names in Applications (IDNA)" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "2.10" [[package]] -category = "dev" -description = "Getting image size from png/jpeg/jpeg2000/gif file" name = "imagesize" +version = "1.2.0" +description = "Getting image size from png/jpeg/jpeg2000/gif file" +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.2.0" [[package]] -category = "dev" -description = "Read metadata from Python packages" -marker = "python_version < \"3.8\"" name = "importlib-metadata" +version = "2.0.0" +description = "Read metadata from Python packages" +category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" -version = "2.0.0" [package.dependencies] zipp = ">=0.5" @@ -353,20 +345,20 @@ docs = ["sphinx", "rst.linker"] testing = ["packaging", "pep517", "importlib-resources (>=1.3)"] [[package]] -category = "dev" -description = "iniconfig: brain-dead simple config-ini parsing" name = "iniconfig" +version = "1.1.1" +description = "iniconfig: brain-dead simple config-ini parsing" +category = "dev" optional = false python-versions = "*" -version = "1.1.1" [[package]] -category = "dev" -description = "A very fast and expressive template engine." name = "jinja2" +version = "2.11.2" +description = "A very fast and expressive template engine." +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "2.11.2" [package.dependencies] MarkupSafe = ">=0.23" @@ -375,43 +367,40 @@ MarkupSafe = ">=0.23" i18n = ["Babel (>=0.8)"] [[package]] -category = "dev" -description = "Python LiveReload is an awesome tool for web developers" name = "livereload" +version = "2.6.3" +description = "Python LiveReload is an awesome tool for web developers" +category = "dev" optional = false python-versions = "*" -version = "2.6.3" [package.dependencies] six = "*" - -[package.dependencies.tornado] -python = ">=2.8" -version = "*" +tornado = {version = "*", markers = "python_version > \"2.7\""} [[package]] -category = "dev" -description = "Safely add untrusted strings to HTML/XML markup." name = "markupsafe" +version = "1.1.1" +description = "Safely add untrusted strings to HTML/XML markup." +category = "dev" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" -version = "1.1.1" [[package]] -category = "dev" -description = "McCabe checker, plugin for flake8" name = "mccabe" +version = "0.6.1" +description = "McCabe checker, plugin for flake8" +category = "dev" optional = false python-versions = "*" -version = "0.6.1" [[package]] -category = "dev" -description = "Optional static typing for Python" name = "mypy" +version = "0.782" +description = "Optional static typing for Python" +category = "dev" optional = false python-versions = ">=3.5" -version = "0.782" [package.dependencies] mypy-extensions = ">=0.4.3,<0.5.0" @@ -422,227 +411,219 @@ typing-extensions = ">=3.7.4" dmypy = ["psutil (>=4.0)"] [[package]] -category = "dev" -description = "Experimental type system extensions for programs checked with the mypy typechecker." name = "mypy-extensions" +version = "0.4.3" +description = "Experimental type system extensions for programs checked with the mypy typechecker." +category = "dev" optional = false python-versions = "*" -version = "0.4.3" [[package]] -category = "dev" -description = "Node.js virtual environment builder" name = "nodeenv" +version = "1.5.0" +description = "Node.js virtual environment builder" +category = "dev" optional = false python-versions = "*" -version = "1.5.0" [[package]] -category = "dev" -description = "Core utilities for Python packages" name = "packaging" +version = "20.4" +description = "Core utilities for Python packages" +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "20.4" [package.dependencies] pyparsing = ">=2.0.2" six = "*" [[package]] -category = "dev" -description = "Utility library for gitignore style pattern matching of file paths." name = "pathspec" +version = "0.8.0" +description = "Utility library for gitignore style pattern matching of file paths." +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "0.8.0" [[package]] -category = "dev" -description = "Python Build Reasonableness" name = "pbr" +version = "5.5.1" +description = "Python Build Reasonableness" +category = "dev" optional = false python-versions = ">=2.6" -version = "5.5.1" [[package]] -category = "dev" -description = "Check PEP-8 naming conventions, plugin for flake8" name = "pep8-naming" +version = "0.11.1" +description = "Check PEP-8 naming conventions, plugin for flake8" +category = "dev" optional = false python-versions = "*" -version = "0.11.1" [package.dependencies] flake8-polyfill = ">=1.0.2,<2" [[package]] -category = "dev" -description = "plugin and hook calling mechanisms for python" name = "pluggy" +version = "0.13.1" +description = "plugin and hook calling mechanisms for python" +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "0.13.1" [package.dependencies] -[package.dependencies.importlib-metadata] -python = "<3.8" -version = ">=0.12" +importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} [package.extras] dev = ["pre-commit", "tox"] [[package]] -category = "dev" -description = "A framework for managing and maintaining multi-language pre-commit hooks." name = "pre-commit" +version = "2.7.1" +description = "A framework for managing and maintaining multi-language pre-commit hooks." +category = "dev" optional = false python-versions = ">=3.6.1" -version = "2.7.1" [package.dependencies] cfgv = ">=2.0.0" identify = ">=1.0.0" +importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} nodeenv = ">=0.11.1" pyyaml = ">=5.1" toml = "*" virtualenv = ">=20.0.8" -[package.dependencies.importlib-metadata] -python = "<3.8" -version = "*" - [[package]] -category = "dev" -description = "Some out-of-the-box hooks for pre-commit." name = "pre-commit-hooks" +version = "3.3.0" +description = "Some out-of-the-box hooks for pre-commit." +category = "dev" optional = false python-versions = ">=3.6.1" -version = "3.2.0" [package.dependencies] "ruamel.yaml" = ">=0.15" toml = "*" [[package]] -category = "dev" -description = "library with cross-python path, ini-parsing, io, code, log facilities" name = "py" +version = "1.9.0" +description = "library with cross-python path, ini-parsing, io, code, log facilities" +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.9.0" [[package]] -category = "dev" -description = "Python style guide checker" name = "pycodestyle" +version = "2.6.0" +description = "Python style guide checker" +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "2.6.0" [[package]] -category = "dev" -description = "Python docstring style checker" name = "pydocstyle" +version = "5.1.1" +description = "Python docstring style checker" +category = "dev" optional = false python-versions = ">=3.5" -version = "5.1.1" [package.dependencies] snowballstemmer = "*" [[package]] -category = "dev" -description = "passive checker of Python programs" name = "pyflakes" +version = "2.2.0" +description = "passive checker of Python programs" +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "2.2.0" [[package]] -category = "dev" -description = "Pygments is a syntax highlighting package written in Python." name = "pygments" +version = "2.7.1" +description = "Pygments is a syntax highlighting package written in Python." +category = "dev" optional = false python-versions = ">=3.5" -version = "2.7.1" [[package]] -category = "dev" -description = "Python parsing module" name = "pyparsing" +version = "2.4.7" +description = "Python parsing module" +category = "dev" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -version = "2.4.7" [[package]] -category = "dev" -description = "pytest: simple powerful testing with Python" name = "pytest" +version = "6.1.1" +description = "pytest: simple powerful testing with Python" +category = "dev" optional = false python-versions = ">=3.5" -version = "6.1.1" [package.dependencies] -atomicwrites = ">=1.0" +atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} attrs = ">=17.4.0" -colorama = "*" +colorama = {version = "*", markers = "sys_platform == \"win32\""} +importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} iniconfig = "*" packaging = "*" pluggy = ">=0.12,<1.0" py = ">=1.8.2" toml = "*" -[package.dependencies.importlib-metadata] -python = "<3.8" -version = ">=0.12" - [package.extras] checkqa_mypy = ["mypy (0.780)"] testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] [[package]] -category = "dev" -description = "World timezone definitions, modern and historical" name = "pytz" +version = "2020.1" +description = "World timezone definitions, modern and historical" +category = "dev" optional = false python-versions = "*" -version = "2020.1" [[package]] -category = "dev" -description = "YAML parser and emitter for Python" name = "pyyaml" +version = "5.3.1" +description = "YAML parser and emitter for Python" +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "5.3.1" [[package]] -category = "dev" -description = "Alternative regular expression module, to replace re." name = "regex" +version = "2020.10.15" +description = "Alternative regular expression module, to replace re." +category = "dev" optional = false python-versions = "*" -version = "2020.10.15" [[package]] -category = "dev" -description = "Tool for reordering python imports" name = "reorder-python-imports" +version = "2.3.5" +description = "Tool for reordering python imports" +category = "dev" optional = false python-versions = ">=3.6.1" -version = "2.3.5" [package.dependencies] "aspy.refactor-imports" = ">=2.1.0" [[package]] -category = "main" -description = "Python HTTP for Humans." name = "requests" +version = "2.24.0" +description = "Python HTTP for Humans." +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "2.24.0" [package.dependencies] certifi = ">=2017.4.17" @@ -655,100 +636,95 @@ security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"] socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)", "win-inet-pton"] [[package]] -category = "dev" -description = "reStructuredText linter" name = "restructuredtext-lint" +version = "1.3.1" +description = "reStructuredText linter" +category = "dev" optional = false python-versions = "*" -version = "1.3.1" [package.dependencies] docutils = ">=0.11,<1.0" [[package]] -category = "dev" -description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" name = "ruamel.yaml" +version = "0.16.12" +description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" +category = "dev" optional = false python-versions = "*" -version = "0.16.12" [package.dependencies] -[package.dependencies."ruamel.yaml.clib"] -python = "<3.9" -version = ">=0.1.2" +"ruamel.yaml.clib" = {version = ">=0.1.2", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.9\""} [package.extras] docs = ["ryd"] jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"] [[package]] -category = "dev" -description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" -marker = "platform_python_implementation == \"CPython\" and python_version < \"3.9\"" name = "ruamel.yaml.clib" +version = "0.2.2" +description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" +category = "dev" optional = false python-versions = "*" -version = "0.2.2" [[package]] -category = "dev" -description = "Checks installed dependencies for known vulnerabilities." name = "safety" +version = "1.9.0" +description = "Checks installed dependencies for known vulnerabilities." +category = "dev" optional = false python-versions = ">=3.5" -version = "1.9.0" [package.dependencies] Click = ">=6.0" dparse = ">=0.5.1" packaging = "*" requests = "*" -setuptools = "*" [[package]] -category = "dev" -description = "Python 2 and 3 compatibility utilities" name = "six" +version = "1.15.0" +description = "Python 2 and 3 compatibility utilities" +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" -version = "1.15.0" [[package]] -category = "dev" -description = "A pure Python implementation of a sliding window memory map manager" name = "smmap" +version = "3.0.4" +description = "A pure Python implementation of a sliding window memory map manager" +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "3.0.4" [[package]] -category = "dev" -description = "This package provides 26 stemmers for 25 languages generated from Snowball algorithms." name = "snowballstemmer" +version = "2.0.0" +description = "This package provides 26 stemmers for 25 languages generated from Snowball algorithms." +category = "dev" optional = false python-versions = "*" -version = "2.0.0" [[package]] -category = "dev" -description = "Python documentation generator" name = "sphinx" +version = "3.2.1" +description = "Python documentation generator" +category = "dev" optional = false python-versions = ">=3.5" -version = "3.2.1" [package.dependencies] -Jinja2 = ">=2.3" -Pygments = ">=2.0" alabaster = ">=0.7,<0.8" babel = ">=1.3" -colorama = ">=0.3.5" +colorama = {version = ">=0.3.5", markers = "sys_platform == \"win32\""} docutils = ">=0.12" imagesize = "*" +Jinja2 = ">=2.3" packaging = "*" +Pygments = ">=2.0" requests = ">=2.5.0" -setuptools = "*" snowballstemmer = ">=1.1" sphinxcontrib-applehelp = "*" sphinxcontrib-devhelp = "*" @@ -763,12 +739,12 @@ lint = ["flake8 (>=3.5.0)", "flake8-import-order", "mypy (>=0.780)", "docutils-s test = ["pytest", "pytest-cov", "html5lib", "typed-ast", "cython"] [[package]] -category = "dev" -description = "Rebuild Sphinx documentation on changes, with live-reload in the browser." name = "sphinx-autobuild" +version = "2020.9.1" +description = "Rebuild Sphinx documentation on changes, with live-reload in the browser." +category = "dev" optional = false python-versions = ">=3.6" -version = "2020.9.1" [package.dependencies] livereload = "*" @@ -778,12 +754,12 @@ sphinx = "*" test = ["pytest", "pytest-cov"] [[package]] -category = "dev" -description = "Read the Docs theme for Sphinx" name = "sphinx-rtd-theme" +version = "0.5.0" +description = "Read the Docs theme for Sphinx" +category = "dev" optional = false python-versions = "*" -version = "0.5.0" [package.dependencies] sphinx = "*" @@ -792,143 +768,139 @@ sphinx = "*" dev = ["transifex-client", "sphinxcontrib-httpdomain", "bump2version"] [[package]] -category = "dev" -description = "sphinxcontrib-applehelp is a sphinx extension which outputs Apple help books" name = "sphinxcontrib-applehelp" +version = "1.0.2" +description = "sphinxcontrib-applehelp is a sphinx extension which outputs Apple help books" +category = "dev" optional = false python-versions = ">=3.5" -version = "1.0.2" [package.extras] lint = ["flake8", "mypy", "docutils-stubs"] test = ["pytest"] [[package]] -category = "dev" -description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." name = "sphinxcontrib-devhelp" +version = "1.0.2" +description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." +category = "dev" optional = false python-versions = ">=3.5" -version = "1.0.2" [package.extras] lint = ["flake8", "mypy", "docutils-stubs"] test = ["pytest"] [[package]] -category = "dev" -description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" name = "sphinxcontrib-htmlhelp" +version = "1.0.3" +description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" +category = "dev" optional = false python-versions = ">=3.5" -version = "1.0.3" [package.extras] lint = ["flake8", "mypy", "docutils-stubs"] test = ["pytest", "html5lib"] [[package]] -category = "dev" -description = "A sphinx extension which renders display math in HTML via JavaScript" name = "sphinxcontrib-jsmath" +version = "1.0.1" +description = "A sphinx extension which renders display math in HTML via JavaScript" +category = "dev" optional = false python-versions = ">=3.5" -version = "1.0.1" [package.extras] test = ["pytest", "flake8", "mypy"] [[package]] -category = "dev" -description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." name = "sphinxcontrib-qthelp" +version = "1.0.3" +description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." +category = "dev" optional = false python-versions = ">=3.5" -version = "1.0.3" [package.extras] lint = ["flake8", "mypy", "docutils-stubs"] test = ["pytest"] [[package]] -category = "dev" -description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." name = "sphinxcontrib-serializinghtml" +version = "1.1.4" +description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." +category = "dev" optional = false python-versions = ">=3.5" -version = "1.1.4" [package.extras] lint = ["flake8", "mypy", "docutils-stubs"] test = ["pytest"] [[package]] -category = "dev" -description = "Manage dynamic plugins for Python applications" name = "stevedore" +version = "3.2.2" +description = "Manage dynamic plugins for Python applications" +category = "dev" optional = false python-versions = ">=3.6" -version = "3.2.2" [package.dependencies] +importlib-metadata = {version = ">=1.7.0", markers = "python_version < \"3.8\""} pbr = ">=2.0.0,<2.1.0 || >2.1.0" -[package.dependencies.importlib-metadata] -python = "<3.8" -version = ">=1.7.0" - [[package]] -category = "dev" -description = "Python Library for Tom's Obvious, Minimal Language" name = "toml" +version = "0.10.1" +description = "Python Library for Tom's Obvious, Minimal Language" +category = "dev" optional = false python-versions = "*" -version = "0.10.1" [[package]] -category = "dev" -description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." -marker = "python_version > \"2.7\"" name = "tornado" +version = "6.0.4" +description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." +category = "dev" optional = false python-versions = ">= 3.5" -version = "6.0.4" [[package]] -category = "dev" -description = "a fork of Python 2 and 3 ast modules with type comment support" name = "typed-ast" +version = "1.4.1" +description = "a fork of Python 2 and 3 ast modules with type comment support" +category = "dev" optional = false python-versions = "*" -version = "1.4.1" [[package]] -category = "dev" -description = "Run-time type checker for Python" name = "typeguard" +version = "2.10.0" +description = "Run-time type checker for Python" +category = "dev" optional = false python-versions = ">=3.5.3" -version = "2.10.0" [package.extras] doc = ["sphinx-rtd-theme", "sphinx-autodoc-typehints (>=1.2.0)"] test = ["pytest", "typing-extensions"] [[package]] -category = "dev" -description = "Backported and Experimental Type Hints for Python 3.5+" name = "typing-extensions" +version = "3.7.4.3" +description = "Backported and Experimental Type Hints for Python 3.5+" +category = "dev" optional = false python-versions = "*" -version = "3.7.4.3" [[package]] -category = "main" -description = "HTTP library with thread-safe connection pooling, file post, and more." name = "urllib3" +version = "1.25.11" +description = "HTTP library with thread-safe connection pooling, file post, and more." +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" -version = "1.25.11" [package.extras] brotli = ["brotlipy (>=0.6.0)"] @@ -936,46 +908,35 @@ secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "cer socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"] [[package]] -category = "dev" -description = "Virtual Python Environment builder" name = "virtualenv" +version = "20.0.35" +description = "Virtual Python Environment builder" +category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" -version = "20.0.35" [package.dependencies] appdirs = ">=1.4.3,<2" distlib = ">=0.3.1,<1" filelock = ">=3.0.0,<4" +importlib-metadata = {version = ">=0.12,<3", markers = "python_version < \"3.8\""} six = ">=1.9.0,<2" -[package.dependencies.importlib-metadata] -python = "<3.8" -version = ">=0.12,<3" - [package.extras] docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=19.9.0rc1)"] testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)", "pytest-xdist (>=1.31.0)", "packaging (>=20.0)", "xonsh (>=0.9.16)"] [[package]] -category = "dev" -description = "A rewrite of the builtin doctest module" name = "xdoctest" +version = "0.15.0" +description = "A rewrite of the builtin doctest module" +category = "dev" optional = false python-versions = "*" -version = "0.15.0" [package.dependencies] six = "*" -[package.dependencies.Pygments] -optional = true -version = "*" - -[package.dependencies.colorama] -optional = true -version = "*" - [package.extras] all = ["six", "pytest", "pytest-cov", "codecov", "scikit-build", "cmake", "ninja", "pybind11", "pygments", "colorama", "nbformat", "nbconvert", "jupyter-client", "ipython", "ipykernel"] colors = ["pygments", "colorama"] @@ -984,22 +945,21 @@ optional = ["pygments", "colorama", "nbformat", "nbconvert", "jupyter-client", " tests = ["pytest", "pytest-cov", "codecov", "scikit-build", "cmake", "ninja", "pybind11", "nbformat", "nbconvert", "jupyter-client", "ipython", "ipykernel"] [[package]] -category = "dev" -description = "Backport of pathlib-compatible object wrapper for zip files" -marker = "python_version < \"3.8\"" name = "zipp" +version = "3.3.1" +description = "Backport of pathlib-compatible object wrapper for zip files" +category = "dev" optional = false python-versions = ">=3.6" -version = "3.3.1" [package.extras] docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"] testing = ["pytest (>=3.5,<3.7.3 || >3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-cov", "jaraco.test (>=3.2.0)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"] [metadata] -content-hash = "b4e8b1df8bbcbfff3e4fb2353cfed0f989434715abe6675953b313facd411d01" -lock-version = "1.0" +lock-version = "1.1" python-versions = "^3.7.0" +content-hash = "ba91b8da35a49796d40e7de872cd9e01aba62ab75fbc9a5cea2e0986bd567518" [metadata.files] alabaster = [ @@ -1055,6 +1015,7 @@ click = [ ] colorama = [ {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, + {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, ] coverage = [ {file = "coverage-5.3-cp27-cp27m-macosx_10_13_intel.whl", hash = "sha256:bd3166bb3b111e76a4f8e2980fa1addf2920a4ca9b2b8ca36a3bc3dedc618270"}, @@ -1257,8 +1218,8 @@ pre-commit = [ {file = "pre_commit-2.7.1.tar.gz", hash = "sha256:c54fd3e574565fe128ecc5e7d2f91279772ddb03f8729645fa812fe809084a70"}, ] pre-commit-hooks = [ - {file = "pre_commit_hooks-3.2.0-py2.py3-none-any.whl", hash = "sha256:8a174237326576c5f2279eba18ccbf2ca2a19fcaab8844db80f576c8fe76c2c2"}, - {file = "pre_commit_hooks-3.2.0.tar.gz", hash = "sha256:917bce8feb048f8271e3a4a900c6d780118d23e8ddf4557ddec9384c0d1dba79"}, + {file = "pre_commit_hooks-3.3.0-py2.py3-none-any.whl", hash = "sha256:2190d72ac867bd9b8880de32d9304ec54182c89720cce56f22742890ed8ba90f"}, + {file = "pre_commit_hooks-3.3.0.tar.gz", hash = "sha256:1e18c0451279fb88653c7b9f8fd73ccc35925e95b636c5b64095538f68a23b06"}, ] py = [ {file = "py-1.9.0-py2.py3-none-any.whl", hash = "sha256:366389d1db726cd2fcfc79732e75410e5fe4d31db13692115529d34069a043c2"}, @@ -1371,6 +1332,8 @@ restructuredtext-lint = [ {file = "ruamel.yaml.clib-0.2.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:5254af7d8bdf4d5484c089f929cb7f5bafa59b4f01d4f48adda4be41e6d29f99"}, {file = "ruamel.yaml.clib-0.2.2-cp38-cp38-win32.whl", hash = "sha256:74161d827407f4db9072011adcfb825b5258a5ccb3d2cd518dd6c9edea9e30f1"}, {file = "ruamel.yaml.clib-0.2.2-cp38-cp38-win_amd64.whl", hash = "sha256:058a1cc3df2a8aecc12f983a48bda99315cebf55a3b3a5463e37bb599b05727b"}, + {file = "ruamel.yaml.clib-0.2.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c6ac7e45367b1317e56f1461719c853fd6825226f45b835df7436bb04031fd8a"}, + {file = "ruamel.yaml.clib-0.2.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:b4b0d31f2052b3f9f9b5327024dc629a253a83d8649d4734ca7f35b60ec3e9e5"}, {file = "ruamel.yaml.clib-0.2.2.tar.gz", hash = "sha256:2d24bd98af676f4990c4d715bcdc2a60b19c56a3fb3a763164d2d8ca0e806ba7"}, ] safety = [ diff --git a/pyproject.toml b/pyproject.toml index fd33d205..665a9e84 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -53,7 +53,7 @@ flake8-rst-docstrings = "^0.0.14" pep8-naming = "^0.11.1" darglint = "^1.5.5" reorder-python-imports = "^2.3.5" -pre-commit-hooks = "^3.2.0" +pre-commit-hooks = "^3.3.0" sphinx-rtd-theme = "^0.5.0" Pygments = "^2.7.1" From 02b80ec676e5f0f19f6c5ed9a6547faa88e5b524 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Oct 2020 20:21:17 +0000 Subject: [PATCH 07/33] Bump poetry from 1.0.10 to 1.1.3 in /.github/workflows (#82) --- .github/workflows/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/constraints.txt b/.github/workflows/constraints.txt index 2937ef31..18efed35 100644 --- a/.github/workflows/constraints.txt +++ b/.github/workflows/constraints.txt @@ -1,5 +1,5 @@ pip==20.2.4 nox==2020.8.22 nox-poetry==0.5.0 -poetry==1.0.10 +poetry==1.1.3 virtualenv==20.0.35 From 69620571acad863fbe2e11d4f77d652f4d159087 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Oct 2020 20:22:07 +0000 Subject: [PATCH 08/33] Bump release-drafter/release-drafter from v5.12.0 to v5.12.1 (#81) --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c325f77b..33779267 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -71,7 +71,7 @@ jobs: repository_url: https://test.pypi.org/legacy/ - name: Publish release notes - uses: release-drafter/release-drafter@v5.12.0 + uses: release-drafter/release-drafter@v5.12.1 with: publish: ${{ steps.check-version.outputs.tag != '' }} tag: ${{ steps.check-version.outputs.tag }} From c6b0b22c7e8fd7000323c3e91268b9a7ef364013 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Oct 2020 20:26:51 +0000 Subject: [PATCH 09/33] Bump mypy from 0.782 to 0.790 (#84) --- poetry.lock | 32 ++++++++++++++++---------------- pyproject.toml | 2 +- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/poetry.lock b/poetry.lock index 7cc47093..66739f81 100644 --- a/poetry.lock +++ b/poetry.lock @@ -396,7 +396,7 @@ python-versions = "*" [[package]] name = "mypy" -version = "0.782" +version = "0.790" description = "Optional static typing for Python" category = "dev" optional = false @@ -959,7 +959,7 @@ testing = ["pytest (>=3.5,<3.7.3 || >3.7.3)", "pytest-checkdocs (>=1.2.3)", "pyt [metadata] lock-version = "1.1" python-versions = "^3.7.0" -content-hash = "ba91b8da35a49796d40e7de872cd9e01aba62ab75fbc9a5cea2e0986bd567518" +content-hash = "40b234f06847f4f8ee765adaca61cc1698dd49bc37b043a609ef19fcf917ad91" [metadata.files] alabaster = [ @@ -1170,20 +1170,20 @@ mccabe = [ {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, ] mypy = [ - {file = "mypy-0.782-cp35-cp35m-macosx_10_6_x86_64.whl", hash = "sha256:2c6cde8aa3426c1682d35190b59b71f661237d74b053822ea3d748e2c9578a7c"}, - {file = "mypy-0.782-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9c7a9a7ceb2871ba4bac1cf7217a7dd9ccd44c27c2950edbc6dc08530f32ad4e"}, - {file = "mypy-0.782-cp35-cp35m-win_amd64.whl", hash = "sha256:c05b9e4fb1d8a41d41dec8786c94f3b95d3c5f528298d769eb8e73d293abc48d"}, - {file = "mypy-0.782-cp36-cp36m-macosx_10_6_x86_64.whl", hash = "sha256:6731603dfe0ce4352c555c6284c6db0dc935b685e9ce2e4cf220abe1e14386fd"}, - {file = "mypy-0.782-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:f05644db6779387ccdb468cc47a44b4356fc2ffa9287135d05b70a98dc83b89a"}, - {file = "mypy-0.782-cp36-cp36m-win_amd64.whl", hash = "sha256:b7fbfabdbcc78c4f6fc4712544b9b0d6bf171069c6e0e3cb82440dd10ced3406"}, - {file = "mypy-0.782-cp37-cp37m-macosx_10_6_x86_64.whl", hash = "sha256:3fdda71c067d3ddfb21da4b80e2686b71e9e5c72cca65fa216d207a358827f86"}, - {file = "mypy-0.782-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:d7df6eddb6054d21ca4d3c6249cae5578cb4602951fd2b6ee2f5510ffb098707"}, - {file = "mypy-0.782-cp37-cp37m-win_amd64.whl", hash = "sha256:a4a2cbcfc4cbf45cd126f531dedda8485671545b43107ded25ce952aac6fb308"}, - {file = "mypy-0.782-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6bb93479caa6619d21d6e7160c552c1193f6952f0668cdda2f851156e85186fc"}, - {file = "mypy-0.782-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:81c7908b94239c4010e16642c9102bfc958ab14e36048fa77d0be3289dda76ea"}, - {file = "mypy-0.782-cp38-cp38-win_amd64.whl", hash = "sha256:5dd13ff1f2a97f94540fd37a49e5d255950ebcdf446fb597463a40d0df3fac8b"}, - {file = "mypy-0.782-py3-none-any.whl", hash = "sha256:e0b61738ab504e656d1fe4ff0c0601387a5489ca122d55390ade31f9ca0e252d"}, - {file = "mypy-0.782.tar.gz", hash = "sha256:eff7d4a85e9eea55afa34888dfeaccde99e7520b51f867ac28a48492c0b1130c"}, + {file = "mypy-0.790-cp35-cp35m-macosx_10_6_x86_64.whl", hash = "sha256:bd03b3cf666bff8d710d633d1c56ab7facbdc204d567715cb3b9f85c6e94f669"}, + {file = "mypy-0.790-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:2170492030f6faa537647d29945786d297e4862765f0b4ac5930ff62e300d802"}, + {file = "mypy-0.790-cp35-cp35m-win_amd64.whl", hash = "sha256:e86bdace26c5fe9cf8cb735e7cedfe7850ad92b327ac5d797c656717d2ca66de"}, + {file = "mypy-0.790-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e97e9c13d67fbe524be17e4d8025d51a7dca38f90de2e462243ab8ed8a9178d1"}, + {file = "mypy-0.790-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0d34d6b122597d48a36d6c59e35341f410d4abfa771d96d04ae2c468dd201abc"}, + {file = "mypy-0.790-cp36-cp36m-win_amd64.whl", hash = "sha256:72060bf64f290fb629bd4a67c707a66fd88ca26e413a91384b18db3876e57ed7"}, + {file = "mypy-0.790-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:eea260feb1830a627fb526d22fbb426b750d9f5a47b624e8d5e7e004359b219c"}, + {file = "mypy-0.790-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:c614194e01c85bb2e551c421397e49afb2872c88b5830e3554f0519f9fb1c178"}, + {file = "mypy-0.790-cp37-cp37m-win_amd64.whl", hash = "sha256:0a0d102247c16ce93c97066443d11e2d36e6cc2a32d8ccc1f705268970479324"}, + {file = "mypy-0.790-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cf4e7bf7f1214826cf7333627cb2547c0db7e3078723227820d0a2490f117a01"}, + {file = "mypy-0.790-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:af4e9ff1834e565f1baa74ccf7ae2564ae38c8df2a85b057af1dbbc958eb6666"}, + {file = "mypy-0.790-cp38-cp38-win_amd64.whl", hash = "sha256:da56dedcd7cd502ccd3c5dddc656cb36113dd793ad466e894574125945653cea"}, + {file = "mypy-0.790-py3-none-any.whl", hash = "sha256:2842d4fbd1b12ab422346376aad03ff5d0805b706102e475e962370f874a5122"}, + {file = "mypy-0.790.tar.gz", hash = "sha256:2b21ba45ad9ef2e2eb88ce4aeadd0112d0f5026418324176fd494a6824b74975"}, ] mypy-extensions = [ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, diff --git a/pyproject.toml b/pyproject.toml index 665a9e84..0167eaa1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,7 +38,7 @@ urllib3 = "^1.25.10" pytest = "^6.1.1" coverage = {extras = ["toml"], version = "^5.3"} safety = "^1.9.0" -mypy = "^0.782" +mypy = "^0.790" typeguard = "^2.9.1" xdoctest = {extras = ["colors"], version = "^0.15.0"} sphinx = "^3.2.1" From fbdbe97a3bcb0ea7db8e6f3f16e731748c85343f Mon Sep 17 00:00:00 2001 From: Oncleben31 Date: Sun, 25 Oct 2020 19:49:10 +0100 Subject: [PATCH 10/33] Fix a lot of flake8 linting errors (#85) * Restore standard ignore list for flake8 In previous version we add some checks to ignore list. * Fix all B950 flake8 errors (line too long) Fix the code and add 2 per-file-ignore paterns for readability reasons. * Fix F401 flake8 errors (import not used) * Fix E302 flake8 errors * Fix E266 flake8 errors * Fix D107 flake8 errors * Fix Dxxx Flake8 errors * Add explanation on flake8 ignored rules * Remove pyling inline ignore rules pylint is no more used and replaced by flake8. * Remove D102 flake8 errors. * Apply suggestions from code review Co-authored-by: Quentame Co-authored-by: Quentame --- .flake8 | 17 ++++++---- src/synology_dsm/__init__.py | 2 ++ src/synology_dsm/api/core/security.py | 11 +++++-- src/synology_dsm/api/core/share.py | 12 ++++--- src/synology_dsm/api/core/system.py | 9 ++++-- src/synology_dsm/api/core/upgrade.py | 1 + src/synology_dsm/api/core/utilization.py | 7 ++-- src/synology_dsm/api/download_station/task.py | 6 +++- src/synology_dsm/api/dsm/information.py | 1 + src/synology_dsm/api/dsm/network.py | 3 +- src/synology_dsm/api/storage/storage.py | 1 + .../api/surveillance_station/__init__.py | 20 ++++++++---- src/synology_dsm/exceptions.py | 10 ++++++ src/synology_dsm/helpers.py | 2 +- src/synology_dsm/synology_dsm.py | 25 +++++++++++---- tests/__init__.py | 11 +++++-- tests/api_data/dsm_5/__init__.py | 11 +++++++ tests/api_data/dsm_6/__init__.py | 32 +++++++++++++++++++ tests/test_synology_dsm.py | 15 ++++----- tests/test_synology_dsm_5.py | 3 +- 20 files changed, 153 insertions(+), 46 deletions(-) diff --git a/.flake8 b/.flake8 index 00bd25b2..85628c2e 100644 --- a/.flake8 +++ b/.flake8 @@ -1,12 +1,15 @@ [flake8] -select = B,B9,C,DAR,E,F,N,RST,S,W -# Some tests have been added to the ignore list to avoid reworking too much -# the code in this PR: D107, D403, B950, E266, C901, F401, E302. -# The error will be processed in a dedicated PR. -# targeted ignore list is: +select = B,B9,C,D,DAR,E,F,N,RST,S,W +# Some rules are ignore on top of the standard ones. +# C901 (complexity) will be processed in a dedicated PR +# DARxxx (documentation in docstrings) will be processed in a dedicated PR +# Final target is: # ignore = E203,E501,RST201,RST203,RST301,W503 -ignore = E203,E501,RST201,RST203,RST301,W503, D107, D403, B950, E266, C901, F401, E302 +ignore = E203,E501,RST201,RST203,RST301,W503, C901, DAR101, DAR201 max-line-length = 80 max-complexity = 10 docstring-convention = google -per-file-ignores = tests/*:S101 +per-file-ignores = + tests/*:S101 + tests/**/const_*.py:B950 + src/synology_dsm/const.py:B950 diff --git a/src/synology_dsm/__init__.py b/src/synology_dsm/__init__.py index 092f3fcb..b883e8be 100644 --- a/src/synology_dsm/__init__.py +++ b/src/synology_dsm/__init__.py @@ -1,2 +1,4 @@ """The python-synology library.""" from .synology_dsm import SynologyDSM + +__all__ = ["SynologyDSM"] diff --git a/src/synology_dsm/api/core/security.py b/src/synology_dsm/api/core/security.py index fcc074c1..eed4ff54 100644 --- a/src/synology_dsm/api/core/security.py +++ b/src/synology_dsm/api/core/security.py @@ -7,6 +7,7 @@ class SynoCoreSecurity: API_KEY = "SYNO.Core.SecurityScan.Status" def __init__(self, dsm): + """Constructor method.""" self._dsm = dsm self._data = {} @@ -38,12 +39,18 @@ def success(self): @property def progress(self): - """Gets the scan progress (100 if finished).""" + """Gets the scan progress. + + Returns: 100 if finished + """ return self._data.get("sysProgress") @property def status(self): - """Gets the last scan status (safe, danger, info, outOfDate, risk, warning).""" + """Gets the last scan status. + + Possible values: safe, danger, info, outOfDate, risk, warning. + """ return self._data.get("sysStatus") @property diff --git a/src/synology_dsm/api/core/share.py b/src/synology_dsm/api/core/share.py index bcc5ad56..aa6d2336 100644 --- a/src/synology_dsm/api/core/share.py +++ b/src/synology_dsm/api/core/share.py @@ -11,15 +11,17 @@ class SynoCoreShare: # are returned plus any keys listed in the "additional" parameter. # NOTE: The value of the additional key must be a string. REQUEST_DATA = { - "additional": '["hidden","encryption","is_aclmode","unite_permission","is_support_acl",' - '"is_sync_share","is_force_readonly","force_readonly_reason","recyclebin",' - '"is_share_moving","is_cluster_share","is_exfat_share","is_cold_storage_share",' - '"support_snapshot","share_quota","enable_share_compress","enable_share_cow",' - '"include_cold_storage_share","is_cold_storage_share"]', + "additional": '["hidden","encryption","is_aclmode","unite_permission",' + '"is_support_acl","is_sync_share","is_force_readonly","force_readonly_reason",' + '"recyclebin","is_share_moving","is_cluster_share","is_exfat_share",' + '"is_cold_storage_share","support_snapshot","share_quota",' + '"enable_share_compress","enable_share_cow","include_cold_storage_share",' + '"is_cold_storage_share"]', "shareType": "all", } def __init__(self, dsm): + """Constructor method.""" self._dsm = dsm self._data = {} diff --git a/src/synology_dsm/api/core/system.py b/src/synology_dsm/api/core/system.py index 4af5870b..4e455b71 100644 --- a/src/synology_dsm/api/core/system.py +++ b/src/synology_dsm/api/core/system.py @@ -7,6 +7,7 @@ class SynoCoreSystem: API_KEY = "SYNO.Core.System" def __init__(self, dsm): + """Constructor method.""" self._dsm = dsm self._data = {} @@ -16,7 +17,9 @@ def update(self): if raw_data: self._data = raw_data["data"] - ### get information + # + # get information + # @property def cpu_clock_speed(self): """Gets System CPU clock speed.""" @@ -97,7 +100,9 @@ def usb_dev(self): """Gets System connected usb devices.""" return self._data.get("usb_dev", []) - ### do system actions + # + # do system actions + # def shutdown(self): """Shutdown NAS.""" res = self._dsm.get( diff --git a/src/synology_dsm/api/core/upgrade.py b/src/synology_dsm/api/core/upgrade.py index 838444ee..250f380c 100644 --- a/src/synology_dsm/api/core/upgrade.py +++ b/src/synology_dsm/api/core/upgrade.py @@ -8,6 +8,7 @@ class SynoCoreUpgrade: API_SERVER_KEY = API_KEY + ".Server" def __init__(self, dsm): + """Constructor method.""" self._dsm = dsm self._data = {} diff --git a/src/synology_dsm/api/core/utilization.py b/src/synology_dsm/api/core/utilization.py index e768c51e..d25946b4 100644 --- a/src/synology_dsm/api/core/utilization.py +++ b/src/synology_dsm/api/core/utilization.py @@ -8,6 +8,7 @@ class SynoCoreUtilization: API_KEY = "SYNO.Core.System.Utilization" def __init__(self, dsm): + """Constructor method.""" self._dsm = dsm self._data = {} @@ -24,17 +25,17 @@ def cpu(self): @property def cpu_other_load(self): - """'Other' percentage of the total CPU load.""" + """Other percentage of the total CPU load.""" return self.cpu.get("other_load") @property def cpu_user_load(self): - """'User' percentage of the total CPU load.""" + """User percentage of the total CPU load.""" return self.cpu.get("user_load") @property def cpu_system_load(self): - """'System' percentage of the total CPU load.""" + """System percentage of the total CPU load.""" return self.cpu.get("system_load") @property diff --git a/src/synology_dsm/api/download_station/task.py b/src/synology_dsm/api/download_station/task.py index b4b6a6cb..b3747ec9 100644 --- a/src/synology_dsm/api/download_station/task.py +++ b/src/synology_dsm/api/download_station/task.py @@ -39,7 +39,11 @@ def size(self): @property def status(self): - """Return status of the task (waiting, downloading, paused, finishing, finished, hash_checking, seeding, filehosting_waiting, extracting, error).""" + """Return status of the task. + + Possible values: waiting, downloading, paused, finishing, finished, + hash_checking, seeding, filehosting_waiting, extracting, error + """ return self._data["status"] @property diff --git a/src/synology_dsm/api/dsm/information.py b/src/synology_dsm/api/dsm/information.py index 7c73cc9e..709a07fb 100644 --- a/src/synology_dsm/api/dsm/information.py +++ b/src/synology_dsm/api/dsm/information.py @@ -7,6 +7,7 @@ class SynoDSMInformation: API_KEY = "SYNO.DSM.Info" def __init__(self, dsm): + """Constructor methods.""" self._dsm = dsm self._data = {} diff --git a/src/synology_dsm/api/dsm/network.py b/src/synology_dsm/api/dsm/network.py index 451d111c..5a0808b4 100644 --- a/src/synology_dsm/api/dsm/network.py +++ b/src/synology_dsm/api/dsm/network.py @@ -7,6 +7,7 @@ class SynoDSMNetwork: API_KEY = "SYNO.DSM.Network" def __init__(self, dsm): + """Constructor method.""" self._dsm = dsm self._data = {} @@ -45,7 +46,7 @@ def interface(self, eth_id): @property def macs(self): - """MACs of the NAS.""" + """MACs of the NAS.""" # noqa: D403 macs = [] for interface in self.interfaces: macs.append(interface["mac"]) diff --git a/src/synology_dsm/api/storage/storage.py b/src/synology_dsm/api/storage/storage.py index 786f3d16..11c2409e 100644 --- a/src/synology_dsm/api/storage/storage.py +++ b/src/synology_dsm/api/storage/storage.py @@ -8,6 +8,7 @@ class SynoStorage: API_KEY = "SYNO.Storage.CGI.Storage" def __init__(self, dsm): + """Constructor method.""" self._dsm = dsm self._data = {} diff --git a/src/synology_dsm/api/surveillance_station/__init__.py b/src/synology_dsm/api/surveillance_station/__init__.py index c89cd73c..001ab6cd 100644 --- a/src/synology_dsm/api/surveillance_station/__init__.py +++ b/src/synology_dsm/api/surveillance_station/__init__.py @@ -1,6 +1,4 @@ """Synology SurveillanceStation API wrapper.""" -import urllib - from .camera import SynoCamera from .const import MOTION_DETECTION_BY_SURVEILLANCE from .const import MOTION_DETECTION_DISABLED @@ -64,7 +62,12 @@ def get_camera(self, camera_id): return self._cameras_by_id[camera_id] def get_camera_live_view_path(self, camera_id, video_format=None): - """Return camera live view path matching camera_id (video_format: mjpeg_http | multicast | mxpeg_http | rtsp_http | rtsp).""" + """Return camera live view path matching camera_id. + + Args: + camera_id: ID of the camera we want to get the live view path. + video_format: mjpeg_http | multicast | mxpeg_http | rtsp_http | rtsp. + """ if video_format: return getattr(self._cameras_by_id[camera_id].live_view, video_format) return self._cameras_by_id[camera_id].live_view @@ -100,7 +103,12 @@ def capture_camera_image(self, camera_id, save=True): ) def download_snapshot(self, snapshot_id, snapshot_size): - """Download snapshot image binary for a givent snapshot_id (snapshot_size: SNAPSHOT_SIZE_ICON | SNAPSHOT_SIZE_FULL).""" + """Download snapshot image binary for a givent snapshot_id. + + Args: + snapshot_id: ID of the snapshot we want to download. + snapshot_size: SNAPSHOT_SIZE_ICON | SNAPSHOT_SIZE_FULL. + """ return self._dsm.get( self.SNAPSHOT_API_KEY, "LoadSnapshot", @@ -130,11 +138,11 @@ def disable_motion_detection(self, camera_id): # Home mode def get_home_mode_status(self): - """Get the state of Home Mode""" + """Get the state of Home Mode.""" return self._dsm.get(self.HOME_MODE_API_KEY, "GetInfo")["data"]["on"] def set_home_mode(self, state): - """Set the state of Home Mode (state: bool)""" + """Set the state of Home Mode (state: bool).""" return self._dsm.get( self.HOME_MODE_API_KEY, "Switch", {"on": str(state).lower()} )["success"] diff --git a/src/synology_dsm/exceptions.py b/src/synology_dsm/exceptions.py index d70998e1..b05ab887 100644 --- a/src/synology_dsm/exceptions.py +++ b/src/synology_dsm/exceptions.py @@ -13,6 +13,7 @@ class SynologyDSMException(Exception): """Generic Synology DSM exception.""" def __init__(self, api, code, details=None): + """Constructor method.""" reason = ERROR_COMMON.get(code) if api and not reason: if api == API_AUTH: @@ -40,6 +41,7 @@ class SynologyDSMRequestException(SynologyDSMException): """Request exception.""" def __init__(self, exception): + """Constructor method.""" ex_class = exception.__class__.__name__ ex_reason = exception.args[0] if hasattr(exception.args[0], "reason"): @@ -52,6 +54,7 @@ class SynologyDSMAPINotExistsException(SynologyDSMException): """API not exists exception.""" def __init__(self, api): + """Constructor method.""" super().__init__(api, -2, f"API {api} does not exists") @@ -59,6 +62,7 @@ class SynologyDSMAPIErrorException(SynologyDSMException): """API returns an error exception.""" def __init__(self, api, code, details): + """Constructor method.""" super().__init__(api, code, details) @@ -67,6 +71,7 @@ class SynologyDSMLoginFailedException(SynologyDSMException): """Failed to login exception.""" def __init__(self, code, details=None): + """Constructor method.""" super().__init__(API_AUTH, code, details) @@ -74,6 +79,7 @@ class SynologyDSMLoginInvalidException(SynologyDSMLoginFailedException): """Invalid password & not admin account exception.""" def __init__(self, username): + """Constructor method.""" message = f"Invalid password or not admin account: {username}" super().__init__(400, message) @@ -82,6 +88,7 @@ class SynologyDSMLoginDisabledAccountException(SynologyDSMLoginFailedException): """Guest & disabled account exception.""" def __init__(self, username): + """Constructor method.""" message = f"Guest or disabled account: {username}" super().__init__(401, message) @@ -90,6 +97,7 @@ class SynologyDSMLoginPermissionDeniedException(SynologyDSMLoginFailedException) """No access to login exception.""" def __init__(self, username): + """Constructor method.""" message = f"Permission denied for account: {username}" super().__init__(402, message) @@ -98,6 +106,7 @@ class SynologyDSMLogin2SARequiredException(SynologyDSMLoginFailedException): """2SA required to login exception.""" def __init__(self, username): + """Constructor method.""" message = f"Two-step authentication required for account: {username}" super().__init__(403, message) @@ -106,5 +115,6 @@ class SynologyDSMLogin2SAFailedException(SynologyDSMLoginFailedException): """2SA code failed exception.""" def __init__(self): + """Constructor method.""" message = "Two-step authentication failed, retry with a new pass code" super().__init__(404, message) diff --git a/src/synology_dsm/helpers.py b/src/synology_dsm/helpers.py index 8098771e..5a120de2 100644 --- a/src/synology_dsm/helpers.py +++ b/src/synology_dsm/helpers.py @@ -7,7 +7,7 @@ class SynoFormatHelper: @staticmethod def bytes_to_readable(num): """Converts bytes to a human readable format.""" - if num < 512: # pylint: disable=no-else-return + if num < 512: return "0 Kb" elif num < 1024: return "1 Kb" diff --git a/src/synology_dsm/synology_dsm.py b/src/synology_dsm/synology_dsm.py index f1863b8e..6b6a09eb 100644 --- a/src/synology_dsm/synology_dsm.py +++ b/src/synology_dsm/synology_dsm.py @@ -49,6 +49,7 @@ def __init__( device_token: str = None, debugmode: bool = False, ): + """Constructor method.""" self.username = username self._password = password self._timeout = timeout or 10 @@ -82,7 +83,7 @@ def __init__( # Build variables if use_https: if not verify_ssl: - # https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings + # https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings # noqa: B950 # disable SSL warnings due to the auto-genenerated cert urllib3.disable_warnings() @@ -96,7 +97,11 @@ def _debuglog(self, message: str): print("DEBUG: " + message) 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].""" + """Returns True if the API URL is not common. + + Common template is nas_base_url/webapi/path?params + Only handles DSM 5 for now. + """ return ( api in self.DSM_5_WEIRD_URL_API and self._information @@ -107,7 +112,10 @@ def _is_weird_api_url(self, api: str) -> bool: def _build_url(self, api: str) -> str: if self._is_weird_api_url(api): if api == SynoStorage.API_KEY: - return f"{self._base_url}/webman/modules/StorageManager/storagehandler.cgi?" + return ( + f"{self._base_url}/webman/modules/StorageManager/" + f"storagehandler.cgi?" + ) return f"{self._base_url}/webapi/{self.apis[api]['path']}?" @@ -166,7 +174,8 @@ def login(self, otp_code: str = None) -> bool: # Not available on API version < 3 self._syno_token = result["data"]["synotoken"] if result["data"].get("did"): - # Not available on API version < 6 && device token is given once per device_name + # Not available on API version < 6 && device token is given once + # per device_name self._device_token = result["data"]["did"] self._debuglog("Authentication successful, token: " + str(self._session_id)) @@ -184,7 +193,10 @@ def logout(self) -> bool: @property def device_token(self) -> str: - """Gets the device token to remember the 2SA access was granted on this device.""" + """Gets the device token. + + Used to remember the 2SA access was granted on this device. + """ return self._device_token def get(self, api: str, method: str, params: dict = None, **kwargs): @@ -250,7 +262,8 @@ def _request( if isinstance(response, dict) and response.get("error") and api != API_AUTH: self._debuglog("Session error: " + str(response["error"]["code"])) if response["error"]["code"] == 119 and retry_once: - # Session ID not valid, see https://github.com/aerialls/synology-srm/pull/3 + # Session ID not valid + # see https://github.com/aerialls/synology-srm/pull/3 self._session_id = None self._syno_token = None self._device_token = None diff --git a/tests/__init__.py b/tests/__init__.py index a1966f24..40653d0f 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -93,7 +93,7 @@ "RAID": DSM_6_STORAGE_STORAGE_DS918_PLUS_RAID5_3DISKS_1VOL, "SHR1": DSM_6_STORAGE_STORAGE_DS213_PLUS_SHR1_2DISKS_2VOLS, "SHR2": DSM_6_STORAGE_STORAGE_DS1819_PLUS_SHR2_8DISKS_1VOL, - "SHR2_EXPANSION": DSM_6_STORAGE_STORAGE_DS1515_PLUS_SHR2_10DISKS_1VOL_WITH_EXPANSION, + "SHR2_EXPANSION": DSM_6_STORAGE_STORAGE_DS1515_PLUS_SHR2_10DISKS_1VOL_WITH_EXPANSION, # noqa: B950 }, }, } @@ -128,6 +128,7 @@ def __init__( device_token=None, debugmode=False, ): + """Constructor method.""" SynologyDSM.__init__( self, dsm_ip, @@ -153,14 +154,18 @@ def _execute_request(self, method, url, params, **kwargs): if "no_internet" in url: raise SynologyDSMRequestException( ConnError( - ": Failed to establish a new connection: [Errno 8] nodename nor servname provided, or not known" + ": Failed to establish a new connection: " + "[Errno 8] nodename nor servname provided, or not known" ) ) if VALID_HOST not in url: raise SynologyDSMRequestException( ConnError( - ": Failed to establish a new connection: [Errno 8] nodename nor servname provided, or not known" + ":" + " Failed to establish a new connection: [Errno 8] nodename " + "nor servname provided, or not known" ) ) diff --git a/tests/api_data/dsm_5/__init__.py b/tests/api_data/dsm_5/__init__.py index 63174dc3..ff260e95 100644 --- a/tests/api_data/dsm_5/__init__.py +++ b/tests/api_data/dsm_5/__init__.py @@ -9,3 +9,14 @@ from .storage.const_5_storage_storage import ( DSM_5_STORAGE_STORAGE_DS410J_RAID5_4DISKS_1VOL, ) + +__all__ = [ + "DSM_5_AUTH_LOGIN", + "DSM_5_AUTH_LOGIN_2SA", + "DSM_5_AUTH_LOGIN_2SA_OTP", + "DSM_5_API_INFO", + "DSM_5_CORE_UTILIZATION", + "DSM_5_DSM_INFORMATION", + "DSM_5_DSM_NETWORK", + "DSM_5_STORAGE_STORAGE_DS410J_RAID5_4DISKS_1VOL", +] diff --git a/tests/api_data/dsm_6/__init__.py b/tests/api_data/dsm_6/__init__.py index 0d4ba31f..26429449 100644 --- a/tests/api_data/dsm_6/__init__.py +++ b/tests/api_data/dsm_6/__init__.py @@ -58,3 +58,35 @@ from .surveillance_station.const_6_surveillance_station_home_mode import ( DSM_6_SURVEILLANCE_STATION_HOME_MODE_SWITCH, ) + +__all__ = [ + "DSM_6_AUTH_LOGIN", + "DSM_6_AUTH_LOGIN_2SA", + "DSM_6_AUTH_LOGIN_2SA_OTP", + "DSM_6_API_INFO", + "DSM_6_CORE_SECURITY", + "DSM_6_CORE_SECURITY_UPDATE_OUTOFDATE", + "DSM_6_CORE_SHARE", + "DSM_6_CORE_SYSTEM_DS218_PLAY", + "DSM_6_CORE_SYSTEM_DS918_PLUS", + "DSM_6_CORE_UPGRADE", + "DSM_6_CORE_UTILIZATION", + "DSM_6_CORE_UTILIZATION_ERROR_1055", + "DSM_6_DOWNLOAD_STATION_INFO_CONFIG", + "DSM_6_DOWNLOAD_STATION_INFO_INFO", + "DSM_6_DOWNLOAD_STATION_STAT_INFO", + "DSM_6_DOWNLOAD_STATION_TASK_LIST", + "DSM_6_DSM_INFORMATION", + "DSM_6_DSM_NETWORK", + "DSM_6_STORAGE_STORAGE_DS1515_PLUS_SHR2_10DISKS_1VOL_WITH_EXPANSION", + "DSM_6_STORAGE_STORAGE_DS1819_PLUS_SHR2_8DISKS_1VOL", + "DSM_6_STORAGE_STORAGE_DS213_PLUS_SHR1_2DISKS_2VOLS", + "DSM_6_STORAGE_STORAGE_DS918_PLUS_RAID5_3DISKS_1VOL", + "DSM_6_API_INFO_SURVEILLANCE_STATION", + "DSM_6_SURVEILLANCE_STATION_CAMERA_EVENT_MD_PARAM_SAVE", + "DSM_6_SURVEILLANCE_STATION_CAMERA_EVENT_MOTION_ENUM", + "DSM_6_SURVEILLANCE_STATION_CAMERA_GET_LIVE_VIEW_PATH", + "DSM_6_SURVEILLANCE_STATION_CAMERA_LIST", + "DSM_6_SURVEILLANCE_STATION_HOME_MODE_GET_INFO", + "DSM_6_SURVEILLANCE_STATION_HOME_MODE_SWITCH", +] diff --git a/tests/test_synology_dsm.py b/tests/test_synology_dsm.py index 2284ea33..de9ccaeb 100644 --- a/tests/test_synology_dsm.py +++ b/tests/test_synology_dsm.py @@ -28,8 +28,6 @@ from synology_dsm.exceptions import SynologyDSMLoginInvalidException from synology_dsm.exceptions import SynologyDSMRequestException -# pylint: disable=no-self-use,protected-access - class TestSynologyDSM(TestCase): """SynologyDSM test cases.""" @@ -37,6 +35,7 @@ class TestSynologyDSM(TestCase): api = None def setUp(self): + """Context initialisation called for all tests.""" self.api = SynologyDSMMock( VALID_HOST, VALID_PORT, @@ -112,9 +111,9 @@ def test_connection_failed(self): assert not error_value["api"] assert error_value["code"] == -1 assert error_value["reason"] == "Unknown" - assert ( - error_value["details"] - == "SSLError = [SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1076)" + assert error_value["details"] == ( + "SSLError = [SSL: WRONG_VERSION_NUMBER] " + "wrong version number (_ssl.c:1076)" ) assert not api.apis.get(API_AUTH) @@ -380,9 +379,9 @@ def test_request_post_failed(self): error_value = error.value.args[0] assert error_value["api"] == "SYNO.FileStation.Upload" assert error_value["code"] == 1805 - assert ( - error_value["reason"] - == "Can’t overwrite or skip the existed file, if no overwrite parameter is given" + assert error_value["reason"] == ( + "Can’t overwrite or skip the existed file, if no overwrite" + " parameter is given" ) assert not error_value["details"] diff --git a/tests/test_synology_dsm_5.py b/tests/test_synology_dsm_5.py index 2b8d299f..488db00e 100644 --- a/tests/test_synology_dsm_5.py +++ b/tests/test_synology_dsm_5.py @@ -21,13 +21,14 @@ from synology_dsm.exceptions import SynologyDSMLoginInvalidException from synology_dsm.exceptions import SynologyDSMRequestException -# pylint: disable=no-self-use,protected-access,anomalous-backslash-in-string + class TestSynologyDSM(TestCase): """SynologyDSM test cases.""" api = None def setUp(self): + """Context initialisation called for all tests.""" self.api = SynologyDSMMock( VALID_HOST, VALID_PORT, From 4156de88cb527f9ebddd146fda4e97d8f543c23a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Oct 2020 08:05:55 +0000 Subject: [PATCH 11/33] Bump pygments from 2.7.1 to 2.7.2 (#87) --- poetry.lock | 14 ++++++++++---- pyproject.toml | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/poetry.lock b/poetry.lock index 66739f81..60ec74cf 100644 --- a/poetry.lock +++ b/poetry.lock @@ -545,7 +545,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "pygments" -version = "2.7.1" +version = "2.7.2" description = "Pygments is a syntax highlighting package written in Python." category = "dev" optional = false @@ -959,7 +959,7 @@ testing = ["pytest (>=3.5,<3.7.3 || >3.7.3)", "pytest-checkdocs (>=1.2.3)", "pyt [metadata] lock-version = "1.1" python-versions = "^3.7.0" -content-hash = "40b234f06847f4f8ee765adaca61cc1698dd49bc37b043a609ef19fcf917ad91" +content-hash = "79620d431701ae3e96dba499f45bda87ad9c7e72e4a9578a432afe800e6bc786" [metadata.files] alabaster = [ @@ -1238,8 +1238,8 @@ pyflakes = [ {file = "pyflakes-2.2.0.tar.gz", hash = "sha256:35b2d75ee967ea93b55750aa9edbbf72813e06a66ba54438df2cfac9e3c27fc8"}, ] pygments = [ - {file = "Pygments-2.7.1-py3-none-any.whl", hash = "sha256:307543fe65c0947b126e83dd5a61bd8acbd84abec11f43caebaf5534cbc17998"}, - {file = "Pygments-2.7.1.tar.gz", hash = "sha256:926c3f319eda178d1bd90851e4317e6d8cdb5e292a3386aac9bd75eca29cf9c7"}, + {file = "Pygments-2.7.2-py3-none-any.whl", hash = "sha256:88a0bbcd659fcb9573703957c6b9cff9fab7295e6e76db54c9d00ae42df32773"}, + {file = "Pygments-2.7.2.tar.gz", hash = "sha256:381985fcc551eb9d37c52088a32914e00517e57f4a21609f48141ba08e193fa0"}, ] pyparsing = [ {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"}, @@ -1428,6 +1428,12 @@ typed-ast = [ {file = "typed_ast-1.4.1-cp38-cp38-win32.whl", hash = "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c"}, {file = "typed_ast-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4"}, {file = "typed_ast-1.4.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34"}, + {file = "typed_ast-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:92c325624e304ebf0e025d1224b77dd4e6393f18aab8d829b5b7e04afe9b7a2c"}, + {file = "typed_ast-1.4.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:d648b8e3bf2fe648745c8ffcee3db3ff903d0817a01a12dd6a6ea7a8f4889072"}, + {file = "typed_ast-1.4.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:fac11badff8313e23717f3dada86a15389d0708275bddf766cca67a84ead3e91"}, + {file = "typed_ast-1.4.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:0d8110d78a5736e16e26213114a38ca35cb15b6515d535413b090bd50951556d"}, + {file = "typed_ast-1.4.1-cp39-cp39-win32.whl", hash = "sha256:b52ccf7cfe4ce2a1064b18594381bccf4179c2ecf7f513134ec2f993dd4ab395"}, + {file = "typed_ast-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:3742b32cf1c6ef124d57f95be609c473d7ec4c14d0090e5a5e05a15269fb4d0c"}, {file = "typed_ast-1.4.1.tar.gz", hash = "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b"}, ] typeguard = [ diff --git a/pyproject.toml b/pyproject.toml index 0167eaa1..a31c2451 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,7 +55,7 @@ darglint = "^1.5.5" reorder-python-imports = "^2.3.5" pre-commit-hooks = "^3.3.0" sphinx-rtd-theme = "^0.5.0" -Pygments = "^2.7.1" +Pygments = "^2.7.2" [tool.poetry.scripts] python-synology = "synology_dsm.__main__:main" From b7b8b4d6b93abef1a648a755169208102619fa8c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Oct 2020 08:06:08 +0000 Subject: [PATCH 12/33] Bump virtualenv from 20.0.35 to 20.1.0 in /.github/workflows (#88) --- .github/workflows/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/constraints.txt b/.github/workflows/constraints.txt index 18efed35..c53d6c56 100644 --- a/.github/workflows/constraints.txt +++ b/.github/workflows/constraints.txt @@ -2,4 +2,4 @@ pip==20.2.4 nox==2020.8.22 nox-poetry==0.5.0 poetry==1.1.3 -virtualenv==20.0.35 +virtualenv==20.1.0 From a5dba9e998195aef3885b98d96a4f93049155804 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Oct 2020 08:12:30 +0000 Subject: [PATCH 13/33] Bump poetry from 1.1.3 to 1.1.4 in /.github/workflows (#89) --- .github/workflows/constraints.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/constraints.txt b/.github/workflows/constraints.txt index c53d6c56..2b085eac 100644 --- a/.github/workflows/constraints.txt +++ b/.github/workflows/constraints.txt @@ -1,5 +1,5 @@ pip==20.2.4 nox==2020.8.22 nox-poetry==0.5.0 -poetry==1.1.3 +poetry==1.1.4 virtualenv==20.1.0 From adf7abfac3383847d8f0882a1de0d15be571dad6 Mon Sep 17 00:00:00 2001 From: Michael <35783820+mib1185@users.noreply.github.com> Date: Tue, 27 Oct 2020 10:45:26 +0100 Subject: [PATCH 14/33] Add Upgrade detail infos (#86) * get update detail info * missing new line at the end * black compliant * flake8 compliant * fix pre-commit * Update tests/api_data/dsm_6/core/const_6_core_upgrade.py * Update tests/api_data/dsm_6/core/const_6_core_upgrade.py Co-authored-by: Quentame --- README.rst | 10 +++++++++ src/synology_dsm/api/core/upgrade.py | 17 +++++++++++++- tests/__init__.py | 4 ++-- tests/api_data/dsm_6/__init__.py | 6 +++-- .../dsm_6/core/const_6_core_upgrade.py | 22 ++++++++++++++++++- tests/test_synology_dsm.py | 5 ++++- 6 files changed, 57 insertions(+), 7 deletions(-) diff --git a/README.rst b/README.rst index 83465a88..e4142504 100644 --- a/README.rst +++ b/README.rst @@ -252,6 +252,16 @@ Upgrade usage if upgrade.update_available: do something ... + # get available version string (return None if no update available) + upgrade.available_version + + # get need of reboot (return None if no update available) + upgrade.reboot_needed + + # get need of service restarts (return None if no update available) + upgrade.service_restarts + + Credits / Special Thanks ======================== - https://github.com/florianeinfalt diff --git a/src/synology_dsm/api/core/upgrade.py b/src/synology_dsm/api/core/upgrade.py index 250f380c..d00839d5 100644 --- a/src/synology_dsm/api/core/upgrade.py +++ b/src/synology_dsm/api/core/upgrade.py @@ -20,5 +20,20 @@ def update(self): @property def update_available(self): - """Gets all Upgrade info.""" + """Gets available update info.""" return self._data["update"].get("available") + + @property + def available_version(self): + """Gets available verion info.""" + return self._data["update"].get("version") + + @property + def reboot_needed(self): + """Gets info if reboot is needed.""" + return self._data["update"].get("reboot") + + @property + def service_restarts(self): + """Gets info if services are restarted.""" + return self._data["update"].get("restart") diff --git a/tests/__init__.py b/tests/__init__.py index 40653d0f..11bf54bb 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -23,7 +23,7 @@ from .api_data.dsm_6 import DSM_6_CORE_SECURITY_UPDATE_OUTOFDATE from .api_data.dsm_6 import DSM_6_CORE_SHARE from .api_data.dsm_6 import DSM_6_CORE_SYSTEM_DS918_PLUS -from .api_data.dsm_6 import DSM_6_CORE_UPGRADE +from .api_data.dsm_6 import DSM_6_CORE_UPGRADE_TRUE from .api_data.dsm_6 import DSM_6_CORE_UTILIZATION from .api_data.dsm_6 import DSM_6_CORE_UTILIZATION_ERROR_1055 from .api_data.dsm_6 import DSM_6_DOWNLOAD_STATION_INFO_CONFIG @@ -88,7 +88,7 @@ "CORE_SHARE": DSM_6_CORE_SHARE, "CORE_SYSTEM": DSM_6_CORE_SYSTEM_DS918_PLUS, "CORE_UTILIZATION": DSM_6_CORE_UTILIZATION, - "CORE_UPGRADE": DSM_6_CORE_UPGRADE, + "CORE_UPGRADE": DSM_6_CORE_UPGRADE_TRUE, "STORAGE_STORAGE": { "RAID": DSM_6_STORAGE_STORAGE_DS918_PLUS_RAID5_3DISKS_1VOL, "SHR1": DSM_6_STORAGE_STORAGE_DS213_PLUS_SHR1_2DISKS_2VOLS, diff --git a/tests/api_data/dsm_6/__init__.py b/tests/api_data/dsm_6/__init__.py index 26429449..37341874 100644 --- a/tests/api_data/dsm_6/__init__.py +++ b/tests/api_data/dsm_6/__init__.py @@ -8,7 +8,8 @@ from .core.const_6_core_share import DSM_6_CORE_SHARE from .core.const_6_core_system import DSM_6_CORE_SYSTEM_DS218_PLAY from .core.const_6_core_system import DSM_6_CORE_SYSTEM_DS918_PLUS -from .core.const_6_core_upgrade import DSM_6_CORE_UPGRADE +from .core.const_6_core_upgrade import DSM_6_CORE_UPGRADE_FALSE +from .core.const_6_core_upgrade import DSM_6_CORE_UPGRADE_TRUE from .core.const_6_core_utilization import DSM_6_CORE_UTILIZATION from .core.const_6_core_utilization import DSM_6_CORE_UTILIZATION_ERROR_1055 from .download_station.const_6_download_station_info import ( @@ -69,7 +70,8 @@ "DSM_6_CORE_SHARE", "DSM_6_CORE_SYSTEM_DS218_PLAY", "DSM_6_CORE_SYSTEM_DS918_PLUS", - "DSM_6_CORE_UPGRADE", + "DSM_6_CORE_UPGRADE_FALSE", + "DSM_6_CORE_UPGRADE_TRUE", "DSM_6_CORE_UTILIZATION", "DSM_6_CORE_UTILIZATION_ERROR_1055", "DSM_6_DOWNLOAD_STATION_INFO_CONFIG", diff --git a/tests/api_data/dsm_6/core/const_6_core_upgrade.py b/tests/api_data/dsm_6/core/const_6_core_upgrade.py index aaf83c60..a1c4ed71 100644 --- a/tests/api_data/dsm_6/core/const_6_core_upgrade.py +++ b/tests/api_data/dsm_6/core/const_6_core_upgrade.py @@ -1,3 +1,23 @@ """DSM 6 SYNO.Core.Upgrade data.""" -DSM_6_CORE_UPGRADE = {"data": {"update": {"available": False}}, "success": True} +DSM_6_CORE_UPGRADE_FALSE = {"data": {"update": {"available": False}}, "success": True} +DSM_6_CORE_UPGRADE_TRUE = { + "data": { + "update": { + "available": True, + "reboot": "now", + "restart": "some", + "type": "nano", + "version": "DSM 6.2.3-25426 Update 2", + "version_details": { + "buildnumber": 25426, + "major": 6, + "micro": 3, + "minor": 2, + "nano": 2, + "os_name": "DSM", + }, + } + }, + "success": True, +} diff --git a/tests/test_synology_dsm.py b/tests/test_synology_dsm.py index de9ccaeb..d24023a9 100644 --- a/tests/test_synology_dsm.py +++ b/tests/test_synology_dsm.py @@ -574,7 +574,10 @@ def test_upgrade(self): """Test upgrade.""" assert self.api.upgrade self.api.upgrade.update() - assert self.api.upgrade.update_available is False + assert self.api.upgrade.update_available + assert self.api.upgrade.available_version == "DSM 6.2.3-25426 Update 2" + assert self.api.upgrade.reboot_needed == "now" + assert self.api.upgrade.service_restarts == "some" def test_utilisation(self): """Test utilisation.""" From 94d98acb8b7c1257cffeb794add745fa464fa9b9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Oct 2020 08:01:18 +0000 Subject: [PATCH 15/33] Bump pre-commit from 2.7.1 to 2.8.1 (#90) --- poetry.lock | 21 +++++++++++++-------- pyproject.toml | 2 +- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/poetry.lock b/poetry.lock index 60ec74cf..54e40dc5 100644 --- a/poetry.lock +++ b/poetry.lock @@ -481,7 +481,7 @@ dev = ["pre-commit", "tox"] [[package]] name = "pre-commit" -version = "2.7.1" +version = "2.8.1" description = "A framework for managing and maintaining multi-language pre-commit hooks." category = "dev" optional = false @@ -579,7 +579,7 @@ py = ">=1.8.2" toml = "*" [package.extras] -checkqa_mypy = ["mypy (0.780)"] +checkqa_mypy = ["mypy (==0.780)"] testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] [[package]] @@ -633,7 +633,7 @@ urllib3 = ">=1.21.1,<1.25.0 || >1.25.0,<1.25.1 || >1.25.1,<1.26" [package.extras] security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"] -socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)", "win-inet-pton"] +socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] [[package]] name = "restructuredtext-lint" @@ -905,7 +905,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" [package.extras] brotli = ["brotlipy (>=0.6.0)"] secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] -socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"] +socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] name = "virtualenv" @@ -935,6 +935,8 @@ optional = false python-versions = "*" [package.dependencies] +colorama = {version = "*", optional = true, markers = "platform_system == \"Windows\" and extra == \"colors\""} +Pygments = {version = "*", optional = true, markers = "extra == \"colors\""} six = "*" [package.extras] @@ -954,12 +956,12 @@ python-versions = ">=3.6" [package.extras] docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"] -testing = ["pytest (>=3.5,<3.7.3 || >3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-cov", "jaraco.test (>=3.2.0)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"] +testing = ["pytest (>=3.5,!=3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-cov", "jaraco.test (>=3.2.0)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"] [metadata] lock-version = "1.1" python-versions = "^3.7.0" -content-hash = "79620d431701ae3e96dba499f45bda87ad9c7e72e4a9578a432afe800e6bc786" +content-hash = "6e301d5ffe7e6f314bbc244258438a1e994d270e882fc24320069f78d3f84758" [metadata.files] alabaster = [ @@ -1214,8 +1216,8 @@ pluggy = [ {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, ] pre-commit = [ - {file = "pre_commit-2.7.1-py2.py3-none-any.whl", hash = "sha256:810aef2a2ba4f31eed1941fc270e72696a1ad5590b9751839c90807d0fff6b9a"}, - {file = "pre_commit-2.7.1.tar.gz", hash = "sha256:c54fd3e574565fe128ecc5e7d2f91279772ddb03f8729645fa812fe809084a70"}, + {file = "pre_commit-2.8.1-py2.py3-none-any.whl", hash = "sha256:7eadaa7f4547a8a19b83230ce430ba81bbe4797bd41c8d7fb54b246164628d1f"}, + {file = "pre_commit-2.8.1.tar.gz", hash = "sha256:8fb2037c404ef8c87125e72564f316cf2bc94fc9c1cb184b8352117de747e164"}, ] pre-commit-hooks = [ {file = "pre_commit_hooks-3.3.0-py2.py3-none-any.whl", hash = "sha256:2190d72ac867bd9b8880de32d9304ec54182c89720cce56f22742890ed8ba90f"}, @@ -1415,16 +1417,19 @@ typed-ast = [ {file = "typed_ast-1.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75"}, {file = "typed_ast-1.4.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652"}, {file = "typed_ast-1.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7"}, + {file = "typed_ast-1.4.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:fcf135e17cc74dbfbc05894ebca928ffeb23d9790b3167a674921db19082401f"}, {file = "typed_ast-1.4.1-cp36-cp36m-win32.whl", hash = "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1"}, {file = "typed_ast-1.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa"}, {file = "typed_ast-1.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614"}, {file = "typed_ast-1.4.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41"}, {file = "typed_ast-1.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b"}, + {file = "typed_ast-1.4.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:f208eb7aff048f6bea9586e61af041ddf7f9ade7caed625742af423f6bae3298"}, {file = "typed_ast-1.4.1-cp37-cp37m-win32.whl", hash = "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe"}, {file = "typed_ast-1.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355"}, {file = "typed_ast-1.4.1-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6"}, {file = "typed_ast-1.4.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907"}, {file = "typed_ast-1.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d"}, + {file = "typed_ast-1.4.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:7e4c9d7658aaa1fc80018593abdf8598bf91325af6af5cce4ce7c73bc45ea53d"}, {file = "typed_ast-1.4.1-cp38-cp38-win32.whl", hash = "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c"}, {file = "typed_ast-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4"}, {file = "typed_ast-1.4.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34"}, diff --git a/pyproject.toml b/pyproject.toml index a31c2451..ac8f47aa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,7 +43,7 @@ typeguard = "^2.9.1" xdoctest = {extras = ["colors"], version = "^0.15.0"} sphinx = "^3.2.1" sphinx-autobuild = "^2020.9.1" -pre-commit = "^2.7.1" +pre-commit = "^2.8.1" flake8 = "^3.8.4" black = "^20.8b1" flake8-bandit = "^2.1.2" From 43876f886798a4cc934a41fe690658e289c8a945 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Oct 2020 08:07:43 +0000 Subject: [PATCH 16/33] Bump pytest from 6.1.1 to 6.1.2 (#91) --- poetry.lock | 8 ++++---- pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/poetry.lock b/poetry.lock index 54e40dc5..ce1eefb0 100644 --- a/poetry.lock +++ b/poetry.lock @@ -561,7 +561,7 @@ python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" [[package]] name = "pytest" -version = "6.1.1" +version = "6.1.2" description = "pytest: simple powerful testing with Python" category = "dev" optional = false @@ -961,7 +961,7 @@ testing = ["pytest (>=3.5,!=3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake [metadata] lock-version = "1.1" python-versions = "^3.7.0" -content-hash = "6e301d5ffe7e6f314bbc244258438a1e994d270e882fc24320069f78d3f84758" +content-hash = "f65b635fcdd8851e2f315b2debd6c61055ccd1a20f771a2afdf2183d37b2f021" [metadata.files] alabaster = [ @@ -1248,8 +1248,8 @@ pyparsing = [ {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"}, ] pytest = [ - {file = "pytest-6.1.1-py3-none-any.whl", hash = "sha256:7a8190790c17d79a11f847fba0b004ee9a8122582ebff4729a082c109e81a4c9"}, - {file = "pytest-6.1.1.tar.gz", hash = "sha256:8f593023c1a0f916110285b6efd7f99db07d59546e3d8c36fc60e2ab05d3be92"}, + {file = "pytest-6.1.2-py3-none-any.whl", hash = "sha256:4288fed0d9153d9646bfcdf0c0428197dba1ecb27a33bb6e031d002fa88653fe"}, + {file = "pytest-6.1.2.tar.gz", hash = "sha256:c0a7e94a8cdbc5422a51ccdad8e6f1024795939cc89159a0ae7f0b316ad3823e"}, ] pytz = [ {file = "pytz-2020.1-py2.py3-none-any.whl", hash = "sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed"}, diff --git a/pyproject.toml b/pyproject.toml index ac8f47aa..09c22b28 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,7 +35,7 @@ requests = "^2.24.0" urllib3 = "^1.25.10" [tool.poetry.dev-dependencies] -pytest = "^6.1.1" +pytest = "^6.1.2" coverage = {extras = ["toml"], version = "^5.3"} safety = "^1.9.0" mypy = "^0.790" From 38e2394e9eb00c7c5d8e71afb5101d47faa6a004 Mon Sep 17 00:00:00 2001 From: Narmishka <73436375+Narmishka@users.noreply.github.com> Date: Thu, 29 Oct 2020 13:51:54 +0100 Subject: [PATCH 17/33] Fix MAC address may be empty if NAS uses PPPoE (#93) --- src/synology_dsm/api/dsm/network.py | 3 +- tests/__init__.py | 4 +- tests/api_data/dsm_6/__init__.py | 4 +- .../api_data/dsm_6/dsm/const_6_dsm_network.py | 55 ++++++++++++++++++- 4 files changed, 60 insertions(+), 6 deletions(-) diff --git a/src/synology_dsm/api/dsm/network.py b/src/synology_dsm/api/dsm/network.py index 5a0808b4..b4195894 100644 --- a/src/synology_dsm/api/dsm/network.py +++ b/src/synology_dsm/api/dsm/network.py @@ -49,7 +49,8 @@ def macs(self): """MACs of the NAS.""" # noqa: D403 macs = [] for interface in self.interfaces: - macs.append(interface["mac"]) + if interface.get("mac"): + macs.append(interface["mac"]) return macs @property diff --git a/tests/__init__.py b/tests/__init__.py index 11bf54bb..b42188ac 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -31,7 +31,7 @@ from .api_data.dsm_6 import DSM_6_DOWNLOAD_STATION_STAT_INFO from .api_data.dsm_6 import DSM_6_DOWNLOAD_STATION_TASK_LIST from .api_data.dsm_6 import DSM_6_DSM_INFORMATION -from .api_data.dsm_6 import DSM_6_DSM_NETWORK +from .api_data.dsm_6 import DSM_6_DSM_NETWORK_2LAN_1PPPOE from .api_data.dsm_6 import ( DSM_6_STORAGE_STORAGE_DS1515_PLUS_SHR2_10DISKS_1VOL_WITH_EXPANSION, ) @@ -83,7 +83,7 @@ "AUTH_LOGIN_2SA": DSM_6_AUTH_LOGIN_2SA, "AUTH_LOGIN_2SA_OTP": DSM_6_AUTH_LOGIN_2SA_OTP, "DSM_INFORMATION": DSM_6_DSM_INFORMATION, - "DSM_NETWORK": DSM_6_DSM_NETWORK, + "DSM_NETWORK": DSM_6_DSM_NETWORK_2LAN_1PPPOE, "CORE_SECURITY": DSM_6_CORE_SECURITY, "CORE_SHARE": DSM_6_CORE_SHARE, "CORE_SYSTEM": DSM_6_CORE_SYSTEM_DS918_PLUS, diff --git a/tests/api_data/dsm_6/__init__.py b/tests/api_data/dsm_6/__init__.py index 37341874..394e7587 100644 --- a/tests/api_data/dsm_6/__init__.py +++ b/tests/api_data/dsm_6/__init__.py @@ -25,7 +25,7 @@ DSM_6_DOWNLOAD_STATION_TASK_LIST, ) from .dsm.const_6_dsm_info import DSM_6_DSM_INFORMATION -from .dsm.const_6_dsm_network import DSM_6_DSM_NETWORK +from .dsm.const_6_dsm_network import DSM_6_DSM_NETWORK_2LAN_1PPPOE from .storage.const_6_storage_storage import ( DSM_6_STORAGE_STORAGE_DS1515_PLUS_SHR2_10DISKS_1VOL_WITH_EXPANSION, ) @@ -79,7 +79,7 @@ "DSM_6_DOWNLOAD_STATION_STAT_INFO", "DSM_6_DOWNLOAD_STATION_TASK_LIST", "DSM_6_DSM_INFORMATION", - "DSM_6_DSM_NETWORK", + "DSM_6_DSM_NETWORK_2LAN_1PPPOE", "DSM_6_STORAGE_STORAGE_DS1515_PLUS_SHR2_10DISKS_1VOL_WITH_EXPANSION", "DSM_6_STORAGE_STORAGE_DS1819_PLUS_SHR2_8DISKS_1VOL", "DSM_6_STORAGE_STORAGE_DS213_PLUS_SHR1_2DISKS_2VOLS", 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 38a6d05f..600151ac 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,6 +1,6 @@ """DSM 6 SYNO.DSM.Network data.""" -DSM_6_DSM_NETWORK = { +DSM_6_DSM_NETWORK_1LAN = { "data": { "dns": ["192.168.0.35"], "gateway": "192.168.0.254", @@ -35,3 +35,56 @@ }, "success": True, } + +DSM_6_DSM_NETWORK_2LAN_1PPPOE = { + "data": { + "dns": ["192.168.0.35"], + "gateway": "192.168.0.254", + "hostname": "NAS_[NAME]", + "interfaces": [ + { + "id": "eth0", + "ip": [{"address": "192.168.5.10", "netmask": "255.255.255.0"}], + "ipv6": [ + { + "address": "2001:b211:317c:147e:211:32ff:fe5d:fd11", + "prefix_length": 64, + "scope": "global", + }, + { + "address": "fe80::211:32ff:fe5d:fd11", + "prefix_length": 64, + "scope": "link", + }, + ], + "mac": "00-11-32-XX-XX-11", + "type": "lan", + }, + { + "id": "eth1", + "ip": [{"address": "192.168.1.100", "netmask": "255.255.255.0"}], + "ipv6": [ + { + "address": "2001:b011:300c:176c:211:11ff:fe5d:fd12", + "prefix_length": 64, + "scope": "global", + }, + { + "address": "fe80::211:31ff:ff5d:fd12", + "prefix_length": 64, + "scope": "link", + }, + ], + "mac": "00-11-32-XX-XX-12", + "type": "lan", + }, + { + "id": "ppp0", + "ip": [{"address": "114.45.2.158", "netmask": "255.255.255.255"}], + "type": "pppoe", + }, + ], + "workgroup": "WORKGROUP", + }, + "success": True, +} From f8ff80c10e3057e6fd6ba64cf6fc9a964197c683 Mon Sep 17 00:00:00 2001 From: Narmishka <73436375+Narmishka@users.noreply.github.com> Date: Fri, 30 Oct 2020 23:57:25 +0100 Subject: [PATCH 18/33] Add CODEOWNERS (#94) --- .github/CODEOWNERS | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..2a5f7cee --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,11 @@ +@Quentame + +.github/* @oncleben31 + +*/surveillance_station/* @shenxn +src/synology_dsm/api/core/share.py @Gestas +src/synology_dsm/api/core/system.py @mib1185 +src/synology_dsm/api/core/upgrade.py @mib1185 +tests/api_data/dsm_6/core/const_6_core_share.py @Gestas +tests/api_data/dsm_6/core/const_6_core_system.py @mib1185 +tests/api_data/dsm_6/core/const_6_core_upgrade.py @mib1185 From b924e9c56c8745ee7e6c5f62efa9fe6d739cd9a0 Mon Sep 17 00:00:00 2001 From: Narmishka <73436375+Narmishka@users.noreply.github.com> Date: Sat, 31 Oct 2020 00:01:31 +0100 Subject: [PATCH 19/33] Add missing code owner (#95) --- .github/CODEOWNERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 2a5f7cee..f1b045a8 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,6 +1,8 @@ @Quentame .github/* @oncleben31 +.darglint @oncleben31 +.flake8 @oncleben31 */surveillance_station/* @shenxn src/synology_dsm/api/core/share.py @Gestas From 5d192bb6437bd88b6fe11fba730c24baf6cd4c12 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Nov 2020 14:16:07 +0000 Subject: [PATCH 20/33] Bump pre-commit from 2.8.1 to 2.8.2 (#96) --- poetry.lock | 8 ++++---- pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/poetry.lock b/poetry.lock index ce1eefb0..c7de87e5 100644 --- a/poetry.lock +++ b/poetry.lock @@ -481,7 +481,7 @@ dev = ["pre-commit", "tox"] [[package]] name = "pre-commit" -version = "2.8.1" +version = "2.8.2" description = "A framework for managing and maintaining multi-language pre-commit hooks." category = "dev" optional = false @@ -961,7 +961,7 @@ testing = ["pytest (>=3.5,!=3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake [metadata] lock-version = "1.1" python-versions = "^3.7.0" -content-hash = "f65b635fcdd8851e2f315b2debd6c61055ccd1a20f771a2afdf2183d37b2f021" +content-hash = "44d49ac15574e836c9ba0eda16ffa0a9844696d3333b176f7ee9356436c3ba8c" [metadata.files] alabaster = [ @@ -1216,8 +1216,8 @@ pluggy = [ {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, ] pre-commit = [ - {file = "pre_commit-2.8.1-py2.py3-none-any.whl", hash = "sha256:7eadaa7f4547a8a19b83230ce430ba81bbe4797bd41c8d7fb54b246164628d1f"}, - {file = "pre_commit-2.8.1.tar.gz", hash = "sha256:8fb2037c404ef8c87125e72564f316cf2bc94fc9c1cb184b8352117de747e164"}, + {file = "pre_commit-2.8.2-py2.py3-none-any.whl", hash = "sha256:22e6aa3bd571debb01eb7d34483f11c01b65237be4eebbf30c3d4fb65762d315"}, + {file = "pre_commit-2.8.2.tar.gz", hash = "sha256:905ebc9b534b991baec87e934431f2d0606ba27f2b90f7f652985f5a5b8b6ae6"}, ] pre-commit-hooks = [ {file = "pre_commit_hooks-3.3.0-py2.py3-none-any.whl", hash = "sha256:2190d72ac867bd9b8880de32d9304ec54182c89720cce56f22742890ed8ba90f"}, diff --git a/pyproject.toml b/pyproject.toml index 09c22b28..a849cc6b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,7 +43,7 @@ typeguard = "^2.9.1" xdoctest = {extras = ["colors"], version = "^0.15.0"} sphinx = "^3.2.1" sphinx-autobuild = "^2020.9.1" -pre-commit = "^2.8.1" +pre-commit = "^2.8.2" flake8 = "^3.8.4" black = "^20.8b1" flake8-bandit = "^2.1.2" From 3758d2a8b90daf8367e1f400b821538ac44c6f84 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Nov 2020 14:23:00 +0000 Subject: [PATCH 21/33] Bump reorder-python-imports from 2.3.5 to 2.3.6 (#97) --- poetry.lock | 8 ++++---- pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/poetry.lock b/poetry.lock index c7de87e5..e294b76b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -608,7 +608,7 @@ python-versions = "*" [[package]] name = "reorder-python-imports" -version = "2.3.5" +version = "2.3.6" description = "Tool for reordering python imports" category = "dev" optional = false @@ -961,7 +961,7 @@ testing = ["pytest (>=3.5,!=3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake [metadata] lock-version = "1.1" python-versions = "^3.7.0" -content-hash = "44d49ac15574e836c9ba0eda16ffa0a9844696d3333b176f7ee9356436c3ba8c" +content-hash = "f01e679ac4f5c58c17d0b0f5af44e8a94ccac2c070c60aced3a52fb4a6394240" [metadata.files] alabaster = [ @@ -1298,8 +1298,8 @@ regex = [ {file = "regex-2020.10.15.tar.gz", hash = "sha256:d25f5cca0f3af6d425c9496953445bf5b288bb5b71afc2b8308ad194b714c159"}, ] reorder-python-imports = [ - {file = "reorder_python_imports-2.3.5-py2.py3-none-any.whl", hash = "sha256:6e8d3baba68c409ec87242757cf579a7ad2b133d1efed498be987b97ee385ac3"}, - {file = "reorder_python_imports-2.3.5.tar.gz", hash = "sha256:7c46593d39899e3fb249248b448bde93ee7417889904f015c0c5a738c23fd0e0"}, + {file = "reorder_python_imports-2.3.6-py2.py3-none-any.whl", hash = "sha256:1299c31adf341eba2c17543e3cc7fab7389766e726ab54d20440917b5b96b5c5"}, + {file = "reorder_python_imports-2.3.6.tar.gz", hash = "sha256:2ea16d2253536e7f90427b383cd046e46977ca25aae82464883eee882bc7d21b"}, ] requests = [ {file = "requests-2.24.0-py2.py3-none-any.whl", hash = "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898"}, diff --git a/pyproject.toml b/pyproject.toml index a849cc6b..0f81db88 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -52,7 +52,7 @@ flake8-docstrings = "^1.5.0" flake8-rst-docstrings = "^0.0.14" pep8-naming = "^0.11.1" darglint = "^1.5.5" -reorder-python-imports = "^2.3.5" +reorder-python-imports = "^2.3.6" pre-commit-hooks = "^3.3.0" sphinx-rtd-theme = "^0.5.0" Pygments = "^2.7.2" From 9ef6fb934c446c65b167ca586943b7fbbdbd2257 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Nov 2020 15:25:56 +0000 Subject: [PATCH 22/33] Bump sphinx from 3.2.1 to 3.3.0 (#98) --- poetry.lock | 10 +++++----- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index e294b76b..6c1a9166 100644 --- a/poetry.lock +++ b/poetry.lock @@ -709,7 +709,7 @@ python-versions = "*" [[package]] name = "sphinx" -version = "3.2.1" +version = "3.3.0" description = "Python documentation generator" category = "dev" optional = false @@ -735,7 +735,7 @@ sphinxcontrib-serializinghtml = "*" [package.extras] docs = ["sphinxcontrib-websupport"] -lint = ["flake8 (>=3.5.0)", "flake8-import-order", "mypy (>=0.780)", "docutils-stubs"] +lint = ["flake8 (>=3.5.0)", "flake8-import-order", "mypy (>=0.790)", "docutils-stubs"] test = ["pytest", "pytest-cov", "html5lib", "typed-ast", "cython"] [[package]] @@ -961,7 +961,7 @@ testing = ["pytest (>=3.5,!=3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake [metadata] lock-version = "1.1" python-versions = "^3.7.0" -content-hash = "f01e679ac4f5c58c17d0b0f5af44e8a94ccac2c070c60aced3a52fb4a6394240" +content-hash = "372f7d159ec1adf678abd431f2f1aead10f8c296cc2fcbb8f9e62bd8e7b5a598" [metadata.files] alabaster = [ @@ -1355,8 +1355,8 @@ snowballstemmer = [ {file = "snowballstemmer-2.0.0.tar.gz", hash = "sha256:df3bac3df4c2c01363f3dd2cfa78cce2840a79b9f1c2d2de9ce8d31683992f52"}, ] sphinx = [ - {file = "Sphinx-3.2.1-py3-none-any.whl", hash = "sha256:ce6fd7ff5b215af39e2fcd44d4a321f6694b4530b6f2b2109b64d120773faea0"}, - {file = "Sphinx-3.2.1.tar.gz", hash = "sha256:321d6d9b16fa381a5306e5a0b76cd48ffbc588e6340059a729c6fdd66087e0e8"}, + {file = "Sphinx-3.3.0-py3-none-any.whl", hash = "sha256:3abdb2c57a65afaaa4f8573cbabd5465078eb6fd282c1e4f87f006875a7ec0c7"}, + {file = "Sphinx-3.3.0.tar.gz", hash = "sha256:1c21e7c5481a31b531e6cbf59c3292852ccde175b504b00ce2ff0b8f4adc3649"}, ] sphinx-autobuild = [ {file = "sphinx-autobuild-2020.9.1.tar.gz", hash = "sha256:4b184a7db893f2100bbd831991ae54ca89167a2b9ce68faea71eaa9e37716aed"}, diff --git a/pyproject.toml b/pyproject.toml index 0f81db88..72fe467f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,7 +41,7 @@ safety = "^1.9.0" mypy = "^0.790" typeguard = "^2.9.1" xdoctest = {extras = ["colors"], version = "^0.15.0"} -sphinx = "^3.2.1" +sphinx = "^3.3.0" sphinx-autobuild = "^2020.9.1" pre-commit = "^2.8.2" flake8 = "^3.8.4" From 35518eb61b92a8c5b369d33f0117c55d4602fb76 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Nov 2020 09:52:47 +0100 Subject: [PATCH 23/33] Update actions/checkout requirement to v2.3.4 (#99) Updates the requirements on [actions/checkout](https://github.com/actions/checkout) to permit the latest version. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/commits/5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 2 +- .github/workflows/tests.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 33779267..2970ae46 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out the repository - uses: actions/checkout@v2.3.3 + uses: actions/checkout@v2.3.4 with: fetch-depth: 2 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index bda431b9..b68ef964 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -32,7 +32,7 @@ jobs: steps: - name: Check out the repository - uses: actions/checkout@v2.3.3 + uses: actions/checkout@v2.3.4 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v2.1.4 @@ -101,7 +101,7 @@ jobs: needs: tests steps: - name: Check out the repository - uses: actions/checkout@v2.3.2 + uses: actions/checkout@v2.3.4 - name: Set up Python 3.9 uses: actions/setup-python@v2.1.4 From d28e92c2f76a64edf7c1f8599097848376f51b68 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Nov 2020 19:26:01 +0000 Subject: [PATCH 24/33] Bump actions/cache from v2.1.2 to v2.1.3 (#100) --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index b68ef964..3fb6fa1c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -70,7 +70,7 @@ jobs: print("::set-output name=result::{}".format(result)) - name: Restore pre-commit cache - uses: actions/cache@v2.1.2 + uses: actions/cache@v2.1.3 if: matrix.session == 'pre-commit' with: path: ~/.cache/pre-commit From 9e3321435d47f71340394d7e9da0f206629323a5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Nov 2020 22:11:58 +0000 Subject: [PATCH 25/33] Bump requests from 2.24.0 to 2.25.0 (#101) --- poetry.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/poetry.lock b/poetry.lock index 6c1a9166..e6780ed7 100644 --- a/poetry.lock +++ b/poetry.lock @@ -619,7 +619,7 @@ python-versions = ">=3.6.1" [[package]] name = "requests" -version = "2.24.0" +version = "2.25.0" description = "Python HTTP for Humans." category = "main" optional = false @@ -629,7 +629,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" certifi = ">=2017.4.17" chardet = ">=3.0.2,<4" idna = ">=2.5,<3" -urllib3 = ">=1.21.1,<1.25.0 || >1.25.0,<1.25.1 || >1.25.1,<1.26" +urllib3 = ">=1.21.1,<1.27" [package.extras] security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"] @@ -1302,8 +1302,8 @@ reorder-python-imports = [ {file = "reorder_python_imports-2.3.6.tar.gz", hash = "sha256:2ea16d2253536e7f90427b383cd046e46977ca25aae82464883eee882bc7d21b"}, ] requests = [ - {file = "requests-2.24.0-py2.py3-none-any.whl", hash = "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898"}, - {file = "requests-2.24.0.tar.gz", hash = "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b"}, + {file = "requests-2.25.0-py2.py3-none-any.whl", hash = "sha256:e786fa28d8c9154e6a4de5d46a1d921b8749f8b74e28bde23768e5e16eece998"}, + {file = "requests-2.25.0.tar.gz", hash = "sha256:7f1a0b932f4a60a1a65caa4263921bb7d9ee911957e0ae4a23a6dd08185ad5f8"}, ] restructuredtext-lint = [ {file = "restructuredtext_lint-1.3.1.tar.gz", hash = "sha256:470e53b64817211a42805c3a104d2216f6f5834b22fe7adb637d1de4d6501fb8"}, From 1e459e6cfe521f739d7aa502345e8694539ace2a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Nov 2020 22:12:16 +0000 Subject: [PATCH 26/33] Bump codecov/codecov-action from v1.0.14 to v1.0.15 (#105) --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 3fb6fa1c..509caf0f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -137,4 +137,4 @@ jobs: nox --force-color --session=coverage -- xml - name: Upload coverage report - uses: codecov/codecov-action@v1.0.14 + uses: codecov/codecov-action@v1.0.15 From da04bd761fb170d463e550039ee860a060262717 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Nov 2020 22:12:29 +0000 Subject: [PATCH 27/33] Bump actions/upload-artifact from v2.2.0 to v2.2.1 (#104) --- .github/workflows/tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 509caf0f..e4bff3d1 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -84,14 +84,14 @@ jobs: - name: Upload coverage data if: always() && matrix.session == 'tests' - uses: "actions/upload-artifact@v2.2.0" + uses: "actions/upload-artifact@v2.2.1" with: name: coverage-data path: ".coverage.*" - name: Upload documentation if: matrix.session == 'docs-build' - uses: actions/upload-artifact@v2.2.0 + uses: actions/upload-artifact@v2.2.1 with: name: docs path: docs/_build From e9c290de72cf621d4b962d700e2324a220c525ea Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Nov 2020 22:12:43 +0000 Subject: [PATCH 28/33] Bump actions/download-artifact from v2.0.5 to v2.0.6 (#103) --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e4bff3d1..bb544907 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -124,7 +124,7 @@ jobs: nox --version - name: Download coverage data - uses: actions/download-artifact@v2.0.5 + uses: actions/download-artifact@v2.0.6 with: name: coverage-data From d05a2785f0368aedfc0fdba4e6037951475220a4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Nov 2020 22:12:53 +0000 Subject: [PATCH 29/33] Bump sphinx from 3.3.0 to 3.3.1 (#102) --- poetry.lock | 8 ++++---- pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/poetry.lock b/poetry.lock index e6780ed7..9808cdf1 100644 --- a/poetry.lock +++ b/poetry.lock @@ -709,7 +709,7 @@ python-versions = "*" [[package]] name = "sphinx" -version = "3.3.0" +version = "3.3.1" description = "Python documentation generator" category = "dev" optional = false @@ -961,7 +961,7 @@ testing = ["pytest (>=3.5,!=3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake [metadata] lock-version = "1.1" python-versions = "^3.7.0" -content-hash = "372f7d159ec1adf678abd431f2f1aead10f8c296cc2fcbb8f9e62bd8e7b5a598" +content-hash = "c52e1e3a8b436b91d7fac920d8745e576575a079def6a53c6ceb8c98530197ad" [metadata.files] alabaster = [ @@ -1355,8 +1355,8 @@ snowballstemmer = [ {file = "snowballstemmer-2.0.0.tar.gz", hash = "sha256:df3bac3df4c2c01363f3dd2cfa78cce2840a79b9f1c2d2de9ce8d31683992f52"}, ] sphinx = [ - {file = "Sphinx-3.3.0-py3-none-any.whl", hash = "sha256:3abdb2c57a65afaaa4f8573cbabd5465078eb6fd282c1e4f87f006875a7ec0c7"}, - {file = "Sphinx-3.3.0.tar.gz", hash = "sha256:1c21e7c5481a31b531e6cbf59c3292852ccde175b504b00ce2ff0b8f4adc3649"}, + {file = "Sphinx-3.3.1-py3-none-any.whl", hash = "sha256:d4e59ad4ea55efbb3c05cde3bfc83bfc14f0c95aa95c3d75346fcce186a47960"}, + {file = "Sphinx-3.3.1.tar.gz", hash = "sha256:1e8d592225447104d1172be415bc2972bd1357e3e12fdc76edf2261105db4300"}, ] sphinx-autobuild = [ {file = "sphinx-autobuild-2020.9.1.tar.gz", hash = "sha256:4b184a7db893f2100bbd831991ae54ca89167a2b9ce68faea71eaa9e37716aed"}, diff --git a/pyproject.toml b/pyproject.toml index 72fe467f..7722ba12 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,7 +41,7 @@ safety = "^1.9.0" mypy = "^0.790" typeguard = "^2.9.1" xdoctest = {extras = ["colors"], version = "^0.15.0"} -sphinx = "^3.3.0" +sphinx = "^3.3.1" sphinx-autobuild = "^2020.9.1" pre-commit = "^2.8.2" flake8 = "^3.8.4" From ae0367fb5379388c3c466708bffc739ff167bedb Mon Sep 17 00:00:00 2001 From: Michael <35783820+mib1185@users.noreply.github.com> Date: Thu, 19 Nov 2020 00:00:12 +0100 Subject: [PATCH 30/33] Fix Upgrade API for DSM 6.1 (#106) --- src/synology_dsm/api/core/upgrade.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/synology_dsm/api/core/upgrade.py b/src/synology_dsm/api/core/upgrade.py index d00839d5..e491ff8f 100644 --- a/src/synology_dsm/api/core/upgrade.py +++ b/src/synology_dsm/api/core/upgrade.py @@ -16,24 +16,24 @@ def update(self): """Updates Upgrade data.""" raw_data = self._dsm.get(self.API_SERVER_KEY, "check") if raw_data: - self._data = raw_data["data"] + self._data = raw_data["data"].get("update", raw_data["data"]) @property def update_available(self): """Gets available update info.""" - return self._data["update"].get("available") + return self._data.get("available") @property def available_version(self): """Gets available verion info.""" - return self._data["update"].get("version") + return self._data.get("version") @property def reboot_needed(self): """Gets info if reboot is needed.""" - return self._data["update"].get("reboot") + return self._data.get("reboot") @property def service_restarts(self): """Gets info if services are restarted.""" - return self._data["update"].get("restart") + return self._data.get("restart") From d394fe3507b324551c37e8c4a7a095410778479f Mon Sep 17 00:00:00 2001 From: Quentin POLLET Date: Fri, 20 Nov 2020 00:25:36 +0100 Subject: [PATCH 31/33] Rename python-synology to synologydsm-api --- CONTRIBUTING.rst | 8 ++++---- LICENSE.txt | 4 ++-- README.rst | 18 +++++++++--------- pyproject.toml | 12 ++++++------ scripts/publish.sh | 2 +- src/synology_dsm/__init__.py | 2 +- 6 files changed, 23 insertions(+), 23 deletions(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index a91139bb..640022ad 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -13,9 +13,9 @@ Here is a list of important resources for contributors: - `Code of Conduct`_ .. _MIT license: https://opensource.org/licenses/MIT -.. _Source Code: https://github.com/ProtoThis/python-synology -.. _Documentation: https://python-synology.readthedocs.io/ -.. _Issue Tracker: https://github.com/ProtoThis/python-synology/issues +.. _Source Code: https://github.com/hacf-fr/synologydsm-api +.. _Documentation: https://synologydsm-api.readthedocs.io/ +.. _Issue Tracker: https://github.com/hacf-fr/synologydsm-api/issues How to report a bug ------------------- @@ -116,6 +116,6 @@ To run linting and code formatting checks before commiting your change, you can It is recommended to open an issue before starting work on anything. This will allow a chance to talk it over with the owners and validate your approach. -.. _pull request: https://github.com/ProtoThis/python-synology/pulls +.. _pull request: https://github.com/hacf-fr/synologydsm-api/pulls .. github-only .. _Code of Conduct: CODE_OF_CONDUCT.rst diff --git a/LICENSE.txt b/LICENSE.txt index a45cf81c..76a4fde2 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,8 +1,8 @@ The MIT License (MIT) -Copyright (c) 2016 ProtoThis +Copyright (c) 2020 hacf-fr Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.rst b/README.rst index e4142504..b03430d3 100644 --- a/README.rst +++ b/README.rst @@ -2,20 +2,20 @@ Python API for Synology DSM =========================== -.. image:: https://travis-ci.org/ProtoThis/python-synology.svg?branch=master - :target: https://travis-ci.org/ProtoThis/python-synology +.. image:: https://travis-ci.org/hacf-fr/synologydsm-api.svg?branch=master + :target: https://travis-ci.org/hacf-fr/synologydsm-api -.. image:: https://img.shields.io/pypi/v/python-synology.svg +.. image:: https://img.shields.io/pypi/v/synologydsm-api.svg :alt: Library version - :target: https://pypi.org/project/python-synology + :target: https://pypi.org/project/synologydsm-api -.. image:: https://img.shields.io/pypi/pyversions/python-synology.svg +.. image:: https://img.shields.io/pypi/pyversions/synologydsm-api.svg :alt: Supported versions - :target: https://pypi.org/project/python-synology + :target: https://pypi.org/project/synologydsm-api -.. image:: https://pepy.tech/badge/python-synology +.. image:: https://pepy.tech/badge/synologydsm-api :alt: Downloads - :target: https://pypi.org/project/python-synology + :target: https://pypi.org/project/synologydsm-api .. image:: https://img.shields.io/badge/code%20style-black-000000.svg :alt: Formated with Black @@ -27,7 +27,7 @@ Installation .. code-block:: bash - [sudo] pip install python-synology + [sudo] pip install synologydsm-api Usage diff --git a/pyproject.toml b/pyproject.toml index 7722ba12..e4241c87 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,13 +1,13 @@ [tool.poetry] -name = "python-synology" +name = "synologydsm-api" version = "1.0.0" description = "Python API for communication with Synology DSM" authors = ["Quentin POLLET (Quentame)", "FG van Zeelst (ProtoThis)"] license = "MIT" readme = "README.rst" -homepage = "https://github.com/ProtoThis/python-synology" -repository = "https://github.com/ProtoThis/python-synology" -documentation = "https://python-synology.readthedocs.io" +homepage = "https://github.com/hacf-fr/synologydsm-api" +repository = "https://github.com/hacf-fr/synologydsm-api" +documentation = "https://synologydsm-api.readthedocs.io" classifiers = [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", @@ -27,7 +27,7 @@ packages = [ ] [tool.poetry.urls] -Changelog = "https://github.com/ProtoThis/python-synology/releases" +Changelog = "https://github.com/hacf-fr/synologydsm-api/releases" [tool.poetry.dependencies] python = "^3.7.0" @@ -58,7 +58,7 @@ sphinx-rtd-theme = "^0.5.0" Pygments = "^2.7.2" [tool.poetry.scripts] -python-synology = "synology_dsm.__main__:main" +synologydsm-api = "synology_dsm.__main__:main" [tool.coverage.paths] source = ["src", "*/site-packages"] diff --git a/scripts/publish.sh b/scripts/publish.sh index 7e370c81..1b9b2754 100755 --- a/scripts/publish.sh +++ b/scripts/publish.sh @@ -1,5 +1,5 @@ # Publish the library -# https://pypi.org/project/python-synology +# https://pypi.org/project/synologydsm-api # Publish documentation here: https://packaging.python.org/tutorials/packaging-projects/ ./scripts/common.sh diff --git a/src/synology_dsm/__init__.py b/src/synology_dsm/__init__.py index b883e8be..f453784e 100644 --- a/src/synology_dsm/__init__.py +++ b/src/synology_dsm/__init__.py @@ -1,4 +1,4 @@ -"""The python-synology library.""" +"""The synologydsm-api library.""" from .synology_dsm import SynologyDSM __all__ = ["SynologyDSM"] From 7214129d270a76fe5bd7c6b43639a852f4d3728f Mon Sep 17 00:00:00 2001 From: Quentame Date: Fri, 20 Nov 2020 00:38:11 +0100 Subject: [PATCH 32/33] Release 1.0.1 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index e4241c87..bf7603d3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "synologydsm-api" -version = "1.0.0" +version = "1.0.1" description = "Python API for communication with Synology DSM" authors = ["Quentin POLLET (Quentame)", "FG van Zeelst (ProtoThis)"] license = "MIT" From 7a4029169903b79cc320c3fd9570507c257063e4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 27 Jan 2021 07:01:54 +0000 Subject: [PATCH 33/33] Bump urllib3 from 1.25.11 to 1.26.3 Bumps [urllib3](https://github.com/urllib3/urllib3) from 1.25.11 to 1.26.3. - [Release notes](https://github.com/urllib3/urllib3/releases) - [Changelog](https://github.com/urllib3/urllib3/blob/1.26.3/CHANGES.rst) - [Commits](https://github.com/urllib3/urllib3/compare/1.25.11...1.26.3) Signed-off-by: dependabot[bot] --- poetry.lock | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index 9808cdf1..e4aa9913 100644 --- a/poetry.lock +++ b/poetry.lock @@ -896,7 +896,7 @@ python-versions = "*" [[package]] name = "urllib3" -version = "1.25.11" +version = "1.26.3" description = "HTTP library with thread-safe connection pooling, file post, and more." category = "main" optional = false @@ -1266,6 +1266,8 @@ pyyaml = [ {file = "PyYAML-5.3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:73f099454b799e05e5ab51423c7bcf361c58d3206fa7b0d555426b1f4d9a3eaf"}, {file = "PyYAML-5.3.1-cp38-cp38-win32.whl", hash = "sha256:06a0d7ba600ce0b2d2fe2e78453a470b5a6e000a985dd4a4e54e436cc36b0e97"}, {file = "PyYAML-5.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:95f71d2af0ff4227885f7a6605c37fd53d3a106fcab511b8860ecca9fcf400ee"}, + {file = "PyYAML-5.3.1-cp39-cp39-win32.whl", hash = "sha256:ad9c67312c84def58f3c04504727ca879cb0013b2517c85a9a253f0cb6380c0a"}, + {file = "PyYAML-5.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:6034f55dab5fea9e53f436aa68fa3ace2634918e8b5994d82f3621c04ff5ed2e"}, {file = "PyYAML-5.3.1.tar.gz", hash = "sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d"}, ] regex = [ @@ -1320,22 +1322,29 @@ restructuredtext-lint = [ {file = "ruamel.yaml.clib-0.2.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:73b3d43e04cc4b228fa6fa5d796409ece6fcb53a6c270eb2048109cbcbc3b9c2"}, {file = "ruamel.yaml.clib-0.2.2-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:53b9dd1abd70e257a6e32f934ebc482dac5edb8c93e23deb663eac724c30b026"}, {file = "ruamel.yaml.clib-0.2.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:839dd72545ef7ba78fd2aa1a5dd07b33696adf3e68fae7f31327161c1093001b"}, + {file = "ruamel.yaml.clib-0.2.2-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:1236df55e0f73cd138c0eca074ee086136c3f16a97c2ac719032c050f7e0622f"}, {file = "ruamel.yaml.clib-0.2.2-cp35-cp35m-win32.whl", hash = "sha256:b1e981fe1aff1fd11627f531524826a4dcc1f26c726235a52fcb62ded27d150f"}, {file = "ruamel.yaml.clib-0.2.2-cp35-cp35m-win_amd64.whl", hash = "sha256:4e52c96ca66de04be42ea2278012a2342d89f5e82b4512fb6fb7134e377e2e62"}, {file = "ruamel.yaml.clib-0.2.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:a873e4d4954f865dcb60bdc4914af7eaae48fb56b60ed6daa1d6251c72f5337c"}, {file = "ruamel.yaml.clib-0.2.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:ab845f1f51f7eb750a78937be9f79baea4a42c7960f5a94dde34e69f3cce1988"}, + {file = "ruamel.yaml.clib-0.2.2-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:2fd336a5c6415c82e2deb40d08c222087febe0aebe520f4d21910629018ab0f3"}, {file = "ruamel.yaml.clib-0.2.2-cp36-cp36m-win32.whl", hash = "sha256:e9f7d1d8c26a6a12c23421061f9022bb62704e38211fe375c645485f38df34a2"}, {file = "ruamel.yaml.clib-0.2.2-cp36-cp36m-win_amd64.whl", hash = "sha256:2602e91bd5c1b874d6f93d3086f9830f3e907c543c7672cf293a97c3fabdcd91"}, {file = "ruamel.yaml.clib-0.2.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:44c7b0498c39f27795224438f1a6be6c5352f82cb887bc33d962c3a3acc00df6"}, {file = "ruamel.yaml.clib-0.2.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:8e8fd0a22c9d92af3a34f91e8a2594eeb35cba90ab643c5e0e643567dc8be43e"}, + {file = "ruamel.yaml.clib-0.2.2-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:75f0ee6839532e52a3a53f80ce64925ed4aed697dd3fa890c4c918f3304bd4f4"}, {file = "ruamel.yaml.clib-0.2.2-cp37-cp37m-win32.whl", hash = "sha256:464e66a04e740d754170be5e740657a3b3b6d2bcc567f0c3437879a6e6087ff6"}, {file = "ruamel.yaml.clib-0.2.2-cp37-cp37m-win_amd64.whl", hash = "sha256:52ae5739e4b5d6317b52f5b040b1b6639e8af68a5b8fd606a8b08658fbd0cab5"}, {file = "ruamel.yaml.clib-0.2.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4df5019e7783d14b79217ad9c56edf1ba7485d614ad5a385d1b3c768635c81c0"}, {file = "ruamel.yaml.clib-0.2.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:5254af7d8bdf4d5484c089f929cb7f5bafa59b4f01d4f48adda4be41e6d29f99"}, + {file = "ruamel.yaml.clib-0.2.2-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:8be05be57dc5c7b4a0b24edcaa2f7275866d9c907725226cdde46da09367d923"}, {file = "ruamel.yaml.clib-0.2.2-cp38-cp38-win32.whl", hash = "sha256:74161d827407f4db9072011adcfb825b5258a5ccb3d2cd518dd6c9edea9e30f1"}, {file = "ruamel.yaml.clib-0.2.2-cp38-cp38-win_amd64.whl", hash = "sha256:058a1cc3df2a8aecc12f983a48bda99315cebf55a3b3a5463e37bb599b05727b"}, {file = "ruamel.yaml.clib-0.2.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c6ac7e45367b1317e56f1461719c853fd6825226f45b835df7436bb04031fd8a"}, {file = "ruamel.yaml.clib-0.2.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:b4b0d31f2052b3f9f9b5327024dc629a253a83d8649d4734ca7f35b60ec3e9e5"}, + {file = "ruamel.yaml.clib-0.2.2-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:1f8c0a4577c0e6c99d208de5c4d3fd8aceed9574bb154d7a2b21c16bb924154c"}, + {file = "ruamel.yaml.clib-0.2.2-cp39-cp39-win32.whl", hash = "sha256:46d6d20815064e8bb023ea8628cfb7402c0f0e83de2c2227a88097e239a7dffd"}, + {file = "ruamel.yaml.clib-0.2.2-cp39-cp39-win_amd64.whl", hash = "sha256:6c0a5dc52fc74eb87c67374a4e554d4761fd42a4d01390b7e868b30d21f4b8bb"}, {file = "ruamel.yaml.clib-0.2.2.tar.gz", hash = "sha256:2d24bd98af676f4990c4d715bcdc2a60b19c56a3fb3a763164d2d8ca0e806ba7"}, ] safety = [ @@ -1451,8 +1460,8 @@ typing-extensions = [ {file = "typing_extensions-3.7.4.3.tar.gz", hash = "sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c"}, ] urllib3 = [ - {file = "urllib3-1.25.11-py2.py3-none-any.whl", hash = "sha256:f5321fbe4bf3fefa0efd0bfe7fb14e90909eb62a48ccda331726b4319897dd5e"}, - {file = "urllib3-1.25.11.tar.gz", hash = "sha256:8d7eaa5a82a1cac232164990f04874c594c9453ec55eef02eab885aa02fc17a2"}, + {file = "urllib3-1.26.3-py2.py3-none-any.whl", hash = "sha256:1b465e494e3e0d8939b50680403e3aedaa2bc434b7d5af64dfd3c958d7f5ae80"}, + {file = "urllib3-1.26.3.tar.gz", hash = "sha256:de3eedaad74a2683334e282005cd8d7f22f4d55fa690a2a1020a416cb0a47e73"}, ] virtualenv = [ {file = "virtualenv-20.0.35-py2.py3-none-any.whl", hash = "sha256:0ebc633426d7468664067309842c81edab11ae97fcaf27e8ad7f5748c89b431b"},