diff --git a/browser/common.py b/browser/common.py
index 215657a..caa35bf 100644
--- a/browser/common.py
+++ b/browser/common.py
@@ -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):
diff --git a/common.py b/common.py
index 5f97ccc..f1ab5e4 100644
--- a/common.py
+++ b/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
diff --git a/concept.py b/concept.py
index 9e47451..4889ee9 100644
--- a/concept.py
+++ b/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()
diff --git a/configure.zcml b/configure.zcml
index 5941aa5..83e1b68 100644
--- a/configure.zcml
+++ b/configure.zcml
@@ -78,7 +78,8 @@
+ attributes="getTypePredicate getDefaultPredicate getTypeConcept
+ getPredicateType" />
diff --git a/helpers.txt b/helpers.txt
index c006d56..1ff4f22 100755
--- a/helpers.txt
+++ b/helpers.txt
@@ -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
>>> topic_type.factory
diff --git a/interfaces.py b/interfaces.py
index f406283..061ce98 100644
--- a/interfaces.py
+++ b/interfaces.py
@@ -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)
diff --git a/knowledge/knowledge.py b/knowledge/knowledge.py
index b6d5189..680becb 100644
--- a/knowledge/knowledge.py
+++ b/knowledge/knowledge.py
@@ -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,))
diff --git a/organize/party.py b/organize/party.py
index 3a39d42..9349c29 100644
--- a/organize/party.py
+++ b/organize/party.py
@@ -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', [])
diff --git a/organize/task.py b/organize/task.py
index b0ba59b..3203bfd 100644
--- a/organize/task.py
+++ b/organize/task.py
@@ -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)
diff --git a/query.py b/query.py
index 0155ccb..95d2bd3 100644
--- a/query.py
+++ b/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,)
diff --git a/resource.py b/resource.py
index 32429e4..6f071b1 100644
--- a/resource.py
+++ b/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
diff --git a/search/README.txt b/search/README.txt
index 9eaa82c..d4d61df 100755
--- a/search/README.txt
+++ b/search/README.txt
@@ -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'
diff --git a/search/browser.py b/search/browser.py
index a86d682..7093edd 100644
--- a/search/browser.py
+++ b/search/browser.py
@@ -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]]
diff --git a/type.py b/type.py
index a810395..e7138bb 100644
--- a/type.py
+++ b/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)
diff --git a/util.py b/util.py
index 4e0c09f..07c6f86 100644
--- a/util.py
+++ b/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)