This repository has been archived on 2023-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
glasnost/shared/common/slots.py

827 lines
24 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.
__doc__ = """Glasnost Common Slots"""
__version__ = '$Revision$'[11:-2]
import copy
import types
import faults
import tools_new as commonTools
class BaseSlot:
"""Slot superclass.
This class must be specialized in order to produce a specific slot
(Attribute, Property...).
Attributes:
===========
*container*:
The object class instance containing the slot.
*parent*:
This is the slot where the object is (if applicable). Default = None.
*value*:
The slot value.
Constructor:
============
Keyword arguments:
------------------
*container*:
The object class instance containing the slot.
*parent*:
This is the slot where the object is (if applicable). Default =
None.
Exception:
----------
*AssertionError*:
The container is None, and the parent too. That's meaning that the
slot is neither in a class, neither in another slot, so nowhere.
"""
container = None
parent = None
value = None
def __init__(self, container = None, parent = None):
if parent is None:
assert container is not None
self.container = container
else:
if container is not None:
self.container = container
self.parent = parent
def __str__(self):
return self.getPath()
def delField(self, fields):
fieldName = self.getFieldName()
del fields[fieldName]
def delFieldOption(self, fields, optionName):
fieldOptionName = self.getFieldOptionName(optionName)
del fields[fieldOptionName]
def delValue(self):
if self.__dict__.has_key('value'):
del self.value
raise NotImplementedError
def detach(self, value):
return Detached(self, value)
def getContainer(self, setIfNone = 0):
if self.container is not None:
return self.container
else:
return self.parent.getValue(setIfNone = setIfNone)
def getContainerFieldName(self):
if self.parent is None:
return ''
else:
return self.parent.getFieldName()
def getContainerFilePathSplitted(self):
if self.container is not None:
return []
else:
return self.parent.getFilePathSplitted()
def getContainerPath(self):
if self.parent is None:
return 'self'
else:
return self.parent.getPath()
def getField(self, fields, default = None):
fieldName = self.getFieldName()
if not fields.has_key(fieldName):
return default
return fields[fieldName]
def getFieldName(self):
raise NotImplementedError
def getFieldOption(self, fields, optionName, default = None):
fieldOptionName = self.getFieldOptionName(optionName)
if not fields.has_key(fieldOptionName):
return default
return fields[fieldOptionName]
def getFieldOptionName(self, optionName):
return '_'.join([self.getFieldName(), optionName])
def getFilePathSplitted(self):
raise NotImplementedError
def getKind(self):
raise NotImplementedError
def getLabel(self):
raise NotImplementedError
def getLocalValue(self, setIfNone = 0):
raise NotImplementedError
def getObject(self):
if self.container is not None \
and self.container.thingCategory == 'object':
return self.container
elif self.parent is not None:
return self.parent.getObject()
else:
return None
def getObjectSlot(self):
if self.container is not None \
and self.container.thingCategory == 'object':
return self.parent
elif self.parent is not None:
return self.parent.getObjectSlot()
else:
return None
def getPath(self):
raise NotImplementedError
def getRootContainer(self):
if self.parent is None:
return self.container
else:
return self.parent.getRootContainer()
def getValue(self, setIfNone = 0):
if self.value is not None:
return self.value
return self.getLocalValue(setIfNone = setIfNone)
def getWidget(self):
return self.getKind().getModelWidget(self)
def hasField(self, fields):
return fields.has_key(self.getFieldName())
def hasFieldOption(self, fields, optionName):
return fields.has_key(self.getFieldOptionName(optionName))
def hasLocalValue(self):
raise NotImplementedError
def hasValue(self):
if self.value is not None:
return 1
return self.hasLocalValue()
def isDefaultValue(self, value):
return 0
def setField(self, fields, value):
fieldName = self.getFieldName()
fields[fieldName] = value
def setFieldOption(self, fields, optionName, value):
fieldOptionName = self.getFieldOptionName(optionName)
fields[fieldOptionName] = value
def setValue(self, value):
if self.__dict__.has_key('value'):
del self.value
raise NotImplementedError
class Attribute(BaseSlot): # Instance Attribute.
"""Define a attribute slot.
Attribute:
==========
*name*:
The attribute slot name.
Constructor:
============
Keyword arguments:
------------------
*name*:
The attribute slot name.
*container*:
The object class instance containing the slot.
*parent*:
This is the slot where the object is (if applicable). Default =
None.
Exception:
----------
*AssertionError*:
The container is None, and the parent too. That's meaning that the
slot is neither in a class, neither in another slot, so nowhere.
"""
name = None
def __init__(self, name, container = None, parent = None):
BaseSlot.__init__(self, container = container, parent = parent)
self.name = name
def delValue(self):
container = self.getContainer()
if container.__dict__.has_key(self.name):
del container.__dict__[self.name]
if self.__dict__.has_key('value'):
del self.value
def getFieldName(self):
return '_'.join(filter(None, [
self.getContainerFieldName(),
self.name]))
def getFilePathSplitted(self):
return self.getContainerFilePathSplitted() + [self.name]
def getKind(self):
# To simplify when converting to Python 2.2 new-style objects.
container = self.getContainer()
if hasattr(container, self.name + '_kindGetter'):
return getattr(container, self.name + '_kindGetter')()
return getattr(container, self.name + '_kind')
def getLabel(self):
return self.name
def getLocalValue(self, setIfNone = 0):
container = self.getContainer(setIfNone = setIfNone)
# FIXME: Shall we uncomment the next lines?
## if hasattr(container, self.name + 'Getter'):
## return getattr(container, self.name + 'Getter')()
return container.__dict__[self.name]
def getPath(self):
return self.getContainerPath() + '.' + self.name
def getValue(self, setIfNone = 0):
# To simplify when converting to Python 2.2 new-style objects.
if self.value is not None:
return self.value
container = self.getContainer(setIfNone = setIfNone)
if hasattr(container, self.name + 'Getter'):
return getattr(container, self.name + 'Getter')()
return getattr(container, self.name)
def hasLocalValue(self):
container = self.getContainer()
return container.__dict__.has_key(self.name)
def hasValue(self):
if self.value is not None:
return 1
return hasattr(self.getContainer(), self.name)
def isDefaultValue(self, value):
containerClass = self.getContainer().__class__
return hasattr(containerClass, self.name) \
and getattr(containerClass, self.name) == value
def setValue(self, value):
container = self.getContainer(setIfNone = 1)
if hasattr(container.__class__, self.name) \
and getattr(container.__class__, self.name) == value:
if container.__dict__.has_key(self.name):
del container.__dict__[self.name]
else:
setattr(container, self.name, value)
if self.__dict__.has_key('value'):
del self.value
class Detached(BaseSlot): # Detached Value.
fieldName = None
filePathSplitted = None
kind = None
label = None
path = None
value = None
def __init__(self, slot, value):
container = slot.getRootContainer()
BaseSlot.__init__(self, container = container)
self.fieldName = slot.getFieldName()
# Do not fail when the slot to detach does not exist.
try:
self.filePathSplitted = slot.getFilePathSplitted()
except:
pass
self.kind = slot.getKind()
try:
self.label = slot.getLabel()
except:
pass
try:
self.path = slot.getPath()
except:
pass
self.value = value
def delValue(self):
if self.__dict__.has_key('value'):
del self.value
def getFieldName(self):
return self.fieldName
def getFilePathSplitted(self):
return self.filePathSplitted
def getKind(self):
return self.kind
def getLabel(self):
return self.label
def getLocalValue(self, setIfNone = 0):
return self.value
def getPath(self):
return self.path
def hasLocalValue(self):
return 1
def setValue(self, value):
self.value = value
class Dummy(BaseSlot): # To use for None slots.
kind = None
def __init__(self, kind, container = None):
self.kind = kind
if container is not None:
self.container = container
def delValue(self):
del self.container
if self.__dict__.has_key('value'):
del self.value
def getFieldName(self):
return ''
def getFilePathSplitted(self):
return []
def getKind(self):
return self.kind
def getLabel(self):
return 'Dummy'
def getLocalValue(self, setIfNone = 0):
return self.container
def getPath(self):
return 'self'
def hasLocalValue(self):
return self.container is not None
def isDefaultValue(self, value):
return value != None
def setValue(self, value):
self.container = value
if self.__dict__.has_key('value'):
del self.value
class Item(BaseSlot): # Sequence Item.
index = None
def __init__(self, index, container = None, parent = None):
BaseSlot.__init__(self, container = container, parent = parent)
self.index = index
def delValue(self):
self.getContainer()[self.index] = None
if self.__dict__.has_key('value'):
del self.value
def getFieldName(self):
return '_'.join(filter(None, [
self.getContainerFieldName(),
str(self.index)]))
def getFilePathSplitted(self):
return self.getContainerFilePathSplitted() + [str(self.index)]
def getKind(self):
return self.parent.getKind().getItemKind(self.index)
def getLabel(self):
return str(self.index)
def getLocalValue(self, setIfNone = 0):
return self.getContainer(setIfNone = setIfNone)[self.index]
def getPath(self):
return self.getContainerPath() + '[%s]' % self.index
def hasLocalValue(self):
container = self.getContainer()
return container is not None and 0 <= self.index < len(container)
def setValue(self, value):
self.getContainer(setIfNone = 1)[self.index] = value
if self.__dict__.has_key('value'):
del self.value
class ItemKey(BaseSlot): # Mapping Item Key.
index = None
def __init__(self, index, container = None, parent = None):
BaseSlot.__init__(self, container = container, parent = parent)
self.index = index
def getFieldName(self):
return '_'.join(filter(None, [
self.getContainerFieldName(),
'keys',
str(self.index)]))
def getKind(self):
return self.parent.getKind().getItemKeyKind(self.index)
def getLabel(self):
return str(self.index)
def getLocalValue(self, setIfNone = 0):
return self.getContainer(setIfNone = setIfNone).keys()[self.index]
def getPath(self):
return self.getContainerPath() + '.keys()[%s]' % self.index
def getValue(self, setIfNone = 0):
if self.value is not None:
return self.value
if self.hasLocalValue():
return self.getLocalValue(setIfNone = setIfNone)
def hasLocalValue(self):
container = self.getContainer()
return container is not None \
and 0 <= self.index < len(container.keys())
class ItemKeyValue(BaseSlot):
# Mapping Item Value accessed vith ItemKey slot as parent.
def delValue(self):
key = self.parent.getValue()
del self.getContainer()[key]
if self.__dict__.has_key('value'):
del self.value
def getContainer(self, setIfNone = 0):
return self.parent.getContainer(setIfNone = setIfNone)
def getContainerFilePathSplitted(self):
return self.parent.getContainerFilePathSplitted()
def getContainerPath(self):
return self.parent.getContainerPath()
def getFieldName(self):
return '_'.join(filter(None, [
self.getContainerFieldName(),
'value']))
def getFilePathSplitted(self):
key = self.parent.getValue()
return self.getContainerFilePathSplitted() + [str(key)]
def getKind(self):
key = self.parent.getValue()
return self.parent.parent.getKind().getItemValueKind(key)
def getLabel(self):
return 'value'
def getLocalValue(self, setIfNone = 0):
key = self.parent.getValue()
return self.getContainer(setIfNone = setIfNone)[key]
def getPath(self):
key = self.parent.getValue()
if type(key) == types.StringType:
key = '\'%s\'' % key
elif type(key) == types.UnicodeType:
key = 'u\'%s\'' % key
else:
key = str(key)
return self.getContainerPath() + '[%s]' % key
def hasLocalValue(self):
key = self.parent.getValue()
container = self.getContainer()
return container is not None and container.has_key(key)
def setValue(self, value):
key = self.parent.getValue()
self.getContainer(setIfNone = 1)[key] = value
if self.__dict__.has_key('value'):
del self.value
class ItemValue(BaseSlot): # Mapping Item Value.
key = None
def __init__(self, key, container = None, parent = None):
BaseSlot.__init__(self, container = container, parent = parent)
self.key = key
def delValue(self):
del self.getContainer()[self.key]
if self.__dict__.has_key('value'):
del self.value
def getFieldName(self):
return '_'.join(filter(None, [
self.getContainerFieldName(),
'values',
str(self.key)]))
def getFilePathSplitted(self):
return self.getContainerFilePathSplitted() + [str(self.key)]
def getKind(self):
return self.parent.getKind().getItemValueKind(self.key)
def getLabel(self):
return str(self.key)
def getLocalValue(self, setIfNone = 0):
return self.getContainer(setIfNone = setIfNone)[self.key]
def getPath(self):
if type(self.key) == types.StringType:
key = '\'%s\'' % self.key
elif type(self.key) == types.UnicodeType:
key = 'u\'%s\'' % self.key
else:
key = str(self.key)
return self.getContainerPath() + '[%s]' % key
def hasLocalValue(self):
container = self.getContainer()
return container is not None and container.has_key(self.key)
def setValue(self, value):
self.getContainer(setIfNone = 1)[self.key] = value
if self.__dict__.has_key('value'):
del self.value
class PropertiesItem(Item): # Item of Properties.
def getFilePathSplitted(self):
properties = self.getContainer()
propertyName = properties[self.index].name
return self.getContainerFilePathSplitted() + [propertyName]
def getLabel(self):
properties = self.getContainer()
propertyName = properties[self.index].name
return propertyName
def getPath(self):
properties = self.getContainer()
propertyName = properties[self.index].name
return self.getContainerPath() + '[\'%s\']' % propertyName
class Property(Attribute): # Card Property.
def delValue(self):
self.setValue(None)
def getKind(self):
# This doesn't work, because the kind would always be a commom kind.
# import properties
# return properties.Property().newKind()
property = commonTools.newThing('other', 'Property')
return property.newKind()
def getLocalValue(self, setIfNone = 0):
card = self.parent.getContainer(setIfNone = setIfNone)
kind = card.getDirectPropertyValueKind(self.name)
if kind is None:
raise faults.MissingItem(self.name)
property = commonTools.newThing('other', 'Property')
property.kind = kind
property.kindName = kind.getThingName()
property.name = self.name
if setIfNone:
self.setValue(property)
return property
def getPath(self):
if type(self.name) == types.StringType:
name = '\'%s\'' % self.name
elif type(self.name) == types.UnicodeType:
name = 'u\'%s\'' % self.name
else:
name = str(self.name)
return self.getContainerPath() + '[%s]' % name
def getValue(self, setIfNone = 0):
if self.value is not None:
if setIfNone:
value = self.value
self.setValue(self.value) # It erases self.value!
self.value = value
return self.value
card = self.parent.getContainer(setIfNone = setIfNone)
kind = card.getDirectPropertyValueKind(self.name)
if kind is None:
kind = card.getPropertyValueKind(self.name)
kind = copy.deepcopy(kind)
property = commonTools.newThing('other', 'Property')
property.kind = kind
property.kindName = kind.getThingName()
property.name = self.name
if setIfNone:
self.setValue(property)
self.value = property
return property
def hasLocalValue(self):
card = self.parent.getContainer()
kind = card.getDirectPropertyValueKind(self.name)
return kind is not None
def hasValue(self):
raise Exception('FIXME: To do')
def isDefaultValue(self, value):
raise Exception('FIXME: To do')
def setValue(self, value):
card = self.parent.getContainer(setIfNone = 1)
if value is None:
kind = None
else:
kind = value.kind
card.setDirectPropertyValueKind(self.name, kind)
if self.__dict__.has_key('value'):
del self.value
class PropertyValue(Attribute): # Card Property Value.
def delValue(self):
values = self.getContainer().values
if values and values.has_key(self.name):
del values[self.name]
if self.__dict__.has_key('value'):
del self.value
def getKind(self):
return self.getContainer().getPropertyValueKind(self.name)
def getLocalValue(self, setIfNone = 0):
card = self.getContainer(setIfNone = setIfNone)
return card.values[self.name]
def getValue(self, setIfNone = 0):
if self.value is not None:
return self.value
return self.getContainer(setIfNone = setIfNone).getPropertyValue(
self.name, self.getKind())
def hasLocalValue(self):
card = self.getContainer()
return card.values is not None and card.values.has_key(self.name)
def hasValue(self):
return 1
def isDefaultValue(self, value):
return self.getContainer().getDefaultPropertyValue(
self.name, self.getKind()) == value
def setValue(self, value):
self.getContainer(setIfNone = 1).setDirectPropertyValue(
self.name, value)
if self.__dict__.has_key('value'):
del self.value
class Root(BaseSlot): # First Instance (rarely needed).
name = ''
def __init__(self, container, name = None):
BaseSlot.__init__(self, container = container, parent = None)
if name is not None:
self.name = name
def delValue(self):
del self.container
if self.__dict__.has_key('value'):
del self.value
def getFieldName(self):
return self.name
def getFilePathSplitted(self):
return []
def getKind(self):
return self.container.newKind()
def getLabel(self):
if self.name:
return self.name
else:
return 'Root'
def getLocalValue(self, setIfNone = 0):
return self.container
def getPath(self):
return 'self'
def getWidget(self):
return self.container.newWidget()
def hasLocalValue(self):
return self.container is not None
def isDefaultValue(self, value):
return value != None
def setValue(self, value):
self.container = value
if self.__dict__.has_key('value'):
del self.value