From 0173642d21cc96af652b2fc0a4422bf11bd1023a Mon Sep 17 00:00:00 2001
From: Yoann Schneider <yschneider@teklia.com>
Date: Fri, 12 Apr 2024 19:00:27 +0200
Subject: [PATCH] Comply with RET502

---
 arkindex/documents/api/elements.py                     | 10 +++++-----
 arkindex/documents/date_parser.py                      |  6 +++---
 arkindex/documents/dates.py                            |  2 +-
 arkindex/documents/indexer.py                          |  2 +-
 arkindex/documents/management/commands/bootstrap.py    |  2 +-
 arkindex/documents/models.py                           |  6 +++---
 arkindex/documents/serializers/elements.py             |  4 ++--
 arkindex/documents/serializers/light.py                |  2 +-
 arkindex/documents/tests/test_edit_elementpath.py      |  2 +-
 arkindex/images/serializers.py                         |  2 +-
 arkindex/ponos/serializers.py                          |  2 +-
 arkindex/process/models.py                             |  4 ++--
 arkindex/process/serializers/files.py                  |  2 +-
 arkindex/project/aws.py                                |  4 ++--
 arkindex/project/gis.py                                |  2 +-
 arkindex/project/rq_overrides.py                       |  4 ++--
 arkindex/project/validators.py                         |  2 +-
 .../training/management/commands/migrate_workers.py    |  4 ++--
 ruff.toml                                              |  2 ++
 19 files changed, 33 insertions(+), 31 deletions(-)

diff --git a/arkindex/documents/api/elements.py b/arkindex/documents/api/elements.py
index f08ae65497..af31201210 100644
--- a/arkindex/documents/api/elements.py
+++ b/arkindex/documents/api/elements.py
@@ -576,7 +576,7 @@ class ElementsListBase(CorpusACLMixin, DestroyModelMixin, ListAPIView):
         # Retrieve the corpus and check user access rights only once
         corpus_id = self.kwargs.get("corpus")
         if corpus_id is None:
-            return
+            return None
 
         corpus = get_object_or_404(Corpus, id=corpus_id)
         self.check_corpus_access(corpus)
@@ -585,13 +585,13 @@ class ElementsListBase(CorpusACLMixin, DestroyModelMixin, ListAPIView):
     @property
     def folder_filter(self):
         if self.clean_params.get("folder") is None:
-            return
+            return None
         return self.clean_params["folder"].lower() not in ("false", "0")
 
     @cached_property
     def type_filter(self):
         if "type" not in self.request.query_params:
-            return
+            return None
         try:
             element_type = self.selected_corpus.types.get(slug=self.clean_params["type"])
         except ElementType.DoesNotExist:
@@ -645,7 +645,7 @@ class ElementsListBase(CorpusACLMixin, DestroyModelMixin, ListAPIView):
         value = self.clean_params.get("metadata_value")
         operator = self.clean_params.get("metadata_operator", "").lower().strip()
         if not any((name, value, operator)):
-            return
+            return None
 
         queryset = MetaData.objects.all()
         errors = defaultdict(list)
@@ -1633,7 +1633,7 @@ class ElementTranscriptions(ListAPIView):
     @property
     def is_recursive(self):
         if not self.request:
-            return
+            return None
         recursive = self.request.query_params.get("recursive")
         return recursive is not None and recursive.lower() not in ("false", "0")
 
diff --git a/arkindex/documents/date_parser.py b/arkindex/documents/date_parser.py
index 0b088dddd5..47a0ffb031 100644
--- a/arkindex/documents/date_parser.py
+++ b/arkindex/documents/date_parser.py
@@ -45,7 +45,7 @@ def year(raw_date):
     """
     match = re.match(r"^(?P<year>\d{4})$", raw_date)
     if not match:
-        return
+        return None
     date = {k: int(v) for k, v in match.groupdict().items()}
     date["type"] = DateType.Exact
     return (date, )
@@ -57,7 +57,7 @@ def year_month(raw_date):
     """
     match = re.match(r"^(?P<year>\d{4})-(?P<month>\d{1,2})$", raw_date)
     if not match:
-        return
+        return None
     date = {k: int(v) for k, v in match.groupdict().items()}
     date["type"] = DateType.Exact
     return (date, )
@@ -70,7 +70,7 @@ def year_month_day(raw_date):
     """
     match = re.match(r"^(?P<year>\d{4})-(?P<month>\d{1,2})-(?P<day>\d{1,2})$", raw_date)
     if not match:
-        return
+        return None
     date = {k: int(v) for k, v in match.groupdict().items()}
     date["type"] = DateType.Exact
     return (date, )
diff --git a/arkindex/documents/dates.py b/arkindex/documents/dates.py
index 10643931a2..34bfa85281 100644
--- a/arkindex/documents/dates.py
+++ b/arkindex/documents/dates.py
@@ -64,7 +64,7 @@ class InterpretedDate(object):
         """
         for s, o in zip(tuple(self), tuple(other)):
             if s is None or o is None:
-                return
+                return None
             if s == o:
                 continue
             return s > o
