)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":27900,"name":"Artem Goncharov","email":"artem.goncharov@gmail.com","username":"gtema"},"change_message_id":"272ab75eff54cff0c5d3fc201a7213d9959cef58","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"89b7e30f_9c1ee195","updated":"2026-10-03 07:35:38.000000000","message":"There is one regression that must be clarified first (either undo behavior change or document it explicitly)","commit_id":"829ed89eb910ae7baaaef615ac4939597ab6f8b0"}],"keystonemiddleware/auth_token/_cache.py":[{"author":{"_account_id":27900,"name":"Artem Goncharov","email":"artem.goncharov@gmail.com","username":"gtema"},"change_message_id":"272ab75eff54cff0c5d3fc201a7213d9959cef58","unresolved":true,"context_lines":[{"line_number":179,"context_line":"        :param object context: The context that was returned from"},{"line_number":180,"context_line":"                               get_cache_key."},{"line_number":181,"context_line":""},{"line_number":182,"context_line":"        :returns: The python object that was saved."},{"line_number":183,"context_line":"        \"\"\""},{"line_number":184,"context_line":"        # memory cache will handle serialization for us"},{"line_number":185,"context_line":"        return data"}],"source_content_type":"text/x-python","patch_set":1,"id":"adda9426_011a223f","line":182,"updated":"2026-10-03 07:35:38.000000000","message":"it\u0027s a serialized object, not the object itself","commit_id":"829ed89eb910ae7baaaef615ac4939597ab6f8b0"},{"author":{"_account_id":9816,"name":"Takashi Kajinami","email":"kajinamit@oss.nttdata.com","username":"kajinamit"},"change_message_id":"790f446dea001cd786083ba16505563cf7e92ed7","unresolved":false,"context_lines":[{"line_number":179,"context_line":"        :param object context: The context that was returned from"},{"line_number":180,"context_line":"                               get_cache_key."},{"line_number":181,"context_line":""},{"line_number":182,"context_line":"        :returns: The python object that was saved."},{"line_number":183,"context_line":"        \"\"\""},{"line_number":184,"context_line":"        # memory cache will handle serialization for us"},{"line_number":185,"context_line":"        return data"}],"source_content_type":"text/x-python","patch_set":1,"id":"3e74a892_d0c4019e","line":182,"in_reply_to":"adda9426_011a223f","updated":"2026-10-03 09:10:49.000000000","message":"I reused the existing comment from another place. Fixed that source reference too.","commit_id":"829ed89eb910ae7baaaef615ac4939597ab6f8b0"},{"author":{"_account_id":27900,"name":"Artem Goncharov","email":"artem.goncharov@gmail.com","username":"gtema"},"change_message_id":"272ab75eff54cff0c5d3fc201a7213d9959cef58","unresolved":true,"context_lines":[{"line_number":187,"context_line":""},{"line_number":188,"context_line":"class SecureTokenSerializer(TokenSerializer):"},{"line_number":189,"context_line":"    \"\"\"Serialize and Deserialize token data. The data is also encrypted."},{"line_number":190,"context_line":""},{"line_number":191,"context_line":"    \"\"\""},{"line_number":192,"context_line":"    def __init__(self, log, security_strategy, secret_key):"},{"line_number":193,"context_line":"        super(SecureTokenSerializer, self).__init__(log)"}],"source_content_type":"text/x-python","patch_set":1,"id":"28c8388a_a00bdf1e","line":190,"updated":"2026-10-03 07:35:38.000000000","message":"nit: why this blank line? The same in the TokenSerializer","commit_id":"829ed89eb910ae7baaaef615ac4939597ab6f8b0"},{"author":{"_account_id":9816,"name":"Takashi Kajinami","email":"kajinamit@oss.nttdata.com","username":"kajinamit"},"change_message_id":"790f446dea001cd786083ba16505563cf7e92ed7","unresolved":false,"context_lines":[{"line_number":187,"context_line":""},{"line_number":188,"context_line":"class SecureTokenSerializer(TokenSerializer):"},{"line_number":189,"context_line":"    \"\"\"Serialize and Deserialize token data. The data is also encrypted."},{"line_number":190,"context_line":""},{"line_number":191,"context_line":"    \"\"\""},{"line_number":192,"context_line":"    def __init__(self, log, security_strategy, secret_key):"},{"line_number":193,"context_line":"        super(SecureTokenSerializer, self).__init__(log)"}],"source_content_type":"text/x-python","patch_set":1,"id":"813ed9d3_0cc1d34d","line":190,"in_reply_to":"28c8388a_a00bdf1e","updated":"2026-10-03 09:10:49.000000000","message":"I was trying to use a consistent format but I think we can just make it one-line. Fixed.","commit_id":"829ed89eb910ae7baaaef615ac4939597ab6f8b0"},{"author":{"_account_id":27900,"name":"Artem Goncharov","email":"artem.goncharov@gmail.com","username":"gtema"},"change_message_id":"272ab75eff54cff0c5d3fc201a7213d9959cef58","unresolved":true,"context_lines":[{"line_number":192,"context_line":"    def __init__(self, log, security_strategy, secret_key):"},{"line_number":193,"context_line":"        super(SecureTokenSerializer, self).__init__(log)"},{"line_number":194,"context_line":"        if not secret_key:"},{"line_number":195,"context_line":"            msg \u003d _(\u0027cache_secret_key must be defined when a \u0027"},{"line_number":196,"context_line":"                    \u0027cache_security_strategy is defined\u0027)"},{"line_number":197,"context_line":"            raise exc.ConfigurationError(msg)"},{"line_number":198,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"fa0ef340_4436507b","line":195,"updated":"2026-10-03 07:35:38.000000000","message":"the message now refers to the config option which does not exist","commit_id":"829ed89eb910ae7baaaef615ac4939597ab6f8b0"},{"author":{"_account_id":9816,"name":"Takashi Kajinami","email":"kajinamit@oss.nttdata.com","username":"kajinamit"},"change_message_id":"790f446dea001cd786083ba16505563cf7e92ed7","unresolved":false,"context_lines":[{"line_number":192,"context_line":"    def __init__(self, log, security_strategy, secret_key):"},{"line_number":193,"context_line":"        super(SecureTokenSerializer, self).__init__(log)"},{"line_number":194,"context_line":"        if not secret_key:"},{"line_number":195,"context_line":"            msg \u003d _(\u0027cache_secret_key must be defined when a \u0027"},{"line_number":196,"context_line":"                    \u0027cache_security_strategy is defined\u0027)"},{"line_number":197,"context_line":"            raise exc.ConfigurationError(msg)"},{"line_number":198,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"ef833c57_6e90514e","line":195,"in_reply_to":"fa0ef340_4436507b","updated":"2026-10-03 09:10:49.000000000","message":"Oh yes. I have to update this in the next change.","commit_id":"829ed89eb910ae7baaaef615ac4939597ab6f8b0"},{"author":{"_account_id":27900,"name":"Artem Goncharov","email":"artem.goncharov@gmail.com","username":"gtema"},"change_message_id":"272ab75eff54cff0c5d3fc201a7213d9959cef58","unresolved":true,"context_lines":[{"line_number":242,"context_line":"        try:"},{"line_number":243,"context_line":"            # unprotect_data will return None if raw_cached is None"},{"line_number":244,"context_line":"            return crypt.unprotect_data(context, data)"},{"line_number":245,"context_line":"        except crypt.InvalidMacError as e:"},{"line_number":246,"context_line":"            self._LOG.info(\"Unable to deserialize, %s\", e)"},{"line_number":247,"context_line":""},{"line_number":248,"context_line":"        # this should have the same effect as data not"}],"source_content_type":"text/x-python","patch_set":1,"id":"a94776bb_6bcbd7bb","line":245,"updated":"2026-10-03 07:35:38.000000000","message":"there is a difference to the previous implementation which logged a general error \"Failed to decrypt/verify cache data\" keeping None as result. Now every other error will raise. This is a behavior change without being mentioned in the commit and/or tested","commit_id":"829ed89eb910ae7baaaef615ac4939597ab6f8b0"},{"author":{"_account_id":9816,"name":"Takashi Kajinami","email":"kajinamit@oss.nttdata.com","username":"kajinamit"},"change_message_id":"790f446dea001cd786083ba16505563cf7e92ed7","unresolved":false,"context_lines":[{"line_number":242,"context_line":"        try:"},{"line_number":243,"context_line":"            # unprotect_data will return None if raw_cached is None"},{"line_number":244,"context_line":"            return crypt.unprotect_data(context, data)"},{"line_number":245,"context_line":"        except crypt.InvalidMacError as e:"},{"line_number":246,"context_line":"            self._LOG.info(\"Unable to deserialize, %s\", e)"},{"line_number":247,"context_line":""},{"line_number":248,"context_line":"        # this should have the same effect as data not"}],"source_content_type":"text/x-python","patch_set":1,"id":"3876d333_17c9d255","line":245,"in_reply_to":"a94776bb_6bcbd7bb","updated":"2026-10-03 09:10:49.000000000","message":"I was trying to narrow down the exception type to avoid hiding unexpected behavior but noticed the current change leaks at least one exception ( DecryptError) actually implemented within the logic. I\u0027ll revert this change.","commit_id":"829ed89eb910ae7baaaef615ac4939597ab6f8b0"}],"keystonemiddleware/external_oauth2_token.py":[{"author":{"_account_id":27900,"name":"Artem Goncharov","email":"artem.goncharov@gmail.com","username":"gtema"},"change_message_id":"272ab75eff54cff0c5d3fc201a7213d9959cef58","unresolved":true,"context_lines":[{"line_number":507,"context_line":"            self._audience, self._client_id,"},{"line_number":508,"context_line":"            self._get_config_option, self._log)"},{"line_number":509,"context_line":""},{"line_number":510,"context_line":"    def _token_cache_factory(self):"},{"line_number":511,"context_line":"        security_strategy \u003d self._conf.get(\u0027memcache_security_strategy\u0027)"},{"line_number":512,"context_line":"        if security_strategy.lower() !\u003d \u0027none\u0027:"},{"line_number":513,"context_line":"            secret_key \u003d self._conf.get(\u0027memcache_secret_key\u0027)"}],"source_content_type":"text/x-python","patch_set":1,"id":"454c68b0_098ef74c","line":510,"updated":"2026-10-03 07:35:38.000000000","message":"there is a slight duplication with the auth_token.__init__._token_cache_factory. Should we factor it out into the common helper? At the very minimum this is related to the serializer, but it feels that the whole cache factory can be made a helper.","commit_id":"829ed89eb910ae7baaaef615ac4939597ab6f8b0"},{"author":{"_account_id":9816,"name":"Takashi Kajinami","email":"kajinamit@oss.nttdata.com","username":"kajinamit"},"change_message_id":"790f446dea001cd786083ba16505563cf7e92ed7","unresolved":true,"context_lines":[{"line_number":507,"context_line":"            self._audience, self._client_id,"},{"line_number":508,"context_line":"            self._get_config_option, self._log)"},{"line_number":509,"context_line":""},{"line_number":510,"context_line":"    def _token_cache_factory(self):"},{"line_number":511,"context_line":"        security_strategy \u003d self._conf.get(\u0027memcache_security_strategy\u0027)"},{"line_number":512,"context_line":"        if security_strategy.lower() !\u003d \u0027none\u0027:"},{"line_number":513,"context_line":"            secret_key \u003d self._conf.get(\u0027memcache_secret_key\u0027)"}],"source_content_type":"text/x-python","patch_set":1,"id":"194093a2_039131ac","line":510,"in_reply_to":"454c68b0_098ef74c","updated":"2026-10-03 09:10:49.000000000","message":"I agree and will try that in a separate patch if you are ok.\n\nI think the easier path is to add all cache options to these two middlewares (which means that we import some options from auth_token to external_oauth2_token) and I\u0027d like to avoid expanding the current scope to include that.","commit_id":"829ed89eb910ae7baaaef615ac4939597ab6f8b0"}],"keystonemiddleware/tests/unit/auth_token/test_cache.py":[{"author":{"_account_id":27900,"name":"Artem Goncharov","email":"artem.goncharov@gmail.com","username":"gtema"},"change_message_id":"272ab75eff54cff0c5d3fc201a7213d9959cef58","unresolved":true,"context_lines":[{"line_number":29,"context_line":"MEMCACHED_AVAILABLE \u003d None"},{"line_number":30,"context_line":""},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"class TestTokenSerializer(base.BaseAuthTokenTestCase):"},{"line_number":33,"context_line":""},{"line_number":34,"context_line":"    def setUp(self):"},{"line_number":35,"context_line":"        super(TestTokenSerializer, self).setUp()"}],"source_content_type":"text/x-python","patch_set":1,"id":"90330a7a_d6c57886","line":32,"updated":"2026-10-03 07:35:38.000000000","message":"aren\u0027t we now leaving the SecureTokenSerializer untested?","commit_id":"829ed89eb910ae7baaaef615ac4939597ab6f8b0"},{"author":{"_account_id":9816,"name":"Takashi Kajinami","email":"kajinamit@oss.nttdata.com","username":"kajinamit"},"change_message_id":"790f446dea001cd786083ba16505563cf7e92ed7","unresolved":false,"context_lines":[{"line_number":29,"context_line":"MEMCACHED_AVAILABLE \u003d None"},{"line_number":30,"context_line":""},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"class TestTokenSerializer(base.BaseAuthTokenTestCase):"},{"line_number":33,"context_line":""},{"line_number":34,"context_line":"    def setUp(self):"},{"line_number":35,"context_line":"        super(TestTokenSerializer, self).setUp()"}],"source_content_type":"text/x-python","patch_set":1,"id":"ee165cf1_785bcb85","line":32,"in_reply_to":"90330a7a_d6c57886","updated":"2026-10-03 09:10:49.000000000","message":"I\u0027ve added several test cases for it (and also a few for base TokenSerializer)","commit_id":"829ed89eb910ae7baaaef615ac4939597ab6f8b0"},{"author":{"_account_id":27900,"name":"Artem Goncharov","email":"artem.goncharov@gmail.com","username":"gtema"},"change_message_id":"272ab75eff54cff0c5d3fc201a7213d9959cef58","unresolved":true,"context_lines":[{"line_number":169,"context_line":"        self.assertEqual(token_cache.get(token), data)"},{"line_number":170,"context_line":""},{"line_number":171,"context_line":"    @mock.patch(\"keystonemiddleware.auth_token._crypt.unprotect_data\")"},{"line_number":172,"context_line":"    def test_corrupted_cache_data(self, mocked_decrypt_data):"},{"line_number":173,"context_line":"        mocked_decrypt_data.side_effect \u003d crypt.InvalidMacError("},{"line_number":174,"context_line":"            \"corrupted\")"},{"line_number":175,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"42fe1f9c_e8976f52","line":172,"updated":"2026-10-03 07:35:38.000000000","message":"as mentioned above - previous (current) implementation would only log error while the new implementation raises the error should a non InvalidMacError be thrown. You really need to clarify this","commit_id":"829ed89eb910ae7baaaef615ac4939597ab6f8b0"},{"author":{"_account_id":9816,"name":"Takashi Kajinami","email":"kajinamit@oss.nttdata.com","username":"kajinamit"},"change_message_id":"790f446dea001cd786083ba16505563cf7e92ed7","unresolved":false,"context_lines":[{"line_number":169,"context_line":"        self.assertEqual(token_cache.get(token), data)"},{"line_number":170,"context_line":""},{"line_number":171,"context_line":"    @mock.patch(\"keystonemiddleware.auth_token._crypt.unprotect_data\")"},{"line_number":172,"context_line":"    def test_corrupted_cache_data(self, mocked_decrypt_data):"},{"line_number":173,"context_line":"        mocked_decrypt_data.side_effect \u003d crypt.InvalidMacError("},{"line_number":174,"context_line":"            \"corrupted\")"},{"line_number":175,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"7ff4c498_f0b851e3","line":172,"in_reply_to":"42fe1f9c_e8976f52","updated":"2026-10-03 09:10:49.000000000","message":"Done","commit_id":"829ed89eb910ae7baaaef615ac4939597ab6f8b0"}]}
