)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"3ad4c9972e332d935df04b990cf652b32219d5ad","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"55af0c59_9e2a06e9","updated":"2024-08-18 22:41:12.000000000","message":"This patch added a few utility functions to use by various places to parse a swift header, which is nice. Put a ``-1``, partially because it still lacks quite a few test cases for the new added functions, also I feel we should have those two internal places which parse real ``Content-type`` headers to just keep using the original ``parse_content_type`` function.\n\nI am also wondering why author decided to implement a new ``extract_header_parameter``, instead of calling the ``parse_content_type`` function within it. The previous patch https://review.opendev.org/c/openstack/swift/+/887908 unifies ``parse_header`` usages with ``parse_content_type``, although there are some space to improve the naming, but I like that patch to only have one implementation function.","commit_id":"ed9aa86bcee17ddc651b2f43468ca4591beeee0d"}],"swift/common/middleware/crypto/crypto_utils.py":[{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"3ad4c9972e332d935df04b990cf652b32219d5ad","unresolved":false,"context_lines":[{"line_number":277,"context_line":"    \"\"\""},{"line_number":278,"context_line":"    if not isinstance(value, str):"},{"line_number":279,"context_line":"        raise ValueError"},{"line_number":280,"context_line":"    return append_header_parameter("},{"line_number":281,"context_line":"        value,"},{"line_number":282,"context_line":"        \u0027swift_meta\u0027,"},{"line_number":283,"context_line":"        dump_crypto_meta(crypto_meta),"}],"source_content_type":"text/x-python","patch_set":4,"id":"16758db4_51e1e107","line":280,"updated":"2024-08-18 22:41:12.000000000","message":"Nice! It\u0027s great to have an utility function ``append_header_parameter``, instead of implementations on each place to use it.","commit_id":"ed9aa86bcee17ddc651b2f43468ca4591beeee0d"}],"swift/common/middleware/crypto/decrypter.py":[{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"6b1d4a311e0dba6f1eca19903d18210bb5e497a9","unresolved":true,"context_lines":[{"line_number":351,"context_line":"            # 2xx response and encrypted body"},{"line_number":352,"context_line":"            body_key \u003d self.get_unwrapped_key("},{"line_number":353,"context_line":"                put_crypto_meta, put_keys[\u0027object\u0027])"},{"line_number":354,"context_line":"            content_type, boundary \u003d extract_header_parameter("},{"line_number":355,"context_line":"                self._response_header_value(\u0027Content-Type\u0027),"},{"line_number":356,"context_line":"                \u0027boundary\u0027)"},{"line_number":357,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"0399797d_62112256","line":354,"range":{"start_line":354,"start_character":12,"end_line":354,"end_character":24},"updated":"2024-08-07 06:47:20.000000000","message":"content_type here could still include other params outside of \u0027boundry\u0027 but in the old version we\u0027d have just the content_type and all other params striped off. So this change makes it possible for the if on line 358 to fail.\n\nDoes it need an partition on \u0027;\u0027 just in case? Or do we want a helper that better matches extracting all params into a dict like parse_content_type did?","commit_id":"d9e6b0ceb368ea7b291f3721e27b77a8e1f8ed23"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"3ad4c9972e332d935df04b990cf652b32219d5ad","unresolved":true,"context_lines":[{"line_number":352,"context_line":"            body_key \u003d self.get_unwrapped_key("},{"line_number":353,"context_line":"                put_crypto_meta, put_keys[\u0027object\u0027])"},{"line_number":354,"context_line":"            content_type, boundary \u003d extract_header_parameter("},{"line_number":355,"context_line":"                self._response_header_value(\u0027Content-Type\u0027),"},{"line_number":356,"context_line":"                \u0027boundary\u0027)"},{"line_number":357,"context_line":""},{"line_number":358,"context_line":"            if (self._get_status_int() \u003d\u003d 206 and"}],"source_content_type":"text/x-python","patch_set":4,"id":"ef3ca620_e40cd058","line":355,"updated":"2024-08-18 22:41:12.000000000","message":"this is ``Content-Type`` header from object server, even it\u0027s internal and we have full control on what to put into the value, but it\u0027s kind of confusing to not to use ``parse_content_type`` on a ``Content-Type`` header.","commit_id":"ed9aa86bcee17ddc651b2f43468ca4591beeee0d"}],"swift/common/middleware/symlink.py":[{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"6b1d4a311e0dba6f1eca19903d18210bb5e497a9","unresolved":true,"context_lines":[{"line_number":397,"context_line":"                        param_dict[\u0027symlink_target_etag\u0027]"},{"line_number":398,"context_line":"                if param_dict[\u0027symlink_target_bytes\u0027]:"},{"line_number":399,"context_line":"                    obj_dict[\u0027symlink_bytes\u0027] \u003d int("},{"line_number":400,"context_line":"                        param_dict[\u0027symlink_target_bytes\u0027])"},{"line_number":401,"context_line":""},{"line_number":402,"context_line":"        return obj_dict"},{"line_number":403,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"bd346c97_a0c00c8a","line":400,"updated":"2024-08-07 06:47:20.000000000","message":"Oh this cleans up much nicer. More reable and reorders logic nicely!","commit_id":"d9e6b0ceb368ea7b291f3721e27b77a8e1f8ed23"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"b8ee7e9f3037fb4c1bc38d0f84aced9e7f0c1bcd","unresolved":true,"context_lines":[{"line_number":572,"context_line":"        if override_header in response_headers and \\"},{"line_number":573,"context_line":"                override_header not in req.headers:"},{"line_number":574,"context_line":"            # When linking to another symlink, we need to be sure to strip out"},{"line_number":575,"context_line":"            # existing symlink params, though"},{"line_number":576,"context_line":"            tgt_override, _ \u003d extract_header_parameters("},{"line_number":577,"context_line":"                response_headers[override_header],"},{"line_number":578,"context_line":"                \u0027symlink_target\u0027,"}],"source_content_type":"text/x-python","patch_set":4,"id":"4e9affe0_6e6f34b7","line":575,"updated":"2024-08-09 17:35:29.000000000","message":"It sure *seems like* master ought to be introducing duplicated params, but testing, I couldn\u0027t actually trip it...\n\nIf there really *can* be duplicated params already out there in the wild, though, we might need to do this stripping multiple times...","commit_id":"ed9aa86bcee17ddc651b2f43468ca4591beeee0d"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"b8ee7e9f3037fb4c1bc38d0f84aced9e7f0c1bcd","unresolved":true,"context_lines":[{"line_number":635,"context_line":"        # override etag may be encrypted in the container db by encryption"},{"line_number":636,"context_line":"        # middleware."},{"line_number":637,"context_line":""},{"line_number":638,"context_line":"        params \u003d collections.OrderedDict({"},{"line_number":639,"context_line":"            \u0027symlink_target\u0027: req.headers[TGT_OBJ_SYSMETA_SYMLINK_HDR]})"},{"line_number":640,"context_line":"        if TGT_ACCT_SYSMETA_SYMLINK_HDR in req.headers:"},{"line_number":641,"context_line":"            params[\u0027symlink_target_etag\u0027] \u003d \\"}],"source_content_type":"text/x-python","patch_set":4,"id":"8693a884_98c457c4","line":638,"range":{"start_line":638,"start_character":17,"end_line":638,"end_character":40},"updated":"2024-08-09 17:35:29.000000000","message":"Needed for py2, because we expect a particular order of params.","commit_id":"ed9aa86bcee17ddc651b2f43468ca4591beeee0d"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"b8ee7e9f3037fb4c1bc38d0f84aced9e7f0c1bcd","unresolved":true,"context_lines":[{"line_number":650,"context_line":"                req.headers[TGT_BYTES_SYSMETA_SYMLINK_HDR]"},{"line_number":651,"context_line":""},{"line_number":652,"context_line":"        override_key \u003d get_container_update_override_key(\u0027etag\u0027)"},{"line_number":653,"context_line":"        req.headers[override_key] \u003d append_header_parameters("},{"line_number":654,"context_line":"            req.headers.get(override_key, MD5_OF_EMPTY_STRING),"},{"line_number":655,"context_line":"            params)"},{"line_number":656,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"c5a4fb1c_4482a9b9","line":653,"updated":"2024-08-09 17:35:29.000000000","message":"This was popping `ValueError`s in the func tests on patchset 1 -- which means today, on master, we maybe have container listings with multiple `symlink_target` params... it seems to come up when\n\n1. copying a symlink or\n2. making a hard link to another symlink.\n\nThe first case seems mostly OK; everything should match. The second case would be trickier, though... but I haven\u0027t actually been able to repro it.","commit_id":"ed9aa86bcee17ddc651b2f43468ca4591beeee0d"}],"swift/common/middleware/versioned_writes/object_versioning.py":[{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"6b1d4a311e0dba6f1eca19903d18210bb5e497a9","unresolved":true,"context_lines":[{"line_number":346,"context_line":"        slo_size \u003d put_req.headers.get(\u0027X-Object-Sysmeta-Slo-Size\u0027)"},{"line_number":347,"context_line":"        if slo_size:"},{"line_number":348,"context_line":"            put_bytes \u003d slo_size"},{"line_number":349,"context_line":"        put_content_type \u003d put_req.headers[\u0027Content-Type\u0027].partition(\u0027;\u0027)[0]"},{"line_number":350,"context_line":""},{"line_number":351,"context_line":"        return (put_resp, vers_obj_name, put_bytes, put_content_type)"},{"line_number":352,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"0793694d_8e6524d7","line":349,"updated":"2024-08-07 06:47:20.000000000","message":"Cool added a partition","commit_id":"d9e6b0ceb368ea7b291f3721e27b77a8e1f8ed23"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"6b1d4a311e0dba6f1eca19903d18210bb5e497a9","unresolved":true,"context_lines":[{"line_number":919,"context_line":"                    item[\u0027bytes\u0027] \u003d tgt_bytes"},{"line_number":920,"context_line":"                    item[\u0027version_symlink\u0027] \u003d True"},{"line_number":921,"context_line":"                    _, sep, params \u003d item[\u0027hash\u0027].partition(\u0027;\u0027)"},{"line_number":922,"context_line":"                    item[\u0027hash\u0027] \u003d item.pop(\u0027symlink_etag\u0027) + sep + params"},{"line_number":923,"context_line":"                    tgt_obj, version \u003d self._split_version_from_name(tgt_obj)"},{"line_number":924,"context_line":"                    if version is not None and \u0027versions\u0027 not in req.params:"},{"line_number":925,"context_line":"                        sp \u003d wsgi_quote(\u0027/v1/%s/%s/%s\u0027 % ("}],"source_content_type":"text/x-python","patch_set":1,"id":"2f7b0efe_4cc4973e","line":922,"updated":"2024-08-07 06:47:20.000000000","message":"K this doesn\u0027t use the new helpers, it just removes the need for parse_header.","commit_id":"d9e6b0ceb368ea7b291f3721e27b77a8e1f8ed23"}],"swift/common/utils/__init__.py":[{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"6b1d4a311e0dba6f1eca19903d18210bb5e497a9","unresolved":true,"context_lines":[{"line_number":2771,"context_line":"        return header, None"},{"line_number":2772,"context_line":"    params \u003d header[idx:]"},{"line_number":2773,"context_line":"    # already validated it needs no escaping"},{"line_number":2774,"context_line":"    m \u003d re.search(\u0027; *\u0027 + name + \u0027\u003d\u0027, params)"},{"line_number":2775,"context_line":"    if not m:"},{"line_number":2776,"context_line":"        # param not found"},{"line_number":2777,"context_line":"        return header, None"}],"source_content_type":"text/x-python","patch_set":1,"id":"ed76d279_e1344263","line":2774,"updated":"2024-08-07 06:47:20.000000000","message":"So this is a regex, so this covers if there is 0 or more spaces between the `;\u0027 and the name.","commit_id":"d9e6b0ceb368ea7b291f3721e27b77a8e1f8ed23"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"3ad4c9972e332d935df04b990cf652b32219d5ad","unresolved":true,"context_lines":[{"line_number":2761,"context_line":"    \"\"\""},{"line_number":2762,"context_line":"    valid_chars \u003d string.ascii_letters + string.digits + \u0027_-\u0027"},{"line_number":2763,"context_line":"    if any(c not in valid_chars for c in name):"},{"line_number":2764,"context_line":"        raise ValueError(\u0027Parameter name may only contain ascii letters, \u0027"},{"line_number":2765,"context_line":"                         \u0027numbers, hyphens, or underscores; got %r\u0027"},{"line_number":2766,"context_line":"                         % name)"},{"line_number":2767,"context_line":"    try:"}],"source_content_type":"text/x-python","patch_set":4,"id":"caf136d7_68119019","line":2764,"updated":"2024-08-18 22:41:12.000000000","message":"this ``ValueError`` check on input ``name`` has no test case yet","commit_id":"ed9aa86bcee17ddc651b2f43468ca4591beeee0d"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"3ad4c9972e332d935df04b990cf652b32219d5ad","unresolved":true,"context_lines":[{"line_number":2766,"context_line":"                         % name)"},{"line_number":2767,"context_line":"    try:"},{"line_number":2768,"context_line":"        idx \u003d header.index(\u0027;\u0027)"},{"line_number":2769,"context_line":"    except ValueError:"},{"line_number":2770,"context_line":"        # no \u0027;\u0027"},{"line_number":2771,"context_line":"        return header, None"},{"line_number":2772,"context_line":"    params \u003d header[idx:]"}],"source_content_type":"text/x-python","patch_set":4,"id":"2ed05950_582704f4","line":2769,"updated":"2024-08-18 22:41:12.000000000","message":"there is no test cases for this too","commit_id":"ed9aa86bcee17ddc651b2f43468ca4591beeee0d"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"3ad4c9972e332d935df04b990cf652b32219d5ad","unresolved":true,"context_lines":[{"line_number":2781,"context_line":"        idx_rest \u003d params.index(\u0027;\u0027, end)"},{"line_number":2782,"context_line":"    except ValueError:"},{"line_number":2783,"context_line":"        # no next \u0027;\u0027"},{"line_number":2784,"context_line":"        val \u003d params[end:]"},{"line_number":2785,"context_line":"        rest \u003d \u0027\u0027"},{"line_number":2786,"context_line":"    else:"},{"line_number":2787,"context_line":"        val \u003d params[end:idx_rest]"}],"source_content_type":"text/x-python","patch_set":4,"id":"22b4bd18_faab6c4f","line":2784,"updated":"2024-08-18 22:41:12.000000000","message":"even for internal usages, I feel we need to trim the surrounding whitespace from the extracted value?\n```val \u003d params[end:].strip()```","commit_id":"ed9aa86bcee17ddc651b2f43468ca4591beeee0d"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"3ad4c9972e332d935df04b990cf652b32219d5ad","unresolved":true,"context_lines":[{"line_number":2795,"context_line":""},{"line_number":2796,"context_line":"    Includes some validation so you don\u0027t shoot yourself in the foot."},{"line_number":2797,"context_line":""},{"line_number":2798,"context_line":"    :param header:"},{"line_number":2799,"context_line":"    :param name:"},{"line_number":2800,"context_line":"    :param value:"},{"line_number":2801,"context_line":"    :raises ValueError: if the parameter name or value contain invalid chars,"}],"source_content_type":"text/x-python","patch_set":4,"id":"cd8c4c2d_add6c47a","line":2798,"updated":"2024-08-18 22:41:12.000000000","message":"add docstring for ``header``, ``name`` and ``value``","commit_id":"ed9aa86bcee17ddc651b2f43468ca4591beeee0d"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"3ad4c9972e332d935df04b990cf652b32219d5ad","unresolved":true,"context_lines":[{"line_number":2835,"context_line":"def append_header_parameters(header, parameters):"},{"line_number":2836,"context_line":"    \"\"\""},{"line_number":2837,"context_line":"    Add several parameters to a header."},{"line_number":2838,"context_line":"    \"\"\""},{"line_number":2839,"context_line":"    for name, value in parameters.items():"},{"line_number":2840,"context_line":"        header \u003d append_header_parameter(header, name, value)"},{"line_number":2841,"context_line":"    return header"}],"source_content_type":"text/x-python","patch_set":4,"id":"96e2c791_f8139100","line":2838,"updated":"2024-08-18 22:41:12.000000000","message":"add docstring for input ``parameters`` and return.","commit_id":"ed9aa86bcee17ddc651b2f43468ca4591beeee0d"}],"swift/proxy/controllers/base.py":[{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"6b1d4a311e0dba6f1eca19903d18210bb5e497a9","unresolved":true,"context_lines":[{"line_number":1697,"context_line":"            # we may need some MIME boundary; fortunately, the object server"},{"line_number":1698,"context_line":"            # would have furnished one for us, so we can just re-use it"},{"line_number":1699,"context_line":"            content_type, boundary \u003d extract_header_parameter(ct, \u0027boundary\u0027)"},{"line_number":1700,"context_line":"            is_multipart \u003d (content_type \u003d\u003d \u0027multipart/byteranges\u0027)"},{"line_number":1701,"context_line":"        else:"},{"line_number":1702,"context_line":"            boundary \u003d None"},{"line_number":1703,"context_line":"            is_multipart \u003d False"}],"source_content_type":"text/x-python","patch_set":1,"id":"6467b596_41985cf4","line":1700,"updated":"2024-08-07 06:47:20.000000000","message":"Again this isn\u0027t stricktly true. What if content_type have more then just boundry attached. This probably needs to be:\n\n    is_multipart \u003d (content_type.partition(\u0027;\u0027)[0] \u003d\u003d \u0027multipart/byteranges\u0027)","commit_id":"d9e6b0ceb368ea7b291f3721e27b77a8e1f8ed23"}],"test/unit/common/test_utils.py":[{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"3ad4c9972e332d935df04b990cf652b32219d5ad","unresolved":true,"context_lines":[{"line_number":2640,"context_line":"            stubfile.write(\"\")"},{"line_number":2641,"context_line":"        self.assertTrue(utils.ismount(tmpdir))"},{"line_number":2642,"context_line":""},{"line_number":2643,"context_line":"    def test_extract_header_parameter(self):"},{"line_number":2644,"context_line":"        hdr \u003d \u0027foo; bar\u003dbaz; ; quux\u003d \u003d ; asdf\u0027"},{"line_number":2645,"context_line":"        self.assertEqual(utils.extract_header_parameter(hdr, \u0027foo\u0027),"},{"line_number":2646,"context_line":"                         (hdr, None))"}],"source_content_type":"text/x-python","patch_set":4,"id":"31fa9c86_1b4d4ce9","line":2643,"updated":"2024-08-18 22:41:12.000000000","message":"need to add test cases:\n  1. to raise ``ValueError`` exception.\n  2. for header only with main value.\n  3. when value has ``\" or /``, like \u0027text/plain; x\u003da/b; y\u0027","commit_id":"ed9aa86bcee17ddc651b2f43468ca4591beeee0d"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"3ad4c9972e332d935df04b990cf652b32219d5ad","unresolved":true,"context_lines":[{"line_number":2649,"context_line":"        self.assertEqual(utils.extract_header_parameter(hdr, \u0027baz\u0027),"},{"line_number":2650,"context_line":"                         (hdr, None))"},{"line_number":2651,"context_line":"        self.assertEqual(utils.extract_header_parameter(hdr, \u0027quux\u0027),"},{"line_number":2652,"context_line":"                         (\u0027foo; bar\u003dbaz; ; asdf\u0027, \u0027 \u003d \u0027))"},{"line_number":2653,"context_line":"        self.assertEqual(utils.extract_header_parameter(hdr, \u0027asdf\u0027),"},{"line_number":2654,"context_line":"                         (hdr, None))"},{"line_number":2655,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"3627af00_00e166db","line":2652,"updated":"2024-08-18 22:41:12.000000000","message":"the retrieved value is ``\u0027 \u003d \u0027``, is that expected the whitespaces should be removed? for example, if this header is ``\u0027foo; bar\u003d baz \u0027``, should the value be ``\u0027baz\u0027`` for parameter bar?","commit_id":"ed9aa86bcee17ddc651b2f43468ca4591beeee0d"}]}
