diff --git a/constraints.txt b/constraints.txt index fbf63fbd2..7e7440765 100644 --- a/constraints.txt +++ b/constraints.txt @@ -163,7 +163,7 @@ rpds-py==0.17.1 # via # jsonschema # referencing -ruff==0.8.6 +ruff==0.9.1 # via -r constraints.in sentry-sdk==2.8.0 # via -r constraints.in diff --git a/docs/requirements.txt b/docs/requirements.txt index fedcf7ebc..fdcc5ccef 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -9,4 +9,4 @@ webtest==3.0.2 cornice==6.1.0 pyramid==2.0.2 python-rapidjson==1.20 -SQLAlchemy==2.0.36 +SQLAlchemy==2.0.37 diff --git a/kinto/__main__.py b/kinto/__main__.py index 51c4875c3..b13750f89 100644 --- a/kinto/__main__.py +++ b/kinto/__main__.py @@ -161,8 +161,7 @@ def main(args=None): if not backend: while True: prompt = ( - "Select the backend you would like to use: " - "(1 - postgresql, default - memory) " + "Select the backend you would like to use: (1 - postgresql, default - memory) " ) answer = input(prompt).strip() try: diff --git a/kinto/core/__init__.py b/kinto/core/__init__.py index 4e6c2c19b..af27bbe0c 100644 --- a/kinto/core/__init__.py +++ b/kinto/core/__init__.py @@ -110,10 +110,8 @@ "trailing_slash_redirect_ttl_seconds": 3600, "multiauth.groupfinder": "kinto.core.authorization.groupfinder", "multiauth.policies": "", - "multiauth.policy.basicauth.use": ( - "kinto.core.authentication." "BasicAuthAuthenticationPolicy" - ), - "multiauth.authorization_policy": ("kinto.core.authorization." "AuthorizationPolicy"), + "multiauth.policy.basicauth.use": "kinto.core.authentication.BasicAuthAuthenticationPolicy", + "multiauth.authorization_policy": "kinto.core.authorization.AuthorizationPolicy", } diff --git a/kinto/core/initialization.py b/kinto/core/initialization.py index 0b8fa7adc..8c3acfc14 100644 --- a/kinto/core/initialization.py +++ b/kinto/core/initialization.py @@ -213,7 +213,7 @@ def setup_deprecation(config): def _end_of_life_tween_factory(handler, registry): """Pyramid tween to handle service end of life.""" - deprecation_msg = "The service you are trying to connect no longer exists" " at this location." + deprecation_msg = "The service you are trying to connect no longer exists at this location." def eos_tween(request): eos_date = registry.settings["eos"] diff --git a/kinto/core/permission/postgresql/__init__.py b/kinto/core/permission/postgresql/__init__.py index 76d6e11f9..f73f5b6db 100644 --- a/kinto/core/permission/postgresql/__init__.py +++ b/kinto/core/permission/postgresql/__init__.py @@ -246,7 +246,7 @@ def get_authorized_principals(self, bound_permissions): query = f""" WITH required_perms AS ( - VALUES {','.join(perm_values)} + VALUES {",".join(perm_values)} ) SELECT principal FROM required_perms JOIN access_control_entries @@ -292,14 +292,14 @@ def get_accessible_objects(self, principals, bound_permissions=None, with_childr object_id_condition = "object_id LIKE pattern" else: object_id_condition = ( - "object_id LIKE pattern " "AND object_id NOT LIKE pattern || '/%'" + "object_id LIKE pattern AND object_id NOT LIKE pattern || '/%'" ) query = f""" WITH required_perms AS ( - VALUES {','.join(perm_values)} + VALUES {",".join(perm_values)} ), user_principals AS ( - VALUES {','.join(principals_values)} + VALUES {",".join(principals_values)} ), potential_objects AS ( SELECT object_id, permission, required_perms.column1 AS pattern @@ -341,7 +341,7 @@ def check_permission(self, principals, bound_permissions): query = f""" WITH required_perms AS ( - VALUES {','.join(perms_values)} + VALUES {",".join(perms_values)} ), allowed_principals AS ( SELECT principal @@ -349,7 +349,7 @@ def check_permission(self, principals, bound_permissions): ON (object_id = column1 AND permission = column2) ), required_principals AS ( - VALUES {','.join(principals_values)} + VALUES {",".join(principals_values)} ) SELECT COUNT(*) AS matched FROM required_principals JOIN allowed_principals @@ -412,7 +412,7 @@ def replace_object_permissions(self, object_id, permissions): if not new_aces: query = f""" WITH specified_perms AS ( - VALUES {','.join(specified_perms)} + VALUES {",".join(specified_perms)} ) DELETE FROM access_control_entries USING specified_perms @@ -422,7 +422,7 @@ def replace_object_permissions(self, object_id, permissions): else: query = f""" WITH specified_perms AS ( - VALUES {','.join(specified_perms)} + VALUES {",".join(specified_perms)} ), delete_specified AS ( DELETE FROM access_control_entries @@ -435,7 +435,7 @@ def replace_object_permissions(self, object_id, permissions): UNION SELECT :object_id ), new_aces AS ( - VALUES {','.join(new_aces)} + VALUES {",".join(new_aces)} ) INSERT INTO access_control_entries(object_id, permission, principal) SELECT DISTINCT d.object_id, n.column1, n.column2 diff --git a/kinto/core/resource/__init__.py b/kinto/core/resource/__init__.py index da447642e..969c76f92 100644 --- a/kinto/core/resource/__init__.py +++ b/kinto/core/resource/__init__.py @@ -1086,7 +1086,7 @@ def is_valid_timestamp(value): operator = COMPARISON.GT else: if param == "_to": - message = "_to is now deprecated, " "you should use _before instead" + message = "_to is now deprecated, you should use _before instead" url = ( "https://kinto.readthedocs.io/en/2.4.0/api/" "resource.html#list-of-available-url-" diff --git a/kinto/core/resource/schema.py b/kinto/core/resource/schema.py index 6246c368a..84c13ff25 100644 --- a/kinto/core/resource/schema.py +++ b/kinto/core/resource/schema.py @@ -37,8 +37,7 @@ class URL(URL): def __init__(self, *args, **kwargs): message = ( - "`kinto.core.resource.schema.URL` is deprecated, " - "use `kinto.core.schema.URL` instead." + "`kinto.core.resource.schema.URL` is deprecated, use `kinto.core.schema.URL` instead." ) warnings.warn(message, DeprecationWarning) super().__init__(*args, **kwargs) diff --git a/kinto/core/storage/postgresql/client.py b/kinto/core/storage/postgresql/client.py index fef82b836..0bd68e256 100644 --- a/kinto/core/storage/postgresql/client.py +++ b/kinto/core/storage/postgresql/client.py @@ -95,14 +95,14 @@ def create_from_config(config, prefix="", with_transaction=True): url = filtered_settings[prefix + "url"] existing_client = _CLIENTS[transaction_per_request].get(url) if existing_client: - msg = "Reuse existing PostgreSQL connection. " f"Parameters {prefix}* will be ignored." + msg = f"Reuse existing PostgreSQL connection. Parameters {prefix}* will be ignored." warnings.warn(msg) return existing_client # Initialize SQLAlchemy engine from filtered_settings. poolclass_key = prefix + "poolclass" filtered_settings.setdefault( - poolclass_key, ("kinto.core.storage.postgresql." "pool.QueuePoolWithMaxBacklog") + poolclass_key, ("kinto.core.storage.postgresql.pool.QueuePoolWithMaxBacklog") ) filtered_settings[poolclass_key] = config.maybe_dotted(filtered_settings[poolclass_key]) engine = sqlalchemy.engine_from_config(filtered_settings, prefix=prefix, url=url) diff --git a/kinto/core/views/errors.py b/kinto/core/views/errors.py index a041383b3..c8fcf780f 100644 --- a/kinto/core/views/errors.py +++ b/kinto/core/views/errors.py @@ -53,7 +53,7 @@ def page_not_found(response, request): if not request.path.startswith(f"/{request.registry.route_prefix}"): errno = ERRORS.VERSION_NOT_AVAILABLE - error_msg = "The requested API version is not available " "on this server." + error_msg = "The requested API version is not available on this server." elif trailing_slash_redirection_enabled: redirect = None @@ -80,8 +80,7 @@ def page_not_found(response, request): def service_unavailable(response, request): if response.content_type != "application/json": error_msg = ( - "Service temporary unavailable " - "due to overloading or maintenance, please retry later." + "Service temporary unavailable due to overloading or maintenance, please retry later." ) response = http_error(response, errno=ERRORS.BACKEND, message=error_msg) diff --git a/kinto/plugins/accounts/__init__.py b/kinto/plugins/accounts/__init__.py index 24adee64c..9f9662cbb 100644 --- a/kinto/plugins/accounts/__init__.py +++ b/kinto/plugins/accounts/__init__.py @@ -83,8 +83,7 @@ def includeme(config): if "basicauth" in auth_policies and policy in auth_policies: if auth_policies.index("basicauth") < auth_policies.index(policy): error_msg = ( - "'basicauth' should not be mentioned before '%s' " - "in 'multiauth.policies' setting." + "'basicauth' should not be mentioned before '%s' in 'multiauth.policies' setting." ) % policy raise ConfigurationError(error_msg) diff --git a/kinto/plugins/default_bucket/__init__.py b/kinto/plugins/default_bucket/__init__.py index b1a551458..000cbf01a 100644 --- a/kinto/plugins/default_bucket/__init__.py +++ b/kinto/plugins/default_bucket/__init__.py @@ -187,6 +187,5 @@ def includeme(config): "default_bucket", description="The default bucket is an alias for a personal" " bucket where collections are created implicitly.", - url="https://kinto.readthedocs.io/en/latest/api/1.x/" - "buckets.html#personal-bucket-default", + url="https://kinto.readthedocs.io/en/latest/api/1.x/buckets.html#personal-bucket-default", ) diff --git a/kinto/plugins/flush.py b/kinto/plugins/flush.py index 13afe270b..447606229 100644 --- a/kinto/plugins/flush.py +++ b/kinto/plugins/flush.py @@ -22,7 +22,7 @@ def flush_post(request): def includeme(config): config.add_api_capability( "flush_endpoint", - description="The __flush__ endpoint can be used to remove " "all data from all backends.", + description="The __flush__ endpoint can be used to remove all data from all backends.", url="https://kinto.readthedocs.io/en/latest/api/1.x/flush.html", ) config.add_cornice_service(flush) diff --git a/kinto/plugins/quotas/__init__.py b/kinto/plugins/quotas/__init__.py index 119e9394a..9620ea4c0 100644 --- a/kinto/plugins/quotas/__init__.py +++ b/kinto/plugins/quotas/__init__.py @@ -7,7 +7,7 @@ def includeme(config): config.add_api_capability( "quotas", - description="Quotas Management on buckets " "and collections.", + description="Quotas Management on buckets and collections.", url="https://kinto.readthedocs.io", ) diff --git a/tests/core/resource/test_events.py b/tests/core/resource/test_events.py index 4ab0fb6e5..28ec3dd4d 100644 --- a/tests/core/resource/test_events.py +++ b/tests/core/resource/test_events.py @@ -97,7 +97,7 @@ def test_events_have_custom_representation(self): self.app.post_json(self.plural_url, self.body, headers=self.headers, status=201) self.assertEqual( repr(self.events[0]), - "".format(self.plural_url), + "".format(self.plural_url), ) def test_post_sends_create_action(self): diff --git a/tests/core/resource/test_sync.py b/tests/core/resource/test_sync.py index 129161b68..90270c0f4 100644 --- a/tests/core/resource/test_sync.py +++ b/tests/core/resource/test_sync.py @@ -41,7 +41,7 @@ def test_filter_with__to_return_an_alert_header(self): json.loads(alert), { "code": "soft-eol", - "message": ("_to is now deprecated, " "you should use _before instead"), + "message": ("_to is now deprecated, you should use _before instead"), "url": ( "https://kinto.readthedocs.io/en/2.4.0/api/resource" ".html#list-of-available-url-parameters" diff --git a/tests/core/support.py b/tests/core/support.py index 464f8e0bc..5a3e027e4 100644 --- a/tests/core/support.py +++ b/tests/core/support.py @@ -12,7 +12,7 @@ # This is the principal a connected user should have (in the tests). -USER_PRINCIPAL = "basicauth:8a931a10fc88ab2f6d1cc02a07d3a81b5d4768f6f13e85c5" "d8d4180419acb1b4" +USER_PRINCIPAL = "basicauth:8a931a10fc88ab2f6d1cc02a07d3a81b5d4768f6f13e85c5d8d4180419acb1b4" class BaseWebTest(testing.BaseWebTest): diff --git a/tests/core/test_authentication.py b/tests/core/test_authentication.py index 868ac3617..fd13cde9c 100644 --- a/tests/core/test_authentication.py +++ b/tests/core/test_authentication.py @@ -25,7 +25,7 @@ def test_basic_auth_is_declined_if_disabled_in_settings(self): { "multiauth.policies": "dummy", "multiauth.policy.dummy.use": ( - "pyramid.authentication." "RepozeWho1AuthenticationPolicy" + "pyramid.authentication.RepozeWho1AuthenticationPolicy" ), } ) @@ -42,7 +42,7 @@ def test_policy_name_is_used(self, basicAuth): { "multiauth.policies": "dummy", "multiauth.policy.dummy.use": ( - "kinto.core.authentication." "BasicAuthAuthenticationPolicy" + "kinto.core.authentication.BasicAuthAuthenticationPolicy" ), } ) @@ -58,7 +58,7 @@ def test_views_are_forbidden_if_unknown_auth_method(self): app.get(self.plural_url, headers=self.headers, status=401) def test_principals_are_fetched_from_permission_backend(self): - patch = mock.patch(("tests.core.support." "AllowAuthorizationPolicy.permits")) + patch = mock.patch(("tests.core.support.AllowAuthorizationPolicy.permits")) self.addCleanup(patch.stop) mocked = patch.start() diff --git a/tests/core/test_scripts.py b/tests/core/test_scripts.py index 6aa241c53..69cda1a3f 100644 --- a/tests/core/test_scripts.py +++ b/tests/core/test_scripts.py @@ -28,10 +28,10 @@ def test_migrate_in_read_only_display_an_error(self): self.registry.settings = {"readonly": "true"} scripts.migrate({"registry": self.registry}) mocked.error.assert_any_call( - "Cannot migrate the storage backend " "while in readonly mode." + "Cannot migrate the storage backend while in readonly mode." ) mocked.error.assert_any_call( - "Cannot migrate the permission " "backend while in readonly mode." + "Cannot migrate the permission backend while in readonly mode." ) def test_migrate_in_dry_run_mode(self): diff --git a/tests/core/test_storage.py b/tests/core/test_storage.py index 823156481..7c15d75ea 100644 --- a/tests/core/test_storage.py +++ b/tests/core/test_storage.py @@ -219,8 +219,8 @@ def test_pool_object_is_shared_among_backend_instances(self): def test_warns_if_configured_pool_size_differs_for_same_backend_type(self): self.backend.load_from_config(self._get_config()) settings = {**self.settings, "storage_pool_size": 1} - msg = "Reuse existing PostgreSQL connection. Parameters storage_* " "will be ignored." - with mock.patch("kinto.core.storage.postgresql.client." "warnings.warn") as mocked: + msg = "Reuse existing PostgreSQL connection. Parameters storage_* will be ignored." + with mock.patch("kinto.core.storage.postgresql.client.warnings.warn") as mocked: self.backend.load_from_config(self._get_config(settings=settings)) mocked.assert_any_call(msg) diff --git a/tests/plugins/test_accounts.py b/tests/plugins/test_accounts.py index 624b03858..d947882ce 100644 --- a/tests/plugins/test_accounts.py +++ b/tests/plugins/test_accounts.py @@ -32,7 +32,7 @@ def get_app_settings(cls, extras=None): # XXX: this should be a default setting. extras.setdefault( "multiauth.policy.account.use", - "kinto.plugins.accounts.authentication." "AccountsAuthenticationPolicy", + "kinto.plugins.accounts.authentication.AccountsAuthenticationPolicy", ) extras.setdefault("account_cache_ttl_seconds", "30") return super().get_app_settings(extras) @@ -865,7 +865,7 @@ def test_create_user_in_read_only_displays_an_error(self): self.registry.settings["readonly"] = "true" code = scripts.create_user({"registry": self.registry}) assert code == 51 - mocked.error.assert_called_once_with("Cannot create a user with " "a readonly server.") + mocked.error.assert_called_once_with("Cannot create a user with a readonly server.") def test_create_user_when_not_included_displays_an_error(self): with mock.patch("kinto.plugins.accounts.scripts.logger") as mocked: @@ -873,7 +873,7 @@ def test_create_user_when_not_included_displays_an_error(self): code = scripts.create_user({"registry": self.registry}) assert code == 52 mocked.error.assert_called_once_with( - "Cannot create a user when the accounts " "plugin is not installed." + "Cannot create a user when the accounts plugin is not installed." ) def test_create_user_with_an_invalid_username_and_password_confirmation_recovers(self): diff --git a/tests/plugins/test_history.py b/tests/plugins/test_history.py index 36088fc25..c55e5eb1d 100644 --- a/tests/plugins/test_history.py +++ b/tests/plugins/test_history.py @@ -479,7 +479,7 @@ class DefaultBucketTest(HistoryWebTest): @classmethod def get_app_settings(cls, extras=None): settings = super().get_app_settings(extras) - settings["includes"] = "kinto.plugins.default_bucket " "kinto.plugins.history" + settings["includes"] = "kinto.plugins.default_bucket kinto.plugins.history" return settings def setUp(self): @@ -539,13 +539,13 @@ def setUp(self): self.julia_headers = get_user_headers("julia") self.alice_principal = ( - "basicauth:d5b0026601f1b251974e09548d44155e16" "812e3c64ff7ae053fe3542e2ca1570" + "basicauth:d5b0026601f1b251974e09548d44155e16812e3c64ff7ae053fe3542e2ca1570" ) self.bob_principal = ( - "basicauth:c031ced27503f788b102ca54269a062ec737" "94bb075154c74a0d4311e74ca8b6" + "basicauth:c031ced27503f788b102ca54269a062ec73794bb075154c74a0d4311e74ca8b6" ) self.julia_principal = ( - "basicauth:d8bab8d9fe0510fcaf9b5ad5942c027fc" "2fdf80b6dc59cc3c48d12a2fcb18f1c" + "basicauth:d8bab8d9fe0510fcaf9b5ad5942c027fc2fdf80b6dc59cc3c48d12a2fcb18f1c" ) bucket = {"permissions": {"read": [self.alice_principal]}} @@ -638,7 +638,7 @@ class ExcludeResourcesTest(HistoryWebTest): def get_app_settings(cls, extras=None): settings = super().get_app_settings(extras) settings["history.exclude_resources"] = ( - "/buckets/a " "/buckets/b/collections/a " "/buckets/b/groups/a" + "/buckets/a /buckets/b/collections/a /buckets/b/groups/a" ) return settings diff --git a/tests/plugins/test_quotas.py b/tests/plugins/test_quotas.py index 27ec5c736..486821698 100644 --- a/tests/plugins/test_quotas.py +++ b/tests/plugins/test_quotas.py @@ -1106,13 +1106,13 @@ def paginated_mock(*args, **kwargs): ) mocked_logger.info.assert_any_call( - "Bucket bucket-1, collection collection-1. " "Final size: 1 records, 78 bytes." + "Bucket bucket-1, collection collection-1. Final size: 1 records, 78 bytes." ) mocked_logger.info.assert_any_call( - "Bucket bucket-1, collection collection-2. " "Final size: 1 records, 79 bytes." + "Bucket bucket-1, collection collection-2. Final size: 1 records, 79 bytes." ) mocked_logger.info.assert_any_call( - "Bucket bucket-1. Final size: " "2 collections, 2 records, 193 bytes." + "Bucket bucket-1. Final size: 2 collections, 2 records, 193 bytes." ) def test_rebuild_quotas_doesnt_update_if_dry_run(self): @@ -1135,8 +1135,8 @@ def paginated_mock(*args, **kwargs): assert not self.storage.update.called mocked.info.assert_any_call( - "Bucket bucket-1, collection collection-1. " "Final size: 1 records, 78 bytes." + "Bucket bucket-1, collection collection-1. Final size: 1 records, 78 bytes." ) mocked.info.assert_any_call( - "Bucket bucket-1. Final size: 1 collections, " "1 records, 114 bytes." + "Bucket bucket-1. Final size: 1 collections, 1 records, 114 bytes." ) diff --git a/tests/support.py b/tests/support.py index 0ea80a9bf..c22b0aa09 100644 --- a/tests/support.py +++ b/tests/support.py @@ -7,7 +7,7 @@ MINIMALIST_COLLECTION = {} MINIMALIST_GROUP = {"data": dict(members=["fxa:user"])} MINIMALIST_RECORD = {"data": dict(name="Hulled Barley", type="Whole Grain")} -USER_PRINCIPAL = "basicauth:8a931a10fc88ab2f6d1cc02a07d3a81b5d4768f6f13e85c5" "d8d4180419acb1b4" +USER_PRINCIPAL = "basicauth:8a931a10fc88ab2f6d1cc02a07d3a81b5d4768f6f13e85c5d8d4180419acb1b4" class BaseWebTest(testing.BaseWebTest): diff --git a/tests/test_scripts.py b/tests/test_scripts.py index fa963f901..49299b444 100644 --- a/tests/test_scripts.py +++ b/tests/test_scripts.py @@ -14,7 +14,7 @@ def test_rebuild_quotas_in_read_only_display_an_error(self): self.registry.settings["readonly"] = "true" code = scripts.rebuild_quotas({"registry": self.registry}) assert code == 41 - mocked.error.assert_any_call("Cannot rebuild quotas while " "in readonly mode.") + mocked.error.assert_any_call("Cannot rebuild quotas while in readonly mode.") def test_rebuild_quotas_when_not_included_display_an_error(self): with mock.patch("kinto.scripts.logger") as mocked: @@ -22,7 +22,7 @@ def test_rebuild_quotas_when_not_included_display_an_error(self): code = scripts.rebuild_quotas({"registry": self.registry}) assert code == 42 mocked.error.assert_any_call( - "Cannot rebuild quotas when " "quotas plugin is not installed." + "Cannot rebuild quotas when quotas plugin is not installed." ) def test_rebuild_quotas_calls_quotas_script(self):