Skip to content

Commit

Permalink
Merge branch 'master' into feature-2375-demo-theme
Browse files Browse the repository at this point in the history
Conflicts:
	ckan/config/environment.py

	comment reformatting

	ckan/controllers/user.py

	redirect on login and flash message fix - keep both

	ckan/lib/helpers.py

	new functions in both branches - keep

	ckan/lib/i18n.py

	minor change

	ckan/templates/group/read.html
	ckan/templates/package/read.html
	ckan/templates/package/resource_read.html
	ckan/templates/package/search.html

	ignore template changes as not relevant

	doc/install-from-source.rst

	less install instructions

	requires/lucid_conflict.txt
	requires/lucid_missing.txt

	requirements jinja2/fanstatic moved to pip-requirements.txt

	setup.py

	use ckan i18n `ripper` not genshi
  • Loading branch information
tobes committed Jul 9, 2012
2 parents b0edf25 + 4636408 commit 997635b
Show file tree
Hide file tree
Showing 72 changed files with 4,427 additions and 817 deletions.
23 changes: 23 additions & 0 deletions CHANGELOG.txt
@@ -1,6 +1,29 @@
CKAN CHANGELOG
++++++++++++++

v1.8
====

* [#2592,#2428] Ubuntu 12.04 Precise is now supported with CKAN source install.
The source install instructions have been updated and simplified.
Some of CKAN's dependencies have been updated and some removed.
* Requirements have been updated see doc/install-from-source.rst
users will need to do a new pip install (#2592)
* [#2304] New 'follow' feature. You'll now see a 'Followers' tab on user and
dataset pages, where you can see how many users are following that user or
dataset. If you're logged in, you'll see a 'Follow' button on the pages of
datasets and other users that you can click to follow them. There are also
API calls for the follow features, see the Action API reference
documentation.
* [#2305] New user dashboards, implemented by Sven R. Kunze
(https://github.com/kunsv) as part of his Masters thesis. When logged in, if
you go to your own user page you'll see a new 'Dashboard' tab where you can
see an activity stream from of all the users and datasets that you're
following.
* [#2345] New action API reference docs. The documentation for CKAN's Action
API has been rewritten, with each function and its arguments and return
values now individually documented.

v1.7.1 2012-06-20
=================

Expand Down
7 changes: 6 additions & 1 deletion ckan/config/deployment.ini_tmpl
Expand Up @@ -24,7 +24,7 @@ app_instance_uuid = ${app_instance_uuid}

# List the names of CKAN extensions to activate.
# Note: This line is required to be here for packaging, even if it is empty.
ckan.plugins = stats synchronous_search
ckan.plugins = stats

# If you'd like to fine-tune the individual locations of the cache data dirs
# for the Cache data, or the Session saves, un-comment the desired settings
Expand Down Expand Up @@ -112,6 +112,11 @@ ckan.gravatar_default = identicon
## Solr support
#solr_url = http://127.0.0.1:8983/solr

## Automatic indexing. Make all changes immediately available via the search
## after editing or creating a dataset. Default is true. If for some reason
## you need the indexing to occur asynchronously, set this option to 0.
# ckan.search.automatic_indexing = 1

## An 'id' for the site (using, for example, when creating entries in a common search index)
## If not specified derived from the site_url
# ckan.site_id = ckan.net
Expand Down
35 changes: 25 additions & 10 deletions ckan/config/environment.py
Expand Up @@ -21,12 +21,14 @@
import ckan.lib.search as search
import ckan.lib.app_globals as app_globals

log = logging.getLogger(__name__)

import lib.jinja_tags

# Suppress benign warning 'Unbuilt egg for setuptools'
warnings.simplefilter('ignore', UserWarning)


class _Helpers(object):
''' Helper object giving access to template helpers stopping
missing functions from causing template exceptions. Useful if
Expand Down Expand Up @@ -97,13 +99,16 @@ def load_environment(global_conf, app_conf):
from pylons.wsgiapp import PylonsApp
import pkg_resources
find_controller_generic = PylonsApp.find_controller

# This is from pylons 1.0 source, will monkey-patch into 0.9.7
def find_controller(self, controller):
if controller in self.controller_classes:
return self.controller_classes[controller]
# Check to see if its a dotted name
if '.' in controller or ':' in controller:
mycontroller = pkg_resources.EntryPoint.parse('x=%s' % controller).load(False)
mycontroller = pkg_resources \
.EntryPoint \
.parse('x=%s' % controller).load(False)
self.controller_classes[controller] = mycontroller
return mycontroller
return find_controller_generic(self, controller)
Expand All @@ -126,6 +131,13 @@ def find_controller(self, controller):
# load all CKAN plugins
p.load_all(config)

# Load the synchronous search plugin, unless already loaded or
# explicitly disabled
if not 'synchronous_search' in config.get('ckan.plugins') and \
asbool(config.get('ckan.search.automatic_indexing', True)):
log.debug('Loading the synchronous search plugin')
p.load('synchronous_search')

for plugin in p.PluginImplementations(p.IConfigurer):
# must do update in place as this does not work:
# config = plugin.update_config(config)
Expand Down Expand Up @@ -160,11 +172,13 @@ def find_controller(self, controller):
config['pylons.app_globals'] = app_globals.Globals()

# add helper functions
restrict_helpers = asbool(config.get('ckan.restrict_template_vars', 'true'))
restrict_helpers = asbool(
config.get('ckan.restrict_template_vars', 'true'))
helpers = _Helpers(h, restrict_helpers)
config['pylons.h'] = helpers

## redo template setup to use genshi.search_path (so remove std template setup)
## redo template setup to use genshi.search_path
## (so remove std template setup)
legacy_templates_path = os.path.join(root, 'templates_legacy')
if asbool(config.get('ckan.legacy_templates', 'no')):
template_paths = [legacy_templates_path]
Expand All @@ -180,6 +194,7 @@ def find_controller(self, controller):

# Translator (i18n)
translator = Translator(pylons.translator)

def template_loaded(template):
translator.setup(template)

Expand Down Expand Up @@ -210,8 +225,6 @@ def template_loaded(template):
# #
#################################################################



'''
This code is based on Genshi code
Expand Down Expand Up @@ -297,11 +310,14 @@ def genshi_lookup_attr(cls, obj, key):

# Setup the SQLAlchemy database engine
# Suppress a couple of sqlalchemy warnings
warnings.filterwarnings('ignore', '^Unicode type received non-unicode bind param value', sqlalchemy.exc.SAWarning)
warnings.filterwarnings('ignore', "^Did not recognize type 'BIGINT' of column 'size'", sqlalchemy.exc.SAWarning)
warnings.filterwarnings('ignore', "^Did not recognize type 'tsvector' of column 'search_vector'", sqlalchemy.exc.SAWarning)
msgs = ['^Unicode type received non-unicode bind param value',
"^Did not recognize type 'BIGINT' of column 'size'",
"^Did not recognize type 'tsvector' of column 'search_vector'"
]
for msg in msgs:
warnings.filterwarnings('ignore', msg, sqlalchemy.exc.SAWarning)

ckan_db = os.environ.get('CKAN_DB')
ckan_db = os.environ.get('CKAN_DB')

if ckan_db:
config['sqlalchemy.url'] = ckan_db
Expand All @@ -320,4 +336,3 @@ def genshi_lookup_attr(cls, obj, key):

for plugin in p.PluginImplementations(p.IConfigurable):
plugin.configure(config)

4 changes: 2 additions & 2 deletions ckan/config/middleware.py
Expand Up @@ -21,7 +21,7 @@

from ckan.plugins import PluginImplementations
from ckan.plugins.interfaces import IMiddleware
from ckan.lib.i18n import get_locales
from ckan.lib.i18n import get_locales_from_config

from ckan.config.environment import load_environment

Expand Down Expand Up @@ -167,7 +167,7 @@ class I18nMiddleware(object):
def __init__(self, app, config):
self.app = app
self.default_locale = config.get('ckan.locale_default', 'en')
self.local_list = get_locales()
self.local_list = get_locales_from_config()

def __call__(self, environ, start_response):
# strip the language selector from the requested url
Expand Down
1 change: 1 addition & 0 deletions ckan/config/routing.py
Expand Up @@ -256,6 +256,7 @@ def make_map():
m.connect('/user/edit', action='edit')
# Note: openid users have slashes in their ids, so need the wildcard
# in the route.
m.connect('/user/dashboard', action='dashboard')
m.connect('/user/followers/{id:.*}', action='followers')
m.connect('/user/edit/{id:.*}', action='edit')
m.connect('/user/reset/{id:.*}', action='perform_reset')
Expand Down
2 changes: 2 additions & 0 deletions ckan/config/solr/CHANGELOG.txt
Expand Up @@ -8,6 +8,8 @@ v1.4 - (ckan>=1.7)
* Add title_string so you can sort alphabetically on title.
* Fields related to analytics, access and view counts.
* Add data_dict field for the whole package_dict.
* Add vocab_* dynamic field so it is possible to facet by vocabulary tags
* Add copyField for text with source vocab_*

v1.3 - (ckan>=1.5.1)
--------------------
Expand Down
2 changes: 2 additions & 0 deletions ckan/config/solr/schema-1.4.xml
Expand Up @@ -153,6 +153,7 @@
<field name="data_dict" type="string" indexed="false" stored="true" />

<dynamicField name="extras_*" type="text" indexed="true" stored="true" multiValued="false"/>
<dynamicField name="vocab_*" type="string" indexed="true" stored="true" multiValued="true"/>
<dynamicField name="*" type="string" indexed="true" stored="false"/>
</fields>

Expand All @@ -165,6 +166,7 @@
<copyField source="download_url" dest="urls"/>
<copyField source="res_url" dest="urls"/>
<copyField source="extras_*" dest="text"/>
<copyField source="vocab_*" dest="text"/>
<copyField source="urls" dest="text"/>
<copyField source="name" dest="text"/>
<copyField source="title" dest="text"/>
Expand Down
1 change: 1 addition & 0 deletions ckan/controllers/api.py
Expand Up @@ -251,6 +251,7 @@ def list(self, ver=None, register=None, subregister=None, id=None):
('dataset', 'activity'): 'package_activity_list',
('group', 'activity'): 'group_activity_list',
('user', 'activity'): 'user_activity_list',
('user', 'dashboard_activity'): 'dashboard_activity_list',
('activity', 'details'): 'activity_detail_list',
}

Expand Down
17 changes: 7 additions & 10 deletions ckan/controllers/datastore.py
@@ -1,9 +1,9 @@
from ckan.lib.base import BaseController, abort, _, c, response, request, g
import ckan.model as model
from ckan.lib.helpers import json
from ckan.lib.jsonp import jsonpify
from ckan.logic import get_action, check_access
from ckan.logic import NotFound, NotAuthorized, ValidationError
from ckan.logic import NotFound, NotAuthorized



class DatastoreController(BaseController):
Expand All @@ -21,8 +21,6 @@ def read(self, id, url=''):

try:
resource = get_action('resource_show')(context, {'id': id})
if not resource.get('webstore_url', ''):
return {'error': 'DataStore is disabled for this resource'}
self._make_redirect(id, url)
return ''
except NotFound:
Expand All @@ -35,13 +33,12 @@ def write(self, id, url):
context = {'model': model, 'session': model.Session,
'user': c.user or c.author}
try:
resource = model.Resource.get(id)
if not resource:
abort(404, _('Resource not found'))
if not resource.webstore_url:
return {'error': 'DataStore is disabled for this resource'}
context["resource"] = resource
check_access('resource_update', context, {'id': id})
resource_dict = get_action('resource_show')(context,{'id':id})
if not resource_dict['webstore_url']:
resource_dict['webstore_url'] = u'active'
get_action('resource_update')(context,resource_dict)

self._make_redirect(id, url)
return ''
except NotFound:
Expand Down
5 changes: 2 additions & 3 deletions ckan/controllers/package.py
Expand Up @@ -744,8 +744,7 @@ def _save_new(self, context, package_type=None):
except DataError:
abort(400, _(u'Integrity Error'))
except SearchIndexError, e:
abort(500, _(u'Unable to add package to search index.') +
repr(e.args))
abort(500, _(u'Unable to add package to search index.'))
except ValidationError, e:
errors = e.error_dict
error_summary = e.error_summary
Expand Down Expand Up @@ -783,7 +782,7 @@ def _save_edit(self, name_or_id, context):
except DataError:
abort(400, _(u'Integrity Error'))
except SearchIndexError, e:
abort(500, _(u'Unable to update search index.') + repr(e.args))
abort(500, _(u'Unable to update search index.'))
except ValidationError, e:
errors = e.error_dict
error_summary = e.error_summary
Expand Down
2 changes: 1 addition & 1 deletion ckan/controllers/related.py
Expand Up @@ -42,7 +42,7 @@ def list(self, id):
base.abort(401, base._('Unauthorized to read package %s') % id)

c.related_count = len(c.pkg.related)

c.action = 'related'
return base.render("package/related_list.html")

def _edit_or_new(self, id, related_id, is_edit):
Expand Down
17 changes: 15 additions & 2 deletions ckan/controllers/user.py
Expand Up @@ -5,6 +5,7 @@
from urllib import quote

import ckan.misc
import ckan.lib.i18n
from ckan.lib.base import *
from ckan.lib import mailer
from ckan.authz import Authorizer
Expand Down Expand Up @@ -117,8 +118,8 @@ def me(self, locale=None):
h.redirect_to(locale=locale, controller='user',
action='login', id=None)
user_ref = c.userobj.get_reference_preferred_for_uri()
h.redirect_to(locale=locale, controller='user',
action='read', id=user_ref)
h.redirect_to(locale=locale, controller='user', action='dashboard',
id=user_ref)

def register(self, data=None, errors=None, error_summary=None):
return self.new(data, errors, error_summary)
Expand Down Expand Up @@ -291,6 +292,11 @@ def logged_in(self):
lang = session.pop('lang', None)
session.save()
came_from = request.params.get('came_from', '')

# we need to set the language explicitly here or the flash
# messages will not be translated.
ckan.lib.i18n.set_lang(lang)

if c.user:
context = {'model': model,
'user': c.user}
Expand Down Expand Up @@ -451,3 +457,10 @@ def followers(self, id=None):
f = get_action('user_follower_list')
c.followers = f(context, {'id': c.user_dict['id']})
return render('user/followers.html')

def dashboard(self, id=None):
context = {'model': model, 'session': model.Session,
'user': c.user or c.author, 'for_view': True}
data_dict = {'id': id, 'user_obj': c.userobj}
self._setup_template_variables(context, data_dict)
return render('user/dashboard.html')
18 changes: 17 additions & 1 deletion ckan/lib/helpers.py
Expand Up @@ -676,7 +676,7 @@ def dict_list_reduce(list_, key, unique=True):

def linked_gravatar(email_hash, size=100, default=None):
return literal(
'<a href="https://gravatar.com/" target="_blank"' +
'<a href="https://gravatar.com/" target="_blank" ' +
'title="%s">' % _('Update your avatar at gravatar.com') +
'%s</a>' % gravatar(email_hash,size,default)
)
Expand Down Expand Up @@ -1160,6 +1160,21 @@ def groups_available():
data_dict = {'available_only': True}
return logic.get_action('group_list_authz')(context, data_dict)

def dashboard_activity_stream(user_id):
'''Return the dashboard activity stream of the given user.
:param user_id: the id of the user
:type user_id: string
:returns: an activity stream as an HTML snippet
:rtype: string
'''
import ckan.logic as logic
context = {'model' : model, 'session':model.Session, 'user':c.user}
return logic.get_action('dashboard_activity_list_html')(context, {'id': user_id})


# these are the functions that will end up in `h` template helpers
# if config option restrict_template_vars is true
__allowed_functions__ = [
Expand Down Expand Up @@ -1229,6 +1244,7 @@ def groups_available():
'remove_url_param',
'add_url_param',
'groups_available',
'dashboard_activity_stream',
# imported into ckan.lib.helpers
'literal',
'link_to',
Expand Down

0 comments on commit 997635b

Please sign in to comment.