Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: adds get sign template and get sign templates methods on Client #835

Merged
merged 6 commits into from
Sep 6, 2023
Merged
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
55 changes: 55 additions & 0 deletions boxsdk/client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
from boxsdk.object.group_membership import GroupMembership
from boxsdk.object.enterprise import Enterprise
from boxsdk.object.collection import Collection
from boxsdk.object.sign_template import SignTemplate
from boxsdk.pagination.box_object_collection import BoxObjectCollection


Expand Down Expand Up @@ -1629,3 +1630,57 @@ def get_sign_requests(
fields=fields,
return_full_pages=False,
)

def sign_template(self, sign_template_id: str) -> 'SignTemplate':
"""
Initialize a :class:`SignTemplate` object, whose box id is sign_template_id.

:param sign_template_id:
The box id of the :class:`SignTemplate` object.
:return:
A :class:`SignTemplate` object with the given sign_template_id.
"""
return self.translator.get('sign_template')(session=self._session, object_id=sign_template_id)

@api_call
def get_sign_templates(
self,
limit: Optional[int] = None,
marker: Optional[str] = None,
) -> 'BoxObjectCollection':
"""
Returns all sign templates

:param limit:
The maximum number of entries to return per page. If not specified, then will use the server-side default.
:param marker:
The paging marker to start paging from.
:returns:
Sign templates
"""
return MarkerBasedObjectCollection(
session=self._session,
url=self.get_url("sign_templates"),
limit=limit,
marker=marker,
return_full_pages=False,
)

@api_call
def get_sign_template(
self,
sign_template_id: str,
) -> Any:
"""
Returns a sign template

:param sign_template_id:
ID of Sign template to fetch
:returns:
Sign template
"""
response = self._session.get(f"{self._session.get_url('sign_templates')}/{sign_template_id}")
return self.translator.translate(
session=self._session,
response_object=response.json(),
)
16 changes: 16 additions & 0 deletions boxsdk/object/sign_template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from typing import Any

from .base_object import BaseObject


class SignTemplate(BaseObject):
"""
Represents a Sign Template used by Box Sign
"""
_item_type = 'sign-template'

def get_url(self, *args: Any) -> str:
"""
Returns the url for this sign template.
"""
return self._session.get_url('sign_templates', self._object_id, *args)
16 changes: 16 additions & 0 deletions docs/source/boxsdk.object.rst
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,14 @@ boxsdk.object.file module
:undoc-members:
:show-inheritance:

boxsdk.object.file\_request module
----------------------------------

.. automodule:: boxsdk.object.file_request
:members:
:undoc-members:
:show-inheritance:

boxsdk.object.file\_version module
----------------------------------

Expand Down Expand Up @@ -300,6 +308,14 @@ boxsdk.object.sign\_request module
:undoc-members:
:show-inheritance:

boxsdk.object.sign\_template module
-----------------------------------

.. automodule:: boxsdk.object.sign_template
:members:
:undoc-members:
:show-inheritance:

boxsdk.object.storage\_policy module
------------------------------------

Expand Down
2 changes: 1 addition & 1 deletion docs/usage/sign_requests.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Get All Sign Requests
------------------------

