work in progress: set up dynamic typing for resources

git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@1271 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2006-07-14 11:49:54 +00:00
parent f2d9bc9af8
commit 04fa445e54
7 changed files with 155 additions and 20 deletions

View file

@ -237,7 +237,7 @@
for="loops.interfaces.IResource"
class=".resource.ResourceConfigureView"
permission="zope.ManageContent">
<page
name="configure.html"
template="resource_configure.pt"
@ -246,6 +246,14 @@
</pages>
<zope:adapter
for="loops.interfaces.IResource
zope.publisher.interfaces.browser.IBrowserRequest"
provides="zope.interface.Interface"
factory="loops.browser.resource.ResourceView"
permission="zope.View"
/>
<!-- document -->
<page

View file

@ -301,6 +301,11 @@
name="loops.conceptTypeSource"
/>
<vocabulary
factory="loops.type.ResourceTypeSourceList"
name="loops.resourceTypeSource"
/>
<vocabulary
factory="loops.type.TypeInterfaceSourceList"
name="loops.TypeInterfaceSource"

View file

@ -25,6 +25,13 @@ and provide a relation registry:
>>> from cybertools.relation.registry import DummyRelationRegistry
>>> from zope.app.testing import ztapi
>>> ztapi.provideUtility(IRelationRegistry, DummyRelationRegistry())
and care for some type adapter machinery:
>>> from loops.interfaces import IConcept
>>> from loops.interfaces import ITypeConcept
>>> from loops.type import TypeConcept
>>> component.provideAdapter(TypeConcept, (IConcept,), ITypeConcept)
Now we can setup a simple loops site with its manager objects, using a
loops setup manager:
@ -52,6 +59,12 @@ We also add some example concepts,
u'Zope 3'
resources,
>>> from loops.resource import Resource
>>> file1 = resources['file1'] = Resource(u'A file')
>>> file1.resourceType = concepts['file']
(the use of Document and MediaAsset may get deprecated soon:)
>>> from loops.resource import Document, MediaAsset
>>> doc1 = Document(u'Zope Info')
@ -82,7 +95,6 @@ interface. The loops framework provides an adapter (LoopsType) for this
purpose:
>>> from cybertools.typology.interfaces import IType
>>> from loops.interfaces import IConcept
>>> from loops.type import ConceptType
>>> ztapi.provideAdapter(IConcept, IType, ConceptType)
>>> cc1_type = IType(cc1)
@ -148,6 +160,25 @@ lazy properties, one should always get a new adapter:
<class 'loops.concept.Concept'>
Now let's have a look at resources.
>>> from loops.interfaces import IResource
>>> from loops.type import LoopsType
>>> component.provideAdapter(LoopsType, (IResource,), IType)
>>> file1_type = IType(file1)
>>> file1_type.title
u'File'
>>> file1_type.token
'.loops/concepts/file'
>>> file1_type.tokenForSearch
'loops:resource:file'
>>> file1_type.qualifiers
('resource',)
>>> file1_type.defaultContainer
<loops.resource.ResourceManager object ...>
>>> file1_type.factory
<class 'loops.resource.Resource'>
(The use of Document and MediaAsset will be deprecated soon...)
>>> from loops.interfaces import IResource
>>> from loops.type import ResourceType
@ -185,10 +216,11 @@ get a type manager from all loops objects, always with the same context:
True
>>> types = typeManager.types
>>> sorted((t.token) for t in types)
['.loops/concepts/predicate', '.loops/concepts/topic',
'.loops/concepts/type', 'loops.resource.Document',
'loops.resource.MediaAsset']
>>> sorted(t.token for t in types)
['.loops/concepts/file', '.loops/concepts/image', '.loops/concepts/predicate',
'.loops/concepts/textdocument', '.loops/concepts/topic',
'.loops/concepts/type',
'loops.resource.Document', 'loops.resource.MediaAsset']
>>> typeManager.getType('.loops/concepts/topic') == cc1_type
True
@ -201,15 +233,14 @@ condition:
['.loops/concepts/predicate', '.loops/concepts/topic', '.loops/concepts/type']
>>> types = typeManager.listTypes(exclude=('concept',))
>>> sorted(t.token for t in types)
['loops.resource.Document', 'loops.resource.MediaAsset']
['.loops/concepts/file', '.loops/concepts/image',
'.loops/concepts/textdocument', 'loops.resource.Document',
'loops.resource.MediaAsset']
Type-based interfaces and adapters
----------------------------------
>>> from loops.interfaces import ITypeConcept
>>> from loops.type import TypeConcept
>>> ztapi.provideAdapter(IConcept, ITypeConcept, TypeConcept)
A type has an optional typeInterface attribute that objects of this type
will be adaptable to. The default for this is None:

View file

@ -177,6 +177,29 @@ class IConceptManagerContained(Interface):
# resource interfaces
class IBaseResource(Interface):
""" New base interface for resources. Functionality beyond this simple
interface is provided by adapters that are chosen via the
resource type's typeInterface.
"""
title = schema.TextLine(
title=_(u'Title'),
description=_(u'Title of the resource'),
default=u'',
missing_value=u'',
required=False)
resourceType = schema.Choice(
title=_(u'Resource Type'),
description=_(u"The type of the resource, specified by a relation to "
"a concept of type 'type'."),
default=None,
source="loops.resourceTypeSource",
required=False)
class IResourceSchema(Interface):
title = schema.TextLine(
@ -201,6 +224,8 @@ class IResourceSchema(Interface):
required=False)
# the next two interfaces are probably obsolete:
class IFileSystemResource(Interface):
fsPath = schema.BytesLine(
@ -517,6 +542,7 @@ class ITypeConcept(Interface):
required=False)
# viewName = schema.TextLine()
# storage = schema.Choice()
class IResourceAdapter(Interface):

