Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions plane/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from .api.milestones import Milestones
from .api.modules import Modules
from .api.pages import Pages
from .api.project_templates import ProjectPageTemplates, ProjectTemplates, ProjectWorkItemTemplates
from .api.projects import Projects
from .api.states import States
from .api.stickies import Stickies
Expand All @@ -14,6 +15,7 @@
from .api.work_item_properties import WorkItemProperties
from .api.work_item_types import WorkItemTypes
from .api.work_items import WorkItems
from .api.workflows import Workflows, WorkflowStates, WorkflowTransitions
from .api.workspaces import Workspaces
from .client import (
OAuthAuthorizationParams,
Expand All @@ -26,6 +28,24 @@
)
from .config import Configuration
from .errors.errors import ConfigurationError, HttpError, PlaneError
from .models.project_templates import (
CreatePageTemplate,
CreateWorkItemTemplate,
PageTemplate,
UpdatePageTemplate,
UpdateWorkItemTemplate,
WorkItemTemplate,
)
from .models.projects import ProjectFeature
from .models.workflows import (
AttachWorkflowStates,
CreateWorkflow,
CreateWorkflowTransition,
UpdateWorkflow,
UpdateWorkflowTransition,
Workflow,
WorkflowTransition,
)

__all__ = [
"PlaneClient",
Expand All @@ -48,6 +68,12 @@
"Estimates",
"Pages",
"Workspaces",
"Workflows",
"WorkflowStates",
"WorkflowTransitions",
"ProjectTemplates",
"ProjectWorkItemTemplates",
"ProjectPageTemplates",
"PlaneError",
"ConfigurationError",
"HttpError",
Expand All @@ -56,4 +82,20 @@
"OAuthTokenExchangeParams",
"OAuthRefreshTokenParams",
"OAuthClientCredentialsParams",
# Workflow models
"Workflow",
"CreateWorkflow",
"UpdateWorkflow",
"AttachWorkflowStates",
"WorkflowTransition",
"CreateWorkflowTransition",
"UpdateWorkflowTransition",
"ProjectFeature",
# Project template models
"WorkItemTemplate",
"CreateWorkItemTemplate",
"UpdateWorkItemTemplate",
"PageTemplate",
"CreatePageTemplate",
"UpdatePageTemplate",
]
5 changes: 5 additions & 0 deletions plane/api/project_templates/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from .base import ProjectTemplates
from .page_templates import ProjectPageTemplates
from .work_item_templates import ProjectWorkItemTemplates

__all__ = ["ProjectTemplates", "ProjectWorkItemTemplates", "ProjectPageTemplates"]
15 changes: 15 additions & 0 deletions plane/api/project_templates/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from typing import Any

from ..base_resource import BaseResource
from .page_templates import ProjectPageTemplates
from .work_item_templates import ProjectWorkItemTemplates


class ProjectTemplates(BaseResource):
"""API client for managing project-scoped templates (work items and pages)."""

def __init__(self, config: Any) -> None:
super().__init__(config, "/workspaces/")

self.work_item_templates = ProjectWorkItemTemplates(config)
self.page_templates = ProjectPageTemplates(config)
90 changes: 90 additions & 0 deletions plane/api/project_templates/page_templates.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
from typing import Any

from ...models.project_templates import (
CreatePageTemplate,
PageTemplate,
UpdatePageTemplate,
)
from ..base_resource import BaseResource


class ProjectPageTemplates(BaseResource):
"""API client for managing page templates within a project."""

def __init__(self, config: Any) -> None:
super().__init__(config, "/workspaces/")

def list(self, workspace_slug: str, project_id: str) -> list[PageTemplate]:
"""List all page templates for a project.

Args:
workspace_slug: The workspace slug identifier
project_id: UUID of the project

Returns:
List of page templates
"""
data = self._get(f"{workspace_slug}/projects/{project_id}/pages/templates/")
items = data.get("results", data) if isinstance(data, dict) else data
return [PageTemplate.model_validate(item) for item in items]

def create(
self,
workspace_slug: str,
project_id: str,
data: CreatePageTemplate,
) -> PageTemplate:
"""Create a new page template for a project.

Args:
workspace_slug: The workspace slug identifier
project_id: UUID of the project
data: Template data

Returns:
The created page template
"""
response = self._post(
f"{workspace_slug}/projects/{project_id}/pages/templates/",
data.model_dump(exclude_none=True),
)
return PageTemplate.model_validate(response)

def update(
self,
workspace_slug: str,
project_id: str,
template_id: str,
data: UpdatePageTemplate,
) -> PageTemplate:
"""Update a page template by ID.

Args:
workspace_slug: The workspace slug identifier
project_id: UUID of the project
template_id: UUID of the template
data: Updated template data

Returns:
The updated page template
"""
response = self._patch(
f"{workspace_slug}/projects/{project_id}/pages/templates/{template_id}/",
data.model_dump(exclude_none=True),
)
return PageTemplate.model_validate(response)

