Skip to content

Commit

Permalink
Merge branch 'master' into coding-standards-tests
Browse files Browse the repository at this point in the history
  • Loading branch information
tobes committed Apr 22, 2013
2 parents 4c0d347 + 0b796a5 commit 45b11bd
Show file tree
Hide file tree
Showing 79 changed files with 1,278 additions and 800 deletions.
34 changes: 26 additions & 8 deletions README.rst
Expand Up @@ -18,14 +18,21 @@ Installation
See the `CKAN Documentation <http://docs.ckan.org>`_ for installation instructions.


Community
---------
Support
-------

* Developer mailing list: `ckan-dev@lists.okfn.org <http://lists.okfn.org/mailman/listinfo/ckan-dev>`_
* Developer IRC channel: `#ckan on irc.freenode.net <http://webchat.freenode.net/?channels=ckan>`_
* `Issue tracker <https://github.com/okfn/ckan/issues>`_
* `CKAN tag on StackOverflow <http://stackoverflow.com/questions/tagged/ckan>`_
* `Wiki <https://github.com/okfn/ckan/wiki>`_
If you need help with CKAN or want to ask a question about CKAN, use either the
`ckan-discuss`_ mailing list or the `CKAN tag on Stack Overflow`_ (try
searching the Stack Overflow and ckan-discuss archives for an answer to your
question first).

If you've found a bug in CKAN, open a new issue on CKAN's `GitHub Issues`_ (try
searching first to see if there's already an issue for your bug).


.. _CKAN tag on Stack Overflow: http://stackoverflow.com/questions/tagged/ckan
.. _ckan-discuss: http://lists.okfn.org/mailman/listinfo/ckan-discuss
.. _GitHub Issues: https://github.com/okfn/ckan/issues


Contributing to CKAN
Expand All @@ -34,11 +41,22 @@ Contributing to CKAN
For contributing to CKAN or its documentation, see
`CONTRIBUTING <https://github.com/okfn/ckan/blob/master/CONTRIBUTING.rst>`_.

If you want to talk about CKAN development say hi to the CKAN developers on the
`ckan-dev`_ mailing list or in the `#ckan`_ IRC channel on irc.freenode.net.

If you've figured out how to do something with CKAN and want to document it for
others, make a new page on the `CKAN wiki`_, and tell us about it on
`ckan-dev`_.

.. _ckan-dev: http://lists.okfn.org/mailman/listinfo/ckan-dev
.. _#ckan: http://webchat.freenode.net/?channels=ckan
.. _CKAN Wiki: https://github.com/okfn/ckan/wiki


Copying and License
-------------------

This material is copyright (c) 2006-2011 Open Knowledge Foundation.
This material is copyright (c) 2006-2013 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
27 changes: 14 additions & 13 deletions ckan/config/environment.py
Expand Up @@ -9,7 +9,6 @@
from paste.deploy.converters import asbool
import sqlalchemy
from pylons import config
from pylons.i18n import _, ungettext
from genshi.template import TemplateLoader
from genshi.filters.i18n import Translator

Expand All @@ -18,10 +17,12 @@
import ckan.plugins as p
import ckan.lib.helpers as h
import ckan.lib.app_globals as app_globals
import ckan.lib.jinja_extensions as jinja_extensions

from ckan.common import _, ungettext

log = logging.getLogger(__name__)

import lib.jinja_extensions

# Suppress benign warning 'Unbuilt egg for setuptools'
warnings.simplefilter('ignore', UserWarning)
Expand Down Expand Up @@ -297,22 +298,22 @@ def genshi_lookup_attr(cls, obj, key):


# Create Jinja2 environment
env = lib.jinja_extensions.Environment(
loader=lib.jinja_extensions.CkanFileSystemLoader(template_paths),
env = jinja_extensions.Environment(
loader=jinja_extensions.CkanFileSystemLoader(template_paths),
autoescape=True,
extensions=['jinja2.ext.do', 'jinja2.ext.with_',
lib.jinja_extensions.SnippetExtension,
lib.jinja_extensions.CkanExtend,
lib.jinja_extensions.CkanInternationalizationExtension,
lib.jinja_extensions.LinkForExtension,
lib.jinja_extensions.ResourceExtension,
lib.jinja_extensions.UrlForStaticExtension,
lib.jinja_extensions.UrlForExtension]
jinja_extensions.SnippetExtension,
jinja_extensions.CkanExtend,
jinja_extensions.CkanInternationalizationExtension,
jinja_extensions.LinkForExtension,
jinja_extensions.ResourceExtension,
jinja_extensions.UrlForStaticExtension,
jinja_extensions.UrlForExtension]
)
env.install_gettext_callables(_, ungettext, newstyle=True)
# custom filters
env.filters['empty_and_escape'] = lib.jinja_extensions.empty_and_escape
env.filters['truncate'] = lib.jinja_extensions.truncate
env.filters['empty_and_escape'] = jinja_extensions.empty_and_escape
env.filters['truncate'] = jinja_extensions.truncate
config['pylons.app_globals'].jinja_env = env

# CONFIGURATION OPTIONS HERE (note: all config options will override
Expand Down
43 changes: 21 additions & 22 deletions ckan/controllers/api.py
Expand Up @@ -5,12 +5,9 @@
import glob
import urllib

from pylons import c, request, response
from pylons.i18n import _, gettext
from paste.util.multidict import MultiDict
from webob.multidict import UnicodeMultiDict
from paste.util.multidict import MultiDict

import ckan.rating
import ckan.model as model
import ckan.logic as logic
import ckan.lib.base as base
Expand All @@ -20,6 +17,8 @@
import ckan.lib.jsonp as jsonp
import ckan.lib.munge as munge

from ckan.common import _, c, request, response


log = logging.getLogger(__name__)

Expand Down Expand Up @@ -159,7 +158,7 @@ def action(self, logic_function, ver=None):
except KeyError:
log.error('Can\'t find logic function: %s' % logic_function)
return self._finish_bad_request(
gettext('Action name not known: %s') % str(logic_function))
_('Action name not known: %s') % str(logic_function))

