diff options
Diffstat (limited to 'gitlab/client.py')
-rw-r--r-- | gitlab/client.py | 62 |
1 files changed, 54 insertions, 8 deletions
diff --git a/gitlab/client.py b/gitlab/client.py index c6ac0d1..73a0a5c 100644 --- a/gitlab/client.py +++ b/gitlab/client.py @@ -24,6 +24,7 @@ import requests import requests.utils from requests_toolbelt.multipart.encoder import MultipartEncoder # type: ignore +import gitlab import gitlab.config import gitlab.const import gitlab.exceptions @@ -37,6 +38,12 @@ REDIRECT_MSG = ( RETRYABLE_TRANSIENT_ERROR_CODES = [500, 502, 503, 504] + list(range(520, 531)) +# https://docs.gitlab.com/ee/api/#offset-based-pagination +_PAGINATION_URL = ( + f"https://python-gitlab.readthedocs.io/en/v{gitlab.__version__}/" + f"api-usage.html#pagination" +) + class Gitlab: """Represents a GitLab server connection. @@ -826,20 +833,59 @@ class Gitlab: # In case we want to change the default behavior at some point as_list = True if as_list is None else as_list - get_all = kwargs.pop("all", False) + get_all = kwargs.pop("all", None) url = self._build_url(path) page = kwargs.get("page") - if get_all is True and as_list is True: - return list(GitlabList(self, url, query_data, **kwargs)) + if as_list is False: + # Generator requested + return GitlabList(self, url, query_data, **kwargs) - if page or as_list is True: - # pagination requested, we return a list - return list(GitlabList(self, url, query_data, get_next=False, **kwargs)) + if get_all is True: + return list(GitlabList(self, url, query_data, **kwargs)) - # No pagination, generator requested - return GitlabList(self, url, query_data, **kwargs) + # pagination requested, we return a list + gl_list = GitlabList(self, url, query_data, get_next=False, **kwargs) + items = list(gl_list) + + def should_emit_warning() -> bool: + # No warning is emitted if any of the following conditions apply: + # * `all=False` was set in the `list()` call. + # * `page` was set in the `list()` call. + # * GitLab did not return the `x-per-page` header. + # * Number of items received is less than per-page value. + # * Number of items received is >= total available. + if get_all is False: + return False + if page is not None: + return False + if gl_list.per_page is None: + return False + if len(items) < gl_list.per_page: + return False + if gl_list.total is not None and len(items) >= gl_list.total: + return False + return True + + if not should_emit_warning(): + return items + + # Warn the user that they are only going to retrieve `per_page` + # maximum items. This is a common cause of issues filed. + total_items = "many" if gl_list.total is None else gl_list.total + utils.warn( + message=( + f"Calling a `list()` method without specifying `all=True` or " + f"`as_list=False` will return a maximum of {gl_list.per_page} items. " + f"Your query returned {len(items)} of {total_items} items. See " + f"{_PAGINATION_URL} for more details. If this was done intentionally, " + f"then this warning can be supressed by adding the argument " + f"`all=False` to the `list()` call." + ), + category=UserWarning, + ) + return items def http_post( self, |