)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":1004568,"name":"Jared Casey","email":"jared.casey@couchbase.com","username":"thejcfactor","avatars":[{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"d1dbb930a12abfaf552cb845f315ff0f61496f90","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"5c7443ab_48f751f0","updated":"2025-11-12 00:40:00.000000000","message":"Good work!! I have a handful of points, but the change is essentially there.  Also, I think if you rebase on top of the latest master that should fix the CI builds.","commit_id":"be28ca63563955ef7e20c00e6ded4e38a96cd342"}],"acouchbase/cluster.py":[{"author":{"_account_id":1004568,"name":"Jared Casey","email":"jared.casey@couchbase.com","username":"thejcfactor","avatars":[{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"d1dbb930a12abfaf552cb845f315ff0f61496f90","unresolved":true,"context_lines":[{"line_number":182,"context_line":"        await self._close_ftr"},{"line_number":183,"context_line":"        super()._destroy_connection()"},{"line_number":184,"context_line":""},{"line_number":185,"context_line":"    async def update_credentials(self, authenticator: Union[CertificateAuthenticator, PasswordAuthenticator]) -\u003e None:"},{"line_number":186,"context_line":"        \"\"\"Update the credentials used by this Cluster."},{"line_number":187,"context_line":""},{"line_number":188,"context_line":"        Args:"}],"source_content_type":"text/x-python","patch_set":1,"id":"06c10b6a_a67940d0","line":185,"updated":"2025-11-12 00:40:00.000000000","message":"I think it would be better to let this be a blocking call.  Since it is blocking call in the C++ core and it is a simple operation, I think jumping through hoops so that it appears async from the app perspective does not provide us with much benefit.","commit_id":"be28ca63563955ef7e20c00e6ded4e38a96cd342"},{"author":{"_account_id":1005381,"name":"Anirudh Lakhotia","display_name":"Anirudh Lakhotia","email":"anirudh.lakhotia@couchbase.com","username":"anirudhlakhotia","avatars":[{"url":"https://www.gravatar.com/avatar/9b86347dbed7e8c52746d07945b7649b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/9b86347dbed7e8c52746d07945b7649b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/9b86347dbed7e8c52746d07945b7649b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/9b86347dbed7e8c52746d07945b7649b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"8509dd730829781ffbdc89fa28e76a68beec1b0d","unresolved":true,"context_lines":[{"line_number":182,"context_line":"        await self._close_ftr"},{"line_number":183,"context_line":"        super()._destroy_connection()"},{"line_number":184,"context_line":""},{"line_number":185,"context_line":"    async def update_credentials(self, authenticator: Union[CertificateAuthenticator, PasswordAuthenticator]) -\u003e None:"},{"line_number":186,"context_line":"        \"\"\"Update the credentials used by this Cluster."},{"line_number":187,"context_line":""},{"line_number":188,"context_line":"        Args:"}],"source_content_type":"text/x-python","patch_set":1,"id":"d72cd5b4_5e353e40","line":185,"in_reply_to":"06c10b6a_a67940d0","updated":"2025-11-19 10:32:44.000000000","message":"Yup, this makes sense. Since the core call is synchronous and quick, there’s no value in pretending it’s async. I’ll update it to be a regular blocking method.","commit_id":"be28ca63563955ef7e20c00e6ded4e38a96cd342"},{"author":{"_account_id":1004568,"name":"Jared Casey","email":"jared.casey@couchbase.com","username":"thejcfactor","avatars":[{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"d1dbb930a12abfaf552cb845f315ff0f61496f90","unresolved":true,"context_lines":[{"line_number":196,"context_line":"            return ClusterLogic._update_credentials(self, auth\u003dauthenticator.as_dict())"},{"line_number":197,"context_line":""},{"line_number":198,"context_line":"        res \u003d await self.loop.run_in_executor(None, _do_update)"},{"line_number":199,"context_line":"        if isinstance(res, BaseCouchbaseException):"},{"line_number":200,"context_line":"            raise ErrorMapper.build_exception(res)"},{"line_number":201,"context_line":"        self._auth \u003d authenticator.as_dict()"},{"line_number":202,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"8c40d4cd_f3d5342b","line":199,"updated":"2025-11-12 00:40:00.000000000","message":"I think all the error translation can happen w/in the \"core\" cluster (e.g. ClusterLogic).  Maybe I am not thinking of all the possible scenarios?","commit_id":"be28ca63563955ef7e20c00e6ded4e38a96cd342"},{"author":{"_account_id":1005381,"name":"Anirudh Lakhotia","display_name":"Anirudh Lakhotia","email":"anirudh.lakhotia@couchbase.com","username":"anirudhlakhotia","avatars":[{"url":"https://www.gravatar.com/avatar/9b86347dbed7e8c52746d07945b7649b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/9b86347dbed7e8c52746d07945b7649b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/9b86347dbed7e8c52746d07945b7649b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/9b86347dbed7e8c52746d07945b7649b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"d0a66051651b7190fb1542e730ce1e3dd9d2abf0","unresolved":true,"context_lines":[{"line_number":196,"context_line":"            return ClusterLogic._update_credentials(self, auth\u003dauthenticator.as_dict())"},{"line_number":197,"context_line":""},{"line_number":198,"context_line":"        res \u003d await self.loop.run_in_executor(None, _do_update)"},{"line_number":199,"context_line":"        if isinstance(res, BaseCouchbaseException):"},{"line_number":200,"context_line":"            raise ErrorMapper.build_exception(res)"},{"line_number":201,"context_line":"        self._auth \u003d authenticator.as_dict()"},{"line_number":202,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"652e343f_a5a29d58","line":199,"in_reply_to":"8c40d4cd_f3d5342b","updated":"2025-11-19 10:34:23.000000000","message":"I’ll move all error translation into ClusterLogic._update_credentials so callers just see mapped SDK exceptions. I don\u0027t see any extra scenarios beyond the standard disconnected guard and normal exception handling.","commit_id":"be28ca63563955ef7e20c00e6ded4e38a96cd342"}],"acouchbase/tests/credentials_t.py":[{"author":{"_account_id":1004568,"name":"Jared Casey","email":"jared.casey@couchbase.com","username":"thejcfactor","avatars":[{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"d1dbb930a12abfaf552cb845f315ff0f61496f90","unresolved":true,"context_lines":[{"line_number":42,"context_line":"    @pytest.mark.asyncio"},{"line_number":43,"context_line":"    async def test_update_credentials_async(self, cb_env):"},{"line_number":44,"context_line":"        cluster \u003d cb_env.cluster"},{"line_number":45,"context_line":"        info_before \u003d await cluster._get_cluster_info()  # ensures connected"},{"line_number":46,"context_line":"        assert info_before is not None"},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"        new_user \u003d f\"pycbc_{uuid.uuid4().hex[:8]}\""}],"source_content_type":"text/x-python","patch_set":1,"id":"d3312e0c_4489294d","line":45,"updated":"2025-11-12 00:40:00.000000000","message":"Since the `cb_env` fixture calls `AsyncCluster.connect()`, that will do `await cluster.on_connect()`, so the cluster should be connected.  I don\u0027t know if getting the cluster info is necessary?","commit_id":"be28ca63563955ef7e20c00e6ded4e38a96cd342"},{"author":{"_account_id":1005381,"name":"Anirudh Lakhotia","display_name":"Anirudh Lakhotia","email":"anirudh.lakhotia@couchbase.com","username":"anirudhlakhotia","avatars":[{"url":"https://www.gravatar.com/avatar/9b86347dbed7e8c52746d07945b7649b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/9b86347dbed7e8c52746d07945b7649b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/9b86347dbed7e8c52746d07945b7649b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/9b86347dbed7e8c52746d07945b7649b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"458649458ba07aad5fbab6e19ceb4d622bccaeee","unresolved":false,"context_lines":[{"line_number":42,"context_line":"    @pytest.mark.asyncio"},{"line_number":43,"context_line":"    async def test_update_credentials_async(self, cb_env):"},{"line_number":44,"context_line":"        cluster \u003d cb_env.cluster"},{"line_number":45,"context_line":"        info_before \u003d await cluster._get_cluster_info()  # ensures connected"},{"line_number":46,"context_line":"        assert info_before is not None"},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"        new_user \u003d f\"pycbc_{uuid.uuid4().hex[:8]}\""}],"source_content_type":"text/x-python","patch_set":1,"id":"19aa67fd_4762a5e1","line":45,"in_reply_to":"d3312e0c_4489294d","updated":"2025-11-21 12:12:50.000000000","message":"Acknowledged","commit_id":"be28ca63563955ef7e20c00e6ded4e38a96cd342"},{"author":{"_account_id":1004568,"name":"Jared Casey","email":"jared.casey@couchbase.com","username":"thejcfactor","avatars":[{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"d1dbb930a12abfaf552cb845f315ff0f61496f90","unresolved":true,"context_lines":[{"line_number":62,"context_line":"                                                                      key_path\u003d\u0027path/to/key\u0027))"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":"    @pytest.mark.asyncio"},{"line_number":65,"context_line":"    async def test_update_credentials_failure_does_not_change_state_async(self, cb_env):"},{"line_number":66,"context_line":"        cluster \u003d cb_env.cluster"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"        # capture original"}],"source_content_type":"text/x-python","patch_set":1,"id":"2ffc4c5f_8bf3fba4","line":65,"updated":"2025-11-12 00:40:00.000000000","message":"I think the same as w/ the couchbase tests, these last two can probably be combined?","commit_id":"be28ca63563955ef7e20c00e6ded4e38a96cd342"}],"couchbase/tests/credentials_t.py":[{"author":{"_account_id":1004568,"name":"Jared Casey","email":"jared.casey@couchbase.com","username":"thejcfactor","avatars":[{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"d1dbb930a12abfaf552cb845f315ff0f61496f90","unresolved":true,"context_lines":[{"line_number":25,"context_line":""},{"line_number":26,"context_line":"class ClassicCredentialsTests:"},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"    @pytest.mark.flaky(reruns\u003d3, reruns_delay\u003d1)"},{"line_number":29,"context_line":"    def test_update_credentials_reflected_in_connection_info(self, couchbase_config):"},{"line_number":30,"context_line":"        conn_string \u003d couchbase_config.get_connection_string()"},{"line_number":31,"context_line":"        username, pw \u003d couchbase_config.get_username_and_pw()"}],"source_content_type":"text/x-python","patch_set":1,"id":"57a1cd2a_722a0490","line":28,"updated":"2025-11-12 00:40:00.000000000","message":"Why is this the only test marked as flaky?","commit_id":"be28ca63563955ef7e20c00e6ded4e38a96cd342"},{"author":{"_account_id":1005381,"name":"Anirudh Lakhotia","display_name":"Anirudh Lakhotia","email":"anirudh.lakhotia@couchbase.com","username":"anirudhlakhotia","avatars":[{"url":"https://www.gravatar.com/avatar/9b86347dbed7e8c52746d07945b7649b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/9b86347dbed7e8c52746d07945b7649b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/9b86347dbed7e8c52746d07945b7649b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/9b86347dbed7e8c52746d07945b7649b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"5adb607d74e231153bcb11cedaa283f921ee0366","unresolved":true,"context_lines":[{"line_number":25,"context_line":""},{"line_number":26,"context_line":"class ClassicCredentialsTests:"},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"    @pytest.mark.flaky(reruns\u003d3, reruns_delay\u003d1)"},{"line_number":29,"context_line":"    def test_update_credentials_reflected_in_connection_info(self, couchbase_config):"},{"line_number":30,"context_line":"        conn_string \u003d couchbase_config.get_connection_string()"},{"line_number":31,"context_line":"        username, pw \u003d couchbase_config.get_username_and_pw()"}],"source_content_type":"text/x-python","patch_set":1,"id":"ea713f8f_8e4d0510","line":28,"in_reply_to":"57a1cd2a_722a0490","updated":"2025-11-21 10:33:15.000000000","message":"Now that update_credentials is a direct blocking core call and error translation happens inside ClusterLogic, there’s no event-loop timing variability left. I’ll remove the @pytest.mark.flaky decorator.","commit_id":"be28ca63563955ef7e20c00e6ded4e38a96cd342"},{"author":{"_account_id":1005381,"name":"Anirudh Lakhotia","display_name":"Anirudh Lakhotia","email":"anirudh.lakhotia@couchbase.com","username":"anirudhlakhotia","avatars":[{"url":"https://www.gravatar.com/avatar/9b86347dbed7e8c52746d07945b7649b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/9b86347dbed7e8c52746d07945b7649b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/9b86347dbed7e8c52746d07945b7649b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/9b86347dbed7e8c52746d07945b7649b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"458649458ba07aad5fbab6e19ceb4d622bccaeee","unresolved":false,"context_lines":[{"line_number":25,"context_line":""},{"line_number":26,"context_line":"class ClassicCredentialsTests:"},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"    @pytest.mark.flaky(reruns\u003d3, reruns_delay\u003d1)"},{"line_number":29,"context_line":"    def test_update_credentials_reflected_in_connection_info(self, couchbase_config):"},{"line_number":30,"context_line":"        conn_string \u003d couchbase_config.get_connection_string()"},{"line_number":31,"context_line":"        username, pw \u003d couchbase_config.get_username_and_pw()"}],"source_content_type":"text/x-python","patch_set":1,"id":"24337a6c_f43eaeee","line":28,"in_reply_to":"ea713f8f_8e4d0510","updated":"2025-11-21 12:12:50.000000000","message":"Done","commit_id":"be28ca63563955ef7e20c00e6ded4e38a96cd342"},{"author":{"_account_id":1004568,"name":"Jared Casey","email":"jared.casey@couchbase.com","username":"thejcfactor","avatars":[{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"d1dbb930a12abfaf552cb845f315ff0f61496f90","unresolved":true,"context_lines":[{"line_number":68,"context_line":""},{"line_number":69,"context_line":"        cluster.close()"},{"line_number":70,"context_line":""},{"line_number":71,"context_line":"    def test_update_credentials_failure_does_not_change_state(self, couchbase_config):"},{"line_number":72,"context_line":"        conn_string \u003d couchbase_config.get_connection_string()"},{"line_number":73,"context_line":"        username, pw \u003d couchbase_config.get_username_and_pw()"},{"line_number":74,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"356c5fba_bc40baff","line":71,"updated":"2025-11-12 00:40:00.000000000","message":"I wonder if this and the test above (`test_update_to_certificate_auth_without_tls_fails`) can be merged?  They appear to be testing the same thing (e.g. we get the expected `InvalidArgumentException` when trying to update a non-TLS connection to use credentials that require a TLS connection).","commit_id":"be28ca63563955ef7e20c00e6ded4e38a96cd342"},{"author":{"_account_id":1005381,"name":"Anirudh Lakhotia","display_name":"Anirudh Lakhotia","email":"anirudh.lakhotia@couchbase.com","username":"anirudhlakhotia","avatars":[{"url":"https://www.gravatar.com/avatar/9b86347dbed7e8c52746d07945b7649b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/9b86347dbed7e8c52746d07945b7649b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/9b86347dbed7e8c52746d07945b7649b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/9b86347dbed7e8c52746d07945b7649b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"5adb607d74e231153bcb11cedaa283f921ee0366","unresolved":true,"context_lines":[{"line_number":68,"context_line":""},{"line_number":69,"context_line":"        cluster.close()"},{"line_number":70,"context_line":""},{"line_number":71,"context_line":"    def test_update_credentials_failure_does_not_change_state(self, couchbase_config):"},{"line_number":72,"context_line":"        conn_string \u003d couchbase_config.get_connection_string()"},{"line_number":73,"context_line":"        username, pw \u003d couchbase_config.get_username_and_pw()"},{"line_number":74,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"5230f355_2fe8687a","line":71,"in_reply_to":"356c5fba_bc40baff","updated":"2025-11-21 10:33:15.000000000","message":"We could merge them, but having a separate\ntest_update_to_certificate_auth_without_tls_fails (which verifies we get the expected InvalidArgumentException on a non-TLS connection) and\ntest_update_credentials_failure_does_not_change_state (which verifies the invariant that a failed update doesn’t mutate the stored cluster credentials)\nmakes the intent a lot clearer.\n\nI think keeping them split makes it easier to debug what exactly went wrong.","commit_id":"be28ca63563955ef7e20c00e6ded4e38a96cd342"},{"author":{"_account_id":1004568,"name":"Jared Casey","email":"jared.casey@couchbase.com","username":"thejcfactor","avatars":[{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"24ab5f62cf3ff759f97a05a2e57312a3fe827619","unresolved":false,"context_lines":[{"line_number":68,"context_line":""},{"line_number":69,"context_line":"        cluster.close()"},{"line_number":70,"context_line":""},{"line_number":71,"context_line":"    def test_update_credentials_failure_does_not_change_state(self, couchbase_config):"},{"line_number":72,"context_line":"        conn_string \u003d couchbase_config.get_connection_string()"},{"line_number":73,"context_line":"        username, pw \u003d couchbase_config.get_username_and_pw()"},{"line_number":74,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"c838dbe6_bfb1f9e6","line":71,"in_reply_to":"5230f355_2fe8687a","updated":"2025-11-25 01:33:55.000000000","message":"Not a hill I\u0027m willing to die on.  But, if update_credentials fails to raise an InvalidArgumentException _both_ tests fail creating 2x the work to \"debug\".","commit_id":"be28ca63563955ef7e20c00e6ded4e38a96cd342"}],"src/connection.cxx":[{"author":{"_account_id":1004568,"name":"Jared Casey","email":"jared.casey@couchbase.com","username":"thejcfactor","avatars":[{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"d1dbb930a12abfaf552cb845f315ff0f61496f90","unresolved":true,"context_lines":[{"line_number":1574,"context_line":""},{"line_number":1575,"context_line":"  static const char* kw_list[] \u003d { \"\", \"auth\", nullptr };"},{"line_number":1576,"context_line":""},{"line_number":1577,"context_line":"  const char* kw_format \u003d \"O!O!\";"},{"line_number":1578,"context_line":"  int ret \u003d PyArg_ParseTupleAndKeywords(args,"},{"line_number":1579,"context_line":"                                        kwargs,"},{"line_number":1580,"context_line":"                                        kw_format,"}],"source_content_type":"text/x-c++src","patch_set":1,"id":"047e79af_cc05940e","line":1577,"updated":"2025-11-12 00:40:00.000000000","message":"We only need the `O!` format specifier for the connection.  For the auth object we can use `O` and that can map directly to PyObject* pyObj_auth.","commit_id":"be28ca63563955ef7e20c00e6ded4e38a96cd342"},{"author":{"_account_id":1005381,"name":"Anirudh Lakhotia","display_name":"Anirudh Lakhotia","email":"anirudh.lakhotia@couchbase.com","username":"anirudhlakhotia","avatars":[{"url":"https://www.gravatar.com/avatar/9b86347dbed7e8c52746d07945b7649b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/9b86347dbed7e8c52746d07945b7649b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/9b86347dbed7e8c52746d07945b7649b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/9b86347dbed7e8c52746d07945b7649b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"b2b02aec3fcdc664c10dc3d914c1945a9eb10104","unresolved":true,"context_lines":[{"line_number":1574,"context_line":""},{"line_number":1575,"context_line":"  static const char* kw_list[] \u003d { \"\", \"auth\", nullptr };"},{"line_number":1576,"context_line":""},{"line_number":1577,"context_line":"  const char* kw_format \u003d \"O!O!\";"},{"line_number":1578,"context_line":"  int ret \u003d PyArg_ParseTupleAndKeywords(args,"},{"line_number":1579,"context_line":"                                        kwargs,"},{"line_number":1580,"context_line":"                                        kw_format,"}],"source_content_type":"text/x-c++src","patch_set":1,"id":"7219862c_c2b89284","line":1577,"in_reply_to":"047e79af_cc05940e","updated":"2025-11-21 11:22:53.000000000","message":"Given how `get_cluster_credentials()` is implemented today, I think we should keep `O!` for the auth parameter. The helper only uses PyDict_* APIs, so relaxing this to `O` would let non-dict inputs through and then silently produce empty credentials (all the PyDict_GetItemString calls would just return nullptr), and push the type error later.","commit_id":"be28ca63563955ef7e20c00e6ded4e38a96cd342"},{"author":{"_account_id":1004568,"name":"Jared Casey","email":"jared.casey@couchbase.com","username":"thejcfactor","avatars":[{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"24ab5f62cf3ff759f97a05a2e57312a3fe827619","unresolved":false,"context_lines":[{"line_number":1574,"context_line":""},{"line_number":1575,"context_line":"  static const char* kw_list[] \u003d { \"\", \"auth\", nullptr };"},{"line_number":1576,"context_line":""},{"line_number":1577,"context_line":"  const char* kw_format \u003d \"O!O!\";"},{"line_number":1578,"context_line":"  int ret \u003d PyArg_ParseTupleAndKeywords(args,"},{"line_number":1579,"context_line":"                                        kwargs,"},{"line_number":1580,"context_line":"                                        kw_format,"}],"source_content_type":"text/x-c++src","patch_set":1,"id":"3adcd8dc_2e59e6d6","line":1577,"in_reply_to":"7219862c_c2b89284","updated":"2025-11-25 01:33:55.000000000","message":"Acknowledged","commit_id":"be28ca63563955ef7e20c00e6ded4e38a96cd342"},{"author":{"_account_id":1004568,"name":"Jared Casey","email":"jared.casey@couchbase.com","username":"thejcfactor","avatars":[{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/20ac69da8a1fb4cc11bdd1c880389132.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"d1dbb930a12abfaf552cb845f315ff0f61496f90","unresolved":true,"context_lines":[{"line_number":1603,"context_line":"    return pycbc_build_exception(err.ec, __FILE__, __LINE__, err.message);"},{"line_number":1604,"context_line":"  }"},{"line_number":1605,"context_line":""},{"line_number":1606,"context_line":"  Py_RETURN_TRUE;"},{"line_number":1607,"context_line":"}"}],"source_content_type":"text/x-c++src","patch_set":1,"id":"349316d3_051487e6","line":1606,"updated":"2025-11-12 00:40:00.000000000","message":"I don\u0027t know if I have a strong preference but, curious why return `True` vs. `None`?  I don\u0027t know if returning `True` will add much value (the update is considered successful if it doesn\u0027t fail).","commit_id":"be28ca63563955ef7e20c00e6ded4e38a96cd342"},{"author":{"_account_id":1005381,"name":"Anirudh Lakhotia","display_name":"Anirudh Lakhotia","email":"anirudh.lakhotia@couchbase.com","username":"anirudhlakhotia","avatars":[{"url":"https://www.gravatar.com/avatar/9b86347dbed7e8c52746d07945b7649b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/9b86347dbed7e8c52746d07945b7649b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/9b86347dbed7e8c52746d07945b7649b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/9b86347dbed7e8c52746d07945b7649b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"b2b02aec3fcdc664c10dc3d914c1945a9eb10104","unresolved":true,"context_lines":[{"line_number":1603,"context_line":"    return pycbc_build_exception(err.ec, __FILE__, __LINE__, err.message);"},{"line_number":1604,"context_line":"  }"},{"line_number":1605,"context_line":""},{"line_number":1606,"context_line":"  Py_RETURN_TRUE;"},{"line_number":1607,"context_line":"}"}],"source_content_type":"text/x-c++src","patch_set":1,"id":"93c34d9c_c84c3dd4","line":1606,"in_reply_to":"349316d3_051487e6","updated":"2025-11-21 11:22:53.000000000","message":"Honestly this is mostly just habit. I tend to return True on the success path because the error path returns an exception, so it makes the contrast obvious when reading the C side. But I don’t feel strongly about it either. We don’t really need a redundant success flag here, and it’s probably also more Pythonic to treat \"no exception\" as success, so I’m fine switching to None.\n\nI\u0027ll update the methods and tests accordingly","commit_id":"be28ca63563955ef7e20c00e6ded4e38a96cd342"},{"author":{"_account_id":1005381,"name":"Anirudh Lakhotia","display_name":"Anirudh Lakhotia","email":"anirudh.lakhotia@couchbase.com","username":"anirudhlakhotia","avatars":[{"url":"https://www.gravatar.com/avatar/9b86347dbed7e8c52746d07945b7649b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d32","height":32},{"url":"https://www.gravatar.com/avatar/9b86347dbed7e8c52746d07945b7649b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d56","height":56},{"url":"https://www.gravatar.com/avatar/9b86347dbed7e8c52746d07945b7649b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d100","height":100},{"url":"https://www.gravatar.com/avatar/9b86347dbed7e8c52746d07945b7649b.jpg?d\u003didenticon\u0026r\u003dpg\u0026s\u003d120","height":120}]},"change_message_id":"458649458ba07aad5fbab6e19ceb4d622bccaeee","unresolved":false,"context_lines":[{"line_number":1603,"context_line":"    return pycbc_build_exception(err.ec, __FILE__, __LINE__, err.message);"},{"line_number":1604,"context_line":"  }"},{"line_number":1605,"context_line":""},{"line_number":1606,"context_line":"  Py_RETURN_TRUE;"},{"line_number":1607,"context_line":"}"}],"source_content_type":"text/x-c++src","patch_set":1,"id":"8c0b70d8_5235bcce","line":1606,"in_reply_to":"93c34d9c_c84c3dd4","updated":"2025-11-21 12:12:50.000000000","message":"Done","commit_id":"be28ca63563955ef7e20c00e6ded4e38a96cd342"}]}
