[ckan-changes] [okfn/ckan] ec1d21: extend plugin.toolkit functions
GitHub
noreply at github.com
Fri Apr 20 14:27:22 UTC 2012
Branch: refs/heads/feature-2302-simple-theming
Home: https://github.com/okfn/ckan
Commit: ec1d2113a66ed66312ad6b56fe441afb633cf8b1
https://github.com/okfn/ckan/commit/ec1d2113a66ed66312ad6b56fe441afb633cf8b1
Author: Toby <toby.junk at gmail.com>
Date: 2012-04-19 (Thu, 19 Apr 2012)
Changed paths:
M ckan/plugins/toolkit.py
Log Message:
-----------
extend plugin.toolkit functions
diff --git a/ckan/plugins/toolkit.py b/ckan/plugins/toolkit.py
index 64a80d7..59de1c9 100644
--- a/ckan/plugins/toolkit.py
+++ b/ckan/plugins/toolkit.py
@@ -1,21 +1,28 @@
-## This file is intended to make functions consistently available to
-## plugins whilst giving developers the ability move code around or
-## change underlying frameworks etc. It should not be used internaly
-## within ckan only by extensions. Functions should only be removed from
-## this file after reasonable depreciation notice has been given.
+## This file is intended to make functions/objects consistently
+## available to plugins whilst giving developers the ability move code
+## around or change underlying frameworks etc. It should not be used
+## internaly within ckan only by extensions. Functions should only be
+## removed from this file after reasonable depreciation notice has
+## been given.
import inspect
import os
+import re
import pylons
import paste.deploy.converters as converters
import webhelpers.html.tags
-import lib.base as base
+import ckan
+import ckan.lib.base as base
+import ckan.logic as logic
+import ckan.lib.cli as cli
+
__all__ = [
- ## Imported functions ##
+ ## Imported functions/objects ##
+ '_', # i18n translation
'c', # template context
'request', # http request object
'render', # template render function
@@ -25,12 +32,22 @@
'asint', # converts an object to an integer
'aslist', # converts an object to a list
'literal', # stop tags in a string being escaped
+ 'get_action', # get logic action function
+ 'check_access', # check logic function authorisation
+ 'NotFound', # action not found exception
+ 'NotAuthorized', # action not authourized exception
+ 'ValidationError', # model update validation error
+ 'CkanCommand', # class for providing cli interfaces
- ## Functions fully defined here ##
+ ## Fully defined in this file ##
'add_template_directory',
'add_public_directory',
+ 'requires_ckan_version',
+ 'check_ckan_version',
+ 'CkanVersionException',
]
+_ = pylons.i18n._
c = pylons.c
request = pylons.request
render = base.render
@@ -40,6 +57,13 @@
aslist = converters.aslist
literal = webhelpers.html.tags.literal
+get_action = logic.get_action
+check_access = logic.check_access
+NotFound = logic.NotFound
+NotAuthorized = logic.NotAuthorized
+ValidationError = logic.ValidationError
+
+CkanCommand = cli.CkanCommand
# wrappers
def render_snippet(template, data=None):
@@ -73,3 +97,38 @@ def _add_served_directory(config, relative_path, config_var):
config[config_var] += ',' + absolute_path
else:
config[config_var] = absolute_path
+
+class CkanVersionException(Exception):
+ ''' Exception raised if required ckan version is not available. '''
+ pass
+
+
+def _version_str_2_list(v_str):
+ ''' conver a version string into a list of ints
+ eg 1.6.1b --> [1, 6, 1] '''
+ v_str = re.sub(r'[^0-9.]', '', v_str)
+ return [int(part) for part in v_str.split('.')]
+
+def check_ckan_version(min_version=None, max_version=None):
+ ''' Check that the ckan version is correct for the plugin. '''
+ current = _version_str_2_list(ckan.__version__)
+
+ if min_version:
+ min_required = _version_str_2_list(min_version)
+ if current < min_required:
+ return False
+ if max_version:
+ max_required = _version_str_2_list(max_version)
+ if current > max_required:
+ return False
+ return True
+
+def requires_ckan_version(min_version, max_version=None):
+ ''' Check that the ckan version is correct for the plugin. '''
+ if not check_ckan_version(min_version=min_version, max_version=max_version):
+ if not max_version:
+ error = 'Requires ckan version %s or higher' % min_version
+ else:
+ error = 'Requires ckan version between %s and %s' % \
+ (min_version, max_version)
+ raise CkanVersionException(error)
================================================================
Commit: 413f680238f204f791d81a384b52748612f58284
https://github.com/okfn/ckan/commit/413f680238f204f791d81a384b52748612f58284
Author: Toby <toby.junk at gmail.com>
Date: 2012-04-19 (Thu, 19 Apr 2012)
Changed paths:
M ckan/plugins/toolkit.py
Log Message:
-----------
[xs] learn to spell
diff --git a/ckan/plugins/toolkit.py b/ckan/plugins/toolkit.py
index 59de1c9..27e0fd0 100644
--- a/ckan/plugins/toolkit.py
+++ b/ckan/plugins/toolkit.py
@@ -35,7 +35,7 @@
'get_action', # get logic action function
'check_access', # check logic function authorisation
'NotFound', # action not found exception
- 'NotAuthorized', # action not authourized exception
+ 'NotAuthorized', # action not authorized exception
'ValidationError', # model update validation error
'CkanCommand', # class for providing cli interfaces
================================================================
Commit: 5ceee26d8cb0b7c6df390d09f978b0acfa6275e5
https://github.com/okfn/ckan/commit/5ceee26d8cb0b7c6df390d09f978b0acfa6275e5
Author: Toby <toby.junk at gmail.com>
Date: 2012-04-19 (Thu, 19 Apr 2012)
Changed paths:
M ckan/plugins/toolkit.py
Log Message:
-----------
[xs] spelling
diff --git a/ckan/plugins/toolkit.py b/ckan/plugins/toolkit.py
index 27e0fd0..de72479 100644
--- a/ckan/plugins/toolkit.py
+++ b/ckan/plugins/toolkit.py
@@ -1,7 +1,7 @@
## This file is intended to make functions/objects consistently
## available to plugins whilst giving developers the ability move code
## around or change underlying frameworks etc. It should not be used
-## internaly within ckan only by extensions. Functions should only be
+## internally within ckan only by extensions. Functions should only be
## removed from this file after reasonable depreciation notice has
## been given.
================================================================
Commit: cf1211145f7cc1896f4bae49c37936dccce112a9
https://github.com/okfn/ckan/commit/cf1211145f7cc1896f4bae49c37936dccce112a9
Author: Toby <toby.junk at gmail.com>
Date: 2012-04-19 (Thu, 19 Apr 2012)
Changed paths:
M ckan/plugins/toolkit.py
Log Message:
-----------
plugin.toolkit NotFound -> ActionNotFound
diff --git a/ckan/plugins/toolkit.py b/ckan/plugins/toolkit.py
index de72479..e635c43 100644
--- a/ckan/plugins/toolkit.py
+++ b/ckan/plugins/toolkit.py
@@ -34,7 +34,7 @@
'literal', # stop tags in a string being escaped
'get_action', # get logic action function
'check_access', # check logic function authorisation
- 'NotFound', # action not found exception
+ 'ActionNotFound', # action not found exception (ckan.logic.NotFound)
'NotAuthorized', # action not authorized exception
'ValidationError', # model update validation error
'CkanCommand', # class for providing cli interfaces
@@ -59,7 +59,7 @@
get_action = logic.get_action
check_access = logic.check_access
-NotFound = logic.NotFound
+ActionNotFound = logic.NotFound ## Name change intentional
NotAuthorized = logic.NotAuthorized
ValidationError = logic.ValidationError
================================================================
Commit: 66b596ce01b1613a9398bb25d6b266e4b4828b6e
https://github.com/okfn/ckan/commit/66b596ce01b1613a9398bb25d6b266e4b4828b6e
Author: Toby <toby.junk at gmail.com>
Date: 2012-04-20 (Fri, 20 Apr 2012)
Changed paths:
M ckan/lib/base.py
Log Message:
-----------
import clean
diff --git a/ckan/lib/base.py b/ckan/lib/base.py
index da9d69f..075029c 100644
--- a/ckan/lib/base.py
+++ b/ckan/lib/base.py
@@ -22,7 +22,7 @@
import ckan.exceptions
import ckan
-from ckan import authz
+import ckan.authz as authz
from ckan.lib import i18n
import ckan.lib.helpers as h
from ckan.plugins import PluginImplementations, IGenshiStreamFilter
================================================================
Commit: 79e42821a2eddfaedb12e6d6a5376ae4a6354a70
https://github.com/okfn/ckan/commit/79e42821a2eddfaedb12e6d6a5376ae4a6354a70
Author: Toby <toby.junk at gmail.com>
Date: 2012-04-20 (Fri, 20 Apr 2012)
Changed paths:
M ckan/lib/cli.py
Log Message:
-----------
import clean in lib/cli
diff --git a/ckan/lib/cli.py b/ckan/lib/cli.py
index 5146aa9..6798cc4 100644
--- a/ckan/lib/cli.py
+++ b/ckan/lib/cli.py
@@ -84,7 +84,7 @@ class ManageDb(CkanCommand):
def command(self):
self._load_config()
- from ckan import model
+ import ckan.model as model
import ckan.lib.search as search
cmd = self.args[0]
@@ -164,7 +164,7 @@ def _postgres_dump(self, filepath):
self._run_cmd(pg_dump_cmd)
def _postgres_load(self, filepath):
- from ckan import model
+ import ckan.model as model
assert not model.repo.are_tables_created(), "Tables already found. You need to 'db clean' before a load."
pg_cmd = self._get_psql_cmd() + ' -f %s' % filepath
self._run_cmd(pg_cmd)
@@ -194,7 +194,7 @@ def load(self, only_load=False):
pg_cmd = self._postgres_load(dump_path)
if not only_load:
print 'Upgrading DB'
- from ckan import model
+ import ckan.model as model
model.repo.upgrade_db()
print 'Rebuilding search index'
@@ -205,7 +205,7 @@ def load(self, only_load=False):
print 'Done'
def simple_dump_csv(self):
- from ckan import model
+ import ckan.model as model
if len(self.args) < 2:
print 'Need csv file path'
return
@@ -215,7 +215,7 @@ def simple_dump_csv(self):
dumper.SimpleDumper().dump(dump_file, format='csv')
def simple_dump_json(self):
- from ckan import model
+ import ckan.model as model
if len(self.args) < 2:
print 'Need json file path'
return
@@ -452,7 +452,7 @@ class Sysadmin(CkanCommand):
def command(self):
self._load_config()
- from ckan import model
+ import ckan.model as model
cmd = self.args[0] if self.args else None
if cmd == None or cmd == 'list':
@@ -465,7 +465,7 @@ def command(self):
print 'Command %s not recognized' % cmd
def list(self):
- from ckan import model
+ import ckan.model as model
print 'Sysadmins:'
sysadmins = model.Session.query(model.SystemRole).filter_by(role=model.Role.ADMIN)
print 'count = %i' % sysadmins.count()
@@ -477,7 +477,7 @@ def list(self):
user_or_authgroup.id)
def add(self):
- from ckan import model
+ import ckan.model as model
if len(self.args) < 2:
print 'Need name of the user to be made sysadmin.'
@@ -501,7 +501,7 @@ def add(self):
print 'Added %s as sysadmin' % username
def remove(self):
- from ckan import model
+ import ckan.model as model
if len(self.args) < 2:
print 'Need name of the user to be made sysadmin.'
@@ -537,7 +537,7 @@ class UserCmd(CkanCommand):
def command(self):
self._load_config()
- from ckan import model
+ import ckan.model as model
if not self.args:
self.list()
@@ -563,7 +563,7 @@ def get_user_str(self, user):
return user_str
def list(self):
- from ckan import model
+ import ckan.model as model
print 'Users:'
users = model.Session.query(model.User)
print 'count = %i' % users.count()
@@ -571,14 +571,14 @@ def list(self):
print self.get_user_str(user)
def show(self):
- from ckan import model
+ import ckan.model as model
username = self.args[0]
user = model.User.get(unicode(username))
print 'User: \n', user
def setpass(self):
- from ckan import model
+ import ckan.model as model
if len(self.args) < 2:
print 'Need name of the user.'
@@ -593,7 +593,7 @@ def setpass(self):
print 'Done'
def search(self):
- from ckan import model
+ import ckan.model as model
if len(self.args) < 2:
print 'Need user name query string.'
@@ -618,7 +618,7 @@ def password_prompt(cls):
return password1
def add(self):
- from ckan import model
+ import ckan.model as model
if len(self.args) < 2:
print 'Need name of the user.'
@@ -671,7 +671,7 @@ def add(self):
print user
def remove(self):
- from ckan import model
+ import ckan.model as model
if len(self.args) < 2:
print 'Need name of the user.'
@@ -704,7 +704,7 @@ class DatasetCmd(CkanCommand):
def command(self):
self._load_config()
- from ckan import model
+ import ckan.model as model
if not self.args:
print self.usage
@@ -722,7 +722,7 @@ def command(self):
self.show(self.args[0])
def list(self):
- from ckan import model
+ import ckan.model as model
print 'Datasets:'
datasets = model.Session.query(model.Package)
print 'count = %i' % datasets.count()
@@ -732,19 +732,19 @@ def list(self):
print '%s %s %s' % (dataset.id, dataset.name, state)
def _get_dataset(self, dataset_ref):
- from ckan import model
+ import ckan.model as model
dataset = model.Package.get(unicode(dataset_ref))
assert dataset, 'Could not find dataset matching reference: %r' % dataset_ref
return dataset
def show(self, dataset_ref):
- from ckan import model
import pprint
dataset = self._get_dataset(dataset_ref)
pprint.pprint(dataset.as_dict())
def delete(self, dataset_ref):
- from ckan import model, plugins
+ from ckan import plugins
+ import ckan.model as model
dataset = self._get_dataset(dataset_ref)
old_state = dataset.state
@@ -756,7 +756,8 @@ def delete(self, dataset_ref):
print '%s %s -> %s' % (dataset.name, old_state, dataset.state)
def purge(self, dataset_ref):
- from ckan import model, plugins
+ from ckan import plugins
+ import ckan.model as model
dataset = self._get_dataset(dataset_ref)
name = dataset.name
@@ -802,7 +803,7 @@ def run_(self):
def view(self):
self._load_config()
- from ckan import model
+ import ckan.model as model
from kombu.transport.sqlalchemy.models import Message
q = model.Session.query(Message)
q_visible = q.filter_by(visible=True)
@@ -816,7 +817,7 @@ def view(self):
def clean(self):
self._load_config()
- from ckan import model
+ import ckan.model as model
import pprint
tasks_initially = model.Session.execute("select * from kombu_message").rowcount
if not tasks_initially:
@@ -847,7 +848,7 @@ class Ratings(CkanCommand):
def command(self):
self._load_config()
- from ckan import model
+ import ckan.model as model
cmd = self.args[0]
if cmd == 'count':
@@ -860,14 +861,14 @@ def command(self):
print 'Command %s not recognized' % cmd
def count(self):
- from ckan import model
+ import ckan.model as model
q = model.Session.query(model.Rating)
print "%i ratings" % q.count()
q = q.filter(model.Rating.user_id == None)
print "of which %i are anonymous ratings" % q.count()
def clean(self, user_ratings=True):
- from ckan import model
+ import ckan.model as model
q = model.Session.query(model.Rating)
print "%i ratings" % q.count()
if not user_ratings:
================================================================
Commit: e3c3c004ff21fa3848d49251310a8a4b399ab496
https://github.com/okfn/ckan/commit/e3c3c004ff21fa3848d49251310a8a4b399ab496
Author: Toby <toby.junk at gmail.com>
Date: 2012-04-20 (Fri, 20 Apr 2012)
Changed paths:
M ckan/plugins/__init__.py
Log Message:
-----------
avoid circular imports in plugins.toolkit
diff --git a/ckan/plugins/__init__.py b/ckan/plugins/__init__.py
index fcb6055..e11e909 100644
--- a/ckan/plugins/__init__.py
+++ b/ckan/plugins/__init__.py
@@ -1,3 +1,19 @@
from ckan.plugins.core import *
from ckan.plugins.interfaces import *
-import toolkit
+
+
+class _Toolkit(object):
+ ''' This object allows us to avoid circular imports while making
+ functions/objects available to plugins. '''
+
+ def __init__(self):
+ self.toolkit = None
+
+ def __getattr__(self, name):
+ if not self.toolkit:
+ import toolkit
+ self.toolkit = toolkit
+ return getattr(self.toolkit, name)
+
+toolkit = _Toolkit()
+del _Toolkit
================================================================
Commit: 762901f7d21dbaecf3f120c21d9136375c632a77
https://github.com/okfn/ckan/commit/762901f7d21dbaecf3f120c21d9136375c632a77
Author: Ross Jones <rossdjones at gmail.com>
Date: 2012-04-20 (Fri, 20 Apr 2012)
Changed paths:
M ckan/lib/base.py
M ckan/lib/cli.py
M ckan/plugins/__init__.py
M ckan/plugins/toolkit.py
Log Message:
-----------
Merge branch 'master' of https://github.com/okfn/ckan
diff --git a/ckan/lib/base.py b/ckan/lib/base.py
index da9d69f..075029c 100644
--- a/ckan/lib/base.py
+++ b/ckan/lib/base.py
@@ -22,7 +22,7 @@
import ckan.exceptions
import ckan
-from ckan import authz
+import ckan.authz as authz
from ckan.lib import i18n
import ckan.lib.helpers as h
from ckan.plugins import PluginImplementations, IGenshiStreamFilter
diff --git a/ckan/lib/cli.py b/ckan/lib/cli.py
index 5146aa9..6798cc4 100644
--- a/ckan/lib/cli.py
+++ b/ckan/lib/cli.py
@@ -84,7 +84,7 @@ class ManageDb(CkanCommand):
def command(self):
self._load_config()
- from ckan import model
+ import ckan.model as model
import ckan.lib.search as search
cmd = self.args[0]
@@ -164,7 +164,7 @@ def _postgres_dump(self, filepath):
self._run_cmd(pg_dump_cmd)
def _postgres_load(self, filepath):
- from ckan import model
+ import ckan.model as model
assert not model.repo.are_tables_created(), "Tables already found. You need to 'db clean' before a load."
pg_cmd = self._get_psql_cmd() + ' -f %s' % filepath
self._run_cmd(pg_cmd)
@@ -194,7 +194,7 @@ def load(self, only_load=False):
pg_cmd = self._postgres_load(dump_path)
if not only_load:
print 'Upgrading DB'
- from ckan import model
+ import ckan.model as model
model.repo.upgrade_db()
print 'Rebuilding search index'
@@ -205,7 +205,7 @@ def load(self, only_load=False):
print 'Done'
def simple_dump_csv(self):
- from ckan import model
+ import ckan.model as model
if len(self.args) < 2:
print 'Need csv file path'
return
@@ -215,7 +215,7 @@ def simple_dump_csv(self):
dumper.SimpleDumper().dump(dump_file, format='csv')
def simple_dump_json(self):
- from ckan import model
+ import ckan.model as model
if len(self.args) < 2:
print 'Need json file path'
return
@@ -452,7 +452,7 @@ class Sysadmin(CkanCommand):
def command(self):
self._load_config()
- from ckan import model
+ import ckan.model as model
cmd = self.args[0] if self.args else None
if cmd == None or cmd == 'list':
@@ -465,7 +465,7 @@ def command(self):
print 'Command %s not recognized' % cmd
def list(self):
- from ckan import model
+ import ckan.model as model
print 'Sysadmins:'
sysadmins = model.Session.query(model.SystemRole).filter_by(role=model.Role.ADMIN)
print 'count = %i' % sysadmins.count()
@@ -477,7 +477,7 @@ def list(self):
user_or_authgroup.id)
def add(self):
- from ckan import model
+ import ckan.model as model
if len(self.args) < 2:
print 'Need name of the user to be made sysadmin.'
@@ -501,7 +501,7 @@ def add(self):
print 'Added %s as sysadmin' % username
def remove(self):
- from ckan import model
+ import ckan.model as model
if len(self.args) < 2:
print 'Need name of the user to be made sysadmin.'
@@ -537,7 +537,7 @@ class UserCmd(CkanCommand):
def command(self):
self._load_config()
- from ckan import model
+ import ckan.model as model
if not self.args:
self.list()
@@ -563,7 +563,7 @@ def get_user_str(self, user):
return user_str
def list(self):
- from ckan import model
+ import ckan.model as model
print 'Users:'
users = model.Session.query(model.User)
print 'count = %i' % users.count()
@@ -571,14 +571,14 @@ def list(self):
print self.get_user_str(user)
def show(self):
- from ckan import model
+ import ckan.model as model
username = self.args[0]
user = model.User.get(unicode(username))
print 'User: \n', user
def setpass(self):
- from ckan import model
+ import ckan.model as model
if len(self.args) < 2:
print 'Need name of the user.'
@@ -593,7 +593,7 @@ def setpass(self):
print 'Done'
def search(self):
- from ckan import model
+ import ckan.model as model
if len(self.args) < 2:
print 'Need user name query string.'
@@ -618,7 +618,7 @@ def password_prompt(cls):
return password1
def add(self):
- from ckan import model
+ import ckan.model as model
if len(self.args) < 2:
print 'Need name of the user.'
@@ -671,7 +671,7 @@ def add(self):
print user
def remove(self):
- from ckan import model
+ import ckan.model as model
if len(self.args) < 2:
print 'Need name of the user.'
@@ -704,7 +704,7 @@ class DatasetCmd(CkanCommand):
def command(self):
self._load_config()
- from ckan import model
+ import ckan.model as model
if not self.args:
print self.usage
@@ -722,7 +722,7 @@ def command(self):
self.show(self.args[0])
def list(self):
- from ckan import model
+ import ckan.model as model
print 'Datasets:'
datasets = model.Session.query(model.Package)
print 'count = %i' % datasets.count()
@@ -732,19 +732,19 @@ def list(self):
print '%s %s %s' % (dataset.id, dataset.name, state)
def _get_dataset(self, dataset_ref):
- from ckan import model
+ import ckan.model as model
dataset = model.Package.get(unicode(dataset_ref))
assert dataset, 'Could not find dataset matching reference: %r' % dataset_ref
return dataset
def show(self, dataset_ref):
- from ckan import model
import pprint
dataset = self._get_dataset(dataset_ref)
pprint.pprint(dataset.as_dict())
def delete(self, dataset_ref):
- from ckan import model, plugins
+ from ckan import plugins
+ import ckan.model as model
dataset = self._get_dataset(dataset_ref)
old_state = dataset.state
@@ -756,7 +756,8 @@ def delete(self, dataset_ref):
print '%s %s -> %s' % (dataset.name, old_state, dataset.state)
def purge(self, dataset_ref):
- from ckan import model, plugins
+ from ckan import plugins
+ import ckan.model as model
dataset = self._get_dataset(dataset_ref)
name = dataset.name
@@ -802,7 +803,7 @@ def run_(self):
def view(self):
self._load_config()
- from ckan import model
+ import ckan.model as model
from kombu.transport.sqlalchemy.models import Message
q = model.Session.query(Message)
q_visible = q.filter_by(visible=True)
@@ -816,7 +817,7 @@ def view(self):
def clean(self):
self._load_config()
- from ckan import model
+ import ckan.model as model
import pprint
tasks_initially = model.Session.execute("select * from kombu_message").rowcount
if not tasks_initially:
@@ -847,7 +848,7 @@ class Ratings(CkanCommand):
def command(self):
self._load_config()
- from ckan import model
+ import ckan.model as model
cmd = self.args[0]
if cmd == 'count':
@@ -860,14 +861,14 @@ def command(self):
print 'Command %s not recognized' % cmd
def count(self):
- from ckan import model
+ import ckan.model as model
q = model.Session.query(model.Rating)
print "%i ratings" % q.count()
q = q.filter(model.Rating.user_id == None)
print "of which %i are anonymous ratings" % q.count()
def clean(self, user_ratings=True):
- from ckan import model
+ import ckan.model as model
q = model.Session.query(model.Rating)
print "%i ratings" % q.count()
if not user_ratings:
diff --git a/ckan/plugins/__init__.py b/ckan/plugins/__init__.py
index fcb6055..e11e909 100644
--- a/ckan/plugins/__init__.py
+++ b/ckan/plugins/__init__.py
@@ -1,3 +1,19 @@
from ckan.plugins.core import *
from ckan.plugins.interfaces import *
-import toolkit
+
+
+class _Toolkit(object):
+ ''' This object allows us to avoid circular imports while making
+ functions/objects available to plugins. '''
+
+ def __init__(self):
+ self.toolkit = None
+
+ def __getattr__(self, name):
+ if not self.toolkit:
+ import toolkit
+ self.toolkit = toolkit
+ return getattr(self.toolkit, name)
+
+toolkit = _Toolkit()
+del _Toolkit
diff --git a/ckan/plugins/toolkit.py b/ckan/plugins/toolkit.py
index 64a80d7..e635c43 100644
--- a/ckan/plugins/toolkit.py
+++ b/ckan/plugins/toolkit.py
@@ -1,21 +1,28 @@
-## This file is intended to make functions consistently available to
-## plugins whilst giving developers the ability move code around or
-## change underlying frameworks etc. It should not be used internaly
-## within ckan only by extensions. Functions should only be removed from
-## this file after reasonable depreciation notice has been given.
+## This file is intended to make functions/objects consistently
+## available to plugins whilst giving developers the ability move code
+## around or change underlying frameworks etc. It should not be used
+## internally within ckan only by extensions. Functions should only be
+## removed from this file after reasonable depreciation notice has
+## been given.
import inspect
import os
+import re
import pylons
import paste.deploy.converters as converters
import webhelpers.html.tags
-import lib.base as base
+import ckan
+import ckan.lib.base as base
+import ckan.logic as logic
+import ckan.lib.cli as cli
+
__all__ = [
- ## Imported functions ##
+ ## Imported functions/objects ##
+ '_', # i18n translation
'c', # template context
'request', # http request object
'render', # template render function
@@ -25,12 +32,22 @@
'asint', # converts an object to an integer
'aslist', # converts an object to a list
'literal', # stop tags in a string being escaped
+ 'get_action', # get logic action function
+ 'check_access', # check logic function authorisation
+ 'ActionNotFound', # action not found exception (ckan.logic.NotFound)
+ 'NotAuthorized', # action not authorized exception
+ 'ValidationError', # model update validation error
+ 'CkanCommand', # class for providing cli interfaces
- ## Functions fully defined here ##
+ ## Fully defined in this file ##
'add_template_directory',
'add_public_directory',
+ 'requires_ckan_version',
+ 'check_ckan_version',
+ 'CkanVersionException',
]
+_ = pylons.i18n._
c = pylons.c
request = pylons.request
render = base.render
@@ -40,6 +57,13 @@
aslist = converters.aslist
literal = webhelpers.html.tags.literal
+get_action = logic.get_action
+check_access = logic.check_access
+ActionNotFound = logic.NotFound ## Name change intentional
+NotAuthorized = logic.NotAuthorized
+ValidationError = logic.ValidationError
+
+CkanCommand = cli.CkanCommand
# wrappers
def render_snippet(template, data=None):
@@ -73,3 +97,38 @@ def _add_served_directory(config, relative_path, config_var):
config[config_var] += ',' + absolute_path
else:
config[config_var] = absolute_path
+
+class CkanVersionException(Exception):
+ ''' Exception raised if required ckan version is not available. '''
+ pass
+
+
+def _version_str_2_list(v_str):
+ ''' conver a version string into a list of ints
+ eg 1.6.1b --> [1, 6, 1] '''
+ v_str = re.sub(r'[^0-9.]', '', v_str)
+ return [int(part) for part in v_str.split('.')]
+
+def check_ckan_version(min_version=None, max_version=None):
+ ''' Check that the ckan version is correct for the plugin. '''
+ current = _version_str_2_list(ckan.__version__)
+
+ if min_version:
+ min_required = _version_str_2_list(min_version)
+ if current < min_required:
+ return False
+ if max_version:
+ max_required = _version_str_2_list(max_version)
+ if current > max_required:
+ return False
+ return True
+
+def requires_ckan_version(min_version, max_version=None):
+ ''' Check that the ckan version is correct for the plugin. '''
+ if not check_ckan_version(min_version=min_version, max_version=max_version):
+ if not max_version:
+ error = 'Requires ckan version %s or higher' % min_version
+ else:
+ error = 'Requires ckan version between %s and %s' % \
+ (min_version, max_version)
+ raise CkanVersionException(error)
================================================================
Commit: 9a20c1438585f0365cfe2a9a0df348071785f4c5
https://github.com/okfn/ckan/commit/9a20c1438585f0365cfe2a9a0df348071785f4c5
Author: Ross Jones <rossdjones at gmail.com>
Date: 2012-04-20 (Fri, 20 Apr 2012)
Changed paths:
M ckan/lib/base.py
M ckan/lib/cli.py
M ckan/plugins/__init__.py
M ckan/plugins/toolkit.py
Log Message:
-----------
Merge branch 'master' into feature-2302-simple-theming
diff --git a/ckan/lib/base.py b/ckan/lib/base.py
index da9d69f..075029c 100644
--- a/ckan/lib/base.py
+++ b/ckan/lib/base.py
@@ -22,7 +22,7 @@
import ckan.exceptions
import ckan
-from ckan import authz
+import ckan.authz as authz
from ckan.lib import i18n
import ckan.lib.helpers as h
from ckan.plugins import PluginImplementations, IGenshiStreamFilter
diff --git a/ckan/lib/cli.py b/ckan/lib/cli.py
index 5146aa9..6798cc4 100644
--- a/ckan/lib/cli.py
+++ b/ckan/lib/cli.py
@@ -84,7 +84,7 @@ class ManageDb(CkanCommand):
def command(self):
self._load_config()
- from ckan import model
+ import ckan.model as model
import ckan.lib.search as search
cmd = self.args[0]
@@ -164,7 +164,7 @@ def _postgres_dump(self, filepath):
self._run_cmd(pg_dump_cmd)
def _postgres_load(self, filepath):
- from ckan import model
+ import ckan.model as model
assert not model.repo.are_tables_created(), "Tables already found. You need to 'db clean' before a load."
pg_cmd = self._get_psql_cmd() + ' -f %s' % filepath
self._run_cmd(pg_cmd)
@@ -194,7 +194,7 @@ def load(self, only_load=False):
pg_cmd = self._postgres_load(dump_path)
if not only_load:
print 'Upgrading DB'
- from ckan import model
+ import ckan.model as model
model.repo.upgrade_db()
print 'Rebuilding search index'
@@ -205,7 +205,7 @@ def load(self, only_load=False):
print 'Done'
def simple_dump_csv(self):
- from ckan import model
+ import ckan.model as model
if len(self.args) < 2:
print 'Need csv file path'
return
@@ -215,7 +215,7 @@ def simple_dump_csv(self):
dumper.SimpleDumper().dump(dump_file, format='csv')
def simple_dump_json(self):
- from ckan import model
+ import ckan.model as model
if len(self.args) < 2:
print 'Need json file path'
return
@@ -452,7 +452,7 @@ class Sysadmin(CkanCommand):
def command(self):
self._load_config()
- from ckan import model
+ import ckan.model as model
cmd = self.args[0] if self.args else None
if cmd == None or cmd == 'list':
@@ -465,7 +465,7 @@ def command(self):
print 'Command %s not recognized' % cmd
def list(self):
- from ckan import model
+ import ckan.model as model
print 'Sysadmins:'
sysadmins = model.Session.query(model.SystemRole).filter_by(role=model.Role.ADMIN)
print 'count = %i' % sysadmins.count()
@@ -477,7 +477,7 @@ def list(self):
user_or_authgroup.id)
def add(self):
- from ckan import model
+ import ckan.model as model
if len(self.args) < 2:
print 'Need name of the user to be made sysadmin.'
@@ -501,7 +501,7 @@ def add(self):
print 'Added %s as sysadmin' % username
def remove(self):
- from ckan import model
+ import ckan.model as model
if len(self.args) < 2:
print 'Need name of the user to be made sysadmin.'
@@ -537,7 +537,7 @@ class UserCmd(CkanCommand):
def command(self):
self._load_config()
- from ckan import model
+ import ckan.model as model
if not self.args:
self.list()
@@ -563,7 +563,7 @@ def get_user_str(self, user):
return user_str
def list(self):
- from ckan import model
+ import ckan.model as model
print 'Users:'
users = model.Session.query(model.User)
print 'count = %i' % users.count()
@@ -571,14 +571,14 @@ def list(self):
print self.get_user_str(user)
def show(self):
- from ckan import model
+ import ckan.model as model
username = self.args[0]
user = model.User.get(unicode(username))
print 'User: \n', user
def setpass(self):
- from ckan import model
+ import ckan.model as model
if len(self.args) < 2:
print 'Need name of the user.'
@@ -593,7 +593,7 @@ def setpass(self):
print 'Done'
def search(self):
- from ckan import model
+ import ckan.model as model
if len(self.args) < 2:
print 'Need user name query string.'
@@ -618,7 +618,7 @@ def password_prompt(cls):
return password1
def add(self):
- from ckan import model
+ import ckan.model as model
if len(self.args) < 2:
print 'Need name of the user.'
@@ -671,7 +671,7 @@ def add(self):
print user
def remove(self):
- from ckan import model
+ import ckan.model as model
if len(self.args) < 2:
print 'Need name of the user.'
@@ -704,7 +704,7 @@ class DatasetCmd(CkanCommand):
def command(self):
self._load_config()
- from ckan import model
+ import ckan.model as model
if not self.args:
print self.usage
@@ -722,7 +722,7 @@ def command(self):
self.show(self.args[0])
def list(self):
- from ckan import model
+ import ckan.model as model
print 'Datasets:'
datasets = model.Session.query(model.Package)
print 'count = %i' % datasets.count()
@@ -732,19 +732,19 @@ def list(self):
print '%s %s %s' % (dataset.id, dataset.name, state)
def _get_dataset(self, dataset_ref):
- from ckan import model
+ import ckan.model as model
dataset = model.Package.get(unicode(dataset_ref))
assert dataset, 'Could not find dataset matching reference: %r' % dataset_ref
return dataset
def show(self, dataset_ref):
- from ckan import model
import pprint
dataset = self._get_dataset(dataset_ref)
pprint.pprint(dataset.as_dict())
def delete(self, dataset_ref):
- from ckan import model, plugins
+ from ckan import plugins
+ import ckan.model as model
dataset = self._get_dataset(dataset_ref)
old_state = dataset.state
@@ -756,7 +756,8 @@ def delete(self, dataset_ref):
print '%s %s -> %s' % (dataset.name, old_state, dataset.state)
def purge(self, dataset_ref):
- from ckan import model, plugins
+ from ckan import plugins
+ import ckan.model as model
dataset = self._get_dataset(dataset_ref)
name = dataset.name
@@ -802,7 +803,7 @@ def run_(self):
def view(self):
self._load_config()
- from ckan import model
+ import ckan.model as model
from kombu.transport.sqlalchemy.models import Message
q = model.Session.query(Message)
q_visible = q.filter_by(visible=True)
@@ -816,7 +817,7 @@ def view(self):
def clean(self):
self._load_config()
- from ckan import model
+ import ckan.model as model
import pprint
tasks_initially = model.Session.execute("select * from kombu_message").rowcount
if not tasks_initially:
@@ -847,7 +848,7 @@ class Ratings(CkanCommand):
def command(self):
self._load_config()
- from ckan import model
+ import ckan.model as model
cmd = self.args[0]
if cmd == 'count':
@@ -860,14 +861,14 @@ def command(self):
print 'Command %s not recognized' % cmd
def count(self):
- from ckan import model
+ import ckan.model as model
q = model.Session.query(model.Rating)
print "%i ratings" % q.count()
q = q.filter(model.Rating.user_id == None)
print "of which %i are anonymous ratings" % q.count()
def clean(self, user_ratings=True):
- from ckan import model
+ import ckan.model as model
q = model.Session.query(model.Rating)
print "%i ratings" % q.count()
if not user_ratings:
diff --git a/ckan/plugins/__init__.py b/ckan/plugins/__init__.py
index fcb6055..e11e909 100644
--- a/ckan/plugins/__init__.py
+++ b/ckan/plugins/__init__.py
@@ -1,3 +1,19 @@
from ckan.plugins.core import *
from ckan.plugins.interfaces import *
-import toolkit
+
+
+class _Toolkit(object):
+ ''' This object allows us to avoid circular imports while making
+ functions/objects available to plugins. '''
+
+ def __init__(self):
+ self.toolkit = None
+
+ def __getattr__(self, name):
+ if not self.toolkit:
+ import toolkit
+ self.toolkit = toolkit
+ return getattr(self.toolkit, name)
+
+toolkit = _Toolkit()
+del _Toolkit
diff --git a/ckan/plugins/toolkit.py b/ckan/plugins/toolkit.py
index 64a80d7..e635c43 100644
--- a/ckan/plugins/toolkit.py
+++ b/ckan/plugins/toolkit.py
@@ -1,21 +1,28 @@
-## This file is intended to make functions consistently available to
-## plugins whilst giving developers the ability move code around or
-## change underlying frameworks etc. It should not be used internaly
-## within ckan only by extensions. Functions should only be removed from
-## this file after reasonable depreciation notice has been given.
+## This file is intended to make functions/objects consistently
+## available to plugins whilst giving developers the ability move code
+## around or change underlying frameworks etc. It should not be used
+## internally within ckan only by extensions. Functions should only be
+## removed from this file after reasonable depreciation notice has
+## been given.
import inspect
import os
+import re
import pylons
import paste.deploy.converters as converters
import webhelpers.html.tags
-import lib.base as base
+import ckan
+import ckan.lib.base as base
+import ckan.logic as logic
+import ckan.lib.cli as cli
+
__all__ = [
- ## Imported functions ##
+ ## Imported functions/objects ##
+ '_', # i18n translation
'c', # template context
'request', # http request object
'render', # template render function
@@ -25,12 +32,22 @@
'asint', # converts an object to an integer
'aslist', # converts an object to a list
'literal', # stop tags in a string being escaped
+ 'get_action', # get logic action function
+ 'check_access', # check logic function authorisation
+ 'ActionNotFound', # action not found exception (ckan.logic.NotFound)
+ 'NotAuthorized', # action not authorized exception
+ 'ValidationError', # model update validation error
+ 'CkanCommand', # class for providing cli interfaces
- ## Functions fully defined here ##
+ ## Fully defined in this file ##
'add_template_directory',
'add_public_directory',
+ 'requires_ckan_version',
+ 'check_ckan_version',
+ 'CkanVersionException',
]
+_ = pylons.i18n._
c = pylons.c
request = pylons.request
render = base.render
@@ -40,6 +57,13 @@
aslist = converters.aslist
literal = webhelpers.html.tags.literal
+get_action = logic.get_action
+check_access = logic.check_access
+ActionNotFound = logic.NotFound ## Name change intentional
+NotAuthorized = logic.NotAuthorized
+ValidationError = logic.ValidationError
+
+CkanCommand = cli.CkanCommand
# wrappers
def render_snippet(template, data=None):
@@ -73,3 +97,38 @@ def _add_served_directory(config, relative_path, config_var):
config[config_var] += ',' + absolute_path
else:
config[config_var] = absolute_path
+
+class CkanVersionException(Exception):
+ ''' Exception raised if required ckan version is not available. '''
+ pass
+
+
+def _version_str_2_list(v_str):
+ ''' conver a version string into a list of ints
+ eg 1.6.1b --> [1, 6, 1] '''
+ v_str = re.sub(r'[^0-9.]', '', v_str)
+ return [int(part) for part in v_str.split('.')]
+
+def check_ckan_version(min_version=None, max_version=None):
+ ''' Check that the ckan version is correct for the plugin. '''
+ current = _version_str_2_list(ckan.__version__)
+
+ if min_version:
+ min_required = _version_str_2_list(min_version)
+ if current < min_required:
+ return False
+ if max_version:
+ max_required = _version_str_2_list(max_version)
+ if current > max_required:
+ return False
+ return True
+
+def requires_ckan_version(min_version, max_version=None):
+ ''' Check that the ckan version is correct for the plugin. '''
+ if not check_ckan_version(min_version=min_version, max_version=max_version):
+ if not max_version:
+ error = 'Requires ckan version %s or higher' % min_version
+ else:
+ error = 'Requires ckan version between %s and %s' % \
+ (min_version, max_version)
+ raise CkanVersionException(error)
================================================================
Commit: e1c747a7ff9e4f494bbbdd221614e82193bad87c
https://github.com/okfn/ckan/commit/e1c747a7ff9e4f494bbbdd221614e82193bad87c
Author: Ross Jones <rossdjones at gmail.com>
Date: 2012-04-20 (Fri, 20 Apr 2012)
Changed paths:
M ckan/controllers/settings.py
A ckan/migration/versions/054_add_setting_table.py
A ckan/model/settings.py
M ckan/templates/settings/index.html
Log Message:
-----------
[2302] Added model and migration
diff --git a/ckan/controllers/settings.py b/ckan/controllers/settings.py
index b84fc7b..7ddaf07 100644
--- a/ckan/controllers/settings.py
+++ b/ckan/controllers/settings.py
@@ -14,6 +14,12 @@ def _ensure_hex(key, data, errors, context):
value = data.get(key)
def is_hex(value):
+ v = ''.join(c for c in value if c != '#')
+ try:
+ x = int(v, 16)
+ except:
+ return False
+ data[key] = v
return True
if not value or not is_hex(value):
@@ -22,7 +28,6 @@ def is_hex(value):
raise dictfunc.StopOnError
class SettingsController(BaseController):
- repo = model.repo
def __before__(self, action, **env):
BaseController.__before__(self, action, **env)
diff --git a/ckan/migration/versions/054_add_setting_table.py b/ckan/migration/versions/054_add_setting_table.py
new file mode 100644
index 0000000..d8e3cf8
--- /dev/null
+++ b/ckan/migration/versions/054_add_setting_table.py
@@ -0,0 +1,16 @@
+from sqlalchemy import *
+from migrate import *
+
+def upgrade(migrate_engine):
+ metadata = MetaData()
+ metadata.bind = migrate_engine
+ migrate_engine.execute('''
+ CREATE TABLE setting (
+ id text NOT NULL,
+ key text,
+ value text
+ );
+
+ ALTER TABLE setting
+ ADD CONSTRAINT setting_pkey PRIMARY KEY (id);
+ ''')
\ No newline at end of file
diff --git a/ckan/model/settings.py b/ckan/model/settings.py
new file mode 100644
index 0000000..2e71bad
--- /dev/null
+++ b/ckan/model/settings.py
@@ -0,0 +1,20 @@
+import datetime
+
+from meta import *
+from core import *
+from package import *
+from types import make_uuid
+from user import User
+
+__all__ = ['Setting']
+
+setting_table = Table('setting', metadata,
+ Column('id', UnicodeText, primary_key=True, default=make_uuid),
+ Column('key', UnicodeText),
+ Column('value', UnicodeText),
+ )
+
+class Setting(DomainObject):
+ pass
+
+mapper(Setting, setting_table)
diff --git a/ckan/templates/settings/index.html b/ckan/templates/settings/index.html
index f96923b..225b8d1 100644
--- a/ckan/templates/settings/index.html
+++ b/ckan/templates/settings/index.html
@@ -20,7 +20,6 @@
</py:match>
<div py:match="content">
-
<div class="alert alert-error" py:if="error_summary">
The form contains invalid entries please correct them and submit again
</div>
@@ -81,7 +80,7 @@
<label class="control-label" for="input01">Footer background</label>
<div class="controls">
<div class="input-prepend">
- <span class='add-on'>#</span><input type="text" class="input-xlarge" id="css_footer" name="css_footer" value="${data.get('css_footer','')}"/>
+ <span class='add-on'>#</span><input type="text" class="input-xlarge" id="css_footer" name="css_footer" value="${data.get('css_footer','')}"/>
</div>
<span class="help-inline" py:if="not errors.get('css_footer')">Hexadecimal value for the footer</span>
<span class="help-inline" py:if="errors.get('css_footer')">${errors['css_footer']}</span>
================================================================
Compare: https://github.com/okfn/ckan/compare/f9e151d...e1c747a
More information about the ckan-changes
mailing list