# -*- coding: iso-8859-1 -*-
#-----------------------------------------------------------------------------
# Modeling Framework: an Object-Relational Bridge for python
#
# Copyright (c) 2001-2004 Sbastien Bigaret <sbigaret@users.sourceforge.net>
# All rights reserved.
#
# This file is part of the Modeling Framework.
#
# This code is distributed under a "3-clause BSD"-style license;
# see the LICENSE file for details.
#-----------------------------------------------------------------------------
"""
KeyValueCoding Mix-in class
CVS information
$Id: KeyValueCoding.py 932 2004-07-20 06:21:57Z sbigaret $
"""
__version__='$Revision: 932 $'[11:-2]
from interfaces.KeyValueCoding import KeyValueCodingInterface
from Modeling.utils import capitalizeFirstLetter,isListOrTuple
try:
from Interface import verify_class_implementation
except: pass
from utils import deprecated
import string
def valueForKeyPath(object, keypath):
"See interfaces.KeyValueCoding for details"
keys=string.split(keypath, '.')
key=keys[0]
keys=keys[1:]
if not keys:
if isListOrTuple(object):
objects=map(lambda o, key=key: o.valueForKey(key), object)
return objects
else:
return object.valueForKey(key)
else:
if isListOrTuple(object):
objects=map(lambda o, key=key: o.valueForKey(key), object)
return map(lambda o,keys=keys: valueForKeyPath(o,string.join(keys, '.')),
objects) # TBD: unittests
else:
object=object.valueForKey(key)
return valueForKeyPath(object, string.join(keys, '.'))
def takeValueForKeyPath(object, value, keypath):
"See interfaces.KeyValueCoding for details"
keys=string.split(keypath, '.')
key=keys[0]
keys=keys[1:]
if isListOrTuple(object):
raise ValueError, 'invalid keypath: got a sequence during traversal'
if not keys:
return object.takeValueForKey(value, key)
else:
object=object.valueForKey(key)
return takeValueForKeyPath(object, value, string.join(keys, '.'))
class KeyValueCoding:
"See interfaces.KeyValueCoding for details"
__implements__=(KeyValueCodingInterface, )
## 1. So-called 'public' access methods
def valueForKey(self, key):
"See interfaces.KeyValueCoding for details"
Key=capitalizeFirstLetter(key)
getter=getattr(self, 'get'+Key, None) # getKey()
if callable(getter): return getter()
getter=getattr(self, key, None) # key()
if callable(getter): return getter()
getter=getattr(self, '_get'+Key, None) # _getKey()
if callable(getter): return getter()
getter=getattr(self, '_'+key, None) # _key()
if callable(getter): return getter()
try: return getattr(self, key) # key property
except AttributeError: pass
try: return getattr(self, '_'+key) # _key property
except AttributeError: pass
self.handleQueryWithUnboundKey(key)
def valueForKeyPath(self, keypath):
"See interfaces.KeyValueCoding for details"
return valueForKeyPath(self, keypath)
def takeValueForKey(self, value, key):
"See interfaces.KeyValueCoding for details"
Key=capitalizeFirstLetter(key)
setter=getattr(self, 'set'+Key, None) # setKey()
if callable(setter): return apply(setter, (value,))
setter=getattr(self, '_set'+Key, None) # _setKey()
if callable(setter): return apply(setter, (value,))
try:
if key in self.__dict__.keys():
setattr(self, key, value) # key attribute
return
except AttributeError: pass
try:
if ('_'+key) in self.__dict__.keys():
setattr(self, '_'+key, value) # _key attribute
return
except AttributeError: pass
self.handleAssignementForUnboundKey(value, key)
def takeValueForKeyPath(self, value, key):
"See interfaces.KeyValueCoding for details"
return takeValueForKeyPath(self, value, key)
## 2. So-called 'private' access methods
def storedValueForKey(self, key):
"See interfaces.KeyValueCoding for details"
Key=capitalizeFirstLetter(key)
getter=getattr(self, '_get'+Key, None) # _getKey()
if callable(getter): return getter()
getter=getattr(self, '_'+key, None) # _key()
if callable(getter): return getter()
self_attributes=self.__dict__.keys()
if '_'+key in self_attributes: # _key property
return getattr(self, '_'+key)
if key in self_attributes: # key property
return getattr(self, key)
getter=getattr(self, 'get'+Key, None) # getKey()
if callable(getter): return getter()
getter=getattr(self, key, None) # key()
if callable(getter): return getter()
self.handleQueryWithUnboundKey(key)
def takeStoredValueForKey(self, value, key):
"See interfaces.KeyValueCoding for details"
Key=capitalizeFirstLetter(key)
setter=getattr(self, '_set'+Key, None) # _setKey()
if callable(setter): return apply(setter, (value,))
try:
if ('_'+key) in self.__dict__.keys():
setattr(self, '_'+key, value) # _key attribute
return
except AttributeError: pass
try:
if key in self.__dict__.keys():
setattr(self, key, value) # key attribute
return
except AttributeError: pass
setter=getattr(self, 'set'+Key, None) # setKey()
if callable(setter): return apply(setter, (value,))
self.handleTakeStoredValueForUnboundKey(value, key)
## 3. Error handling
def handleQueryWithUnboundKey(self, key):
"See interfaces.KeyValueCoding for details"
raise AttributeError, key
def handleAssignementForUnboundKey(self, value, key):
"See interfaces.KeyValueCoding for details"
raise AttributeError, key
#def handleTakeValueForUnboundKey(self, value, key):
# "See interfaces.KeyValueCoding for details"
# raise AttributeError, key
#
#def handleTakeStoredValueForUnboundKey(self, value, key):
# "See interfaces.KeyValueCoding for details"
# raise AttributeError, key
#def unableToSetNullForKey(self, key):
# "Raises ValueError"
# raise ValueError
# Extensions
def takeStoredValuesFromDictionary(self, dictionary):
"See interfaces.KeyValueCoding for details"
for key in dictionary.keys():
self.takeStoredValueForKey(dictionary[key], key)
def takeValuesFromDictionary(self, dictionary):
"See interfaces.KeyValueCoding for details"
for key in dictionary.keys():
self.takeValueForKey(dictionary[key], key)
def valuesForKeys(self, keys):
"See interfaces.KeyValueCoding for details"
res=[]
for key in keys:
res.append(self.valueForKey(key))
return res
# DEPRECATED aliases
def setValueForKey(self, value, key):
"DEPRECATED -- alias for takeValueForKey()"
deprecated('setValueForKey', 'takeValueForKey', '0.9.1')
self.takeValueForKey(value, key)
def setValueForKeyPath(self, value, keypath):
"DEPRECATED -- alias for takeValueForKeyPath()"
deprecated('setValueForKeyPath', 'takeValueForKeyPath', '0.9.1')
self.takeValueForKeyPath(value, keypath)
def setStoredValueForKey(self, value, key):
"DEPRECATED -- alias for 'takeStoredValueForKey()'"
deprecated('setStoredValueForKey', 'takeStoredValueForKey', '0.9.1')
self.takeStoredValueForKey(self, value, key)
try:
verify_class_implementation(KeyValueCodingInterface, KeyValueCoding)
except:
pass
|