)]}'
{"nova/cmd/manage.py":[{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"a481b8c217bb22eec8f3e6197f0e65a3445da6be","unresolved":false,"context_lines":[{"line_number":1165,"context_line":"            # first with URL quotes before trying to split the URL."},{"line_number":1166,"context_line":"            try:"},{"line_number":1167,"context_line":"                connection \u003d CONF.database.connection"},{"line_number":1168,"context_line":"                start \u003d connection.find(\u0027:\u0027, connection.find(\u0027:\u0027) + 1)"},{"line_number":1169,"context_line":"                end \u003d connection.rfind(\u0027@\u0027)"},{"line_number":1170,"context_line":"                password \u003d connection[start+1:end]"},{"line_number":1171,"context_line":"                encoded_password \u003d urllib.quote(password)"},{"line_number":1172,"context_line":"                connection \u003d connection.replace(password, encoded_password)"},{"line_number":1173,"context_line":"            except IndexError:"}],"source_content_type":"text/x-python","patch_set":1,"id":"3f044301_9c717647","line":1170,"range":{"start_line":1168,"start_character":16,"end_line":1170,"end_character":50},"updated":"2017-05-12 02:58:15.000000000","message":"This should probably all be done with regex match.","commit_id":"2bd59fd8b8a38ed84da4108e39adfe28e38e89db"},{"author":{"_account_id":21813,"name":"Andrey Volkov","email":"m@amadev.ru","username":"avolkov"},"change_message_id":"aac43ed5693719a0da1e74a455413f2775c33e34","unresolved":false,"context_lines":[{"line_number":1169,"context_line":"            # would be the credentials in the netloc. We have to start after"},{"line_number":1170,"context_line":"            # :// specifically because the credentials in the netloc are split"},{"line_number":1171,"context_line":"            # on the : between \u003cusername\u003e:\u003cpassword\u003e."},{"line_number":1172,"context_line":"            match \u003d re.search(\":(?!//).*@\", connection)"},{"line_number":1173,"context_line":"            if match:"},{"line_number":1174,"context_line":"                # Should be a single match; strip the : and @ off the ends."},{"line_number":1175,"context_line":"                password \u003d match.group(0)[1:-1]"}],"source_content_type":"text/x-python","patch_set":2,"id":"3f044301_51a4f0a5","line":1172,"updated":"2017-05-12 11:46:57.000000000","message":"looks like a hack, can we use sqlalchemy which parses such things correctly?\n\n\nfrom sqlalchemy.engine.url import make_url\nurl \u003d make_url(\"mysql+pymysql://nova:abcd0123?AB@controller/nova\")\nprint url.username, url.password, url.host, url.port, url.database\n\n\u003e nova abcd0123?AB controller None nova","commit_id":"4928233170e285c4602b1e8990ebd7f3f26e600d"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"e52b6a0fa4fdeba50850fd14533d24f516ca650b","unresolved":false,"context_lines":[{"line_number":1169,"context_line":"            # would be the credentials in the netloc. We have to start after"},{"line_number":1170,"context_line":"            # :// specifically because the credentials in the netloc are split"},{"line_number":1171,"context_line":"            # on the : between \u003cusername\u003e:\u003cpassword\u003e."},{"line_number":1172,"context_line":"            match \u003d re.search(\":(?!//).*@\", connection)"},{"line_number":1173,"context_line":"            if match:"},{"line_number":1174,"context_line":"                # Should be a single match; strip the : and @ off the ends."},{"line_number":1175,"context_line":"                password \u003d match.group(0)[1:-1]"}],"source_content_type":"text/x-python","patch_set":2,"id":"1f013ff3_7b19bf86","line":1172,"in_reply_to":"3f044301_51a4f0a5","updated":"2017-05-12 14:34:41.000000000","message":"I agree this is a bit hacky. I didn\u0027t know that existed in sqla but I\u0027ll give it a try, thanks.","commit_id":"4928233170e285c4602b1e8990ebd7f3f26e600d"},{"author":{"_account_id":11904,"name":"Sean McGinnis","email":"sean.mcginnis@gmail.com","username":"SeanM"},"change_message_id":"16ee8b73905e7a39c519f5d8aae37fb97f1b0cac","unresolved":false,"context_lines":[{"line_number":1180,"context_line":"                urlparse.urlsplit(connection)"},{"line_number":1181,"context_line":"            root, ext \u003d os.path.splitext(path)"},{"line_number":1182,"context_line":"            path \u003d root + \"_cell0\" + ext"},{"line_number":1183,"context_line":"            return urlparse.urlunsplit((scheme, urllib.unquote(netloc), path,"},{"line_number":1184,"context_line":"                                        query, fragment))"},{"line_number":1185,"context_line":""},{"line_number":1186,"context_line":"        dbc \u003d database_connection or cell0_default_connection()"}],"source_content_type":"text/x-python","patch_set":2,"id":"3f044301_b6a7aabd","line":1183,"range":{"start_line":1183,"start_character":55,"end_line":1183,"end_character":62},"updated":"2017-05-12 10:32:12.000000000","message":"No idea why it would be just showing up now, but it appears unquote has moved from urllib to urllib.parse in py3.","commit_id":"4928233170e285c4602b1e8990ebd7f3f26e600d"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"e52b6a0fa4fdeba50850fd14533d24f516ca650b","unresolved":false,"context_lines":[{"line_number":1180,"context_line":"                urlparse.urlsplit(connection)"},{"line_number":1181,"context_line":"            root, ext \u003d os.path.splitext(path)"},{"line_number":1182,"context_line":"            path \u003d root + \"_cell0\" + ext"},{"line_number":1183,"context_line":"            return urlparse.urlunsplit((scheme, urllib.unquote(netloc), path,"},{"line_number":1184,"context_line":"                                        query, fragment))"},{"line_number":1185,"context_line":""},{"line_number":1186,"context_line":"        dbc \u003d database_connection or cell0_default_connection()"}],"source_content_type":"text/x-python","patch_set":2,"id":"1f013ff3_fb238fbd","line":1183,"range":{"start_line":1183,"start_character":55,"end_line":1183,"end_character":62},"in_reply_to":"3f044301_b6a7aabd","updated":"2017-05-12 14:34:41.000000000","message":"I think I noticed something like that when digging through python docs on urllib, but forgot to use six. Good point, will change.","commit_id":"4928233170e285c4602b1e8990ebd7f3f26e600d"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"3ea612f1727ff42fba0a3405d02d74c7992d45dc","unresolved":false,"context_lines":[{"line_number":1170,"context_line":"            # the username and db name are both \u0027nova\u0027 we need to only replace"},{"line_number":1171,"context_line":"            # the last one, which is the database name in the URL, not the"},{"line_number":1172,"context_line":"            # username."},{"line_number":1173,"context_line":"            connection \u003d connection.rstrip(url.database)"},{"line_number":1174,"context_line":"            return connection + cell0_db_name"},{"line_number":1175,"context_line":""},{"line_number":1176,"context_line":"        dbc \u003d database_connection or cell0_default_connection()"}],"source_content_type":"text/x-python","patch_set":4,"id":"ff0f0b1f_8e2be02e","line":1173,"range":{"start_line":1173,"start_character":36,"end_line":1173,"end_character":42},"updated":"2017-05-19 11:49:33.000000000","message":"\u0027rstrip\u0027 doesn\u0027t do what you\u0027d think it does.\n\n   \u003e\u003e\u003e \u0027testsssssts\u0027.rstrip(\u0027st\u0027)\n   \u0027te\u0027\n\nAndrey\u0027s solution looks like the better approach here","commit_id":"9a9a620ea2d06e51c01b0864d7275b57d7203e5a"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"58b1c3a3d56423264b474fb1601afcc9215d1c7c","unresolved":false,"context_lines":[{"line_number":1170,"context_line":"            # the username and db name are both \u0027nova\u0027 we need to only replace"},{"line_number":1171,"context_line":"            # the last one, which is the database name in the URL, not the"},{"line_number":1172,"context_line":"            # username."},{"line_number":1173,"context_line":"            connection \u003d connection.rstrip(url.database)"},{"line_number":1174,"context_line":"            return connection + cell0_db_name"},{"line_number":1175,"context_line":""},{"line_number":1176,"context_line":"        dbc \u003d database_connection or cell0_default_connection()"}],"source_content_type":"text/x-python","patch_set":4,"id":"ff0f0b1f_72b97cca","line":1173,"range":{"start_line":1173,"start_character":36,"end_line":1173,"end_character":42},"in_reply_to":"ff0f0b1f_3258a430","updated":"2017-05-20 00:11:04.000000000","message":"Eh, maybe that\u0027s not the greatest idea. We want to be able to re-make the url with the new database name in it.","commit_id":"9a9a620ea2d06e51c01b0864d7275b57d7203e5a"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"b225ea6075f4b50467f19c9619df0de2eaafc377","unresolved":false,"context_lines":[{"line_number":1170,"context_line":"            # the username and db name are both \u0027nova\u0027 we need to only replace"},{"line_number":1171,"context_line":"            # the last one, which is the database name in the URL, not the"},{"line_number":1172,"context_line":"            # username."},{"line_number":1173,"context_line":"            connection \u003d connection.rstrip(url.database)"},{"line_number":1174,"context_line":"            return connection + cell0_db_name"},{"line_number":1175,"context_line":""},{"line_number":1176,"context_line":"        dbc \u003d database_connection or cell0_default_connection()"}],"source_content_type":"text/x-python","patch_set":4,"id":"ff0f0b1f_3258a430","line":1173,"range":{"start_line":1173,"start_character":36,"end_line":1173,"end_character":42},"in_reply_to":"ff0f0b1f_4788f86f","updated":"2017-05-19 23:51:11.000000000","message":"It seems like rstrip will always work as expected because of the forward slash separating the database name from the rest of the url, that is, rstrip will remove all of the specified characters from the end of the string until a character not in the set is reached (which will be the /). I would think there will probably always be a separator of some sort that doesn\u0027t match the chars set in rsplit. Although you could have a problem if the database name somehow contains a separator?\n\nI could see that ideally what we want here is like an \"rreplace()\" to replace the last occurrence of the substring. Maybe like:\n\n return cell_0_db_name.join(connection.rsplit(url.database, 1))","commit_id":"9a9a620ea2d06e51c01b0864d7275b57d7203e5a"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"d6b14b5eeae4005837b913ec3d8e92397784161e","unresolved":false,"context_lines":[{"line_number":1170,"context_line":"            # the username and db name are both \u0027nova\u0027 we need to only replace"},{"line_number":1171,"context_line":"            # the last one, which is the database name in the URL, not the"},{"line_number":1172,"context_line":"            # username."},{"line_number":1173,"context_line":"            connection \u003d connection.rstrip(url.database)"},{"line_number":1174,"context_line":"            return connection + cell0_db_name"},{"line_number":1175,"context_line":""},{"line_number":1176,"context_line":"        dbc \u003d database_connection or cell0_default_connection()"}],"source_content_type":"text/x-python","patch_set":4,"id":"ff0f0b1f_ec17daa2","line":1173,"range":{"start_line":1173,"start_character":36,"end_line":1173,"end_character":42},"in_reply_to":"ff0f0b1f_72b97cca","updated":"2017-05-22 08:30:38.000000000","message":"\u003e I would think there will probably always be a separator of some sort that doesn\u0027t match the chars set in rsplit. Although you could have a problem if the database name somehow contains a separator?\n\nThat\u0027s what I was concerned with (the semantics of rstrip have caught me out more than once). Is / always going to be the separator, and is / always an invalid character for a database name? If so, this would be OK, I guess? Also, we\u0027ll never have a trailing slash, right?","commit_id":"9a9a620ea2d06e51c01b0864d7275b57d7203e5a"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"80c81a032a52c835fa32e0882e319d1197e22b01","unresolved":false,"context_lines":[{"line_number":1170,"context_line":"            # the username and db name are both \u0027nova\u0027 we need to only replace"},{"line_number":1171,"context_line":"            # the last one, which is the database name in the URL, not the"},{"line_number":1172,"context_line":"            # username."},{"line_number":1173,"context_line":"            connection \u003d connection.rstrip(url.database)"},{"line_number":1174,"context_line":"            return connection + cell0_db_name"},{"line_number":1175,"context_line":""},{"line_number":1176,"context_line":"        dbc \u003d database_connection or cell0_default_connection()"}],"source_content_type":"text/x-python","patch_set":4,"id":"ff0f0b1f_4788f86f","line":1173,"range":{"start_line":1173,"start_character":36,"end_line":1173,"end_character":42},"in_reply_to":"ff0f0b1f_8e2be02e","updated":"2017-05-19 22:55:42.000000000","message":"Then why doesn\u0027t the test against this connection string fail?\n\nmysql+pymysql://nova:abcd0123:AB@controller/nova","commit_id":"9a9a620ea2d06e51c01b0864d7275b57d7203e5a"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"89166009817e8ca4fa3d3f78489c0c15f0de0785","unresolved":false,"context_lines":[{"line_number":1170,"context_line":"            # the username and db name are both \u0027nova\u0027 we need to only replace"},{"line_number":1171,"context_line":"            # the last one, which is the database name in the URL, not the"},{"line_number":1172,"context_line":"            # username."},{"line_number":1173,"context_line":"            connection \u003d connection.rstrip(url.database)"},{"line_number":1174,"context_line":"            return connection + cell0_db_name"},{"line_number":1175,"context_line":""},{"line_number":1176,"context_line":"        dbc \u003d database_connection or cell0_default_connection()"}],"source_content_type":"text/x-python","patch_set":4,"id":"ff0f0b1f_512c13ab","line":1173,"range":{"start_line":1173,"start_character":36,"end_line":1173,"end_character":42},"in_reply_to":"ff0f0b1f_ec17daa2","updated":"2017-05-22 15:18:27.000000000","message":"I don\u0027t think you\u0027d have a db name with / in it, no, and / is the separator in a URL, so I think we\u0027re OK here until someone comes along with a case that proves this wrong. As noted below, str(url) doesn\u0027t help us either. We could probably add some complicated parsing code here for breaking the URL into pieces and putting it back together, but that\u0027s what I started with and was suggested we use make_url, which is nice and simple.","commit_id":"9a9a620ea2d06e51c01b0864d7275b57d7203e5a"},{"author":{"_account_id":21813,"name":"Andrey Volkov","email":"m@amadev.ru","username":"avolkov"},"change_message_id":"ca480e5352e5c13df74daff6cbd5416526cc14d1","unresolved":false,"context_lines":[{"line_number":1171,"context_line":"            # the last one, which is the database name in the URL, not the"},{"line_number":1172,"context_line":"            # username."},{"line_number":1173,"context_line":"            connection \u003d connection.rstrip(url.database)"},{"line_number":1174,"context_line":"            return connection + cell0_db_name"},{"line_number":1175,"context_line":""},{"line_number":1176,"context_line":"        dbc \u003d database_connection or cell0_default_connection()"},{"line_number":1177,"context_line":"        ctxt \u003d context.RequestContext()"}],"source_content_type":"text/x-python","patch_set":4,"id":"1f013ff3_15404435","line":1174,"updated":"2017-05-12 19:18:56.000000000","message":"possibly can be replaced with:\nurl.database +\u003d \u0027_cell0\u0027\nreturn str(url)","commit_id":"9a9a620ea2d06e51c01b0864d7275b57d7203e5a"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"5d49d958d45babc8e9dd2d9d972bcdac8d93280d","unresolved":false,"context_lines":[{"line_number":1171,"context_line":"            # the last one, which is the database name in the URL, not the"},{"line_number":1172,"context_line":"            # username."},{"line_number":1173,"context_line":"            connection \u003d connection.rstrip(url.database)"},{"line_number":1174,"context_line":"            return connection + cell0_db_name"},{"line_number":1175,"context_line":""},{"line_number":1176,"context_line":"        dbc \u003d database_connection or cell0_default_connection()"},{"line_number":1177,"context_line":"        ctxt \u003d context.RequestContext()"}],"source_content_type":"text/x-python","patch_set":4,"id":"ff0f0b1f_27298437","line":1174,"in_reply_to":"1f013ff3_15404435","updated":"2017-05-19 23:02:52.000000000","message":"This doesn\u0027t work as stringifying the url encodes the special characters and in some cases blows up with a UnicodeDecodeError:\n\n\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\nFailed 4 tests - output below:\n\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\n\nnova.tests.unit.test_nova_manage.CellV2CommandsTestCase.test_map_cell0_default_database_special_characters_4_mysql_pymysql___nova_abcd0123_AB_controller_nova\n-------------------------------------------------------------------------------------------------------------------------------------------------------------\n\nCaptured traceback:\n~~~~~~~~~~~~~~~~~~~\n    Traceback (most recent call last):\n      File \"/home/user/git/nova/.tox/py27/local/lib/python2.7/site-packages/ddt.py\", line 139, in wrapper\n        return func(self, *args, **kwargs)\n      File \"nova/tests/unit/test_nova_manage.py\", line 1162, in test_map_cell0_default_database_special_characters\n        cell_mapping.database_connection)\n      File \"/home/user/git/nova/.tox/py27/local/lib/python2.7/site-packages/testtools/testcase.py\", line 411, in assertEqual\n        self.assertThat(observed, matcher, message)\n      File \"/home/user/git/nova/.tox/py27/local/lib/python2.7/site-packages/testtools/testcase.py\", line 498, in assertThat\n        raise mismatch_error\n    testtools.matchers._impl.MismatchError: !\u003d:\n    reference \u003d \u0027mysql+pymysql://nova:abcd0123/AB@controller/nova_cell0\u0027\n    actual    \u003d u\u0027mysql+pymysql://nova:abcd0123%2FAB@controller/nova_cell0\u0027\n    \n    \n\nnova.tests.unit.test_nova_manage.CellV2CommandsTestCase.test_map_cell0_default_database_special_characters_5_mysql_pymysql___test_abcd0123_AB_controller_nova\n-------------------------------------------------------------------------------------------------------------------------------------------------------------\n\nCaptured traceback:\n~~~~~~~~~~~~~~~~~~~\n    Traceback (most recent call last):\n      File \"/home/user/git/nova/.tox/py27/local/lib/python2.7/site-packages/ddt.py\", line 139, in wrapper\n        return func(self, *args, **kwargs)\n      File \"nova/tests/unit/test_nova_manage.py\", line 1155, in test_map_cell0_default_database_special_characters\n        self.commands.map_cell0()\n      File \"nova/cmd/manage.py\", line 1153, in map_cell0\n        self._map_cell0(database_connection\u003ddatabase_connection)\n      File \"nova/cmd/manage.py\", line 1184, in _map_cell0\n        database_connection\u003ddbc)\n      File \"/home/user/git/nova/.tox/py27/local/lib/python2.7/site-packages/oslo_versionedobjects/base.py\", line 307, in __init__\n        setattr(self, key, kwargs[key])\n      File \"/home/user/git/nova/.tox/py27/local/lib/python2.7/site-packages/oslo_versionedobjects/base.py\", line 72, in setter\n        field_value \u003d field.coerce(self, name, value)\n      File \"/home/user/git/nova/.tox/py27/local/lib/python2.7/site-packages/oslo_versionedobjects/fields.py\", line 195, in coerce\n        return self._type.coerce(obj, attr, value)\n      File \"/home/user/git/nova/.tox/py27/local/lib/python2.7/site-packages/oslo_versionedobjects/fields.py\", line 261, in coerce\n        return six.text_type(value)\n    UnicodeDecodeError: \u0027ascii\u0027 codec can\u0027t decode byte 0xab in position 29: ordinal not in range(128)\n    \n\nnova.tests.unit.test_nova_manage.CellV2CommandsTestCase.test_map_cell0_default_database_special_characters_1_mysql_pymysql___nova_abcd0123_AB_controller_nova\n-------------------------------------------------------------------------------------------------------------------------------------------------------------\n\nCaptured traceback:\n~~~~~~~~~~~~~~~~~~~\n    Traceback (most recent call last):\n      File \"/home/user/git/nova/.tox/py27/local/lib/python2.7/site-packages/ddt.py\", line 139, in wrapper\n        return func(self, *args, **kwargs)\n      File \"nova/tests/unit/test_nova_manage.py\", line 1162, in test_map_cell0_default_database_special_characters\n        cell_mapping.database_connection)\n      File \"/home/user/git/nova/.tox/py27/local/lib/python2.7/site-packages/testtools/testcase.py\", line 411, in assertEqual\n        self.assertThat(observed, matcher, message)\n      File \"/home/user/git/nova/.tox/py27/local/lib/python2.7/site-packages/testtools/testcase.py\", line 498, in assertThat\n        raise mismatch_error\n    testtools.matchers._impl.MismatchError: !\u003d:\n    reference \u003d \u0027mysql+pymysql://nova:abcd0123:AB@controller/nova_cell0\u0027\n    actual    \u003d u\u0027mysql+pymysql://nova:abcd0123%3AAB@controller/nova_cell0\u0027\n    \n    \n\nnova.tests.unit.test_nova_manage.CellV2CommandsTestCase.test_map_cell0_default_database_special_characters_3_mysql_pymysql___nova_abcd0123_AB_controller_nova\n-------------------------------------------------------------------------------------------------------------------------------------------------------------\n\nCaptured traceback:\n~~~~~~~~~~~~~~~~~~~\n    Traceback (most recent call last):\n      File \"/home/user/git/nova/.tox/py27/local/lib/python2.7/site-packages/ddt.py\", line 139, in wrapper\n        return func(self, *args, **kwargs)\n      File \"nova/tests/unit/test_nova_manage.py\", line 1162, in test_map_cell0_default_database_special_characters\n        cell_mapping.database_connection)\n      File \"/home/user/git/nova/.tox/py27/local/lib/python2.7/site-packages/testtools/testcase.py\", line 411, in assertEqual\n        self.assertThat(observed, matcher, message)\n      File \"/home/user/git/nova/.tox/py27/local/lib/python2.7/site-packages/testtools/testcase.py\", line 498, in assertThat\n        raise mismatch_error\n    testtools.matchers._impl.MismatchError: !\u003d:\n    reference \u003d \u0027mysql+pymysql://nova:abcd0123@AB@controller/nova_cell0\u0027\n    actual    \u003d u\u0027mysql+pymysql://nova:abcd0123%40AB@controller/nova_cell0\u0027\n    \n    \n\n\n\u003d\u003d\u003d\u003d\u003d\u003d\nTotals\n\u003d\u003d\u003d\u003d\u003d\u003d\nRan: 108 tests in 20.0000 sec.\n - Passed: 104\n - Skipped: 0\n - Expected Fail: 0\n - Unexpected Success: 0\n - Failed: 4\nSum of execute time for each test: 21.0831 sec.","commit_id":"9a9a620ea2d06e51c01b0864d7275b57d7203e5a"}]}
