PageRenderTime 44ms CodeModel.GetById 9ms RepoModel.GetById 1ms app.codeStats 0ms

/python/lib/PyAMF-0.6.1/pyamf/tests/adapters/test_sqlalchemy.py

https://gitlab.com/gregtyka/frankenserver
Python | 415 lines | 282 code | 107 blank | 26 comment | 16 complexity | a72d1ca1f7284205720951e9685a9c11 MD5 | raw file
  1. # Copyright (c) The PyAMF Project.
  2. # See LICENSE.txt for details.
  3. """
  4. PyAMF SQLAlchemy adapter tests.
  5. @since 0.4
  6. """
  7. import unittest
  8. try:
  9. import sqlalchemy
  10. from sqlalchemy import MetaData, Table, Column, Integer, String, ForeignKey, \
  11. create_engine
  12. from sqlalchemy.orm import mapper, relation, sessionmaker, clear_mappers
  13. from pyamf.adapters import _sqlalchemy_orm as adapter
  14. except ImportError:
  15. sqlalchemy = None
  16. import pyamf.flex
  17. from pyamf.tests.util import Spam
  18. class BaseObject(object):
  19. def __init__(self, **kwargs):
  20. self.__dict__.update(kwargs)
  21. class User(BaseObject):
  22. def __init__(self, **kwargs):
  23. BaseObject.__init__(self, **kwargs)
  24. self.lazy_loaded = [LazyLoaded()]
  25. class Address(BaseObject):
  26. pass
  27. class LazyLoaded(BaseObject):
  28. pass
  29. class AnotherLazyLoaded(BaseObject):
  30. pass
  31. class BaseTestCase(unittest.TestCase):
  32. """
  33. Initialise up all table/mappers.
  34. """
  35. def setUp(self):
  36. if not sqlalchemy:
  37. self.skipTest("'sqlalchemy' is not available")
  38. # Create DB and map objects
  39. self.metadata = MetaData()
  40. self.engine = create_engine('sqlite:///:memory:', echo=False)
  41. Session = sessionmaker(bind=self.engine)
  42. self.session = Session()
  43. self.tables = {}
  44. self.tables['users'] = Table('users', self.metadata,
  45. Column('id', Integer, primary_key=True),
  46. Column('name', String(64)))
  47. self.tables['addresses'] = Table('addresses', self.metadata,
  48. Column('id', Integer, primary_key=True),
  49. Column('user_id', Integer, ForeignKey('users.id')),
  50. Column('email_address', String(128)))
  51. self.tables['lazy_loaded'] = Table('lazy_loaded', self.metadata,
  52. Column('id', Integer, primary_key=True),
  53. Column('user_id', Integer, ForeignKey('users.id')))
  54. self.tables['another_lazy_loaded'] = Table('another_lazy_loaded', self.metadata,
  55. Column('id', Integer, primary_key=True),
  56. Column('user_id', Integer, ForeignKey('users.id')))
  57. self.mappers = {}
  58. self.mappers['user'] = mapper(User, self.tables['users'], properties={
  59. 'addresses': relation(Address, backref='user', lazy=False),
  60. 'lazy_loaded': relation(LazyLoaded, lazy=True),
  61. 'another_lazy_loaded': relation(AnotherLazyLoaded, lazy=True)
  62. })
  63. self.mappers['addresses'] = mapper(Address, self.tables['addresses'])
  64. self.mappers['lazy_loaded'] = mapper(LazyLoaded,
  65. self.tables['lazy_loaded'])
  66. self.mappers['another_lazy_loaded'] = mapper(AnotherLazyLoaded,
  67. self.tables['another_lazy_loaded'])
  68. self.metadata.create_all(self.engine)
  69. pyamf.register_class(User, 'server.User')
  70. pyamf.register_class(Address, 'server.Address')
  71. pyamf.register_class(LazyLoaded, 'server.LazyLoaded')
  72. def tearDown(self):
  73. clear_mappers()
  74. pyamf.unregister_class(User)
  75. pyamf.unregister_class(Address)
  76. pyamf.unregister_class(LazyLoaded)
  77. def _build_obj(self):
  78. user = User()
  79. user.name = "test_user"
  80. user.addresses.append(Address(email_address="test@example.org"))
  81. return user
  82. def _save(self, obj):
  83. # this covers deprecation warnings etc.
  84. if hasattr(self.session, 'add'):
  85. self.session.add(obj)
  86. elif hasattr(self.session, 'save'):
  87. self.session.save(obj)
  88. else:
  89. raise AttributeError('Don\'t know how to save an object')
  90. def _clear(self):
  91. # this covers deprecation warnings etc.
  92. if hasattr(self.session, 'expunge_all'):
  93. self.session.expunge_all()
  94. elif hasattr(self.session, 'clear'):
  95. self.session.clear()
  96. else:
  97. raise AttributeError('Don\'t know how to clear session')
  98. class SATestCase(BaseTestCase):
  99. def _test_obj(self, encoded, decoded):
  100. self.assertEqual(User, decoded.__class__)
  101. self.assertEqual(encoded.name, decoded.name)
  102. self.assertEqual(encoded.addresses[0].email_address, decoded.addresses[0].email_address)
  103. def test_encode_decode_transient(self):
  104. user = self._build_obj()
  105. encoder = pyamf.get_encoder(pyamf.AMF3)
  106. encoder.writeElement(user)
  107. encoded = encoder.stream.getvalue()
  108. decoded = pyamf.get_decoder(pyamf.AMF3, encoded).readElement()
  109. self._test_obj(user, decoded)
  110. def test_encode_decode_persistent(self):
  111. user = self._build_obj()
  112. self._save(user)
  113. self.session.commit()
  114. self.session.refresh(user)
  115. encoder = pyamf.get_encoder(pyamf.AMF3)
  116. encoder.writeElement(user)
  117. encoded = encoder.stream.getvalue()
  118. decoded = pyamf.get_decoder(pyamf.AMF3, encoded).readElement()
  119. self._test_obj(user, decoded)
  120. def test_encode_decode_list(self):
  121. max = 5
  122. for i in range(0, max):
  123. user = self._build_obj()
  124. user.name = "%s" % i
  125. self._save(user)
  126. self.session.commit()
  127. users = self.session.query(User).all()
  128. encoder = pyamf.get_encoder(pyamf.AMF3)
  129. encoder.writeElement(users)
  130. encoded = encoder.stream.getvalue()
  131. decoded = pyamf.get_decoder(pyamf.AMF3, encoded).readElement()
  132. self.assertEqual([].__class__, decoded.__class__)
  133. for i in range(0, max):
  134. self._test_obj(users[i], decoded[i])
  135. def test_sa_merge(self):
  136. user = self._build_obj()
  137. for i, string in enumerate(['one', 'two', 'three']):
  138. addr = Address(email_address="%s@example.org" % string)
  139. user.addresses.append(addr)
  140. self._save(user)
  141. self.session.commit()
  142. self.session.refresh(user)
  143. encoder = pyamf.get_encoder(pyamf.AMF3)
  144. encoder.writeElement(user)
  145. encoded = encoder.stream.getvalue()
  146. decoded = pyamf.get_decoder(pyamf.AMF3, encoded).readElement()
  147. del decoded.addresses[0]
  148. del decoded.addresses[1]
  149. merged_user = self.session.merge(decoded)
  150. self.assertEqual(len(merged_user.addresses), 2)
  151. def test_encode_decode_with_references(self):
  152. user = self._build_obj()
  153. self._save(user)
  154. self.session.commit()
  155. self.session.refresh(user)
  156. max = 5
  157. users = []
  158. for i in range(0, max):
  159. users.append(user)
  160. encoder = pyamf.get_encoder(pyamf.AMF3)
  161. encoder.writeElement(users)
  162. encoded = encoder.stream.getvalue()
  163. decoded = pyamf.get_decoder(pyamf.AMF3, encoded).readElement()
  164. for i in range(0, max):
  165. self.assertEqual(id(decoded[0]), id(decoded[i]))
  166. class BaseClassAliasTestCase(BaseTestCase):
  167. def setUp(self):
  168. BaseTestCase.setUp(self)
  169. self.alias = pyamf.get_class_alias(User)
  170. class ClassAliasTestCase(BaseClassAliasTestCase):
  171. def test_type(self):
  172. self.assertEqual(self.alias.__class__, adapter.SaMappedClassAlias)
  173. def test_get_mapper(self):
  174. self.assertFalse(hasattr(self.alias, 'mapper'))
  175. self.alias.compile()
  176. mapper = adapter.class_mapper(User)
  177. self.assertTrue(hasattr(self.alias, 'mapper'))
  178. self.assertEqual(id(mapper), id(self.alias.mapper))
  179. self.assertEqual(self.alias.static_attrs, [])
  180. def test_get_attrs(self):
  181. u = self._build_obj()
  182. attrs = self.alias.getEncodableAttributes(u)
  183. self.assertEqual(sorted(attrs.keys()), [
  184. 'addresses',
  185. 'another_lazy_loaded',
  186. 'id',
  187. 'lazy_loaded',
  188. 'name',
  189. 'sa_key',
  190. 'sa_lazy'
  191. ])
  192. self.assertEqual(attrs['sa_key'], [None])
  193. self.assertEqual(attrs['sa_lazy'], [])
  194. def test_get_attributes(self):
  195. u = self._build_obj()
  196. self.assertFalse(u in self.session)
  197. self.assertEqual([None], self.mappers['user'].primary_key_from_instance(u))
  198. attrs = self.alias.getEncodableAttributes(u)
  199. self.assertEqual(attrs, {
  200. 'addresses': u.addresses,
  201. 'lazy_loaded': u.lazy_loaded,
  202. 'another_lazy_loaded': [],
  203. 'id': None,
  204. 'name': 'test_user',
  205. 'sa_lazy': [],
  206. 'sa_key': [None]
  207. })
  208. def test_property(self):
  209. class Person(object):
  210. foo = 'bar'
  211. baz = 'gak'
  212. def _get_rw_property(self):
  213. return self.foo
  214. def _set_rw_property(self, val):
  215. self.foo = val
  216. def _get_ro_property(self):
  217. return self.baz
  218. rw = property(_get_rw_property, _set_rw_property)
  219. ro = property(_get_ro_property)
  220. self.mappers['person'] = mapper(Person, self.tables['users'])
  221. alias = adapter.SaMappedClassAlias(Person, 'person')
  222. obj = Person()
  223. attrs = alias.getEncodableAttributes(obj)
  224. self.assertEqual(attrs, {
  225. 'id': None,
  226. 'name': None,
  227. 'sa_key': [None],
  228. 'sa_lazy': [],
  229. 'rw': 'bar',
  230. 'ro': 'gak'})
  231. self.assertEqual(obj.ro, 'gak')
  232. alias.applyAttributes(obj, {
  233. 'sa_key': [None],
  234. 'sa_lazy': [],
  235. 'id': None,
  236. 'name': None,
  237. 'rw': 'bar',
  238. 'ro': 'baz'})
  239. self.assertEqual(obj.ro, 'gak')
  240. class ApplyAttributesTestCase(BaseClassAliasTestCase):
  241. def test_undefined(self):
  242. u = self.alias.createInstance()
  243. attrs = {
  244. 'sa_lazy': ['another_lazy_loaded'],
  245. 'sa_key': [None],
  246. 'addresses': [],
  247. 'lazy_loaded': [],
  248. 'another_lazy_loaded': pyamf.Undefined, # <-- the important bit
  249. 'id': None,
  250. 'name': 'test_user'
  251. }
  252. self.alias.applyAttributes(u, attrs)
  253. d = u.__dict__.copy()
  254. if sqlalchemy.__version__.startswith('0.4'):
  255. self.assertTrue('_state' in d)
  256. del d['_state']
  257. else:
  258. self.assertTrue('_sa_instance_state' in d)
  259. del d['_sa_instance_state']
  260. self.assertEqual(d, {
  261. 'lazy_loaded': [],
  262. 'addresses': [],
  263. 'name': 'test_user',
  264. 'id': None
  265. })
  266. def test_decode_unaliased(self):
  267. u = self.alias.createInstance()
  268. attrs = {
  269. 'sa_lazy': [],
  270. 'sa_key': [None],
  271. 'addresses': [],
  272. 'lazy_loaded': [],
  273. # this is important because we haven't registered AnotherLazyLoaded
  274. # as an alias and the decoded object for an untyped object is an
  275. # instance of pyamf.ASObject
  276. 'another_lazy_loaded': [pyamf.ASObject({'id': 1, 'user_id': None})],
  277. 'id': None,
  278. 'name': 'test_user'
  279. }
  280. # sqlalchemy can't find any state to work with
  281. self.assertRaises(AttributeError, self.alias.applyAttributes, u, attrs)
  282. class AdapterTestCase(BaseTestCase):
  283. """
  284. Checks to see if the adapter will actually intercept a class correctly.
  285. """
  286. def test_mapped(self):
  287. self.assertNotEquals(None, adapter.class_mapper(User))
  288. self.assertTrue(adapter.is_class_sa_mapped(User))
  289. def test_instance(self):
  290. u = User()
  291. self.assertTrue(adapter.is_class_sa_mapped(u))
  292. def test_not_mapped(self):
  293. self.assertRaises(adapter.UnmappedInstanceError, adapter.class_mapper, Spam)
  294. self.assertFalse(adapter.is_class_sa_mapped(Spam))
  295. class ExcludableAttrsTestCase(BaseTestCase):
  296. """
  297. Tests for #790
  298. """
  299. def test_core_attrs(self):
  300. """
  301. Ensure that sa_key and sa_lazy can be excluded
  302. """
  303. a = adapter.SaMappedClassAlias(Address, exclude_attrs=['sa_lazy', 'sa_key'])
  304. u = Address()
  305. attrs = a.getEncodableAttributes(u)
  306. self.assertFalse('sa_key' in attrs)
  307. self.assertFalse('sa_lazy' in attrs)