
This series of patches reorganize kimchi's path vars generation code to allow plugin use kimchi s ui handler. Changes: v2: Rebase Remove the optimization for plugin paths since it just have a few instantiations. Mark Wu (3): Reorganize the kimchi's paths gereneration code Add test cases for paths generation code Allow plugin use kimchi's ui handler src/kimchi/cachebust.py | 4 +- src/kimchi/config.py.in | 155 +++++++++++++++++++----------------------------- src/kimchi/root.py | 23 ++++--- src/kimchi/server.py | 14 +++-- src/kimchi/template.py | 17 ++++-- src/kimchi/utils.py | 6 +- src/kimchid.in | 7 ++- tests/test_config.py | 73 +++++++++++++++++++++++ tests/test_plugin.py | 4 +- 9 files changed, 178 insertions(+), 125 deletions(-) create mode 100644 tests/test_config.py -- 1.8.4.2

This patch reorganizes kimchi's paths generation code to make the user of path vars can work with both kimchi root app and plugin app. Signed-off-by: Mark Wu <wudxw@linux.vnet.ibm.com> --- src/kimchi/cachebust.py | 4 +- src/kimchi/config.py.in | 155 +++++++++++++++++++----------------------------- src/kimchi/root.py | 7 ++- src/kimchi/server.py | 10 ++-- src/kimchi/template.py | 14 +++-- src/kimchi/utils.py | 6 +- src/kimchid.in | 7 ++- tests/test_plugin.py | 4 +- 8 files changed, 91 insertions(+), 116 deletions(-) diff --git a/src/kimchi/cachebust.py b/src/kimchi/cachebust.py index 9a71f4f..7844695 100644 --- a/src/kimchi/cachebust.py +++ b/src/kimchi/cachebust.py @@ -23,11 +23,11 @@ import os -from kimchi.config import get_prefix +from kimchi.config import paths def href(url): # for error.html, url is absolute path - f = os.path.join(get_prefix(), 'ui', url.lstrip("/")) + f = os.path.join(paths.ui_dir, url.lstrip("/")) mtime = os.path.getmtime(f) return "%s?cacheBust=%s" % (url, mtime) diff --git a/src/kimchi/config.py.in b/src/kimchi/config.py.in index 22fe614..f32c008 100644 --- a/src/kimchi/config.py.in +++ b/src/kimchi/config.py.in @@ -28,7 +28,6 @@ import platform from ConfigParser import SafeConfigParser -from glob import iglob from kimchi.xmlutils import xpath_get_text @@ -37,86 +36,24 @@ from kimchi.xmlutils import xpath_get_text DEFAULT_LOG_LEVEL = "debug" -def get_prefix(): - if __file__[0] == '/': - base = os.path.dirname(__file__) - else: - base = os.path.dirname('./%s' % __file__) - - if os.access('%s/../../src/kimchi/config.py' % base, os.F_OK): - return '%s/../..' % base - else: - return '@pkgdatadir@' - - -def without_installation(): - return get_prefix() != '@pkgdatadir@' - - -def get_config_dir(): - prefix = get_prefix() - - if prefix == '@pkgdatadir@': - return '@sysconfdir@/kimchi' - else: - return os.path.join(prefix, 'src') - - -def _get_kimchi_src_dir(): - prefix = get_prefix() - return ('@kimchidir@' if prefix == '@pkgdatadir@' - else os.path.join(prefix, 'src/kimchi')) - - -def get_api_schema_file(): - return os.path.join(_get_kimchi_src_dir(), 'API.json') - - -def get_default_log_dir(): - prefix = get_prefix() - - if prefix == '@pkgdatadir@': - return "@localstatedir@/log/kimchi" - - return os.path.join(prefix, 'log') - - -def get_state_path(): - prefix = get_prefix() - - if prefix == '@pkgdatadir@': - return "@localstatedir@/lib/kimchi" - - return os.path.join(prefix, 'data') - - def get_session_path(): - return os.path.join(get_state_path(), 'sessions') + return os.path.join(paths.state_dir, 'sessions') def get_object_store(): - return os.path.join(get_prefix(), 'data', 'objectstore') + return os.path.join(paths.state_dir, 'objectstore') def get_distros_store(): - return os.path.join(get_config_dir(), 'distros.d') - - -def get_template_path(resource): - return '%s/ui/pages/%s.tmpl' % (get_prefix(), resource) + return os.path.join(paths.conf_dir, 'distros.d') def get_screenshot_path(): - return "%s/data/screenshots" % get_prefix() - - -def get_mo_path(): - return '%s/mo' % get_prefix() + return os.path.join(paths.state_dir, 'screenshots') -def get_support_language(): - mopath = "%s/*" % get_mo_path() - return [path.rsplit('/', 1)[1] for path in iglob(mopath)] +def get_debugreports_path(): + return os.path.join(paths.state_dir, 'debugreports') def find_qemu_binary(): @@ -137,37 +74,65 @@ def find_qemu_binary(): return location -def get_debugreports_path(): - return os.path.join(get_prefix(), 'data', 'debugreports') +class Paths(object): + + def __init__(self): + self.prefix = self.get_prefix() + self.installed = (self.prefix == '@pkgdatadir@') + + if self.installed: + self.state_dir = '@localstatedir@/lib/kimchi' + self.log_dir = '@localstatedir@/log/kimchi' + self.conf_dir = '@sysconfdir@/kimchi' + self.src_dir = '@kimchidir@' + self.plugins_dir = '@kimchidir@' + else: + self.state_dir = self.add_prefix('data') + self.log_dir = self.add_prefix('log') + self.conf_dir = self.add_prefix('src') + self.src_dir = self.add_prefix('src/kimchi') + self.plugins_dir = self.add_prefix('plugins') + + self.ui_dir = self.add_prefix('ui') + self.mo_dir = self.add_prefix('mo') + + def get_prefix(self): + if __file__[0] == '/': + base = os.path.dirname(__file__) + else: + base = os.path.dirname('./%s' % __file__) + + if os.access('%s/../../src/kimchi/config.py' % base, os.F_OK): + return os.path.abspath('%s/../..' % base) + else: + return '@pkgdatadir@' + + def add_prefix(self, subdir): + return os.path.join(self.prefix, subdir) + def get_template_path(self, resource): + return os.path.join(self.ui_dir, 'pages/%s.tmpl' % resource) -def get_plugins_dir(): - prefix = get_prefix() - if prefix == '@pkgdatadir@': - prefix = '@kimchidir@' - return os.path.join(prefix, 'plugins') +paths = Paths() -def get_plugin_config(name): - prefix = get_prefix() - if prefix == '@pkgdatadir@': - base_dir = '@sysconfdir@/kimchi/plugins.d/' - else: - base_dir = os.path.join(prefix, 'plugins') - return os.path.join(base_dir, '%s/%s.conf' % (name, name)) +class PluginPaths(Paths): -def _get_plugin_ui_dir(name): - prefix = get_prefix() - if prefix == '@pkgdatadir@': - base_dir = '@pkgdatadir@/plugins/' - else: - base_dir = os.path.join(prefix, 'plugins') - return os.path.join(base_dir, '%s/ui' % name) + def __init__(self, name): + super(PluginPaths, self).__init__() + self.plugin_dir = os.path.join('plugins', name) + if self.installed: + self.conf_dir = '@sysconfdir@/kimchi/plugins.d' + self.src_dir = os.path.join('@kimchidir@', self.plugin_dir) + else: + self.conf_dir = self.add_prefix(self.plugin_dir) + self.src_dir = self.add_prefix(self.plugin_dir) -def get_plugin_tab_xml(name): - return os.path.join(_get_plugin_ui_dir(name), 'config/tab-ext.xml') + self.ui_dir = self.add_prefix(os.path.join(self.plugin_dir, 'ui')) + self.mo_dir = self.add_prefix(os.path.join(self.plugin_dir, 'mo')) + self.conf_file = os.path.join(self.conf_dir, '%s.conf' % name) def _get_config(): @@ -180,12 +145,12 @@ def _get_config(): config.set("server", "ssl_key", "") config.set("server", "environment", "development") config.add_section("logging") - config.set("logging", "log_dir", get_default_log_dir()) + config.set("logging", "log_dir", paths.log_dir) config.set("logging", "log_level", DEFAULT_LOG_LEVEL) config.add_section("display") config.set("display", "display_proxy_port", "64667") - config_file = os.path.join(get_config_dir(), 'kimchi.conf') + config_file = os.path.join(paths.conf_dir, 'kimchi.conf') if os.path.exists(config_file): config.read(config_file) return config @@ -195,4 +160,4 @@ config = _get_config() if __name__ == '__main__': - print get_prefix() + print paths.prefix diff --git a/src/kimchi/root.py b/src/kimchi/root.py index 83a777c..6e107bc 100644 --- a/src/kimchi/root.py +++ b/src/kimchi/root.py @@ -23,11 +23,12 @@ import cherrypy import json +import os from kimchi import auth from kimchi import template -from kimchi.config import get_api_schema_file +from kimchi.config import paths from kimchi.control import sub_nodes from kimchi.control.base import Resource from kimchi.control.utils import parse_request @@ -50,8 +51,8 @@ class Root(Resource): for ident, node in sub_nodes.items(): setattr(self, ident, node(model)) - - self.api_schema = json.load(open(get_api_schema_file())) + self.api_schema = json.load(open(os.path.join(paths.src_dir, + 'API.json'))) def error_production_handler(self, status, message, traceback, version): data = {'code': status, 'reason': message} diff --git a/src/kimchi/server.py b/src/kimchi/server.py index 2a9f53f..9884249 100644 --- a/src/kimchi/server.py +++ b/src/kimchi/server.py @@ -33,6 +33,7 @@ from kimchi import config from kimchi import model from kimchi import mockmodel from kimchi import vnc +from kimchi.config import paths, PluginPaths from kimchi.control import sub_nodes from kimchi.root import Root from kimchi.utils import get_enabled_plugins, import_class @@ -64,8 +65,8 @@ class Server(object): CACHEEXPIRES = 31536000 configObj = { '/': {'tools.trailing_slash.on': False, - 'tools.staticdir.root': config.get_prefix(), - 'tools.staticfile.root': config.get_prefix(), + 'tools.staticdir.root': paths.prefix, + 'tools.staticfile.root': paths.prefix, 'request.methods_with_bodies': ('POST', 'PUT'), 'tools.nocache.on': True, 'tools.sessions.on': True, @@ -209,7 +210,8 @@ class Server(object): plugin_config['/ui/config/tab-ext.xml'] = { 'tools.staticfile.on': True, 'tools.staticfile.filename': - config.get_plugin_tab_xml(plugin_name), + os.path.join(PluginPaths(plugin_name).ui_dir, + 'config/tab-ext.xml'), 'tools.nocache.on': True} except KeyError: continue @@ -231,7 +233,7 @@ class Server(object): cert = options.ssl_cert key = options.ssl_key if not cert or not key: - config_dir = config.get_config_dir() + config_dir = paths.conf_dir cert = '%s/kimchi-cert.pem' % config_dir key = '%s/kimchi-key.pem' % config_dir diff --git a/src/kimchi/template.py b/src/kimchi/template.py index f854657..37676b6 100644 --- a/src/kimchi/template.py +++ b/src/kimchi/template.py @@ -28,9 +28,10 @@ import os from Cheetah.Template import Template +from glob import iglob -from kimchi import config +from kimchi.config import paths def get_lang(): @@ -54,8 +55,13 @@ def get_lang(): return langs +def get_support_languages(): + mopath = "%s/*" % paths.mo_dir + return [path.rsplit('/', 1)[1] for path in iglob(mopath)] + + def validate_language(langs): - supportLangs = config.get_support_language() + supportLangs = get_support_languages() for lang in langs: if lang in supportLangs: return lang @@ -86,12 +92,12 @@ def render(resource, data): cherrypy.response.headers['Content-Type'] = 'application/json;charset=utf-8' return json.dumps(data, indent=2, separators=(',', ':')) elif can_accept_html(): - filename = config.get_template_path(resource) + filename = paths.get_template_path(resource) try: params = {'data': data} lang = validate_language(get_lang()) gettext_conf = {'domain': 'kimchi', - 'localedir': config.get_mo_path(), + 'localedir': paths.mo_dir, 'lang': [lang]} params['lang'] = gettext_conf return Template(file=filename, searchList=params).respond() diff --git a/src/kimchi/utils.py b/src/kimchi/utils.py index c7ececf..ae0cfac 100644 --- a/src/kimchi/utils.py +++ b/src/kimchi/utils.py @@ -28,10 +28,10 @@ import urllib2 from cherrypy.lib.reprconf import Parser +from kimchi.config import paths, PluginPaths from kimchi.exception import TimeoutExpired -from kimchi import config from threading import Timer @@ -48,7 +48,7 @@ def is_digit(value): def _load_plugin_conf(name): - plugin_conf = config.get_plugin_config(name) + plugin_conf = PluginPaths(name).conf_file if not os.path.exists(plugin_conf): cherrypy.log.error_log.error("Plugin configuration file %s" " doesn't exist." % plugin_conf) @@ -62,7 +62,7 @@ def _load_plugin_conf(name): def get_enabled_plugins(): - plugin_dir = config.get_plugins_dir() + plugin_dir = paths.plugins_dir try: dir_contents = os.listdir(plugin_dir) except OSError: diff --git a/src/kimchid.in b/src/kimchid.in index 548fa52..eebc017 100644 --- a/src/kimchid.in +++ b/src/kimchid.in @@ -30,12 +30,13 @@ sys.path.insert(1, '@pythondir@') import kimchi.server import kimchi.config -if kimchi.config.without_installation(): - sys.path.append(kimchi.config.get_prefix()) -from kimchi.config import config +from kimchi.config import config, paths from optparse import OptionParser +if not paths.installed: + sys.path.append(paths.prefix) + ACCESS_LOG = "kimchi-access.log" ERROR_LOG = "kimchi-error.log" diff --git a/tests/test_plugin.py b/tests/test_plugin.py index 42c87a9..e5c9053 100644 --- a/tests/test_plugin.py +++ b/tests/test_plugin.py @@ -32,7 +32,7 @@ from functools import partial import kimchi.mockmodel import kimchi.server import utils -from kimchi import config +from kimchi.config import paths test_server = None @@ -48,7 +48,7 @@ def setUpModule(): host = '127.0.0.1' port = utils.get_free_port('http') ssl_port = None - sys.path.append(config.get_prefix()) + sys.path.append(paths.prefix) test_server = utils.run_server(host, port, ssl_port, test_mode=True, model=model) -- 1.8.4.2

