0001-generic-endpoint-define-optional-category-for-displa.patch
passerelle/base/models.py | ||
---|---|---|
132 | 132 |
# permission descriptions |
133 | 133 |
_can_access_description = _('Access is limited to the following API users:') |
134 | 134 | |
135 |
# category ordering for display |
|
136 |
_category_ordering = [] |
|
137 | ||
135 | 138 |
class Meta: |
136 | 139 |
abstract = True |
137 | 140 | |
... | ... | |
253 | 256 |
endpoint_info = copy.copy(method.endpoint_info) |
254 | 257 |
endpoint_info.http_method = http_method |
255 | 258 |
endpoints.append(endpoint_info) |
256 |
endpoints.sort(key=lambda x: (x.display_order or 99999999, x.name or '', x.pattern or '')) |
|
259 |
endpoints.sort(key=lambda x: (x.display_category_order, x.display_category, x.display_order or 99999999, x.name or '', x.pattern or ''))
|
|
257 | 260 |
if hasattr(self, 'queries'): |
258 | 261 |
self.append_custom_queries(endpoints) |
259 | 262 |
return endpoints |
passerelle/templates/passerelle/manage/service_view.html | ||
---|---|---|
62 | 62 |
<div> |
63 | 63 |
{% if object.api_description %}<p>{{object.api_description|safe}}</p>{% endif %} |
64 | 64 |
{% block endpoints %} |
65 |
<ul class="endpoints"> |
|
66 |
{% for endpoint in object.get_endpoints_infos %} |
|
67 |
{% if endpoint.show %} |
|
68 |
{% include "passerelle/manage/endpoint.html" with endpoint=endpoint %} |
|
69 |
{% endif %} |
|
65 |
{% regroup object.get_endpoints_infos by display_category as endpoints_groups %} |
|
66 |
{% for endpoints in endpoints_groups %} |
|
67 |
{% if endpoints.grouper %}<h4>{{ endpoints.grouper }}</h4>{% elif not forloop.first %}<h4>{% trans "Misc" %}</h4>{% endif %} |
|
68 |
<ul class="endpoints"> |
|
69 |
{% for endpoint in endpoints.list %} |
|
70 |
{% if endpoint.show %} |
|
71 |
{% include "passerelle/manage/endpoint.html" with endpoint=endpoint %} |
|
72 |
{% endif %} |
|
73 |
{% endfor %} |
|
74 |
</ul> |
|
70 | 75 |
{% endfor %} |
71 |
</ul> |
|
72 | 76 |
{% endblock %} |
73 | 77 |
</div> |
74 | 78 |
</div> |
passerelle/utils/api.py | ||
---|---|---|
23 | 23 |
from django.utils.safestring import mark_safe |
24 | 24 | |
25 | 25 |
# make APIError available from this module |
26 |
from .jsonresponse import APIError |
|
26 |
from .jsonresponse import APIError # noqa
|
|
27 | 27 | |
28 | 28 | |
29 | 29 |
class endpoint(object): |
... | ... | |
45 | 45 |
post=None, |
46 | 46 |
show=True, |
47 | 47 |
show_undocumented_params=True, |
48 |
display_order=0): |
|
48 |
display_order=0, |
|
49 |
display_category=''): |
|
49 | 50 |
self.perm = perm |
50 | 51 |
self.methods = methods |
51 | 52 |
self.serializer_type = serializer_type |
... | ... | |
75 | 76 |
self.show = show |
76 | 77 |
self.show_undocumented_params = show_undocumented_params |
77 | 78 |
self.display_order = display_order |
79 |
self.display_category = display_category |
|
78 | 80 | |
79 | 81 |
def __call__(self, func): |
80 | 82 |
func.endpoint_info = self |
... | ... | |
83 | 85 |
self.func = func |
84 | 86 |
return func |
85 | 87 | |
88 |
@property |
|
89 |
def display_category_order(self): |
|
90 |
if not self.display_category: |
|
91 |
# no category, put it at the end |
|
92 |
return 99999999 |
|
93 |
# self.object is attached in BaseResource.get_endpoints_infos method |
|
94 |
if self.display_category not in self.object._category_ordering: |
|
95 |
# category without ordering, put it at the end, just before no category |
|
96 |
return 99999998 |
|
97 |
return self.object._category_ordering.index(self.display_category) |
|
98 | ||
86 | 99 |
def get_example_params(self): |
87 | 100 |
return dict([(x, self.parameters[x]['example_value']) for x in self.parameters or {} |
88 | 101 |
if x in self.parameters and 'example_value' in self.parameters[x]]) |
tests/test_generic_endpoint.py | ||
---|---|---|
752 | 752 |
pass |
753 | 753 | |
754 | 754 | |
755 |
class DummyConnectorWithOrderingAndCategory(DummyConnectorBase): |
|
756 |
_category_ordering = ['Foo', 'Bar'] |
|
757 | ||
758 |
@endpoint(display_category='Foo') |
|
759 |
def a(self, request): |
|
760 |
pass |
|
761 | ||
762 |
@endpoint(display_category='Bar', display_order=2) |
|
763 |
def b(self, request): |
|
764 |
pass |
|
765 | ||
766 |
@endpoint() |
|
767 |
def c(self, request): |
|
768 |
pass |
|
769 | ||
770 |
@endpoint(display_category='Bar', display_order=1) |
|
771 |
def d(self, request): |
|
772 |
pass |
|
773 | ||
774 |
@endpoint(display_category='Blah') |
|
775 |
def e(self, request): |
|
776 |
pass |
|
777 | ||
778 | ||
755 | 779 |
@pytest.mark.parametrize('connector_class, expected_ordering', [ |
756 | 780 |
(DummyConnectorWithoutOrdering, ['a', 'b', 'caa', 'cbb']), |
757 | 781 |
(DummyConnectorWithOrdering, ['caa', 'cbb', 'a', 'b']), |
782 |
(DummyConnectorWithOrderingAndCategory, ['a', 'd', 'b', 'e', 'c']), |
|
758 | 783 |
]) |
759 | 784 |
def test_generic_up_in_endpoints_ordering(db, app, connector_class, expected_ordering): |
760 | 785 |
connector = connector_class() |
761 |
- |