Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c832174

Browse files
committed
Configurable group and package blueprints
1 parent 6815ce1 commit c832174

8 files changed

Lines changed: 174 additions & 4 deletions

File tree

ckan/lib/plugins.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,14 +146,23 @@ def register_package_blueprints(app):
146146
dataset.import_name,
147147
url_prefix='/{}'.format(package_type),
148148
url_defaults={'package_type': package_type})
149+
if hasattr(plugin, 'prepare_dataset_blueprint'):
150+
dataset_blueprint = plugin.prepare_dataset_blueprint(
151+
package_type,
152+
dataset_blueprint)
149153
register_dataset_plugin_rules(dataset_blueprint)
154+
150155
app.register_blueprint(dataset_blueprint)
151156

152157
resource_blueprint = Blueprint(
153158
u'{}_resource'.format(package_type),
154159
resource.import_name,
155160
url_prefix=u'/{}/<id>/resource'.format(package_type),
156161
url_defaults={u'package_type': package_type})
162+
if hasattr(plugin, 'prepare_resource_blueprint'):
163+
resource_blueprint = plugin.prepare_resource_blueprint(
164+
package_type,
165+
resource_blueprint)
157166
dataset_resource_rules(resource_blueprint)
158167
app.register_blueprint(resource_blueprint)
159168
log.debug(
@@ -259,8 +268,12 @@ def register_group_blueprints(app):
259268
blueprint = Blueprint(group_type,
260269
group.import_name,
261270
url_prefix='/{}'.format(group_type),
262-
url_defaults={u'group_type': group_type,
263-
u'is_organization': is_organization})
271+
url_defaults={
272+
u'group_type': group_type,
273+
u'is_organization': is_organization})
274+
if hasattr(plugin, 'prepare_group_blueprint'):
275+
blueprint = plugin.prepare_group_blueprint(
276+
group_type, blueprint)
264277
register_group_plugin_rules(blueprint)
265278
app.register_blueprint(blueprint)
266279

