Skip to content

Commit

Permalink
format
Browse files Browse the repository at this point in the history
  • Loading branch information
Ronald Krist committed Jul 23, 2024
1 parent 4d2fe6e commit 336346d
Show file tree
Hide file tree
Showing 15 changed files with 106 additions and 102 deletions.
23 changes: 11 additions & 12 deletions oarepo_workflows/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from .base import Workflow
from .permissions import (
DefaultWorkflowPermissionPolicy,
IfInState,
Expand All @@ -15,14 +14,14 @@
)

__all__ = (
'IfInState',
'WorkflowPermission',
'DefaultWorkflowPermissionPolicy',
'WorkflowPermissionPolicy',
'WorkflowRequestPolicy',
'WorkflowRequest',
'WorkflowTransitions',
'RecipientGeneratorMixin',
'AutoRequest',
'AutoApprove',
)
"IfInState",
"WorkflowPermission",
"DefaultWorkflowPermissionPolicy",
"WorkflowPermissionPolicy",
"WorkflowRequestPolicy",
"WorkflowRequest",
"WorkflowTransitions",
"RecipientGeneratorMixin",
"AutoRequest",
"AutoApprove",
)
2 changes: 1 addition & 1 deletion oarepo_workflows/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ def permissions(self):

@property
def requests(self):
return self.requests_cls()
return self.requests_cls()
11 changes: 7 additions & 4 deletions oarepo_workflows/ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,22 @@ def init_config(self, app):
@cached_property
def state_changed_notifiers(self):
group_name = "oarepo_workflows.state_changed_notifiers"
return [x.load() for x in importlib_metadata.entry_points().select(group=group_name)]
return [
x.load() for x in importlib_metadata.entry_points().select(group=group_name)
]

@cached_property
def workflow_changed_notifiers(self):
group_name = "oarepo_workflows.workflow_changed_notifiers"
return [x.load() for x in importlib_metadata.entry_points().select(group=group_name)]
return [
x.load() for x in importlib_metadata.entry_points().select(group=group_name)
]

@cached_property
def default_workflow_getters(self):
group_name = "oarepo_workflows.default_workflow_getters"
return [
x.load()
for x in importlib_metadata.entry_points().select(group=group_name)
x.load() for x in importlib_metadata.entry_points().select(group=group_name)
]

def set_state(self, identity, record, value, *args, uow=None, **kwargs):
Expand Down
10 changes: 5 additions & 5 deletions oarepo_workflows/permissions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
from .policy import DefaultWorkflowPermissionPolicy, WorkflowPermissionPolicy

__all__ = (
'IfInState',
'WorkflowPermission',
'DefaultWorkflowPermissionPolicy',
'WorkflowPermissionPolicy',
)
"IfInState",
"WorkflowPermission",
"DefaultWorkflowPermissionPolicy",
"WorkflowPermissionPolicy",
)
11 changes: 6 additions & 5 deletions oarepo_workflows/permissions/generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@ def __init__(self, action=None):
super().__init__()
self._action = action


def _get_permission_class_from_workflow(self, record=None, action_name=None, **kwargs):
def _get_permission_class_from_workflow(
self, record=None, action_name=None, **kwargs
):
if record:
workflow_id = get_workflow_from_record(record)
if not workflow_id:
workflow_id = current_oarepo_workflows.get_default_workflow(record=record, **kwargs)
workflow_id = current_oarepo_workflows.get_default_workflow(
record=record, **kwargs
)
else:
# TODO: should not we raise an exception here ???
# record doesn't have to be here - ie. in case of create in community, in such case we need default value for the community
Expand Down Expand Up @@ -77,5 +80,3 @@ def query_filter(self, **kwargs):
then_query = self._make_query(self.then_, **kwargs)

return q_instate & then_query


5 changes: 2 additions & 3 deletions oarepo_workflows/permissions/policy.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from invenio_records_permissions import RecordPermissionPolicy
from invenio_records_permissions.generators import AuthenticatedUser, SystemProcess
from oarepo_runtime.services.generators import RecordOwners

from oarepo_workflows.permissions.generators import WorkflowPermission

from .generators import IfInState


