Commit 696b84c4 authored by Kirill Smelkov's avatar Kirill Smelkov

zeo: Fix parsing URI with IPv6 address

The code was crashing this way:

---- 8< ----
======================================================================
ERROR: test_call_ipv6 (zodburi.tests.test_resolvers.TestClientStorageURIResolver)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/kirr/src/wendelin/venv/z-dev/local/lib/python2.7/site-packages/mock/mock.py", line 1305, in patched
    return func(*args, **keywargs)
  File "/home/kirr/src/wendelin/z/zodburi/zodburi/tests/test_resolvers.py", line 265, in test_call_ipv6
    factory, dbkw = resolver('zeo://[::1]:9090?debug=true')
  File "/home/kirr/src/wendelin/z/zodburi/zodburi/resolvers.py", line 141, in __call__
    host, port = netloc.split(':')
ValueError: too many values to unpack

======================================================================
ERROR: test_call_ipv6_no_port (zodburi.tests.test_resolvers.TestClientStorageURIResolver)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/kirr/src/wendelin/venv/z-dev/local/lib/python2.7/site-packages/mock/mock.py", line 1305, in patched
    return func(*args, **keywargs)
  File "/home/kirr/src/wendelin/z/zodburi/zodburi/tests/test_resolvers.py", line 258, in test_call_ipv6_no_port
    factory, dbkw = resolver('zeo://[::1]?debug=true')
  File "/home/kirr/src/wendelin/z/zodburi/zodburi/resolvers.py", line 141, in __call__
    host, port = netloc.split(':')
ValueError: too many values to unpack
---- 8< ----

Fix it by leveraging the fact that urlparse.urlsplit return() tuple-like object
with additional .hostname and .port attributes which already parse IPv6 correctly:

In [2]: u = urlsplit('http://[::1]:5553')

In [3]: u
Out[3]: SplitResult(scheme='http', netloc='[::1]:5553', path='', query='', fragment='')

In [4]: u.netloc
Out[4]: '[::1]:5553'

In [5]: u.hostname
Out[5]: '::1'

In [6]: u.port
Out[6]: 5553

In [7]: u = urlsplit('http://[::1]')

In [8]: u.hostname
Out[8]: '::1'

In [9]: u.port

In [10]: repr(u.port)
Out[10]: 'None'
parent 71fb5f10
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
- Add support for Python 3.6. - Add support for Python 3.6.
- Fix parsing of ``zeo://`` URI with IPv6 address.
2.2.2 (2017-05-05) 2.2.2 (2017-05-05)
------------------ ------------------
......
...@@ -134,21 +134,19 @@ class ClientStorageURIResolver(Resolver): ...@@ -134,21 +134,19 @@ class ClientStorageURIResolver(Resolver):
# urlsplit doesnt understand zeo URLs so force to something that # urlsplit doesnt understand zeo URLs so force to something that
# doesn't break # doesn't break
uri = uri.replace('zeo://', 'http://', 1) uri = uri.replace('zeo://', 'http://', 1)
(scheme, netloc, path, query, frag) = urlsplit(uri) u = urlsplit(uri)
if netloc: if u.netloc:
# TCP URL # TCP URL
if ':' in netloc: host = u.hostname
host, port = netloc.split(':') port = u.port
port = int(port) if port is None:
else:
host = netloc
port = 9991 port = 9991
args = ((host, port),) args = ((host, port),)
else: else:
# Unix domain socket URL # Unix domain socket URL
path = os.path.normpath(path) path = os.path.normpath(u.path)
args = (path,) args = (path,)
kw = dict(parse_qsl(query)) kw = dict(parse_qsl(u.query))
kw, unused = self.interpret_kwargs(kw) kw, unused = self.interpret_kwargs(kw)
if 'demostorage' in kw: if 'demostorage' in kw:
kw.pop('demostorage') kw.pop('demostorage')
......
...@@ -252,6 +252,20 @@ class TestClientStorageURIResolver(unittest.TestCase): ...@@ -252,6 +252,20 @@ class TestClientStorageURIResolver(unittest.TestCase):
factory() factory()
ClientStorage.assert_called_once_with(('localhost', 8080), debug=1) ClientStorage.assert_called_once_with(('localhost', 8080), debug=1)
@mock.patch('zodburi.resolvers.ClientStorage')
def test_call_ipv6_no_port(self, ClientStorage):
resolver = self._makeOne()
factory, dbkw = resolver('zeo://[::1]?debug=true')
factory()
ClientStorage.assert_called_once_with(('::1', 9991), debug=1)
@mock.patch('zodburi.resolvers.ClientStorage')
def test_call_ipv6(self, ClientStorage):
resolver = self._makeOne()
factory, dbkw = resolver('zeo://[::1]:9090?debug=true')
factory()
ClientStorage.assert_called_once_with(('::1', 9090), debug=1)
@mock.patch('zodburi.resolvers.ClientStorage') @mock.patch('zodburi.resolvers.ClientStorage')
def test_call_unix(self, ClientStorage): def test_call_unix(self, ClientStorage):
resolver = self._makeOne() resolver = self._makeOne()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment