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:
		
							parent
							
								
									f2d9bc9af8
								
							
						
					
					
						commit
						04fa445e54
					
				
					 7 changed files with 155 additions and 20 deletions
				
			
		|  | @ -246,6 +246,14 @@ | ||||||
|      |      | ||||||
|   </pages> |   </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 --> |   <!-- document --> | ||||||
| 
 | 
 | ||||||
|   <page |   <page | ||||||
|  |  | ||||||
|  | @ -301,6 +301,11 @@ | ||||||
|       name="loops.conceptTypeSource" |       name="loops.conceptTypeSource" | ||||||
|       /> |       /> | ||||||
| 
 | 
 | ||||||
|  |   <vocabulary | ||||||
|  |       factory="loops.type.ResourceTypeSourceList" | ||||||
|  |       name="loops.resourceTypeSource" | ||||||
|  |       /> | ||||||
|  | 
 | ||||||
|   <vocabulary |   <vocabulary | ||||||
|       factory="loops.type.TypeInterfaceSourceList" |       factory="loops.type.TypeInterfaceSourceList" | ||||||
|       name="loops.TypeInterfaceSource" |       name="loops.TypeInterfaceSource" | ||||||
|  |  | ||||||
							
								
								
									
										51
									
								
								helpers.txt
									
										
									
									
									
								
							
							
						
						
									
										51
									
								
								helpers.txt
									
										
									
									
									
								
							|  | @ -26,6 +26,13 @@ and provide a relation registry: | ||||||
|   >>> from zope.app.testing import ztapi |   >>> from zope.app.testing import ztapi | ||||||
|   >>> ztapi.provideUtility(IRelationRegistry, DummyRelationRegistry()) |   >>> 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 | Now we can setup a simple loops site with its manager objects, using a | ||||||
| loops setup manager: | loops setup manager: | ||||||
|    |    | ||||||
|  | @ -53,6 +60,12 @@ We also add some example concepts, | ||||||
| 
 | 
 | ||||||
| resources, | 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 |   >>> from loops.resource import Document, MediaAsset | ||||||
|   >>> doc1 = Document(u'Zope Info') |   >>> doc1 = Document(u'Zope Info') | ||||||
|   >>> resources['doc1'] = doc1 |   >>> resources['doc1'] = doc1 | ||||||
|  | @ -82,7 +95,6 @@ interface. The loops framework provides an adapter (LoopsType) for this | ||||||
| purpose: | purpose: | ||||||
| 
 | 
 | ||||||
|   >>> from cybertools.typology.interfaces import IType |   >>> from cybertools.typology.interfaces import IType | ||||||
|   >>> from loops.interfaces import IConcept |  | ||||||
|   >>> from loops.type import ConceptType |   >>> from loops.type import ConceptType | ||||||
|   >>> ztapi.provideAdapter(IConcept, IType, ConceptType) |   >>> ztapi.provideAdapter(IConcept, IType, ConceptType) | ||||||
|   >>> cc1_type = IType(cc1) |   >>> cc1_type = IType(cc1) | ||||||
|  | @ -149,6 +161,25 @@ lazy properties, one should always get a new adapter: | ||||||
| 
 | 
 | ||||||
| Now let's have a look at resources. | 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.interfaces import IResource | ||||||
|   >>> from loops.type import ResourceType |   >>> from loops.type import ResourceType | ||||||
|   >>> ztapi.provideAdapter(IResource, IType, ResourceType) |   >>> ztapi.provideAdapter(IResource, IType, ResourceType) | ||||||
|  | @ -185,10 +216,11 @@ get a type manager from all loops objects, always with the same context: | ||||||
|   True |   True | ||||||
| 
 | 
 | ||||||
|   >>> types = typeManager.types |   >>> types = typeManager.types | ||||||
|   >>> sorted((t.token) for t in types) |   >>> sorted(t.token for t in types) | ||||||
|     ['.loops/concepts/predicate', '.loops/concepts/topic', |     ['.loops/concepts/file', '.loops/concepts/image', '.loops/concepts/predicate',  | ||||||
|      '.loops/concepts/type', 'loops.resource.Document', |      '.loops/concepts/textdocument', '.loops/concepts/topic',  | ||||||
|      'loops.resource.MediaAsset'] |      '.loops/concepts/type',  | ||||||
|  |      'loops.resource.Document', 'loops.resource.MediaAsset'] | ||||||
| 
 | 
 | ||||||
