set up Configurator stuff
git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@1858 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
87d60fd415
commit
7ea411b923
4 changed files with 156 additions and 26 deletions
|
@ -26,8 +26,92 @@ This means that all calls to services (like crawler, transporter, ...)
|
|||
return a deferred that must be supplied with a callback method (and in
|
||||
most cases also an errback method).
|
||||
|
||||
>>> from loops.agent.core import Agent
|
||||
>>> agent = Agent()
|
||||
>>> from loops.agent import core
|
||||
>>> agent = core.Agent()
|
||||
|
||||
|
||||
Configuration Management
|
||||
========================
|
||||
|
||||
Functionality
|
||||
|
||||
- Storage of configuration parameters
|
||||
- Interface to the browser-based user interface that allows the
|
||||
editing of configuration parameters
|
||||
|
||||
All configuration parameters are always accessible via the ``config``
|
||||
attribute of the agent object.
|
||||
|
||||
>>> config = agent.config
|
||||
|
||||
This already provides all needed sections (transport, crawl, ui), so
|
||||
we can directly put information into these sections by loading a
|
||||
string with the corresponding assignment.
|
||||
|
||||
>>> config.load('transport.url = "http://loops.cy55.de"')
|
||||
>>> config.transport.url
|
||||
'http://loops.cy55.de'
|
||||
|
||||
This setting may also contain indexed access; thus we can model
|
||||
configuration parameters with multiple instances (like crawling
|
||||
jobs).
|
||||
|
||||
>>> config.load('''
|
||||
... crawl[0].type = "filesystem"
|
||||
... crawl[0].directory = "documents/projects"
|
||||
... ''')
|
||||
>>> config.crawl[0].type
|
||||
'filesystem'
|
||||
>>> config.crawl[0].directory
|
||||
'documents/projects'
|
||||
|
||||
Subsections are created automatically when they are first accessed.
|
||||
|
||||
>>> config.load('ui.web.port = 8081')
|
||||
>>> config.ui.web.port
|
||||
8081
|
||||
|
||||
The ``setdefault()`` method allows to retrieve a value and set
|
||||
it with a default if not found, in one statement.
|
||||
|
||||
>>> config.ui.web.setdefault('port', 8080)
|
||||
8081
|
||||
>>> config.transport.setdefault('user', 'loops')
|
||||
'loops'
|
||||
|
||||
We can output a configuration in a form that is ready for loading
|
||||
just by converting it to a string representation.
|
||||
|
||||
>>> print config
|
||||
crawl[0].directory = 'documents/projects'
|
||||
crawl[0].type = 'filesystem'
|
||||
transport.url = 'http://loops.cy55.de'
|
||||
transport.user = 'loops'
|
||||
ui.web.port = 8081
|
||||
|
||||
The configuration may also be saved to a file -
|
||||
for testing purposes let's use the loops.agent package directory
|
||||
for storage; normally it would be stored in the users home directory.
|
||||
|
||||
>>> import os
|
||||
>>> os.environ['HOME'] = os.path.dirname(core.__file__)
|
||||
|
||||
>>> config.save()
|
||||
|
||||
>>> fn = config.getDefaultConfigFile()
|
||||
>>> fn
|
||||
'....loops.agent.cfg'
|
||||
|
||||
>>> print open(fn).read()
|
||||
crawl[0].directory = 'documents/projects'
|
||||
crawl[0].type = 'filesystem'
|
||||
transport.url = 'http://loops.cy55.de'
|
||||
transport.user = 'loops'
|
||||
ui.web.port = 8081
|
||||
|
||||
Cleaning up up...
|
||||
|
||||
>>> os.unlink(fn)
|
||||
|
||||
|
||||
Scheduling
|
||||
|
@ -185,16 +269,6 @@ Configuration (per install/update job)
|
|||
- package names
|
||||
|
||||
|
||||
Configuration Management
|
||||
========================
|
||||
|
||||
Functionality
|
||||
|
||||
- Storage of configuration parameters
|
||||
- Interface to the browser-based user interface that allows the
|
||||
editing of configuration parameters
|
||||
|
||||
|
||||
Browser-based User Interface
|
||||
============================
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ Management of agent configuration.
|
|||
$Id$
|
||||
"""
|
||||
|
||||
import os
|
||||
from zope.interface import implements
|
||||
from loops.agent.interfaces import IConfigurator
|
||||
|
||||
|
@ -30,21 +31,75 @@ class Configurator(object):
|
|||
|
||||
implements(IConfigurator)
|
||||
|
||||
def loadConfiguration(self):
|
||||
pass
|
||||
def __init__(self, *sections, **kw):
|
||||
for s in sections:
|
||||
setattr(self, s, ConfigSection())
|
||||
self.filename = kw.get('filename')
|
||||
|
||||
def addConfigOption(self, key, value):
|
||||
setattr(self, key, value)
|
||||
def load(self, p=None, filename=None):
|
||||
if p is None:
|
||||
fn = self.getConfigFile(filename)
|
||||
if fn is not None:
|
||||
f = open(fn, 'r')
|
||||
p = f.read()
|
||||
f.close()
|
||||
if p is None:
|
||||
return
|
||||
exec p in self.__dict__
|
||||
|
||||
def getConfigOption(self, key, value):
|
||||
return getattr(self, key, None)
|
||||
def save(self, filename=None):
|
||||
fn = self.getConfigFile(filename)
|
||||
if fn is None:
|
||||
fn = self.getDefaultConfigFile()
|
||||
if fn is not None:
|
||||
f = open(fn, 'w')
|
||||
f.write(repr(self))
|
||||
f.close()
|
||||
|
||||
def __repr__(self):
|
||||
result = []
|
||||
for name, value in self.__dict__.items():
|
||||
if isinstance(value, ConfigSection):
|
||||
value.collect(name, result)
|
||||
return '\n'.join(sorted(result))
|
||||
|
||||
def getConfigFile(self, filename=None):
|
||||
if filename is not None:
|
||||
self.filename = filename
|
||||
if self.filename is None:
|
||||
fn = self.getDefaultConfigFile()
|
||||
if os.path.isfile(fn):
|
||||
self.filename = fn
|
||||
return self.filename
|
||||
|
||||
def getDefaultConfigFile(self):
|
||||
return os.path.join(os.path.expanduser('~'), '.loops.agent.cfg')
|
||||
|
||||
|
||||
conf = Configurator()
|
||||
class ConfigSection(list):
|
||||
|
||||
# this is just for convenience during the development phase,
|
||||
# thus we can retrieve the port easily via ``conf.ui.web.port``
|
||||
conf.addConfigOption('ui', Configurator())
|
||||
conf.ui.addConfigOption('web', Configurator())
|
||||
conf.ui.web.addConfigOption('port', 10095)
|
||||
def __getattr__(self, attr):
|
||||
value = ConfigSection()
|
||||
setattr(self, attr, value)
|
||||
return value
|
||||
|
||||
def __getitem__(self, idx):
|
||||
while idx >= len(self):
|
||||
self.append(ConfigSection())
|
||||
return list.__getitem__(self, idx)
|
||||
|
||||
def setdefault(self, attr, value):
|
||||
if attr not in self.__dict__:
|
||||
setattr(self, attr, value)
|
||||
return value
|
||||
return getattr(self, attr)
|
||||
|
||||
def collect(self, ident, result):
|
||||
for idx, element in enumerate(self):
|
||||
element.collect('%s[%i]' % (ident, idx), result)
|
||||
for name, value in self.__dict__.items():
|
||||
if isinstance(value, ConfigSection):
|
||||
value.collect('%s.%s' % (ident, name), result)
|
||||
elif isinstance(value, (str, int)):
|
||||
result.append('%s.%s = %s' % (ident, name, repr(value)))
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ class Agent(object):
|
|||
implements(IAgent)
|
||||
|
||||
def __init__(self):
|
||||
configurator = self.configurator = Configurator()
|
||||
configurator.loadConfiguration()
|
||||
config = self.config = Configurator('ui', 'crawl', 'transport')
|
||||
config.load()
|
||||
self.scheduler = Scheduler()
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#! /usr/bin/env python
|
||||
#
|
||||
# Run with ``trial2.4 tests.py`` to execute the twisted unit tests.
|
||||
# Run with ``python tests.py`` to execute the doctests.
|
||||
|
|
Loading…
Add table
Reference in a new issue