anon-iclr-submission/benchname-bug-localization huggingface dataset:
Repository: librephotos/librephotos
Issue: KeyError when trying to "Find Similar Faces"

## 🐛 Bug Report

* [x] I am including my log files in zip format.
* [x] I have looked for similar issues among all the former issues, including closed ones.

### What Operating system and version is LibrePhotos running on:
Manjaro

### What architecture is LibrePhotos running on:
x64

### How is LibrePhotos installed:
Docker-Compose on dev tag

### How is your picture library mounted on the host (or in the virtual machine):
Local file system 

### Description of issue:

I used both the first version and the newest clustering versions on my production system. When using the latest version, it creates the clusters, but is not able to add the encoding, because of a key error.

```
2022-08-15 11:48:52,079 : face_classify.py : cluster_all_faces : 100 : ERROR : An error occurred
Traceback (most recent call last):
  File "/code/api/face_classify.py", line 86, in cluster_all_faces
    target_count: int = create_all_clusters(user, lrj)
  File "/code/api/face_classify.py", line 161, in create_all_clusters
    new_clusters: list[Cluster] = ClusterManager.try_add_cluster(
  File "/code/api/cluster_manager.py", line 127, in try_add_cluster
    encoding_by_person[closest_cluster.person.id].append(encoding)
KeyError: 1
```

### How can we reproduce it:

Use the old version, update, rerun on the new version


Changed files:
api/cluster_manager.py

diff --git a/api/cluster_manager.py b/api/cluster_manager.py
index 8ffac69..8c95929 100644
--- a/api/cluster_manager.py
+++ b/api/cluster_manager.py
@@ -112,7 +112,7 @@ class ClusterManager:
                     if unknown_person.id not in clusters_by_person.keys():
                         clusters_by_person[closest_cluster.person.id] = closest_cluster
                         added_clusters.append(closest_cluster)
-                        encoding_by_person[closest_cluster.id] = []
+                        encoding_by_person[closest_cluster.person.id] = []
                         face_ids_by_cluster[closest_cluster.id] = []
                 else:
                     min_distance: np.float64 = np.Infinity
Repository: librephotos/librephotos
Issue: New user "deleted" is in the database 

An unknown user "deleted" started to appear after #553. This could also be related to the scanning no longer working.

Changed files:
api/views/user.py, api/models/user.py

diff --git a/api/models/user.py b/api/models/user.py
index 5da823f..e2ce91e 100644
--- a/api/models/user.py
+++ b/api/models/user.py
@@ -50,4 +50,8 @@ def get_admin_user():
 
 
 def get_deleted_user():
-    return User.objects.get_or_create(username="deleted")[0]
+    deleted_user: User = User.objects.get_or_create(username="deleted")[0]
+    if deleted_user.is_active is not False:
+        deleted_user.is_active = False
+        deleted_user.save()
+    return deleted_user
diff --git a/api/views/user.py b/api/views/user.py
index 4331b6e..6b855a4 100644
--- a/api/views/user.py
+++ b/api/views/user.py
@@ -61,27 +61,31 @@ class UserViewSet(viewsets.ModelViewSet):
     permission_classes = (IsUserOrReadOnly,)
 
     def get_queryset(self):
-        queryset = User.objects.only(
-            "id",
-            "username",
-            "email",
-            "scan_directory",
-            "transcode_videos",
-            "confidence",
-            "semantic_search_topk",
-            "first_name",
-            "last_name",
-            "date_joined",
-            "avatar",
-            "nextcloud_server_address",
-            "nextcloud_username",
-            "nextcloud_scan_directory",
-            "favorite_min_rating",
-            "image_scale",
-            "save_metadata_to_disk",
-            "datetime_rules",
-            "default_timezone",
-        ).order_by("-last_login")
+        queryset = (
+            User.objects.exclude(is_active=False)
+            .only(
+                "id",
+                "username",
+                "email",
+                "scan_directory",
+                "transcode_videos",
+                "confidence",
+                "semantic_search_topk",
+                "first_name",
+                "last_name",
+                "date_joined",
+                "avatar",
+                "nextcloud_server_address",
+                "nextcloud_username",
+                "nextcloud_scan_directory",
+                "favorite_min_rating",
+                "image_scale",
+                "save_metadata_to_disk",
+                "datetime_rules",
+                "default_timezone",
+            )
+            .order_by("-last_login")
+        )
         return queryset
 
     def get_permissions(self):
Repository: librephotos/librephotos
Issue: cant start scan from cli


## 🐛 Bug Report

* [x] I am including my log files in zip format.
* [x] I have looked for similar issues among all the former issues including closed ones.

### What Operating system and version is LibrePhotos running on:


### What architecture is LibrePhotos running on:
x64


### How is LibrePhotos installed:
Docker

### How is you picture library mounted on the host (or in the virtual machine):
Local file system