diff --git a/arkindex/documents/indexer.py b/arkindex/documents/indexer.py
index 203722ec31..f4f57ea0c2 100644
--- a/arkindex/documents/indexer.py
+++ b/arkindex/documents/indexer.py
@@ -221,7 +221,7 @@ class Indexer(object):
 
     def hash_worker(self, worker_version):
         if not worker_version:
-            return
+            return None
 
         return worker_version.worker.name
 
diff --git a/arkindex/documents/management/commands/bootstrap.py b/arkindex/documents/management/commands/bootstrap.py
index 3ca2dacd4a..aa3bfe85c1 100644
--- a/arkindex/documents/management/commands/bootstrap.py
+++ b/arkindex/documents/management/commands/bootstrap.py
@@ -94,7 +94,7 @@ class Command(BaseCommand):
                 self.success(f"Image server {server.id} created")
             except IntegrityError as e:
                 self.fail(f"Failed to create image server: {e}")
-                return
+                return None
         return server
 
     def handle(self, **options):
diff --git a/arkindex/documents/models.py b/arkindex/documents/models.py
index e100e2b25e..f8fda6ea2c 100644
--- a/arkindex/documents/models.py
+++ b/arkindex/documents/models.py
@@ -644,7 +644,7 @@ class Element(IndexableModel):
         Cropped IIIF URL for this element's image, if there is one.
         """
         if not self.polygon or not self.image_id:
-            return
+            return None
 
         from arkindex.project.tools import bounding_box
         x, y, width, height = bounding_box(self.polygon)
@@ -660,7 +660,7 @@ class Element(IndexableModel):
         Same as `iiif_url`, but resized to up to 400 pixels and with rotation and mirroring
         """
         if not self.polygon or not self.image_id:
-            return
+            return None
 
         from arkindex.project.tools import bounding_box
         x, y, width, height = bounding_box(self.polygon)
@@ -1159,7 +1159,7 @@ class MetaData(InterpretedDateMixin, models.Model):
     @property
     def raw_dates(self):
         if self.type != MetaType.Date:
-            return
+            return None
         return self.value
 
     def clean(self):
diff --git a/arkindex/documents/serializers/elements.py b/arkindex/documents/serializers/elements.py
index 7c70990226..ad9b227200 100644
--- a/arkindex/documents/serializers/elements.py
+++ b/arkindex/documents/serializers/elements.py
@@ -406,7 +406,7 @@ class ElementTinySerializer(serializers.ModelSerializer):
         This method ensures the zone attribute is None.
         """
         if not element.image_id or not element.polygon:
-            return
+            return None
         return ZoneSerializer(element).data
 
     class Meta:
@@ -599,7 +599,7 @@ class ElementSerializer(ElementTinySerializer):
     @cached_property
     def element_rights(self):
         if not self.instance:
-            return
+            return None
 
         user = self.context["request"].user
         level = get_max_level(user, self.instance.corpus)
diff --git a/arkindex/documents/serializers/light.py b/arkindex/documents/serializers/light.py
index 6a8189eebb..3d6ebce7ea 100644
--- a/arkindex/documents/serializers/light.py
+++ b/arkindex/documents/serializers/light.py
@@ -59,7 +59,7 @@ class ElementZoneSerializer(ElementLightSerializer):
         This method ensures the zone attribute is None.
         """
         if not element.image_id or not element.polygon:
-            return
+            return None
         return ZoneLightSerializer(element).data
 
     class Meta(ElementLightSerializer.Meta):
diff --git a/arkindex/documents/tests/test_edit_elementpath.py b/arkindex/documents/tests/test_edit_elementpath.py
index 21455699fd..866aa77cde 100644
--- a/arkindex/documents/tests/test_edit_elementpath.py
+++ b/arkindex/documents/tests/test_edit_elementpath.py
@@ -32,7 +32,7 @@ class TestEditElementPath(FixtureTestCase):
 
         if paths is None or len(paths) < 1:
             self.assertNotIn(elements[element_name].id, tree)
-            return
+            return None
 
         element_names = {e.id: e.name for e in elements.values()}
 
diff --git a/arkindex/images/serializers.py b/arkindex/images/serializers.py
index 1b0805674f..05709481ea 100644
--- a/arkindex/images/serializers.py
+++ b/arkindex/images/serializers.py
@@ -59,7 +59,7 @@ class ImageSerializer(serializers.ModelSerializer):
     @extend_schema_field(serializers.CharField(allow_null=True))
     def get_s3_url(self, obj):
         if "request" not in self.context:
-            return
+            return None
         # Only allow the S3 URL for admins or Ponos tasks
         if is_admin_or_ponos_task(self.context["request"]):
             return obj.s3_url
diff --git a/arkindex/ponos/serializers.py b/arkindex/ponos/serializers.py
index 932cc7c0c9..9bc7a5c636 100644
--- a/arkindex/ponos/serializers.py
+++ b/arkindex/ponos/serializers.py
@@ -225,7 +225,7 @@ class ArtifactSerializer(serializers.ModelSerializer):
         """Only add the PUT url to store the file for agents during creation"""
         request = self.context.get("request")
         if not request or request.method != "POST":
