diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 21ad101..3ba1704 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,11 +22,11 @@ repos: hooks: - id: isort - repo: https://github.com/psf/black - rev: 23.12.0 + rev: 23.12.1 hooks: - id: black - repo: https://github.com/astral-sh/ruff-pre-commit - rev: 'v0.1.8' + rev: 'v0.1.9' hooks: - id: ruff - repo: https://github.com/asottile/pyupgrade diff --git a/changes/161.feature b/changes/161.feature new file mode 100644 index 0000000..2c0df3b --- /dev/null +++ b/changes/161.feature @@ -0,0 +1 @@ +Add a duplicate() method to Project. diff --git a/docs/usage.rst b/docs/usage.rst index fa8a22e..e7f5a11 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -100,6 +100,18 @@ Create a project new_project = api.projects.create('TEST PROJECT', 'TESTING API') +****************************************************** +Duplicate an existing project +****************************************************** + +If you have a project, you can duplicate it (duplicates most of the settings, +but not the user stories or tasks) + +.. code:: python + + old_project = api.projects.get_by_slug('nephila') + new_project = old_project.duplicate('TEST PROJECT', 'TESTING API') + ****************************************************** Create a new user story ****************************************************** diff --git a/taiga/models/models.py b/taiga/models/models.py index dcd7fa6..a09c496 100644 --- a/taiga/models/models.py +++ b/taiga/models/models.py @@ -1753,6 +1753,20 @@ def list_tags(self): response = self.requester.get("/{}/{}/tags_colors".format(self.endpoint, self.id)) return response.json() + def duplicate(self, name, description, is_private=False, users=[], **attrs): + """ + Duplicate a :class:`Project` + + :param name: name of new :class:`Project` + :param description: description of new :class:`Project` + :param is_private: determines if the project is private or not + :param users: users of the new :class:`Project` + :param attrs: optional attributes for the new :class:`Project` + """ + attrs.update({"name": name, "description": description, "is_private": is_private, "users": users}) + response = self.requester.post("/{endpoint}/{id}/duplicate", payload=attrs, endpoint=self.endpoint, id=self.id) + return self.parse(self.requester, response.json()) + class Projects(ListResource): """ diff --git a/tests/test_projects.py b/tests/test_projects.py index f20ca53..2777ec1 100644 --- a/tests/test_projects.py +++ b/tests/test_projects.py @@ -178,6 +178,18 @@ def test_import_project(self, mock_requestmaker_post): endpoint="importer", ) + @patch("taiga.requestmaker.RequestMaker.post") + def test_duplicate_project(self, mock_requestmaker_post): + rm = RequestMaker("/api/v1", "fakehost", "faketoken") + project = Project(rm, id=1) + project.duplicate("PR 1 1", "PR 1 desc 1") + mock_requestmaker_post.assert_called_with( + "/{endpoint}/{id}/duplicate", + payload={"name": "PR 1 1", "description": "PR 1 desc 1", "is_private": False, "users": []}, + endpoint="projects", + id=project.id, + ) + @patch("taiga.models.IssueStatuses.create") def test_add_issue_status(self, mock_new_issue_status): rm = RequestMaker("/api/v1", "fakehost", "faketoken")