context = {'model': model, 'session': model.Session, 'user': c.user,
'api_version': ver}
Expand All @@ -172,12 +171,12 @@ def action(self, logic_function, ver=None):
except ValueError, inst:
log.error('Bad request data: %s' % str(inst))
return self._finish_bad_request(
gettext('JSON Error: %s') % str(inst))
_('JSON Error: %s') % str(inst))
if not isinstance(request_data, dict):
# this occurs if request_data is blank
log.error('Bad request data - not dict: %r' % request_data)
return self._finish_bad_request(
gettext('Bad request data: %s') %
_('Bad request data: %s') %
'Request data JSON decoded to %r but '
'it needs to be a dictionary.' % request_data)
try:
Expand Down Expand Up @@ -265,7 +264,7 @@ def list(self, ver=None, register=None, subregister=None, id=None):
action = self._get_action_from_map(action_map, register, subregister)
if not action:
return self._finish_bad_request(
gettext('Cannot list entity of this type: %s') % register)
_('Cannot list entity of this type: %s') % register)
try:
return self._finish_ok(action(context, {'id': id}))
except NotFound, e:
Expand Down Expand Up @@ -296,7 +295,7 @@ def show(self, ver=None, register=None, subregister=None,
action = self._get_action_from_map(action_map, register, subregister)
if not action:
return self._finish_bad_request(
gettext('Cannot read entity of this type: %s') % register)
_('Cannot read entity of this type: %s') % register)
try:
return self._finish_ok(action(context, data_dict))
except NotFound, e:
Expand Down Expand Up @@ -331,12 +330,12 @@ def create(self, ver=None, register=None, subregister=None,
data_dict.update(request_data)
except ValueError, inst:
return self._finish_bad_request(
gettext('JSON Error: %s') % str(inst))
_('JSON Error: %s') % str(inst))

action = self._get_action_from_map(action_map, register, subregister)
if not action:
return self._finish_bad_request(
gettext('Cannot create new entity of this type: %s %s') %
_('Cannot create new entity of this type: %s %s') %
(register, subregister))

