# -*- coding: iso-8859-15 -*- # Glasnost # By: Odile Bénassy # Romain Chantereau # Nicolas Clapiès # Pierre-Antoine Dejace # Thierry Dulieu # Florent Monnier # Cédric Musso # Frédéric Péters # Benjamin Poussin # Emmanuel Raviart # Sébastien Régnier # Emmanuel Saracco # # Copyright (C) 2000, 2001 Easter-eggs & Emmanuel Raviart # Copyright (C) 2002 Odile Bénassy, Code Lutin, Thierry Dulieu, Easter-eggs, # Entr'ouvert, Frédéric Péters, Benjamin Poussin, Emmanuel Raviart, # Emmanuel Saracco & Théridion # Copyright (C) 2003 Odile Bénassy, Romain Chantereau, Nicolas Clapiès, # Code Lutin, Pierre-Antoine Dejace, Thierry Dulieu, Easter-eggs, # Entr'ouvert, Florent Monnier, Cédric Musso, Ouvaton, Frédéric Péters, # Benjamin Poussin, Rodolphe Quiédeville, Emmanuel Raviart, Sébastien # Régnier, Emmanuel Saracco, Théridion & Vecam # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. from __future__ import nested_scopes __doc__ = """Glasnost Common Kinds""" __version__ = '$Revision$'[11:-2] import base64 import copy import cStringIO import locale import marshal import re import string import sys import time import traceback import types import jails import slots import translation import things import system from tools import * import tools_new as commonTools ## import connectors # Do not remove! import functions # Do not remove! import modes # Do not remove! import properties # Do not remove! import uploads # Do not remove! import values # Do not remove! import widgets # Do not remove! register = things.register class BaseKind(things.BaseThing): balloonHelp = None class balloonHelp_kindClass: _kindName = 'String' label = N_('Balloon Help') stateInViewMode = 'read-only/hidden-if-empty' widget_rows = 4 widgetName = 'TextArea' containerNames = None class containerNames_kindClass: _kindName = 'Sequence' importExport = 'private' itemKind_valueName = 'KindName' label = N_('Containers') stateInEditMode = 'hidden' stateInViewMode = 'hidden' defaultValue = None defaultValue_kind_importExport = 'private' defaultValue_kind_label = N_('Default Value') defaultValue_kind_stateInEditMode = 'hidden' defaultValue_kind_stateInViewMode = 'hidden' defaultValue_kindName = None # To override ## helpAlias = None ## class helpAlias_kindClass: ## _kindName = 'Alias' ## label = N_('Help Alias') getter = None importExport = 'public' class importExport_kindClass: _kindName = 'Choice' importExport = 'private' isRequired = 1 label = N_('Protection') stateInEditMode = 'hidden' stateInViewMode = 'hidden' labels = { 'from-server-only': N_('Read Only'), 'private': N_('Private'), 'public': N_('Read/Write'), 'to-server-only': N_('Write Only'), } values = [ 'private', 'to-server-only', 'from-server-only', 'public', ] isAutomaticallyModified = 0 class isAutomaticallyModified_kindClass: _kindName = 'Boolean' importExport = 'private' stateInEditMode = 'hidden' stateInViewMode = 'hidden' # When isModifiable is false, the slot can only be set once and not # modified. isModifiable = 1 class isModifiable_kindClass: _kindName = 'Boolean' importExport = 'private' stateInEditMode = 'hidden' stateInViewMode = 'hidden' # When false, isPractical means that the kind can not be used to describe # a real value, but only to describe an expected value. isPractical = 1 class isPractical_kindClass: _kindName = 'Boolean' importExport = 'private' stateInEditMode = 'hidden' stateInViewMode = 'hidden' isRequired = 0 class isRequired_kindClass: _kindName = 'Boolean' label = N_('Mandatory') ## labels = { ## '0': N_('Optional'), ## '1': N_('Required'), ## } isRequiredInEditMode = 0 class isRequiredInEditMode_kindClass: _kindName = 'Boolean' importExport = 'private' stateInEditMode = 'hidden' stateInViewMode = 'hidden' isTranslatable = 0 class isTranslatable_kindClass: _kindName = 'Boolean' importExport = 'private' label = N_('Translatable') ## labels = { ## '0': N_('Invariant'), ## '1': N_('Translatable'), ## } stateInEditMode = 'hidden' stateInViewMode = 'hidden' label = None class label_kindClass: _kindName = 'String' balloonHelp = N_('Enter a user-friendly field name') label = N_('Field Label') stateInViewMode = 'read-only/hidden-if-empty' labelPlural = None class labelPlural_kindClass: _kindName = 'String' importExport = 'private' label = N_('Label (plural form)') stateInEditMode = 'hidden' stateInViewMode = 'hidden' possibleWidgetNames = None class possibleWidgetNames_kindClass: _kindName = 'Sequence' importExport = 'private' itemKind_valueName = 'WidgetName' stateInEditMode = 'hidden' stateInViewMode = 'hidden' pythonStorageType = None # not defined as a kind since it would require a new kind PythonType that # would only be useful here. stateInCreateMode = None class stateInCreateMode_kindClass: _kindName = 'Choice' importExport = 'private' label = N_('Creation Mode') labels = { '': N_('Same As Edition Mode'), 'hidden': N_('Hidden'), 'read-only': N_('Read Only'), 'read-only/hidden-if-empty': N_('Read Only / Hidden If Empty'), 'read-write': N_('Read/Write'), } sortLabels = 0 stateInEditMode = 'hidden' stateInViewMode = 'hidden' values = [ None, 'hidden', 'read-only/hidden-if-empty', 'read-only', 'read-write', ] stateInEditMode = 'read-write' class stateInEditMode_kindClass: _kindName = 'Choice' importExport = 'private' isRequired = 1 label = N_('Edition Mode') labels = { 'hidden': N_('Hidden'), 'read-only': N_('Read Only'), 'read-only/hidden-if-empty': N_('Read Only / Hidden If Empty'), 'read-write': N_('Read/Write'), } sortLabels = 0 stateInEditMode = 'hidden' stateInViewMode = 'hidden' values = [ 'hidden', 'read-only/hidden-if-empty', 'read-only', 'read-write', ] stateInViewMode = 'read-only/hidden-if-empty' class stateInViewMode_kindClass: _kindName = 'Choice' importExport = 'private' isRequired = 1 label = N_('View Mode') labels = { 'hidden': N_('Hidden'), 'read-only': N_('Read Only'), 'read-only/hidden-if-empty': N_('Read Only / Hidden If Empty'), } sortLabels = 0 stateInEditMode = 'hidden' stateInViewMode = 'hidden' values = [ 'hidden', 'read-only/hidden-if-empty', 'read-only', ] tagInCreateMode = None class tagInCreateMode_kindClass: _kindName = 'Choice' importExport = 'private' label = N_('Creation Aspect') labels = { '': N_('Same As Edition Aspect'), 'div': N_('Standard Without Label'), 'div-with-label': N_('Standard With Label'), 'h1': N_('Header 1'), 'h2': N_('Header 2'), 'h3': N_('Header 3'), 'h4': N_('Header 4'), 'h5': N_('Header 5'), 'h6': N_('Header 6'), } sortLabels = 0 stateInEditMode = 'hidden' stateInViewMode = 'hidden' values = [ None, 'div-with-label', 'div', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', ] tagInEditMode = 'div-with-label' class tagInEditMode_kindClass: _kindName = 'Choice' importExport = 'private' isRequired = 1 label = N_('Edition Aspect') labels = { 'div': N_('Standard Without Label'), 'div-with-label': N_('Standard With Label'), 'h1': N_('Header 1'), 'h2': N_('Header 2'), 'h3': N_('Header 3'), 'h4': N_('Header 4'), 'h5': N_('Header 5'), 'h6': N_('Header 6'), } sortLabels = 0 stateInEditMode = 'hidden' stateInViewMode = 'hidden' values = [ 'div-with-label', 'div', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', ] tagInViewMode = 'div-with-label' class tagInViewMode_kindClass: _kindName = 'Choice' importExport = 'private' isRequired = 1 label = N_('View Aspect') labels = { 'div': N_('Standard Without Label'), 'div-with-label': N_('Standard With Label'), 'h1': N_('Header 1'), 'h2': N_('Header 2'), 'h3': N_('Header 3'), 'h4': N_('Header 4'), 'h5': N_('Header 5'), 'h6': N_('Header 6'), } sortLabels = 0 stateInEditMode = 'hidden' stateInViewMode = 'hidden' values = [ 'div-with-label', 'div', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', ] textFormat = None class textFormat_kindClass: _kindName = 'Choice' importExport = 'private' label = N_('Text Format') labels = { '': N_('Text'), 'docbook': N_('DocBook'), 'html': N_('HTML'), 'rst': N_('reStructuredText'), 'spip': N_('SPIP'), 'text': N_('Preformatted Text'), } stateInEditMode = 'hidden' stateInViewMode = 'hidden' values = [ None, 'docbook', 'html', 'rst', 'spip', 'text', ] textMaxLength = None class textMaxLength_kindClass: _kindName = 'Integer' importExport = 'private' label = N_('Maximum Number of Characters') stateInEditMode = 'hidden' stateInViewMode = 'hidden' thingCategory = 'kind' thingPublicCategory_kind_stateInEditMode = 'read-only/hidden-if-empty' thingPublicCategory_kind_stateInViewMode = 'read-only/hidden-if-empty' thingPublicName_kind_label = N_('Type') thingPublicName_kind_stateInEditMode = 'read-only/hidden-if-empty' thingPublicName_kind_stateInViewMode = 'read-only/hidden-if-empty' useCustomStorage = 0 class useCustomStorage_kindClass: _kindName = 'Boolean' importExport = 'private' stateInEditMode = 'hidden' stateInViewMode = 'hidden' useFileStorage = 0 class useFileStorage_kindClass: _kindName = 'Boolean' importExport = 'from-server-only' label = N_('Storage') labels = { '0': N_('Internal'), '1': N_('In External File'), } stateInEditMode = 'hidden' stateInViewMode = 'hidden' widget = None class widget_kindClass: _kindName = 'Widget' isRequired = 1 label = N_('Widget') def getGroupedValues(self, slot): return None def getter(self, slot): return slot.getContainer().getModelWidget(slot.parent) def getValues(self, slot): values = slot.getContainer().getPossibleWidgetNames() if values: return values else: return ['InputText'] widgetName = 'InputText' class widgetName_kindClass: _kindName = 'WidgetName' importExport = 'private' stateInEditMode = 'hidden' stateInViewMode = 'hidden' def __init__(self, **attributes): things.BaseThing.__init__(self) for name, value in attributes.items(): # Ensure that each argument has been declared as an attribute. if not hasattr(self.__class__, name): raise Exception('Undeclared attribute %s for %s' % ( name, self.__class__.__name__)) if getattr(self, name) == value: continue setattr(self, name, value) def accepts(self, kind): """Test whether the given kind is always compatible with self. For example: - Integer accepts Integer. - Number accepts Integer. - Integer doesn't accept Number. """ return self.includes(kind) def acquireNonCoreValue(self, slot, objectDirectoryPath): pass def buildOptions(self, options): for name, value in options.items(): # Ensure that each option has been declared as an attribute. nameBase = name.split('_')[0] if not hasattr(self.__class__, nameBase): raise Exception('Undeclared attribute %s for %s' % ( name, self.__class__.__name__)) if hasattr(self, name) and getattr(self, name) == value: continue setattr(self, name, value) def checkModelValue(self, slot, value): assert self.isPractical if self.isRequired and value is None: raise faults.MissingSlotValue(slot) if value is None: return if type(value) is not self.pythonStorageType: raise faults.BadSlotValue(slot, value) def checkModelValueHolder(self, slot, valueHolder): assert self.isPractical if not self.accepts(valueHolder.kind): raise faults.KindsIncompatibility(self, valueHolder.kind) self.checkModelValue(slot, valueHolder.value) def convertValueFromOtherType(self, value): if value is None and self.pythonStorageType is types.StringType: return '' if type(value) is types.InstanceType: raise NotImplementedError try: return self.pythonStorageType(value) except: raise 'convertValueFrom not implemented for %s' % \ repr((self, type(value))) raise NotImplementedError def convertValueToOtherType(self, value, otherType): if value is None and otherType is types.StringType: return '' raise 'convertValueTo not implemented for %s' % \ repr((self, otherType)) raise NotImplementedError def convertValueIds( self, slot, value, sourceDispatcherId, destinationDispatcherId): assert self.isPractical return value def equals(self, kind): """Test whether two kinds are equal.""" return self.getThingName() == kind.getThingName() def executeModel(self, slot, when, command = None): pass def exportValueToXmlRpc(self, slot, value): assert self.isPractical if type(value) in (types.StringType, types.UnicodeType): value = utf8(value) return value def getBalloonHelp(self): return self.balloonHelp def getCmpFunction(self): return cmp def getDefaultValue(self, slot): return self.defaultValue def getModelFieldTag(self, slot): layoutMode = context.getVar('layoutMode') if layoutMode == 'edit': isCreateEditMode = context.getVar('isCreateEditMode', default = 0) if isCreateEditMode and self.tagInCreateMode is not None: return self.tagInCreateMode else: return self.tagInEditMode elif layoutMode == 'use': aspect = context.getVar('aspect') return aspect.htmlTag else: return self.tagInViewMode def getModelLabel(self, slot): if self.label: return self.label return slot.getLabel() def getModelLabelPlural(self, slot): if self.labelPlural: return self.labelPlural return self.getModelLabel(slot) def getModelSlotByPath(self, slot, path): if path.startswith('self'): path = path[len('self'):] if not path: return slot raise Exception('Path "%s" not found' % path) def getModelWidget(self, slot, forceEmbedding = 0): if self.widget is None: widgetOptionHeader = 'widget_' widgetOptionHeaderLen = len(widgetOptionHeader) widgetOptionNames = [ name for name in self.__dict__.keys() if name.startswith(widgetOptionHeader) \ and not name.startswith(widgetOptionHeader + 'kind')] baseClasses = self.getC3ClassLinearization() for baseClass in baseClasses: for name in baseClass.__dict__.keys(): if name.startswith(widgetOptionHeader) \ and not name.startswith(widgetOptionHeader + 'kind') \ and name not in widgetOptionNames: widgetOptionNames.append(name) widgetOptions = {} for widgetOptionName in widgetOptionNames: widgetOptions[widgetOptionName[widgetOptionHeaderLen:] ] = getattr(self, widgetOptionName) widget = self.newModelWidget(slot) widget.buildOptions(widgetOptions) self.widget = widget return self.widget def getOrderedLayoutSlotNames(self, parentSlot = None): slotNames = things.BaseThing.getOrderedLayoutSlotNames( self, parentSlot = parentSlot) slotNames += [ 'label', 'labelPlural', 'widgetName', 'widget', 'textFormat', 'importExport', 'tagInCreateMode', 'stateInCreateMode', 'tagInEditMode', 'stateInEditMode', 'tagInViewMode', 'stateInViewMode', 'isRequired', 'defaultValue', 'balloonHelp', 'textMaxLength', ## 'helpAlias', 'useFileStorage', 'useCustomStorage'] return slotNames def getPossibleWidgetNames(self): assert self.isPractical if self.possibleWidgetNames is not None: return self.possibleWidgetNames return [self.widgetName] def getRealKindClass(self): return self.__class__.__bases__[-1] def getTextFormat(self, slot): return self.textFormat def getTextMaxLength(self): return self.textMaxLength def importValueFromXmlRpc(self, slot, value): assert self.isPractical if type(value) in (types.StringType, types.UnicodeType): value = iso8859_15(value) value = value.replace('\r\n', '\n') # MS-DOS return character value = value.replace('\r', '\n') # MacOS return character return value def includes(self, kind): """Test whether the given kind is included in self. For example: - Integer includes Integer. - Number includes Integer. - Integer doesn't include Number. """ if self.equals(kind): return 1 if kind.containerNames is None: return 0 for kindContainerName in kind.containerNames: if self.includes(commonTools.newThing( 'kind', kindContainerName)): return 1 return 0 def intersects(self, kind): """Test whether the given kind has an intersection with self. For example: - Integer has an intersection with Integer. - Number has an intersection with Integer. - Integer has an intersection with Number. """ # To override, because the test below is incomplete. return self.includes(kind) or kind.includes(self) def isEmptyModelValue(self, slot, value): return value is None def isExportable(self): raise NotImplementedError def isHidden(self, slot): layoutMode = context.getVar('layoutMode') if layoutMode == 'edit': isCreateEditMode = context.getVar('isCreateEditMode', default = 0) if isCreateEditMode: return self.stateInCreateMode == 'hidden' \ or (self.stateInCreateMode == 'read-only/hidden-if-empty' and self.modelValueIsEmpty(slot)) \ or (self.stateInCreateMode is None and (self.stateInEditMode == 'hidden' or (self.stateInEditMode == 'read-only/hidden-if-empty' and self.modelValueIsEmpty(slot)))) else: return self.stateInEditMode == 'hidden' \ or self.stateInEditMode == 'read-only/hidden-if-empty' \ and self.modelValueIsEmpty(slot) elif layoutMode == 'use': aspect = context.getVar('aspect') return aspect.state == 'hidden' \ or aspect.state == 'read-only/hidden-if-empty' \ and self.modelValueIsEmpty(slot) else: return self.stateInViewMode == 'hidden' \ or self.stateInViewMode == 'read-only/hidden-if-empty' \ and self.modelValueIsEmpty(slot) def isImportable(self): raise NotImplementedError def isInCore(self, slot): return not self.useCustomStorage and not self.useFileStorage def isReadOnly(self, slot): layoutMode = context.getVar('layoutMode') if layoutMode == 'edit': isCreateEditMode = context.getVar('isCreateEditMode', default = 0) if isCreateEditMode: return self.stateInCreateMode == 'read-only' \ or (self.stateInCreateMode == 'read-only/hidden-if-empty' and not self.modelValueIsEmpty(slot)) \ or (self.stateInCreateMode is None and (self.stateInEditMode == 'read-only' or (self.stateInEditMode == 'read-only/hidden-if-empty' and not self.modelValueIsEmpty(slot)))) else: return self.stateInEditMode == 'read-only' \ or self.stateInEditMode == 'read-only/hidden-if-empty' \ and not self.modelValueIsEmpty(slot) elif layoutMode == 'use': aspect = context.getVar('aspect') return aspect.state == 'read-only' \ or aspect.state == 'read-only/hidden-if-empty' \ and not self.modelValueIsEmpty(slot) else: return self.stateInViewMode == 'read-only' \ or self.stateInViewMode == 'read-only/hidden-if-empty' \ and not self.modelValueIsEmpty(slot) def mayAccept(self, kind): """Test whether the given kind may be compatible with self. For example: - Integer always accepts Integer. - Number always accepts Integer. - Integer may accept Number, because sometimes a Number is an Integer. """ return self.intersects(kind) def modelValueIsEmpty(self, slot): return self.isEmptyModelValue(slot, slot.getValue()) def newJail(self, slot): return jails.Jail(slot) def releaseNonCoreValue(self, slot): pass def removeValueIds(self, slot, value, rolesToKeep): return value def repairValue(self, slot, value, toVersion): assert self.isPractical if toVersion == 5004: if type(value) in (types.StringType, types.UnicodeType): repairedValue = value.replace('\r\n', '\n') repairedValue = repairedValue.replace('\r', '\n') if repairedValue != value: return repairedValue return None def saveNonCoreValue(self, slot, objectDirectoryPath): pass def setAutomaticalValue(self, slot, init = 0): raise NotImplementedError def setToDefaultValue(self, slot): defaultValue = self.getDefaultValue(slot) if defaultValue is not None: slot.setValue(defaultValue) def upgradeModel(self, slot, model, toVersion): changed = 0 # Call upgradeModel_xxx methods. classes = commonTools.getC3ClassLinearization(self.__class__) upgradeMethodNames = [] for class_ in classes: for attributeName in class_.__dict__.keys(): if attributeName.startswith('upgradeModel_'): if not attributeName in upgradeMethodNames: upgradeMethodNames.append(attributeName) upgradeMethodNames.sort() for upgradeMethodName in upgradeMethodNames: if upgradeMethodName[len('upgradeModel_'):] < toVersion: continue modelChanged, model = getattr(self, upgradeMethodName)(slot, model) changed = changed or modelChanged return changed, model register(BaseKind) class AbstractSequence(BaseKind): canInsertOrDelete = 1 minCount = None minCount_kind_label = N_('Minimum Number of Items') minCount_kindName = 'Integer' maxCount = None maxCount_kind_label = N_('Maximum Number of Items') maxCount_kindName = 'Integer' widgetName = 'Multi' def checkModelValue(self, slot, value): BaseKind.checkModelValue(self, slot, value) if value is None: return if self.minCount and len(value) < self.minCount: raise faults.BadSlotValue(slot, value) if self.maxCount and len(value) > self.maxCount: raise faults.BadSlotValue(slot, value) def convertValueIds(self, slot, value, sourceDispatcherId, destinationDispatcherId): try: len(value) except TypeError: raise Exception('Unsized value (= %s) for slot %s' % (value, slot)) for i in range(len(value)): itemSlot = self.getItemSlot(slot, i) newItem = itemSlot.getKind().convertValueIds( itemSlot, value[i], sourceDispatcherId, destinationDispatcherId) if newItem != value[i]: value[i] = newItem return value def executeModel(self, slot, when, command = None): value = slot.getValue() if value is None: return for i in range(len(value)): itemSlot = self.getItemSlot(slot, i) itemSlot.getKind().executeModel(itemSlot, when, command = command) def exportValueToXmlRpc(self, slot, value): if value is None: return [] exportedValue = [] for i in range(len(value)): itemSlot = self.getItemSlot(slot, i) exportedValue.append(itemSlot.getKind().exportValueToXmlRpc( itemSlot, value[i])) return exportedValue def getItemKind(self, index): raise NotImplementedError def getMinCount(self, slot): return self.minCount def getMaxCount(self, slot): return self.maxCount def getItemSlot(self, slot, index): return slots.Item(index, parent = slot) def getModelSlotByPath(self, slot, path): if path.startswith('self'): path = path[len('self'):] if not path: return slot if path[0] != '[' or not ']' in path: raise Exception('Path "%s" not found' % path) index = int(path[1:path.index(']')]) return self.getItemKind(index).getModelSlotByPath( self.getItemSlot(slot, index), path[path.index(']') + 1:]) def getOrderedLayoutSlotNames(self, parentSlot = None): slotNames = BaseKind.getOrderedLayoutSlotNames( self, parentSlot = parentSlot) slotNames += ['maxCount'] return slotNames def importValueFromXmlRpc(self, slot, importedValue): if importedValue is None: return [] value = [] slot.value = value for i in range(len(importedValue)): itemSlot = self.getItemSlot(slot, i) value.append(itemSlot.getKind().importValueFromXmlRpc( itemSlot, importedValue[i])) del slot.value return value def newJail(self, slot): return jails.MutableSequence(slot) def removeValueIds(self, slot, value, rolesToKeep): indexesToDelete = [] for i in range(len(value)): itemSlot = self.getItemSlot(slot, i) newItem = itemSlot.getKind().removeValueIds( itemSlot, value[i], rolesToKeep) if newItem != value[i]: indexesToDelete.append(i) indexesToDelete.reverse() for i in indexesToDelete: del value[i] if not value: return None return value def repairValue(self, slot, value, toVersion): if toVersion == 4000: changed = 0 for i in range(len(value)): itemSlot = self.getItemSlot(slot, i) newItem = itemSlot.getKind().repairValue( itemSlot, value[i], toVersion) if newItem: changed = 1 value[i] = newItem if changed: return value return None def setToDefaultValue(self, slot): BaseKind.setToDefaultValue(self, slot) for i in range(len(slot.getValue() or [])): itemSlot = self.getItemSlot(slot, i) itemKind = itemSlot.getKind() itemKind.setToDefaultValue(itemSlot) def upgradeModel(self, slot, model, toVersion): changed, model = BaseKind.upgradeModel(self, slot, model, toVersion) # Upgrade each item. if model is not None: for i, item in zip(range(len(model)), model): itemSlot = self.getItemSlot(slot, i) itemChanged, item = itemSlot.getKind().upgradeModel( itemSlot, item, toVersion) if itemChanged: changed = 1 model[i] = item return changed, model class Alias(BaseKind): defaultValue_kindName = 'Alias' pythonStorageType = types.StringType thingPublicCategory = None # N_('Glasnost') thingPublicName = N_('Alias') def checkModelValue(self, slot, value): BaseKind.checkModelValue(self, slot, value) if self.isRequired and value == '': raise faults.MissingSlotValue(slot) if value: if ' ' in value: # or '/' in value: raise faults.BadSlotValue(slot, value) register(Alias) class Any(BaseKind): defaultValue_kindName = 'Any' isPractical = 0 thingPublicCategory = None # N_('Glasnost') thingPublicName = N_('Any') register(Any) class Boolean(BaseKind): containerNames = ['Any'] defaultValue = 0 defaultValue_kindName = 'Boolean' labels = { '0': N_('False'), '1': N_('True'), } labels_kind_keyKind_value_stateInEditMode = 'read-only' labels_kind_keyKind_valueName = 'String' labels_kind_label = N_('Labels') labels_kind_valueKind_valueName = 'String' labels_kindName = 'Mapping' possibleWidgetNames = ['InputCheckBox', 'Select'] pythonStorageType = types.IntType # in Python 2.3 that could have been BooleanType sortLabels = 0 sortLabels_kind_balloonHelp = N_( 'Check the box to sort labels alphabetically') sortLabels_kind_importExport = 'private' sortLabels_kind_label = N_('Sort Labels') sortLabels_kind_stateInEditMode = 'hidden' sortLabels_kind_stateInViewMode = 'hidden' sortLabels_kindName = 'Boolean' thingPublicCategory = N_('Numbers') thingPublicName = N_('Boolean') titles = None titles_kind_importExport = 'private' titles_kind_keyKind_value_stateInEditMode = 'read-only' titles_kind_keyKind_valueName = 'String' titles_kind_label = N_('Titles') titles_kind_stateInEditMode = 'hidden' titles_kind_stateInViewMode = 'hidden' titles_kind_valueKind_valueName = 'String' titles_kindName = 'Mapping' values = [0, 1] values_kind_importExport = 'private' values_kind_itemKind_valueName = 'Boolean' values_kind_stateInEditMode = 'hidden' values_kind_stateInViewMode = 'hidden' values_kindName = 'Sequence' widgetName = 'InputCheckBox' def checkModelValue(self, slot, value): BaseKind.checkModelValue(self, slot, value) if value not in (None, 0, 1): raise faults.BadSlotValue(slot, value) def convertValueFromOtherType(self, value): if type(value) is types.StringType: if value in ('0', '1'): return int(value) raise faults.BadValue() return BaseKind.convertValueFromOtherType(self, value) def convertValueToOtherType(self, value, otherType): if otherType is types.StringType: return str(value) return BaseKind.convertValueToOtherType(self, value, otherType) def getGroupedValues(self, slot): return None def getLabels(self, slot): return self.labels def getSortedValues(self, slot): values = self.getValues(slot) if values is not None: values = values[:] labels = self.getLabels(slot) values.sort(lambda x, y: locale.strcoll(_(labels[x]), _(labels[y]))) return values def getValues(self, slot): return self.values def getOrderedLayoutSlotNames(self, parentSlot = None): slotNames = BaseKind.getOrderedLayoutSlotNames( self, parentSlot = parentSlot) slotNames += ['values', 'labels', 'titles'] return slotNames def newJail(self, slot): return jails.Numeric(slot) register(Boolean) class Choice(BaseKind): defaultValue_kindName = 'Choice' groupedValues = None groupedValues_kind_importExport = 'private' groupedValues_kind_keyKind_valueName = 'String' groupedValues_kind_stateInEditMode = 'hidden' groupedValues_kind_stateInViewMode = 'hidden' groupedValues_kind_valueKind_valueName = 'String' groupedValues_kindName = 'Mapping' # only use is in Metis; marked with a FIXME to remove it groupedValuesGetterName = None groupedValuesGetterName_kind_importExport = 'private' groupedValuesGetterName_kind_stateInEditMode = 'hidden' groupedValuesGetterName_kind_stateInViewMode = 'hidden' groupedValuesGetterName_kindName = 'PythonIdentifier' groupNames = None groupNames_kind_importExport = 'private' groupNames_kind_itemKind_valueName = 'String' groupNames_kind_stateInEditMode = 'hidden' groupNames_kind_stateInViewMode = 'hidden' groupNames_kindName = 'Sequence' # only use is in Metis; marked with a FIXME to remove it groupNamesGetterName = None groupNamesGetterName_kind_importExport = 'private' groupNamesGetterName_kind_stateInEditMode = 'hidden' groupNamesGetterName_kind_stateInViewMode = 'hidden' groupNamesGetterName_kindName = 'PythonIdentifier' labels = None labels_kind_importExport = 'private' labels_kind_keyKind_valueName = 'String' labels_kind_label = N_('Labels') labels_kind_stateInEditMode = 'hidden' labels_kind_stateInViewMode = 'hidden' labels_kind_valueKind_valueName = 'String' labels_kindName = 'Mapping' possibleWidgetNames = ['Select', 'RadioButtons'] pythonStorageType = types.StringType sortLabels = 1 sortLabels_kind_importExport = 'private' sortLabels_kind_balloonHelp = N_( 'Check the box to sort labels alphabetically') sortLabels_kind_label = N_('Sort Labels') sortLabels_kind_stateInEditMode = 'hidden' sortLabels_kind_stateInViewMode = 'hidden' sortLabels_kindName = 'Boolean' thingPublicCategory = N_('Data') thingPublicName = N_('Exclusive Choice') titles = None titles_kind_importExport = 'private' titles_kind_keyKind_value_stateInEditMode = 'read-only' titles_kind_keyKind_valueName = 'String' titles_kind_label = N_('Titles') titles_kind_stateInEditMode = 'hidden' titles_kind_stateInViewMode = 'hidden' titles_kind_valueKind_valueName = 'String' titles_kindName = 'Mapping' values = None values_kind_itemKind_valueName = 'String' values_kind_label = N_('Values') values_kindName = 'Sequence' widgetName = 'Select' def checkModelValue(self, slot, value): BaseKind.checkModelValue(self, slot, value) if value and self.values and value not in self.getValues(slot): raise faults.BadSlotValue(slot, value) def getGroupedValues(self, slot): return None def getGroupLabels(self, slot): return None def getLabels(self, slot): if self.labels: return self.labels labels = {} values = self.getValues(slot) if values is not None: for value in values: labels[str(value)] = str(value) return labels def getOrderedLayoutSlotNames(self, parentSlot = None): slotNames = BaseKind.getOrderedLayoutSlotNames( self, parentSlot = parentSlot) slotNames += ['values', 'labels', 'titles'] return slotNames def getSortedValues(self, slot): values = self.getValues(slot) if values is None: return None values = values[:] sortedValues = [] if None in values: sortedValues.append(None) values.remove(None) if '__all__' in values: sortedValues.append('__all__') values.remove('__all__') labels = self.getLabels(slot) values.sort(lambda x, y: locale.strcoll(_(labels[x]), _(labels[y]))) sortedValues += values return sortedValues def getValues(self, slot): groupedValuesGetterName = self.groupedValuesGetterName if groupedValuesGetterName is not None: currentSlot = slot while currentSlot is not None: container = currentSlot.getContainer() try: groupedValuesGetter = getattr(container, groupedValuesGetterName) except AttributeError: currentSlot = currentSlot.parent continue groupedValues = groupedValuesGetter(slot) assert type(groupedValues) is type({}) values = [] for group in groupedValues.keys(): assert type(groupedValues[group]) is type([]) values += groupedValues[group] return values return [] if self.groupedValues: result = [] assert type(self.groupedValues) is type({}) for key in self.groupedValues.keys(): assert type(self.groupedValues[key]) is type([]) for value in self.groupedValues[key]: result.append(value) return result if self.values: return self.values else: return [] register(Choice) class Data(BaseKind): defaultValue_kindName = 'Data' pythonStorageType = types.StringType thingPublicCategory = None # N_('Data') def convertValueFromOtherType(self, value): if type(value) is types.InstanceType and \ value.getThingName() == 'Upload': return value.data def exportValueToXmlRpc(self, slot, value): if value: value = base64.encodestring(value) return value def importValueFromXmlRpc(self, slot, value): if value: value = base64.decodestring(value) return value register(Data) class Time(BaseKind): defaultValue_kindName = 'Time' formatString = '%Y-%m-%d %H:%M:%S' formatString_kind_label = N_('Date & Time Format') formatString_kindName = 'String' formatStringDay = '%Y-%m-%d' formatStringDay_kind_label = N_('Date Format') formatStringDay_kindName = 'String' pythonStorageType = types.FloatType # seconds since epoch textMaxLength = 19 thingPublicCategory = N_('Date & Time') thingPublicName = N_('Date & Time') widget_size = 19 widgetName = 'Time' def convertValueFromOtherType(self, value): if type(value) is types.IntType: return float(value) if type(value) is types.StringType: if value == '': return None formatDate = ( self.formatStringDay, '%Y-%m-%d', '%y-%m-%d', '%d/%m/%Y', '%d/%m/%y' ) formatTime = ( '%H:%M:%S', '%H:%M', '' ) for format in [x + ' ' + y for x in formatDate for y in formatTime]: try: t = time.strptime(value, format) except ValueError: continue break else: raise faults.BadValue() # Set Daylight Saving Time to -1, so that it is handled # correctly by mktime. t = tuple(list(t[0:-1]) + [-1]) try: value = time.mktime(t) except OverflowError: raise faults.BadValue() return value return BaseKind.convertValueFromOtherType(self, value) def convertValueToOtherType(self, value, otherType): if otherType is types.StringType: if not value: return '' tupleTime = time.localtime(value) if tuple(tupleTime[3:6]) == (0, 0, 0): formatString = self.formatStringDay else: formatString = self.formatString return time.strftime(formatString, time.localtime(value)) return BaseKind.convertValueToOtherType(self, value, otherType) register(Time) class DispatcherId(BaseKind): containerNames = ['Any', 'String'] defaultValue_kindName = 'DispatcherId' pythonStorageType = types.StringType thingPublicCategory = None # N_('Glasnost') thingPublicName = N_('Glasnost Dispatcher ID') widget_size = 40 widgetName = 'InputText' def convertValueIds( self, slot, value, sourceDispatcherId, destinationDispatcherId): return value.replace(sourceDispatcherId, destinationDispatcherId) def newJail(self, slot): return jails.String(slot) register(DispatcherId) class Duration(BaseKind): defaultValue_kindName = 'Duration' pythonStorageType = types.FloatType # number of seconds requiredParts = ['day', 'hour', 'minute', 'second'] requiredParts_kind_itemKind_valueName = 'String' requiredParts_kindName = 'Sequence' thingPublicCategory = None # N_('Date & Time') thingPublicName = N_('Duration') widgetName = 'Duration' register(Duration) class Email(BaseKind): containerNames = ['Any', 'String'] defaultValue_kindName = 'Email' pythonStorageType = types.StringType thingPublicCategory = N_('Text') thingPublicName = N_('Email Address') widgetName = 'Email' def checkModelValue(self, slot, value): BaseKind.checkModelValue(self, slot, value) if value is None: return if value == '': if self.isRequired: raise faults.MissingSlotValue(slot) return if not re.match(r'^\S+@\S+$', value): raise faults.BadSlotValue(slot, value) def newJail(self, slot): return jails.String(slot) register(Email) class Fields(BaseKind): containerNames = ['Any'] defaultValue_kindName = 'Fields' pythonStorageType = types.StringType # ~ thingPublicCategory = None # N_('Glasnost') thingPublicName = N_('Fields') def exportValueToXmlRpc(self, slot, value): return base64.encodestring(marshal.dumps(value)) def importValueFromXmlRpc(self, slot, valueImport): return marshal.loads(base64.decodestring(valueImport)) register(Fields) class Path(BaseKind): checkFilePath = 1 checkFilePath_kindName = 'Boolean' containerNames = ['Any', 'String'] defaultValue_kindName = 'Path' pythonStorageType = types.StringType thingPublicCategory = None # N_('Text') thingPublicName = N_('Path') def checkModelValue(self, slot, value): BaseKind.checkModelValue(self, slot, value) if value is None: return if self.checkFilePath: from glasnost.proxy.tools import getProxyForServerRole systemFilesProxy = getProxyForServerRole('systemfiles') systemFilesProxy.checkFilePath(value) def newJail(self, slot): return jails.String(slot) register(Path) class FilePath(Path): containerNames = ['Any', 'String'] defaultValue_kindName = 'FilePath' thingPublicCategory = None # N_('Text') thingPublicName = N_('File Path') def newJail(self, slot): return jails.String(slot) register(FilePath) class Fingerprint(BaseKind): containerNames = ['Any', 'String'] defaultValue_kindName = 'Fingerprint' pythonStorageType = types.StringType textMaxLength = 50 thingPublicCategory = N_('Text') thingPublicName = N_('OpenPGP Fingerprint') def checkModelValue(self, slot, value): BaseKind.checkModelValue(self, slot, value) if value is None or value == '': return value = value.replace(' ', '') if len(value) != 40: raise faults.BadSlotValue(slot, value) for char in value: if char not in string.hexdigits: raise faults.BadSlotValue(slot, value) def convertValueToOtherType(self, value, otherType): if otherType is types.StringType: if value is None: return '' value = value.replace(' ', '') return '%s %s %s %s %s %s %s %s %s %s' % ( value[ 0: 4], value[ 4: 8], value[ 8:12], value[12:16], value[16:20], value[20:24], value[24:28], value[28:32], value[32:36], value[36:40]) return BaseKind.convertValueToOtherType(self, value, otherType) def newJail(self, slot): return jails.String(slot) register(Fingerprint) class Float(BaseKind): defaultValue_kindName = 'Float' pythonStorageType = types.FloatType thingPublicCategory = N_('Numbers') thingPublicName = N_('Float Number') def convertValueFromOtherType(self, value): if type(value) in (types.IntType, types.StringType): try: return float(value) except ValueError: pass return BaseKind.convertValueFromOtherType(self, value) def convertValueToOtherType(self, value, otherType): if otherType is types.StringType: if value is None: return '' return str(value) return BaseKind.convertValueToOtherType(self, value, otherType) def newJail(self, slot): return jails.Numeric(slot) register(Float) class Id(BaseKind): containerNames = ['Any'] defaultValue_kindName = 'Id' permanentIds = None pythonStorageType = types.StringType rememberedIds = 0 rememberedIds_kindName = 'Boolean' serverRoles = None serverRoles_kindName = 'AcceptedRoles' thingPublicCategory = N_('Links') thingPublicName = N_('Object') widgetName = 'SelectId' def checkModelValue(self, slot, value): BaseKind.checkModelValue(self, slot, value) if value: try: commonTools.extractDispatcherId(value) except: raise faults.BadSlotValue(slot, value) def convertValueIds( self, slot, value, sourceDispatcherId, destinationDispatcherId): if value is None: return None return value.replace(sourceDispatcherId, destinationDispatcherId) def equals(self, kind): if not BaseKind.equals(self, kind): return 0 if self.getServerRoles(None) is None: serverRoles = None else: serverRoles = self.getServerRoles(None)[:] serverRoles.sort() if kind.serverRoles is None: kindServerRoles = None else: kindServerRoles = kind.getServerRoles(None)[:] kindServerRoles.sort() return serverRoles == kindServerRoles def getLabels(self, slot): values = self.getValues(slot) from glasnost.proxy.tools import getObjectLabelsTranslated labels = getObjectLabelsTranslated(values, context.getVar('readLanguages')) return labels def getServerRoles(self, slot): return self.serverRoles def getGroupedValues(self, slot): values = self.getValues(slot) groupedValues = {} for v in values: if v in (self.permanentIds or []): role = None else: role = commonTools.extractRole(v) if not groupedValues.has_key(role): groupedValues[role] = [] groupedValues[role].append(v) return groupedValues def getGroupLabels(self, slot): groupNames = self.getGroupedValues(slot).keys() d = {} for role in groupNames: if not role: d[''] = None continue common = getCommonForServerRole(role) d[common.getTranslatedObjectsNameCapitalized()] = role return d def getValues(self, slot): from glasnost.proxy.tools import getProxyForServerRole result = [] result.extend(self.permanentIds or []) currentValue = slot.getValue() serverRoles = self.getServerRoles(slot) or context.getVar('knownRoles') for role in serverRoles: proxy = getProxyForServerRole(role) if not hasattr(proxy, 'getObjectIds'): continue try: objectIds = None if self.rememberedIds: user = context.getVar('user') if user and user.objectsMemory and \ user.objectsMemory.has_key(role) and \ user.objectsMemory[role]: objectIds = user.objectsMemory[role] if currentValue and \ commonTools.extractRole(currentValue) == role: objectIds.append(currentValue) if not objectIds: objectIds = proxy.getObjectIds() except faults.UserAccessDenied: continue if role == 'groups' and serverRoles and serverRoles != ['groups']: objectIds = proxy.getObjectIdsWithCriteria( 'not object.acceptedRoles or '\ ' [x for x in object.acceptedRoles if x in %r]' % ( serverRoles)) result.extend(objectIds) return result def includes(self, kind): if BaseKind.includes(self, kind): return 1 if self.getThingName() != kind.getThingName(): return 0 if not self.getServerRoles(None): return 1 if not kind.getServerRoles(None): return 0 for kindServerRole in kind.serverRoles: if not kindServerRole in self.getServerRoles(None): return 0 return 1 def intersects(self, kind): if BaseKind.intersects(self, kind): return 1 if self.getThingName() != kind.getThingName(): return 0 if not self.getServerRoles(None) or not kind.getServerRoles(None): return 1 for kindServerRole in kind.serverRoles: if kindServerRole in self.getServerRoles(None): return 1 return 0 def isEmptyModelValue(self, slot, value): return not value def removeValueIds(self, slot, value, rolesToKeep): if not commonTools.extractRole(value) in rolesToKeep: return None return value def repairValue(self, slot, value, toVersion): if toVersion == 4000: return repairId(value) return None def upgradeModel_0001_0028(self, slot, model): """Convert user ids from "people" to "identities".""" changed = 0 if self.serverRoles is not None and 'identities' in self.serverRoles \ and not 'people' in self.serverRoles \ and commonTools.extractRole(model) == 'people': changed = 1 model = '%s/%s' % ( commonTools.makeApplicationId(model, 'identities'), commonTools.extractLocalId(model)) return changed, model register(Id) class Integer(BaseKind): containerNames = ['Any'] defaultValue_kindName = 'Integer' max = None max_kind_label = N_('Maximum Value') max_kindName = 'Integer' min = None min_kind_label = N_('Minimum Value') min_kindName = 'Integer' pythonStorageType = types.IntType textMaxLength = 10 thingPublicCategory = N_('Numbers') thingPublicName = N_('Integer Number') def checkModelValue(self, slot, value): BaseKind.checkModelValue(self, slot, value) if value is None: return if self.min is not None and value < self.min: raise faults.ValueTooSmall(slot, value) if self.max is not None and value > self.max: raise faults.ValueTooBig(slot, value) def convertValueFromOtherType(self, value): if type(value) is types.FloatType: return int(value) if type(value) is types.StringType: try: return int(value) except ValueError: raise faults.BadValue() return BaseKind.convertValueFromOtherType(self, value) def convertValueToOtherType(self, value, otherType): if otherType is types.StringType: if value is None: return '' return str(value) if otherType is types.FloatType: return float(value) return BaseKind.convertValueToOtherType(self, value, otherType) def getOrderedLayoutSlotNames(self, parentSlot = None): slotNames = BaseKind.getOrderedLayoutSlotNames( self, parentSlot = parentSlot) slotNames = slotNames[:] i = slotNames.index('defaultValue') slotNames[i:i] = ['min', 'max'] return slotNames def getTextMaxLength(self): if self.min is not None and self.max is not None: textMaxLength = max(len(str(self.min)), len(str(self.max))) else: textMaxLength = BaseKind.getTextMaxLength(self) return textMaxLength def newJail(self, slot): return jails.Numeric(slot) register(Integer) class IntegerChoice(Choice): defaultValue_kindName = 'IntegerChoice' pythonStorageType = types.IntType thingPublicCategory = None # N_('Choice') thingPublicName = N_('Integer Choice') titles_kind_keyKind_valueName = 'Integer' values_kind_itemKind_valueName = 'Integer' register(IntegerChoice) class LanguageChoice(Choice): balloonHelp = N_('Select the [language->language] of '\ 'this [object->objects].') containerNames = ['Any'] defaultValue_kindName = 'LanguageChoice' label = N_('Language') labels = translation.languageLabels isRequired = 1 thingPublicCategory = N_('Data') thingPublicName = N_('Language') values = translation.languageKeys values_kind_importExport = 'private' values_kind_stateInEditMode = 'hidden' values_kind_stateInViewMode = 'hidden' def checkModelValue(self, slot, value): BaseKind.checkModelValue(self, slot, value) return 1 def getDefaultValue(self, slot): languages = context.getVar('readLanguages') if languages and languages[0] in self.values: return languages[0] else: return 'en' def getValues(self, slot): from glasnost.proxy.tools import getProxyForServerRole translationsProxy = getProxyForServerRole('translations') if translationsProxy: try: return translationsProxy.getPossibleLanguages() except faults.UnknownServerId: return self.values return self.values register(LanguageChoice) class Link(BaseKind): defaultValue_kindName = 'Link' pythonStorageType = types.TupleType # (name, url) thingPublicCategory = None # N_('Data') thingPublicName = N_('Link') def checkModelValue(self, slot, value): BaseKind.checkModelValue(self, slot, value) if value is None: return if len(value) != 2: raise faults.BadSlotValue(slot, value) def convertValueIds( self, slot, value, sourceDispatcherId, destinationDispatcherId): name, url = value if url.startswith('id:'): url = url.replace(sourceDispatcherId, destinationDispatcherId) return (name, url) def isEmptyModelValue(self, slot, value): return value is None or not value[0] and not value[1] def removeValueIds(self, slot, value, rolesToKeep): name, url = value if url.startswith('id:') \ and not commonTools.extractRole(url[3:]) in rolesToKeep: return None return value def repairValue(self, slot, value, toVersion): if toVersion == 4000: name, url = value if url.startswith('id:'): newId = repairId(url[3:]) if newId: return (name, 'id:' + newId) return None register(Link) class Mapping(BaseKind): containerNames = ['Any'] defaultValue_kindName = 'Mapping' deleteNullValues = 0 deleteNullValues_kindName = 'Boolean' keyKind = None keyKind_kind_isRequired = 1 keyKind_kindName = 'Kind' pythonStorageType = types.DictType requiredCount = 0 requiredCount_kindName = 'Integer' thingPublicCategory = None # N_('Data') thingPublicName = N_('Mapping') valueKind = None valueKind_kind_isRequired = 1 valueKind_kindName = 'Kind' widgetName = 'Mapping' def buildKinds(self): # Should be converted to a class method, when porting Glasnost to # Python 2.2. BaseKind.buildKinds(self) # Build keyKind from keyKind_valueName attributes. if hasattr(self, 'keyKind_valueName') \ and self.keyKind_valueName is not None: baseClasses = self.getC3ClassLinearization() keyKindOptionNames = [key for key in self.__dict__.keys() if key.startswith('keyKind_value_')] for baseClass in baseClasses: for key in baseClass.__dict__.keys(): if key.startswith('keyKind_value_') \ and not key in keyKindOptionNames: keyKindOptionNames.append(key) keyKindOptions = {} for keyKindOptionName in keyKindOptionNames: keyKindOptions[keyKindOptionName[len('keyKind_value_'):] ] = getattr(self, keyKindOptionName) keyKind = commonTools.newThing('kind', self.keyKind_valueName) keyKind.buildOptions(keyKindOptions) self.__class__.keyKind = keyKind # Build valueKind from valueKind_valueName attributes. if hasattr(self, 'valueKind_valueName') \ and self.valueKind_valueName is not None: baseClasses = self.getC3ClassLinearization() valueKindOptionNames = [key for key in self.__dict__.keys() if key.startswith('valueKind_value_')] for baseClass in baseClasses: for key in baseClass.__dict__.keys(): if key.startswith('valueKind_value_') \ and not key in valueKindOptionNames: valueKindOptionNames.append(key) valueKindOptions = {} for valueKindOptionName in valueKindOptionNames: valueKindOptions[valueKindOptionName[len('valueKind_value_'):] ] = getattr(self, valueKindOptionName) valueKind = commonTools.newThing('kind', self.valueKind_valueName) valueKind.buildOptions(valueKindOptions) self.__class__.valueKind = valueKind # Build keyKind from keyKind_valueClass attributes. if hasattr(self, 'keyKind_valueClass') \ and self.keyKind_valueClass is not None: realKindClass = commonTools.getThingClass( 'kind', self.keyKind_valueClass._kindName) class class_(self.keyKind_valueClass, realKindClass): pass kind = class_() kind.buildOptions({}) self.__class__.keyKind = kind # Build valueKind from valueKind_valueClass attributes. if hasattr(self, 'valueKind_valueClass') \ and self.valueKind_valueClass is not None: realKindClass = commonTools.getThingClass( 'kind', self.valueKind_valueClass._kindName) class class_(self.valueKind_valueClass, realKindClass): pass kind = class_() kind.buildOptions({}) self.__class__.valueKind = kind def buildOptions(self, options): baseClasses = self.getC3ClassLinearization() keyKindOptionNames = [key for key in self.__dict__.keys() if key.startswith('keyKind_value_')] for baseClass in baseClasses: for key in baseClass.__dict__.keys(): if key.startswith('keyKind_value_') \ and not key in keyKindOptionNames: keyKindOptionNames.append(key) keyKindOptions = {} for keyKindOptionName in keyKindOptionNames: keyKindOptions[keyKindOptionName[len('keyKind_value_'):] ] = getattr(self, keyKindOptionName) keyKindOptionNames = [key for key in options.keys() if key.startswith('keyKind_value_')] for keyKindOptionName in keyKindOptionNames: keyKindOptions[keyKindOptionName[len('keyKind_value_'):] ] = options[keyKindOptionName] del options[keyKindOptionName] if options.has_key('keyKind_valueName'): keyKindName = options['keyKind_valueName'] del options['keyKind_valueName'] elif hasattr(self, 'keyKind_valueName'): keyKindName = self.keyKind_valueName else: keyKindName = None if options.has_key('keyKind_valueClass'): keyKindClass = options['keyKind_valueClass'] del options['keyKind_valueClass'] elif hasattr(self, 'keyKind_valueClass'): keyKindClass = self.keyKind_valueClass else: keyKindClass = None valueKindOptionNames = [key for key in self.__dict__.keys() if key.startswith('valueKind_value_')] for baseClass in baseClasses: for key in baseClass.__dict__.keys(): if key.startswith('valueKind_value_') \ and not key in valueKindOptionNames: valueKindOptionNames.append(key) valueKindOptions = {} for valueKindOptionName in valueKindOptionNames: valueKindOptions[valueKindOptionName[len('valueKind_value_'):] ] = getattr(self, valueKindOptionName) valueKindOptionNames = [key for key in options.keys() if key.startswith('valueKind_value_')] for valueKindOptionName in valueKindOptionNames: valueKindOptions[valueKindOptionName[len('valueKind_value_'):] ] = options[valueKindOptionName] del options[valueKindOptionName] if options.has_key('valueKind_valueName'): valueKindName = options['valueKind_valueName'] del options['valueKind_valueName'] elif hasattr(self, 'valueKind_valueName'): valueKindName = self.valueKind_valueName else: valueKindName = None if options.has_key('valueKind_valueClass'): valueKindClass = options['valueKind_valueClass'] del options['valueKind_valueClass'] elif hasattr(self, 'valueKind_valueClass'): valueKindClass = self.valueKind_valueClass else: valueKindClass = None BaseKind.buildOptions(self, options) if keyKindClass is not None: realKindClass = commonTools.getThingClass( 'kind', keyKindClass._kindName) class class_(keyKindClass, realKindClass): pass keyKind = class_() keyKind.buildOptions(keyKindOptions) self.keyKind = keyKind elif keyKindName is not None: keyKind = commonTools.newThing('kind', keyKindName) keyKind.buildOptions(keyKindOptions) self.keyKind = keyKind if valueKindClass is not None: realKindClass = commonTools.getThingClass( 'kind', valueKindClass._kindName) class class_(valueKindClass, realKindClass): pass valueKind = class_() valueKind.buildOptions(valueKindOptions) self.valueKind = valueKind elif valueKindName is not None: valueKind = commonTools.newThing('kind', valueKindName) valueKind.buildOptions(valueKindOptions) self.valueKind = valueKind def checkModelValue(self, slot, value): BaseKind.checkModelValue(self, slot, value) if self.requiredCount > 0: if value is None: raise faults.MissingSlotValue(slot) if len(value) < self.requiredCount: raise faults.BadSlotValue(slot, value) def convertValueIds( self, slot, value, sourceDispatcherId, destinationDispatcherId): keyIndex = 0 for key, val in value.items(): keySlot = self.getItemKeySlot(slot, keyIndex) newKey = keySlot.getKind().convertValueIds( keySlot, key, sourceDispatcherId, destinationDispatcherId) if newKey != key: del value[key] value[newKey] = val keyIndex += 1 for key, val in value.items(): valueSlot = self.getItemValueSlot(slot, key) newVal = valueSlot.getKind().convertValueIds( valueSlot, val, sourceDispatcherId, destinationDispatcherId) if newVal != val: value[key] = newVal return value def executeModel(self, slot, when, command = None): value = slot.getValue() if value is None: return keyIndex = 0 for key, itemValue in value.items(): keySlot = self.getItemKeySlot(slot, keyIndex) keySlot.getKind().executeModel(keySlot, when, command = command) valueSlot = self.getItemValueSlot(slot, key) valueSlot.getKind().executeModel( valueSlot, when, command = command) keyIndex += 1 def exportValueToXmlRpc(self, slot, value): if value is None: return {} exportedValue = {} keyIndex = 0 try: value.items() except: raise str((self, slot, value)) for key, itemValue in value.items(): keySlot = self.getItemKeySlot(slot, keyIndex) exportedKey = keySlot.getKind().exportValueToXmlRpc(keySlot, key) valueSlot = self.getItemValueSlot(slot, key) exportedItemValue = valueSlot.getKind().exportValueToXmlRpc( valueSlot, itemValue) exportedValue[exportedKey] = exportedItemValue keyIndex += 1 return exportedValue def getItemKeyKind(self, index): return self.keyKind def getItemKeySlot(self, slot, index): return slots.ItemKey(index, parent = slot) def getItemKeyValueKind(self, key): return self.valueKind def getItemKeyValueSlot(self, slot): return slots.ItemKeyValue(parent = slot) def getItemValueKind(self, key): return self.valueKind def getItemValueSlot(self, slot, key): return slots.ItemValue(key, parent = slot) def getModelSlotByPath(self, slot, path): if path.startswith('self'): path = path[len('self'):] if not path: return slot if path.startswith('.keys()[') and ']' in path: index = int(path[len('.keys()['):path.index(']')]) return self.getItemKeyKind(index).getModelSlotByPath( self.getItemKeySlot(slot, index), path[path.index(']') + 1:]) if path[0] != '[' or not ']' in path: raise Exception('Path "%s" not found' % path) key = eval(path[1:path.index(']')], {}) return self.getItemValueKind(key).getModelSlotByPath( self.getItemValueSlot(slot, key), path[path.index(']') + 1:]) def importValueFromXmlRpc(self, slot, importedValue): if importedValue is None: return {} value = {} slot.value = value keyIndex = 0 for importedKey, importedItemValue in importedValue.items(): keySlot = self.getItemKeySlot(slot, keyIndex) key = keySlot.getKind().importValueFromXmlRpc(keySlot, importedKey) valueSlot = self.getItemValueSlot(slot, key) itemValue = valueSlot.getKind().importValueFromXmlRpc( valueSlot, importedItemValue) value[key] = itemValue keyIndex += 1 del slot.value return value def isEmptyModelValue(self, slot, value): return not value def newJail(self, slot): return jails.Mapping(slot) def removeValueIds(self, slot, value, rolesToKeep): keyIndex = 0 for key, val in value.items(): keySlot = self.getItemKeySlot(slot, keyIndex) newKey = keySlot.getKind().removeValueIds( keySlot, key, rolesToKeep) if newKey != key: del value[key] keyIndex += 1 for key, val in value.items(): valueSlot = self.getItemValueSlot(slot, key) newVal = valueSlot.getKind().removeValueIds( valueSlot, val, rolesToKeep) if newVal != val: del value[key] if not value: return None return value def repairValue(self, slot, value, toVersion): if toVersion == 4000: changed = 0 keyIndex = 0 for key, val in value.items(): keySlot = self.getItemKeySlot(slot, keyIndex) newKey = keySlot.getKind().repairValue(keySlot, key, toVersion) if newKey: changed = 1 del value[key] value[newKey] = val keyIndex += 1 for key, val in value.items(): valueSlot = self.getItemValueSlot(slot, key) newVal = valueSlot.getKind().repairValue( valueSlot, val, toVersion) if newVal: changed = 1 value[key] = newVal if changed: return value return None def upgradeModel(self, slot, model, toVersion): changed, model = BaseKind.upgradeModel(self, slot, model, toVersion) # Upgrade each key and value. if model is not None: for keyIndex, key in zip(range(len(model.keys())), model.keys()): keySlot = self.getItemKeySlot(slot, keyIndex) keyChanged, upgradedKey = keySlot.getKind().upgradeModel( keySlot, key, toVersion) if keyChanged: changed = 1 model[upgradedKey] = model.pop(key) for key, value in model.items(): valueSlot = self.getItemValueSlot(slot, key) valueChanged, value = valueSlot.getKind().upgradeModel( valueSlot, value, toVersion) if valueChanged: changed = 1 model[key] = value return changed, model register(Mapping) class Marks(BaseKind): defaultValue_kindName = 'Marks' pythonStorageType = types.DictType ## thingPublicCategory = N_('Other') def convertValueIds( self, slot, value, sourceDispatcherId, destinationDispatcherId): for id, mark in value.items(): newId = id.replace(sourceDispatcherId, destinationDispatcherId) if newId != id: del value[id] value[newId] = mark return value def exportValueToXmlRpc(self, slot, value): exportedValue = {} if value is not None: for objectId, mark in value.items(): if mark is None: exportedMark = -1 else: exportedMark = mark exportedValue[objectId] = exportedMark return exportedValue def importValueFromXmlRpc(self, slot, importedValue): value = {} slot.value = value for objectId, importedMark in importedValue.items(): if importedMark == -1: mark = None else: mark = importedMark value[objectId] = mark if not value: value = None del slot.value return value def removeValueIds(self, slot, value, rolesToKeep): for id in value.keys(): if not commonTools.extractRole(id) in rolesToKeep: del value[id] if not value: return None return value def repairValue(self, slot, value, toVersion): if toVersion == 4000: changed = 0 for id, mark in value.items(): newId = repairId(id) if newId: changed = 1 del value[id] value[newId] = mark if changed: return value return None register(Marks) class Memory(BaseKind): defaultValue_kindName = 'Memory' pythonStorageType = types.DictType ## thingPublicCategory = N_('Other') def checkModelValue(self, slot, value): BaseKind.checkModelValue(self, slot, value) if value and type(value) is not types.DictType: raise faults.BadSlotValue(slot, value) def convertValueIds( self, slot, value, sourceDispatcherId, destinationDispatcherId): for serverId, serverMemory in value.items(): newServerId = serverId.replace( sourceDispatcherId, destinationDispatcherId) if newServerId != serverId: del value[serverId] value[newServerId] = serverMemory for i in range(len(serverMemory)): itemId = serverMemory[i] newItemId = itemId.replace( sourceDispatcherId, destinationDispatcherId) if newItemId != itemId: serverMemory[i] = newItemId return value def removeValueIds(self, slot, value, rolesToKeep): for serverId, serverMemory in value.items(): if not commonTools.extractRole(serverId) in rolesToKeep: del value[serverId] continue indexesToDelete = [] for i in range(len(serverMemory)): itemId = serverMemory[i] if not commonTools.extractRole(itemId) in rolesToKeep: indexesToDelete.append(i) indexesToDelete.reverse() for i in indexesToDelete: del serverMemory[i] if not serverMemory: del value[serverId] if not value: return None return value register(Memory) class PairwiseMatrix(BaseKind): defaultValue_kindName = 'PairwiseMatrix' pythonStorageType = types.DictType ## thingPublicCategory = N_('Other') def checkModelValue(self, slot, value): BaseKind.checkModelValue(self, slot, value) if value and type(value) is not types.DictType: raise faults.BadSlotValue(slot, value) def convertValueIds( self, slot, value, sourceDispatcherId, destinationDispatcherId): for id1, row in value.items(): newId1 = id1.replace(sourceDispatcherId, destinationDispatcherId) if newId1 != id1: del value[id1] value[newId1] = row for id2, score in row.items(): newId2 = id2.replace( sourceDispatcherId, destinationDispatcherId) if newId2 != id2: del row[id2] row[newId2] = score return value def removeValueIds(self, slot, value, rolesToKeep): for id1, row in value.items(): if not commonTools.extractRole(id1) in rolesToKeep: del value[id1] continue for id2, score in row.items(): if not commonTools.extractRole(id2) in rolesToKeep: del row[id2] if not row: del value[id1] if not value: return None return value def repairValue(self, slot, value, toVersion): if toVersion == 4000: changed = 0 for id1, row in value.items(): newId1 = repairId(id1) if newId1: changed = 1 del value[id1] value[newId1] = row for id2, score in row.items(): newId2 = repairId(id2) if newId2: changed = 1 del row[id2] row[newId2] = score if changed: return value return None register(PairwiseMatrix) class Password(BaseKind): defaultValue_kindName = 'Password' # enterTwice is not used anymore, but should be... enterTwice = 0 enterTwice_kind_importExport = 'private' enterTwice_kind_label = N_('Enter Twice') enterTwice_kind_stateInEditMode = 'hidden' enterTwice_kind_stateInViewMode = 'hidden' enterTwice_kindName = 'Boolean' pythonStorageType = types.StringType thingPublicCategory = N_('Text') thingPublicName = N_('Password') widgetName = 'InputPassword' register(Password) class PythonIdentifier(BaseKind): defaultValue_kindName = 'PythonIdentifier' invalidValues = None invalidValues_kind_itemKind_valueName = 'PythonIdentifier' invalidValues_kind_label = N_('Invalid values') invalidValues_kindName = 'Sequence' pythonStorageType = types.StringType thingPublicCategory = None # N_('Text') thingPublicName = N_('Python Identifier') def checkModelValue(self, slot, value): BaseKind.checkModelValue(self, slot, value) if value is None: return if self.invalidValues and value in self.invalidValues: raise faults.BadSlotValue(slot, value) if re.match('[a-zA-Z_][a-zA-Z0-9_]*$', value) is None: raise faults.BadSlotValue(slot, value) register(PythonIdentifier) class Rating(BaseKind): defaultValue_kindName = 'Rating' pythonStorageType = types.DictType ## thingPublicCategory = N_('Other') def checkModelValue(self, slot, value): BaseKind.checkModelValue(self, slot, value) if value and type(value) is not types.DictType: raise faults.BadSlotValue(slot, value) def convertValueIds( self, slot, value, sourceDispatcherId, destinationDispatcherId): for k in ['wins', 'losses', 'ties']: v = value[k] for i in range(len(v)): id = v[i] newId = id.replace(sourceDispatcherId, destinationDispatcherId) if newId != id: v[i] = newId return value def removeValueIds(self, slot, value, rolesToKeep): for k in ['wins', 'losses', 'ties']: v = value[k] r = range(len(v)) r.reverse() for i in r: id = v[i] if not commonTools.extractRole(id) in rolesToKeep: del v[i] return value def repairValue(self, slot, value, toVersion): if toVersion == 4000: changed = 0 for k in ['wins', 'losses', 'ties']: v = value[k] for i in range(len(v)): id = v[i] newId = repairId(id) if newId: changed = 1 v[i] = newId if changed: return value return None register(Rating) class Script(BaseKind): builtins = { 'abs': abs, 'cmp': cmp, 'complex': complex, 'divmod': divmod, 'float': float, 'hash': hash, 'hex': hex, 'int': int, 'len': len, 'long': long, 'None': None, 'oct': oct, 'pow': pow, 'repr': repr, 'str': str, 'unicode': unicode, } containerNames = ['Any', 'String'] defaultValue_kindName = 'Script' executeOnDisplay = 0 class executeOnDisplay_kindClass: _kindName = 'Boolean' label = N_('Execute On Display') executeOnSubmit = 0 class executeOnSubmit_kindClass: _kindName = 'Boolean' label = N_('Execute On Submit') sourceCode = None class sourceCode_kindClass: _kindName = 'ScriptSourceCode' label = N_('Source Code') #tagInEditMode = 'div' #tagInViewMode = 'div' stateInEditMode = 'read-only' stateInViewMode = 'read-only' textFormat = 'text' thingPublicCategory = N_('Data') thingPublicName = N_('Script') widgetName = 'TextArea' def executeModel(self, slot, when, command = None): if not (when == 'onDisplay' and self.executeOnDisplay) \ and not (when == 'onSubmit' and self.executeOnSubmit): return if not self.sourceCode: return objectSlot = slots.Root(slot.getObject()) objectJail = objectSlot.newJail() globals_ = { '__builtins__': self.builtins, 'command': command, 'self': objectJail, } locals_ = {} # stdin = sys.stdin stdout = sys.stdout stderr = sys.stderr sys.stdout = sys.stderr = executionOutputIO = cStringIO.StringIO() try: exec '%s\n' % self.sourceCode in globals_, locals_ except: ## traceback.print_exception(sys.exc_type, sys.exc_value, None) traceback.print_exc() # sys.stdin = stdin sys.stdout = stdout sys.stderr = stderr slot.setValue(executionOutputIO.getvalue()) def getOrderedLayoutSlotNames(self, parentSlot = None): slotNames = BaseKind.getOrderedLayoutSlotNames( self, parentSlot = parentSlot) slotNames += ['sourceCode', 'executeOnDisplay', 'executeOnSubmit'] return slotNames def newJail(self, slot): return jails.String(slot) register(Script) class ScriptSourceCode(BaseKind): containerNames = ['Any', 'String'] defaultValue_kindName = 'ScriptSourceCode' pythonStorageType = types.StringType thingPublicCategory = None # N_('Data') thingPublicName = N_('Script Source Code') widget_rows = 10 widget_viewInTextArea = 1 widgetName = 'TextArea' def checkModelValue(self, slot, value): BaseKind.checkModelValue(self, slot, value) if value and type(value) is not types.StringType: raise faults.BadSlotValue(slot, value) if value and ( value.find ('__') >= 0 or value.find ('_model') >= 0): raise faults.BadSlotValue(slot, value) def newJail(self, slot): return jails.String(slot) register(ScriptSourceCode) class Sequence(AbstractSequence): containerNames = ['Any'] defaultValue_kindName = 'Sequence' class isRequired_kindClass(AbstractSequence.isRequired_kindClass): importExport = 'private' stateInEditMode = 'hidden' stateInViewMode = 'hidden' itemKind = None itemKind_kind_isRequired = 1 itemKind_kind_label = N_('Item Type') itemKind_kindName = 'Kind' itemKind_valueName = 'String' pythonStorageType = types.ListType thingPublicCategory = N_('Data') thingPublicName = N_('Sequence') def buildKinds(self): # Should be converted to a class method, when porting Glasnost to # Python 2.2. AbstractSequence.buildKinds(self) # Build itemKind from itemKind_valueName attributes. if hasattr(self, 'itemKind_valueName') \ and self.itemKind_valueName is not None: baseClasses = self.getC3ClassLinearization() itemKindOptionNames = [key for key in self.__dict__.keys() if key.startswith('itemKind_value_')] for baseClass in baseClasses: for key in baseClass.__dict__.keys(): if key.startswith('itemKind_value_') \ and not key in itemKindOptionNames: itemKindOptionNames.append(key) itemKindOptions = {} for itemKindOptionName in itemKindOptionNames: itemKindOptions[itemKindOptionName[len('itemKind_value_'):] ] = getattr(self, itemKindOptionName) itemKind = commonTools.newThing('kind', self.itemKind_valueName) itemKind.buildOptions(itemKindOptions) self.__class__.itemKind = itemKind # Build itemKind from itemKind_valueClass attributes. if hasattr(self, 'itemKind_valueClass') \ and self.itemKind_valueClass is not None: realKindClass = commonTools.getThingClass( 'kind', self.itemKind_valueClass._kindName) class class_(self.itemKind_valueClass, realKindClass): pass kind = class_() kind.buildOptions({}) self.__class__.itemKind = kind def buildOptions(self, options): baseClasses = self.getC3ClassLinearization() itemKindOptionNames = [key for key in self.__dict__.keys() if key.startswith('itemKind_value_')] for baseClass in baseClasses: for key in baseClass.__dict__.keys(): if key.startswith('itemKind_value_') \ and not key in itemKindOptionNames: itemKindOptionNames.append(key) itemKindOptions = {} for itemKindOptionName in itemKindOptionNames: itemKindOptions[itemKindOptionName[len('itemKind_value_'):] ] = getattr(self, itemKindOptionName) itemKindOptionNames = [key for key in options.keys() if key.startswith('itemKind_value_')] for itemKindOptionName in itemKindOptionNames: itemKindOptions[itemKindOptionName[len('itemKind_value_'):] ] = options[itemKindOptionName] del options[itemKindOptionName] if options.has_key('itemKind_valueName'): itemKindName = options['itemKind_valueName'] del options['itemKind_valueName'] else: itemKindName = self.itemKind_valueName if options.has_key('itemKind_valueClass'): itemKindClass = options['itemKind_valueClass'] del options['itemKind_valueClass'] elif hasattr(self, 'itemKind_valueClass'): itemKindClass = self.itemKind_valueClass else: itemKindClass = None AbstractSequence.buildOptions(self, options) if itemKindClass is not None: realKindClass = commonTools.getThingClass( 'kind', itemKindClass._kindName) class class_(itemKindClass, realKindClass): pass itemKind = class_() itemKind.buildOptions(itemKindOptions) self.itemKind = itemKind elif itemKindName is not None: itemKind = commonTools.newThing('kind', itemKindName) itemKind.buildOptions(itemKindOptions) self.itemKind = itemKind #def checkModelValue(self, slot, value): # AbstractSequence.checkModelValue(self, slot, value) # if len(value or []) < self.requiredCount: # raise faults.MissingSlotValue(slot) #def getDefaultValue(self, slot): # if self.defaultValue: # return self.defaultValue # return [self.itemKind.getDefaultValue(slot) \ # for i in range(self.minCount or 1)] def getItemKind(self, index): return self.itemKind ## def getModelLabel(self, slot): ## if self.label: ## return self.label ## return self.itemKind.getModelLabelPlural(self.getItemSlot(slot, 0)) ## def getModelLabelPlural(self, slot): ## if self.labelPlural: ## return self.labelPlural ## return self.itemKind.getModelLabelPlural(self.getItemSlot(slot, 0)) def getOrderedLayoutSlotNames(self, parentSlot = None): slotNames = AbstractSequence.getOrderedLayoutSlotNames( self, parentSlot = parentSlot) slotNames = slotNames[:] i = slotNames.index('maxCount') slotNames[i:i] = ['itemKind'] return slotNames def includes(self, kind): if AbstractSequence.includes(self, kind): return 1 if not isinstance(kind, Sequence): return 0 if self.itemKind is None: return 1 if kind.itemKind is None: return 0 return self.itemKind.includes(kind.itemKind) def intersects(self, kind): if AbstractSequence.intersects(self, kind): return 1 if not isinstance(kind, Sequence): return 0 if self.itemKind is None or kind.itemKind is None: return 1 return self.itemKind.intersects(kind.itemKind) def isEmptyModelValue(self, slot, value): return not value register(Sequence) class AcceptedRoles(Sequence): balloonHelp = N_('Select accepted Glasnost objects types. '\ 'Click on "Apply" to update the list proposed below.') containerNames = ['Any', 'Sequence'] defaultValue = [ '__all__' ] defaultValue_kindName = 'AcceptedRoles' itemKind_kind_importExport = 'private' itemKind_kind_stateInEditMode = 'hidden' itemKind_kind_stateInViewMode = 'hidden' itemKind_value_allowAll = 1 itemKind_value_allowNone = 1 itemKind_valueName = 'ServerRole' label = N_('Accepted Types') minCount = 1 thingPublicCategory = None # N_('Data') thingPublicName = N_('Accepted Roles') register(AcceptedRoles) class UsersSet(Sequence): containerNames = ['Any', 'Sequence'] defaultValue_kindName = 'UsersSet' itemKind_kind_importExport = 'private' itemKind_kind_stateInEditMode = 'hidden' itemKind_kind_stateInViewMode = 'hidden' itemKind_value_permanentIds = [system.generalPublicId, system.loggedUsersGroupId] itemKind_value_serverRoles = ['groups', 'identities'] itemKind_valueName = 'Id' label = N_('Users') minCount = 0 thingPublicCategory = N_('People Set') thingPublicName = N_('Users') def getDefaultValue(self, slot): userId = context.getVar('userId') if userId: return [userId] else: return None register(UsersSet) class AuthorsSet(UsersSet): balloonHelp = N_('Choose the author(s) for this object.') containerNames = ['Any', 'Sequence'] defaultValue_kindName = 'AuthorsSet' # Remove generelPublic from the menu, because the authorsSet must be # countable. # FIXME: that's useless since the user may "visit" the group and it will # be shown nevertheless itemKind_value_permanentIds = None itemKind_value_serverRoles = ['groups', 'people'] label = N_('Authors') thingPublicName = N_('Authors') def getDefaultValue(self, slot): user = context.getVar('user') if user is not None and user.personId is not None: return [user.personId] else: return None register(AuthorsSet) class Properties(Sequence): itemKind_kind_importExport = 'private' itemKind_kind_stateInEditMode = 'hidden' itemKind_kind_stateInViewMode = 'hidden' itemKind_value_valueThingCategory = 'other' itemKind_value_valueThingName = 'Property' itemKind_valueName = 'Thing' label = N_('Properties') stateInViewMode = 'read-only/hidden-if-empty' thingPublicCategory = None # N_('Glasnost') thingPublicName = N_('Properties') widget_reorderingButtons = 0 widgetName = 'Multi' def exportValueToXmlRpc(self, slot, value): if value is None: return [] exportedValue = [] for i in range(len(value)): property = value[i] propertySlot = self.getPropertySlot(slot, property.name) exportedProperty = propertySlot.getKind().exportValueToXmlRpc( propertySlot, property) exportedValue.append(exportedProperty) return exportedValue def getItemSlot(self, slot, index): return slots.PropertiesItem(index, parent = slot) def getModelSlotByPath(self, slot, path): if path.startswith('self'): path = path[len('self'):] if not path: return slot if path[0] != '[' or not ']' in path: raise Exception('Path "%s" not found' % path) key = eval(path[1:path.index(']')], {}) if type(key) in (types.StringType, types.UnicodeType): # Key is a property name. # FIXME: We should raise Exception('Path "%s" not found' % path), # when there is no property named key. kind = slot.getContainer().getDirectPropertyValueKind(key) if kind is None: kind = slot.getContainer().getPropertyValueKind(key) kind = copy.deepcopy(kind) property = commonTools.newThing('other', 'Property') property.kind = kind property.name = key return property.getSlotByPath( path[path.index(']') + 1:], parentSlot = slot.getContainer().getPropertySlot( key, parentSlot = slot.parent)) else: # Key is an integer index. return self.getItemKind(key).getModelSlotByPath( self.getItemSlot(slot, key), path[path.index(']') + 1:]) def getPropertySlot(self, slot, name): return slots.Property(name, parent = slot) def importValueFromXmlRpc(self, slot, importedValue): if importedValue is None: return [] value = [] slot.value = value for i in range(len(importedValue)): importedProperty = importedValue[i] propertyName = importedProperty['name'] propertySlot = self.getPropertySlot(slot, propertyName) value.append(propertySlot.getKind().importValueFromXmlRpc( propertySlot, importedProperty)) del slot.value return value register(Properties) class ReadersSet(UsersSet): balloonHelp = N_( 'Select one or more [readers->readers-and-editors] or groups of readers for '\ 'this [object->objects] (Readers are allowed to view objects, they have '\ 'read access to them). '\ 'Click on "[Others->buttons-others]" if your choice is not proposed in the '\ 'list. Click on "Add" to add another one. '\ 'Select "None" to remove one.') containerNames = ['Any', 'Sequence', 'UsersSet'] defaultValue_kindName = 'ReadersSet' label = N_('Readers') thingPublicName = N_('Readers') register(ReadersSet) class ServerId(Id): containerNames = ['Any', 'String'] defaultValue_kindName = 'ServerId' thingPublicCategory = None # N_('Glasnost') thingPublicName = N_('Glasnost Server ID') ## widgetName = 'SelectServerId' widget_size = 40 widgetName = 'InputText' def newJail(self, slot): return jails.String(slot) def removeValueIds(self, slot, value, rolesToKeep): return value register(ServerId) class ServerRole(Choice): allowAll = 0 allowAll_kindName = 'Boolean' allowNone = 0 allowNone_kindName = 'Boolean' containerNames = ['Any', 'String'] defaultValue_kindName = 'ServerRole' pythonStorageType = types.StringType thingPublicCategory = None # N_('Glasnost') thingPublicName = N_('Server Role') def getLabels(self, slot): roles = self.getValues(slot) labels = {} for role in roles: if role in [None, '__all__']: continue common = getCommonForServerRole(role) if common is None: label = role else: label = common.objectsNameCapitalized labels[role] = label return labels def getValues(self, slot): from glasnost.proxy.DispatcherProxy import getRegisteredRoles values = [] if self.allowNone: values.append(None) if self.allowAll: values.append('__all__') registeredRoles = getRegisteredRoles(context.getVar('dispatcherId')) for role in registeredRoles: common = getCommonForServerRole(role) if common is None: continue if not hasattr(common, 'useObjectIds') or not common.useObjectIds: continue values.append(role) return values def newJail(self, slot): return jails.String(slot) register(ServerRole) class SlotName(Choice): defaultValue_kindName = 'SlotName' pythonStorageType = types.StringType thingPublicCategory = None # N_('Glasnost') thingPublicName = N_('Slot Name') register(SlotName) class Source(BaseKind): defaultValue_kindName = 'Source' pythonStorageType = types.StringType thingPublicCategory = None # N_('Glasnost') def convertValueIds( self, slot, value, sourceDispatcherId, destinationDispatcherId): return value.replace(sourceDispatcherId, destinationDispatcherId) def removeValueIds(self, slot, value, rolesToKeep): if not commonTools.extractRole(value) in rolesToKeep: return None return value register(Source) class String(BaseKind): containerNames = ['Any'] defaultValue_kindName = 'String' isTranslatable = 1 class isTranslatable_kindClass(BaseKind.isTranslatable_kindClass): importExport = 'public' stateInEditMode = 'read-write' stateInViewMode = 'read-only' possibleWidgetNames = ['InputText', 'TextArea'] pythonStorageType = types.StringType class textFormat_kindClass(BaseKind.textFormat_kindClass): importExport = 'public' stateInEditMode = 'read-write' stateInViewMode = 'read-only/hidden-if-empty' class textMaxLength_kindClass(BaseKind.textMaxLength_kindClass): importExport = 'public' stateInEditMode = 'read-write' stateInViewMode = 'read-only/hidden-if-empty' thingPublicCategory = N_('Text') thingPublicName = N_('Text') class useFileStorage_kindClass(BaseKind.useFileStorage_kindClass): importExport = 'public' stateInEditMode = 'read-write' stateInViewMode = 'read-only' def checkModelValue(self, slot, value): BaseKind.checkModelValue(self, slot, value) if self.isRequired and value == '': raise faults.MissingSlotValue(slot) if self.getTextFormat(slot) == 'html': from xml.dom.minidom import parseString import xml try: value = unicode(value,'iso-8859-15') import codecs value = codecs.utf_8_encode(value)[0] parseString(value) except xml.parsers.expat.ExpatError: raise faults.BadSlotValue(slot, value) def convertValueToOtherType(self, value, otherType): if otherType is types.StringType: return value return BaseKind.convertValueToOtherType(self, value, otherType) def getCmpFunction(self): return locale.strcoll def isEmptyModelValue(self, slot, value): return not value def newJail(self, slot): return jails.String(slot) register(String) class Structure(AbstractSequence): canInsertOrDelete = 0 containerNames = ['Any'] defaultValue_kindName = 'Structure' parameters = None parameters_kind_itemKind_value_valueThingCategory = 'other' parameters_kind_itemKind_value_valueThingName = 'Parameter' parameters_kind_itemKind_valueName = 'Thing' parameters_kindName = 'Sequence' thingPublicCategory = None # N_('Data') thingPublicName = N_('Structure') def getItemKind(self, index): if self.parameters is None or index >= len(self.parameters): return None return self.parameters[index].kind def isEmptyModelValue(self, slot, value): if value is None: return 1 for i in range(len(self.parameters)): itemSlot = self.getItemSlot(slot, i) if not itemSlot.getKind().isEmptyModelValue(itemSlot, value[i]): return 0 return 1 register(Structure) class Thing(Choice): accessInCreateMode = None class accessInCreateMode_kindClass: _kindName = 'Choice' importExport = 'private' label = N_('Access in Creation Mode') labels = { '': N_('Same As Edition Mode'), 'embedded': N_('Embedded'), 'pointed': N_('Link'), } sortLabels = 0 stateInEditMode = 'hidden' stateInViewMode = 'hidden' values = [ None, 'embedded', 'pointed', ] accessInEditMode = 'embedded' class accessInEditMode_kindClass: _kindName = 'Choice' importExport = 'private' isRequired = 1 label = N_('Access in Edition Mode') labels = { 'embedded': N_('Embedded'), 'pointed': N_('Link'), } sortLabels = 0 stateInEditMode = 'hidden' stateInViewMode = 'hidden' values = [ 'embedded', 'pointed', ] accessInViewMode = 'embedded' class accessInViewMode_kindClass: _kindName = 'Choice' importExport = 'private' isRequired = 1 label = N_('Access in View Mode') labels = { 'embedded': N_('Embedded'), 'pointed': N_('Link'), } sortLabels = 0 stateInEditMode = 'hidden' stateInViewMode = 'hidden' values = [ 'embedded', 'pointed', ] containerNames = ['Any'] defaultValue_kindName = 'Thing' possibleWidgetNames = ['Thing'] pythonStorageType = types.InstanceType thingPublicCategory = None # N_('Data') thingPublicName = N_('Thing') valueThingCategory = None valueThingCategory_kind_stateInEditMode = 'hidden' valueThingCategory_kind_stateInViewMode = 'hidden' valueThingCategory_kindName = 'String' valueThingName = None valueThingName_kind_stateInEditMode = 'hidden' valueThingName_kind_stateInViewMode = 'hidden' valueThingName_kindName = 'String' values_kind_importExport = 'private' values_kind_stateInEditMode = 'hidden' values_kind_stateInViewMode = 'hidden' widgetName = 'Thing' class widgetName_kindClass(Choice.widgetName_kindClass): importExport = 'private' def checkModelValue(self, slot, value): # Pay attention: Use BaseKind instead of Choice. BaseKind.checkModelValue(self, slot, value) # TODO: check value is an instance of the appropriate class def convertValueIds(self, slot, value, sourceDispatcherId, destinationDispatcherId): if value is None: return None value.convertIds( sourceDispatcherId, destinationDispatcherId, parentSlot = slot) return value def convertValueToOtherType(self, value, otherType): if otherType is types.StringType: return value.getThingName() return BaseKind.convertValueToOtherType(self, value, otherType) def equals(self, kind): if not Choice.equals(self, kind): return 0 return self.valueThingCategory == kind.valueThingCategory \ and self.valueThingName == kind.valueThingName def executeModel(self, slot, when, command = None): value = slot.getValue() if value is None: return value.execute(when, parentSlot = slot, command = command) def exportValueToXmlRpc(self, slot, value): if value is None: return None return value.exportToXmlRpc(parentSlot = slot) def getGroupedValues(self, slot): categories = [] groupedValues = {} for thingClass in commonTools.getAllThingClasses().values(): if thingClass.thingCategory != self.valueThingCategory: continue if thingClass.thingPublicCategory is None: continue if not thingClass.thingPublicCategory in categories: categories.append(thingClass.thingPublicCategory) groupedValues[thingClass.thingPublicCategory] = [] groupedValues[thingClass.thingPublicCategory].append( thingClass.getThingName.im_func(thingClass)) return groupedValues #categories.sort(lambda x, y: locale.strcoll(_(x), _(y))) #labels = self.getLabels(slot) #for values in groupedValues.values(): # values.sort(lambda x, y: # locale.strcoll(_(labels[x]), _(labels[y]))) def getGroupLabels(self, slot): groupNames = self.getGroupedValues(slot).keys() groupLabels = {} for g in groupNames: groupLabels[_(g)] = g return groupLabels def getDefaultValue(self, slot): value = commonTools.newThing( self.valueThingCategory, self.valueThingName) return value.getDefaultValue(slot) def getLabels(self, slot): if self.labels is not None: return self.labels self.labels = {} for thingClass in commonTools.getAllThingClasses().values(): if thingClass.thingCategory != self.valueThingCategory: continue value = thingClass.getThingName.im_func(thingClass) self.labels[value] = _( thingClass.getThingPublicName.im_func(thingClass) ) return self.labels def getModelSlotByPath(self, slot, path): value = slot.getValue() if value is None: value = commonTools.newThing( self.valueThingCategory, self.valueThingName) slot = slot.detach(value) return value.getSlotByPath(path, parentSlot = slot) def getModelWidget(self, slot, forceEmbedding = 0): if forceEmbedding or self.isModelEmbedded(slot): return Choice.getModelWidget( self, slot, forceEmbedding = forceEmbedding) else: widget = commonTools.newThing('widget', 'Select') widgetOptionHeader = 'widget_' widgetOptionHeaderLen = len(widgetOptionHeader) widgetOptionNames = [ name for name in self.__dict__.keys() if name.startswith(widgetOptionHeader) \ and not name.startswith(widgetOptionHeader + 'kind')] baseClasses = self.getC3ClassLinearization() for baseClass in baseClasses: for name in baseClass.__dict__.keys(): if name.startswith(widgetOptionHeader) \ and not name.startswith(widgetOptionHeader + 'kind') \ and name not in widgetOptionNames: widgetOptionNames.append(name) widgetOptions = {} for widgetOptionName in widgetOptionNames: widgetOptions[widgetOptionName[widgetOptionHeaderLen:] ] = getattr(self, widgetOptionName) widget.buildOptions(widgetOptions) return widget def getValues(self, slot): if self.values is not None: return self.values self.values = [ thingClass.getThingName.im_func(thingClass) for thingClass in commonTools.getAllThingClasses().values() if thingClass.thingCategory == self.valueThingCategory \ and thingClass.thingPublicCategory is not None] return self.values def importValueFromXmlRpc(self, slot, importedValue): if importedValue is None: return None value = commonTools.newThing( importedValue['__thingCategory__'], importedValue['__thingName__']) slot.value = value value.importFromXmlRpc(importedValue, parentSlot = slot) del slot.value return value def includes(self, kind): if Choice.includes(self, kind): return 1 if self.getThingName() != kind.getThingName(): return 0 if self.valueThingCategory is None: return 1 if self.valueThingCategory != kind.valueThingCategory: return 0 if self.valueThingName is None: return 1 return self.valueThingName == kind.valueThingName def intersects(self, kind): if Choice.intersects(self, kind): return 1 if self.getThingName() != kind.getThingName(): return 0 if self.valueThingCategory is None or kind.valueThingCategory is None: return 1 if self.valueThingCategory != kind.valueThingCategory: return 0 if self.valueThingName is None or kind.valueThingName is None: return 1 return self.valueThingName == kind.valueThingName def isEmptyModelValue(self, slot, value): if value is None: return 1 if self.isModelEmbedded(slot): return value.isEmpty(parentSlot = slot) else: return 0 def isModelEmbedded(self, slot): layoutMode = context.getVar('layoutMode') if layoutMode == 'edit': isCreateEditMode = context.getVar('isCreateEditMode', default = 0) if isCreateEditMode: return self.accessInCreateMode == 'embedded' \ or self.accessInCreateMode is None \ and self.accessInEditMode == 'embedded' else: return self.accessInEditMode == 'embedded' elif layoutMode == 'use': return 1 else: return self.accessInViewMode == 'embedded' def newJail(self, slot): if self.valueThingCategory == 'object': return jails.Object(slot) else: return jails.Thing(slot) def removeValueIds(self, slot, value, rolesToKeep): if value is None: return None value.removeIds(rolesToKeep, parentSlot = slot) return value def repairValue(self, slot, value, toVersion): if toVersion == 4000: changed = value.repair(toVersion, parentSlot = slot) if changed: return value return None def setToDefaultValue(self, slot): if self.isModelEmbedded(slot): slot, value = self.getCreatedModelSlotAndValue(slot) if self.getDefaultValue(slot): slot.getKind().setToDefaultValue(slot) else: BaseKind.setToDefaultValue(self, slot) def upgradeModel(self, slot, model, toVersion): changed, model = BaseKind.upgradeModel(self, slot, model, toVersion) if model is not None: if model.upgrade(toVersion, parentSlot = slot): changed = 1 return changed, model register(Thing) class Union(BaseKind): containerNames = ['Any'] defaultValue_kindName = 'Union' isPractical = 0 items = None items_kind_itemKind_valueName = 'Kind' items_kind_label = N_('Items') items_kindName = 'Sequence' thingPublicCategory = None # N_('Glasnost') thingPublicName = N_('Union') def equals(self, kind): if not BaseKind.equals(self, kind): return 0 if not self.items or not kind.items: return 0 if len(self.items) != len(kind.items): return 0 for item in self.items: for kindItem in kind.items: if item.equals(kindItem): break else: return 0 return 1 def includes(self, kind): if BaseKind.includes(self, kind): return 1 if self.items is not None: for item in self.items: if item.includes(kind): return 1 return 0 def intersects(self, kind): if BaseKind.intersects(self, kind): return 1 if self.getThingName() != kind.getThingName(): if not self.items or not kind.items: return 0 for item in self.items: for kindItem in kind.items: if item.intersects(kindItem): return 1 return 0 if self.items is not None: for item in self.items: if item.intersects(kind): return 1 return 0 register(Union) class CreationTime(Time): defaultValue_kindName = 'CreationTime' importExport = 'from-server-only' isAutomaticallyModified = 1 class isRequired_kindClass(Time.isRequired_kindClass): importExport = 'private' stateInEditMode = 'hidden' stateInViewMode = 'hidden' label = N_('Creation Time') stateInEditMode = 'read-only' thingPublicName = N_('Creation Time') def accepts(self, kind): if isinstance(kind, Time): return 1 return Time.accepts(self, kind) def setAutomaticalValue(self, slot, init = 0): if init: slot.setValue(time.time()) register(CreationTime) class ModificationTime(Time): defaultValue_kindName = 'ModificationTime' importExport = 'from-server-only' isAutomaticallyModified = 1 class isRequired_kindClass(Time.isRequired_kindClass): importExport = 'private' stateInEditMode = 'hidden' stateInViewMode = 'hidden' label = N_('Modification Time') stateInEditMode = 'read-only' thingPublicName = N_('Modification Time') def setAutomaticalValue(self, slot, init = 0): slot.setValue(time.time()) register(ModificationTime) class Token(BaseKind): containerNames = ['Any', 'String'] defaultValue_kindName = 'Token' pythonStorageType = types.StringType thingPublicCategory = None # N_('Text') thingPublicName = N_('Token') def convertValueIds( self, slot, value, sourceDispatcherId, destinationDispatcherId): if value is None: return None return value.replace(sourceDispatcherId, destinationDispatcherId) def newJail(self, slot): return jails.String(slot) register(Token) class ApplicationToken(Token): containerNames = ['Any', 'String', 'Token'] defaultValue_kindName = 'ApplicationToken' thingPublicName = N_('Application Token') register(ApplicationToken) class UserToken(Token): containerNames = ['Any', 'String', 'Token'] defaultValue_kindName = 'UserToken' thingPublicName = N_('User Token') register(UserToken) class TranslationToAdd(BaseKind): defaultValue_kindName = 'TranslationToAdd' thingPublicCategory = None register(TranslationToAdd) class TranslatorsSets(BaseKind): defaultValue_kindName = 'TranslatorsSets' pythonStorageType = types.DictType thingPublicCategory = None # N_('Glasnost') def convertValueIds( self, slot, value, sourceDispatcherId, destinationDispatcherId): for translationName, translatorsSet in value.items(): if translatorsSet: for i in range(len(translatorsSet)): id = translatorsSet[i] newId = id.replace( sourceDispatcherId, destinationDispatcherId) if newId != id: translatorsSet[i] = newId return value def removeValueIds(self, slot, value, rolesToKeep): for translationName, translatorsSet in value.items(): if translatorsSet: r = range(len(translatorsSet)) r.reverse() for i in r: id = translatorsSet[i] if not commonTools.extractRole(id) in rolesToKeep: del translatorsSet[i] if not translatorsSet: del value[translationName] if not value: return None return value def repairValue(self, slot, value, toVersion): if toVersion == 4000: changed = 0 for translationName, translatorsSet in value.items(): if translatorsSet: for i in range(len(translatorsSet)): id = translatorsSet[i] newId = repairId(id) if newId: changed = 1 translatorsSet[i] = newId if changed: return value return None def upgradeModel_0001_0028(self, slot, model): """Convert user ids from "people" to "identities".""" changed = 0 model = slot.getValue() if model: changed = 1 for key in model.keys(): model[key] = [x.replace('/people', '/identities') \ for x in model[key]] return changed, model register(TranslatorsSets) class WritersSet(UsersSet): balloonHelp = N_( 'Select one or more [editors->readers-and-editors] or groups of editors '\ 'for this [object->objects] (Editors can modify or delete objects). '\ 'Click on "[Others->buttons-others]" if your choice is not proposed in the '\ 'list. Click on "Add" to add another one. '\ 'Select "None" to remove one.') containerNames = ['Any', 'Sequence', 'UsersSet'] defaultValue_kindName = 'WritersSet' label = N_('Editors') thingPublicName = N_('Editors') register(WritersSet) class XChoice(Choice): defaultValue_kindName = 'XChoice' pythonStorageType = types.StringType thingPublicCategory = None # N_('Choice') thingPublicName = N_('Extended Choice') widgetName = 'XSelect' register(XChoice) class Command(BaseKind): action = None class action_kindClass: _kindName = 'PythonIdentifier' label = N_('Action') defaultValue_kindName = 'Command' nextModeName = None class nextModeName_kindClass: _kindName = 'PythonIdentifier' label = N_('Next Mode') nextObjectId = None class nextObjectId_kindClass: _kindName = 'Id' label = N_('Next Object') possibleWidgetNames = ['PushButton'] thingPublicCategory = N_('Links') thingPublicName = N_('Push Button') widgetName = 'PushButton' def getOrderedLayoutSlotNames(self, parentSlot = None): slotNames = BaseKind.getOrderedLayoutSlotNames( self, parentSlot = parentSlot) slotNames += ['action', 'nextObjectId', 'nextModeName'] return slotNames register(Command) class Fault(Thing): defaultValue_kindName = 'Fault' thingPublicCategory = None # N_('Glasnost') thingPublicName = N_('Fault') valueThingCategory = 'other' valueThingName = 'Fault' register(Fault) ## class InputConnector(Thing): ## defaultInput_kindName = 'InputConnector' ## thingPublicCategory = None # N_('Glasnost') ## thingPublicName = N_('Input Connector') ## valueThingCategory = 'other' ## valueThingName = 'InputConnector' ## register(InputConnector) class Kind(Thing): accessInEditMode = 'pointed' accessInViewMode = 'pointed' defaultValue_kindName = 'Kind' thingPublicCategory = None # N_('Glasnost') thingPublicName = N_('Kind') valueThingCategory = 'kind' valueThingName = 'BaseKind' def convertValueFromOtherType(self, value): if type(value) is types.StringType and value: return commonTools.newThing('kind', value) return BaseKind.convertValueFromOtherType(self, value) register(Kind) class KindName(Choice): defaultValue_kindName = 'KindName' pythonStorageType = types.StringType thingPublicCategory = None # N_('Glasnost') thingPublicName = N_('Kind Name') ## def __init__(self, **attributes): ## Choice.__init__(self, **attributes) ## self.values = [ ## kindClass.getThingName.im_func(kindClass) ## for kindClass in commonTools.getAllThingClasses().values() ## if kindClass.thingCategory == 'kind'] def getGroupedValues(self, slot): categories = [] groupedValues = {} for kindClass in commonTools.getAllThingClasses().values(): if kindClass.thingCategory != 'kind': continue if kindClass.thingPublicCategory is None: continue if not kindClass.thingPublicCategory in categories: categories.append(kindClass.thingPublicCategory) groupedValues[kindClass.thingPublicCategory] = [] groupedValues[kindClass.thingPublicCategory].append( kindClass.getThingName.im_func(kindClass)) for values in groupedValues.values(): values.sort(lambda x, y: locale.strcoll(_(labels[x]), _(labels[y]))) return groupedValues def getGroupLabels(self, slot): categories = self.getGroupedValues(slot).keys() groupLabels = {} for cat in categories: groupLabels[_(cat)] = cat return categories def getValues(self, slot): return [ kindClass.getThingName.im_func(kindClass) for kindClass in commonTools.getAllThingClasses().values() if kindClass.thingCategory == 'kind' \ and kindClass.thingPublicCategory is not None] register(KindName) class Mode(Thing): accessInEditMode = 'pointed' accessInViewMode = 'pointed' defaultValue_kindName = 'Mode' isRequired = 1 # Important for submitField2. thingPublicCategory = None # N_('Glasnost') thingPublicName = N_('Mode') valueThingCategory = 'mode' valueThingName = 'ModeAbstract' def convertValueFromOtherType(self, value): if not value: return None if type(value) is types.StringType: return commonTools.newThing('mode', value) return BaseKind.convertValueFromOtherType(self, value) def convertValueToOtherType(self, value, otherType): if otherType is types.StringType and value: return value.getThingName() return BaseKind.convertValueToOtherType(self, value, otherType) def getGroupedValues(self, slot): return None register(Mode) ## class OutputConnector(Thing): ## defaultOutput_kindName = 'OutputConnector' ## thingPublicCategory = None # N_('Glasnost') ## thingPublicName = N_('Output Connector') ## valueThingCategory = 'other' ## valueThingName = 'OutputConnector' ## register(OutputConnector) class Upload(Thing): defaultValue_kindName = 'Upload' thingPublicCategory = N_('Data') thingPublicName = N_('File') valueThingCategory = 'other' valueThingName = 'Upload' widgetName = 'UploadFile' register(Upload) class ValueHolder(Thing): defaultValue_kindName = 'ValueHolder' thingPublicCategory = None # N_('Glasnost') thingPublicName = N_('Value Holder') valueThingCategory = 'other' valueThingName = 'ValueHolder' register(ValueHolder) class Widget(Thing): accessInEditMode = 'pointed' accessInViewMode = 'pointed' defaultValue_kindName = 'Widget' thingPublicCategory = None # N_('Glasnost') thingPublicName = N_('Widget') valueThingCategory = 'widget' valueThingName = 'BaseWidget' def convertValueFromOtherType(self, value): if type(value) is types.StringType and value: return commonTools.newThing('widget', value) return BaseKind.convertValueFromOtherType(self, value) register(Widget) class WidgetName(Choice): defaultValue_kindName = 'WidgetName' thingPublicCategory = None # N_('Glasnost') thingPublicName = N_('Widget Name') def getValues(self, slot): values = Choice.getValues(self, slot) if values: return values else: return ['InputText'] register(WidgetName)