From 4065352c7e9779cfeae34f01073ef6c43aeae488 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Tue, 6 Feb 2018 18:13:27 -0500 Subject: Add flag for class-level disallow of events, apply to OptionEngine Fixed bug where events associated with an :class:`Engine` at the class level would be doubled when the :meth:`.Engine.execution_options` method were used. To achieve this, the semi-private class :class:`.OptionEngine` no longer accepts events directly at the class level and will raise an error; the class only propagates class-level events from its parent :class:`.Engine`. Instance-level events continue to work as before. The comments present another way of doing this where we would copy events from the parent engine at option time rather than linking the event listeners, but this would be a behavioral change that adding new events to the parent engine would not take effect for an already-created OptionEngine. Change-Id: Id128516f54103fbad9a2210d6571eceb59c8b0cb Fixes: #4181 --- lib/sqlalchemy/engine/base.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'lib/sqlalchemy/engine/base.py') diff --git a/lib/sqlalchemy/engine/base.py b/lib/sqlalchemy/engine/base.py index 4bae94317..aa9358cd6 100644 --- a/lib/sqlalchemy/engine/base.py +++ b/lib/sqlalchemy/engine/base.py @@ -2189,6 +2189,8 @@ class Engine(Connectable, log.Identified): class OptionEngine(Engine): + _sa_propagate_class_events = False + def __init__(self, proxied, execution_options): self._proxied = proxied self.url = proxied.url @@ -2196,7 +2198,21 @@ class OptionEngine(Engine): self.logging_name = proxied.logging_name self.echo = proxied.echo log.instance_logger(self, echoflag=self.echo) + + # note: this will propagate events that are assigned to the parent + # engine after this OptionEngine is created. Since we share + # the events of the parent we also disallow class-level events + # to apply to the OptionEngine class directly. + # + # the other way this can work would be to transfer existing + # events only, using: + # self.dispatch._update(proxied.dispatch) + # + # that might be more appropriate however it would be a behavioral + # change for logic that assigns events to the parent engine and + # would like it to take effect for the already-created sub-engine. self.dispatch = self.dispatch._join(proxied.dispatch) + self._execution_options = proxied._execution_options self.update_execution_options(**execution_options) -- cgit v1.2.1