7 files changed
@@ -54,6 +54,7 @@ API examples | |||
| 54 | 54 | gl_objects/search | |
| 55 | 55 | gl_objects/settings | |
| 56 | 56 | gl_objects/snippets | |
| 57 | + gl_objects/statistics | ||
| 57 | 58 | gl_objects/system_hooks | |
| 58 | 59 | gl_objects/templates | |
| 59 | 60 | gl_objects/todos | |
@@ -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() | ||
@@ -188,6 +188,8 @@ def __init__( | |||
| 188 | 188 | """See :class:`~gitlab.v4.objects.PersonalAccessTokenManager`""" | |
| 189 | 189 | self.topics = objects.TopicManager(self) | |
| 190 | 190 | """See :class:`~gitlab.v4.objects.TopicManager`""" | |
| 191 | + self.statistics = objects.ApplicationStatisticsManager(self) | ||
| 192 | + """See :class:`~gitlab.v4.objects.ApplicationStatisticsManager`""" | ||
| 191 | 193 | ||
| 192 | 194 | def __enter__(self) -> "Gitlab": | |
| 193 | 195 | return self | |
@@ -13,6 +13,8 @@ | |||
| 13 | 13 | "IssuesStatisticsManager", | |
| 14 | 14 | "ProjectIssuesStatistics", | |
| 15 | 15 | "ProjectIssuesStatisticsManager", | |
| 16 | + "ApplicationStatistics", | ||
| 17 | + "ApplicationStatisticsManager", | ||
| 16 | 18 | ] | |
| 17 | 19 | ||
| 18 | 20 | ||
@@ -71,3 +73,15 @@ class ProjectIssuesStatisticsManager(GetWithoutIdMixin, RESTManager): | |||
| 71 | 73 | ||
| 72 | 74 | def get(self, **kwargs: Any) -> ProjectIssuesStatistics: | |
| 73 | 75 | 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)) | ||
@@ -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() | ||
@@ -94,7 +94,18 @@ def reset_gitlab(gl: gitlab.Gitlab) -> None: | |||
| 94 | 94 | helpers.safe_delete(deploy_token) | |
| 95 | 95 | logging.info(f"Deleting project: {project.path_with_namespace!r}") | |
| 96 | 96 | helpers.safe_delete(project) | |
| 97 | + | ||
| 97 | 98 | 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 | + | ||
| 98 | 109 | for deploy_token in group.deploytokens.list(): | |
| 99 | 110 | logging.info( | |
| 100 | 111 | f"Deleting deploy token: {deploy_token.username!r} in " | |
@@ -110,7 +121,7 @@ def reset_gitlab(gl: gitlab.Gitlab) -> None: | |||
| 110 | 121 | logging.info(f"Deleting variable: {variable.key!r}") | |
| 111 | 122 | helpers.safe_delete(variable) | |
| 112 | 123 | for user in gl.users.list(): | |
| 113 | - if user.username != "root": | ||
| 124 | + if user.username not in ["root", "ghost"]: | ||
| 114 | 125 | logging.info(f"Deleting user: {user.username!r}") | |
| 115 | 126 | helpers.safe_delete(user, hard_delete=True) | |
| 116 | 127 | ||
@@ -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