4040before_models_committed = _signals .signal ('before-models-committed' )
4141
4242
43+ def _sa_url_set (url , ** kwargs ):
44+ try :
45+ url = url .set (** kwargs )
46+ except AttributeError :
47+ # SQLAlchemy <= 1.3
48+ for key , value in kwargs .items ():
49+ setattr (url , key , value )
50+
51+ return url
52+
53+
54+ def _sa_url_query_setdefault (url , ** kwargs ):
55+ query = dict (url .query )
56+
57+ for key , value in kwargs .items ():
58+ query .setdefault (key , value )
59+
60+ return _sa_url_set (url , query = query )
61+
62+
4363def _make_table (db ):
4464 def _make_table (* args , ** kwargs ):
4565 if len (args ) > 1 and isinstance (args [1 ], db .Column ):
@@ -552,7 +572,7 @@ def get_engine(self):
552572 return self ._engine
553573
554574 sa_url = make_url (uri )
555- options = self .get_options (sa_url , echo )
575+ sa_url , options = self .get_options (sa_url , echo )
556576 self ._engine = rv = self ._sa .create_engine (sa_url , options )
557577
558578 if _record_queries (self ._app ):
@@ -566,8 +586,9 @@ def get_engine(self):
566586 def get_options (self , sa_url , echo ):
567587 options = {}
568588
569- self ._sa .apply_pool_defaults (self ._app , options )
570- self ._sa .apply_driver_hacks (self ._app , sa_url , options )
589+ options = self ._sa .apply_pool_defaults (self ._app , options )
590+ sa_url , options = self ._sa .apply_driver_hacks (self ._app , sa_url , options )
591+
571592 if echo :
572593 options ['echo' ] = echo
573594
@@ -578,7 +599,7 @@ def get_options(self, sa_url, echo):
578599 # Give options set in SQLAlchemy.__init__() ultimate priority
579600 options .update (self ._sa ._engine_options )
580601
581- return options
602+ return sa_url , options
582603
583604
584605def get_state (app ):
@@ -861,6 +882,11 @@ def shutdown_session(response_or_exc):
861882 return response_or_exc
862883
863884 def apply_pool_defaults (self , app , options ):
885+ """
886+ .. versionchanged:: 2.5
887+ Returns the ``options`` dict, for consistency with
888+ :meth:`apply_driver_hacks`.
889+ """
864890 def _setdefault (optionkey , configkey ):
865891 value = app .config [configkey ]
866892 if value is not None :
@@ -869,6 +895,7 @@ def _setdefault(optionkey, configkey):
869895 _setdefault ('pool_timeout' , 'SQLALCHEMY_POOL_TIMEOUT' )
870896 _setdefault ('pool_recycle' , 'SQLALCHEMY_POOL_RECYCLE' )
871897 _setdefault ('max_overflow' , 'SQLALCHEMY_MAX_OVERFLOW' )
898+ return options
872899
873900 def apply_driver_hacks (self , app , sa_url , options ):
874901 """This method is called before engine creation and used to inject
@@ -879,9 +906,15 @@ def apply_driver_hacks(self, app, sa_url, options):
879906 The default implementation provides some saner defaults for things
880907 like pool sizes for MySQL and sqlite. Also it injects the setting of
881908 `SQLALCHEMY_NATIVE_UNICODE`.
909+
910+ .. versionchanged:: 2.5
911+ Returns ``(sa_url, options)``. SQLAlchemy 1.4 made the URL
912+ immutable, so any changes to it must now be passed back up
913+ to the original caller.
882914 """
883915 if sa_url .drivername .startswith ('mysql' ):
884- sa_url .query .setdefault ('charset' , 'utf8' )
916+ sa_url = _sa_url_query_setdefault (sa_url , charset = "utf8" )
917+
885918 if sa_url .drivername != 'mysql+gaerdbms' :
886919 options .setdefault ('pool_size' , 10 )
887920 options .setdefault ('pool_recycle' , 7200 )
@@ -911,7 +944,9 @@ def apply_driver_hacks(self, app, sa_url, options):
911944
912945 # if it's not an in memory database we make the path absolute.
913946 if not detected_in_memory :
914- sa_url .database = os .path .join (app .root_path , sa_url .database )
947+ sa_url = _sa_url_set (
948+ sa_url , database = os .path .join (app .root_path , sa_url .database )
949+ )
915950
916951 unu = app .config ['SQLALCHEMY_NATIVE_UNICODE' ]
917952 if unu is None :
@@ -932,6 +967,8 @@ def apply_driver_hacks(self, app, sa_url, options):
932967 DeprecationWarning
933968 )
934969
970+ return sa_url , options
971+
935972 @property
936973 def engine (self ):
937974 """Gives access to the engine. If the database configuration is bound
0 commit comments