)]}'
{"swiftclient/client.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"271d13eb9c35f4809713061e78cba7badc65417e","unresolved":false,"context_lines":[{"line_number":454,"context_line":"        old_getheader \u003d self.resp.raw.getheader"},{"line_number":455,"context_line":""},{"line_number":456,"context_line":"        def _decode_header(string):"},{"line_number":457,"context_line":"            if not string:"},{"line_number":458,"context_line":"                return string"},{"line_number":459,"context_line":"            if six.PY2:"},{"line_number":460,"context_line":"                return string.decode(\u0027utf-8\u0027)"}],"source_content_type":"text/x-python","patch_set":1,"id":"9f6a8fd7_5f280333","line":457,"range":{"start_line":457,"start_character":15,"end_line":457,"end_character":25},"updated":"2018-04-17 22:06:46.000000000","message":"I\u0027m guessing this is to cover None? Might be better to explicitly check is-None -- Otherwise py2 will *usually* return unicode, but will return bytes when blank.","commit_id":"4574351646669b40e35df2ed02284f0e831988c5"},{"author":{"_account_id":17363,"name":"Timur Alperovich","email":"timur@timuralp.com","username":"timuralp"},"change_message_id":"8b613ba0f55626d7d0cc05608c8587a398b25f90","unresolved":false,"context_lines":[{"line_number":454,"context_line":"        old_getheader \u003d self.resp.raw.getheader"},{"line_number":455,"context_line":""},{"line_number":456,"context_line":"        def _decode_header(string):"},{"line_number":457,"context_line":"            if not string:"},{"line_number":458,"context_line":"                return string"},{"line_number":459,"context_line":"            if six.PY2:"},{"line_number":460,"context_line":"                return string.decode(\u0027utf-8\u0027)"}],"source_content_type":"text/x-python","patch_set":1,"id":"9f6a8fd7_3f518f63","line":457,"range":{"start_line":457,"start_character":15,"end_line":457,"end_character":25},"in_reply_to":"9f6a8fd7_5f280333","updated":"2018-04-17 22:42:58.000000000","message":"Done","commit_id":"4574351646669b40e35df2ed02284f0e831988c5"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"271d13eb9c35f4809713061e78cba7badc65417e","unresolved":false,"context_lines":[{"line_number":458,"context_line":"                return string"},{"line_number":459,"context_line":"            if six.PY2:"},{"line_number":460,"context_line":"                return string.decode(\u0027utf-8\u0027)"},{"line_number":461,"context_line":"            return string.encode(\u0027iso-8859-1\u0027).decode(\u0027utf-8\u0027)"},{"line_number":462,"context_line":""},{"line_number":463,"context_line":"        def _encode_header(string):"},{"line_number":464,"context_line":"            if not string:"}],"source_content_type":"text/x-python","patch_set":1,"id":"9f6a8fd7_df9e5362","line":461,"range":{"start_line":461,"start_character":46,"end_line":461,"end_character":62},"updated":"2018-04-17 22:06:46.000000000","message":"What should we do if this fails? Even ignoring whatever crazy response we might get from some server *not running swift*, objects in swift can have non-utf8 metadata :-(\n\nI don\u0027t really have any recommendations -- I\u0027m certainly open to suggestions here.","commit_id":"4574351646669b40e35df2ed02284f0e831988c5"},{"author":{"_account_id":17363,"name":"Timur Alperovich","email":"timur@timuralp.com","username":"timuralp"},"change_message_id":"8b613ba0f55626d7d0cc05608c8587a398b25f90","unresolved":false,"context_lines":[{"line_number":458,"context_line":"                return string"},{"line_number":459,"context_line":"            if six.PY2:"},{"line_number":460,"context_line":"                return string.decode(\u0027utf-8\u0027)"},{"line_number":461,"context_line":"            return string.encode(\u0027iso-8859-1\u0027).decode(\u0027utf-8\u0027)"},{"line_number":462,"context_line":""},{"line_number":463,"context_line":"        def _encode_header(string):"},{"line_number":464,"context_line":"            if not string:"}],"source_content_type":"text/x-python","patch_set":1,"id":"9f6a8fd7_c22bdc7f","line":461,"range":{"start_line":461,"start_character":46,"end_line":461,"end_character":62},"in_reply_to":"9f6a8fd7_df9e5362","updated":"2018-04-17 22:42:58.000000000","message":"Good point. Currently, in Python 2, swiftclient will return the metadata URL-encoded as a unicode string. That seems like a reasonable thing we can do here?","commit_id":"4574351646669b40e35df2ed02284f0e831988c5"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"271d13eb9c35f4809713061e78cba7badc65417e","unresolved":false,"context_lines":[{"line_number":467,"context_line":"                if isinstance(string, unicode):"},{"line_number":468,"context_line":"                    return string.encode(\u0027utf-8\u0027)"},{"line_number":469,"context_line":"                return string"},{"line_number":470,"context_line":"            return string.encode(\u0027utf-8\u0027).decode(\u0027iso-8859-1\u0027)"},{"line_number":471,"context_line":""},{"line_number":472,"context_line":"        def getheaders():"},{"line_number":473,"context_line":"            return [(_decode_header(k), _decode_header(v))"}],"source_content_type":"text/x-python","patch_set":1,"id":"9f6a8fd7_1f228b53","line":470,"updated":"2018-04-17 22:06:46.000000000","message":"Man, I hate py3 and http...","commit_id":"4574351646669b40e35df2ed02284f0e831988c5"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"fcc7fbd8daa34ccce27f3a69ca4154e415844eaf","unresolved":false,"context_lines":[{"line_number":456,"context_line":"        def _decode_header(string):"},{"line_number":457,"context_line":"            if string is None or six.PY2:"},{"line_number":458,"context_line":"                return string"},{"line_number":459,"context_line":"            return string.encode(\u0027iso-8859-1\u0027)"},{"line_number":460,"context_line":""},{"line_number":461,"context_line":"        def _encode_header(string):"},{"line_number":462,"context_line":"            if string is None or six.PY2:"}],"source_content_type":"text/x-python","patch_set":2,"id":"5f7c97a3_78051d79","line":459,"updated":"2018-07-10 21:46:22.000000000","message":"Not\n\n string.encode(\u0027iso-8859-1\u0027).decode(\u0027utf8\u0027)\n\n? It seems weird that this doesn\u0027t mirror _encode_header...\n\nI guess it maybe hit complications with object metadata (which can be arbitrary bytes, not just UTF-8)? Would errors\u003d\u0027surrogateescape\u0027 help?\n\nAt any rate, I\u0027m not sure I like having headers always be bytes -- native strings seems better to me...","commit_id":"f6c730e73a1ba0868dce24cc9b2667bcedba969b"},{"author":{"_account_id":17363,"name":"Timur Alperovich","email":"timur@timuralp.com","username":"timuralp"},"change_message_id":"746974f52bc483d1a3a8223b9eccc59f967b2b7f","unresolved":false,"context_lines":[{"line_number":456,"context_line":"        def _decode_header(string):"},{"line_number":457,"context_line":"            if string is None or six.PY2:"},{"line_number":458,"context_line":"                return string"},{"line_number":459,"context_line":"            return string.encode(\u0027iso-8859-1\u0027)"},{"line_number":460,"context_line":""},{"line_number":461,"context_line":"        def _encode_header(string):"},{"line_number":462,"context_line":"            if string is None or six.PY2:"}],"source_content_type":"text/x-python","patch_set":2,"id":"5f7c97a3_39ab3571","line":459,"in_reply_to":"5f7c97a3_78051d79","updated":"2018-07-20 19:40:23.000000000","message":"Reworked the python3 part to return native strings. We should probably add a test case for the cases where object metadata is not a valid UTF-8 sequence, but I think we can defer that to another patch?","commit_id":"f6c730e73a1ba0868dce24cc9b2667bcedba969b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"6dcf1bd4673c9d84f44e3ae9832aa25c1ef5be31","unresolved":false,"context_lines":[{"line_number":458,"context_line":"        def _decode_header(string):"},{"line_number":459,"context_line":"            if string is None or six.PY2:"},{"line_number":460,"context_line":"                return string"},{"line_number":461,"context_line":"            return string.encode(\u0027iso-8859-1\u0027).decode(\u0027utf-8\u0027)"},{"line_number":462,"context_line":""},{"line_number":463,"context_line":"        def _encode_header(string):"},{"line_number":464,"context_line":"            if string is None or six.PY2:"}],"source_content_type":"text/x-python","patch_set":5,"id":"5f7c97a3_827f3fbb","line":461,"range":{"start_line":461,"start_character":47,"end_line":461,"end_character":62},"updated":"2018-07-24 06:24:40.000000000","message":"I\u0027m a little worried about what happens when this fails... But maybe the UnicodeDecodeError is tolerable? I certainly don\u0027t have a *better* idea...","commit_id":"f4a2b16c2cc65410765abdff7a45532305a4548f"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"6dcf1bd4673c9d84f44e3ae9832aa25c1ef5be31","unresolved":false,"context_lines":[{"line_number":528,"context_line":""},{"line_number":529,"context_line":"    auth_token \u003d resp.getheader(\u0027x-auth-token\u0027)"},{"line_number":530,"context_line":"    if auth_token is not None:"},{"line_number":531,"context_line":"        auth_token \u003d parse_header_string(auth_token)"},{"line_number":532,"context_line":"    return url, resp.getheader(\u0027x-storage-token\u0027, auth_token)"},{"line_number":533,"context_line":""},{"line_number":534,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"5f7c97a3_c2121762","line":531,"range":{"start_line":531,"start_character":21,"end_line":531,"end_character":52},"updated":"2018-07-24 06:24:40.000000000","message":"With line 713 below, won\u0027t this happen twice if the server only responds with x-auth-token (and not x-storage-token)?","commit_id":"f4a2b16c2cc65410765abdff7a45532305a4548f"},{"author":{"_account_id":17363,"name":"Timur Alperovich","email":"timur@timuralp.com","username":"timuralp"},"change_message_id":"e76cb3271f829d99a8fd0ff14513299134fcc9c6","unresolved":false,"context_lines":[{"line_number":528,"context_line":""},{"line_number":529,"context_line":"    auth_token \u003d resp.getheader(\u0027x-auth-token\u0027)"},{"line_number":530,"context_line":"    if auth_token is not None:"},{"line_number":531,"context_line":"        auth_token \u003d parse_header_string(auth_token)"},{"line_number":532,"context_line":"    return url, resp.getheader(\u0027x-storage-token\u0027, auth_token)"},{"line_number":533,"context_line":""},{"line_number":534,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"5f7c97a3_d3f09d95","line":531,"range":{"start_line":531,"start_character":21,"end_line":531,"end_character":52},"in_reply_to":"5f7c97a3_c2121762","updated":"2018-07-24 17:25:45.000000000","message":"True. Will remove line 713 change and move this validation into the get_auth_* functions. I need to check the keystone behavior in this case.","commit_id":"f4a2b16c2cc65410765abdff7a45532305a4548f"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"6dcf1bd4673c9d84f44e3ae9832aa25c1ef5be31","unresolved":false,"context_lines":[{"line_number":716,"context_line":"        return os_options[\u0027object_storage_url\u0027], token"},{"line_number":717,"context_line":"    else:"},{"line_number":718,"context_line":"        if storage_url is not None:"},{"line_number":719,"context_line":"            return parse_header_string(storage_url), token"},{"line_number":720,"context_line":"        return storage_url, token"},{"line_number":721,"context_line":""},{"line_number":722,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"5f7c97a3_a23fdbdd","line":719,"range":{"start_line":719,"start_character":19,"end_line":719,"end_character":51},"updated":"2018-07-24 06:24:40.000000000","message":"I thought the storage url came back from keystone in a JSON catalogue -- calling parse_header_string on it seems weird... Should we only do this for v1 responses?","commit_id":"f4a2b16c2cc65410765abdff7a45532305a4548f"},{"author":{"_account_id":17363,"name":"Timur Alperovich","email":"timur@timuralp.com","username":"timuralp"},"change_message_id":"e76cb3271f829d99a8fd0ff14513299134fcc9c6","unresolved":false,"context_lines":[{"line_number":716,"context_line":"        return os_options[\u0027object_storage_url\u0027], token"},{"line_number":717,"context_line":"    else:"},{"line_number":718,"context_line":"        if storage_url is not None:"},{"line_number":719,"context_line":"            return parse_header_string(storage_url), token"},{"line_number":720,"context_line":"        return storage_url, token"},{"line_number":721,"context_line":""},{"line_number":722,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"5f7c97a3_33255117","line":719,"range":{"start_line":719,"start_character":19,"end_line":719,"end_character":51},"in_reply_to":"5f7c97a3_a23fdbdd","updated":"2018-07-24 17:25:45.000000000","message":"Possibly! Will check the keystone behavior.","commit_id":"f4a2b16c2cc65410765abdff7a45532305a4548f"}],"tests/unit/test_swiftclient.py":[{"author":{"_account_id":330,"name":"John Dickinson","email":"me@not.mn","username":"notmyname"},"change_message_id":"9f5758bd81807d9a876e4765f323abfe5f62a500","unresolved":false,"context_lines":[{"line_number":1911,"context_line":""},{"line_number":1912,"context_line":"        resp \u003d conn.getresponse()"},{"line_number":1913,"context_line":"        with open(\u0027/tmp/foo\u0027, \u0027w\u0027) as tmp:"},{"line_number":1914,"context_line":"            tmp.write(\u0027raw: %s\u0027 % resp.getheaders())"},{"line_number":1915,"context_line":"        self.assertEqual("},{"line_number":1916,"context_line":"            \u0027\\xd8\\xaa-value\u0027, resp.getheader(\u0027\\xd8\\xaa-unicode\u0027))"},{"line_number":1917,"context_line":"        self.assertEqual("}],"source_content_type":"text/x-python","patch_set":3,"id":"5f7c97a3_853437fc","line":1914,"updated":"2018-07-23 18:17:10.000000000","message":"looks like leftover printf debugging","commit_id":"3005161fc47935a4a9ef61745f262b50c4ba65ff"},{"author":{"_account_id":17363,"name":"Timur Alperovich","email":"timur@timuralp.com","username":"timuralp"},"change_message_id":"f21b711d61d386784e2eaf6bb385f91aa3844484","unresolved":false,"context_lines":[{"line_number":1911,"context_line":""},{"line_number":1912,"context_line":"        resp \u003d conn.getresponse()"},{"line_number":1913,"context_line":"        with open(\u0027/tmp/foo\u0027, \u0027w\u0027) as tmp:"},{"line_number":1914,"context_line":"            tmp.write(\u0027raw: %s\u0027 % resp.getheaders())"},{"line_number":1915,"context_line":"        self.assertEqual("},{"line_number":1916,"context_line":"            \u0027\\xd8\\xaa-value\u0027, resp.getheader(\u0027\\xd8\\xaa-unicode\u0027))"},{"line_number":1917,"context_line":"        self.assertEqual("}],"source_content_type":"text/x-python","patch_set":3,"id":"5f7c97a3_409ccd5b","line":1914,"in_reply_to":"5f7c97a3_853437fc","updated":"2018-07-23 18:40:19.000000000","message":"Done","commit_id":"3005161fc47935a4a9ef61745f262b50c4ba65ff"},{"author":{"_account_id":330,"name":"John Dickinson","email":"me@not.mn","username":"notmyname"},"change_message_id":"9f5758bd81807d9a876e4765f323abfe5f62a500","unresolved":false,"context_lines":[{"line_number":1939,"context_line":""},{"line_number":1940,"context_line":"        resp \u003d conn.getresponse()"},{"line_number":1941,"context_line":"        with open(\u0027/tmp/foo\u0027, \u0027w\u0027) as tmp:"},{"line_number":1942,"context_line":"            tmp.write(\u0027raw: %s\u0027 % resp.headers)"},{"line_number":1943,"context_line":"        self.assertEqual("},{"line_number":1944,"context_line":"            \u0027\\u062a-value\u0027, resp.getheader(\u0027\\u062a-unicode\u0027))"},{"line_number":1945,"context_line":"        self.assertEqual("}],"source_content_type":"text/x-python","patch_set":3,"id":"5f7c97a3_a53933f2","line":1942,"updated":"2018-07-23 18:17:10.000000000","message":"same","commit_id":"3005161fc47935a4a9ef61745f262b50c4ba65ff"},{"author":{"_account_id":17363,"name":"Timur Alperovich","email":"timur@timuralp.com","username":"timuralp"},"change_message_id":"f21b711d61d386784e2eaf6bb385f91aa3844484","unresolved":false,"context_lines":[{"line_number":1939,"context_line":""},{"line_number":1940,"context_line":"        resp \u003d conn.getresponse()"},{"line_number":1941,"context_line":"        with open(\u0027/tmp/foo\u0027, \u0027w\u0027) as tmp:"},{"line_number":1942,"context_line":"            tmp.write(\u0027raw: %s\u0027 % resp.headers)"},{"line_number":1943,"context_line":"        self.assertEqual("},{"line_number":1944,"context_line":"            \u0027\\u062a-value\u0027, resp.getheader(\u0027\\u062a-unicode\u0027))"},{"line_number":1945,"context_line":"        self.assertEqual("}],"source_content_type":"text/x-python","patch_set":3,"id":"5f7c97a3_6099c969","line":1942,"in_reply_to":"5f7c97a3_a53933f2","updated":"2018-07-23 18:40:19.000000000","message":"Done","commit_id":"3005161fc47935a4a9ef61745f262b50c4ba65ff"},{"author":{"_account_id":330,"name":"John Dickinson","email":"me@not.mn","username":"notmyname"},"change_message_id":"9f5758bd81807d9a876e4765f323abfe5f62a500","unresolved":false,"context_lines":[{"line_number":2901,"context_line":"            [\u0027GET\u0027, path], {}, MockHttpResponse(status\u003d200, headers\u003d[]), \u0027\u0027)"},{"line_number":2902,"context_line":"        request_log_line \u003d mock_log.mock_calls[0]"},{"line_number":2903,"context_line":"        with open(\u0027/tmp/foo\u0027, \u0027w\u0027) as f:"},{"line_number":2904,"context_line":"            f.write(str(request_log_line.__dict__))"},{"line_number":2905,"context_line":"        self.assertEqual(\u0027REQ: %s\u0027, request_log_line[1][0])"},{"line_number":2906,"context_line":"        self.assertEqual(u\u0027curl -i -X GET %s\u0027 % path, request_log_line[1][1])"},{"line_number":2907,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"5f7c97a3_252523c0","line":2904,"updated":"2018-07-23 18:17:10.000000000","message":"same","commit_id":"3005161fc47935a4a9ef61745f262b50c4ba65ff"},{"author":{"_account_id":17363,"name":"Timur Alperovich","email":"timur@timuralp.com","username":"timuralp"},"change_message_id":"f21b711d61d386784e2eaf6bb385f91aa3844484","unresolved":false,"context_lines":[{"line_number":2901,"context_line":"            [\u0027GET\u0027, path], {}, MockHttpResponse(status\u003d200, headers\u003d[]), \u0027\u0027)"},{"line_number":2902,"context_line":"        request_log_line \u003d mock_log.mock_calls[0]"},{"line_number":2903,"context_line":"        with open(\u0027/tmp/foo\u0027, \u0027w\u0027) as f:"},{"line_number":2904,"context_line":"            f.write(str(request_log_line.__dict__))"},{"line_number":2905,"context_line":"        self.assertEqual(\u0027REQ: %s\u0027, request_log_line[1][0])"},{"line_number":2906,"context_line":"        self.assertEqual(u\u0027curl -i -X GET %s\u0027 % path, request_log_line[1][1])"},{"line_number":2907,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"5f7c97a3_00a6d5ad","line":2904,"in_reply_to":"5f7c97a3_252523c0","updated":"2018-07-23 18:40:19.000000000","message":"Done","commit_id":"3005161fc47935a4a9ef61745f262b50c4ba65ff"}]}