Expand Down Expand Up @@ -67,6 +69,3 @@ class WorkflowPermissionPolicy(RecordPermissionPolicy):
can_draft_commit_files = [WorkflowPermission("can_commit_files")]
can_draft_read_files = [WorkflowPermission("can_read_files")]
can_draft_update_files = [WorkflowPermission("can_update_files")]



11 changes: 4 additions & 7 deletions oarepo_workflows/records/systemfields/workflow.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from invenio_db import db
from invenio_records.systemfields.model import ModelField
from oarepo_runtime.records.systemfields import MappingSystemFieldMixin

Expand All @@ -13,15 +12,13 @@ def __init__(self):

def post_create(self, parent_record):
if not parent_record.workflow:
parent_record.workflow = current_oarepo_workflows.get_default_workflow(record=parent_record)
parent_record.workflow = current_oarepo_workflows.get_default_workflow(
record=parent_record
)

def pre_commit(self, parent_record):
super().pre_commit(parent_record)

@property
def mapping(self):
return {
self.attr_name: {
"type": "keyword"
}
}
return {self.attr_name: {"type": "keyword"}}
14 changes: 7 additions & 7 deletions oarepo_workflows/requests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
)

__all__ = (
'WorkflowRequestPolicy',
'WorkflowRequest',
'WorkflowTransitions',
'RecipientGeneratorMixin',
'AutoRequest',
'AutoApprove',
)
"WorkflowRequestPolicy",
"WorkflowRequest",
"WorkflowTransitions",
"RecipientGeneratorMixin",
"AutoRequest",
"AutoApprove",
)
62 changes: 35 additions & 27 deletions oarepo_workflows/requests/policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,16 @@
from invenio_requests.services.permissions import PermissionPolicy

from oarepo_workflows.permissions.generators import WorkflowPermission
from oarepo_workflows.utils import get_workflow_from_record, get_from_requests_workflow
from oarepo_workflows.utils import get_from_requests_workflow, get_workflow_from_record


@dataclasses.dataclass
class WorkflowRequest:
requesters: List[Generator] | Tuple[Generator]
recipients: List[Generator] | Tuple[Generator]
transitions: Optional['WorkflowTransitions'] = dataclasses.field(
default_factory=lambda: WorkflowTransitions())
transitions: Optional["WorkflowTransitions"] = dataclasses.field(
default_factory=lambda: WorkflowTransitions()
)

def reference_receivers(self, **kwargs):
if not self.recipients:
Expand All @@ -35,45 +36,49 @@ class WorkflowTransitions:
If the request is approved, the record will be moved to state defined in approved.
If the request is rejected, the record will be moved to state defined in rejected.
"""

submitted: Optional[str] = None
approved: Optional[str] = None
rejected: Optional[str] = None


class WorkflowRequestPolicy:
"""Base class for workflow request policies. Inherit from this class
and add properties to define specific requests for a workflow.
The name of the property is the request_type name and the value must be
an instance of WorkflowRequest.
Example:
class MyWorkflowRequests(WorkflowRequestPolicy):
delete_request = WorkflowRequest(
requesters = [
IfInState("published", RecordOwner())
],
recipients = [CommunityRole("curator")],
transitions: WorkflowTransitions(
submitted = 'considered_for_deletion',
approved = 'deleted',
rejected = 'published'
)
)
and add properties to define specific requests for a workflow.
The name of the property is the request_type name and the value must be
an instance of WorkflowRequest.
Example:
class MyWorkflowRequests(WorkflowRequestPolicy):
delete_request = WorkflowRequest(
requesters = [
IfInState("published", RecordOwner())
],
recipients = [CommunityRole("curator")],
transitions: WorkflowTransitions(
submitted = 'considered_for_deletion',
approved = 'deleted',
rejected = 'published'
)
)
"""

def __getitem__(self, item):
try:
return getattr(self, item)
except AttributeError:
raise KeyError(f"Request type {item} not defined in {self.__class__.__name__}")
raise KeyError(
f"Request type {item} not defined in {self.__class__.__name__}"
)


class RecipientGeneratorMixin:
"""
Mixin for permission generators that can be used as recipients in WorkflowRequest.
"""

def reference_receivers(self, record=None, request_type=None, **kwargs):
"""
Taken the context (will include record amd request type at least),
Expand All @@ -87,6 +92,7 @@ def reference_receivers(self, record=None, request_type=None, **kwargs):
"""
raise NotImplementedError("Implement reference receiver in your code")


auto_request_need = SystemRoleNeed("auto_request")
auto_approve_need = SystemRoleNeed("auto_approve")

Expand All @@ -96,6 +102,7 @@ class AutoRequest(Generator):
Auto request generator. This generator is used to automatically create a request
when a record is moved to a specific state.
"""