|   >>> typeManager.getType('.loops/concepts/topic') == cc1_type |   >>> typeManager.getType('.loops/concepts/topic') == cc1_type | ||||||
|   True |   True | ||||||
|  | @ -201,15 +233,14 @@ condition: | ||||||
|   ['.loops/concepts/predicate', '.loops/concepts/topic', '.loops/concepts/type'] |   ['.loops/concepts/predicate', '.loops/concepts/topic', '.loops/concepts/type'] | ||||||
|   >>> types = typeManager.listTypes(exclude=('concept',)) |   >>> types = typeManager.listTypes(exclude=('concept',)) | ||||||
|   >>> sorted(t.token for t in types) |   >>> 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 | 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 | A type has an optional typeInterface attribute that objects of this type | ||||||
| will be adaptable to. The default for this is None: | will be adaptable to. The default for this is None: | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -177,6 +177,29 @@ class IConceptManagerContained(Interface): | ||||||
| 
 | 
 | ||||||
| # resource interfaces | # 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): | class IResourceSchema(Interface): | ||||||
| 
 | 
 | ||||||
|     title = schema.TextLine( |     title = schema.TextLine( | ||||||
|  | @ -201,6 +224,8 @@ class IResourceSchema(Interface): | ||||||
|                 required=False) |                 required=False) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | # the next two interfaces are probably obsolete: | ||||||
|  | 
 | ||||||
| class IFileSystemResource(Interface): | class IFileSystemResource(Interface): | ||||||
| 
 | 
 | ||||||
|     fsPath = schema.BytesLine( |     fsPath = schema.BytesLine( | ||||||
|  | @ -517,6 +542,7 @@ class ITypeConcept(Interface): | ||||||
|         required=False) |         required=False) | ||||||
| 
 | 
 | ||||||
|     # viewName = schema.TextLine() |     # viewName = schema.TextLine() | ||||||
|  |     # storage = schema.Choice() | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class IResourceAdapter(Interface): | class IResourceAdapter(Interface): | ||||||
|  |  | ||||||
							
								
								
									
										36
									
								
								resource.py
									
										
									
									
									
								
							
							
						
						
									
										36
									
								
								resource.py
									
										
									
									
									
								
							|  | @ -40,7 +40,7 @@ from textindexng.content import IndexContentCollector | ||||||
| from cybertools.relation.registry import getRelations | from cybertools.relation.registry import getRelations | ||||||
| from cybertools.relation.interfaces import IRelatable | from cybertools.relation.interfaces import IRelatable | ||||||
| 
 | 
 | ||||||
| from interfaces import IResource | from interfaces import IBaseResource, IResource | ||||||
| from interfaces import IDocument, IDocumentSchema, IDocumentView | from interfaces import IDocument, IDocumentSchema, IDocumentView | ||||||
| from interfaces import IMediaAsset, IMediaAssetSchema, IMediaAssetView | from interfaces import IMediaAsset, IMediaAssetSchema, IMediaAssetView | ||||||
| from interfaces import IFileSystemResource, IControlledResource | from interfaces import IFileSystemResource, IControlledResource | ||||||
|  | @ -55,11 +55,32 @@ _ = MessageFactory('loops') | ||||||
| 
 | 
 | ||||||
| class Resource(Contained, Persistent): | class Resource(Contained, Persistent): | ||||||
| 
 | 
 | ||||||
|     implements(IResource, IFileSystemResource, IControlledResource, |     implements(IBaseResource, IResource, IFileSystemResource, IControlledResource, | ||||||
|                IResourceManagerContained, IRelatable) |                IResourceManagerContained, IRelatable) | ||||||
|                 |                 | ||||||
|  |     proxyInterface = IMediaAssetView | ||||||
|  | 
 | ||||||
|     _size = _width = _height = 0 |     _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'' |     _title = u'' | ||||||
|     def getTitle(self): return self._title |     def getTitle(self): return self._title | ||||||
|     def setTitle(self, title): self._title = title |     def setTitle(self, title): self._title = title | ||||||
|  | @ -169,6 +190,17 @@ class ResourceManager(BTreeContainer): | ||||||
|         return self.getLoopsRoot().getViewManager() |         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): | class DocumentWriteFileAdapter(object): | ||||||
| 
 | 
 | ||||||
|     implements(IWriteFile) |     implements(IWriteFile) | ||||||
|  |  | ||||||
							
								
								
									
										14
									
								
								setup.py
									
										
									
									
									
								
							
							
						
						
									
										14
									
								
								setup.py
									
										
									
									
									
								
							|  | @ -28,7 +28,7 @@ from zope import component | ||||||
