From bd1ddb2b534e21b13e07fdb72f2c520f30b9e202 Mon Sep 17 00:00:00 2001 From: Miguel Grinberg Date: Thu, 21 May 2020 05:54:47 -0400 Subject: [PATCH] Fix query string escaping in engine URLs Fixed issue in :class:`.URL` object where stringifying the object would not URL encode special characters, preventing the URL from being re-consumable as a real URL. Pull request courtesy Miguel Grinberg. Fixes: #5341 Closes: #5342 Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/5342 Pull-request-sha: 362ca3398336a3a892e8020530f0c68d4f2d1d01 Change-Id: Ief6218122d1ec0c70479eb1a90e1c16433801924 (cherry picked from commit 2644693c0bf5b775f7a7283cdbf566a37872586f) --- doc/build/changelog/unreleased_13/5341.rst | 7 +++++++ lib/sqlalchemy/engine/url.py | 2 +- test/engine/test_parseconnect.py | 5 +++++ 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 doc/build/changelog/unreleased_13/5341.rst diff --git a/doc/build/changelog/unreleased_13/5341.rst b/doc/build/changelog/unreleased_13/5341.rst new file mode 100644 index 0000000000..28df9cb586 --- /dev/null +++ b/doc/build/changelog/unreleased_13/5341.rst @@ -0,0 +1,7 @@ +.. change:: + :tags: bug, engine + :tickets: 5341 + + Fixed issue in :class:`.URL` object where stringifying the object + would not URL encode special characters, preventing the URL from being + re-consumable as a real URL. Pull request courtesy Miguel Grinberg. \ No newline at end of file diff --git a/lib/sqlalchemy/engine/url.py b/lib/sqlalchemy/engine/url.py index 5950fa0217..7b7a0047ce 100644 --- a/lib/sqlalchemy/engine/url.py +++ b/lib/sqlalchemy/engine/url.py @@ -96,7 +96,7 @@ class URL(object): keys = list(self.query) keys.sort() s += "?" + "&".join( - "%s=%s" % (k, element) + "%s=%s" % (util.quote_plus(k), util.quote_plus(element)) for k in keys for element in util.to_list(self.query[k]) ) diff --git a/test/engine/test_parseconnect.py b/test/engine/test_parseconnect.py index 1277425c15..77b882f2c1 100644 --- a/test/engine/test_parseconnect.py +++ b/test/engine/test_parseconnect.py @@ -147,6 +147,11 @@ class URLTest(fixtures.TestBase): "dialect://user:pass@host/db?arg1=param1&arg2=param2&arg2=param3", ) + test_url = "dialect://user:pass@host/db?arg1%3D=param1&arg2=param+2" + u = url.make_url(test_url) + eq_(u.query, {"arg1=": "param1", "arg2": "param 2"}) + eq_(str(u), test_url) + def test_comparison(self): components = ( "drivername", -- 2.39.5