)]}'
{"rally/common/objects/task.py":[{"author":{"_account_id":7428,"name":"Yaroslav Lobankov","email":"lobankovyv@gmail.com","username":"ylobankov"},"change_message_id":"4015da3a4b792e8c340f2198f8ca8d2e1cc56dad","unresolved":false,"context_lines":[{"line_number":103,"context_line":"        \"hook\": {\"type\": \"string\"},"},{"line_number":104,"context_line":"        \"started_at\": {\"type\": \"number\"},"},{"line_number":105,"context_line":"        \"finished_at\": {\"type\": \"number\"},"},{"line_number":106,"context_line":"        \"triggered_on\": {"},{"line_number":107,"context_line":"            \"type\": \"object\","},{"line_number":108,"context_line":"            \"properties\": {"},{"line_number":109,"context_line":"                \"iteration\": {\"type\": \"integer\"}"}],"source_content_type":"text/x-python","patch_set":11,"id":"fa7ab95a_dea08193","line":106,"range":{"start_line":106,"start_character":19,"end_line":106,"end_character":21},"updated":"2016-08-26 10:09:05.000000000","message":"I know that the \u0027triggered_on\u0027 field was designed in the final version of the hook spec (https://review.openstack.org/#/c/357770/) but the use of \u0027on\u0027  is not correct when we talk about the time (hook can be triggered by the time in the future). I think the use of \u0027at\u0027 will be suitable both for iterations and the time. Guys, what do you think about it?","commit_id":"5ce64426998dc9b62b2ed171f4d520a763b1c27a"},{"author":{"_account_id":19011,"name":"Anton Studenov","email":"tohin1332@gmail.com","username":"tohin"},"change_message_id":"0c6a4b0dd4b29e2411bf9362120c4c8f1df8b361","unresolved":false,"context_lines":[{"line_number":103,"context_line":"        \"hook\": {\"type\": \"string\"},"},{"line_number":104,"context_line":"        \"started_at\": {\"type\": \"number\"},"},{"line_number":105,"context_line":"        \"finished_at\": {\"type\": \"number\"},"},{"line_number":106,"context_line":"        \"triggered_on\": {"},{"line_number":107,"context_line":"            \"type\": \"object\","},{"line_number":108,"context_line":"            \"properties\": {"},{"line_number":109,"context_line":"                \"iteration\": {\"type\": \"integer\"}"}],"source_content_type":"text/x-python","patch_set":11,"id":"fa7ab95a_41bef7d4","line":106,"range":{"start_line":106,"start_character":19,"end_line":106,"end_character":21},"in_reply_to":"fa7ab95a_dea08193","updated":"2016-08-29 08:45:11.000000000","message":"renamed to \"triggered_at\"","commit_id":"5ce64426998dc9b62b2ed171f4d520a763b1c27a"},{"author":{"_account_id":7428,"name":"Yaroslav Lobankov","email":"lobankovyv@gmail.com","username":"ylobankov"},"change_message_id":"4015da3a4b792e8c340f2198f8ca8d2e1cc56dad","unresolved":false,"context_lines":[{"line_number":163,"context_line":"                }"},{"line_number":164,"context_line":"            }"},{"line_number":165,"context_line":"        },"},{"line_number":166,"context_line":"        \"hooks\": {"},{"line_number":167,"context_line":"            \"type\": \"array\","},{"line_number":168,"context_line":"            \"items\": HOOK_FULL_RESULT_SCHEMA,"},{"line_number":169,"context_line":"        },"}],"source_content_type":"text/x-python","patch_set":11,"id":"fa7ab95a_5e655143","line":166,"range":{"start_line":166,"start_character":9,"end_line":166,"end_character":14},"updated":"2016-08-26 10:09:05.000000000","message":"I suppose to name it \u0027hook\u0027 to keep consistency with other keys in the dictionary.","commit_id":"5ce64426998dc9b62b2ed171f4d520a763b1c27a"},{"author":{"_account_id":7428,"name":"Yaroslav Lobankov","email":"lobankovyv@gmail.com","username":"ylobankov"},"change_message_id":"2fa95bf126bbfaa770f2bdba1694669551bb2350","unresolved":false,"context_lines":[{"line_number":163,"context_line":"                }"},{"line_number":164,"context_line":"            }"},{"line_number":165,"context_line":"        },"},{"line_number":166,"context_line":"        \"hooks\": {"},{"line_number":167,"context_line":"            \"type\": \"array\","},{"line_number":168,"context_line":"            \"items\": HOOK_FULL_RESULT_SCHEMA,"},{"line_number":169,"context_line":"        },"}],"source_content_type":"text/x-python","patch_set":11,"id":"fa7ab95a_56043f16","line":166,"range":{"start_line":166,"start_character":9,"end_line":166,"end_character":14},"in_reply_to":"fa7ab95a_5e655143","updated":"2016-08-26 15:33:35.000000000","message":"Sorry about that. We can have more than 1 hook in this section. So the plural is more suitable. Please, ignore this comment.","commit_id":"5ce64426998dc9b62b2ed171f4d520a763b1c27a"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"5b1d5763f9ec9d9e5afded6db2dfb8437c552007","unresolved":false,"context_lines":[{"line_number":96,"context_line":"    \"additionalProperties\": False"},{"line_number":97,"context_line":"}"},{"line_number":98,"context_line":""},{"line_number":99,"context_line":"HOOK_FULL_RESULT_SCHEMA \u003d {"},{"line_number":100,"context_line":"    \"type\": \"object\","},{"line_number":101,"context_line":"    \"$schema\": consts.JSON_SCHEMA,"},{"line_number":102,"context_line":"    \"properties\": {"}],"source_content_type":"text/x-python","patch_set":14,"id":"9a89bdaa_52cb4b53","line":99,"updated":"2016-09-06 12:31:49.000000000","message":"I would recommend to use this schema in rally.task.hook - this will reduce code duplication and allow to rename this to just HOOK_RESULT_SCHEMA.\n\nI believe that properties \"started_at\" and \"finished_at\" do not block this change","commit_id":"4dfb469afbff0ae36e3dff12ef4c346921300f68"}],"rally/common/utils.py":[{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"269c45db1b3b6b1f4a64c3a9ec20a84a65125ee2","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":14,"id":"9a89bdaa_3c7931f7","line":668,"updated":"2016-09-06 12:40:45.000000000","message":"How about another methods that reflects Queue interface?","commit_id":"4dfb469afbff0ae36e3dff12ef4c346921300f68"},{"author":{"_account_id":12395,"name":"Roman Vasylets","email":"pomeo92@gmail.com","username":"rvasilets"},"change_message_id":"4d241288a82eef25a0e98927cc3985b5a95b746b","unresolved":false,"context_lines":[{"line_number":77,"context_line":"        sys.stderr \u003d self.stderr"},{"line_number":78,"context_line":""},{"line_number":79,"context_line":""},{"line_number":80,"context_line":"class Timer(object):"},{"line_number":81,"context_line":"    def __enter__(self):"},{"line_number":82,"context_line":"        self.error \u003d None"},{"line_number":83,"context_line":"        self.start \u003d time.time()"}],"source_content_type":"text/x-python","patch_set":19,"id":"7a8ec9b2_86d74322","line":80,"updated":"2016-09-15 11:56:43.000000000","message":"We should add docs that it should be used only as context manager. Otherwise we will be able to call finish_timestamp() before __exit__ that will give us an error","commit_id":"8b385c68cc716c9aa3cc4185c73d6cd1b5593494"},{"author":{"_account_id":19011,"name":"Anton Studenov","email":"tohin1332@gmail.com","username":"tohin"},"change_message_id":"f80e3b4baace0ec4b0f031955dfbd4c8a25f20aa","unresolved":false,"context_lines":[{"line_number":77,"context_line":"        sys.stderr \u003d self.stderr"},{"line_number":78,"context_line":""},{"line_number":79,"context_line":""},{"line_number":80,"context_line":"class Timer(object):"},{"line_number":81,"context_line":"    def __enter__(self):"},{"line_number":82,"context_line":"        self.error \u003d None"},{"line_number":83,"context_line":"        self.start \u003d time.time()"}],"source_content_type":"text/x-python","patch_set":19,"id":"7a8ec9b2_92ef4586","line":80,"in_reply_to":"7a8ec9b2_86d74322","updated":"2016-09-16 11:16:31.000000000","message":"Done","commit_id":"8b385c68cc716c9aa3cc4185c73d6cd1b5593494"},{"author":{"_account_id":12395,"name":"Roman Vasylets","email":"pomeo92@gmail.com","username":"rvasilets"},"change_message_id":"1a909d4da28781934ce3cbf64615f7152cc5c861","unresolved":false,"context_lines":[{"line_number":659,"context_line":""},{"line_number":660,"context_line":""},{"line_number":661,"context_line":"class DequeAsQueue(object):"},{"line_number":662,"context_line":"    \"\"\"Allows to use some of Queue methods on collections.deque.\"\"\""},{"line_number":663,"context_line":""},{"line_number":664,"context_line":"    def __init__(self, deque):"},{"line_number":665,"context_line":"        self.deque \u003d deque"}],"source_content_type":"text/x-python","patch_set":19,"id":"7a8ec9b2_2fd80def","line":662,"updated":"2016-09-15 11:49:22.000000000","message":"Why not just to use deque as a queue when its needed? At least newcomers will not have the questions what methods and attributes this custom class has opposite to standard python structure.","commit_id":"8b385c68cc716c9aa3cc4185c73d6cd1b5593494"},{"author":{"_account_id":19011,"name":"Anton Studenov","email":"tohin1332@gmail.com","username":"tohin"},"change_message_id":"7168c3d0dd1b5e6fd78a2c3284e49858492b9c8c","unresolved":false,"context_lines":[{"line_number":659,"context_line":""},{"line_number":660,"context_line":""},{"line_number":661,"context_line":"class DequeAsQueue(object):"},{"line_number":662,"context_line":"    \"\"\"Allows to use some of Queue methods on collections.deque.\"\"\""},{"line_number":663,"context_line":""},{"line_number":664,"context_line":"    def __init__(self, deque):"},{"line_number":665,"context_line":"        self.deque \u003d deque"}],"source_content_type":"text/x-python","patch_set":19,"id":"7a8ec9b2_b180f847","line":662,"in_reply_to":"7a8ec9b2_2fd80def","updated":"2016-09-15 13:09:25.000000000","message":"It is used only here [1] to avoid creation of queue listener thread. \n\n[1] https://review.openstack.org/#/c/367366/7/rally/plugins/common/runners/serial.py@69","commit_id":"8b385c68cc716c9aa3cc4185c73d6cd1b5593494"},{"author":{"_account_id":12395,"name":"Roman Vasylets","email":"pomeo92@gmail.com","username":"rvasilets"},"change_message_id":"1a909d4da28781934ce3cbf64615f7152cc5c861","unresolved":false,"context_lines":[{"line_number":677,"context_line":"        return bool(self.deque)"},{"line_number":678,"context_line":""},{"line_number":679,"context_line":""},{"line_number":680,"context_line":"class Stopwatch(object):"},{"line_number":681,"context_line":"    \"\"\"Allows to sleep till specified time since start.\"\"\""},{"line_number":682,"context_line":""},{"line_number":683,"context_line":"    def __init__(self, stop_event\u003dNone):"}],"source_content_type":"text/x-python","patch_set":19,"id":"7a8ec9b2_d5a3b74d","line":680,"updated":"2016-09-15 11:49:22.000000000","message":"here should be CamelCase","commit_id":"8b385c68cc716c9aa3cc4185c73d6cd1b5593494"},{"author":{"_account_id":19011,"name":"Anton Studenov","email":"tohin1332@gmail.com","username":"tohin"},"change_message_id":"7168c3d0dd1b5e6fd78a2c3284e49858492b9c8c","unresolved":false,"context_lines":[{"line_number":677,"context_line":"        return bool(self.deque)"},{"line_number":678,"context_line":""},{"line_number":679,"context_line":""},{"line_number":680,"context_line":"class Stopwatch(object):"},{"line_number":681,"context_line":"    \"\"\"Allows to sleep till specified time since start.\"\"\""},{"line_number":682,"context_line":""},{"line_number":683,"context_line":"    def __init__(self, stop_event\u003dNone):"}],"source_content_type":"text/x-python","patch_set":19,"id":"7a8ec9b2_1157ecce","line":680,"in_reply_to":"7a8ec9b2_d5a3b74d","updated":"2016-09-15 13:09:25.000000000","message":"It is one word. https://en.wiktionary.org/wiki/stopwatch","commit_id":"8b385c68cc716c9aa3cc4185c73d6cd1b5593494"},{"author":{"_account_id":9545,"name":"Andriy Kurilin","email":"andr.kurilin@gmail.com","username":"akurilin"},"change_message_id":"168e97c6c8818517c8131a34a22626389f6a4373","unresolved":false,"context_lines":[{"line_number":692,"context_line":"    def start(self):"},{"line_number":693,"context_line":"        self._start_time \u003d time.time()"},{"line_number":694,"context_line":""},{"line_number":695,"context_line":"    def sleep_till_second(self, sec):"},{"line_number":696,"context_line":"        \"\"\"Sleeps till specified second since start.\"\"\""},{"line_number":697,"context_line":"        target_time \u003d self._start_time + sec"},{"line_number":698,"context_line":"        current_time \u003d time.time()"}],"source_content_type":"text/x-python","patch_set":19,"id":"7a8ec9b2_1fb660dc","line":695,"range":{"start_line":695,"start_character":8,"end_line":695,"end_character":25},"updated":"2016-09-15 09:53:11.000000000","message":"If you will re-submit this patch. Please rename this method to just \"sleep\"","commit_id":"8b385c68cc716c9aa3cc4185c73d6cd1b5593494"},{"author":{"_account_id":19011,"name":"Anton Studenov","email":"tohin1332@gmail.com","username":"tohin"},"change_message_id":"f80e3b4baace0ec4b0f031955dfbd4c8a25f20aa","unresolved":false,"context_lines":[{"line_number":692,"context_line":"    def start(self):"},{"line_number":693,"context_line":"        self._start_time \u003d time.time()"},{"line_number":694,"context_line":""},{"line_number":695,"context_line":"    def sleep_till_second(self, sec):"},{"line_number":696,"context_line":"        \"\"\"Sleeps till specified second since start.\"\"\""},{"line_number":697,"context_line":"        target_time \u003d self._start_time + sec"},{"line_number":698,"context_line":"        current_time \u003d time.time()"}],"source_content_type":"text/x-python","patch_set":19,"id":"7a8ec9b2_f2ea4973","line":695,"range":{"start_line":695,"start_character":8,"end_line":695,"end_character":25},"in_reply_to":"7a8ec9b2_1fb660dc","updated":"2016-09-16 11:16:31.000000000","message":"Done","commit_id":"8b385c68cc716c9aa3cc4185c73d6cd1b5593494"},{"author":{"_account_id":12395,"name":"Roman Vasylets","email":"pomeo92@gmail.com","username":"rvasilets"},"change_message_id":"1a909d4da28781934ce3cbf64615f7152cc5c861","unresolved":false,"context_lines":[{"line_number":705,"context_line":"        if self._stop_event:"},{"line_number":706,"context_line":"            self._stop_event.wait(sec)"},{"line_number":707,"context_line":"        else:"},{"line_number":708,"context_line":"            time.sleep(sec)"}],"source_content_type":"text/x-python","patch_set":19,"id":"7a8ec9b2_75ef4387","line":708,"updated":"2016-09-15 11:49:22.000000000","message":"please use interruptible sleep here. Its critical to runners timeout","commit_id":"8b385c68cc716c9aa3cc4185c73d6cd1b5593494"},{"author":{"_account_id":19011,"name":"Anton Studenov","email":"tohin1332@gmail.com","username":"tohin"},"change_message_id":"f80e3b4baace0ec4b0f031955dfbd4c8a25f20aa","unresolved":false,"context_lines":[{"line_number":705,"context_line":"        if self._stop_event:"},{"line_number":706,"context_line":"            self._stop_event.wait(sec)"},{"line_number":707,"context_line":"        else:"},{"line_number":708,"context_line":"            time.sleep(sec)"}],"source_content_type":"text/x-python","patch_set":19,"id":"7a8ec9b2_72f71959","line":708,"in_reply_to":"7a8ec9b2_75ef4387","updated":"2016-09-16 11:16:31.000000000","message":"Done","commit_id":"8b385c68cc716c9aa3cc4185c73d6cd1b5593494"}],"rally/plugins/common/hook/sys_call.py":[{"author":{"_account_id":11748,"name":"Chris St. Pierre","email":"cstpierr@cisco.com","username":"stpierre"},"change_message_id":"3556d4a282f30dbe0ccf4376c32ff1878099d49e","unresolved":false,"context_lines":[{"line_number":43,"context_line":"        self.action_name \u003d self.config[\"action_name\"]"},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"    def run(self):"},{"line_number":46,"context_line":"        rc \u003d os.system(self.cmd)"},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"        return {"},{"line_number":49,"context_line":"            \"action\": self.action_name,"}],"source_content_type":"text/x-python","patch_set":7,"id":"3ac371cc_1c43346d","line":46,"updated":"2016-08-18 16:14:01.000000000","message":"The hook result schema has facilities for handling output and error, so this should use subprocess.Popen() instead in order to capture stdout and stderr. Otherwise this hook is just a black box that will be impossible to troubleshoot.","commit_id":"a5e82dd17cc707cbf0baf7f882ae64180106b9fc"},{"author":{"_account_id":19011,"name":"Anton Studenov","email":"tohin1332@gmail.com","username":"tohin"},"change_message_id":"43a9d44afc2ebc7469b8bfca456f25f93b0d06c3","unresolved":false,"context_lines":[{"line_number":43,"context_line":"        self.action_name \u003d self.config[\"action_name\"]"},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"    def run(self):"},{"line_number":46,"context_line":"        rc \u003d os.system(self.cmd)"},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"        return {"},{"line_number":49,"context_line":"            \"action\": self.action_name,"}],"source_content_type":"text/x-python","patch_set":7,"id":"1ac06dbe_08eb3014","line":46,"in_reply_to":"3ac371cc_1c43346d","updated":"2016-08-23 14:15:28.000000000","message":"Done","commit_id":"a5e82dd17cc707cbf0baf7f882ae64180106b9fc"},{"author":{"_account_id":7428,"name":"Yaroslav Lobankov","email":"lobankovyv@gmail.com","username":"ylobankov"},"change_message_id":"4015da3a4b792e8c340f2198f8ca8d2e1cc56dad","unresolved":false,"context_lines":[{"line_number":29,"context_line":"        \"$schema\": consts.JSON_SCHEMA,"},{"line_number":30,"context_line":"        \"properties\": {"},{"line_number":31,"context_line":"            \"cmd\": {\"type\": \"string\"},"},{"line_number":32,"context_line":"            \"action_name\": {\"type\": \"string\"},"},{"line_number":33,"context_line":"        },"},{"line_number":34,"context_line":"        \"required\": ["},{"line_number":35,"context_line":"            \"cmd\","}],"source_content_type":"text/x-python","patch_set":11,"id":"fa7ab95a_c196e093","line":32,"range":{"start_line":32,"start_character":19,"end_line":32,"end_character":24},"updated":"2016-08-26 10:09:05.000000000","message":"IMHO, \u0027name\u0027 is redundant because we can specify not only action name here but also the full description of what the hook does.","commit_id":"5ce64426998dc9b62b2ed171f4d520a763b1c27a"},{"author":{"_account_id":19011,"name":"Anton Studenov","email":"tohin1332@gmail.com","username":"tohin"},"change_message_id":"0c6a4b0dd4b29e2411bf9362120c4c8f1df8b361","unresolved":false,"context_lines":[{"line_number":29,"context_line":"        \"$schema\": consts.JSON_SCHEMA,"},{"line_number":30,"context_line":"        \"properties\": {"},{"line_number":31,"context_line":"            \"cmd\": {\"type\": \"string\"},"},{"line_number":32,"context_line":"            \"action_name\": {\"type\": \"string\"},"},{"line_number":33,"context_line":"        },"},{"line_number":34,"context_line":"        \"required\": ["},{"line_number":35,"context_line":"            \"cmd\","}],"source_content_type":"text/x-python","patch_set":11,"id":"fa7ab95a_c1e3e703","line":32,"range":{"start_line":32,"start_character":19,"end_line":32,"end_character":24},"in_reply_to":"fa7ab95a_b6990b71","updated":"2016-08-29 08:45:11.000000000","message":"Done","commit_id":"5ce64426998dc9b62b2ed171f4d520a763b1c27a"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"27114582e9861c83678e0b3b01040128334077d7","unresolved":false,"context_lines":[{"line_number":29,"context_line":"        \"$schema\": consts.JSON_SCHEMA,"},{"line_number":30,"context_line":"        \"properties\": {"},{"line_number":31,"context_line":"            \"cmd\": {\"type\": \"string\"},"},{"line_number":32,"context_line":"            \"action_name\": {\"type\": \"string\"},"},{"line_number":33,"context_line":"        },"},{"line_number":34,"context_line":"        \"required\": ["},{"line_number":35,"context_line":"            \"cmd\","}],"source_content_type":"text/x-python","patch_set":11,"id":"fa7ab95a_b6990b71","line":32,"range":{"start_line":32,"start_character":19,"end_line":32,"end_character":24},"in_reply_to":"fa7ab95a_c196e093","updated":"2016-08-26 15:26:36.000000000","message":"Agree","commit_id":"5ce64426998dc9b62b2ed171f4d520a763b1c27a"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"496ca319e6e358c2c53021cd2364939f823c91ce","unresolved":false,"context_lines":[{"line_number":38,"context_line":"        \"additionalProperties\": False,"},{"line_number":39,"context_line":"    }"},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"    def __init__(self, config):"},{"line_number":42,"context_line":"        super(SysCallHook, self).__init__(config)"},{"line_number":43,"context_line":"        self.cmd \u003d self.config[\"cmd\"]"},{"line_number":44,"context_line":"        self.action_name \u003d self.config[\"action_name\"]"}],"source_content_type":"text/x-python","patch_set":11,"id":"fa7ab95a_b6358b47","line":41,"updated":"2016-08-26 15:27:56.000000000","message":"this __init__ is redundant since  self.config[\"cmd\"] and self.config[\"action_name\"] already saved by superclass __init__()","commit_id":"5ce64426998dc9b62b2ed171f4d520a763b1c27a"},{"author":{"_account_id":19011,"name":"Anton Studenov","email":"tohin1332@gmail.com","username":"tohin"},"change_message_id":"0c6a4b0dd4b29e2411bf9362120c4c8f1df8b361","unresolved":false,"context_lines":[{"line_number":38,"context_line":"        \"additionalProperties\": False,"},{"line_number":39,"context_line":"    }"},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"    def __init__(self, config):"},{"line_number":42,"context_line":"        super(SysCallHook, self).__init__(config)"},{"line_number":43,"context_line":"        self.cmd \u003d self.config[\"cmd\"]"},{"line_number":44,"context_line":"        self.action_name \u003d self.config[\"action_name\"]"}],"source_content_type":"text/x-python","patch_set":11,"id":"fa7ab95a_e1f2abd1","line":41,"in_reply_to":"fa7ab95a_b6358b47","updated":"2016-08-29 08:45:11.000000000","message":"Done","commit_id":"5ce64426998dc9b62b2ed171f4d520a763b1c27a"}],"rally/plugins/common/runners/constant.py":[{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"5b1d5763f9ec9d9e5afded6db2dfb8437c552007","unresolved":false,"context_lines":[{"line_number":298,"context_line":"                if not event_queue.empty():"},{"line_number":299,"context_line":"                    self._send_event(event_queue.get())"},{"line_number":300,"context_line":"                else:"},{"line_number":301,"context_line":"                    time.sleep(0.001)"},{"line_number":302,"context_line":""},{"line_number":303,"context_line":"        event_listener_thread \u003d threading.Thread(target\u003devent_listener)"},{"line_number":304,"context_line":""}],"source_content_type":"text/x-python","patch_set":14,"id":"9a89bdaa_48de3c6e","line":301,"updated":"2016-09-06 12:31:49.000000000","message":"0.001 seems to be too small period, maybe reduce it to at least 0.01 (or even bigger)","commit_id":"4dfb469afbff0ae36e3dff12ef4c346921300f68"}],"rally/plugins/common/trigger/event.py":[{"author":{"_account_id":9545,"name":"Andriy Kurilin","email":"andr.kurilin@gmail.com","username":"akurilin"},"change_message_id":"e441411374b674033af4585a05e9f97f595a7431","unresolved":false,"context_lines":[{"line_number":17,"context_line":"from rally.task import trigger"},{"line_number":18,"context_line":""},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"@trigger.configure(name\u003d\"event\")"},{"line_number":21,"context_line":"class EventTrigger(trigger.Trigger):"},{"line_number":22,"context_line":"    \"\"\"Triggers hook on specified iterations.\"\"\""},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"    CONFIG_SCHEMA \u003d {"},{"line_number":25,"context_line":"        \"type\": \"object\","},{"line_number":26,"context_line":"        \"$schema\": consts.JSON_SCHEMA,"},{"line_number":27,"context_line":"        \"properties\": {"},{"line_number":28,"context_line":"            \"unit\": {\"enum\": [\"iteration\"]},"},{"line_number":29,"context_line":"            \"at\": {"},{"line_number":30,"context_line":"                \"type\": \"array\","},{"line_number":31,"context_line":"                \"minItems\": 1,"},{"line_number":32,"context_line":"                \"items\": {"},{"line_number":33,"context_line":"                    \"type\": \"integer\","},{"line_number":34,"context_line":"                    \"minimum\": 1,"},{"line_number":35,"context_line":"                    \"uniqueItems\": True,"},{"line_number":36,"context_line":"                }"},{"line_number":37,"context_line":"            },"},{"line_number":38,"context_line":"        },"},{"line_number":39,"context_line":"        \"required\": ["},{"line_number":40,"context_line":"            \"unit\","},{"line_number":41,"context_line":"            \"at\","},{"line_number":42,"context_line":"        ],"},{"line_number":43,"context_line":"        \"additionalProperties\": False,"},{"line_number":44,"context_line":"    }"},{"line_number":45,"context_line":""},{"line_number":46,"context_line":"    def on_iteration(self, iteration_number):"},{"line_number":47,"context_line":"        return iteration_number in self.config[\"at\"]"}],"source_content_type":"text/x-python","patch_set":13,"id":"fa7ab95a_a1c6d897","line":47,"range":{"start_line":20,"start_character":0,"end_line":47,"end_character":52},"updated":"2016-08-29 11:31:37.000000000","message":"why we need to make this pluggable? It looks redundant, since HookExecutor is already hardcoded to on_iteration and I can\u0027t imagine another possible implementation for \"on_itaration\"","commit_id":"2fcdfea8861656101257033ab969baa912edb47c"},{"author":{"_account_id":19011,"name":"Anton Studenov","email":"tohin1332@gmail.com","username":"tohin"},"change_message_id":"a2d89bc5af4e6413eccbcf26478fad0332ac4f58","unresolved":false,"context_lines":[{"line_number":17,"context_line":"from rally.task import trigger"},{"line_number":18,"context_line":""},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"@trigger.configure(name\u003d\"event\")"},{"line_number":21,"context_line":"class EventTrigger(trigger.Trigger):"},{"line_number":22,"context_line":"    \"\"\"Triggers hook on specified iterations.\"\"\""},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"    CONFIG_SCHEMA \u003d {"},{"line_number":25,"context_line":"        \"type\": \"object\","},{"line_number":26,"context_line":"        \"$schema\": consts.JSON_SCHEMA,"},{"line_number":27,"context_line":"        \"properties\": {"},{"line_number":28,"context_line":"            \"unit\": {\"enum\": [\"iteration\"]},"},{"line_number":29,"context_line":"            \"at\": {"},{"line_number":30,"context_line":"                \"type\": \"array\","},{"line_number":31,"context_line":"                \"minItems\": 1,"},{"line_number":32,"context_line":"                \"items\": {"},{"line_number":33,"context_line":"                    \"type\": \"integer\","},{"line_number":34,"context_line":"                    \"minimum\": 1,"},{"line_number":35,"context_line":"                    \"uniqueItems\": True,"},{"line_number":36,"context_line":"                }"},{"line_number":37,"context_line":"            },"},{"line_number":38,"context_line":"        },"},{"line_number":39,"context_line":"        \"required\": ["},{"line_number":40,"context_line":"            \"unit\","},{"line_number":41,"context_line":"            \"at\","},{"line_number":42,"context_line":"        ],"},{"line_number":43,"context_line":"        \"additionalProperties\": False,"},{"line_number":44,"context_line":"    }"},{"line_number":45,"context_line":""},{"line_number":46,"context_line":"    def on_iteration(self, iteration_number):"},{"line_number":47,"context_line":"        return iteration_number in self.config[\"at\"]"}],"source_content_type":"text/x-python","patch_set":13,"id":"fa7ab95a_416a6cef","line":47,"range":{"start_line":20,"start_character":0,"end_line":47,"end_character":52},"in_reply_to":"fa7ab95a_a1c6d897","updated":"2016-08-29 11:44:01.000000000","message":"Another implementation: https://review.openstack.org/#/c/360740/4/rally/plugins/common/trigger/periodic.py","commit_id":"2fcdfea8861656101257033ab969baa912edb47c"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"5b1d5763f9ec9d9e5afded6db2dfb8437c552007","unresolved":false,"context_lines":[{"line_number":19,"context_line":""},{"line_number":20,"context_line":"@trigger.configure(name\u003d\"event\")"},{"line_number":21,"context_line":"class EventTrigger(trigger.Trigger):"},{"line_number":22,"context_line":"    \"\"\"Triggers hook on specified iterations.\"\"\""},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"    CONFIG_SCHEMA \u003d {"},{"line_number":25,"context_line":"        \"type\": \"object\","}],"source_content_type":"text/x-python","patch_set":14,"id":"9a89bdaa_663df1ba","line":22,"updated":"2016-09-06 12:31:49.000000000","message":"Is this trigger is planned to remain for iterations only?\nWord \"event\" gives more flexibility, so I thought this trigger could support another unit types in future","commit_id":"4dfb469afbff0ae36e3dff12ef4c346921300f68"},{"author":{"_account_id":19011,"name":"Anton Studenov","email":"tohin1332@gmail.com","username":"tohin"},"change_message_id":"7f47a39401aa2f0f3e313abd65b1716a429f73cc","unresolved":false,"context_lines":[{"line_number":19,"context_line":""},{"line_number":20,"context_line":"@trigger.configure(name\u003d\"event\")"},{"line_number":21,"context_line":"class EventTrigger(trigger.Trigger):"},{"line_number":22,"context_line":"    \"\"\"Triggers hook on specified iterations.\"\"\""},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"    CONFIG_SCHEMA \u003d {"},{"line_number":25,"context_line":"        \"type\": \"object\","}],"source_content_type":"text/x-python","patch_set":14,"id":"9a89bdaa_1c3c6d2e","line":22,"in_reply_to":"9a89bdaa_663df1ba","updated":"2016-09-06 12:43:26.000000000","message":"It supports if type of values will be the same. If we will use integer type for seconds too.","commit_id":"4dfb469afbff0ae36e3dff12ef4c346921300f68"},{"author":{"_account_id":9545,"name":"Andriy Kurilin","email":"andr.kurilin@gmail.com","username":"akurilin"},"change_message_id":"68fccb1b943715ad8309c9c3af29fcd7e47d6c09","unresolved":false,"context_lines":[{"line_number":25,"context_line":"        \"type\": \"object\","},{"line_number":26,"context_line":"        \"$schema\": consts.JSON_SCHEMA,"},{"line_number":27,"context_line":"        \"properties\": {"},{"line_number":28,"context_line":"            \"unit\": {\"enum\": [\"iteration\", \"time\"]},"},{"line_number":29,"context_line":"            \"at\": {"},{"line_number":30,"context_line":"                \"type\": \"array\","},{"line_number":31,"context_line":"                \"minItems\": 1,"}],"source_content_type":"text/x-python","patch_set":16,"id":"9a89bdaa_afbaa56c","line":28,"range":{"start_line":28,"start_character":41,"end_line":28,"end_character":49},"updated":"2016-09-09 11:45:33.000000000","message":"as far as I understand it is not implemented yet, but validation will not fail if user tries to choose it","commit_id":"593e081e4a550ac636bb95513675a4a483b0eb1d"},{"author":{"_account_id":19011,"name":"Anton Studenov","email":"tohin1332@gmail.com","username":"tohin"},"change_message_id":"560c35e5a9604643c540915b3bf3e8f63cfbecec","unresolved":false,"context_lines":[{"line_number":25,"context_line":"        \"type\": \"object\","},{"line_number":26,"context_line":"        \"$schema\": consts.JSON_SCHEMA,"},{"line_number":27,"context_line":"        \"properties\": {"},{"line_number":28,"context_line":"            \"unit\": {\"enum\": [\"iteration\", \"time\"]},"},{"line_number":29,"context_line":"            \"at\": {"},{"line_number":30,"context_line":"                \"type\": \"array\","},{"line_number":31,"context_line":"                \"minItems\": 1,"}],"source_content_type":"text/x-python","patch_set":16,"id":"9a89bdaa_6ad40b47","line":28,"range":{"start_line":28,"start_character":41,"end_line":28,"end_character":49},"in_reply_to":"9a89bdaa_afbaa56c","updated":"2016-09-09 11:50:00.000000000","message":"support for time events is added in second patch: https://review.openstack.org/#/c/367364/2/rally/task/hook.py@70","commit_id":"593e081e4a550ac636bb95513675a4a483b0eb1d"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"ee331455d677eadf27a700011fa396b1b6e72a51","unresolved":false,"context_lines":[{"line_number":18,"context_line":""},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"@trigger.configure(name\u003d\"event\")"},{"line_number":21,"context_line":"class EventTrigger(trigger.Trigger):"},{"line_number":22,"context_line":"    \"\"\"Triggers hook on specified event.\"\"\""},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"    CONFIG_SCHEMA \u003d {"}],"source_content_type":"text/x-python","patch_set":18,"id":"9a89bdaa_b47fdf15","line":21,"updated":"2016-09-13 01:57:36.000000000","message":"Should it be called IterationTrigger?","commit_id":"ea6e2fdaff7c98bea319aa23b9efaf2c87695cd1"},{"author":{"_account_id":19011,"name":"Anton Studenov","email":"tohin1332@gmail.com","username":"tohin"},"change_message_id":"3bd3399cf057138298e6a92e0faa4b460ad90831","unresolved":false,"context_lines":[{"line_number":18,"context_line":""},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"@trigger.configure(name\u003d\"event\")"},{"line_number":21,"context_line":"class EventTrigger(trigger.Trigger):"},{"line_number":22,"context_line":"    \"\"\"Triggers hook on specified event.\"\"\""},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"    CONFIG_SCHEMA \u003d {"}],"source_content_type":"text/x-python","patch_set":18,"id":"9a89bdaa_e51d2e74","line":21,"in_reply_to":"9a89bdaa_b47fdf15","updated":"2016-09-13 07:31:52.000000000","message":"No, it is suitable for both iteration and time event types.","commit_id":"ea6e2fdaff7c98bea319aa23b9efaf2c87695cd1"},{"author":{"_account_id":9545,"name":"Andriy Kurilin","email":"andr.kurilin@gmail.com","username":"akurilin"},"change_message_id":"a4fe2be51e01873ce22fca658f4748490079c9d4","unresolved":false,"context_lines":[{"line_number":25,"context_line":"        \"type\": \"object\","},{"line_number":26,"context_line":"        \"$schema\": consts.JSON_SCHEMA,"},{"line_number":27,"context_line":"        \"properties\": {"},{"line_number":28,"context_line":"            \"at\": {"},{"line_number":29,"context_line":"                \"type\": \"array\","},{"line_number":30,"context_line":"                \"minItems\": 1,"},{"line_number":31,"context_line":"                \"items\": {"},{"line_number":32,"context_line":"                    \"type\": \"integer\","},{"line_number":33,"context_line":"                    \"minimum\": 0,"},{"line_number":34,"context_line":"                    \"uniqueItems\": True,"},{"line_number":35,"context_line":"                }"},{"line_number":36,"context_line":"            },"},{"line_number":37,"context_line":"        },"},{"line_number":38,"context_line":"        \"required\": [\"at\"],"},{"line_number":39,"context_line":"        \"additionalProperties\": False,"}],"source_content_type":"text/x-python","patch_set":18,"id":"9a89bdaa_01febd37","line":36,"range":{"start_line":28,"start_character":12,"end_line":36,"end_character":14},"updated":"2016-09-12 12:17:49.000000000","message":"actually, previous schema was better. It allowed to set different properties based on unit.\nFor example, we numerate iterations from 1, not from 0. so 0 is invalid value. But in case of time unit, 0 is a valid value.\n\nAlso, in future, it would be nice to extend hooks to be launched not only iterations, but after execution of all iterations and contexts. For example to add custom processing of results. In this case, we will add new events like \"load-is-finished\" and should be accepted be jsonschema...","commit_id":"ea6e2fdaff7c98bea319aa23b9efaf2c87695cd1"},{"author":{"_account_id":9545,"name":"Andriy Kurilin","email":"andr.kurilin@gmail.com","username":"akurilin"},"change_message_id":"168e97c6c8818517c8131a34a22626389f6a4373","unresolved":false,"context_lines":[{"line_number":27,"context_line":"        \"oneOf\": ["},{"line_number":28,"context_line":"            {"},{"line_number":29,"context_line":"                \"properties\": {"},{"line_number":30,"context_line":"                    \"unit\": {\"enum\": [\"time\"]},"},{"line_number":31,"context_line":"                    \"at\": {"},{"line_number":32,"context_line":"                        \"type\": \"array\","},{"line_number":33,"context_line":"                        \"minItems\": 1,"}],"source_content_type":"text/x-python","patch_set":19,"id":"7a8ec9b2_6f1775ed","line":30,"range":{"start_line":30,"start_character":20,"end_line":30,"end_character":47},"updated":"2016-09-15 09:53:11.000000000","message":"Alternative way:\n\n\"unit\": {\"type\": \"string\", \"pattern\": \"^time$\"}","commit_id":"8b385c68cc716c9aa3cc4185c73d6cd1b5593494"}],"rally/task/hook.py":[{"author":{"_account_id":11748,"name":"Chris St. Pierre","email":"cstpierr@cisco.com","username":"stpierre"},"change_message_id":"3556d4a282f30dbe0ccf4376c32ff1878099d49e","unresolved":false,"context_lines":[{"line_number":47,"context_line":"    return result"},{"line_number":48,"context_line":""},{"line_number":49,"context_line":""},{"line_number":50,"context_line":"class HookExecuter(object):"},{"line_number":51,"context_line":"    \"\"\"Runs hooks and collects results from them.\"\"\""},{"line_number":52,"context_line":""},{"line_number":53,"context_line":"    def __init__(self, config):"}],"source_content_type":"text/x-python","patch_set":7,"id":"3ac371cc_68454241","line":50,"updated":"2016-08-18 16:14:01.000000000","message":"Spelling (here and elsewhere: Executor","commit_id":"a5e82dd17cc707cbf0baf7f882ae64180106b9fc"},{"author":{"_account_id":19011,"name":"Anton Studenov","email":"tohin1332@gmail.com","username":"tohin"},"change_message_id":"43a9d44afc2ebc7469b8bfca456f25f93b0d06c3","unresolved":false,"context_lines":[{"line_number":47,"context_line":"    return result"},{"line_number":48,"context_line":""},{"line_number":49,"context_line":""},{"line_number":50,"context_line":"class HookExecuter(object):"},{"line_number":51,"context_line":"    \"\"\"Runs hooks and collects results from them.\"\"\""},{"line_number":52,"context_line":""},{"line_number":53,"context_line":"    def __init__(self, config):"}],"source_content_type":"text/x-python","patch_set":7,"id":"1ac06dbe_c8e59838","line":50,"in_reply_to":"3ac371cc_68454241","updated":"2016-08-23 14:15:28.000000000","message":"Done","commit_id":"a5e82dd17cc707cbf0baf7f882ae64180106b9fc"},{"author":{"_account_id":11748,"name":"Chris St. Pierre","email":"cstpierr@cisco.com","username":"stpierre"},"change_message_id":"3556d4a282f30dbe0ccf4376c32ff1878099d49e","unresolved":false,"context_lines":[{"line_number":56,"context_line":""},{"line_number":57,"context_line":"        # load hooks for iterations"},{"line_number":58,"context_line":"        iterations_config \u003d config.get(\"hook\", {}).get(\"iterations\", {})"},{"line_number":59,"context_line":"        self.hooks \u003d dict("},{"line_number":60,"context_line":"            ("},{"line_number":61,"context_line":"                int(iter_num),"},{"line_number":62,"context_line":"                [self._get_hook(hook_as_dict) for hook_as_dict in hooks]"}],"source_content_type":"text/x-python","patch_set":7,"id":"3ac371cc_8f6b6884","line":59,"updated":"2016-08-18 16:14:01.000000000","message":"I don\u0027t think we support py2.6 any more, so you can use an actual dict comprehension here.","commit_id":"a5e82dd17cc707cbf0baf7f882ae64180106b9fc"},{"author":{"_account_id":11748,"name":"Chris St. Pierre","email":"cstpierr@cisco.com","username":"stpierre"},"change_message_id":"3556d4a282f30dbe0ccf4376c32ff1878099d49e","unresolved":false,"context_lines":[{"line_number":65,"context_line":"            if iter_num.isdigit()"},{"line_number":66,"context_line":"        )"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"        self.pereodic_hooks \u003d dict("},{"line_number":69,"context_line":"            (int(iter_num), hooks)"},{"line_number":70,"context_line":"            for iter_num, hooks"},{"line_number":71,"context_line":"            in iterations_config.get(\"pereodic\", {}).items()"}],"source_content_type":"text/x-python","patch_set":7,"id":"3ac371cc_6fdf0cd6","line":68,"updated":"2016-08-18 16:14:01.000000000","message":"Spelling, here and elsewhere: periodic\n\nAlso, use a dict comprehension.","commit_id":"a5e82dd17cc707cbf0baf7f882ae64180106b9fc"},{"author":{"_account_id":19011,"name":"Anton Studenov","email":"tohin1332@gmail.com","username":"tohin"},"change_message_id":"43a9d44afc2ebc7469b8bfca456f25f93b0d06c3","unresolved":false,"context_lines":[{"line_number":65,"context_line":"            if iter_num.isdigit()"},{"line_number":66,"context_line":"        )"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"        self.pereodic_hooks \u003d dict("},{"line_number":69,"context_line":"            (int(iter_num), hooks)"},{"line_number":70,"context_line":"            for iter_num, hooks"},{"line_number":71,"context_line":"            in iterations_config.get(\"pereodic\", {}).items()"}],"source_content_type":"text/x-python","patch_set":7,"id":"1ac06dbe_08d2105c","line":68,"in_reply_to":"3ac371cc_6fdf0cd6","updated":"2016-08-23 14:15:28.000000000","message":"Done","commit_id":"a5e82dd17cc707cbf0baf7f882ae64180106b9fc"},{"author":{"_account_id":11748,"name":"Chris St. Pierre","email":"cstpierr@cisco.com","username":"stpierre"},"change_message_id":"3556d4a282f30dbe0ccf4376c32ff1878099d49e","unresolved":false,"context_lines":[{"line_number":69,"context_line":"            (int(iter_num), hooks)"},{"line_number":70,"context_line":"            for iter_num, hooks"},{"line_number":71,"context_line":"            in iterations_config.get(\"pereodic\", {}).items()"},{"line_number":72,"context_line":"        )"},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"    @staticmethod"},{"line_number":75,"context_line":"    def _get_hook(hook_as_dict):"}],"source_content_type":"text/x-python","patch_set":7,"id":"3ac371cc_92026bb2","line":72,"updated":"2016-08-18 16:14:01.000000000","message":"This seems like a design flaw. Why do we cram periodic tasks into the same \"iterations\" key along with non-periodic tasks? Why don\u0027t we do:\n\n    \"hook\": {\n        \"iterations\": {\n            20: [...]\n        },\n        \"periodic\": {\n            10: [...]\n        }\n     }\n\nThat gets rid of all of the logic that you\u0027ve got to distinguish periodic from iteration-based hooks, and all of the int() casting as well. It should also simplify the schema a bit, since you can just check for integers rather than using a regex to ensure that keys are either \"periodic\" or numeric.","commit_id":"a5e82dd17cc707cbf0baf7f882ae64180106b9fc"},{"author":{"_account_id":11748,"name":"Chris St. Pierre","email":"cstpierr@cisco.com","username":"stpierre"},"change_message_id":"3556d4a282f30dbe0ccf4376c32ff1878099d49e","unresolved":false,"context_lines":[{"line_number":72,"context_line":"        )"},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"    @staticmethod"},{"line_number":75,"context_line":"    def _get_hook(hook_as_dict):"},{"line_number":76,"context_line":"        # there should be only one hook in dict"},{"line_number":77,"context_line":"        hook_name, hook_config \u003d six.next(six.iteritems(hook_as_dict))"},{"line_number":78,"context_line":"        return Hook.get(hook_name)(hook_config)"}],"source_content_type":"text/x-python","patch_set":7,"id":"3ac371cc_f2ff5f63","line":75,"updated":"2016-08-18 16:14:01.000000000","message":"The existence of this function suggests to me that the hook configuration interface is designed poorly. Instead of a dict-within-a-dict, I\u0027d suggest:\n\n    \"hook\": {\n        \"iterations\": {\n            20: [{\n                    \"name\": \"example_hook\",\n                    \"arg1\": \"foo\",\n                    \"arg2\": \"bar\"\n                }]\n        }\n    }\n\nOtherwise you\u0027re spending a lot of time unwrapping hooks from the dict, and there\u0027s a lot of extra syntactic sugar in the config as well.","commit_id":"a5e82dd17cc707cbf0baf7f882ae64180106b9fc"},{"author":{"_account_id":11748,"name":"Chris St. Pierre","email":"cstpierr@cisco.com","username":"stpierre"},"change_message_id":"3556d4a282f30dbe0ccf4376c32ff1878099d49e","unresolved":false,"context_lines":[{"line_number":73,"context_line":""},{"line_number":74,"context_line":"    @staticmethod"},{"line_number":75,"context_line":"    def _get_hook(hook_as_dict):"},{"line_number":76,"context_line":"        # there should be only one hook in dict"},{"line_number":77,"context_line":"        hook_name, hook_config \u003d six.next(six.iteritems(hook_as_dict))"},{"line_number":78,"context_line":"        return Hook.get(hook_name)(hook_config)"},{"line_number":79,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"3ac371cc_12083b27","line":76,"updated":"2016-08-18 16:14:01.000000000","message":"What if there isn\u0027t? Is StopIteration a reasonable error to show to the end user when that happens?","commit_id":"a5e82dd17cc707cbf0baf7f882ae64180106b9fc"},{"author":{"_account_id":11748,"name":"Chris St. Pierre","email":"cstpierr@cisco.com","username":"stpierre"},"change_message_id":"3556d4a282f30dbe0ccf4376c32ff1878099d49e","unresolved":false,"context_lines":[{"line_number":108,"context_line":"        results \u003d []"},{"line_number":109,"context_line":"        for iter_num in sorted(self.hooks.keys()):"},{"line_number":110,"context_line":"            for hook in self.hooks[iter_num]:"},{"line_number":111,"context_line":"                r \u003d hook.result()"},{"line_number":112,"context_line":"                r[\"iteration\"] \u003d iter_num"},{"line_number":113,"context_line":"                results.append(r)"},{"line_number":114,"context_line":"        return results"}],"source_content_type":"text/x-python","patch_set":7,"id":"3ac371cc_12595b8e","line":111,"updated":"2016-08-18 16:14:01.000000000","message":"Single-letter variable names are the devil. \u0027result\u0027 would be a great name for this.","commit_id":"a5e82dd17cc707cbf0baf7f882ae64180106b9fc"},{"author":{"_account_id":11748,"name":"Chris St. Pierre","email":"cstpierr@cisco.com","username":"stpierre"},"change_message_id":"3556d4a282f30dbe0ccf4376c32ff1878099d49e","unresolved":false,"context_lines":[{"line_number":254,"context_line":"            output - diagram data in task.OUTPUT_SCHEMA format"},{"line_number":255,"context_line":"        \"\"\""},{"line_number":256,"context_line":""},{"line_number":257,"context_line":"    def result(self):"},{"line_number":258,"context_line":"        \"\"\"Wait and return result of hook.\"\"\""},{"line_number":259,"context_line":"        if self.thread.ident is not None:"},{"line_number":260,"context_line":"            # hook is stil running, wait for result"}],"source_content_type":"text/x-python","patch_set":7,"id":"3ac371cc_8d5410ca","line":257,"updated":"2016-08-18 16:14:01.000000000","message":"When you write the docs for this feature, please make sure to include that multiple hooks for the same iteration are run in parallel.","commit_id":"a5e82dd17cc707cbf0baf7f882ae64180106b9fc"},{"author":{"_account_id":9545,"name":"Andriy Kurilin","email":"andr.kurilin@gmail.com","username":"akurilin"},"change_message_id":"e441411374b674033af4585a05e9f97f595a7431","unresolved":false,"context_lines":[{"line_number":70,"context_line":""},{"line_number":71,"context_line":"        self.hooks \u003d []"},{"line_number":72,"context_line":""},{"line_number":73,"context_line":"    def on_iteration(self):"},{"line_number":74,"context_line":"        \"\"\"Notify about complete iteration."},{"line_number":75,"context_line":""},{"line_number":76,"context_line":"        This method should be called to inform HookExecutor that"},{"line_number":77,"context_line":"        iteration has ended."},{"line_number":78,"context_line":"        It runs hooks configured for current iteration."},{"line_number":79,"context_line":"        \"\"\""},{"line_number":80,"context_line":"        self.iter_count +\u003d 1"},{"line_number":81,"context_line":""},{"line_number":82,"context_line":"        for trigger_obj, hook_name, hook_args in self.triggers:"},{"line_number":83,"context_line":"            if trigger_obj.on_iteration(self.iter_count):"},{"line_number":84,"context_line":"                hook \u003d Hook.get(hook_name)(hook_args)"},{"line_number":85,"context_line":"                hook.set_triggered_at({\"iteration\": self.iter_count})"},{"line_number":86,"context_line":"                self.hooks.append(hook)"},{"line_number":87,"context_line":"                hook.start()"},{"line_number":88,"context_line":""},{"line_number":89,"context_line":"    def results(self):"},{"line_number":90,"context_line":"        \"\"\"Returns list of dicts with hook results.\"\"\""}],"source_content_type":"text/x-python","patch_set":13,"id":"fa7ab95a_668066f8","line":87,"range":{"start_line":73,"start_character":4,"end_line":87,"end_character":28},"updated":"2016-08-29 11:31:37.000000000","message":"1) on_iteration means that something should be launch in parallel to iteration, but not after it.\n2) it is hardcode to only one way to launch hooks. How periodic executor will work? Separate class or just separate method?","commit_id":"2fcdfea8861656101257033ab969baa912edb47c"},{"author":{"_account_id":19011,"name":"Anton Studenov","email":"tohin1332@gmail.com","username":"tohin"},"change_message_id":"742d0dedbd65d55db01f670a8f0fa7adc701042d","unresolved":false,"context_lines":[{"line_number":70,"context_line":""},{"line_number":71,"context_line":"        self.hooks \u003d []"},{"line_number":72,"context_line":""},{"line_number":73,"context_line":"    def on_iteration(self):"},{"line_number":74,"context_line":"        \"\"\"Notify about complete iteration."},{"line_number":75,"context_line":""},{"line_number":76,"context_line":"        This method should be called to inform HookExecutor that"},{"line_number":77,"context_line":"        iteration has ended."},{"line_number":78,"context_line":"        It runs hooks configured for current iteration."},{"line_number":79,"context_line":"        \"\"\""},{"line_number":80,"context_line":"        self.iter_count +\u003d 1"},{"line_number":81,"context_line":""},{"line_number":82,"context_line":"        for trigger_obj, hook_name, hook_args in self.triggers:"},{"line_number":83,"context_line":"            if trigger_obj.on_iteration(self.iter_count):"},{"line_number":84,"context_line":"                hook \u003d Hook.get(hook_name)(hook_args)"},{"line_number":85,"context_line":"                hook.set_triggered_at({\"iteration\": self.iter_count})"},{"line_number":86,"context_line":"                self.hooks.append(hook)"},{"line_number":87,"context_line":"                hook.start()"},{"line_number":88,"context_line":""},{"line_number":89,"context_line":"    def results(self):"},{"line_number":90,"context_line":"        \"\"\"Returns list of dicts with hook results.\"\"\""}],"source_content_type":"text/x-python","patch_set":13,"id":"fa7ab95a_c9ebf776","line":87,"range":{"start_line":73,"start_character":4,"end_line":87,"end_character":28},"in_reply_to":"fa7ab95a_668066f8","updated":"2016-08-29 14:52:30.000000000","message":"1) Is it ok to rename it to \"on_iteration_complete\"?\n2) We just need a separate plugin. Periodic is just another trigger_obj that should return True for the iteration numbers that configured to run hook. see [1]\n\n[1] https://review.openstack.org/#/c/360740/4/rally/plugins/common/trigger/periodic.py","commit_id":"2fcdfea8861656101257033ab969baa912edb47c"},{"author":{"_account_id":19011,"name":"Anton Studenov","email":"tohin1332@gmail.com","username":"tohin"},"change_message_id":"7805de6439a4b9f30016fb61fe1b26262e5bb7af","unresolved":false,"context_lines":[{"line_number":70,"context_line":""},{"line_number":71,"context_line":"        self.hooks \u003d []"},{"line_number":72,"context_line":""},{"line_number":73,"context_line":"    def on_iteration(self):"},{"line_number":74,"context_line":"        \"\"\"Notify about complete iteration."},{"line_number":75,"context_line":""},{"line_number":76,"context_line":"        This method should be called to inform HookExecutor that"},{"line_number":77,"context_line":"        iteration has ended."},{"line_number":78,"context_line":"        It runs hooks configured for current iteration."},{"line_number":79,"context_line":"        \"\"\""},{"line_number":80,"context_line":"        self.iter_count +\u003d 1"},{"line_number":81,"context_line":""},{"line_number":82,"context_line":"        for trigger_obj, hook_name, hook_args in self.triggers:"},{"line_number":83,"context_line":"            if trigger_obj.on_iteration(self.iter_count):"},{"line_number":84,"context_line":"                hook \u003d Hook.get(hook_name)(hook_args)"},{"line_number":85,"context_line":"                hook.set_triggered_at({\"iteration\": self.iter_count})"},{"line_number":86,"context_line":"                self.hooks.append(hook)"},{"line_number":87,"context_line":"                hook.start()"},{"line_number":88,"context_line":""},{"line_number":89,"context_line":"    def results(self):"},{"line_number":90,"context_line":"        \"\"\"Returns list of dicts with hook results.\"\"\""}],"source_content_type":"text/x-python","patch_set":13,"id":"fa7ab95a_7669c6bd","line":87,"range":{"start_line":73,"start_character":4,"end_line":87,"end_character":28},"in_reply_to":"fa7ab95a_c9ebf776","updated":"2016-09-02 14:22:00.000000000","message":"Done","commit_id":"2fcdfea8861656101257033ab969baa912edb47c"},{"author":{"_account_id":9545,"name":"Andriy Kurilin","email":"andr.kurilin@gmail.com","username":"akurilin"},"change_message_id":"e441411374b674033af4585a05e9f97f595a7431","unresolved":false,"context_lines":[{"line_number":91,"context_line":"        return [hook.result() for hook in self.hooks]"},{"line_number":92,"context_line":""},{"line_number":93,"context_line":""},{"line_number":94,"context_line":"def configure(name, namespace\u003d\"default\"):"},{"line_number":95,"context_line":"    return plugin.configure(name\u003dname, namespace\u003dnamespace)"},{"line_number":96,"context_line":""},{"line_number":97,"context_line":""},{"line_number":98,"context_line":"@plugin.base()"}],"source_content_type":"text/x-python","patch_set":13,"id":"fa7ab95a_06b5da2f","line":95,"range":{"start_line":94,"start_character":0,"end_line":95,"end_character":59},"updated":"2016-08-29 11:31:37.000000000","message":"it is a full duplicate of plugin configure. Let\u0027s use just alias instead:\n   \n   configure \u003d plugin.configure\n\nAlso, please move it to the top of module(before methods and classes)","commit_id":"2fcdfea8861656101257033ab969baa912edb47c"},{"author":{"_account_id":19011,"name":"Anton Studenov","email":"tohin1332@gmail.com","username":"tohin"},"change_message_id":"7805de6439a4b9f30016fb61fe1b26262e5bb7af","unresolved":false,"context_lines":[{"line_number":91,"context_line":"        return [hook.result() for hook in self.hooks]"},{"line_number":92,"context_line":""},{"line_number":93,"context_line":""},{"line_number":94,"context_line":"def configure(name, namespace\u003d\"default\"):"},{"line_number":95,"context_line":"    return plugin.configure(name\u003dname, namespace\u003dnamespace)"},{"line_number":96,"context_line":""},{"line_number":97,"context_line":""},{"line_number":98,"context_line":"@plugin.base()"}],"source_content_type":"text/x-python","patch_set":13,"id":"fa7ab95a_c1f70ed1","line":95,"range":{"start_line":94,"start_character":0,"end_line":95,"end_character":59},"in_reply_to":"fa7ab95a_06b5da2f","updated":"2016-09-02 14:22:00.000000000","message":"Done","commit_id":"2fcdfea8861656101257033ab969baa912edb47c"},{"author":{"_account_id":9545,"name":"Andriy Kurilin","email":"andr.kurilin@gmail.com","username":"akurilin"},"change_message_id":"e441411374b674033af4585a05e9f97f595a7431","unresolved":false,"context_lines":[{"line_number":123,"context_line":""},{"line_number":124,"context_line":"    ACTION_UNKNOWN \u003d \"unknown\""},{"line_number":125,"context_line":""},{"line_number":126,"context_line":"    STATUS_SUCCESS \u003d \"success\""},{"line_number":127,"context_line":"    STATUS_FAILED \u003d \"failed\""},{"line_number":128,"context_line":"    STATUS_WRONG_FORMAT \u003d \"wrong format\""},{"line_number":129,"context_line":"    STATUS_ABORTED \u003d \"aborted\""},{"line_number":130,"context_line":""},{"line_number":131,"context_line":"    @staticmethod"},{"line_number":132,"context_line":"    def validate(config):"}],"source_content_type":"text/x-python","patch_set":13,"id":"fa7ab95a_2601fe05","line":129,"range":{"start_line":126,"start_character":4,"end_line":129,"end_character":30},"updated":"2016-08-29 11:31:37.000000000","message":"unified way to store constant values https://github.com/openstack/rally/blob/master/rally/consts.py#L51","commit_id":"2fcdfea8861656101257033ab969baa912edb47c"},{"author":{"_account_id":19011,"name":"Anton Studenov","email":"tohin1332@gmail.com","username":"tohin"},"change_message_id":"7805de6439a4b9f30016fb61fe1b26262e5bb7af","unresolved":false,"context_lines":[{"line_number":123,"context_line":""},{"line_number":124,"context_line":"    ACTION_UNKNOWN \u003d \"unknown\""},{"line_number":125,"context_line":""},{"line_number":126,"context_line":"    STATUS_SUCCESS \u003d \"success\""},{"line_number":127,"context_line":"    STATUS_FAILED \u003d \"failed\""},{"line_number":128,"context_line":"    STATUS_WRONG_FORMAT \u003d \"wrong format\""},{"line_number":129,"context_line":"    STATUS_ABORTED \u003d \"aborted\""},{"line_number":130,"context_line":""},{"line_number":131,"context_line":"    @staticmethod"},{"line_number":132,"context_line":"    def validate(config):"}],"source_content_type":"text/x-python","patch_set":13,"id":"fa7ab95a_01fe56ad","line":129,"range":{"start_line":126,"start_character":4,"end_line":129,"end_character":30},"in_reply_to":"fa7ab95a_2601fe05","updated":"2016-09-02 14:22:00.000000000","message":"Done","commit_id":"2fcdfea8861656101257033ab969baa912edb47c"},{"author":{"_account_id":9545,"name":"Andriy Kurilin","email":"andr.kurilin@gmail.com","username":"akurilin"},"change_message_id":"e441411374b674033af4585a05e9f97f595a7431","unresolved":false,"context_lines":[{"line_number":130,"context_line":""},{"line_number":131,"context_line":"    @staticmethod"},{"line_number":132,"context_line":"    def validate(config):"},{"line_number":133,"context_line":"        hook_schemas \u003d ["},{"line_number":134,"context_line":"            {"},{"line_number":135,"context_line":"                \"properties\": {"},{"line_number":136,"context_line":"                    \"name\": {\"enum\": [hook.get_name()]},"},{"line_number":137,"context_line":"                    \"args\": hook.CONFIG_SCHEMA,"},{"line_number":138,"context_line":"                    \"trigger\": {\"type\": \"object\"},"},{"line_number":139,"context_line":"                },"},{"line_number":140,"context_line":"                \"required\": [\"name\", \"args\", \"trigger\"],"},{"line_number":141,"context_line":"                \"additionalProperties\": False,"},{"line_number":142,"context_line":"            }"},{"line_number":143,"context_line":"            for hook in Hook.get_all()"},{"line_number":144,"context_line":"        ]"},{"line_number":145,"context_line":""},{"line_number":146,"context_line":"        schema \u003d {"},{"line_number":147,"context_line":"            \"$schema\": consts.JSON_SCHEMA,"}],"source_content_type":"text/x-python","patch_set":13,"id":"fa7ab95a_5b425f69","line":144,"range":{"start_line":133,"start_character":8,"end_line":144,"end_character":9},"updated":"2016-08-29 11:31:37.000000000","message":"if I have several hooks at my task, this code will create list of hook_schemas N times. Why we need to construct them?\nImo, it would be much better to do something like:\n\n    if not \"name\" in config:\n        raise Exception(\"You are doing something wrong...\")\n    hook_cls \u003d Hook.get(config[\"name\"])\n    schema \u003d {}\n    json.validate()","commit_id":"2fcdfea8861656101257033ab969baa912edb47c"},{"author":{"_account_id":19011,"name":"Anton Studenov","email":"tohin1332@gmail.com","username":"tohin"},"change_message_id":"7805de6439a4b9f30016fb61fe1b26262e5bb7af","unresolved":false,"context_lines":[{"line_number":130,"context_line":""},{"line_number":131,"context_line":"    @staticmethod"},{"line_number":132,"context_line":"    def validate(config):"},{"line_number":133,"context_line":"        hook_schemas \u003d ["},{"line_number":134,"context_line":"            {"},{"line_number":135,"context_line":"                \"properties\": {"},{"line_number":136,"context_line":"                    \"name\": {\"enum\": [hook.get_name()]},"},{"line_number":137,"context_line":"                    \"args\": hook.CONFIG_SCHEMA,"},{"line_number":138,"context_line":"                    \"trigger\": {\"type\": \"object\"},"},{"line_number":139,"context_line":"                },"},{"line_number":140,"context_line":"                \"required\": [\"name\", \"args\", \"trigger\"],"},{"line_number":141,"context_line":"                \"additionalProperties\": False,"},{"line_number":142,"context_line":"            }"},{"line_number":143,"context_line":"            for hook in Hook.get_all()"},{"line_number":144,"context_line":"        ]"},{"line_number":145,"context_line":""},{"line_number":146,"context_line":"        schema \u003d {"},{"line_number":147,"context_line":"            \"$schema\": consts.JSON_SCHEMA,"}],"source_content_type":"text/x-python","patch_set":13,"id":"fa7ab95a_6125625a","line":144,"range":{"start_line":133,"start_character":8,"end_line":144,"end_character":9},"in_reply_to":"fa7ab95a_5b425f69","updated":"2016-09-02 14:22:00.000000000","message":"Done","commit_id":"2fcdfea8861656101257033ab969baa912edb47c"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"5b1d5763f9ec9d9e5afded6db2dfb8437c552007","unresolved":false,"context_lines":[{"line_number":61,"context_line":"        It runs hooks configured for current iteration."},{"line_number":62,"context_line":"        \"\"\""},{"line_number":63,"context_line":"        for trigger_obj, hook_name, hook_args in self.triggers:"},{"line_number":64,"context_line":"            if trigger_obj.is_runnable("},{"line_number":65,"context_line":"                    event_type\u003d\"iteration\", value\u003diteration):"},{"line_number":66,"context_line":"                hook \u003d Hook.get(hook_name)(hook_args)"},{"line_number":67,"context_line":"                hook.set_triggered_at({\"iteration\": iteration})"}],"source_content_type":"text/x-python","patch_set":14,"id":"9a89bdaa_fc3b49cf","line":64,"updated":"2016-09-06 12:31:49.000000000","message":"is_runnable(event_type\u003d\"iteration\", ...) is called for all triggers, but there is no guarantee that all these triggers have type \"iteration\"","commit_id":"4dfb469afbff0ae36e3dff12ef4c346921300f68"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"93671e1b9816da8555cae7e3e512be29938fa654","unresolved":false,"context_lines":[{"line_number":61,"context_line":"        It runs hooks configured for current iteration."},{"line_number":62,"context_line":"        \"\"\""},{"line_number":63,"context_line":"        for trigger_obj, hook_name, hook_args in self.triggers:"},{"line_number":64,"context_line":"            if trigger_obj.is_runnable("},{"line_number":65,"context_line":"                    event_type\u003d\"iteration\", value\u003diteration):"},{"line_number":66,"context_line":"                hook \u003d Hook.get(hook_name)(hook_args)"},{"line_number":67,"context_line":"                hook.set_triggered_at({\"iteration\": iteration})"}],"source_content_type":"text/x-python","patch_set":14,"id":"9a89bdaa_621dd4bc","line":64,"in_reply_to":"9a89bdaa_42a1b0a2","updated":"2016-09-06 13:13:39.000000000","message":"This is very problematic case, I think we have to discuss how to avoid redundant actions","commit_id":"4dfb469afbff0ae36e3dff12ef4c346921300f68"},{"author":{"_account_id":19011,"name":"Anton Studenov","email":"tohin1332@gmail.com","username":"tohin"},"change_message_id":"fcdcaba308c64a797ffd8788eb46f4c65416efac","unresolved":false,"context_lines":[{"line_number":61,"context_line":"        It runs hooks configured for current iteration."},{"line_number":62,"context_line":"        \"\"\""},{"line_number":63,"context_line":"        for trigger_obj, hook_name, hook_args in self.triggers:"},{"line_number":64,"context_line":"            if trigger_obj.is_runnable("},{"line_number":65,"context_line":"                    event_type\u003d\"iteration\", value\u003diteration):"},{"line_number":66,"context_line":"                hook \u003d Hook.get(hook_name)(hook_args)"},{"line_number":67,"context_line":"                hook.set_triggered_at({\"iteration\": iteration})"}],"source_content_type":"text/x-python","patch_set":14,"id":"9a89bdaa_6b004802","line":64,"in_reply_to":"9a89bdaa_621dd4bc","updated":"2016-09-06 14:56:58.000000000","message":"By the way, trigger\u0027s code should be very simple. So it is not so big overhead.","commit_id":"4dfb469afbff0ae36e3dff12ef4c346921300f68"},{"author":{"_account_id":19011,"name":"Anton Studenov","email":"tohin1332@gmail.com","username":"tohin"},"change_message_id":"e9e53ca69d804f5435a66c5b67263829eff7da59","unresolved":false,"context_lines":[{"line_number":61,"context_line":"        It runs hooks configured for current iteration."},{"line_number":62,"context_line":"        \"\"\""},{"line_number":63,"context_line":"        for trigger_obj, hook_name, hook_args in self.triggers:"},{"line_number":64,"context_line":"            if trigger_obj.is_runnable("},{"line_number":65,"context_line":"                    event_type\u003d\"iteration\", value\u003diteration):"},{"line_number":66,"context_line":"                hook \u003d Hook.get(hook_name)(hook_args)"},{"line_number":67,"context_line":"                hook.set_triggered_at({\"iteration\": iteration})"}],"source_content_type":"text/x-python","patch_set":14,"id":"9a89bdaa_e7b816e8","line":64,"in_reply_to":"9a89bdaa_67b6c63e","updated":"2016-09-06 12:53:51.000000000","message":"I think a new timer thread should added to run\nis_runnable(event_type\u003d\"seconds\", value\u003dseconds_since_start)\nevery second for all triggers. \nI think we can add it in separate patch in future.","commit_id":"4dfb469afbff0ae36e3dff12ef4c346921300f68"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"f3ddc12b46ec6fe2a5865eafd6bc2dd9c7fb494b","unresolved":false,"context_lines":[{"line_number":61,"context_line":"        It runs hooks configured for current iteration."},{"line_number":62,"context_line":"        \"\"\""},{"line_number":63,"context_line":"        for trigger_obj, hook_name, hook_args in self.triggers:"},{"line_number":64,"context_line":"            if trigger_obj.is_runnable("},{"line_number":65,"context_line":"                    event_type\u003d\"iteration\", value\u003diteration):"},{"line_number":66,"context_line":"                hook \u003d Hook.get(hook_name)(hook_args)"},{"line_number":67,"context_line":"                hook.set_triggered_at({\"iteration\": iteration})"}],"source_content_type":"text/x-python","patch_set":14,"id":"9a89bdaa_cbf794f3","line":64,"in_reply_to":"9a89bdaa_6b004802","updated":"2016-09-06 14:59:52.000000000","message":"I\u0027m not agree that this overhead is reasonable","commit_id":"4dfb469afbff0ae36e3dff12ef4c346921300f68"},{"author":{"_account_id":19011,"name":"Anton Studenov","email":"tohin1332@gmail.com","username":"tohin"},"change_message_id":"30bedce78599ff78f5d4380fbe7561dfa8dfc83b","unresolved":false,"context_lines":[{"line_number":61,"context_line":"        It runs hooks configured for current iteration."},{"line_number":62,"context_line":"        \"\"\""},{"line_number":63,"context_line":"        for trigger_obj, hook_name, hook_args in self.triggers:"},{"line_number":64,"context_line":"            if trigger_obj.is_runnable("},{"line_number":65,"context_line":"                    event_type\u003d\"iteration\", value\u003diteration):"},{"line_number":66,"context_line":"                hook \u003d Hook.get(hook_name)(hook_args)"},{"line_number":67,"context_line":"                hook.set_triggered_at({\"iteration\": iteration})"}],"source_content_type":"text/x-python","patch_set":14,"id":"9a89bdaa_42a1b0a2","line":64,"in_reply_to":"9a89bdaa_a799ae21","updated":"2016-09-06 13:10:37.000000000","message":"yes, they both will check the same list of triggers. otherwise we need to split them into two lists and add additional logic to check their types.","commit_id":"4dfb469afbff0ae36e3dff12ef4c346921300f68"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"52330fb34db6cb1f58e9253a4f9fe708f52de970","unresolved":false,"context_lines":[{"line_number":61,"context_line":"        It runs hooks configured for current iteration."},{"line_number":62,"context_line":"        \"\"\""},{"line_number":63,"context_line":"        for trigger_obj, hook_name, hook_args in self.triggers:"},{"line_number":64,"context_line":"            if trigger_obj.is_runnable("},{"line_number":65,"context_line":"                    event_type\u003d\"iteration\", value\u003diteration):"},{"line_number":66,"context_line":"                hook \u003d Hook.get(hook_name)(hook_args)"},{"line_number":67,"context_line":"                hook.set_triggered_at({\"iteration\": iteration})"}],"source_content_type":"text/x-python","patch_set":14,"id":"9a89bdaa_67b6c63e","line":64,"in_reply_to":"9a89bdaa_dc5e8575","updated":"2016-09-06 12:48:34.000000000","message":"Will triggers of type \"seconds\" started on per-iteration basis? (I mean check is_runnable() for all of them right here)","commit_id":"4dfb469afbff0ae36e3dff12ef4c346921300f68"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"df1757d2abfb8206e47c69f0708c66e623810551","unresolved":false,"context_lines":[{"line_number":61,"context_line":"        It runs hooks configured for current iteration."},{"line_number":62,"context_line":"        \"\"\""},{"line_number":63,"context_line":"        for trigger_obj, hook_name, hook_args in self.triggers:"},{"line_number":64,"context_line":"            if trigger_obj.is_runnable("},{"line_number":65,"context_line":"                    event_type\u003d\"iteration\", value\u003diteration):"},{"line_number":66,"context_line":"                hook \u003d Hook.get(hook_name)(hook_args)"},{"line_number":67,"context_line":"                hook.set_triggered_at({\"iteration\": iteration})"}],"source_content_type":"text/x-python","patch_set":14,"id":"9a89bdaa_a799ae21","line":64,"in_reply_to":"9a89bdaa_e7b816e8","updated":"2016-09-06 13:00:47.000000000","message":"Is it possible that on_iteration() will run each iteration for \"seconds\" triggers (redundant action)?","commit_id":"4dfb469afbff0ae36e3dff12ef4c346921300f68"},{"author":{"_account_id":19011,"name":"Anton Studenov","email":"tohin1332@gmail.com","username":"tohin"},"change_message_id":"7f47a39401aa2f0f3e313abd65b1716a429f73cc","unresolved":false,"context_lines":[{"line_number":61,"context_line":"        It runs hooks configured for current iteration."},{"line_number":62,"context_line":"        \"\"\""},{"line_number":63,"context_line":"        for trigger_obj, hook_name, hook_args in self.triggers:"},{"line_number":64,"context_line":"            if trigger_obj.is_runnable("},{"line_number":65,"context_line":"                    event_type\u003d\"iteration\", value\u003diteration):"},{"line_number":66,"context_line":"                hook \u003d Hook.get(hook_name)(hook_args)"},{"line_number":67,"context_line":"                hook.set_triggered_at({\"iteration\": iteration})"}],"source_content_type":"text/x-python","patch_set":14,"id":"9a89bdaa_dc5e8575","line":64,"in_reply_to":"9a89bdaa_fc3b49cf","updated":"2016-09-06 12:43:26.000000000","message":"Triggers should decide which type of events they support.","commit_id":"4dfb469afbff0ae36e3dff12ef4c346921300f68"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"5b1d5763f9ec9d9e5afded6db2dfb8437c552007","unresolved":false,"context_lines":[{"line_number":78,"context_line":"class Hook(plugin.Plugin):"},{"line_number":79,"context_line":"    \"\"\"Factory for hook classes.\"\"\""},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"    RESULT_SCHEMA \u003d {"},{"line_number":82,"context_line":"        \"type\": \"object\","},{"line_number":83,"context_line":"        \"$schema\": consts.JSON_SCHEMA,"},{"line_number":84,"context_line":"        \"properties\": {"}],"source_content_type":"text/x-python","patch_set":14,"id":"9a89bdaa_939f90b3","line":81,"updated":"2016-09-06 12:31:49.000000000","message":"Can this be replaced with schema from common.objects.task ?","commit_id":"4dfb469afbff0ae36e3dff12ef4c346921300f68"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"5b1d5763f9ec9d9e5afded6db2dfb8437c552007","unresolved":false,"context_lines":[{"line_number":103,"context_line":""},{"line_number":104,"context_line":"    ACTION_UNKNOWN \u003d \"unknown\""},{"line_number":105,"context_line":""},{"line_number":106,"context_line":"    @staticmethod"},{"line_number":107,"context_line":"    def validate(config):"},{"line_number":108,"context_line":"        hook_schema \u003d Hook.get(config[\"name\"]).CONFIG_SCHEMA"},{"line_number":109,"context_line":"        jsonschema.validate(config[\"args\"], hook_schema)"}],"source_content_type":"text/x-python","patch_set":14,"id":"9a89bdaa_f3cb7c51","line":106,"updated":"2016-09-06 12:31:49.000000000","message":"@classmethod","commit_id":"4dfb469afbff0ae36e3dff12ef4c346921300f68"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"5b1d5763f9ec9d9e5afded6db2dfb8437c552007","unresolved":false,"context_lines":[{"line_number":105,"context_line":""},{"line_number":106,"context_line":"    @staticmethod"},{"line_number":107,"context_line":"    def validate(config):"},{"line_number":108,"context_line":"        hook_schema \u003d Hook.get(config[\"name\"]).CONFIG_SCHEMA"},{"line_number":109,"context_line":"        jsonschema.validate(config[\"args\"], hook_schema)"},{"line_number":110,"context_line":""},{"line_number":111,"context_line":"        trigger.Trigger.validate(config[\"trigger\"])"}],"source_content_type":"text/x-python","patch_set":14,"id":"9a89bdaa_d3ebd8ae","line":108,"updated":"2016-09-06 12:31:49.000000000","message":"schema \u003d cls.get(config[\"name\"]).CONFIG_SCHEMA","commit_id":"4dfb469afbff0ae36e3dff12ef4c346921300f68"}],"rally/task/trigger.py":[{"author":{"_account_id":7428,"name":"Yaroslav Lobankov","email":"lobankovyv@gmail.com","username":"ylobankov"},"change_message_id":"4015da3a4b792e8c340f2198f8ca8d2e1cc56dad","unresolved":false,"context_lines":[{"line_number":18,"context_line":"import jsonschema"},{"line_number":19,"context_line":"import six"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"# from rally.common.i18n import _"},{"line_number":22,"context_line":"from rally.common import logging"},{"line_number":23,"context_line":"# from rally.common import objects"},{"line_number":24,"context_line":"from rally.common.plugin import plugin"}],"source_content_type":"text/x-python","patch_set":11,"id":"fa7ab95a_a1b0fcf5","line":21,"updated":"2016-08-26 10:09:05.000000000","message":"We should either remove or uncomment it.","commit_id":"5ce64426998dc9b62b2ed171f4d520a763b1c27a"},{"author":{"_account_id":19011,"name":"Anton Studenov","email":"tohin1332@gmail.com","username":"tohin"},"change_message_id":"0c6a4b0dd4b29e2411bf9362120c4c8f1df8b361","unresolved":false,"context_lines":[{"line_number":18,"context_line":"import jsonschema"},{"line_number":19,"context_line":"import six"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"# from rally.common.i18n import _"},{"line_number":22,"context_line":"from rally.common import logging"},{"line_number":23,"context_line":"# from rally.common import objects"},{"line_number":24,"context_line":"from rally.common.plugin import plugin"}],"source_content_type":"text/x-python","patch_set":11,"id":"fa7ab95a_81b8ffe6","line":21,"in_reply_to":"fa7ab95a_a1b0fcf5","updated":"2016-08-29 08:45:11.000000000","message":"Done","commit_id":"5ce64426998dc9b62b2ed171f4d520a763b1c27a"},{"author":{"_account_id":7428,"name":"Yaroslav Lobankov","email":"lobankovyv@gmail.com","username":"ylobankov"},"change_message_id":"4015da3a4b792e8c340f2198f8ca8d2e1cc56dad","unresolved":false,"context_lines":[{"line_number":20,"context_line":""},{"line_number":21,"context_line":"# from rally.common.i18n import _"},{"line_number":22,"context_line":"from rally.common import logging"},{"line_number":23,"context_line":"# from rally.common import objects"},{"line_number":24,"context_line":"from rally.common.plugin import plugin"},{"line_number":25,"context_line":"from rally import consts"},{"line_number":26,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"fa7ab95a_818218ff","line":23,"updated":"2016-08-26 10:09:05.000000000","message":"ditto","commit_id":"5ce64426998dc9b62b2ed171f4d520a763b1c27a"},{"author":{"_account_id":19011,"name":"Anton Studenov","email":"tohin1332@gmail.com","username":"tohin"},"change_message_id":"0c6a4b0dd4b29e2411bf9362120c4c8f1df8b361","unresolved":false,"context_lines":[{"line_number":20,"context_line":""},{"line_number":21,"context_line":"# from rally.common.i18n import _"},{"line_number":22,"context_line":"from rally.common import logging"},{"line_number":23,"context_line":"# from rally.common import objects"},{"line_number":24,"context_line":"from rally.common.plugin import plugin"},{"line_number":25,"context_line":"from rally import consts"},{"line_number":26,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"fa7ab95a_e1c9cb79","line":23,"in_reply_to":"fa7ab95a_818218ff","updated":"2016-08-29 08:45:11.000000000","message":"Done","commit_id":"5ce64426998dc9b62b2ed171f4d520a763b1c27a"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"5b1d5763f9ec9d9e5afded6db2dfb8437c552007","unresolved":false,"context_lines":[{"line_number":29,"context_line":"class Trigger(plugin.Plugin):"},{"line_number":30,"context_line":"    \"\"\"Factory for trigger classes.\"\"\""},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"    @staticmethod"},{"line_number":33,"context_line":"    def validate(config):"},{"line_number":34,"context_line":"        trigger_schema \u003d Trigger.get(config[\"name\"]).CONFIG_SCHEMA"},{"line_number":35,"context_line":"        jsonschema.validate(config[\"args\"], trigger_schema)"}],"source_content_type":"text/x-python","patch_set":14,"id":"9a89bdaa_969f7eb3","line":32,"updated":"2016-09-06 12:31:49.000000000","message":"@classmethod","commit_id":"4dfb469afbff0ae36e3dff12ef4c346921300f68"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"5b1d5763f9ec9d9e5afded6db2dfb8437c552007","unresolved":false,"context_lines":[{"line_number":31,"context_line":""},{"line_number":32,"context_line":"    @staticmethod"},{"line_number":33,"context_line":"    def validate(config):"},{"line_number":34,"context_line":"        trigger_schema \u003d Trigger.get(config[\"name\"]).CONFIG_SCHEMA"},{"line_number":35,"context_line":"        jsonschema.validate(config[\"args\"], trigger_schema)"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"    def __init__(self, config):"}],"source_content_type":"text/x-python","patch_set":14,"id":"9a89bdaa_36bb1229","line":34,"updated":"2016-09-06 12:31:49.000000000","message":"schema \u003d cls.get(config[\"name\"]).CONFIG_SCHEMA","commit_id":"4dfb469afbff0ae36e3dff12ef4c346921300f68"},{"author":{"_account_id":12395,"name":"Roman Vasylets","email":"pomeo92@gmail.com","username":"rvasilets"},"change_message_id":"1a909d4da28781934ce3cbf64615f7152cc5c861","unresolved":false,"context_lines":[{"line_number":20,"context_line":""},{"line_number":21,"context_line":"from rally.common.plugin import plugin"},{"line_number":22,"context_line":""},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"configure \u003d plugin.configure"},{"line_number":25,"context_line":""},{"line_number":26,"context_line":""}],"source_content_type":"text/x-python","patch_set":19,"id":"7a8ec9b2_4be4663a","line":23,"updated":"2016-09-15 11:49:22.000000000","message":"Isn\u0027t it a redundant line?","commit_id":"8b385c68cc716c9aa3cc4185c73d6cd1b5593494"},{"author":{"_account_id":19011,"name":"Anton Studenov","email":"tohin1332@gmail.com","username":"tohin"},"change_message_id":"f80e3b4baace0ec4b0f031955dfbd4c8a25f20aa","unresolved":false,"context_lines":[{"line_number":20,"context_line":""},{"line_number":21,"context_line":"from rally.common.plugin import plugin"},{"line_number":22,"context_line":""},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"configure \u003d plugin.configure"},{"line_number":25,"context_line":""},{"line_number":26,"context_line":""}],"source_content_type":"text/x-python","patch_set":19,"id":"7a8ec9b2_52913df0","line":23,"in_reply_to":"7a8ec9b2_4be4663a","updated":"2016-09-16 11:16:31.000000000","message":"Done","commit_id":"8b385c68cc716c9aa3cc4185c73d6cd1b5593494"},{"author":{"_account_id":9545,"name":"Andriy Kurilin","email":"andr.kurilin@gmail.com","username":"akurilin"},"change_message_id":"168e97c6c8818517c8131a34a22626389f6a4373","unresolved":false,"context_lines":[{"line_number":38,"context_line":"        self.config \u003d config"},{"line_number":39,"context_line":""},{"line_number":40,"context_line":"    @abc.abstractmethod"},{"line_number":41,"context_line":"    def get_supported_event_type(self):"},{"line_number":42,"context_line":"        \"\"\"Returns supported event type.\"\"\""},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"    @abc.abstractmethod"}],"source_content_type":"text/x-python","patch_set":19,"id":"7a8ec9b2_812f35f5","line":41,"range":{"start_line":41,"start_character":8,"end_line":41,"end_character":33},"updated":"2016-09-15 09:53:11.000000000","message":"I dislike word support\" here. it is better to rephrase it somehow. maybe configured? listened?","commit_id":"8b385c68cc716c9aa3cc4185c73d6cd1b5593494"},{"author":{"_account_id":19011,"name":"Anton Studenov","email":"tohin1332@gmail.com","username":"tohin"},"change_message_id":"f80e3b4baace0ec4b0f031955dfbd4c8a25f20aa","unresolved":false,"context_lines":[{"line_number":38,"context_line":"        self.config \u003d config"},{"line_number":39,"context_line":""},{"line_number":40,"context_line":"    @abc.abstractmethod"},{"line_number":41,"context_line":"    def get_supported_event_type(self):"},{"line_number":42,"context_line":"        \"\"\"Returns supported event type.\"\"\""},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"    @abc.abstractmethod"}],"source_content_type":"text/x-python","patch_set":19,"id":"7a8ec9b2_b2c281e7","line":41,"range":{"start_line":41,"start_character":8,"end_line":41,"end_character":33},"in_reply_to":"7a8ec9b2_812f35f5","updated":"2016-09-16 11:16:31.000000000","message":"Done","commit_id":"8b385c68cc716c9aa3cc4185c73d6cd1b5593494"}],"tests/functional/test_cli_task.py":[{"author":{"_account_id":11748,"name":"Chris St. Pierre","email":"cstpierr@cisco.com","username":"stpierre"},"change_message_id":"3556d4a282f30dbe0ccf4376c32ff1878099d49e","unresolved":false,"context_lines":[{"line_number":1065,"context_line":"            \"finished_at\": mock.ANY,"},{"line_number":1066,"context_line":"            \"hook\": \"sys_call\","},{"line_number":1067,"context_line":"            \"iteration\": iteration,"},{"line_number":1068,"context_line":"            \"started_at\": mock.ANY,"},{"line_number":1069,"context_line":"            \"status\": \"success\""},{"line_number":1070,"context_line":"        }"},{"line_number":1071,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"3ac371cc_ad658c45","line":1068,"updated":"2016-08-18 16:14:01.000000000","message":"It would be nice to ensure that finished_at and started_at are at least timestamps.","commit_id":"a5e82dd17cc707cbf0baf7f882ae64180106b9fc"},{"author":{"_account_id":19011,"name":"Anton Studenov","email":"tohin1332@gmail.com","username":"tohin"},"change_message_id":"43a9d44afc2ebc7469b8bfca456f25f93b0d06c3","unresolved":false,"context_lines":[{"line_number":1065,"context_line":"            \"finished_at\": mock.ANY,"},{"line_number":1066,"context_line":"            \"hook\": \"sys_call\","},{"line_number":1067,"context_line":"            \"iteration\": iteration,"},{"line_number":1068,"context_line":"            \"started_at\": mock.ANY,"},{"line_number":1069,"context_line":"            \"status\": \"success\""},{"line_number":1070,"context_line":"        }"},{"line_number":1071,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"1ac06dbe_a8b93c17","line":1068,"in_reply_to":"3ac371cc_ad658c45","updated":"2016-08-23 14:15:28.000000000","message":"Done","commit_id":"a5e82dd17cc707cbf0baf7f882ae64180106b9fc"},{"author":{"_account_id":11748,"name":"Chris St. Pierre","email":"cstpierr@cisco.com","username":"stpierre"},"change_message_id":"3556d4a282f30dbe0ccf4376c32ff1878099d49e","unresolved":false,"context_lines":[{"line_number":1073,"context_line":"        tmp_file \u003d utils.TempFile(\"hook_test\")"},{"line_number":1074,"context_line":"        rally \u003d utils.Rally()"},{"line_number":1075,"context_line":"        cfg \u003d self._get_sample_task_config("},{"line_number":1076,"context_line":"            cmd\u003d\"/bin/touch {}\".format(tmp_file.filename),"},{"line_number":1077,"context_line":"            action_name\u003d\"touch\")"},{"line_number":1078,"context_line":"        config \u003d utils.TaskConfig(cfg)"},{"line_number":1079,"context_line":"        rally(\"task start --task %s\" % config.filename)"}],"source_content_type":"text/x-python","patch_set":7,"id":"3ac371cc_2dcfdc56","line":1076,"updated":"2016-08-18 16:14:01.000000000","message":"The tempfile dance you do here is very clever, but it\u0027s deeply non-obvious, and it makes it unnecessarily difficult to verify that the hook has been called. (You also depend on /bin/touch existing, which, while extremely likely, is an unnecessary dependency.) I\u0027d suggest instead mocking out the hook\u0027s run() method and checking that it\u0027s been run.","commit_id":"a5e82dd17cc707cbf0baf7f882ae64180106b9fc"}],"tests/unit/plugins/common/hook/test_sys_call.py":[{"author":{"_account_id":11748,"name":"Chris St. Pierre","email":"cstpierr@cisco.com","username":"stpierre"},"change_message_id":"3556d4a282f30dbe0ccf4376c32ff1878099d49e","unresolved":false,"context_lines":[{"line_number":37,"context_line":"            }"},{"line_number":38,"context_line":"        )"},{"line_number":39,"context_line":""},{"line_number":40,"context_line":"    @mock.patch(\"rally.plugins.common.hook.sys_call.os\")"},{"line_number":41,"context_line":"    def test_run(self, mock_os):"},{"line_number":42,"context_line":"        mock_os.system.return_value \u003d 0"},{"line_number":43,"context_line":"        hook \u003d sys_call.SysCallHook("}],"source_content_type":"text/x-python","patch_set":7,"id":"3ac371cc_adc10ce6","line":40,"updated":"2016-08-18 16:14:01.000000000","message":"1. Don\u0027t mock the entire os module, just mock os.system\n2. Don\u0027t mock the module as imported, mock it as it exists in the stdlib. That\u0027s one of the strengths of only importing modules, not symbols from modules -- mocking Just Works. (And this won\u0027t have to be changed if the sys_call module ever moves.)\n\nE.g.:\n\n    @mock.patch(\"os.system\")\n    def test_run(self, mock_os_system):\n        ...","commit_id":"a5e82dd17cc707cbf0baf7f882ae64180106b9fc"},{"author":{"_account_id":19011,"name":"Anton Studenov","email":"tohin1332@gmail.com","username":"tohin"},"change_message_id":"43a9d44afc2ebc7469b8bfca456f25f93b0d06c3","unresolved":false,"context_lines":[{"line_number":37,"context_line":"            }"},{"line_number":38,"context_line":"        )"},{"line_number":39,"context_line":""},{"line_number":40,"context_line":"    @mock.patch(\"rally.plugins.common.hook.sys_call.os\")"},{"line_number":41,"context_line":"    def test_run(self, mock_os):"},{"line_number":42,"context_line":"        mock_os.system.return_value \u003d 0"},{"line_number":43,"context_line":"        hook \u003d sys_call.SysCallHook("}],"source_content_type":"text/x-python","patch_set":7,"id":"1ac06dbe_e83214a6","line":40,"in_reply_to":"3ac371cc_adc10ce6","updated":"2016-08-23 14:15:28.000000000","message":"Done","commit_id":"a5e82dd17cc707cbf0baf7f882ae64180106b9fc"}],"tests/unit/task/test_engine.py":[{"author":{"_account_id":11748,"name":"Chris St. Pierre","email":"cstpierr@cisco.com","username":"stpierre"},"change_message_id":"3556d4a282f30dbe0ccf4376c32ff1878099d49e","unresolved":false,"context_lines":[{"line_number":491,"context_line":"            mock_task_get_status, mock_hook_executer):"},{"line_number":492,"context_line":"        mock_sla_instance \u003d mock.MagicMock()"},{"line_number":493,"context_line":"        mock_sla_checker.return_value \u003d mock_sla_instance"},{"line_number":494,"context_line":"        mock_hook_executer_instane \u003d mock_hook_executer.return_value"},{"line_number":495,"context_line":"        mock_task_get_status.return_value \u003d consts.TaskStatus.RUNNING"},{"line_number":496,"context_line":"        key \u003d {\"kw\": {\"fake\": 2}, \"name\": \"fake\", \"pos\": 0}"},{"line_number":497,"context_line":"        task \u003d mock.MagicMock()"}],"source_content_type":"text/x-python","patch_set":7,"id":"3ac371cc_0d43006d","line":494,"updated":"2016-08-18 16:14:01.000000000","message":"Spelling (here and elsewhere): instance","commit_id":"a5e82dd17cc707cbf0baf7f882ae64180106b9fc"},{"author":{"_account_id":19011,"name":"Anton Studenov","email":"tohin1332@gmail.com","username":"tohin"},"change_message_id":"43a9d44afc2ebc7469b8bfca456f25f93b0d06c3","unresolved":false,"context_lines":[{"line_number":491,"context_line":"            mock_task_get_status, mock_hook_executer):"},{"line_number":492,"context_line":"        mock_sla_instance \u003d mock.MagicMock()"},{"line_number":493,"context_line":"        mock_sla_checker.return_value \u003d mock_sla_instance"},{"line_number":494,"context_line":"        mock_hook_executer_instane \u003d mock_hook_executer.return_value"},{"line_number":495,"context_line":"        mock_task_get_status.return_value \u003d consts.TaskStatus.RUNNING"},{"line_number":496,"context_line":"        key \u003d {\"kw\": {\"fake\": 2}, \"name\": \"fake\", \"pos\": 0}"},{"line_number":497,"context_line":"        task \u003d mock.MagicMock()"}],"source_content_type":"text/x-python","patch_set":7,"id":"1ac06dbe_681f4408","line":494,"in_reply_to":"3ac371cc_0d43006d","updated":"2016-08-23 14:15:28.000000000","message":"Done","commit_id":"a5e82dd17cc707cbf0baf7f882ae64180106b9fc"}]}
