Hello,

Some legacy code at work that I don't fully understand (and whose authors 
are all long gone) does the following to eventually insert some values into 
the table it gets:

meta = sqlalchemy.MetaData(bind=session.get_bind())
meta.reflect()
table = sqlalchemy.Table(TableName.__tablename__, meta, autoload=True)

The meta.reflect() call fails if the session comes from a sessionmaker 
bound to a copy of an engine that has a non-default isolation level, for 
example:

engine = sqlalchemy.create_engine(setup)
maker = sqlalchemy.orm.sessionmaker(bind=engine.execution_options(
isolation_level='SERIALIZABLE'))
session = maker()

The error message it gives is "AttributeError: 'OptionEngine' object has no 
attribute 'engine'". The reason seems to be that in this case, 
session.get_bind() returns an OptionEngine, which seems to be a facade 
around the original Engine; it proxies to the original one.

See below for a minimal complete example [A] with a Conda environment [B].

I can get around this by checking whether the get_bind() call gives me an 
OptionEngine, and pull the proxied Engine out of the object if it does, but 
that involves using internal SQLAlchemy object variables and might break in 
the future.

1. Should what I'm doing here work at all? That is, should OptionEngine 
define 'engine' and have it resolve to whatever original Engine it was 
created from?

2. If not, and what I've inherited is horrifying, does anyone have ideas on 
how to make it better? The only comments around this piece of code say they 
do this dance to be able to insert values into columns that are in the DB 
table but not the SQLAlchemy ORM table.

Thank you,
Gunnar

[A] Minimal example (done here in sqlite3, also works on SQL Server):

import sqlalchemy
import sqlalchemy.orm
import sqlalchemy.ext.declarative

Base = sqlalchemy.ext.declarative.declarative_base()

class Foo(Base):
    __tablename__ = 'foos'
    id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
    val = sqlalchemy.Column(sqlalchemy.Integer)

if __name__ == '__main__':
    db = sqlalchemy.create_engine('sqlite:///')
    Foo.metadata.create_all(db)

    maker = sqlalchemy.orm.sessionmaker(bind=db.execution_options(
isolation_level='SERIALIZABLE'))
    session = maker()

    bind = session.get_bind()
    meta = sqlalchemy.MetaData(bind=bind)
    meta.reflect()
    table = sqlalchemy.Table(Foo.__tablename__, meta, autoload=True)

    vals = list(range(100))
    ins = table.insert().values(vals)
    session.execute(ins)
    session.commit()
    session.close()

[B] Conda environment that reproduces the problem in the example:

# Name                    Version                   Build  Channel
_libgcc_mutex             0.1                        main  
ca-certificates           2019.5.15                     0  
certifi                   2019.6.16                py37_0  
libedit                   3.1.20181209         hc058e9b_0  
libffi                    3.2.1                hd88cf55_4  
libgcc-ng                 9.1.0                hdf63c60_0  
libstdcxx-ng              9.1.0                hdf63c60_0  
ncurses                   6.1                  he6710b0_1  
openssl                   1.1.1c               h7b6447c_1  
pip                       19.1.1                   py37_0  
python                    3.7.3                h0371630_0  
readline                  7.0                  h7b6447c_5  
setuptools                41.0.1                   py37_0  
sqlalchemy                1.3.5            py37h7b6447c_0  
sqlite                    3.28.0               h7b6447c_0  
tk                        8.6.8                hbc83047_0  
wheel                     0.33.4                   py37_0  
xz                        5.2.4                h14c3975_4  
zlib                      1.2.11               h7b6447c_3  


-- 
SQLAlchemy - 
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable 
Example.  See  http://stackoverflow.com/help/mcve for a full description.
--- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at https://groups.google.com/group/sqlalchemy.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/sqlalchemy/d81b41c0-5e38-4601-a487-c763d3896b91%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to