)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5c19bcbe58c06cc032f78c74144e1c4a65ebe7b6","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"b3c38b94_90decf87","updated":"2025-12-02 13:04:27.000000000","message":"love the helper!","commit_id":"8b3feb378f80378cd23875e3c6ab0a07a1fdec34"}],"test/unit/obj/test_ssync_sender.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5c19bcbe58c06cc032f78c74144e1c4a65ebe7b6","unresolved":true,"context_lines":[{"line_number":114,"context_line":"                line \u003d b\"\\r\\n%s\" % line"},{"line_number":115,"context_line":"            expected +\u003d b\u0027%x%s\\r\\n\\r\\n\u0027 % (len(line), line)"},{"line_number":116,"context_line":""},{"line_number":117,"context_line":"        self.assertEqual(b\u0027\u0027.join(messages), expected)"},{"line_number":118,"context_line":""},{"line_number":119,"context_line":""},{"line_number":120,"context_line":"@patch_policies()"}],"source_content_type":"text/x-python","patch_set":1,"id":"0d1bb72a_7a14563d","line":117,"updated":"2025-12-02 13:04:27.000000000","message":"Matt - where do you stand on the (expected, actual) vs (actual, expected) arg order debate?\n\nI prefer (expected, actual) because pycharm actually labels failures that way. But I can\u0027t require it. However, if you like also like (expected, actual) then we could take the opportunity to flip here.\n\nBut I do think the order passed in to this helper (which IS (expected, actual)) should match the order forwarded to self.assertEqual, otherwise it gets very confusing.","commit_id":"8b3feb378f80378cd23875e3c6ab0a07a1fdec34"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"b87da87281bc5be3946a874dc2d03a84a05f8840","unresolved":false,"context_lines":[{"line_number":114,"context_line":"                line \u003d b\"\\r\\n%s\" % line"},{"line_number":115,"context_line":"            expected +\u003d b\u0027%x%s\\r\\n\\r\\n\u0027 % (len(line), line)"},{"line_number":116,"context_line":""},{"line_number":117,"context_line":"        self.assertEqual(b\u0027\u0027.join(messages), expected)"},{"line_number":118,"context_line":""},{"line_number":119,"context_line":""},{"line_number":120,"context_line":"@patch_policies()"}],"source_content_type":"text/x-python","patch_set":1,"id":"80400495_1d8fc8ac","line":117,"in_reply_to":"0d1bb72a_7a14563d","updated":"2025-12-03 03:22:58.000000000","message":"Yeah, I\u0027m probably one of the annoying ones who just does one then the other.. then worry about which is the right way :P\n\nHappy to go (expected, actual)","commit_id":"8b3feb378f80378cd23875e3c6ab0a07a1fdec34"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5c19bcbe58c06cc032f78c74144e1c4a65ebe7b6","unresolved":true,"context_lines":[{"line_number":131,"context_line":"                    \u0027partition\u0027: \u002799\u0027}  # sufficient for Sender.__init__"},{"line_number":132,"context_line":"        self.sender \u003d ssync_sender.Sender(self.daemon, None, self.job, None)"},{"line_number":133,"context_line":"        self.ts_iter \u003d make_timestamp_iter()"},{"line_number":134,"context_line":"        self.ts \u003d next(self.ts_iter)"},{"line_number":135,"context_line":""},{"line_number":136,"context_line":"    def test_call_catches_MessageTimeout(self):"},{"line_number":137,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"d5f6f5f9_277b90dd","line":134,"updated":"2025-12-02 13:04:27.000000000","message":"we have a proliferation of ways we do this:\n* in some places self.ts IS the iter\n* in some places self.ts() is a method that returns next(self.ts_iter) \n\nI think this is another new variant 😊\n\nhow would you feel about adopting self.ts() to return next(self.ts_iter) for consistency with test_diskfile.py and controllers/test_obj.py?","commit_id":"8b3feb378f80378cd23875e3c6ab0a07a1fdec34"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"83db6a78bbf2dc9a50715316b26aeae7d343cd9d","unresolved":false,"context_lines":[{"line_number":131,"context_line":"                    \u0027partition\u0027: \u002799\u0027}  # sufficient for Sender.__init__"},{"line_number":132,"context_line":"        self.sender \u003d ssync_sender.Sender(self.daemon, None, self.job, None)"},{"line_number":133,"context_line":"        self.ts_iter \u003d make_timestamp_iter()"},{"line_number":134,"context_line":"        self.ts \u003d next(self.ts_iter)"},{"line_number":135,"context_line":""},{"line_number":136,"context_line":"    def test_call_catches_MessageTimeout(self):"},{"line_number":137,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"3eee9d66_c397cdfa","line":134,"in_reply_to":"d5f6f5f9_277b90dd","updated":"2025-12-05 16:03:36.000000000","message":"Done","commit_id":"8b3feb378f80378cd23875e3c6ab0a07a1fdec34"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5c19bcbe58c06cc032f78c74144e1c4a65ebe7b6","unresolved":true,"context_lines":[{"line_number":866,"context_line":"            [b\u0027:MISSING_CHECK: START\u0027,"},{"line_number":867,"context_line":"             b\u00279d41d8cd98f00b204e9800998ecf0abc %s\u0027 %"},{"line_number":868,"context_line":"             ts1.internal.encode(\u0027ascii\u0027),"},{"line_number":869,"context_line":"             \u0027\u0027],"},{"line_number":870,"context_line":"            connection.sent)"},{"line_number":871,"context_line":""},{"line_number":872,"context_line":"    def test_missing_check_has_empty_suffixes(self):"}],"source_content_type":"text/x-python","patch_set":1,"id":"f0184b46_5dc59f80","line":869,"updated":"2025-12-02 13:04:27.000000000","message":"ok, I can see how it was going to be impossible to future proof these assertion because the hex length preambles will change...hence the helper assertion. Nice.","commit_id":"8b3feb378f80378cd23875e3c6ab0a07a1fdec34"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"83db6a78bbf2dc9a50715316b26aeae7d343cd9d","unresolved":false,"context_lines":[{"line_number":866,"context_line":"            [b\u0027:MISSING_CHECK: START\u0027,"},{"line_number":867,"context_line":"             b\u00279d41d8cd98f00b204e9800998ecf0abc %s\u0027 %"},{"line_number":868,"context_line":"             ts1.internal.encode(\u0027ascii\u0027),"},{"line_number":869,"context_line":"             \u0027\u0027],"},{"line_number":870,"context_line":"            connection.sent)"},{"line_number":871,"context_line":""},{"line_number":872,"context_line":"    def test_missing_check_has_empty_suffixes(self):"}],"source_content_type":"text/x-python","patch_set":1,"id":"34439ccc_7122897b","line":869,"in_reply_to":"f0184b46_5dc59f80","updated":"2025-12-05 16:03:36.000000000","message":"Acknowledged","commit_id":"8b3feb378f80378cd23875e3c6ab0a07a1fdec34"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5c19bcbe58c06cc032f78c74144e1c4a65ebe7b6","unresolved":true,"context_lines":[{"line_number":948,"context_line":"        expected_messages \u003d ["},{"line_number":949,"context_line":"            b\u0027:MISSING_CHECK: START\u0027,"},{"line_number":950,"context_line":"            b\u00279d41d8cd98f00b204e9800998ecf0abc %s\u0027 % ("},{"line_number":951,"context_line":"                timestamps[0].internal.encode(\u0027ascii\u0027)),"},{"line_number":952,"context_line":"            b\u00279d41d8cd98f00b204e9800998ecf0def %s m:186a0\u0027 % ("},{"line_number":953,"context_line":"                timestamps[1].internal.encode(\u0027ascii\u0027)),"},{"line_number":954,"context_line":"            (b\u00279d41d8cd98f00b204e9800998ecf1def %s \u0027"}],"source_content_type":"text/x-python","patch_set":1,"id":"b78bbe1e_42f66ef0","line":951,"updated":"2025-12-02 13:04:27.000000000","message":"given the failing test below, would it work to have the helper do the ascii encoding and pass in a str rather than bytes?","commit_id":"8b3feb378f80378cd23875e3c6ab0a07a1fdec34"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"83db6a78bbf2dc9a50715316b26aeae7d343cd9d","unresolved":false,"context_lines":[{"line_number":948,"context_line":"        expected_messages \u003d ["},{"line_number":949,"context_line":"            b\u0027:MISSING_CHECK: START\u0027,"},{"line_number":950,"context_line":"            b\u00279d41d8cd98f00b204e9800998ecf0abc %s\u0027 % ("},{"line_number":951,"context_line":"                timestamps[0].internal.encode(\u0027ascii\u0027)),"},{"line_number":952,"context_line":"            b\u00279d41d8cd98f00b204e9800998ecf0def %s m:186a0\u0027 % ("},{"line_number":953,"context_line":"                timestamps[1].internal.encode(\u0027ascii\u0027)),"},{"line_number":954,"context_line":"            (b\u00279d41d8cd98f00b204e9800998ecf1def %s \u0027"}],"source_content_type":"text/x-python","patch_set":1,"id":"63692d09_fbef113d","line":951,"in_reply_to":"b78bbe1e_42f66ef0","updated":"2025-12-05 16:03:36.000000000","message":"Done","commit_id":"8b3feb378f80378cd23875e3c6ab0a07a1fdec34"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5c19bcbe58c06cc032f78c74144e1c4a65ebe7b6","unresolved":true,"context_lines":[{"line_number":1380,"context_line":"        object_parts \u003d (\u0027a\u0027, \u0027c\u0027, \u0027o\u0027)"},{"line_number":1381,"context_line":"        df \u003d self._make_open_diskfile(device, part, *object_parts)"},{"line_number":1382,"context_line":"        object_hash \u003d utils.hash_path(*object_parts)"},{"line_number":1383,"context_line":"        delete_timestamp \u003d utils.normalize_timestamp(Timestamp.now())"},{"line_number":1384,"context_line":"        df.delete(delete_timestamp)"},{"line_number":1385,"context_line":"        connection \u003d FakeConnection()"},{"line_number":1386,"context_line":"        self.sender.job \u003d {"}],"source_content_type":"text/x-python","patch_set":1,"id":"e1c91120_94b81fc9","line":1383,"updated":"2025-12-02 13:04:27.000000000","message":"nit: I\u0027ve been trying to move away from string timestamps in favour of Timestamp instances, then using `.internal` where it is asserted. Just a nit though.\n\nI wonder how useful `normalize_timestamp` is these days?","commit_id":"8b3feb378f80378cd23875e3c6ab0a07a1fdec34"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"83db6a78bbf2dc9a50715316b26aeae7d343cd9d","unresolved":false,"context_lines":[{"line_number":1380,"context_line":"        object_parts \u003d (\u0027a\u0027, \u0027c\u0027, \u0027o\u0027)"},{"line_number":1381,"context_line":"        df \u003d self._make_open_diskfile(device, part, *object_parts)"},{"line_number":1382,"context_line":"        object_hash \u003d utils.hash_path(*object_parts)"},{"line_number":1383,"context_line":"        delete_timestamp \u003d utils.normalize_timestamp(Timestamp.now())"},{"line_number":1384,"context_line":"        df.delete(delete_timestamp)"},{"line_number":1385,"context_line":"        connection \u003d FakeConnection()"},{"line_number":1386,"context_line":"        self.sender.job \u003d {"}],"source_content_type":"text/x-python","patch_set":1,"id":"d9ca0698_9d6dd7dc","line":1383,"in_reply_to":"8204fa88_3dbbf1bd","updated":"2025-12-05 16:03:36.000000000","message":"Acknowledged","commit_id":"8b3feb378f80378cd23875e3c6ab0a07a1fdec34"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"b87da87281bc5be3946a874dc2d03a84a05f8840","unresolved":true,"context_lines":[{"line_number":1380,"context_line":"        object_parts \u003d (\u0027a\u0027, \u0027c\u0027, \u0027o\u0027)"},{"line_number":1381,"context_line":"        df \u003d self._make_open_diskfile(device, part, *object_parts)"},{"line_number":1382,"context_line":"        object_hash \u003d utils.hash_path(*object_parts)"},{"line_number":1383,"context_line":"        delete_timestamp \u003d utils.normalize_timestamp(Timestamp.now())"},{"line_number":1384,"context_line":"        df.delete(delete_timestamp)"},{"line_number":1385,"context_line":"        connection \u003d FakeConnection()"},{"line_number":1386,"context_line":"        self.sender.job \u003d {"}],"source_content_type":"text/x-python","patch_set":1,"id":"8204fa88_3dbbf1bd","line":1383,"in_reply_to":"e1c91120_94b81fc9","updated":"2025-12-03 03:22:58.000000000","message":"yeah, I was on the fence here. I didn\u0027t want to change the existing test too much, but definitely needed to change time.time(). Figuriing out ussfulness of `normalize_timestamp` might be a outside of scope? But also happy to change it to juse be a timestamp in this one case, if we\u0027re happy for it.","commit_id":"8b3feb378f80378cd23875e3c6ab0a07a1fdec34"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5c19bcbe58c06cc032f78c74144e1c4a65ebe7b6","unresolved":true,"context_lines":[{"line_number":1703,"context_line":"                                utils.Timestamp(\u00271381679759.90941\u0027))"},{"line_number":1704,"context_line":"        expected_messages \u003d ["},{"line_number":1705,"context_line":"            b\u0027DELETE /a/c/o\\r\\nX-Timestamp: 1381679759.90941\\r\\n\u0027]"},{"line_number":1706,"context_line":"        self.assertConnectionMessages(expected_messages, connection.sent)"},{"line_number":1707,"context_line":""},{"line_number":1708,"context_line":"    def test_send_put_initial_timeout(self):"},{"line_number":1709,"context_line":"        df \u003d self._make_open_diskfile()"}],"source_content_type":"text/x-python","patch_set":1,"id":"2f4004f9_655279b4","line":1706,"updated":"2025-12-02 13:04:27.000000000","message":"I think this one got missed?","commit_id":"8b3feb378f80378cd23875e3c6ab0a07a1fdec34"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5c19bcbe58c06cc032f78c74144e1c4a65ebe7b6","unresolved":true,"context_lines":[{"line_number":1776,"context_line":"             b\u0027Some-Other-Header: value\\r\\n\u0027"},{"line_number":1777,"context_line":"             b\u0027%(meta_name)s: %(meta)s\\r\\n\u0027"},{"line_number":1778,"context_line":"             b\u0027%(no_commit)s\u0027"},{"line_number":1779,"context_line":"             b\u0027X-Timestamp: %(X-Timestamp)s\\r\\n\u0027 % expected),"},{"line_number":1780,"context_line":"            b\u0027%(chunk_size)s\\r\\n%(body)s\u0027 % expected]"},{"line_number":1781,"context_line":"        self.assertConnectionMessages(expected_messages, connection.sent)"},{"line_number":1782,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"54e8ee90_0ea43d02","line":1779,"range":{"start_line":1779,"start_character":51,"end_line":1779,"end_character":59},"updated":"2025-12-02 13:04:27.000000000","message":"IIUC zuul has barfed on the expected dict having str keys but the format \u0027string\u0027 being bytes?","commit_id":"8b3feb378f80378cd23875e3c6ab0a07a1fdec34"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"b87da87281bc5be3946a874dc2d03a84a05f8840","unresolved":true,"context_lines":[{"line_number":1776,"context_line":"             b\u0027Some-Other-Header: value\\r\\n\u0027"},{"line_number":1777,"context_line":"             b\u0027%(meta_name)s: %(meta)s\\r\\n\u0027"},{"line_number":1778,"context_line":"             b\u0027%(no_commit)s\u0027"},{"line_number":1779,"context_line":"             b\u0027X-Timestamp: %(X-Timestamp)s\\r\\n\u0027 % expected),"},{"line_number":1780,"context_line":"            b\u0027%(chunk_size)s\\r\\n%(body)s\u0027 % expected]"},{"line_number":1781,"context_line":"        self.assertConnectionMessages(expected_messages, connection.sent)"},{"line_number":1782,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"585753ab_a781f1e4","line":1779,"range":{"start_line":1779,"start_character":51,"end_line":1779,"end_character":59},"in_reply_to":"54e8ee90_0ea43d02","updated":"2025-12-03 03:22:58.000000000","message":"ahh thanks. Ops missed it.","commit_id":"8b3feb378f80378cd23875e3c6ab0a07a1fdec34"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"83db6a78bbf2dc9a50715316b26aeae7d343cd9d","unresolved":false,"context_lines":[{"line_number":1776,"context_line":"             b\u0027Some-Other-Header: value\\r\\n\u0027"},{"line_number":1777,"context_line":"             b\u0027%(meta_name)s: %(meta)s\\r\\n\u0027"},{"line_number":1778,"context_line":"             b\u0027%(no_commit)s\u0027"},{"line_number":1779,"context_line":"             b\u0027X-Timestamp: %(X-Timestamp)s\\r\\n\u0027 % expected),"},{"line_number":1780,"context_line":"            b\u0027%(chunk_size)s\\r\\n%(body)s\u0027 % expected]"},{"line_number":1781,"context_line":"        self.assertConnectionMessages(expected_messages, connection.sent)"},{"line_number":1782,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"b9718a21_6d1b3d8d","line":1779,"range":{"start_line":1779,"start_character":51,"end_line":1779,"end_character":59},"in_reply_to":"585753ab_a781f1e4","updated":"2025-12-05 16:03:36.000000000","message":"Done","commit_id":"8b3feb378f80378cd23875e3c6ab0a07a1fdec34"}]}
