[Kimchi-devel] [PATCH 1/2] Add static directory configurations for plugin's ui
Zhou Zheng Sheng
zhshzhou at linux.vnet.ibm.com
Tue Mar 4 07:51:38 UTC 2014
on 2014/02/28 17:59, Mark Wu wrote:
> Plugin needs static directory configuration for ui requirements,
> such as css, js, etc, as what we do for kimchi base. So this
> patch refactors the server configuration to make plugin can share
> the same code with kimchi. To avoid the warning messages reported from
> cherrypy's path checker, it also adds empty ui directory for the
> sample plugin, which also can demonstrate plugin's ui directory
> sturcture. We can add actual ui files under those direcotries later.
> ---
> plugins/sample/ui/css/.gitignore | 0
> plugins/sample/ui/images/.gitignore | 0
> plugins/sample/ui/js/.gitignore | 0
> plugins/sample/ui/libs/.gitignore | 0
> src/kimchi/config.py.in | 79 +++++++++++++++++++++++++++++++++++++
> src/kimchi/server.py | 77 ++----------------------------------
> 6 files changed, 82 insertions(+), 74 deletions(-)
> create mode 100644 plugins/sample/ui/css/.gitignore
> create mode 100644 plugins/sample/ui/images/.gitignore
> create mode 100644 plugins/sample/ui/js/.gitignore
> create mode 100644 plugins/sample/ui/libs/.gitignore
>
> diff --git a/plugins/sample/ui/css/.gitignore b/plugins/sample/ui/css/.gitignore
> new file mode 100644
> index 0000000..e69de29
> diff --git a/plugins/sample/ui/images/.gitignore b/plugins/sample/ui/images/.gitignore
> new file mode 100644
> index 0000000..e69de29
> diff --git a/plugins/sample/ui/js/.gitignore b/plugins/sample/ui/js/.gitignore
> new file mode 100644
> index 0000000..e69de29
> diff --git a/plugins/sample/ui/libs/.gitignore b/plugins/sample/ui/libs/.gitignore
> new file mode 100644
> index 0000000..e69de29
> diff --git a/src/kimchi/config.py.in b/src/kimchi/config.py.in
> index 2747164..f599c4d 100644
> --- a/src/kimchi/config.py.in
> +++ b/src/kimchi/config.py.in
> @@ -127,6 +127,85 @@ class PluginPaths(Paths):
> self.conf_file = os.path.join(self.conf_dir, '%s.conf' % name)
>
>
> +class AppConfig(dict):
> +
> + # expires is one year.
> + CACHEEXPIRES = 31536000
> +
> + def _get_ui_configs(self, paths):
> + ui_configs = {}
> + for sub_dir in ('css', 'js', 'libs', 'images'):
> + ui_configs['/' + sub_dir] = {
> + 'tools.staticdir.on': True,
> + 'tools.staticdir.dir': os.path.join(paths.ui_dir, sub_dir),
> + 'tools.nocache.on': False}
> + if sub_dir != 'images':
> + ui_configs['/' + sub_dir].update({
> + 'tools.expires.on': True,
> + 'tools.expires.secs': AppConfig.CACHEEXPIRES})
> + return ui_configs
> +
Hi,
The patch is good, but I don't like the way it uses inheritance. The
KimchiConfig and PluginConfig don't have to be the subclass of
AppConfig, and AppConfig is actual just a container for UI related
config, but not general configurations. Inheritance expresses a strong
"is-a-kind-of" relationship. It seems an overkill to use object
encapsulation and inheritance here. May I propose a better way to model
these three configs as follow?
Basically, the concept is rather simple:
kimchi_config = basic_kimchi_config + ui_config(kimchi_paths)
plugin_config = basic_plugin_config + ui_config(plugin_paths)
So in my opinion it should be a use case of composition, not inheritance.
Pseudo code is like this.
def _get_ui_config(paths):
ui_configs = {}
for sub_dir in ('css', 'js', 'libs', 'images'):
...
# almose the same as AppConfig.__init__ in you code.
return ui_configs
def _get_kimchi_config():
c = {'/': {'tools.trailing_slash.on': False, ...}
c.update(_get_ui_config(paths))
return c
def _get_plugin_ui_config(plugin_name):
c = {'/ui/config/tab-ext.xml': {...
c.update(_get_ui_config(PluginPaths(plugin_name)))
return c
class Server(object):
def __init__(self, options):
...
self.configObj = _get_kimchi_config()
def _load_plugins(self):
...
for plugin_name, plugin_config in get_enabled_plugins():
...
plugin_config.update(_get_plugin_ui_config(plugin_name))
If you prefer the objective way. Maybe you can consider the following
object model.
class UIConfig(dict):
def __init__(self, paths):
for sub_dir in ('css', 'js', 'libs', 'images'):
...
# almose the same as AppConfig.__init__ in you code.
class KimchiConfig(dict):
def __init__(self):
super(KimchiConfig, self).__init__()
kimchi_config = {...}
self.update(self.kimchi_config)
self.update(UIConfig(paths))
class PluginConfig(dict):
def __init__(self):
super(PluginConfig, self).__init__()
plugin_config = {...}
self.update(plugin_config)
self.update(UIConfig(PluginPaths(plugin_name)))
> +
> +class KimchiConfig(AppConfig):
> + kimchi_config = {
> + '/': {'tools.trailing_slash.on': False,
> + 'request.methods_with_bodies': ('POST', 'PUT'),
> + 'tools.nocache.on': True,
> + 'tools.sessions.on': True,
> + 'tools.sessions.name': 'kimchi',
> + 'tools.sessions.httponly': True,
> + 'tools.sessions.locking': 'explicit',
> + 'tools.sessions.storage_type': 'ram',
> + 'tools.kimchiauth.on': False},
> + '/data/screenshots': {
> + 'tools.staticdir.on': True,
> + 'tools.staticdir.dir': get_screenshot_path(),
> + 'tools.nocache.on': False
> + },
> + '/data/debugreports': {
> + 'tools.staticdir.on': True,
> + 'tools.staticdir.dir': get_debugreports_path(),
> + 'tools.nocache.on': False,
> + 'tools.kimchiauth.on': True,
> + 'tools.staticdir.content_types': {'xz': 'application/x-xz'}
> + },
> + '/config/ui/tabs.xml': {
> + 'tools.staticfile.on': True,
> + 'tools.staticfile.filename': '%s/config/ui/tabs.xml' %
> + paths.prefix,
> + 'tools.nocache.on': True
> + },
> + '/favicon.ico': {
> + 'tools.staticfile.on': True,
> + 'tools.staticfile.filename': '%s/images/logo.ico' % paths.ui_dir
> + },
> + '/help': {
> + 'tools.staticdir.on': True,
> + 'tools.staticdir.dir': '%s/ui/pages/help' % paths.prefix,
> + 'tools.nocache.on': False
> + }
> + }
> +
> + def __init__(self):
> + super(KimchiConfig, self).__init__(self)
> + self.update(self.kimchi_config)
> + self.update(self._get_ui_configs(paths))
> +
> +
> +class PluginConfig(AppConfig):
> + def __init__(self, plugin_name):
> + super(PluginConfig, self).__init__(self)
> + plugin_config = {
> + '/ui/config/tab-ext.xml': {
> + 'tools.staticfile.on': True,
> + 'tools.staticfile.filename':
> + os.path.join(PluginPaths(plugin_name).ui_dir,
> + 'config/tab-ext.xml'),
> + 'tools.nocache.on': True}}
> + self.update(plugin_config)
> + self.update(self._get_ui_configs(PluginPaths(plugin_name)))
> +
> +
> def _get_config():
> config = SafeConfigParser()
> config.add_section("server")
> diff --git a/src/kimchi/server.py b/src/kimchi/server.py
> index 5475b92..0d02868 100644
> --- a/src/kimchi/server.py
> +++ b/src/kimchi/server.py
> @@ -29,7 +29,7 @@ from kimchi import config
> from kimchi.model import model
> from kimchi import mockmodel
> from kimchi import vnc
> -from kimchi.config import paths, PluginPaths
> +from kimchi.config import paths, KimchiConfig, PluginConfig
> from kimchi.control import sub_nodes
> from kimchi.root import KimchiRoot
> from kimchi.utils import get_enabled_plugins, import_class
> @@ -57,73 +57,6 @@ def set_no_cache():
>
>
> class Server(object):
> - # expires is one year.
> - CACHEEXPIRES = 31536000
> - configObj = {
> - '/': {'tools.trailing_slash.on': False,
> - 'request.methods_with_bodies': ('POST', 'PUT'),
> - 'tools.nocache.on': True,
> - 'tools.sessions.on': True,
> - 'tools.sessions.name': 'kimchi',
> - 'tools.sessions.httponly': True,
> - 'tools.sessions.locking': 'explicit',
> - 'tools.sessions.storage_type': 'ram',
> - 'tools.kimchiauth.on': False},
> - '/css': {
> - 'tools.staticdir.on': True,
> - 'tools.staticdir.dir': '%s/ui/css' % paths.prefix,
> - 'tools.expires.on': True,
> - 'tools.expires.secs': CACHEEXPIRES,
> - 'tools.nocache.on': False
> - },
> - '/js': {
> - 'tools.staticdir.on': True,
> - 'tools.staticdir.dir': '%s/ui/js' % paths.prefix,
> - 'tools.expires.on': True,
> - 'tools.expires.secs': CACHEEXPIRES,
> - 'tools.nocache.on': False
> - },
> - '/libs': {
> - 'tools.staticdir.on': True,
> - 'tools.staticdir.dir': '%s/ui/libs' % paths.prefix,
> - 'tools.expires.on': True,
> - 'tools.expires.secs': CACHEEXPIRES,
> - 'tools.nocache.on': False,
> - },
> - '/images': {
> - 'tools.staticdir.on': True,
> - 'tools.staticdir.dir': '%s/ui/images' % paths.prefix,
> - 'tools.nocache.on': False
> - },
> - '/data/screenshots': {
> - 'tools.staticdir.on': True,
> - 'tools.staticdir.dir': config.get_screenshot_path(),
> - 'tools.nocache.on': False
> - },
> - '/data/debugreports': {
> - 'tools.staticdir.on': True,
> - 'tools.staticdir.dir': config.get_debugreports_path(),
> - 'tools.nocache.on': False,
> - 'tools.kimchiauth.on': True,
> - 'tools.staticdir.content_types': {'xz': 'application/x-xz'}
> - },
> - '/config/ui/tabs.xml': {
> - 'tools.staticfile.on': True,
> - 'tools.staticfile.filename': '%s/config/ui/tabs.xml' %
> - paths.prefix,
> - 'tools.nocache.on': True
> - },
> - '/favicon.ico': {
> - 'tools.staticfile.on': True,
> - 'tools.staticfile.filename': '%s/images/logo.ico' % paths.ui_dir
> - },
> - '/help': {
> - 'tools.staticdir.on': True,
> - 'tools.staticdir.dir': '%s/ui/pages/help' % paths.prefix,
> - 'tools.nocache.on': False
> - }
> - }
> -
> def __init__(self, options):
> make_dirs = [
> os.path.dirname(os.path.abspath(options.access_log)),
> @@ -137,6 +70,7 @@ class Server(object):
> if not os.path.isdir(directory):
> os.makedirs(directory)
>
> + self.configObj = KimchiConfig()
> cherrypy.tools.nocache = cherrypy.Tool('on_end_resource', set_no_cache)
> cherrypy.tools.kimchiauth = cherrypy.Tool('before_handler',
> auth.kimchiauth)
> @@ -214,12 +148,7 @@ class Server(object):
> script_name = plugin_config['kimchi']['uri']
> del plugin_config['kimchi']
>
> - plugin_config['/ui/config/tab-ext.xml'] = {
> - 'tools.staticfile.on': True,
> - 'tools.staticfile.filename':
> - os.path.join(PluginPaths(plugin_name).ui_dir,
> - 'config/tab-ext.xml'),
> - 'tools.nocache.on': True}
> + plugin_config.update(PluginConfig(plugin_name))
> except KeyError:
> continue
>
--
Thanks and best regards!
Zhou Zheng Sheng / 周征晟
E-mail: zhshzhou at linux.vnet.ibm.com
Telephone: 86-10-82454397
More information about the Kimchi-devel
mailing list