1from sqlalchemy import ForeignKey 2from sqlalchemy import Integer 3from sqlalchemy import String 4from sqlalchemy import util 5from sqlalchemy.orm import backref 6from sqlalchemy.orm import configure_mappers 7from sqlalchemy.orm import mapper 8from sqlalchemy.orm import relationship 9from sqlalchemy.testing import fixtures 10from sqlalchemy.testing.schema import Column 11from sqlalchemy.testing.schema import Table 12 13__all__ = () 14 15 16class FixtureTest(fixtures.MappedTest): 17 """A MappedTest pre-configured with a common set of fixtures. 18 19 """ 20 21 run_define_tables = "once" 22 run_setup_classes = "once" 23 run_setup_mappers = "each" 24 run_inserts = "each" 25 run_deletes = "each" 26 27 @classmethod 28 def setup_classes(cls): 29 class Base(cls.Comparable): 30 pass 31 32 class User(Base): 33 pass 34 35 class Order(Base): 36 pass 37 38 class Item(Base): 39 pass 40 41 class Keyword(Base): 42 pass 43 44 class Address(Base): 45 pass 46 47 class Dingaling(Base): 48 pass 49 50 class Node(Base): 51 pass 52 53 class CompositePk(Base): 54 pass 55 56 @classmethod 57 def _setup_stock_mapping(cls): 58 ( 59 Node, 60 composite_pk_table, 61 users, 62 Keyword, 63 items, 64 Dingaling, 65 order_items, 66 item_keywords, 67 Item, 68 User, 69 dingalings, 70 Address, 71 keywords, 72 CompositePk, 73 nodes, 74 Order, 75 orders, 76 addresses, 77 ) = ( 78 cls.classes.Node, 79 cls.tables.composite_pk_table, 80 cls.tables.users, 81 cls.classes.Keyword, 82 cls.tables.items, 83 cls.classes.Dingaling, 84 cls.tables.order_items, 85 cls.tables.item_keywords, 86 cls.classes.Item, 87 cls.classes.User, 88 cls.tables.dingalings, 89 cls.classes.Address, 90 cls.tables.keywords, 91 cls.classes.CompositePk, 92 cls.tables.nodes, 93 cls.classes.Order, 94 cls.tables.orders, 95 cls.tables.addresses, 96 ) 97 98 # use OrderedDict on this one to support some tests that 99 # assert the order of attributes (e.g. orm/test_inspect) 100 mapper( 101 User, 102 users, 103 properties=util.OrderedDict( 104 [ 105 ( 106 "addresses", 107 relationship( 108 Address, backref="user", order_by=addresses.c.id 109 ), 110 ), 111 ( 112 "orders", 113 relationship( 114 Order, backref="user", order_by=orders.c.id 115 ), 116 ), # o2m, m2o 117 ] 118 ), 119 ) 120 mapper( 121 Address, 122 addresses, 123 properties={ 124 # o2o 125 "dingaling": relationship( 126 Dingaling, uselist=False, backref="address" 127 ) 128 }, 129 ) 130 mapper(Dingaling, dingalings) 131 mapper( 132 Order, 133 orders, 134 properties={ 135 # m2m 136 "items": relationship( 137 Item, secondary=order_items, order_by=items.c.id 138 ), 139 "address": relationship(Address), # m2o 140 }, 141 ) 142 mapper( 143 Item, 144 items, 145 properties={ 146 "keywords": relationship( 147 Keyword, secondary=item_keywords 148 ) # m2m 149 }, 150 ) 151 mapper(Keyword, keywords) 152 153 mapper( 154 Node, 155 nodes, 156 properties={ 157 "children": relationship( 158 Node, backref=backref("parent", remote_side=[nodes.c.id]) 159 ) 160 }, 161 ) 162 163 mapper(CompositePk, composite_pk_table) 164 165 configure_mappers() 166 167 @classmethod 168 def define_tables(cls, metadata): 169 Table( 170 "users", 171 metadata, 172 Column( 173 "id", Integer, primary_key=True, test_needs_autoincrement=True 174 ), 175 Column("name", String(30), nullable=False), 176 test_needs_acid=True, 177 test_needs_fk=True, 178 ) 179 180 Table( 181 "addresses", 182 metadata, 183 Column( 184 "id", Integer, primary_key=True, test_needs_autoincrement=True 185 ), 186 Column("user_id", None, ForeignKey("users.id")), 187 Column("email_address", String(50), nullable=False), 188 test_needs_acid=True, 189 test_needs_fk=True, 190 ) 191 192 Table( 193 "email_bounces", 194 metadata, 195 Column("id", Integer, ForeignKey("addresses.id")), 196 Column("bounces", Integer), 197 ) 198 199 Table( 200 "orders", 201 metadata, 202 Column( 203 "id", Integer, primary_key=True, test_needs_autoincrement=True 204 ), 205 Column("user_id", None, ForeignKey("users.id")), 206 Column("address_id", None, ForeignKey("addresses.id")), 207 Column("description", String(30)), 208 Column("isopen", Integer), 209 test_needs_acid=True, 210 test_needs_fk=True, 211 ) 212 213 Table( 214 "dingalings", 215 metadata, 216 Column( 217 "id", Integer, primary_key=True, test_needs_autoincrement=True 218 ), 219 Column("address_id", None, ForeignKey("addresses.id")), 220 Column("data", String(30)), 221 test_needs_acid=True, 222 test_needs_fk=True, 223 ) 224 225 Table( 226 "items", 227 metadata, 228 Column( 229 "id", Integer, primary_key=True, test_needs_autoincrement=True 230 ), 231 Column("description", String(30), nullable=False), 232 test_needs_acid=True, 233 test_needs_fk=True, 234 ) 235 236 Table( 237 "order_items", 238 metadata, 239 Column("item_id", None, ForeignKey("items.id")), 240 Column("order_id", None, ForeignKey("orders.id")), 241 test_needs_acid=True, 242 test_needs_fk=True, 243 ) 244 245 Table( 246 "keywords", 247 metadata, 248 Column( 249 "id", Integer, primary_key=True, test_needs_autoincrement=True 250 ), 251 Column("name", String(30), nullable=False), 252 test_needs_acid=True, 253 test_needs_fk=True, 254 ) 255 256 Table( 257 "item_keywords", 258 metadata, 259 Column("item_id", None, ForeignKey("items.id")), 260 Column("keyword_id", None, ForeignKey("keywords.id")), 261 test_needs_acid=True, 262 test_needs_fk=True, 263 ) 264 265 Table( 266 "nodes", 267 metadata, 268 Column( 269 "id", Integer, primary_key=True, test_needs_autoincrement=True 270 ), 271 Column("parent_id", Integer, ForeignKey("nodes.id")), 272 Column("data", String(30)), 273 test_needs_acid=True, 274 test_needs_fk=True, 275 ) 276 277 Table( 278 "composite_pk_table", 279 metadata, 280 Column("i", Integer, primary_key=True), 281 Column("j", Integer, primary_key=True), 282 Column("k", Integer, nullable=False), 283 ) 284 285 @classmethod 286 def setup_mappers(cls): 287 pass 288 289 @classmethod 290 def fixtures(cls): 291 return dict( 292 users=( 293 ("id", "name"), 294 (7, "jack"), 295 (8, "ed"), 296 (9, "fred"), 297 (10, "chuck"), 298 ), 299 addresses=( 300 ("id", "user_id", "email_address"), 301 (1, 7, "jack@bean.com"), 302 (2, 8, "ed@wood.com"), 303 (3, 8, "ed@bettyboop.com"), 304 (4, 8, "ed@lala.com"), 305 (5, 9, "fred@fred.com"), 306 ), 307 email_bounces=( 308 ("id", "bounces"), 309 (1, 1), 310 (2, 0), 311 (3, 5), 312 (4, 0), 313 (5, 0), 314 ), 315 orders=( 316 ("id", "user_id", "description", "isopen", "address_id"), 317 (1, 7, "order 1", 0, 1), 318 (2, 9, "order 2", 0, 4), 319 (3, 7, "order 3", 1, 1), 320 (4, 9, "order 4", 1, 4), 321 (5, 7, "order 5", 0, None), 322 ), 323 dingalings=( 324 ("id", "address_id", "data"), 325 (1, 2, "ding 1/2"), 326 (2, 5, "ding 2/5"), 327 ), 328 items=( 329 ("id", "description"), 330 (1, "item 1"), 331 (2, "item 2"), 332 (3, "item 3"), 333 (4, "item 4"), 334 (5, "item 5"), 335 ), 336 order_items=( 337 ("item_id", "order_id"), 338 (1, 1), 339 (2, 1), 340 (3, 1), 341 (1, 2), 342 (2, 2), 343 (3, 2), 344 (3, 3), 345 (4, 3), 346 (5, 3), 347 (1, 4), 348 (5, 4), 349 (5, 5), 350 ), 351 keywords=( 352 ("id", "name"), 353 (1, "blue"), 354 (2, "red"), 355 (3, "green"), 356 (4, "big"), 357 (5, "small"), 358 (6, "round"), 359 (7, "square"), 360 ), 361 item_keywords=( 362 ("keyword_id", "item_id"), 363 (2, 1), 364 (2, 2), 365 (4, 1), 366 (6, 1), 367 (5, 2), 368 (3, 3), 369 (4, 3), 370 (7, 2), 371 (6, 3), 372 ), 373 nodes=(("id", "parent_id", "data"),), 374 composite_pk_table=( 375 ("i", "j", "k"), 376 (1, 2, 3), 377 (2, 1, 4), 378 (1, 1, 5), 379 (2, 2, 6), 380 ), 381 ) 382 383 @util.memoized_property 384 def static(self): 385 return CannedResults(self) 386 387 388class CannedResults(object): 389 """Built on demand, instances use mappers in effect at time of call.""" 390 391 def __init__(self, test): 392 self.test = test 393 394 @property 395 def user_result(self): 396 User = self.test.classes.User 397 398 return [User(id=7), User(id=8), User(id=9), User(id=10)] 399 400 @property 401 def user_address_result(self): 402 User, Address = self.test.classes.User, self.test.classes.Address 403 404 return [ 405 User(id=7, addresses=[Address(id=1)]), 406 User( 407 id=8, 408 addresses=[ 409 Address(id=2, email_address="ed@wood.com"), 410 Address(id=3, email_address="ed@bettyboop.com"), 411 Address(id=4, email_address="ed@lala.com"), 412 ], 413 ), 414 User(id=9, addresses=[Address(id=5)]), 415 User(id=10, addresses=[]), 416 ] 417 418 @property 419 def address_user_result(self): 420 User, Address = self.test.classes.User, self.test.classes.Address 421 u7 = User(id=7) 422 u8 = User(id=8) 423 u9 = User(id=9) 424 return [ 425 Address(id=1, email_address="jack@bean.com", user=u7), 426 Address(id=2, email_address="ed@wood.com", user=u8), 427 Address(id=3, email_address="ed@bettyboop.com", user=u8), 428 Address(id=4, email_address="ed@lala.com", user=u8), 429 Address(id=5, user=u9), 430 ] 431 432 @property 433 def user_all_result(self): 434 User, Address, Order, Item = ( 435 self.test.classes.User, 436 self.test.classes.Address, 437 self.test.classes.Order, 438 self.test.classes.Item, 439 ) 440 441 return [ 442 User( 443 id=7, 444 addresses=[Address(id=1)], 445 orders=[ 446 Order( 447 description="order 1", 448 items=[ 449 Item(description="item 1"), 450 Item(description="item 2"), 451 Item(description="item 3"), 452 ], 453 ), 454 Order(description="order 3"), 455 Order(description="order 5"), 456 ], 457 ), 458 User( 459 id=8, addresses=[Address(id=2), Address(id=3), Address(id=4)] 460 ), 461 User( 462 id=9, 463 addresses=[Address(id=5)], 464 orders=[ 465 Order( 466 description="order 2", 467 items=[ 468 Item(description="item 1"), 469 Item(description="item 2"), 470 Item(description="item 3"), 471 ], 472 ), 473 Order( 474 description="order 4", 475 items=[ 476 Item(description="item 1"), 477 Item(description="item 5"), 478 ], 479 ), 480 ], 481 ), 482 User(id=10, addresses=[]), 483 ] 484 485 @property 486 def user_order_result(self): 487 User, Order, Item = ( 488 self.test.classes.User, 489 self.test.classes.Order, 490 self.test.classes.Item, 491 ) 492 return [ 493 User( 494 id=7, 495 orders=[ 496 Order(id=1, items=[Item(id=1), Item(id=2), Item(id=3)]), 497 Order(id=3, items=[Item(id=3), Item(id=4), Item(id=5)]), 498 Order(id=5, items=[Item(id=5)]), 499 ], 500 ), 501 User(id=8, orders=[]), 502 User( 503 id=9, 504 orders=[ 505 Order(id=2, items=[Item(id=1), Item(id=2), Item(id=3)]), 506 Order(id=4, items=[Item(id=1), Item(id=5)]), 507 ], 508 ), 509 User(id=10), 510 ] 511 512 @property 513 def item_keyword_result(self): 514 Item, Keyword = self.test.classes.Item, self.test.classes.Keyword 515 return [ 516 Item( 517 id=1, 518 keywords=[ 519 Keyword(name="red"), 520 Keyword(name="big"), 521 Keyword(name="round"), 522 ], 523 ), 524 Item( 525 id=2, 526 keywords=[ 527 Keyword(name="red"), 528 Keyword(name="small"), 529 Keyword(name="square"), 530 ], 531 ), 532 Item( 533 id=3, 534 keywords=[ 535 Keyword(name="green"), 536 Keyword(name="big"), 537 Keyword(name="round"), 538 ], 539 ), 540 Item(id=4, keywords=[]), 541 Item(id=5, keywords=[]), 542 ] 543 544 @property 545 def user_item_keyword_result(self): 546 Item, Keyword = self.test.classes.Item, self.test.classes.Keyword 547 User, Order = self.test.classes.User, self.test.classes.Order 548 549 item1, item2, item3, item4, item5 = ( 550 Item( 551 id=1, 552 keywords=[ 553 Keyword(name="red"), 554 Keyword(name="big"), 555 Keyword(name="round"), 556 ], 557 ), 558 Item( 559 id=2, 560 keywords=[ 561 Keyword(name="red"), 562 Keyword(name="small"), 563 Keyword(name="square"), 564 ], 565 ), 566 Item( 567 id=3, 568 keywords=[ 569 Keyword(name="green"), 570 Keyword(name="big"), 571 Keyword(name="round"), 572 ], 573 ), 574 Item(id=4, keywords=[]), 575 Item(id=5, keywords=[]), 576 ) 577 578 user_result = [ 579 User( 580 id=7, 581 orders=[ 582 Order(id=1, items=[item1, item2, item3]), 583 Order(id=3, items=[item3, item4, item5]), 584 Order(id=5, items=[item5]), 585 ], 586 ), 587 User(id=8, orders=[]), 588 User( 589 id=9, 590 orders=[ 591 Order(id=2, items=[item1, item2, item3]), 592 Order(id=4, items=[item1, item5]), 593 ], 594 ), 595 User(id=10, orders=[]), 596 ] 597 return user_result 598