From: Mike Bayer Date: Wed, 23 Oct 2013 19:02:36 +0000 (-0400) Subject: - The regexp used by the :func:`.url.make_url` function now parses X-Git-Tag: rel_0_8_3~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=785e44c48be5a25a71b2f2d4fe5e5219ffcb93a8;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - The regexp used by the :func:`.url.make_url` function now parses ipv6 addresses, e.g. surrounded by brackets. [ticket:2851] --- diff --git a/doc/build/changelog/changelog_07.rst b/doc/build/changelog/changelog_07.rst index 3a46580db5..f658a7d87e 100644 --- a/doc/build/changelog/changelog_07.rst +++ b/doc/build/changelog/changelog_07.rst @@ -6,6 +6,14 @@ .. changelog:: :version: 0.7.11 + .. change:: + :tags: bug, engine + :tickets: 2851 + :versions: 0.8.3, 0.9.0 + + The regexp used by the :func:`.url.make_url` function now parses + ipv6 addresses, e.g. surrounded by brackets. + .. change:: :tags: bug, orm :tickets: 2807 diff --git a/lib/sqlalchemy/engine/url.py b/lib/sqlalchemy/engine/url.py index b15bfbd524..08b620752f 100644 --- a/lib/sqlalchemy/engine/url.py +++ b/lib/sqlalchemy/engine/url.py @@ -71,7 +71,10 @@ class URL(object): else urllib.quote_plus(self.password)) s += "@" if self.host is not None: - s += self.host + if ':' in self.host: + s += "[%s]" % self.host + else: + s += self.host if self.port is not None: s += ':' + str(self.port) if self.database is not None: @@ -171,7 +174,10 @@ def _parse_rfc1738_args(name): (?::(?P[^/]*))? @)? (?: - (?P[^/:]*) + (?: + \[(?P[^/]+)\] | + (?P[^/:]+) + )? (?::(?P[^/]*))? )? (?:/(?P.*))? @@ -196,6 +202,9 @@ def _parse_rfc1738_args(name): components['password'] = \ urllib.unquote_plus(components['password']) + ipv4host = components.pop('ipv4host') + ipv6host = components.pop('ipv6host') + components['host'] = ipv4host or ipv6host name = components.pop('name') return URL(name, **components) else: diff --git a/test/engine/test_parseconnect.py b/test/engine/test_parseconnect.py index b7edb655cd..b9bb3393e7 100644 --- a/test/engine/test_parseconnect.py +++ b/test/engine/test_parseconnect.py @@ -16,6 +16,7 @@ class ParseConnectTest(fixtures.TestBase): for text in ( 'dbtype://username:password@hostspec:110//usr/db_file.db', 'dbtype://username:password@hostspec/database', + 'dbtype+apitype://username:password@hostspec/database', 'dbtype://username:password@hostspec', 'dbtype://username:password@/database', 'dbtype://username@hostspec', @@ -23,25 +24,31 @@ class ParseConnectTest(fixtures.TestBase): 'dbtype://hostspec/database', 'dbtype://hostspec', 'dbtype://hostspec/?arg1=val1&arg2=val2', - 'dbtype:///database', + 'dbtype+apitype:///database', 'dbtype:///:memory:', 'dbtype:///foo/bar/im/a/file', 'dbtype:///E:/work/src/LEM/db/hello.db', 'dbtype:///E:/work/src/LEM/db/hello.db?foo=bar&hoho=lala', 'dbtype://', - 'dbtype://username:password@/db', - 'dbtype:////usr/local/mailman/lists/_xtest@example.com/memb' - 'ers.db', - 'dbtype://username:apples%2Foranges@hostspec/mydatabase', + 'dbtype://username:password@/database', + 'dbtype:////usr/local/_xtest@example.com/members.db', + 'dbtype://username:apples%2Foranges@hostspec/database', + 'dbtype://username:password@[2001:da8:2004:1000:202:116:160:90]/database?foo=bar', + 'dbtype://username:password@[2001:da8:2004:1000:202:116:160:90]:80/database?foo=bar' ): u = url.make_url(text) - assert u.drivername == 'dbtype' - assert u.username == 'username' or u.username is None - assert u.password == 'password' or u.password \ - == 'apples/oranges' or u.password is None - assert u.host == 'hostspec' or u.host == '127.0.0.1' \ - or not u.host - assert str(u) == text + + assert u.drivername in ('dbtype', 'dbtype+apitype') + assert u.username in ('username', None) + assert u.password in ('password', 'apples/oranges', None) + assert u.host in ('hostspec', '127.0.0.1', + '2001:da8:2004:1000:202:116:160:90', '', None), u.host + assert u.database in ('database', + '/usr/local/_xtest@example.com/members.db', + '/usr/db_file.db', ':memory:', '', + 'foo/bar/im/a/file', + 'E:/work/src/LEM/db/hello.db', None), u.database + eq_(str(u), text) class DialectImportTest(fixtures.TestBase): def test_import_base_dialects(self):