diff --git a/browser/common.py b/browser/common.py index 2ef9181..2ba109d 100644 --- a/browser/common.py +++ b/browser/common.py @@ -27,7 +27,9 @@ from zope.app.dublincore.interfaces import ICMFDublinCore from zope.app.form.browser.interfaces import ITerms from zope.app.intid.interfaces import IIntIds from zope.cachedescriptors.property import Lazy +from zope.dottedname.resolve import resolve from zope.interface import implements +from zope.schema.vocabulary import SimpleTerm from zope.security.proxy import removeSecurityProxy from cybertools.typology.interfaces import IType @@ -116,3 +118,21 @@ class LoopsTerms(object): return self.loopsRoot.loopsTraverse(token) +class InterfaceTerms(object): + """ Provide the ITerms interface for source list of interfaces. + """ + + implements(ITerms) + + def __init__(self, source, request): + self.source = source + self.request = request + + def getTerm(self, value): + token = '.'.join((value.__module__, value.__name__)) + return SimpleTerm(value, token, token) + + def getValue(self, token): + return resolve(token) + + diff --git a/browser/concept.py b/browser/concept.py index 52d8d01..fb5af05 100644 --- a/browser/concept.py +++ b/browser/concept.py @@ -39,7 +39,7 @@ from zope.publisher.interfaces.browser import IBrowserRequest from zope import schema from zope.schema.interfaces import IIterableSource from zope.security.proxy import removeSecurityProxy -from cybertools.typology.interfaces import ITypeManager +from cybertools.typology.interfaces import IType, ITypeManager from loops.interfaces import IConcept from loops.concept import Concept, ConceptTypeSourceList, PredicateSourceList from loops.browser.common import BaseView, LoopsTerms @@ -48,9 +48,25 @@ from loops import util class ConceptEditForm(EditForm): - form_fields = FormFields(IConcept) template = NamedTemplate('pageform') + @Lazy + def typeInterface(self): + print IType(self.context) + print IType(self.context).typeInterface + return IType(self.context).typeInterface + + @property + def form_fields(self): + fields = FormFields(IConcept) + typeInterface = self.typeInterface + if typeInterface is not None: + fields = FormFields(fields, typeInterface) + #typeAdapter = zapi.queryAdapter(self.context, typeInterface) + #if typeAdapter is not None: + #... + return fields + class ConceptView(BaseView): diff --git a/browser/configure.zcml b/browser/configure.zcml index aeb3bdc..728c436 100644 --- a/browser/configure.zcml +++ b/browser/configure.zcml @@ -478,6 +478,10 @@ for="loops.concept.PredicateSourceList zope.publisher.interfaces.browser.IBrowserRequest" /> + + + + >> sorted(t.token for t in types) ['loops.resource.Document', 'loops.resource.MediaAsset'] -Type-based interfaces ---------------------- +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: + >>> cc1_type.typeInterface >>> cc1_type.typeInterface is None True For concept objects that provide types (type providers) the value of the typeInterface attribute is the ITypeConcept interface: - >>> from loops.interfaces import ITypeConcept >>> topic_type.typeInterface is ITypeConcept True -We now want to have a topic (i.e. a concept that has topic_type as its type) -to provide the interface ITopic. This is done by assigning this interface -to topic_type.typeProvider, i.e. the 'topic' concept, via an adapter: - - >>> from loops.type import TypeConcept - >>> ztapi.provideAdapter(IConcept, ITypeConcept, TypeConcept) +We now want to have a topic (i.e. a concept that has topic as its +conceptType and thus topic_type as its type) to be adaptable to ITopic. +This is done by assigning this interface to topic_type.typeProvider, +i.e. the 'topic' concept, via an adapter: >>> class ITopic(Interface): pass >>> from zope.interface import implements diff --git a/interfaces.py b/interfaces.py index bfcb5d6..d59ea62 100644 --- a/interfaces.py +++ b/interfaces.py @@ -473,9 +473,14 @@ class IIndexAttributes(Interface): # types stuff class ITypeConcept(Interface): - """ This interface should be provided by concepts of type 'type'. + """ Concepts of type 'type' should be adaptable to this interface. """ - typeInterface = Attribute('The interface provided by objects of this type') - + typeInterface = schema.Choice( + title=_(u'Type Interface'), + description=_(u'An interface that objects of this type can ' + 'be adapted to'), + default=None, + source="loops.TypeInterfaceSource", + required=False) diff --git a/type.py b/type.py index 2673534..84e20ba 100644 --- a/type.py +++ b/type.py @@ -27,6 +27,8 @@ from zope.component import adapts from zope.interface import implements from zope.cachedescriptors.property import Lazy from zope.dottedname.resolve import resolve +from zope import schema +from zope.security.proxy import removeSecurityProxy from cybertools.typology.type import BaseType, TypeManager from loops.interfaces import ILoopsObject, IConcept, IResource from loops.interfaces import ITypeConcept @@ -58,7 +60,7 @@ class LoopsType(BaseType): class ConceptType(LoopsType): - """ The type adapter for concept objects. + """ The IType adapter for concept objects. """ adapts(IConcept) @@ -77,11 +79,11 @@ class ConceptType(LoopsType): @Lazy def typeInterface(self): adapter = zapi.queryAdapter(self.typeProvider, ITypeConcept) - if adapter is not None: + if adapter is not None: # always gives TypeConcept return adapter.typeInterface else: - conceptType = self.context.conceptType - if conceptType is conceptType.getConceptManager().getTypeConcept(): + conceptType = self.typeProvider + if conceptType is conceptType.getLoopsRoot().getConceptManager().getTypeConcept(): return ITypeConcept return None @@ -177,17 +179,39 @@ class LoopsTypeManager(TypeManager): class TypeConcept(object): + """ typeInterface adapter for concepts of type 'type'. + """ implements(ITypeConcept) adapts(IConcept) def __init__(self, context): - self.context = context + self.context = removeSecurityProxy(context) def getTypeInterface(self): - return getattr(self.context, '_typeInterface', None) + ti = getattr(self.context, '_typeInterface', None) + if ti is None: + conceptType = self.context + if conceptType == conceptType.getLoopsRoot().getConceptManager().getTypeConcept(): + return ITypeConcept + return ti def setTypeInterface(self, ifc): self.context._typeInterface = ifc typeInterface = property(getTypeInterface, setTypeInterface) +class TypeInterfaceSourceList(object): + + implements(schema.interfaces.IIterableSource) + + typeInterfaces = (ITypeConcept,) + + def __init__(self, context): + self.context = context + + def __iter__(self): + return iter(self.typeInterfaces) + + def __len__(self): + return len(self.typeInterfaces) +