Skip to content

Commit

Permalink
Merge branch 'master' into 1251-resource-view
Browse files Browse the repository at this point in the history
Conflicts:
	ckanext/resourceproxy/tests/test_proxy.py
  • Loading branch information
vitorbaptista committed Jun 16, 2014
2 parents 6224995 + baca61b commit 194d6c1
Show file tree
Hide file tree
Showing 112 changed files with 3,324 additions and 861 deletions.
23 changes: 23 additions & 0 deletions CHANGELOG.rst
Expand Up @@ -7,6 +7,29 @@
Changelog
---------

v2.3
====

API changes and deprecations
----------------------------

* ``helpers.get_action()`` (or ``h.get_action()`` in templates) is deprecated.

Since action functions raise exceptions and templates cannot catch
exceptions, it's not a good idea to call action functions from templates.

Instead, have your controller method call the action function and pass the
result to your template using the ``extra_vars`` param of ``render()``.

Alternatively you can wrap individual action functions in custom template
helper functions that handle any exceptions appropriately, but this is likely
to make your the logic in your templates more complex and templates are
difficult to test and debug.

Note that logic.get_action() and toolkit.get_action() are *not* deprecated,
core code and plugin code should still use ``get_action()``.


v2.2 2014-02-04
===============

Expand Down
2 changes: 1 addition & 1 deletion README.rst
Expand Up @@ -60,7 +60,7 @@ others, make a new page on the `CKAN wiki`_, and tell us about it on
Copying and License
-------------------

This material is copyright (c) 2006-2013 Open Knowledge Foundation.
This material is copyright (c) 2006-2014 Open Knowledge Foundation.

It is open and licensed under the GNU Affero General Public License (AGPL) v3.0
whose full text may be found at:
Expand Down
2 changes: 2 additions & 0 deletions ckan/controllers/related.py
Expand Up @@ -116,6 +116,8 @@ def list(self, id):

try:
c.pkg_dict = logic.get_action('package_show')(context, data_dict)
c.related_list = logic.get_action('related_list')(context,
data_dict)
c.pkg = context['package']
c.resources_json = h.json.dumps(c.pkg_dict.get('resources', []))
except logic.NotFound:
Expand Down
4 changes: 3 additions & 1 deletion ckan/lib/cli.py
Expand Up @@ -147,10 +147,12 @@ def _load_config(self):

self.registry.register(pylons.c, c)

self.site_user = logic.get_action('get_site_user')({'ignore_auth': True}, {})
self.site_user = logic.get_action('get_site_user')({'ignore_auth': True,
'defer_commit': True}, {})

pylons.c.user = self.site_user['name']
pylons.c.userobj = model.User.get(self.site_user['name'])
model.repo.commit_and_remove()

## give routes enough information to run url_for
parsed = urlparse.urlparse(conf.get('ckan.site_url', 'http://0.0.0.0'))
Expand Down
19 changes: 9 additions & 10 deletions ckan/lib/dictization/model_save.py
Expand Up @@ -381,14 +381,13 @@ def group_member_save(context, group_dict, member_table_name):
return processed


def group_dict_save(group_dict, context):
def group_dict_save(group_dict, context, prevent_packages_update=False):
from ckan.lib.search import rebuild

model = context["model"]
session = context["session"]
group = context.get("group")
allow_partial_update = context.get("allow_partial_update", False)
prevent_packages_update = context.get("prevent_packages_update", False)

Group = model.Group
if group:
Expand Down Expand Up @@ -418,14 +417,6 @@ def group_dict_save(group_dict, context):
'Groups: %r Tags: %r', pkgs_edited, group_users_changed,
group_groups_changed, group_tags_changed)

# We will get a list of packages that we have either added or
# removed from the group, and trigger a re-index.
package_ids = pkgs_edited['removed']
package_ids.extend( pkgs_edited['added'] )
if package_ids:
session.commit()
map( rebuild, package_ids )

extras = group_extras_save(group_dict.get("extras", {}), context)
if extras or not allow_partial_update:
old_extras = set(group.extras.keys())
Expand All @@ -435,6 +426,14 @@ def group_dict_save(group_dict, context):
for key in new_extras:
group.extras[key] = extras[key]

# We will get a list of packages that we have either added or
# removed from the group, and trigger a re-index.
package_ids = pkgs_edited['removed']
package_ids.extend( pkgs_edited['added'] )
if package_ids:
session.commit()
map( rebuild, package_ids )

return group


Expand Down
16 changes: 15 additions & 1 deletion ckan/lib/helpers.py
Expand Up @@ -737,8 +737,12 @@ def check_access(action, data_dict=None):
return authorized


@maintain.deprecated("helpers.get_action() is deprecated and will be removed "
"in a future version of CKAN. Instead, please use the "
"extra_vars param to render() in your controller to pass "
"results from action functions to your templates.")
def get_action(action_name, data_dict=None):
'''Calls an action function from a template.'''
'''Calls an action function from a template. Deprecated in CKAN 2.3.'''
if data_dict is None:
data_dict = {}
return logic.get_action(action_name)({}, data_dict)
Expand Down Expand Up @@ -1923,6 +1927,15 @@ def unified_resource_format(format):
def check_config_permission(permission):
return new_authz.check_config_permission(permission)


def get_organization(org=None):
if org is None:
return {}
try:
return logic.get_action('organization_show')({}, {'id': org})
except (NotFound, ValidationError, NotAuthorized):
return {}

