From 57a194fec3455aae01861483ce30c2e161a562e0 Mon Sep 17 00:00:00 2001 From: Tim Graham Date: Mon, 28 Jul 2025 10:47:08 -0400 Subject: [PATCH] Bump pre-commit Ruff to 0.12.5 --- .pre-commit-config.yaml | 2 +- django_mongodb_backend/aggregates.py | 4 ++-- django_mongodb_backend/cache.py | 2 +- django_mongodb_backend/compiler.py | 8 +++----- django_mongodb_backend/fields/__init__.py | 4 ++-- django_mongodb_backend/fields/array.py | 2 +- django_mongodb_backend/fields/embedded_model.py | 2 +- .../fields/polymorphic_embedded_model.py | 2 +- django_mongodb_backend/forms/__init__.py | 2 +- django_mongodb_backend/forms/fields/__init__.py | 2 +- django_mongodb_backend/forms/fields/array.py | 2 +- django_mongodb_backend/functions.py | 2 +- django_mongodb_backend/indexes.py | 2 +- .../management/commands/createcachecollection.py | 2 +- django_mongodb_backend/operations.py | 2 +- django_mongodb_backend/schema.py | 2 +- django_mongodb_backend/utils.py | 9 ++------- tests/cache_/tests.py | 10 +++++----- tests/forms_tests_/test_array.py | 3 +-- tests/indexes_/test_checks.py | 2 +- tests/model_fields_/models.py | 5 ++++- tests/model_fields_/test_arrayfield.py | 8 ++++---- tests/model_fields_/test_embedded_model.py | 2 +- .../test_polymorphic_embedded_model_array.py | 6 ++---- tests/raw_query_/models.py | 2 +- tests/raw_query_/test_raw_aggregate.py | 4 ++-- 26 files changed, 43 insertions(+), 50 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7a3301328..fc90100b6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -20,7 +20,7 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.1.3 + rev: v0.12.5 hooks: - id: ruff args: ["--fix", "--show-fixes"] diff --git a/django_mongodb_backend/aggregates.py b/django_mongodb_backend/aggregates.py index e67cefa2f..31f4b29ba 100644 --- a/django_mongodb_backend/aggregates.py +++ b/django_mongodb_backend/aggregates.py @@ -21,7 +21,7 @@ def aggregate( node.filter = None source_expressions = node.get_source_expressions() condition = When(self.filter, then=source_expressions[0]) - node.set_source_expressions([Case(condition)] + source_expressions[1:]) + node.set_source_expressions([Case(condition), *source_expressions[1:]]) else: node = self lhs_mql = process_lhs(node, compiler, connection) @@ -45,7 +45,7 @@ def count(self, compiler, connection, resolve_inner_expression=False, **extra_co condition = When( self.filter, then=Case(When(IsNull(source_expressions[0], False), then=Value(1))) ) - node.set_source_expressions([Case(condition)] + source_expressions[1:]) + node.set_source_expressions([Case(condition), *source_expressions[1:]]) inner_expression = process_lhs(node, compiler, connection) else: lhs_mql = process_lhs(self, compiler, connection) diff --git a/django_mongodb_backend/cache.py b/django_mongodb_backend/cache.py index 00b903afe..878336262 100644 --- a/django_mongodb_backend/cache.py +++ b/django_mongodb_backend/cache.py @@ -17,7 +17,7 @@ def dumps(self, obj): # For better incr() and decr() atomicity, don't pickle integers. # Using type() rather than isinstance() matches only integers and not # subclasses like bool. - if type(obj) is int: # noqa: E721 + if type(obj) is int: return obj return pickle.dumps(obj, self.protocol) diff --git a/django_mongodb_backend/compiler.py b/django_mongodb_backend/compiler.py index a99834cf4..7e1248286 100644 --- a/django_mongodb_backend/compiler.py +++ b/django_mongodb_backend/compiler.py @@ -668,7 +668,7 @@ def execute_sql(self, returning_fields=None): ) if value is None and not field.null and not field.primary_key: raise IntegrityError( - "You can't set %s (a non-nullable field) to None." % field.name + f"You can't set {field.name} (a non-nullable field) to None." ) field_values[field.column] = value @@ -728,13 +728,11 @@ def execute_sql(self, result_type): value = value.resolve_expression(self.query, allow_joins=False, for_save=True) if value.contains_aggregate: raise FieldError( - "Aggregate functions are not allowed in this query " - f"({field.name}={value})." + f"Aggregate functions are not allowed in this query ({field.name}={value})." ) if value.contains_over_clause: raise FieldError( - "Window expressions are not allowed in this query " - f"({field.name}={value})." + f"Window expressions are not allowed in this query ({field.name}={value})." ) elif hasattr(value, "prepare_database_save"): if field.remote_field: diff --git a/django_mongodb_backend/fields/__init__.py b/django_mongodb_backend/fields/__init__.py index 87a7cac82..0c95afd69 100644 --- a/django_mongodb_backend/fields/__init__.py +++ b/django_mongodb_backend/fields/__init__.py @@ -9,14 +9,14 @@ from .polymorphic_embedded_model_array import PolymorphicEmbeddedModelArrayField __all__ = [ - "register_fields", "ArrayField", "EmbeddedModelArrayField", "EmbeddedModelField", "ObjectIdAutoField", "ObjectIdField", - "PolymorphicEmbeddedModelField", "PolymorphicEmbeddedModelArrayField", + "PolymorphicEmbeddedModelField", + "register_fields", ] diff --git a/django_mongodb_backend/fields/array.py b/django_mongodb_backend/fields/array.py index 8a9f7e0a0..afec856a2 100644 --- a/django_mongodb_backend/fields/array.py +++ b/django_mongodb_backend/fields/array.py @@ -53,7 +53,7 @@ def model(self): return self.__dict__["model"] except KeyError: raise AttributeError( - "'%s' object has no attribute 'model'" % self.__class__.__name__ + f"'{self.__class__.__name__}' object has no attribute 'model'" ) from None @model.setter diff --git a/django_mongodb_backend/fields/embedded_model.py b/django_mongodb_backend/fields/embedded_model.py index 4b49a4710..092438ea1 100644 --- a/django_mongodb_backend/fields/embedded_model.py +++ b/django_mongodb_backend/fields/embedded_model.py @@ -26,7 +26,7 @@ def db_type(self, connection): return "embeddedDocuments" def check(self, **kwargs): - from ..models import EmbeddedModel + from ..models import EmbeddedModel # noqa: PLC0415 errors = super().check(**kwargs) if not issubclass(self.embedded_model, EmbeddedModel): diff --git a/django_mongodb_backend/fields/polymorphic_embedded_model.py b/django_mongodb_backend/fields/polymorphic_embedded_model.py index f25556e18..e41038443 100644 --- a/django_mongodb_backend/fields/polymorphic_embedded_model.py +++ b/django_mongodb_backend/fields/polymorphic_embedded_model.py @@ -28,7 +28,7 @@ def db_type(self, connection): return "embeddedDocuments" def check(self, **kwargs): - from ..models import EmbeddedModel + from ..models import EmbeddedModel # noqa: PLC0415 errors = super().check(**kwargs) embedded_fields = {} diff --git a/django_mongodb_backend/forms/__init__.py b/django_mongodb_backend/forms/__init__.py index eb15e7627..dedf8d89d 100644 --- a/django_mongodb_backend/forms/__init__.py +++ b/django_mongodb_backend/forms/__init__.py @@ -10,8 +10,8 @@ __all__ = [ "EmbeddedModelArrayField", "EmbeddedModelField", + "ObjectIdField", "SimpleArrayField", "SplitArrayField", "SplitArrayWidget", - "ObjectIdField", ] diff --git a/django_mongodb_backend/forms/fields/__init__.py b/django_mongodb_backend/forms/fields/__init__.py index 214c0f808..4bbcc8fbe 100644 --- a/django_mongodb_backend/forms/fields/__init__.py +++ b/django_mongodb_backend/forms/fields/__init__.py @@ -6,8 +6,8 @@ __all__ = [ "EmbeddedModelArrayField", "EmbeddedModelField", + "ObjectIdField", "SimpleArrayField", "SplitArrayField", "SplitArrayWidget", - "ObjectIdField", ] diff --git a/django_mongodb_backend/forms/fields/array.py b/django_mongodb_backend/forms/fields/array.py index 854508cc5..8a8d4fbc3 100644 --- a/django_mongodb_backend/forms/fields/array.py +++ b/django_mongodb_backend/forms/fields/array.py @@ -163,7 +163,7 @@ def get_context(self, name, value, attrs=None): if id_: final_attrs = {**final_attrs, "id": f"{id_}_{i}"} context["widget"]["subwidgets"].append( - self.widget.get_context(name + "_%s" % i, widget_value, final_attrs)["widget"] + self.widget.get_context(name + f"_{i}", widget_value, final_attrs)["widget"] ) return context diff --git a/django_mongodb_backend/functions.py b/django_mongodb_backend/functions.py index a93a30d3c..c45800a0a 100644 --- a/django_mongodb_backend/functions.py +++ b/django_mongodb_backend/functions.py @@ -99,7 +99,7 @@ def extract(self, compiler, connection): lhs_mql = process_lhs(self, compiler, connection) operator = EXTRACT_OPERATORS.get(self.lookup_name) if operator is None: - raise NotSupportedError("%s is not supported." % self.__class__.__name__) + raise NotSupportedError(f"{self.__class__.__name__} is not supported.") if timezone := self.get_tzname(): lhs_mql = {"date": lhs_mql, "timezone": timezone} return {f"${operator}": lhs_mql} diff --git a/django_mongodb_backend/indexes.py b/django_mongodb_backend/indexes.py index aeff8cf33..7c0730e44 100644 --- a/django_mongodb_backend/indexes.py +++ b/django_mongodb_backend/indexes.py @@ -237,7 +237,7 @@ def check(self, model, connection): if num_arrayfields == 0: errors.append( Error( - "VectorSearchIndex requires at least one ArrayField to " "store vector data.", + "VectorSearchIndex requires at least one ArrayField to store vector data.", obj=model, id=f"{self._error_id_prefix}.E006", hint="If you want to perform search operations without vectors, " diff --git a/django_mongodb_backend/management/commands/createcachecollection.py b/django_mongodb_backend/management/commands/createcachecollection.py index 389c24335..54f7e7a31 100644 --- a/django_mongodb_backend/management/commands/createcachecollection.py +++ b/django_mongodb_backend/management/commands/createcachecollection.py @@ -45,6 +45,6 @@ def check_collection(self, database, collection_name): connection = connections[database] if cache._collection_name in connection.introspection.table_names(): if self.verbosity > 0: - self.stdout.write("Cache collection '%s' already exists." % cache._collection_name) + self.stdout.write(f"Cache collection '{cache._collection_name}' already exists.") return cache.create_indexes() diff --git a/django_mongodb_backend/operations.py b/django_mongodb_backend/operations.py index bd4651eae..b90a4cc52 100644 --- a/django_mongodb_backend/operations.py +++ b/django_mongodb_backend/operations.py @@ -308,7 +308,7 @@ def datetime_cast_time_sql(self, sql, params, tzname): return f"({sql})::time", params def format_for_duration_arithmetic(self, sql): - return "INTERVAL %s MILLISECOND" % sql + return f"INTERVAL {sql} MILLISECOND" def time_trunc_sql(self, lookup_type, sql, params, tzname=None): return f"DATE_TRUNC(%s, {sql})::time", (lookup_type, *params) diff --git a/django_mongodb_backend/schema.py b/django_mongodb_backend/schema.py index da3ec9613..a12086a6e 100644 --- a/django_mongodb_backend/schema.py +++ b/django_mongodb_backend/schema.py @@ -18,7 +18,7 @@ def ignore_embedded_models(func): def wrapper(self, model, *args, **kwargs): parent_model = kwargs.get("parent_model") - from .models import EmbeddedModel + from .models import EmbeddedModel # noqa: PLC0415 if issubclass(model, EmbeddedModel) and parent_model is None: return diff --git a/django_mongodb_backend/utils.py b/django_mongodb_backend/utils.py index f8a47cda7..634ec234b 100644 --- a/django_mongodb_backend/utils.py +++ b/django_mongodb_backend/utils.py @@ -17,7 +17,7 @@ def check_django_compatability(): installed version of Django. For example, any django-mongodb-backend 5.0.x is compatible with Django 5.0.y. """ - from . import __version__ + from . import __version__ # noqa: PLC0415 if django.VERSION[:2] != get_version_tuple(__version__)[:2]: A = django.VERSION[0] @@ -145,12 +145,7 @@ def log(self, op, duration, args, kwargs=None): operation = f"db.{self.collection_name}{op}({args})" if len(settings.DATABASES) > 1: msg += f"; alias={self.db.alias}" - self.db.queries_log.append( - { - "sql": operation, - "time": "%.3f" % duration, - } - ) + self.db.queries_log.append({"sql": operation, "time": f"{duration:.3f}"}) logger.debug( msg, duration, diff --git a/tests/cache_/tests.py b/tests/cache_/tests.py index c28b549e5..17237c0f2 100644 --- a/tests/cache_/tests.py +++ b/tests/cache_/tests.py @@ -1,9 +1,11 @@ """These tests are forked from Django's tests/cache/tests.py.""" + import os import pickle import time from functools import wraps from unittest import mock +from zlib import compress, decompress from bson import SON from django.conf import settings @@ -344,8 +346,6 @@ def test_unicode(self): def test_binary_string(self): # Binary strings should be cacheable - from zlib import compress, decompress - value = "value_to_be_compressed" compressed_value = compress(value.encode()) @@ -476,11 +476,11 @@ def _perform_cull_test(self, cull_cache_name, initial_count, final_count): # Create initial cache key entries. This will overflow the cache, # causing a cull. for i in range(1, initial_count): - cull_cache.set("cull%d" % i, "value", 1000) + cull_cache.set(f"cull{i}", "value", 1000) count = 0 # Count how many keys are left in the cache. for i in range(1, initial_count): - if cull_cache.has_key("cull%d" % i): + if cull_cache.has_key(f"cull{i}"): count += 1 self.assertEqual(count, final_count) @@ -550,7 +550,7 @@ def test_invalid_key_length(self): # memcached limits key length to 250. key = ("a" * 250) + "清" expected_warning = ( - "Cache key will cause errors if used with memcached: " f"'{key}' (longer than 250)" + f"Cache key will cause errors if used with memcached: '{key}' (longer than 250)" ) self._perform_invalid_key_test(key, expected_warning) diff --git a/tests/forms_tests_/test_array.py b/tests/forms_tests_/test_array.py index 360a68c49..d86c4b7d4 100644 --- a/tests/forms_tests_/test_array.py +++ b/tests/forms_tests_/test_array.py @@ -240,8 +240,7 @@ class SplitForm(forms.Form): def test_invalid_integer(self): msg = ( - "Item 2 in the array did not validate: Ensure this value is less than or " - "equal to 100." + "Item 2 in the array did not validate: Ensure this value is less than or equal to 100." ) with self.assertRaisesMessage(exceptions.ValidationError, msg): SplitArrayField(forms.IntegerField(max_value=100), size=2).clean([0, 101]) diff --git a/tests/indexes_/test_checks.py b/tests/indexes_/test_checks.py index c39d88c7d..10b22d11f 100644 --- a/tests/indexes_/test_checks.py +++ b/tests/indexes_/test_checks.py @@ -212,7 +212,7 @@ class Meta: errors, [ checks.Error( - "VectorSearchIndex requires at least one ArrayField to " "store vector data.", + "VectorSearchIndex requires at least one ArrayField to store vector data.", id="django_mongodb_backend.indexes.VectorSearchIndex.E006", obj=NoSearchVectorModel, hint="If you want to perform search operations without vectors, " diff --git a/tests/model_fields_/models.py b/tests/model_fields_/models.py index 4ce67bb31..c05b0556c 100644 --- a/tests/model_fields_/models.py +++ b/tests/model_fields_/models.py @@ -39,6 +39,9 @@ def __init__(self, tag_id): def __eq__(self, other): return isinstance(other, Tag) and self.tag_id == other.tag_id + def __hash__(self): + return hash(self.tag_id) + class TagField(models.SmallIntegerField): def from_db_value(self, value, expression, connection): @@ -185,7 +188,7 @@ class Section(EmbeddedModel): artifacts = EmbeddedModelArrayField("Artifact", null=True) def __str__(self): - return "Section %d" % self.number + return f"Section {self.number}" # Details about a specific artifact. diff --git a/tests/model_fields_/test_arrayfield.py b/tests/model_fields_/test_arrayfield.py index aecfe0074..a7dc54853 100644 --- a/tests/model_fields_/test_arrayfield.py +++ b/tests/model_fields_/test_arrayfield.py @@ -179,7 +179,7 @@ def test_other_array_types(self): instance = OtherTypesArrayModel( ips=["192.168.0.1", "::1"], uuids=[uuid.uuid4()], - decimals=[decimal.Decimal(1.25), 1.75], + decimals=[decimal.Decimal("1.25"), 1.75], tags=[Tag(1), Tag(2), Tag(3)], json=[{"a": 1}, {"b": 2}], ) @@ -542,11 +542,11 @@ class TestEnum(enum.Enum): ) def test_unsupported_lookup(self): - msg = "Unsupported lookup '0_bar' for ArrayField or join on the field not " "permitted." + msg = "Unsupported lookup '0_bar' for ArrayField or join on the field not permitted." with self.assertRaisesMessage(FieldError, msg): list(NullableIntegerArrayModel.objects.filter(field__0_bar=[2])) - msg = "Unsupported lookup '0bar' for ArrayField or join on the field not " "permitted." + msg = "Unsupported lookup '0bar' for ArrayField or join on the field not permitted." with self.assertRaisesMessage(FieldError, msg): list(NullableIntegerArrayModel.objects.filter(field__0bar=[2])) @@ -581,7 +581,7 @@ class OtherTypesExactQueryingTests(TestCase): def setUpTestData(cls): cls.ips = ["192.168.0.1", "::1"] cls.uuids = [uuid.uuid4()] - cls.decimals = [decimal.Decimal(1.25), 1.75] + cls.decimals = [decimal.Decimal("1.25"), 1.75] cls.tags = [Tag(1), Tag(2), Tag(3)] cls.objs = [ OtherTypesArrayModel.objects.create( diff --git a/tests/model_fields_/test_embedded_model.py b/tests/model_fields_/test_embedded_model.py index 250a48855..f6a3f8721 100644 --- a/tests/model_fields_/test_embedded_model.py +++ b/tests/model_fields_/test_embedded_model.py @@ -38,7 +38,7 @@ def test_deconstruct(self): self.assertEqual(kwargs, {"embedded_model": "Data", "null": True}) def test_get_db_prep_save_invalid(self): - msg = "Expected instance of type , " "not ." + msg = "Expected instance of type , not ." with self.assertRaisesMessage(TypeError, msg): Holder(data=42).save() diff --git a/tests/model_fields_/test_polymorphic_embedded_model_array.py b/tests/model_fields_/test_polymorphic_embedded_model_array.py index 9986a8c9d..7223e6a3a 100644 --- a/tests/model_fields_/test_polymorphic_embedded_model_array.py +++ b/tests/model_fields_/test_polymorphic_embedded_model_array.py @@ -156,14 +156,12 @@ def test_invalid_field(self): Owner.objects.filter(pets__xxx=10).first() def test_invalid_lookup(self): - msg = "Unsupported lookup 'return' for PolymorphicEmbeddedModelArrayField " "of 'CharField'" + msg = "Unsupported lookup 'return' for PolymorphicEmbeddedModelArrayField of 'CharField'" with self.assertRaisesMessage(FieldDoesNotExist, msg): Owner.objects.filter(pets__name__return="xxx") def test_unsupported_lookup(self): - msg = ( - "Unsupported lookup 'range' for PolymorphicEmbeddedModelArrayField " "of 'DecimalField'" - ) + msg = "Unsupported lookup 'range' for PolymorphicEmbeddedModelArrayField of 'DecimalField'" with self.assertRaisesMessage(FieldDoesNotExist, msg): Owner.objects.filter(pets__weight__range=[10]) diff --git a/tests/raw_query_/models.py b/tests/raw_query_/models.py index 4b647c9c7..bdffde6a6 100644 --- a/tests/raw_query_/models.py +++ b/tests/raw_query_/models.py @@ -18,7 +18,7 @@ def __init__(self, *args, **kwargs): # treated differently than fields. for k in kwargs: assert k in [f.attname for f in self._meta.fields], ( - "Author.__init__ got an unexpected parameter: %s" % k + f"Author.__init__ got an unexpected parameter: {k}" ) diff --git a/tests/raw_query_/test_raw_aggregate.py b/tests/raw_query_/test_raw_aggregate.py index ce87311a6..bfea45936 100644 --- a/tests/raw_query_/test_raw_aggregate.py +++ b/tests/raw_query_/test_raw_aggregate.py @@ -33,7 +33,7 @@ def setUpTestData(cls): author=cls.a1, paperback=False, opening_line=( - "It was a bright cold day in April and the clocks were striking " "thirteen." + "It was a bright cold day in April and the clocks were striking thirteen." ), ) cls.b2 = Book.objects.create( @@ -166,7 +166,7 @@ def test_order_handler(self): ("first_name, last_name, dob, id"), ) for select in selects: - select = {col: 1 for col in select.split(", ")} + select = dict.fromkeys(select.split(", "), 1) query = [{"$project": select}] authors = Author.objects.all() self.assertSuccessfulRawQuery(Author, query, authors)