diff --git a/README.txt b/README.txt index 6a38c05..33e81d3 100755 --- a/README.txt +++ b/README.txt @@ -8,7 +8,7 @@ The loops platform is built up of three parts: (1) concepts: simple interconnected objects usually representing meta-information -(2) resources: (possibly large) atomic objects like documents and media assets +(2) resources: (possibly large) atomic objects like documents and files (3) views: objects (usually hierarchically organized nodes) providing access to and presenting concepts or resources @@ -31,8 +31,7 @@ Let's start with creating a few example concepts, putting them in a top-level loops container and a concept manager: >>> from loops import Loops - >>> site['loops'] = Loops() - >>> loopsRoot = site['loops'] + >>> loopsRoot = site['loops'] = Loops() >>> from loops.concept import ConceptManager, Concept >>> loopsRoot['concepts'] = ConceptManager() @@ -230,11 +229,11 @@ Index attributes adapter Resources and what they have to do with Concepts ================================================ - >>> from loops.interfaces import IResource, IDocument, IMediaAsset + >>> from loops.interfaces import IResource, IDocument We first need a resource manager: - >>> from loops.resource import ResourceManager + >>> from loops.resource import ResourceManager, Resource >>> loopsRoot['resources'] = ResourceManager() >>> resources = loopsRoot['resources'] @@ -251,11 +250,11 @@ A common type of resource is a document: >>> doc1.contentType u'' -Another one is a media asset: +We can also directly use Resource objects; these behave like files. +In fact, by using resource types we can explicitly assign a resource +the 'file' type, but we will use this feature later: - >>> from loops.interfaces import IMediaAsset - >>> from loops.resource import MediaAsset - >>> img = MediaAsset(u'A png Image') + >>> img = Resource(u'A png Image') For testing we use some simple files from the tests directory: @@ -270,7 +269,7 @@ For testing we use some simple files from the tests directory: >>> img.contentType 'image/png' - >>> pdf = MediaAsset(u'A pdf File') + >>> pdf = Resource(u'A pdf File') >>> pdf.data = open(os.path.join(path, 'test.pdf')).read() >>> pdf.getSize() 25862 @@ -499,8 +498,7 @@ view; these views we have to provide as multi-adapters: >>> sorted((t.token, t.title) for t in view.targetTypes()) [('.loops/concepts/topic', u'Topic'), ('.loops/concepts/type', u'Type'), ('.loops/concepts/unknown', u'Unknown Type'), - ('loops.resource.Document', u'Document'), - ('loops.resource.MediaAsset', u'Media Asset')] + ('loops.resource.Document', u'Document')] >>> view.update() True >>> sorted(resources.keys()) diff --git a/configure.zcml b/configure.zcml index 50928ed..d1e75b0 100644 --- a/configure.zcml +++ b/configure.zcml @@ -188,7 +188,9 @@ + interface=".interfaces.IBaseResource + zope.app.size.interfaces.ISized" /> + - + diff --git a/helpers.txt b/helpers.txt index 7c25b9e..b261971 100755 --- a/helpers.txt +++ b/helpers.txt @@ -12,7 +12,7 @@ Let's first do some basic imports >>> from zope.app.testing.setup import placefulSetUp, placefulTearDown >>> site = placefulSetUp(True) - + >>> from zope import interface, component >>> from zope.app import zapi >>> from zope.app.tests import ztapi @@ -25,7 +25,7 @@ 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 @@ -35,7 +35,7 @@ and care for some type adapter machinery: Now we can setup a simple loops site with its manager objects, using a loops setup manager: - + >>> from loops import Loops >>> loopsRoot = site['loops'] = Loops() @@ -46,7 +46,7 @@ loops setup manager: u'has Type' We also add some example concepts, - + >>> from loops.concept import Concept >>> cc1 = Concept(u'Zope') >>> concepts['cc1'] = cc1 @@ -59,21 +59,21 @@ 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:) +(the use of Document may get deprecated soon:) - >>> from loops.resource import Document, MediaAsset + >>> from loops.resource import Document >>> doc1 = Document(u'Zope Info') >>> resources['doc1'] = doc1 >>> doc1.title u'Zope Info' - >>> img1 = MediaAsset(u'An Image') - >>> resources['img1'] = img1 + >>> img1 = resources['img1'] = Resource(u'An Image') + >>> img1.resourceType = concepts['file'] and nodes (in view space): @@ -81,7 +81,7 @@ and nodes (in view space): >>> m1 = Node(u'Home') >>> views['m1'] = m1 >>> m1.nodeType = 'menu' - + >>> m1p1 = Node(u'Page') >>> m1['p1'] = m1p1 >>> m1p1.nodeType = 'page' @@ -160,7 +160,7 @@ lazy properties, one should always get a new adapter: Now let's have a look at resources. - + >>> from loops.interfaces import IResource >>> from loops.type import LoopsType >>> component.provideAdapter(LoopsType, (IResource,), IType) @@ -177,12 +177,12 @@ Now let's have a look at resources. >>> file1_type.factory - -(The use of Document and MediaAsset will be deprecated soon...) - >>> from loops.interfaces import IResource +(The use of Document will be deprecated soon...) + + >>> from loops.interfaces import IResource, IDocument >>> from loops.type import ResourceType - >>> ztapi.provideAdapter(IResource, IType, ResourceType) + >>> ztapi.provideAdapter(IDocument, IType, ResourceType) >>> doc1_type = IType(doc1) >>> doc1_type.title @@ -197,10 +197,14 @@ Now let's have a look at resources. >>> doc1_type.factory - + >>> img1_type = IType(img1) + >>> img1_type.token + '.loops/concepts/file' + >>> img1_type.tokenForSearch + 'loops:resource:file' >>> img1_type.title - u'Media Asset' + u'File' Can we find out somehow which types are available? This is the time to look for a type manager. This could be a utility; but in the loops package it @@ -217,10 +221,10 @@ get a type manager from all loops objects, always with the same context: >>> types = typeManager.types >>> 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'] + ['.loops/concepts/file', '.loops/concepts/image', '.loops/concepts/predicate', + '.loops/concepts/textdocument', '.loops/concepts/topic', + '.loops/concepts/type', + 'loops.resource.Document'] >>> typeManager.getType('.loops/concepts/topic') == cc1_type True @@ -233,9 +237,8 @@ condition: ['.loops/concepts/predicate', '.loops/concepts/topic', '.loops/concepts/type'] >>> types = typeManager.listTypes(exclude=('concept',)) >>> sorted(t.token for t in types) - ['.loops/concepts/file', '.loops/concepts/image', - '.loops/concepts/textdocument', 'loops.resource.Document', - 'loops.resource.MediaAsset'] + ['.loops/concepts/file', '.loops/concepts/image', + '.loops/concepts/textdocument', 'loops.resource.Document'] Type-based interfaces and adapters @@ -264,7 +267,7 @@ i.e. the 'topic' concept, via an adapter: ... implements(ITopic) ... def __init__(self, context): pass >>> component.provideAdapter(Topic, (IConcept,), ITopic) - + >>> ITypeConcept(topic).typeInterface = ITopic >>> cc1.conceptType = topic @@ -308,7 +311,7 @@ the concept... ...but only when the view exists, i.e. there is a class registered as a view/multi-adapter with this name: - + >>> sq_view is sq_baseView True @@ -368,7 +371,7 @@ browser). >>> from loops.browser.node import ViewPropertiesConfigurator >>> component.provideAdapter(ViewPropertiesConfigurator, (INode,), ... IViewConfiguratorSchema) - + >>> pageConfigurator = IViewConfiguratorSchema(m1) >>> pageConfigurator.skinName = 'SuperSkin' diff --git a/interfaces.py b/interfaces.py index 5229138..d78c07c 100644 --- a/interfaces.py +++ b/interfaces.py @@ -305,21 +305,14 @@ class IDocument(IDocumentSchema, IResource): """ -class IMediaAssetSchema(IResourceSchema): +# media asset is probably obsolete - replaced by plain Resource with +# resourceType = file. - data = schema.Bytes( - title=_(u'Data'), - description=_(u'Media asset file'), - default='', - missing_value='', - required=False) - - -class IMediaAssetView(IMediaAssetSchema): +class IMediaAssetView(IResourceSchema): """ Used for accessing a media asset via a node's target attribute""" -class IMediaAsset(IMediaAssetSchema, IResource, IBaseAsset): +class IMediaAsset(IResourceSchema, IResource, IBaseAsset): """ A resource containing a (typically binary) file-like content or an image. """ diff --git a/resource.py b/resource.py index 1dc9904..606208f 100644 --- a/resource.py +++ b/resource.py @@ -46,7 +46,7 @@ from cybertools.typology.interfaces import ITypeManager from interfaces import IBaseResource, IResource from interfaces import IFile from interfaces import IDocument, IDocumentSchema, IDocumentView -from interfaces import IMediaAsset, IMediaAssetSchema, IMediaAssetView +from interfaces import IMediaAsset, IMediaAssetView from interfaces import IResourceManager, IResourceManagerContained from interfaces import ILoopsContained from interfaces import IIndexAttributes @@ -192,9 +192,6 @@ class FileAdapter(ResourceAdapterBase): implements(IFile) - # TODO: provide specialized access to data attribute analog to zope.app.file; - # automatically set contentType... - class DocumentWriteFileAdapter(object): diff --git a/type.py b/type.py index 160bfa9..f2c4bfd 100644 --- a/type.py +++ b/type.py @@ -133,7 +133,8 @@ class ResourceType(LoopsType): #adapts(IResource) - typeTitles = {'MediaAsset': u'Media Asset'} + #typeTitles = {'MediaAsset': u'Media Asset'} + typeTitles = {} typeInterface = None qualifiers = ('resource',) @@ -212,7 +213,8 @@ class LoopsTypeManager(TypeManager): def resourceTypes(self): return tuple([ResourceTypeInfo(self.context, cls) - for cls in (Document, MediaAsset)]) + for cls in (Document,)]) + #for cls in (Document, MediaAsset)]) class TypeConcept(AdapterBase):