3889 lines
126 KiB
Python
3889 lines
126 KiB
Python
# -*- coding: iso-8859-15 -*-
|
|
|
|
|
|
# Glasnost
|
|
# By: Odile Bénassy <obenassy@entrouvert.com>
|
|
# Romain Chantereau <rchantereau@entrouvert.com>
|
|
# Nicolas Clapiès <nclapies@easter-eggs.org>
|
|
# Pierre-Antoine Dejace <padejace@entrouvert.be>
|
|
# Thierry Dulieu <tdulieu@easter-eggs.com>
|
|
# Florent Monnier <monnier@codelutin.com>
|
|
# Cédric Musso <cmusso@easter-eggs.org>
|
|
# Frédéric Péters <fpeters@entrouvert.be>
|
|
# Benjamin Poussin <poussin@codelutin.com>
|
|
# Emmanuel Raviart <eraviart@entrouvert.com>
|
|
# Sébastien Régnier <regnier@codelutin.com>
|
|
# Emmanuel Saracco <esaracco@easter-eggs.com>
|
|
#
|
|
# 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])
|
|
value = time.mktime(t)
|
|
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:
|
|
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)
|
|
|