internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: comic/grand-challenge.org

Issue:
"Run algorithm" page is missing the breadcrumb bar
Maybe this is on purpose, but I find it confusing that the page that allows users to upload images and run an algorithm does not show the breadcrumb bar to get back to the algorithm overview page.

Example: https://grand-challenge.org/algorithms/vertebra-segmentation/run/

To be consistent with the job list the title of that page could also read "Run this algorithm" instead "Run an algorithm"


Discussion:
Related: #994 - maybe review all breadcrumbs for these apps.
Also missing on the "add user" page: https://grand-challenge.org/algorithms/vertebra-segmentation/users/update/
The fix does not quite work, the breadcrumbs are not correct for:

- algorithm_execution_session_create.html 
- algorithm_user_groups_form.html 
- algorithmimage_form.html 

```
       <li class="breadcrumb-item"><a
                href="{{ algorithm.get_absolute_url }}">{{ algorithm.title }}
        </a>
```

Is returning an empty string

Resolving patch:
diff --git a/app/grandchallenge/algorithms/views.py b/app/grandchallenge/algorithms/views.py
--- a/app/grandchallenge/algorithms/views.py
+++ b/app/grandchallenge/algorithms/views.py
@@ -212,6 +212,11 @@ def form_valid(self, form):
 
         return super().form_valid(form)
 
