summaryrefslogtreecommitdiff
path: root/test/ext/declarative/test_basic.py
diff options
context:
space:
mode:
Diffstat (limited to 'test/ext/declarative/test_basic.py')
-rw-r--r--test/ext/declarative/test_basic.py2273
1 files changed, 0 insertions, 2273 deletions
diff --git a/test/ext/declarative/test_basic.py b/test/ext/declarative/test_basic.py
deleted file mode 100644
index b7b5ec61a..000000000
--- a/test/ext/declarative/test_basic.py
+++ /dev/null
@@ -1,2273 +0,0 @@
-import sqlalchemy as sa
-from sqlalchemy import CheckConstraint
-from sqlalchemy import event
-from sqlalchemy import exc
-from sqlalchemy import ForeignKey
-from sqlalchemy import ForeignKeyConstraint
-from sqlalchemy import Index
-from sqlalchemy import inspect
-from sqlalchemy import Integer
-from sqlalchemy import MetaData
-from sqlalchemy import String
-from sqlalchemy import testing
-from sqlalchemy import UniqueConstraint
-from sqlalchemy import util
-from sqlalchemy.ext import declarative as decl
-from sqlalchemy.ext.declarative import DeclarativeMeta
-from sqlalchemy.ext.declarative import declared_attr
-from sqlalchemy.ext.declarative import synonym_for
-from sqlalchemy.ext.declarative.base import _DeferredMapperConfig
-from sqlalchemy.ext.hybrid import hybrid_property
-from sqlalchemy.orm import backref
-from sqlalchemy.orm import class_mapper
-from sqlalchemy.orm import clear_mappers
-from sqlalchemy.orm import close_all_sessions
-from sqlalchemy.orm import column_property
-from sqlalchemy.orm import composite
-from sqlalchemy.orm import configure_mappers
-from sqlalchemy.orm import create_session
-from sqlalchemy.orm import deferred
-from sqlalchemy.orm import descriptor_props
-from sqlalchemy.orm import exc as orm_exc
-from sqlalchemy.orm import joinedload
-from sqlalchemy.orm import mapper
-from sqlalchemy.orm import relationship
-from sqlalchemy.orm import Session
-from sqlalchemy.orm.events import MapperEvents
-from sqlalchemy.testing import assert_raises
-from sqlalchemy.testing import assert_raises_message
-from sqlalchemy.testing import assertions
-from sqlalchemy.testing import eq_
-from sqlalchemy.testing import expect_warnings
-from sqlalchemy.testing import fixtures
-from sqlalchemy.testing import is_
-from sqlalchemy.testing import mock
-from sqlalchemy.testing.schema import Column
-from sqlalchemy.testing.schema import Table
-from sqlalchemy.util import with_metaclass
-
-
-Base = None
-
-User = Address = None
-
-
-class DeclarativeTestBase(
- fixtures.TestBase,
- testing.AssertsExecutionResults,
- testing.AssertsCompiledSQL,
-):
- __dialect__ = "default"
-
- def setup(self):
- global Base
- Base = decl.declarative_base(testing.db)
-
- def teardown(self):
- close_all_sessions()
- clear_mappers()
- Base.metadata.drop_all()
-
-
-class DeclarativeTest(DeclarativeTestBase):
- def test_basic(self):
- class User(Base, fixtures.ComparableEntity):
- __tablename__ = "users"
-
- id = Column(
- "id", Integer, primary_key=True, test_needs_autoincrement=True
- )
- name = Column("name", String(50))
- addresses = relationship("Address", backref="user")
-
- class Address(Base, fixtures.ComparableEntity):
- __tablename__ = "addresses"
-
- id = Column(
- Integer, primary_key=True, test_needs_autoincrement=True
- )
- email = Column(String(50), key="_email")
- user_id = Column(
- "user_id", Integer, ForeignKey("users.id"), key="_user_id"
- )
-
- Base.metadata.create_all()
-
- eq_(Address.__table__.c["id"].name, "id")
- eq_(Address.__table__.c["_email"].name, "email")
- eq_(Address.__table__.c["_user_id"].name, "user_id")
-
- u1 = User(
- name="u1", addresses=[Address(email="one"), Address(email="two")]
- )
- sess = create_session()
- sess.add(u1)
- sess.flush()
- sess.expunge_all()
-
- eq_(
- sess.query(User).all(),
- [
- User(
- name="u1",
- addresses=[Address(email="one"), Address(email="two")],
- )
- ],
- )
-
- a1 = sess.query(Address).filter(Address.email == "two").one()
- eq_(a1, Address(email="two"))
- eq_(a1.user, User(name="u1"))
-
- def test_deferred_reflection_default_error(self):
- class MyExt(object):
- @classmethod
- def prepare(cls):
- "sample prepare method"
- to_map = _DeferredMapperConfig.classes_for_base(cls)
- for thingy in to_map:
- thingy.map()
-
- @classmethod
- def _sa_decl_prepare(cls):
- pass
-
- class User(MyExt, Base):
- __tablename__ = "user"
- id = Column(Integer, primary_key=True)
-
- assert_raises_message(
- orm_exc.UnmappedClassError,
- "Class test.ext.declarative.test_basic.User has a deferred "
- "mapping on it. It is not yet usable as a mapped class.",
- Session().query,
- User,
- )
-
- User.prepare()
-
- self.assert_compile(
- Session().query(User), 'SELECT "user".id AS user_id FROM "user"'
- )
-
- def test_unicode_string_resolve(self):
- class User(Base, fixtures.ComparableEntity):
- __tablename__ = "users"
-
- id = Column(
- "id", Integer, primary_key=True, test_needs_autoincrement=True
- )
- name = Column("name", String(50))
- addresses = relationship(util.u("Address"), backref="user")
-
- class Address(Base, fixtures.ComparableEntity):
- __tablename__ = "addresses"
-
- id = Column(
- Integer, primary_key=True, test_needs_autoincrement=True
- )
- email = Column(String(50), key="_email")
- user_id = Column(
- "user_id", Integer, ForeignKey("users.id"), key="_user_id"
- )
-
- assert User.addresses.property.mapper.class_ is Address
-
- def test_unicode_string_resolve_backref(self):
- class User(Base, fixtures.ComparableEntity):
- __tablename__ = "users"
-
- id = Column(
- "id", Integer, primary_key=True, test_needs_autoincrement=True
- )
- name = Column("name", String(50))
-
- class Address(Base, fixtures.ComparableEntity):
- __tablename__ = "addresses"
-
- id = Column(
- Integer, primary_key=True, test_needs_autoincrement=True
- )
- email = Column(String(50), key="_email")
- user_id = Column(
- "user_id", Integer, ForeignKey("users.id"), key="_user_id"
- )
- user = relationship(
- User,
- backref=backref("addresses", order_by=util.u("Address.email")),
- )
-
- assert Address.user.property.mapper.class_ is User
-
- def test_no_table(self):
- def go():
- class User(Base):
- id = Column("id", Integer, primary_key=True)
-
- assert_raises_message(
- sa.exc.InvalidRequestError, "does not have a __table__", go
- )
-
- def test_table_args_empty_dict(self):
- class MyModel(Base):
- __tablename__ = "test"
- id = Column(Integer, primary_key=True)
- __table_args__ = {}
-
- def test_table_args_empty_tuple(self):
- class MyModel(Base):
- __tablename__ = "test"
- id = Column(Integer, primary_key=True)
- __table_args__ = ()
-
- def test_cant_add_columns(self):
- t = Table(
- "t",
- Base.metadata,
- Column("id", Integer, primary_key=True),
- Column("data", String),
- )
-
- def go():
- class User(Base):
- __table__ = t
- foo = Column(Integer, primary_key=True)
-
- # can't specify new columns not already in the table
-
- assert_raises_message(
- sa.exc.ArgumentError,
- "Can't add additional column 'foo' when " "specifying __table__",
- go,
- )
-
- # regular re-mapping works tho
-
- class Bar(Base):
- __table__ = t
- some_data = t.c.data
-
- assert (
- class_mapper(Bar).get_property("some_data").columns[0] is t.c.data
- )
-
- def test_lower_case_c_column_warning(self):
- with assertions.expect_warnings(
- r"Attribute 'x' on class <class .*Foo.* appears to be a "
- r"non-schema 'sqlalchemy.sql.column\(\)' object; "
- ):
-
- class Foo(Base):
- __tablename__ = "foo"
-
- id = Column(Integer, primary_key=True)
- x = sa.sql.expression.column(Integer)
- y = Column(Integer)
-
- class MyMixin(object):
- x = sa.sql.expression.column(Integer)
- y = Column(Integer)
-
- with assertions.expect_warnings(
- r"Attribute 'x' on class <class .*MyMixin.* appears to be a "
- r"non-schema 'sqlalchemy.sql.column\(\)' object; "
- ):
-
- class Foo2(MyMixin, Base):
- __tablename__ = "foo2"
-
- id = Column(Integer, primary_key=True)
-
- with assertions.expect_warnings(
- r"Attribute 'x' on class <class .*Foo3.* appears to be a "
- r"non-schema 'sqlalchemy.sql.column\(\)' object; "
- ):
-
- class Foo3(Base):
- __tablename__ = "foo3"
-
- id = Column(Integer, primary_key=True)
-
- @declared_attr
- def x(cls):
- return sa.sql.expression.column(Integer)
-
- y = Column(Integer)
-
- with assertions.expect_warnings(
- r"Attribute 'x' on class <class .*Foo4.* appears to be a "
- r"non-schema 'sqlalchemy.sql.column\(\)' object; "
- ):
-
- class MyMixin2(object):
- @declared_attr
- def x(cls):
- return sa.sql.expression.column(Integer)
-
- y = Column(Integer)
-
- class Foo4(MyMixin2, Base):
- __tablename__ = "foo4"
-
- id = Column(Integer, primary_key=True)
-
- def test_column_named_twice(self):
- def go():
- class Foo(Base):
- __tablename__ = "foo"
-
- id = Column(Integer, primary_key=True)
- x = Column("x", Integer)
- y = Column("x", Integer)
-
- assert_raises_message(
- sa.exc.SAWarning,
- "On class 'Foo', Column object 'x' named directly multiple times, "
- "only one will be used: x, y",
- go,
- )
-
- def test_column_repeated_under_prop(self):
- def go():
- class Foo(Base):
- __tablename__ = "foo"
-
- id = Column(Integer, primary_key=True)
- x = Column("x", Integer)
- y = column_property(x)
- z = Column("x", Integer)
-
- assert_raises_message(
- sa.exc.SAWarning,
- "On class 'Foo', Column object 'x' named directly multiple times, "
- "only one will be used: x, y, z",
- go,
- )
-
- def test_using_explicit_prop_in_schema_objects(self):
- class Foo(Base):
- __tablename__ = "foo"
-
- id = Column(Integer, primary_key=True)
- cprop = column_property(Column(Integer))
-
- __table_args__ = (UniqueConstraint(cprop),)
-
- uq = [
- c
- for c in Foo.__table__.constraints
- if isinstance(c, UniqueConstraint)
- ][0]
- is_(uq.columns.cprop, Foo.__table__.c.cprop)
-
- class Bar(Base):
- __tablename__ = "bar"
-
- id = Column(Integer, primary_key=True)
- cprop = deferred(Column(Integer))
-
- __table_args__ = (CheckConstraint(cprop > sa.func.foo()),)
-
- ck = [
- c
- for c in Bar.__table__.constraints
- if isinstance(c, CheckConstraint)
- ][0]
- is_(ck.columns.cprop, Bar.__table__.c.cprop)
-
- if testing.requires.python3.enabled:
- # test the existing failure case in case something changes
- def go():
- class Bat(Base):
- __tablename__ = "bat"
-
- id = Column(Integer, primary_key=True)
- cprop = deferred(Column(Integer))
-
- # we still can't do an expression like
- # "cprop > 5" because the column property isn't
- # a full blown column
-
- __table_args__ = (CheckConstraint(cprop > 5),)
-
- assert_raises(TypeError, go)
-
- def test_relationship_level_msg_for_invalid_callable(self):
- class A(Base):
- __tablename__ = "a"
- id = Column(Integer, primary_key=True)
-
- class B(Base):
- __tablename__ = "b"
- id = Column(Integer, primary_key=True)
- a_id = Column(Integer, ForeignKey("a.id"))
- a = relationship("a")
-
- assert_raises_message(
- sa.exc.ArgumentError,
- "relationship 'a' expects a class or a mapper "
- "argument .received: .*Table",
- configure_mappers,
- )
-
- def test_relationship_level_msg_for_invalid_object(self):
- class A(Base):
- __tablename__ = "a"
- id = Column(Integer, primary_key=True)
-
- class B(Base):
- __tablename__ = "b"
- id = Column(Integer, primary_key=True)
- a_id = Column(Integer, ForeignKey("a.id"))
- a = relationship(A.__table__)
-
- assert_raises_message(
- sa.exc.ArgumentError,
- "relationship 'a' expects a class or a mapper "
- "argument .received: .*Table",
- configure_mappers,
- )
-
- def test_difficult_class(self):
- """test no getattr() errors with a customized class"""
-
- # metaclass to mock the way zope.interface breaks getattr()
- class BrokenMeta(type):
- def __getattribute__(self, attr):
- if attr == "xyzzy":
- raise AttributeError("xyzzy")
- else:
- return object.__getattribute__(self, attr)
-
- # even though this class has an xyzzy attribute, getattr(cls,"xyzzy")
- # fails
- class BrokenParent(with_metaclass(BrokenMeta)):
- xyzzy = "magic"
-
- # _as_declarative() inspects obj.__class__.__bases__
- class User(BrokenParent, fixtures.ComparableEntity):
- __tablename__ = "users"
- id = Column(
- "id", Integer, primary_key=True, test_needs_autoincrement=True
- )
- name = Column("name", String(50))
-
- decl.instrument_declarative(User, {}, Base.metadata)
-
- def test_reserved_identifiers(self):
- def go1():
- class User1(Base):
- __tablename__ = "user1"
- id = Column(Integer, primary_key=True)
- metadata = Column(Integer)
-
- def go2():
- class User2(Base):
- __tablename__ = "user2"
- id = Column(Integer, primary_key=True)
- metadata = relationship("Address")
-
- for go in (go1, go2):
- assert_raises_message(
- exc.InvalidRequestError,
- "Attribute name 'metadata' is reserved "
- "for the MetaData instance when using a "
- "declarative base class.",
- go,
- )
-
- def test_undefer_column_name(self):
- # TODO: not sure if there was an explicit
- # test for this elsewhere
- foo = Column(Integer)
- eq_(str(foo), "(no name)")
- eq_(foo.key, None)
- eq_(foo.name, None)
- decl.base._undefer_column_name("foo", foo)
- eq_(str(foo), "foo")
- eq_(foo.key, "foo")
- eq_(foo.name, "foo")
-
- def test_recompile_on_othermapper(self):
- """declarative version of the same test in mappers.py"""
-
- from sqlalchemy.orm import mapperlib
-
- class User(Base):
- __tablename__ = "users"
-
- id = Column("id", Integer, primary_key=True)
- name = Column("name", String(50))
-
- class Address(Base):
- __tablename__ = "addresses"
-
- id = Column("id", Integer, primary_key=True)
- email = Column("email", String(50))
- user_id = Column("user_id", Integer, ForeignKey("users.id"))
- user = relationship(
- "User", primaryjoin=user_id == User.id, backref="addresses"
- )
-
- assert mapperlib.Mapper._new_mappers is True
- u = User() # noqa
- assert User.addresses
- assert mapperlib.Mapper._new_mappers is False
-
- def test_string_dependency_resolution(self):
- class User(Base, fixtures.ComparableEntity):
-
- __tablename__ = "users"
- id = Column(
- Integer, primary_key=True, test_needs_autoincrement=True
- )
- name = Column(String(50))
- addresses = relationship(
- "Address",
- order_by="desc(Address.email)",
- primaryjoin="User.id==Address.user_id",
- foreign_keys="[Address.user_id]",
- backref=backref(
- "user",
- primaryjoin="User.id==Address.user_id",
- foreign_keys="[Address.user_id]",
- ),
- )
-
- class Address(Base, fixtures.ComparableEntity):
-
- __tablename__ = "addresses"
- id = Column(
- Integer, primary_key=True, test_needs_autoincrement=True
- )
- email = Column(String(50))
- user_id = Column(Integer) # note no foreign key
-
- Base.metadata.create_all()
- sess = create_session()
- u1 = User(
- name="ed",
- addresses=[
- Address(email="abc"),
- Address(email="def"),
- Address(email="xyz"),
- ],
- )
- sess.add(u1)
- sess.flush()
- sess.expunge_all()
- eq_(
- sess.query(User).filter(User.name == "ed").one(),
- User(
- name="ed",
- addresses=[
- Address(email="xyz"),
- Address(email="def"),
- Address(email="abc"),
- ],
- ),
- )
-
- class Foo(Base, fixtures.ComparableEntity):
-
- __tablename__ = "foo"
- id = Column(Integer, primary_key=True)
- rel = relationship("User", primaryjoin="User.addresses==Foo.id")
-
- assert_raises_message(
- exc.InvalidRequestError,
- "'addresses' is not an instance of " "ColumnProperty",
- configure_mappers,
- )
-
- def test_string_dependency_resolution_synonym(self):
- class User(Base, fixtures.ComparableEntity):
-
- __tablename__ = "users"
- id = Column(
- Integer, primary_key=True, test_needs_autoincrement=True
- )
- name = Column(String(50))
-
- Base.metadata.create_all()
- sess = create_session()
- u1 = User(name="ed")
- sess.add(u1)
- sess.flush()
- sess.expunge_all()
- eq_(sess.query(User).filter(User.name == "ed").one(), User(name="ed"))
-
- class Foo(Base, fixtures.ComparableEntity):
-
- __tablename__ = "foo"
- id = Column(Integer, primary_key=True)
- _user_id = Column(Integer)
- rel = relationship(
- "User",
- uselist=False,
- foreign_keys=[User.id],
- primaryjoin="Foo.user_id==User.id",
- )
-
- @synonym_for("_user_id")
- @property
- def user_id(self):
- return self._user_id
-
- foo = Foo()
- foo.rel = u1
- assert foo.rel == u1
-
- def test_string_dependency_resolution_orm_descriptor(self):
- from sqlalchemy.ext.hybrid import hybrid_property
-
- class User(Base):
- __tablename__ = "user"
- id = Column(Integer, primary_key=True)
- firstname = Column(String(50))
- lastname = Column(String(50))
- game_id = Column(Integer, ForeignKey("game.id"))
-
- @hybrid_property
- def fullname(self):
- return self.firstname + " " + self.lastname
-
- class Game(Base):
- __tablename__ = "game"
- id = Column(Integer, primary_key=True)
- name = Column(String(50))
- users = relationship("User", order_by="User.fullname")
-
- s = Session()
- self.assert_compile(
- s.query(Game).options(joinedload(Game.users)),
- "SELECT game.id AS game_id, game.name AS game_name, "
- "user_1.id AS user_1_id, user_1.firstname AS user_1_firstname, "
- "user_1.lastname AS user_1_lastname, "
- "user_1.game_id AS user_1_game_id "
- 'FROM game LEFT OUTER JOIN "user" AS user_1 ON game.id = '
- "user_1.game_id ORDER BY "
- "user_1.firstname || :firstname_1 || user_1.lastname",
- )
-
- def test_string_dependency_resolution_asselectable(self):
- class A(Base):
- __tablename__ = "a"
-
- id = Column(Integer, primary_key=True)
- b_id = Column(ForeignKey("b.id"))
-
- d = relationship(
- "D",
- secondary="join(B, D, B.d_id == D.id)."
- "join(C, C.d_id == D.id)",
- primaryjoin="and_(A.b_id == B.id, A.id == C.a_id)",
- secondaryjoin="D.id == B.d_id",
- )
-
- class B(Base):
- __tablename__ = "b"
-
- id = Column(Integer, primary_key=True)
- d_id = Column(ForeignKey("d.id"))
-
- class C(Base):
- __tablename__ = "c"
-
- id = Column(Integer, primary_key=True)
- a_id = Column(ForeignKey("a.id"))
- d_id = Column(ForeignKey("d.id"))
-
- class D(Base):
- __tablename__ = "d"
-
- id = Column(Integer, primary_key=True)
-
- s = Session()
- self.assert_compile(
- s.query(A).join(A.d),
- "SELECT a.id AS a_id, a.b_id AS a_b_id FROM a JOIN "
- "(b AS b_1 JOIN d AS d_1 ON b_1.d_id = d_1.id "
- "JOIN c AS c_1 ON c_1.d_id = d_1.id) ON a.b_id = b_1.id "
- "AND a.id = c_1.a_id JOIN d ON d.id = b_1.d_id",
- )
-
- def test_string_dependency_resolution_no_table(self):
- class User(Base, fixtures.ComparableEntity):
- __tablename__ = "users"
- id = Column(
- Integer, primary_key=True, test_needs_autoincrement=True
- )
- name = Column(String(50))
-
- class Bar(Base, fixtures.ComparableEntity):
- __tablename__ = "bar"
- id = Column(Integer, primary_key=True)
- rel = relationship("User", primaryjoin="User.id==Bar.__table__.id")
-
- assert_raises_message(
- AttributeError,
- "does not have a mapped column named " "'__table__'",
- configure_mappers,
- )
-
- def test_string_w_pj_annotations(self):
- class User(Base, fixtures.ComparableEntity):
- __tablename__ = "users"
- id = Column(
- Integer, primary_key=True, test_needs_autoincrement=True
- )
- name = Column(String(50))
-
- class Address(Base, fixtures.ComparableEntity):
-
- __tablename__ = "addresses"
- id = Column(
- Integer, primary_key=True, test_needs_autoincrement=True
- )
- email = Column(String(50))
- user_id = Column(Integer)
- user = relationship(
- "User", primaryjoin="remote(User.id)==foreign(Address.user_id)"
- )
-
- eq_(
- Address.user.property._join_condition.local_remote_pairs,
- [(Address.__table__.c.user_id, User.__table__.c.id)],
- )
-
- def test_string_dependency_resolution_no_magic(self):
- """test that full tinkery expressions work as written"""
-
- class User(Base, fixtures.ComparableEntity):
-
- __tablename__ = "users"
- id = Column(Integer, primary_key=True)
- addresses = relationship(
- "Address",
- primaryjoin="User.id==Address.user_id.prop.columns[0]",
- )
-
- class Address(Base, fixtures.ComparableEntity):
-
- __tablename__ = "addresses"
- id = Column(Integer, primary_key=True)
- user_id = Column(Integer, ForeignKey("users.id"))
-
- configure_mappers()
- eq_(
- str(User.addresses.prop.primaryjoin),
- "users.id = addresses.user_id",
- )
-
- def test_string_dependency_resolution_module_qualified(self):
- class User(Base, fixtures.ComparableEntity):
-
- __tablename__ = "users"
- id = Column(Integer, primary_key=True)
- addresses = relationship(
- "%s.Address" % __name__,
- primaryjoin="%s.User.id==%s.Address.user_id.prop.columns[0]"
- % (__name__, __name__),
- )
-
- class Address(Base, fixtures.ComparableEntity):
-
- __tablename__ = "addresses"
- id = Column(Integer, primary_key=True)
- user_id = Column(Integer, ForeignKey("users.id"))
-
- configure_mappers()
- eq_(
- str(User.addresses.prop.primaryjoin),
- "users.id = addresses.user_id",
- )
-
- def test_string_dependency_resolution_in_backref(self):
- class User(Base, fixtures.ComparableEntity):
-
- __tablename__ = "users"
- id = Column(Integer, primary_key=True)
- name = Column(String(50))
- addresses = relationship(
- "Address",
- primaryjoin="User.id==Address.user_id",
- backref="user",
- )
-
- class Address(Base, fixtures.ComparableEntity):
-
- __tablename__ = "addresses"
- id = Column(Integer, primary_key=True)
- email = Column(String(50))
- user_id = Column(Integer, ForeignKey("users.id"))
-
- configure_mappers()
- eq_(
- str(User.addresses.property.primaryjoin),
- str(Address.user.property.primaryjoin),
- )
-
- def test_string_dependency_resolution_tables(self):
- class User(Base, fixtures.ComparableEntity):
-
- __tablename__ = "users"
- id = Column(Integer, primary_key=True)
- name = Column(String(50))
- props = relationship(
- "Prop",
- secondary="user_to_prop",
- primaryjoin="User.id==user_to_prop.c.u" "ser_id",
- secondaryjoin="user_to_prop.c.prop_id=" "=Prop.id",
- backref="users",
- )
-
- class Prop(Base, fixtures.ComparableEntity):
-
- __tablename__ = "props"
- id = Column(Integer, primary_key=True)
- name = Column(String(50))
-
- user_to_prop = Table(
- "user_to_prop",
- Base.metadata,
- Column("user_id", Integer, ForeignKey("users.id")),
- Column("prop_id", Integer, ForeignKey("props.id")),
- )
-
- configure_mappers()
- assert (
- class_mapper(User).get_property("props").secondary is user_to_prop
- )
-
- def test_string_dependency_resolution_schemas(self):
- Base = decl.declarative_base()
-
- class User(Base):
-
- __tablename__ = "users"
- __table_args__ = {"schema": "fooschema"}
-
- id = Column(Integer, primary_key=True)
- name = Column(String(50))
- props = relationship(
- "Prop",
- secondary="fooschema.user_to_prop",
- primaryjoin="User.id==fooschema.user_to_prop.c.user_id",
- secondaryjoin="fooschema.user_to_prop.c.prop_id==Prop.id",
- backref="users",
- )
-
- class Prop(Base):
-
- __tablename__ = "props"
- __table_args__ = {"schema": "fooschema"}
-
- id = Column(Integer, primary_key=True)
- name = Column(String(50))
-
- user_to_prop = Table(
- "user_to_prop",
- Base.metadata,
- Column("user_id", Integer, ForeignKey("fooschema.users.id")),
- Column("prop_id", Integer, ForeignKey("fooschema.props.id")),
- schema="fooschema",
- )
- configure_mappers()
-
- assert (
- class_mapper(User).get_property("props").secondary is user_to_prop
- )
-
- def test_string_dependency_resolution_annotations(self):
- Base = decl.declarative_base()
-
- class Parent(Base):
- __tablename__ = "parent"
- id = Column(Integer, primary_key=True)
- name = Column(String)
- children = relationship(
- "Child",
- primaryjoin="Parent.name=="
- "remote(foreign(func.lower(Child.name_upper)))",
- )
-
- class Child(Base):
- __tablename__ = "child"
- id = Column(Integer, primary_key=True)
- name_upper = Column(String)
-
- configure_mappers()
- eq_(
- Parent.children.property._calculated_foreign_keys,
- set([Child.name_upper.property.columns[0]]),
- )
-
- def test_shared_class_registry(self):
- reg = {}
- Base1 = decl.declarative_base(testing.db, class_registry=reg)
- Base2 = decl.declarative_base(testing.db, class_registry=reg)
-
- class A(Base1):
- __tablename__ = "a"
- id = Column(Integer, primary_key=True)
-
- class B(Base2):
- __tablename__ = "b"
- id = Column(Integer, primary_key=True)
- aid = Column(Integer, ForeignKey(A.id))
- as_ = relationship("A")
-
- assert B.as_.property.mapper.class_ is A
-
- def test_uncompiled_attributes_in_relationship(self):
- class Address(Base, fixtures.ComparableEntity):
-
- __tablename__ = "addresses"
- id = Column(
- Integer, primary_key=True, test_needs_autoincrement=True
- )
- email = Column(String(50))
- user_id = Column(Integer, ForeignKey("users.id"))
-
- class User(Base, fixtures.ComparableEntity):
-
- __tablename__ = "users"
- id = Column(
- Integer, primary_key=True, test_needs_autoincrement=True
- )
- name = Column(String(50))
- addresses = relationship(
- "Address",
- order_by=Address.email,
- foreign_keys=Address.user_id,
- remote_side=Address.user_id,
- )
-
- # get the mapper for User. User mapper will compile,
- # "addresses" relationship will call upon Address.user_id for
- # its clause element. Address.user_id is a _CompileOnAttr,
- # which then calls class_mapper(Address). But ! We're already
- # "in compilation", but class_mapper(Address) needs to
- # initialize regardless, or COA's assertion fails and things
- # generally go downhill from there.
-
- class_mapper(User)
- Base.metadata.create_all()
- sess = create_session()
- u1 = User(
- name="ed",
- addresses=[
- Address(email="abc"),
- Address(email="xyz"),
- Address(email="def"),
- ],
- )
- sess.add(u1)
- sess.flush()
- sess.expunge_all()
- eq_(
- sess.query(User).filter(User.name == "ed").one(),
- User(
- name="ed",
- addresses=[
- Address(email="abc"),
- Address(email="def"),
- Address(email="xyz"),
- ],
- ),
- )
-
- def test_nice_dependency_error(self):
- class User(Base):
-
- __tablename__ = "users"
- id = Column("id", Integer, primary_key=True)
- addresses = relationship("Address")
-
- class Address(Base):
-
- __tablename__ = "addresses"
- id = Column(Integer, primary_key=True)
- foo = sa.orm.column_property(User.id == 5)
-
- # this used to raise an error when accessing User.id but that's
- # no longer the case since we got rid of _CompileOnAttr.
-
- assert_raises(sa.exc.ArgumentError, configure_mappers)
-
- def test_nice_dependency_error_works_with_hasattr(self):
- class User(Base):
-
- __tablename__ = "users"
- id = Column("id", Integer, primary_key=True)
- addresses = relationship("Address")
-
- # hasattr() on a compile-loaded attribute
- try:
- hasattr(User.addresses, "property")
- except exc.InvalidRequestError:
- assert sa.util.compat.py3k
-
- # the exception is preserved. Remains the
- # same through repeated calls.
- for i in range(3):
- assert_raises_message(
- sa.exc.InvalidRequestError,
- "^One or more mappers failed to initialize"
- " - can't proceed with initialization of other mappers. "
- r"Triggering mapper: 'mapped class User->users'. "
- "Original exception was: When initializing.*",
- configure_mappers,
- )
-
- def test_custom_base(self):
- class MyBase(object):
- def foobar(self):
- return "foobar"
-
- Base = decl.declarative_base(cls=MyBase)
- assert hasattr(Base, "metadata")
- assert Base().foobar() == "foobar"
-
- def test_uses_get_on_class_col_fk(self):
-
- # test [ticket:1492]
-
- class Master(Base):
-
- __tablename__ = "master"
- id = Column(
- Integer, primary_key=True, test_needs_autoincrement=True
- )
-
- class Detail(Base):
-
- __tablename__ = "detail"
- id = Column(
- Integer, primary_key=True, test_needs_autoincrement=True
- )
- master_id = Column(None, ForeignKey(Master.id))
- master = relationship(Master)
-
- Base.metadata.create_all()
- configure_mappers()
- assert class_mapper(Detail).get_property("master").strategy.use_get
- m1 = Master()
- d1 = Detail(master=m1)
- sess = create_session()
- sess.add(d1)
- sess.flush()
- sess.expunge_all()
- d1 = sess.query(Detail).first()
- m1 = sess.query(Master).first()
-
- def go():
- assert d1.master
-
- self.assert_sql_count(testing.db, go, 0)
-
- def test_index_doesnt_compile(self):
- class User(Base):
- __tablename__ = "users"
- id = Column("id", Integer, primary_key=True)
- name = Column("name", String(50))
- error = relationship("Address")
-
- i = Index("my_index", User.name)
-
- # compile fails due to the nonexistent Addresses relationship
- assert_raises(sa.exc.InvalidRequestError, configure_mappers)
-
- # index configured
- assert i in User.__table__.indexes
- assert User.__table__.c.id not in set(i.columns)
- assert User.__table__.c.name in set(i.columns)
-
- # tables create fine
- Base.metadata.create_all()
-
- def test_add_prop(self):
- class User(Base, fixtures.ComparableEntity):
-
- __tablename__ = "users"
- id = Column(
- "id", Integer, primary_key=True, test_needs_autoincrement=True
- )
-
- User.name = Column("name", String(50))
- User.addresses = relationship("Address", backref="user")
-
- class Address(Base, fixtures.ComparableEntity):
-
- __tablename__ = "addresses"
- id = Column(
- Integer, primary_key=True, test_needs_autoincrement=True
- )
-
- Address.email = Column(String(50), key="_email")
- Address.user_id = Column(
- "user_id", Integer, ForeignKey("users.id"), key="_user_id"
- )
- Base.metadata.create_all()
- eq_(Address.__table__.c["id"].name, "id")
- eq_(Address.__table__.c["_email"].name, "email")
- eq_(Address.__table__.c["_user_id"].name, "user_id")
- u1 = User(
- name="u1", addresses=[Address(email="one"), Address(email="two")]
- )
- sess = create_session()
- sess.add(u1)
- sess.flush()
- sess.expunge_all()
- eq_(
- sess.query(User).all(),
- [
- User(
- name="u1",
- addresses=[Address(email="one"), Address(email="two")],
- )
- ],
- )
- a1 = sess.query(Address).filter(Address.email == "two").one()
- eq_(a1, Address(email="two"))
- eq_(a1.user, User(name="u1"))
-
- def test_alt_name_attr_subclass_column_inline(self):
- # [ticket:2900]
- class A(Base):
- __tablename__ = "a"
- id = Column("id", Integer, primary_key=True)
- data = Column("data")
-
- class ASub(A):
- brap = A.data
-
- assert ASub.brap.property is A.data.property
- assert isinstance(
- ASub.brap.original_property, descriptor_props.SynonymProperty
- )
-
- def test_alt_name_attr_subclass_relationship_inline(self):
- # [ticket:2900]
- class A(Base):
- __tablename__ = "a"
- id = Column("id", Integer, primary_key=True)
- b_id = Column(Integer, ForeignKey("b.id"))
- b = relationship("B", backref="as_")
-
- class B(Base):
- __tablename__ = "b"
- id = Column("id", Integer, primary_key=True)
-
- configure_mappers()
-
- class ASub(A):
- brap = A.b
-
- assert ASub.brap.property is A.b.property
- assert isinstance(
- ASub.brap.original_property, descriptor_props.SynonymProperty
- )
- ASub(brap=B())
-
- def test_alt_name_attr_subclass_column_attrset(self):
- # [ticket:2900]
- class A(Base):
- __tablename__ = "a"
- id = Column("id", Integer, primary_key=True)
- data = Column("data")
-
- A.brap = A.data
- assert A.brap.property is A.data.property
- assert isinstance(
- A.brap.original_property, descriptor_props.SynonymProperty
- )
-
- def test_alt_name_attr_subclass_relationship_attrset(self):
- # [ticket:2900]
- class A(Base):
- __tablename__ = "a"
- id = Column("id", Integer, primary_key=True)
- b_id = Column(Integer, ForeignKey("b.id"))
- b = relationship("B", backref="as_")
-
- A.brap = A.b
-
- class B(Base):
- __tablename__ = "b"
- id = Column("id", Integer, primary_key=True)
-
- assert A.brap.property is A.b.property
- assert isinstance(
- A.brap.original_property, descriptor_props.SynonymProperty
- )
- A(brap=B())
-
- def test_eager_order_by(self):
- class Address(Base, fixtures.ComparableEntity):
-
- __tablename__ = "addresses"
- id = Column(
- "id", Integer, primary_key=True, test_needs_autoincrement=True
- )
- email = Column("email", String(50))
- user_id = Column("user_id", Integer, ForeignKey("users.id"))
-
- class User(Base, fixtures.ComparableEntity):
-
- __tablename__ = "users"
- id = Column(
- "id", Integer, primary_key=True, test_needs_autoincrement=True
- )
- name = Column("name", String(50))
- addresses = relationship("Address", order_by=Address.email)
-
- Base.metadata.create_all()
- u1 = User(
- name="u1", addresses=[Address(email="two"), Address(email="one")]
- )
- sess = create_session()
- sess.add(u1)
- sess.flush()
- sess.expunge_all()
- eq_(
- sess.query(User).options(joinedload(User.addresses)).all(),
- [
- User(
- name="u1",
- addresses=[Address(email="one"), Address(email="two")],
- )
- ],
- )
-
- def test_order_by_multi(self):
- class Address(Base, fixtures.ComparableEntity):
-
- __tablename__ = "addresses"
- id = Column(
- "id", Integer, primary_key=True, test_needs_autoincrement=True
- )
- email = Column("email", String(50))
- user_id = Column("user_id", Integer, ForeignKey("users.id"))
-
- class User(Base, fixtures.ComparableEntity):
-
- __tablename__ = "users"
- id = Column(
- "id", Integer, primary_key=True, test_needs_autoincrement=True
- )
- name = Column("name", String(50))
- addresses = relationship(
- "Address", order_by=(Address.email, Address.id)
- )
-
- Base.metadata.create_all()
- u1 = User(
- name="u1", addresses=[Address(email="two"), Address(email="one")]
- )
- sess = create_session()
- sess.add(u1)
- sess.flush()
- sess.expunge_all()
- u = sess.query(User).filter(User.name == "u1").one()
- u.addresses
-
- def test_as_declarative(self):
- class User(fixtures.ComparableEntity):
-
- __tablename__ = "users"
- id = Column(
- "id", Integer, primary_key=True, test_needs_autoincrement=True
- )
- name = Column("name", String(50))
- addresses = relationship("Address", backref="user")
-
- class Address(fixtures.ComparableEntity):
-
- __tablename__ = "addresses"
- id = Column(
- "id", Integer, primary_key=True, test_needs_autoincrement=True
- )
- email = Column("email", String(50))
- user_id = Column("user_id", Integer, ForeignKey("users.id"))
-
- reg = {}
- decl.instrument_declarative(User, reg, Base.metadata)
- decl.instrument_declarative(Address, reg, Base.metadata)
- Base.metadata.create_all()
- u1 = User(
- name="u1", addresses=[Address(email="one"), Address(email="two")]
- )
- sess = create_session()
- sess.add(u1)
- sess.flush()
- sess.expunge_all()
- eq_(
- sess.query(User).all(),
- [
- User(
- name="u1",
- addresses=[Address(email="one"), Address(email="two")],
- )
- ],
- )
-
- def test_custom_mapper_attribute(self):
- def mymapper(cls, tbl, **kwargs):
- m = sa.orm.mapper(cls, tbl, **kwargs)
- m.CHECK = True
- return m
-
- base = decl.declarative_base()
-
- class Foo(base):
- __tablename__ = "foo"
- __mapper_cls__ = mymapper
- id = Column(Integer, primary_key=True)
-
- eq_(Foo.__mapper__.CHECK, True)
-
- def test_custom_mapper_argument(self):
- def mymapper(cls, tbl, **kwargs):
- m = sa.orm.mapper(cls, tbl, **kwargs)
- m.CHECK = True
- return m
-
- base = decl.declarative_base(mapper=mymapper)
-
- class Foo(base):
- __tablename__ = "foo"
- id = Column(Integer, primary_key=True)
-
- eq_(Foo.__mapper__.CHECK, True)
-
- def test_no_change_to_all_descriptors(self):
- base = decl.declarative_base()
-
- class Foo(base):
- __tablename__ = "foo"
- id = Column(Integer, primary_key=True)
-
- eq_(Foo.__mapper__.all_orm_descriptors.keys(), ["id"])
-
- def test_oops(self):
-
- with testing.expect_warnings(
- "Ignoring declarative-like tuple value of " "attribute 'name'"
- ):
-
- class User(Base, fixtures.ComparableEntity):
-
- __tablename__ = "users"
- id = Column("id", Integer, primary_key=True)
- name = (Column("name", String(50)),)
-
- def test_table_args_no_dict(self):
- class Foo1(Base):
-
- __tablename__ = "foo"
- __table_args__ = (ForeignKeyConstraint(["id"], ["foo.bar"]),)
- id = Column("id", Integer, primary_key=True)
- bar = Column("bar", Integer)
-
- assert Foo1.__table__.c.id.references(Foo1.__table__.c.bar)
-
- def test_table_args_type(self):
- def err():
- class Foo1(Base):
-
- __tablename__ = "foo"
- __table_args__ = ForeignKeyConstraint(["id"], ["foo.id"])
- id = Column("id", Integer, primary_key=True)
-
- assert_raises_message(
- sa.exc.ArgumentError, "__table_args__ value must be a tuple, ", err
- )
-
- def test_table_args_none(self):
- class Foo2(Base):
-
- __tablename__ = "foo"
- __table_args__ = None
- id = Column("id", Integer, primary_key=True)
-
- assert Foo2.__table__.kwargs == {}
-
- def test_table_args_dict_format(self):
- class Foo2(Base):
-
- __tablename__ = "foo"
- __table_args__ = {"mysql_engine": "InnoDB"}
- id = Column("id", Integer, primary_key=True)
-
- assert Foo2.__table__.kwargs["mysql_engine"] == "InnoDB"
-
- def test_table_args_tuple_format(self):
- class Foo2(Base):
-
- __tablename__ = "foo"
- __table_args__ = {"mysql_engine": "InnoDB"}
- id = Column("id", Integer, primary_key=True)
-
- class Bar(Base):
-
- __tablename__ = "bar"
- __table_args__ = (
- ForeignKeyConstraint(["id"], ["foo.id"]),
- {"mysql_engine": "InnoDB"},
- )
- id = Column("id", Integer, primary_key=True)
-
- assert Bar.__table__.c.id.references(Foo2.__table__.c.id)
- assert Bar.__table__.kwargs["mysql_engine"] == "InnoDB"
-
- def test_table_cls_attribute(self):
- class Foo(Base):
- __tablename__ = "foo"
-
- @classmethod
- def __table_cls__(cls, *arg, **kw):
- name = arg[0]
- return Table(name + "bat", *arg[1:], **kw)
-
- id = Column(Integer, primary_key=True)
-
- eq_(Foo.__table__.name, "foobat")
-
- def test_table_cls_attribute_return_none(self):
- from sqlalchemy.schema import Column, PrimaryKeyConstraint
-
- class AutoTable(object):
- @declared_attr
- def __tablename__(cls):
- return cls.__name__
-
- @classmethod
- def __table_cls__(cls, *arg, **kw):
- for obj in arg[1:]:
- if (
- isinstance(obj, Column) and obj.primary_key
- ) or isinstance(obj, PrimaryKeyConstraint):
- return Table(*arg, **kw)
-
- return None
-
- class Person(AutoTable, Base):
- id = Column(Integer, primary_key=True)
-
- class Employee(Person):
- employee_name = Column(String)
-
- is_(inspect(Employee).local_table, Person.__table__)
-
- def test_expression(self):
- class User(Base, fixtures.ComparableEntity):
-
- __tablename__ = "users"
- id = Column(
- "id", Integer, primary_key=True, test_needs_autoincrement=True
- )
- name = Column("name", String(50))
- addresses = relationship("Address", backref="user")
-
- class Address(Base, fixtures.ComparableEntity):
-
- __tablename__ = "addresses"
- id = Column(
- "id", Integer, primary_key=True, test_needs_autoincrement=True
- )
- email = Column("email", String(50))
- user_id = Column("user_id", Integer, ForeignKey("users.id"))
-
- User.address_count = sa.orm.column_property(
- sa.select(sa.func.count(Address.id))
- .where(Address.user_id == User.id)
- .scalar_subquery()
- )
- Base.metadata.create_all()
- u1 = User(
- name="u1", addresses=[Address(email="one"), Address(email="two")]
- )
- sess = create_session()
- sess.add(u1)
- sess.flush()
- sess.expunge_all()
- eq_(
- sess.query(User).all(),
- [
- User(
- name="u1",
- address_count=2,
- addresses=[Address(email="one"), Address(email="two")],
- )
- ],
- )
-
- def test_useless_declared_attr(self):
- class Address(Base, fixtures.ComparableEntity):
-
- __tablename__ = "addresses"
- id = Column(
- "id", Integer, primary_key=True, test_needs_autoincrement=True
- )
- email = Column("email", String(50))
- user_id = Column("user_id", Integer, ForeignKey("users.id"))
-
- class User(Base, fixtures.ComparableEntity):
-
- __tablename__ = "users"
- id = Column(
- "id", Integer, primary_key=True, test_needs_autoincrement=True
- )
- name = Column("name", String(50))
- addresses = relationship("Address", backref="user")
-
- @declared_attr
- def address_count(cls):
- # this doesn't really gain us anything. but if
- # one is used, lets have it function as expected...
- return sa.orm.column_property(
- sa.select(sa.func.count(Address.id))
- .where(Address.user_id == cls.id)
- .scalar_subquery()
- )
-
- Base.metadata.create_all()
- u1 = User(
- name="u1", addresses=[Address(email="one"), Address(email="two")]
- )
- sess = create_session()
- sess.add(u1)
- sess.flush()
- sess.expunge_all()
- eq_(
- sess.query(User).all(),
- [
- User(
- name="u1",
- address_count=2,
- addresses=[Address(email="one"), Address(email="two")],
- )
- ],
- )
-
- def test_declared_on_base_class(self):
- class MyBase(Base):
- __tablename__ = "foo"
- id = Column(Integer, primary_key=True)
-
- @declared_attr
- def somecol(cls):
- return Column(Integer)
-
- class MyClass(MyBase):
- __tablename__ = "bar"
- id = Column(Integer, ForeignKey("foo.id"), primary_key=True)
-
- # previously, the 'somecol' declared_attr would be ignored
- # by the mapping and would remain unused. now we take
- # it as part of MyBase.
-
- assert "somecol" in MyBase.__table__.c
- assert "somecol" not in MyClass.__table__.c
-
- def test_decl_cascading_warns_non_mixin(self):
- with expect_warnings(
- "Use of @declared_attr.cascading only applies to "
- "Declarative 'mixin' and 'abstract' classes. "
- "Currently, this flag is ignored on mapped class "
- "<class '.*.MyBase'>"
- ):
-
- class MyBase(Base):
- __tablename__ = "foo"
- id = Column(Integer, primary_key=True)
-
- @declared_attr.cascading
- def somecol(cls):
- return Column(Integer)
-
- def test_column(self):
- class User(Base, fixtures.ComparableEntity):
-
- __tablename__ = "users"
- id = Column(
- "id", Integer, primary_key=True, test_needs_autoincrement=True
- )
- name = Column("name", String(50))
-
- User.a = Column("a", String(10))
- User.b = Column(String(10))
- Base.metadata.create_all()
- u1 = User(name="u1", a="a", b="b")
- eq_(u1.a, "a")
- eq_(User.a.get_history(u1), (["a"], (), ()))
- sess = create_session()
- sess.add(u1)
- sess.flush()
- sess.expunge_all()
- eq_(sess.query(User).all(), [User(name="u1", a="a", b="b")])
-
- def test_column_properties(self):
- class Address(Base, fixtures.ComparableEntity):
-
- __tablename__ = "addresses"
- id = Column(
- Integer, primary_key=True, test_needs_autoincrement=True
- )
- email = Column(String(50))
- user_id = Column(Integer, ForeignKey("users.id"))
-
- class User(Base, fixtures.ComparableEntity):
-
- __tablename__ = "users"
- id = Column(
- "id", Integer, primary_key=True, test_needs_autoincrement=True
- )
- name = Column("name", String(50))
-
- adr_count = sa.orm.column_property(
- sa.select(sa.func.count(Address.id))
- .where(Address.user_id == id)
- .scalar_subquery()
- )
- addresses = relationship(Address)
-
- Base.metadata.create_all()
- u1 = User(
- name="u1", addresses=[Address(email="one"), Address(email="two")]
- )
- sess = create_session()
- sess.add(u1)
- sess.flush()
- sess.expunge_all()
- eq_(
- sess.query(User).all(),
- [
- User(
- name="u1",
- adr_count=2,
- addresses=[Address(email="one"), Address(email="two")],
- )
- ],
- )
-
- def test_column_properties_2(self):
- class Address(Base, fixtures.ComparableEntity):
-
- __tablename__ = "addresses"
- id = Column(Integer, primary_key=True)
- email = Column(String(50))
- user_id = Column(Integer, ForeignKey("users.id"))
-
- class User(Base, fixtures.ComparableEntity):
-
- __tablename__ = "users"
- id = Column("id", Integer, primary_key=True)
- name = Column("name", String(50))
-
- # this is not "valid" but we want to test that Address.id
- # doesn't get stuck into user's table
-
- adr_count = Address.id
-
- eq_(set(User.__table__.c.keys()), set(["id", "name"]))
- eq_(set(Address.__table__.c.keys()), set(["id", "email", "user_id"]))
-
- def test_deferred(self):
- class User(Base, fixtures.ComparableEntity):
-
- __tablename__ = "users"
- id = Column(
- Integer, primary_key=True, test_needs_autoincrement=True
- )
- name = sa.orm.deferred(Column(String(50)))
-
- Base.metadata.create_all()
- sess = create_session()
- sess.add(User(name="u1"))
- sess.flush()
- sess.expunge_all()
- u1 = sess.query(User).filter(User.name == "u1").one()
- assert "name" not in u1.__dict__
-
- def go():
- eq_(u1.name, "u1")
-
- self.assert_sql_count(testing.db, go, 1)
-
- def test_composite_inline(self):
- class AddressComposite(fixtures.ComparableEntity):
- def __init__(self, street, state):
- self.street = street
- self.state = state
-
- def __composite_values__(self):
- return [self.street, self.state]
-
- class User(Base, fixtures.ComparableEntity):
- __tablename__ = "user"
- id = Column(
- Integer, primary_key=True, test_needs_autoincrement=True
- )
- address = composite(
- AddressComposite,
- Column("street", String(50)),
- Column("state", String(2)),
- )
-
- Base.metadata.create_all()
- sess = Session()
- sess.add(User(address=AddressComposite("123 anywhere street", "MD")))
- sess.commit()
- eq_(
- sess.query(User).all(),
- [User(address=AddressComposite("123 anywhere street", "MD"))],
- )
-
- def test_composite_separate(self):
- class AddressComposite(fixtures.ComparableEntity):
- def __init__(self, street, state):
- self.street = street
- self.state = state
-
- def __composite_values__(self):
- return [self.street, self.state]
-
- class User(Base, fixtures.ComparableEntity):
- __tablename__ = "user"
- id = Column(
- Integer, primary_key=True, test_needs_autoincrement=True
- )
- street = Column(String(50))
- state = Column(String(2))
- address = composite(AddressComposite, street, state)
-
- Base.metadata.create_all()
- sess = Session()
- sess.add(User(address=AddressComposite("123 anywhere street", "MD")))
- sess.commit()
- eq_(
- sess.query(User).all(),
- [User(address=AddressComposite("123 anywhere street", "MD"))],
- )
-
- def test_mapping_to_join(self):
- users = Table(
- "users", Base.metadata, Column("id", Integer, primary_key=True)
- )
- addresses = Table(
- "addresses",
- Base.metadata,
- Column("id", Integer, primary_key=True),
- Column("user_id", Integer, ForeignKey("users.id")),
- )
- usersaddresses = sa.join(
- users, addresses, users.c.id == addresses.c.user_id
- )
-
- class User(Base):
- __table__ = usersaddresses
- __table_args__ = {"primary_key": [users.c.id]}
-
- # need to use column_property for now
- user_id = column_property(users.c.id, addresses.c.user_id)
- address_id = addresses.c.id
-
- assert User.__mapper__.get_property("user_id").columns[0] is users.c.id
- assert (
- User.__mapper__.get_property("user_id").columns[1]
- is addresses.c.user_id
- )
-
- def test_synonym_inline(self):
- class User(Base, fixtures.ComparableEntity):
-
- __tablename__ = "users"
- id = Column(
- "id", Integer, primary_key=True, test_needs_autoincrement=True
- )
- _name = Column("name", String(50))
-
- def _set_name(self, name):
- self._name = "SOMENAME " + name
-
- def _get_name(self):
- return self._name
-
- name = sa.orm.synonym(
- "_name", descriptor=property(_get_name, _set_name)
- )
-
- Base.metadata.create_all()
- sess = create_session()
- u1 = User(name="someuser")
- eq_(u1.name, "SOMENAME someuser")
- sess.add(u1)
- sess.flush()
- eq_(
- sess.query(User).filter(User.name == "SOMENAME someuser").one(), u1
- )
-
- def test_synonym_no_descriptor(self):
- from sqlalchemy.orm.properties import ColumnProperty
-
- class CustomCompare(ColumnProperty.Comparator):
-
- __hash__ = None
-
- def __eq__(self, other):
- return self.__clause_element__() == other + " FOO"
-
- class User(Base, fixtures.ComparableEntity):
-
- __tablename__ = "users"
- id = Column(
- "id", Integer, primary_key=True, test_needs_autoincrement=True
- )
- _name = Column("name", String(50))
- name = sa.orm.synonym("_name", comparator_factory=CustomCompare)
-
- Base.metadata.create_all()
- sess = create_session()
- u1 = User(name="someuser FOO")
- sess.add(u1)
- sess.flush()
- eq_(sess.query(User).filter(User.name == "someuser").one(), u1)
-
- def test_synonym_added(self):
- class User(Base, fixtures.ComparableEntity):
-
- __tablename__ = "users"
- id = Column(
- "id", Integer, primary_key=True, test_needs_autoincrement=True
- )
- _name = Column("name", String(50))
-
- def _set_name(self, name):
- self._name = "SOMENAME " + name
-
- def _get_name(self):
- return self._name
-
- name = property(_get_name, _set_name)
-
- User.name = sa.orm.synonym("_name", descriptor=User.name)
- Base.metadata.create_all()
- sess = create_session()
- u1 = User(name="someuser")
- eq_(u1.name, "SOMENAME someuser")
- sess.add(u1)
- sess.flush()
- eq_(
- sess.query(User).filter(User.name == "SOMENAME someuser").one(), u1
- )
-
- def test_reentrant_compile_via_foreignkey(self):
- class User(Base, fixtures.ComparableEntity):
-
- __tablename__ = "users"
- id = Column(
- "id", Integer, primary_key=True, test_needs_autoincrement=True
- )
- name = Column("name", String(50))
- addresses = relationship("Address", backref="user")
-
- class Address(Base, fixtures.ComparableEntity):
-
- __tablename__ = "addresses"
- id = Column(
- "id", Integer, primary_key=True, test_needs_autoincrement=True
- )
- email = Column("email", String(50))
- user_id = Column("user_id", Integer, ForeignKey(User.id))
-
- # previous versions would force a re-entrant mapper compile via
- # the User.id inside the ForeignKey but this is no longer the
- # case
-
- sa.orm.configure_mappers()
- eq_(
- list(Address.user_id.property.columns[0].foreign_keys)[0].column,
- User.__table__.c.id,
- )
- Base.metadata.create_all()
- u1 = User(
- name="u1", addresses=[Address(email="one"), Address(email="two")]
- )
- sess = create_session()
- sess.add(u1)
- sess.flush()
- sess.expunge_all()
- eq_(
- sess.query(User).all(),
- [
- User(
- name="u1",
- addresses=[Address(email="one"), Address(email="two")],
- )
- ],
- )
-
- def test_relationship_reference(self):
- class Address(Base, fixtures.ComparableEntity):
-
- __tablename__ = "addresses"
- id = Column(
- "id", Integer, primary_key=True, test_needs_autoincrement=True
- )
- email = Column("email", String(50))
- user_id = Column("user_id", Integer, ForeignKey("users.id"))
-
- class User(Base, fixtures.ComparableEntity):
-
- __tablename__ = "users"
- id = Column(
- "id", Integer, primary_key=True, test_needs_autoincrement=True
- )
- name = Column("name", String(50))
- addresses = relationship(
- "Address", backref="user", primaryjoin=id == Address.user_id
- )
-
- User.address_count = sa.orm.column_property(
- sa.select(sa.func.count(Address.id))
- .where(Address.user_id == User.id)
- .scalar_subquery()
- )
- Base.metadata.create_all()
- u1 = User(
- name="u1", addresses=[Address(email="one"), Address(email="two")]
- )
- sess = create_session()
- sess.add(u1)
- sess.flush()
- sess.expunge_all()
- eq_(
- sess.query(User).all(),
- [
- User(
- name="u1",
- address_count=2,
- addresses=[Address(email="one"), Address(email="two")],
- )
- ],
- )
-
- def test_pk_with_fk_init(self):
- class Bar(Base):
-
- __tablename__ = "bar"
- id = sa.Column(
- sa.Integer, sa.ForeignKey("foo.id"), primary_key=True
- )
- ex = sa.Column(sa.Integer, primary_key=True)
-
- class Foo(Base):
-
- __tablename__ = "foo"
- id = sa.Column(sa.Integer, primary_key=True)
- bars = sa.orm.relationship(Bar)
-
- assert Bar.__mapper__.primary_key[0] is Bar.__table__.c.id
- assert Bar.__mapper__.primary_key[1] is Bar.__table__.c.ex
-
- def test_with_explicit_autoloaded(self):
- meta = MetaData(testing.db)
- t1 = Table(
- "t1",
- meta,
- Column("id", String(50), primary_key=True),
- Column("data", String(50)),
- )
- meta.create_all()
- try:
-
- class MyObj(Base):
-
- __table__ = Table("t1", Base.metadata, autoload=True)
-
- sess = create_session()
- m = MyObj(id="someid", data="somedata")
- sess.add(m)
- sess.flush()
- eq_(t1.select().execute().fetchall(), [("someid", "somedata")])
- finally:
- meta.drop_all()
-
- def test_synonym_for(self):
- class User(Base, fixtures.ComparableEntity):
-
- __tablename__ = "users"
- id = Column(
- "id", Integer, primary_key=True, test_needs_autoincrement=True
- )
- name = Column("name", String(50))
-
- @decl.synonym_for("name")
- @property
- def namesyn(self):
- return self.name
-
- Base.metadata.create_all()
- sess = create_session()
- u1 = User(name="someuser")
- eq_(u1.name, "someuser")
- eq_(u1.namesyn, "someuser")
- sess.add(u1)
- sess.flush()
- rt = sess.query(User).filter(User.namesyn == "someuser").one()
- eq_(rt, u1)
-
- def test_duplicate_classes_in_base(self):
- class Test(Base):
- __tablename__ = "a"
- id = Column(Integer, primary_key=True)
-
- assert_raises_message(
- sa.exc.SAWarning,
- "This declarative base already contains a class with ",
- lambda: type(Base)(
- "Test",
- (Base,),
- dict(__tablename__="b", id=Column(Integer, primary_key=True)),
- ),
- )
-
- @testing.teardown_events(MapperEvents)
- def test_instrument_class_before_instrumentation(self):
- # test #3388
-
- canary = mock.Mock()
-
- @event.listens_for(mapper, "instrument_class")
- def instrument_class(mp, cls):
- canary.instrument_class(mp, cls)
-
- @event.listens_for(object, "class_instrument")
- def class_instrument(cls):
- canary.class_instrument(cls)
-
- class Test(Base):
- __tablename__ = "test"
- id = Column(Integer, primary_key=True)
-
- eq_(
- canary.mock_calls,
- [
- mock.call.instrument_class(Test.__mapper__, Test),
- mock.call.class_instrument(Test),
- ],
- )
-
- def test_cls_docstring(self):
- class MyBase(object):
- """MyBase Docstring"""
-
- Base = decl.declarative_base(cls=MyBase)
-
- eq_(Base.__doc__, MyBase.__doc__)
-
- def test_delattr_mapped_raises(self):
- Base = decl.declarative_base()
-
- class Foo(Base):
- __tablename__ = "foo"
-
- id = Column(Integer, primary_key=True)
- data = Column(String)
-
- def go():
- del Foo.data
-
- assert_raises_message(
- NotImplementedError,
- "Can't un-map individual mapped attributes on a mapped class.",
- go,
- )
-
- def test_delattr_hybrid_fine(self):
- Base = decl.declarative_base()
-
- class Foo(Base):
- __tablename__ = "foo"
-
- id = Column(Integer, primary_key=True)
- data = Column(String)
-
- @hybrid_property
- def data_hybrid(self):
- return self.data
-
- assert "data_hybrid" in Foo.__mapper__.all_orm_descriptors.keys()
-
- del Foo.data_hybrid
-
- assert "data_hybrid" not in Foo.__mapper__.all_orm_descriptors.keys()
-
- assert not hasattr(Foo, "data_hybrid")
-
- def test_setattr_hybrid_updates_descriptors(self):
- Base = decl.declarative_base()
-
- class Foo(Base):
- __tablename__ = "foo"
-
- id = Column(Integer, primary_key=True)
- data = Column(String)
-
- assert "data_hybrid" not in Foo.__mapper__.all_orm_descriptors.keys()
-
- @hybrid_property
- def data_hybrid(self):
- return self.data
-
- Foo.data_hybrid = data_hybrid
- assert "data_hybrid" in Foo.__mapper__.all_orm_descriptors.keys()
-
- del Foo.data_hybrid
-
- assert "data_hybrid" not in Foo.__mapper__.all_orm_descriptors.keys()
-
- assert not hasattr(Foo, "data_hybrid")
-
- @testing.requires.python36
- def test_kw_support_in_declarative_meta_init(self):
- # This will not fail if DeclarativeMeta __init__ supports **kw
-
- class BaseUser(Base):
- __tablename__ = "base"
- id_ = Column(Integer, primary_key=True)
-
- @classmethod
- def __init_subclass__(cls, random_keyword=False, **kw):
- super().__init_subclass__(**kw)
- cls._set_random_keyword_used_here = random_keyword
-
- class User(BaseUser):
- __tablename__ = "user"
- id_ = Column(Integer, ForeignKey("base.id_"), primary_key=True)
-
- # Check the default option
- eq_(User._set_random_keyword_used_here, False)
-
- # Build the metaclass with a keyword!
- bases = (BaseUser,)
- UserType = DeclarativeMeta("UserType", bases, {}, random_keyword=True)
-
- # Check to see if __init_subclass__ works in supported versions
- eq_(UserType._set_random_keyword_used_here, True)
-
-
-def _produce_test(inline, stringbased):
- class ExplicitJoinTest(fixtures.MappedTest):
- @classmethod
- def define_tables(cls, metadata):
- global User, Address
- Base = decl.declarative_base(metadata=metadata)
-
- class User(Base, fixtures.ComparableEntity):
-
- __tablename__ = "users"
- id = Column(
- Integer, primary_key=True, test_needs_autoincrement=True
- )
- name = Column(String(50))
-
- class Address(Base, fixtures.ComparableEntity):
-
- __tablename__ = "addresses"
- id = Column(
- Integer, primary_key=True, test_needs_autoincrement=True
- )
- email = Column(String(50))
- user_id = Column(Integer, ForeignKey("users.id"))
- if inline:
- if stringbased:
- user = relationship(
- "User",
- primaryjoin="User.id==Address.user_id",
- backref="addresses",
- )
- else:
- user = relationship(
- User,
- primaryjoin=User.id == user_id,
- backref="addresses",
- )
-
- if not inline:
- configure_mappers()
- if stringbased:
- Address.user = relationship(
- "User",
- primaryjoin="User.id==Address.user_id",
- backref="addresses",
- )
- else:
- Address.user = relationship(
- User,
- primaryjoin=User.id == Address.user_id,
- backref="addresses",
- )
-
- @classmethod
- def insert_data(cls, connection):
- params = [
- dict(list(zip(("id", "name"), column_values)))
- for column_values in [
- (7, "jack"),
- (8, "ed"),
- (9, "fred"),
- (10, "chuck"),
- ]
- ]
-
- connection.execute(User.__table__.insert(), params)
- connection.execute(
- Address.__table__.insert(),
- [
- dict(list(zip(("id", "user_id", "email"), column_values)))
- for column_values in [
- (1, 7, "jack@bean.com"),
- (2, 8, "ed@wood.com"),
- (3, 8, "ed@bettyboop.com"),
- (4, 8, "ed@lala.com"),
- (5, 9, "fred@fred.com"),
- ]
- ],
- )
-
- def test_aliased_join(self):
-
- # this query will screw up if the aliasing enabled in
- # query.join() gets applied to the right half of the join
- # condition inside the any(). the join condition inside of
- # any() comes from the "primaryjoin" of the relationship,
- # and should not be annotated with _orm_adapt.
- # PropertyLoader.Comparator will annotate the left side with
- # _orm_adapt, though.
-
- sess = create_session()
- eq_(
- sess.query(User)
- .join(User.addresses, aliased=True)
- .filter(Address.email == "ed@wood.com")
- .filter(User.addresses.any(Address.email == "jack@bean.com"))
- .all(),
- [],
- )
-
- ExplicitJoinTest.__name__ = "ExplicitJoinTest%s%s" % (
- inline and "Inline" or "Separate",
- stringbased and "String" or "Literal",
- )
- return ExplicitJoinTest
-
-
-for inline in True, False:
- for stringbased in True, False:
- testclass = _produce_test(inline, stringbased)
- exec("%s = testclass" % testclass.__name__)
- del testclass