try:
Expand Down Expand Up @@ -390,12 +389,12 @@ def update(self, ver=None, register=None, subregister=None,
data_dict.update(request_data)
except ValueError, inst:
return self._finish_bad_request(
gettext('JSON Error: %s') % str(inst))
_('JSON Error: %s') % str(inst))

action = self._get_action_from_map(action_map, register, subregister)
if not action:
return self._finish_bad_request(
gettext('Cannot update entity of this type: %s') %
_('Cannot update entity of this type: %s') %
register.encode('utf-8'))
try:
response_data = action(context, data_dict)
Expand Down Expand Up @@ -439,7 +438,7 @@ def delete(self, ver=None, register=None, subregister=None,
action = self._get_action_from_map(action_map, register, subregister)
if not action:
return self._finish_bad_request(
gettext('Cannot delete entity of this type: %s %s') %
_('Cannot delete entity of this type: %s %s') %
(register, subregister or ''))
try:
response_data = action(context, data_dict)
Expand All @@ -462,11 +461,11 @@ def search(self, ver=None, register=None):
id = request.params['since_id']
if not id:
return self._finish_bad_request(
gettext(u'No revision specified'))
_(u'No revision specified'))
rev = model.Session.query(model.Revision).get(id)
if rev is None:
return self._finish_not_found(
gettext(u'There is no revision with id: %s') % id)
_(u'There is no revision with id: %s') % id)
since_time = rev.timestamp
elif 'since_time' in request.params:
since_time_str = request.params['since_time']
Expand All @@ -476,7 +475,7 @@ def search(self, ver=None, register=None):
return self._finish_bad_request('ValueError: %s' % inst)
else:
return self._finish_bad_request(
gettext("Missing search term ('since_id=UUID' or " +
_("Missing search term ('since_id=UUID' or " +
" 'since_time=TIMESTAMP')"))
revs = model.Session.query(model.Revision).\
filter(model.Revision.timestamp > since_time)
Expand All @@ -486,7 +485,7 @@ def search(self, ver=None, register=None):
params = MultiDict(self._get_search_params(request.params))
except ValueError, e:
return self._finish_bad_request(
gettext('Could not read parameters: %r' % e))
_('Could not read parameters: %r' % e))

# if using API v2, default to returning the package ID if
# no field list is specified
Expand Down Expand Up @@ -543,10 +542,10 @@ def search(self, ver=None, register=None):
except search.SearchError, e:
log.exception(e)
return self._finish_bad_request(
gettext('Bad search option: %s') % e)
_('Bad search option: %s') % e)
else:
return self._finish_not_found(
gettext('Unknown register: %s') % register)
_('Unknown register: %s') % register)

