Skip to content

Commit 652a522

Browse files
authored
Add missing 'filter_roles' to Search index_list (#1376)
2 parents 202c07c + 352468a commit 652a522

3 files changed

Lines changed: 78 additions & 2 deletions

File tree

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Added
2+
-----
3+
4+
- Added support for ``filter_roles`` as a parameter to ``SearchClient.index_list``. (:pr:`NUMBER`)

src/globus_sdk/services/search/client.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,28 @@
11
from __future__ import annotations
22

33
import logging
4+
import sys
45
import typing as t
56
import uuid
67

78
from globus_sdk import client, paging, response
8-
from globus_sdk._internal.remarshal import strseq_listify
9+
from globus_sdk._internal.remarshal import commajoin, strseq_listify
910
from globus_sdk._missing import MISSING, MissingType
1011
from globus_sdk.scopes import SearchScopes
1112

1213
from .data import SearchQueryV1, SearchScrollQuery
1314
from .errors import SearchAPIError
1415
from .response import IndexListResponse
1516

17+
if sys.version_info >= (3, 10):
18+
from typing import TypeAlias
19+
else:
20+
from typing_extensions import TypeAlias
21+
1622
log = logging.getLogger(__name__)
1723

24+
_VALID_ROLE_NAMES_T: TypeAlias = t.Literal["owner", "admin", "writer"]
25+
1826

1927
class SearchClient(client.BaseClient):
2028
r"""
@@ -229,12 +237,18 @@ def get_index(
229237

230238
def index_list(
231239
self,
240+
filter_roles: (
241+
_VALID_ROLE_NAMES_T | t.Iterable[_VALID_ROLE_NAMES_T] | MissingType
242+
) = MISSING,
232243
*,
233244
query_params: dict[str, t.Any] | None = None,
234245
) -> response.IterableResponse:
235246
"""
236247
Get a list of indices on which the caller has permissions.
237248
249+
:param filter_roles: An iterable of roles to use to filter the listing. By
250+
default, all indices where the user has a role are returned.
251+
Valid values are ``owner``, ``admin``, and ``writer``.
238252
:param query_params: additional parameters to pass as query params
239253
240254
.. tab-set::
@@ -260,6 +274,7 @@ def index_list(
260274
:ref: search/reference/index_list/
261275
""" # noqa: E501
262276
log.debug("SearchClient.index_list()")
277+
query_params = {"filter_roles": commajoin(filter_roles), **(query_params or {})}
263278
return IndexListResponse(self.get("/v1/index_list", query_params=query_params))
264279

265280
#

tests/functional/services/search/test_index_list.py

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
from globus_sdk.testing import load_response
1+
import dataclasses
2+
import urllib.parse
3+
4+
import pytest
5+
6+
from globus_sdk._missing import MISSING
7+
from globus_sdk.testing import get_last_request, load_response
28

39

410
def test_search_index_list(client):
@@ -24,3 +30,54 @@ def test_search_index_list_is_iterable(client):
2430
index_list = list(res)
2531
assert len(index_list) == len(index_ids)
2632
assert [i["id"] for i in index_list] == index_ids
33+
34+
35+
_OMIT = object()
36+
37+
38+
@dataclasses.dataclass
39+
class FilterRoleParam:
40+
name: str
41+
value: object
42+
expect_parsed_param: object = None
43+
44+
@property
45+
def missing(self) -> bool:
46+
return self.value in (_OMIT, MISSING)
47+
48+
@property
49+
def call_kwargs(self) -> dict[str, object]:
50+
return {} if self.value is _OMIT else {"filter_roles": self.value}
51+
52+
def __str__(self) -> str:
53+
return self.name
54+
55+
56+
@pytest.mark.parametrize(
57+
"filter_param",
58+
[
59+
FilterRoleParam("omitted", _OMIT),
60+
FilterRoleParam("missing", MISSING),
61+
FilterRoleParam("ownerstr", "owner", ["owner"]),
62+
FilterRoleParam("adminstr", "admin", ["admin"]),
63+
FilterRoleParam("writerstr", "writer", ["writer"]),
64+
FilterRoleParam("tuple", ("owner", "admin"), ["owner,admin"]),
65+
FilterRoleParam("list", ["admin", "writer"], ["admin,writer"]),
66+
FilterRoleParam("duplicates", ("admin", "admin"), ["admin,admin"]),
67+
# this isn't a real role, but it should be passed through as though it were
68+
# -- this value can be a typing time error but never a runtime error
69+
FilterRoleParam("unknown_str", "ambassador", ["ambassador"]),
70+
],
71+
ids=str,
72+
)
73+
def test_search_index_list_encodes_filter_roles_as_expected(client, filter_param):
74+
load_response(client.index_list).metadata
75+
res = client.index_list(**filter_param.call_kwargs)
76+
assert res.http_status == 200
77+
78+
req = get_last_request()
79+
parsed_qs = urllib.parse.parse_qs(urllib.parse.urlparse(req.url).query)
80+
if filter_param.missing:
81+
assert "filter_roles" not in parsed_qs
82+
else:
83+
assert parsed_qs["filter_roles"] == filter_param.expect_parsed_param

0 commit comments

Comments
 (0)