This patch adds test cases for paths generation code. Signed-off-by: Mark Wu <wudxw@linux.vnet.ibm.com> --- tests/test_config.py | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 tests/test_config.py diff --git a/tests/test_config.py b/tests/test_config.py new file mode 100644 index 0000000..4ad88f0 --- /dev/null +++ b/tests/test_config.py @@ -0,0 +1,73 @@ +# +# Project Kimchi +# +# Copyright IBM, Corp. 2013 +# +# Authors: +# Mark Wu <wudxw@linux.vnet.ibm.com> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +import unittest + + +from kimchi.config import Paths, PluginPaths + + +class ConfigTests(unittest.TestCase): + def test_installed_paths(self): + Paths.get_prefix = lambda self: '/usr/share/kimchi' + paths = Paths() + self.assertEquals(paths.state_dir, '/var/lib/kimchi') + self.assertEquals(paths.log_dir, '/var/log/kimchi') + self.assertEquals(paths.conf_dir, '/etc/kimchi') + self.assertEquals(paths.src_dir, + '/usr/lib/python2.7/site-packages/kimchi') + self.assertEquals(paths.plugins_dir, + '/usr/lib/python2.7/site-packages/kimchi') + self.assertEquals(paths.ui_dir, '/usr/share/kimchi/ui') + self.assertEquals(paths.mo_dir, '/usr/share/kimchi/mo') + + def test_uninstalled_paths(self): + Paths.get_prefix = lambda self: '/home/user/kimchi' + paths = Paths() + self.assertEquals(paths.state_dir, '/home/user/kimchi/data') + self.assertEquals(paths.log_dir, '/home/user/kimchi/log') + self.assertEquals(paths.conf_dir, '/home/user/kimchi/src') + self.assertEquals(paths.src_dir, '/home/user/kimchi/src/kimchi') + self.assertEquals(paths.plugins_dir, '/home/user/kimchi/plugins') + self.assertEquals(paths.ui_dir, '/home/user/kimchi/ui') + self.assertEquals(paths.mo_dir, '/home/user/kimchi/mo') + + def test_installed_plugin_paths(self): + PluginPaths.get_prefix = lambda self: '/usr/share/kimchi' + paths = PluginPaths('sample') + self.assertEquals(paths.conf_dir, '/etc/kimchi/plugins.d') + self.assertEquals(paths.conf_file, '/etc/kimchi/plugins.d/sample.conf') + self.assertEquals( + paths.src_dir, + '/usr/lib/python2.7/site-packages/kimchi/plugins/sample') + self.assertEquals(paths.ui_dir, '/usr/share/kimchi/plugins/sample/ui') + self.assertEquals(paths.mo_dir, '/usr/share/kimchi/plugins/sample/mo') + + def test_uninstalled_plugin_paths(self): + PluginPaths.get_prefix = lambda self: '/home/user/kimchi' + paths = PluginPaths('sample') + self.assertEquals(paths.conf_dir, '/home/user/kimchi/plugins/sample') + self.assertEquals( + paths.conf_file, '/home/user/kimchi/plugins/sample/sample.conf') + self.assertEquals(paths.src_dir, '/home/user/kimchi/plugins/sample') + self.assertEquals(paths.ui_dir, '/home/user/kimchi/plugins/sample/ui') + self.assertEquals(paths.mo_dir, '/home/user/kimchi/plugins/sample/mo') -- 1.8.4.2

