Skip to content

Commit 31ec146

Browse files
authored
Merge pull request #2347 from Shreya-7/issue-2264-add-application-statistics
feat(api): add application statistics
2 parents bd82d74 + 6fcf3b6 commit 31ec146

File tree

7 files changed

+111
-1
lines changed

7 files changed

+111
-1
lines changed

docs/api-objects.rst

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ API examples
5454
gl_objects/search
5555
gl_objects/settings
5656
gl_objects/snippets
57+
gl_objects/statistics
5758
gl_objects/system_hooks
5859
gl_objects/templates
5960
gl_objects/todos

docs/gl_objects/statistics.rst

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
##########
2+
Statistics
3+
##########
4+
5+
Reference
6+
---------
7+
8+
* v4 API:
9+
10+
+ :class:`gitlab.v4.objects.ApplicationStatistics`
11+
+ :class:`gitlab.v4.objects.ApplicationStatisticsManager`
12+
+ :attr:`gitlab.Gitlab.statistics`
13+
14+
* GitLab API: https://docs.gitlab.com/ee/api/statistics.html
15+
16+
Examples
17+
--------
18+
19+
Get the statistics::
20+
21+
statistics = gl.statistics.get()

gitlab/client.py

+2
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,8 @@ def __init__(
188188
"""See :class:`~gitlab.v4.objects.PersonalAccessTokenManager`"""
189189
self.topics = objects.TopicManager(self)
190190
"""See :class:`~gitlab.v4.objects.TopicManager`"""
191+
self.statistics = objects.ApplicationStatisticsManager(self)
192+
"""See :class:`~gitlab.v4.objects.ApplicationStatisticsManager`"""
191193

192194
def __enter__(self) -> "Gitlab":
193195
return self

gitlab/v4/objects/statistics.py

+14
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
"IssuesStatisticsManager",
1414
"ProjectIssuesStatistics",
1515
"ProjectIssuesStatisticsManager",
16+
"ApplicationStatistics",
17+
"ApplicationStatisticsManager",
1618
]
1719

1820

@@ -71,3 +73,15 @@ class ProjectIssuesStatisticsManager(GetWithoutIdMixin, RESTManager):
7173

7274
def get(self, **kwargs: Any) -> ProjectIssuesStatistics:
7375
return cast(ProjectIssuesStatistics, super().get(**kwargs))
76+
77+
78+
class ApplicationStatistics(RESTObject):
79+
_id_attr = None
80+
81+
82+
class ApplicationStatisticsManager(GetWithoutIdMixin, RESTManager):
83+
_path = "/application/statistics"
84+
_obj_cls = ApplicationStatistics
85+
86+
def get(self, **kwargs: Any) -> ApplicationStatistics:
87+
return cast(ApplicationStatistics, super().get(**kwargs))
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
"""
2+
GitLab API: https://docs.gitlab.com/ee/api/statistics.html
3+
"""
4+
5+
6+
def test_get_statistics(gl):
7+
statistics = gl.statistics.get()
8+
9+
assert statistics.snippets.isdigit()
10+
assert statistics.users.isdigit()
11+
assert statistics.groups.isdigit()
12+
assert statistics.projects.isdigit()

tests/functional/conftest.py

+12-1
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,18 @@ def reset_gitlab(gl: gitlab.Gitlab) -> None:
9494
helpers.safe_delete(deploy_token)
9595
logging.info(f"Deleting project: {project.path_with_namespace!r}")
9696
helpers.safe_delete(project)
97+
9798
for group in gl.groups.list():
99+
100+
# skip deletion of a descendant group to prevent scenarios where parent group
101+
# gets deleted leaving a dangling descendant whose deletion will throw 404s.
102+
if group.parent_id:
103+
logging.info(
104+
f"Skipping deletion of {group.full_path} as it is a descendant "
105+
f"group and will be removed when the parent group is deleted"
106+
)
107+
continue
108+
98109
for deploy_token in group.deploytokens.list():
99110
logging.info(
100111
f"Deleting deploy token: {deploy_token.username!r} in "
@@ -110,7 +121,7 @@ def reset_gitlab(gl: gitlab.Gitlab) -> None:
110121
logging.info(f"Deleting variable: {variable.key!r}")
111122
helpers.safe_delete(variable)
112123
for user in gl.users.list():
113-
if user.username != "root":
124+
if user.username not in ["root", "ghost"]:
114125
logging.info(f"Deleting user: {user.username!r}")
115126
helpers.safe_delete(user, hard_delete=True)
116127

tests/unit/objects/test_statistics.py

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
"""
2+
GitLab API: https://docs.gitlab.com/ee/api/statistics.html
3+
"""
4+
5+
import pytest
6+
import responses
7+
8+
content = {
9+
"forks": "10",
10+
"issues": "76",
11+
"merge_requests": "27",
12+
"notes": "954",
13+
"snippets": "50",
14+
"ssh_keys": "10",
15+
"milestones": "40",
16+
"users": "50",
17+
"groups": "10",
18+
"projects": "20",
19+
"active_users": "50",
20+
}
21+
22+
23+
@pytest.fixture
24+
def resp_application_statistics():
25+
26+
with responses.RequestsMock() as rsps:
27+
rsps.add(
28+
method=responses.GET,
29+
url="http://localhost/api/v4/application/statistics",
30+
json=content,
31+
content_type="application/json",
32+
status=200,
33+
)
34+
35+
yield rsps
36+
37+
38+
def test_get_statistics(gl, resp_application_statistics):
39+
statistics = gl.statistics.get()
40+
assert statistics.forks == content["forks"]
41+
assert statistics.merge_requests == content["merge_requests"]
42+
assert statistics.notes == content["notes"]
43+
assert statistics.snippets == content["snippets"]
44+
assert statistics.ssh_keys == content["ssh_keys"]
45+
assert statistics.milestones == content["milestones"]
46+
assert statistics.users == content["users"]
47+
assert statistics.groups == content["groups"]
48+
assert statistics.projects == content["projects"]
49+
assert statistics.active_users == content["active_users"]

0 commit comments

Comments
 (0)