)]}'
{"swiftclient/client.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"bb66abf747549299f9875f8c399db6e111baa861","unresolved":false,"context_lines":[{"line_number":336,"context_line":"        msg \u003d \u0027Unauthorized. Check username, password and tenant name/id.\u0027"},{"line_number":337,"context_line":"        if auth_version in AUTH_VERSIONS_V3:"},{"line_number":338,"context_line":"            msg \u003d (\u0027Unauthorized. Check username/id, password, \u0027"},{"line_number":339,"context_line":"                   \u0027tenant name/id and user/tenant domain name/id.\u0027)"},{"line_number":340,"context_line":"        raise ClientException(msg)"},{"line_number":341,"context_line":"    except exceptions.AuthorizationFailure as err:"},{"line_number":342,"context_line":"        raise ClientException(\u0027Authorization Failure. %s\u0027 % err)"}],"source_content_type":"text/x-python","patch_set":3,"id":"5a890539_061675f1","line":339,"updated":"2014-11-12 22:28:01.000000000","message":"better.","commit_id":"68cab6f2a23d94cafb1e3328baebb4db33877903"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"bb66abf747549299f9875f8c399db6e111baa861","unresolved":false,"context_lines":[{"line_number":386,"context_line":"        # We are handling a special use case here where the user argument"},{"line_number":387,"context_line":"        # specifies both the user name and tenant name in the form tenant:user"},{"line_number":388,"context_line":"        if user and not kwargs.get(\u0027tenant_name\u0027) and \u0027:\u0027 in user:"},{"line_number":389,"context_line":"            os_options[\u0027tenant_name\u0027], user \u003d user.split(\u0027:\u0027)"},{"line_number":390,"context_line":""},{"line_number":391,"context_line":"        # We are allowing to have an tenant_name argument in get_auth"},{"line_number":392,"context_line":"        # directly without having os_options"}],"source_content_type":"text/x-python","patch_set":3,"id":"5a890539_46d79d23","line":389,"updated":"2014-11-12 22:28:01.000000000","message":"fine.","commit_id":"68cab6f2a23d94cafb1e3328baebb4db33877903"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"bb66abf747549299f9875f8c399db6e111baa861","unresolved":false,"context_lines":[{"line_number":462,"context_line":"        while listing:"},{"line_number":463,"context_line":"            marker \u003d listing[-1][\u0027name\u0027]"},{"line_number":464,"context_line":"            listing \u003d get_account(url, token, marker, limit, prefix,"},{"line_number":465,"context_line":"                                  end_marker, http_conn)[1]"},{"line_number":466,"context_line":"            if listing:"},{"line_number":467,"context_line":"                rv[1].extend(listing)"},{"line_number":468,"context_line":"        return rv"}],"source_content_type":"text/x-python","patch_set":3,"id":"5a890539_86e18500","line":465,"updated":"2014-11-12 22:28:01.000000000","message":"better.","commit_id":"68cab6f2a23d94cafb1e3328baebb4db33877903"},{"author":{"_account_id":9216,"name":"Joel Wright","email":"joel.wright@gmail.com","username":"jjw-sohonet"},"change_message_id":"63caad35d5a712f709e755b80511a394068a9f02","unresolved":false,"context_lines":[{"line_number":982,"context_line":"    if hasattr(contents, \u0027read\u0027):"},{"line_number":983,"context_line":"        if chunk_size is None:"},{"line_number":984,"context_line":"            chunk_size \u003d 65536"},{"line_number":985,"context_line":"        if content_length is None:"},{"line_number":986,"context_line":"            class md5_chunk_gen(object):"},{"line_number":987,"context_line":"                def __init__(self, content, chunk_size\u003dchunk_size):"},{"line_number":988,"context_line":"                    self.content \u003d content"}],"source_content_type":"text/x-python","patch_set":3,"id":"5a890539_60738ae7","line":985,"updated":"2014-11-13 13:27:59.000000000","message":"Perhaps it would be better to only calculate the md5sum on the fly if the given etag is None, rather than content_length?","commit_id":"68cab6f2a23d94cafb1e3328baebb4db33877903"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"bb66abf747549299f9875f8c399db6e111baa861","unresolved":false,"context_lines":[{"line_number":1003,"context_line":"                    return self.__next__()"},{"line_number":1004,"context_line":""},{"line_number":1005,"context_line":"                def __iter__(self):"},{"line_number":1006,"context_line":"                    return self"},{"line_number":1007,"context_line":""},{"line_number":1008,"context_line":"            chunk_reader \u003d md5_chunk_gen(contents, chunk_size)"},{"line_number":1009,"context_line":"            conn.putrequest(path, headers\u003dheaders, data\u003dchunk_reader)"}],"source_content_type":"text/x-python","patch_set":3,"id":"5a890539_0119ff78","line":1006,"updated":"2014-11-12 22:28:01.000000000","message":"maybe this would look better as a utility class next LengthWrapper instead of an inline def?","commit_id":"68cab6f2a23d94cafb1e3328baebb4db33877903"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"bb66abf747549299f9875f8c399db6e111baa861","unresolved":false,"context_lines":[{"line_number":1012,"context_line":"            # Fixes https://github.com/kennethreitz/requests/issues/1648"},{"line_number":1013,"context_line":"            data \u003d LengthWrapper(contents, content_length)"},{"line_number":1014,"context_line":"            conn.putrequest(path, headers\u003dheaders, data\u003ddata)"},{"line_number":1015,"context_line":"            md5sum \u003d data.get_md5sum()"},{"line_number":1016,"context_line":"    else:"},{"line_number":1017,"context_line":"        if chunk_size is not None:"},{"line_number":1018,"context_line":"            warn_msg \u003d (\u0027%s object has no \"read\" method, ignoring chunk_size\u0027"}],"source_content_type":"text/x-python","patch_set":3,"id":"5a890539_a6ca014d","line":1015,"updated":"2014-11-12 22:28:01.000000000","message":"where does a LengthWrapper get a get_md5sum method from? (!)","commit_id":"68cab6f2a23d94cafb1e3328baebb4db33877903"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"bb66abf747549299f9875f8c399db6e111baa861","unresolved":false,"context_lines":[{"line_number":1016,"context_line":"    else:"},{"line_number":1017,"context_line":"        if chunk_size is not None:"},{"line_number":1018,"context_line":"            warn_msg \u003d (\u0027%s object has no \"read\" method, ignoring chunk_size\u0027"},{"line_number":1019,"context_line":"                        % type(contents).__name__)"},{"line_number":1020,"context_line":"            warnings.warn(warn_msg, stacklevel\u003d2)"},{"line_number":1021,"context_line":"        conn.request(\u0027PUT\u0027, path, contents, headers)"},{"line_number":1022,"context_line":"        md5sum \u003d None"}],"source_content_type":"text/x-python","patch_set":3,"id":"5a890539_46e15dcf","line":1019,"updated":"2014-11-12 22:28:01.000000000","message":"better","commit_id":"68cab6f2a23d94cafb1e3328baebb4db33877903"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"bb66abf747549299f9875f8c399db6e111baa861","unresolved":false,"context_lines":[{"line_number":1041,"context_line":"                              http_scheme\u003dparsed.scheme,"},{"line_number":1042,"context_line":"                              http_host\u003dconn.host, http_path\u003dpath,"},{"line_number":1043,"context_line":"                              http_status\u003dresp.status, http_reason\u003dresp.reason,"},{"line_number":1044,"context_line":"                              http_response_content\u003dbody)"},{"line_number":1045,"context_line":""},{"line_number":1046,"context_line":"    return etag"},{"line_number":1047,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"5a890539_66e819b5","line":1044,"updated":"2014-11-12 22:28:01.000000000","message":"seems reasonable; but isn\u0027t this why the return signature is etag?  maybe it\u0027s better to not give the client the option of ignoring it...","commit_id":"68cab6f2a23d94cafb1e3328baebb4db33877903"},{"author":{"_account_id":9216,"name":"Joel Wright","email":"joel.wright@gmail.com","username":"jjw-sohonet"},"change_message_id":"63caad35d5a712f709e755b80511a394068a9f02","unresolved":false,"context_lines":[{"line_number":1041,"context_line":"                              http_scheme\u003dparsed.scheme,"},{"line_number":1042,"context_line":"                              http_host\u003dconn.host, http_path\u003dpath,"},{"line_number":1043,"context_line":"                              http_status\u003dresp.status, http_reason\u003dresp.reason,"},{"line_number":1044,"context_line":"                              http_response_content\u003dbody)"},{"line_number":1045,"context_line":""},{"line_number":1046,"context_line":"    return etag"},{"line_number":1047,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"5a890539_00a1e646","line":1044,"in_reply_to":"5a890539_66e819b5","updated":"2014-11-13 13:27:59.000000000","message":"It might be nice if the error made it more clear that the upload did not match the expected md5sum, but there is now an object stored that is using storage space.","commit_id":"68cab6f2a23d94cafb1e3328baebb4db33877903"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"da76c03363fc0f7046e1ac5815e578513f57e672","unresolved":false,"context_lines":[{"line_number":1002,"context_line":"            warn_msg \u003d \u0027%s object has no \\\"read\\\" method, ignoring chunk_size\u0027\\"},{"line_number":1003,"context_line":"                % type(contents).__name__"},{"line_number":1004,"context_line":"            warnings.warn(warn_msg, stacklevel\u003d2)"},{"line_number":1005,"context_line":"        conn.request(\u0027PUT\u0027, path, contents, headers)"},{"line_number":1006,"context_line":"    resp \u003d conn.getresponse()"},{"line_number":1007,"context_line":"    body \u003d resp.read()"},{"line_number":1008,"context_line":"    headers \u003d {\u0027X-Auth-Token\u0027: token}"}],"source_content_type":"text/x-python","patch_set":5,"id":"5a890539_1afcdc71","side":"PARENT","line":1005,"updated":"2014-11-22 00:57:32.000000000","message":"I don\u0027t understand the justification for punting on the on the string or iterable /non-readable case?\n\nThis behavior of this method is already getting convoluted as to when you should expect the returned etag to be validated and exception raised on mismatch (and the value of the exception message depending on who did the validation) or when the etag validation is left to caller.\n\nnit: In fact, to illuminate just how complex this contract is I think the doc string needs to be updated - except that looking at what\u0027s there now I continue to think it\u0027s obvious that this method is a low level wrapper around the HTTP request that should *not* be attempting this kind of validation - highlighted by the fact it\u0027s signature allows you to supply either an iterable, or a readable, and returns the etag - it\u0027s trying to leave the approach for etag validation up to the caller.  The Md5ing utility class is good, document it and make it available to people using the bindings, and then make our command line client use it (probably in service.SwiftService._upload_object_job - which could use some refactoring anyway)","commit_id":"202bbab2d06b9ef751fba306effd09f3bae8f383"},{"author":{"_account_id":13470,"name":"Daniel Wakefield","email":"dan@danw.eu","username":"danw"},"change_message_id":"9d5e406ef5de005f00ff0e60a20e170181285cd7","unresolved":false,"context_lines":[{"line_number":1002,"context_line":"            warn_msg \u003d \u0027%s object has no \\\"read\\\" method, ignoring chunk_size\u0027\\"},{"line_number":1003,"context_line":"                % type(contents).__name__"},{"line_number":1004,"context_line":"            warnings.warn(warn_msg, stacklevel\u003d2)"},{"line_number":1005,"context_line":"        conn.request(\u0027PUT\u0027, path, contents, headers)"},{"line_number":1006,"context_line":"    resp \u003d conn.getresponse()"},{"line_number":1007,"context_line":"    body \u003d resp.read()"},{"line_number":1008,"context_line":"    headers \u003d {\u0027X-Auth-Token\u0027: token}"}],"source_content_type":"text/x-python","patch_set":5,"id":"5a890539_f2b634f8","side":"PARENT","line":1005,"in_reply_to":"5a890539_1afcdc71","updated":"2014-11-24 17:05:11.000000000","message":"This doesnt (shouldnt?) accept an iterable. The doc string state a filelike object, a string or None.\n\nFilelike is handled by ChunkIter or LengthWrapper depending on content length being passed in.\n\nNone and string are handled here and I assume requests does an empty PUT (is it a POST if it has no content?) if it is None otherwise it sends the string as is.\n\nI can see its getting a bit complicated and will update the doc string to match whatever behavior we decide on.\n\nIf im reading it right you\u0027d like all the md5 related stuff removed from this class, still using the md5 calculating classes with verify\u003dFalse, \nand add the option for the content param to be a ChunkIter or LengthWrapper \ninstance that has already been initialized to verify\u003dTrue \nand that the client can use to get the md5 as needed.\n\nIf thats right then yes that does sound better at the expense of needing some more test reworks but thats ok with me.","commit_id":"202bbab2d06b9ef751fba306effd09f3bae8f383"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d83359cf9af3efaa31f6ebe43647dca766d75b77","unresolved":false,"context_lines":[{"line_number":1002,"context_line":"            warn_msg \u003d \u0027%s object has no \\\"read\\\" method, ignoring chunk_size\u0027\\"},{"line_number":1003,"context_line":"                % type(contents).__name__"},{"line_number":1004,"context_line":"            warnings.warn(warn_msg, stacklevel\u003d2)"},{"line_number":1005,"context_line":"        conn.request(\u0027PUT\u0027, path, contents, headers)"},{"line_number":1006,"context_line":"    resp \u003d conn.getresponse()"},{"line_number":1007,"context_line":"    body \u003d resp.read()"},{"line_number":1008,"context_line":"    headers \u003d {\u0027X-Auth-Token\u0027: token}"}],"source_content_type":"text/x-python","patch_set":5,"id":"5a890539_d5a8428e","side":"PARENT","line":1005,"in_reply_to":"5a890539_f2b634f8","updated":"2014-11-24 17:49:48.000000000","message":"idk, I think it works like this on purpose - there may be tests for it...\n\n    In [19]: client.put_object(url, token, \u0027test\u0027, \u0027test\u0027, iter([\u0027awesome\u0027]))\n    Out[19]: \u0027be121740bf988b2225a313fa1f107ca1\u0027\n\n    In [20]: meta, body \u003d client.get_object(url, token, \u0027test\u0027, \u0027test\u0027)\n\n    In [21]: meta[\u0027etag\u0027], body\n    Out[21]: (\u0027be121740bf988b2225a313fa1f107ca1\u0027, \u0027awesome\u0027)\n\nYou *are* reading what I\u0027m saying right passing in the content param as a md5ing thing and then having the caller check the return value (except for LengthWrapper, it has to stay in here for the content-length option to work right, requests (used to at least) always read to EOF regardless of content-length option, which clients use for segmented uploads.) - but I\u0027m not sure how much believe myself anymore that it\u0027s important it work that way - it\u0027s just apparent to me that\u0027s how the interface was imagined originally.\n\nIf you go for it watch out handing in an iterable (vs readable), I\u0027d guess the requests lib will again ignore the content-length option and segmented uploads will read too much...","commit_id":"202bbab2d06b9ef751fba306effd09f3bae8f383"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"da76c03363fc0f7046e1ac5815e578513f57e672","unresolved":false,"context_lines":[{"line_number":986,"context_line":"        if chunk_size is None:"},{"line_number":987,"context_line":"            chunk_size \u003d 65536"},{"line_number":988,"context_line":"        if content_length is None:"},{"line_number":989,"context_line":"            chunk_reader \u003d ChunkIter(contents, chunk_size, check_md5)"},{"line_number":990,"context_line":"            conn.putrequest(path, headers\u003dheaders, data\u003dchunk_reader)"},{"line_number":991,"context_line":"            md5sum \u003d chunk_reader.get_md5sum()"},{"line_number":992,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":5,"id":"5a890539_dabb34e3","line":989,"updated":"2014-11-22 00:57:32.000000000","message":"nit: I think the name here should indicate that it\u0027s also converting a readable to an iterable.","commit_id":"5b083afe790abb5905c4e48059b671b8452e0c81"},{"author":{"_account_id":13470,"name":"Daniel Wakefield","email":"dan@danw.eu","username":"danw"},"change_message_id":"519c8676451a39fa9508681ecb56a71c81cd4862","unresolved":false,"context_lines":[{"line_number":986,"context_line":"        if chunk_size is None:"},{"line_number":987,"context_line":"            chunk_size \u003d 65536"},{"line_number":988,"context_line":"        if content_length is None:"},{"line_number":989,"context_line":"            chunk_reader \u003d ChunkIter(contents, chunk_size, check_md5)"},{"line_number":990,"context_line":"            conn.putrequest(path, headers\u003dheaders, data\u003dchunk_reader)"},{"line_number":991,"context_line":"            md5sum \u003d chunk_reader.get_md5sum()"},{"line_number":992,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":5,"id":"5a890539_ea02c20a","line":989,"in_reply_to":"5a890539_dabb34e3","updated":"2014-11-24 13:37:31.000000000","message":"Done","commit_id":"5b083afe790abb5905c4e48059b671b8452e0c81"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"e0159dae72a728d9c48c0133904269f72c0f9c27","unresolved":false,"context_lines":[{"line_number":987,"context_line":"        if content_length is None:"},{"line_number":988,"context_line":"            data \u003d ReadableToIterable(contents, chunk_size, md5\u003dFalse)"},{"line_number":989,"context_line":"        else:"},{"line_number":990,"context_line":"            data \u003d LengthWrapper(contents, content_length, md5\u003dFalse)"},{"line_number":991,"context_line":""},{"line_number":992,"context_line":"        conn.putrequest(path, headers\u003dheaders, data\u003ddata)"},{"line_number":993,"context_line":"    else:"}],"source_content_type":"text/x-python","patch_set":6,"id":"5a890539_6f42006a","line":990,"updated":"2014-11-26 21:36:30.000000000","message":"This is an interesting compromise!  we get to reuse the existing tools but just tell them to skip the extra md5ing, quite useful when an etag is supplied to caller I think.  I rather like it!","commit_id":"d6b52c7aed4b90bfcf147c7c3419a65e469875ef"}],"swiftclient/service.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"d6c757fdce92d8905d1854b20a187d947ba9e282","unresolved":false,"context_lines":[{"line_number":1031,"context_line":"            else:"},{"line_number":1032,"context_line":"                with fp:"},{"line_number":1033,"context_line":"                    md5sum \u003d get_md5_sum(fp)"},{"line_number":1034,"context_line":"                    req_headers[\u0027If-None-Match\u0027] \u003d md5sum"},{"line_number":1035,"context_line":""},{"line_number":1036,"context_line":"        try:"},{"line_number":1037,"context_line":"            start_time \u003d time()"}],"source_content_type":"text/x-python","patch_set":1,"id":"9aa7fdbe_154730bd","line":1034,"updated":"2014-10-24 14:10:53.000000000","message":"nit: no need for the md5sum variable, just set the header on one line","commit_id":"beba9fd24c13b9971d4ec522913df7f1287dfe6a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"bb66abf747549299f9875f8c399db6e111baa861","unresolved":false,"context_lines":[{"line_number":264,"context_line":"        else:"},{"line_number":265,"context_line":"            if source.hasattr(\u0027read\u0027) or source is None:"},{"line_number":266,"context_line":"                if (object_name is None"},{"line_number":267,"context_line":"                        or not isinstance(object_name, string_types)):"},{"line_number":268,"context_line":"                    raise SwiftError("},{"line_number":269,"context_line":"                        \"Object names must be specified as strings for uploads\""},{"line_number":270,"context_line":"                        \" from None or file like objects.\""}],"source_content_type":"text/x-python","patch_set":3,"id":"5a890539_c6cc6d64","line":267,"updated":"2014-11-12 22:28:01.000000000","message":"fine.","commit_id":"68cab6f2a23d94cafb1e3328baebb4db33877903"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"bb66abf747549299f9875f8c399db6e111baa861","unresolved":false,"context_lines":[{"line_number":314,"context_line":"        self._expected_etag \u003d headers.get(\u0027etag\u0027)"},{"line_number":315,"context_line":""},{"line_number":316,"context_line":"        if (\u0027x-object-manifest\u0027 not in headers"},{"line_number":317,"context_line":"                and \u0027x-static-large-object\u0027 not in headers):"},{"line_number":318,"context_line":"            self.actual_md5 \u003d md5()"},{"line_number":319,"context_line":""},{"line_number":320,"context_line":"        if \u0027content-length\u0027 in headers:"}],"source_content_type":"text/x-python","patch_set":3,"id":"5a890539_a6d121fd","line":317,"updated":"2014-11-12 22:28:01.000000000","message":"fine.","commit_id":"68cab6f2a23d94cafb1e3328baebb4db33877903"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"bb66abf747549299f9875f8c399db6e111baa861","unresolved":false,"context_lines":[{"line_number":333,"context_line":"                )"},{"line_number":334,"context_line":""},{"line_number":335,"context_line":"        if (self._content_length is not None"},{"line_number":336,"context_line":"                and self._actual_read !\u003d self._content_length):"},{"line_number":337,"context_line":"            raise SwiftError("},{"line_number":338,"context_line":"                \u0027Error downloading %s: read_length !\u003d content_length, \u0027"},{"line_number":339,"context_line":"                \u0027%d !\u003d %d\u0027 % (self._path, self._actual_read,"}],"source_content_type":"text/x-python","patch_set":3,"id":"5a890539_06d755ee","line":336,"updated":"2014-11-12 22:28:01.000000000","message":"jeez, fine.","commit_id":"68cab6f2a23d94cafb1e3328baebb4db33877903"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"bb66abf747549299f9875f8c399db6e111baa861","unresolved":false,"context_lines":[{"line_number":570,"context_line":"            else:"},{"line_number":571,"context_line":"                response_dict \u003d {}"},{"line_number":572,"context_line":"                headers \u003d split_headers(options[\u0027meta\u0027], \u0027X-Account-Meta-\u0027)"},{"line_number":573,"context_line":"                headers.update(split_headers(options[\u0027header\u0027], \u0027\u0027))"},{"line_number":574,"context_line":"                res[\u0027headers\u0027] \u003d headers"},{"line_number":575,"context_line":"                try:"},{"line_number":576,"context_line":"                    post \u003d self.thread_manager.container_pool.submit("}],"source_content_type":"text/x-python","patch_set":3,"id":"5a890539_2605317a","line":573,"updated":"2014-11-12 22:28:01.000000000","message":"fine.","commit_id":"68cab6f2a23d94cafb1e3328baebb4db33877903"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"bb66abf747549299f9875f8c399db6e111baa861","unresolved":false,"context_lines":[{"line_number":1187,"context_line":"        _header \u003d split_headers(options[\"header\"])"},{"line_number":1188,"context_line":"        if POLICY in _header:"},{"line_number":1189,"context_line":"            policy_header[POLICY] \u003d _header[POLICY]"},{"line_number":1190,"context_line":""},{"line_number":1191,"context_line":"        create_containers \u003d ["},{"line_number":1192,"context_line":"            self.thread_manager.container_pool.submit("},{"line_number":1193,"context_line":"                self._create_container_job, container, headers\u003dpolicy_header"}],"source_content_type":"text/x-python","patch_set":3,"id":"5a890539_66ff3968","line":1190,"updated":"2014-11-12 22:28:01.000000000","message":"fine.","commit_id":"68cab6f2a23d94cafb1e3328baebb4db33877903"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"bb66abf747549299f9875f8c399db6e111baa861","unresolved":false,"context_lines":[{"line_number":1407,"context_line":"                if (ct.split(\u0027;\u0027, 1)[0] \u003d\u003d \u0027text/directory\u0027"},{"line_number":1408,"context_line":"                        and cl \u003d\u003d 0"},{"line_number":1409,"context_line":"                        and et \u003d\u003d _empty_string_etag"},{"line_number":1410,"context_line":"                        and mt \u003d\u003d put_headers[\u0027x-object-meta-mtime\u0027]):"},{"line_number":1411,"context_line":"                    res[\u0027success\u0027] \u003d True"},{"line_number":1412,"context_line":"                    return res"},{"line_number":1413,"context_line":"            except ClientException as err:"}],"source_content_type":"text/x-python","patch_set":3,"id":"5a890539_06ee75b4","line":1410,"updated":"2014-11-12 22:28:01.000000000","message":"yeah... ok, that\u0027s probably better.","commit_id":"68cab6f2a23d94cafb1e3328baebb4db33877903"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"e0159dae72a728d9c48c0133904269f72c0f9c27","unresolved":false,"context_lines":[{"line_number":1730,"context_line":"                    raise SwiftError(\u0027Object upload failed: remote and local \u0027"},{"line_number":1731,"context_line":"                                     \u0027object md5 did not match, {0} !\u003d {1}\\n\u0027"},{"line_number":1732,"context_line":"                                     \u0027remote object has has been removed.\u0027"},{"line_number":1733,"context_line":"                                     .format(etag, contents.get_md5sum()))"},{"line_number":1734,"context_line":""},{"line_number":1735,"context_line":"            if old_manifest or old_slo_manifest_paths:"},{"line_number":1736,"context_line":"                if old_manifest:"}],"source_content_type":"text/x-python","patch_set":6,"id":"5a890539_af74e8d0","line":1733,"updated":"2014-11-26 21:36:30.000000000","message":"argh!  s/has has/has not/ ?","commit_id":"d6b52c7aed4b90bfcf147c7c3419a65e469875ef"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"05c7b75f613a1b77a3b230c64a6acc54e4bae859","unresolved":false,"context_lines":[{"line_number":1479,"context_line":"                                   content_length\u003dsegment_size,"},{"line_number":1480,"context_line":"                                   response_dict\u003dresults_dict)"},{"line_number":1481,"context_line":""},{"line_number":1482,"context_line":"            if etag and etag !\u003d contents.get_md5sum():"},{"line_number":1483,"context_line":"                raise SwiftError(\u0027Segment upload failed: remote and local \u0027"},{"line_number":1484,"context_line":"                                 \u0027object md5 did not match, {0} !\u003d {1}\\n\u0027"},{"line_number":1485,"context_line":"                                 \u0027remote segment has not been removed.\u0027"}],"source_content_type":"text/x-python","patch_set":7,"id":"5a890539_690f6e39","line":1482,"updated":"2014-12-05 01:56:57.000000000","message":"hrmm... i added a name error here and all tests still passed :\\","commit_id":"1ee31bac6f81c36eda0be9e327180b7a725c257f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"05c7b75f613a1b77a3b230c64a6acc54e4bae859","unresolved":false,"context_lines":[{"line_number":1480,"context_line":"                                   response_dict\u003dresults_dict)"},{"line_number":1481,"context_line":""},{"line_number":1482,"context_line":"            if etag and etag !\u003d contents.get_md5sum():"},{"line_number":1483,"context_line":"                raise SwiftError(\u0027Segment upload failed: remote and local \u0027"},{"line_number":1484,"context_line":"                                 \u0027object md5 did not match, {0} !\u003d {1}\\n\u0027"},{"line_number":1485,"context_line":"                                 \u0027remote segment has not been removed.\u0027"},{"line_number":1486,"context_line":"                                 .format(etag, contents.get_md5sum()))"}],"source_content_type":"text/x-python","patch_set":7,"id":"5a890539_2932c60f","line":1483,"updated":"2014-12-05 01:56:57.000000000","message":"hrmm.... I added a name error here and all tests still passed :\\","commit_id":"1ee31bac6f81c36eda0be9e327180b7a725c257f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"05c7b75f613a1b77a3b230c64a6acc54e4bae859","unresolved":false,"context_lines":[{"line_number":1710,"context_line":"            else:"},{"line_number":1711,"context_line":"                res[\u0027large_object\u0027] \u003d False"},{"line_number":1712,"context_line":"                obr \u003d {}"},{"line_number":1713,"context_line":"                if path is not None:"},{"line_number":1714,"context_line":"                    content_length \u003d getsize(path)"},{"line_number":1715,"context_line":"                    contents \u003d LengthWrapper(open(path, \u0027rb\u0027),"},{"line_number":1716,"context_line":"                                             content_length,"}],"source_content_type":"text/x-python","patch_set":7,"id":"5a890539_24002d00","line":1713,"updated":"2014-12-05 01:56:57.000000000","message":"seems to get hit with test upload","commit_id":"1ee31bac6f81c36eda0be9e327180b7a725c257f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"05c7b75f613a1b77a3b230c64a6acc54e4bae859","unresolved":false,"context_lines":[{"line_number":1715,"context_line":"                    contents \u003d LengthWrapper(open(path, \u0027rb\u0027),"},{"line_number":1716,"context_line":"                                             content_length,"},{"line_number":1717,"context_line":"                                             md5\u003dTrue)"},{"line_number":1718,"context_line":"                else:"},{"line_number":1719,"context_line":"                    content_length \u003d None"},{"line_number":1720,"context_line":"                    contents \u003d ReadableToIterable(stream, md5\u003dTrue)"},{"line_number":1721,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"5a890539_6406b51d","line":1718,"updated":"2014-12-05 01:56:57.000000000","message":"branch may not be covered :\\","commit_id":"1ee31bac6f81c36eda0be9e327180b7a725c257f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"05c7b75f613a1b77a3b230c64a6acc54e4bae859","unresolved":false,"context_lines":[{"line_number":1726,"context_line":"                )"},{"line_number":1727,"context_line":"                res[\u0027response_dict\u0027] \u003d obr"},{"line_number":1728,"context_line":""},{"line_number":1729,"context_line":"                if etag and etag !\u003d contents.get_md5sum():"},{"line_number":1730,"context_line":"                    raise SwiftError(\u0027Object upload failed: remote and local \u0027"},{"line_number":1731,"context_line":"                                     \u0027object md5 did not match, {0} !\u003d {1}\\n\u0027"},{"line_number":1732,"context_line":"                                     \u0027remote object has not been removed.\u0027"}],"source_content_type":"text/x-python","patch_set":7,"id":"5a890539_8912da5e","line":1729,"updated":"2014-12-05 01:56:57.000000000","message":"oh god here too!","commit_id":"1ee31bac6f81c36eda0be9e327180b7a725c257f"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5434cbd8a472adf1bfc53a143d68b6a39b24b7f6","unresolved":false,"context_lines":[{"line_number":1477,"context_line":"                raise SwiftError(\u0027Segment upload failed: remote and local \u0027"},{"line_number":1478,"context_line":"                                 \u0027object md5 did not match, {0} !\u003d {1}\\n\u0027"},{"line_number":1479,"context_line":"                                 \u0027remote segment has not been removed.\u0027"},{"line_number":1480,"context_line":"                                 .format(etag, contents.get_md5sum()))"},{"line_number":1481,"context_line":""},{"line_number":1482,"context_line":"            res.update({"},{"line_number":1483,"context_line":"                \u0027success\u0027: True,"}],"source_content_type":"text/x-python","patch_set":13,"id":"ba7be1f8_9aa680c0","line":1480,"updated":"2015-02-20 14:44:21.000000000","message":"See comment below re \\n\n\nAlso, I see:\n\u0027Aborting manifest creation because not all segments could be uploaded.\u0027\n\nI wonder if we could return the segment index with segment error - that way just one segment could be re-uploaded?","commit_id":"f0300e3714e0d8cdd0ed9e4744b813e3b263d034"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5434cbd8a472adf1bfc53a143d68b6a39b24b7f6","unresolved":false,"context_lines":[{"line_number":1724,"context_line":"                    raise SwiftError(\u0027Object upload failed: remote and local \u0027"},{"line_number":1725,"context_line":"                                     \u0027object md5 did not match, {0} !\u003d {1}\\n\u0027"},{"line_number":1726,"context_line":"                                     \u0027remote object has not been removed.\u0027"},{"line_number":1727,"context_line":"                                     .format(etag, contents.get_md5sum()))"},{"line_number":1728,"context_line":""},{"line_number":1729,"context_line":"            if old_manifest or old_slo_manifest_paths:"},{"line_number":1730,"context_line":"                drs \u003d []"}],"source_content_type":"text/x-python","patch_set":13,"id":"ba7be1f8_ba26e466","line":1727,"updated":"2015-02-20 14:44:21.000000000","message":"I see the \\n on printed stderr i.e. not a newline.\n\nAlso \u0027upload failed\u0027 could be misleading - the file was uploaded, but failed verification, as borne out by the warning that the object has not been removed. Hat to word smith but how about:\n\nObject upload verification failed: md5 mismatch, local {0} !\u003d remote {1}","commit_id":"f0300e3714e0d8cdd0ed9e4744b813e3b263d034"}],"swiftclient/utils.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"bb66abf747549299f9875f8c399db6e111baa861","unresolved":false,"context_lines":[{"line_number":118,"context_line":"        return self._length"},{"line_number":119,"context_line":""},{"line_number":120,"context_line":"    def get_md5sum(self):"},{"line_number":121,"context_line":"        return self.md5sum.hexdigest()"},{"line_number":122,"context_line":""},{"line_number":123,"context_line":"    def read(self, *args, **kwargs):"},{"line_number":124,"context_line":"        if self._remaining \u003c\u003d 0:"}],"source_content_type":"text/x-python","patch_set":3,"id":"5a890539_66365954","line":121,"updated":"2014-11-12 22:28:01.000000000","message":"oh, i guess it got it from here.","commit_id":"68cab6f2a23d94cafb1e3328baebb4db33877903"},{"author":{"_account_id":9216,"name":"Joel Wright","email":"joel.wright@gmail.com","username":"jjw-sohonet"},"change_message_id":"63caad35d5a712f709e755b80511a394068a9f02","unresolved":false,"context_lines":[{"line_number":126,"context_line":"        chunk \u003d self._readable.read("},{"line_number":127,"context_line":"            *args, **kwargs)[:self._remaining]"},{"line_number":128,"context_line":"        self._remaining -\u003d len(chunk)"},{"line_number":129,"context_line":"        try:"},{"line_number":130,"context_line":"            self.md5sum.update(chunk)"},{"line_number":131,"context_line":"        except TypeError:"},{"line_number":132,"context_line":"            self.md5sum.update(chunk.encode())"}],"source_content_type":"text/x-python","patch_set":3,"id":"5a890539_0014864c","line":129,"updated":"2014-11-13 13:27:59.000000000","message":"Related to my comment in client.py, a \"don\u0027t calculate the md5sum\" option for the case where an etag was supplied to put_object would be required here if we take that approach...","commit_id":"68cab6f2a23d94cafb1e3328baebb4db33877903"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"bb66abf747549299f9875f8c399db6e111baa861","unresolved":false,"context_lines":[{"line_number":130,"context_line":"            self.md5sum.update(chunk)"},{"line_number":131,"context_line":"        except TypeError:"},{"line_number":132,"context_line":"            self.md5sum.update(chunk.encode())"},{"line_number":133,"context_line":""},{"line_number":134,"context_line":"        return chunk"}],"source_content_type":"text/x-python","patch_set":3,"id":"5a890539_660d7990","line":133,"updated":"2014-11-12 22:28:01.000000000","message":"there\u0027s a thing with read method that returns unicode!?  lol @ python3 io.TextIOWrapper - i love the notion that developers don\u0027t want to think about encoding because it\u0027s too hard and we can just stick our heads in the sand and pretend that for the last 70 years of computers they\u0027ve been storing *strings* instead of bytes [1]\n\n1. https://docs.python.org/2/library/io.html#performance","commit_id":"68cab6f2a23d94cafb1e3328baebb4db33877903"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"da76c03363fc0f7046e1ac5815e578513f57e672","unresolved":false,"context_lines":[{"line_number":115,"context_line":"        pass"},{"line_number":116,"context_line":""},{"line_number":117,"context_line":"    def hexdigest(self, *a, **kw):"},{"line_number":118,"context_line":"        return \u0027\u0027"},{"line_number":119,"context_line":""},{"line_number":120,"context_line":""},{"line_number":121,"context_line":"class ChunkIter(object):"}],"source_content_type":"text/x-python","patch_set":5,"id":"5a890539_9aefecb0","line":118,"updated":"2014-11-22 00:57:32.000000000","message":"nit: hrmm... is this really the right thing to do?  Maybe None to indicate it\u0027s not really an valid etag, or raise an exception - it\u0027s probably never reasonable to consider this return value as valid or useful in any context.","commit_id":"5b083afe790abb5905c4e48059b671b8452e0c81"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d83359cf9af3efaa31f6ebe43647dca766d75b77","unresolved":false,"context_lines":[{"line_number":115,"context_line":"        pass"},{"line_number":116,"context_line":""},{"line_number":117,"context_line":"    def hexdigest(self, *a, **kw):"},{"line_number":118,"context_line":"        return \u0027\u0027"},{"line_number":119,"context_line":""},{"line_number":120,"context_line":""},{"line_number":121,"context_line":"class ChunkIter(object):"}],"source_content_type":"text/x-python","patch_set":5,"id":"5a890539_75a4ee4a","line":118,"in_reply_to":"5a890539_8aa77e0a","updated":"2014-11-24 17:49:48.000000000","message":"yeah you\u0027re right, i was wrong about the exception for sure.  #retract","commit_id":"5b083afe790abb5905c4e48059b671b8452e0c81"},{"author":{"_account_id":13470,"name":"Daniel Wakefield","email":"dan@danw.eu","username":"danw"},"change_message_id":"519c8676451a39fa9508681ecb56a71c81cd4862","unresolved":false,"context_lines":[{"line_number":115,"context_line":"        pass"},{"line_number":116,"context_line":""},{"line_number":117,"context_line":"    def hexdigest(self, *a, **kw):"},{"line_number":118,"context_line":"        return \u0027\u0027"},{"line_number":119,"context_line":""},{"line_number":120,"context_line":""},{"line_number":121,"context_line":"class ChunkIter(object):"}],"source_content_type":"text/x-python","patch_set":5,"id":"5a890539_8aa77e0a","line":118,"in_reply_to":"5a890539_9aefecb0","updated":"2014-11-24 13:37:31.000000000","message":"Im not sure. The duck typing means that it is evaluated as False and therefore isnt tested to be a match against the server response etag but it also allows any future string operations that may be applied to the generated MD5 to be valid as well. \n\n+0 for returns None. Might be clearer that the value is a Noop.\n\n-1 for an exception. Having to wrap all calls to hexdigest rather than just testing the returned values truth-ness seems a bit extreme.","commit_id":"5b083afe790abb5905c4e48059b671b8452e0c81"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"da76c03363fc0f7046e1ac5815e578513f57e672","unresolved":false,"context_lines":[{"line_number":118,"context_line":"        return \u0027\u0027"},{"line_number":119,"context_line":""},{"line_number":120,"context_line":""},{"line_number":121,"context_line":"class ChunkIter(object):"},{"line_number":122,"context_line":"    def __init__(self, content, chunk_size\u003d65536, md5\u003dTrue):"},{"line_number":123,"context_line":"        self.content \u003d content"},{"line_number":124,"context_line":"        self.md5sum \u003d hashlib.md5() if md5 else NoopMD5()"}],"source_content_type":"text/x-python","patch_set":5,"id":"5a890539_3a01986a","line":121,"updated":"2014-11-22 00:57:32.000000000","message":"nit: doc string maybe, I could see this being consumed directly.","commit_id":"5b083afe790abb5905c4e48059b671b8452e0c81"},{"author":{"_account_id":13470,"name":"Daniel Wakefield","email":"dan@danw.eu","username":"danw"},"change_message_id":"519c8676451a39fa9508681ecb56a71c81cd4862","unresolved":false,"context_lines":[{"line_number":118,"context_line":"        return \u0027\u0027"},{"line_number":119,"context_line":""},{"line_number":120,"context_line":""},{"line_number":121,"context_line":"class ChunkIter(object):"},{"line_number":122,"context_line":"    def __init__(self, content, chunk_size\u003d65536, md5\u003dTrue):"},{"line_number":123,"context_line":"        self.content \u003d content"},{"line_number":124,"context_line":"        self.md5sum \u003d hashlib.md5() if md5 else NoopMD5()"}],"source_content_type":"text/x-python","patch_set":5,"id":"5a890539_8a7e9e68","line":121,"in_reply_to":"5a890539_3a01986a","updated":"2014-11-24 13:37:31.000000000","message":"Done","commit_id":"5b083afe790abb5905c4e48059b671b8452e0c81"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"da76c03363fc0f7046e1ac5815e578513f57e672","unresolved":false,"context_lines":[{"line_number":131,"context_line":"        chunk \u003d self.content.read(self.chunk_size)"},{"line_number":132,"context_line":"        if not chunk:"},{"line_number":133,"context_line":"            raise StopIteration"},{"line_number":134,"context_line":"        self.md5sum.update(chunk)"},{"line_number":135,"context_line":"        return chunk"},{"line_number":136,"context_line":""},{"line_number":137,"context_line":"    def next(self):"}],"source_content_type":"text/x-python","patch_set":5,"id":"5a890539_7a008034","line":134,"updated":"2014-11-22 00:57:32.000000000","message":"if chunk is unicode as is most likely the case in python3 you should encode here before you update your md5 guy.","commit_id":"5b083afe790abb5905c4e48059b671b8452e0c81"},{"author":{"_account_id":13470,"name":"Daniel Wakefield","email":"dan@danw.eu","username":"danw"},"change_message_id":"519c8676451a39fa9508681ecb56a71c81cd4862","unresolved":false,"context_lines":[{"line_number":131,"context_line":"        chunk \u003d self.content.read(self.chunk_size)"},{"line_number":132,"context_line":"        if not chunk:"},{"line_number":133,"context_line":"            raise StopIteration"},{"line_number":134,"context_line":"        self.md5sum.update(chunk)"},{"line_number":135,"context_line":"        return chunk"},{"line_number":136,"context_line":""},{"line_number":137,"context_line":"    def next(self):"}],"source_content_type":"text/x-python","patch_set":5,"id":"5a890539_aa251ac3","line":134,"in_reply_to":"5a890539_7a008034","updated":"2014-11-24 13:37:31.000000000","message":"These are only used to wrap files. All files opened for upload by Service are done as \"rb\" so I\u0027m not sure that encoding is needed here. \n\nOf course if anyone has based something on the client API and passes in files not opened as binary they will be caught out by this if running on python3,\nSo ill add something like below just in case.\n\ntry:\n    if self.encode_chunks:\n        chunk \u003d chunk.encode()\n    self.md5sum.update(chunk)\nexcept TypeError:\n    self.encode_chunks \u003d True\n    self.md5sum.update(chunk.encode())","commit_id":"5b083afe790abb5905c4e48059b671b8452e0c81"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d83359cf9af3efaa31f6ebe43647dca766d75b77","unresolved":false,"context_lines":[{"line_number":131,"context_line":"        chunk \u003d self.content.read(self.chunk_size)"},{"line_number":132,"context_line":"        if not chunk:"},{"line_number":133,"context_line":"            raise StopIteration"},{"line_number":134,"context_line":"        self.md5sum.update(chunk)"},{"line_number":135,"context_line":"        return chunk"},{"line_number":136,"context_line":""},{"line_number":137,"context_line":"    def next(self):"}],"source_content_type":"text/x-python","patch_set":5,"id":"5a890539_d596823d","line":134,"in_reply_to":"5a890539_aa251ac3","updated":"2014-11-24 17:49:48.000000000","message":"That\u0027s a good idea!  IMHO, you could drop the LBYL check and always fall back to the slower exception case \"for backwards compat\" - just put something in the doc string that strongly suggests you use it with binary files.","commit_id":"5b083afe790abb5905c4e48059b671b8452e0c81"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"da76c03363fc0f7046e1ac5815e578513f57e672","unresolved":false,"context_lines":[{"line_number":142,"context_line":""},{"line_number":143,"context_line":""},{"line_number":144,"context_line":"class LengthWrapper(object):"},{"line_number":145,"context_line":"    def __init__(self, readable, length, md5\u003dTrue):"},{"line_number":146,"context_line":"        self._length \u003d self._remaining \u003d length"},{"line_number":147,"context_line":"        self._readable \u003d readable"},{"line_number":148,"context_line":"        self.md5sum \u003d hashlib.md5() if md5 else NoopMD5()"}],"source_content_type":"text/x-python","patch_set":5,"id":"5a890539_1a33fc62","line":145,"updated":"2014-11-22 00:57:32.000000000","message":"nit: man this signature looks frightening similar to ChunkIter.  Should we just always convert to a md5ing-iterable and sometimes make it smart enough to truncate a readable at length rather than having two things that do md5ing?","commit_id":"5b083afe790abb5905c4e48059b671b8452e0c81"},{"author":{"_account_id":13470,"name":"Daniel Wakefield","email":"dan@danw.eu","username":"danw"},"change_message_id":"519c8676451a39fa9508681ecb56a71c81cd4862","unresolved":false,"context_lines":[{"line_number":142,"context_line":""},{"line_number":143,"context_line":""},{"line_number":144,"context_line":"class LengthWrapper(object):"},{"line_number":145,"context_line":"    def __init__(self, readable, length, md5\u003dTrue):"},{"line_number":146,"context_line":"        self._length \u003d self._remaining \u003d length"},{"line_number":147,"context_line":"        self._readable \u003d readable"},{"line_number":148,"context_line":"        self.md5sum \u003d hashlib.md5() if md5 else NoopMD5()"}],"source_content_type":"text/x-python","patch_set":5,"id":"5a890539_2ad4ca1e","line":145,"in_reply_to":"5a890539_1a33fc62","updated":"2014-11-24 13:37:31.000000000","message":"I\u0027ll have to check the requests code again, This was designed to get around a bug (feature?) in its interface which I think depends on the detection of either an \"__iter__\" or \"read\" method so Im not sure if they could be merged.","commit_id":"5b083afe790abb5905c4e48059b671b8452e0c81"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d83359cf9af3efaa31f6ebe43647dca766d75b77","unresolved":false,"context_lines":[{"line_number":142,"context_line":""},{"line_number":143,"context_line":""},{"line_number":144,"context_line":"class LengthWrapper(object):"},{"line_number":145,"context_line":"    def __init__(self, readable, length, md5\u003dTrue):"},{"line_number":146,"context_line":"        self._length \u003d self._remaining \u003d length"},{"line_number":147,"context_line":"        self._readable \u003d readable"},{"line_number":148,"context_line":"        self.md5sum \u003d hashlib.md5() if md5 else NoopMD5()"}],"source_content_type":"text/x-python","patch_set":5,"id":"5a890539_15400aa4","line":145,"in_reply_to":"5a890539_2ad4ca1e","updated":"2014-11-24 17:49:48.000000000","message":"I have some memory of this...\n\nAfter the requests lib refactor segmented uploads were broke for awhile, it was embarassing and I think it\u0027s what prompted the swiftclient functional test suite although I don\u0027t honestly think I know how those work :\\\n\nOur cli would hand in open file pointers seeked out to the middle of the file and give a content-length as the value of upload off the fp.  It would sort of arrange these requests to make a segmented object.  Only requests lib was reading till EOF (ignoring the content-length option/header).  So the final swift large object was too big.  This wraps the body passed in to limit the readable bytes to content-length so that our method continued to work according to the doc string.","commit_id":"5b083afe790abb5905c4e48059b671b8452e0c81"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"da76c03363fc0f7046e1ac5815e578513f57e672","unresolved":false,"context_lines":[{"line_number":158,"context_line":"            return \u0027\u0027"},{"line_number":159,"context_line":"        chunk \u003d self._readable.read(*args, **kwargs)[:self._remaining]"},{"line_number":160,"context_line":"        self._remaining -\u003d len(chunk)"},{"line_number":161,"context_line":"        self.md5sum.update(chunk)"},{"line_number":162,"context_line":""},{"line_number":163,"context_line":"        return chunk"}],"source_content_type":"text/x-python","patch_set":5,"id":"5a890539_baf6685b","line":161,"updated":"2014-11-22 00:57:32.000000000","message":"if chunk is unicode as is most likely the case in python3 you should encode here before you update your md5 guy.","commit_id":"5b083afe790abb5905c4e48059b671b8452e0c81"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d83359cf9af3efaa31f6ebe43647dca766d75b77","unresolved":false,"context_lines":[{"line_number":158,"context_line":"            return \u0027\u0027"},{"line_number":159,"context_line":"        chunk \u003d self._readable.read(*args, **kwargs)[:self._remaining]"},{"line_number":160,"context_line":"        self._remaining -\u003d len(chunk)"},{"line_number":161,"context_line":"        self.md5sum.update(chunk)"},{"line_number":162,"context_line":""},{"line_number":163,"context_line":"        return chunk"}],"source_content_type":"text/x-python","patch_set":5,"id":"5a890539_35526667","line":161,"in_reply_to":"5a890539_baf6685b","updated":"2014-11-24 17:49:48.000000000","message":"Really this is one that changes an existing interface.  Since it\u0027s new, you could probably just say the ChunkIter just *has* to be used with binary readables (but you might wanna doc it that way).  Of course here, if you could somehow pull the md5ing out of the LengthWrapper entirely that might also be good...","commit_id":"5b083afe790abb5905c4e48059b671b8452e0c81"}],"tests/unit/test_service.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"d6c757fdce92d8905d1854b20a187d947ba9e282","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright (c) 2010-2013 OpenStack, LLC."},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"# Licensed under the Apache License, Version 2.0 (the \"License\");"},{"line_number":4,"context_line":"# you may not use this file except in compliance with the License."}],"source_content_type":"text/x-python","patch_set":1,"id":"9aa7fdbe_d0c5b68e","line":1,"updated":"2014-10-24 14:10:53.000000000","message":"its 2014 :)","commit_id":"beba9fd24c13b9971d4ec522913df7f1287dfe6a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5434cbd8a472adf1bfc53a143d68b6a39b24b7f6","unresolved":false,"context_lines":[{"line_number":554,"context_line":""},{"line_number":555,"context_line":"class TestServiceUpload(testtools.TestCase):"},{"line_number":556,"context_line":""},{"line_number":557,"context_line":"    def _assertDictEqual(self, a, b, m\u003dNone):"},{"line_number":558,"context_line":"        # assertDictEqual is not available in py2.6 so use a shallow check"},{"line_number":559,"context_line":"        # instead"},{"line_number":560,"context_line":"        if not m:"}],"source_content_type":"text/x-python","patch_set":13,"id":"ba7be1f8_37aa0d1a","line":557,"updated":"2015-02-20 14:44:21.000000000","message":"nit: we have one of these in TestServiceDelete too. Time for a base class?","commit_id":"f0300e3714e0d8cdd0ed9e4744b813e3b263d034"},{"author":{"_account_id":9216,"name":"Joel Wright","email":"joel.wright@gmail.com","username":"jjw-sohonet"},"change_message_id":"aeff70b871c46e67c49d7b3641c632c1b8fff6c3","unresolved":false,"context_lines":[{"line_number":554,"context_line":""},{"line_number":555,"context_line":"class TestServiceUpload(testtools.TestCase):"},{"line_number":556,"context_line":""},{"line_number":557,"context_line":"    def _assertDictEqual(self, a, b, m\u003dNone):"},{"line_number":558,"context_line":"        # assertDictEqual is not available in py2.6 so use a shallow check"},{"line_number":559,"context_line":"        # instead"},{"line_number":560,"context_line":"        if not m:"}],"source_content_type":"text/x-python","patch_set":13,"id":"ba7be1f8_9f6ad918","line":557,"in_reply_to":"ba7be1f8_37aa0d1a","updated":"2015-02-21 01:06:38.000000000","message":"I have added a TestServiceBase class in the memory usage patch here https://review.openstack.org/#/c/130339/\n\nI\u0027d happily do the refactoring as part of that patch to save holding this one up (assuming that gets accepted of course!).","commit_id":"f0300e3714e0d8cdd0ed9e4744b813e3b263d034"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5434cbd8a472adf1bfc53a143d68b6a39b24b7f6","unresolved":false,"context_lines":[{"line_number":664,"context_line":""},{"line_number":665,"context_line":"    def test_upload_object_job_file(self):"},{"line_number":666,"context_line":"        # Uploading a file results in the file object being wrapped in a"},{"line_number":667,"context_line":"        # LengthWrapper. This test sets the options is such a way that much"},{"line_number":668,"context_line":"        # of _upload_object_job is skipped bringing the critical path down"},{"line_number":669,"context_line":"        # to around 60 lines to ease testing."},{"line_number":670,"context_line":"        with tempfile.NamedTemporaryFile() as f:"}],"source_content_type":"text/x-python","patch_set":13,"id":"ba7be1f8_b7b43df3","line":667,"updated":"2015-02-20 14:44:21.000000000","message":"s/is/in/","commit_id":"f0300e3714e0d8cdd0ed9e4744b813e3b263d034"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5434cbd8a472adf1bfc53a143d68b6a39b24b7f6","unresolved":false,"context_lines":[{"line_number":666,"context_line":"        # Uploading a file results in the file object being wrapped in a"},{"line_number":667,"context_line":"        # LengthWrapper. This test sets the options is such a way that much"},{"line_number":668,"context_line":"        # of _upload_object_job is skipped bringing the critical path down"},{"line_number":669,"context_line":"        # to around 60 lines to ease testing."},{"line_number":670,"context_line":"        with tempfile.NamedTemporaryFile() as f:"},{"line_number":671,"context_line":"            f.write(b\u0027a\u0027 * 30)"},{"line_number":672,"context_line":"            f.flush()"}],"source_content_type":"text/x-python","patch_set":13,"id":"ba7be1f8_f7cdd587","line":669,"updated":"2015-02-20 14:44:21.000000000","message":"yup. that method is ripe for refactoring :) and then test coverage for the other 150+ lines","commit_id":"f0300e3714e0d8cdd0ed9e4744b813e3b263d034"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5434cbd8a472adf1bfc53a143d68b6a39b24b7f6","unresolved":false,"context_lines":[{"line_number":701,"context_line":"            # Check for mtime and path separately as they are calculated"},{"line_number":702,"context_line":"            # from the temp file and will be different each time."},{"line_number":703,"context_line":"            mtime \u003d float(r[\u0027headers\u0027][\u0027x-object-meta-mtime\u0027])"},{"line_number":704,"context_line":"            self.assertAlmostEqual(mtime, expected_mtime, delta\u003d1)"},{"line_number":705,"context_line":"            del r[\u0027headers\u0027][\u0027x-object-meta-mtime\u0027]"},{"line_number":706,"context_line":""},{"line_number":707,"context_line":"            self.assertEqual(r[\u0027path\u0027], f.name)"}],"source_content_type":"text/x-python","patch_set":13,"id":"ba7be1f8_371a0d18","line":704,"updated":"2015-02-20 14:44:21.000000000","message":"i must be missing something in your comment, but aren\u0027t we expecting them to be exactly equal in this case ?","commit_id":"f0300e3714e0d8cdd0ed9e4744b813e3b263d034"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5434cbd8a472adf1bfc53a143d68b6a39b24b7f6","unresolved":false,"context_lines":[{"line_number":718,"context_line":"            self.assertIsInstance(contents, utils.LengthWrapper)"},{"line_number":719,"context_line":"            self.assertEqual(len(contents), 30)"},{"line_number":720,"context_line":"            # This read forces the LengthWrapper to calculate the md5"},{"line_number":721,"context_line":"            # for the read content."},{"line_number":722,"context_line":"            self.assertEqual(contents.read(), b\u0027a\u0027 * 30)"},{"line_number":723,"context_line":"            self.assertEqual(contents.get_md5sum(), md5(b\u0027a\u0027 * 30).hexdigest())"},{"line_number":724,"context_line":""}],"source_content_type":"text/x-python","patch_set":13,"id":"ba7be1f8_b7999d70","line":721,"updated":"2015-02-20 14:44:21.000000000","message":"ok so as a side effect we\u0027re checking that the LengthWrapper was init\u0027d with md5 \u003d True","commit_id":"f0300e3714e0d8cdd0ed9e4744b813e3b263d034"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5434cbd8a472adf1bfc53a143d68b6a39b24b7f6","unresolved":false,"context_lines":[{"line_number":758,"context_line":"                                              \u0027segment_size\u0027: 0})"},{"line_number":759,"context_line":""},{"line_number":760,"context_line":"            mtime \u003d float(r[\u0027headers\u0027][\u0027x-object-meta-mtime\u0027])"},{"line_number":761,"context_line":"            self.assertAlmostEqual(mtime, expected_mtime, delta\u003d10)"},{"line_number":762,"context_line":"            del r[\u0027headers\u0027][\u0027x-object-meta-mtime\u0027]"},{"line_number":763,"context_line":""},{"line_number":764,"context_line":"            self._assertDictEqual(r, expected_r)"}],"source_content_type":"text/x-python","patch_set":13,"id":"ba7be1f8_376ccd9c","line":761,"updated":"2015-02-20 14:44:21.000000000","message":"not sure this achieves much, and wouldn\u0027t we expect mtime \u003e\u003d expected_time?","commit_id":"f0300e3714e0d8cdd0ed9e4744b813e3b263d034"}],"tests/unit/test_swiftclient.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"bb66abf747549299f9875f8c399db6e111baa861","unresolved":false,"context_lines":[{"line_number":110,"context_line":"        self.reason \u003d \"OK\""},{"line_number":111,"context_line":"        self.buffer \u003d []"},{"line_number":112,"context_line":"        self.requests_params \u003d None"},{"line_number":113,"context_line":"        self.headers \u003d {\u0027etag\u0027: \u0027d41d8cd98f00b204e9800998ecf8427e\u0027}"},{"line_number":114,"context_line":"        if headers:"},{"line_number":115,"context_line":"            self.headers.update(headers)"},{"line_number":116,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"5a890539_e1b9532f","line":113,"updated":"2014-11-12 22:28:01.000000000","message":"can you label this as the zero byte hash?\n\nalso, doesn\u0027t it need to have double quotes around it to match the real response returned by swift?","commit_id":"68cab6f2a23d94cafb1e3328baebb4db33877903"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"bb66abf747549299f9875f8c399db6e111baa861","unresolved":false,"context_lines":[{"line_number":158,"context_line":""},{"line_number":159,"context_line":"        for k, v in kw[\u0027headers\u0027].items():"},{"line_number":160,"context_line":"            self.buffer.append((k, v))"},{"line_number":161,"context_line":""},{"line_number":162,"context_line":"        return self.fake_response()"},{"line_number":163,"context_line":""},{"line_number":164,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"5a890539_61a64312","line":161,"updated":"2014-11-12 22:28:01.000000000","message":"maybe this would be clearer if you used super?  I think it\u0027d also be reasonable to just add this to the standard class - or maybe better to have the default etag based on the body attribute?  I wonder if it would be better to do all of this in tests.unit.utils.fake_http_connect instead of keeping two ways of doing things.  In particular if the base implementation would return an etag header based on the body of the response (unless it\u0027s overridden explicitly with an etag param) I think that be a pretty good improvement to the fake.","commit_id":"68cab6f2a23d94cafb1e3328baebb4db33877903"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"bb66abf747549299f9875f8c399db6e111baa861","unresolved":false,"context_lines":[{"line_number":746,"context_line":"        req_data \u003d resp.requests_params[\u0027data\u0027]"},{"line_number":747,"context_line":"        self.assertTrue(isinstance(req_data, swiftclient.utils.LengthWrapper))"},{"line_number":748,"context_line":"        self.assertEqual(raw_data_len, len(req_data.read()))"},{"line_number":749,"context_line":"        self.assertEqual(req_data.get_md5sum(), md5(raw_data).hexdigest())"},{"line_number":750,"context_line":""},{"line_number":751,"context_line":"    def test_chunk_upload(self):"},{"line_number":752,"context_line":"        # Chunked upload happens when no content_length is passed to put_object"}],"source_content_type":"text/x-python","patch_set":3,"id":"5a890539_66b73987","line":749,"updated":"2014-11-12 22:28:01.000000000","message":"so this second test is just to verify that put_object behaves the same if called with content_length\u003dx and headers\u003d{\u0027content-length\u0027: x} ?","commit_id":"68cab6f2a23d94cafb1e3328baebb4db33877903"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"bb66abf747549299f9875f8c399db6e111baa861","unresolved":false,"context_lines":[{"line_number":773,"context_line":""},{"line_number":774,"context_line":"    def test_md5_mismatch(self):"},{"line_number":775,"context_line":"        conn \u003d c.http_connection(u\u0027http://www.test.com\u0027)"},{"line_number":776,"context_line":"        resp \u003d ConsumingResponse(status\u003d200)"},{"line_number":777,"context_line":"        conn[1].getresponse \u003d resp.fake_response"},{"line_number":778,"context_line":"        conn[1]._request \u003d resp._fake_request"},{"line_number":779,"context_line":"        raw_data \u003d (\u0027asdf\u0027 * 256).encode()  # 68a3c26adeabceba5250b8ba8e3f45a2"}],"source_content_type":"text/x-python","patch_set":3,"id":"5a890539_26645121","line":776,"updated":"2014-11-12 22:28:01.000000000","message":"what etag is ConsumingResponse returning here?","commit_id":"68cab6f2a23d94cafb1e3328baebb4db33877903"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"da76c03363fc0f7046e1ac5815e578513f57e672","unresolved":false,"context_lines":[{"line_number":132,"context_line":"        self.status \u003d 200"},{"line_number":133,"context_line":"        self.requests_params \u003d kwarg"},{"line_number":134,"context_line":"        # This simulate previous httplib implementation that would do a"},{"line_number":135,"context_line":"        # putrequest() and then use putheader() to send header."},{"line_number":136,"context_line":"        for k, v in kwarg[\u0027headers\u0027].items():"},{"line_number":137,"context_line":"            self.buffer.append((k, v))"},{"line_number":138,"context_line":"        return self.fake_response()"}],"source_content_type":"text/x-python","patch_set":5,"id":"5a890539_5a4024a5","side":"PARENT","line":135,"updated":"2014-11-22 00:57:32.000000000","message":"this comment seems mis-placed now?","commit_id":"202bbab2d06b9ef751fba306effd09f3bae8f383"},{"author":{"_account_id":13470,"name":"Daniel Wakefield","email":"dan@danw.eu","username":"danw"},"change_message_id":"519c8676451a39fa9508681ecb56a71c81cd4862","unresolved":false,"context_lines":[{"line_number":132,"context_line":"        self.status \u003d 200"},{"line_number":133,"context_line":"        self.requests_params \u003d kwarg"},{"line_number":134,"context_line":"        # This simulate previous httplib implementation that would do a"},{"line_number":135,"context_line":"        # putrequest() and then use putheader() to send header."},{"line_number":136,"context_line":"        for k, v in kwarg[\u0027headers\u0027].items():"},{"line_number":137,"context_line":"            self.buffer.append((k, v))"},{"line_number":138,"context_line":"        return self.fake_response()"}],"source_content_type":"text/x-python","patch_set":5,"id":"5a890539_b6374a4c","side":"PARENT","line":135,"in_reply_to":"5a890539_5a4024a5","updated":"2014-11-24 13:37:31.000000000","message":"Yes, my mistake.","commit_id":"202bbab2d06b9ef751fba306effd09f3bae8f383"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"da76c03363fc0f7046e1ac5815e578513f57e672","unresolved":false,"context_lines":[{"line_number":737,"context_line":"            self.assertTrue(isinstance(req_data,"},{"line_number":738,"context_line":"                                       swiftclient.utils.LengthWrapper))"},{"line_number":739,"context_line":"            self.assertEqual(raw_data_len, len(req_data.read()))"},{"line_number":740,"context_line":"            self.assertEqual(req_data.get_md5sum(), md5(raw_data).hexdigest())"},{"line_number":741,"context_line":""},{"line_number":742,"context_line":"    def test_chunk_upload(self):"},{"line_number":743,"context_line":"        # Chunked upload happens when no content_length is passed to put_object"}],"source_content_type":"text/x-python","patch_set":5,"id":"5a890539_5a274412","line":740,"updated":"2014-11-22 00:57:32.000000000","message":"nit: maybe this code should be cleaned up to:\n\n  for kwarg in ({\u0027headers\u0027: {\u0027Content-Length\u0027: X}}, {\u0027content_length\u0027: X}):","commit_id":"5b083afe790abb5905c4e48059b671b8452e0c81"},{"author":{"_account_id":13470,"name":"Daniel Wakefield","email":"dan@danw.eu","username":"danw"},"change_message_id":"519c8676451a39fa9508681ecb56a71c81cd4862","unresolved":false,"context_lines":[{"line_number":737,"context_line":"            self.assertTrue(isinstance(req_data,"},{"line_number":738,"context_line":"                                       swiftclient.utils.LengthWrapper))"},{"line_number":739,"context_line":"            self.assertEqual(raw_data_len, len(req_data.read()))"},{"line_number":740,"context_line":"            self.assertEqual(req_data.get_md5sum(), md5(raw_data).hexdigest())"},{"line_number":741,"context_line":""},{"line_number":742,"context_line":"    def test_chunk_upload(self):"},{"line_number":743,"context_line":"        # Chunked upload happens when no content_length is passed to put_object"}],"source_content_type":"text/x-python","patch_set":5,"id":"5a890539_96808ec0","line":740,"in_reply_to":"5a890539_5a274412","updated":"2014-11-24 13:37:31.000000000","message":"Done","commit_id":"5b083afe790abb5905c4e48059b671b8452e0c81"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"da76c03363fc0f7046e1ac5815e578513f57e672","unresolved":false,"context_lines":[{"line_number":764,"context_line":""},{"line_number":765,"context_line":"    def test_md5_mismatch(self):"},{"line_number":766,"context_line":"        conn \u003d c.http_connection(\u0027http://www.test.com\u0027)"},{"line_number":767,"context_line":"        resp \u003d MockHttpResponse(200, {\u0027etag\u0027: \u0027\"badresponseetag\"\u0027}, True)"},{"line_number":768,"context_line":"        conn[1].getresponse \u003d resp.fake_response"},{"line_number":769,"context_line":"        conn[1]._request \u003d resp._fake_request"},{"line_number":770,"context_line":"        raw_data \u003d (\u0027asdf\u0027 * 256).encode()"}],"source_content_type":"text/x-python","patch_set":5,"id":"5a890539_da7a54f0","line":767,"updated":"2014-11-22 00:57:32.000000000","message":"nit: maybe name the verify kwarg for clarity","commit_id":"5b083afe790abb5905c4e48059b671b8452e0c81"},{"author":{"_account_id":13470,"name":"Daniel Wakefield","email":"dan@danw.eu","username":"danw"},"change_message_id":"519c8676451a39fa9508681ecb56a71c81cd4862","unresolved":false,"context_lines":[{"line_number":764,"context_line":""},{"line_number":765,"context_line":"    def test_md5_mismatch(self):"},{"line_number":766,"context_line":"        conn \u003d c.http_connection(\u0027http://www.test.com\u0027)"},{"line_number":767,"context_line":"        resp \u003d MockHttpResponse(200, {\u0027etag\u0027: \u0027\"badresponseetag\"\u0027}, True)"},{"line_number":768,"context_line":"        conn[1].getresponse \u003d resp.fake_response"},{"line_number":769,"context_line":"        conn[1]._request \u003d resp._fake_request"},{"line_number":770,"context_line":"        raw_data \u003d (\u0027asdf\u0027 * 256).encode()"}],"source_content_type":"text/x-python","patch_set":5,"id":"5a890539_d66db633","line":767,"in_reply_to":"5a890539_da7a54f0","updated":"2014-11-24 13:37:31.000000000","message":"Done","commit_id":"5b083afe790abb5905c4e48059b671b8452e0c81"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"da76c03363fc0f7046e1ac5815e578513f57e672","unresolved":false,"context_lines":[{"line_number":778,"context_line":"                              url\u003d\u0027http://www.test.com\u0027,"},{"line_number":779,"context_line":"                              http_conn\u003dconn,"},{"line_number":780,"context_line":"                              contents\u003dmock_file,"},{"line_number":781,"context_line":"                              chunk_size\u003dchunk_size)"},{"line_number":782,"context_line":""},{"line_number":783,"context_line":"    def test_md5_match(self):"},{"line_number":784,"context_line":"        conn \u003d c.http_connection(\u0027http://www.test.com\u0027)"}],"source_content_type":"text/x-python","patch_set":5,"id":"5a890539_9a1d2cc1","line":781,"updated":"2014-11-22 00:57:32.000000000","message":"nice work, good test.","commit_id":"5b083afe790abb5905c4e48059b671b8452e0c81"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"05c7b75f613a1b77a3b230c64a6acc54e4bae859","unresolved":false,"context_lines":[{"line_number":792,"context_line":"                                chunk_size\u003dchunk_size)"},{"line_number":793,"context_line":""},{"line_number":794,"context_line":"            self.assertNotEquals(etag, contents.get_md5sum())"},{"line_number":795,"context_line":"            self.assertEquals(raw_data_md5, contents.get_md5sum())"},{"line_number":796,"context_line":""},{"line_number":797,"context_line":"    def test_md5_match(self):"},{"line_number":798,"context_line":"        conn \u003d c.http_connection(\u0027http://www.test.com\u0027)"}],"source_content_type":"text/x-python","patch_set":7,"id":"5a890539_895ada7f","line":795,"updated":"2014-12-05 01:56:57.000000000","message":"i like this test pretty good!","commit_id":"1ee31bac6f81c36eda0be9e327180b7a725c257f"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5434cbd8a472adf1bfc53a143d68b6a39b24b7f6","unresolved":false,"context_lines":[{"line_number":805,"context_line":"                                contents\u003dcontents,"},{"line_number":806,"context_line":"                                chunk_size\u003dchunk_size)"},{"line_number":807,"context_line":""},{"line_number":808,"context_line":"            self.assertNotEquals(etag, contents.get_md5sum())"},{"line_number":809,"context_line":"            self.assertEquals(raw_data_md5, contents.get_md5sum())"},{"line_number":810,"context_line":""},{"line_number":811,"context_line":"    def test_md5_match(self):"}],"source_content_type":"text/x-python","patch_set":13,"id":"ba7be1f8_215baf55","line":808,"updated":"2015-02-20 14:44:21.000000000","message":"nit: also \n\n  self.assertEqual(etag, \u0027\"badresponseetag\"\u0027)","commit_id":"f0300e3714e0d8cdd0ed9e4744b813e3b263d034"}],"tests/unit/test_utils.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"da76c03363fc0f7046e1ac5815e578513f57e672","unresolved":false,"context_lines":[{"line_number":163,"context_line":""},{"line_number":164,"context_line":"class TestLengthWrapper(testtools.TestCase):"},{"line_number":165,"context_line":""},{"line_number":166,"context_line":"    def test_stringio(self):"},{"line_number":167,"context_line":"        contents \u003d six.StringIO(\u0027a\u0027 * 100)"},{"line_number":168,"context_line":"        data \u003d u.LengthWrapper(contents, 42)"},{"line_number":169,"context_line":"        self.assertEqual(42, len(data))"}],"source_content_type":"text/x-python","patch_set":5,"id":"5a890539_3aeb5879","side":"PARENT","line":166,"updated":"2014-11-22 00:57:32.000000000","message":"AH!  I was totally confused why these changes here, at first I thought you were just cleaning stuff up again - but that was wrong.\n\nThese changes are actually *needed* because in python 3 a StringIO object is going to hand out unicode stuff and you can\u0027t just give that to the new md5 guy in there all raw!\n\nThe fact that this test broke should have highlighted that the interface to the object is changing and you need to fix the code.  Good test.\n\nGetting this test to pass on the current code unchanged should probably be a blocker or we risk breaking clients.  If you want to add a new test to validate we also do the right thing with byte based streams in python3 that\u0027s cool by me.","commit_id":"202bbab2d06b9ef751fba306effd09f3bae8f383"},{"author":{"_account_id":13470,"name":"Daniel Wakefield","email":"dan@danw.eu","username":"danw"},"change_message_id":"519c8676451a39fa9508681ecb56a71c81cd4862","unresolved":false,"context_lines":[{"line_number":163,"context_line":""},{"line_number":164,"context_line":"class TestLengthWrapper(testtools.TestCase):"},{"line_number":165,"context_line":""},{"line_number":166,"context_line":"    def test_stringio(self):"},{"line_number":167,"context_line":"        contents \u003d six.StringIO(\u0027a\u0027 * 100)"},{"line_number":168,"context_line":"        data \u003d u.LengthWrapper(contents, 42)"},{"line_number":169,"context_line":"        self.assertEqual(42, len(data))"}],"source_content_type":"text/x-python","patch_set":5,"id":"5a890539_562c6602","side":"PARENT","line":166,"in_reply_to":"5a890539_3aeb5879","updated":"2014-11-24 13:37:31.000000000","message":"Since the Service class always opens files in \"rb\" mode I think this test was originally testing a slightly different behavior than what actually occurs. \n\nI agree I\u0027ll will have to check that the new test works properly on the old code though just to be sure.","commit_id":"202bbab2d06b9ef751fba306effd09f3bae8f383"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"05c7b75f613a1b77a3b230c64a6acc54e4bae859","unresolved":false,"context_lines":[{"line_number":226,"context_line":""},{"line_number":227,"context_line":"    def test_tempfile(self):"},{"line_number":228,"context_line":"        with tempfile.NamedTemporaryFile(mode\u003d\u0027wb\u0027) as f:"},{"line_number":229,"context_line":"            f.write((\u0027a\u0027 * 100).encode())"},{"line_number":230,"context_line":"            f.flush()"},{"line_number":231,"context_line":"            contents \u003d open(f.name, \u0027rb\u0027)"},{"line_number":232,"context_line":"            data \u003d u.LengthWrapper(contents, 42)"}],"source_content_type":"text/x-python","patch_set":7,"id":"5a890539_c959425c","line":229,"updated":"2014-12-05 01:56:57.000000000","message":"not super jazzed about loosing the test coverage for files opened without the \u0027b\u0027 flag :\\\n\nI actually coded the StringIO test back in just to make sure the exception handling all worked like I thought...\n\nhttps://gist.github.com/clayg/5f363c95a728d6bae881","commit_id":"1ee31bac6f81c36eda0be9e327180b7a725c257f"}],"tests/unit/utils.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5434cbd8a472adf1bfc53a143d68b6a39b24b7f6","unresolved":false,"context_lines":[{"line_number":127,"context_line":"                       \u0027last-modified\u0027: self.timestamp,"},{"line_number":128,"context_line":"                       \u0027x-object-meta-test\u0027: \u0027testing\u0027,"},{"line_number":129,"context_line":"                       \u0027etag\u0027:"},{"line_number":130,"context_line":"                       self.etag or \u0027\"d41d8cd98f00b204e9800998ecf8427e\"\u0027,"},{"line_number":131,"context_line":"                       \u0027x-works\u0027: \u0027yes\u0027,"},{"line_number":132,"context_line":"                       \u0027x-account-container-count\u0027: 12345}"},{"line_number":133,"context_line":"            if not self.timestamp:"}],"source_content_type":"text/x-python","patch_set":13,"id":"ba7be1f8_f4507660","line":130,"updated":"2015-02-20 14:44:21.000000000","message":"nit: add comment that this is md5 hash of empty string.","commit_id":"f0300e3714e0d8cdd0ed9e4744b813e3b263d034"}]}
