Skip to content

Commit

Permalink
Merge branch 'master' into enh-1803-clean-up-routes
Browse files Browse the repository at this point in the history
Conflicts:
	ckan/config/routing.py
  • Loading branch information
tobes committed Feb 28, 2012
2 parents 88419af + 1a9227d commit 593943a
Show file tree
Hide file tree
Showing 120 changed files with 19,071 additions and 14,367 deletions.
6 changes: 3 additions & 3 deletions .tx/config
@@ -1,13 +1,13 @@
[main]
host = http://www.transifex.net

[ckan.1-5]
[ckan.1-6]
file_filter = ckan/i18n/<lang>/LC_MESSAGES/ckan.po
source_file = ckan/i18n/ckan.pot
source_lang = en
type = PO

# Namings not quite the same in Transifex and babel:
# Transifex vs Babel (& CKAN)
# 'sr@Latin' vs 'sr_Latn'
trans.sr@Latin = ckan/i18n/sr_Latn/LC_MESSAGES/ckan.po
trans.sr@latin = ckan/i18n/sr_Latn/LC_MESSAGES/ckan.po
trans.sr@latin = ckan/i18n/sr_Latn/LC_MESSAGES/ckan.po
51 changes: 49 additions & 2 deletions CHANGELOG.txt
@@ -1,7 +1,52 @@
CKAN CHANGELOG
++++++++++++++

v1.5.1 2011-01-04
v1.6 2012-02-24
===============