def delete(
self,
workspace_slug: str,
project_id: str,
template_id: str,
) -> None:
"""Delete a page template by ID.

Args:
workspace_slug: The workspace slug identifier
project_id: UUID of the project
template_id: UUID of the template
"""
self._delete(f"{workspace_slug}/projects/{project_id}/pages/templates/{template_id}/")
90 changes: 90 additions & 0 deletions plane/api/project_templates/work_item_templates.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
from typing import Any

from ...models.project_templates import (
CreateWorkItemTemplate,
UpdateWorkItemTemplate,
WorkItemTemplate,
)
from ..base_resource import BaseResource


class ProjectWorkItemTemplates(BaseResource):
"""API client for managing work item templates within a project."""

def __init__(self, config: Any) -> None:
super().__init__(config, "/workspaces/")

def list(self, workspace_slug: str, project_id: str) -> list[WorkItemTemplate]:
"""List all work item templates for a project.

Args:
workspace_slug: The workspace slug identifier
project_id: UUID of the project

Returns:
List of work item templates
"""
data = self._get(f"{workspace_slug}/projects/{project_id}/workitems/templates/")
items = data.get("results", data) if isinstance(data, dict) else data
return [WorkItemTemplate.model_validate(item) for item in items]

def create(
self,
workspace_slug: str,
project_id: str,
data: CreateWorkItemTemplate,
) -> WorkItemTemplate:
"""Create a new work item template for a project.

Args:
workspace_slug: The workspace slug identifier
project_id: UUID of the project
data: Template data

Returns:
The created work item template
"""
response = self._post(
f"{workspace_slug}/projects/{project_id}/workitems/templates/",
data.model_dump(exclude_none=True),
)
return WorkItemTemplate.model_validate(response)

def update(
self,
workspace_slug: str,
project_id: str,
template_id: str,
data: UpdateWorkItemTemplate,
) -> WorkItemTemplate:
"""Update a work item template by ID.

Args:
workspace_slug: The workspace slug identifier
project_id: UUID of the project
template_id: UUID of the template
data: Updated template data

Returns:
The updated work item template
"""
response = self._patch(
f"{workspace_slug}/projects/{project_id}/workitems/templates/{template_id}",
data.model_dump(exclude_none=True),
)
return WorkItemTemplate.model_validate(response)

def delete(
self,
workspace_slug: str,
project_id: str,
template_id: str,
) -> None:
"""Delete a work item template by ID.

Args:
workspace_slug: The workspace slug identifier
project_id: UUID of the project
template_id: UUID of the template
"""
self._delete(f"{workspace_slug}/projects/{project_id}/workitems/templates/{template_id}/")
1 change: 1 addition & 0 deletions plane/api/projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,4 @@ def unarchive(self, workspace_slug: str, project_id: str) -> None:
None (HTTP 204 No Content)
"""
self._delete(f"{workspace_slug}/projects/{project_id}/archive")

5 changes: 5 additions & 0 deletions plane/api/workflows/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from .base import Workflows
from .states import WorkflowStates
from .transitions import WorkflowTransitions

__all__ = ["WorkflowStates", "WorkflowTransitions", "Workflows"]
76 changes: 76 additions & 0 deletions plane/api/workflows/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
from typing import Any

from ...models.workflows import CreateWorkflow, UpdateWorkflow, Workflow
from ..base_resource import BaseResource
from .states import WorkflowStates
from .transitions import WorkflowTransitions


class Workflows(BaseResource):
"""API client for managing project workflows."""

def __init__(self, config: Any) -> None:
super().__init__(config, "/workspaces/")

self.states = WorkflowStates(config)
self.transitions = WorkflowTransitions(config)

def list(self, workspace_slug: str, project_id: str) -> list[Workflow]:
"""List all workflows for a project.

Args:
workspace_slug: The workspace slug identifier
project_id: UUID of the project

Returns:
List of workflows
"""
data = self._get(f"{workspace_slug}/projects/{project_id}/workflows/")
items = data.get("results", data) if isinstance(data, dict) else data
return [Workflow.model_validate(item) for item in items]

def create(
self,
workspace_slug: str,
project_id: str,
data: CreateWorkflow,
) -> Workflow:
"""Create a new workflow for a project.

Args:
workspace_slug: The workspace slug identifier
project_id: UUID of the project
data: Workflow data

Returns:
The created workflow
"""
response = self._post(
f"{workspace_slug}/projects/{project_id}/workflows/",
data.model_dump(exclude_none=True),
)
return Workflow.model_validate(response)

def update(
self,
workspace_slug: str,
project_id: str,
workflow_id: str,
data: UpdateWorkflow,
) -> Workflow:
"""Update a workflow by ID.

Args:
workspace_slug: The workspace slug identifier
project_id: UUID of the project
workflow_id: UUID of the workflow
data: Updated workflow data

Returns:
The updated workflow
"""
response = self._patch(
f"{workspace_slug}/projects/{project_id}/workflows/{workflow_id}/",
data.model_dump(exclude_none=True),
)
return Workflow.model_validate(response)
Loading