# these are the functions that will end up in `h` template helpers
__allowed_functions__ = [
# functions defined in ckan.lib.helpers
Expand Down Expand Up @@ -2015,6 +2028,7 @@ def check_config_permission(permission):
'list_dict_filter',
'new_activities',
'time_ago_from_timestamp',
'get_organization',
'has_more_facets',
# imported into ckan.lib.helpers
'literal',
Expand Down
3 changes: 2 additions & 1 deletion ckan/logic/action/create.py
Expand Up @@ -1317,7 +1317,8 @@ def _group_or_org_member_create(context, data_dict, is_org=False):
member_create_context = {
'model': model,
'user': user,
'session': session
'session': session,
'ignore_auth': context.get('ignore_auth'),
}
logic.get_action('member_create')(member_create_context, member_dict)

Expand Down
10 changes: 10 additions & 0 deletions ckan/logic/action/get.py
Expand Up @@ -2087,6 +2087,16 @@ def term_translation_show(context, data_dict):

# Only internal services are allowed to call get_site_user.
def get_site_user(context, data_dict):
'''Return the ckan site user
:param defer_commit: by default (or if set to false) get_site_user will
commit and clean up the current transaction, it will also close and
discard the current session in the context. If set to true, caller
is responsible for commiting transaction after get_site_user is
called. Leaving open connections can cause cli commands to hang!
(optional, default: False)
:type defer_commit: boolean
'''
_check_access('get_site_user', context, data_dict)
model = context['model']
site_id = config.get('ckan.site_id', 'ckan_site_user')
Expand Down
13 changes: 5 additions & 8 deletions ckan/logic/action/update.py
Expand Up @@ -614,14 +614,8 @@ def _group_or_org_update(context, data_dict, is_org=False):
else:
rev.message = _(u'REST API: Update object %s') % data.get("name")

# when editing an org we do not want to update the packages if using the
# new templates.
if ((not is_org)
and not converters.asbool(
config.get('ckan.legacy_templates', False))
and 'api_version' not in context):
context['prevent_packages_update'] = True
group = model_save.group_dict_save(data, context)
group = model_save.group_dict_save(data, context,
prevent_packages_update=is_org)

if is_org:
plugin_type = plugins.IOrganizationController
Expand Down Expand Up @@ -708,6 +702,9 @@ def organization_update(context, data_dict):
:param id: the name or id of the organization to update
:type id: string
:param packages: ignored. use
:py:func:`~ckan.logic.action.update.package_owner_org_update`
to change package ownership
:returns: the updated organization
:rtype: dictionary
Expand Down
17 changes: 17 additions & 0 deletions ckan/new_tests/helpers.py
Expand Up @@ -17,6 +17,10 @@
This module is reserved for these very useful functions.
'''
import pylons.config as config
import webtest

import ckan.config.middleware
import ckan.model as model
import ckan.logic as logic

Expand Down Expand Up @@ -120,3 +124,16 @@ def call_auth(auth_name, context, **kwargs):
'context dict')

return logic.check_access(auth_name, context, data_dict=kwargs)


def _get_test_app():
'''Return a webtest.TestApp for CKAN, with legacy templates disabled.
For functional tests that need to request CKAN pages or post to the API.
Unit tests shouldn't need this.
'''
config['ckan.legacy_templates'] = False
app = ckan.config.middleware.make_app(config['global_conf'], **config)
app = webtest.TestApp(app)
return app
2 changes: 1 addition & 1 deletion ckan/new_tests/logic/action/test_update.py
Expand Up @@ -101,7 +101,7 @@ def test_user_update_with_invalid_name(self):
user = factories.User()

invalid_names = ('', 'a', False, 0, -1, 23, 'new', 'edit', 'search',
'a'*200, 'Hi!', 'i++%')
'a' * 200, 'Hi!', 'i++%')
for name in invalid_names:
user['name'] = name
nose.tools.assert_raises(logic.ValidationError,
Expand Down
4 changes: 2 additions & 2 deletions ckan/new_tests/logic/test_validators.py
Expand Up @@ -163,7 +163,7 @@ def test_name_validator_with_invalid_value(self):
('a', 2, False),
[13, None, True],
{'foo': 'bar'},
lambda x: x**2,
lambda x: x ** 2,

# Certain reserved strings aren't allowed as names.
'new',
Expand Down Expand Up @@ -241,7 +241,7 @@ def test_user_name_validator_with_non_string_value(self):
('a', 2, False),
[13, None, True],
{'foo': 'bar'},
lambda x: x**2,
lambda x: x ** 2,
]

# Mock ckan.model.
Expand Down
2 changes: 1 addition & 1 deletion ckan/plugins/interfaces.py
Expand Up @@ -180,7 +180,7 @@ def after_rollback(self, session):

class IDomainObjectModification(Interface):
"""
Receives notification of new, changed and deleted datesets.
Receives notification of new, changed and deleted datasets.
"""

def notify(self, entity, operation):
Expand Down
4 changes: 2 additions & 2 deletions ckan/public/base/javascript/modules/custom-fields.js
Expand Up @@ -90,14 +90,14 @@ this.ckan.module('custom-fields', function (jQuery, _) {
*/
_onChange: function (event) {
if (event.target.value !== '') {
var parent = jQuery(event.target).parents('.control-custom');
var parent = jQuery(event.target).parents(this.options.fieldSelector);
this.newField(parent);
}
},

/* Event handler called when the remove checkbox is checked */
_onRemove: function (event) {
var parent = jQuery(event.target).parents('.control-custom');
var parent = jQuery(event.target).parents(this.options.fieldSelector);
this.disableField(parent, event.target.checked);
}
};
Expand Down

0 comments on commit 194d6c1

Please sign in to comment.