summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShreya <a.shreya202@gmail.com>2022-10-29 00:54:57 +0530
committerNejc Habjan <nejc.habjan@siemens.com>2022-11-01 09:59:05 +0100
commit6fcf3b68be095e614b969f5922ad8a67978cd4db (patch)
treee567469a20428d43c9e1d5a6f95f5da19ecb6cb3
parentbd82d745c8ea9ff6ff078a4c961a2d6e64a2f63c (diff)
downloadgitlab-6fcf3b68be095e614b969f5922ad8a67978cd4db.tar.gz
feat(api): add application statistics
-rw-r--r--docs/api-objects.rst1
-rw-r--r--docs/gl_objects/statistics.rst21
-rw-r--r--gitlab/client.py2
-rw-r--r--gitlab/v4/objects/statistics.py14
-rw-r--r--tests/functional/api/test_statistics.py12
-rw-r--r--tests/functional/conftest.py13
-rw-r--r--tests/unit/objects/test_statistics.py49
7 files changed, 111 insertions, 1 deletions
diff --git a/docs/api-objects.rst b/docs/api-objects.rst
index 349b7cf..c025056 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 0000000..d1d72eb
--- /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 6e81f6a..9814fa2 100644
--- a/gitlab/client.py
+++ b/gitlab/client.py
@@ -188,6 +188,8 @@ class Gitlab:
"""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 1de963e..ce4dc3a 100644
--- a/gitlab/v4/objects/statistics.py
+++ b/gitlab/v4/objects/statistics.py
@@ -13,6 +13,8 @@ __all__ = [
"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 0000000..ee0f4a9
--- /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 b75a1e1..d2ff5e0 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 0000000..a65b6e1
--- /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"]