Package pyamf :: Package adapters :: Module _sqlalchemy_orm
[hide private]
[frames] | no frames]

Source Code for Module pyamf.adapters._sqlalchemy_orm

  1  # Copyright (c) 2007-2009 The PyAMF Project. 
  2  # See LICENSE for details. 
  3   
  4  """ 
  5  SQLAlchemy adapter module. 
  6   
  7  @see: U{SQLAlchemy homepage (external)<http://www.sqlalchemy.org>} 
  8   
  9  @since: 0.4 
 10  """ 
 11   
 12  from sqlalchemy import orm, __version__ 
 13   
 14  try: 
 15      from sqlalchemy.orm import class_mapper 
 16  except ImportError: 
 17      from sqlalchemy.orm.util import class_mapper 
 18   
 19  import pyamf 
 20   
 21  UnmappedInstanceError = None 
 22   
 23  try: 
 24      class_mapper(dict) 
 25  except Exception, e: 
 26      UnmappedInstanceError = e.__class__ 
 27   
 28   
29 -class SaMappedClassAlias(pyamf.ClassAlias):
30 KEY_ATTR = 'sa_key' 31 LAZY_ATTR = 'sa_lazy' 32 EXCLUDED_ATTRS = [ 33 '_entity_name', '_instance_key', '_sa_adapter', '_sa_appender', 34 '_sa_class_manager', '_sa_initiator', '_sa_instance_state', 35 '_sa_instrumented', '_sa_iterator', '_sa_remover', '_sa_session_id', 36 '_state' 37 ] 38 39 STATE_ATTR = '_sa_instance_state' 40 41 if __version__.startswith('0.4'): 42 STATE_ATTR = '_state' 43
44 - def getCustomProperties(self):
45 self.mapper = class_mapper(self.klass) 46 self.exclude_attrs.update(self.EXCLUDED_ATTRS) 47 48 self.properties = [] 49 50 for prop in self.mapper.iterate_properties: 51 self.properties.append(prop.key) 52 53 self.encodable_properties.update(self.properties) 54 self.decodable_properties.update(self.properties) 55 self.static_attrs.update(self.properties)
56
57 - def getEncodableAttributes(self, obj, **kwargs):
58 """ 59 Returns a C{tuple} containing a dict of static and dynamic attributes 60 for C{obj}. 61 """ 62 sa, da = pyamf.ClassAlias.getEncodableAttributes(self, obj, **kwargs) 63 64 if not da: 65 da = {} 66 67 lazy_attrs = [] 68 69 # primary_key_from_instance actually changes obj.__dict__ if 70 # primary key properties do not already exist in obj.__dict__ 71 da[self.KEY_ATTR] = self.mapper.primary_key_from_instance(obj) 72 73 for attr in self.properties: 74 if attr not in obj.__dict__: 75 lazy_attrs.append(attr) 76 77 da[self.LAZY_ATTR] = lazy_attrs 78 79 return sa, da
80
81 - def getDecodableAttributes(self, obj, attrs, **kwargs):
82 """ 83 """ 84 attrs = pyamf.ClassAlias.getDecodableAttributes(self, obj, attrs, **kwargs) 85 86 # Delete lazy-loaded attrs. 87 # 88 # Doing it this way ensures that lazy-loaded attributes are not 89 # attached to the object, even if there is a default value specified 90 # in the __init__ method. 91 # 92 # This is the correct behavior, because SQLAlchemy ignores __init__. 93 # So, an object retreived from a DB with SQLAlchemy will not have a 94 # lazy-loaded value, even if __init__ specifies a default value. 95 if self.LAZY_ATTR in attrs: 96 obj_state = None 97 98 if hasattr(orm.attributes, 'instance_state'): 99 obj_state = orm.attributes.instance_state(obj) 100 101 for lazy_attr in attrs[self.LAZY_ATTR]: 102 if lazy_attr in obj.__dict__: 103 # Delete directly from the dict, so 104 # SA callbacks are not triggered. 105 del obj.__dict__[lazy_attr] 106 107 # Delete from committed_state so SA thinks this attribute was 108 # never modified. 109 # 110 # If the attribute was set in the __init__ method, 111 # SA will think it is modified and will try to update 112 # it in the database. 113 if obj_state is not None: 114 if lazy_attr in obj_state.committed_state: 115 del obj_state.committed_state[lazy_attr] 116 if lazy_attr in obj_state.dict: 117 del obj_state.dict[lazy_attr] 118 119 if lazy_attr in attrs: 120 del attrs[lazy_attr] 121 122 del attrs[self.LAZY_ATTR] 123 124 if self.KEY_ATTR in attrs: 125 del attrs[self.KEY_ATTR] 126 127 return attrs
128 129
130 -def is_class_sa_mapped(klass):
131 """ 132 @rtype: C{bool} 133 """ 134 if not isinstance(klass, type): 135 klass = type(klass) 136 137 try: 138 class_mapper(klass) 139 except UnmappedInstanceError: 140 return False 141 142 return True
143 144 pyamf.register_alias_type(SaMappedClassAlias, is_class_sa_mapped) 145