From 6fcf3b68be095e614b969f5922ad8a67978cd4db Mon Sep 17 00:00:00 2001 From: Shreya Date: Sat, 29 Oct 2022 00:54:57 +0530 Subject: [PATCH] feat(api): add application statistics --- docs/api-objects.rst | 1 + docs/gl_objects/statistics.rst | 21 +++++++++++ gitlab/client.py | 2 + gitlab/v4/objects/statistics.py | 14 +++++++ tests/functional/api/test_statistics.py | 12 ++++++ tests/functional/conftest.py | 13 ++++++- tests/unit/objects/test_statistics.py | 49 +++++++++++++++++++++++++ 7 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 docs/gl_objects/statistics.rst create mode 100644 tests/functional/api/test_statistics.py create mode 100644 tests/unit/objects/test_statistics.py diff --git a/docs/api-objects.rst b/docs/api-objects.rst index 349b7cf83..c02505621 100644 --- a/docs/api-objects.rst +++ b/docs/api-objects.rst @@ -54,6 +54,7 @@ API examples gl_objects/search gl_objects/settings gl_objects/snippets + gl_objects/statistics gl_objects/system_hooks gl_objects/templates gl_objects/todos diff --git a/docs/gl_objects/statistics.rst b/docs/gl_objects/statistics.rst new file mode 100644 index 000000000..d1d72eb9e --- /dev/null +++ b/docs/gl_objects/statistics.rst @@ -0,0 +1,21 @@ +########## +Statistics +########## + +Reference +--------- + +* v4 API: + + + :class:`gitlab.v4.objects.ApplicationStatistics` + + :class:`gitlab.v4.objects.ApplicationStatisticsManager` + + :attr:`gitlab.Gitlab.statistics` + +* GitLab API: https://docs.gitlab.com/ee/api/statistics.html + +Examples +-------- + +Get the statistics:: + + statistics = gl.statistics.get() diff --git a/gitlab/client.py b/gitlab/client.py index 6e81f6acb..9814fa2b1 100644 --- a/gitlab/client.py +++ b/gitlab/client.py @@ -188,6 +188,8 @@ def __init__( """See :class:`~gitlab.v4.objects.PersonalAccessTokenManager`""" self.topics = objects.TopicManager(self) """See :class:`~gitlab.v4.objects.TopicManager`""" + self.statistics = objects.ApplicationStatisticsManager(self) + """See :class:`~gitlab.v4.objects.ApplicationStatisticsManager`""" def __enter__(self) -> "Gitlab": return self diff --git a/gitlab/v4/objects/statistics.py b/gitlab/v4/objects/statistics.py index 1de963e0c..ce4dc3a25 100644 --- a/gitlab/v4/objects/statistics.py +++ b/gitlab/v4/objects/statistics.py @@ -13,6 +13,8 @@ "IssuesStatisticsManager", "ProjectIssuesStatistics", "ProjectIssuesStatisticsManager", + "ApplicationStatistics", + "ApplicationStatisticsManager", ] @@ -71,3 +73,15 @@ class ProjectIssuesStatisticsManager(GetWithoutIdMixin, RESTManager): def get(self, **kwargs: Any) -> ProjectIssuesStatistics: return cast(ProjectIssuesStatistics, super().get(**kwargs)) + + +class ApplicationStatistics(RESTObject): + _id_attr = None + + +class ApplicationStatisticsManager(GetWithoutIdMixin, RESTManager): + _path = "/application/statistics" + _obj_cls = ApplicationStatistics + + def get(self, **kwargs: Any) -> ApplicationStatistics: + return cast(ApplicationStatistics, super().get(**kwargs)) diff --git a/tests/functional/api/test_statistics.py b/tests/functional/api/test_statistics.py new file mode 100644 index 000000000..ee0f4a96e --- /dev/null +++ b/tests/functional/api/test_statistics.py @@ -0,0 +1,12 @@ +""" +GitLab API: https://docs.gitlab.com/ee/api/statistics.html +""" + + +def test_get_statistics(gl): + statistics = gl.statistics.get() + + assert statistics.snippets.isdigit() + assert statistics.users.isdigit() + assert statistics.groups.isdigit() + assert statistics.projects.isdigit() diff --git a/tests/functional/conftest.py b/tests/functional/conftest.py index b75a1e168..d2ff5e0ab 100644 --- a/tests/functional/conftest.py +++ b/tests/functional/conftest.py @@ -94,7 +94,18 @@ def reset_gitlab(gl: gitlab.Gitlab) -> None: helpers.safe_delete(deploy_token) logging.info(f"Deleting project: {project.path_with_namespace!r}") helpers.safe_delete(project) + for group in gl.groups.list(): + + # skip deletion of a descendant group to prevent scenarios where parent group + # gets deleted leaving a dangling descendant whose deletion will throw 404s. + if group.parent_id: + logging.info( + f"Skipping deletion of {group.full_path} as it is a descendant " + f"group and will be removed when the parent group is deleted" + ) + continue + for deploy_token in group.deploytokens.list(): logging.info( f"Deleting deploy token: {deploy_token.username!r} in " @@ -110,7 +121,7 @@ def reset_gitlab(gl: gitlab.Gitlab) -> None: logging.info(f"Deleting variable: {variable.key!r}") helpers.safe_delete(variable) for user in gl.users.list(): - if user.username != "root": + if user.username not in ["root", "ghost"]: logging.info(f"Deleting user: {user.username!r}") helpers.safe_delete(user, hard_delete=True) diff --git a/tests/unit/objects/test_statistics.py b/tests/unit/objects/test_statistics.py new file mode 100644 index 000000000..a65b6e1ed --- /dev/null +++ b/tests/unit/objects/test_statistics.py @@ -0,0 +1,49 @@ +""" +GitLab API: https://docs.gitlab.com/ee/api/statistics.html +""" + +import pytest +import responses + +content = { + "forks": "10", + "issues": "76", + "merge_requests": "27", + "notes": "954", + "snippets": "50", + "ssh_keys": "10", + "milestones": "40", + "users": "50", + "groups": "10", + "projects": "20", + "active_users": "50", +} + + +@pytest.fixture +def resp_application_statistics(): + + with responses.RequestsMock() as rsps: + rsps.add( + method=responses.GET, + url="http://localhost/api/v4/application/statistics", + json=content, + content_type="application/json", + status=200, + ) + + yield rsps + + +def test_get_statistics(gl, resp_application_statistics): + statistics = gl.statistics.get() + assert statistics.forks == content["forks"] + assert statistics.merge_requests == content["merge_requests"] + assert statistics.notes == content["notes"] + assert statistics.snippets == content["snippets"] + assert statistics.ssh_keys == content["ssh_keys"] + assert statistics.milestones == content["milestones"] + assert statistics.users == content["users"] + assert statistics.groups == content["groups"] + assert statistics.projects == content["projects"] + assert statistics.active_users == content["active_users"]