extending composer and organize.schema to provide basis for tumsm
git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@1845 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
7aad7a6430
commit
242c4a4921
13 changed files with 225 additions and 31 deletions
|
@ -54,7 +54,9 @@ class Template(object):
|
||||||
implements(ITemplate)
|
implements(ITemplate)
|
||||||
|
|
||||||
componentStorage = Jeep
|
componentStorage = Jeep
|
||||||
|
components = None
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.components = self.componentStorage()
|
if self.componentStorage is not None:
|
||||||
|
self.components = self.componentStorage()
|
||||||
|
|
||||||
|
|
|
@ -31,25 +31,25 @@ class Instance(object):
|
||||||
|
|
||||||
implements(IInstance)
|
implements(IInstance)
|
||||||
|
|
||||||
templateStorage = dict
|
templateFactory = dict
|
||||||
templateAttributeName = '__ctc_templates__'
|
templateAttributeName = '__ctc_template__'
|
||||||
|
|
||||||
aspect = 'composer.default'
|
aspect = 'composer.default'
|
||||||
|
|
||||||
def __init__(self, context):
|
def __init__(self, context):
|
||||||
self.context = context
|
self.context = context
|
||||||
self.instances = []
|
|
||||||
|
|
||||||
def setTemplate(self, template):
|
def setTemplate(self, temp):
|
||||||
templates = getattr(self.context,
|
template = getattr(self.context,
|
||||||
self.templateAttributeName, self.templateStorage())
|
self.templateAttributeName,
|
||||||
templates.setdefault(self.aspect, template)
|
self.templateFactory())
|
||||||
setattr(self.context, self.templateAttributeName, templates)
|
template.setdefault(self.aspect, temp)
|
||||||
|
setattr(self.context, self.templateAttributeName, template)
|
||||||
def getTemplate(self):
|
def getTemplate(self):
|
||||||
templates = getattr(self.context, self.templateAttributeName, {})
|
template = getattr(self.context, self.templateAttributeName, {})
|
||||||
return templates.get(self.aspect, None)
|
return template.get(self.aspect, [])
|
||||||
template = property(getTemplate, setTemplate)
|
template = property(getTemplate, setTemplate)
|
||||||
|
|
||||||
def applyTemplate(self, *args, **kw):
|
def applyTemplates(self, *args, **kw):
|
||||||
raise ValueError('To be implemented by subclass')
|
raise ValueError('To be implemented by subclass')
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ class ITemplate(Interface):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
components = Attribute('An ordered sequence of the components this '
|
components = Attribute('An ordered sequence of the components this '
|
||||||
'object is built upon')
|
'object is built upon')
|
||||||
|
|
||||||
|
|
||||||
# instances
|
# instances
|
||||||
|
@ -62,9 +62,9 @@ class IInstance(Interface):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
context = Attribute('Object this instance adapter has been created for')
|
context = Attribute('Object this instance adapter has been created for')
|
||||||
template = Attribute('The template to be used for this instance')
|
template = Attribute('A template to be used for this instance')
|
||||||
aspect = Attribute('A dotted name that helps to store and retrieve the '
|
aspect = Attribute('A dotted name that helps to store and retrieve the '
|
||||||
'template.')
|
'template.')
|
||||||
|
|
||||||
def applyTemplate(*args, **kw):
|
def applyTemplate(*args, **kw):
|
||||||
""" Apply the template using the instance's context. Note that this
|
""" Apply the template using the instance's context. Note that this
|
||||||
|
|
4
composer/schema/browser/__init__.py
Normal file
4
composer/schema/browser/__init__.py
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
"""
|
||||||
|
$Id$
|
||||||
|
"""
|
||||||
|
|
34
composer/schema/browser/base.py
Normal file
34
composer/schema/browser/base.py
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
#
|
||||||
|
# Copyright (c) 2007 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
|
||||||
|
#
|
||||||
|
|
||||||
|
"""
|
||||||
|
Basic browser view classes for composer.schema.
|
||||||
|
|
||||||
|
$Id$
|
||||||
|
"""
|
||||||
|
|
||||||
|
from zope.cachedescriptors.property import Lazy
|
||||||
|
|
||||||
|
from cybertools.composer.instance import Instance
|
||||||
|
|
||||||
|
|
||||||
|
class SchemaView(object):
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def fields(self):
|
||||||
|
return self.context.fields
|
19
composer/schema/browser/configure.zcml
Normal file
19
composer/schema/browser/configure.zcml
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<!-- $Id$ -->
|
||||||
|
|
||||||
|
<configure
|
||||||
|
xmlns="http://namespaces.zope.org/browser"
|
||||||
|
xmlns:zope="http://namespaces.zope.org/zope"
|
||||||
|
i18n_domain="zope">
|
||||||
|
|
||||||
|
<page
|
||||||
|
for="cybertools.composer.schema.interfaces.ISchema"
|
||||||
|
name="index.html"
|
||||||
|
class="cybertools.composer.schema.browser.base.SchemaView"
|
||||||
|
permission="zope.View"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<defaultView
|
||||||
|
name="index.html"
|
||||||
|
for="cybertools.composer.schema.interfaces.ISchema" />
|
||||||
|
|
||||||
|
</configure>
|
|
@ -35,8 +35,15 @@ class Field(Component):
|
||||||
|
|
||||||
def __init__(self, name, title=None, renderFactory=None, **kw):
|
def __init__(self, name, title=None, renderFactory=None, **kw):
|
||||||
assert name
|
assert name
|
||||||
self.name = self.__name__ = name
|
self.__name__ = name
|
||||||
title = title is None and name or title
|
title = title or u''
|
||||||
self.renderFactory = renderFactory # use for rendering field content
|
self.renderFactory = renderFactory # use for rendering field content
|
||||||
super(Field, self).__init__(title, __name__=name, **kw)
|
super(Field, self).__init__(title, __name__=name, **kw)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
return self.__name__
|
||||||
|
|
||||||
|
@property
|
||||||
|
def title(self):
|
||||||
|
return self.title or self.name
|
||||||
|
|
|
@ -38,6 +38,9 @@ class ISchema(ITemplate):
|
||||||
fields = Attribute('The components the schema is built up of. '
|
fields = Attribute('The components the schema is built up of. '
|
||||||
'Should be a sequence of IField objects.')
|
'Should be a sequence of IField objects.')
|
||||||
|
|
||||||
|
manager = Attribute('A manager object that may provide special '
|
||||||
|
'features, e.g. a factory of o')
|
||||||
|
|
||||||
|
|
||||||
class IField(IComponent):
|
class IField(IComponent):
|
||||||
""" May be used for data entry or display.
|
""" May be used for data entry or display.
|
||||||
|
|
|
@ -33,7 +33,12 @@ class Schema(Template):
|
||||||
|
|
||||||
implements(ISchema)
|
implements(ISchema)
|
||||||
|
|
||||||
def __init__(self, *fields):
|
name = u''
|
||||||
|
manager = None
|
||||||
|
|
||||||
|
def __init__(self, *fields, **kw):
|
||||||
|
self.name = kw.get('name', u'')
|
||||||
|
self.manager = kw.get('manager', None)
|
||||||
super(Schema, self).__init__()
|
super(Schema, self).__init__()
|
||||||
for f in fields:
|
for f in fields:
|
||||||
self.components.append(f)
|
self.components.append(f)
|
||||||
|
|
|
@ -128,6 +128,18 @@ class IServiceManager(Interface):
|
||||||
|
|
||||||
services = Attribute('A collection of services managed by this object.')
|
services = Attribute('A collection of services managed by this object.')
|
||||||
|
|
||||||
|
clients = Attribute('A collection of client objects (e.g. persons) '
|
||||||
|
'that have registered or want to register for '
|
||||||
|
'services managed by this service manager.')
|
||||||
|
|
||||||
|
clientSchemas = Attribute('An optional collection of schema objects '
|
||||||
|
'that describe the data fields of the client '
|
||||||
|
'objects.')
|
||||||
|
|
||||||
|
def addClient(client):
|
||||||
|
""" Add the client object given to the collection of clients.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
class IServiceGroup(Interface):
|
class IServiceGroup(Interface):
|
||||||
""" A group of related services or a general service definition,
|
""" A group of related services or a general service definition,
|
||||||
|
@ -183,6 +195,24 @@ class IScheduledService(IService):
|
||||||
duration = Attribute('Time delta between start and end date/time.')
|
duration = Attribute('Time delta between start and end date/time.')
|
||||||
|
|
||||||
|
|
||||||
|
class IClient(Interface):
|
||||||
|
""" An fairly abstract interface for objects to be used as clients
|
||||||
|
for services.
|
||||||
|
"""
|
||||||
|
|
||||||
|
manager = Attribute('The object that cares for this client.')
|
||||||
|
|
||||||
|
|
||||||
|
class IClientFactory(Interface):
|
||||||
|
""" Creates client objects.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __call__(data):
|
||||||
|
""" Creates and returns a client object built from the
|
||||||
|
data set provided.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
class IRegistration(Interface):
|
class IRegistration(Interface):
|
||||||
""" Information about the registration of a client with a service.
|
""" Information about the registration of a client with a service.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -22,9 +22,15 @@ Service management classes.
|
||||||
$Id$
|
$Id$
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from BTrees.OOBTree import OOBTree
|
||||||
|
from zope.cachedescriptors.property import Lazy
|
||||||
|
from zope.component import adapts
|
||||||
from zope.interface import implements
|
from zope.interface import implements
|
||||||
|
from cybertools.composer.interfaces import IInstance
|
||||||
|
from cybertools.util.jeep import Jeep
|
||||||
|
|
||||||
from cybertools.organize.interfaces import IServiceManager
|
from cybertools.organize.interfaces import IServiceManager
|
||||||
|
from cybertools.organize.interfaces import IClient, IClientFactory
|
||||||
from cybertools.organize.interfaces import IService, IScheduledService
|
from cybertools.organize.interfaces import IService, IScheduledService
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,6 +38,30 @@ class ServiceManager(object):
|
||||||
|
|
||||||
implements(IServiceManager)
|
implements(IServiceManager)
|
||||||
|
|
||||||
|
servicesFactory = list
|
||||||
|
clientSchemasFactory = Jeep
|
||||||
|
clientsFactory = OOBTree
|
||||||
|
|
||||||
|
clientNum = 0
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
if self.servicesFactory is not None:
|
||||||
|
self.services = self.servicesFactory()
|
||||||
|
if self.clientSchemasFactory is not None:
|
||||||
|
self.clientSchemas = self.clientSchemasFactory()
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def clients(self):
|
||||||
|
return self.clientsFactory()
|
||||||
|
|
||||||
|
def addClient(self, client):
|
||||||
|
name = self.generateClientName(client)
|
||||||
|
self.clients[name] = client
|
||||||
|
|
||||||
|
def generateClientName(self, client):
|
||||||
|
self.clientNum += 1
|
||||||
|
return '%05i' % self.clientNum
|
||||||
|
|
||||||
|
|
||||||
class Service(object):
|
class Service(object):
|
||||||
|
|
||||||
|
@ -60,6 +90,57 @@ class ScheduledService(Service):
|
||||||
implements(IScheduledService)
|
implements(IScheduledService)
|
||||||
|
|
||||||
|
|
||||||
|
class Client(object):
|
||||||
|
|
||||||
|
implements(IClient)
|
||||||
|
|
||||||
|
def __init__(self, manager):
|
||||||
|
self.manager = manager
|
||||||
|
|
||||||
|
|
||||||
|
class ClientFactory(object):
|
||||||
|
|
||||||
|
implements(IClientFactory)
|
||||||
|
adapts(IServiceManager)
|
||||||
|
|
||||||
|
def __init__(self, context):
|
||||||
|
self.context = context
|
||||||
|
|
||||||
|
def __call__(self):
|
||||||
|
return Client(self.context)
|
||||||
|
|
||||||
|
|
||||||
|
class ClientInstanceAdapter(object):
|
||||||
|
|
||||||
|
implements(IInstance)
|
||||||
|
adapts(IClient)
|
||||||
|
|
||||||
|
baseAspect = 'service.client.'
|
||||||
|
schema = 'default'
|
||||||
|
|
||||||
|
@property
|
||||||
|
def aspect(self):
|
||||||
|
return self.baseAspect + self.schema
|
||||||
|
|
||||||
|
@property
|
||||||
|
def template(self):
|
||||||
|
return self.context.manager.clientSchemas.get(self.schema, None)
|
||||||
|
|
||||||
|
def __init__(self, context):
|
||||||
|
self.context = context
|
||||||
|
|
||||||
|
def applyTemplate(self, data={}, schema='default', **kw):
|
||||||
|
if getattr(self.context, 'attributes', None) is None:
|
||||||
|
self.context.attributes = OOBTree()
|
||||||
|
self.schema = schema
|
||||||
|
template = self.template
|
||||||
|
attributes = self.context.attributes.setdefault(self.aspect, OOBTree())
|
||||||
|
if template is not None:
|
||||||
|
for c in template.components:
|
||||||
|
name = c.name
|
||||||
|
attributes[name] = data.get(name, u'')
|
||||||
|
|
||||||
|
|
||||||
class Registration(object):
|
class Registration(object):
|
||||||
|
|
||||||
def __init__(self, client):
|
def __init__(self, client):
|
||||||
|
|
12
util/jeep.py
12
util/jeep.py
|
@ -31,10 +31,10 @@ class Jeep(object):
|
||||||
_attributes = ('_sequence',)
|
_attributes = ('_sequence',)
|
||||||
|
|
||||||
def __init__(self, seq=[]):
|
def __init__(self, seq=[]):
|
||||||
self._sequence = []
|
sequence = self._sequence = []
|
||||||
for item in seq:
|
for attr, value in seq:
|
||||||
attr, value = item
|
sequence.append(attr)
|
||||||
setattr(self, attr, value)
|
object.__setattr__(self, attr, value)
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
return len(self._sequence)
|
return len(self._sequence)
|
||||||
|
@ -47,11 +47,11 @@ class Jeep(object):
|
||||||
if not attr in self._attributes:
|
if not attr in self._attributes:
|
||||||
if getattr(self, attr, _notfound) is _notfound:
|
if getattr(self, attr, _notfound) is _notfound:
|
||||||
self._sequence.append(attr)
|
self._sequence.append(attr)
|
||||||
object.__setattr__(self, attr, value)
|
super(Jeep, self).__setattr__(attr, value)
|
||||||
|
|
||||||
def __delattr__(self, attr):
|
def __delattr__(self, attr):
|
||||||
del self._sequence[self.index(attr)]
|
del self._sequence[self.index(attr)]
|
||||||
object.__delattr__(self, attr)
|
super(Jeep, self).__delattr__(attr)
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
if type(key) in (int, long):
|
if type(key) in (int, long):
|
||||||
|
|
|
@ -21,26 +21,33 @@ A general purpose (thus 'Jeep') class that provides most of the interfaces
|
||||||
of sequences and dictionaries and in addition allows attribute access to
|
of sequences and dictionaries and in addition allows attribute access to
|
||||||
the dictionary entries.
|
the dictionary entries.
|
||||||
|
|
||||||
|
This is the Zope-based persistent variant of the Jeep class.
|
||||||
|
|
||||||
$Id$
|
$Id$
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from persistent import Persistent
|
||||||
from persistent.list import PersistentList
|
from persistent.list import PersistentList
|
||||||
from BTrees.OOBTree import OOBTree
|
from BTrees.OOBTree import OOBTree
|
||||||
|
from zope.app.container.interfaces import IContainer
|
||||||
|
from zope.interface import implements
|
||||||
|
|
||||||
_notfound = object()
|
_notfound = object()
|
||||||
_nodefault = object()
|
_nodefault = object()
|
||||||
|
|
||||||
|
|
||||||
class Jeep(object):
|
class Jeep(Persistent):
|
||||||
|
|
||||||
|
implements(IContainer)
|
||||||
|
|
||||||
_attributes = ('_sequence', '_mapping')
|
_attributes = ('_sequence', '_mapping')
|
||||||
|
|
||||||
def __init__(self, seq=[]):
|
def __init__(self, seq=[]):
|
||||||
self._sequence = PersistentList()
|
sequence = self._sequence = PersistentList()
|
||||||
self._mapping = OOBTree()
|
mapping = self._mapping = OOBTree()
|
||||||
for item in seq:
|
for attr, value in seq:
|
||||||
attr, value = item
|
sequence.append(attr)
|
||||||
setattr(self, attr, value)
|
mapping[attr] = value
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
return len(self._sequence)
|
return len(self._sequence)
|
||||||
|
@ -60,7 +67,7 @@ class Jeep(object):
|
||||||
|
|
||||||
def __setattr__(self, attr, value):
|
def __setattr__(self, attr, value):
|
||||||
if attr in self._attributes:
|
if attr in self._attributes:
|
||||||
object.__setattr__(self, attr, value)
|
super(Jeep, self).__setattr__(attr, value)
|
||||||
else:
|
else:
|
||||||
if getattr(self, attr, _notfound) is _notfound:
|
if getattr(self, attr, _notfound) is _notfound:
|
||||||
self._sequence.append(attr)
|
self._sequence.append(attr)
|
||||||
|
@ -87,6 +94,8 @@ class Jeep(object):
|
||||||
def __contains__(self, key):
|
def __contains__(self, key):
|
||||||
return getattr(self, key, _notfound) is not _notfound
|
return getattr(self, key, _notfound) is not _notfound
|
||||||
|
|
||||||
|
has_key = __contains__
|
||||||
|
|
||||||
def keys(self):
|
def keys(self):
|
||||||
return [key for key in self._sequence]
|
return [key for key in self._sequence]
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue