diff --git a/docs/gl_objects/projects.rst b/docs/gl_objects/projects.rst index d76684755..f1eca382d 100644 --- a/docs/gl_objects/projects.rst +++ b/docs/gl_objects/projects.rst @@ -754,3 +754,54 @@ Protect a single repository tag or several project repository tags using a wildc Unprotect the given protected tag or wildcard protected tag.:: protected_tag.delete() + +Additional project statistics +============================= + +Reference +--------- + +* v4 API: + + + :class:`gitlab.v4.objects.ProjectAdditionalStatistics` + + :class:`gitlab.v4.objects.ProjectAdditionalStatisticsManager` + + :attr:`gitlab.v4.objects.Project.additionalstatistics` + +* GitLab API: https://docs.gitlab.com/ce/api/project_statistics.html + +Examples +--------- + +Get all additional statistics of a project:: + + statistics = project.additionalstatistics.get() + +Get total fetches in last 30 days of a project:: + + total_fetches = project.additionalstatistics.get()['fetches']['total'] + +Project issues statistics +========================= + +Reference +--------- + +* v4 API: + + + :class:`gitlab.v4.objects.ProjectIssuesStatistics` + + :class:`gitlab.v4.objects.ProjectIssuesStatisticsManager` + + :attr:`gitlab.v4.objects.Project.issuesstatistics` + +* GitLab API: https://docs.gitlab.com/ce/api/issues_statistics.html#get-project-issues-statistics + +Examples +--------- + +Get statistics of all issues in a project:: + + statistics = project.issuesstatistics.get() + +Get statistics of issues in a project with ``foobar`` in ``title`` and +``description``:: + + statistics = project.issuesstatistics.get(search='foobar') diff --git a/gitlab/tests/test_gitlab.py b/gitlab/tests/test_gitlab.py index 7449b3a66..5bf373a13 100644 --- a/gitlab/tests/test_gitlab.py +++ b/gitlab/tests/test_gitlab.py @@ -553,6 +553,62 @@ def resp_get_environment(url, request): self.assertEqual(environment.last_deployment, "sometime") self.assertEqual(environment.name, "environment_name") + def test_project_additional_statistics(self): + @urlmatch( + scheme="http", netloc="localhost", path="/api/v4/projects/1$", method="get" + ) + def resp_get_project(url, request): + headers = {"content-type": "application/json"} + content = '{"name": "name", "id": 1}'.encode("utf-8") + return response(200, content, headers, None, 5, request) + + @urlmatch( + scheme="http", + netloc="localhost", + path="/api/v4/projects/1/statistics", + method="get", + ) + def resp_get_environment(url, request): + headers = {"content-type": "application/json"} + content = """{"fetches": {"total": 50, "days": [{"count": 10, "date": "2018-01-10"}]}}""".encode( + "utf-8" + ) + return response(200, content, headers, None, 5, request) + + with HTTMock(resp_get_project, resp_get_environment): + project = self.gl.projects.get(1) + statistics = project.additionalstatistics.get() + self.assertIsInstance(statistics, ProjectAdditionalStatistics) + self.assertEqual(statistics.fetches["total"], 50) + + def test_project_issues_statistics(self): + @urlmatch( + scheme="http", netloc="localhost", path="/api/v4/projects/1$", method="get" + ) + def resp_get_project(url, request): + headers = {"content-type": "application/json"} + content = '{"name": "name", "id": 1}'.encode("utf-8") + return response(200, content, headers, None, 5, request) + + @urlmatch( + scheme="http", + netloc="localhost", + path="/api/v4/projects/1/issues_statistics", + method="get", + ) + def resp_get_environment(url, request): + headers = {"content-type": "application/json"} + content = """{"statistics": {"counts": {"all": 20, "closed": 5, "opened": 15}}}""".encode( + "utf-8" + ) + return response(200, content, headers, None, 5, request) + + with HTTMock(resp_get_project, resp_get_environment): + project = self.gl.projects.get(1) + statistics = project.issuesstatistics.get() + self.assertIsInstance(statistics, ProjectIssuesStatistics) + self.assertEqual(statistics.statistics["counts"]["all"], 20) + def test_groups(self): @urlmatch( scheme="http", netloc="localhost", path="/api/v4/groups/1", method="get" diff --git a/gitlab/v4/objects.py b/gitlab/v4/objects.py index 89e3259b0..91b946dc8 100644 --- a/gitlab/v4/objects.py +++ b/gitlab/v4/objects.py @@ -3997,6 +3997,26 @@ class ProjectImportManager(GetWithoutIdMixin, RESTManager): _from_parent_attrs = {"project_id": "id"} +class ProjectAdditionalStatistics(RefreshMixin, RESTObject): + _id_attr = None + + +class ProjectAdditionalStatisticsManager(GetWithoutIdMixin, RESTManager): + _path = "/projects/%(project_id)s/statistics" + _obj_cls = ProjectAdditionalStatistics + _from_parent_attrs = {"project_id": "id"} + + +class ProjectIssuesStatistics(RefreshMixin, RESTObject): + _id_attr = None + + +class ProjectIssuesStatisticsManager(GetWithoutIdMixin, RESTManager): + _path = "/projects/%(project_id)s/issues_statistics" + _obj_cls = ProjectIssuesStatistics + _from_parent_attrs = {"project_id": "id"} + + class Project(SaveMixin, ObjectDeleteMixin, RESTObject): _short_print_attr = "path" _managers = ( @@ -4042,6 +4062,8 @@ class Project(SaveMixin, ObjectDeleteMixin, RESTObject): ("variables", "ProjectVariableManager"), ("wikis", "ProjectWikiManager"), ("clusters", "ProjectClusterManager"), + ("additionalstatistics", "ProjectAdditionalStatisticsManager"), + ("issuesstatistics", "ProjectIssuesStatisticsManager"), ) @cli.register_custom_action("Project", ("submodule", "branch", "commit_sha"))