work in progress: sub-elements, e.g. for annotations and state information, for export/import
git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@2477 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
d944aca0f5
commit
9dec6887b6
10 changed files with 221 additions and 36 deletions
|
@ -272,9 +272,9 @@
|
||||||
provides="loops.interfaces.IExternalFile" />
|
provides="loops.interfaces.IExternalFile" />
|
||||||
<class class="loops.resource.ExternalFileAdapter">
|
<class class="loops.resource.ExternalFileAdapter">
|
||||||
<require permission="zope.View"
|
<require permission="zope.View"
|
||||||
interface="loops.interfaces.IFile" />
|
interface="loops.interfaces.IExternalFile" />
|
||||||
<require permission="zope.ManageContent"
|
<require permission="zope.ManageContent"
|
||||||
set_schema="loops.interfaces.IFile" />
|
set_schema="loops.interfaces.IExternalFile" />
|
||||||
</class>
|
</class>
|
||||||
|
|
||||||
<adapter factory="loops.resource.TextDocumentAdapter" trusted="True"
|
<adapter factory="loops.resource.TextDocumentAdapter" trusted="True"
|
||||||
|
@ -409,6 +409,7 @@
|
||||||
<include package=".rest" />
|
<include package=".rest" />
|
||||||
<include package=".search" />
|
<include package=".search" />
|
||||||
<include package=".security" />
|
<include package=".security" />
|
||||||
|
<include package=".stateful" />
|
||||||
<include package=".versioning" />
|
<include package=".versioning" />
|
||||||
<include package=".xmlrpc" />
|
<include package=".xmlrpc" />
|
||||||
|
|
||||||
|
|
27
external/README.txt
vendored
27
external/README.txt
vendored
|
@ -74,6 +74,19 @@ Working with nodes
|
||||||
>>> elements = reader.read(input)
|
>>> elements = reader.read(input)
|
||||||
>>> loader.load(elements)
|
>>> loader.load(elements)
|
||||||
|
|
||||||
|
Sub-elements
|
||||||
|
------------
|
||||||
|
|
||||||
|
>>> from loops.external import annotation
|
||||||
|
|
||||||
|
>>> input = """concept('myquery', u'My Query', 'query', viewName='mystuff.html')[
|
||||||
|
... annotations(creators='john')]"""
|
||||||
|
>>> elements = reader.read(input)
|
||||||
|
>>> elements[0].subElements
|
||||||
|
[{'creators': 'john'}]
|
||||||
|
|
||||||
|
>>> loader.load(elements)
|
||||||
|
[('creators', 'john')]
|
||||||
|
|
||||||
Exporting loops Objects
|
Exporting loops Objects
|
||||||
=======================
|
=======================
|
||||||
|
@ -107,6 +120,20 @@ Writing object information to the external storage
|
||||||
node('home', u'Home', '', u'menu', body=u'Welcome')
|
node('home', u'Home', '', u'menu', body=u'Welcome')
|
||||||
node('myquery', u'My Query', 'home', u'page', target=u'concepts/myquery')...
|
node('myquery', u'My Query', 'home', u'page', target=u'concepts/myquery')...
|
||||||
|
|
||||||
|
Writing subElements
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
>>> input = """concept('myquery', u'My Query', 'query', viewName='mystuff.html')[
|
||||||
|
... annotations(creators='john'),
|
||||||
|
... annotations(modified='2007-08-12')]"""
|
||||||
|
>>> elements = reader.read(input)
|
||||||
|
>>> output = StringIO()
|
||||||
|
>>> writer.write(elements, output)
|
||||||
|
>>> print output.getvalue()
|
||||||
|
concept('myquery', u'My Query', 'query', viewName='mystuff.html')[
|
||||||
|
annotations(creators='john'),
|
||||||
|
annotations(modified='2007-08-12')]...
|
||||||
|
|
||||||
|
|
||||||
The Export/Import View
|
The Export/Import View
|
||||||
======================
|
======================
|
||||||
|
|
57
external/annotation.py
vendored
Normal file
57
external/annotation.py
vendored
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
#
|
||||||
|
|
||||||
|
"""
|
||||||
|
Export/import of annotations.
|
||||||
|
|
||||||
|
$Id$
|
||||||
|
"""
|
||||||
|
|
||||||
|
from zope.component import adapts
|
||||||
|
from zope.interface import implements
|
||||||
|
|
||||||
|
from loops.external.element import Element, elementTypes
|
||||||
|
from loops.external.interfaces import ISubExtractor
|
||||||
|
from loops.interfaces import ILoopsObject
|
||||||
|
|
||||||
|
|
||||||
|
class AnnotationsElement(Element):
|
||||||
|
|
||||||
|
elementType = 'annotations'
|
||||||
|
|
||||||
|
def __init__(self, **kw):
|
||||||
|
for k, v in kw.items():
|
||||||
|
self[k] = v
|
||||||
|
|
||||||
|
def __call__(self, loader):
|
||||||
|
print self.items()
|
||||||
|
|
||||||
|
|
||||||
|
class AnnotationsExtractor(object):
|
||||||
|
|
||||||
|
implements(ISubExtractor)
|
||||||
|
adapts(ILoopsObject)
|
||||||
|
|
||||||
|
def extract(self):
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
elementTypes.update(dict(
|
||||||
|
annotations=AnnotationsElement,
|
||||||
|
))
|
||||||
|
|
63
external/base.py
vendored
63
external/base.py
vendored
|
@ -36,7 +36,7 @@ from cybertools.composer.interfaces import IInstance
|
||||||
from cybertools.composer.schema.interfaces import ISchemaFactory
|
from cybertools.composer.schema.interfaces import ISchemaFactory
|
||||||
from cybertools.typology.interfaces import IType
|
from cybertools.typology.interfaces import IType
|
||||||
from loops.common import adapted
|
from loops.common import adapted
|
||||||
from loops.external.interfaces import ILoader, IExtractor
|
from loops.external.interfaces import ILoader, IExtractor, ISubExtractor
|
||||||
from loops.external.element import elementTypes
|
from loops.external.element import elementTypes
|
||||||
from loops.interfaces import IConceptSchema, IResourceSchema
|
from loops.interfaces import IConceptSchema, IResourceSchema
|
||||||
from loops.resource import Document, MediaAsset
|
from loops.resource import Document, MediaAsset
|
||||||
|
@ -81,6 +81,8 @@ class Loader(Base, SetupManager):
|
||||||
def load(self, elements):
|
def load(self, elements):
|
||||||
for element in elements:
|
for element in elements:
|
||||||
element(self)
|
element(self)
|
||||||
|
if element.subElements is not None:
|
||||||
|
self.load(element.subElements)
|
||||||
|
|
||||||
# TODO: care for setting attributes via Instance (Editor)
|
# TODO: care for setting attributes via Instance (Editor)
|
||||||
# instead of using SetupManager methods:
|
# instead of using SetupManager methods:
|
||||||
|
@ -103,7 +105,9 @@ class Extractor(Base):
|
||||||
typeElement = elementTypes['type']
|
typeElement = elementTypes['type']
|
||||||
for obj in self.typeConcept.getChildren([self.typePredicate]):
|
for obj in self.typeConcept.getChildren([self.typePredicate]):
|
||||||
data = self.getObjectData(obj)
|
data = self.getObjectData(obj)
|
||||||
yield typeElement(getName(obj), obj.title, **data)
|
element = typeElement(getName(obj), obj.title, **data)
|
||||||
|
self.provideSubElements(obj, element)
|
||||||
|
yield element
|
||||||
|
|
||||||
def extractConcepts(self):
|
def extractConcepts(self):
|
||||||
conceptElement = elementTypes['concept']
|
conceptElement = elementTypes['concept']
|
||||||
|
@ -112,7 +116,9 @@ class Extractor(Base):
|
||||||
if obj.conceptType != typeConcept:
|
if obj.conceptType != typeConcept:
|
||||||
data = self.getObjectData(obj)
|
data = self.getObjectData(obj)
|
||||||
tp = getName(obj.conceptType)
|
tp = getName(obj.conceptType)
|
||||||
yield conceptElement(name, obj.title, tp, **data)
|
element = conceptElement(name, obj.title, tp, **data)
|
||||||
|
self.provideSubElements(obj, element)
|
||||||
|
yield element
|
||||||
|
|
||||||
def extractResources(self):
|
def extractResources(self):
|
||||||
elementClass = elementTypes['resource']
|
elementClass = elementTypes['resource']
|
||||||
|
@ -123,26 +129,9 @@ class Extractor(Base):
|
||||||
tp = 'textdocument'
|
tp = 'textdocument'
|
||||||
element = elementClass(name, obj.title, tp, **data)
|
element = elementClass(name, obj.title, tp, **data)
|
||||||
element.processExport(self)
|
element.processExport(self)
|
||||||
|
self.provideSubElements(obj, element)
|
||||||
yield element
|
yield element
|
||||||
|
|
||||||
def getObjectData(self, obj, defaultInterface=IConceptSchema):
|
|
||||||
aObj = adapted(obj)
|
|
||||||
schemaFactory = component.getAdapter(aObj, ISchemaFactory)
|
|
||||||
ti = IType(obj).typeInterface or defaultInterface
|
|
||||||
schema = schemaFactory(ti, manager=self) #, request=self.request)
|
|
||||||
instance = IInstance(aObj)
|
|
||||||
instance.template = schema
|
|
||||||
# TODO: use ``_not_exportable`` attribute of adapter to control export;
|
|
||||||
# this should also convert object attributes like e.g. typeInterface
|
|
||||||
#data = instance.applyTemplate(mode='export')
|
|
||||||
data = instance.applyTemplate(mode='edit')
|
|
||||||
if 'title' in data:
|
|
||||||
del data['title']
|
|
||||||
data['description'] = obj.description
|
|
||||||
if not data['description']:
|
|
||||||
del data['description']
|
|
||||||
return data
|
|
||||||
|
|
||||||
def extractChildren(self):
|
def extractChildren(self):
|
||||||
childElement = elementTypes['child']
|
childElement = elementTypes['child']
|
||||||
typePredicate = self.typePredicate
|
typePredicate = self.typePredicate
|
||||||
|
@ -172,7 +161,7 @@ class Extractor(Base):
|
||||||
def extractNodes(self, parent=None, path=''):
|
def extractNodes(self, parent=None, path=''):
|
||||||
if parent is None:
|
if parent is None:
|
||||||
parent = self.views
|
parent = self.views
|
||||||
element = elementTypes['node']
|
elementClass = elementTypes['node']
|
||||||
for name, obj in parent.items():
|
for name, obj in parent.items():
|
||||||
data = {}
|
data = {}
|
||||||
for attr in ('description', 'body', 'viewName'):
|
for attr in ('description', 'body', 'viewName'):
|
||||||
|
@ -182,8 +171,36 @@ class Extractor(Base):
|
||||||
target = obj.target
|
target = obj.target
|
||||||
if target is not None:
|
if target is not None:
|
||||||
data['target'] = '/'.join((getName(getParent(target)), getName(target)))
|
data['target'] = '/'.join((getName(getParent(target)), getName(target)))
|
||||||
yield element(name, obj.title, path, obj.nodeType, **data)
|
elem = elementClass(name, obj.title, path, obj.nodeType, **data)
|
||||||
|
self.provideSubElements(obj, elem)
|
||||||
|
yield elem
|
||||||
childPath = path and '/'.join((path, name)) or name
|
childPath = path and '/'.join((path, name)) or name
|
||||||
for elem in self.extractNodes(obj, childPath):
|
for elem in self.extractNodes(obj, childPath):
|
||||||
|
self.provideSubElements(obj, elem)
|
||||||
yield elem
|
yield elem
|
||||||
|
|
||||||
|
# helper methods
|
||||||
|
|
||||||
|
def getObjectData(self, obj, defaultInterface=IConceptSchema):
|
||||||
|
aObj = adapted(obj)
|
||||||
|
schemaFactory = component.getAdapter(aObj, ISchemaFactory)
|
||||||
|
ti = IType(obj).typeInterface or defaultInterface
|
||||||
|
schema = schemaFactory(ti, manager=self) #, request=self.request)
|
||||||
|
instance = IInstance(aObj)
|
||||||
|
instance.template = schema
|
||||||
|
# TODO: use ``_not_exportable`` attribute of adapter to control export;
|
||||||
|
# this should also convert object attributes like e.g. typeInterface
|
||||||
|
#data = instance.applyTemplate(mode='export')
|
||||||
|
data = instance.applyTemplate(mode='edit')
|
||||||
|
if 'title' in data:
|
||||||
|
del data['title']
|
||||||
|
data['description'] = obj.description
|
||||||
|
if not data['description']:
|
||||||
|
del data['description']
|
||||||
|
return data
|
||||||
|
|
||||||
|
def provideSubElements(self, obj, element):
|
||||||
|
for name, extractor in component.getAdapters((obj,), ISubExtractor):
|
||||||
|
for sub in extractor.extract():
|
||||||
|
element.add(sub)
|
||||||
|
|
||||||
|
|
2
external/browser.py
vendored
2
external/browser.py
vendored
|
@ -89,7 +89,7 @@ class ExportImport(object):
|
||||||
return False
|
return False
|
||||||
reader = component.getUtility(IReader)
|
reader = component.getUtility(IReader)
|
||||||
elements = reader.read(data)
|
elements = reader.read(data)
|
||||||
loader = Loader(self.context, )
|
loader = Loader(self.context)
|
||||||
loader.load(elements)
|
loader.load(elements)
|
||||||
self.message = u'Content uploaded and imported.'
|
self.message = u'Content uploaded and imported.'
|
||||||
return False
|
return False
|
||||||
|
|
29
external/element.py
vendored
29
external/element.py
vendored
|
@ -37,6 +37,10 @@ class Element(dict):
|
||||||
implements(IElement)
|
implements(IElement)
|
||||||
|
|
||||||
elementType = ''
|
elementType = ''
|
||||||
|
posArgs = ()
|
||||||
|
object = None
|
||||||
|
parent = None
|
||||||
|
subElements = None
|
||||||
|
|
||||||
def __init__(self, name, title, type=None, *args, **kw):
|
def __init__(self, name, title, type=None, *args, **kw):
|
||||||
self['name'] = name
|
self['name'] = name
|
||||||
|
@ -46,9 +50,24 @@ class Element(dict):
|
||||||
for k, v in kw.items():
|
for k, v in kw.items():
|
||||||
self[k] = v
|
self[k] = v
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
if isinstance(key, Element):
|
||||||
|
key = (key,)
|
||||||
|
if isinstance(key, tuple):
|
||||||
|
for item in key:
|
||||||
|
item.parent = self
|
||||||
|
self.add(item)
|
||||||
|
return key
|
||||||
|
return super(Element, self).__getitem__(key)
|
||||||
|
|
||||||
def processExport(self, extractor):
|
def processExport(self, extractor):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def add(self, element):
|
||||||
|
if self.subElements is None:
|
||||||
|
self.subElements = []
|
||||||
|
self.subElements.append(element)
|
||||||
|
|
||||||
def __call__(self, loader):
|
def __call__(self, loader):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -62,7 +81,7 @@ class ConceptElement(Element):
|
||||||
type = loader.concepts[self['type']]
|
type = loader.concepts[self['type']]
|
||||||
kw = dict((k, v) for k, v in self.items()
|
kw = dict((k, v) for k, v in self.items()
|
||||||
if k not in self.posArgs)
|
if k not in self.posArgs)
|
||||||
loader.addConcept(self['name'], self['title'], type, **kw)
|
self.object = loader.addConcept(self['name'], self['title'], type, **kw)
|
||||||
|
|
||||||
|
|
||||||
class TypeElement(ConceptElement):
|
class TypeElement(ConceptElement):
|
||||||
|
@ -83,7 +102,8 @@ class TypeElement(ConceptElement):
|
||||||
ti = self.get('typeInterface')
|
ti = self.get('typeInterface')
|
||||||
if ti:
|
if ti:
|
||||||
kw['typeInterface'] = resolve(ti)
|
kw['typeInterface'] = resolve(ti)
|
||||||
loader.addConcept(self['name'], self['title'], loader.typeConcept, **kw)
|
self.object = loader.addConcept(self['name'], self['title'],
|
||||||
|
loader.typeConcept, **kw)
|
||||||
|
|
||||||
|
|
||||||
class ChildElement(Element):
|
class ChildElement(Element):
|
||||||
|
@ -128,7 +148,7 @@ class ResourceElement(Element):
|
||||||
content = content.decode('UTF-8')
|
content = content.decode('UTF-8')
|
||||||
kw['data'] = content
|
kw['data'] = content
|
||||||
f.close()
|
f.close()
|
||||||
loader.addResource(self['name'], self['title'], type, **kw)
|
self.object = loader.addResource(self['name'], self['title'], type, **kw)
|
||||||
|
|
||||||
|
|
||||||
class ResourceRelationElement(ChildElement):
|
class ResourceRelationElement(ChildElement):
|
||||||
|
@ -160,6 +180,7 @@ class NodeElement(Element):
|
||||||
if target is not None:
|
if target is not None:
|
||||||
targetObject = traverse(loader.context, target, None)
|
targetObject = traverse(loader.context, target, None)
|
||||||
node.target = targetObject
|
node.target = targetObject
|
||||||
|
self.object = node
|
||||||
|
|
||||||
|
|
||||||
# element registry
|
# element registry
|
||||||
|
@ -172,3 +193,5 @@ elementTypes = dict(
|
||||||
resourceRelation=ResourceRelationElement,
|
resourceRelation=ResourceRelationElement,
|
||||||
node=NodeElement,
|
node=NodeElement,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
toplevelElements = ('type', 'concept', 'resource', 'resourceRelation', 'node')
|
||||||
|
|
22
external/interfaces.py
vendored
22
external/interfaces.py
vendored
|
@ -36,6 +36,21 @@ class IElement(Interface):
|
||||||
or IElement objects.
|
or IElement objects.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
elementType = Attribute('A string denoting the element type.')
|
||||||
|
object = Attribute('The object that has been created from this '
|
||||||
|
'element during import.')
|
||||||
|
parent = Attribute('An optional parent element that this element is part of.')
|
||||||
|
subElements = Attribute('An optional list of sub-elements; initially None.')
|
||||||
|
|
||||||
|
def processExport(extractor):
|
||||||
|
""" Will be called by the extractor during export to allow for
|
||||||
|
special handling e.g. of certain attributes.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def add(element):
|
||||||
|
""" Add a sub-element, may be called by the extractor during export.
|
||||||
|
"""
|
||||||
|
|
||||||
def __call__(loader):
|
def __call__(loader):
|
||||||
""" Create the object that is specified by the element in the
|
""" Create the object that is specified by the element in the
|
||||||
context of the loader and return it.
|
context of the loader and return it.
|
||||||
|
@ -75,7 +90,8 @@ class IWriter(Interface):
|
||||||
|
|
||||||
class IExtractor(Interface):
|
class IExtractor(Interface):
|
||||||
""" Extracts information from loops objects and provides them as
|
""" Extracts information from loops objects and provides them as
|
||||||
IElement objects. Will typically be used as an adapter.
|
IElement objects. Will typically be used as an adapter on the
|
||||||
|
loops root object.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def extract():
|
def extract():
|
||||||
|
@ -83,3 +99,7 @@ class IExtractor(Interface):
|
||||||
the content of the context object.
|
the content of the context object.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
class ISubExtractor(IExtractor):
|
||||||
|
""" Used for extracting special informations from individual objects
|
||||||
|
that will be represented by sub-elements.
|
||||||
|
"""
|
||||||
|
|
20
external/pyfunc.py
vendored
20
external/pyfunc.py
vendored
|
@ -27,7 +27,7 @@ from zope.cachedescriptors.property import Lazy
|
||||||
from zope.interface import implements
|
from zope.interface import implements
|
||||||
|
|
||||||
from loops.external.interfaces import IReader, IWriter
|
from loops.external.interfaces import IReader, IWriter
|
||||||
from loops.external.element import elementTypes
|
from loops.external.element import elementTypes, toplevelElements
|
||||||
|
|
||||||
|
|
||||||
class PyReader(object):
|
class PyReader(object):
|
||||||
|
@ -50,6 +50,7 @@ class InputProcessor(dict):
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
def factory(*args, **kw):
|
def factory(*args, **kw):
|
||||||
element = elementTypes[key](*args, **kw)
|
element = elementTypes[key](*args, **kw)
|
||||||
|
if key in toplevelElements:
|
||||||
self.elements.append(element)
|
self.elements.append(element)
|
||||||
return element
|
return element
|
||||||
return factory
|
return factory
|
||||||
|
@ -59,8 +60,8 @@ class PyWriter(object):
|
||||||
|
|
||||||
implements(IWriter)
|
implements(IWriter)
|
||||||
|
|
||||||
def write(self, elements, output):
|
def write(self, elements, output, level=0):
|
||||||
for element in elements:
|
for idx, element in enumerate(elements):
|
||||||
args = []
|
args = []
|
||||||
for arg in element.posArgs:
|
for arg in element.posArgs:
|
||||||
if arg in element:
|
if arg in element:
|
||||||
|
@ -68,7 +69,18 @@ class PyWriter(object):
|
||||||
for k, v in element.items():
|
for k, v in element.items():
|
||||||
if k not in element.posArgs:
|
if k not in element.posArgs:
|
||||||
args.append("%s=%s" % (str(k), repr(v)))
|
args.append("%s=%s" % (str(k), repr(v)))
|
||||||
output.write('%s(%s)\n' % (element.elementType, ', '.join(args)))
|
if not element.subElements:
|
||||||
|
output.write('%s%s(%s)'
|
||||||
|
% (level*' ', element.elementType, ', '.join(args)))
|
||||||
|
else:
|
||||||
|
output.write('%s%s(%s)[\n'
|
||||||
|
% (level*' ', element.elementType, ', '.join(args)))
|
||||||
|
self.write(element.subElements, output, level+1)
|
||||||
|
output.write(']')
|
||||||
|
if level == 0:
|
||||||
|
output.write('\n')
|
||||||
|
elif idx < len(elements) - 1:
|
||||||
|
output.write(',\n')
|
||||||
|
|
||||||
|
|
||||||
def toStr(value):
|
def toStr(value):
|
||||||
|
|
|
@ -662,7 +662,35 @@ class IFile(IResourceAdapter, IResourceSchema):
|
||||||
localFilename = Attribute('Filename provided during upload.')
|
localFilename = Attribute('Filename provided during upload.')
|
||||||
|
|
||||||
|
|
||||||
|
class IStorageInfo(Interface):
|
||||||
|
|
||||||
|
storageName = schema.BytesLine(
|
||||||
|
title=_(u'Storage Name'),
|
||||||
|
description=_(u'The name of a storage utility used for this '
|
||||||
|
'object.'),
|
||||||
|
default='',
|
||||||
|
missing_value='',
|
||||||
|
required=False)
|
||||||
|
|
||||||
|
storageParams = schema.BytesLine(
|
||||||
|
title=_(u'Storage Parameters'),
|
||||||
|
description=_(u'Information used to address the external '
|
||||||
|
'storage, e.g. a filename or path.'),
|
||||||
|
default='',
|
||||||
|
missing_value='',
|
||||||
|
required=False)
|
||||||
|
|
||||||
|
externalAddress = schema.BytesLine(
|
||||||
|
title=_(u'External Address'),
|
||||||
|
description=_(u'The full address for accessing the object '
|
||||||
|
'on the external storage, e.g. a filename or path.'),
|
||||||
|
default='',
|
||||||
|
missing_value='',
|
||||||
|
required=False)
|
||||||
|
|
||||||
|
|
||||||
class IExternalFile(IFile):
|
class IExternalFile(IFile):
|
||||||
|
#class IExternalFile(IFile, IStorageInfo):
|
||||||
""" A file whose content (data attribute) is not stored in the ZODB
|
""" A file whose content (data attribute) is not stored in the ZODB
|
||||||
but somewhere else, typically in the file system.
|
but somewhere else, typically in the file system.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
i18n_domain="loops">
|
i18n_domain="loops">
|
||||||
|
|
||||||
<zope:utility
|
<zope:utility
|
||||||
factory="cybertools.stateful.publishing.simplePublishing"
|
factory="cybertools.stateful.publishing.simplePublishingFactory"
|
||||||
name="loops.simple_publishing" />
|
name="loops.simple_publishing" />
|
||||||
|
|
||||||
<zope:adapter
|
<zope:adapter
|
||||||
|
|
Loading…
Add table
Reference in a new issue