ckan/plugins/interfaces.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1313,6 +1313,39 @@ def validate(self, context, data_dict, schema, action):
13131313
:rtype: (dictionary, dictionary)
13141314
'''
13151315

1316+
def prepare_dataset_blueprint(self, package_type, blueprint):
1317+
u'''Update or replace dataset blueprint for given package type.
1318+
1319+
Internally CKAN registers blueprint for every custom dataset
1320+
type. Before default routes added to this blueprint and it
1321+
registered inside application this method is called. It can be
1322+
used either for registration of the view function under new
1323+
path or under existing path(like `/new`), in which case this
1324+
new function will be used instead of default one.
1325+
1326+
Note, this blueprint has prefix `/{package_type}`.
1327+
1328+
:rtype: flask.Blueprint
1329+
1330+
'''
1331+
1332+
def prepare_resource_blueprint(self, package_type, blueprint):
1333+
u'''Update or replace resource blueprint for given package type.
1334+
1335+
Internally CKAN registers separate resource blueprint for
1336+
every custom dataset type. Before default routes added to this
1337+
blueprint and it registered inside application this method is
1338+
called. It can be used either for registration of the view
1339+
function under new path or under existing path(like `/new`),
1340+
in which case this new function will be used instead of
1341+
default one.
1342+
1343+
Note, this blueprint has prefix `/{package_type}/<id>/resource`.
1344+
1345+
:rtype: flask.Blueprint
1346+
1347+
'''
1348+
13161349

13171350
class IGroupForm(Interface):
13181351
u'''
@@ -1477,6 +1510,23 @@ def validate(self, context, data_dict, schema, action):
14771510
:rtype: (dictionary, dictionary)
14781511
'''
14791512

1513+
def prepare_group_blueprint(self, group_type, blueprint):
1514+
u'''Update or replace group blueprint for given group type.
1515+
1516+
Internally CKAN registers separate blueprint for
1517+
every custom group type. Before default routes added to this
1518+
blueprint and it registered inside application this method is
1519+
called. It can be used either for registration of the view
1520+
function under new path or under existing path(like `/new`),
1521+
in which case this new function will be used instead of
1522+
default one.
1523+
1524+
Note, this blueprint has prefix `/{group_type}`.
1525+
1526+
:rtype: flask.Blueprint
1527+
1528+
'''
1529+
14801530
# End of hooks ############################################################
14811531

14821532

ckan/tests/helpers.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,9 @@ def open(self, *args, **kwargs):
254254
res = super(CKANTestClient, self).open(*args, **kwargs)
255255

256256
if status:
257-
assert res.status_code == status, (res.status_code, status)
257+
assert (
258+
res.status_code == status
259+
), "Actual: {}. Expected: {}".format(res.status_code, status)
258260

259261
return res
260262

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# encoding: utf-8
2+
3+
import ckan.plugins as p
4+
import ckan.plugins.toolkit as tk
5+
6+
7+
def fancy_route(package_type):
8+
return u'Hello, {}'.format(package_type)
9+
10+
11+
def fancy_resource_route(package_type, id):
12+
return u'Hello, {}:{}'.format(package_type, id)
13+
14+
15+
class ExampleIDatasetFormPlugin(p.SingletonPlugin, tk.DefaultDatasetForm):
16+
p.implements(p.IDatasetForm)
17+
18+
def is_fallback(self):
19+
return False
20+
21+
def package_types(self):
22+
return [u'fancy_type']
23+
24+
def prepare_dataset_blueprint(self, package_type, bp):
25+
bp.add_url_rule(u'/fancy-route', view_func=fancy_route)
26+
bp.add_url_rule(u'/new', view_func=fancy_route)
27+
return bp
28+
29+
def prepare_resource_blueprint(self, package_type, bp):
30+
bp.add_url_rule(u'/new', view_func=fancy_resource_route)
31+
return bp

ckanext/example_idatasetform/tests/test_example_idatasetform.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,3 +443,29 @@ def test_custom_search(self, app):
443443
a = six.ensure_text(response.data).index("test_package_a")
444444
b = six.ensure_text(response.data).index("test_package_b")
445445
assert a < b
446+
447+
448+
@pytest.mark.ckan_config("ckan.plugins", u"example_idatasetform_v6")
449+
@pytest.mark.usefixtures(
450+
"with_plugins", "with_request_context"
451+
)
452+
class TestBlueprintPreparations(object):
453+
def test_additional_routes_are_registered(self, app):
454+
resp = app.get("/fancy_type/fancy-route", status=200)
455+
assert resp.body == u'Hello, fancy_type'
456+
457+
def test_existing_routes_are_replaced(self, app):
458+
resp = app.get("/fancy_type/new", status=200)
459+
assert resp.body == u'Hello, fancy_type'
460+
461+
resp = app.get("/fancy_type/random/resource/new", status=200)
462+
assert resp.body == u'Hello, fancy_type:random'
463+
464+
@pytest.mark.usefixtures(u'clean_db', u'clean_index')
465+
def test_existing_routes_are_untouched(self, app):
466+
resp = app.get("/fancy_type", status=200)
467+
page = bs4.BeautifulSoup(resp.body)
468+
links = [
469+
a['href'] for a in page.select(".breadcrumb a")
470+
]
471+
assert links == ['/', '/fancy_type/']
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# encoding: utf-8
2+
3+
import ckan.plugins as plugins
4+
import ckan.plugins.toolkit as tk
5+
6+
7+
def fancy_route(group_type, is_organization):
8+
return u'Hello, {}'.format(group_type)
9+
10+
11+
class ExampleIGroupFormPlugin(plugins.SingletonPlugin, tk.DefaultGroupForm):
12+
plugins.implements(plugins.IGroupForm, inherit=False)
13+
14+
def is_fallback(self):
15+
return False
16+
17+
def group_types(self):
18+
return [u'fancy_type']
19+
20+
def prepare_group_blueprint(self, package_type, bp):
21+
bp.add_url_rule(u'/fancy-route', view_func=fancy_route)
22+
bp.add_url_rule(u'/new', view_func=fancy_route)
23+
return bp

ckanext/example_igroupform/tests/test_controllers.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
import pytest
44
import six
5+
import bs4
56
from ckan.lib.helpers import url_for
67

7-
import ckan.plugins as plugins
88
import ckan.tests.helpers as helpers
99
import ckan.model as model
1010
from ckan.tests import factories
@@ -221,3 +221,26 @@ def test_custom_group_form(self, app):
221221
env, response, group_name = _get_group_edit_page(app, group_type)
222222

223223
assert helpers.body_contains(response, "My Custom Group Form!")
224+
225+
226+
@pytest.mark.ckan_config("ckan.plugins", u"example_igroupform_v2")
227+
@pytest.mark.usefixtures(
228+
"with_plugins", "with_request_context"
229+
)
230+
class TestBlueprintPreparations(object):
231+
def test_additional_routes_are_registered(self, app):
232+
resp = app.get("/fancy_type/fancy-route", status=200)
233+
assert resp.body == u'Hello, fancy_type'
234+
235+
def test_existing_routes_are_replaced(self, app):
236+
resp = app.get("/fancy_type/new", status=200)
237+
assert resp.body == u'Hello, fancy_type'
238+
239+
# @pytest.mark.usefixtures(u'clean_db', u'clean_index')
240+
def test_existing_routes_are_untouched(self, app):
241+
resp = app.get("/fancy_type", status=200)
242+
page = bs4.BeautifulSoup(resp.body)
243+
links = [
244+
a['href'] for a in page.select(".breadcrumb a")
245+
]
246+
assert links == ['/', '/fancy_type/']

setup.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,9 @@
107107
'example_idatasetform_v3 = ckanext.example_idatasetform.plugin_v3:ExampleIDatasetFormPlugin',
108108
'example_idatasetform_v4 = ckanext.example_idatasetform.plugin_v4:ExampleIDatasetFormPlugin',
109109
'example_idatasetform_v5 = ckanext.example_idatasetform.plugin_v5:ExampleIDatasetFormPlugin',
110+
'example_idatasetform_v6 = ckanext.example_idatasetform.plugin_v6:ExampleIDatasetFormPlugin',
110111
'example_igroupform = ckanext.example_igroupform.plugin:ExampleIGroupFormPlugin',
112+
'example_igroupform_v2 = ckanext.example_igroupform.plugin_v2:ExampleIGroupFormPlugin',
111113
'example_igroupform_default_group_type = ckanext.example_igroupform.plugin:ExampleIGroupFormPlugin_DefaultGroupType',
112114
'example_igroupform_organization = ckanext.example_igroupform.plugin:ExampleIGroupFormOrganizationPlugin',
113115
'example_iauthfunctions_v1 = ckanext.example_iauthfunctions.plugin_v1:ExampleIAuthFunctionsPlugin',

0 commit comments

Comments
 (0)