| from zope.component import adapts | from zope.component import adapts | ||||||
| from zope.interface import implements, Interface | 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.concept import ConceptManager, Concept | ||||||
| from loops.resource import ResourceManager | from loops.resource import ResourceManager | ||||||
| from loops.view import ViewManager, Node | from loops.view import ViewManager, Node | ||||||
|  | @ -73,8 +73,16 @@ class SetupManager(object): | ||||||
|         hasType = self.addObject(conceptManager, Concept, 'hasType', title=u'has Type') |         hasType = self.addObject(conceptManager, Concept, 'hasType', title=u'has Type') | ||||||
|         predicate = self.addObject(conceptManager, Concept, 'predicate', title=u'Predicate') |         predicate = self.addObject(conceptManager, Concept, 'predicate', title=u'Predicate') | ||||||
|         standard = self.addObject(conceptManager, Concept, 'standard', title=u'subobject') |         standard = self.addObject(conceptManager, Concept, 'standard', title=u'subobject') | ||||||
|         typeConcept.conceptType = typeConcept |         file = self.addObject(conceptManager, Concept, 'file', title=u'File') | ||||||
|         predicate.conceptType = typeConcept |         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 |         hasType.conceptType = predicate | ||||||
|         standard.conceptType = predicate |         standard.conceptType = predicate | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										33
									
								
								type.py
									
										
									
									
									
								
							
							
						
						
									
										33
									
								
								type.py
									
										
									
									
									
								
							|  | @ -30,8 +30,10 @@ from zope.dottedname.resolve import resolve | ||||||
| from zope import schema | from zope import schema | ||||||
| from zope.security.proxy import removeSecurityProxy | from zope.security.proxy import removeSecurityProxy | ||||||
| from cybertools.typology.type import BaseType, TypeManager | from cybertools.typology.type import BaseType, TypeManager | ||||||
|  | from cybertools.typology.interfaces import ITypeManager | ||||||
| from loops.interfaces import ILoopsObject, IConcept, IResource | 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.concept import Concept | ||||||
| from loops.resource import Resource, Document, MediaAsset | from loops.resource import Resource, Document, MediaAsset | ||||||
| 
 | 
 | ||||||
|  | @ -92,7 +94,8 @@ class LoopsType(BaseType): | ||||||
| 
 | 
 | ||||||
|     @Lazy |     @Lazy | ||||||
|     def typeProvider(self): |     def typeProvider(self): | ||||||
|         return self.context.conceptType |         # TODO: unify this type attribute naming... | ||||||
|  |         return self.context.resourceType | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class LoopsTypeInfo(LoopsType): | class LoopsTypeInfo(LoopsType): | ||||||
|  | @ -110,6 +113,10 @@ class ConceptType(LoopsType): | ||||||
| 
 | 
 | ||||||
|     adapts(IConcept) |     adapts(IConcept) | ||||||
| 
 | 
 | ||||||
|  |     @Lazy | ||||||
|  |     def typeProvider(self): | ||||||
|  |         return self.context.conceptType | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| class ConceptTypeInfo(LoopsTypeInfo): | class ConceptTypeInfo(LoopsTypeInfo): | ||||||
|     """ The type info class used by the type manager for listing types. |     """ The type info class used by the type manager for listing types. | ||||||
|  | @ -233,8 +240,7 @@ class TypeInterfaceSourceList(object): | ||||||
| 
 | 
 | ||||||
|     implements(schema.interfaces.IIterableSource) |     implements(schema.interfaces.IIterableSource) | ||||||
| 
 | 
 | ||||||
|     #typeInterfaces = (ITypeConcept, IFile, IImage,) |     typeInterfaces = (ITypeConcept, IFile, ITextDocument) | ||||||
|     typeInterfaces = (ITypeConcept,) |  | ||||||
| 
 | 
 | ||||||
|     def __init__(self, context): |     def __init__(self, context): | ||||||
|         self.context = context |         self.context = context | ||||||
|  | @ -246,6 +252,25 @@ class TypeInterfaceSourceList(object): | ||||||
|         return len(self.typeInterfaces) |         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): | class AdapterBase(object): | ||||||
|     """ (Mix-in) Class for concept adapters that provide editing of fields |     """ (Mix-in) Class for concept adapters that provide editing of fields | ||||||
|         defined by the type interface. |         defined by the type interface. | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 helmutm
						helmutm