)]}'
{"karbor/services/protection/bank_plugins/s3_bank_plugin.py":[{"author":{"_account_id":17151,"name":"chenying","email":"chenyingko@gmail.com","username":"chenying"},"change_message_id":"10171cad7fde43f42569b7890b89b58635ea7646","unresolved":false,"context_lines":[{"line_number":147,"context_line":"            raise exception.BankGetObjectFailed(reason\u003derr, key\u003dkey)"},{"line_number":148,"context_line":""},{"line_number":149,"context_line":"    def list_objects(self, prefix\u003dNone, limit\u003dNone, marker\u003dNone,"},{"line_number":150,"context_line":"                     sort_dir\u003dNone):"},{"line_number":151,"context_line":"        try:"},{"line_number":152,"context_line":"            response \u003d self._get_bucket("},{"line_number":153,"context_line":"                bucket\u003dself.bank_object_bucket,"}],"source_content_type":"text/x-python","patch_set":6,"id":"1f1a1f67_06164356","line":150,"range":{"start_line":150,"start_character":21,"end_line":150,"end_character":29},"updated":"2017-07-18 02:55:25.000000000","message":"Can the S3 handle the sort_dir parameter? or this parameter is not needed?","commit_id":"3a5c6cb7090f1ca2ec0bb1342e13b810a1b5abff"},{"author":{"_account_id":21224,"name":"jiaopengju","email":"jiaopengju_yewu@cmss.chinamobile.com","username":"jiaopengju"},"change_message_id":"466a53254f5ec857ed8050211ec5d4ab86810636","unresolved":false,"context_lines":[{"line_number":147,"context_line":"            raise exception.BankGetObjectFailed(reason\u003derr, key\u003dkey)"},{"line_number":148,"context_line":""},{"line_number":149,"context_line":"    def list_objects(self, prefix\u003dNone, limit\u003dNone, marker\u003dNone,"},{"line_number":150,"context_line":"                     sort_dir\u003dNone):"},{"line_number":151,"context_line":"        try:"},{"line_number":152,"context_line":"            response \u003d self._get_bucket("},{"line_number":153,"context_line":"                bucket\u003dself.bank_object_bucket,"}],"source_content_type":"text/x-python","patch_set":6,"id":"1f1a1f67_2980f0be","line":150,"range":{"start_line":150,"start_character":21,"end_line":150,"end_character":29},"in_reply_to":"1f1a1f67_06164356","updated":"2017-07-18 03:22:24.000000000","message":"sort_dir is not needed. I think we can remove it in another patch(use full listing)","commit_id":"3a5c6cb7090f1ca2ec0bb1342e13b810a1b5abff"},{"author":{"_account_id":20883,"name":"Yuval Brik","email":"yuval@brik.org.il","username":"yuvalbr"},"change_message_id":"0da07d19373b7fbcae8fdd48d62d9e79882fef03","unresolved":false,"context_lines":[{"line_number":195,"context_line":""},{"line_number":196,"context_line":"    def _put_object(self, bucket, obj, contents, headers\u003dNone):"},{"line_number":197,"context_line":"        try:"},{"line_number":198,"context_line":"            LOG.info(\u0027{0}, {1}, {2}\u0027.format(bucket, obj, headers))"},{"line_number":199,"context_line":"            self.connection.put_object("},{"line_number":200,"context_line":"                Bucket\u003dbucket,"},{"line_number":201,"context_line":"                Key\u003dobj,"}],"source_content_type":"text/x-python","patch_set":6,"id":"1f1a1f67_5bdf89d5","line":198,"range":{"start_line":198,"start_character":21,"end_line":198,"end_character":65},"updated":"2017-07-17 12:44:15.000000000","message":"a bit more informative","commit_id":"3a5c6cb7090f1ca2ec0bb1342e13b810a1b5abff"},{"author":{"_account_id":21224,"name":"jiaopengju","email":"jiaopengju_yewu@cmss.chinamobile.com","username":"jiaopengju"},"change_message_id":"466a53254f5ec857ed8050211ec5d4ab86810636","unresolved":false,"context_lines":[{"line_number":195,"context_line":""},{"line_number":196,"context_line":"    def _put_object(self, bucket, obj, contents, headers\u003dNone):"},{"line_number":197,"context_line":"        try:"},{"line_number":198,"context_line":"            LOG.info(\u0027{0}, {1}, {2}\u0027.format(bucket, obj, headers))"},{"line_number":199,"context_line":"            self.connection.put_object("},{"line_number":200,"context_line":"                Bucket\u003dbucket,"},{"line_number":201,"context_line":"                Key\u003dobj,"}],"source_content_type":"text/x-python","patch_set":6,"id":"1f1a1f67_4969ecf6","line":198,"range":{"start_line":198,"start_character":21,"end_line":198,"end_character":65},"in_reply_to":"1f1a1f67_5bdf89d5","updated":"2017-07-18 03:22:24.000000000","message":"This is using for debug, so I will remove it.","commit_id":"3a5c6cb7090f1ca2ec0bb1342e13b810a1b5abff"}],"karbor/services/protection/clients/s3.py":[{"author":{"_account_id":17151,"name":"chenying","email":"chenyingko@gmail.com","username":"chenying"},"change_message_id":"10171cad7fde43f42569b7890b89b58635ea7646","unresolved":false,"context_lines":[{"line_number":19,"context_line":"s3_client_opts \u003d ["},{"line_number":20,"context_line":"    cfg.StrOpt(SERVICE + \u0027_endpoint\u0027,"},{"line_number":21,"context_line":"               help\u003d\u0027URL of the S3 compatible storage endpoint.\u0027),"},{"line_number":22,"context_line":"    cfg.StrOpt(\u0027s3_access_key\u0027,"},{"line_number":23,"context_line":"               help\u003d\u0027Access key for S3 compatible storage.\u0027),"},{"line_number":24,"context_line":"    cfg.StrOpt(\u0027s3_secret_key\u0027,"},{"line_number":25,"context_line":"               secret\u003dTrue,"}],"source_content_type":"text/x-python","patch_set":6,"id":"1f1a1f67_c9c3bc88","line":22,"range":{"start_line":22,"start_character":16,"end_line":22,"end_character":18},"updated":"2017-07-18 02:55:25.000000000","message":"Why not use \u0027SERVICE +\u0027 here?","commit_id":"3a5c6cb7090f1ca2ec0bb1342e13b810a1b5abff"},{"author":{"_account_id":21224,"name":"jiaopengju","email":"jiaopengju_yewu@cmss.chinamobile.com","username":"jiaopengju"},"change_message_id":"466a53254f5ec857ed8050211ec5d4ab86810636","unresolved":false,"context_lines":[{"line_number":19,"context_line":"s3_client_opts \u003d ["},{"line_number":20,"context_line":"    cfg.StrOpt(SERVICE + \u0027_endpoint\u0027,"},{"line_number":21,"context_line":"               help\u003d\u0027URL of the S3 compatible storage endpoint.\u0027),"},{"line_number":22,"context_line":"    cfg.StrOpt(\u0027s3_access_key\u0027,"},{"line_number":23,"context_line":"               help\u003d\u0027Access key for S3 compatible storage.\u0027),"},{"line_number":24,"context_line":"    cfg.StrOpt(\u0027s3_secret_key\u0027,"},{"line_number":25,"context_line":"               secret\u003dTrue,"}],"source_content_type":"text/x-python","patch_set":6,"id":"1f1a1f67_c96a9c18","line":22,"range":{"start_line":22,"start_character":16,"end_line":22,"end_character":18},"in_reply_to":"1f1a1f67_c9c3bc88","updated":"2017-07-18 03:22:24.000000000","message":"Done","commit_id":"3a5c6cb7090f1ca2ec0bb1342e13b810a1b5abff"}],"karbor/tests/unit/protection/fake_s3_client.py":[{"author":{"_account_id":20883,"name":"Yuval Brik","email":"yuval@brik.org.il","username":"yuvalbr"},"change_message_id":"0da07d19373b7fbcae8fdd48d62d9e79882fef03","unresolved":false,"context_lines":[{"line_number":16,"context_line":"from botocore.exceptions import ClientError"},{"line_number":17,"context_line":""},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"class FakeS3Client(object):"},{"line_number":20,"context_line":"    def __init__(self, *args, **kwargs):"},{"line_number":21,"context_line":"        super(FakeS3Client, self).__init__()"},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"    @classmethod"},{"line_number":24,"context_line":"    def connection(cls, *args, **kargs):"},{"line_number":25,"context_line":"        return FakeS3Connection()"},{"line_number":26,"context_line":""},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"class FakeS3Connection(object):"},{"line_number":29,"context_line":"    def __init__(self, *args, **kwargs):"},{"line_number":30,"context_line":"        super(FakeS3Connection, self).__init__()"},{"line_number":31,"context_line":"        self.s3_dir \u003d tempfile.mkdtemp()"},{"line_number":32,"context_line":"        self.object_headers \u003d {}"},{"line_number":33,"context_line":""},{"line_number":34,"context_line":"    def create_bucket(self, Bucket):"},{"line_number":35,"context_line":"        bucket_dir \u003d self.s3_dir + \"/\" + Bucket"},{"line_number":36,"context_line":"        if os.path.exists(bucket_dir) is True:"},{"line_number":37,"context_line":"            return"},{"line_number":38,"context_line":"        else:"},{"line_number":39,"context_line":"            os.makedirs(bucket_dir)"},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"    def list_objects(self, Bucket, Prefix, MaxKeys, Marker):"},{"line_number":42,"context_line":"        bucket_dir \u003d self.s3_dir + \"/\" + Bucket"},{"line_number":43,"context_line":"        body \u003d []"},{"line_number":44,"context_line":"        if Prefix:"},{"line_number":45,"context_line":"            objects_dir \u003d bucket_dir + \"/\" + Prefix"},{"line_number":46,"context_line":"        else:"},{"line_number":47,"context_line":"            objects_dir \u003d bucket_dir"},{"line_number":48,"context_line":"        for f in os.listdir(objects_dir):"},{"line_number":49,"context_line":"            key_name \u003d f if not Prefix else \"{0}/{1}\".format(Prefix, f)"},{"line_number":50,"context_line":"            if os.path.isfile(objects_dir + \"/\" + f):"},{"line_number":51,"context_line":"                body.append({\"Key\": key_name})"},{"line_number":52,"context_line":"            else:"},{"line_number":53,"context_line":"                body.append(self.list_objects("},{"line_number":54,"context_line":"                    Bucket, key_name, MaxKeys, Marker"},{"line_number":55,"context_line":"                )[\u0027Contents\u0027])"},{"line_number":56,"context_line":"        return {\u0027Contents\u0027: body}"},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"    def put_object(self, Bucket, Key, Body, Metadata\u003dNone):"},{"line_number":59,"context_line":"        bucket_dir \u003d self.s3_dir + \"/\" + Bucket"},{"line_number":60,"context_line":"        obj_file \u003d bucket_dir + \"/\" + Key"},{"line_number":61,"context_line":"        obj_dir \u003d obj_file[0:obj_file.rfind(\"/\")]"},{"line_number":62,"context_line":"        if os.path.exists(bucket_dir) is True:"},{"line_number":63,"context_line":"            if os.path.exists(obj_dir) is False:"},{"line_number":64,"context_line":"                os.makedirs(obj_dir)"},{"line_number":65,"context_line":"            with open(obj_file, \"w\") as f:"},{"line_number":66,"context_line":"                f.write(Body)"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"            self.object_headers[obj_file] \u003d {}"},{"line_number":69,"context_line":"            for key, value in Metadata.items():"},{"line_number":70,"context_line":"                self.object_headers[obj_file][str(key)] \u003d str(value)"},{"line_number":71,"context_line":"            return"},{"line_number":72,"context_line":"        else:"},{"line_number":73,"context_line":"            raise ClientError(\"error_bucket\")"},{"line_number":74,"context_line":""},{"line_number":75,"context_line":"    def get_object(self, Bucket, Key):"},{"line_number":76,"context_line":"        bucket_dir \u003d self.s3_dir + \"/\" + Bucket"},{"line_number":77,"context_line":"        obj_file \u003d bucket_dir + \"/\" + Key"},{"line_number":78,"context_line":"        if os.path.exists(bucket_dir) is True:"},{"line_number":79,"context_line":"            if os.path.exists(obj_file) is True:"},{"line_number":80,"context_line":"                with open(obj_file, \"r\") as f:"},{"line_number":81,"context_line":"                    return {"},{"line_number":82,"context_line":"                        \u0027Metadata\u0027: self.object_headers[obj_file],"},{"line_number":83,"context_line":"                        \u0027Body\u0027: FakeS3ResponseStream(f.read())"},{"line_number":84,"context_line":"                    }"},{"line_number":85,"context_line":"            else:"},{"line_number":86,"context_line":"                raise ClientError(\"error_obj\")"},{"line_number":87,"context_line":"        else:"},{"line_number":88,"context_line":"            raise ClientError(\"error_container\")"},{"line_number":89,"context_line":""},{"line_number":90,"context_line":"    def delete_object(self, Bucket, Key):"},{"line_number":91,"context_line":"        bucket_dir \u003d self.s3_dir + \"/\" + Bucket"},{"line_number":92,"context_line":"        obj_file \u003d bucket_dir + \"/\" + Key"},{"line_number":93,"context_line":"        if os.path.exists(bucket_dir) is True:"},{"line_number":94,"context_line":"            if os.path.exists(obj_file) is True:"},{"line_number":95,"context_line":"                os.remove(obj_file)"},{"line_number":96,"context_line":"                self.object_headers.pop(obj_file)"},{"line_number":97,"context_line":"            else:"},{"line_number":98,"context_line":"                raise ClientError(\"error_obj\")"},{"line_number":99,"context_line":"        else:"},{"line_number":100,"context_line":"            raise ClientError(\"error_container\")"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":""},{"line_number":103,"context_line":"class FakeS3ResponseStream(object):"},{"line_number":104,"context_line":"    def __init__(self, data):"},{"line_number":105,"context_line":"        self.data \u003d data"},{"line_number":106,"context_line":""},{"line_number":107,"context_line":"    def read(self):"},{"line_number":108,"context_line":"        return self.data"}],"source_content_type":"text/x-python","patch_set":6,"id":"1f1a1f67_db1039ab","line":108,"range":{"start_line":19,"start_character":0,"end_line":108,"end_character":24},"updated":"2017-07-17 12:44:15.000000000","message":"1. Use lower case first letter for variable names (unless you are mimicking the same names as in botocore?)\n2. Can we use botocore Stubber instead?\nhttps://botocore.readthedocs.io/en/latest/reference/stubber.html\nIf not, I prefer if we store all of that in memory (dict) instead of file system.","commit_id":"3a5c6cb7090f1ca2ec0bb1342e13b810a1b5abff"},{"author":{"_account_id":21224,"name":"jiaopengju","email":"jiaopengju_yewu@cmss.chinamobile.com","username":"jiaopengju"},"change_message_id":"466a53254f5ec857ed8050211ec5d4ab86810636","unresolved":false,"context_lines":[{"line_number":16,"context_line":"from botocore.exceptions import ClientError"},{"line_number":17,"context_line":""},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"class FakeS3Client(object):"},{"line_number":20,"context_line":"    def __init__(self, *args, **kwargs):"},{"line_number":21,"context_line":"        super(FakeS3Client, self).__init__()"},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"    @classmethod"},{"line_number":24,"context_line":"    def connection(cls, *args, **kargs):"},{"line_number":25,"context_line":"        return FakeS3Connection()"},{"line_number":26,"context_line":""},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"class FakeS3Connection(object):"},{"line_number":29,"context_line":"    def __init__(self, *args, **kwargs):"},{"line_number":30,"context_line":"        super(FakeS3Connection, self).__init__()"},{"line_number":31,"context_line":"        self.s3_dir \u003d tempfile.mkdtemp()"},{"line_number":32,"context_line":"        self.object_headers \u003d {}"},{"line_number":33,"context_line":""},{"line_number":34,"context_line":"    def create_bucket(self, Bucket):"},{"line_number":35,"context_line":"        bucket_dir \u003d self.s3_dir + \"/\" + Bucket"},{"line_number":36,"context_line":"        if os.path.exists(bucket_dir) is True:"},{"line_number":37,"context_line":"            return"},{"line_number":38,"context_line":"        else:"},{"line_number":39,"context_line":"            os.makedirs(bucket_dir)"},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"    def list_objects(self, Bucket, Prefix, MaxKeys, Marker):"},{"line_number":42,"context_line":"        bucket_dir \u003d self.s3_dir + \"/\" + Bucket"},{"line_number":43,"context_line":"        body \u003d []"},{"line_number":44,"context_line":"        if Prefix:"},{"line_number":45,"context_line":"            objects_dir \u003d bucket_dir + \"/\" + Prefix"},{"line_number":46,"context_line":"        else:"},{"line_number":47,"context_line":"            objects_dir \u003d bucket_dir"},{"line_number":48,"context_line":"        for f in os.listdir(objects_dir):"},{"line_number":49,"context_line":"            key_name \u003d f if not Prefix else \"{0}/{1}\".format(Prefix, f)"},{"line_number":50,"context_line":"            if os.path.isfile(objects_dir + \"/\" + f):"},{"line_number":51,"context_line":"                body.append({\"Key\": key_name})"},{"line_number":52,"context_line":"            else:"},{"line_number":53,"context_line":"                body.append(self.list_objects("},{"line_number":54,"context_line":"                    Bucket, key_name, MaxKeys, Marker"},{"line_number":55,"context_line":"                )[\u0027Contents\u0027])"},{"line_number":56,"context_line":"        return {\u0027Contents\u0027: body}"},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"    def put_object(self, Bucket, Key, Body, Metadata\u003dNone):"},{"line_number":59,"context_line":"        bucket_dir \u003d self.s3_dir + \"/\" + Bucket"},{"line_number":60,"context_line":"        obj_file \u003d bucket_dir + \"/\" + Key"},{"line_number":61,"context_line":"        obj_dir \u003d obj_file[0:obj_file.rfind(\"/\")]"},{"line_number":62,"context_line":"        if os.path.exists(bucket_dir) is True:"},{"line_number":63,"context_line":"            if os.path.exists(obj_dir) is False:"},{"line_number":64,"context_line":"                os.makedirs(obj_dir)"},{"line_number":65,"context_line":"            with open(obj_file, \"w\") as f:"},{"line_number":66,"context_line":"                f.write(Body)"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"            self.object_headers[obj_file] \u003d {}"},{"line_number":69,"context_line":"            for key, value in Metadata.items():"},{"line_number":70,"context_line":"                self.object_headers[obj_file][str(key)] \u003d str(value)"},{"line_number":71,"context_line":"            return"},{"line_number":72,"context_line":"        else:"},{"line_number":73,"context_line":"            raise ClientError(\"error_bucket\")"},{"line_number":74,"context_line":""},{"line_number":75,"context_line":"    def get_object(self, Bucket, Key):"},{"line_number":76,"context_line":"        bucket_dir \u003d self.s3_dir + \"/\" + Bucket"},{"line_number":77,"context_line":"        obj_file \u003d bucket_dir + \"/\" + Key"},{"line_number":78,"context_line":"        if os.path.exists(bucket_dir) is True:"},{"line_number":79,"context_line":"            if os.path.exists(obj_file) is True:"},{"line_number":80,"context_line":"                with open(obj_file, \"r\") as f:"},{"line_number":81,"context_line":"                    return {"},{"line_number":82,"context_line":"                        \u0027Metadata\u0027: self.object_headers[obj_file],"},{"line_number":83,"context_line":"                        \u0027Body\u0027: FakeS3ResponseStream(f.read())"},{"line_number":84,"context_line":"                    }"},{"line_number":85,"context_line":"            else:"},{"line_number":86,"context_line":"                raise ClientError(\"error_obj\")"},{"line_number":87,"context_line":"        else:"},{"line_number":88,"context_line":"            raise ClientError(\"error_container\")"},{"line_number":89,"context_line":""},{"line_number":90,"context_line":"    def delete_object(self, Bucket, Key):"},{"line_number":91,"context_line":"        bucket_dir \u003d self.s3_dir + \"/\" + Bucket"},{"line_number":92,"context_line":"        obj_file \u003d bucket_dir + \"/\" + Key"},{"line_number":93,"context_line":"        if os.path.exists(bucket_dir) is True:"},{"line_number":94,"context_line":"            if os.path.exists(obj_file) is True:"},{"line_number":95,"context_line":"                os.remove(obj_file)"},{"line_number":96,"context_line":"                self.object_headers.pop(obj_file)"},{"line_number":97,"context_line":"            else:"},{"line_number":98,"context_line":"                raise ClientError(\"error_obj\")"},{"line_number":99,"context_line":"        else:"},{"line_number":100,"context_line":"            raise ClientError(\"error_container\")"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":""},{"line_number":103,"context_line":"class FakeS3ResponseStream(object):"},{"line_number":104,"context_line":"    def __init__(self, data):"},{"line_number":105,"context_line":"        self.data \u003d data"},{"line_number":106,"context_line":""},{"line_number":107,"context_line":"    def read(self):"},{"line_number":108,"context_line":"        return self.data"}],"source_content_type":"text/x-python","patch_set":6,"id":"1f1a1f67_499b2c17","line":108,"range":{"start_line":19,"start_character":0,"end_line":108,"end_character":24},"in_reply_to":"1f1a1f67_db1039ab","updated":"2017-07-18 03:22:24.000000000","message":"1. botocore use upper case\n2. I think botocore Stubber is not suitable here, because we want to mock s3 and store some data and I can not find a way to store temp data with using Stubber. I will use dict instead of file system.","commit_id":"3a5c6cb7090f1ca2ec0bb1342e13b810a1b5abff"}]}
