work in progress: loops.config for generic management of configuration options, settings, preferences
git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@2518 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
4d5bfed47f
commit
87ec9a2860
10 changed files with 194 additions and 13 deletions
|
@ -53,6 +53,9 @@ class CrawlingJob(BaseCrawlingJob):
|
|||
for path, dirs, files in os.walk(directory):
|
||||
if '.svn' in dirs:
|
||||
del dirs[dirs.index('.svn')]
|
||||
self.loadFiles(files, pattern)
|
||||
|
||||
def loadFiles(self, files, pattern):
|
||||
for f in filter(files, pattern):
|
||||
filename = os.path.join(path, f)
|
||||
mtime = datetime.fromtimestamp(os.path.getmtime(filename))
|
||||
|
|
|
@ -433,7 +433,8 @@ class BaseView(GenericView, I18NView):
|
|||
|
||||
def registerDojoDateWidget(self):
|
||||
self.registerDojo()
|
||||
jsCall = 'dojo.require("dijit.form.DateTextBox");'
|
||||
jsCall = ('dojo.require("dijit.form.DateTextBox"); '
|
||||
'dojo.require("dijit.form.TimeTextBox");')
|
||||
self.controller.macros.register('js-execute', jsCall, jsCall=jsCall)
|
||||
|
||||
def registerDojoTextWidget(self):
|
||||
|
|
73
config/README.txt
Normal file
73
config/README.txt
Normal file
|
@ -0,0 +1,73 @@
|
|||
===============================================================
|
||||
loops - Linked Objects for Organization and Processing Services
|
||||
===============================================================
|
||||
|
||||
Management of configuration settings and preferences.
|
||||
|
||||
($Id$)
|
||||
|
||||
|
||||
Setting up a loops Site and Utilities
|
||||
=====================================
|
||||
|
||||
Let's do some basic set up
|
||||
|
||||
>>> from zope import component, interface
|
||||
>>> from zope.traversing.api import getName
|
||||
>>> from zope.app.testing.setup import placefulSetUp, placefulTearDown
|
||||
>>> site = placefulSetUp(True)
|
||||
|
||||
and build a simple loops site with a concept manager and some concepts
|
||||
(with a relation registry, a catalog, and all the type machinery - what
|
||||
in real life is done via standard ZCML setup or via local utility
|
||||
configuration):
|
||||
|
||||
>>> from loops.integrator.testsetup import TestSite
|
||||
>>> t = TestSite(site)
|
||||
>>> concepts, resources, views = t.setup()
|
||||
>>> loopsRoot = concepts.getLoopsRoot()
|
||||
|
||||
|
||||
Options Adapters
|
||||
================
|
||||
|
||||
Global and site options
|
||||
-----------------------
|
||||
|
||||
>>> from loops.config.base import LoopsOptions
|
||||
>>> component.provideAdapter(LoopsOptions)
|
||||
|
||||
>>> from cybertools.meta.interfaces import IOptions
|
||||
>>> opt = IOptions(loopsRoot)
|
||||
>>> opt
|
||||
<loops.config.base.LoopsOptions object ...>
|
||||
>>> str(opt)
|
||||
''
|
||||
|
||||
We now use the loops root object's options field to define
|
||||
some options.
|
||||
|
||||
>>> loopsRoot.options = ['useVersioning', 'organize.tracking:changes, access']
|
||||
>>> opt = IOptions(loopsRoot)
|
||||
>>> print opt
|
||||
organize(tracking=['changes', 'access'])
|
||||
useVersioning=True
|
||||
|
||||
>>> opt.organize.tracking
|
||||
['changes', 'access']
|
||||
>>> opt.useVersioning
|
||||
True
|
||||
|
||||
If we query an option that is not defined on the site level we get a
|
||||
dummy element that corresponds to False.
|
||||
|
||||
>>> opt.i18n.languages
|
||||
<AutoElement 'languages'>
|
||||
>>> bool(opt.i18n.languages)
|
||||
False
|
||||
|
||||
|
||||
Fin de partie
|
||||
=============
|
||||
|
||||
>>> placefulTearDown()
|
4
config/__init__.py
Normal file
4
config/__init__.py
Normal file
|
@ -0,0 +1,4 @@
|
|||
"""
|
||||
$Id$
|
||||
"""
|
||||
|
68
config/base.py
Normal file
68
config/base.py
Normal file
|
@ -0,0 +1,68 @@
|
|||
#
|
||||
# Copyright (c) 2008 Helmut Merz helmutm@cy55.de
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
"""
|
||||
Adapters and others classes for analyzing resources.
|
||||
|
||||
$Id$
|
||||
"""
|
||||
|
||||
from zope.cachedescriptors.property import Lazy
|
||||
from zope import component
|
||||
from zope.component import adapts
|
||||
from zope.traversing.api import getName, getParent
|
||||
|
||||
from cybertools.meta.config import Options
|
||||
from cybertools.meta.namespace import Executor, ExecutionError
|
||||
from cybertools.typology.interfaces import IType
|
||||
from loops.interfaces import ILoops
|
||||
|
||||
|
||||
class LoopsOptions(Options):
|
||||
|
||||
adapts(ILoops)
|
||||
|
||||
builtins = Options.builtins + ('True', 'False')
|
||||
True, False = True, False
|
||||
|
||||
def __init__(self, context, *args, **kw):
|
||||
self.context = context
|
||||
super(LoopsOptions, self).__init__(*args, **kw)
|
||||
self.loadContextOptions()
|
||||
|
||||
def parseContextOptions(self):
|
||||
def result():
|
||||
for opt in self.context.options:
|
||||
parts = opt.split(':', 1)
|
||||
key = parts[0].strip()
|
||||
if len(parts) == 1:
|
||||
value = 'True'
|
||||
else:
|
||||
value = repr([p.strip() for p in parts[1].split(',')])
|
||||
yield '='.join((key, value))
|
||||
return '\n'.join(result())
|
||||
|
||||
def loadContextOptions(self):
|
||||
code = self.parseContextOptions()
|
||||
rc = Executor(self).execute(code)
|
||||
if rc:
|
||||
raise ExecutionError('\n' + result)
|
||||
|
||||
#def __getitem__(self, key):
|
||||
# opt = self.baseOptions.get(key)
|
||||
# return opt
|
23
config/tests.py
Executable file
23
config/tests.py
Executable file
|
@ -0,0 +1,23 @@
|
|||
# $Id$
|
||||
|
||||
import unittest, doctest
|
||||
from zope.testing.doctestunit import DocFileSuite
|
||||
from zope.interface.verify import verifyClass
|
||||
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
"Basic tests for the config sub-package."
|
||||
|
||||
def testSomething(self):
|
||||
pass
|
||||
|
||||
|
||||
def test_suite():
|
||||
flags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
|
||||
return unittest.TestSuite((
|
||||
unittest.makeSuite(Test),
|
||||
DocFileSuite('README.txt', optionflags=flags),
|
||||
))
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(defaultTest='test_suite')
|
|
@ -1,5 +1,5 @@
|
|||
#
|
||||
# Copyright (c) 2007 Helmut Merz helmutm@cy55.de
|
||||
# Copyright (c) 2008 Helmut Merz helmutm@cy55.de
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -54,6 +54,8 @@ class LanguageInfo(object):
|
|||
if opt.startswith('languages:'):
|
||||
return opt[len('languages:'):].split(',')
|
||||
return []
|
||||
# new implementation:
|
||||
# return IOptions(self.context).i18n.languages
|
||||
|
||||
@Lazy
|
||||
def defaultLanguage(self):
|
||||
|
|
|
@ -121,6 +121,8 @@ class I18NAdapterBase(AdapterBase):
|
|||
tp = IType(self.context)
|
||||
attrs = tp.optionsDict.get('i18nattributes', '')
|
||||
return [attr.strip() for attr in attrs.split(',')]
|
||||
# new implementation:
|
||||
# return self.options.i18n.attributes
|
||||
|
||||
def __getattr__(self, attr):
|
||||
self.checkAttr(attr)
|
||||
|
|
|
@ -60,8 +60,8 @@ class Events(ConceptView):
|
|||
cm = self.loopsRoot.getConceptManager()
|
||||
tEvent = cm['event']
|
||||
hasType = cm.getTypePredicate()
|
||||
sort = lambda x: x.adapted.start
|
||||
now = datetime.today()
|
||||
sort = lambda x: x.adapted.start or now
|
||||
relViews = (self.childViewFactory(r, self.request, contextIsSecond=True)
|
||||
for r in tEvent.getChildRelations([hasType], sort=None))
|
||||
return sorted((rv for rv in relViews
|
||||
|
|
|
@ -47,11 +47,16 @@ class ChangeManager(object):
|
|||
return
|
||||
self.context = context
|
||||
|
||||
@Lazy
|
||||
def options(self):
|
||||
return IOptions(self.context)
|
||||
|
||||
@Lazy
|
||||
def valid(self):
|
||||
return not (self.context is None or
|
||||
self.storage is None or
|
||||
self.person is None)
|
||||
# and 'changes' in self.options.tracking
|
||||
|
||||
@Lazy
|
||||
def loopsRoot(self):
|
||||
|
|
Loading…
Add table
Reference in a new issue