summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNejc Habjan <nejc.habjan@siemens.com>2022-07-24 23:14:06 +0200
committerJohn Villalovos <john@sodarock.com>2022-07-27 08:29:24 -0700
commit194ee0100c2868c1a9afb161c15f3145efb01c7c (patch)
tree2af6cd63ec2ee357a43accbdbc13342d61f87f24
parent66461ba519a85bfbd3cba284a0c8de11a3ac7cde (diff)
downloadgitlab-194ee0100c2868c1a9afb161c15f3145efb01c7c.tar.gz
feat: add support for iterations API
-rw-r--r--docs/api-objects.rst1
-rw-r--r--docs/gl_objects/iterations.rst33
-rw-r--r--gitlab/v4/objects/__init__.py1
-rw-r--r--gitlab/v4/objects/groups.py2
-rw-r--r--gitlab/v4/objects/iterations.py26
-rw-r--r--gitlab/v4/objects/projects.py2
-rw-r--r--tests/unit/objects/test_iterations.py47
7 files changed, 112 insertions, 0 deletions
diff --git a/docs/api-objects.rst b/docs/api-objects.rst
index 3754c25..3c76d77 100644
--- a/docs/api-objects.rst
+++ b/docs/api-objects.rst
@@ -28,6 +28,7 @@ API examples
gl_objects/group_access_tokens
gl_objects/invitations
gl_objects/issues
+ gl_objects/iterations
gl_objects/keys
gl_objects/boards
gl_objects/labels
diff --git a/docs/gl_objects/iterations.rst b/docs/gl_objects/iterations.rst
new file mode 100644
index 0000000..8db0c2e
--- /dev/null
+++ b/docs/gl_objects/iterations.rst
@@ -0,0 +1,33 @@
+##########
+Iterations
+##########
+
+
+Reference
+---------
+
+* v4 API:
+
+ + :class:`gitlab.v4.objects.GroupIteration`
+ + :class:`gitlab.v4.objects.GroupIterationManager`
+ + :attr:`gitlab.v4.objects.Group.iterations`
+ + :class:`gitlab.v4.objects.ProjectIterationManager`
+ + :attr:`gitlab.v4.objects.Project.iterations`
+
+* GitLab API: https://docs.gitlab.com/ee/api/iterations.html
+
+Examples
+--------
+
+.. note::
+
+ GitLab no longer has project iterations. Using a project endpoint returns
+ the ancestor groups' iterations.
+
+List iterations for a project's ancestor groups::
+
+ iterations = project.iterations.list()
+
+List iterations for a group::
+
+ iterations = group.iterations.list()
diff --git a/gitlab/v4/objects/__init__.py b/gitlab/v4/objects/__init__.py
index 542fc30..1e374cd 100644
--- a/gitlab/v4/objects/__init__.py
+++ b/gitlab/v4/objects/__init__.py
@@ -47,6 +47,7 @@ from .hooks import *
from .integrations import *
from .invitations import *
from .issues import *
+from .iterations import *
from .jobs import *
from .keys import *
from .labels import *
diff --git a/gitlab/v4/objects/groups.py b/gitlab/v4/objects/groups.py
index 5b35e00..9a6c473 100644
--- a/gitlab/v4/objects/groups.py
+++ b/gitlab/v4/objects/groups.py
@@ -24,6 +24,7 @@ from .group_access_tokens import GroupAccessTokenManager # noqa: F401
from .hooks import GroupHookManager # noqa: F401
from .invitations import GroupInvitationManager # noqa: F401
from .issues import GroupIssueManager # noqa: F401
+from .iterations import GroupIterationManager # noqa: F401
from .labels import GroupLabelManager # noqa: F401
from .members import ( # noqa: F401
GroupBillableMemberManager,
@@ -71,6 +72,7 @@ class Group(SaveMixin, ObjectDeleteMixin, RESTObject):
invitations: GroupInvitationManager
issues: GroupIssueManager
issues_statistics: GroupIssuesStatisticsManager
+ iterations: GroupIterationManager
labels: GroupLabelManager
members: GroupMemberManager
members_all: GroupMemberAllManager
diff --git a/gitlab/v4/objects/iterations.py b/gitlab/v4/objects/iterations.py
new file mode 100644
index 0000000..30895ff
--- /dev/null
+++ b/gitlab/v4/objects/iterations.py
@@ -0,0 +1,26 @@
+from gitlab.base import RESTManager, RESTObject
+from gitlab.mixins import ListMixin
+
+__all__ = [
+ "ProjectIterationManager",
+ "GroupIteration",
+ "GroupIterationManager",
+]
+
+
+class GroupIteration(RESTObject):
+ _repr_attr = "title"
+
+
+class GroupIterationManager(ListMixin, RESTManager):
+ _path = "/groups/{group_id}/iterations"
+ _obj_cls = GroupIteration
+ _from_parent_attrs = {"group_id": "id"}
+ _list_filters = ("state", "search", "include_ancestors")
+
+
+class ProjectIterationManager(ListMixin, RESTManager):
+ _path = "/projects/{project_id}/iterations"
+ _obj_cls = GroupIteration
+ _from_parent_attrs = {"project_id": "id"}
+ _list_filters = ("state", "search", "include_ancestors")
diff --git a/gitlab/v4/objects/projects.py b/gitlab/v4/objects/projects.py
index e46e53d..803239f 100644
--- a/gitlab/v4/objects/projects.py
+++ b/gitlab/v4/objects/projects.py
@@ -57,6 +57,7 @@ from .hooks import ProjectHookManager # noqa: F401
from .integrations import ProjectIntegrationManager, ProjectServiceManager # noqa: F401
from .invitations import ProjectInvitationManager # noqa: F401
from .issues import ProjectIssueManager # noqa: F401
+from .iterations import GroupIterationManager # noqa: F401
from .jobs import ProjectJobManager # noqa: F401
from .labels import ProjectLabelManager # noqa: F401
from .members import ProjectMemberAllManager, ProjectMemberManager # noqa: F401
@@ -185,6 +186,7 @@ class Project(RefreshMixin, SaveMixin, ObjectDeleteMixin, RepositoryMixin, RESTO
invitations: ProjectInvitationManager
issues: ProjectIssueManager
issues_statistics: ProjectIssuesStatisticsManager
+ iterations: GroupIterationManager
jobs: ProjectJobManager
keys: ProjectKeyManager
labels: ProjectLabelManager
diff --git a/tests/unit/objects/test_iterations.py b/tests/unit/objects/test_iterations.py
new file mode 100644
index 0000000..0848691
--- /dev/null
+++ b/tests/unit/objects/test_iterations.py
@@ -0,0 +1,47 @@
+"""
+GitLab API: https://docs.gitlab.com/ee/api/iterations.html
+"""
+
+import re
+
+import pytest
+import responses
+
+iterations_content = [
+ {
+ "id": 53,
+ "iid": 13,
+ "group_id": 5,
+ "title": "Iteration II",
+ "description": "Ipsum Lorem ipsum",
+ "state": 2,
+ "created_at": "2020-01-27T05:07:12.573Z",
+ "updated_at": "2020-01-27T05:07:12.573Z",
+ "due_date": "2020-02-01",
+ "start_date": "2020-02-14",
+ "web_url": "http://gitlab.example.com/groups/my-group/-/iterations/13",
+ }
+]
+
+
+@pytest.fixture
+def resp_iterations_list():
+ with responses.RequestsMock() as rsps:
+ rsps.add(
+ method=responses.GET,
+ url=re.compile(r"http://localhost/api/v4/(groups|projects)/1/iterations"),
+ json=iterations_content,
+ content_type="application/json",
+ status=200,
+ )
+ yield rsps
+
+
+def test_list_group_iterations(group, resp_iterations_list):
+ iterations = group.iterations.list()
+ assert iterations[0].group_id == 5
+
+
+def test_list_project_iterations(project, resp_iterations_list):
+ iterations = project.iterations.list()
+ assert iterations[0].group_id == 5