def needs(self, **kwargs):
"""Enabling Needs."""
return [auto_request_need]
Expand All @@ -108,19 +115,20 @@ class AutoApprove(RecipientGeneratorMixin, Generator):
"""

def reference_receivers(self, record=None, request_type=None, **kwargs):
return [{
"auto_approve": "true"
}]
return [{"auto_approve": "true"}]


class CreatorsFromWorkflow(WorkflowPermission):
"""
generator for accesing request creators
"""

def _get_generators(self, record, **kwargs):
request_type = kwargs["request_type"]
workflow_id = get_workflow_from_record(record)
return get_from_requests_workflow(workflow_id, request_type.type_id, "requesters")
return get_from_requests_workflow(
workflow_id, request_type.type_id, "requesters"
)


class CreatorsFromWorkflowPermissionPolicy(PermissionPolicy):
Expand Down
9 changes: 6 additions & 3 deletions oarepo_workflows/utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from itertools import chain

from oarepo_workflows.proxies import current_oarepo_workflows

Expand All @@ -11,6 +10,7 @@ def get_workflow_from_record(record, **kwargs):
else:
return None


"""
def needs_from_generators(generators, **kwargs):
needs = [
Expand All @@ -22,10 +22,13 @@ def needs_from_generators(generators, **kwargs):
return set(chain.from_iterable(needs))
"""


def get_from_requests_workflow(workflow_id, type_id, segment):
try:
request = getattr(current_oarepo_workflows.record_workflows[workflow_id].requests, type_id)
request = getattr(
current_oarepo_workflows.record_workflows[workflow_id].requests, type_id
)
ret = getattr(request, segment)
return ret
except (KeyError, AttributeError):
return []
return []
29 changes: 15 additions & 14 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,25 +57,25 @@ def query_filter(self, **kwargs):

class MyWorkflowRequests(WorkflowRequestPolicy):
delete_request = WorkflowRequest(
requesters=[
IfInState("published", RecordOwners())
],
requesters=[IfInState("published", RecordOwners())],
recipients=[Administration()],
transitions = WorkflowTransitions(
submitted='considered_for_deletion',
approved='deleted',
rejected='published'
)
transitions=WorkflowTransitions(
submitted="considered_for_deletion",
approved="deleted",
rejected="published",
),
)


WORKFLOWS = {
"my_workflow": Workflow(
label = _("Default workflow"),
permissions_cls = DefaultWorkflowPermissionPolicy,
requests_cls = MyWorkflowRequests
label=_("Default workflow"),
permissions_cls=DefaultWorkflowPermissionPolicy,
requests_cls=MyWorkflowRequests,
)
}


@pytest.fixture
def mappings():
# update the mappings
Expand All @@ -88,7 +88,6 @@ def mappings():
ThesisRecord.index.refresh()



@pytest.fixture
def record_service(mappings):
from thesis.proxies import current_service
Expand All @@ -102,14 +101,16 @@ def state_change_function():

return current_oarepo_workflows.set_state


@pytest.fixture(scope="module")
def extra_entry_points():
return {
'oarepo_workflows.default_workflow_getters': [
'test_getter = tests.utils:get_default_workflow',
"oarepo_workflows.default_workflow_getters": [
"test_getter = tests.utils:get_default_workflow",
]
}


@pytest.fixture(scope="module")
def create_app(instance_path, entry_points):
"""Application factory fixture."""
Expand Down
Loading

0 comments on commit 336346d

Please sign in to comment.