Files
notifications-admin/app/notify_client/service_api_client.py
Chris Hill-Scott 2cecadfcbc Add flake8 linting to project
The GDS Way™[1] recommends using Flake8 to lint Python projects.

This commit takes the Flake8 config from Digital Marketplace API[2] and
removes the bits we don’t need.

It changes the `max_complexity` setting to 14, which is the most complex
code we have in this repo currently (we shouldn’t be writing code _more_
complex than what we already have).

This commit also fixes the errors found by Flake8, which includes 6(!)
tests which were never getting run because they had the same names as
existing tests.

Here is a full list of the errors that were found and fixed:
```
./app/__init__.py:2:1: F401 're' imported but unused
./app/__init__.py:4:1: F401 'json' imported but unused
./app/__init__.py:8:1: F401 'dateutil' imported but unused
./app/__init__.py:11:1: F401 'flask.escape' imported but unused
./app/__init__.py:41:1: F401 'app.proxy_fix' imported but unused
./app/__init__.py:129:5: F821 undefined name 'proxy_fix'
./app/__init__.py:221:19: F821 undefined name 'highlight'
./app/__init__.py:221:35: F821 undefined name 'JavascriptLexer'
./app/__init__.py:221:54: F821 undefined name 'HtmlFormatter'
./app/config.py:2:1: F401 'datetime.timedelta' imported but unused
./app/event_handlers.py:2:1: F401 'flask_login.current_user' imported but unused
./app/utils.py:11:1: F401 'dateutil.parser' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.two_factor' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.notifications' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.add_service' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.forgot_password' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.inbound_number' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.styleguide' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.organisations' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.letter_jobs' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.verify' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.conversation' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.api_keys' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.send' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.dashboard' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.jobs' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.manage_users' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.sign_in' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.sign_out' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.code_not_received' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.invites' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.platform_admin' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.providers' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.service_settings' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.index' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.new_password' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.user_profile' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.feedback' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.choose_service' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.templates' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.register' imported but unused
./app/main/forms.py:12:1: F401 'wtforms.SelectField' imported but unused
./app/main/views/api_keys.py:37:29: E241 multiple spaces after ':'
./app/main/views/feedback.py:3:1: F401 'flask.flash' imported but unused
./app/main/views/feedback.py:122:17: E123 closing bracket does not match indentation of opening bracket's line
./app/main/views/inbound_number.py:1:1: F401 'flask.url_for' imported but unused
./app/main/views/inbound_number.py:1:1: F401 'flask.session' imported but unused
./app/main/views/inbound_number.py:1:1: F401 'flask.redirect' imported but unused
./app/main/views/inbound_number.py:1:1: F401 'flask.request' imported but unused
./app/main/views/inbound_number.py:13:1: F401 'flask.jsonify' imported but unused
./app/main/views/jobs.py:31:1: F401 'app.utils.get_template' imported but unused
./app/main/views/letter_jobs.py:1:1: F401 'datetime' imported but unused
./app/main/views/letter_jobs.py:6:1: F401 'app.format_datetime_24h' imported but unused
./app/main/views/manage_users.py:111:9: E123 closing bracket does not match indentation of opening bracket's line
./app/main/views/notifications.py:121:5: F841 local variable 'status_args' is assigned to but never used
./app/main/views/organisations.py:1:1: F401 'flask.request' imported but unused
./app/main/views/service_settings.py:77:9: E123 closing bracket does not match indentation of opening bracket's line
./app/main/views/service_settings.py:82:9: E123 closing bracket does not match indentation of opening bracket's line
./app/main/views/service_settings.py:420:13: E123 closing bracket does not match indentation of opening bracket's line
./app/main/views/sign_in.py:12:1: F401 'flask_login.confirm_login' imported but unused
./app/main/views/sign_in.py:17:1: F401 'app.service_api_client' imported but unused
./app/main/views/sign_in.py:62:13: E123 closing bracket does not match indentation of opening bracket's line
./app/main/views/templates.py:4:1: F401 'flask.json' imported but unused
./app/main/views/templates.py:17:1: F401 'notifications_utils.formatters.escape_html' imported but unused
./app/main/views/templates.py:23:1: F401 'app.utils.get_help_argument' imported but unused
./app/main/views/templates.py:64:13: E123 closing bracket does not match indentation of opening bracket's line
./app/notify_client/service_api_client.py:6:1: F401 '.notification_api_client' imported but unused
./app/notify_client/user_api_client.py:1:1: F401 'uuid' imported but unused
./app/notify_client/user_api_client.py:3:1: F401 'flask.session' imported but unused
./tests/__init__.py:1:1: F401 'csv' imported but unused
./tests/app/main/test_asset_fingerprinter.py:2:1: F401 'os' imported but unused
./tests/app/main/test_asset_fingerprinter.py:4:1: F401 'unittest.mock' imported but unused
./tests/app/main/test_asset_fingerprinter.py:98:9: F841 local variable 'string_with_unicode_character' is assigned to but never used
./tests/app/main/test_errorhandlers.py:2:1: F401 'flask.url_for' imported but unused
./tests/app/main/test_permissions.py:26:13: F841 local variable 'response' is assigned to but never used
./tests/app/main/test_placeholder_form.py:3:1: F401 'wtforms.Label' imported but unused
./tests/app/main/test_placeholder_form.py:11:10: F841 local variable 'req' is assigned to but never used
./tests/app/main/test_two_factor_form.py:10:67: F841 local variable 'req' is assigned to but never used
./tests/app/main/test_two_factor_form.py:23:65: F841 local variable 'req' is assigned to but never used
./tests/app/main/test_two_factor_form.py:37:48: F841 local variable 'req' is assigned to but never used
./tests/app/main/test_two_factor_form.py:51:67: F841 local variable 'req' is assigned to but never used
./tests/app/main/test_two_factor_form.py:65:67: F841 local variable 'req' is assigned to but never used
./tests/app/main/views/test_accept_invite.py:356:5: F841 local variable 'element' is assigned to but never used
./tests/app/main/views/test_activity.py:11:1: F811 redefinition of unused 'mock_get_notifications' from line 11
./tests/app/main/views/test_activity.py:18:1: F401 'datetime.datetime' imported but unused
./tests/app/main/views/test_activity.py:102:5: F841 local variable 'content' is assigned to but never used
./tests/app/main/views/test_activity.py:104:5: F841 local variable 'notification' is assigned to but never used
./tests/app/main/views/test_activity.py:337:5: F841 local variable '_notifications_mock' is assigned to but never used
./tests/app/main/views/test_activity.py:373:13: E126 continuation line over-indented for hanging indent
./tests/app/main/views/test_activity.py:378:9: E121 continuation line under-indented for hanging indent
./tests/app/main/views/test_activity.py:404:13: E126 continuation line over-indented for hanging indent
./tests/app/main/views/test_activity.py:407:9: E121 continuation line under-indented for hanging indent
./tests/app/main/views/test_api_keys.py:354:5: F841 local variable 'response' is assigned to but never used
./tests/app/main/views/test_conversation.py:5:1: F401 'bs4.BeautifulSoup' imported but unused
./tests/app/main/views/test_conversation.py:198:5: F841 local variable 'mock_get_inbound_sms' is assigned to but never used
./tests/app/main/views/test_dashboard.py:53:5: F841 local variable 'mock_template_stats' is assigned to but never used
./tests/app/main/views/test_dashboard.py:72:5: F841 local variable 'mock_template_stats' is assigned to but never used
./tests/app/main/views/test_jobs.py:2:1: F401 'uuid' imported but unused
./tests/app/main/views/test_jobs.py:3:1: F401 'urllib.parse.urlparse' imported but unused
./tests/app/main/views/test_jobs.py:3:1: F401 'urllib.parse.quote' imported but unused
./tests/app/main/views/test_jobs.py:3:1: F401 'urllib.parse.parse_qs' imported but unused
./tests/app/main/views/test_jobs.py:9:1: F401 'app.main.views.jobs.get_status_filters' imported but unused
./tests/app/main/views/test_jobs.py:10:1: F401 'tests.notification_json' imported but unused
./tests/app/main/views/test_letters.py:6:1: F401 'tests.service_json' imported but unused
./tests/app/main/views/test_notifications.py:5:1: F401 'app.utils.REQUESTED_STATUSES' imported but unused
./tests/app/main/views/test_notifications.py:5:1: F401 'app.utils.DELIVERED_STATUSES' imported but unused
./tests/app/main/views/test_notifications.py:5:1: F401 'app.utils.SENDING_STATUSES' imported but unused
./tests/app/main/views/test_notifications.py:5:1: F401 'app.utils.FAILURE_STATUSES' imported but unused
./tests/app/main/views/test_platform_admin.py:242:13: E126 continuation line over-indented for hanging indent
./tests/app/main/views/test_platform_admin.py:247:13: E126 continuation line over-indented for hanging indent
./tests/app/main/views/test_send.py:3:1: F401 'unittest.mock.Mock' imported but unused
./tests/app/main/views/test_send.py:18:1: F811 redefinition of unused 'mock_get_service' from line 18
./tests/app/main/views/test_send.py:18:1: F401 'tests.conftest.multiple_letter_contact_blocks' imported but unused
./tests/app/main/views/test_send.py:18:1: F401 'tests.conftest.no_sms_senders' imported but unused
./tests/app/main/views/test_send.py:18:1: F401 'tests.conftest.multiple_sms_senders' imported but unused
./tests/app/main/views/test_send.py:18:1: F401 'tests.conftest.no_letter_contact_blocks' imported but unused
./tests/app/main/views/test_send.py:102:5: F841 local variable 'response' is assigned to but never used
./tests/app/main/views/test_send.py:870:5: F841 local variable 'response' is assigned to but never used
./tests/app/main/views/test_send.py:1367:5: F841 local variable 'service_id' is assigned to but never used
./tests/app/main/views/test_send.py:1451:13: E126 continuation line over-indented for hanging indent
./tests/app/main/views/test_send.py:1620:80: E226 missing whitespace around arithmetic operator
./tests/app/main/views/test_send.py:1909:13: E126 continuation line over-indented for hanging indent
./tests/app/main/views/test_send.py:1912:9: E121 continuation line under-indented for hanging indent
./tests/app/main/views/test_service_settings.py:13:1: F811 redefinition of unused 'no_reply_to_email_addresses' from line 13
./tests/app/main/views/test_service_settings.py:13:1: F401 'tests.conftest.single_reply_to_email_address' imported but unused
./tests/app/main/views/test_service_settings.py:28:5: E123 closing bracket does not match indentation of opening bracket's line
./tests/app/main/views/test_service_settings.py:104:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:166:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:186:5: F841 local variable 'mocked_get_fn' is assigned to but never used
./tests/app/main/views/test_service_settings.py:217:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:237:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:257:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:307:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:340:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:466:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:555:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:615:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:719:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:874:5: F841 local variable 'page' is assigned to but never used
./tests/app/main/views/test_service_settings.py:902:5: F841 local variable 'page' is assigned to but never used
./tests/app/main/views/test_service_settings.py:954:5: F841 local variable 'page' is assigned to but never used
./tests/app/main/views/test_service_settings.py:986:5: F841 local variable 'page' is assigned to but never used
./tests/app/main/views/test_service_settings.py:1101:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:1121:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:1271:1: F811 redefinition of unused 'test_set_letter_contact_block_saves' from line 1189
./tests/app/main/views/test_service_settings.py:1433:5: F841 local variable 'page' is assigned to but never used
./tests/app/main/views/test_service_settings.py:1495:5: F841 local variable 'mocked_get_fn' is assigned to but never used
./tests/app/main/views/test_service_settings.py:1540:5: F841 local variable 'mocked_get_fn' is assigned to but never used
./tests/app/main/views/test_service_settings.py:1570:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:1589:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:1621:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:1641:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:1658:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:1676:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:1697:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:1759:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:1775:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_templates.py:3:1: F401 'uuid' imported but unused
./tests/app/main/views/test_templates.py:11:1: F401 'tests.conftest.mock_get_user' imported but unused
./tests/app/main/views/test_templates.py:514:1: F811 redefinition of unused 'mock_get_user' from line 11
./tests/app/main/views/test_templates.py:672:1: F811 redefinition of unused 'mock_get_user' from line 11
./tests/app/main/views/test_templates.py:795:1: F811 redefinition of unused 'mock_get_user' from line 11
./tests/app/main/views/test_templates.py:835:1: F811 redefinition of unused 'mock_get_user' from line 11
./tests/app/main/views/test_two_factor.py:67:13: E126 continuation line over-indented for hanging indent
./tests/app/notify_client/test_notification_client.py:79:5: F841 local variable 'mock_post' is assigned to but never used
```

