Skip to content

Commit

Permalink
feat: Add new method to update project workflow (#1836)
Browse files Browse the repository at this point in the history
  • Loading branch information
florianlega authored Dec 24, 2024
1 parent 1e9cc08 commit fb90304
Show file tree
Hide file tree
Showing 14 changed files with 204 additions and 1 deletion.
3 changes: 3 additions & 0 deletions docs/sdk/project_workflow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Project Workflow module

::: kili.presentation.client.project_workflow.ProjectWorkflowClientMethods
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ nav:
- Project: sdk/project.md
- Project User: sdk/project_user.md
- Project Version: sdk/project_version.md
- Project Workflow: sdk/project_workflow.md
- Tag: sdk/tag.md
- User: sdk/user.md
- Command Line Interface:
Expand Down
4 changes: 4 additions & 0 deletions src/kili/adapters/kili_api_gateway/kili_api_gateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
OrganizationOperationMixin,
)
from kili.adapters.kili_api_gateway.project.operations_mixin import ProjectOperationMixin
from kili.adapters.kili_api_gateway.project_workflow.operations_mixin import (
ProjectWorkflowOperationMixin,
)
from kili.adapters.kili_api_gateway.tag import TagOperationMixin
from kili.adapters.kili_api_gateway.user.operation_mixin import UserOperationMixin
from kili.core.graphql.graphql_client import GraphQLClient
Expand All @@ -32,6 +35,7 @@ class KiliAPIGateway(
NotificationOperationMixin,
OrganizationOperationMixin,
ProjectOperationMixin,
ProjectWorkflowOperationMixin,
TagOperationMixin,
UserOperationMixin,
EventOperationMixin,
Expand Down
Empty file.
12 changes: 12 additions & 0 deletions src/kili/adapters/kili_api_gateway/project_workflow/mappers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
"""GraphQL payload data mappers for project operations."""

from typing import Dict

from .types import ProjectWorkflowDataKiliAPIGatewayInput


def project_input_mapper(data: ProjectWorkflowDataKiliAPIGatewayInput) -> Dict:
"""Build the GraphQL ProjectWorfklowData variable to be sent in an operation."""
return {
"enforceStepSeparation": data.enforce_step_separation,
}
12 changes: 12 additions & 0 deletions src/kili/adapters/kili_api_gateway/project_workflow/operations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
"""GraphQL Project Workflow operations."""


def get_update_project_workflow_mutation(fragment: str) -> str:
"""Return the GraphQL editProjectWorkflowSettings mutation."""
return f"""
mutation editProjectWorkflowSettings($input: EditProjectWorkflowSettingsInput!) {{
data: editProjectWorkflowSettings(input: $input) {{
{fragment}
}}
}}
"""
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"""Mixin extending Kili API Gateway class with Projects related operations."""

from typing import Dict

from kili.adapters.kili_api_gateway.base import BaseOperationMixin
from kili.adapters.kili_api_gateway.helpers.queries import (
fragment_builder,
)
from kili.domain.project import ProjectId

from .mappers import project_input_mapper
from .operations import (
get_update_project_workflow_mutation,
)
from .types import ProjectWorkflowDataKiliAPIGatewayInput


class ProjectWorkflowOperationMixin(BaseOperationMixin):
"""Mixin extending Kili API Gateway class with Projects workflow related operations."""

def update_project_workflow(
self,
project_id: ProjectId,
project_workflow_data: ProjectWorkflowDataKiliAPIGatewayInput,
) -> Dict:
"""Update properties in a project workflow."""
project_workflow_input = project_input_mapper(data=project_workflow_data)

fields = tuple(name for name, val in project_workflow_input.items() if val is not None)
fragment = fragment_builder(fields)
mutation = get_update_project_workflow_mutation(fragment)

project_workflow_input["projectId"] = project_id

variables = {"input": project_workflow_input}
result = self.graphql_client.execute(mutation, variables)
return result["data"]
11 changes: 11 additions & 0 deletions src/kili/adapters/kili_api_gateway/project_workflow/types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
"""Types for the ProjectWorkflow-related Kili API gateway functions."""

from dataclasses import dataclass
from typing import Optional


@dataclass
class ProjectWorkflowDataKiliAPIGatewayInput:
"""ProjectWorkflow input data for Kili API Gateway."""

enforce_step_separation: Optional[bool]
2 changes: 2 additions & 0 deletions src/kili/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
from kili.presentation.client.notification import NotificationClientMethods
from kili.presentation.client.organization import OrganizationClientMethods
from kili.presentation.client.project import ProjectClientMethods
from kili.presentation.client.project_workflow import ProjectWorkflowClientMethods
from kili.presentation.client.tag import TagClientMethods
from kili.presentation.client.user import UserClientMethods
from kili.use_cases.api_key import ApiKeyUseCases
Expand Down Expand Up @@ -68,6 +69,7 @@ class Kili( # pylint: disable=too-many-ancestors,too-many-instance-attributes
NotificationClientMethods,
OrganizationClientMethods,
ProjectClientMethods,
ProjectWorkflowClientMethods,
TagClientMethods,
UserClientMethods,
):
Expand Down
1 change: 0 additions & 1 deletion src/kili/entrypoints/mutations/asset/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,6 @@ def assign_assets_to_labelers(
external_ids: Optional[List[str]] = None,
project_id: Optional[str] = None,
) -> List[Dict[str, Any]]:
# pylint: disable=line-too-long
"""Assign a list of assets to a list of labelers.
Args:
Expand Down
37 changes: 37 additions & 0 deletions src/kili/presentation/client/project_workflow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"""Client presentation methods for project workflow."""

from typing import Any, Dict, Optional

from typeguard import typechecked

from kili.domain.project import ProjectId
from kili.use_cases.project_workflow import ProjectWorkflowUseCases

from .base import BaseClientMethods


class ProjectWorkflowClientMethods(BaseClientMethods):
"""Client presentation methods for project workflow."""

@typechecked
def update_project_workflow(
self,
project_id: str,
enforce_step_separation: Optional[bool] = None,
) -> Dict[str, Any]:
"""Update properties of a project workflow.
Args:
project_id: Id of the project.
enforce_step_separation: Prevents the same user from being assigned to
multiple steps in the workflow for a same asset,
ensuring independent review and labeling processes
Returns:
A dict with the changed properties which indicates if the mutation was successful,
else an error message.
"""
return ProjectWorkflowUseCases(self.kili_api_gateway).update_project_workflow(
project_id=ProjectId(project_id),
enforce_step_separation=enforce_step_separation,
)
25 changes: 25 additions & 0 deletions src/kili/use_cases/project_workflow/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"""Project use cases."""

from typing import Dict, Optional

from kili.adapters.kili_api_gateway.project_workflow.types import (
ProjectWorkflowDataKiliAPIGatewayInput,
)
from kili.domain.project import ProjectId
from kili.use_cases.base import BaseUseCases


class ProjectWorkflowUseCases(BaseUseCases):
"""ProjectWorkflow use cases."""

def update_project_workflow(
self,
project_id: ProjectId,
enforce_step_separation: Optional[bool] = None,
) -> Dict[str, object]:
"""Update properties in a project workflow."""
project_workflow_data = ProjectWorkflowDataKiliAPIGatewayInput(
enforce_step_separation=enforce_step_separation,
)

return self._kili_api_gateway.update_project_workflow(project_id, project_workflow_data)
29 changes: 29 additions & 0 deletions tests/integration/presentation/test_project_workflow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import pytest_mock

from kili.adapters.kili_api_gateway.kili_api_gateway import KiliAPIGateway
from kili.adapters.kili_api_gateway.project_workflow.operations import (
get_update_project_workflow_mutation,
)
from kili.presentation.client.project_workflow import ProjectWorkflowClientMethods


def test_when_updating_project_workflow_then_it_returns_updated_project_workflow(
mocker: pytest_mock.MockerFixture,
):
kili = ProjectWorkflowClientMethods()
kili.kili_api_gateway = KiliAPIGateway(
graphql_client=mocker.MagicMock(), http_client=mocker.MagicMock()
)
# Given
project_id = "fake_proj_id"

# When
kili.update_project_workflow(project_id, enforce_step_separation=False)

# Then
kili.kili_api_gateway.graphql_client.execute.assert_called_once_with(
get_update_project_workflow_mutation(" enforceStepSeparation"),
{
"input": {"projectId": "fake_proj_id", "enforceStepSeparation": False},
},
)
31 changes: 31 additions & 0 deletions tests/integration/use_cases/test_project_workflow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from kili.adapters.kili_api_gateway.kili_api_gateway import KiliAPIGateway
from kili.adapters.kili_api_gateway.project_workflow.types import (
ProjectWorkflowDataKiliAPIGatewayInput,
)
from kili.domain.project import ProjectId
from kili.use_cases.project_workflow import ProjectWorkflowUseCases


def test_given_a_project_workflow_when_update_it_then_it_updates_project_workflow_props(
kili_api_gateway: KiliAPIGateway,
):
# Given
def mocked_update_project_workflow(
project_id: ProjectId,
project_workflow_data: ProjectWorkflowDataKiliAPIGatewayInput,
):
return {
"enforce_step_separation": project_workflow_data.enforce_step_separation,
"project_id": project_id,
}

kili_api_gateway.update_project_workflow.side_effect = mocked_update_project_workflow

# When
project = ProjectWorkflowUseCases(kili_api_gateway).update_project_workflow(
project_id=ProjectId("fake_proj_id"),
enforce_step_separation=False,
)

# Then
assert project == {"enforce_step_separation": False, "project_id": "fake_proj_id"}

0 comments on commit fb90304

Please sign in to comment.