View file

@ -40,7 +40,7 @@ from textindexng.content import IndexContentCollector
from cybertools.relation.registry import getRelations
from cybertools.relation.interfaces import IRelatable
from interfaces import IResource
from interfaces import IBaseResource, IResource
from interfaces import IDocument, IDocumentSchema, IDocumentView
from interfaces import IMediaAsset, IMediaAssetSchema, IMediaAssetView
from interfaces import IFileSystemResource, IControlledResource
@ -55,11 +55,32 @@ _ = MessageFactory('loops')
class Resource(Contained, Persistent):
implements(IResource, IFileSystemResource, IControlledResource,
implements(IBaseResource, IResource, IFileSystemResource, IControlledResource,
IResourceManagerContained, IRelatable)
proxyInterface = IMediaAssetView
_size = _width = _height = 0
def getResourceType(self):
typePred = self.getLoopsRoot().getConceptManager().getTypePredicate()
if typePred is None:
return None
concepts = self.getConcepts([typePred])
# TODO (?): check for multiple types (->Error)
return concepts and concepts[0] or None
def setResourceType(self, concept):
current = self.getResourceType()
if current != concept:
typePred = self.getLoopsRoot().getConceptManager().getTypePredicate()
if typePred is None:
raise ValueError('No type predicate found for '
+ zapi.getName(self))
if current is not None:
self.deassignConcept(current, [typePred])
self.assignConcept(concept, typePred)
resourceType = property(getResourceType, setResourceType)
_title = u''
def getTitle(self): return self._title
def setTitle(self, title): self._title = title
@ -167,6 +188,17 @@ class ResourceManager(BTreeContainer):
def getViewManager(self):
return self.getLoopsRoot().getViewManager()
# adapters and similar stuff
class FileAdapter(object):
""" A type adapter for providing file functionality for resources.
"""
def __init__(self, context):
self.context = context
class DocumentWriteFileAdapter(object):

View file

@ -28,7 +28,7 @@ from zope import component
from zope.component import adapts
from zope.interface import implements, Interface
from loops.interfaces import ILoops
from loops.interfaces import ILoops, ITypeConcept, IFile, IImage, ITextDocument
from loops.concept import ConceptManager, Concept
from loops.resource import ResourceManager
from loops.view import ViewManager, Node
@ -73,8 +73,16 @@ class SetupManager(object):
hasType = self.addObject(conceptManager, Concept, 'hasType', title=u'has Type')
predicate = self.addObject(conceptManager, Concept, 'predicate', title=u'Predicate')
standard = self.addObject(conceptManager, Concept, 'standard', title=u'subobject')
typeConcept.conceptType = typeConcept
predicate.conceptType = typeConcept
file = self.addObject(conceptManager, Concept, 'file', title=u'File')
image = self.addObject(conceptManager, Concept, 'image', title=u'Image')
textdocument = self.addObject(conceptManager, Concept,
'textdocument', title=u'Text Document')
for c in (typeConcept, file, image, textdocument, predicate):
c.conceptType = typeConcept
ITypeConcept(typeConcept).typeInterface = ITypeConcept
ITypeConcept(file).typeInterface = IFile
ITypeConcept(image).typeInterface = IImage
ITypeConcept(textdocument).typeInterface = ITextDocument
hasType.conceptType = predicate
standard.conceptType = predicate

33
type.py
View file

@ -30,8 +30,10 @@ from zope.dottedname.resolve import resolve
from zope import schema
from zope.security.proxy import removeSecurityProxy
from cybertools.typology.type import BaseType, TypeManager
from cybertools.typology.interfaces import ITypeManager
from loops.interfaces import ILoopsObject, IConcept, IResource
from loops.interfaces import ITypeConcept, IResourceAdapter, IFile, IImage
from loops.interfaces import ITypeConcept
from loops.interfaces import IResourceAdapter, IFile, IImage, ITextDocument
from loops.concept import Concept
from loops.resource import Resource, Document, MediaAsset
@ -92,7 +94,8 @@ class LoopsType(BaseType):
@Lazy
def typeProvider(self):
return self.context.conceptType
# TODO: unify this type attribute naming...
return self.context.resourceType
class LoopsTypeInfo(LoopsType):
@ -110,6 +113,10 @@ class ConceptType(LoopsType):
adapts(IConcept)
@Lazy
def typeProvider(self):
return self.context.conceptType
class ConceptTypeInfo(LoopsTypeInfo):
""" The type info class used by the type manager for listing types.
@ -233,8 +240,7 @@ class TypeInterfaceSourceList(object):
implements(schema.interfaces.IIterableSource)
#typeInterfaces = (ITypeConcept, IFile, IImage,)
typeInterfaces = (ITypeConcept,)
typeInterfaces = (ITypeConcept, IFile, ITextDocument)
def __init__(self, context):
self.context = context
@ -246,6 +252,25 @@ class TypeInterfaceSourceList(object):
return len(self.typeInterfaces)
class ResourceTypeSourceList(object):
implements(schema.interfaces.IIterableSource)
def __init__(self, context):
self.context = context
def __iter__(self):
return iter(self.resourceTypes)
@Lazy
def resourceTypes(self):
types = ITypeManager(self.context).listTypes(include=('resource',))
return [t.typeProvider for t in types]
def __len__(self):
return len(self.resourceTypes)
class AdapterBase(object):
""" (Mix-in) Class for concept adapters that provide editing of fields
defined by the type interface.