mirror of
https://github.com/yweber/lodel2.git
synced 2025-12-03 17:26:54 +01:00
New way to handles plugin
- renamed Plugins class to Plugin - an instance represent a loaded plugin - classmethod allows to preload & load plugins
This commit is contained in:
parent
3a87551f2e
commit
61f19772fb
15 changed files with 322 additions and 188 deletions
|
|
@ -1,5 +1,5 @@
|
|||
[lodel2.datasources.default]
|
||||
identifier = dummy.example
|
||||
identifier = dummy_datasource.example
|
||||
|
||||
[lodel2.datasource.dummy_datasource.example]
|
||||
dummy =
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ from lodel.settings import Settings
|
|||
|
||||
|
||||
#Load plugins
|
||||
from lodel.plugin import Plugins
|
||||
Plugins.bootstrap()
|
||||
from lodel.plugin import Plugin
|
||||
Plugin.load_all()
|
||||
|
||||
from lodel.plugin import LodelHook
|
||||
LodelHook.call_hook('lodel2_bootstraped', '__main__', None)
|
||||
|
|
|
|||
|
|
@ -1 +1,14 @@
|
|||
#-*- coding: utf-8 -*-
|
||||
|
||||
##@page lodel2_start Lodel2 boot mechanism
|
||||
#
|
||||
# @par Lodel2 boot sequence
|
||||
# see @ref install/loader.py
|
||||
# 1. lodel package is imported
|
||||
# 2. settings are started
|
||||
# 3. plugins are pre-loaded from conf to load plugins configuration specs
|
||||
# 4. settings are loaded from conf and checked
|
||||
# 3. plugins are loaded (hooks are registered etc)
|
||||
# 4. "lodel2_bootstraped" hooks are called
|
||||
# 5. "lodel2_loader_main" hooks are called (if runned from loader.py as main executable)
|
||||
#
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import importlib
|
||||
|
||||
from lodel.plugin import Plugins
|
||||
from lodel.plugin import Plugin
|
||||
from lodel import logger
|
||||
from lodel.settings import Settings
|
||||
from lodel.settings.utils import SettingsError
|
||||
|
|
@ -221,7 +221,7 @@ class LeObject(object):
|
|||
|
||||
ds_conf = getattr(ds_conf, ds_name)
|
||||
#Checks that the datasource plugin exists
|
||||
ds_plugin_module = Plugins.plugin_module(ds_plugin)
|
||||
ds_plugin_module = Plugin.get(ds_plugin).module
|
||||
try:
|
||||
datasource_class = getattr(ds_plugin_module, "Datasource")
|
||||
except AttributeError as e:
|
||||
|
|
|
|||
|
|
@ -40,4 +40,4 @@
|
|||
#
|
||||
|
||||
from .hooks import LodelHook
|
||||
from .plugins import Plugins
|
||||
from .plugins import Plugin
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
#-*- coding: utf-8 -*-
|
||||
|
||||
import sys
|
||||
import os.path
|
||||
|
||||
import importlib
|
||||
import copy
|
||||
from importlib.machinery import SourceFileLoader, SourcelessFileLoader
|
||||
|
||||
import plugins
|
||||
|
||||
## @package lodel.plugins Lodel2 plugins management
|
||||
|
|
@ -15,23 +17,160 @@ import plugins
|
|||
# - confspec.py containing a configuration specification dictionary named CONFSPEC
|
||||
|
||||
##@brief The package in wich we will load plugins modules
|
||||
VIRTUAL_PACKAGE_NAME = 'lodel.plugins_pkg'
|
||||
CONFSPEC_FILENAME = 'confspec.py'
|
||||
MAIN_FILENAME = '__init__.py'
|
||||
VIRTUAL_PACKAGE_NAME = 'lodel.plugins'
|
||||
INIT_FILENAME = '__init__.py' # Loaded with settings
|
||||
CONFSPEC_FILENAME_VARNAME = '__confspec__'
|
||||
CONFSPEC_VARNAME = 'CONFSPEC'
|
||||
LOADER_FILENAME_VARNAME = '__loader__'
|
||||
|
||||
class PluginError(Exception):
|
||||
pass
|
||||
|
||||
class Plugins(object):
|
||||
class Plugin(object):
|
||||
|
||||
##@brief Stores plugin directories paths
|
||||
_plugin_directories = None
|
||||
##@brief Optimisation cache storage for plugin paths
|
||||
_plugin_paths = dict()
|
||||
|
||||
def __init__(self): # may be useless
|
||||
_plugin_instances = dict()
|
||||
|
||||
##@brief Plugin class constructor
|
||||
#
|
||||
# Called by setting in early stage of lodel2 boot sequence using classmethod
|
||||
# register
|
||||
#
|
||||
# @param plugin_name str : plugin name
|
||||
# @throw PluginError
|
||||
def __init__(self, plugin_name):
|
||||
self.started()
|
||||
|
||||
self.name = plugin_name
|
||||
self.path = self.plugin_path(plugin_name)
|
||||
self.module = None
|
||||
self.__confspecs = dict()
|
||||
|
||||
# Importing __init__.py
|
||||
plugin_module = '%s.%s' % ( VIRTUAL_PACKAGE_NAME,
|
||||
plugin_name)
|
||||
init_source = self.path + INIT_FILENAME
|
||||
try:
|
||||
loader = SourceFileLoader(plugin_module, init_source)
|
||||
self.module = loader.load_module()
|
||||
except ImportError as e:
|
||||
raise PluginError("Failed to load plugin '%s'. It seems that the plugin name is not valid" % plugin_name)
|
||||
|
||||
# loading confspecs
|
||||
try:
|
||||
# Loading confspec directly from __init__.py
|
||||
self.__confspecs = getattr(self.module, CONFSPEC_VARNAME)
|
||||
except AttributeError:
|
||||
# Loading file in __confspec__ var in __init__.py
|
||||
try:
|
||||
module = self._import_from_init_var(CONFSPEC_FILENAME_VARNAME)
|
||||
except AttributeError:
|
||||
msg = "Malformed plugin {plugin} . No {varname} not {filevar} found in __init__.py"
|
||||
msg = msg.format(
|
||||
plugin = self.name,
|
||||
varname = CONFSPEC_VARNAME,
|
||||
filevar = CONFSPEC_FILENAME_VARNAME)
|
||||
raise PluginError(msg)
|
||||
except ImportError as e:
|
||||
msg = "Broken plugin {plugin} : {expt}"
|
||||
msg = msg.format(
|
||||
plugin = self.name,
|
||||
expt = str(e))
|
||||
raise PluginError(msg)
|
||||
|
||||
try:
|
||||
# loading confpsecs from file
|
||||
self.__confspecs = getattr(module, CONFSPEC_VARNAME)
|
||||
except AttributeError:
|
||||
msg = "Broken plugin. {varname} not found in '{filename}'"
|
||||
msg = msg.format(
|
||||
varname = CONFSPEC_VARNAME,
|
||||
filename = confspec_filename)
|
||||
raise PluginError(msg)
|
||||
|
||||
##@brief Try to import a file from a variable in __init__.py
|
||||
#@param varname str : The variable name
|
||||
#@throw AttributeError if varname not found
|
||||
#@throw ImportError if the file fails to be imported
|
||||
#@throw PluginError if the filename was not valid
|
||||
def _import_from_init_var(self, varname):
|
||||
# Read varname
|
||||
filename = getattr(self.module, varname)
|
||||
#Path are not allowed
|
||||
if filename != os.path.basename(filename):
|
||||
msg = "Invalid {varname} content : '{fname}' for plugin {name}"
|
||||
msg = msg.format(
|
||||
varname = varname,
|
||||
fname = filename,
|
||||
name = self.name)
|
||||
raise PluginError(msg)
|
||||
# importing the file in varname
|
||||
module_name = self.module.__name__+"."+varname
|
||||
filename = self.path + filename
|
||||
loader = SourceFileLoader(module_name, filename)
|
||||
return loader.load_module()
|
||||
|
||||
##@brief Register hooks etc
|
||||
def load(self):
|
||||
from lodel import logger
|
||||
try:
|
||||
return self._import_from_init_var(LOADER_FILENAME_VARNAME)
|
||||
except AttributeError:
|
||||
msg = "Malformed plugin {plugin}. No {varname} found in __init__.py"
|
||||
msg = msg.format(
|
||||
plugin = self.name,
|
||||
varname = LOADER_FILENAME_VARNAME)
|
||||
raise PluginError(msg)
|
||||
except ImportError as e:
|
||||
msg = "Broken plugin {plugin} : {expt}"
|
||||
msg = msg.format(
|
||||
plugin = self.name,
|
||||
expt = str(e))
|
||||
raise PluginError(msg)
|
||||
logger.debug("Plugin '%s' loaded" % self.name)
|
||||
|
||||
@classmethod
|
||||
def load_all(cls):
|
||||
errors = dict()
|
||||
for name, plugin in cls._plugin_instances.items():
|
||||
try:
|
||||
plugin.load()
|
||||
except PluginError as e:
|
||||
errors[name] = e
|
||||
if len(errors) > 0:
|
||||
msg = "Errors while loading plugins :"
|
||||
for name, e in errors.items():
|
||||
msg += "\n\t%20s : %s" % (name,e)
|
||||
msg += "\n"
|
||||
raise PluginError(msg)
|
||||
|
||||
@property
|
||||
def confspecs(self):
|
||||
return copy.copy(self.__confspecs)
|
||||
|
||||
##@brief Register a new plugin
|
||||
#
|
||||
# preload
|
||||
@classmethod
|
||||
def register(cls, plugin_name):
|
||||
if plugin_name in cls._plugin_instances:
|
||||
msg = "Plugin allready registered with same name %s"
|
||||
msg %= plugin_name
|
||||
raise PluginError(msg)
|
||||
plugin = cls(plugin_name)
|
||||
cls._plugin_instances[plugin_name] = plugin
|
||||
return plugin
|
||||
|
||||
@classmethod
|
||||
def get(cls, plugin_name):
|
||||
try:
|
||||
return cls._plugin_instances[plugin_name]
|
||||
except KeyError:
|
||||
msg = "No plugin named '%s' loaded"
|
||||
msg %= plugin_name
|
||||
raise PluginError(msg)
|
||||
|
||||
##@brief Given a plugin name returns the plugin path
|
||||
# @param plugin_name str : The plugin name
|
||||
|
|
@ -40,8 +179,8 @@ class Plugins(object):
|
|||
def plugin_path(cls, plugin_name):
|
||||
cls.started()
|
||||
try:
|
||||
return cls._plugin_paths[plugin_name]
|
||||
except KeyError:
|
||||
return cls.get(plugin_name).path
|
||||
except PluginError:
|
||||
pass
|
||||
|
||||
path = None
|
||||
|
|
@ -51,71 +190,41 @@ class Plugins(object):
|
|||
return plugin_path
|
||||
raise NameError("No plugin named '%s'" % plugin_name)
|
||||
|
||||
##@brief Fetch a confspec given a plugin_name
|
||||
# @param plugin_name str : The plugin name
|
||||
# @return a dict of conf spec
|
||||
# @throw PluginError if plugin_name is not valid
|
||||
@classmethod
|
||||
def get_confspec(cls, plugin_name):
|
||||
cls.started()
|
||||
plugin_path = cls.plugin_path(plugin_name)
|
||||
plugin_module = '%s.%s' % ( VIRTUAL_PACKAGE_NAME,
|
||||
plugin_name)
|
||||
conf_spec_module = plugin_module + '.confspec'
|
||||
|
||||
conf_spec_source = plugin_path + CONFSPEC_FILENAME
|
||||
try:
|
||||
loader = SourceFileLoader(conf_spec_module, conf_spec_source)
|
||||
confspec_module = loader.load_module()
|
||||
except ImportError:
|
||||
raise PluginError("Failed to load plugin '%s'. It seems that the plugin name is not valid" % plugin_name)
|
||||
return getattr(confspec_module, CONFSPEC_VARNAME)
|
||||
|
||||
##@brief Load a module to register plugin's hooks
|
||||
# @param plugin_name str : The plugin name
|
||||
@classmethod
|
||||
def load_plugin(cls, plugin_name):
|
||||
cls.plugin_module(plugin_name)
|
||||
|
||||
##@brief Load a plugin module and return it
|
||||
#@return the plugin module
|
||||
@classmethod
|
||||
def plugin_module(cls, plugin_name):
|
||||
cls.started()
|
||||
plugin_path = cls.plugin_path(plugin_name)
|
||||
plugin_module = '%s.%s' % ( VIRTUAL_PACKAGE_NAME,
|
||||
plugin_name)
|
||||
main_module = plugin_module
|
||||
main_source = plugin_path + MAIN_FILENAME
|
||||
try:
|
||||
loader = SourceFileLoader(main_module, main_source)
|
||||
module = loader.load_module()
|
||||
return module
|
||||
except ImportError as e:
|
||||
raise e
|
||||
raise PluginError("Failed to load plugin '%s'. It seems that the plugin name is not valid" % plugin_name)
|
||||
def plugin_module_name(cls, plugin_name):
|
||||
return "%s.%s" % (VIRTUAL_PACKAGE_NAME, plugin_name)
|
||||
|
||||
|
||||
##@brief Bootstrap the Plugins class
|
||||
##@brief Start the Plugin class
|
||||
#
|
||||
# Called by Settings.__bootstrap()
|
||||
#
|
||||
# This method load path and preload plugins
|
||||
@classmethod
|
||||
def bootstrap(cls):
|
||||
from lodel.settings import Settings
|
||||
for plugin_name in Settings.plugins:
|
||||
cls.load_plugin(plugin_name)
|
||||
|
||||
@classmethod
|
||||
def start(cls, plugins_directories):
|
||||
def start(cls, plugins_directories, plugins):
|
||||
if cls._plugin_directories is not None:
|
||||
return
|
||||
import inspect
|
||||
self_path = inspect.getsourcefile(Plugins)
|
||||
self_path = inspect.getsourcefile(Plugin)
|
||||
default_plugin_path = os.path.abspath(self_path + '../../../../plugins')
|
||||
if plugins_directories is None:
|
||||
plugins_directories = list()
|
||||
plugins_directories += [ default_plugin_path ]
|
||||
cls._plugin_directories = list(set(plugins_directories))
|
||||
for plugin_name in plugins:
|
||||
cls.register(plugin_name)
|
||||
|
||||
|
||||
@classmethod
|
||||
def started(cls, raise_if_not = True):
|
||||
res = cls._plugin_directories is not None
|
||||
if raise_if_not and not res:
|
||||
raise RuntimeError("Class Plugins is not initialized")
|
||||
|
||||
##@page lodel2_plugins Lodel2 plugins system
|
||||
#
|
||||
# @par Plugin structure
|
||||
#A plugin is a package (a folder containing, at least, an __init__.py file.
|
||||
#This file should expose multiple things :
|
||||
# - a CONFSPEC variable containing configuration specifications
|
||||
# - an _activate() method that returns True if the plugin can be activated (
|
||||
# optionnal)
|
||||
#
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import warnings
|
|||
import types # for dynamic bindings
|
||||
from collections import namedtuple
|
||||
|
||||
from lodel.plugin.plugins import Plugins, PluginError
|
||||
from lodel.plugin.plugins import Plugin, PluginError
|
||||
from lodel.settings.utils import SettingsError, SettingsErrors
|
||||
from lodel.settings.validator import SettingValidator, LODEL2_CONF_SPECS
|
||||
from lodel.settings.settings_loader import SettingsLoader
|
||||
|
|
@ -153,15 +153,15 @@ class Settings(object, metaclass=MetaSettings):
|
|||
plugins_path_opt_specs[0],
|
||||
False)
|
||||
# Starting the Plugins class
|
||||
Plugins.start(plugins_path)
|
||||
Plugin.start(plugins_path, plugins_list)
|
||||
# Fetching conf specs from plugins
|
||||
specs = [lodel2_specs]
|
||||
errors = list()
|
||||
for plugin_name in plugins_list:
|
||||
try:
|
||||
specs.append(Plugins.get_confspec(plugin_name))
|
||||
specs.append(Plugin.get(plugin_name).confspecs)
|
||||
except PluginError as e:
|
||||
errors.append(e)
|
||||
errors.append(SettingsError(msg=str(e)))
|
||||
if len(errors) > 0: #Raise all plugins import errors
|
||||
raise SettingsErrors(errors)
|
||||
self.__conf_specs = self.__merge_specs(specs)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
from lodel.settings.validator import SettingValidator
|
||||
|
||||
__loader__ = 'main.py'
|
||||
|
||||
CONFSPEC = {
|
||||
'lodel2.datasources.*': {
|
||||
'identifier': ( None,
|
||||
SettingValidator('string'))}}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
#-*- coding: utf-8 -*-
|
||||
|
||||
from lodel.settings.validator import SettingValidator
|
||||
|
||||
CONFSPEC = {
|
||||
'lodel2.datasources.*': {
|
||||
'identifier': ( None,
|
||||
SettingValidator('string'))}}
|
||||
|
|
@ -1,2 +1,10 @@
|
|||
from lodel.settings.validator import SettingValidator
|
||||
|
||||
__loader__ = "main.py"
|
||||
__confspec__ = "confspec.py"
|
||||
__author__ = "Lodel2 dev team"
|
||||
__fullname__ = "Dummy plugin"
|
||||
|
||||
|
||||
def _activate():
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
from lodel.plugin import LodelHook
|
||||
|
||||
def _activate():
|
||||
return True
|
||||
|
||||
|
||||
##@brief Hook's callback example
|
||||
@LodelHook('leapi_get_pre')
|
||||
@LodelHook('leapi_get_post')
|
||||
|
|
|
|||
|
|
@ -1 +1,86 @@
|
|||
from lodel.settings.validator import SettingValidator
|
||||
from .main import DummyDatasource as Datasource
|
||||
|
||||
__loader__ = 'main.py'
|
||||
|
||||
CONFSPEC = {
|
||||
'lodel2.datasource.dummy_datasource.*' : {
|
||||
'dummy': ( None,
|
||||
SettingValidator('dummy'))}
|
||||
}
|
||||
|
||||
##@page lodel2_datasources Lodel2 datasources
|
||||
#
|
||||
#@par lodel2_datasources_intro Intro
|
||||
# A single lodel2 website can interact with multiple datasources. This page
|
||||
# aims to describe configuration & organisation of datasources in lodel2.
|
||||
# Each object is attached to a datasource. This association is done in the
|
||||
# editorial model, the datasource is identified by a name.
|
||||
#
|
||||
#@par Datasources declaration
|
||||
# To define a datasource you have to write something like this in confs file :
|
||||
#<pre>
|
||||
#[lodel2.datasources.DATASOURCE_NAME]
|
||||
#identifier = DATASOURCE_FAMILY.SOURCE_NAME
|
||||
#</pre>
|
||||
# See below for DATASOURCE_FAMILY & SOURCE_NAME
|
||||
#
|
||||
#@par Datasources plugins
|
||||
# Each datasource family is a plugin. For example mysql or a mongodb plugins.
|
||||
# Here is the CONFSPEC variable templates for datasources plugins
|
||||
#<pre>
|
||||
#CONFSPEC = {
|
||||
# 'lodel2.datasource.example.*' : {
|
||||
# 'conf1' : VALIDATOR_OPTS,
|
||||
# 'conf2' : VALIDATOR_OPTS,
|
||||
# ...
|
||||
# }
|
||||
#}
|
||||
#</pre>
|
||||
#MySQL example
|
||||
#<pre>
|
||||
#CONFSPEC = {
|
||||
# 'lodel2.datasource.mysql.*' : {
|
||||
# 'host': ( 'localhost',
|
||||
# SettingValidator('host')),
|
||||
# 'db_name': ( 'lodel',
|
||||
# SettingValidator('string')),
|
||||
# 'username': ( None,
|
||||
# SettingValidator('string')),
|
||||
# 'password': ( None,
|
||||
# SettingValidator('string')),
|
||||
# }
|
||||
#}
|
||||
#</pre>
|
||||
#
|
||||
#@par Configuration example
|
||||
#<pre>
|
||||
# [lodel2.datasources.main]
|
||||
# identifier = mysql.Core
|
||||
# [lodel2.datasources.revues_write]
|
||||
# identifier = mysql.Revues
|
||||
# [lodel2.datasources.revues_read]
|
||||
# identifier = mysql.Revues
|
||||
# [lodel2.datasources.annuaire_persons]
|
||||
# identifier = persons_web_api.example
|
||||
# ;
|
||||
# ; Then, in the editorial model you are able to use "main", "revues_write",
|
||||
# ; etc as datasource
|
||||
# ;
|
||||
# ; Here comes the datasources declarations
|
||||
# [lodel2.datasource.mysql.Core]
|
||||
# host = db.core.labocleo.org
|
||||
# db_name = core
|
||||
# username = foo
|
||||
# password = bar
|
||||
# ;
|
||||
# [lodel2.datasource.mysql.Revues]
|
||||
# host = revues.org
|
||||
# db_name = RO
|
||||
# username = foo
|
||||
# password = bar
|
||||
# ;
|
||||
# [lodel2.datasource.persons_web_api.example]
|
||||
# host = foo.bar
|
||||
# username = cleo
|
||||
#</pre>
|
||||
|
|
|
|||
|
|
@ -1,85 +0,0 @@
|
|||
#-*- coding: utf-8 -*-
|
||||
|
||||
from lodel.settings.validator import SettingValidator
|
||||
|
||||
CONFSPEC = {
|
||||
'lodel2.datasource.dummy_datasource.*' : {
|
||||
'dummy': ( None,
|
||||
SettingValidator('dummy'))}
|
||||
}
|
||||
|
||||
##@page lodel2_datasources Lodel2 datasources
|
||||
#
|
||||
#@par lodel2_datasources_intro Intro
|
||||
# A single lodel2 website can interact with multiple datasources. This page
|
||||
# aims to describe configuration & organisation of datasources in lodel2.
|
||||
# Each object is attached to a datasource. This association is done in the
|
||||
# editorial model, the datasource is identified by a name.
|
||||
#
|
||||
#@par Datasources declaration
|
||||
# To define a datasource you have to write something like this in confs file :
|
||||
#<pre>
|
||||
#[lodel2.datasources.DATASOURCE_NAME]
|
||||
#identifier = DATASOURCE_FAMILY.SOURCE_NAME
|
||||
#</pre>
|
||||
# See below for DATASOURCE_FAMILY & SOURCE_NAME
|
||||
#
|
||||
#@par Datasources plugins
|
||||
# Each datasource family is a plugin. For example mysql or a mongodb plugins.
|
||||
# Here is the CONFSPEC variable templates for datasources plugins
|
||||
#<pre>
|
||||
#CONFSPEC = {
|
||||
# 'lodel2.datasource.example.*' : {
|
||||
# 'conf1' : VALIDATOR_OPTS,
|
||||
# 'conf2' : VALIDATOR_OPTS,
|
||||
# ...
|
||||
# }
|
||||
#}
|
||||
#</pre>
|
||||
#MySQL example
|
||||
#<pre>
|
||||
#CONFSPEC = {
|
||||
# 'lodel2.datasource.mysql.*' : {
|
||||
# 'host': ( 'localhost',
|
||||
# SettingValidator('host')),
|
||||
# 'db_name': ( 'lodel',
|
||||
# SettingValidator('string')),
|
||||
# 'username': ( None,
|
||||
# SettingValidator('string')),
|
||||
# 'password': ( None,
|
||||
# SettingValidator('string')),
|
||||
# }
|
||||
#}
|
||||
#</pre>
|
||||
#
|
||||
#@par Configuration example
|
||||
#<pre>
|
||||
# [lodel2.datasources.main]
|
||||
# identifier = mysql.Core
|
||||
# [lodel2.datasources.revues_write]
|
||||
# identifier = mysql.Revues
|
||||
# [lodel2.datasources.revues_read]
|
||||
# identifier = mysql.Revues
|
||||
# [lodel2.datasources.annuaire_persons]
|
||||
# identifier = persons_web_api.example
|
||||
# ;
|
||||
# ; Then, in the editorial model you are able to use "main", "revues_write",
|
||||
# ; etc as datasource
|
||||
# ;
|
||||
# ; Here comes the datasources declarations
|
||||
# [lodel2.datasource.mysql.Core]
|
||||
# host = db.core.labocleo.org
|
||||
# db_name = core
|
||||
# username = foo
|
||||
# password = bar
|
||||
# ;
|
||||
# [lodel2.datasource.mysql.Revues]
|
||||
# host = revues.org
|
||||
# db_name = RO
|
||||
# username = foo
|
||||
# password = bar
|
||||
# ;
|
||||
# [lodel2.datasource.persons_web_api.example]
|
||||
# host = foo.bar
|
||||
# username = cleo
|
||||
#</pre>
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
from lodel.settings.validator import SettingValidator
|
||||
|
||||
__loader__ = 'main.py'
|
||||
|
||||
CONFSPEC = {
|
||||
'lodel2.webui': {
|
||||
'standalone': ( False,
|
||||
SettingValidator('bool')),
|
||||
'listen_address': ( '127.0.0.1',
|
||||
SettingValidator('dummy')),
|
||||
'listen_port': ( '9090',
|
||||
SettingValidator('int')),
|
||||
},
|
||||
'lodel2.webui.sessions': {
|
||||
'directory': ( '/tmp/lodel2_session',
|
||||
SettingValidator('path')),
|
||||
'expiration': ( 900,
|
||||
SettingValidator('int')),
|
||||
'file_template': ( 'lodel2_%s.sess',
|
||||
SettingValidator('dummy')),
|
||||
}
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
#-*- coding: utf-8 -*-
|
||||
|
||||
from lodel.settings.validator import SettingValidator
|
||||
|
||||
CONFSPEC = {
|
||||
'lodel2.webui': {
|
||||
'standalone': ( False,
|
||||
SettingValidator('bool')),
|
||||
'listen_address': ( '127.0.0.1',
|
||||
SettingValidator('dummy')),
|
||||
'listen_port': ( '9090',
|
||||
SettingValidator('int')),
|
||||
},
|
||||
'lodel2.webui.sessions': {
|
||||
'directory': ( '/tmp/lodel2_session',
|
||||
SettingValidator('path')),
|
||||
'expiration': ( 900,
|
||||
SettingValidator('int')),
|
||||
'file_template': ( 'lodel2_%s.sess',
|
||||
SettingValidator('dummy')),
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue