Commit e5a43799 authored by John L. Villalovos's avatar John L. Villalovos Committed by Nejc Habjan
Browse files

fix(cli): generate UserWarning if `list` does not return all entries

Previously in the CLI, calls to `list()` would have `get_all=False` by
default. Therefore hiding the fact that not all items are being
returned if there were more than 20 items.

Added `--no-get-all` option to `list` actions. Along with the already
existing `--get-all`.

Closes: #2900
parent 7d04315d
Loading
Loading
Loading
Loading
+17 −3
Original line number Diff line number Diff line
@@ -869,6 +869,7 @@ class Gitlab:
        query_data: Optional[Dict[str, Any]] = None,
        *,
        iterator: Optional[bool] = None,
        message_details: Optional[utils.WarnMessageData] = None,
        **kwargs: Any,
    ) -> Union["GitlabList", List[Dict[str, Any]]]:
        """Make a GET request to the Gitlab server for list-oriented queries.
@@ -952,7 +953,16 @@ class Gitlab:
        # 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(
        if message_details is not None:
            message = message_details.message.format_map(
                {
                    "len_items": len(items),
                    "per_page": gl_list.per_page,
                    "total_items": total_items,
                }
            )
            show_caller = message_details.show_caller
        else:
            message = (
                f"Calling a `list()` method without specifying `get_all=True` or "
                f"`iterator=True` will return a maximum of {gl_list.per_page} items. "
@@ -960,8 +970,12 @@ class Gitlab:
                f"{_PAGINATION_URL} for more details. If this was done intentionally, "
                f"then this warning can be supressed by adding the argument "
                f"`get_all=False` to the `list()` call."
            ),
            )
            show_caller = True
        utils.warn(
            message=message,
            category=UserWarning,
            show_caller=show_caller,
        )
        return items

+7 −0
Original line number Diff line number Diff line
import dataclasses
import email.message
import logging
import pathlib
@@ -205,3 +206,9 @@ def warn(
        stacklevel=stacklevel,
        source=source,
    )


@dataclasses.dataclass
class WarnMessageData:
    message: str
    show_caller: bool
+25 −7
Original line number Diff line number Diff line
import argparse
import json
import operator
import sys
from typing import Any, Dict, List, Optional, Type, TYPE_CHECKING, Union
@@ -140,8 +141,16 @@ class GitlabCLI:
    ) -> Union[gitlab.base.RESTObjectList, List[gitlab.base.RESTObject]]:
        if TYPE_CHECKING:
            assert isinstance(self.mgr, gitlab.mixins.ListMixin)
        message_details = gitlab.utils.WarnMessageData(
            message=(
                "Your query returned {len_items} of {total_items} items. To return all "
                "items use `--get-all`. To silence this warning use `--no-get-all`."
            ),
            show_caller=False,
        )

        try:
            result = self.mgr.list(**self.args)
            result = self.mgr.list(**self.args, message_details=message_details)
        except Exception as e:  # pragma: no cover, cli.die is unit-tested
            cli.die("Impossible to list objects", e)
        return result
@@ -238,12 +247,25 @@ def _populate_sub_parser_by_class(

            sub_parser_action.add_argument("--page", required=False, type=int)
            sub_parser_action.add_argument("--per-page", required=False, type=int)
            sub_parser_action.add_argument(
            get_all_group = sub_parser_action.add_mutually_exclusive_group()
            get_all_group.add_argument(
                "--get-all",
                required=False,
                action="store_true",
                action="store_const",
                const=True,
                default=None,
                dest="get_all",
                help="Return all items from the server, without pagination.",
            )
            get_all_group.add_argument(
                "--no-get-all",
                required=False,
                action="store_const",
                const=False,
                default=None,
                dest="get_all",
                help="Don't return all items from the server.",
            )

        if action_name == "delete":
            if cls._id_attr is not None:
@@ -416,8 +438,6 @@ def get_dict(
class JSONPrinter:
    @staticmethod
    def display(d: Union[str, Dict[str, Any]], **_kwargs: Any) -> None:
        import json  # noqa

        print(json.dumps(d))

    @staticmethod
@@ -426,8 +446,6 @@ class JSONPrinter:
        fields: List[str],
        **_kwargs: Any,
    ) -> None:
        import json  # noqa

        print(json.dumps([get_dict(obj, fields) for obj in data]))