+    def get_context_data(self, *args, **kwargs):
+        context = super().get_context_data(*args, **kwargs)
+        context.update({"algorithm": self.algorithm})
+        return context
+
 
 class AlgorithmImageDetail(
     LoginRequiredMixin, ObjectPermissionRequiredMixin, DetailView
@@ -229,6 +234,11 @@ class AlgorithmImageUpdate(
     permission_required = f"{AlgorithmImage._meta.app_label}.change_{AlgorithmImage._meta.model_name}"
     raise_exception = True
 
+    def get_context_data(self, *args, **kwargs):
+        context = super().get_context_data(*args, **kwargs)
+        context.update({"algorithm": self.object.algorithm})
+        return context
+
 
 class AlgorithmExecutionSessionCreate(
     LoginRequiredMixin,
@@ -270,6 +280,11 @@ def form_valid(self, form):
         form.instance.algorithm_image = self.algorithm.latest_ready_image
         return super().form_valid(form)
 
+    def get_context_data(self, *args, **kwargs):
+        context = super().get_context_data(*args, **kwargs)
+        context.update({"algorithm": self.algorithm})
+        return context
+
     def get_success_url(self):
         return reverse(
             "algorithms:jobs-list", kwargs={"slug": self.kwargs["slug"]}


Test patch:
Repository: comic/grand-challenge.org

Issue:
The schema is empty for unauthorised users.
Another problem with this - the schema is empty for unauthorised users. You need to add `public=True` to `get_schema_view`.

_Originally posted by @jmsmkn in https://github.com/comic/grand-challenge.org/issues/1017#issuecomment-567254400_


Discussion:

Resolving patch:
diff --git a/app/grandchallenge/api/urls.py b/app/grandchallenge/api/urls.py
--- a/app/grandchallenge/api/urls.py
+++ b/app/grandchallenge/api/urls.py
@@ -78,6 +78,7 @@
             "policies:detail", kwargs={"slug": "terms-of-service"}
         ),
     ),
+    public=True,
     permission_classes=(permissions.AllowAny,),
     patterns=[path("api/v1/", include(router.urls))],
 )


Test patch:
diff --git a/app/tests/api_tests/test_urls.py b/app/tests/api_tests/test_urls.py
--- a/app/tests/api_tests/test_urls.py
+++ b/app/tests/api_tests/test_urls.py
@@ -17,6 +17,10 @@ def test_api_docs_generation(
     client, schema, schema_format,
 ):
     kwargs = dict(format=schema_format) if schema == "schema-json" else None
-    assert_viewname_status(
-        code=200, url=reverse(f"api:{schema}", kwargs=kwargs), client=client,
+    response = assert_viewname_status(
+        code=200, url=reverse(f"api:{schema}", kwargs=kwargs), client=client
     )
+    if schema_format is not None:
+        assert len(response.data["paths"]) > 0
+    else:
+        assert len(response.content) > 0
Repository: comic/grand-challenge.org

Issue:
Duplicate email to algorithm user that is also an editor when job fails
A tiny improvement request: When an algorithm job fails, the editors and the job creator are emailed (#1018), but there is apparently no check whether the job creator is one of the algorithm editor and would receive an email anyway - I was testing a new algorithm and always received two emails when a job failed.


Discussion:

Resolving patch:
diff --git a/app/grandchallenge/algorithms/emails.py b/app/grandchallenge/algorithms/emails.py
--- a/app/grandchallenge/algorithms/emails.py
+++ b/app/grandchallenge/algorithms/emails.py
@@ -99,7 +99,8 @@ def send_failed_job_email(job):
         o.email for o in algorithm.editors_group.user_set.all()
     ]
     recipient_emails.append(job.creator.email)
-    for email in recipient_emails:
+
+    for email in {*recipient_emails}:
         send_mail(
             subject=(
                 f"[{Site.objects.get_current().domain.lower()}] "


Test patch:
Repository: comic/grand-challenge.org

Issue:
Adding timestamps to reader study answers
Would it be possible to add timestamps to the reader study answers? Based on the timestamps, I could calculate the average time that participants need for answering all questions. It would be nice to provide a time indication to (new) participants beforehand, because I assume that without any indication many participants are reluctant to start scoring the cases. 


Discussion:

Resolving patch:
diff --git a/app/grandchallenge/reader_studies/models.py b/app/grandchallenge/reader_studies/models.py
--- a/app/grandchallenge/reader_studies/models.py
+++ b/app/grandchallenge/reader_studies/models.py
@@ -626,7 +626,12 @@ class Answer(UUIDModel):
     images = models.ManyToManyField("cases.Image", related_name="answers")
     answer = JSONField()
 
-    csv_headers = Question.csv_headers + ["Answer", "Images", "Creator"]
+    csv_headers = Question.csv_headers + [
+        "Created",
+        "Answer",
+        "Images",
+        "Creator",
+    ]
 
     class Meta:
         ordering = ("creator", "created")
@@ -643,6 +648,7 @@ def api_url(self):
     @property
     def csv_values(self):
         return self.question.csv_values + [
+            self.created.isoformat(),
             self.answer,
             "; ".join(self.images.values_list("name", flat=True)),
             self.creator.username,
diff --git a/app/grandchallenge/reader_studies/serializers.py b/app/grandchallenge/reader_studies/serializers.py
--- a/app/grandchallenge/reader_studies/serializers.py
+++ b/app/grandchallenge/reader_studies/serializers.py
@@ -106,4 +106,12 @@ def validate(self, attrs):
 
     class Meta:
         model = Answer
-        fields = ("answer", "api_url", "creator", "images", "pk", "question")
+        fields = (
+            "answer",
+            "api_url",
+            "created",
+            "creator",
+            "images",
+            "pk",
+            "question",
+        )


Test patch:
Repository: comic/grand-challenge.org

Issue:
Improve annotation admin pages
The graders have asked me to delete all annotations for one user for a specific image. There is currently no easy way to do this in the admin pages. I will need to find a way to make this possible. Probably by adding certain search_fields or list_filters.

Also, I have noticed that some admin pages take extremely long to load. For example the change page for a polygon annotation set. I think this happens because it has to load a lot of data which it does not do efficiently and because it makes all inline model fields are editable by default. It will most likely never happen that we need to change this data manually so those fields can all be set to read_only. It might also be better to just have some statistics there about the number of inline models and not show the actual inline models at all.
Example loading time for an admin page:
![image](https://user-images.githubusercontent.com/2001094/73462398-08bf9380-437c-11ea-9116-a6170c114176.png)



Discussion:
Sometimes it is easier to do this via the python shell, especially if it is a 1 off. More powerful, but more risky. 

Edit: you said the same thing in your comment, sorry!

Resolving patch:
diff --git a/app/grandchallenge/annotations/admin.py b/app/grandchallenge/annotations/admin.py
--- a/app/grandchallenge/annotations/admin.py
+++ b/app/grandchallenge/annotations/admin.py
@@ -19,23 +19,33 @@ class BooleanClassificationAnnotationAdmin(admin.ModelAdmin):
 class SinglePolygonAnnotationInline(admin.StackedInline):
     model = SinglePolygonAnnotation
     extra = 0
+    readonly_fields = (
+        "annotation_set",
+        "value",
+        "x_axis_orientation",
+        "y_axis_orientation",
+        "z",
+    )
 
 
 class PolygonAnnotationSetAdmin(admin.ModelAdmin):
-    search_fields = ("grader__username", "created", "name")
+    search_fields = ("grader__username", "created", "name", "image__name")
     list_filter = ("created", "grader__username", "name")
     inlines = [SinglePolygonAnnotationInline]
+    readonly_fields = ("grader", "image", "name", "created")
 
 
 class SingleLandmarkAnnotationInline(admin.StackedInline):
     model = SingleLandmarkAnnotation
     extra = 0
+    readonly_fields = ("image", "landmarks")
 
 
 class LandmarkAnnotationSetAdmin(admin.ModelAdmin):
     search_fields = ("grader__username", "created")
     list_filter = ("created", "grader__username")
     inlines = [SingleLandmarkAnnotationInline]
+    readonly_fields = ("grader", "created")
 
 
 admin.site.register(ETDRSGridAnnotation)


Test patch:
Repository: comic/grand-challenge.org

Issue:
Add functionality to filter ImageFile objects by RawImageUploadSession from a client
**Is your feature request related to a problem? Please describe.**
I would like to know which ImageFile was generated by a specific RawImageUploadSession from gcapi
**Describe the solution you'd like**
Add an additional item to the existing set of filters in ImageViewSet.get_queryset()




Discussion:

Resolving patch:
diff --git a/app/grandchallenge/cases/views.py b/app/grandchallenge/cases/views.py
--- a/app/grandchallenge/cases/views.py
+++ b/app/grandchallenge/cases/views.py
@@ -51,6 +51,7 @@ def get_queryset(self):
         filters = {
             "worklist": self.request.query_params.get("worklist", None),
             "study": self.request.query_params.get("study", None),
+            "origin": self.request.query_params.get("origin", None),
         }
         filters = {k: v for k, v in filters.items() if v is not None}
 


Test patch:
diff --git a/app/tests/cases_tests/test_api.py b/app/tests/cases_tests/test_api.py
--- a/app/tests/cases_tests/test_api.py
+++ b/app/tests/cases_tests/test_api.py
@@ -1,12 +1,16 @@
 import pytest
 
 from grandchallenge.cases.models import RawImageFile, RawImageUploadSession
-from tests.algorithms_tests.factories import AlgorithmImageFactory
+from tests.algorithms_tests.factories import (
+    AlgorithmFactory,
+    AlgorithmImageFactory,
+    AlgorithmResultFactory,
+)
 from tests.cases_tests.factories import (
     RawImageFileFactory,
     RawImageUploadSessionFactory,
 )
-from tests.factories import UserFactory
+from tests.factories import ImageFactory, UserFactory
 from tests.utils import get_view_for_user
 
 
@@ -321,3 +325,39 @@ def request_processing():
     # Jobs should only be run once
     response = request_processing()
     assert response.status_code == 400
+
+
+@pytest.mark.django_db
+def test_filter_images_api_view(client):
+    alg = AlgorithmFactory()
+    user = UserFactory()
+    alg.add_editor(user=user)
+
+    alg_result = AlgorithmResultFactory(
+        job__algorithm_image__algorithm=alg, job__creator=user
+    )
+
+    im = ImageFactory()
+    alg_result.images.add(im)
+
+    response = get_view_for_user(
+        viewname="api:image-list",
+        client=client,
+        user=user,
+        content_type="application/json",
+    )
+    assert response.status_code == 200
+    assert {r["pk"] for r in response.json()["results"]} == {
+        str(i.pk) for i in [alg_result.job.image, im]
+    }
+
+    response = get_view_for_user(
+        client=client,
+        user=user,
+        viewname="api:image-list",
+        data={"origin": str(im.origin.pk)},
+        content_type="application/json",
+    )
+    assert response.status_code == 200
+    assert response.json()["count"] == 1
+    assert response.json()["results"][0]["pk"] == str(im.pk)
Repository: comic/grand-challenge.org

Issue:
Reader study completed message is visible when study is not completed
![Screenshot_20200209_164820](https://user-images.githubusercontent.com/12661555/74105211-1931f400-4b5c-11ea-96d8-6b4663386d09.png)



Discussion:

Resolving patch:
diff --git a/app/grandchallenge/reader_studies/templatetags/get_ground_truth.py b/app/grandchallenge/reader_studies/templatetags/get_ground_truth.py
--- a/app/grandchallenge/reader_studies/templatetags/get_ground_truth.py
+++ b/app/grandchallenge/reader_studies/templatetags/get_ground_truth.py
@@ -5,6 +5,7 @@
 
 @register.simple_tag
 def get_ground_truth(obj, image, question):
-    """Get the auth token for the user."""
+    """Get the ground truth value for the image/question combination in reader
+    study obj."""
     ground_truths = obj.statistics["ground_truths"]
     return ground_truths[image][question]


Test patch:
Repository: comic/grand-challenge.org

Issue:
Add latest build date to django front page
**Is your feature request related to a problem? Please describe.**
It is at the moment cumbersome to find the latest date grand-challenge was updated to know which changes were included. This could be solved by putting the latest update date at the bottom of the page.

**Describe the solution you'd like**
Adding a new templatetag for the update date which we can grab from the git repository.

**Describe alternatives you've considered**
A version number, but this is a hassle to maintain and requires additional lookup



Discussion:
The date isn't really informative and makes it hard to track back, the commit ID is more useful and is available from the deployment. 

Resolving patch:
diff --git a/app/config/settings.py b/app/config/settings.py
--- a/app/config/settings.py
+++ b/app/config/settings.py
@@ -21,6 +21,8 @@ def strtobool(val) -> bool:
 
 DEBUG = strtobool(os.environ.get("DEBUG", "True"))
 
+COMMIT_ID = os.environ.get("COMMIT_ID", "unknown")
+
 ADMINS = (
     # ('Your Name', 'your_email@example.com'),
 )
@@ -258,7 +260,7 @@ def strtobool(val) -> bool:
                 "django.template.context_processors.request",
                 "django.contrib.messages.context_processors.messages",
                 "grandchallenge.core.context_processors.challenge",
-                "grandchallenge.core.context_processors.google_keys",
+                "grandchallenge.core.context_processors.deployment_info",
                 "grandchallenge.core.context_processors.debug",
                 "grandchallenge.core.context_processors.sentry_dsn",
                 "grandchallenge.core.context_processors.policy_pages",
@@ -550,6 +552,7 @@ def strtobool(val) -> bool:
         CeleryIntegration(),
         RedisIntegration(),
     ],
+    release=COMMIT_ID,
 )
 
 REST_FRAMEWORK = {
diff --git a/app/grandchallenge/core/context_processors.py b/app/grandchallenge/core/context_processors.py
--- a/app/grandchallenge/core/context_processors.py
+++ b/app/grandchallenge/core/context_processors.py
@@ -33,10 +33,11 @@ def challenge(request):
     }
 
 
-def google_keys(*_, **__):
+def deployment_info(*_, **__):
     return {
         "google_analytics_id": settings.GOOGLE_ANALYTICS_ID,
         "geochart_api_key": settings.GOOGLE_MAPS_API_KEY,
+        "COMMIT_ID": settings.COMMIT_ID,
     }
 
 


Test patch:
Repository: comic/grand-challenge.org

Issue:
local variable 'file_origin' referenced before assignment
https://github.com/comic/grand-challenge.org/commit/e92de073dbf28a80d84075b9dc1c6d39d8cd5777#diff-06cfbdc71403fdb7de1ab89e3d50d139R214


Discussion:

Resolving patch:
diff --git a/app/grandchallenge/cases/image_builders/dicom.py b/app/grandchallenge/cases/image_builders/dicom.py
--- a/app/grandchallenge/cases/image_builders/dicom.py
+++ b/app/grandchallenge/cases/image_builders/dicom.py
@@ -187,6 +187,7 @@ def _process_dicom_file(dicom_ds):  # noqa: C901
         z_i = avg_origin_diff[2]
     except IndexError:
         z_i = 1.0
+
     for index, partial in enumerate(dicom_ds.headers):
         ds = pydicom.dcmread(str(partial["file"]))
 
@@ -211,8 +212,10 @@ def _process_dicom_file(dicom_ds):  # noqa: C901
 
     img = _create_sitk_image(dcm_array)
 
-    sitk_origin = ref_origin if z_i > 0.0 else tuple(file_origin)
-    z_i = np.abs(z_i)
+    if origin is None:
+        origin = (0.0, 0.0, 0.0)
+    sitk_origin = ref_origin if z_i >= 0.0 else tuple(origin)
+    z_i = np.abs(z_i) if not np.isnan(z_i) else 1.0
 
     if "PixelSpacing" in ref_file:
         x_i, y_i = (float(x) for x in ref_file.PixelSpacing)
@@ -233,7 +236,6 @@ def _process_dicom_file(dicom_ds):  # noqa: C901
         # Set Additional Meta Data
         img.SetMetaData("ContentTimes", " ".join(content_times))
         img.SetMetaData("Exposures", " ".join(exposures))
-
     # Convert the SimpleITK image to our internal representation
     return convert_itk_to_internal(img)
 


Test patch:
Repository: comic/grand-challenge.org

Issue:
Allow PatientID, PatientName and StudyDate through in metadata of mha/mhd,zraw
See title. This metadata is scrubbed of during import, but should stay, because it can be used by the ImageInfoPlugin


Discussion:

Resolving patch:
diff --git a/app/grandchallenge/cases/image_builders/metaio_utils.py b/app/grandchallenge/cases/image_builders/metaio_utils.py
--- a/app/grandchallenge/cases/image_builders/metaio_utils.py
+++ b/app/grandchallenge/cases/image_builders/metaio_utils.py
@@ -51,7 +51,16 @@
     r"(\s(2[0-3]|[0-1]\d)[0-5]\d[0-5]\d(\.\d\d\d)?)*$"
 )
 
+LENGTH_LIMIT_MATCH_REGEXP: Pattern = re.compile(r"^.{0,128}$")
+
+STUDYDATE_MATCH_REGEXP: Pattern = re.compile(r"^\d{4}\d{1,2}\d{1,2}$")
+
 ADDITIONAL_HEADERS: Dict[str, Pattern] = {
+    "PatientID": LENGTH_LIMIT_MATCH_REGEXP,
+    "PatientName": LENGTH_LIMIT_MATCH_REGEXP,
+    "StudyDate": STUDYDATE_MATCH_REGEXP,
+    "StudyInstanceUID": LENGTH_LIMIT_MATCH_REGEXP,
+    "SeriesInstanceUID": LENGTH_LIMIT_MATCH_REGEXP,
     "Exposures": FLOAT_LIST_MATCH_REGEXP,
     "ContentTimes": CONTENT_TIMES_LIST_MATCH_REGEXP,
     "t0": FLOAT_MATCH_REGEXP,


Test patch:
diff --git a/app/tests/cases_tests/resources/image10x10x10-extra-stuff.mhd b/app/tests/cases_tests/resources/image10x10x10-extra-stuff.mhd
--- a/app/tests/cases_tests/resources/image10x10x10-extra-stuff.mhd
+++ b/app/tests/cases_tests/resources/image10x10x10-extra-stuff.mhd
@@ -25,6 +25,12 @@ Some_values = "Huh? ✓😄"
 
 ElementDataFile = image10x10x10.zraw
 
+PatientID = 1234
+PatientName = ☺😄☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺☺
+StudyDate = 20020304
+StudyInstanceUID = 1.2.3.4
+SeriesInstanceUID = 1.2.3.4
+
 
 
 
@@ -32,4 +38,4 @@ this = should not be here
 and ignored
 altogether
 but = valid 
-yes = 1
\ No newline at end of file
+yes = 1
diff --git a/app/tests/cases_tests/resources/image10x11x12x13-extra-stuff.mhd b/app/tests/cases_tests/resources/image10x11x12x13-extra-stuff.mhd
--- a/app/tests/cases_tests/resources/image10x11x12x13-extra-stuff.mhd
+++ b/app/tests/cases_tests/resources/image10x11x12x13-extra-stuff.mhd
@@ -11,6 +11,11 @@ ElementSpacing = 0.429 0.429 0.5 1
 DimSize = 10 11 12 13
 AnatomicalOrientation = RAI
 ElementType = MET_UCHAR
+PatientID = 1234
+PatientName = Patient 1234
+StudyDate = 20020304
+StudyInstanceUID = 1.2.3.4
+SeriesInstanceUID = 1.2.3.4
 ContentTimes = 000000.000 111111.111 121212.333 121213 121214 121215 121216 121217 121218 121219 121220 121221 235959.999
 Exposures = 1 2 3e-5 4 5.2 6 7 8 9 10 11 12 13.0
 t0 = 12.5
diff --git a/app/tests/cases_tests/resources/image3x4-extra-stuff.mhd b/app/tests/cases_tests/resources/image3x4-extra-stuff.mhd
--- a/app/tests/cases_tests/resources/image3x4-extra-stuff.mhd
+++ b/app/tests/cases_tests/resources/image3x4-extra-stuff.mhd
@@ -17,4 +17,9 @@ Exposures = 100.2
 t0 = 12.5
 t1 = 1.2e-6
 Bogus = nonsense 1234
+PatientID = 1234
+PatientName = Patient 1234
+StudyDate = 20020304
+StudyInstanceUID = 1.2.3.4
+SeriesInstanceUID = 1.2.3.4
 ElementDataFile = image3x4.zraw
Repository: comic/grand-challenge.org

Issue:
Workstation names are blank in dropdown
Update a reader study or algorithm, blank choices for workstations.


Discussion:

Resolving patch:
diff --git a/app/grandchallenge/workstations/models.py b/app/grandchallenge/workstations/models.py
--- a/app/grandchallenge/workstations/models.py
+++ b/app/grandchallenge/workstations/models.py
@@ -90,7 +90,8 @@ def latest_ready_image(self):
         )
 
     def __str__(self):
-        return f"Workstation {self.title}" + " (Public)" if self.public else ""
+        public = " (Public)" if self.public else ""
+        return f"Workstation {self.title}{public}"
 
     def get_absolute_url(self):
         return reverse("workstations:detail", kwargs={"slug": self.slug})


Test patch:
Repository: comic/grand-challenge.org

Issue:
Zip of DICOMs fail with long filenames
In the zip unpacking the folder names are prepended to the filenames, which results in a filename being too long to store in the db.



Discussion:

Resolving patch:
diff --git a/app/grandchallenge/cases/tasks.py b/app/grandchallenge/cases/tasks.py
--- a/app/grandchallenge/cases/tasks.py
+++ b/app/grandchallenge/cases/tasks.py
@@ -229,7 +229,7 @@ def fix_mhd_file(file, prefix):
         pass
 
 
-def extract_and_flatten(file, path, prefix=None, is_tar=False):
+def extract_and_flatten(file, path, prefix="", is_tar=False):
     """
     Extracts a flattened list of all files in `file` to `path`.
 
@@ -255,9 +255,12 @@ def extract_and_flatten(file, path, prefix=None, is_tar=False):
             continue
         # For any file that is inside a directory, prepend the directory
         # name(s) to the filename
-        _filename = re.sub(r"[/:?]", "-", filename)
+        _filename = "-".join(Path(filename).parts[-2:])
         base_name = os.path.basename(filename)
-        setattr(info, filename_attr, (prefix or "") + _filename)
+        _prefix = _filename.replace(base_name, "")
+        setattr(
+            info, filename_attr, (prefix if not _prefix else "") + _filename
+        )
         file.extract(info, path)
         filename = getattr(info, filename_attr)
         new_files.append(


Test patch:
diff --git a/app/tests/cases_tests/test_background_tasks.py b/app/tests/cases_tests/test_background_tasks.py
--- a/app/tests/cases_tests/test_background_tasks.py
+++ b/app/tests/cases_tests/test_background_tasks.py
@@ -347,17 +347,11 @@ def test_extract_and_flatten(tmpdir, file_name, func, is_tar):
 
     expected = [
         {"prefix": "folder-0-", "path": tmpdir_path / "folder-0-file-0.txt"},
+        {"prefix": "folder-1-", "path": tmpdir_path / "folder-1-file-1.txt"},
+        {"prefix": "folder-2-", "path": tmpdir_path / "folder-2-file-2.txt"},
         {
-            "prefix": "folder-0-folder-1-",
-            "path": tmpdir_path / "folder-0-folder-1-file-1.txt",
-        },
-        {
-            "prefix": "folder-0-folder-1-folder-2-",
-            "path": tmpdir_path / "folder-0-folder-1-folder-2-file-2.txt",
-        },
-        {
-            "prefix": "folder-0-folder-1-folder-2-",
-            "path": tmpdir_path / "folder-0-folder-1-folder-2-folder-3.zip",
+            "prefix": "folder-2-",
+            "path": tmpdir_path / "folder-2-folder-3.zip",
         },
     ]
     assert sorted(new_files, key=lambda k: k["path"]) == expected
@@ -378,11 +372,10 @@ def test_check_compressed_and_extract(tmpdir, file_name):
 
     expected = [
         "folder-0-file-0.txt",
-        "folder-0-folder-1-file-1.txt",
-        "folder-0-folder-1-folder-2-file-2.txt",
-        "folder-0-folder-1-folder-2-folder-3-file-3.txt",
+        "folder-1-file-1.txt",
+        "folder-2-file-2.txt",
+        "folder-3-file-3.txt",
     ]
-
     assert sorted([x.name for x in tmpdir_path.iterdir()]) == expected