def test_nonpoly_oftype_subclass(self): Company = _poly_fixtures.Company Person = _poly_fixtures.Person Engineer = _poly_fixtures.Engineer emapper = inspect(Engineer) cmapper = inspect(Company) pmapper = inspect(Person) p1 = PathRegistry.coerce( ( cmapper, cmapper.attrs.employees, emapper, emapper.attrs.paperwork, ) ) eq_( p1.path, ( cmapper, cmapper.attrs.employees, pmapper, pmapper.attrs.paperwork, ), ) eq_( p1.natural_path, ( cmapper, cmapper.attrs.employees, pmapper, pmapper.attrs.paperwork, ), )
def test_length(self): umapper = inspect(self.classes.User) amapper = inspect(self.classes.Address) pneg1 = PathRegistry.coerce(()) p0 = PathRegistry.coerce((umapper,)) p1 = PathRegistry.coerce((umapper, umapper.attrs.addresses)) p2 = PathRegistry.coerce((umapper, umapper.attrs.addresses, amapper)) p3 = PathRegistry.coerce( ( umapper, umapper.attrs.addresses, amapper, amapper.attrs.email_address, ) ) eq_(len(pneg1), 0) eq_(len(p0), 1) eq_(len(p1), 2) eq_(len(p2), 3) eq_(len(p3), 4) eq_(pneg1.length, 0) eq_(p0.length, 1) eq_(p1.length, 2) eq_(p2.length, 3) eq_(p3.length, 4)
def test_serialize_context_dict(self): reg = util.OrderedDict() umapper = inspect(self.classes.User) amapper = inspect(self.classes.Address) p1 = PathRegistry.coerce((umapper, umapper.attrs.addresses)) p2 = PathRegistry.coerce((umapper, umapper.attrs.addresses, amapper)) p3 = PathRegistry.coerce((amapper, amapper.attrs.email_address)) p1.set(reg, "p1key", "p1value") p2.set(reg, "p2key", "p2value") p3.set(reg, "p3key", "p3value") eq_( reg, { ("p1key", p1.path): "p1value", ("p2key", p2.path): "p2value", ("p3key", p3.path): "p3value", }, ) serialized = PathRegistry.serialize_context_dict( reg, ("p1key", "p2key") ) eq_( serialized, [ (("p1key", p1.serialize()), "p1value"), (("p2key", p2.serialize()), "p2value"), ], )
def test_plain_aliased_compound(self): Company = _poly_fixtures.Company Person = _poly_fixtures.Person Engineer = _poly_fixtures.Engineer cmapper = inspect(Company) emapper = inspect(Engineer) c_alias = aliased(Company) p_alias = aliased(Person) c_alias = inspect(c_alias) p_alias = inspect(p_alias) p1 = PathRegistry.coerce( (c_alias, cmapper.attrs.employees, p_alias, emapper.attrs.machines) ) # plain AliasedClass - the path keeps that AliasedClass directly # as is in the path eq_( p1.path, ( c_alias, cmapper.attrs.employees, p_alias, emapper.attrs.machines, ), )
def test_info(self): A = self._fixture() inspect(A).all_orm_descriptors.value.info["some key"] = "some value" eq_( inspect(A).all_orm_descriptors.value.info, {"some key": "some value"}, )
def test_eq(self): umapper = inspect(self.classes.User) amapper = inspect(self.classes.Address) u_alias = inspect(aliased(self.classes.User)) p1 = PathRegistry.coerce((umapper, umapper.attrs.addresses)) p2 = PathRegistry.coerce((umapper, umapper.attrs.addresses)) p3 = PathRegistry.coerce((umapper, umapper.attrs.name)) p4 = PathRegistry.coerce((u_alias, umapper.attrs.addresses)) p5 = PathRegistry.coerce((umapper, umapper.attrs.addresses, amapper)) p6 = PathRegistry.coerce( (amapper, amapper.attrs.user, umapper, umapper.attrs.addresses) ) p7 = PathRegistry.coerce( ( amapper, amapper.attrs.user, umapper, umapper.attrs.addresses, amapper, amapper.attrs.email_address, ) ) is_(p1 == p2, True) is_(p1 == p3, False) is_(p1 == p4, False) is_(p1 == p5, False) is_(p6 == p7, False) is_(p6 == p7.parent.parent, True) is_(p1 != p2, False) is_(p1 != p3, True) is_(p1 != p4, True) is_(p1 != p5, True)
def test_attrs_props_prop_added_after_configure(self): class Thing(InspectionAttr): pass class AnonClass(object): __foo__ = "bar" __bat__ = Thing() from sqlalchemy_1_3.orm import mapper, column_property from sqlalchemy_1_3.ext.hybrid import hybrid_property m = mapper(AnonClass, self.tables.users) eq_(set(inspect(AnonClass).attrs.keys()), set(["id", "name"])) eq_( set(inspect(AnonClass).all_orm_descriptors.keys()), set(["id", "name"]), ) m.add_property("q", column_property(self.tables.users.c.name)) def desc(self): return self.name AnonClass.foob = hybrid_property(desc) eq_(set(inspect(AnonClass).attrs.keys()), set(["id", "name", "q"])) eq_( set(inspect(AnonClass).all_orm_descriptors.keys()), set(["id", "name", "q", "foob"]), )
def test_deseralize(self): User = self.classes.User Address = self.classes.Address umapper = inspect(self.classes.User) amapper = inspect(self.classes.Address) p1 = PathRegistry.coerce( ( umapper, umapper.attrs.addresses, amapper, amapper.attrs.email_address, ) ) p2 = PathRegistry.coerce((umapper, umapper.attrs.addresses, amapper)) p3 = PathRegistry.coerce((umapper, umapper.attrs.addresses)) eq_( PathRegistry.deserialize( [(User, "addresses"), (Address, "email_address")] ), p1, ) eq_( PathRegistry.deserialize([(User, "addresses"), (Address, None)]), p2, ) eq_(PathRegistry.deserialize([(User, "addresses")]), p3)
def test_aliased_class(self): Address = self.classes.Address ualias = aliased(Address) insp = inspect(ualias) is_(insp.mapper, inspect(Address)) is_(insp.selectable, ualias._aliased_insp.selectable) assert not insp.is_selectable assert insp.is_aliased_class
def test_with_poly_sub(self): Company = _poly_fixtures.Company Person = _poly_fixtures.Person Engineer = _poly_fixtures.Engineer emapper = inspect(Engineer) cmapper = inspect(Company) p_poly = with_polymorphic(Person, [Engineer]) e_poly_insp = inspect(p_poly.Engineer) # noqa - used by comment below p_poly_insp = inspect(p_poly) p1 = PathRegistry.coerce((p_poly_insp, emapper.attrs.machines)) # changes as of #5082: when a with_polymorphic is in the middle # of a path, the natural path makes sure it uses the base mappers, # however when it's at the root, the with_polymorphic stays in # the natural path # this behavior is the same as pre #5082, it was temporarily changed # but this proved to be incorrect. The path starts on a # with_polymorphic(), so a Query will "naturally" construct a path # that comes from that wp. eq_(p1.path, (e_poly_insp, emapper.attrs.machines)) eq_(p1.natural_path, (e_poly_insp, emapper.attrs.machines)) # this behavior is new as of the final version of #5082. # the path starts on a normal entity and has a with_polymorphic # in the middle, for this to match what Query will generate it needs # to use the non aliased mappers in the natural path. p2 = PathRegistry.coerce( ( cmapper, cmapper.attrs.employees, p_poly_insp, emapper.attrs.machines, ) ) eq_( p2.path, ( cmapper, cmapper.attrs.employees, e_poly_insp, emapper.attrs.machines, ), ) eq_( p2.natural_path, ( cmapper, cmapper.attrs.employees, emapper, emapper.attrs.machines, ), )
def test_is_instance(self): User = self.classes.User u1 = User(name="ed") insp = inspect(u1) assert insp.is_instance insp = inspect(User) assert not insp.is_instance insp = inspect(aliased(User)) assert not insp.is_instance
def test_plain(self): Person = _poly_fixtures.Person Engineer = _poly_fixtures.Engineer pmapper = inspect(Person) emapper = inspect(Engineer) p1 = PathRegistry.coerce((pmapper, emapper.attrs.machines)) # given a mapper and an attribute on a subclass, # the path converts what you get to be against that subclass eq_(p1.path, (emapper, emapper.attrs.machines))
def test_path(self): umapper = inspect(self.classes.User) amapper = inspect(self.classes.Address) p1 = PathRegistry.coerce((umapper, umapper.attrs.addresses)) p2 = PathRegistry.coerce((umapper, umapper.attrs.addresses, amapper)) p3 = PathRegistry.coerce((amapper, amapper.attrs.email_address)) eq_(p1.path, (umapper, umapper.attrs.addresses)) eq_(p2.path, (umapper, umapper.attrs.addresses, amapper)) eq_(p3.path, (amapper, amapper.attrs.email_address))
def test_plain_aliased(self): Person = _poly_fixtures.Person Engineer = _poly_fixtures.Engineer emapper = inspect(Engineer) p_alias = aliased(Person) p_alias = inspect(p_alias) p1 = PathRegistry.coerce((p_alias, emapper.attrs.machines)) # plain AliasedClass - the path keeps that AliasedClass directly # as is in the path eq_(p1.path, (p_alias, emapper.attrs.machines))
def test_slice(self): umapper = inspect(self.classes.User) amapper = inspect(self.classes.Address) path = PathRegistry.coerce( ( umapper, umapper.attrs.addresses, amapper, amapper.attrs.email_address, ) ) eq_(path[1:3], (umapper.attrs.addresses, amapper))
def test_indexed_key(self): umapper = inspect(self.classes.User) amapper = inspect(self.classes.Address) path = PathRegistry.coerce( ( umapper, umapper.attrs.addresses, amapper, amapper.attrs.email_address, ) ) eq_(path[1], umapper.attrs.addresses) eq_(path[3], amapper.attrs.email_address)
def test_indexed_entity(self): umapper = inspect(self.classes.User) amapper = inspect(self.classes.Address) path = PathRegistry.coerce( ( umapper, umapper.attrs.addresses, amapper, amapper.attrs.email_address, ) ) is_(path[0], umapper) is_(path[2], amapper)
def test_with_poly_use_mapper(self): Person = _poly_fixtures.Person Engineer = _poly_fixtures.Engineer emapper = inspect(Engineer) p_poly = with_polymorphic(Person, [Engineer], _use_mapper_path=True) p_poly = inspect(p_poly) p1 = PathRegistry.coerce((p_poly, emapper.attrs.machines)) # polymorphic AliasedClass with the "use_mapper_path" flag - # the AliasedClass acts just like the base mapper eq_(p1.path, (emapper, emapper.attrs.machines))
def test_state_info_pickle(self): users = self.tables.users mapper(User, users) u1 = User(id=1, name="ed") sa.inspect(u1).info["some_key"] = "value" state_dict = sa.inspect(u1).__getstate__() state = sa_state.InstanceState.__new__(sa_state.InstanceState) state.__setstate__(state_dict) u2 = state.obj() eq_(sa.inspect(u2).info["some_key"], "value")
def test_with_poly_base_one(self): Person = _poly_fixtures.Person Engineer = _poly_fixtures.Engineer pmapper = inspect(Person) emapper = inspect(Engineer) p_poly = with_polymorphic(Person, [Engineer]) p_poly = inspect(p_poly) # "name" is actually on Person, not Engineer p1 = PathRegistry.coerce((p_poly, emapper.attrs.name)) # polymorphic AliasedClass - because "name" is on Person, # we get Person, not Engineer eq_(p1.path, (p_poly, pmapper.attrs.name))
def test_insp_aliased_column_prop(self): User = self.classes.User ua = aliased(User) prop = inspect(ua.name) is_(prop, ua.name) is_(prop.property.parent.mapper, class_mapper(User)) assert not hasattr(prop.property, "mapper") is_(prop.parent.entity, ua) is_(prop.parent.class_, User) is_(prop._parentmapper, class_mapper(User)) assert not hasattr(prop, "mapper") is_(prop._parententity, inspect(ua))
def test_insp_aliased_relationship_prop(self): User = self.classes.User Address = self.classes.Address ua = aliased(User) prop = inspect(ua.addresses) is_(prop, ua.addresses) is_(prop.property.parent.mapper, class_mapper(User)) is_(prop.property.mapper, class_mapper(Address)) is_(prop.parent.entity, ua) is_(prop.parent.class_, User) is_(prop._parentmapper, class_mapper(User)) is_(prop.mapper, class_mapper(Address)) is_(prop._parententity, inspect(ua))
def test_no_pk(self): metadata = self.metadata Table( "sometable", metadata, Column("id_a", Unicode(255)), Column("id_b", Unicode(255)), Index("pk_idx_1", "id_a", "id_b", unique=True), Index("pk_idx_2", "id_b", "id_a", unique=True), ) metadata.create_all() insp = inspect(testing.db) eq_( insp.get_indexes("sometable"), [ { "name": "pk_idx_1", "column_names": ["id_a", "id_b"], "dialect_options": {}, "unique": True, }, { "name": "pk_idx_2", "column_names": ["id_b", "id_a"], "dialect_options": {}, "unique": True, }, ], )
def test_select(self): t = Table("t", MetaData(), Column("x", Integer)) s = t.select() is_(inspect(s), s) assert s.is_selectable is_(s.selectable, s)
def test_reflect_table_comment(self): local_parent = Table( "parent", self.metadata, Column("q", Integer), comment="my local comment", ) local_parent.create(testing.db) insp = inspect(testing.db) eq_( insp.get_table_comment("parent", schema=testing.config.test_schema), {"text": "my table comment"}, ) eq_( insp.get_table_comment("parent", ), {"text": "my local comment"}, ) eq_( insp.get_table_comment( "parent", schema=testing.db.dialect.default_schema_name), {"text": "my local comment"}, )
def test_get_includes_getclause(self): # test issue #3597 User = self.classes.User bq = self.bakery(lambda s: s.query(User)) for i in range(5): sess = Session() u1 = bq(sess).get(7) eq_(u1.name, "jack") sess.close() eq_(len(bq._bakery), 2) # simulate race where mapper._get_clause # may be generated more than once from sqlalchemy_1_3 import inspect del inspect(User).__dict__["_get_clause"] for i in range(5): sess = Session() u1 = bq(sess).get(7) eq_(u1.name, "jack") sess.close() eq_(len(bq._bakery), 4)
def test_info_from_hybrid(self): A = self._fixture() A._value.info["foo"] = "bar" A.value.info["bar"] = "hoho" insp = inspect(A) is_(insp.all_orm_descriptors["value"].info, A.value.info)
def test_view_reflection(self): Table("x", self.metadata, Column("a", Integer), Column("b", String(50))) self.metadata.create_all() with testing.db.connect() as conn: conn.execute("CREATE VIEW v1 AS SELECT * FROM x") conn.execute("CREATE ALGORITHM=MERGE VIEW v2 AS SELECT * FROM x") conn.execute( "CREATE ALGORITHM=UNDEFINED VIEW v3 AS SELECT * FROM x") conn.execute( "CREATE DEFINER=CURRENT_USER VIEW v4 AS SELECT * FROM x") @event.listens_for(self.metadata, "before_drop") def cleanup(*arg, **kw): with testing.db.connect() as conn: for v in ["v1", "v2", "v3", "v4"]: conn.execute("DROP VIEW %s" % v) insp = inspect(testing.db) for v in ["v1", "v2", "v3", "v4"]: eq_( [(col["name"], col["type"].__class__) for col in insp.get_columns(v)], [("a", mysql.INTEGER), ("b", mysql.VARCHAR)], )
def test_reflection_with_unique_constraint(self): insp = inspect(testing.db) meta = self.metadata uc_table = Table( "mysql_uc", meta, Column("a", String(10)), UniqueConstraint("a", name="uc_a"), ) uc_table.create() # MySQL converts unique constraints into unique indexes. # separately we get both indexes = dict((i["name"], i) for i in insp.get_indexes("mysql_uc")) constraints = set(i["name"] for i in insp.get_unique_constraints("mysql_uc")) self.assert_("uc_a" in indexes) self.assert_(indexes["uc_a"]["unique"]) self.assert_("uc_a" in constraints) # reflection here favors the unique index, as that's the # more "official" MySQL construct reflected = Table("mysql_uc", MetaData(testing.db), autoload=True) indexes = dict((i.name, i) for i in reflected.indexes) constraints = set(uc.name for uc in reflected.constraints) self.assert_("uc_a" in indexes) self.assert_(indexes["uc_a"].unique) self.assert_("uc_a" not in constraints)
def test_addition(self): umapper = inspect(self.classes.User) amapper = inspect(self.classes.Address) p1 = PathRegistry.coerce((umapper, umapper.attrs.addresses)) p2 = PathRegistry.coerce((amapper, amapper.attrs.email_address)) eq_( p1 + p2, PathRegistry.coerce( ( umapper, umapper.attrs.addresses, amapper, amapper.attrs.email_address, ) ), )