-            return
+            return None
         return obj.s3_put_url
 
     def validate_path(self, path):
diff --git a/arkindex/process/models.py b/arkindex/process/models.py
index 94d0412029..5699d7c6a3 100644
--- a/arkindex/process/models.py
+++ b/arkindex/process/models.py
@@ -806,13 +806,13 @@ class WorkerVersion(models.Model):
     @property
     def docker_command(self):
         if "docker" not in self.configuration:
-            return
+            return None
         return self.configuration["docker"].get("command")
 
     @property
     def docker_shm_size(self):
         if "docker" not in self.configuration:
-            return
+            return None
         return self.configuration["docker"].get("shm_size")
 
 
diff --git a/arkindex/process/serializers/files.py b/arkindex/process/serializers/files.py
index 497aa2e5f5..3dbc77b799 100644
--- a/arkindex/process/serializers/files.py
+++ b/arkindex/process/serializers/files.py
@@ -40,7 +40,7 @@ class DataFileSerializer(serializers.ModelSerializer):
     @extend_schema_field(serializers.CharField(allow_null=True))
     def get_s3_url(self, obj):
         if "request" not in self.context:
-            return
+            return None
         # Only allow the S3 URL for ponos tasks of Files or IIIF processes or admins
         request = self.context["request"]
         if is_admin_or_ponos_task(request):
diff --git a/arkindex/project/aws.py b/arkindex/project/aws.py
index 659f37326a..51b392337e 100644
--- a/arkindex/project/aws.py
+++ b/arkindex/project/aws.py
@@ -64,7 +64,7 @@ def requires_s3_object(func):
             logger.debug(
                 f"Function {func.__name__} requires file to have s3_object property, skipping"
             )
-            return
+            return None
         return func(self, *args, **kwargs)
     return wrapper
 
@@ -92,7 +92,7 @@ class S3FileMixin(object):
 
     def get_s3_object(self):
         if not self.s3_bucket or not self.s3_key:
-            return
+            return None
         return s3.Object(self.s3_bucket, self.s3_key)
 
     s3_object = cached_property(get_s3_object)
diff --git a/arkindex/project/gis.py b/arkindex/project/gis.py
index 8f80e295c1..3b02fc4a4d 100644
--- a/arkindex/project/gis.py
+++ b/arkindex/project/gis.py
@@ -14,7 +14,7 @@ def ensure_linear_ring(value):
     # Polygons are nullable, so this can get called with None values;
     # if we had a non-null field, null values would be handled elsewhere by Django.
     if value is None:
-        return
+        return None
 
     if isinstance(value, str):
         value = GEOSGeometry(value, srid=0)
diff --git a/arkindex/project/rq_overrides.py b/arkindex/project/rq_overrides.py
index ae53b22aed..82e109a8d5 100644
--- a/arkindex/project/rq_overrides.py
+++ b/arkindex/project/rq_overrides.py
@@ -10,13 +10,13 @@ from rq.utils import as_text, decode_redis_hash
 
 def as_int(value) -> Optional[int]:
     if value is None:
-        return
+        return None
     return int(value)
 
 
 def as_float(value) -> Optional[float]:
     if value is None:
-        return
+        return None
     return float(value)
 
 
diff --git a/arkindex/project/validators.py b/arkindex/project/validators.py
index 15fb732317..7c5cdbe9fc 100644
--- a/arkindex/project/validators.py
+++ b/arkindex/project/validators.py
@@ -41,7 +41,7 @@ class ConditionalUniqueValidator(serializers.UniqueTogetherValidator):
 
     def __call__(self, attrs, serializer):
         if not self.condition(attrs):
-            return
+            return None
         return super().__call__(attrs, serializer)
 
 
diff --git a/arkindex/training/management/commands/migrate_workers.py b/arkindex/training/management/commands/migrate_workers.py
index 51e1516508..8408d89e41 100644
--- a/arkindex/training/management/commands/migrate_workers.py
+++ b/arkindex/training/management/commands/migrate_workers.py
@@ -32,7 +32,7 @@ def choose(instances, name_field="name", title="Pick one item", allow_skip=False
     # Easy immediate choices
     nb = instances.count()
     if nb == 0:
-        return
+        return None
     elif nb == 1:
         return instances.first()
 
@@ -54,7 +54,7 @@ def choose(instances, name_field="name", title="Pick one item", allow_skip=False
         if choice in choices:
             value = choices[choice]
             if value is None:
-                return
+                return None
             return instances.get(pk=choices[choice])
 
 
diff --git a/ruff.toml b/ruff.toml
index 749c24cac4..3b796847f5 100644
--- a/ruff.toml
+++ b/ruff.toml
@@ -8,5 +8,7 @@ quote-style = "double"
 select = ["Q0", "F", "W", "E",
     # flake8-return: unnecessary-return-none
     "RET501",
+    # flake8-return: implicit-return-value
+    "RET502",
 ]
 ignore = ["E501"]
-- 
GitLab