provide system qualifier for type type and predicate, check it when searching; + some minor refactorings
git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@1605 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
a2932828fb
commit
6e3e08c781
15 changed files with 146 additions and 88 deletions
|
@ -140,6 +140,13 @@ class BaseView(GenericView):
|
|||
def value(self):
|
||||
return self.context
|
||||
|
||||
@Lazy
|
||||
def uniqueId(self):
|
||||
return util.getUidForObject(self.context)
|
||||
#return zapi.getUtility(IRelationRegistry).getUniqueIdForObject(self.context)
|
||||
|
||||
# type stuff
|
||||
|
||||
@Lazy
|
||||
def type(self):
|
||||
return IType(self.context)
|
||||
|
@ -174,35 +181,47 @@ class BaseView(GenericView):
|
|||
for o in objs:
|
||||
yield BaseView(o, request)
|
||||
|
||||
# type listings
|
||||
|
||||
def listTypes(self, include=None, exclude=None, sortOn='title'):
|
||||
types = [dict(token=t.token, title=t.title)
|
||||
for t in ITypeManager(self.context).listTypes(include, exclude)]
|
||||
if sortOn:
|
||||
types.sort(key=lambda x: x[sortOn])
|
||||
return types
|
||||
|
||||
def resourceTypes(self):
|
||||
return util.KeywordVocabulary([(t.token, t.title)
|
||||
for t in ITypeManager(self.context).listTypes(('resource',))
|
||||
if t.factory == Resource])
|
||||
return util.KeywordVocabulary(self.listTypes(('resource',) ('hidden',)))
|
||||
#if t.factory == Resource]) # ? if necessary -> type.qualifiers
|
||||
|
||||
def conceptTypes(self):
|
||||
return util.KeywordVocabulary([(t.token, t.title)
|
||||
for t in ITypeManager(self.context).listTypes(('concept',))])
|
||||
return util.KeywordVocabulary(self.listTypes(('concept',), ('hidden',)))
|
||||
|
||||
def listTypesForSearch(self, include=None, exclude=None, sortOn='title'):
|
||||
types = [dict(token=t.tokenForSearch, title=t.title)
|
||||
for t in ITypeManager(self.context).listTypes(include, exclude)]
|
||||
if sortOn:
|
||||
types.sort(key=lambda x: x[sortOn])
|
||||
return types
|
||||
|
||||
def typesForSearch(self):
|
||||
general = [('loops:resource:*', 'Any Resource'),
|
||||
('loops:concept:*', 'Any Concept'),]
|
||||
return util.KeywordVocabulary(general + sorted([(t.tokenForSearch, t.title)
|
||||
for t in ITypeManager(self.context).types])
|
||||
+ [('loops:*', 'Any')])
|
||||
return util.KeywordVocabulary(general
|
||||
+ self.listTypesForSearch(exclude=('system', 'hidden',))
|
||||
+ [('loops:*', 'Any')])
|
||||
|
||||
def conceptTypesForSearch(self):
|
||||
general = [('loops:concept:*', 'Any Concept'),]
|
||||
return util.KeywordVocabulary(general + [(t.tokenForSearch, t.title)
|
||||
for t in ITypeManager(self.context).listTypes(('concept',))])
|
||||
return util.KeywordVocabulary(general
|
||||
+ self.listTypesForSearch(('concept',), ('system', 'hidden',),))
|
||||
|
||||
def resourceTypesForSearch(self):
|
||||
general = [('loops:resource:*', 'Any Resource'),]
|
||||
return util.KeywordVocabulary(general + [(t.tokenForSearch, t.title)
|
||||
for t in ITypeManager(self.context).listTypes(('resource',))])
|
||||
return util.KeywordVocabulary(general
|
||||
+ self.listTypesForSearch(('resource',), ('system', 'hidden'),))
|
||||
|
||||
@Lazy
|
||||
def uniqueId(self):
|
||||
return zapi.getUtility(IRelationRegistry).getUniqueIdForObject(self.context)
|
||||
# controllling editing
|
||||
|
||||
@Lazy
|
||||
def editable(self):
|
||||
|
|
16
common.py
16
common.py
|
@ -42,29 +42,31 @@ class AdapterBase(object):
|
|||
|
||||
adapts(IConcept)
|
||||
|
||||
_attributes = ('context', '__parent__', )
|
||||
_schemas = list(IConcept)
|
||||
_adapterAttributes = ('context', '__parent__', )
|
||||
_contextAttributes = list(IConcept)
|
||||
|
||||
def __init__(self, context):
|
||||
self.context = context # to get the permission stuff right
|
||||
self.__parent__ = context
|
||||
self.context = context
|
||||
self.__parent__ = context # to get the permission stuff right
|
||||
|
||||
def __getattr__(self, attr):
|
||||
self.checkAttr(attr)
|
||||
return getattr(self.context, '_' + attr, None)
|
||||
|
||||
def __setattr__(self, attr, value):
|
||||
if attr in self._attributes:
|
||||
if attr in self._adapterAttributes:
|
||||
object.__setattr__(self, attr, value)
|
||||
else:
|
||||
self.checkAttr(attr)
|
||||
setattr(self.context, '_' + attr, value)
|
||||
|
||||
def checkAttr(self, attr):
|
||||
if attr not in self._schemas:
|
||||
if attr not in self._contextAttributes:
|
||||
raise AttributeError(attr)
|
||||
|
||||
def __eq__(self, other):
|
||||
if other is None:
|
||||
return False
|
||||
return self.context == other.context
|
||||
|
||||
|
||||
|
@ -72,7 +74,7 @@ class ResourceAdapterBase(AdapterBase):
|
|||
|
||||
adapts(IResource)
|
||||
|
||||
_schemas = list(IResourceAdapter)
|
||||
_contextAttributes = list(IResourceAdapter)
|
||||
|
||||
|
||||
# other adapters
|
||||
|
|
19
concept.py
19
concept.py
|
@ -149,10 +149,6 @@ class Concept(Contained, Persistent):
|
|||
|
||||
def deassignChild(self, child, predicates=None):
|
||||
registry = zapi.getUtility(IRelationRegistry)
|
||||
#relations = []
|
||||
#for rs in relationships:
|
||||
# relations.extend(registry.query(first=self, second=concept,
|
||||
# relationship=rs))
|
||||
for rel in self.getChildRelations(predicates, child):
|
||||
registry.unregister(rel)
|
||||
|
||||
|
@ -192,6 +188,7 @@ class ConceptManager(BTreeContainer):
|
|||
typeConcept = None
|
||||
typePredicate = None
|
||||
defaultPredicate = None
|
||||
predicateType = None
|
||||
|
||||
def getLoopsRoot(self):
|
||||
return zapi.getParent(self)
|
||||
|
@ -209,19 +206,27 @@ class ConceptManager(BTreeContainer):
|
|||
self.defaultPredicate = self['standard']
|
||||
return self.defaultPredicate
|
||||
|
||||
def getPredicateType(self):
|
||||
if self.predicateType is None:
|
||||
dp = self.getDefaultPredicate()
|
||||
self.predicateType = dp.conceptType
|
||||
return self.predicateType
|
||||
|
||||
def getViewManager(self):
|
||||
return self.getLoopsRoot().getViewManager()
|
||||
|
||||
|
||||
# adapters and similar components
|
||||
|
||||
class ConceptSourceList(object):
|
||||
class xxxConceptSourceList(object):
|
||||
|
||||
# seems to be obsolete
|
||||
|
||||
implements(schema.interfaces.IIterableSource)
|
||||
|
||||
def __init__(self, context):
|
||||
#self.context = context
|
||||
self.context = removeSecurityProxy(context)
|
||||
self.context = context
|
||||
#self.context = removeSecurityProxy(context)
|
||||
root = self.context.getLoopsRoot()
|
||||
self.concepts = root.getConceptManager()
|
||||
|
||||
|
|
|
@ -78,7 +78,8 @@
|
|||
|
||||
<require
|
||||
permission="zope.View"
|
||||
attributes="getTypePredicate getDefaultPredicate getTypeConcept" />
|
||||
attributes="getTypePredicate getDefaultPredicate getTypeConcept
|
||||
getPredicateType" />
|
||||
|
||||
</class>
|
||||
|
||||
|
|
|
@ -130,7 +130,7 @@ So let's check the type of the type object:
|
|||
>>> type_type.tokenForSearch
|
||||
'loops:concept:type'
|
||||
>>> type_type.qualifiers
|
||||
('concept',)
|
||||
('concept', 'system')
|
||||
|
||||
Now we register another type ('topic') and assign it to cc1:
|
||||
|
||||
|
@ -151,7 +151,7 @@ lazy properties, one should always get a new adapter:
|
|||
>>> cc1_type.typeProvider == topic
|
||||
True
|
||||
>>> topic_type.qualifiers
|
||||
('concept',)
|
||||
('concept', 'system')
|
||||
>>> topic_type.defaultContainer
|
||||
<loops.concept.ConceptManager object ...>
|
||||
>>> topic_type.factory
|
||||
|
|
|
@ -155,23 +155,30 @@ class IConceptView(Interface):
|
|||
""" Used for accessing a concept via a node's target attribute"""
|
||||
|
||||
|
||||
class IConceptManager(ILoopsObject, IContainer):
|
||||
#class IConceptManager(ILoopsObject, IContainer):
|
||||
class IConceptManager(ILoopsObject):
|
||||
""" A manager/container for concepts.
|
||||
"""
|
||||
contains(IConcept)
|
||||
|
||||
def getTypeConcept():
|
||||
""" Return the concept that provides the type object,
|
||||
i.e. the type of all types.
|
||||
"""
|
||||
|
||||
def getTypePredicate():
|
||||
""" Return the concept that provides the type predicate.
|
||||
"""
|
||||
|
||||
def getTypeConcept():
|
||||
""" Return the concept that provides the type object.
|
||||
"""
|
||||
|
||||
def getDefaultPredicate():
|
||||
""" Return the concept that provides the default (standard) predicate.
|
||||
"""
|
||||
|
||||
def getPredicateType():
|
||||
""" Return the concept that provides the predicate type object,
|
||||
i.e. the type of all predicates.
|
||||
"""
|
||||
|
||||
class IConceptManagerContained(Interface):
|
||||
containers(IConceptManager)
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ class Topic(AdapterBase, KnowledgeAdapterMixin):
|
|||
"""
|
||||
|
||||
implements(IKnowledgeElement)
|
||||
_attributes = ('context', '__parent__', 'parent')
|
||||
_adapterAttributes = ('context', '__parent__', 'parent')
|
||||
|
||||
def getParent(self):
|
||||
parents = self.context.getParents((self.standardPred,))
|
||||
|
|
|
@ -72,8 +72,8 @@ class Person(AdapterBase, BasePerson):
|
|||
|
||||
implements(IPerson)
|
||||
|
||||
_attributes = ('context', '__parent__', 'userId', 'phoneNumbers')
|
||||
_schemas = list(IPerson) + list(IConcept)
|
||||
_adapterAttributes = ('context', '__parent__', 'userId', 'phoneNumbers')
|
||||
_contextAttributes = list(IPerson) + list(IConcept)
|
||||
|
||||
def getUserId(self):
|
||||
return getattr(self.context, '_userId', None)
|
||||
|
@ -162,8 +162,8 @@ class Address(AdapterBase):
|
|||
|
||||
implements(IAddress)
|
||||
|
||||
_attributes = ('context', '__parent__', 'lines')
|
||||
_schemas = list(IAddress) + list(IConcept)
|
||||
_adapterAttributes = ('context', '__parent__', 'lines')
|
||||
_contextAttributes = list(IAddress) + list(IConcept)
|
||||
|
||||
def getLines(self):
|
||||
return getattr(self.context, '_lines', [])
|
||||
|
|
|
@ -39,6 +39,6 @@ class Task(AdapterBase):
|
|||
|
||||
implements(ITask)
|
||||
|
||||
_attributes = ('context', '__parent__',)
|
||||
_schemas = list(ITask) + list(IConcept)
|
||||
_adapterAttributes = ('context', '__parent__',)
|
||||
_contextAttributes = list(ITask) + list(IConcept)
|
||||
|
||||
|
|
22
query.py
22
query.py
|
@ -28,6 +28,7 @@ from zope import traversing
|
|||
from zope.app.catalog.interfaces import ICatalog
|
||||
from zope.cachedescriptors.property import Lazy
|
||||
|
||||
from cybertools.typology.interfaces import IType
|
||||
from loops.interfaces import IConcept
|
||||
from loops.common import AdapterBase
|
||||
from loops.type import TypeInterfaceSourceList
|
||||
|
@ -59,7 +60,7 @@ class BaseQuery(object):
|
|||
def loopsRoot(self):
|
||||
return self.context.context.getLoopsRoot()
|
||||
|
||||
def queryConcepts(self, title=None, type=None):
|
||||
def queryConcepts(self, title=None, type=None, **kw):
|
||||
if type.endswith('*'):
|
||||
start = type[:-1]
|
||||
end = start + '\x7f'
|
||||
|
@ -71,16 +72,23 @@ class BaseQuery(object):
|
|||
else:
|
||||
result = cat.searchResults(loops_type=(start, end))
|
||||
result = set(r for r in result if r.getLoopsRoot() == self.loopsRoot)
|
||||
if 'exclude' in kw:
|
||||
r1 = set()
|
||||
for r in result:
|
||||
qur = IType(r).qualifiers
|
||||
if not [qux for qux in kw['exclude'] if qux in qur]:
|
||||
r1.add(r)
|
||||
result = r1
|
||||
return result
|
||||
|
||||
def queryConceptsWithChildren(self, title=None, type=None, uid=None):
|
||||
def queryConceptsWithChildren(self, title=None, type=None, uid=None, **kw):
|
||||
if title: # there are a few characters that the index doesn't like
|
||||
title = title.replace('(', ' ').replace(')', ' ')
|
||||
if not title and not uid and (type is None or '*' in type):
|
||||
return None
|
||||
result = set()
|
||||
if not uid:
|
||||
queue = list(self.queryConcepts(title=title, type=type))
|
||||
queue = list(self.queryConcepts(title=title, type=type, **kw))
|
||||
else:
|
||||
queue = [util.getObjectForUid(uid)]
|
||||
concepts = []
|
||||
|
@ -100,7 +108,7 @@ class BaseQuery(object):
|
|||
class FullQuery(BaseQuery):
|
||||
|
||||
def query(self, text=None, type=None, useTitle=True, useFull=False,
|
||||
conceptTitle=None, conceptUid=None, conceptType=None):
|
||||
conceptTitle=None, conceptUid=None, conceptType=None, **kw):
|
||||
result = set()
|
||||
rc = self.queryConceptsWithChildren(title=conceptTitle, uid=conceptUid,
|
||||
type=conceptType)
|
||||
|
@ -136,10 +144,10 @@ class ConceptQuery(BaseQuery):
|
|||
""" Find concepts of type `type` whose title starts with `title`.
|
||||
"""
|
||||
|
||||
def query(self, title=None, type=None):
|
||||
def query(self, title=None, type=None, **kw):
|
||||
if title and not title.endswith('*'):
|
||||
title += '*'
|
||||
return self.queryConcepts(title=title, type=type)
|
||||
return self.queryConcepts(title=title, type=type, **kw)
|
||||
|
||||
|
||||
# QueryConcept: concept objects that allow querying the database.
|
||||
|
@ -161,7 +169,7 @@ class QueryConcept(AdapterBase):
|
|||
|
||||
implements(IQueryConcept)
|
||||
|
||||
_schemas = list(IQueryConcept) + list(IConcept)
|
||||
_contextAttributes = list(IQueryConcept) + list(IConcept)
|
||||
|
||||
|
||||
TypeInterfaceSourceList.typeInterfaces += (IQueryConcept,)
|
||||
|
|
11
resource.py
11
resource.py
|
@ -200,10 +200,9 @@ class FileAdapter(ResourceAdapterBase):
|
|||
"""
|
||||
|
||||
implements(IFile)
|
||||
_schemas = list(IFile) + list(IBaseResource)
|
||||
|
||||
# let the adapter handle the data attribute:
|
||||
_attributes = ResourceAdapterBase._attributes + ('data',)
|
||||
_contextAttributes = list(IFile) + list(IBaseResource)
|
||||
_adapterAttributes = ResourceAdapterBase._adapterAttributes + ('data',)
|
||||
|
||||
def setData(self, data): self.context.data = data
|
||||
def getData(self): return self.context.data
|
||||
|
@ -251,7 +250,7 @@ class DocumentAdapter(ResourceAdapterBase):
|
|||
"""
|
||||
|
||||
# let the adapter handle the data attribute:
|
||||
_attributes = ResourceAdapterBase._attributes + ('data',)
|
||||
_adapterAttributes = ResourceAdapterBase._adapterAttributes + ('data',)
|
||||
|
||||
def setData(self, data): self.context._data = data.replace('\r', '')
|
||||
def getData(self): return self.context._data
|
||||
|
@ -263,7 +262,7 @@ class TextDocumentAdapter(DocumentAdapter):
|
|||
"""
|
||||
|
||||
implements(IDocument)
|
||||
_schemas = list(IDocument) + list(IBaseResource)
|
||||
_contextAttributes = list(IDocument) + list(IBaseResource)
|
||||
|
||||
|
||||
class NoteAdapter(DocumentAdapter):
|
||||
|
@ -271,7 +270,7 @@ class NoteAdapter(DocumentAdapter):
|
|||
"""
|
||||
|
||||
implements(INote)
|
||||
_schemas = list(INote) + list(IBaseResource)
|
||||
_contextAttributes = list(INote) + list(IBaseResource)
|
||||
|
||||
|
||||
# other adapters
|
||||
|
|
|
@ -78,13 +78,13 @@ zcml in real life:
|
|||
|
||||
>>> t = searchView.typesForSearch()
|
||||
>>> len(t)
|
||||
11
|
||||
9
|
||||
>>> t.getTermByToken('loops:resource:*').title
|
||||
'Any Resource'
|
||||
|
||||
>>> t = searchView.conceptTypesForSearch()
|
||||
>>> len(t)
|
||||
5
|
||||
3
|
||||
>>> t.getTermByToken('loops:concept:*').title
|
||||
'Any Concept'
|
||||
|
||||
|
|
|
@ -77,11 +77,11 @@ class Search(BaseView):
|
|||
request.response.setHeader('Content-Type', 'text/plain; charset=UTF-8')
|
||||
title = request.get('searchString', '').replace('(', ' ').replace(')', ' ')
|
||||
type = request.get('searchType') or 'loops:concept:*'
|
||||
result = ConceptQuery(self).query(title=title, type=type)
|
||||
registry = component.getUtility(IRelationRegistry)
|
||||
result = ConceptQuery(self).query(title=title, type=type, exclude=('system',))
|
||||
#registry = component.getUtility(IRelationRegistry)
|
||||
# simple way to provide JSON format:
|
||||
return str(sorted([[`o.title`[2:-1] + ' (%s)' % `o.conceptType.title`[2:-1],
|
||||
`registry.getUniqueIdForObject(o)`]
|
||||
`int(util.getUidForObject(o))`]
|
||||
for o in result
|
||||
if o.getLoopsRoot() == self.loopsRoot])).replace('\\\\x', '\\x')
|
||||
#return str(sorted([[`o.title`[2:-1], `traversing.api.getName(o)`[2:-1]]
|
||||
|
|
57
type.py
57
type.py
|
@ -22,13 +22,14 @@ Type management stuff.
|
|||
$Id$
|
||||
"""
|
||||
|
||||
from zope.app import zapi
|
||||
from zope import component, schema
|
||||
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 zope.traversing.api import getName
|
||||
|
||||
from cybertools.typology.type import BaseType, TypeManager
|
||||
from cybertools.typology.interfaces import ITypeManager
|
||||
from loops.interfaces import ILoopsObject, IConcept, IResource
|
||||
|
@ -44,7 +45,8 @@ class LoopsType(BaseType):
|
|||
|
||||
adapts(ILoopsObject)
|
||||
|
||||
factoryMapping = dict(concept=Concept, resource=Resource, document=Document)
|
||||
factoryMapping = dict(concept=Concept, resource=Resource)
|
||||
#document=Document)
|
||||
containerMapping = dict(concept='concepts', resource='resources')
|
||||
|
||||
@Lazy
|
||||
|
@ -60,27 +62,31 @@ class LoopsType(BaseType):
|
|||
@Lazy
|
||||
def tokenForSearch(self):
|
||||
tp = self.typeProvider
|
||||
typeName = tp is None and 'unknown' or str(zapi.getName(tp))
|
||||
typeName = tp is None and 'unknown' or str(getName(tp))
|
||||
return ':'.join(('loops', self.qualifiers[0], typeName,))
|
||||
|
||||
@Lazy
|
||||
def typeInterface(self):
|
||||
adapter = zapi.queryAdapter(self.typeProvider, ITypeConcept)
|
||||
adapter = component.queryAdapter(self.typeProvider, ITypeConcept)
|
||||
if adapter is not None:
|
||||
return removeSecurityProxy(adapter.typeInterface)
|
||||
else:
|
||||
conceptType = self.typeProvider
|
||||
typeConcept = self.root.getConceptManager().getTypeConcept()
|
||||
if conceptType is typeConcept:
|
||||
return ITypeConcept
|
||||
if self.typeProvider is self.typeConcept:
|
||||
return ITypeConcept # typeConcept always is a type concept
|
||||
return None
|
||||
|
||||
@Lazy
|
||||
def qualifiers(self):
|
||||
ti = self.typeInterface
|
||||
if ti is None or not issubclass(ti, IResourceAdapter):
|
||||
return ('concept',)
|
||||
return ('resource',)
|
||||
qu = ['concept',]
|
||||
else:
|
||||
qu = ['resource',]
|
||||
# check typeProvider for additional qualifiers:
|
||||
if self.typeProvider in (self.typeConcept, self.predicateType,):
|
||||
qu.append('system')
|
||||
# how to set a type to 'hidden'?
|
||||
return tuple(qu)
|
||||
|
||||
@Lazy
|
||||
def factory(self):
|
||||
|
@ -91,10 +97,6 @@ class LoopsType(BaseType):
|
|||
def defaultContainer(self):
|
||||
return self.root[self.containerMapping.get(self.qualifiers[0], 'concept')]
|
||||
|
||||
@Lazy
|
||||
def root(self):
|
||||
return self.context.getLoopsRoot()
|
||||
|
||||
@Lazy
|
||||
def typeProvider(self):
|
||||
# TODO: unify this type attribute naming...
|
||||
|
@ -115,6 +117,20 @@ class LoopsType(BaseType):
|
|||
result['default'].append(opt)
|
||||
return result
|
||||
|
||||
# general infos
|
||||
|
||||
@Lazy
|
||||
def root(self):
|
||||
return self.context.getLoopsRoot()
|
||||
|
||||
@Lazy
|
||||
def typeConcept(self):
|
||||
return self.root.getConceptManager().getTypeConcept()
|
||||
|
||||
@Lazy
|
||||
def predicateType(self):
|
||||
return self.root.getConceptManager().getPredicateType()
|
||||
|
||||
|
||||
class LoopsTypeInfo(LoopsType):
|
||||
""" The type info class used by the type manager for listing types.
|
||||
|
@ -144,13 +160,10 @@ class ConceptTypeInfo(LoopsTypeInfo):
|
|||
|
||||
class ResourceType(LoopsType):
|
||||
""" The 'old-style' resource type - different classes (Document, MediaAsset)
|
||||
per type. Will be replaced by new style types that are governed by
|
||||
per type. Are replaced by new style types that are governed by
|
||||
type concepts as is already the case for concepts.
|
||||
"""
|
||||
|
||||
#adapts(IResource)
|
||||
|
||||
#typeTitles = {'MediaAsset': u'Media Asset'}
|
||||
typeTitles = {}
|
||||
|
||||
typeInterface = None
|
||||
|
@ -165,8 +178,6 @@ class ResourceType(LoopsType):
|
|||
@Lazy
|
||||
def token(self):
|
||||
return '.'.join((self.factory.__module__, self.className))
|
||||
#cn = self.className
|
||||
#return '/'.join(('.loops/resources', cn.lower(),))
|
||||
|
||||
@Lazy
|
||||
def tokenForSearch(self):
|
||||
|
@ -240,7 +251,7 @@ class TypeConcept(AdapterBase):
|
|||
|
||||
implements(ITypeConcept)
|
||||
|
||||
_schemas = list(ITypeConcept) + list(IConcept)
|
||||
_contextAttributes = list(ITypeConcept) + list(IConcept)
|
||||
|
||||
def getTypeInterface(self):
|
||||
ti = getattr(self.context, '_typeInterface', None)
|
||||
|
@ -255,10 +266,8 @@ class TypeConcept(AdapterBase):
|
|||
|
||||
def getOptions(self):
|
||||
return getattr(self.context, '_options', [])
|
||||
#return super(TypeConcept, self).options or []
|
||||
def setOptions(self, value):
|
||||
self.context._options = value
|
||||
#super(TypeConcept, self).options = value
|
||||
options = property(getOptions, setOptions)
|
||||
|
||||
|
||||
|
|
12
util.py
12
util.py
|
@ -36,8 +36,16 @@ _ = MessageFactory('zope') # it's easier not use a special i18n domain...
|
|||
class KeywordVocabulary(vocabulary.SimpleVocabulary):
|
||||
|
||||
def __init__(self, items, *interfaces):
|
||||
terms = [vocabulary.SimpleTerm(token, token, title)
|
||||
for token, title in items]
|
||||
""" ``items`` may be a tuple of (token, title) or a dictionary
|
||||
with corresponding elements named 'token' and 'title'.
|
||||
"""
|
||||
terms = []
|
||||
for t in items:
|
||||
if type(t) is dict:
|
||||
token, title = t['token'], t['title']
|
||||
else:
|
||||
token, title = t
|
||||
terms.append(vocabulary.SimpleTerm(token, token, title))
|
||||
super(KeywordVocabulary, self).__init__(terms, *interfaces)
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue