)]}'
{"swiftclient/service.py":[{"author":{"_account_id":13470,"name":"Daniel Wakefield","email":"dan@danw.eu","username":"danw"},"change_message_id":"59a6246ee3d314e1fadc5ce867674f9ea84fb6a7","unresolved":false,"context_lines":[{"line_number":926,"context_line":"                                shuffle(containers)"},{"line_number":927,"context_line":""},{"line_number":928,"context_line":"                            for con in containers:"},{"line_number":929,"context_line":"                                self._download_container(con, options_copy)"},{"line_number":930,"context_line":"                        else:"},{"line_number":931,"context_line":"                            raise part[\"error\"]"},{"line_number":932,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"3a961159_0f8753d8","line":929,"updated":"2014-12-18 16:34:20.000000000","message":"The tests didnt show this (bad) but this would be a breaking change since this would result in an implicit None return and\nswiftclient.shell.st_download expects SwiftService.download to act as an iterator. \nI think changing this to\n\n    for res in self._download_container(con, options_copy)\n        yield res\n\nwould be enough, but some tests to be sure would be nice.","commit_id":"6b17b44bf943b632abcf45de27a78824a42eea68"},{"author":{"_account_id":9216,"name":"Joel Wright","email":"joel.wright@gmail.com","username":"jjw-sohonet"},"change_message_id":"678c6fce14b3e17e8d19305ed7911fea24f0ac93","unresolved":false,"context_lines":[{"line_number":926,"context_line":"                                shuffle(containers)"},{"line_number":927,"context_line":""},{"line_number":928,"context_line":"                            for con in containers:"},{"line_number":929,"context_line":"                                self._download_container(con, options_copy)"},{"line_number":930,"context_line":"                        else:"},{"line_number":931,"context_line":"                            raise part[\"error\"]"},{"line_number":932,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"3a961159_798a931b","line":929,"in_reply_to":"3a961159_0f8753d8","updated":"2014-12-30 21:23:38.000000000","message":"Good catch, thanks for spotting this. I\u0027ll fix the code and add an appropriate test.","commit_id":"6b17b44bf943b632abcf45de27a78824a42eea68"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"a5bdcba4ad1362a759e9f3ea676ddcd57e6377ce","unresolved":false,"context_lines":[{"line_number":1131,"context_line":"                                next_page_downs \u003d self._submit_page_downloads("},{"line_number":1132,"context_line":"                                    container, _page_generator, options"},{"line_number":1133,"context_line":"                                )"},{"line_number":1134,"context_line":"                            except Exception as err:"},{"line_number":1135,"context_line":"                                # Allow the current page to finish downloading"},{"line_number":1136,"context_line":"                                error \u003d err"},{"line_number":1137,"context_line":"                            finally:"}],"source_content_type":"text/x-python","patch_set":9,"id":"ba7be1f8_3190dd49","line":1134,"updated":"2015-02-24 20:18:38.000000000","message":"I\u0027m against except Exception: without a very strong justification. It\u0027s a terrible practice.","commit_id":"c7c9f9623c315a5948ea0f9db8eef49074bcb19d"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"8618b8d67e7cd80623dc8333469e534784c39a62","unresolved":false,"context_lines":[{"line_number":1131,"context_line":"                                next_page_downs \u003d self._submit_page_downloads("},{"line_number":1132,"context_line":"                                    container, _page_generator, options"},{"line_number":1133,"context_line":"                                )"},{"line_number":1134,"context_line":"                            except Exception as err:"},{"line_number":1135,"context_line":"                                # Allow the current page to finish downloading"},{"line_number":1136,"context_line":"                                error \u003d err"},{"line_number":1137,"context_line":"                            finally:"}],"source_content_type":"text/x-python","patch_set":9,"id":"ba7be1f8_ec1478ea","line":1134,"in_reply_to":"ba7be1f8_1678f98e","updated":"2015-02-25 20:47:06.000000000","message":"The assertion \"we don\u0027t want to crash out potentially leaving a bunch of download operations inaccessible\" makes no sense to me, sorry. Perhaps I\u0027m missing something, but why does it matter if \"a bunch\" of \"operations\" is \"inaccessible\" or not, at the moment you re-raise? It\u0027s not like anyone expects a consistent state at that time, considering that it\u0027s impossible when you stepped on an unexpected exception. The client is going to terminate at that point, and it\u0027s essential for the traceback to make sense when that happens.\n\nIf there\u0027s no good reason to catch anything, don\u0027t catch it. You\u0027re not making anyone any favours by postponing exceptions, IMHO. At least the stack trace will make sense if you don\u0027t do this.","commit_id":"c7c9f9623c315a5948ea0f9db8eef49074bcb19d"},{"author":{"_account_id":9216,"name":"Joel Wright","email":"joel.wright@gmail.com","username":"jjw-sohonet"},"change_message_id":"60d7e396332f76f166636a500af9dcc660abbbdc","unresolved":false,"context_lines":[{"line_number":1131,"context_line":"                                next_page_downs \u003d self._submit_page_downloads("},{"line_number":1132,"context_line":"                                    container, _page_generator, options"},{"line_number":1133,"context_line":"                                )"},{"line_number":1134,"context_line":"                            except Exception as err:"},{"line_number":1135,"context_line":"                                # Allow the current page to finish downloading"},{"line_number":1136,"context_line":"                                error \u003d err"},{"line_number":1137,"context_line":"                            finally:"}],"source_content_type":"text/x-python","patch_set":9,"id":"ba7be1f8_1678f98e","line":1134,"in_reply_to":"ba7be1f8_3190dd49","updated":"2015-02-25 19:46:30.000000000","message":"Hi Pete, I understand your feeling about \u0027except Exception\u0027, but I think it has a valid purpose here. We don\u0027t want to crash out potentially leaving a bunch of download operations inaccessible, so we:\n\n - catch the error caused by trying to get the next page of the listing\n - trigger a codepath that stops more pages being downloaded\n - then when the current set of running downloads complete re-raise the error\n\nIf you really have a major issue with this, what would you prefer to see?","commit_id":"c7c9f9623c315a5948ea0f9db8eef49074bcb19d"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"2512b6f60c0437802ee2b774c8b305004ce614a7","unresolved":false,"context_lines":[{"line_number":752,"context_line":"        else:"},{"line_number":753,"context_line":"            options \u003d self._options"},{"line_number":754,"context_line":""},{"line_number":755,"context_line":"        rq \u003d Queue(maxsize\u003d10)  # Stop the queue consuming too many results"},{"line_number":756,"context_line":""},{"line_number":757,"context_line":"        if container is None:"},{"line_number":758,"context_line":"            listing_future \u003d self.thread_manager.container_pool.submit("}],"source_content_type":"text/x-python","patch_set":11,"id":"7a016987_2d7bd129","line":755,"updated":"2015-05-21 20:33:02.000000000","message":"Why a queue size of 10? Not saying it\u0027s too small or too large, I just have no context with which to say, \"yeah, this seems good.\"","commit_id":"0f064ee0b16ddec707c99e85b141535d5ece9561"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"04f74d31c70846dba1e1cd5d0fe46645d8b574d4","unresolved":false,"context_lines":[{"line_number":752,"context_line":"        else:"},{"line_number":753,"context_line":"            options \u003d self._options"},{"line_number":754,"context_line":""},{"line_number":755,"context_line":"        rq \u003d Queue(maxsize\u003d10)  # Stop the queue consuming too many results"},{"line_number":756,"context_line":""},{"line_number":757,"context_line":"        if container is None:"},{"line_number":758,"context_line":"            listing_future \u003d self.thread_manager.container_pool.submit("}],"source_content_type":"text/x-python","patch_set":11,"id":"7a016987_048e802d","line":755,"updated":"2015-05-25 02:47:42.000000000","message":"Yeah, Cool, but is 10 some sweet point you\u0027ve tested, or should we make this configuratble and defaulted to 10?","commit_id":"0f064ee0b16ddec707c99e85b141535d5ece9561"},{"author":{"_account_id":9216,"name":"Joel Wright","email":"joel.wright@gmail.com","username":"jjw-sohonet"},"change_message_id":"a90608e8d8804aafb036f78d3eb8579bf7621a72","unresolved":false,"context_lines":[{"line_number":752,"context_line":"        else:"},{"line_number":753,"context_line":"            options \u003d self._options"},{"line_number":754,"context_line":""},{"line_number":755,"context_line":"        rq \u003d Queue(maxsize\u003d10)  # Stop the queue consuming too many results"},{"line_number":756,"context_line":""},{"line_number":757,"context_line":"        if container is None:"},{"line_number":758,"context_line":"            listing_future \u003d self.thread_manager.container_pool.submit("}],"source_content_type":"text/x-python","patch_set":11,"id":"7a016987_a9952389","line":755,"in_reply_to":"7a016987_048e802d","updated":"2015-05-26 12:31:36.000000000","message":"I don\u0027t think it\u0027s necessary to provide a configuration here - it\u0027s really just \u0027a large number of result pages that doesn\u0027t consume too much RAM\u0027. If your list results are coming back faster than you can process them, then that should always be the case and we want to stop it using up all the memory in the machine consuming hundreds of pages of listings that still need to be processed, so I can\u0027t see how a configuration option would help.","commit_id":"0f064ee0b16ddec707c99e85b141535d5ece9561"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"2512b6f60c0437802ee2b774c8b305004ce614a7","unresolved":false,"context_lines":[{"line_number":921,"context_line":"                            containers \u003d [i[\u0027name\u0027] for i in part[\"listing\"]]"},{"line_number":922,"context_line":""},{"line_number":923,"context_line":"                            if options[\u0027shuffle\u0027]:"},{"line_number":924,"context_line":"                                shuffle(containers)"},{"line_number":925,"context_line":""},{"line_number":926,"context_line":"                            for con in containers:"},{"line_number":927,"context_line":"                                for res in self._download_container("}],"source_content_type":"text/x-python","patch_set":11,"id":"7a016987_4d43adb2","line":924,"updated":"2015-05-21 20:33:02.000000000","message":"If we only shuffle the container listings within a single page, will we still get the load-reduction benefits? In particular, when objects have a common prefix, will they store \"near\" each other, so that we\u0027re more likely to hit the same handful of servers?","commit_id":"0f064ee0b16ddec707c99e85b141535d5ece9561"},{"author":{"_account_id":9216,"name":"Joel Wright","email":"joel.wright@gmail.com","username":"jjw-sohonet"},"change_message_id":"a90608e8d8804aafb036f78d3eb8579bf7621a72","unresolved":false,"context_lines":[{"line_number":921,"context_line":"                            containers \u003d [i[\u0027name\u0027] for i in part[\"listing\"]]"},{"line_number":922,"context_line":""},{"line_number":923,"context_line":"                            if options[\u0027shuffle\u0027]:"},{"line_number":924,"context_line":"                                shuffle(containers)"},{"line_number":925,"context_line":""},{"line_number":926,"context_line":"                            for con in containers:"},{"line_number":927,"context_line":"                                for res in self._download_container("}],"source_content_type":"text/x-python","patch_set":11,"id":"7a016987_c95bbff5","line":924,"in_reply_to":"7a016987_4d43adb2","updated":"2015-05-26 12:31:36.000000000","message":"Shuffling by page should be fine - objects are located according to their hash, so object names sharing the same prefix should be stored no closer to each other than any other objects. We\u0027re relying on the hashing algorithm used by the ring to spread things out here, but then that\u0027s its purpose :)","commit_id":"0f064ee0b16ddec707c99e85b141535d5ece9561"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"04f74d31c70846dba1e1cd5d0fe46645d8b574d4","unresolved":false,"context_lines":[{"line_number":1125,"context_line":"                    yield o_down.result()"},{"line_number":1126,"context_line":""},{"line_number":1127,"context_line":"                    # Do we need to start the next set of downloads yet?"},{"line_number":1128,"context_line":"                    if trigger_next_page:  # Must be non-zero int or False"},{"line_number":1129,"context_line":"                        page_results_yielded +\u003d 1"},{"line_number":1130,"context_line":"                        if page_results_yielded \u003e trigger_next_page:"},{"line_number":1131,"context_line":"                            try:"}],"source_content_type":"text/x-python","patch_set":11,"id":"7a016987_e48004f9","line":1128,"updated":"2015-05-25 02:47:42.000000000","message":"This comment is a little redundent, cause tht is what if \u003cvariable\u003e means. I don\u0027t really mind if you want to mention it, but if you don\u0027t put it on the same line as some code, either comment about or below.","commit_id":"0f064ee0b16ddec707c99e85b141535d5ece9561"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"2512b6f60c0437802ee2b774c8b305004ce614a7","unresolved":false,"context_lines":[{"line_number":1125,"context_line":"                    yield o_down.result()"},{"line_number":1126,"context_line":""},{"line_number":1127,"context_line":"                    # Do we need to start the next set of downloads yet?"},{"line_number":1128,"context_line":"                    if trigger_next_page:  # Must be non-zero int or False"},{"line_number":1129,"context_line":"                        page_results_yielded +\u003d 1"},{"line_number":1130,"context_line":"                        if page_results_yielded \u003e trigger_next_page:"},{"line_number":1131,"context_line":"                            try:"}],"source_content_type":"text/x-python","patch_set":11,"id":"7a016987_2d7631d7","line":1128,"updated":"2015-05-21 20:33:02.000000000","message":"You mean \"non-zero int *and not* False\", yes? Or maybe just leave it at \"non-zero int\"?","commit_id":"0f064ee0b16ddec707c99e85b141535d5ece9561"},{"author":{"_account_id":9216,"name":"Joel Wright","email":"joel.wright@gmail.com","username":"jjw-sohonet"},"change_message_id":"a90608e8d8804aafb036f78d3eb8579bf7621a72","unresolved":false,"context_lines":[{"line_number":1125,"context_line":"                    yield o_down.result()"},{"line_number":1126,"context_line":""},{"line_number":1127,"context_line":"                    # Do we need to start the next set of downloads yet?"},{"line_number":1128,"context_line":"                    if trigger_next_page:  # Must be non-zero int or False"},{"line_number":1129,"context_line":"                        page_results_yielded +\u003d 1"},{"line_number":1130,"context_line":"                        if page_results_yielded \u003e trigger_next_page:"},{"line_number":1131,"context_line":"                            try:"}],"source_content_type":"text/x-python","patch_set":11,"id":"7a016987_09a557b4","line":1128,"in_reply_to":"7a016987_2d7631d7","updated":"2015-05-26 12:31:36.000000000","message":"No, I really do mean \u0027non-zero int or False\u0027; this wasn\u0027t left as a comment describing how an if decision is made! it was there as a pointer to the fact that I was using \u0027trigger_next_page\u0027 as both a boolean and an integer. Clearly I need to improve the comment or change the decision process.","commit_id":"0f064ee0b16ddec707c99e85b141535d5ece9561"},{"author":{"_account_id":9216,"name":"Joel Wright","email":"joel.wright@gmail.com","username":"jjw-sohonet"},"change_message_id":"a90608e8d8804aafb036f78d3eb8579bf7621a72","unresolved":false,"context_lines":[{"line_number":1125,"context_line":"                    yield o_down.result()"},{"line_number":1126,"context_line":""},{"line_number":1127,"context_line":"                    # Do we need to start the next set of downloads yet?"},{"line_number":1128,"context_line":"                    if trigger_next_page:  # Must be non-zero int or False"},{"line_number":1129,"context_line":"                        page_results_yielded +\u003d 1"},{"line_number":1130,"context_line":"                        if page_results_yielded \u003e trigger_next_page:"},{"line_number":1131,"context_line":"                            try:"}],"source_content_type":"text/x-python","patch_set":11,"id":"7a016987_292a53e8","line":1128,"in_reply_to":"7a016987_e48004f9","updated":"2015-05-26 12:31:36.000000000","message":"As the code stands this comment is absolutely not redundant; it\u0027s not describing the working of the if statement, it was meant as a statement about \u0027trigger_next_page\u0027 because that variable could be either an int or a boolean depending on whether an error has occurred.\n\nAs I said above, I think I\u0027ll just need to add a second variable to make this clearer, or improve the comment.","commit_id":"0f064ee0b16ddec707c99e85b141535d5ece9561"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"2512b6f60c0437802ee2b774c8b305004ce614a7","unresolved":false,"context_lines":[{"line_number":1139,"context_line":"                                # Something unexpected went wrong - cancel"},{"line_number":1140,"context_line":"                                # remaining downloads"},{"line_number":1141,"context_line":"                                for _d in page_downs:"},{"line_number":1142,"context_line":"                                    _d.cancel()"},{"line_number":1143,"context_line":"                                raise"},{"line_number":1144,"context_line":"                            finally:"},{"line_number":1145,"context_line":"                                # Stop counting and testing"}],"source_content_type":"text/x-python","patch_set":11,"id":"7a016987_3812f157","line":1142,"updated":"2015-05-21 20:33:02.000000000","message":"What all happens in .cancel()? Could this clobber the exception frame? It might be better to capture with sys.exc_info and reraise with six.reraise.","commit_id":"0f064ee0b16ddec707c99e85b141535d5ece9561"},{"author":{"_account_id":9216,"name":"Joel Wright","email":"joel.wright@gmail.com","username":"jjw-sohonet"},"change_message_id":"a90608e8d8804aafb036f78d3eb8579bf7621a72","unresolved":false,"context_lines":[{"line_number":1139,"context_line":"                                # Something unexpected went wrong - cancel"},{"line_number":1140,"context_line":"                                # remaining downloads"},{"line_number":1141,"context_line":"                                for _d in page_downs:"},{"line_number":1142,"context_line":"                                    _d.cancel()"},{"line_number":1143,"context_line":"                                raise"},{"line_number":1144,"context_line":"                            finally:"},{"line_number":1145,"context_line":"                                # Stop counting and testing"}],"source_content_type":"text/x-python","patch_set":11,"id":"7a016987_694debc3","line":1142,"in_reply_to":"7a016987_3812f157","updated":"2015-05-26 12:31:36.000000000","message":"I don\u0027t think this is an issue, but I\u0027ll have a closer look into it.","commit_id":"0f064ee0b16ddec707c99e85b141535d5ece9561"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"2512b6f60c0437802ee2b774c8b305004ce614a7","unresolved":false,"context_lines":[{"line_number":1149,"context_line":"            if err.http_status !\u003d 404:"},{"line_number":1150,"context_line":"                raise"},{"line_number":1151,"context_line":"            raise SwiftError("},{"line_number":1152,"context_line":"                \u0027Container %r not found\u0027 % container, container\u003dcontainer"},{"line_number":1153,"context_line":"            )"},{"line_number":1154,"context_line":""},{"line_number":1155,"context_line":"    # Upload related methods"}],"source_content_type":"text/x-python","patch_set":11,"id":"7a016987_eda4994b","line":1152,"updated":"2015-05-21 20:33:02.000000000","message":"If an object is present during container listing but is deleted before we get a chance to download it, will we still trip this? If so, it\u0027ll really confuse the user.\n\nMore generally, I\u0027m always a little leery of long try blocks; if we could get this fairly tight around the container page listings, I\u0027d feel a lot better.","commit_id":"0f064ee0b16ddec707c99e85b141535d5ece9561"},{"author":{"_account_id":9216,"name":"Joel Wright","email":"joel.wright@gmail.com","username":"jjw-sohonet"},"change_message_id":"a90608e8d8804aafb036f78d3eb8579bf7621a72","unresolved":false,"context_lines":[{"line_number":1149,"context_line":"            if err.http_status !\u003d 404:"},{"line_number":1150,"context_line":"                raise"},{"line_number":1151,"context_line":"            raise SwiftError("},{"line_number":1152,"context_line":"                \u0027Container %r not found\u0027 % container, container\u003dcontainer"},{"line_number":1153,"context_line":"            )"},{"line_number":1154,"context_line":""},{"line_number":1155,"context_line":"    # Upload related methods"}],"source_content_type":"text/x-python","patch_set":11,"id":"7a016987_492b4f95","line":1152,"in_reply_to":"7a016987_eda4994b","updated":"2015-05-26 12:31:36.000000000","message":"You make a fair point, I\u0027ll need to check whether an object deletion could trigger this, and it may be possible to move the except closer to the initial call to list().","commit_id":"0f064ee0b16ddec707c99e85b141535d5ece9561"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f8adf6659ef7e131e9ab522f397842153e0b604c","unresolved":false,"context_lines":[{"line_number":1196,"context_line":"                        except ClientException as err:"},{"line_number":1197,"context_line":"                            # Allow the current page to finish downloading"},{"line_number":1198,"context_line":"                            error \u003d err"},{"line_number":1199,"context_line":"                        except Exception:"},{"line_number":1200,"context_line":"                            # Something unexpected went wrong - cancel"},{"line_number":1201,"context_line":"                            # remaining downloads"},{"line_number":1202,"context_line":"                            for _d in page_downs:"}],"source_content_type":"text/x-python","patch_set":14,"id":"fa1b9901_ba037f41","line":1199,"updated":"2015-08-26 14:54:47.000000000","message":"why different handling for Exception vs ClientException? ie why not always allow current page to finish before raising?","commit_id":"a8c4df98eee43b419d6dd30e80c838d9f2efd025"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"b5e5d2ba17508269c6b40315b83743be9f2a5466","unresolved":false,"context_lines":[{"line_number":1200,"context_line":"                            # Something unexpected went wrong - cancel"},{"line_number":1201,"context_line":"                            # remaining downloads"},{"line_number":1202,"context_line":"                            for _d in page_downs:"},{"line_number":1203,"context_line":"                                _d.cancel()"},{"line_number":1204,"context_line":"                            raise"},{"line_number":1205,"context_line":"                        finally:"},{"line_number":1206,"context_line":"                            # Stop counting and testing"}],"source_content_type":"text/x-python","patch_set":14,"id":"3a50d1a3_1d5f6fe6","line":1203,"updated":"2015-07-20 23:41:40.000000000","message":"Did we ever look into whether this could eat the exception frame? I\u0027d hate for the cleanup to cause a TypeError when we go to re-raise.","commit_id":"a8c4df98eee43b419d6dd30e80c838d9f2efd025"}],"swiftclient/shell.py":[{"author":{"_account_id":13470,"name":"Daniel Wakefield","email":"dan@danw.eu","username":"danw"},"change_message_id":"761025c5986add5fe3e15de0b1536cdc871a991a","unresolved":false,"context_lines":[{"line_number":230,"context_line":"    parser.add_option("},{"line_number":231,"context_line":"        \u0027--no-shuffle\u0027, action\u003d\u0027store_true\u0027, dest\u003d\u0027shuffle\u0027,"},{"line_number":232,"context_line":"        default\u003dTrue, help\u003d\u0027Download files in order. Turn off shuffling of\u0027"},{"line_number":233,"context_line":"        \u0027 containers and objects.\u0027)"},{"line_number":234,"context_line":"    (options, args) \u003d parse_args(parser, args)"},{"line_number":235,"context_line":"    args \u003d args[1:]"},{"line_number":236,"context_line":"    if options.out_file \u003d\u003d \u0027-\u0027:"}],"source_content_type":"text/x-python","patch_set":4,"id":"3a961159_4ea21afd","line":233,"updated":"2015-01-06 11:42:23.000000000","message":"Action should be store_false.","commit_id":"eea0924acc38175b4e105852555f330c7621414e"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"2512b6f60c0437802ee2b774c8b305004ce614a7","unresolved":false,"context_lines":[{"line_number":234,"context_line":"        \u0027both sides.\u0027)"},{"line_number":235,"context_line":"    parser.add_option("},{"line_number":236,"context_line":"        \u0027--no-shuffle\u0027, action\u003d\u0027store_false\u0027, dest\u003d\u0027shuffle\u0027,"},{"line_number":237,"context_line":"        default\u003dTrue, help\u003d\u0027By default, download order is randomised in order \u0027"},{"line_number":238,"context_line":"        \u0027to reduce the load on individual drives when multiple clients are \u0027"},{"line_number":239,"context_line":"        \u0027executed simultaneously to download the same set of objects (e.g. a \u0027"},{"line_number":240,"context_line":"        \u0027nightly automated download script to multiple servers). Enable this \u0027"}],"source_content_type":"text/x-python","patch_set":11,"id":"7a016987_586c8dcd","line":237,"updated":"2015-05-21 20:33:02.000000000","message":"Shuffle-by-default is only for whole-container (or by extension, whole-account) downloads, right? Maybe note that in the help text.","commit_id":"0f064ee0b16ddec707c99e85b141535d5ece9561"},{"author":{"_account_id":9216,"name":"Joel Wright","email":"joel.wright@gmail.com","username":"jjw-sohonet"},"change_message_id":"a90608e8d8804aafb036f78d3eb8579bf7621a72","unresolved":false,"context_lines":[{"line_number":234,"context_line":"        \u0027both sides.\u0027)"},{"line_number":235,"context_line":"    parser.add_option("},{"line_number":236,"context_line":"        \u0027--no-shuffle\u0027, action\u003d\u0027store_false\u0027, dest\u003d\u0027shuffle\u0027,"},{"line_number":237,"context_line":"        default\u003dTrue, help\u003d\u0027By default, download order is randomised in order \u0027"},{"line_number":238,"context_line":"        \u0027to reduce the load on individual drives when multiple clients are \u0027"},{"line_number":239,"context_line":"        \u0027executed simultaneously to download the same set of objects (e.g. a \u0027"},{"line_number":240,"context_line":"        \u0027nightly automated download script to multiple servers). Enable this \u0027"}],"source_content_type":"text/x-python","patch_set":11,"id":"7a016987_49022f0d","line":237,"in_reply_to":"7a016987_586c8dcd","updated":"2015-05-26 12:31:36.000000000","message":"Good spot.","commit_id":"0f064ee0b16ddec707c99e85b141535d5ece9561"}],"tests/unit/test_service.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b88df196f07ac47f34af8245a74f5ea99e2a7a51","unresolved":false,"context_lines":[{"line_number":597,"context_line":"            \u0027read_length\u0027: len(b\u0027objcontent\u0027),"},{"line_number":598,"context_line":"        })"},{"line_number":599,"context_line":""},{"line_number":600,"context_line":"        with mock.patch(BUILTIN_OPEN) as mock_open:"},{"line_number":601,"context_line":"            actual_r \u003d SwiftService._download_object_job("},{"line_number":602,"context_line":"                mock_conn, \u0027test_c\u0027, \u0027test_o\u0027, self.opts)"},{"line_number":603,"context_line":"            actual_r \u003d dict(  # Need to override the times we got from the call"}],"source_content_type":"text/x-python","patch_set":5,"id":"3a961159_91be48ff","line":600,"updated":"2015-01-12 17:42:29.000000000","message":"would it alternatively work to generate a temporary file to use as outfile and then also be able to assert its contents \u003d\u003d objcontent?","commit_id":"7e7ecb1f873c108d57dd6aae1c5916234dc11474"},{"author":{"_account_id":9216,"name":"Joel Wright","email":"joel.wright@gmail.com","username":"jjw-sohonet"},"change_message_id":"2d2608c33ee8264c10a7225d81a33a90cea2157d","unresolved":false,"context_lines":[{"line_number":597,"context_line":"            \u0027read_length\u0027: len(b\u0027objcontent\u0027),"},{"line_number":598,"context_line":"        })"},{"line_number":599,"context_line":""},{"line_number":600,"context_line":"        with mock.patch(BUILTIN_OPEN) as mock_open:"},{"line_number":601,"context_line":"            actual_r \u003d SwiftService._download_object_job("},{"line_number":602,"context_line":"                mock_conn, \u0027test_c\u0027, \u0027test_o\u0027, self.opts)"},{"line_number":603,"context_line":"            actual_r \u003d dict(  # Need to override the times we got from the call"}],"source_content_type":"text/x-python","patch_set":5,"id":"3a961159_e99884ce","line":600,"in_reply_to":"3a961159_91be48ff","updated":"2015-01-12 19:06:34.000000000","message":"I can add a mocked return value to mock_open so that we can see what would have been written to the opened file. Is that sufficient to cover the content checking?","commit_id":"7e7ecb1f873c108d57dd6aae1c5916234dc11474"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b88df196f07ac47f34af8245a74f5ea99e2a7a51","unresolved":false,"context_lines":[{"line_number":816,"context_line":"        while mock_conn.get_account.call_count !\u003d count or stable \u003c 5:"},{"line_number":817,"context_line":"            if mock_conn.get_account.call_count \u003d\u003d count:"},{"line_number":818,"context_line":"                stable +\u003d 1"},{"line_number":819,"context_line":"            else:"},{"line_number":820,"context_line":"                count \u003d mock_conn.get_account.call_count"},{"line_number":821,"context_line":"            # The test requires a small sleep to allow other threads to"},{"line_number":822,"context_line":"            # execute"}],"source_content_type":"text/x-python","patch_set":5,"id":"3a961159_8851c165","line":819,"updated":"2015-01-12 17:42:29.000000000","message":"reset stable \u003d 0 , since call count has changed. Otherwise this could \u0027staircase\u0027 towards stable \u003d 5 rather than flatline.","commit_id":"7e7ecb1f873c108d57dd6aae1c5916234dc11474"},{"author":{"_account_id":9216,"name":"Joel Wright","email":"joel.wright@gmail.com","username":"jjw-sohonet"},"change_message_id":"2d2608c33ee8264c10a7225d81a33a90cea2157d","unresolved":false,"context_lines":[{"line_number":816,"context_line":"        while mock_conn.get_account.call_count !\u003d count or stable \u003c 5:"},{"line_number":817,"context_line":"            if mock_conn.get_account.call_count \u003d\u003d count:"},{"line_number":818,"context_line":"                stable +\u003d 1"},{"line_number":819,"context_line":"            else:"},{"line_number":820,"context_line":"                count \u003d mock_conn.get_account.call_count"},{"line_number":821,"context_line":"            # The test requires a small sleep to allow other threads to"},{"line_number":822,"context_line":"            # execute"}],"source_content_type":"text/x-python","patch_set":5,"id":"3a961159_d1a4504d","line":819,"in_reply_to":"3a961159_8851c165","updated":"2015-01-12 19:06:34.000000000","message":"Agreed, I\u0027ll change this.","commit_id":"7e7ecb1f873c108d57dd6aae1c5916234dc11474"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b88df196f07ac47f34af8245a74f5ea99e2a7a51","unresolved":false,"context_lines":[{"line_number":820,"context_line":"                count \u003d mock_conn.get_account.call_count"},{"line_number":821,"context_line":"            # The test requires a small sleep to allow other threads to"},{"line_number":822,"context_line":"            # execute"},{"line_number":823,"context_line":"            sleep(0.05)"},{"line_number":824,"context_line":""},{"line_number":825,"context_line":"        # This should be 12 calls to get_account"},{"line_number":826,"context_line":"        # 1 for first_list_part, 10 for the values on the queue and"}],"source_content_type":"text/x-python","patch_set":5,"id":"3a961159_68d495bd","line":823,"updated":"2015-01-12 17:42:29.000000000","message":"So to check I understand the motivation here...if no change to call count in .25 secs then we assume no more calls are going to be made, correct?","commit_id":"7e7ecb1f873c108d57dd6aae1c5916234dc11474"},{"author":{"_account_id":9216,"name":"Joel Wright","email":"joel.wright@gmail.com","username":"jjw-sohonet"},"change_message_id":"2d2608c33ee8264c10a7225d81a33a90cea2157d","unresolved":false,"context_lines":[{"line_number":820,"context_line":"                count \u003d mock_conn.get_account.call_count"},{"line_number":821,"context_line":"            # The test requires a small sleep to allow other threads to"},{"line_number":822,"context_line":"            # execute"},{"line_number":823,"context_line":"            sleep(0.05)"},{"line_number":824,"context_line":""},{"line_number":825,"context_line":"        # This should be 12 calls to get_account"},{"line_number":826,"context_line":"        # 1 for first_list_part, 10 for the values on the queue and"}],"source_content_type":"text/x-python","patch_set":5,"id":"3a961159_513ea0db","line":823,"in_reply_to":"3a961159_68d495bd","updated":"2015-01-12 19:06:34.000000000","message":"This was my assumption, yes.\n\nIt\u0027s ugly and more than a bit hacky, but I couldn\u0027t come up with another simple or readable way to test that the threads weren\u0027t generating more results. I\u0027m more than happy to take suggestions here!","commit_id":"7e7ecb1f873c108d57dd6aae1c5916234dc11474"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b88df196f07ac47f34af8245a74f5ea99e2a7a51","unresolved":false,"context_lines":[{"line_number":825,"context_line":"        # This should be 12 calls to get_account"},{"line_number":826,"context_line":"        # 1 for first_list_part, 10 for the values on the queue and"},{"line_number":827,"context_line":"        # 1 for the value blocking whilst trying to place onto the queue"},{"line_number":828,"context_line":"        self.assertEqual(12, mock_conn.get_account.call_count)"},{"line_number":829,"context_line":""},{"line_number":830,"context_line":"        # Collect all remaining results from the generator"},{"line_number":831,"context_line":"        list_results \u003d [first_list_part] + list(lg)"}],"source_content_type":"text/x-python","patch_set":5,"id":"3a961159_9671dee0","line":828,"updated":"2015-01-12 17:42:29.000000000","message":"If this assertion fails then my test runner never returns - I guess the list thread never exits because we\u0027re not reading the rest of the iterator. Could we have a try + finally that drains the iterator?\n\nOr stash the call count and make assertion after draining the iterator?","commit_id":"7e7ecb1f873c108d57dd6aae1c5916234dc11474"},{"author":{"_account_id":9216,"name":"Joel Wright","email":"joel.wright@gmail.com","username":"jjw-sohonet"},"change_message_id":"2d2608c33ee8264c10a7225d81a33a90cea2157d","unresolved":false,"context_lines":[{"line_number":825,"context_line":"        # This should be 12 calls to get_account"},{"line_number":826,"context_line":"        # 1 for first_list_part, 10 for the values on the queue and"},{"line_number":827,"context_line":"        # 1 for the value blocking whilst trying to place onto the queue"},{"line_number":828,"context_line":"        self.assertEqual(12, mock_conn.get_account.call_count)"},{"line_number":829,"context_line":""},{"line_number":830,"context_line":"        # Collect all remaining results from the generator"},{"line_number":831,"context_line":"        list_results \u003d [first_list_part] + list(lg)"}],"source_content_type":"text/x-python","patch_set":5,"id":"3a961159_5115c047","line":828,"in_reply_to":"3a961159_9671dee0","updated":"2015-01-12 19:06:34.000000000","message":"Agreed.","commit_id":"7e7ecb1f873c108d57dd6aae1c5916234dc11474"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"6a7d2e894689ec13430b4317feeffdb56f2c0d94","unresolved":false,"context_lines":[{"line_number":576,"context_line":""},{"line_number":577,"context_line":"    def test_download_object_job(self):"},{"line_number":578,"context_line":"        mock_conn \u003d self._get_mock_connection()"},{"line_number":579,"context_line":"        objcontent \u003d six.BytesIO(b\u0027objcontent\u0027)"},{"line_number":580,"context_line":"        mock_conn.get_object.side_effect \u003d ["},{"line_number":581,"context_line":"            ({\u0027content-type\u0027: \u0027text/plain\u0027,"},{"line_number":582,"context_line":"              \u0027etag\u0027: \u00272cbbfe139a744d6abbe695e17f3c1991\u0027},"}],"source_content_type":"text/x-python","patch_set":8,"id":"da86d52c_9d7fc1df","line":579,"updated":"2015-02-11 21:17:55.000000000","message":"using unqualified BytesIO everywhere else","commit_id":"ada88428b3734c0422371306d920db452e29dbf8"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"2512b6f60c0437802ee2b774c8b305004ce614a7","unresolved":false,"context_lines":[{"line_number":822,"context_line":"            # execute - in this mocked environment we assume that if the call"},{"line_number":823,"context_line":"            # count to get_account has not changed in 0.25s then no more calls"},{"line_number":824,"context_line":"            # will be made."},{"line_number":825,"context_line":"            sleep(0.05)"},{"line_number":826,"context_line":""},{"line_number":827,"context_line":"        stable_get_account_call_count \u003d mock_conn.get_account.call_count"},{"line_number":828,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"7a016987_189f3560","line":825,"updated":"2015-05-21 20:33:02.000000000","message":"So, how long do we expect this test to take?\n\nI\u0027m not really feeling this \"wait until our call count stops changing\" method of waiting on threads. Why can\u0027t we join them with a timeout, then verify the threads aren\u0027t still alive?","commit_id":"0f064ee0b16ddec707c99e85b141535d5ece9561"},{"author":{"_account_id":9216,"name":"Joel Wright","email":"joel.wright@gmail.com","username":"jjw-sohonet"},"change_message_id":"a90608e8d8804aafb036f78d3eb8579bf7621a72","unresolved":false,"context_lines":[{"line_number":822,"context_line":"            # execute - in this mocked environment we assume that if the call"},{"line_number":823,"context_line":"            # count to get_account has not changed in 0.25s then no more calls"},{"line_number":824,"context_line":"            # will be made."},{"line_number":825,"context_line":"            sleep(0.05)"},{"line_number":826,"context_line":""},{"line_number":827,"context_line":"        stable_get_account_call_count \u003d mock_conn.get_account.call_count"},{"line_number":828,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"7a016987_5b879612","line":825,"in_reply_to":"7a016987_189f3560","updated":"2015-05-26 12:31:36.000000000","message":"I understand what you\u0027re saying, and I share your feelings about this test, but we can\u0027t join() the threads with a timeout because this is not executing as a bunch of simple threads, but rather within a concurrent.futures.ThreadPoolExecutor. I\u0027d love suggestions on how to make this test better, but the only way to access the actual threads is via private fields on the Executor class which is equally distasteful.","commit_id":"0f064ee0b16ddec707c99e85b141535d5ece9561"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f8adf6659ef7e131e9ab522f397842153e0b604c","unresolved":false,"context_lines":[{"line_number":667,"context_line":"            \u0027success\u0027: True,"},{"line_number":668,"context_line":"            \u0027listing\u0027: [{\u0027name\u0027: \u0027test_o\u0027}],"},{"line_number":669,"context_line":"            \u0027marker\u0027: \u0027\u0027"},{"line_number":670,"context_line":"        })"},{"line_number":671,"context_line":""},{"line_number":672,"context_line":"        SwiftService._list_container_job("},{"line_number":673,"context_line":"            mock_conn, \u0027test_c\u0027, long_opts, mock_q"}],"source_content_type":"text/x-python","patch_set":14,"id":"fa1b9901_c323eabb","line":670,"updated":"2015-08-26 14:54:47.000000000","message":"nit: expected_r_long \u003d\u003d expected_r so you could just re-use expected_r\n\nso is the purpose of this assertion to verify that the long option is ignored by container listing?","commit_id":"a8c4df98eee43b419d6dd30e80c838d9f2efd025"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f8adf6659ef7e131e9ab522f397842153e0b604c","unresolved":false,"context_lines":[{"line_number":1268,"context_line":"    def _readbody(self):"},{"line_number":1269,"context_line":"        yield self.obj_content"},{"line_number":1270,"context_line":""},{"line_number":1271,"context_line":"    def _assertDictEqual(self, a, b, m\u003dNone):"},{"line_number":1272,"context_line":"        # assertDictEqual is not available in py2.6 so use a shallow check"},{"line_number":1273,"context_line":"        # instead"},{"line_number":1274,"context_line":"        if not m:"}],"source_content_type":"text/x-python","patch_set":14,"id":"fa1b9901_3e699cf9","line":1271,"updated":"2015-08-26 14:54:47.000000000","message":"we have one of these in _TestServiceBase as well","commit_id":"a8c4df98eee43b419d6dd30e80c838d9f2efd025"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f8adf6659ef7e131e9ab522f397842153e0b604c","unresolved":false,"context_lines":[{"line_number":1293,"context_line":"        \"\"\""},{"line_number":1294,"context_line":"        as_comp.side_effect \u003d ["},{"line_number":1295,"context_line":""},{"line_number":1296,"context_line":"        ]"},{"line_number":1297,"context_line":"        sub_page.side_effect \u003d ["},{"line_number":1298,"context_line":"            range(0, 10), range(0, 10), []  # simulate multiple result pages"},{"line_number":1299,"context_line":"        ]"}],"source_content_type":"text/x-python","patch_set":14,"id":"fa1b9901_544b0fb1","line":1296,"updated":"2015-08-26 14:54:47.000000000","message":"nit:redundant, is set again at line 1309","commit_id":"a8c4df98eee43b419d6dd30e80c838d9f2efd025"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f8adf6659ef7e131e9ab522f397842153e0b604c","unresolved":false,"context_lines":[{"line_number":1314,"context_line":"        s \u003d SwiftService()"},{"line_number":1315,"context_line":"        down_gen \u003d s._download_container(\u0027test_c\u0027, self.opts)"},{"line_number":1316,"context_line":"        results \u003d list(down_gen)"},{"line_number":1317,"context_line":"        self.assertEqual(20, len(results))"},{"line_number":1318,"context_line":""},{"line_number":1319,"context_line":"    @mock.patch(\u0027swiftclient.service.SwiftService.list\u0027)"},{"line_number":1320,"context_line":"    @mock.patch(\u0027swiftclient.service.SwiftService._submit_page_downloads\u0027)"}],"source_content_type":"text/x-python","patch_set":14,"id":"fa1b9901_32d9c8f3","line":1317,"updated":"2015-08-26 14:54:47.000000000","message":"nothing here verifies that the next page is fetched before the current one is completely consumed.\n\nsee my dependent patch for a suggestion.","commit_id":"a8c4df98eee43b419d6dd30e80c838d9f2efd025"}],"tests/unit/test_shell.py":[{"author":{"_account_id":13470,"name":"Daniel Wakefield","email":"dan@danw.eu","username":"danw"},"change_message_id":"88ac65f1e6349b2d26ff030cc04d476907115413","unresolved":false,"context_lines":[{"line_number":375,"context_line":"        mock_shuffle.side_effect \u003d lambda l: l"},{"line_number":376,"context_line":"        connection.return_value.get_object.return_value \u003d ["},{"line_number":377,"context_line":"            {\u0027content-type\u0027: \u0027text/plain\u0027,"},{"line_number":378,"context_line":"             \u0027etag\u0027: \u0027d41d8cd98f00b204e9800998ecf8427e\u0027},"},{"line_number":379,"context_line":"            \u0027\u0027]"},{"line_number":380,"context_line":""},{"line_number":381,"context_line":"        connection.return_value.get_container.side_effect \u003d ["}],"source_content_type":"text/x-python","patch_set":11,"id":"9a80dd14_53b26349","line":378,"updated":"2015-03-16 11:32:14.000000000","message":"nit: The merge has introduced the `EMPTY_ETAG` constant that would be better here.","commit_id":"0f064ee0b16ddec707c99e85b141535d5ece9561"},{"author":{"_account_id":9216,"name":"Joel Wright","email":"joel.wright@gmail.com","username":"jjw-sohonet"},"change_message_id":"a90608e8d8804aafb036f78d3eb8579bf7621a72","unresolved":false,"context_lines":[{"line_number":375,"context_line":"        mock_shuffle.side_effect \u003d lambda l: l"},{"line_number":376,"context_line":"        connection.return_value.get_object.return_value \u003d ["},{"line_number":377,"context_line":"            {\u0027content-type\u0027: \u0027text/plain\u0027,"},{"line_number":378,"context_line":"             \u0027etag\u0027: \u0027d41d8cd98f00b204e9800998ecf8427e\u0027},"},{"line_number":379,"context_line":"            \u0027\u0027]"},{"line_number":380,"context_line":""},{"line_number":381,"context_line":"        connection.return_value.get_container.side_effect \u003d ["}],"source_content_type":"text/x-python","patch_set":11,"id":"7a016987_9b750e34","line":378,"in_reply_to":"9a80dd14_53b26349","updated":"2015-05-26 12:31:36.000000000","message":"Good spot - will use that now.","commit_id":"0f064ee0b16ddec707c99e85b141535d5ece9561"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f8adf6659ef7e131e9ab522f397842153e0b604c","unresolved":false,"context_lines":[{"line_number":392,"context_line":"            (None, [{\u0027name\u0027: \u0027pseudo/\u0027}]),"},{"line_number":393,"context_line":"            (None, []),"},{"line_number":394,"context_line":"        ]"},{"line_number":395,"context_line":"        connection.return_value.auth_end_time \u003d 0"},{"line_number":396,"context_line":"        connection.return_value.attempts \u003d 0"},{"line_number":397,"context_line":"        connection.return_value.get_account.side_effect \u003d ["},{"line_number":398,"context_line":"            (None, [{\u0027name\u0027: \u0027container\u0027}]),"}],"source_content_type":"text/x-python","patch_set":14,"id":"fa1b9901_8852f133","line":395,"updated":"2015-08-26 14:54:47.000000000","message":"nit: not necessary","commit_id":"a8c4df98eee43b419d6dd30e80c838d9f2efd025"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f8adf6659ef7e131e9ab522f397842153e0b604c","unresolved":false,"context_lines":[{"line_number":393,"context_line":"            (None, []),"},{"line_number":394,"context_line":"        ]"},{"line_number":395,"context_line":"        connection.return_value.auth_end_time \u003d 0"},{"line_number":396,"context_line":"        connection.return_value.attempts \u003d 0"},{"line_number":397,"context_line":"        connection.return_value.get_account.side_effect \u003d ["},{"line_number":398,"context_line":"            (None, [{\u0027name\u0027: \u0027container\u0027}]),"},{"line_number":399,"context_line":"            (None, [])"}],"source_content_type":"text/x-python","patch_set":14,"id":"fa1b9901_a826d5cb","line":396,"updated":"2015-08-26 14:54:47.000000000","message":"nit: not necessary","commit_id":"a8c4df98eee43b419d6dd30e80c838d9f2efd025"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f8adf6659ef7e131e9ab522f397842153e0b604c","unresolved":false,"context_lines":[{"line_number":412,"context_line":"        mock_shuffle.reset_mock()"},{"line_number":413,"context_line":"        connection.return_value.get_object.return_value \u003d ["},{"line_number":414,"context_line":"            {\u0027content-type\u0027: \u0027text/plain\u0027,"},{"line_number":415,"context_line":"             \u0027etag\u0027: \u0027d41d8cd98f00b204e9800998ecf8427e\u0027},"},{"line_number":416,"context_line":"            \u0027\u0027]"},{"line_number":417,"context_line":""},{"line_number":418,"context_line":"        connection.return_value.get_container.side_effect \u003d ["}],"source_content_type":"text/x-python","patch_set":14,"id":"fa1b9901_a33b56d0","line":415,"updated":"2015-08-26 14:54:47.000000000","message":"nit: return_value does not need to be re-set, it persists in the mock object\n\nnit : could use EMPTY_ETAG","commit_id":"a8c4df98eee43b419d6dd30e80c838d9f2efd025"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f8adf6659ef7e131e9ab522f397842153e0b604c","unresolved":false,"context_lines":[{"line_number":421,"context_line":"            (None, []),"},{"line_number":422,"context_line":"        ]"},{"line_number":423,"context_line":"        connection.return_value.auth_end_time \u003d 0"},{"line_number":424,"context_line":"        connection.return_value.attempts \u003d 0"},{"line_number":425,"context_line":"        connection.return_value.get_account.side_effect \u003d ["},{"line_number":426,"context_line":"            (None, [{\u0027name\u0027: \u0027container\u0027}]),"},{"line_number":427,"context_line":"            (None, [])"}],"source_content_type":"text/x-python","patch_set":14,"id":"fa1b9901_0814a14a","line":424,"updated":"2015-08-26 14:54:47.000000000","message":"nit: as above, these mocked return values are not necessary","commit_id":"a8c4df98eee43b419d6dd30e80c838d9f2efd025"}]}