To make kimchi's error handler and tabs handler resued for plugin, this patch moves the resource related code into a subclass. With this change, the plugin can have error handler and tabs handler by inheriting from this class. Signed-off-by: Mark Wu <wudxw@linux.vnet.ibm.com> --- src/kimchi/root.py | 20 +++++++++++++------- src/kimchi/server.py | 4 ++-- src/kimchi/template.py | 5 ++--- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/kimchi/root.py b/src/kimchi/root.py index 6e107bc..c3d471e 100644 --- a/src/kimchi/root.py +++ b/src/kimchi/root.py @@ -36,7 +36,7 @@ from kimchi.exception import OperationFailed class Root(Resource): - def __init__(self, model, dev_env): + def __init__(self, model, dev_env=False): super(Root, self).__init__(model) self._handled_error = ['error_page.400', 'error_page.404', 'error_page.405', 'error_page.406', @@ -49,11 +49,6 @@ class Root(Resource): self._cp_config = dict([(key, self.error_development_handler) for key in self._handled_error]) - for ident, node in sub_nodes.items(): - setattr(self, ident, node(model)) - self.api_schema = json.load(open(os.path.join(paths.src_dir, - 'API.json'))) - def error_production_handler(self, status, message, traceback, version): data = {'code': status, 'reason': message} res = template.render('error.html', data) @@ -70,7 +65,7 @@ class Root(Resource): return res def get(self): - return self.default('kimchi-ui.html') + return self.default(self.default_page) @cherrypy.expose def default(self, page, **kwargs): @@ -84,6 +79,17 @@ class Root(Resource): return template.render('tabs/' + page, None) raise cherrypy.HTTPError(404) + +class KimchiRoot(Root): + def __init__(self, model, dev_env): + super(KimchiRoot, self).__init__(model, dev_env) + self.default_page = 'kimchi-ui.html' + for ident, node in sub_nodes.items(): + setattr(self, ident, node(model)) + self.api_schema = json.load(open(os.path.join(paths.src_dir, + 'API.json'))) + self.paths = paths + @cherrypy.expose def login(self, *args): params = parse_request() diff --git a/src/kimchi/server.py b/src/kimchi/server.py index 9884249..6b5925c 100644 --- a/src/kimchi/server.py +++ b/src/kimchi/server.py @@ -35,7 +35,7 @@ from kimchi import mockmodel from kimchi import vnc from kimchi.config import paths, PluginPaths from kimchi.control import sub_nodes -from kimchi.root import Root +from kimchi.root import KimchiRoot from kimchi.utils import get_enabled_plugins, import_class @@ -192,7 +192,7 @@ class Server(object): if node.url_auth: self.configObj["/%s" % ident] = {'tools.kimchiauth.on': True} - self.app = cherrypy.tree.mount(Root(model_instance, dev_env), + self.app = cherrypy.tree.mount(KimchiRoot(model_instance, dev_env), config=self.configObj) self._load_plugins() diff --git a/src/kimchi/template.py b/src/kimchi/template.py index 37676b6..7891923 100644 --- a/src/kimchi/template.py +++ b/src/kimchi/template.py @@ -31,9 +31,6 @@ from Cheetah.Template import Template from glob import iglob -from kimchi.config import paths - - def get_lang(): cookie = cherrypy.request.cookie if "kimchiLang" in cookie.keys(): @@ -56,6 +53,7 @@ def get_lang(): def get_support_languages(): + paths = cherrypy.request.app.root.paths mopath = "%s/*" % paths.mo_dir return [path.rsplit('/', 1)[1] for path in iglob(mopath)] @@ -88,6 +86,7 @@ def can_accept_html(): can_accept('*/*') def render(resource, data): + paths = cherrypy.request.app.root.paths if can_accept('application/json'): cherrypy.response.headers['Content-Type'] = 'application/json;charset=utf-8' return json.dumps(data, indent=2, separators=(',', ':')) -- 1.8.4.2

The test cases are failing with this patch set .[24/Jan/2014:14:59:05] HTTP Traceback (most recent call last): File "/usr/lib/python2.7/dist-packages/cherrypy/_cprequest.py", line 656, in respond response.body = self.handler() File "/usr/lib/python2.7/dist-packages/cherrypy/lib/encoding.py", line 188, in __call__ self.body = self.oldhandler(*args, **kwargs) File "/usr/lib/python2.7/dist-packages/cherrypy/_cpdispatch.py", line 34, in __call__ return self.callable(*self.args, **self.kwargs) File "/home/alinefm/kimchi/src/kimchi/control/base.py", line 275, in index return self.create(*args) File "/home/alinefm/kimchi/src/kimchi/control/base.py", line 213, in create return res.get() File "/home/alinefm/kimchi/src/kimchi/control/base.py", line 164, in get return kimchi.template.render(get_class_name(self), self.data) File "/home/alinefm/kimchi/src/kimchi/template.py", line 89, in render paths = cherrypy.request.app.root.paths AttributeError: 'Drawings' object has no attribute 'paths' 127.0.0.1 - - [24/Jan/2014:14:59:05] "POST /plugins/sample/rectangles HTTP/1.1" 500 805 "" "" F[24/Jan/2014:14:59:05] ENGINE Bus STOPPING [24/Jan/2014:14:59:05] ENGINE HTTP Server cherrypy._cpwsgi_server.CPWSGIServer(('127.0.0.1', 56824)) shut down [24/Jan/2014:14:59:05] ENGINE HTTP Server cherrypy._cpwsgi_server.CPWSGIServer(('127.0.0.1', 40264)) shut down [24/Jan/2014:14:59:05] ENGINE Stopped thread 'Session cleanup'. [24/Jan/2014:14:59:05] ENGINE Stopped thread '_TimeoutMonitor'. [24/Jan/2014:14:59:05] ENGINE Bus STOPPED [24/Jan/2014:14:59:05] ENGINE Bus EXITING [24/Jan/2014:14:59:05] ENGINE Bus EXITED ====================================================================== ERROR: test_collection (test_mockmodel.MockModelTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/alinefm/kimchi/tests/test_mockmodel.py", line 60, in test_collection self.assertEquals('[]', c.index()) File "/home/alinefm/kimchi/src/kimchi/control/base.py", line 266, in index return self.get(filter_params) File "/home/alinefm/kimchi/src/kimchi/control/base.py", line 257, in get return kimchi.template.render(get_class_name(self), data) File "/home/alinefm/kimchi/src/kimchi/template.py", line 89, in render paths = cherrypy.request.app.root.paths AttributeError: 'Drawings' object has no attribute 'paths' ====================================================================== ERROR: test_resource (test_mockmodel.MockModelTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/alinefm/kimchi/tests/test_mockmodel.py", line 77, in test_resource self.assertEquals('{}', r.index()) File "/home/alinefm/kimchi/src/kimchi/control/base.py", line 115, in index return self.get() File "/home/alinefm/kimchi/src/kimchi/control/base.py", line 164, in get return kimchi.template.render(get_class_name(self), self.data) File "/home/alinefm/kimchi/src/kimchi/template.py", line 89, in render paths = cherrypy.request.app.root.paths AttributeError: 'Drawings' object has no attribute 'paths' ====================================================================== FAIL: test_development_env (test_exception.ExceptionTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/alinefm/kimchi/tests/test_exception.py", line 98, in test_development_env self.assertEquals(msg, resp.get('reason')) AssertionError: 'Delete is not allowed for root' != u'Delete is not allowed for kimchiroot' ====================================================================== FAIL: test_production_env (test_exception.ExceptionTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/alinefm/kimchi/tests/test_exception.py", line 68, in test_production_env self.assertEquals(msg, resp.get('reason')) AssertionError: 'Delete is not allowed for root' != u'Delete is not allowed for kimchiroot' ====================================================================== FAIL: test_installed_paths (test_config.ConfigTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/alinefm/kimchi/tests/test_config.py", line 37, in test_installed_paths '/usr/lib/python2.7/site-packages/kimchi') AssertionError: '/usr/lib/python2.7/dist-packages/kimchi' != '/usr/lib/python2.7/site-packages/kimchi' ====================================================================== FAIL: test_installed_plugin_paths (test_config.ConfigTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/alinefm/kimchi/tests/test_config.py", line 61, in test_installed_plugin_paths '/usr/lib/python2.7/site-packages/kimchi/plugins/sample') AssertionError: '/usr/lib/python2.7/dist-packages/kimchi/plugins/sample' != '/usr/lib/python2.7/site-packages/kimchi/plugins/sample' ====================================================================== FAIL: test_rectangles (test_plugin.PluginTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/alinefm/kimchi/tests/test_plugin.py", line 89, in test_rectangles self._create_rectangle_and_assert('small', 10, 8) File "/home/alinefm/kimchi/tests/test_plugin.py", line 74, in _create_rectangle_and_assert self.assertEquals(201, resp.status) AssertionError: 201 != 500 ---------------------------------------------------------------------- Ran 136 tests in 108.748s FAILED (failures=5, errors=2) On 01/24/2014 04:31 AM, Mark Wu wrote:
This series of patches reorganize kimchi's path vars generation code to allow plugin use kimchi s ui handler.
Changes: v2: Rebase Remove the optimization for plugin paths since it just have a few instantiations.
Mark Wu (3): Reorganize the kimchi's paths gereneration code Add test cases for paths generation code Allow plugin use kimchi's ui handler
src/kimchi/cachebust.py | 4 +- src/kimchi/config.py.in | 155 +++++++++++++++++++----------------------------- src/kimchi/root.py | 23 ++++--- src/kimchi/server.py | 14 +++-- src/kimchi/template.py | 17 ++++-- src/kimchi/utils.py | 6 +- src/kimchid.in | 7 ++- tests/test_config.py | 73 +++++++++++++++++++++++ tests/test_plugin.py | 4 +- 9 files changed, 178 insertions(+), 125 deletions(-) create mode 100644 tests/test_config.py
participants (2)
-
Aline Manera
-
Mark Wu