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): |         for path, dirs, files in os.walk(directory): | ||||||
|             if '.svn' in dirs: |             if '.svn' in dirs: | ||||||
|                 del dirs[dirs.index('.svn')] |                 del dirs[dirs.index('.svn')] | ||||||
|  |             self.loadFiles(files, pattern) | ||||||
|  | 
 | ||||||
|  |     def loadFiles(self, files, pattern): | ||||||
|         for f in filter(files, pattern): |         for f in filter(files, pattern): | ||||||
|             filename = os.path.join(path, f) |             filename = os.path.join(path, f) | ||||||
|             mtime = datetime.fromtimestamp(os.path.getmtime(filename)) |             mtime = datetime.fromtimestamp(os.path.getmtime(filename)) | ||||||
|  |  | ||||||
|  | @ -433,7 +433,8 @@ class BaseView(GenericView, I18NView): | ||||||
| 
 | 
 | ||||||
|     def registerDojoDateWidget(self): |     def registerDojoDateWidget(self): | ||||||
|         self.registerDojo() |         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) |         self.controller.macros.register('js-execute', jsCall, jsCall=jsCall) | ||||||
| 
 | 
 | ||||||
|     def registerDojoTextWidget(self): |     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 | #  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 | #  it under the terms of the GNU General Public License as published by | ||||||
|  | @ -54,6 +54,8 @@ class LanguageInfo(object): | ||||||
|             if opt.startswith('languages:'): |             if opt.startswith('languages:'): | ||||||
|                 return opt[len('languages:'):].split(',') |                 return opt[len('languages:'):].split(',') | ||||||
|         return [] |         return [] | ||||||
|  |         # new implementation: | ||||||
|  |         # return IOptions(self.context).i18n.languages | ||||||
| 
 | 
 | ||||||
|     @Lazy |     @Lazy | ||||||
|     def defaultLanguage(self): |     def defaultLanguage(self): | ||||||
|  |  | ||||||
|  | @ -121,6 +121,8 @@ class I18NAdapterBase(AdapterBase): | ||||||
|         tp = IType(self.context) |         tp = IType(self.context) | ||||||
|         attrs = tp.optionsDict.get('i18nattributes', '') |         attrs = tp.optionsDict.get('i18nattributes', '') | ||||||
|         return [attr.strip() for attr in attrs.split(',')] |         return [attr.strip() for attr in attrs.split(',')] | ||||||
|  |         # new implementation: | ||||||
|  |         # return self.options.i18n.attributes | ||||||
| 
 | 
 | ||||||
|     def __getattr__(self, attr): |     def __getattr__(self, attr): | ||||||
|         self.checkAttr(attr) |         self.checkAttr(attr) | ||||||
|  |  | ||||||
|  | @ -60,8 +60,8 @@ class Events(ConceptView): | ||||||
|         cm = self.loopsRoot.getConceptManager() |         cm = self.loopsRoot.getConceptManager() | ||||||
|         tEvent = cm['event'] |         tEvent = cm['event'] | ||||||
|         hasType = cm.getTypePredicate() |         hasType = cm.getTypePredicate() | ||||||
|         sort = lambda x: x.adapted.start |  | ||||||
|         now = datetime.today() |         now = datetime.today() | ||||||
|  |         sort = lambda x: x.adapted.start or now | ||||||
|         relViews = (self.childViewFactory(r, self.request, contextIsSecond=True) |         relViews = (self.childViewFactory(r, self.request, contextIsSecond=True) | ||||||
|                         for r in tEvent.getChildRelations([hasType], sort=None)) |                         for r in tEvent.getChildRelations([hasType], sort=None)) | ||||||
|         return sorted((rv for rv in relViews |         return sorted((rv for rv in relViews | ||||||
|  |  | ||||||
|  | @ -47,11 +47,16 @@ class ChangeManager(object): | ||||||
|             return |             return | ||||||
|         self.context = context |         self.context = context | ||||||
| 
 | 
 | ||||||
|  |     @Lazy | ||||||
|  |     def options(self): | ||||||
|  |         return IOptions(self.context) | ||||||
|  | 
 | ||||||
|     @Lazy |     @Lazy | ||||||
|     def valid(self): |     def valid(self): | ||||||
|         return not (self.context is None or |         return not (self.context is None or | ||||||
|                     self.storage is None or |                     self.storage is None or | ||||||
|                     self.person is None) |                     self.person is None) | ||||||
|  |         # and 'changes' in self.options.tracking | ||||||
| 
 | 
 | ||||||
|     @Lazy |     @Lazy | ||||||
|     def loopsRoot(self): |     def loopsRoot(self): | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 helmutm
						helmutm