Skip to content
Draft
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
22 changes: 22 additions & 0 deletions docs/reference/experimental/async/form.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# FormGroup and Form

Contained within this file are experimental interfaces for working with the Synapse Python
Client. Unless otherwise noted these interfaces are subject to change at any time. Use
at your own risk.

## API Reference

::: synapseclient.models.FormGroup
options:
inherited_members: true
members:
- create_async


::: synapseclient.models.FormData
options:
inherited_members: true
members:
- create_async
- list_async
- download_async
1 change: 1 addition & 0 deletions docs/reference/experimental/mixins/form_data.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
::: synapseclient.models.mixins.FormData
1 change: 1 addition & 0 deletions docs/reference/experimental/mixins/form_group.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
::: synapseclient.models.mixins.FormGroup
22 changes: 22 additions & 0 deletions docs/reference/experimental/sync/form.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# FormGroup and Form

Contained within this file are experimental interfaces for working with the Synapse Python
Client. Unless otherwise noted these interfaces are subject to change at any time. Use
at your own risk.

## API Reference

::: synapseclient.models.FormGroup
options:
inherited_members: true
members:
- create


::: synapseclient.models.FormData
options:
inherited_members: true
members:
- create
- list
- download
4 changes: 4 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ nav:
- Functional Interfaces: reference/experimental/functional_interfaces.md
- SchemaOrganization: reference/experimental/sync/schema_organization.md
- JSONSchema: reference/experimental/sync/json_schema.md
- FormGroup and Form: reference/experimental/sync/form.md
- Extensions:
- Curator: reference/extensions/curator.md
- Asynchronous:
Expand All @@ -128,13 +129,16 @@ nav:
- Link: reference/experimental/async/link_entity.md
- SchemaOrganization: reference/experimental/async/schema_organization.md
- JSONSchema: reference/experimental/async/json_schema.md
- FormGroup and Form: reference/experimental/async/form.md
- Mixins:
- AccessControllable: reference/experimental/mixins/access_controllable.md
- StorableContainer: reference/experimental/mixins/storable_container.md
- AsynchronousCommunicator: reference/experimental/mixins/asynchronous_communicator.md
- FailureStrategy: reference/experimental/mixins/failure_strategy.md
- BaseJSONSchema: reference/experimental/mixins/base_json_schema.md
- ContainerEntityJSONSchema: reference/experimental/mixins/container_json_schema.md
- FormData: reference/experimental/mixins/form_data.md
- FormGroup: reference/experimental/mixins/form_group.md

- Further Reading:
- Home: explanations/home.md
Expand Down
9 changes: 9 additions & 0 deletions synapseclient/api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@
put_file_multipart_add,
put_file_multipart_complete,
)
from .form_services import (
create_form_data_async,
create_form_group_async,
list_form_data_async,
)
from .json_schema_services import (
bind_json_schema_to_entity,
create_organization,
Expand Down Expand Up @@ -282,4 +287,8 @@
"get_evaluation_acl",
"update_evaluation_acl",
"get_evaluation_permissions",
# form services
"create_form_group_async",
"create_form_data_async",
"list_form_data_async",
]
173 changes: 173 additions & 0 deletions synapseclient/api/form_services.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
import json
from typing import TYPE_CHECKING, Any, AsyncGenerator, Generator, Optional

from synapseclient.api.api_client import rest_post_paginated_async
from synapseclient.core.async_utils import wrap_async_generator_to_sync_generator

if TYPE_CHECKING:
from synapseclient import Synapse
from synapseclient.models.mixins.form import StateEnum


async def create_form_group_async(
synapse_client: "Synapse",
name: str,
) -> dict[str, Any]:
"""
<https://rest-docs.synapse.org/rest/POST/form/group.html>
Create a form group asynchronously.

Arguments:
synapse_client: The Synapse client to use for the request.
name: A globally unique name for the group. Required. Between 3 and 256 characters.

Returns:
A Form group object as a dictionary.
Object matching <https://rest-docs.synapse.org/rest/org/sagebionetworks/repo/model/form/FormGroup.html>
"""
from synapseclient import Synapse

client = Synapse.get_client(synapse_client=synapse_client)

return await client.rest_post_async(uri=f"/form/group?name={name}", body={})


async def create_form_data_async(
synapse_client: "Synapse",
group_id: str,
form_change_request: dict[str, Any],
) -> dict[str, Any]:
"""
<https://rest-docs.synapse.org/rest/POST/form/data.html>
Create a new FormData object. The caller will own the resulting object and will have access to read, update, and delete the FormData object.

Arguments:
synapse_client: The Synapse client to use for the request.
group_id: The ID of the form group.
form_change_request: a dictionary of form change request matching <https://rest-docs.synapse.org/rest/org/sagebionetworks/repo/model/form/FormChangeRequest.html>.

Returns:
A Form data object as a dictionary.
Object matching <https://rest-docs.synapse.org/rest/org/sagebionetworks/repo/model/form/FormData.html>

Note: The caller must have the SUBMIT permission on the FormGroup to create/update/submit FormData.
"""
from synapseclient import Synapse

