)]}'
{"tox.ini":[{"author":{"_account_id":2,"name":"Monty Taylor","email":"mordred@inaugust.com","username":"mordred"},"change_message_id":"9e3eb0dc195c55803922214081ffa2a4b8f5aa33","unresolved":false,"context_lines":[{"line_number":16,"context_line":"[testenv:pep8]"},{"line_number":17,"context_line":"install_command \u003d pip install {opts} {packages}"},{"line_number":18,"context_line":"commands \u003d"},{"line_number":19,"context_line":"  mypy --strict zuul_registry/filesystem.py"},{"line_number":20,"context_line":"  flake8 {posargs}"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"[testenv:venv]"}],"source_content_type":"text/x-properties","patch_set":3,"id":"3fa7e38b_0227c2b8","line":19,"updated":"2019-10-03 08:58:01.000000000","message":"You add types to everything to seem to only be running mypy on filesystem here ...","commit_id":"0d4f01fde6cd2028f8ab7ff4632ad9e86854c8e1"},{"author":{"_account_id":2,"name":"Monty Taylor","email":"mordred@inaugust.com","username":"mordred"},"change_message_id":"009ff5c5c224f1cfb77b6f4d059203a411563c89","unresolved":false,"context_lines":[{"line_number":16,"context_line":"[testenv:pep8]"},{"line_number":17,"context_line":"install_command \u003d pip install {opts} {packages}"},{"line_number":18,"context_line":"commands \u003d"},{"line_number":19,"context_line":"  mypy --strict zuul_registry/filesystem.py"},{"line_number":20,"context_line":"  flake8 {posargs}"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"[testenv:venv]"}],"source_content_type":"text/x-properties","patch_set":3,"id":"3fa7e38b_a26fce90","line":19,"in_reply_to":"3fa7e38b_0227c2b8","updated":"2019-10-03 09:12:47.000000000","message":"NM - I see discussion in IRC about this. Maybe adding a comment here that it\u0027s not a mistake would be nice - but can be done in a followup.","commit_id":"0d4f01fde6cd2028f8ab7ff4632ad9e86854c8e1"},{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"b17939ea7aa15f23eb4b100875a81c71d396993b","unresolved":false,"context_lines":[{"line_number":16,"context_line":"[testenv:pep8]"},{"line_number":17,"context_line":"install_command \u003d pip install {opts} {packages}"},{"line_number":18,"context_line":"commands \u003d"},{"line_number":19,"context_line":"  mypy --strict zuul_registry/filesystem.py"},{"line_number":20,"context_line":"  flake8 {posargs}"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"[testenv:venv]"}],"source_content_type":"text/x-properties","patch_set":3,"id":"3fa7e38b_f2bfd1cd","line":19,"in_reply_to":"3fa7e38b_42f29a9c","updated":"2019-10-03 12:57:46.000000000","message":"Oops, that\u0027s a left over from PS1. Next PS will remove the filesystem module scope.","commit_id":"0d4f01fde6cd2028f8ab7ff4632ad9e86854c8e1"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"ac06beabcb03e8c0fe2cf4595798093bfb073f2e","unresolved":false,"context_lines":[{"line_number":16,"context_line":"[testenv:pep8]"},{"line_number":17,"context_line":"install_command \u003d pip install {opts} {packages}"},{"line_number":18,"context_line":"commands \u003d"},{"line_number":19,"context_line":"  mypy --strict zuul_registry/filesystem.py"},{"line_number":20,"context_line":"  flake8 {posargs}"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"[testenv:venv]"}],"source_content_type":"text/x-properties","patch_set":3,"id":"3fa7e38b_42f29a9c","line":19,"in_reply_to":"3fa7e38b_a26fce90","updated":"2019-10-03 09:51:39.000000000","message":"Yes please - I\u0027ve no idea what\u0027s happening here","commit_id":"0d4f01fde6cd2028f8ab7ff4632ad9e86854c8e1"}],"zuul_registry/filesystem.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"865bceff92b51bfec43541aad39ab01a6bc8a68a","unresolved":false,"context_lines":[{"line_number":63,"context_line":"        if not os.path.exists(path):"},{"line_number":64,"context_line":"            return None"},{"line_number":65,"context_line":"        with open(path, \u0027rb\u0027) as f:"},{"line_number":66,"context_line":"            while True:"},{"line_number":67,"context_line":"                chunk \u003d f.read(4096)"},{"line_number":68,"context_line":"                if not chunk:"},{"line_number":69,"context_line":"                    return"},{"line_number":70,"context_line":"                yield chunk"},{"line_number":71,"context_line":""},{"line_number":72,"context_line":"    def delete_object(self, path: str) -\u003e None:"},{"line_number":73,"context_line":"        path \u003d os.path.join(self.root, path)"}],"source_content_type":"text/x-python","patch_set":5,"id":"3fa7e38b_234af67f","line":70,"range":{"start_line":66,"start_character":12,"end_line":70,"end_character":27},"updated":"2019-10-03 23:08:45.000000000","message":"Maybe\n\n yield from iter(lambda: f.read(4096), b\u0027\u0027)\n\n? Might also want to pull the read size out to a constant or even make it properly configurable -- my gut says 4k is pretty small. If you do, I\u0027d also pass it to open() as a buffering kwarg.","commit_id":"cbf3fcd7e6b182bed3140d85e993d6e35f5b17ab"},{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"9e248408f03dd356c52284dc97401a6675d0a106","unresolved":false,"context_lines":[{"line_number":63,"context_line":"        if not os.path.exists(path):"},{"line_number":64,"context_line":"            return None"},{"line_number":65,"context_line":"        with open(path, \u0027rb\u0027) as f:"},{"line_number":66,"context_line":"            while True:"},{"line_number":67,"context_line":"                chunk \u003d f.read(4096)"},{"line_number":68,"context_line":"                if not chunk:"},{"line_number":69,"context_line":"                    return"},{"line_number":70,"context_line":"                yield chunk"},{"line_number":71,"context_line":""},{"line_number":72,"context_line":"    def delete_object(self, path: str) -\u003e None:"},{"line_number":73,"context_line":"        path \u003d os.path.join(self.root, path)"}],"source_content_type":"text/x-python","patch_set":5,"id":"3fa7e38b_49c07351","line":70,"range":{"start_line":66,"start_character":12,"end_line":70,"end_character":27},"in_reply_to":"3fa7e38b_234af67f","updated":"2019-10-04 01:39:23.000000000","message":"+1","commit_id":"cbf3fcd7e6b182bed3140d85e993d6e35f5b17ab"}],"zuul_registry/main.py":[{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"ac06beabcb03e8c0fe2cf4595798093bfb073f2e","unresolved":false,"context_lines":[{"line_number":21,"context_line":"import json"},{"line_number":22,"context_line":"import urllib"},{"line_number":23,"context_line":"import yaml"},{"line_number":24,"context_line":"from typing import Any, Dict, List, Optional, Union"},{"line_number":25,"context_line":""},{"line_number":26,"context_line":"from . import filesystem"},{"line_number":27,"context_line":"from . import storage"}],"source_content_type":"text/x-python","patch_set":3,"id":"3fa7e38b_424e1ac2","line":24,"updated":"2019-10-03 09:51:39.000000000","message":"I wonder if we should make this another exception to the \"only import modules\" rule, like the various i18n markers? If not, this needs to be changed","commit_id":"0d4f01fde6cd2028f8ab7ff4632ad9e86854c8e1"},{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"b17939ea7aa15f23eb4b100875a81c71d396993b","unresolved":false,"context_lines":[{"line_number":21,"context_line":"import json"},{"line_number":22,"context_line":"import urllib"},{"line_number":23,"context_line":"import yaml"},{"line_number":24,"context_line":"from typing import Any, Dict, List, Optional, Union"},{"line_number":25,"context_line":""},{"line_number":26,"context_line":"from . import filesystem"},{"line_number":27,"context_line":"from . import storage"}],"source_content_type":"text/x-python","patch_set":3,"id":"3fa7e38b_5293455d","line":24,"in_reply_to":"3fa7e38b_424e1ac2","updated":"2019-10-03 12:57:46.000000000","message":"What is the rule you are referring too?","commit_id":"0d4f01fde6cd2028f8ab7ff4632ad9e86854c8e1"},{"author":{"_account_id":1,"name":"James E. Blair","email":"jim@acmegating.com","username":"corvus"},"change_message_id":"ab76d3b22503d2fa933597cdd05bdb59ed77c2f1","unresolved":false,"context_lines":[{"line_number":128,"context_line":"           \u0027response.stream\u0027: True})"},{"line_number":129,"context_line":"    def get_blob(self,"},{"line_number":130,"context_line":"                 repository: str,"},{"line_number":131,"context_line":"                 digest: str) -\u003e Optional[Generator[bytes, None, None]]:"},{"line_number":132,"context_line":"        namespace \u003d self.get_namespace()"},{"line_number":133,"context_line":"        self.log.info(\u0027Get blob %s %s\u0027, repository, digest)"},{"line_number":134,"context_line":"        size \u003d self.storage.blob_size(namespace, digest)"}],"source_content_type":"text/x-python","patch_set":5,"id":"3fa7e38b_d5062621","line":131,"updated":"2019-10-04 18:03:43.000000000","message":"How did you know to put Generator[bytes, None, None] here?","commit_id":"cbf3fcd7e6b182bed3140d85e993d6e35f5b17ab"},{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"4e591597166b45f4d5799ee0deb16baa58c356ab","unresolved":false,"context_lines":[{"line_number":128,"context_line":"           \u0027response.stream\u0027: True})"},{"line_number":129,"context_line":"    def get_blob(self,"},{"line_number":130,"context_line":"                 repository: str,"},{"line_number":131,"context_line":"                 digest: str) -\u003e Optional[Generator[bytes, None, None]]:"},{"line_number":132,"context_line":"        namespace \u003d self.get_namespace()"},{"line_number":133,"context_line":"        self.log.info(\u0027Get blob %s %s\u0027, repository, digest)"},{"line_number":134,"context_line":"        size \u003d self.storage.blob_size(namespace, digest)"}],"source_content_type":"text/x-python","patch_set":5,"id":"3fa7e38b_409276a1","line":131,"in_reply_to":"3fa7e38b_d5062621","updated":"2019-10-04 18:33:22.000000000","message":"Because mypy knows that storage.stream_blob returns a generator, and thus the get_blob definition need to at least contains that type. The Generator and Callable syntax is a bit odd at first, it\u0027s syntax is documented here: https://docs.python.org/3/library/typing.html#typing.Generator  It\u0027s Generator[YieldType, SendType, ReturnType]","commit_id":"cbf3fcd7e6b182bed3140d85e993d6e35f5b17ab"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"865bceff92b51bfec43541aad39ab01a6bc8a68a","unresolved":false,"context_lines":[{"line_number":131,"context_line":"                 digest: str) -\u003e Optional[Generator[bytes, None, None]]:"},{"line_number":132,"context_line":"        namespace \u003d self.get_namespace()"},{"line_number":133,"context_line":"        self.log.info(\u0027Get blob %s %s\u0027, repository, digest)"},{"line_number":134,"context_line":"        size \u003d self.storage.blob_size(namespace, digest)"},{"line_number":135,"context_line":"        if size is None:"},{"line_number":136,"context_line":"            self.not_found()"},{"line_number":137,"context_line":"            return None"},{"line_number":138,"context_line":"        res \u003d cherrypy.response"},{"line_number":139,"context_line":"        res.headers[\u0027Docker-Content-Digest\u0027] \u003d digest"},{"line_number":140,"context_line":"        return self.storage.stream_blob(namespace, digest)"}],"source_content_type":"text/x-python","patch_set":5,"id":"3fa7e38b_ee55a5fb","line":137,"range":{"start_line":134,"start_character":8,"end_line":137,"end_character":23},"updated":"2019-10-03 23:08:45.000000000","message":"Off-topic: so when using an object store... we make two requests for every GET? First a HEAD to check the size, then a GET to fetch the data (which may not match what was reported for the HEAD)?","commit_id":"cbf3fcd7e6b182bed3140d85e993d6e35f5b17ab"},{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"9e248408f03dd356c52284dc97401a6675d0a106","unresolved":false,"context_lines":[{"line_number":131,"context_line":"                 digest: str) -\u003e Optional[Generator[bytes, None, None]]:"},{"line_number":132,"context_line":"        namespace \u003d self.get_namespace()"},{"line_number":133,"context_line":"        self.log.info(\u0027Get blob %s %s\u0027, repository, digest)"},{"line_number":134,"context_line":"        size \u003d self.storage.blob_size(namespace, digest)"},{"line_number":135,"context_line":"        if size is None:"},{"line_number":136,"context_line":"            self.not_found()"},{"line_number":137,"context_line":"            return None"},{"line_number":138,"context_line":"        res \u003d cherrypy.response"},{"line_number":139,"context_line":"        res.headers[\u0027Docker-Content-Digest\u0027] \u003d digest"},{"line_number":140,"context_line":"        return self.storage.stream_blob(namespace, digest)"}],"source_content_type":"text/x-python","patch_set":5,"id":"3fa7e38b_c9e22302","line":137,"range":{"start_line":134,"start_character":8,"end_line":137,"end_character":23},"in_reply_to":"3fa7e38b_ee55a5fb","updated":"2019-10-04 01:39:23.000000000","message":"The size doesn\u0027t seem to be used here for the GET, only to check if the blob exists.","commit_id":"cbf3fcd7e6b182bed3140d85e993d6e35f5b17ab"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"865bceff92b51bfec43541aad39ab01a6bc8a68a","unresolved":false,"context_lines":[{"line_number":137,"context_line":"            return None"},{"line_number":138,"context_line":"        res \u003d cherrypy.response"},{"line_number":139,"context_line":"        res.headers[\u0027Docker-Content-Digest\u0027] \u003d digest"},{"line_number":140,"context_line":"        return self.storage.stream_blob(namespace, digest)"},{"line_number":141,"context_line":""},{"line_number":142,"context_line":"    @cherrypy.expose  # type: ignore"},{"line_number":143,"context_line":"    @cherrypy.config(  # type: ignore"}],"source_content_type":"text/x-python","patch_set":5,"id":"3fa7e38b_83064a20","line":140,"range":{"start_line":140,"start_character":28,"end_line":140,"end_character":39},"updated":"2019-10-03 23:08:45.000000000","message":"+100 -- OOM errors suck.\n\nBut -- I wonder if we switched from a response with a Content-Length to a chunk-encoded response... was that intentional?","commit_id":"cbf3fcd7e6b182bed3140d85e993d6e35f5b17ab"},{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"9e248408f03dd356c52284dc97401a6675d0a106","unresolved":false,"context_lines":[{"line_number":137,"context_line":"            return None"},{"line_number":138,"context_line":"        res \u003d cherrypy.response"},{"line_number":139,"context_line":"        res.headers[\u0027Docker-Content-Digest\u0027] \u003d digest"},{"line_number":140,"context_line":"        return self.storage.stream_blob(namespace, digest)"},{"line_number":141,"context_line":""},{"line_number":142,"context_line":"    @cherrypy.expose  # type: ignore"},{"line_number":143,"context_line":"    @cherrypy.config(  # type: ignore"}],"source_content_type":"text/x-python","patch_set":5,"id":"3fa7e38b_a9e5670c","line":140,"range":{"start_line":140,"start_character":28,"end_line":140,"end_character":39},"in_reply_to":"3fa7e38b_83064a20","updated":"2019-10-04 01:39:23.000000000","message":"I think that cherrypy automatically do that when using response.stream and generator.","commit_id":"cbf3fcd7e6b182bed3140d85e993d6e35f5b17ab"},{"author":{"_account_id":1,"name":"James E. Blair","email":"jim@acmegating.com","username":"corvus"},"change_message_id":"ab76d3b22503d2fa933597cdd05bdb59ed77c2f1","unresolved":false,"context_lines":[{"line_number":233,"context_line":"            return manifestblob"},{"line_number":234,"context_line":"        manifest_obj \u003d self.storage.get_manifest(namespace, repository, ref)"},{"line_number":235,"context_line":"        if manifest_obj is None:"},{"line_number":236,"context_line":"            manifest: Dict[Any, Any] \u003d {}"},{"line_number":237,"context_line":"        else:"},{"line_number":238,"context_line":"            manifest \u003d json.loads(manifest_obj)"},{"line_number":239,"context_line":"        for ct in [x.strip() for x in headers[\u0027Accept\u0027].split(\u0027,\u0027)]:"}],"source_content_type":"text/x-python","patch_set":5,"id":"3fa7e38b_f501e207","line":236,"updated":"2019-10-04 18:03:43.000000000","message":"I find this syntax very unintuitive and hard to read.","commit_id":"cbf3fcd7e6b182bed3140d85e993d6e35f5b17ab"},{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"4e591597166b45f4d5799ee0deb16baa58c356ab","unresolved":false,"context_lines":[{"line_number":233,"context_line":"            return manifestblob"},{"line_number":234,"context_line":"        manifest_obj \u003d self.storage.get_manifest(namespace, repository, ref)"},{"line_number":235,"context_line":"        if manifest_obj is None:"},{"line_number":236,"context_line":"            manifest: Dict[Any, Any] \u003d {}"},{"line_number":237,"context_line":"        else:"},{"line_number":238,"context_line":"            manifest \u003d json.loads(manifest_obj)"},{"line_number":239,"context_line":"        for ct in [x.strip() for x in headers[\u0027Accept\u0027].split(\u0027,\u0027)]:"}],"source_content_type":"text/x-python","patch_set":5,"id":"3fa7e38b_40d7d650","line":236,"in_reply_to":"3fa7e38b_f501e207","updated":"2019-10-04 18:33:22.000000000","message":"Hum, that\u0027s because json returns such type. This is a bit odd because the variable is first defined in the if then scope.","commit_id":"cbf3fcd7e6b182bed3140d85e993d6e35f5b17ab"},{"author":{"_account_id":1,"name":"James E. Blair","email":"jim@acmegating.com","username":"corvus"},"change_message_id":"ab76d3b22503d2fa933597cdd05bdb59ed77c2f1","unresolved":false,"context_lines":[{"line_number":265,"context_line":"        cherrypy.server.ssl_private_key \u003d self.conf[\u0027tls-key\u0027]"},{"line_number":266,"context_line":""},{"line_number":267,"context_line":"        driver \u003d self.conf[\u0027storage\u0027][\u0027driver\u0027]"},{"line_number":268,"context_line":"        backend \u003d DRIVERS[driver](self.conf[\u0027storage\u0027])  # type: ignore"},{"line_number":269,"context_line":"        self.store \u003d storage.Storage(backend, self.conf[\u0027storage\u0027])"},{"line_number":270,"context_line":""},{"line_number":271,"context_line":"        authz \u003d Authorization(self.conf[\u0027users\u0027])"}],"source_content_type":"text/x-python","patch_set":5,"id":"3fa7e38b_a0feca02","line":268,"updated":"2019-10-04 18:03:43.000000000","message":"Why ignore here?","commit_id":"cbf3fcd7e6b182bed3140d85e993d6e35f5b17ab"},{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"4e591597166b45f4d5799ee0deb16baa58c356ab","unresolved":false,"context_lines":[{"line_number":265,"context_line":"        cherrypy.server.ssl_private_key \u003d self.conf[\u0027tls-key\u0027]"},{"line_number":266,"context_line":""},{"line_number":267,"context_line":"        driver \u003d self.conf[\u0027storage\u0027][\u0027driver\u0027]"},{"line_number":268,"context_line":"        backend \u003d DRIVERS[driver](self.conf[\u0027storage\u0027])  # type: ignore"},{"line_number":269,"context_line":"        self.store \u003d storage.Storage(backend, self.conf[\u0027storage\u0027])"},{"line_number":270,"context_line":""},{"line_number":271,"context_line":"        authz \u003d Authorization(self.conf[\u0027users\u0027])"}],"source_content_type":"text/x-python","patch_set":5,"id":"3fa7e38b_c0be66d3","line":268,"in_reply_to":"3fa7e38b_a0feca02","updated":"2019-10-04 18:33:22.000000000","message":"Next PS fixes that, it\u0027s because the DRIVERS needed an annotation.","commit_id":"cbf3fcd7e6b182bed3140d85e993d6e35f5b17ab"},{"author":{"_account_id":1,"name":"James E. Blair","email":"jim@acmegating.com","username":"corvus"},"change_message_id":"574324518df272060c0ac6526e1feb36e8b8207a","unresolved":false,"context_lines":[{"line_number":117,"context_line":"        size \u003d self.storage.blob_size(namespace, digest)"},{"line_number":118,"context_line":"        if size is None:"},{"line_number":119,"context_line":"            self.not_found()"},{"line_number":120,"context_line":"            return None"},{"line_number":121,"context_line":"        res \u003d cherrypy.response"},{"line_number":122,"context_line":"        res.headers[\u0027Docker-Content-Digest\u0027] \u003d digest"},{"line_number":123,"context_line":"        return {}"}],"source_content_type":"text/x-python","patch_set":6,"id":"3fa7e38b_606f72c5","line":120,"updated":"2019-10-04 18:09:11.000000000","message":"Why did you change this?  This is set up for the shadow work.","commit_id":"4f4830f0f4d40c8336c346c84e044bfdf574dba0"},{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"4e591597166b45f4d5799ee0deb16baa58c356ab","unresolved":false,"context_lines":[{"line_number":117,"context_line":"        size \u003d self.storage.blob_size(namespace, digest)"},{"line_number":118,"context_line":"        if size is None:"},{"line_number":119,"context_line":"            self.not_found()"},{"line_number":120,"context_line":"            return None"},{"line_number":121,"context_line":"        res \u003d cherrypy.response"},{"line_number":122,"context_line":"        res.headers[\u0027Docker-Content-Digest\u0027] \u003d digest"},{"line_number":123,"context_line":"        return {}"}],"source_content_type":"text/x-python","patch_set":6,"id":"3fa7e38b_00c0fe29","line":120,"in_reply_to":"3fa7e38b_606f72c5","updated":"2019-10-04 18:33:22.000000000","message":"This is because \"not_found\" of \"RegistryAPI\" does not return a value.\n\nHow is making shadow work?","commit_id":"4f4830f0f4d40c8336c346c84e044bfdf574dba0"}],"zuul_registry/storage.py":[{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"ac06beabcb03e8c0fe2cf4595798093bfb073f2e","unresolved":false,"context_lines":[{"line_number":20,"context_line":"import rehash  # type: ignore"},{"line_number":21,"context_line":"import threading"},{"line_number":22,"context_line":"import time"},{"line_number":23,"context_line":"from io import BytesIO"},{"line_number":24,"context_line":"from typing import Dict, List, Optional, Tuple"},{"line_number":25,"context_line":"from uuid import uuid4"},{"line_number":26,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"3fa7e38b_82d972f5","line":23,"updated":"2019-10-03 09:51:39.000000000","message":"This definitely shouldn\u0027t be an exception to the \"only import modules\" rule, but maybe that\u0027s not enforced in zuul?","commit_id":"0d4f01fde6cd2028f8ab7ff4632ad9e86854c8e1"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"ac06beabcb03e8c0fe2cf4595798093bfb073f2e","unresolved":false,"context_lines":[{"line_number":25,"context_line":"from uuid import uuid4"},{"line_number":26,"context_line":""},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"from . storageutils import ObjectInfo, StorageDriver, UploadStreamer"},{"line_number":29,"context_line":""},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"class UploadRecord:"}],"source_content_type":"text/x-python","patch_set":3,"id":"3fa7e38b_42e37aa5","line":28,"updated":"2019-10-03 09:51:39.000000000","message":"Ditto","commit_id":"0d4f01fde6cd2028f8ab7ff4632ad9e86854c8e1"},{"author":{"_account_id":1,"name":"James E. Blair","email":"jim@acmegating.com","username":"corvus"},"change_message_id":"ab76d3b22503d2fa933597cdd05bdb59ed77c2f1","unresolved":false,"context_lines":[{"line_number":240,"context_line":"        now \u003d time.time()"},{"line_number":241,"context_line":"        upload_target \u003d now - self.upload_exp"},{"line_number":242,"context_line":"        if self.manifest_exp:"},{"line_number":243,"context_line":"            manifest_target: Optional[float] \u003d now - self.manifest_exp"},{"line_number":244,"context_line":"        else:"},{"line_number":245,"context_line":"            manifest_target \u003d None"},{"line_number":246,"context_line":"        for namespace in self.backend.list_objects(\u0027\u0027):"}],"source_content_type":"text/x-python","patch_set":5,"id":"3fa7e38b_c0018606","line":243,"updated":"2019-10-04 18:03:43.000000000","message":"This also is difficult to read.  And shouldn\u0027t this not even be necessary?","commit_id":"cbf3fcd7e6b182bed3140d85e993d6e35f5b17ab"},{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"4e591597166b45f4d5799ee0deb16baa58c356ab","unresolved":false,"context_lines":[{"line_number":240,"context_line":"        now \u003d time.time()"},{"line_number":241,"context_line":"        upload_target \u003d now - self.upload_exp"},{"line_number":242,"context_line":"        if self.manifest_exp:"},{"line_number":243,"context_line":"            manifest_target: Optional[float] \u003d now - self.manifest_exp"},{"line_number":244,"context_line":"        else:"},{"line_number":245,"context_line":"            manifest_target \u003d None"},{"line_number":246,"context_line":"        for namespace in self.backend.list_objects(\u0027\u0027):"}],"source_content_type":"text/x-python","patch_set":5,"id":"3fa7e38b_e0ab6272","line":243,"in_reply_to":"3fa7e38b_c0018606","updated":"2019-10-04 18:33:22.000000000","message":"This is because L245 this variable is set to None. Perhaps we should set it to None L241.","commit_id":"cbf3fcd7e6b182bed3140d85e993d6e35f5b17ab"}],"zuul_registry/storageutils.py":[{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"ac06beabcb03e8c0fe2cf4595798093bfb073f2e","unresolved":false,"context_lines":[{"line_number":49,"context_line":"            yield d"},{"line_number":50,"context_line":""},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"ObjectData \u003d Union[bytes, UploadStreamer]"},{"line_number":53,"context_line":""},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"class StorageDriver(metaclass\u003dABCMeta):"}],"source_content_type":"text/x-python","patch_set":3,"id":"3fa7e38b_c2e8ca7d","line":52,"updated":"2019-10-03 09:51:39.000000000","message":"How come you moved this? Wonder if it should have been done separately?","commit_id":"0d4f01fde6cd2028f8ab7ff4632ad9e86854c8e1"},{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"b17939ea7aa15f23eb4b100875a81c71d396993b","unresolved":false,"context_lines":[{"line_number":49,"context_line":"            yield d"},{"line_number":50,"context_line":""},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"ObjectData \u003d Union[bytes, UploadStreamer]"},{"line_number":53,"context_line":""},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"class StorageDriver(metaclass\u003dABCMeta):"}],"source_content_type":"text/x-python","patch_set":3,"id":"3fa7e38b_92a9bd91","line":52,"in_reply_to":"3fa7e38b_c2e8ca7d","updated":"2019-10-03 12:57:46.000000000","message":"This is because we need the UploadStreamer class name reference to properly type the put method below. And to avoid circular import this class may live better in this module.","commit_id":"0d4f01fde6cd2028f8ab7ff4632ad9e86854c8e1"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"865bceff92b51bfec43541aad39ab01a6bc8a68a","unresolved":false,"context_lines":[{"line_number":42,"context_line":"        self.queue.put(data)"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"    def __iter__(self) -\u003e Generator[bytes, None, None]:"},{"line_number":45,"context_line":"        while True:"},{"line_number":46,"context_line":"            d \u003d self.queue.get()"},{"line_number":47,"context_line":"            if d is None:"},{"line_number":48,"context_line":"                break"},{"line_number":49,"context_line":"            yield d"},{"line_number":50,"context_line":""},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"ObjectData \u003d Union[bytes, UploadStreamer]"}],"source_content_type":"text/x-python","patch_set":5,"id":"3fa7e38b_237196e1","line":49,"range":{"start_line":45,"start_character":8,"end_line":49,"end_character":19},"updated":"2019-10-03 23:08:45.000000000","message":"Simpler as\n\n yield from iter(self.queue.get, None)\n\n? Oh, just realized this was just moved from elsewhere...","commit_id":"cbf3fcd7e6b182bed3140d85e993d6e35f5b17ab"},{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"9e248408f03dd356c52284dc97401a6675d0a106","unresolved":false,"context_lines":[{"line_number":42,"context_line":"        self.queue.put(data)"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"    def __iter__(self) -\u003e Generator[bytes, None, None]:"},{"line_number":45,"context_line":"        while True:"},{"line_number":46,"context_line":"            d \u003d self.queue.get()"},{"line_number":47,"context_line":"            if d is None:"},{"line_number":48,"context_line":"                break"},{"line_number":49,"context_line":"            yield d"},{"line_number":50,"context_line":""},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"ObjectData \u003d Union[bytes, UploadStreamer]"}],"source_content_type":"text/x-python","patch_set":5,"id":"3fa7e38b_69ef6fe9","line":49,"range":{"start_line":45,"start_character":8,"end_line":49,"end_character":19},"in_reply_to":"3fa7e38b_237196e1","updated":"2019-10-04 01:39:23.000000000","message":"+1","commit_id":"cbf3fcd7e6b182bed3140d85e993d6e35f5b17ab"}],"zuul_registry/swift.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"fbcf0085a6504d96857bd4a48d2f9b8039d548c9","unresolved":false,"context_lines":[{"line_number":109,"context_line":"                if isinstance(data, bytes):"},{"line_number":110,"context_line":"                    f.write(data)"},{"line_number":111,"context_line":"                else:"},{"line_number":112,"context_line":"                    for chunk in data:"},{"line_number":113,"context_line":"                        f.write(chunk)"},{"line_number":114,"context_line":"            retry_function("},{"line_number":115,"context_line":"                lambda: self.conn.object_store.upload_object(  # type: ignore"}],"source_content_type":"text/x-python","patch_set":2,"id":"3fa7e38b_ab5811fa","line":112,"range":{"start_line":112,"start_character":20,"end_line":112,"end_character":37},"updated":"2019-10-02 22:57:59.000000000","message":"Looks like this could also take an iterable of bytes...","commit_id":"209698aa5275f85a4269ef8a04a3d51056111edc"},{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"40b5276e29dd98cd191fa9b52c1a216eec92644b","unresolved":false,"context_lines":[{"line_number":109,"context_line":"                if isinstance(data, bytes):"},{"line_number":110,"context_line":"                    f.write(data)"},{"line_number":111,"context_line":"                else:"},{"line_number":112,"context_line":"                    for chunk in data:"},{"line_number":113,"context_line":"                        f.write(chunk)"},{"line_number":114,"context_line":"            retry_function("},{"line_number":115,"context_line":"                lambda: self.conn.object_store.upload_object(  # type: ignore"}],"source_content_type":"text/x-python","patch_set":2,"id":"3fa7e38b_abe571de","line":112,"range":{"start_line":112,"start_character":20,"end_line":112,"end_character":37},"in_reply_to":"3fa7e38b_ab5811fa","updated":"2019-10-02 23:10:55.000000000","message":"good catch!","commit_id":"209698aa5275f85a4269ef8a04a3d51056111edc"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"865bceff92b51bfec43541aad39ab01a6bc8a68a","unresolved":false,"context_lines":[{"line_number":137,"context_line":"                    self.get_url(path), stream\u003dTrue))"},{"line_number":138,"context_line":"        except keystoneauth1.exceptions.http.NotFound:"},{"line_number":139,"context_line":"            return None"},{"line_number":140,"context_line":"        return ret.iter_content(chunk_size\u003d4096)  # type: ignore"},{"line_number":141,"context_line":""},{"line_number":142,"context_line":"    def delete_object(self, path: str) -\u003e None:"},{"line_number":143,"context_line":"        retry_function("}],"source_content_type":"text/x-python","patch_set":5,"id":"3fa7e38b_6e6215db","line":140,"range":{"start_line":140,"start_character":43,"end_line":140,"end_character":47},"updated":"2019-10-03 23:08:45.000000000","message":"As with the filesystem module, you might want to pull this out to a constant.","commit_id":"cbf3fcd7e6b182bed3140d85e993d6e35f5b17ab"},{"author":{"_account_id":9311,"name":"Tristan Cacqueray","email":"tdecacqu@redhat.com","username":"tristanC"},"change_message_id":"9e248408f03dd356c52284dc97401a6675d0a106","unresolved":false,"context_lines":[{"line_number":137,"context_line":"                    self.get_url(path), stream\u003dTrue))"},{"line_number":138,"context_line":"        except keystoneauth1.exceptions.http.NotFound:"},{"line_number":139,"context_line":"            return None"},{"line_number":140,"context_line":"        return ret.iter_content(chunk_size\u003d4096)  # type: ignore"},{"line_number":141,"context_line":""},{"line_number":142,"context_line":"    def delete_object(self, path: str) -\u003e None:"},{"line_number":143,"context_line":"        retry_function("}],"source_content_type":"text/x-python","patch_set":5,"id":"3fa7e38b_89ec2bf4","line":140,"range":{"start_line":140,"start_character":43,"end_line":140,"end_character":47},"in_reply_to":"3fa7e38b_6e6215db","updated":"2019-10-04 01:39:23.000000000","message":"+1","commit_id":"cbf3fcd7e6b182bed3140d85e993d6e35f5b17ab"}]}