Major:
* Resources now have their own pages, as well as showing in the Dataset (#1445, #1449)
* Group pages enhanced, including in-group search (#1521)
* User pages enhanced with lists of datasets (#1396) and recent activity (#1515)
* Dataset view page decluttered (#1450)
* Tags not restricted to just letters and dashes (#1453)
* Stats Extension and Storage Extension moved into core CKAN (#1576, #1608)
* Ability to mounting CKAN at a sub-URL (#1401, #1659)
* 5 Stars of Openness ratings show by resources, if ckanext-qa is installed (#1583)
* Recline Data Explorer (for previewing and plotting data) improved and v2 moved into core CKAN (#1602, #1630)

Minor:
* 'About' page rewritten and easily customisable in the config (#1626)
* Gravatar picture displayed next to My Account link (#1528)
* 'Delete' button for datasets (#1425)
* Relationships API more RESTful, validated and documented (#1695)
* User name displayed when logged in (#1529)
* Database dumps now exclude deleted packages (#1623)
* Dataset/Tag name length now limited to 100 characters in API (#1473)
* 'Status' API call now includes installed extensions (#1488)
* Command-line interface for list/read/deleting datasets (#1499)
* Slug API calls tidied up and documented (#1500)
* Users nagged to add email address if missing from their account (#1413)
* Model and API for Users to become Members of a Group in a certain Capacity (#1531, #1477)
* Extension interface to adjust search queries, indexing and results (#1547, #1738)
* API for changing permissions (#1688)

Bug fixes:
* Group deletion didn't work (#1536)
* metadata_created used to return an entirely wrong date (#1546)
* Unicode characters in field-specific API search queries caused exception (since CKAN 1.5) (#1798)
* Sometimes task_status errors weren't being recorded (#1483)
* Registering or Logging in failed silently when already logged in (#1799)
* Deleted packages were browseable by administrators and appeared in dumps (#1283, #1623)
* Facicon was a broken link unless corrected in config file (#1627)
* Dataset search showed last result of each page out of order (#1683)
* 'Simple search' mode showed 0 packages on home page (#1709)
* Occasionally, 'My Account' shows when user is not logged in (#1513)
* Could not change language when on a tag page that had accented characters or dataset creation page (#1783, #1791)
* Editing package via API deleted its relationships (#1786)


v1.5.1 2012-01-04
=================

Major:
Expand All @@ -27,7 +72,7 @@ Minor:
* New config options to ease CSS insertion into the template (#1380)
* Removed ETag browser cache headers (#1422)
* CKAN version number and admin contact in new 'status_show' API (#1087)
* Upgrade SQLAlchemy to 0.7.3 (#1433)
* Upgrade SQLAlchemy to 0.7.3 (compatible with Postgres up to 9.1) (#1433)
* SOLR schema is now versioned (#1498)

Bug fixes:
Expand All @@ -42,6 +87,7 @@ Bug fixes:
* OpenID registration disablement explained better (#1532)
* Data upload (with ckanext-storage) failed if spaces in the filename (#1518)
* Resource download count fixed (integration with ckanext-googleanalytics) (#1451)
* Multiple CKANs with same dataset IDs on the same SOLR core would conflict (#1462)


v1.5 2011-11-07
Expand Down Expand Up @@ -83,6 +129,7 @@ Bug fixes:
* Various minor exceptions cropped up (mostly since 1.4.3) (#1334, #1346)
* Extra field couldn't be set to original value when key deleted (#1356)
* JSONP callback parameter didn't work for the Action API (since 1.4.3) (#1437)
* The same tag could be added to a package multiple times (#1331)


v1.4.3.1 2011-09-30
Expand Down
5 changes: 5 additions & 0 deletions ckan/config/routing.py
Expand Up @@ -16,6 +16,7 @@ def make_map():
"""Create, configure and return the routes Mapper"""
# import controllers here rather than at root level because
# pylons config is initialised by this point.
<<<<<<< HEAD


# Helpers to reduce code clutter
Expand All @@ -28,6 +29,10 @@ def make_map():

from ckan.controllers.package import register_pluggable_behaviour as register_package_behaviour
from ckan.controllers.group import register_pluggable_behaviour as register_group_behaviour
=======
from lib.plugins import register_package_plugins as register_package_behaviour
from lib.plugins import register_group_plugins as register_group_behaviour
>>>>>>> master

map = Mapper(directory=config['pylons.paths']['controllers'],
always_scan=config['debug'])
Expand Down
10 changes: 5 additions & 5 deletions ckan/controllers/api.py
Expand Up @@ -11,7 +11,6 @@
from ckan.lib.search import (query_for, QueryOptions, SearchIndexError, SearchError,
SearchQueryError, DEFAULT_OPTIONS,
convert_legacy_parameters_to_solr)
from ckan.plugins import PluginImplementations, IGroupController
from ckan.lib.navl.dictization_functions import DataError
from ckan.lib.munge import munge_name, munge_title_to_name, munge_tag
from ckan.logic import get_action, check_access
Expand Down Expand Up @@ -144,13 +143,16 @@ def get_api(self, ver=None):
return self._finish_ok(response_data)

def action(self, logic_function):
# FIXME this is a hack till ver gets passed
api_version = 3
function = get_action(logic_function)
if not function:
log.error('Can\'t find logic function: %s' % logic_function)
return self._finish_bad_request(
gettext('Action name not known: %s') % str(logic_function))

context = {'model': model, 'session': model.Session, 'user': c.user}
context = {'model': model, 'session': model.Session, 'user': c.user,
'api_version':api_version}
model.Session()._context = context
return_dict = {'help': function.__doc__}
try:
Expand Down Expand Up @@ -276,7 +278,6 @@ def show(self, ver=None, register=None, subregister=None, id=None, id2=None):
return self._finish_bad_request(
gettext('Cannot read entity of this type: %s') % register)
try:

return self._finish_ok(action(context, data_dict))
except NotFound, e:
extra_msg = e.extra_msg
Expand Down Expand Up @@ -643,8 +644,7 @@ def is_slug_valid(self):
if slugtype==u'group':
response_data = dict(valid=not bool(group_exists(slug)))
return self._finish_ok(response_data)
return self._finish_bad_request(gettext('Bad slug type: %s') % slugtype)

return self._finish_bad_request('Bad slug type: %s' % slugtype)

def dataset_autocomplete(self):
q = request.params.get('incomplete', '')
Expand Down
144 changes: 3 additions & 141 deletions ckan/controllers/group.py
Expand Up @@ -3,158 +3,20 @@
import datetime
from urllib import urlencode

from sqlalchemy.orm import eagerload_all
from ckan.lib.base import BaseController, c, model, request, render, h, g
from ckan.lib.base import ValidationException, abort, gettext
from pylons.i18n import get_lang, _
import ckan.authz as authz
from ckan.authz import Authorizer
from ckan.lib.helpers import Page
from ckan.plugins import PluginImplementations, IGroupController, IGroupForm
from ckan.lib.navl.dictization_functions import DataError, unflatten, validate
from ckan.logic import NotFound, NotAuthorized, ValidationError
from ckan.logic import check_access, get_action
from ckan.logic.schema import group_form_schema
from ckan.logic import tuplize_dict, clean_dict, parse_params
from ckan.lib.dictization.model_dictize import package_dictize
import ckan.forms
import ckan.logic.action.get

log = logging.getLogger(__name__)

# Mapping from group-type strings to IDatasetForm instances
_controller_behaviour_for = dict()

# The fallback behaviour
_default_controller_behaviour = None

def register_pluggable_behaviour(map):
"""
Register the various IGroupForm instances.
This method will setup the mappings between package types and the registered
IGroupForm instances. If it's called more than once an
exception will be raised.
"""
global _default_controller_behaviour

# Create the mappings and register the fallback behaviour if one is found.
for plugin in PluginImplementations(IGroupForm):
if plugin.is_fallback():
if _default_controller_behaviour is not None:
raise ValueError, "More than one fallback "\
"IGroupForm has been registered"
_default_controller_behaviour = plugin

for group_type in plugin.group_types():
# Create the routes based on group_type here, this will allow us to have top level
# objects that are actually Groups, but first we need to make sure we are not
# clobbering an existing domain

# Our version of routes doesn't allow the environ to be passed into the match call
# and so we have to set it on the map instead. This looks like a threading problem
# waiting to happen but it is executed sequentially from instead the routing setup

map.connect('%s_index' % (group_type,),
'/%s' % (group_type,), controller='group', action='index')
map.connect('%s_new' % (group_type,),
'/%s/new' % (group_type,), controller='group', action='new')
map.connect('%s_read' % (group_type,),
'/%s/{id}' % (group_type,), controller='group', action='read')
map.connect('%s_action' % (group_type,),
'/%s/{action}/{id}' % (group_type,), controller='group',
requirements=dict(action='|'.join(['edit', 'authz', 'history' ]))
)

if group_type in _controller_behaviour_for:
raise ValueError, "An existing IGroupForm is "\
"already associated with the package type "\
"'%s'" % group_type
_controller_behaviour_for[group_type] = plugin

# Setup the fallback behaviour if one hasn't been defined.
if _default_controller_behaviour is None:
_default_controller_behaviour = DefaultGroupForm()


def _lookup_plugin(group_type):
"""
Returns the plugin controller associoated with the given group type.
If the group type is None or cannot be found in the mapping, then the
fallback behaviour is used.
"""
if group_type is None:
return _default_controller_behaviour
return _controller_behaviour_for.get(group_type,
_default_controller_behaviour)


class DefaultGroupForm(object):
"""
Provides a default implementation of the pluggable Group controller behaviour.
This class has 2 purposes:
- it provides a base class for IGroupForm implementations
to use if only a subset of the method hooks need to be customised.
- it provides the fallback behaviour if no plugin is setup to provide
the fallback behaviour.
Note - this isn't a plugin implementation. This is deliberate, as
we don't want this being registered.
"""

def group_form(self):
return 'group/new_group_form.html'

def form_to_db_schema(self):
return group_form_schema()
from lib.plugins import lookup_group_plugin as _lookup_plugin

def db_to_form_schema(self):
'''This is an interface to manipulate data from the database
into a format suitable for the form (optional)'''


def check_data_dict(self, data_dict):
'''Check if the return data is correct, mostly for checking out if
spammers are submitting only part of the form
# Resources might not exist yet (eg. Add Dataset)
surplus_keys_schema = ['__extras', '__junk', 'state', 'groups',
'extras_validation', 'save', 'return_to',
'resources']
schema_keys = package_form_schema().keys()
keys_in_schema = set(schema_keys) - set(surplus_keys_schema)
missing_keys = keys_in_schema - set(data_dict.keys())
if missing_keys:
#print data_dict
#print missing_keys
log.info('incorrect form fields posted')
raise DataError(data_dict)
'''
pass

def setup_template_variables(self, context, data_dict):
c.is_sysadmin = Authorizer().is_sysadmin(c.user)

## This is messy as auths take domain object not data_dict
context_group = context.get('group',None)
group = context_group or c.group
if group:
try:
if not context_group:
context['group'] = group
check_access('group_change_state',context)
c.auth_for_change_state = True
except NotAuthorized:
c.auth_for_change_state = False

############## End of pluggable group behaviour ##############
log = logging.getLogger(__name__)


class GroupController(BaseController):
Expand Down Expand Up @@ -421,7 +283,7 @@ def _save_new(self, context, group_type=None):
except NotAuthorized:
abort(401, _('Unauthorized to read group %s') % '')
except NotFound, e:
abort(404, _('Package not found'))
abort(404, _('Group not found'))
except DataError:
abort(400, _(u'Integrity Error'))
except ValidationError, e:
Expand Down
16 changes: 10 additions & 6 deletions ckan/controllers/home.py
Expand Up @@ -15,6 +15,8 @@
from ckan.lib.hash import get_redirect
from ckan.lib.helpers import url_for

CACHE_PARAMETER = '__cache'

class HomeController(BaseController):
repo = model.repo

Expand Down Expand Up @@ -67,14 +69,16 @@ def index(self):
c.userobj.name.startswith('https://www.google.com/accounts/o8/id')
if not c.userobj.email and (is_google_id and not c.userobj.fullname):
msg = _('Please <a href="%s">update your profile</a>'
' and add your email address and your full name. %s uses'
' your email address if you need to reset your'
' password.''') % (url, g.site_title)
' and add your email address and your full name. ') % url + \
_('%s uses your email address'
' if you need to reset your password.') \
% g.site_title
elif not c.userobj.email:
msg = _('Please <a href="%s">update your profile</a>'
' and add your email address. %s uses your email address'
' if you need to reset your password.') \
% (url, g.site_title)
' and add your email address. ') % url + \
_('%s uses your email address'
' if you need to reset your password.') \
% g.site_title
elif is_google_id and not c.userobj.fullname:
msg = _('Please <a href="%s">update your profile</a>'
' and add your full name.') % (url)
Expand Down

0 comments on commit 593943a

Please sign in to comment.