From 9b21afc660c0dc07eaf1c0239f91b0b3937dc2ea Mon Sep 17 00:00:00 2001 From: Artem Rys Date: Mon, 29 Aug 2022 14:39:20 +0200 Subject: [PATCH 1/2] feat: introduce 4 new methods for the CredentialManager and deprecate some old ones This commit introduces 4 new methods for the CredentialManager: get_raw_passwords, get_raw_passwords_in_realm, get_clear_passwords, get_clear_passwords_in_realm which now should be used to access passwords through CredentialManager. Some old methods like _get_all_passwords_in_realm and _get_all_passwords were deprecated. --- solnlib/credentials.py | 95 ++++++++++--- tests/integration/test_conf_manager.py | 118 ++++++++++++--- tests/integration/test_credentials.py | 82 +++++++++-- tests/unit/test_conf_manager.py | 189 ------------------------- tests/unit/test_credentials.py | 139 +----------------- 5 files changed, 243 insertions(+), 380 deletions(-) diff --git a/solnlib/credentials.py b/solnlib/credentials.py index add21c73..53f02375 100644 --- a/solnlib/credentials.py +++ b/solnlib/credentials.py @@ -18,8 +18,10 @@ import json import re +import warnings +from typing import Dict, List -from splunklib import binding +from splunklib import binding, client from . import splunk_rest_client as rest_client from .net_utils import validate_scheme_host_port @@ -79,7 +81,7 @@ def __init__( port: int = None, **context: dict, ): - """Initializes CredentialsManager. + """Initializes CredentialManager. Arguments: session_key: Splunk access token. @@ -123,9 +125,11 @@ def get_password(self, user: str) -> str: realm='realm_test') >>> cm.get_password('testuser2') """ - - all_passwords = self._get_all_passwords() - for password in all_passwords: + if self._realm is not None: + passwords = self.get_clear_passwords_in_realm() + else: + passwords = self.get_clear_passwords() + for password in passwords: if password["username"] == user and password["realm"] == self._realm: return password["clear_password"] @@ -182,14 +186,16 @@ def _update_password(self, user: str, password: str): self._storage_passwords.create(password, user, self._realm) except binding.HTTPError as ex: if ex.status == 409: - all_passwords = self._get_all_passwords_in_realm() - for pwd_stanza in all_passwords: + if self._realm is not None: + passwords = self.get_raw_passwords_in_realm() + else: + passwords = self.get_raw_passwords() + for pwd_stanza in passwords: if pwd_stanza.realm == self._realm and pwd_stanza.username == user: pwd_stanza.update(password=password) return raise ValueError( - "Can not get the password object for realm: %s user: %s" - % (self._realm, user) + f"Can not get the password object for realm: {self._realm} user: {user}" ) else: raise ex @@ -211,12 +217,15 @@ def delete_password(self, user: str): realm='realm_test') >>> cm.delete_password('testuser1') """ - all_passwords = self._get_all_passwords_in_realm() + if self._realm is not None: + passwords = self.get_raw_passwords_in_realm() + else: + passwords = self.get_raw_passwords() deleted = False ent_pattern = re.compile( r"({}{}\d+)".format(user.replace("\\", "\\\\"), self.SEP) ) - for password in list(all_passwords): + for password in passwords: match = (user == password.username) or ent_pattern.match(password.username) if match and password.realm == self._realm: password.delete() @@ -224,12 +233,45 @@ def delete_password(self, user: str): if not deleted: raise CredentialNotExistException( - "Failed to delete password of realm={}, user={}".format( - self._realm, user - ) + f"Failed to delete password of realm={self._realm}, user={user}" ) - def _get_all_passwords_in_realm(self): + def get_raw_passwords(self) -> List[client.StoragePassword]: + """Returns all passwords in the "raw" format.""" + warnings.warn( + "Please pass realm to the CredentialManager, " + "so it can utilize get_raw_passwords_in_realm method instead." + ) + return self._storage_passwords.list(count=-1) + + def get_raw_passwords_in_realm(self) -> List[client.StoragePassword]: + """Returns all passwords within the realm in the "raw" format.""" + if self._realm is None: + raise ValueError("No realm was specified") + return self._storage_passwords.list(count=-1, search=f"realm={self._realm}") + + def get_clear_passwords(self) -> List[Dict[str, str]]: + """Returns all passwords in the "clear" format.""" + warnings.warn( + "Please pass realm to the CredentialManager, " + "so it can utilize get_clear_passwords_in_realm method instead." + ) + raw_passwords = self.get_raw_passwords() + return self._get_clear_passwords(raw_passwords) + + def get_clear_passwords_in_realm(self) -> List[Dict[str, str]]: + """Returns all passwords within the realm in the "clear" format.""" + if self._realm is None: + raise ValueError("No realm was specified") + raw_passwords = self.get_raw_passwords_in_realm() + return self._get_clear_passwords(raw_passwords) + + def _get_all_passwords_in_realm(self) -> List[client.StoragePassword]: + warnings.warn( + "_get_all_passwords_in_realm is deprecated, " + "please use get_raw_passwords_in_realm instead.", + stacklevel=2, + ) if self._realm: all_passwords = self._storage_passwords.list( count=-1, search=f"realm={self._realm}" @@ -238,13 +280,12 @@ def _get_all_passwords_in_realm(self): all_passwords = self._storage_passwords.list(count=-1, search="") return all_passwords - @retry(exceptions=[binding.HTTPError]) - def _get_all_passwords(self): - all_passwords = self._storage_passwords.list(count=-1) - + def _get_clear_passwords( + self, passwords: List[client.StoragePassword] + ) -> List[Dict[str, str]]: results = {} ptn = re.compile(rf"(.+){self.SEP}(\d+)") - for password in all_passwords: + for password in passwords: match = ptn.match(password.name) if match: actual_name = match.group(1) + ":" @@ -263,7 +304,7 @@ def _get_all_passwords(self): # Backward compatibility # To deal with the password with only one stanza which is generated by the old version. - for password in all_passwords: + for password in passwords: match = ptn.match(password.name) if (not match) and (password.name not in results): results[password.name] = { @@ -289,6 +330,16 @@ def _get_all_passwords(self): return list(results.values()) + @retry(exceptions=[binding.HTTPError]) + def _get_all_passwords(self) -> List[Dict[str, str]]: + warnings.warn( + "_get_all_passwords is deprecated, " + "please use get_all_passwords_in_realm instead.", + stacklevel=2, + ) + passwords = self._storage_passwords.list(count=-1) + return self._get_clear_passwords(passwords) + @retry(exceptions=[binding.HTTPError]) def get_session_key( @@ -317,7 +368,7 @@ def get_session_key( ValueError: if scheme, host or port are invalid. Examples: - >>> credentials.get_session_key('user', 'password') + >>> get_session_key('user', 'password') """ validate_scheme_host_port(scheme, host, port) diff --git a/tests/integration/test_conf_manager.py b/tests/integration/test_conf_manager.py index ed778243..bd8434d4 100644 --- a/tests/integration/test_conf_manager.py +++ b/tests/integration/test_conf_manager.py @@ -26,9 +26,8 @@ from solnlib import conf_manager -def test_conf_manager(): - session_key = context.get_session_key() - cfm = conf_manager.ConfManager( +def _build_conf_manager(session_key: str) -> conf_manager.ConfManager: + return conf_manager.ConfManager( session_key, context.app, owner=context.owner, @@ -37,23 +36,106 @@ def test_conf_manager(): port=context.port, ) - try: - conf = cfm.get_conf("test") - except conf_manager.ConfManagerException: - conf = cfm.create_conf("test") - - assert not conf.stanza_exist("test_stanza") - conf.update("test_stanza", {"k1": 1, "k2": 2}, ["k1"]) - assert conf.get("test_stanza")["k1"] == 1 - assert int(conf.get("test_stanza")["k2"]) == 2 - assert conf.get("test_stanza")["eai:appName"] == "solnlib_demo" - assert len(conf.get_all()) == 1 - conf.delete("test_stanza") + +def test_conf_manager_when_no_conf_then_throw_exception(): + session_key = context.get_session_key() + cfm = _build_conf_manager(session_key) + + with pytest.raises(conf_manager.ConfManagerException): + cfm.get_conf("non_existent_configuration_file") + + +def test_conf_manager_when_conf_file_exists_but_no_specific_stanza_then_throw_exception(): + session_key = context.get_session_key() + cfm = _build_conf_manager(session_key) + + splunk_ta_addon_settings_conf_file = cfm.get_conf("splunk_ta_addon_settings") + with pytest.raises(conf_manager.ConfStanzaNotExistException): - conf.get("test_stanza") + splunk_ta_addon_settings_conf_file.get( + "non_existent_stanza_under_existing_conf_file" + ) + + +@pytest.mark.parametrize( + "stanza_name,expected_result", + [ + ("logging", True), + ("non_existent_stanza_under_existing_conf_file", False), + ], +) +def test_conf_manager_stanza_exist(stanza_name, expected_result): + session_key = context.get_session_key() + cfm = _build_conf_manager(session_key) + + splunk_ta_addon_settings_conf_file = cfm.get_conf("splunk_ta_addon_settings") + + assert ( + splunk_ta_addon_settings_conf_file.stanza_exist(stanza_name) == expected_result + ) + + +def test_conf_manager_when_conf_file_exists(): + session_key = context.get_session_key() + cfm = _build_conf_manager(session_key) + + splunk_ta_addon_settings_conf_file = cfm.get_conf("splunk_ta_addon_settings") + + expected_result = { + "disabled": "0", + "eai:access": { + "app": "solnlib_demo", + "can_change_perms": "1", + "can_list": "1", + "can_share_app": "1", + "can_share_global": "1", + "can_share_user": "0", + "can_write": "1", + "modifiable": "1", + "owner": "nobody", + "perms": {"read": ["*"], "write": ["admin"]}, + "removable": "0", + "sharing": "global", + }, + "eai:appName": "solnlib_demo", + "eai:userName": "nobody", + "log_level": "DEBUG", + } + assert splunk_ta_addon_settings_conf_file.get("logging") == expected_result + + +def test_conf_manager_delete_non_existent_stanza_then_throw_exception(): + session_key = context.get_session_key() + cfm = _build_conf_manager(session_key) + + splunk_ta_addon_settings_conf_file = cfm.get_conf("splunk_ta_addon_settings") + with pytest.raises(conf_manager.ConfStanzaNotExistException): - conf.delete("test_stanza") - conf.reload() + splunk_ta_addon_settings_conf_file.delete( + "non_existent_stanza_under_existing_conf_file" + ) + + +def test_conf_manager_create_conf(): + session_key = context.get_session_key() + cfm = _build_conf_manager(session_key) + + conf_file = cfm.create_conf("conf_file_that_did_not_exist_before") + conf_file.update("stanza", {"key": "value"}) + + assert conf_file.get("stanza")["key"] == "value" + + +def test_conf_manager_update_conf_with_encrypted_keys(): + session_key = context.get_session_key() + cfm = _build_conf_manager(session_key) + + conf_file = cfm.create_conf("conf_file_with_encrypted_keys") + conf_file.update( + "stanza", {"key1": "value1", "key2": "value2"}, encrypt_keys=["key2"] + ) + + assert conf_file.get("stanza")["key2"] == "value2" def test_get_log_level(): diff --git a/tests/integration/test_credentials.py b/tests/integration/test_credentials.py index 35c3883c..42bc9c83 100644 --- a/tests/integration/test_credentials.py +++ b/tests/integration/test_credentials.py @@ -16,6 +16,7 @@ import os.path as op import sys +from typing import Optional import pytest @@ -25,7 +26,9 @@ from solnlib import credentials -def test_credential_manager(): +def _build_credential_manager( + realm: Optional[str] = None, +) -> credentials.CredentialManager: session_key = credentials.get_session_key( context.username, context.password, @@ -33,28 +36,81 @@ def test_credential_manager(): host=context.host, port=context.port, ) - - cm = credentials.CredentialManager( + return credentials.CredentialManager( session_key, context.app, owner=context.owner, - realm=context.app, + realm=realm, scheme=context.scheme, host=context.host, port=context.port, ) - cm.set_password("testuser1", "password1") - assert cm.get_password("testuser1") == "password1" - long_password = "".join(["1111111111" for i in range(30)]) - cm.set_password("testuser2", long_password) - assert cm.get_password("testuser2") == long_password +def test_get_password(): + cm = _build_credential_manager(realm=context.app) + + cm.set_password("user1", "password1") + assert cm.get_password("user1") == "password1" + + +def test_get_password_when_no_user_exists_then_throw_exception(): + cm = _build_credential_manager(realm=context.app) - cm.delete_password("testuser1") with pytest.raises(credentials.CredentialNotExistException): - cm.get_password("testuser1") + cm.get_password("nonexistentuser") + + +def test_delete_password(): + cm = _build_credential_manager(realm=context.app) + cm.set_password("user2", "password2") + + cm.delete_password("user2") - cm.delete_password("testuser2") with pytest.raises(credentials.CredentialNotExistException): - cm.get_password("testuser2") + cm.get_password("user2") + + +def test_delete_password_when_no_user_exists_then_throw_exception(): + cm = _build_credential_manager(realm=context.app) + + with pytest.raises(credentials.CredentialNotExistException): + cm.delete_password("nonexistentuser") + + +def test_get_clear_passwords_in_realm(): + cm = _build_credential_manager(realm=context.app) + cm.set_password("user3", "password3") + + expected_result = { + "name": "solnlib_demo:user3", + "realm": "solnlib_demo", + "username": "user3", + "clear_password": "password3", + } + results = cm.get_clear_passwords_in_realm() + for result in results: + if result["name"] == expected_result["name"]: + assert result["realm"] == expected_result["realm"] + assert result["username"] == expected_result["username"] + assert result["clear_password"] == expected_result["clear_password"] + break + + +def test_get_clear_passwords(): + cm = _build_credential_manager() + cm.set_password("user3", "password3") + + expected_result = { + "name": "solnlib_demo:user3", + "realm": "solnlib_demo", + "username": "user3", + "clear_password": "password3", + } + results = cm.get_clear_passwords() + for result in results: + if result["name"] == expected_result["name"]: + assert result["realm"] == expected_result["realm"] + assert result["username"] == expected_result["username"] + assert result["clear_password"] == expected_result["clear_password"] + break diff --git a/tests/unit/test_conf_manager.py b/tests/unit/test_conf_manager.py index 1ab77007..1f1b49ce 100644 --- a/tests/unit/test_conf_manager.py +++ b/tests/unit/test_conf_manager.py @@ -13,200 +13,11 @@ # See the License for the specific language governing permissions and # limitations under the License. # - -import hashlib from unittest import mock -import common -import pytest -from splunklib import binding, client -from splunklib.data import record - from solnlib import conf_manager -def test_conf_manager(monkeypatch): - credentials_store = {} - all_stanzas = {} - - def mock_storage_passwords_list(self, count=None, **kwargs): - return credentials_store.values() - - def mock_storage_passwords_create(self, password, username, realm=None): - title = f"{realm}:{username}:" if realm else f":{username}:" - password = client.StoragePassword( - None, - f"storage/passwords/{title}", - state=record( - { - "content": { - "clear_password": password, - "encr_password": hashlib.md5(password.encode()).digest(), - "password": "********", - "realm": realm, - "username": username, - }, - "title": title, - } - ), - ) - credentials_store[title] = password - return password - - def mock_storage_passwords_delete(self, username, realm=None): - title = f"{realm}:{username}:" if realm else f":{username}:" - if title in credentials_store: - del credentials_store[title] - else: - raise KeyError("No such entity %s" % username) - - def mock_storage_password_delete(self): - if self.name in credentials_store: - del credentials_store[self.name] - else: - raise KeyError("No such entity %s" % self.name) - - def mock_configuration_get( - self, name="", owner=None, app=None, sharing=None, **query - ): - return common.make_response_record("") - - def mock_configuration_file_list(self, count=None, **kwargs): - if not hasattr(mock_configuration_file_list, "normal_mode"): - mock_configuration_file_list.normal_mode = True - raise binding.HTTPError(common.make_response_record("", status=404)) - else: - if "name" in kwargs: - if kwargs["name"] in all_stanzas: - stanza_mgr = client.Stanza( - self.service, - "configs/conf-test/{}/".format(kwargs["name"]), - skip_refresh=True, - ) - stanza_mgr._state = common.record( - { - "title": kwargs["name"], - "access": common.record({"app": "test"}), - "content": all_stanzas[kwargs["name"]], - } - ) - return [stanza_mgr] - else: - raise binding.HTTPError(common.make_response_record("", status=404)) - else: - stanza_mgrs = [] - for stanza_name, stanza in list(all_stanzas.items()): - stanza_mgr = client.Stanza( - self.service, - f"configs/conf-test/{stanza_name}/", - skip_refresh=True, - ) - stanza_mgr._state = common.record( - { - "title": stanza_name, - "access": common.record({"app": "test"}), - "content": stanza, - } - ) - stanza_mgrs.append(stanza_mgr) - - return stanza_mgrs - - def mock_configuration_file_get( - self, name="", owner=None, app=None, sharing=None, **query - ): - return common.make_response_record("") - - def mock_configuration_file_create(self, name, **params): - stanza_mgr = client.Stanza( - self.service, f"configs/conf-test/{name}/", skip_refresh=True - ) - stanza_mgr._state = common.record({"title": name, "content": {}}) - return stanza_mgr - - def mock_configuration_file_delete(self, name, **params): - del all_stanzas[name] - - def mock_stanza_submit(self, stanza): - all_stanzas[self.name] = stanza - - common.mock_splunkhome(monkeypatch) - monkeypatch.setattr(client.StoragePasswords, "list", mock_storage_passwords_list) - monkeypatch.setattr( - client.StoragePasswords, "create", mock_storage_passwords_create - ) - monkeypatch.setattr( - client.StoragePasswords, "delete", mock_storage_passwords_delete - ) - monkeypatch.setattr(client.StoragePassword, "delete", mock_storage_password_delete) - monkeypatch.setattr(client.Configurations, "get", mock_configuration_get) - monkeypatch.setattr(client.ConfigurationFile, "get", mock_configuration_file_get) - monkeypatch.setattr(client.ConfigurationFile, "list", mock_configuration_file_list) - monkeypatch.setattr( - client.ConfigurationFile, "create", mock_configuration_file_create - ) - monkeypatch.setattr( - client.ConfigurationFile, "delete", mock_configuration_file_delete - ) - monkeypatch.setattr(client.Stanza, "submit", mock_stanza_submit) - - cfm = conf_manager.ConfManager(common.SESSION_KEY, common.app) - conf = cfm.get_conf("test") - assert not conf.stanza_exist("test_stanza") - conf.update("test_stanza", {"k1": 1, "k2": 2}, ["k1", "key_not_exist"]) - assert conf.get("test_stanza") == { - "k2": 2, - "k1": 1, - "eai:access": common.record({"app": "test"}), - "eai:appName": "test", - } - assert conf.get_all() == { - "test_stanza": { - "k2": 2, - "k1": 1, - "eai:access": common.record({"app": "test"}), - "eai:appName": "test", - } - } - - conf.delete("test_stanza") - with pytest.raises(conf_manager.ConfStanzaNotExistException): - conf.get("test_stanza") - with pytest.raises(conf_manager.ConfStanzaNotExistException): - conf.delete("test_stanza") - conf.reload() - - cfm = conf_manager.ConfManager( - common.SESSION_KEY, - common.app, - realm=f"__REST_CREDENTIAL__#{common.app}#configs/conf-test", - ) - conf = cfm.get_conf("test") - assert not conf.stanza_exist("test_stanza") - conf.update("test_stanza", {"k1": 1, "k2": 2}, ["k1", "key_not_exist"]) - assert conf.get("test_stanza") == { - "k2": 2, - "k1": 1, - "eai:access": common.record({"app": "test"}), - "eai:appName": "test", - } - assert conf.get_all() == { - "test_stanza": { - "k2": 2, - "k1": 1, - "eai:access": common.record({"app": "test"}), - "eai:appName": "test", - } - } - - conf.delete("test_stanza") - with pytest.raises(conf_manager.ConfStanzaNotExistException): - conf.get("test_stanza") - with pytest.raises(conf_manager.ConfStanzaNotExistException): - conf.delete("test_stanza") - conf.reload() - - @mock.patch.object(conf_manager, "ConfManager") def test_get_log_level_when_error_getting_conf(mock_conf_manager_class): mock_conf_manager = mock_conf_manager_class.return_value diff --git a/tests/unit/test_credentials.py b/tests/unit/test_credentials.py index 55ca8418..0d3f99b5 100644 --- a/tests/unit/test_credentials.py +++ b/tests/unit/test_credentials.py @@ -13,150 +13,13 @@ # See the License for the specific language governing permissions and # limitations under the License. # - -import hashlib - import common import pytest -from splunklib import binding, client -from splunklib.data import record +from splunklib import binding from solnlib import credentials -def test_credential_manager(monkeypatch): - credentials_store = {} - - def mock_storage_passwords_list(self, count=None, **kwargs): - return list(credentials_store.values()) - - def mock_storage_passwords_create(self, password, username, realm=None): - title = f"{realm}:{username}:" if realm else f":{username}:" - password = client.StoragePassword( - None, - f"storage/passwords/{title}", - state=record( - { - "content": { - "clear_password": password, - "encr_password": hashlib.md5(password.encode("utf-8")).digest(), - "password": "********", - "realm": realm, - "username": username, - }, - "title": title, - } - ), - ) - credentials_store[title] = password - return password - - def mock_storage_passwords_delete(self, username, realm=None): - title = f"{realm}:{username}:" if realm else f":{username}:" - if title in credentials_store: - del credentials_store[title] - else: - raise KeyError("No such entity %s" % username) - - def mock_storage_password_delete(self): - if self.name in credentials_store: - del credentials_store[self.name] - else: - raise KeyError("No such entity %s" % self.name) - - common.mock_splunkhome(monkeypatch) - monkeypatch.setattr(client.StoragePasswords, "list", mock_storage_passwords_list) - monkeypatch.setattr( - client.StoragePasswords, "create", mock_storage_passwords_create - ) - monkeypatch.setattr( - client.StoragePasswords, "delete", mock_storage_passwords_delete - ) - monkeypatch.setattr(client.StoragePassword, "delete", mock_storage_password_delete) - - cm = credentials.CredentialManager( - common.SESSION_KEY, common.app, realm="realm_test" - ) - cm.set_password("testuser1", "password1") - assert cm.get_password("testuser1") == "password1" - - long_password = "".join(["1111111111" for i in range(30)]) - cm.set_password("testuser2", long_password) - assert cm.get_password("testuser2") == long_password - - # change short password to long password - long_password = "".join(["1111111111" for i in range(30)]) - cm.set_password("testuser1", long_password) - assert cm.get_password("testuser1") == long_password - - # change to longer password - longer_password = "".join(["1111111111" for i in range(120)]) - cm.set_password("testuser1", longer_password) - assert cm.get_password("testuser1") == longer_password - - # change longer password to long password - long_password = "".join(["1111111111" for i in range(30)]) - cm.set_password("testuser1", long_password) - assert cm.get_password("testuser1") == long_password - - # change long password to short password - cm.set_password("testuser1", "shortpwd") - assert cm.get_password("testuser1") == "shortpwd" - - # password length = 1 - cm.set_password("testuser1", "a") - assert cm.get_password("testuser1") == "a" - - # password length = 255 - pwd_255 = "".join(["a" for i in range(255)]) - cm.set_password("testuser1", pwd_255) - assert cm.get_password("testuser1") == pwd_255 - - # password length = 256 - pwd_256 = "".join(["a" for i in range(256)]) - cm.set_password("testuser1", pwd_256) - assert cm.get_password("testuser1") == pwd_256 - - # password length = 255 * 2 - pwd_510 = "".join(["a" for i in range(510)]) - cm.set_password("testuser1", pwd_510) - assert cm.get_password("testuser1") == pwd_510 - - # password is empty - cm.set_password("testuser1", "") - assert cm.get_password("testuser1") == "" - - # password = '`' - cm.set_password("testuser1", "`") - assert cm.get_password("testuser1") == "`" - - # password is substring of END_MARK - pwd_substr = "``splunk_cred_sep``S``splunk_cred_sep``P``" - cm.set_password("testuser1", pwd_substr) - assert cm.get_password("testuser1") == pwd_substr - - # test _update_password - # Update a password which does not exist. create a new one. - cm._update_password("testuser3", "beforechange") - assert cm.get_password("testuser3") == "beforechange" - - # update an existed password - cm._update_password("testuser3", "changed") - assert cm.get_password("testuser3") == "changed" - - cm.delete_password("testuser1") - with pytest.raises(Exception): - cm.get_password("testuser1") - - cm.delete_password("testuser2") - with pytest.raises(Exception): - cm.get_password("testuser2") - - cm.delete_password("testuser3") - with pytest.raises(Exception): - cm.get_password("testuser3") - - def test_get_session_key(monkeypatch): def _mock_session_key_post(self, url, headers=None, **kwargs): return common.make_response_record( From e2a43309b2a5f6ddaf078343735ab105968a9145 Mon Sep 17 00:00:00 2001 From: Artem Rys Date: Mon, 29 Aug 2022 14:51:05 +0200 Subject: [PATCH 2/2] chore: pre-commit autoupdate --- .pre-commit-config.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2af950e7..d68f28af 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,11 +1,11 @@ repos: - repo: https://github.com/asottile/pyupgrade - rev: v2.31.1 + rev: v2.37.3 hooks: - id: pyupgrade args: [--py37-plus] - repo: https://github.com/psf/black - rev: 22.3.0 + rev: 22.6.0 hooks: - id: black - repo: https://github.com/PyCQA/isort @@ -13,12 +13,12 @@ repos: hooks: - id: isort - repo: https://github.com/PyCQA/flake8 - rev: 4.0.1 + rev: 5.0.4 hooks: - id: flake8 exclude: ^tests - repo: https://github.com/myint/docformatter - rev: v1.4 + rev: v1.5.0 hooks: - id: docformatter args: [--in-place]