Repository: pulp/pulpcore

Issue:
pulp_href__in filter doesn't handle empty set properly
We make use of the `pulp_href__in` filter and it works great. We store pulp hrefs for some various things and we can easily look up the resources in pulp using this filter.

There is an edge case that I don't think it's properly handling though. It certain cases, the set will be empty and when we pass that to pulp, it seems that *all* results get returned. I think that *no* results should instead be returned.

Current behavior:

```
$ http :8080/pulp/api/v3/repositories/ pulp_href__in==
{
    "count": 1,
    "next": null,
    "previous": null,
    "results": [
        {
            "description": null,
            "latest_version_href": "/pulp/api/v3/repositories/deb/apt/1cc3ba78-bbf6-4373-b742-725785f010be/versions/0/",
            "name": "pmc_cli_test_repo_8fa0535e-c76f-4a60-8c1d-257290ec88c2",
            "pulp_created": "2023-09-18T12:46:41.212285Z",
            "pulp_href": "/pulp/api/v3/repositories/deb/apt/1cc3ba78-bbf6-4373-b742-725785f010be/",
            "pulp_labels": {},
            "remote": null,
            "retain_repo_versions": null,
            "versions_href": "/pulp/api/v3/repositories/deb/apt/1cc3ba78-bbf6-4373-b742-725785f010be/versions/"
        }
    ]
}
```

Expected behavior:

No results (ie `[]`) get returned.



Discussion:
Looks like the problem is with django-filter: https://github.com/carltongibson/django-filter/issues/1609

Resolving patch:
diff --git a/pulpcore/filters.py b/pulpcore/filters.py
--- a/pulpcore/filters.py
+++ b/pulpcore/filters.py
@@ -124,11 +124,19 @@ def filter(self, qs, value):
 
 
 class IdInFilter(BaseInFilter, filters.UUIDFilter):
-    pass
+    def filter(self, qs, value):
+        if value is None:
+            return qs
+        return qs.filter(pk__in=value)
 
 
 class HREFInFilter(BaseInFilter, filters.CharFilter):
-    pass
+    def filter(self, qs, value):
+        if value is None:
+            return qs
+
+        pks = [extract_pk(href) for href in value]
+        return qs.filter(pk__in=pks)
 
 
 class PulpTypeFilter(filters.ChoiceFilter):
@@ -270,8 +278,8 @@ class BaseFilterSet(filterset.FilterSet):
     """
 
     help_text = {}
-    pulp_id__in = IdInFilter(field_name="pk", lookup_expr="in")
-    pulp_href__in = HREFInFilter(field_name="pk", method="filter_pulp_href")
+    pulp_id__in = IdInFilter(field_name="pk")
+    pulp_href__in = HREFInFilter(field_name="pk")
     q = ExpressionFilter()
 
     FILTER_DEFAULTS = {
@@ -307,11 +315,6 @@ class BaseFilterSet(filterset.FilterSet):
         "ne": _("not equal to"),
     }
 
-    def filter_pulp_href(self, queryset, name, value):
-        # Convert each href to a pk
-        pks = [extract_pk(href) for href in value]
-        return queryset.filter(pk__in=pks)
-
     @classmethod
     def get_filters(cls):
         filters = super().get_filters()


Test patch:
diff --git a/pulpcore/tests/functional/api/test_filter.py b/pulpcore/tests/functional/api/test_filter.py
--- a/pulpcore/tests/functional/api/test_filter.py
+++ b/pulpcore/tests/functional/api/test_filter.py
@@ -87,6 +87,10 @@ def test_pulp_id_href_filter(
         redi_results = redirect_contentguard_api_client.list(**{filter: rbac_sample})
         assert redi_results.count == 0
 
+        # test out empty list
+        redi_results = redirect_contentguard_api_client.list(**{filter: []})
+        assert redi_results.count == 0
+
         # Test that filter fails when not a valid type
         with pytest.raises(ApiException) as exc:
             content_guards_api_client.list(**{filter: ["hello"]})