From: Mike Bayer Date: Mon, 8 Jul 2019 14:42:20 +0000 (-0400) Subject: Ensure .engine is part of Connectable interface, implement as descriptor X-Git-Tag: rel_1_4_0b1~804 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3238d953b42f67761dc3019bd27f2960ae2e525f;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Ensure .engine is part of Connectable interface, implement as descriptor Fixed bug where using reflection function such as :meth:`.MetaData.reflect` with an :class:`.Engine` object that had execution options applied to it would fail, as the resulting :class:`.OptionEngine` proxy object failed to include a ``.engine`` attribute used within the reflection routines. Fixes: #4754 Change-Id: I6c342af5c6db6fe362b9d25f3f26d6859f62f87a --- diff --git a/doc/build/changelog/unreleased_13/4754.rst b/doc/build/changelog/unreleased_13/4754.rst new file mode 100644 index 0000000000..d8a3375cc6 --- /dev/null +++ b/doc/build/changelog/unreleased_13/4754.rst @@ -0,0 +1,8 @@ +.. change:: + :tags: bug, engine + :tickets: 4754 + + Fixed bug where using reflection function such as :meth:`.MetaData.reflect` + with an :class:`.Engine` object that had execution options applied to it + would fail, as the resulting :class:`.OptionEngine` proxy object failed to + include a ``.engine`` attribute used within the reflection routines. diff --git a/lib/sqlalchemy/engine/base.py b/lib/sqlalchemy/engine/base.py index 7aee1a73b2..07d1b8f893 100644 --- a/lib/sqlalchemy/engine/base.py +++ b/lib/sqlalchemy/engine/base.py @@ -1899,13 +1899,16 @@ class Engine(Connectable, log.Identified): if logging_name: self.logging_name = logging_name self.echo = echo - self.engine = self log.instance_logger(self, echoflag=echo) if proxy: interfaces.ConnectionProxy._adapt_listener(self, proxy) if execution_options: self.update_execution_options(**execution_options) + @property + def engine(self): + return self + def update_execution_options(self, **opt): r"""Update the default execution_options dictionary of this :class:`.Engine`. diff --git a/lib/sqlalchemy/engine/interfaces.py b/lib/sqlalchemy/engine/interfaces.py index 4806e72a58..aadadb8457 100644 --- a/lib/sqlalchemy/engine/interfaces.py +++ b/lib/sqlalchemy/engine/interfaces.py @@ -1117,6 +1117,13 @@ class Connectable(object): """ + engine = None + """The :class:`.Engine` instance referred to by this :class:`.Connectable`. + + May be ``self`` if this is already an :class:`.Engine`. + + """ + @util.deprecated( "1.3", "The :meth:`.Engine.contextual_connect` and " diff --git a/test/engine/test_execute.py b/test/engine/test_execute.py index 20c8ae659c..335c3a487b 100644 --- a/test/engine/test_execute.py +++ b/test/engine/test_execute.py @@ -635,10 +635,14 @@ class ExecuteTest(fixtures.TestBase): options={"execution_options": {"base": "x1"}} ) + is_(eng.engine, eng) + eng1 = eng.execution_options(foo="b1") + is_(eng1.engine, eng1) eng2 = eng.execution_options(foo="b2") eng1a = eng1.execution_options(bar="a1") eng2a = eng2.execution_options(foo="b3", bar="a2") + is_(eng2a.engine, eng2a) eq_(eng._execution_options, {"base": "x1"}) eq_(eng1._execution_options, {"base": "x1", "foo": "b1"}) diff --git a/test/engine/test_reflection.py b/test/engine/test_reflection.py index 3dc3a4461c..1cabf8963c 100644 --- a/test/engine/test_reflection.py +++ b/test/engine/test_reflection.py @@ -1198,6 +1198,11 @@ class ReflectionTest(fixtures.TestBase, ComparesTables): def test_reflect_uses_bind_engine_reflect(self): self._test_reflect_uses_bind(lambda e: MetaData().reflect(e)) + def test_reflect_uses_bind_option_engine_reflect(self): + self._test_reflect_uses_bind( + lambda e: MetaData().reflect(e.execution_options(foo="bar")) + ) + @testing.provide_metadata def test_reflect_all(self): existing = testing.db.table_names()