[Zope3-checkins] SVN: Zope3/trunk/src/optionstorage/ Adding
"optionstorage" product to src/, as requested by Stephan Richter.
Gustavo Niemeyer
niemeyer at conectiva.com
Fri Nov 12 13:49:40 EST 2004
Log message for revision 28445:
Adding "optionstorage" product to src/, as requested by Stephan Richter.
This is a generic solution for including editable and multi-lingual
vocbulary-like information in any annotatable object.
Changed:
A Zope3/trunk/src/optionstorage/
A Zope3/trunk/src/optionstorage/__init__.py
A Zope3/trunk/src/optionstorage/browser/
A Zope3/trunk/src/optionstorage/browser/__init__.py
A Zope3/trunk/src/optionstorage/browser/configure.zcml
A Zope3/trunk/src/optionstorage/browser/meta.zcml
A Zope3/trunk/src/optionstorage/browser/metaconfigure.py
A Zope3/trunk/src/optionstorage/browser/metadirectives.py
A Zope3/trunk/src/optionstorage/browser/optiondict.pt
A Zope3/trunk/src/optionstorage/browser/optionstorage.pt
A Zope3/trunk/src/optionstorage/browser/widgets.py
A Zope3/trunk/src/optionstorage/configure.zcml
A Zope3/trunk/src/optionstorage/interfaces.py
A Zope3/trunk/src/optionstorage/meta.zcml
A Zope3/trunk/src/optionstorage/metaconfigure.py
A Zope3/trunk/src/optionstorage/metadirectives.py
A Zope3/trunk/src/optionstorage/vocabulary.py
-=-
Added: Zope3/trunk/src/optionstorage/__init__.py
===================================================================
--- Zope3/trunk/src/optionstorage/__init__.py 2004-11-12 15:11:54 UTC (rev 28444)
+++ Zope3/trunk/src/optionstorage/__init__.py 2004-11-12 18:49:40 UTC (rev 28445)
@@ -0,0 +1,215 @@
+from zope.app.annotation.interfaces import IAnnotatable, IAnnotations
+from zope.proxy import removeAllProxies
+from zope.interface import implements
+from zope.app import zapi
+
+from persistent.dict import PersistentDict
+from persistent import Persistent
+
+from interfaces import IOptionStorage, IOptionDict
+
+from UserDict import IterableUserDict
+
+OptionStorageKey = "optionstorage"
+
+class Table(object):
+ # Based on zope's SecurityMap.
+
+ def __init__(self):
+ self._byrow = {}
+ self._bycol = {}
+
+ def __nonzero__(self):
+ return bool(self._byrow)
+
+ def _changed(self):
+ pass
+
+ def clear(self):
+ self._byrow.clear()
+ self._bycol.clear()
+ self._changed()
+
+ def addCell(self, rowkey, colkey, value):
+ row = self._byrow.get(rowkey)
+ if row:
+ if row.get(colkey) is value:
+ return False
+ else:
+ row = self._byrow[rowkey] = {}
+
+ col = self._bycol.get(colkey)
+ if not col:
+ col = self._bycol[colkey] = {}
+
+ row[colkey] = value
+ col[rowkey] = value
+
+ self._changed()
+
+ return True
+
+ def delCell(self, rowkey, colkey):
+ row = self._byrow.get(rowkey)
+ if row and (colkey in row):
+ del row[colkey]
+ if not row:
+ del self._byrow[rowkey]
+ col = self._bycol[colkey]
+ del col[rowkey]
+ if not col:
+ del self._bycol[colkey]
+ return True
+
+ self._changed()
+
+ return False
+
+ def queryCell(self, rowkey, colkey, default=None):
+ row = self._byrow.get(rowkey)
+ if row:
+ return row.get(colkey, default)
+ else:
+ return default
+
+ def getCell(self, rowkey, colkey):
+ marker = object()
+ cell = self.queryCell(rowkey, colkey, marker)
+ if cell is marker:
+ raise KeyError, "Invalid row/column pair"
+ return cell
+
+ def getRow(self, rowkey):
+ row = self._byrow.get(rowkey)
+ if row:
+ return row.items()
+ else:
+ return []
+
+ def getCol(self, colkey):
+ col = self._bycol.get(colkey)
+ if col:
+ return col.items()
+ else:
+ return []
+
+ def getRowKeys(self):
+ return self._byrow.keys()
+
+ def getColKeys(self):
+ return self._bycol.keys()
+
+ def getAllCells(self):
+ res = []
+ for r in self._byrow.keys():
+ for c in self._byrow[r].items():
+ res.append((r,) + c)
+ return res
+
+
+class PersistentTable(Table, Persistent):
+
+ def _changed(self):
+ self._p_changed = 1
+
+
+class OptionDict(Persistent):
+
+ implements(IOptionDict)
+
+ def __init__(self):
+ self._defaultkey = None
+ self._defaultlanguage = None
+ self._table = PersistentTable()
+
+ def getLanguages(self):
+ return self._table.getColKeys()
+
+ def getDefaultLanguage(self):
+ return self._defaultlanguage
+
+ def setDefaultLanguage(self, language):
+ self._defaultlanguage = language
+
+ def getDefaultKey(self):
+ return self._defaultkey
+
+ def setDefaultKey(self, key):
+ self._defaultkey = key
+
+ def getKeys(self):
+ return self._table.getRowKeys()
+
+ def queryValue(self, key, language, default=None):
+ return self._table.queryCell(key, language, default)
+
+ def getValue(self, key, language):
+ return self._table.getCell(key, language)
+
+ def addValue(self, key, language, value):
+ self._table.addCell(key, language, value)
+
+ def delValue(self, key, language):
+ self._table.delCell(key, language)
+
+ def delAllValues(self):
+ self._table.clear()
+ self._defaultkey = None
+
+
+class OptionStorage(IterableUserDict, object):
+
+ implements(IOptionStorage)
+
+ def __init__(self, context):
+ annotations = IAnnotations(removeAllProxies(context))
+ if OptionStorageKey in annotations:
+ self.data = annotations[OptionStorageKey]
+ else:
+ self.data = annotations[OptionStorageKey] = PersistentDict()
+
+def queryOptionStorage(context, name):
+ lookuplist = zapi.getParents(context)
+ lookuplist.insert(0, context)
+ for object in lookuplist:
+ object = removeAllProxies(object)
+ if IAnnotatable.providedBy(object):
+ annotations = IAnnotations(object)
+ if OptionStorageKey in annotations:
+ storage = IOptionStorage(object)
+ if name in storage:
+ return storage[name]
+ return None
+
+class OptionStorageProperty(object):
+
+ def __init__(self, name, dictname, islist=False, readonly=False):
+ self._name = name
+ self._dictname = dictname
+ self._islist = islist
+ self._readonly = readonly
+
+ def __get__(self, object, type_=None):
+ dict = queryOptionStorage(object, self._dictname)
+ if dict:
+ default = dict.getDefaultKey()
+ return getattr(object, self._name, default)
+
+ def __set__(self, object, value):
+ if self._readonly:
+ raise AttributeError, "Attribute '%s' is read-only" % self._name
+ if type(value) is not list:
+ values = [value]
+ else:
+ values = value
+ dict = queryOptionStorage(object, self._dictname)
+ if dict:
+ keys = dict.getKeys()
+ invalid = [x for x in values if x not in keys]
+ if invalid:
+ raise ValueError, "Invalid values: %s" % \
+ ", ".join(map(repr, invalid))
+ if self._islist:
+ value = values
+ setattr(object, self._name, value)
+
Added: Zope3/trunk/src/optionstorage/browser/__init__.py
===================================================================
--- Zope3/trunk/src/optionstorage/browser/__init__.py 2004-11-12 15:11:54 UTC (rev 28444)
+++ Zope3/trunk/src/optionstorage/browser/__init__.py 2004-11-12 18:49:40 UTC (rev 28445)
@@ -0,0 +1,87 @@
+from zope.app.pagetemplate.viewpagetemplatefile import ViewPageTemplateFile
+from optionstorage.interfaces import IOptionStorage
+from optionstorage import OptionDict
+from zope.exceptions import NotFoundError
+
+def checkFields(request, *fields):
+ for field in fields:
+ if field not in request:
+ return False
+ return True
+
+class OptionStorageView(object):
+
+ storagetemplate = ViewPageTemplateFile("optionstorage.pt")
+ dicttemplate = ViewPageTemplateFile("optiondict.pt")
+
+ dictlist = [] # (name, topic)
+
+ def __init__(self, context, request):
+ self.context = context
+ self.request = request
+ self.name = None
+ self.topic = None
+ self.dict = None
+
+ def getNameTopicList(self):
+ storage = IOptionStorage(self.context)
+ for name, topic in self.dictlist:
+ yield {"name": name, "topic": topic}
+
+ def __call__(self, name=None):
+ if name is None:
+ return self.storagetemplate()
+
+ storage = IOptionStorage(self.context)
+ for _name, topic in self.dictlist:
+ if name == _name:
+ if name not in storage:
+ storage[name] = OptionDict()
+ self.dict = storage[name]
+ self.name = name
+ self.topic = topic
+ break
+ else:
+ raise NotFoundError(self.context, name, self.request)
+
+ form = self.request.form
+ if "SAVE" not in form:
+ return self.dicttemplate()
+
+ language = {}
+ key = {}
+ value = {}
+ for entry in form:
+ entryvalue = form[entry].strip()
+ if not entryvalue:
+ pass
+ elif entry.startswith("lang-"):
+ language[int(entry[5:])] = entryvalue
+ elif entry.startswith("key-"):
+ key[int(entry[4:])] = entryvalue
+ elif entry.startswith("value-"):
+ tok = entry.split("-")
+ value[int(tok[1]), int(tok[2])] = entryvalue
+
+ try:
+ defaultkey = int(form["default-key"])
+ except KeyError:
+ defaultkey = None
+
+ try:
+ defaultlanguage = int(form["default-lang"])
+ except KeyError:
+ defaultlanguage = None
+
+ self.dict.delAllValues()
+ for keynum, languagenum in value:
+ if keynum in key and languagenum in language:
+ self.dict.addValue(key[keynum], language[languagenum],
+ value[keynum, languagenum])
+ if defaultkey in key:
+ self.dict.setDefaultKey(key[defaultkey])
+ if defaultlanguage in language:
+ self.dict.setDefaultLanguage(language[defaultlanguage])
+
+ return self.dicttemplate()
+
Added: Zope3/trunk/src/optionstorage/browser/configure.zcml
===================================================================
--- Zope3/trunk/src/optionstorage/browser/configure.zcml 2004-11-12 15:11:54 UTC (rev 28444)
+++ Zope3/trunk/src/optionstorage/browser/configure.zcml 2004-11-12 18:49:40 UTC (rev 28445)
@@ -0,0 +1,14 @@
+<configure
+ xmlns="http://namespaces.zope.org/browser"
+ xmlns:zope="http://namespaces.zope.org/zope">
+
+<zope:view
+ type="zope.publisher.interfaces.browser.IBrowserRequest"
+ for="zope.schema.interfaces.IChoice
+ optionstorage.interfaces.IOptionStorageVocabulary"
+ provides="zope.app.form.interfaces.IInputWidget"
+ factory=".widgets.OptionStorageVocabularyWidget"
+ permission="zope.Public"
+ />
+
+</configure>
Added: Zope3/trunk/src/optionstorage/browser/meta.zcml
===================================================================
--- Zope3/trunk/src/optionstorage/browser/meta.zcml 2004-11-12 15:11:54 UTC (rev 28444)
+++ Zope3/trunk/src/optionstorage/browser/meta.zcml 2004-11-12 18:49:40 UTC (rev 28445)
@@ -0,0 +1,22 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ xmlns:meta="http://namespaces.zope.org/meta">
+
+<meta:directives namespace="http://namespaces.zope.org/browser">
+
+<meta:complexDirective
+ name="optionStorage"
+ schema=".metadirectives.IOptionStorageDirective"
+ handler=".metaconfigure.optionStorage"
+ >
+
+ <meta:subdirective
+ name="options"
+ schema=".metadirectives.IOptionStorageOptionsSubdirective"
+ />
+
+</meta:complexDirective>
+
+</meta:directives>
+
+</configure>
Added: Zope3/trunk/src/optionstorage/browser/metaconfigure.py
===================================================================
--- Zope3/trunk/src/optionstorage/browser/metaconfigure.py 2004-11-12 15:11:54 UTC (rev 28444)
+++ Zope3/trunk/src/optionstorage/browser/metaconfigure.py 2004-11-12 18:49:40 UTC (rev 28445)
@@ -0,0 +1,22 @@
+from zope.app.publisher.browser.viewmeta import page
+from optionstorage.browser import OptionStorageView
+
+class optionStorage(object):
+
+ def __init__(self, _context, class_=None, **kwargs):
+ self._context = _context
+ self.class_ = class_
+ self.opts = kwargs.copy()
+ self.dictlist = []
+
+ def options(self, _context, name, topic):
+ self.dictlist.append((name, topic))
+
+ def __call__(self):
+ class_ = self.class_
+ if class_ is None:
+ class_ = OptionStorageView
+ class_ = type("OptionStorageView", (class_,),
+ {"dictlist": self.dictlist})
+ page(self._context, class_=class_, **self.opts)
+ return ()
Added: Zope3/trunk/src/optionstorage/browser/metadirectives.py
===================================================================
--- Zope3/trunk/src/optionstorage/browser/metadirectives.py 2004-11-12 15:11:54 UTC (rev 28444)
+++ Zope3/trunk/src/optionstorage/browser/metadirectives.py 2004-11-12 18:49:40 UTC (rev 28445)
@@ -0,0 +1,24 @@
+from zope.app.publisher.browser.metadirectives import IViewDirective
+from zope.configuration.fields import MessageID
+from zope.interface import Interface
+from zope.schema import TextLine
+
+
+class IOptionStorageDirective(IViewDirective):
+ """
+ The manageableVocabularies directive is used to create a
+ vocabulary editing view for a given interface.
+ """
+
+class IOptionStorageOptionsSubdirective(Interface):
+
+ name = TextLine(
+ title=u"Key of option dictionary in storage",
+ required=True,
+ )
+
+ topic = MessageID(
+ title=u"Topic of option dictionary in storage",
+ required=True,
+ )
+
Added: Zope3/trunk/src/optionstorage/browser/optiondict.pt
===================================================================
--- Zope3/trunk/src/optionstorage/browser/optiondict.pt 2004-11-12 15:11:54 UTC (rev 28444)
+++ Zope3/trunk/src/optionstorage/browser/optiondict.pt 2004-11-12 18:49:40 UTC (rev 28445)
@@ -0,0 +1,61 @@
+<html metal:use-macro="context/@@standard_macros/view">
+<body>
+<div metal:fill-slot="body"
+ tal:define="dict view/dict"
+ i18n:domain="optionstorage">
+
+ <h2 tal:content="view/topic">Some Topic</h2>
+ <br />
+ <form method="post" tal:attributes="action request/URL">
+
+ <input type="hidden" name="name" tal:attributes="value view/name" />
+
+ <table>
+ <!-- Language row -->
+ <tr>
+ <td> </td>
+ <td><center><b i18n:translate="">Keys</b></center></td>
+ <td tal:repeat="language python:dict.getLanguages()+['']">
+ <b i18n:translate="">Language:</b>
+ <input type="text" size="5"
+ tal:attributes="value language;
+ name string:lang-${repeat/language/index}" />
+ <input type="radio" name="default-lang"
+ tal:attributes="value repeat/language/index;
+ checked python:language == dict.getDefaultLanguage()" />
+ </td>
+ </tr>
+ <tr tal:repeat="key python:dict.getKeys()+['']*3">
+ <td>
+ <input type="radio" name="default-key"
+ tal:attributes="value repeat/key/index;
+ checked python:key == dict.getDefaultKey()" />
+ </td>
+ <td>
+ <input type="text" size="10"
+ tal:attributes="value key;
+ name string:key-${repeat/key/index}" />
+ </td>
+ <td tal:repeat="language python:dict.getLanguages()+['']">
+ <input type="text" size="20"
+ tal:attributes="value python:dict.queryValue(key, language);
+ name string:value-${repeat/key/index}-${repeat/language/index}" />
+ </td>
+ </tr>
+
+ <tr>
+ <td colspan="2"><b i18n:translate="">Default</b></td>
+ </tr>
+
+ </table>
+
+ <input type="submit" name="SAVE" value="Save" />
+
+ </form>
+
+</div>
+</body>
+</html>
+
+<!-- vim:ts=2:sw=2:et:ft=html
+ -->
Added: Zope3/trunk/src/optionstorage/browser/optionstorage.pt
===================================================================
--- Zope3/trunk/src/optionstorage/browser/optionstorage.pt 2004-11-12 15:11:54 UTC (rev 28444)
+++ Zope3/trunk/src/optionstorage/browser/optionstorage.pt 2004-11-12 18:49:40 UTC (rev 28445)
@@ -0,0 +1,17 @@
+<html metal:use-macro="context/@@standard_macros/view">
+<body>
+<div metal:fill-slot="body">
+
+<ul>
+ <li tal:repeat="dict view/getNameTopicList">
+ <a tal:attributes="href string:${request/URL}?name=${dict/name}"
+ tal:content="dict/topic" />
+ </li>
+</ul>
+
+</div>
+</body>
+</html>
+
+<!-- vim:ts=2:sw=2:et:ft=html
+ -->
Added: Zope3/trunk/src/optionstorage/browser/widgets.py
===================================================================
--- Zope3/trunk/src/optionstorage/browser/widgets.py 2004-11-12 15:11:54 UTC (rev 28444)
+++ Zope3/trunk/src/optionstorage/browser/widgets.py 2004-11-12 18:49:40 UTC (rev 28445)
@@ -0,0 +1,9 @@
+from zope.app.form.browser import DropdownWidget
+
+class OptionStorageVocabularyWidget(DropdownWidget):
+
+ def _getDefault(self):
+ default = self.vocabulary.getDefaultKey()
+ if not default:
+ default = super(OptionStorageVocabularyWidget, self)._getDefault()
+ return default
Added: Zope3/trunk/src/optionstorage/configure.zcml
===================================================================
--- Zope3/trunk/src/optionstorage/configure.zcml 2004-11-12 15:11:54 UTC (rev 28444)
+++ Zope3/trunk/src/optionstorage/configure.zcml 2004-11-12 18:49:40 UTC (rev 28445)
@@ -0,0 +1,34 @@
+<configure xmlns="http://namespaces.zope.org/zope">
+
+<class class="optionstorage.OptionStorage">
+ <require
+ permission="zope.View"
+ interface="zope.interface.common.mapping.IReadMapping"
+ />
+ <require
+ permission="zope.ManageContent"
+ interface="zope.interface.common.mapping.IWriteMapping"
+ />
+</class>
+
+<class class="optionstorage.OptionDict">
+ <require
+ permission="zope.View"
+ interface=".interfaces.IOptionDictRead"
+ />
+ <require
+ permission="zope.ManageContent"
+ interface=".interfaces.IOptionDictWrite"
+ />
+</class>
+
+<adapter
+ factory="optionstorage.OptionStorage"
+ provides="optionstorage.interfaces.IOptionStorage"
+ for="zope.app.annotation.interfaces.IAnnotatable"
+ permission="zope.View"
+ />
+
+<include package=".browser" />
+
+</configure>
Added: Zope3/trunk/src/optionstorage/interfaces.py
===================================================================
--- Zope3/trunk/src/optionstorage/interfaces.py 2004-11-12 15:11:54 UTC (rev 28444)
+++ Zope3/trunk/src/optionstorage/interfaces.py 2004-11-12 18:49:40 UTC (rev 28445)
@@ -0,0 +1,47 @@
+from zope.interface.common.mapping import IMapping
+from zope.interface import Interface
+
+class IOptionDictRead(Interface):
+ """Option dictionary read interface."""
+
+ def getLanguages():
+ """Return available languages."""
+
+ def getDefaultKey():
+ """Return default key."""
+
+ def getKeys():
+ """Return available keys."""
+
+ def queryValue(key, language, default=None):
+ """Return value for key/language pair."""
+
+ def getValue(key, language):
+ """Return value for key/language pair."""
+
+class IOptionDictWrite(Interface):
+ """Option dictionary write interface."""
+
+ def setDefaultKey(key):
+ """Change default key."""
+
+ def addValue(key, language, value):
+ """Add value for a key/language pair."""
+
+ def delValue(key, language):
+ """Delete value for a key/language pair."""
+
+ def delAllValues():
+ """Delete all values."""
+
+class IOptionDict(IOptionDictRead,IOptionDictWrite):
+ """Option dictionary."""
+
+class IOptionStorage(IMapping):
+ """Option storage, mapping names to option dictionaries."""
+
+class IOptionStorageVocabulary(Interface):
+
+ def getDefaultKey():
+ """Return default key for an option storage vocabulary."""
+
Added: Zope3/trunk/src/optionstorage/meta.zcml
===================================================================
--- Zope3/trunk/src/optionstorage/meta.zcml 2004-11-12 15:11:54 UTC (rev 28444)
+++ Zope3/trunk/src/optionstorage/meta.zcml 2004-11-12 18:49:40 UTC (rev 28445)
@@ -0,0 +1,14 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ xmlns:meta="http://namespaces.zope.org/meta">
+
+<meta:directive
+ namespace="http://namespaces.zope.org/zope"
+ name="optionStorageVocabulary"
+ schema=".metadirectives.IOptionStorageVocabularyDirective"
+ handler=".metaconfigure.optionStorageVocabulary"
+ />
+
+<include package=".browser" file="meta.zcml" />
+
+</configure>
Added: Zope3/trunk/src/optionstorage/metaconfigure.py
===================================================================
--- Zope3/trunk/src/optionstorage/metaconfigure.py 2004-11-12 15:11:54 UTC (rev 28444)
+++ Zope3/trunk/src/optionstorage/metaconfigure.py 2004-11-12 18:49:40 UTC (rev 28445)
@@ -0,0 +1,7 @@
+from optionstorage.vocabulary import OptionStorageVocabulary
+from zope.app.schema.metaconfigure import vocabulary
+
+def optionStorageVocabulary(_context, name):
+ def factory(object, name=name):
+ return OptionStorageVocabulary(object, name=name)
+ vocabulary(_context, name, factory)
Added: Zope3/trunk/src/optionstorage/metadirectives.py
===================================================================
--- Zope3/trunk/src/optionstorage/metadirectives.py 2004-11-12 15:11:54 UTC (rev 28444)
+++ Zope3/trunk/src/optionstorage/metadirectives.py 2004-11-12 18:49:40 UTC (rev 28445)
@@ -0,0 +1,13 @@
+from zope.interface import Interface
+from zope.schema import TextLine
+
+class IOptionStorageVocabularyDirective(Interface):
+ """
+ Define a named vocabulary fetching information from an option storage.
+ """
+
+ name = TextLine(
+ title=u"Name",
+ description=u"Provides the name for the option storage "\
+ u"vocabulary.",
+ required=True)
Added: Zope3/trunk/src/optionstorage/vocabulary.py
===================================================================
--- Zope3/trunk/src/optionstorage/vocabulary.py 2004-11-12 15:11:54 UTC (rev 28444)
+++ Zope3/trunk/src/optionstorage/vocabulary.py 2004-11-12 18:49:40 UTC (rev 28445)
@@ -0,0 +1,83 @@
+from zope.schema.interfaces import IVocabularyTokenized
+from zope.schema.vocabulary import SimpleTerm
+from zope.interface import implements
+from zope.app import zapi
+
+from zope.security.management import getInteraction
+from zope.i18n.negotiator import negotiator
+
+from optionstorage.interfaces import IOptionStorage, IOptionStorageVocabulary
+from optionstorage import OptionStorageKey, queryOptionStorage
+
+
+class OptionStorageVocabulary(object):
+
+ # Order matters here. We want our multi-view adapter to be chosen
+ # before the IVocabulary default one.
+ implements(IOptionStorageVocabulary, IVocabularyTokenized)
+
+ def __init__(self, context, name):
+ self.dict = queryOptionStorage(context, name)
+ if self.dict:
+ # Workaround. Hopefully, in the future titles will be
+ # computed as a view.
+ interaction = getInteraction()
+ request = interaction.participations[0]
+ self.language = negotiator.getLanguage(self.dict.getLanguages(),
+ request)
+ self.defaultlanguage = self.dict.getDefaultLanguage()
+
+ def __contains__(self, key):
+ if self.dict:
+ try:
+ self.dict.getValue(key, self.language)
+ return True
+ except KeyError:
+ try:
+ self.dict.getValue(key, self.defaultlanguage)
+ return True
+ except KeyError:
+ pass
+ return False
+
+ def getTerm(self, key):
+ if self.dict:
+ try:
+ value = self.dict.getValue(key, self.language)
+ return SimpleTerm(key, title=value)
+ except KeyError:
+ try:
+ value = self.dict.getValue(key, self.defaultlanguage)
+ return SimpleTerm(key, title=value)
+ except KeyError:
+ pass
+ raise LookupError
+
+ def getTermByToken(self, token):
+ return self.getTerm(token)
+
+ def __iter__(self):
+ if self.dict:
+ for key in self.dict.getKeys():
+ try:
+ yield self.getTerm(key)
+ except LookupError:
+ pass
+
+ def __len__(self):
+ count = 0
+ if self.dict:
+ marker = object()
+ for key in self.dict.getKeys():
+ if (self.dict.queryValue(key, self.language,
+ marker) is not marker
+ or self.dict.queryValue(key, self.defaultlanguage,
+ marker) is not marker):
+
+ count += 1
+ return count
+
+ def getDefaultKey(self):
+ if self.dict:
+ return self.dict.getDefaultKey()
+
More information about the Zope3-Checkins
mailing list