general: automatically generate endpoints panel (#17691)
This commit is contained in:
parent
8776d64bc3
commit
ba46913719
|
@ -1,3 +1,4 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# passerelle - uniform access to multiple data sources and services
|
||||
# Copyright (C) 2017 Entr'ouvert
|
||||
#
|
||||
|
@ -26,11 +27,20 @@ from passerelle.utils.api import endpoint
|
|||
|
||||
class AirQuality(BaseResource):
|
||||
category = _('Misc')
|
||||
api_description = _(u'''
|
||||
This API provides a unique format for the air quality data of various places.
|
||||
(But only supports the Rhône-Alpes region for now).
|
||||
''')
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('Air Quality')
|
||||
|
||||
@endpoint(pattern='^(?P<country>\w+)/(?P<city>\w+)/$')
|
||||
@endpoint(pattern='^(?P<country>\w+)/(?P<city>\w+)/$',
|
||||
example_pattern='{country}/{city}/',
|
||||
parameters={
|
||||
'country': {'description': _('Country Code'), 'example_value': 'fr'},
|
||||
'city': {'description': _('City Name'), 'example_value': 'lyon'},
|
||||
})
|
||||
def details(self, request, country, city, **kwargs):
|
||||
methods = {
|
||||
('fr', 'albertville'): 'air_rhonealpes',
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
{% extends "passerelle/manage/service_view.html" %}
|
||||
{% load i18n passerelle %}
|
||||
|
||||
{% block endpoints %}
|
||||
<p>
|
||||
{% blocktrans %}
|
||||
This API provides a unique format for the air quality data of various places.
|
||||
(But only supports the Rhône-Alpes region for now).
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>{% trans 'Details:' %} <a href="details/fr/lyon/"
|
||||
>{{ site_base_uri }}{{ object.get_absolute_url }}details/<i>country</i>/<i>city</i>/</a></li>
|
||||
</ul>
|
||||
{% endblock %}
|
||||
|
||||
{% block security %}
|
||||
<p>
|
||||
{% trans 'The data is open.' %}
|
||||
</p>
|
||||
{% endblock %}
|
|
@ -31,7 +31,7 @@ class Feed(BaseResource):
|
|||
class Meta:
|
||||
verbose_name = _('Feed')
|
||||
|
||||
@endpoint(perm='can_access')
|
||||
@endpoint(perm='can_access', description=_('Feed'))
|
||||
def json(self, request):
|
||||
response = self.requests.get(self.url)
|
||||
response.raise_for_status()
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
{% extends "passerelle/manage/service_view.html" %}
|
||||
{% load i18n passerelle %}
|
||||
|
||||
{% block endpoints %}
|
||||
<ul>
|
||||
<li>
|
||||
{% trans "Feed:" %}
|
||||
{% url "generic-endpoint" connector="feeds" slug=object.slug endpoint="json" as endpoint_path %}
|
||||
<a href="{{endpoint_path}}">{{endpoint_path}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endblock %}
|
|
@ -60,14 +60,18 @@ class JsonDataStore(BaseResource):
|
|||
class Meta:
|
||||
verbose_name = _('JSON Data Store')
|
||||
|
||||
@endpoint(perm='can_access', name='data', pattern=r'$')
|
||||
@endpoint(perm='can_access', name='data', pattern=r'$',
|
||||
description=_('Listing'))
|
||||
def list(self, request, name_id=None, **kwargs):
|
||||
objects = JsonData.objects.filter(datastore=self)
|
||||
if name_id:
|
||||
objects = objects.filter(name_id=name_id)
|
||||
return {'data': [{'id': x.uuid, 'text': x.text, 'content': x.content} for x in objects]}
|
||||
|
||||
@endpoint(perm='can_access', methods=['post'], name='data', pattern=r'create$')
|
||||
@endpoint(perm='can_access', methods=['post'], name='data',
|
||||
pattern=r'create$',
|
||||
example_pattern='create',
|
||||
description=_('Create'))
|
||||
def create(self, request, name_id=None, **kwargs):
|
||||
attrs = {
|
||||
'content': json.loads(request.body),
|
||||
|
@ -88,7 +92,13 @@ class JsonDataStore(BaseResource):
|
|||
attrs['name_id'] = name_id
|
||||
return JsonData.objects.get(**attrs)
|
||||
|
||||
@endpoint(perm='can_access', methods=['get', 'post'], name='data', pattern=r'(?P<uuid>\w+)/$',)
|
||||
@endpoint(perm='can_access', methods=['get', 'post'], name='data',
|
||||
pattern=r'(?P<uuid>\w+)/$',
|
||||
example_pattern='{uuid}/',
|
||||
description_get=_('Get'),
|
||||
description_post=_('Replace'),
|
||||
parameters={'uuid': {'description': _('Object identifier'), 'example_value': '12345'}},
|
||||
)
|
||||
def get_or_replace(self, request, uuid, name_id=None):
|
||||
data = self.get_data_object(uuid, name_id)
|
||||
if request.method == 'POST':
|
||||
|
@ -96,7 +106,12 @@ class JsonDataStore(BaseResource):
|
|||
data.save()
|
||||
return {'id': data.uuid, 'text': data.text, 'content': data.content}
|
||||
|
||||
@endpoint(perm='can_access', methods=['post'], name='data', pattern=r'(?P<uuid>\w+)/delete$')
|
||||
@endpoint(perm='can_access', methods=['post'], name='data',
|
||||
description=_('Delete'),
|
||||
pattern=r'(?P<uuid>\w+)/delete$',
|
||||
example_pattern='{uuid}/delete',
|
||||
parameters={'uuid': {'description': _('Object identifier'), 'example_value': '12345'}},
|
||||
)
|
||||
def delete(self, request, uuid, name_id=None):
|
||||
self.get_data_object(uuid, name_id).delete()
|
||||
return {}
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
{% extends "passerelle/manage/service_view.html" %}
|
||||
{% load i18n passerelle %}
|
||||
|
||||
{% block endpoints %}
|
||||
<ul>
|
||||
<li>{% trans 'Listing:' %} <a href="data/"
|
||||
>{{ site_base_uri }}{{ object.get_absolute_url }}data/</a></li>
|
||||
<li>{% trans 'Create:' %} <a href="data/create"
|
||||
>{{ site_base_uri }}{{ object.get_absolute_url }}data/create</a> (POST)</li>
|
||||
<li>{% trans 'Get:' %} <a href="data/uuid/"
|
||||
>{{ site_base_uri }}{{ object.get_absolute_url }}data/<i>uuid</i/>/</a></li>
|
||||
<li>{% trans 'Replace:' %} <a href="data/uuid/"
|
||||
>{{ site_base_uri }}{{ object.get_absolute_url }}data/<i>uuid</i/>/</a> (POST)</li>
|
||||
<li>{% trans 'Delete:' %} <a href="data/uuid/delete"
|
||||
>{{ site_base_uri }}{{ object.get_absolute_url }}data/<i>uuid</i/>/delete</a> (POST)</li>
|
||||
</ul>
|
||||
|
||||
{% endblock %}
|
|
@ -48,7 +48,12 @@ class OpenGIS(BaseResource):
|
|||
def get_icon_class(cls):
|
||||
return 'gis'
|
||||
|
||||
@endpoint(perm='can_access')
|
||||
@endpoint(perm='can_access',
|
||||
description=_('Get feature info'),
|
||||
parameters={
|
||||
'lat': {'description': _('Latitude'), 'example_value': '45.79689'},
|
||||
'lon': {'description': _('Longitude'), 'example_value': '4.78414'},
|
||||
})
|
||||
def feature_info(self, request, lat, lon):
|
||||
bbox = '%s,%s,%s,%s' % (lat, lon, float(lat) + 0.002, float(lon) + 0.002)
|
||||
params = {
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
{% extends "passerelle/manage/service_view.html" %}
|
||||
{% load i18n passerelle %}
|
||||
|
||||
{% block endpoints %}
|
||||
<ul>
|
||||
<li>
|
||||
{% trans "Get feature info:" %}
|
||||
{% url "generic-endpoint" connector="opengis" slug=object.slug endpoint="feature_info" as endpoint_path %}
|
||||
<a href="{{endpoint_path}}?lat=45.796890&lon=4.784140"
|
||||
>{{endpoint_path}}?lat=45.796890&lon=4.784140</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endblock %}
|
|
@ -1,3 +1,4 @@
|
|||
import copy
|
||||
import inspect
|
||||
import logging
|
||||
import os
|
||||
|
@ -198,21 +199,25 @@ class BaseResource(models.Model):
|
|||
fields.append((field, value))
|
||||
return fields
|
||||
|
||||
@classmethod
|
||||
def get_endpoints(cls):
|
||||
def get_endpoints_infos(self):
|
||||
endpoints = []
|
||||
for name, method in inspect.getmembers(cls, predicate=inspect.ismethod):
|
||||
for name, method in inspect.getmembers(self, predicate=inspect.ismethod):
|
||||
if hasattr(method, 'endpoint_info'):
|
||||
endpoints.append((name, method))
|
||||
method.endpoint_info.object = self
|
||||
for http_method in method.endpoint_info.methods:
|
||||
# duplicate information to give each method its own entry
|
||||
endpoint_info = copy.copy(method.endpoint_info)
|
||||
endpoint_info.http_method = http_method
|
||||
endpoints.append(endpoint_info)
|
||||
endpoints.sort(key=lambda x: (x.name, x.pattern))
|
||||
return endpoints
|
||||
|
||||
@classmethod
|
||||
def get_connector_permissions(cls):
|
||||
def get_connector_permissions(self):
|
||||
perms = {}
|
||||
for endpoint in cls.get_endpoints():
|
||||
permission = endpoint[1].endpoint_info.perm
|
||||
for endpoint_info in self.get_endpoints_infos():
|
||||
permission = endpoint_info.perm
|
||||
if permission:
|
||||
perms[permission] = getattr(cls,
|
||||
perms[permission] = getattr(self,
|
||||
'_%s_description' % permission,
|
||||
_('Access (%s) is limited to the following API users:') % permission)
|
||||
return [{'key': x[0], 'label': x[1]} for x in perms.items()]
|
||||
|
|
|
@ -63,25 +63,49 @@ class StubInvoicesConnector(BaseResource):
|
|||
def get_invoice(self, invoice_id):
|
||||
return self.invoices.get(invoice_id)
|
||||
|
||||
@endpoint(name='invoices', pattern='^history/$')
|
||||
@endpoint(name='invoices', pattern='^history/$',
|
||||
description=_('Get list of paid invoices'),
|
||||
example_pattern='history/')
|
||||
def invoices_history(self, request, NameID=None, **kwargs):
|
||||
return {'data': [x for x in self.get_invoices() if x.get('payment_date')]}
|
||||
|
||||
@endpoint(name='invoices')
|
||||
@endpoint(name='invoices',
|
||||
description=_('Get list of unpaid invoices'))
|
||||
def invoices_list(self, request, NameID=None, **kwargs):
|
||||
return {'data': [x for x in self.get_invoices() if not x.get('payment_date')]}
|
||||
|
||||
@endpoint(name='invoice', pattern='^(?P<invoice_id>\w+)/?$')
|
||||
@endpoint(name='invoice', pattern='^(?P<invoice_id>\w+)/?$',
|
||||
description=_('Get invoice details'),
|
||||
example_pattern='{invoice_id}/',
|
||||
parameters={
|
||||
'invoice_id': {
|
||||
'description': _('Invoice identifier'),
|
||||
'example_value': invoices.keys()[0],
|
||||
}})
|
||||
def invoice(self, request, invoice_id, NameID=None, **kwargs):
|
||||
return {'data': self.get_invoice(invoice_id)}
|
||||
|
||||
@endpoint(name='invoice', pattern='^(?P<invoice_id>\w+)/pdf/?$')
|
||||
@endpoint(name='invoice', pattern='^(?P<invoice_id>\w+)/pdf/?$',
|
||||
description=_('Get invoice as a PDF file'),
|
||||
example_pattern='{invoice_id}/pdf/',
|
||||
parameters={
|
||||
'invoice_id': {
|
||||
'description': _('Invoice identifier'),
|
||||
'example_value': invoices.keys()[0],
|
||||
}})
|
||||
def invoice_pdf(self, request, invoice_id, NameID=None, **kwargs):
|
||||
response = HttpResponse(content_type='application/pdf')
|
||||
response['Content-Disposition'] = 'attachment; filename="%s.pdf"' % invoice_id
|
||||
response.write('')
|
||||
return response
|
||||
|
||||
@endpoint(name='invoice', perm='can_access', methods=['post'], pattern='^(?P<invoice_id>\w+)/pay/?$')
|
||||
@endpoint(name='invoice', perm='can_access', methods=['post'], pattern='^(?P<invoice_id>\w+)/pay/?$',
|
||||
description=_('Pay invoice'),
|
||||
example_pattern='{invoice_id}/pay/',
|
||||
parameters={
|
||||
'invoice_id': {
|
||||
'description': _('Invoice identifier'),
|
||||
'example_value': invoices.keys()[0],
|
||||
}})
|
||||
def invoice_pay(self, request, invoice_id, NameID=None, **kwargs):
|
||||
return {'data': None}
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
{% extends "passerelle/manage/service_view.html" %}
|
||||
{% load i18n passerelle %}
|
||||
|
||||
{% block description %}
|
||||
{% endblock %}
|
||||
|
||||
{% block endpoints %}
|
||||
<ul>
|
||||
<li>{% trans 'Get invoice history list:' %}
|
||||
{% url 'generic-endpoint' connector='stub-invoices' slug=object.slug endpoint='invoices' rest='history/' as invoices_history_url %}
|
||||
<a href="{{ invoices_history_url }}">{{ site_base_uri }}{{ invoices_history_url }}?NameID=...</a>
|
||||
</li>
|
||||
<li>{% trans 'Get invoice list:' %}
|
||||
{% url 'generic-endpoint' connector='stub-invoices' slug=object.slug endpoint='invoices' rest='' as invoices_url %}
|
||||
<a href="{{ invoices_url }}">{{ site_base_uri }}{{ invoices_url }}?NameID=...</a>
|
||||
</li>
|
||||
<li>{% trans 'Show invoice details:' %}
|
||||
{% url 'generic-endpoint' connector='stub-invoices' slug=object.slug endpoint='invoice' rest='20150916/' as invoice_details_url %}
|
||||
<a href="{{ invoice_details_url }}">{{ site_base_uri }}{{ invoice_details_url }}</a>
|
||||
<em>20150916</em> {% trans 'is invoice identifier' %}
|
||||
</li>
|
||||
<li>{% trans 'Get invoice pdf:' %}
|
||||
{% url 'generic-endpoint' connector='stub-invoices' slug=object.slug endpoint='invoice' rest='20150916/pdf/' as invoice_download_url %}
|
||||
<a href="{{ invoice_download_url }}">{{ site_base_uri }}{{ invoice_download_url }}</a>
|
||||
</li>
|
||||
<li>{% trans 'Pay invoice:' %}
|
||||
{% url 'generic-endpoint' connector='stub-invoices' slug=object.slug endpoint='invoice' rest='20150916/pay/' as payment_url %}
|
||||
<a href="{{ payment_url }}">{{ site_base_uri }}{{ payment_url }}?NameID=...</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endblock %}
|
|
@ -38,7 +38,12 @@ class Tcl(BaseResource):
|
|||
class Meta:
|
||||
verbose_name = _('TCL')
|
||||
|
||||
@endpoint(pattern='^(?P<identifier>\w+)/?$', perm='can_access')
|
||||
@endpoint(pattern='^(?P<identifier>\w+)/?$', perm='can_access',
|
||||
description=_('Info about a stop'),
|
||||
example_pattern='{identifier}/',
|
||||
parameters={
|
||||
'identifier': {'description': _('Stop Identifier'), 'example_value': '30211'}
|
||||
})
|
||||
def stop(self, request, identifier):
|
||||
stop_object = Stop.objects.get(id_data=identifier)
|
||||
stop = {
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
{% extends "passerelle/manage/service_view.html" %}
|
||||
{% load i18n passerelle %}
|
||||
|
||||
{% block endpoints %}
|
||||
<ul>
|
||||
<li>
|
||||
{% trans "Info about a stop:" %}
|
||||
{% url "generic-endpoint" connector="tcl" slug=object.slug endpoint="stop" as endpoint_path %}
|
||||
<a href="{{endpoint_path}}/30211/"
|
||||
>{{endpoint_path}}/<i>id</i>/</a>
|
||||
</pre>
|
||||
</li>
|
||||
</ul>
|
||||
{% endblock %}
|
|
@ -1,3 +1,9 @@
|
|||
i.varname {
|
||||
background: #eee;
|
||||
font-family: monospace;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
div#queries,
|
||||
div#security,
|
||||
div#logs,
|
||||
|
|
|
@ -33,7 +33,29 @@
|
|||
<div id="endpoints">
|
||||
<h3>{% trans 'Endpoints' %}</h3>
|
||||
<div>
|
||||
{% if object.api_description %}<p>{{object.api_description}}</p>{% endif %}
|
||||
{% block endpoints %}
|
||||
<ul>
|
||||
{% for endpoint in object.get_endpoints_infos %}
|
||||
<li>{{endpoint.description}}{% trans ':' %}
|
||||
<a href="{{endpoint.example_url}}">{{ site_base_uri }}{{endpoint.example_url_as_html}}</a>
|
||||
{% if endpoint.methods|length > 1 %}
|
||||
({{endpoint.http_method|upper}})
|
||||
{% endif %}
|
||||
{% if endpoint.has_params %}
|
||||
<ul class="params">
|
||||
{% for param in endpoint.get_params %}
|
||||
<li>{{param.name}}
|
||||
{% if param.optional %}({% trans 'optional' %}{% if param.default_value %},
|
||||
{% trans 'default value:' %} {{param.default_value}}{% endif %}){% endif %}
|
||||
{% if param.description %}{% trans ':' %} {{param.description}}{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -14,19 +14,110 @@
|
|||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import inspect
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
|
||||
class endpoint(object):
|
||||
do_not_call_in_templates = True
|
||||
|
||||
def __init__(self, serializer_type='json-api', perm=None, methods=['get'], name=None, pattern=None,
|
||||
wrap_response=False):
|
||||
wrap_response=False,
|
||||
description=None,
|
||||
description_get=None,
|
||||
description_post=None,
|
||||
example_pattern=None,
|
||||
parameters=None):
|
||||
self.perm = perm
|
||||
self.methods = methods
|
||||
self.serializer_type = serializer_type
|
||||
self.pattern = pattern
|
||||
self.name = name
|
||||
self.wrap_response = wrap_response
|
||||
self.descriptions = {
|
||||
'get': description_get or description,
|
||||
'post': description_post or description,
|
||||
}
|
||||
self.example_pattern = example_pattern
|
||||
self.parameters = parameters
|
||||
|
||||
def __call__(self, func):
|
||||
func.endpoint_info = self
|
||||
if not self.name:
|
||||
self.name = func.func_name
|
||||
self.func = func
|
||||
return func
|
||||
|
||||
def get_example_params(self):
|
||||
return dict([(x, self.parameters[x]['example_value']) for x in self.parameters or {}
|
||||
if x in self.parameters and 'example_value' in self.parameters[x]])
|
||||
|
||||
def get_query_parameters(self):
|
||||
query_parameters = []
|
||||
for param, param_value in self.get_example_params().items():
|
||||
if param in (self.example_pattern or ''):
|
||||
continue
|
||||
query_parameters.append((param, param_value))
|
||||
return query_parameters
|
||||
|
||||
def example_url(self):
|
||||
kwargs = {
|
||||
'connector': self.object.get_connector_slug(),
|
||||
'slug': self.object.slug,
|
||||
'endpoint': self.name,
|
||||
}
|
||||
if self.example_pattern:
|
||||
kwargs['rest'] = self.example_pattern.format(**self.get_example_params())
|
||||
|
||||
query_string = ''
|
||||
query_parameters = self.get_query_parameters()
|
||||
if query_parameters:
|
||||
query_string = '?' + '&'.join(['%s=%s' % x for x in query_parameters])
|
||||
|
||||
return reverse('generic-endpoint', kwargs=kwargs) + query_string
|
||||
|
||||
def example_url_as_html(self):
|
||||
kwargs = {
|
||||
'connector': self.object.get_connector_slug(),
|
||||
'slug': self.object.slug,
|
||||
'endpoint': self.name,
|
||||
}
|
||||
if self.example_pattern:
|
||||
kwargs['rest'] = self.example_pattern.format(
|
||||
**dict([(x, '$%s$' % x) for x in self.get_example_params().keys()]))
|
||||
|
||||
url = reverse('generic-endpoint', kwargs=kwargs)
|
||||
for param in self.get_example_params():
|
||||
url = url.replace('$%s$' % param, '<i class="varname">%s</i>' % param)
|
||||
|
||||
query_string = ''
|
||||
query_parameters = self.get_query_parameters()
|
||||
if query_parameters:
|
||||
query_string = '?' + '&'.join(['%s=<i class="varname">%s</i>' % (x[0], x[0]) for x in query_parameters])
|
||||
|
||||
return mark_safe(url + query_string)
|
||||
|
||||
def has_params(self):
|
||||
argspec = inspect.getargspec(self.func)
|
||||
return len(argspec.args) > 2 # (self, request)
|
||||
|
||||
@property
|
||||
def description(self):
|
||||
return self.descriptions.get(self.http_method)
|
||||
|
||||
def get_params(self):
|
||||
params = []
|
||||
defaults = dict(zip(
|
||||
reversed(inspect.getargspec(self.func).args),
|
||||
reversed(inspect.getargspec(self.func).defaults or [])))
|
||||
for param in inspect.getargspec(self.func).args[2:]:
|
||||
param_info = {'name': param}
|
||||
if self.parameters and param in self.parameters and self.parameters[param].get('description'):
|
||||
param_info['description'] = self.parameters[param].get('description')
|
||||
if param in defaults:
|
||||
param_info['optional'] = True
|
||||
param_info['default_value'] = defaults[param]
|
||||
params.append(param_info)
|
||||
return params
|
||||
|
|
|
@ -25,9 +25,11 @@ import pytest
|
|||
|
||||
import utils
|
||||
|
||||
from passerelle.base.models import ResourceLog, ProxyLogger
|
||||
from passerelle.base.models import BaseResource, ResourceLog, ProxyLogger
|
||||
from passerelle.contrib.mdel.models import MDEL
|
||||
from passerelle.contrib.arcgis.models import Arcgis
|
||||
from passerelle.contrib.stub_invoices.models import StubInvoicesConnector
|
||||
from passerelle.utils.api import endpoint
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
@ -131,3 +133,91 @@ def test_proxy_logger(mocked_get, caplog, app, arcgis):
|
|||
assert ResourceLog.objects.count() == 2
|
||||
assert ResourceLog.objects.last().message == 'first warning'
|
||||
assert ResourceLog.objects.last().levelno == 30
|
||||
|
||||
|
||||
class FakeConnectorBase(object):
|
||||
slug = 'connector'
|
||||
|
||||
def get_connector_slug(self):
|
||||
return 'fake'
|
||||
|
||||
@endpoint()
|
||||
def foo1(self, request):
|
||||
pass
|
||||
|
||||
@endpoint(name='bar')
|
||||
def foo2(self, request, param1):
|
||||
pass
|
||||
|
||||
@endpoint()
|
||||
def foo3(self, request, param1, param2):
|
||||
pass
|
||||
|
||||
@endpoint()
|
||||
def foo4(self, request, param1, param2='a', param3='b'):
|
||||
pass
|
||||
|
||||
@endpoint(pattern='^test/$', example_pattern='test/')
|
||||
def foo5(self, request, param1='a', param2='b', param3='c'):
|
||||
pass
|
||||
|
||||
@endpoint(pattern='^(?P<param1>\w+)/?$',
|
||||
example_pattern='{param1}/',
|
||||
parameters={
|
||||
'param1': {'description': 'param 1', 'example_value': 'bar'}})
|
||||
def foo6(self, request, param1, param2='a'):
|
||||
pass
|
||||
|
||||
@endpoint(description_get='foo7 get', description_post='foo7 post',
|
||||
methods=['get', 'post'])
|
||||
def foo7(self, request, param1='a', param2='b', param3='c'):
|
||||
pass
|
||||
|
||||
|
||||
def test_endpoint_decorator():
|
||||
connector = FakeConnectorBase()
|
||||
for i in range(6):
|
||||
getattr(connector, 'foo%d' % (i+1)).endpoint_info.object = connector
|
||||
|
||||
assert connector.foo1.endpoint_info.name == 'foo1'
|
||||
assert connector.foo2.endpoint_info.name == 'bar'
|
||||
assert not connector.foo1.endpoint_info.has_params()
|
||||
assert connector.foo2.endpoint_info.has_params()
|
||||
assert connector.foo2.endpoint_info.get_params() == [{'name': 'param1'}]
|
||||
assert connector.foo3.endpoint_info.get_params() == [{'name': 'param1'}, {'name': 'param2'}]
|
||||
assert connector.foo4.endpoint_info.get_params() == [
|
||||
{'name': 'param1'},
|
||||
{'name': 'param2', 'optional': True, 'default_value': 'a'},
|
||||
{'name': 'param3', 'optional': True, 'default_value': 'b'}]
|
||||
assert connector.foo5.endpoint_info.get_params() == [
|
||||
{'name': 'param1', 'optional': True, 'default_value': 'a'},
|
||||
{'name': 'param2', 'optional': True, 'default_value': 'b'},
|
||||
{'name': 'param3', 'optional': True, 'default_value': 'c'}]
|
||||
|
||||
assert connector.foo6.endpoint_info.get_params() == [
|
||||
{'name': 'param1', 'description': 'param 1'},
|
||||
{'name': 'param2', 'optional': True, 'default_value': 'a'}]
|
||||
|
||||
assert connector.foo1.endpoint_info.example_url() == '/fake/connector/foo1'
|
||||
assert connector.foo1.endpoint_info.example_url_as_html() == '/fake/connector/foo1'
|
||||
assert connector.foo2.endpoint_info.example_url() == '/fake/connector/bar'
|
||||
assert connector.foo3.endpoint_info.example_url() == '/fake/connector/foo3'
|
||||
assert connector.foo5.endpoint_info.example_url() == '/fake/connector/foo5/test/'
|
||||
assert connector.foo5.endpoint_info.example_url_as_html() == '/fake/connector/foo5/test/'
|
||||
assert connector.foo6.endpoint_info.example_url() == '/fake/connector/foo6/bar/'
|
||||
assert connector.foo6.endpoint_info.example_url_as_html() == '/fake/connector/foo6/<i class="varname">param1</i>/'
|
||||
|
||||
connector.foo6.endpoint_info.pattern = None
|
||||
connector.foo6.endpoint_info.example_pattern = None
|
||||
assert connector.foo6.endpoint_info.example_url() == '/fake/connector/foo6?param1=bar'
|
||||
assert connector.foo6.endpoint_info.example_url_as_html() == '/fake/connector/foo6?param1=<i class="varname">param1</i>'
|
||||
|
||||
connector.foo7.endpoint_info.http_method = 'get'
|
||||
assert connector.foo7.endpoint_info.description == 'foo7 get'
|
||||
connector.foo7.endpoint_info.http_method = 'post'
|
||||
assert connector.foo7.endpoint_info.description == 'foo7 post'
|
||||
|
||||
def test_endpoint_description_in_template(app, db):
|
||||
StubInvoicesConnector(slug='fake').save()
|
||||
resp = app.get('/stub-invoices/fake/')
|
||||
assert 'Get invoice details' in resp.text
|
||||
|
|
Loading…
Reference in New Issue