-
Notifications
You must be signed in to change notification settings - Fork 35
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add tests for paginator signature matching (#779)
These tests enforce that decorated methods of the target client classes satisfy the paginator interfaces for their decorators. For example, if a method is decorated with the MarkerPaginator, then it must take a named argument `marker` for the paginator to use. It's acceptable for the argument to be keyword-only or for it to be positional-or-keyword. But it's not acceptable for it to be, e.g., positional-only.
- Loading branch information
Showing
1 changed file
with
81 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
""" | ||
Inspect the signatures of paginated methods and compare them against their | ||
attached paginator requirements. | ||
""" | ||
import inspect | ||
|
||
import pytest | ||
|
||
import globus_sdk | ||
from globus_sdk.paging import ( | ||
HasNextPaginator, | ||
LastKeyPaginator, | ||
LimitOffsetTotalPaginator, | ||
MarkerPaginator, | ||
NextTokenPaginator, | ||
NullableMarkerPaginator, | ||
) | ||
|
||
_CLIENTS_TO_CHECK = ( | ||
# alphabetical by service name | ||
# Auth | ||
globus_sdk.AuthClient, | ||
globus_sdk.NativeAppAuthClient, | ||
globus_sdk.ConfidentialAppAuthClient, | ||
# Flows | ||
globus_sdk.FlowsClient, | ||
globus_sdk.SpecificFlowClient, | ||
# GCS | ||
globus_sdk.GCSClient, | ||
# Groups | ||
globus_sdk.GroupsClient, | ||
# Search | ||
globus_sdk.SearchClient, | ||
# Timers | ||
globus_sdk.TimerClient, | ||
# Transfer | ||
globus_sdk.TransferClient, | ||
) | ||
|
||
_METHODS_TO_CHECK = [] | ||
for cls in _CLIENTS_TO_CHECK: | ||
methods = inspect.getmembers(cls, predicate=inspect.isfunction) | ||
for name, value in methods: | ||
if name.startswith("_"): | ||
continue | ||
# inherited, non-overloaded methods | ||
if name not in cls.__dict__: | ||
continue | ||
if getattr(value, "_has_paginator", False): | ||
_METHODS_TO_CHECK.append(value) | ||
|
||
|
||
@pytest.mark.parametrize("method", _METHODS_TO_CHECK) | ||
def test_paginated_method_matches_paginator_requirements(method): | ||
paginator_class = method._paginator_class | ||
|
||
sig = inspect.signature(method) | ||
kwarg_names = { | ||
p.name | ||
for p in sig.parameters.values() | ||
if p.kind in (p.POSITIONAL_OR_KEYWORD, p.KEYWORD_ONLY) | ||
} | ||
|
||
if ( | ||
paginator_class is HasNextPaginator | ||
or paginator_class is LimitOffsetTotalPaginator | ||
): | ||
expect_params = ("limit", "offset") | ||
elif ( | ||
paginator_class is MarkerPaginator or paginator_class is NullableMarkerPaginator | ||
): | ||
expect_params = ("marker",) | ||
elif paginator_class is LastKeyPaginator: | ||
expect_params = ("last_key",) | ||
elif paginator_class is NextTokenPaginator: | ||
expect_params = ("next_token",) | ||
else: | ||
raise NotImplementedError(f"unrecognized paginator class: {paginator_class}") | ||
|
||
for param_name in expect_params: | ||
assert param_name in kwarg_names, method.__qualname__ |