[Zope-CVS] CVS: Products/Ape/lib/apelib/zope2 - __init__.py:1.1 basemapper.py:1.1 classifier.py:1.1 fsmapper.py:1.1 ofsserial.py:1.1 scripts.py:1.1 security.py:1.1 sqlmapper.py:1.1
Shane Hathaway
shane@zope.com
Wed, 9 Apr 2003 23:10:00 -0400
Update of /cvs-repository/Products/Ape/lib/apelib/zope2
In directory cvs.zope.org:/tmp/cvs-serv32010/lib/apelib/zope2
Added Files:
__init__.py basemapper.py classifier.py fsmapper.py
ofsserial.py scripts.py security.py sqlmapper.py
Log Message:
Moved apelib into a "lib" subdirectory. This simplified the
Python hacking required to make apelib a top-level package. Sorry
about the flood of checkins, but CVS makes a move like this quite painful.
=== Added File Products/Ape/lib/apelib/zope2/__init__.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Zope 2 support.
$Id: __init__.py,v 1.1 2003/04/10 03:09:58 shane Exp $
"""
=== Added File Products/Ape/lib/apelib/zope2/basemapper.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Zope 2 apelib mappers.
$Id: basemapper.py,v 1.1 2003/04/10 03:09:58 shane Exp $
"""
from apelib.core import gateways, mapper, serializers
from apelib.zodb3 import serializers as zodb3serializers
from apelib.zope2 import classifier, ofsserial, scripts, security
def createZope2Mapper(app_key, stored_keychains):
"""Returns a mapper tree for Zope 2 objects (without any gateways)."""
# Create and configure the root mapper
root_mapper = mapper.Mapper()
cfr = classifier.MetaTypeClassifier()
root_mapper.setClassifier(cfr)
cs = serializers.CompositeSerializer('Persistence', 'PersistentMapping')
serializer = zodb3serializers.FixedPersistentMapping()
serializer.add('Application', (app_key,), ('OFS.Application.Application',))
cs.addSerializer('items', serializer)
cs.addSerializer('roll_call', zodb3serializers.RollCall())
root_mapper.setSerializer(cs)
root_mapper.setGateway(gateways.CompositeGateway()) # No storage necessary
# Prepare some common names
if stored_keychains:
folder_items_serializer = ofsserial.FolderItemsByKeychain()
else:
folder_items_serializer = ofsserial.FolderItems()
# abstract base mapper
m = root_mapper.addSubMapper('base')
cs = serializers.CompositeSerializer(None, None)
m.setSerializer(cs)
cs.addSerializer('id', ofsserial.IdAttribute())
cs.addSerializer('modtime', zodb3serializers.ModTimeAttribute())
cs.addSerializer('security', security.SecurityAttributes())
cs.addSerializer('remainder', zodb3serializers.RemainingState(), final=1)
base = cs
# abstract mapper with properties
m = root_mapper.addSubMapper('base_p')
cs = serializers.CompositeSerializer(None, None, base)
m.setSerializer(cs)
cs.addSerializer('properties', ofsserial.OFSProperties())
base_p = cs
# folder mapper
m = root_mapper.addSubMapper('OFS.Folder.Folder')
cs = serializers.CompositeSerializer('OFS.Folder', 'Folder', base_p)
m.setSerializer(cs)
cs.addSerializer('items', folder_items_serializer)
cfr.registerDefaultLoader('Folder', 'OFS.Folder.Folder', 1)
# file mapper
m = root_mapper.addSubMapper('OFS.Image.File')
cs = serializers.CompositeSerializer('OFS.Image', 'File', base_p)
m.setSerializer(cs)
cs.addSerializer('data', ofsserial.FilePData())
cfr.registerDefaultLoader('File', 'OFS.Image.File', 0)
cfr.setFlags('OFS.Image.File', cfr.CONTENT_TYPE_ATTR)
# image mapper
m = root_mapper.addSubMapper('OFS.Image.Image')
cs = serializers.CompositeSerializer('OFS.Image', 'Image', base_p)
m.setSerializer(cs)
cs.addSerializer('data', ofsserial.FilePData())
cfr.register('Image', 'OFS.Image.Image', (
'.gif', '.jpg', '.jpeg', '.png'))
cfr.setFlags('OFS.Image.Image', cfr.CONTENT_TYPE_ATTR)
# page template mapper
m = root_mapper.addSubMapper('ZopePageTemplate') # abbreviated name
cs = serializers.CompositeSerializer(
'Products.PageTemplates.ZopePageTemplate', 'ZopePageTemplate', base_p)
m.setSerializer(cs)
cs.addSerializer('text', serializers.StringDataAttribute('_text'))
cfr.register('Page Template', 'ZopePageTemplate', (
'.html', '.htm', '.zpt', '.pt'))
# dtml method mapper
m = root_mapper.addSubMapper('OFS.DTMLMethod.DTMLMethod')
cs = serializers.CompositeSerializer('OFS.DTMLMethod', 'DTMLMethod', base)
m.setSerializer(cs)
cs.addSerializer('text', serializers.StringDataAttribute('raw'))
cfr.register('DTML Method', 'OFS.DTMLMethod.DTMLMethod', ('.dtml',))
# dtml document mapper
m = root_mapper.addSubMapper('OFS.DTMLDocument.DTMLDocument')
cs = serializers.CompositeSerializer(
'OFS.DTMLDocument', 'DTMLDocument', base_p)
m.setSerializer(cs)
cs.addSerializer('text', serializers.StringDataAttribute('raw'))
cfr.register('DTML Document', 'OFS.DTMLDocument.DTMLDocument')
# zsql mapper
m = root_mapper.addSubMapper('Products.ZSQLMethods.SQL.SQL')
cs = serializers.CompositeSerializer(
'Products.ZSQLMethods.SQL', 'SQL', base)
m.setSerializer(cs)
cs.addSerializer('properties',
scripts.ZSQLMethodPropertiesSerializer(), 1)
cs.addSerializer('text', scripts.ZSQLMethodSerializer())
cfr.register('Z SQL Method', 'Products.ZSQLMethods.SQL.SQL', (
'.sql', ))
# python script mapper
m = root_mapper.addSubMapper('PythonScript') # abbreviated name
cs = serializers.CompositeSerializer(
'Products.PythonScripts.PythonScript', 'PythonScript', base)
m.setSerializer(cs)
cs.addSerializer('body', scripts.PythonScriptSerializer())
cfr.register('Script (Python)', 'PythonScript', ('.py', ))
# user folder mapper
m = root_mapper.addSubMapper('AccessControl.User.UserFolder')
cs = serializers.CompositeSerializer(
'AccessControl.User', 'UserFolder', base)
m.setSerializer(cs)
cs.addSerializer('data', security.UserFolderSerializer())
cfr.register('User Folder', 'AccessControl.User.UserFolder')
# anyfolder mapper
m = root_mapper.addSubMapper('anyfolder')
cs = serializers.AnyObjectSerializer(base)
m.setSerializer(cs)
cs.addSerializer('properties', serializers.OptionalSerializer(
ofsserial.OFSProperties(), []), 1)
cs.addSerializer('items', folder_items_serializer)
cfr.registerDefaultStorage('(folderish object)', 'anyfolder', 1)
# anyfile mapper
m = root_mapper.addSubMapper('anyfile')
cs = serializers.AnyObjectSerializer(base)
m.setSerializer(cs)
cs.addSerializer('properties', serializers.OptionalSerializer(
ofsserial.OFSProperties(), []), 1)
cfr.registerDefaultStorage('(fileish object)', 'anyfile', 0)
# application mapper
m = root_mapper.addSubMapper('OFS.Application.Application')
cs = serializers.CompositeSerializer(
'OFS.Application', 'Application', base_p)
m.setSerializer(cs)
cs.removeSerializer('id')
cs.addSerializer('items', folder_items_serializer)
cfr.registerKey(
'Application', 'OFS.Application.Application', app_key)
# Other stuff
cfr.register('CMF Skins Tool', 'anyfile') # XXX workaround
cfr.register('Control Panel', 'anyfile') # XXX workaround
return root_mapper
=== Added File Products/Ape/lib/apelib/zope2/classifier.py ===
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Zope 2 meta_type based classification.
$Id: classifier.py,v 1.1 2003/04/10 03:09:58 shane Exp $
"""
from mimetypes import guess_extension
from Acquisition import aq_base
from OFS.ObjectManager import ObjectManager
from apelib.core.interfaces import IClassifier
from apelib.core.exceptions import DeserializationError
# guess_extension() is useful but it's unoptimized and sometimes
# chooses strange extensions. fixed_extensions does nothing other than
# suggest a filename extension given a content type. It contains
# some better defaults.
fixed_extensions = {
'text/plain': '.txt',
'text/html': '.html',
'image/png': '.png',
'image/jpg': '.jpg',
'image/jpeg': '.jpg',
'image/gif': '.gif',
'application/octet-stream': '', # No extension--too overloaded.
}
class MetaTypeClassifier:
"""A classifier based on meta_type attributes.
"""
__implements__ = IClassifier
# flag values (constant)
CONTENT_TYPE_ATTR = 1
def __init__(self, gw=None):
self.gw = gw
self.key_to_res = {}
self.ext_to_mt = {}
self.mt_to_ext = {}
self.fmt_to_mt = {}
self.mt_to_mapper = {}
self.flags = {}
def setGateway(self, gw):
self.gw = gw
def register(self, meta_type, mapper_name, extensions=()):
"""Registers a mapper to handle a Zope meta_type."""
for ext in extensions:
if not ext.startswith('.'):
ext = '.' + ext
ext = ext.lower()
self.ext_to_mt[ext] = meta_type
if extensions:
self.mt_to_ext[meta_type] = extensions[0]
self.mt_to_mapper[meta_type] = mapper_name
def registerKey(self, meta_type, mapper_name, key):
"""Registers a mapper to handle a specific path.
For example, the application object mapper usually handles
the path '/'.
"""
self.key_to_res[key] = ({'meta_type': meta_type}, mapper_name)
def registerDefaultLoader(self, meta_type, mapper_name, isdir):
"""Registers a mapper to load unknown files or directories."""
if isdir:
ext = '<directory>'
else:
ext = '<file>'
self.ext_to_mt[ext] = meta_type
self.mt_to_mapper[meta_type] = mapper_name
def registerDefaultStorage(self, meta_type, mapper_name, folderish):
"""Registers a mapper to store unknown objects."""
if folderish:
fmt = 'folder'
else:
fmt = 'file'
self.fmt_to_mt[fmt] = meta_type
self.mt_to_mapper[meta_type] = mapper_name
def setFlags(self, mapper_name, flags):
"""Sets flags associated with a certain mapper."""
self.flags[mapper_name] = flags
def classifyObject(self, value, keychain):
"""Chooses a mapper and classification for storing an object."""
res = self.key_to_res.get(keychain[-1])
if res is not None:
return res
mt = value.meta_type
mapper_name = self.mt_to_mapper.get(mt)
if mapper_name is None:
folderish = isinstance(value, ObjectManager)
# Store in a default format
if folderish:
fmt = 'folder'
else:
fmt = 'file'
mt = self.fmt_to_mt.get(fmt)
if mt is None:
raise SerializationError(
'No classification known for %s' % repr(keychain))
mapper_name = self.mt_to_mapper.get(mt)
if mapper_name is None:
raise DeserializationError(
'No mapper known for meta_type %s' % repr(mt))
klass = value.__class__
ci = '%s:%s' % (klass.__module__, klass.__name__)
classification = {'meta_type': mt, 'class_name': ci}
flags = self.flags.get(mapper_name, 0)
if flags and (flags & MetaTypeClassifier.CONTENT_TYPE_ATTR):
ct = str(getattr(aq_base(value), 'content_type', None))
if ct:
ext = fixed_extensions.get(ct)
if ext is None:
ext = guess_extension(ct)
else:
ext = self.mt_to_ext.get(mt)
if ext:
classification['extension'] = ext
return classification, mapper_name
def classifyState(self, event):
"""Chooses a mapper and classification for loading an object."""
keychain = event.getKeychain()
res = self.key_to_res.get(keychain[-1])
if res is not None:
return res
classification, serial = self.gw.load(event)
mt = classification.get('meta_type')
if mt is None:
t = classification.get('node_type')
if t == 'd':
# Directory
mt = self.ext_to_mt.get('<directory>', 'Folder')
elif t == 'f':
# File
ext = classification.get('extension')
if ext:
if not ext.startswith('.'):
ext = '.' + ext
mt = self.ext_to_mt.get(ext.lower())
if not mt:
mt = self.ext_to_mt.get('<file>', 'File')
else:
raise DeserializationError(
'No classification known for %s' % repr(keychain))
assert mt is not None
classification['meta_type'] = mt
mapper_name = self.mt_to_mapper.get(mt)
if mapper_name is None:
raise DeserializationError(
'No mapper known for meta_type %s' % repr(mt))
return classification, mapper_name
def store(self, event, classification):
"""Stores the classification of an object."""
return self.gw.store(event, classification)
=== Added File Products/Ape/lib/apelib/zope2/fsmapper.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""A basic mapping from Zope 2 objects to the filesystem.
$Id: fsmapper.py,v 1.1 2003/04/10 03:09:58 shane Exp $
"""
from apelib.core import gateways, keygen
from apelib.fs \
import classification, connection, properties, security, structure
from apelib.zope2 import basemapper
def createMapper(basepath, volatile=1, **kw):
"""Object mapper factory.
Usage in database configuration file:
factory=apelib.zope2.fsmapper.createMapper
"""
# The "volatile" argument is ignored.
conn = connection.FSConnection(basepath, **kw)
root_mapper = basemapper.createZope2Mapper('/', 0)
root_mapper.getClassifier().setGateway(
classification.FSClassificationSection(conn))
root_mapper.setKeychainGenerator(keygen.PathKeychainGenerator())
file_binary_data = structure.FSFileData(conn, text=0)
file_text_data = structure.FSFileData(conn, text=1)
# abstract base gateway
g = gateways.CompositeGateway()
g.addGateway('id', structure.FSAutoId())
g.addGateway('modtime', structure.FSModTime(conn))
g.addGateway('remainder', properties.FSSectionData(conn, 'remainder'))
g.addGateway('security', security.FSSecurityAttributes(conn))
root_mapper.getSubMapper('base').setGateway(g)
base = g
# abstract base gateway with properties
g = gateways.CompositeGateway(base)
g.addGateway('properties', properties.FSProperties(conn))
root_mapper.getSubMapper('base_p').setGateway(g)
base_p = g
# folder gateway
g = gateways.CompositeGateway(base_p)
g.addGateway('items', structure.FSDirectoryItems(conn))
root_mapper.getSubMapper('OFS.Folder.Folder').setGateway(g)
# page template gateway
g = gateways.CompositeGateway(base_p)
g.addGateway('text', file_text_data)
root_mapper.getSubMapper('ZopePageTemplate').setGateway(g)
# dtml method gateway
g = gateways.CompositeGateway(base)
g.addGateway('text', file_text_data)
root_mapper.getSubMapper('OFS.DTMLMethod.DTMLMethod').setGateway(g)
# dtml document gateway
g = gateways.CompositeGateway(base_p)
g.addGateway('text', file_text_data)
root_mapper.getSubMapper('OFS.DTMLDocument.DTMLDocument').setGateway(g)
# zsqlmethod mapper
g = gateways.CompositeGateway(base)
g.addGateway('text', file_text_data)
g.addGateway('properties', properties.FSProperties(
conn, 'ZSQL Properties'), 1)
root_mapper.getSubMapper('Products.ZSQLMethods.SQL.SQL').setGateway(g)
# python script mapper
g = gateways.CompositeGateway(base)
g.addGateway('body', file_text_data)
root_mapper.getSubMapper('PythonScript').setGateway(g)
# file gateway
g = gateways.CompositeGateway(base_p)
g.addGateway('data', file_binary_data)
root_mapper.getSubMapper('OFS.Image.File').setGateway(g)
# image gateway is identical
root_mapper.getSubMapper('OFS.Image.Image').setGateway(g)
# user folder gateway
g = gateways.CompositeGateway(base)
g.addGateway('data', security.FSUserList(conn))
root_mapper.getSubMapper('AccessControl.User.UserFolder').setGateway(g)
# anyfolder object gateway
g = gateways.CompositeGateway(base_p)
g.addGateway('items', structure.FSDirectoryItems(conn))
root_mapper.getSubMapper('anyfolder').setGateway(g)
# anyfile object gateway
g = gateways.CompositeGateway(base_p)
g.addGateway('remainder', file_binary_data, 1)
root_mapper.getSubMapper('anyfile').setGateway(g)
# application gateway
g = gateways.CompositeGateway(base_p)
g.removeGateway('id')
g.addGateway('items', structure.FSDirectoryItems(conn))
root_mapper.getSubMapper('OFS.Application.Application').setGateway(g)
root_mapper.checkConfiguration()
return root_mapper, [conn]
=== Added File Products/Ape/lib/apelib/zope2/ofsserial.py ===
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Serializers for OFSP (object file system product) objects
$Id: ofsserial.py,v 1.1 2003/04/10 03:09:58 shane Exp $
"""
from cPickle import dumps, loads
from types import DictType, StringType
from Acquisition import aq_base
from OFS.SimpleItem import Item_w__name__
from OFS.ObjectManager import ObjectManager
from OFS.Image import File
from OFS.PropertyManager import PropertyManager
from apelib.core.interfaces import ISerializer
from apelib.core.schemas import FieldSchema, RowSequenceSchema
from apelib.core.exceptions import SerializationError
string_repr_types = {
# Properties that are safe to render as strings for storage.
# Other kinds of properties get pickled.
'string': 1,
'float': 1,
'int': 1,
'long': 1,
'string': 1,
'date': 1,
'date_international': 1,
'text': 1,
'boolean': 1,
}
class FilePData:
"""Serializer of the 'data' attribute of OFS.File and OFS.Image"""
__implements__ = ISerializer
schema = FieldSchema('data', 'string')
def getSchema(self):
return self.schema
def canSerialize(self, object):
return isinstance(object, File)
def serialize(self, object, event):
event.notifySerialized('data', object.data, 1)
event.ignoreAttribute('size')
event.ignoreAttribute('width')
event.ignoreAttribute('height')
return str(object.data)
def deserialize(self, object, event, state):
data, size = object._read_data(state)
if not object.__dict__.get('content_type'):
# Guess the content type.
content_type = object._get_content_type(
state, data, object.__name__)
else:
# The properties serializer is authoritative. Defer to it.
content_type = None
object.update_data(data, content_type, size)
event.notifyDeserialized('data', object.data)
class FolderItems:
"""Serializer for the items in an ObjectManager.
This version does not store keychains, but instead assumes they
can be computed."""
__implements__ = ISerializer
schema = RowSequenceSchema()
schema.addField('id', 'string', 1)
def getSchema(self):
return self.schema
def canSerialize(self, object):
return isinstance(object, ObjectManager)
def serialize(self, object, event):
assert isinstance(object, ObjectManager), repr(object)
state = []
event.ignoreAttribute('_objects')
mps = getattr(object, '_mount_points', None)
for id, subob in object.objectItems():
if mps and mps.has_key(id):
# Store the mount point rather than the mounted object.
subob = mps[id]
base = aq_base(subob)
keychain = event.identifyObject(base)
expected = event.makeKeychain(id, 0)
if keychain is not None and keychain != expected:
raise SerializationError(
"Subobject %s has unexpected keychain, %s. Expected %s." %
(repr(base), repr(keychain), repr(expected)))
keychain = expected
event.notifySerializedRef(id, base, 1, keychain)
state.append((id,))
event.ignoreAttribute('_use_fixed_oids_')
# Add a marker that tells the folder it has to move/rename
# in a special way. The _setOb patch sees this attribute.
object._use_fixed_oids_ = 1
return state
def deserialize(self, object, event, state):
assert isinstance(object, ObjectManager)
object._use_fixed_oids_ = 1
for (id,) in state:
keychain = event.makeKeychain(id, 0)
subob = event.dereference(id, keychain)
setattr(object, id, subob)
object._objects += ({'id': id, 'meta_type':
subob.__class__.meta_type},)
class FolderItemsByKeychain:
""" """
__implements__ = ISerializer
schema = RowSequenceSchema()
schema.addField('id', 'string', 1)
schema.addField('keychain', 'keychain')
def getSchema(self):
return self.schema
def canSerialize(self, object):
return isinstance(object, ObjectManager)
def serialize(self, object, event):
assert isinstance(object, ObjectManager), repr(object)
state = []
event.ignoreAttribute('_objects')
mps = getattr(object, '_mount_points', None)
for id, subob in object.objectItems():
if mps and mps.has_key(id):
# Store the mount point rather than the mounted object.
subob = mps[id]
base = aq_base(subob)
keychain = event.identifyObject(base)
if keychain is None:
keychain = event.makeKeychain(id, 1)
event.notifySerializedRef(id, base, 1, keychain)
state.append((id, keychain))
return state
def deserialize(self, object, event, state):
assert isinstance(object, ObjectManager)
for (id, keychain) in state:
subob = event.dereference(id, keychain)
setattr(object, id, subob)
object._objects += ({'id': id, 'meta_type':
subob.__class__.meta_type},)
class IdAttribute:
"""Zope 2 id attribute."""
__implements__ = ISerializer
schema = FieldSchema('id', 'string')
def getSchema(self):
return self.schema
def canSerialize(self, object):
return 1
def getAttrNameFor(self, object):
if isinstance(object, Item_w__name__):
return '__name__'
else:
return 'id'
def serialize(self, object, event):
attrname = self.getAttrNameFor(object)
id = getattr(object, attrname)
assert id, 'ID of %r is %r' % (object, id)
event.notifySerialized(attrname, id, 1)
return id
def deserialize(self, object, event, state):
attrname = self.getAttrNameFor(object)
setattr(object, attrname, state)
event.notifyDeserialized(attrname, state)
class OFSProperties:
"""Serializer for OFS.PropertyManager properties."""
__implements__ = ISerializer
schema = RowSequenceSchema()
schema.addField('id', 'string', 1)
schema.addField('type', 'string')
schema.addField('data', 'string')
def getSchema(self):
return self.schema
def canSerialize(self, object):
return isinstance(object, PropertyManager)
def serialize(self, object, event):
res = []
assert isinstance(object, PropertyManager), repr(object)
assert object._properties is object._propertyMap()
event.ignoreAttribute('_properties')
for p in object._properties:
name = p['id']
t = p['type']
event.ignoreAttribute(name)
data = object.getProperty(name)
if t == 'lines':
v = '\n'.join(data)
elif string_repr_types.get(t):
v = str(data)
else:
# Pickle the value and any extra info about the property.
# Extra info is present in select and multi-select properties.
d = p.copy()
del d['id']
del d['type']
if d.has_key('mode'):
del d['mode']
d['value'] = data
v = dumps(d)
res.append((name, t, v))
return res
def deserialize(self, object, event, state):
assert isinstance(object, PropertyManager)
assert object._properties is object._propertyMap()
if not state:
# No stored properties. Revert the object to its
# class-defined property schema.
if object.__dict__.has_key('_properties'):
del object._properties
return
old_props = object.propdict()
new_props = {}
for id, t, v in state:
p = old_props.get(id)
if p is None:
p = {'mode': 'wd'}
else:
p = p.copy()
p['id'] = id
p['type'] = t
if v and not string_repr_types.get(t) and t != 'lines':
# v is a pickle.
# Check the pickle for extra property info.
d = loads(v)
if isinstance(d, DictType):
del d['value']
if d:
# The data is stored with extra property info.
p.update(d)
new_props[id] = p
if old_props != new_props:
object._properties = tuple(new_props.values())
for id, t, v in state:
if t == 'lines':
data = v.split('\n')
elif string_repr_types.get(t):
data = str(v)
elif v:
d = loads(v)
if isinstance(d, DictType):
# The data is stored with extra property info.
data = d['value']
else:
data = d
else:
# Fall back to a default.
data = ''
object._updateProperty(id, data)
=== Added File Products/Ape/lib/apelib/zope2/scripts.py ===
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Zope 2 script serialization
$Id: scripts.py,v 1.1 2003/04/10 03:09:58 shane Exp $
"""
import re
from types import StringType
from Products.PythonScripts.PythonScript import PythonScript
from Products.ZSQLMethods.SQL import SQL, SQLConnectionIDs
from Shared.DC.ZRDB.Aqueduct import parse
try:
from IOBTree import Bucket
except ImportError:
Bucket = lambda: {}
from apelib.core.interfaces import ISerializer
from apelib.core.schemas import FieldSchema, RowSequenceSchema
class PythonScriptSerializer:
"""Serializer for PythonScripts.
PythonScriptSerializer serializes using the same representation
as FTP or WebDAV. All computable attributes like compiled code
are dropped.
"""
__implements__ = ISerializer
schema = FieldSchema('data', 'string')
def getSchema(self):
return self.schema
def canSerialize(self, object):
return isinstance(object, PythonScript)
def serialize(self, object, event):
assert isinstance(object, PythonScript)
data = object.read()
assert isinstance(data, StringType)
event.ignoreAttributes((
'title', '_params', '_body', '_bind_names',
'warnings', 'errors', '_code', 'Python_magic',
'Script_magic', 'func_defaults', 'func_code',
'co_varnames', 'co_argcount',
))
return data
def deserialize(self, object, event, state):
assert isinstance(state, StringType)
assert isinstance(object, PythonScript)
object.write(state)
object._makeFunction()
class ZSQLMethodSerializer:
"""Serializer for ZSQLMethods.
ZSQLMethodSerializer serializes using the same representation
as FTP or WebDAV. All computable attributes like compiled code
are dropped.
"""
__implements__ = ISerializer
schema = FieldSchema('data', 'string')
params_re = re.compile(r'\s*<params>(.*)</params>\s*\n', re.I | re.S)
def getSchema(self):
return self.schema
def canSerialize(self, object):
return isinstance(object, SQL)
def serialize(self, object, event):
data = object.document_src()
event.ignoreAttributes(('_arg', 'template', 'arguments_src', 'src'))
return data
def deserialize(self, object, event, state):
assert isinstance(state, StringType)
assert isinstance(object, SQL)
body = state
m = self.params_re.match(body)
if m:
object.arguments_src = m.group(1)
body = body[m.end():]
else:
object.arguments_src = ''
object._arg = parse(object.arguments_src)
object.src = body
object.template = object.template_class(body)
object.template.cook()
object._v_cache = ({}, Bucket())
if not hasattr(object, 'connection_id'):
object.connection_id = ''
class ZSQLMethodPropertiesSerializer:
__implements__ = ISerializer
schema = RowSequenceSchema()
schema.addField('id', 'string', 1)
schema.addField('type', 'string')
schema.addField('data', 'string')
attributes = {
'title': str,
'connection_id': str,
'max_rows_': int,
'max_cache_': int,
'cache_time': int,
'class_name_': str,
'class_file_': str,
'zclass': str, # XXX, what's that
'allow_simple_one_argument_traversal': int,
'connection_hook': str,
}
def getSchema(self):
return self.schema
def canSerialize(self, object):
return isinstance(object, SQL)
def serialize(self, object, event):
assert isinstance(object, SQL)
res = []
for attribute, factory in self.attributes.items():
if not hasattr(object, attribute):
continue
value = getattr(object, attribute)
t = factory.__name__
if value is None:
if factory in (int, long):
value = 0
else:
value = ''
value = str(value)
event.notifySerialized(attribute, value, 1)
res.append((attribute, t, value))
event.ignoreAttribute('_col')
return res
def deserialize(self, object, event, state):
assert isinstance(object, SQL)
for attribute, t, value in state:
factory = self.attributes.get(attribute)
if factory is None:
continue
value = factory(value)
setattr(object, attribute, value)
event.notifyDeserialized(attribute, value)
if not hasattr(object, 'connection_id'):
object.connection_id = ''
=== Added File Products/Ape/lib/apelib/zope2/security.py ===
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Zope 2 security information serializers.
$Id: security.py,v 1.1 2003/04/10 03:09:58 shane Exp $
"""
from types import TupleType
from Persistence import PersistentMapping
from AccessControl.User import User, UserFolder
from AccessControl.Permission import pname
import Products
from apelib.core.interfaces import ISerializer
from apelib.core.schemas import RowSequenceSchema
_permission_dict_cache = None
def getPermissionDict():
"""Returns a dictionary mapping permission attribute name to permission.
Does not discover permissions defined in ZClass products, since that
would require access to the Zope application in the database.
"""
global _permission_dict_cache
if _permission_dict_cache is not None:
return _permission_dict_cache
res = {}
for item in Products.__ac_permissions__:
p = item[0]
attr = pname(p)
res[attr] = p
_permission_dict_cache = res
return res
## Declaration types:
##
## executable owner
## "executable-owner", "", "", path/to/userfolder/username
## local roles
## "local-role", role_name, "", username
## user-defined roles
## "define-role", role_name, "", ""
## proxy roles
## "proxy-role", role_name, "", ""
## permission mapping
## "permission-role", role_name, permission_name, ""
## "permission-no-acquire", "", permission_name, ""
STANDARD_ROLES = {
'Anonymous': 1,
'Authenticated': 1,
'Manager': 1,
'Owner': 1,
}
class SecurityAttributes:
"""Zope 2 security attribute serializer."""
__implements__ = ISerializer
schema = RowSequenceSchema()
schema.addField('declaration_type', 'string')
schema.addField('role', 'string')
schema.addField('permission', 'string')
schema.addField('username', 'string')
def getSchema(self):
return self.schema
def canSerialize(self, obj):
return 1
def serialize(self, obj, event):
res = []
eo = getattr(obj, '_owner', None)
if eo is not None:
event.ignoreAttribute('_owner')
path, username = eo
if '/' in username:
raise ValueError, '/ not allowed in user names'
s = '%s/%s' % ('/'.join(path), username)
res.append(('executable-owner', '', '', s))
roles = getattr(obj, '__ac_roles__', None)
if roles is not None:
event.ignoreAttribute('__ac_roles__')
for role in roles:
if not STANDARD_ROLES.has_key(role):
res.append(('define-role', role, '', ''))
local_roles = getattr(obj, '__ac_local_roles__', None)
if local_roles is not None:
event.ignoreAttribute('__ac_local_roles__')
for username, roles in local_roles.items():
for role in roles:
res.append(('local-role', role, '', username))
proxy_roles = getattr(obj, '_proxy_roles', None)
if proxy_roles is not None:
event.ignoreAttribute('_proxy_roles')
for role in proxy_roles:
res.append(('proxy-role', role, '', ''))
p_dict = None
for attr, value in obj.__dict__.items():
if attr.endswith('_Permission') and attr.startswith('_'):
if p_dict is None:
p_dict = getPermissionDict()
p = p_dict.get(attr)
if p is not None:
event.ignoreAttribute(attr)
for role in value:
res.append(('permission-role', role, p, ''))
# List means acquired, tuple means not acquired.
if isinstance(role, TupleType):
res.append(('permission-no-acquire', '', p, ''))
return res
def deserialize(self, obj, event, state):
local_roles = {} # { username -> [role,] }
defined_roles = [] # [role,]
proxy_roles = [] # [role,]
permission_roles = {} # { permission -> [role,] }
permission_acquired = {} # { permission -> 0 or 1 }
for decl_type, role, permission, username in state:
if decl_type == 'executable-owner':
assert not role
assert not permission
assert username
pos = username.rfind('/')
if pos < 0:
# Default to the root folder
ufolder = ['acl_users']
uname = username
else:
ufolder = list(username[:pos].split('/'))
uname = username[pos + 1:]
assert ufolder
assert uname
obj._owner = (ufolder, uname)
elif decl_type == 'local-role':
assert role
assert not permission
assert username
r = local_roles.get(username)
if r is None:
r = []
local_roles[username] = r
r.append(role)
elif decl_type == 'define-role':
assert role
assert not permission
assert not username
defined_roles.append(role)
elif decl_type == 'proxy-role':
assert role
assert not permission
assert not username
proxy_roles.append(role)
elif decl_type == 'permission-role':
assert role
assert permission
assert not username
r = permission_roles.get(permission)
if r is None:
r = []
permission_roles[permission] = r
r.append(role)
if not permission_acquired.has_key(permission):
permission_acquired[permission] = 1
elif decl_type == 'permission-no-acquire':
assert not role
assert permission
assert not username
permission_acquired[permission] = 0
else:
raise ValueError, (
'declaration_type %s unknown' % repr(decl_type))
if local_roles:
obj.__ac_local_roles__ = local_roles
if defined_roles:
obj.__ac_roles__ = defined_roles
if proxy_roles:
obj._proxy_roles = proxy_roles
for p, acquired in permission_acquired.items():
roles = permission_roles.get(p)
if not acquired:
roles = tuple(roles)
setattr(obj, pname(p), roles)
class UserFolderSerializer:
"""Serializer for a user folder.
This version lets the application keep a list of all users in RAM.
"""
__implements__ = ISerializer
schema = RowSequenceSchema()
schema.addField('id', 'string', 1)
schema.addField('password', 'string')
schema.addField('roles', 'string:list')
schema.addField('domains', 'string:list')
def getSchema(self):
return self.schema
def canSerialize(self, object):
return isinstance(object, UserFolder)
def serialize(self, object, event):
assert isinstance(object, UserFolder), repr(object)
state = []
event.ignoreAttribute('data')
for id, user in object.data.items():
assert isinstance(user, User), repr(user)
assert len(user.__dict__.keys()) == 4, user.__dict__.keys()
state.append((id, user.__,
tuple(user.roles), tuple(user.domains)))
event.notifySerialized(id, user, 0)
event.addUnmanagedPersistentObjects([object.data])
event.addUnmanagedPersistentObjects(object.data.values())
return state
def deserialize(self, object, event, state):
assert isinstance(object, UserFolder)
object.data = PersistentMapping()
for id, password, roles, domains in state:
user = User(id, password, roles, domains)
object.data[id] = user
event.notifyDeserialized(id, user)
event.addUnmanagedPersistentObjects([object.data])
event.addUnmanagedPersistentObjects(object.data.values())
=== Added File Products/Ape/lib/apelib/zope2/sqlmapper.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""A basic mapping from Zope 2 objects to a Postgres database.
$Id: sqlmapper.py,v 1.1 2003/04/10 03:09:58 shane Exp $
"""
from apelib.core import gateways
from apelib.sql import classification, keygen, properties, security, structure
from apelib.zope2 import basemapper
def createSQLMapper(conn):
"""Object mapper factory, with extra return arg for testing purposes
"""
root_mapper = basemapper.createZope2Mapper(0, 1)
root_mapper.setKeychainGenerator(keygen.SQLKeychainGenerator(conn))
folder_items_gw = structure.SQLFolderItems(conn)
item_id_gw = structure.SQLItemId(conn)
remainder_gw = structure.SQLRemainder(conn)
file_data_gw = structure.SQLObjectData(conn)
modtime_gw = structure.SQLModTime(conn)
properties_gw = properties.SQLProperties(conn)
security_gw = security.SQLSecurityAttributes(conn)
userlist_gw = security.SQLUserList(conn)
classification_gw = classification.SQLClassification(conn)
keychain_gen = keygen.SQLKeychainGenerator(conn)
gws = (
folder_items_gw,
remainder_gw,
item_id_gw,
file_data_gw,
modtime_gw,
properties_gw,
security_gw,
userlist_gw,
classification_gw,
keychain_gen,
)
root_mapper.getClassifier().setGateway(classification_gw)
# abstract base gateway
g = gateways.CompositeGateway()
g.addGateway('id', item_id_gw)
g.addGateway('modtime', modtime_gw)
g.addGateway('remainder', remainder_gw)
g.addGateway('security', security_gw)
root_mapper.getSubMapper('base').setGateway(g)
base = g
# abstract base gateway with properties
g = gateways.CompositeGateway(base)
g.addGateway('properties', properties_gw)
root_mapper.getSubMapper('base_p').setGateway(g)
base_p = g
# folder gateway
g = gateways.CompositeGateway(base_p)
g.addGateway('items', folder_items_gw)
root_mapper.getSubMapper('OFS.Folder.Folder').setGateway(g)
# page template gateway
g = gateways.CompositeGateway(base_p)
g.addGateway('text', file_data_gw)
root_mapper.getSubMapper('ZopePageTemplate').setGateway(g)
# dtml method gateway
g = gateways.CompositeGateway(base)
g.addGateway('text', file_data_gw)
root_mapper.getSubMapper('OFS.DTMLMethod.DTMLMethod').setGateway(g)
# dtml document gateway
g = gateways.CompositeGateway(base_p)
g.addGateway('text', file_data_gw)
root_mapper.getSubMapper('OFS.DTMLDocument.DTMLDocument').setGateway(g)
# zsqlmethod mapper
g = gateways.CompositeGateway(base_p)
g.addGateway('text', file_data_gw)
root_mapper.getSubMapper('Products.ZSQLMethods.SQL.SQL').setGateway(g)
# python script mapper
g = gateways.CompositeGateway(base)
g.addGateway('body', file_data_gw)
root_mapper.getSubMapper('PythonScript').setGateway(g)
# file gateway
g = gateways.CompositeGateway(base_p)
g.addGateway('data', file_data_gw)
root_mapper.getSubMapper('OFS.Image.File').setGateway(g)
# image gateway is identical
root_mapper.getSubMapper('OFS.Image.Image').setGateway(g)
# user folder gateway
g = gateways.CompositeGateway(base)
g.addGateway('data', userlist_gw)
root_mapper.getSubMapper('AccessControl.User.UserFolder').setGateway(g)
# anyfolder object gateway
g = gateways.CompositeGateway(base_p)
g.addGateway('items', folder_items_gw)
root_mapper.getSubMapper('anyfolder').setGateway(g)
# anyfile object gateway
g = gateways.CompositeGateway(base_p)
root_mapper.getSubMapper('anyfile').setGateway(g)
# application gateway
g = gateways.CompositeGateway(base_p)
g.removeGateway('id')
g.addGateway('items', folder_items_gw)
root_mapper.getSubMapper('OFS.Application.Application').setGateway(g)
root_mapper.checkConfiguration()
return root_mapper, [conn], gws
def createPostgreSQLMapper(params='', table_prefix='zodb', volatile=1):
"""Object mapper factory.
Usage in database configuration file:
factory=apelib.zope2.fsmapper.createMapper
"""
# The "volatile" argument is ignored.
from apelib.sql import pg
conn = pg.PsycopgConnection(params, table_prefix)
return createSQLMapper(conn)[:2]