I want to use SQLAlchemy to read databases, which are not mapped to Objects (needs to access DBs unknown at time of development). One of the functionalities is to read the column names of different tables. Therefore I wrote this Connector:
MyConnector.py
import sqlalchemy as db
class MyConnector:
    __engine = None
    def __init__(self, db_connection):
        self.__engine = db.create_engine(db_connection)
    def __get_table(self, tbl_name):
        metadata = db.MetaData()
        table = db.Table(tbl_name, metadata)
        inspector = db.inspect(self.__engine)
        inspector.reflect_table(table, None)
        return table
    def get_table_columns(self, tbl_name):
        table = self.__get_table(tbl_name)
        return table.columns.keys()
Which is tested by following UnitTest:
ConnectorTest.py
import unittest
from MyConnector import MyConnector
class MyTestCase(unittest.TestCase):
    db_string = "sqlite:///myTest.db"
    expected_columns_user = ["id", "f_name", "l_name", "note"]
    expected_columns_address = ["id", "street", "number", "postal_code", "additional_information", "fk_user"]
    def test_get_table_columns_user(self):
        connector = MyConnector(self.db_string)
        answer = connector.get_table_columns("user")
        self.assertListEqual(self.expected_columns_user, answer)
    def test_get_table_columns_address(self):
        connector = MyConnector(self.db_string)
        answer = connector.get_table_columns("address")
        self.assertListEqual(self.expected_columns_address, answer)
if __name__ == '__main__':
    unittest.main()
SQLite DB contains only these two empty tables:
CREATE TABLE user (
    id INTEGER NOT NULL DEFAULT AUTO_INCREMENT,
    f_name VARCHAR,
    l_name VARCHAR,
    note VARCHAR,
    PRIMARY KEY (
        id
    )
);
CREATE TABLE address (
    id INTEGER NOT NULL DEFAULT AUTO_INCREMENT,
    street VARCHAR NOT NULL,
    number INTEGER,
    postal_code INTEGER NOT NULL,
    additional_information VARCHAR,
    fk_user INTEGER NOT NULL,
    PRIMARY KEY (
        id
    ),
    FOREIGN KEY (
        fk_user
    )
    REFERENCES user(id) ON DELETE CASCADE
);
The test test_get_table_columns_user works as expected.
The test test_get_table_columns_address raises an error:
Error
Traceback (most recent call last):
  File "ConnectorTest.py", line 17, in test_get_table_columns_address
    answer = connector.get_table_columns("address")
  File "MyConnector.py", line 17, in get_table_columns
    table = self.__get_table(tbl_name)
  File "MyConnector.py", line 13, in __get_table
    inspector.reflect_table(table, None)
  File "venv\lib\site-packages\sqlalchemy\engine\reflection.py", line 802, in reflect_table
    reflection_options,
  File "venv\lib\site-packages\sqlalchemy\engine\reflection.py", line 988, in _reflect_fk
    **reflection_options
  File "<string>", line 2, in __new__
  File "venv\lib\site-packages\sqlalchemy\util\deprecations.py", line 298, in warned
    return fn(*args, **kwargs)
  File "venv\lib\site-packages\sqlalchemy\sql\schema.py", line 601, in __new__
    metadata._remove_table(name, schema)
  File "venv\lib\site-packages\sqlalchemy\util\langhelpers.py", line 72, in __exit__
    with_traceback=exc_tb,
  File "venv\lib\site-packages\sqlalchemy\util\compat.py", line 207, in raise_
    raise exception
  File "venv\lib\site-packages\sqlalchemy\sql\schema.py", line 596, in __new__
    table._init(name, metadata, *args, **kw)
  File "venv\lib\site-packages\sqlalchemy\sql\schema.py", line 676, in _init
    resolve_fks=resolve_fks,
  File "venv\lib\site-packages\sqlalchemy\sql\schema.py", line 705, in _autoload
    with insp._inspection_context() as conn_insp:
  File "AppData\Local\Programs\Python\Python37\lib\contextlib.py", line 112, in __enter__
    return next(self.gen)
  File "venv\lib\site-packages\sqlalchemy\engine\reflection.py", line 217, in _inspection_context
    sub_insp = self._construct(self.__class__._init_connection, conn)
  File "venv\lib\site-packages\sqlalchemy\engine\reflection.py", line 117, in _construct
    init(self, bind)
  File "venv\lib\site-packages\sqlalchemy\engine\reflection.py", line 135, in _init_connection
    self.engine = connection.__engine
AttributeError: 'Connection' object has no attribute '_Inspector__engine'
Since both tests run exactly identical code, except the parameter for the table name, I am pretty confused by the outcome.
Using Google I found this PR: https://github.com/laughingman7743/PyAthena/pull/65/files Seems not relevant to this Problem (Engine, not Connection).
Many posts about Sessions (like Python SQLAlchemy Query: AttributeError: 'Connection' object has no attribute 'contextual_connect' or https://github.com/sqlalchemy/sqlalchemy/issues/4046). Which should not matter because using the Inspector in this context seems not even to need a call to engine.connect().
For the sake of ruling out lingering locks or similar problems, I also changed the parameter of test_get_table_columns_address to "user". This works up to the assert, which obviously does not match. So it looks like a problem with the table (-name?) to me - which is pretty weird.
Could someone with more experience and insight to SQLAlchemy point out, where/what the Problem with my code is? Thanks in advance!
Python 3.7.4
SQLAlchemy 1.4.20