client = Synapse.get_client(synapse_client=synapse_client)

return await client.rest_post_async(
uri=f"/form/data?groupId={group_id}",
body=json.dumps(form_change_request),
)


async def list_form_data_async(
synapse_client: "Synapse",
group_id: str,
filter_by_state: Optional[list["StateEnum"]] = None,
as_reviewer: bool = False,
) -> AsyncGenerator[dict[str, Any], None]:
"""
List FormData objects and their associated status that match the filters of the provided request.

When as_reviewer=False: <https://rest-docs.synapse.org/rest/POST/form/data/list.html>
Returns FormData objects owned by the caller. Only objects owned by the caller will be returned.

When as_reviewer=True: <https://rest-docs.synapse.org/rest/POST/form/data/list/reviewer.html>
Returns FormData objects for the entire group. This is used by service accounts to review submissions.
Requires READ_PRIVATE_SUBMISSION permission on the FormGroup.

Arguments:
synapse_client: The Synapse client to use for the request.
group_id: The ID of the form group. Required.
filter_by_state: Optional list of StateEnum values to filter the FormData objects.
When as_reviewer=False (default), valid values are:
- StateEnum.WAITING_FOR_SUBMISSION
- StateEnum.SUBMITTED_WAITING_FOR_REVIEW
- StateEnum.ACCEPTED
- StateEnum.REJECTED
If None, returns all FormData objects.

When as_reviewer=True, valid values are:
- StateEnum.SUBMITTED_WAITING_FOR_REVIEW (default if None)
- StateEnum.ACCEPTED
- StateEnum.REJECTED
Note: WAITING_FOR_SUBMISSION is NOT allowed when as_reviewer=True.

as_reviewer: If True, uses the reviewer endpoint to list FormData for the entire group.
If False (default), lists only FormData owned by the caller.

Yields:
A single page of FormData objects matching the request.
Object matching <https://rest-docs.synapse.org/rest/org/sagebionetworks/repo/model/form/ListResponse.html>
"""
from synapseclient import Synapse

client = Synapse.get_client(synapse_client=synapse_client)

body: dict[str, Any] = {"groupId": group_id, "filterByState": filter_by_state}

if as_reviewer:
uri = "/form/data/list/reviewer"
else:
uri = "/form/data/list"

async for item in rest_post_paginated_async(
uri=uri,
body=body,
synapse_client=client,
):
yield item


def list_form_data_sync(
synapse_client: "Synapse",
group_id: str,
filter_by_state: Optional[list["StateEnum"]] = None,
as_reviewer: bool = False,
) -> Generator[dict[str, Any], None, None]:
"""
List FormData objects and their associated status that match the filters of the provided request.

This is the synchronous version of list_form_data_async.

When as_reviewer=False: <https://rest-docs.synapse.org/rest/POST/form/data/list.html>
Returns FormData objects owned by the caller. Only objects owned by the caller will be returned.

When as_reviewer=True: <https://rest-docs.synapse.org/rest/POST/form/data/list/reviewer.html>
Returns FormData objects for the entire group. This is used by service accounts to review submissions.
Requires READ_PRIVATE_SUBMISSION permission on the FormGroup.

Arguments:
synapse_client: The Synapse client to use for the request.
group_id: The ID of the form group. Required.
filter_by_state: Optional list of StateEnum values to filter the FormData objects.
When as_reviewer=False (default), valid values are:
- StateEnum.WAITING_FOR_SUBMISSION
- StateEnum.SUBMITTED_WAITING_FOR_REVIEW
- StateEnum.ACCEPTED
- StateEnum.REJECTED
If None, returns all FormData objects.

When as_reviewer=True, valid values are:
- StateEnum.SUBMITTED_WAITING_FOR_REVIEW (default if None)
- StateEnum.ACCEPTED
- StateEnum.REJECTED
Note: WAITING_FOR_SUBMISSION is NOT allowed when as_reviewer=True.

as_reviewer: If True, uses the reviewer endpoint to list FormData for the entire group.
If False (default), lists only FormData owned by the caller.

Yields:
A single page of FormData objects matching the request.
Object matching <https://rest-docs.synapse.org/rest/org/sagebionetworks/repo/model/form/ListResponse.html>
"""
return wrap_async_generator_to_sync_generator(
list_form_data_async(
synapse_client=synapse_client,
group_id=group_id,
filter_by_state=filter_by_state,
as_reviewer=as_reviewer,
)
)
4 changes: 4 additions & 0 deletions synapseclient/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from synapseclient.models.evaluation import Evaluation
from synapseclient.models.file import File, FileHandle
from synapseclient.models.folder import Folder
from synapseclient.models.form import FormData, FormGroup
from synapseclient.models.link import Link
from synapseclient.models.materializedview import MaterializedView
from synapseclient.models.mixins.table_components import QueryMixin
Expand Down Expand Up @@ -132,6 +133,9 @@
# JSON Schema models
"SchemaOrganization",
"JSONSchema",
# Form models
"FormGroup",
"FormData",
]

# Static methods to expose as functions
Expand Down
Loading
Loading