1. https://gds-way.cloudapps.digital/manuals/programming-languages/python/linting.html#how-to-use-flake8
2. d5ab8afef4/.flake8
2017-10-20 11:02:39 +01:00

373 lines
12 KiB
Python

from __future__ import unicode_literals
from flask import url_for
from app.utils import BrowsableItem
from app.notify_client import _attach_current_user, NotifyAdminAPIClient
class ServiceAPIClient(NotifyAdminAPIClient):
# Fudge assert in the super __init__ so
# we can set those variables later.
def __init__(self):
super().__init__("a" * 73, "b")
def init_app(self, application):
self.base_url = application.config['API_HOST_NAME']
self.service_id = application.config['ADMIN_CLIENT_USER_NAME']
self.api_key = application.config['ADMIN_CLIENT_SECRET']
def create_service(self, service_name, message_limit, restricted, user_id, email_from):
"""
Create a service and return the json.
"""
data = {
"name": service_name,
"active": True,
"message_limit": message_limit,
"user_id": user_id,
"restricted": restricted,
"email_from": email_from
}
data = _attach_current_user(data)
return self.post("/service", data)['data']['id']
def get_service(self, service_id):
return self._get_service(service_id, detailed=False, today_only=False)
def get_detailed_service(self, service_id):
return self._get_service(service_id, detailed=True, today_only=False)
def get_detailed_service_for_today(self, service_id):
return self._get_service(service_id, detailed=True, today_only=True)
def _get_service(self, service_id, detailed, today_only):
"""
Retrieve a service.
:param detailed - return additional details, including notification statistics
:param today_only - return statistics only for today. No effect if detailed not passed in
"""
params = {}
if detailed:
params['detailed'] = detailed
if today_only:
params['today_only'] = today_only
return self.get(
'/service/{0}'.format(service_id),
params=params)
def get_services(self, params_dict=None):
"""
Retrieve a list of services.
"""
return self.get('/service', params=params_dict)
def get_active_services(self, params_dict=None):
"""
Retrieve a list of active services.
"""
params_dict['only_active'] = True
return self.get_services(params_dict)
def update_service(
self,
service_id,
**kwargs
):
"""
Update a service.
"""
data = _attach_current_user(kwargs)
disallowed_attributes = set(data.keys()) - {
'name',
'message_limit',
'active',
'restricted',
'email_from',
'reply_to_email_address',
'research_mode',
'sms_sender',
'created_by',
'branding',
'organisation',
'letter_contact_block',
'dvla_organisation',
'permissions'
}
if disallowed_attributes:
raise TypeError('Not allowed to update service attributes: {}'.format(
", ".join(disallowed_attributes)
))
endpoint = "/service/{0}".format(service_id)
return self.post(endpoint, data)
def update_service_with_properties(self, service_id, properties):
return self.update_service(service_id, **properties)
def archive_service(self, service_id):
return self.post('/service/{}/archive'.format(service_id), data=None)
def suspend_service(self, service_id):
return self.post('/service/{}/suspend'.format(service_id), data=None)
def resume_service(self, service_id):
return self.post('/service/{}/resume'.format(service_id), data=None)
def remove_user_from_service(self, service_id, user_id):
"""
Remove a user from a service
"""
endpoint = '/service/{service_id}/users/{user_id}'.format(
service_id=service_id,
user_id=user_id)
data = _attach_current_user({})
return self.delete(endpoint, data)
def create_service_template(self, name, type_, content, service_id, subject=None, process_type='normal'):
"""
Create a service template.
"""
data = {
"name": name,
"template_type": type_,
"content": content,
"service": service_id,
"process_type": process_type
}
if subject:
data.update({
'subject': subject
})
data = _attach_current_user(data)
endpoint = "/service/{0}/template".format(service_id)
return self.post(endpoint, data)
def update_service_template(self, id_, name, type_, content, service_id, subject=None, process_type=None):
"""
Update a service template.
"""
data = {
'id': id_,
'name': name,
'template_type': type_,
'content': content,
'service': service_id
}
if subject:
data.update({
'subject': subject
})
if process_type:
data.update({
'process_type': process_type
})
data = _attach_current_user(data)
endpoint = "/service/{0}/template/{1}".format(service_id, id_)
return self.post(endpoint, data)
def redact_service_template(self, service_id, id_):
return self.post(
"/service/{}/template/{}".format(service_id, id_),
_attach_current_user(
{'redact_personalisation': True}
),
)
def get_service_template(self, service_id, template_id, version=None, *params):
"""
Retrieve a service template.
"""
endpoint = '/service/{service_id}/template/{template_id}'.format(
service_id=service_id,
template_id=template_id)
if version:
endpoint = '{base}/version/{version}'.format(base=endpoint, version=version)
return self.get(endpoint, *params)
def get_service_template_versions(self, service_id, template_id, *params):
"""
Retrieve a list of versions for a template
"""
endpoint = '/service/{service_id}/template/{template_id}/versions'.format(
service_id=service_id,
template_id=template_id
)
return self.get(endpoint, *params)
def get_service_templates(self, service_id, *params):
"""
Retrieve all templates for service.
"""
endpoint = '/service/{service_id}/template'.format(
service_id=service_id)
return self.get(endpoint, *params)
def delete_service_template(self, service_id, template_id):
"""
Set a service template's archived flag to True
"""
endpoint = "/service/{0}/template/{1}".format(service_id, template_id)
data = {
'archived': True
}
data = _attach_current_user(data)
return self.post(endpoint, data=data)
def is_service_name_unique(self, name, email_from):
"""
Check that the service name or email from are unique across all services.
"""
endpoint = "/service/unique"
params = {"name": name, "email_from": email_from}
return self.get(url=endpoint, params=params)["result"]
# Temp access of service history data. Includes service and api key history
def get_service_history(self, service_id):
return self.get('/service/{0}/history'.format(service_id))
def get_monthly_notification_stats(self, service_id, year):
return self.get(url='/service/{}/notifications/monthly?year={}'.format(service_id, year))
def get_whitelist(self, service_id):
return self.get(url='/service/{}/whitelist'.format(service_id))
def update_whitelist(self, service_id, data):
return self.put(url='/service/{}/whitelist'.format(service_id), data=data)
def get_inbound_sms(self, service_id, user_number=''):
return self.get(
'/service/{}/inbound-sms?user_number={}'.format(
service_id,
user_number,
)
)['data']
def get_inbound_sms_by_id(self, service_id, notification_id):
return self.get(
'/service/{}/inbound-sms/{}'.format(
service_id,
notification_id,
)
)
def get_inbound_sms_summary(self, service_id):
return self.get(
'/service/{}/inbound-sms/summary'.format(service_id)
)
def create_service_inbound_api(self, service_id, url, bearer_token, user_id):
data = {
"url": url,
"bearer_token": bearer_token,
"updated_by_id": user_id
}
return self.post("/service/{}/inbound-api".format(service_id), data)
def update_service_inbound_api(self, service_id, url, bearer_token, user_id, inbound_api_id):
data = {
"url": url,
"updated_by_id": user_id
}
if bearer_token:
data['bearer_token'] = bearer_token
return self.post("/service/{}/inbound-api/{}".format(service_id, inbound_api_id), data)
def get_service_inbound_api(self, service_id, inbound_sms_api_id):
return self.get(
"/service/{}/inbound-api/{}".format(
service_id, inbound_sms_api_id
)
)['data']
def get_reply_to_email_addresses(self, service_id):
return self.get(
"/service/{}/email-reply-to".format(
service_id
)
)
def get_reply_to_email_address(self, service_id, reply_to_email_id):
return self.get(
"/service/{}/email-reply-to/{}".format(
service_id,
reply_to_email_id
)
)
def add_reply_to_email_address(self, service_id, email_address, is_default=False):
return self.post(
"/service/{}/email-reply-to".format(service_id),
data={
"email_address": email_address,
"is_default": is_default
}
)
def update_reply_to_email_address(self, service_id, reply_to_email_id, email_address, is_default=False):
return self.post(
"/service/{}/email-reply-to/{}".format(
service_id,
reply_to_email_id,
),
data={
"email_address": email_address,
"is_default": is_default
}
)
def get_letter_contacts(self, service_id):
return self.get(
"/service/{}/letter-contact".format(
service_id
)
)
def get_letter_contact(self, service_id, letter_contact_id):
return self.get(
"/service/{}/letter-contact/{}".format(
service_id,
letter_contact_id
)
)
def add_letter_contact(self, service_id, contact_block, is_default=False):
return self.post(
"/service/{}/letter-contact".format(service_id),
data={
"contact_block": contact_block,
"is_default": is_default
}
)
def update_letter_contact(self, service_id, letter_contact_id, contact_block, is_default=False):
return self.post(
"/service/{}/letter-contact/{}".format(
service_id,
letter_contact_id,
),
data={
"contact_block": contact_block,
"is_default": is_default
}
)
class ServicesBrowsableItem(BrowsableItem):
@property
def title(self):
return self._item['name']
@property
def link(self):
return url_for('main.service_dashboard', service_id=self._item['id'])
@property
def destructive(self):
return False
@property
def hint(self):
return None