> ### Description of issue:
> error when trying to start scan from the cli for docker.
> 
> # docker exec --user root backend python3 manage.py scan
> Traceback (most recent call last):
>   File "/code/manage.py", line 22, in <module>
>     execute_from_command_line(sys.argv)
>   File "/usr/local/lib/python3.9/dist-packages/django/core/management/__init__.py", line 401, in execute_from_command_line
>     utility.execute()
>   File "/usr/local/lib/python3.9/dist-packages/django/core/management/__init__.py", line 395, in execute
>     self.fetch_command(subcommand).run_from_argv(self.argv)
>   File "/usr/local/lib/python3.9/dist-packages/django/core/management/base.py", line 330, in run_from_argv
>     self.execute(*args, **cmd_options)
>   File "/usr/local/lib/python3.9/dist-packages/django/core/management/base.py", line 371, in execute
>     output = self.handle(*args, **options)
>   File "/code/api/management/commands/scan.py", line 12, in handle
>     scan_photos(user,uuid.uuid4())
> TypeError: scan_photos() missing 1 required positional argument: 'job_id'
> 

### How can we reproduce it:

docker exec --user root backend python3 manage.py scan

#### Additional Information:

* Include a ZIP file containing your `log` files.


Changed files:
api/management/commands/scan.py

diff --git a/api/management/commands/scan.py b/api/management/commands/scan.py
index 42234a0..e472b45 100644
--- a/api/management/commands/scan.py
+++ b/api/management/commands/scan.py
@@ -7,6 +7,13 @@ import django_rq
 
 class Command(BaseCommand):
     help = 'scan directory for all users'
-    def handle(self, *args, **kwargs):
+
+    def add_arguments(self, parser):
+        parser.add_argument('-f', '--full-scan',
+            help=('Run full scan'),
+            action='store_true'
+        )
+
+    def handle(self, *args, **options):
         for user in User.objects.all():
-            scan_photos(user,uuid.uuid4())
+            scan_photos(user, options['full_scan'], uuid.uuid4())
Repository: librephotos/librephotos
Issue: Duplicated faces on rescan faces

Face recognition is not deterministic and will sometimes create slightly different location points for a face. If you rescan faces, then this will lead to duplicates of the same face.

To reduce the number of duplications, this function should check all faces for an image. If none match the new faces within a certain margin (+-5%), then add the face. Otherwise, skip.

Maybe this is possible to do within the getOrCreate call, but I haven't checked up on the documentation yet.

https://github.com/LibrePhotos/librephotos/blob/8d834d9721b56656441be74b4c5bacb7200698f2/api/models/photo.py#L320-L364

Changed files:
api/models/face.py, api/models/photo.py

diff --git a/api/models/face.py b/api/models/face.py
index c1befce..ec0e81a 100644
--- a/api/models/face.py
+++ b/api/models/face.py
@@ -1,4 +1,7 @@
+import os
+
 from django.db import models
+from django.dispatch import receiver
 
 from api.models.person import Person, get_unknown_person
 from api.models.photo import Photo
@@ -26,3 +29,11 @@ class Face(models.Model):
 
     def __str__(self):
         return "%d" % self.id
+
+
+# From: https://stackoverflow.com/questions/16041232/django-delete-filefield
+@receiver(models.signals.post_delete, sender=Face)
+def auto_delete_file_on_delete(sender, instance, **kwargs):
+    if instance.image:
+        if os.path.isfile(instance.image.path):
+            os.remove(instance.image.path)
diff --git a/api/models/photo.py b/api/models/photo.py
index d813b5a..ac92fb4 100644
--- a/api/models/photo.py
+++ b/api/models/photo.py
@@ -444,7 +444,23 @@ class Photo(models.Model):
 
                 image_path = self.image_hash + "_" + str(idx_face) + ".jpg"
 
-                face, created = api.models.face.Face.objects.get_or_create(
+                margin = 2
+                existing_faces = api.models.face.Face.objects.filter(
+                    photo=self,
+                    location_top__lte    = face_location[0]+margin,
+                    location_top__gte    = face_location[0]-margin,
+                    location_right__lte  = face_location[1]+margin,
+                    location_right__gte  = face_location[1]-margin,
+                    location_bottom__lte = face_location[2]+margin,
+                    location_bottom__gte = face_location[2]-margin,
+                    location_left__lte   = face_location[3]+margin,
+                    location_left__gte   = face_location[3]-margin,
+                )
+
+                if existing_faces.count() != 0:
+                    continue
+
+                face = api.models.face.Face(
                     image_path=image_path,
                     photo=self,
                     location_top=face_location[0],
@@ -452,7 +468,7 @@ class Photo(models.Model):
                     location_bottom=face_location[2],
                     location_left=face_location[3],
                     encoding=face_encoding.tobytes().hex(),
-                    defaults={"person": unknown_person},
+                    person=unknown_person,
                 )
 
                 face_io = BytesIO()