diff --git a/taskflow/tests/unit/test_utils.py b/taskflow/tests/unit/test_utils.py index 2465f9fad..c136cb7cd 100644 --- a/taskflow/tests/unit/test_utils.py +++ b/taskflow/tests/unit/test_utils.py @@ -262,6 +262,42 @@ class TestLookFor(test.TestCase): self.assertEqual([10, 44], misc.look_for(hay, [44, 10])) +class TestMergeUri(test.TestCase): + def test_merge(self): + url = "http://www.yahoo.com/?a=b&c=d" + parsed = misc.parse_uri(url) + joined = misc.merge_uri(parsed, {}) + self.assertEqual('b', joined.get('a')) + self.assertEqual('d', joined.get('c')) + self.assertEqual('www.yahoo.com', joined.get('hostname')) + + def test_merge_existing_hostname(self): + url = "http://www.yahoo.com/" + parsed = misc.parse_uri(url) + joined = misc.merge_uri(parsed, {'hostname': 'b.com'}) + self.assertEqual('b.com', joined.get('hostname')) + + def test_merge_user_password(self): + url = "http://josh:harlow@www.yahoo.com/" + parsed = misc.parse_uri(url) + joined = misc.merge_uri(parsed, {}) + self.assertEqual('www.yahoo.com', joined.get('hostname')) + self.assertEqual('josh', joined.get('username')) + self.assertEqual('harlow', joined.get('password')) + + def test_merge_user_password_existing(self): + url = "http://josh:harlow@www.yahoo.com/" + parsed = misc.parse_uri(url) + existing = { + 'username': 'joe', + 'password': 'biggie', + } + joined = misc.merge_uri(parsed, existing) + self.assertEqual('www.yahoo.com', joined.get('hostname')) + self.assertEqual('joe', joined.get('username')) + self.assertEqual('biggie', joined.get('password')) + + class TestClamping(test.TestCase): def test_simple_clamp(self): result = misc.clamp(1.0, 2.0, 3.0) diff --git a/taskflow/utils/misc.py b/taskflow/utils/misc.py index ee5fb393a..ffd487ef5 100644 --- a/taskflow/utils/misc.py +++ b/taskflow/utils/misc.py @@ -124,21 +124,29 @@ def reverse_enumerate(items): def merge_uri(uri, conf): """Merges a parsed uri into the given configuration dictionary. - Merges the username, password, hostname, and query params of a uri into - the given configuration (it does not overwrite the configuration keys if - they already exist) and returns the adjusted configuration. + Merges the username, password, hostname, port, and query parameters of + a URI into the given configuration dictionary (it does **not** overwrite + existing configuration keys if they already exist) and returns the merged + configuration. NOTE(harlowja): does not merge the path, scheme or fragment. """ - for (k, v) in [('username', uri.username), ('password', uri.password)]: - if not v: - continue - conf.setdefault(k, v) - if uri.hostname: - hostname = uri.hostname - if uri.port is not None: - hostname += ":%s" % (uri.port) - conf.setdefault('hostname', hostname) + uri_port = uri.port + specials = [ + ('username', uri.username, lambda v: bool(v)), + ('password', uri.password, lambda v: bool(v)), + # NOTE(harlowja): A different check function is used since 0 is + # false (when bool(v) is applied), and that is a valid port... + ('port', uri_port, lambda v: v is not None), + ] + hostname = uri.hostname + if hostname: + if uri_port is not None: + hostname += ":%s" % (uri_port) + specials.append(('hostname', hostname, lambda v: bool(v))) + for (k, v, is_not_empty_value_func) in specials: + if is_not_empty_value_func(v): + conf.setdefault(k, v) for (k, v) in six.iteritems(uri.params()): conf.setdefault(k, v) return conf