)]}'
{"bin/swift-ring-builder-analyzer":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0f5d4c58d0ec210b94a085b01404893ae2ad9cc8","unresolved":false,"context_lines":[{"line_number":19,"context_line":""},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"if __name__ \u003d\u003d \"__main__\":"},{"line_number":22,"context_line":"    sys.exit(main())"}],"source_content_type":"application/octet-stream","patch_set":1,"id":"ba3cc151_bce4efe0","line":22,"updated":"2015-07-01 17:53:20.000000000","message":"perfect that\u0027s what a bin script is supposed to look like - kudos!","commit_id":"509bb016d085b77c6d96b0ed8c56a9fe7e8566fb"}],"swift/cli/ring_builder_analyzer.py":[{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"51d9000fcdc87e2304c454513a7dccf92829483c","unresolved":false,"context_lines":[{"line_number":28,"context_line":"next round begins."},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"Scenarios are specified in JSON. Example scenario for a gradual device"},{"line_number":31,"context_line":"addition:"},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"{"},{"line_number":34,"context_line":"    \"part_power\": 12,"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba3cc151_97f0e468","line":31,"updated":"2015-07-01 17:30:33.000000000","message":"Could you add a second colon to make it sphinx-friendly? And indent the following block by one space?","commit_id":"509bb016d085b77c6d96b0ed8c56a9fe7e8566fb"},{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"5535a82bde169468738dffcafb84e76b3e10e5f2","unresolved":false,"context_lines":[{"line_number":28,"context_line":"next round begins."},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"Scenarios are specified in JSON. Example scenario for a gradual device"},{"line_number":31,"context_line":"addition:"},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"{"},{"line_number":34,"context_line":"    \"part_power\": 12,"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba3cc151_02fb3148","line":31,"in_reply_to":"ba3cc151_97f0e468","updated":"2015-07-01 19:11:22.000000000","message":"Done","commit_id":"509bb016d085b77c6d96b0ed8c56a9fe7e8566fb"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0f5d4c58d0ec210b94a085b01404893ae2ad9cc8","unresolved":false,"context_lines":[{"line_number":244,"context_line":"                raise ValueError("},{"line_number":245,"context_line":"                    \"Unknown command (round %d, command %d): \""},{"line_number":246,"context_line":"                    \"\u0027%s\u0027 should be one of \u0027add\u0027, \u0027remove\u0027, \u0027set_weight\u0027\" %"},{"line_number":247,"context_line":"                    (round_index, command_index, command[0]))"},{"line_number":248,"context_line":"            parsed_round.append(parsed_command)"},{"line_number":249,"context_line":"        parsed_scenario[\u0027rounds\u0027].append(parsed_round)"},{"line_number":250,"context_line":"    return parsed_scenario"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba3cc151_fc535737","line":247,"updated":"2015-07-01 17:53:20.000000000","message":"nit: I generally prefer a map[cmd] \u003e\u003d function instead of an elif chain for readability and maintenance reasons...\n\n    command_map \u003d {\u0027add\u0027: _parse_add_command, ...}\n\n    parsed_command \u003d command_map[command[0]]\n\n    parsed_command(round_index, command_index, command)\n\nyou capture the KeyError to handle the default case.  It doesn\u0027t appear to be relevant in this case but sometimes using the single call site means your commands need to accept **kwargs.","commit_id":"509bb016d085b77c6d96b0ed8c56a9fe7e8566fb"},{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"5535a82bde169468738dffcafb84e76b3e10e5f2","unresolved":false,"context_lines":[{"line_number":244,"context_line":"                raise ValueError("},{"line_number":245,"context_line":"                    \"Unknown command (round %d, command %d): \""},{"line_number":246,"context_line":"                    \"\u0027%s\u0027 should be one of \u0027add\u0027, \u0027remove\u0027, \u0027set_weight\u0027\" %"},{"line_number":247,"context_line":"                    (round_index, command_index, command[0]))"},{"line_number":248,"context_line":"            parsed_round.append(parsed_command)"},{"line_number":249,"context_line":"        parsed_scenario[\u0027rounds\u0027].append(parsed_round)"},{"line_number":250,"context_line":"    return parsed_scenario"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba3cc151_62255dbf","line":247,"in_reply_to":"ba3cc151_fc535737","updated":"2015-07-01 19:11:22.000000000","message":"Done","commit_id":"509bb016d085b77c6d96b0ed8c56a9fe7e8566fb"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0f5d4c58d0ec210b94a085b01404893ae2ad9cc8","unresolved":false,"context_lines":[{"line_number":301,"context_line":"    parser.add_argument("},{"line_number":302,"context_line":"        \u0027scenario_path\u0027,"},{"line_number":303,"context_line":"        help\u003d\"Path to the scenario file\")"},{"line_number":304,"context_line":"    args \u003d parser.parse_args(argv)"},{"line_number":305,"context_line":""},{"line_number":306,"context_line":"    try:"},{"line_number":307,"context_line":"        with open(args.scenario_path) as sfh:"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba3cc151_d7bc2c08","line":304,"updated":"2015-07-01 17:53:20.000000000","message":"nit: I generally prefer to make the parser a global built up at the top of the file.\n\na) sometimes it\u0027s just as easy to look at how the parser is setup than the help - especially if you\u0027re debugging - nice to have them up top.\n\nb) it\u0027s *super* nice if ever need to monkey patch a script.\n\nc) the parser instance ends up just being a factory for instances of options/namespace/args, and normal behavior will only parse_args once.  The downsides normally associated with globals are fairly mitigated - it\u0027s almost more like a class so it makes sense not to have it buried and inaccessible in main.\n\n... heck it\u0027s even a little easier to unittest.","commit_id":"509bb016d085b77c6d96b0ed8c56a9fe7e8566fb"},{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"5535a82bde169468738dffcafb84e76b3e10e5f2","unresolved":false,"context_lines":[{"line_number":301,"context_line":"    parser.add_argument("},{"line_number":302,"context_line":"        \u0027scenario_path\u0027,"},{"line_number":303,"context_line":"        help\u003d\"Path to the scenario file\")"},{"line_number":304,"context_line":"    args \u003d parser.parse_args(argv)"},{"line_number":305,"context_line":""},{"line_number":306,"context_line":"    try:"},{"line_number":307,"context_line":"        with open(args.scenario_path) as sfh:"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba3cc151_9d0c823c","line":304,"in_reply_to":"ba3cc151_d7bc2c08","updated":"2015-07-01 19:11:22.000000000","message":"Done","commit_id":"509bb016d085b77c6d96b0ed8c56a9fe7e8566fb"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"bce57033ec93ccb0fa60a83a81b4dff39260b31e","unresolved":false,"context_lines":[{"line_number":73,"context_line":"            ], ["},{"line_number":74,"context_line":"                [\"set_weight\", 15, 8000]"},{"line_number":75,"context_line":"            ]]"},{"line_number":76,"context_line":"    }"},{"line_number":77,"context_line":""},{"line_number":78,"context_line":"\"\"\""},{"line_number":79,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"ba3cc151_5d8b48c3","line":76,"updated":"2015-07-02 07:11:12.000000000","message":"NIT: Could you add a sample of removing a device to this scenario, I know the 2 values of the array are obvious, but just for completeness sake.\n\n(and cause no doubt we will get it asked in channel one day)","commit_id":"cfc96afecdb1cc602761a4a532011228c08ccb23"},{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"fcc16b4d64ee2c38abe8a62d8bf6444e3983f010","unresolved":false,"context_lines":[{"line_number":73,"context_line":"            ], ["},{"line_number":74,"context_line":"                [\"set_weight\", 15, 8000]"},{"line_number":75,"context_line":"            ]]"},{"line_number":76,"context_line":"    }"},{"line_number":77,"context_line":""},{"line_number":78,"context_line":"\"\"\""},{"line_number":79,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"ba3cc151_d231695b","line":76,"in_reply_to":"ba3cc151_5d8b48c3","updated":"2015-07-02 15:16:22.000000000","message":"Done","commit_id":"cfc96afecdb1cc602761a4a532011228c08ccb23"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"9655ee494e811a1f04788f5c66a2c480cf3df174","unresolved":false,"context_lines":[{"line_number":28,"context_line":"next round begins."},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"Scenarios are specified in JSON. Example scenario for a gradual device"},{"line_number":31,"context_line":"addition::"},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"    {"},{"line_number":34,"context_line":"        \"part_power\": 12,"}],"source_content_type":"text/x-python","patch_set":3,"id":"ba3cc151_d4b2aa4b","line":31,"updated":"2015-07-02 18:54:17.000000000","message":"Great, thanks @mattoliver - now this comment doesn\u0027t match the example.  sigh.","commit_id":"ccf0758ef1f362312a6197f86455f680ebd990d3"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"d32ff407e15a23410fda6d09b4d6351e38529ce5","unresolved":false,"context_lines":[{"line_number":28,"context_line":"next round begins."},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"Scenarios are specified in JSON. Example scenario for a gradual device"},{"line_number":31,"context_line":"addition::"},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"    {"},{"line_number":34,"context_line":"        \"part_power\": 12,"}],"source_content_type":"text/x-python","patch_set":3,"id":"ba3cc151_0fec5128","line":31,"in_reply_to":"ba3cc151_d4b2aa4b","updated":"2015-07-10 05:57:08.000000000","message":"Well sorry :P\n\nI just wanted the doc\u0027s to have an example of possible actions. We could add 2 scenarios, or change the example to including a remove at some point that makes sense.","commit_id":"ccf0758ef1f362312a6197f86455f680ebd990d3"}],"swift/common/ring/utils.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0f5d4c58d0ec210b94a085b01404893ae2ad9cc8","unresolved":false,"context_lines":[{"line_number":403,"context_line":"    Convert optparse style options into a dictionary for searching."},{"line_number":404,"context_line":""},{"line_number":405,"context_line":"    :param opts: optparse style options"},{"line_number":406,"context_line":"    :returns: a dictionary with search values to filter devices,"},{"line_number":407,"context_line":"              supported parameters are id, region, zone, ip, port,"},{"line_number":408,"context_line":"              replication_ip, replication_port, device, weight, meta"},{"line_number":409,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":1,"id":"ba3cc151_7738c03d","line":406,"updated":"2015-07-01 17:53:20.000000000","message":"phew, wasn\u0027t me.","commit_id":"509bb016d085b77c6d96b0ed8c56a9fe7e8566fb"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0f5d4c58d0ec210b94a085b01404893ae2ad9cc8","unresolved":false,"context_lines":[{"line_number":454,"context_line":""},{"line_number":455,"context_line":"    :returns: dictionary with keys \u0027region\u0027, \u0027zone\u0027, \u0027ip\u0027, \u0027port\u0027, \u0027device\u0027,"},{"line_number":456,"context_line":"        \u0027replication_ip\u0027, \u0027replication_port\u0027, \u0027meta\u0027"},{"line_number":457,"context_line":"    :raises: ValueError if add_value is malformed"},{"line_number":458,"context_line":"    \"\"\""},{"line_number":459,"context_line":"    region \u003d None"},{"line_number":460,"context_line":"    rest \u003d add_value"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba3cc151_971464a0","line":457,"updated":"2015-07-01 17:53:20.000000000","message":"nice doc","commit_id":"509bb016d085b77c6d96b0ed8c56a9fe7e8566fb"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0f5d4c58d0ec210b94a085b01404893ae2ad9cc8","unresolved":false,"context_lines":[{"line_number":482,"context_line":"    if rest.startswith(\u0027R\u0027):"},{"line_number":483,"context_line":"        replication_ip, replication_port, rest \u003d  \\"},{"line_number":484,"context_line":"            parse_address(rest[1:])"},{"line_number":485,"context_line":"    if not rest.startswith(\u0027/\u0027):"},{"line_number":486,"context_line":"        raise ValueError("},{"line_number":487,"context_line":"            \u0027Invalid add value: %s\u0027 % add_value)"},{"line_number":488,"context_line":"    i \u003d 1"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba3cc151_09335cf7","line":485,"updated":"2015-07-01 17:53:20.000000000","message":"nit: there\u0027s a number of error conditions of this function that are not covered by any unittests.","commit_id":"509bb016d085b77c6d96b0ed8c56a9fe7e8566fb"},{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"9e13ff974d8cf6762c6bc5fe5bff8506e258080b","unresolved":false,"context_lines":[{"line_number":482,"context_line":"    if rest.startswith(\u0027R\u0027):"},{"line_number":483,"context_line":"        replication_ip, replication_port, rest \u003d  \\"},{"line_number":484,"context_line":"            parse_address(rest[1:])"},{"line_number":485,"context_line":"    if not rest.startswith(\u0027/\u0027):"},{"line_number":486,"context_line":"        raise ValueError("},{"line_number":487,"context_line":"            \u0027Invalid add value: %s\u0027 % add_value)"},{"line_number":488,"context_line":"    i \u003d 1"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba3cc151_b2f1456d","line":485,"in_reply_to":"ba3cc151_09335cf7","updated":"2015-07-02 15:16:28.000000000","message":"yeah, I just grabbed this code out of the ring builder CLI and put it here so I could call it from the analyzer; I didn\u0027t really think too much about it beyond that.","commit_id":"509bb016d085b77c6d96b0ed8c56a9fe7e8566fb"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0f5d4c58d0ec210b94a085b01404893ae2ad9cc8","unresolved":false,"context_lines":[{"line_number":497,"context_line":"    meta \u003d \u0027\u0027"},{"line_number":498,"context_line":"    if rest.startswith(\u0027_\u0027):"},{"line_number":499,"context_line":"        meta \u003d rest[1:]"},{"line_number":500,"context_line":""},{"line_number":501,"context_line":"    return {\u0027region\u0027: region, \u0027zone\u0027: zone, \u0027ip\u0027: ip, \u0027port\u0027: port,"},{"line_number":502,"context_line":"            \u0027device\u0027: device_name, \u0027replication_ip\u0027: replication_ip,"},{"line_number":503,"context_line":"            \u0027replication_port\u0027: replication_port, \u0027meta\u0027: meta}"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba3cc151_d7faec42","line":500,"updated":"2015-07-01 17:53:20.000000000","message":"hrmm... NameError here doesn\u0027t blow up any tests in tests.unit.common.ring\n\noic - it\u0027s tangentially covered in test.unit.cli","commit_id":"509bb016d085b77c6d96b0ed8c56a9fe7e8566fb"}],"test/unit/cli/test_ring_builder_analyzer.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0f5d4c58d0ec210b94a085b01404893ae2ad9cc8","unresolved":false,"context_lines":[{"line_number":39,"context_line":"        # Just test that it produced some output as it ran; the fact that"},{"line_number":40,"context_line":"        # this doesn\u0027t crash and produces output that resembles something"},{"line_number":41,"context_line":"        # useful is good enough."},{"line_number":42,"context_line":"        self.assertTrue(\u0027Rebalance\u0027 in fake_stdout.getvalue())"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"class TestParseScenario(unittest.TestCase):"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba3cc151_e9f07800","line":42,"updated":"2015-07-01 17:53:20.000000000","message":"lol useful enough and easy to maintain - I like a test that knows it\u0027s limits.","commit_id":"509bb016d085b77c6d96b0ed8c56a9fe7e8566fb"}]}