Calling the [`client.get_sign_requests()`][get-all-sign-requests]
will return an iterable that will page through all the Sign Requests. This method offers `limit` and `fields` parameters. The `limit` parameter specifies the maximum number of items to be returned in a single response. The `fields` parameter is used to specify what additional properties should be returned on the return object. For more information on what `fields` are available, please refer to the [developer documentation](https://developer.box.com/guides/sign-request/).
will return an iterable that will page through all the Sign Requests. This method offers `limit` and `fields` parameters. The `limit` parameter specifies the maximum number of items to be returned in a single response. The `fields` parameter is used to specify what additional properties should be returned on the return object. For more information on what `fields` are available, please refer to the [developer documentation](https://developer.box.com/guides/box-sign/).

<!-- sample get_sign_requests -->
```python
Expand Down
39 changes: 39 additions & 0 deletions docs/usage/sign_templates.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
Sign Templates
==============

Sign Templates are reusable templates that can be used to create Sign Requests. For now, Sign Templates can only be created through the Box web application.

<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->

- [Get All Sign Templates](#get-all-sign-templates)
- [Get Sign Template by ID](#get-sign-template-by-id)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

Get All Sign Templates
----------------------

Calling the [`client.get_sign_templates()`][get-all-sign-templates] method will return an iterable that will page through all the Sign Templates. This method offers `limit` parameter. The `limit` parameter specifies the maximum number of items to be returned in a single response.

<!-- sample get_sign_templates -->
```python
sign_templates = client.get_sign_templates()
for sign_template in sign_templates:
print(f'(Sign Template ID: {sign_template.id})')
```

[get-all-sign-templates]: https://box-python-sdk.readthedocs.io/en/latest/boxsdk.client.html#boxsdk.client.client.Client.get_sign_templates

Get Sign Template by ID
-----------------------

Calling the [`client.get_sign_template(template_id)`][get-sign-template] method will return a Sign Template object.

<!-- sample get_sign_template -->
```python
sign_template = client.get_sign_template('12345')
print(f'(Sign Template ID: {sign_template.id})')
```

[get-sign-template]: https://box-python-sdk.readthedocs.io/en/latest/boxsdk.client.html#boxsdk.client.client.Client.get_sign_template
8 changes: 8 additions & 0 deletions test/integration_new/object/sign_template_itest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from boxsdk.pagination.box_object_collection import BoxObjectCollection

from test.integration_new import CLIENT


def test_get_sign_templates():
sign_templates = CLIENT.get_sign_templates()
assert isinstance(sign_templates, BoxObjectCollection)
150 changes: 150 additions & 0 deletions test/unit/client/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
from boxsdk.object.legal_hold_policy_assignment import LegalHoldPolicyAssignment
from boxsdk.object.metadata_cascade_policy import MetadataCascadePolicy
from boxsdk.object.sign_request import SignRequest
from boxsdk.object.sign_template import SignTemplate
from boxsdk.object.task import Task
from boxsdk.object.task_assignment import TaskAssignment
from boxsdk.object.webhook import Webhook
Expand Down Expand Up @@ -1663,6 +1664,105 @@ def mock_sign_request_response():
return mock_sign_request


@pytest.fixture(scope='module')
def mock_sign_template_response():
mock_sign_template = {
"id": "93153068-5420-467b-b8ef-8e54bfb7be42",
"type": "sign-template",
"name": "important-file.pdf",
"email_message": "Please sign this document.\n\nKind regards",
"email_subject": "Box User (boxuser@box.com) has requested your signature on a document",
"parent_folder": {
"id": "123456789",
"etag": "0",
"type": "folder",
"sequence_id": "0",
"name": "My Sign Requests"
},
"auto_expire_days": "null",
"source_files": [
{
"id": "123456",
"etag": "0",
"type": "file",
"sequence_id": "0",
"sha1": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"file_version": {
"id": "123456",
"type": "file_version",
"sha1": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}
}
],
"are_email_settings_locked": "false",
"are_fields_locked": "false",
"are_files_locked": "false",
"are_options_locked": "false",
"are_recipients_locked": "false",
"signers": [
{
"email": "",
"label": "",
"public_id": "AAQXQXJZ4",
"role": "final_copy_reader",
"is_in_person": "false",
"order": 1,
"inputs": []
},
{
"email": "",
"label": "",
"public_id": "13XQXJZ4",
"role": "signer",
"is_in_person": "false",
"order": 1,
"inputs": [
{
"document_tag_id": None,
"id": "0260f921-3b52-477f-ae74-0b0b0b0b0b0b",
"type": "signature",
"text_value": None,
"is_required": True,
"coordinates": {
"x": 0.27038464059712,
"y": 0.10051756244533624
},
"dimensions": {
"width": 0.23570031566618235,
"height": 0.04781003891921971
},
"date_value": None,
"page_index": 0,
"checkbox_value": None,
"document_id": "2fdf9003-d798-40ee-be7f-0b0b0b0b0b0b",
"content_type": "signature",
"dropdown_choices": None,
"group_id": None,
"label": None
}
]
}
],
"ready_sign_link": None,
"custom_branding": None,
"days_valid": 0,
"additional_info": {
"non_editable": [],
"required": {
"signers": [
[
"email"
],
[
"email"
]
]
}
}
}
return mock_sign_template


def test_get_sign_requests(mock_client, mock_box_session, mock_sign_request_response):
expected_url = f'{API.BASE_API_URL}/sign_requests'

Expand Down Expand Up @@ -1750,3 +1850,53 @@ def test_file_request(mock_client):

assert isinstance(file_request, FileRequest)
assert file_request.object_id == file_request_id


def test_get_sign_templates_from_id(mock_client, mock_box_session, mock_sign_template_response):
test_sign_template_id = '93153068-5420-467b-b8ef-8e54bfb7be42'
expected_url = f'{API.BASE_API_URL}/sign_templates/{test_sign_template_id}'
mock_box_session.get.return_value.json.return_value = mock_sign_template_response

sign_template = mock_client.sign_template(test_sign_template_id).get()

mock_box_session.get.assert_called_once_with(expected_url, headers=None, params=None)

assert isinstance(sign_template, SignTemplate)
assert sign_template.id == '93153068-5420-467b-b8ef-8e54bfb7be42'


def test_get_sign_template(mock_client, mock_box_session, mock_sign_template_response):
test_sign_template_id = '93153068-5420-467b-b8ef-8e54bfb7be42'
expected_url = f'{API.BASE_API_URL}/sign_templates/{test_sign_template_id}'
mock_box_session.get.return_value.json.return_value = mock_sign_template_response

sign_template = mock_client.get_sign_template(test_sign_template_id)

mock_box_session.get.assert_called_once_with(expected_url)

assert isinstance(sign_template, SignTemplate)
assert sign_template.id == '93153068-5420-467b-b8ef-8e54bfb7be42'
assert sign_template.name == 'important-file.pdf'
assert sign_template.email_message == 'Please sign this document.\n\nKind regards'


def test_get_sign_templates(mock_client, mock_box_session, mock_sign_template_response):
expected_url = f'{API.BASE_API_URL}/sign_templates'

mock_sign_template = mock_sign_template_response
mock_box_session.get.return_value.json.return_value = {
'total_count': 1,
'limit': 100,
'entries': [mock_sign_template],
'next_marker': None,
'previous_marker': None,
}

sign_templates = mock_client.get_sign_templates()

sign_template = sign_templates.next()

mock_box_session.get.assert_called_once_with(expected_url, params={})
assert isinstance(sign_template, SignTemplate)
assert sign_template.id == '93153068-5420-467b-b8ef-8e54bfb7be42'
assert sign_template.name == 'important-file.pdf'
6 changes: 6 additions & 0 deletions test/unit/object/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from boxsdk.object.retention_policy_assignment import RetentionPolicyAssignment
from boxsdk.object.search import Search
from boxsdk.object.sign_request import SignRequest
from boxsdk.object.sign_template import SignTemplate
from boxsdk.object.storage_policy import StoragePolicy
from boxsdk.object.storage_policy_assignment import StoragePolicyAssignment
from boxsdk.object.terms_of_service import TermsOfService
Expand Down Expand Up @@ -420,3 +421,8 @@ def test_sign_request(mock_box_session, mock_object_id):
@pytest.fixture()
def test_file_request(mock_box_session, mock_object_id):
return FileRequest(mock_box_session, mock_object_id)


@pytest.fixture()
def test_sign_template(mock_box_session, mock_object_id):
return SignTemplate(mock_box_session, mock_object_id)
Loading
Loading