@classmethod
def _get_search_params(cls, request_params):
Expand All @@ -555,7 +554,7 @@ def _get_search_params(cls, request_params):
qjson_param = request_params['qjson'].replace('\\\\u', '\\u')
params = h.json.loads(qjson_param, encoding='utf8')
except ValueError, e:
raise ValueError(gettext('Malformed qjson value') + ': %r'
raise ValueError(_('Malformed qjson value: %r')
% e)
elif len(request_params) == 1 and \
len(request_params.values()[0]) < 2 and \
Expand All @@ -572,7 +571,7 @@ def _get_search_params(cls, request_params):

def markdown(self, ver=None):
raw_markdown = request.params.get('q', '')
results = ckan.misc.MarkdownFormat().to_html(raw_markdown)
results = h.render_markdown(raw_markdown)

return self._finish_ok(results)

Expand Down
29 changes: 15 additions & 14 deletions ckan/controllers/feed.py
Expand Up @@ -21,16 +21,17 @@
# TODO fix imports
import logging
import urlparse
from urllib import urlencode

import webhelpers.feedgenerator
from pylons import config
from pylons.i18n import _
from urllib import urlencode

from ckan import model
from ckan.lib.base import BaseController, c, request, response, json, abort, g
import ckan.model as model
import ckan.lib.base as base
import ckan.lib.helpers as h
from ckan.logic import get_action, NotFound
import ckan.logic as logic

from ckan.common import _, g, c, request, response, json

# TODO make the item list configurable
ITEMS_LIMIT = 20
Expand All @@ -55,7 +56,7 @@ def _package_search(data_dict):
data_dict['rows'] = ITEMS_LIMIT

# package_search action modifies the data_dict, so keep our copy intact.
query = get_action('package_search')(context, data_dict.copy())
query = logic.get_action('package_search')(context, data_dict.copy())

return query['count'], query['results']

Expand Down Expand Up @@ -151,7 +152,7 @@ def _create_atom_id(resource_path, authority_name=None, date_string=None):
return ':'.join(['tag', tagging_entity, resource_path])


class FeedController(BaseController):
class FeedController(base.BaseController):
base_url = config.get('ckan.site_url')

def _alternate_url(self, params, **kwargs):
Expand All @@ -170,9 +171,9 @@ def group(self, id):
try:
context = {'model': model, 'session': model.Session,
'user': c.user or c.author}
group_dict = get_action('group_show')(context, {'id': id})
except NotFound:
abort(404, _('Group not found'))
group_dict = logic.get_action('group_show')(context, {'id': id})
except logic.NotFound:
base.abort(404, _('Group not found'))

data_dict, params = self._parse_url_params()
data_dict['fq'] = 'groups:"%s"' % id
Expand Down Expand Up @@ -281,9 +282,9 @@ def custom(self):
try:
page = int(request.params.get('page', 1))
except ValueError:
abort(400, _('"page" parameter must be a positive integer'))
base.abort(400, _('"page" parameter must be a positive integer'))
if page < 0:
abort(400, _('"page" parameter must be a positive integer'))
base.abort(400, _('"page" parameter must be a positive integer'))

limit = ITEMS_LIMIT
data_dict = {
Expand Down Expand Up @@ -433,9 +434,9 @@ def _parse_url_params(self):
try:
page = int(request.params.get('page', 1)) or 1
except ValueError:
abort(400, _('"page" parameter must be a positive integer'))
base.abort(400, _('"page" parameter must be a positive integer'))
if page < 0:
abort(400, _('"page" parameter must be a positive integer'))
base.abort(400, _('"page" parameter must be a positive integer'))

limit = ITEMS_LIMIT
data_dict = {
Expand Down
9 changes: 1 addition & 8 deletions ckan/controllers/group.py
Expand Up @@ -201,14 +201,7 @@ def _read(self, id, limit):
else:
q += ' groups:"%s"' % c.group_dict.get('name')

try:
description_formatted = ckan.misc.MarkdownFormat().to_html(
c.group_dict.get('description', ''))
c.description_formatted = genshi.HTML(description_formatted)
except Exception, e:
error_msg = "<span class='inline-warning'>%s</span>" %\
_("Cannot render description")
c.description_formatted = genshi.HTML(error_msg)
c.description_formatted = h.render_markdown(c.group_dict.get('description'))

context['return_query'] = True

Expand Down
7 changes: 4 additions & 3 deletions ckan/controllers/home.py
@@ -1,5 +1,4 @@
from pylons.i18n import _
from pylons import g, c, config, cache
from pylons import config, cache
import sqlalchemy.exc

import ckan.logic as logic
Expand All @@ -9,6 +8,8 @@
import ckan.model as model
import ckan.lib.helpers as h

from ckan.common import _, g, c

CACHE_PARAMETERS = ['__cache', '__no_cache__']

# horrible hack
Expand Down Expand Up @@ -143,7 +144,7 @@ def db_to_form_schema(group_type=None):
global dirty_cached_group_stuff
if not dirty_cached_group_stuff:
groups_data = []
groups = config.get('demo.featured_groups', '').split()
groups = config.get('ckan.featured_groups', '').split()

for group_name in groups:
group = get_group(group_name)
Expand Down

0 comments on commit 45b11bd

Please sign in to comment.