)]}'
{"rally/benchmark/processing/charts.py":[{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"a4baa00276e9939885c59044fa1453fbd5394b71","unresolved":false,"context_lines":[{"line_number":16,"context_line":"import math"},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"from rally import exceptions"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"def average(values):"},{"line_number":22,"context_line":"    \"\"\"Find the simple average of a list of values."}],"source_content_type":"text/x-python","patch_set":1,"id":"ba7be1f8_1774ec9a","line":19,"updated":"2015-03-01 22:14:26.000000000","message":"You should create abstract class\n\n   class AbstractDiagram(object): \n\n with 2 abstract methods render() and add_value() otherwise code won\u0027t be self checked and so on.","commit_id":"8c47e8875b0b2237a950f1cf0ae33f61cba82952"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"60e401b1994e12b0593deaf3fe61962dcc9eadf0","unresolved":false,"context_lines":[{"line_number":16,"context_line":"import math"},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"from rally import exceptions"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"def average(values):"},{"line_number":22,"context_line":"    \"\"\"Find the simple average of a list of values."}],"source_content_type":"text/x-python","patch_set":1,"id":"9a80dd14_0368f41b","line":19,"in_reply_to":"ba7be1f8_1774ec9a","updated":"2015-03-06 17:44:33.000000000","message":"Done","commit_id":"8c47e8875b0b2237a950f1cf0ae33f61cba82952"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"a4baa00276e9939885c59044fa1453fbd5394b71","unresolved":false,"context_lines":[{"line_number":21,"context_line":"def average(values):"},{"line_number":22,"context_line":"    \"\"\"Find the simple average of a list of values."},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"    :parameter values: non-empty list of numbers"},{"line_number":25,"context_line":"    :returns: float"},{"line_number":26,"context_line":"    \"\"\""},{"line_number":27,"context_line":"    if values:"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba7be1f8_3cf1d76a","line":24,"updated":"2015-03-01 22:14:26.000000000","message":"In whole project, except this module we are using: \n\n  :param values:\n\nI would prefer to keep this style","commit_id":"8c47e8875b0b2237a950f1cf0ae33f61cba82952"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"60e401b1994e12b0593deaf3fe61962dcc9eadf0","unresolved":false,"context_lines":[{"line_number":21,"context_line":"def average(values):"},{"line_number":22,"context_line":"    \"\"\"Find the simple average of a list of values."},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"    :parameter values: non-empty list of numbers"},{"line_number":25,"context_line":"    :returns: float"},{"line_number":26,"context_line":"    \"\"\""},{"line_number":27,"context_line":"    if values:"}],"source_content_type":"text/x-python","patch_set":1,"id":"9a80dd14_2359788e","line":24,"in_reply_to":"ba7be1f8_3cf1d76a","updated":"2015-03-06 17:44:33.000000000","message":"Done","commit_id":"8c47e8875b0b2237a950f1cf0ae33f61cba82952"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"a4baa00276e9939885c59044fa1453fbd5394b71","unresolved":false,"context_lines":[{"line_number":24,"context_line":"    :parameter values: non-empty list of numbers"},{"line_number":25,"context_line":"    :returns: float"},{"line_number":26,"context_line":"    \"\"\""},{"line_number":27,"context_line":"    if values:"},{"line_number":28,"context_line":"        return math.fsum(values) / len(values)"},{"line_number":29,"context_line":"    raise exceptions.InvalidArgumentsException(\"values can not be empty\")"},{"line_number":30,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"ba7be1f8_7cd42fbd","line":27,"updated":"2015-03-01 22:14:26.000000000","message":"I think it\u0027s simpler to read next code:\n\n  if not values:\n     raise...\n\n  return stuf","commit_id":"8c47e8875b0b2237a950f1cf0ae33f61cba82952"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"60e401b1994e12b0593deaf3fe61962dcc9eadf0","unresolved":false,"context_lines":[{"line_number":24,"context_line":"    :parameter values: non-empty list of numbers"},{"line_number":25,"context_line":"    :returns: float"},{"line_number":26,"context_line":"    \"\"\""},{"line_number":27,"context_line":"    if values:"},{"line_number":28,"context_line":"        return math.fsum(values) / len(values)"},{"line_number":29,"context_line":"    raise exceptions.InvalidArgumentsException(\"values can not be empty\")"},{"line_number":30,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"9a80dd14_6356105e","line":27,"in_reply_to":"ba7be1f8_7cd42fbd","updated":"2015-03-06 17:44:33.000000000","message":"Done","commit_id":"8c47e8875b0b2237a950f1cf0ae33f61cba82952"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"a4baa00276e9939885c59044fa1453fbd5394b71","unresolved":false,"context_lines":[{"line_number":26,"context_line":"    \"\"\""},{"line_number":27,"context_line":"    if values:"},{"line_number":28,"context_line":"        return math.fsum(values) / len(values)"},{"line_number":29,"context_line":"    raise exceptions.InvalidArgumentsException(\"values can not be empty\")"},{"line_number":30,"context_line":""},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"def percentile(values, percent):"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba7be1f8_592fc4f6","line":29,"updated":"2015-03-01 22:14:26.000000000","message":"I would prefer to use here standard \"ValueError\" instead of task invalid argument exception","commit_id":"8c47e8875b0b2237a950f1cf0ae33f61cba82952"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"60e401b1994e12b0593deaf3fe61962dcc9eadf0","unresolved":false,"context_lines":[{"line_number":26,"context_line":"    \"\"\""},{"line_number":27,"context_line":"    if values:"},{"line_number":28,"context_line":"        return math.fsum(values) / len(values)"},{"line_number":29,"context_line":"    raise exceptions.InvalidArgumentsException(\"values can not be empty\")"},{"line_number":30,"context_line":""},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"def percentile(values, percent):"}],"source_content_type":"text/x-python","patch_set":1,"id":"9a80dd14_8353046a","line":29,"in_reply_to":"ba7be1f8_592fc4f6","updated":"2015-03-06 17:44:33.000000000","message":"Done","commit_id":"8c47e8875b0b2237a950f1cf0ae33f61cba82952"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"a4baa00276e9939885c59044fa1453fbd5394b71","unresolved":false,"context_lines":[{"line_number":37,"context_line":"    :returns: percentile of values"},{"line_number":38,"context_line":"    \"\"\""},{"line_number":39,"context_line":"    if not values:"},{"line_number":40,"context_line":"        return None"},{"line_number":41,"context_line":"    values.sort()"},{"line_number":42,"context_line":"    k \u003d (len(values) - 1) * percent"},{"line_number":43,"context_line":"    f \u003d math.floor(k)"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba7be1f8_dce43bae","line":40,"updated":"2015-03-01 22:14:26.000000000","message":"I would prefer to chose one of 2 possible styles. returning None on invalid argument or raising Exception but not both.","commit_id":"8c47e8875b0b2237a950f1cf0ae33f61cba82952"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"60e401b1994e12b0593deaf3fe61962dcc9eadf0","unresolved":false,"context_lines":[{"line_number":37,"context_line":"    :returns: percentile of values"},{"line_number":38,"context_line":"    \"\"\""},{"line_number":39,"context_line":"    if not values:"},{"line_number":40,"context_line":"        return None"},{"line_number":41,"context_line":"    values.sort()"},{"line_number":42,"context_line":"    k \u003d (len(values) - 1) * percent"},{"line_number":43,"context_line":"    f \u003d math.floor(k)"}],"source_content_type":"text/x-python","patch_set":1,"id":"9a80dd14_c3497cb8","line":40,"in_reply_to":"ba7be1f8_dce43bae","updated":"2015-03-06 17:44:33.000000000","message":"Done","commit_id":"8c47e8875b0b2237a950f1cf0ae33f61cba82952"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"a4baa00276e9939885c59044fa1453fbd5394b71","unresolved":false,"context_lines":[{"line_number":55,"context_line":"        self.__dict__.update(kwargs)"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"class DiagramChart(dict):"},{"line_number":59,"context_line":"    \"\"\"Chart for generic stacked area.\"\"\""},{"line_number":60,"context_line":"    def __init__(self, size, limit\u003d1000, merge\u003dNone, normalize\u003dNone):"},{"line_number":61,"context_line":"        \"\"\"Init diagram."}],"source_content_type":"text/x-python","patch_set":1,"id":"ba7be1f8_bcfce740","line":58,"updated":"2015-03-01 22:14:26.000000000","message":"I dislike the name of this class. \n\nIt requires to read docstring to understand that it\u0027s actually not diagram but \"stacked are\"\n\nIt should be called\n\n  class StackedArea(dict):\n     ..","commit_id":"8c47e8875b0b2237a950f1cf0ae33f61cba82952"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"60e401b1994e12b0593deaf3fe61962dcc9eadf0","unresolved":false,"context_lines":[{"line_number":55,"context_line":"        self.__dict__.update(kwargs)"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"class DiagramChart(dict):"},{"line_number":59,"context_line":"    \"\"\"Chart for generic stacked area.\"\"\""},{"line_number":60,"context_line":"    def __init__(self, size, limit\u003d1000, merge\u003dNone, normalize\u003dNone):"},{"line_number":61,"context_line":"        \"\"\"Init diagram."}],"source_content_type":"text/x-python","patch_set":1,"id":"9a80dd14_e3c92027","line":58,"in_reply_to":"ba7be1f8_bcfce740","updated":"2015-03-06 17:44:33.000000000","message":"Done","commit_id":"8c47e8875b0b2237a950f1cf0ae33f61cba82952"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"a4baa00276e9939885c59044fa1453fbd5394b71","unresolved":false,"context_lines":[{"line_number":56,"context_line":""},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"class DiagramChart(dict):"},{"line_number":59,"context_line":"    \"\"\"Chart for generic stacked area.\"\"\""},{"line_number":60,"context_line":"    def __init__(self, size, limit\u003d1000, merge\u003dNone, normalize\u003dNone):"},{"line_number":61,"context_line":"        \"\"\"Init diagram."},{"line_number":62,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"ba7be1f8_dcfb5b45","line":59,"updated":"2015-03-01 22:14:26.000000000","message":"one blank line is missing","commit_id":"8c47e8875b0b2237a950f1cf0ae33f61cba82952"},{"author":{"_account_id":9545,"name":"Andriy Kurilin","email":"andr.kurilin@gmail.com","username":"akurilin"},"change_message_id":"c8fd321b2eb2d9eceeadc15ed94adcc4d294a41e","unresolved":false,"context_lines":[{"line_number":56,"context_line":""},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"class DiagramChart(dict):"},{"line_number":59,"context_line":"    \"\"\"Chart for generic stacked area.\"\"\""},{"line_number":60,"context_line":"    def __init__(self, size, limit\u003d1000, merge\u003dNone, normalize\u003dNone):"},{"line_number":61,"context_line":"        \"\"\"Init diagram."},{"line_number":62,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"9a80dd14_f54916b8","line":59,"in_reply_to":"9a80dd14_eadbf518","updated":"2015-03-05 15:37:19.000000000","message":"imo, blank line will help with readability.","commit_id":"8c47e8875b0b2237a950f1cf0ae33f61cba82952"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"e594fcae684808496c646ba2ff756dc6bb317669","unresolved":false,"context_lines":[{"line_number":56,"context_line":""},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"class DiagramChart(dict):"},{"line_number":59,"context_line":"    \"\"\"Chart for generic stacked area.\"\"\""},{"line_number":60,"context_line":"    def __init__(self, size, limit\u003d1000, merge\u003dNone, normalize\u003dNone):"},{"line_number":61,"context_line":"        \"\"\"Init diagram."},{"line_number":62,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"9a80dd14_eadbf518","line":59,"in_reply_to":"ba7be1f8_dcfb5b45","updated":"2015-03-05 15:23:50.000000000","message":"According to PEP257: There\u0027s no blank line either before or after the docstring. \n\nhttps://www.python.org/dev/peps/pep-0257/","commit_id":"8c47e8875b0b2237a950f1cf0ae33f61cba82952"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"60e401b1994e12b0593deaf3fe61962dcc9eadf0","unresolved":false,"context_lines":[{"line_number":56,"context_line":""},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"class DiagramChart(dict):"},{"line_number":59,"context_line":"    \"\"\"Chart for generic stacked area.\"\"\""},{"line_number":60,"context_line":"    def __init__(self, size, limit\u003d1000, merge\u003dNone, normalize\u003dNone):"},{"line_number":61,"context_line":"        \"\"\"Init diagram."},{"line_number":62,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"9a80dd14_43d58cb7","line":59,"in_reply_to":"ba7be1f8_dcfb5b45","updated":"2015-03-06 17:44:33.000000000","message":"Okay, let it be extra empty line","commit_id":"8c47e8875b0b2237a950f1cf0ae33f61cba82952"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"a4baa00276e9939885c59044fa1453fbd5394b71","unresolved":false,"context_lines":[{"line_number":62,"context_line":""},{"line_number":63,"context_line":"        :param size: how many times we will call `add_value()\u0027 for each key"},{"line_number":64,"context_line":"        :param limit: int, max length of result key values list"},{"line_number":65,"context_line":"        :param merge: function that merges two values"},{"line_number":66,"context_line":"        :param normalize: function to sanitize value"},{"line_number":67,"context_line":"        \"\"\""},{"line_number":68,"context_line":"        super(DiagramChart, self).__init__()"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba7be1f8_bc8307a8","line":65,"updated":"2015-03-01 22:14:26.000000000","message":"After looking on comment on line 72: \n\n  :param normalize: function that will be used instead of _default_normalize \n                    to sanitize value.","commit_id":"8c47e8875b0b2237a950f1cf0ae33f61cba82952"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"60e401b1994e12b0593deaf3fe61962dcc9eadf0","unresolved":false,"context_lines":[{"line_number":62,"context_line":""},{"line_number":63,"context_line":"        :param size: how many times we will call `add_value()\u0027 for each key"},{"line_number":64,"context_line":"        :param limit: int, max length of result key values list"},{"line_number":65,"context_line":"        :param merge: function that merges two values"},{"line_number":66,"context_line":"        :param normalize: function to sanitize value"},{"line_number":67,"context_line":"        \"\"\""},{"line_number":68,"context_line":"        super(DiagramChart, self).__init__()"}],"source_content_type":"text/x-python","patch_set":1,"id":"9a80dd14_63dd30e0","line":65,"in_reply_to":"ba7be1f8_bc8307a8","updated":"2015-03-06 17:44:33.000000000","message":"Done","commit_id":"8c47e8875b0b2237a950f1cf0ae33f61cba82952"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"a4baa00276e9939885c59044fa1453fbd5394b71","unresolved":false,"context_lines":[{"line_number":69,"context_line":"        self.size \u003d size"},{"line_number":70,"context_line":"        self.limit \u003d limit"},{"line_number":71,"context_line":"        self.normalize \u003d (normalize"},{"line_number":72,"context_line":"                          or (lambda i: i and round(float(i), 2) or 0.0))"},{"line_number":73,"context_line":"        self.merge \u003d ("},{"line_number":74,"context_line":"            merge"},{"line_number":75,"context_line":"            or (lambda a, b: self.normalize((a + self.normalize(b)) / 2)))"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba7be1f8_7ca26f4c","line":72,"updated":"2015-03-01 22:14:26.000000000","message":"Make code simpler\n\n  @statimethod\n  def _default_normalize(i):\n     ...\n\n\n  def __init__(self, ...): \n\n    self.normalize \u003d normilze or self._default_normalize()","commit_id":"8c47e8875b0b2237a950f1cf0ae33f61cba82952"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"60e401b1994e12b0593deaf3fe61962dcc9eadf0","unresolved":false,"context_lines":[{"line_number":69,"context_line":"        self.size \u003d size"},{"line_number":70,"context_line":"        self.limit \u003d limit"},{"line_number":71,"context_line":"        self.normalize \u003d (normalize"},{"line_number":72,"context_line":"                          or (lambda i: i and round(float(i), 2) or 0.0))"},{"line_number":73,"context_line":"        self.merge \u003d ("},{"line_number":74,"context_line":"            merge"},{"line_number":75,"context_line":"            or (lambda a, b: self.normalize((a + self.normalize(b)) / 2)))"}],"source_content_type":"text/x-python","patch_set":1,"id":"9a80dd14_e3f04069","line":72,"in_reply_to":"ba7be1f8_7ca26f4c","updated":"2015-03-06 17:44:33.000000000","message":"Done","commit_id":"8c47e8875b0b2237a950f1cf0ae33f61cba82952"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"a4baa00276e9939885c59044fa1453fbd5394b71","unresolved":false,"context_lines":[{"line_number":81,"context_line":""},{"line_number":82,"context_line":"    def add_value(self, name, value):"},{"line_number":83,"context_line":"        if name not in self:"},{"line_number":84,"context_line":"            self[name] \u003d Expando(values\u003d[], factor\u003d0, index\u003d0, buffered\u003d0)"},{"line_number":85,"context_line":"        self[name].index +\u003d 1"},{"line_number":86,"context_line":""},{"line_number":87,"context_line":"        if self.factor \u003e\u003d 1:"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba7be1f8_5ce84b7c","line":84,"updated":"2015-03-01 22:14:26.000000000","message":"Why not just using dict here instead of Exapndo. \n\nI don\u0027t think that it is big difference to type:\n\n  self[name][\"value\"] \n\n  vs\n\n  self[name].value\n\n\nBtw construction self[name] is quite hard readable. The first question is  Name of what?? the second self[name] mother of god. \n\nwhat about having just something like:\n\n\n   class StackedAreaChart(object):\n\n      def __init__(self):\n          self.data \u003d {}\n\n      def add_value(self, line_name, value): \n          self.data[\"line_name\"] \u003d ....\n\n      def render(self):\n           return self.data\n       \n\nThis code is simpler and self documented, which are key aspects of code quality.","commit_id":"8c47e8875b0b2237a950f1cf0ae33f61cba82952"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"60e401b1994e12b0593deaf3fe61962dcc9eadf0","unresolved":false,"context_lines":[{"line_number":81,"context_line":""},{"line_number":82,"context_line":"    def add_value(self, name, value):"},{"line_number":83,"context_line":"        if name not in self:"},{"line_number":84,"context_line":"            self[name] \u003d Expando(values\u003d[], factor\u003d0, index\u003d0, buffered\u003d0)"},{"line_number":85,"context_line":"        self[name].index +\u003d 1"},{"line_number":86,"context_line":""},{"line_number":87,"context_line":"        if self.factor \u003e\u003d 1:"}],"source_content_type":"text/x-python","patch_set":1,"id":"9a80dd14_43ecac8f","line":84,"in_reply_to":"ba7be1f8_5ce84b7c","updated":"2015-03-06 17:44:33.000000000","message":"Done","commit_id":"8c47e8875b0b2237a950f1cf0ae33f61cba82952"},{"author":{"_account_id":9545,"name":"Andriy Kurilin","email":"andr.kurilin@gmail.com","username":"akurilin"},"change_message_id":"c46fa4b645c821c06262acc061014bf36789d95d","unresolved":false,"context_lines":[{"line_number":82,"context_line":"    def add_value(self, name, value):"},{"line_number":83,"context_line":"        if name not in self:"},{"line_number":84,"context_line":"            self[name] \u003d Expando(values\u003d[], factor\u003d0, index\u003d0, buffered\u003d0)"},{"line_number":85,"context_line":"        self[name].index +\u003d 1"},{"line_number":86,"context_line":""},{"line_number":87,"context_line":"        if self.factor \u003e\u003d 1:"},{"line_number":88,"context_line":"            self[name].values.append((self[name].index, value))"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba7be1f8_77d448bd","line":85,"updated":"2015-03-01 23:34:48.000000000","message":"\u003e self[name]...\n\nyou make me hurt. please, stop doing it, stop write such code!","commit_id":"8c47e8875b0b2237a950f1cf0ae33f61cba82952"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"a4baa00276e9939885c59044fa1453fbd5394b71","unresolved":false,"context_lines":[{"line_number":115,"context_line":"        return result"},{"line_number":116,"context_line":""},{"line_number":117,"context_line":""},{"line_number":118,"context_line":"class AvgChart(dict):"},{"line_number":119,"context_line":"    \"\"\"Chart for average values.\"\"\""},{"line_number":120,"context_line":"    def add_value(self, key, value):"},{"line_number":121,"context_line":"        try:"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba7be1f8_fc8d7fd4","line":118,"updated":"2015-03-01 22:14:26.000000000","message":"I believe it\u0027s \n\n  PieChart \n\nor you can call it\n\n  AvaragePieChart","commit_id":"8c47e8875b0b2237a950f1cf0ae33f61cba82952"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"60e401b1994e12b0593deaf3fe61962dcc9eadf0","unresolved":false,"context_lines":[{"line_number":115,"context_line":"        return result"},{"line_number":116,"context_line":""},{"line_number":117,"context_line":""},{"line_number":118,"context_line":"class AvgChart(dict):"},{"line_number":119,"context_line":"    \"\"\"Chart for average values.\"\"\""},{"line_number":120,"context_line":"    def add_value(self, key, value):"},{"line_number":121,"context_line":"        try:"}],"source_content_type":"text/x-python","patch_set":1,"id":"9a80dd14_239ed807","line":118,"in_reply_to":"ba7be1f8_fc8d7fd4","updated":"2015-03-06 17:44:33.000000000","message":"Done","commit_id":"8c47e8875b0b2237a950f1cf0ae33f61cba82952"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"a4baa00276e9939885c59044fa1453fbd5394b71","unresolved":false,"context_lines":[{"line_number":130,"context_line":"        return [{\"key\": k, \"values\": v[0] / v[1]} for k, v in self.items()]"},{"line_number":131,"context_line":""},{"line_number":132,"context_line":""},{"line_number":133,"context_line":"class LoadProfileChart(list):"},{"line_number":134,"context_line":"    \"\"\"Chart for parallel durations.\"\"\""},{"line_number":135,"context_line":"    def __init__(self, name, ratio\u003d200, start\u003dNone, end\u003dNone):"},{"line_number":136,"context_line":"        self._name \u003d name"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba7be1f8_fc001f04","line":133,"updated":"2015-03-01 22:14:26.000000000","message":"I don\u0027t see any reason to make this class base from list. Try to make simple not hard to read code.","commit_id":"8c47e8875b0b2237a950f1cf0ae33f61cba82952"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"60e401b1994e12b0593deaf3fe61962dcc9eadf0","unresolved":false,"context_lines":[{"line_number":130,"context_line":"        return [{\"key\": k, \"values\": v[0] / v[1]} for k, v in self.items()]"},{"line_number":131,"context_line":""},{"line_number":132,"context_line":""},{"line_number":133,"context_line":"class LoadProfileChart(list):"},{"line_number":134,"context_line":"    \"\"\"Chart for parallel durations.\"\"\""},{"line_number":135,"context_line":"    def __init__(self, name, ratio\u003d200, start\u003dNone, end\u003dNone):"},{"line_number":136,"context_line":"        self._name \u003d name"}],"source_content_type":"text/x-python","patch_set":1,"id":"9a80dd14_638b70c3","line":133,"in_reply_to":"ba7be1f8_fc001f04","updated":"2015-03-06 17:44:33.000000000","message":"Done","commit_id":"8c47e8875b0b2237a950f1cf0ae33f61cba82952"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"a4baa00276e9939885c59044fa1453fbd5394b71","unresolved":false,"context_lines":[{"line_number":132,"context_line":""},{"line_number":133,"context_line":"class LoadProfileChart(list):"},{"line_number":134,"context_line":"    \"\"\"Chart for parallel durations.\"\"\""},{"line_number":135,"context_line":"    def __init__(self, name, ratio\u003d200, start\u003dNone, end\u003dNone):"},{"line_number":136,"context_line":"        self._name \u003d name"},{"line_number":137,"context_line":"        self._tstamp_start \u003d start"},{"line_number":138,"context_line":"        self._tstamp_end \u003d end"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba7be1f8_3702d009","line":135,"updated":"2015-03-01 22:14:26.000000000","message":"as far as I know we are storing start and duration. Not start and end information. So it makes sense to change end to duration.","commit_id":"8c47e8875b0b2237a950f1cf0ae33f61cba82952"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"60e401b1994e12b0593deaf3fe61962dcc9eadf0","unresolved":false,"context_lines":[{"line_number":132,"context_line":""},{"line_number":133,"context_line":"class LoadProfileChart(list):"},{"line_number":134,"context_line":"    \"\"\"Chart for parallel durations.\"\"\""},{"line_number":135,"context_line":"    def __init__(self, name, ratio\u003d200, start\u003dNone, end\u003dNone):"},{"line_number":136,"context_line":"        self._name \u003d name"},{"line_number":137,"context_line":"        self._tstamp_start \u003d start"},{"line_number":138,"context_line":"        self._tstamp_end \u003d end"}],"source_content_type":"text/x-python","patch_set":1,"id":"9a80dd14_c38edccf","line":135,"in_reply_to":"ba7be1f8_3702d009","updated":"2015-03-06 17:44:33.000000000","message":"Done","commit_id":"8c47e8875b0b2237a950f1cf0ae33f61cba82952"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"a4baa00276e9939885c59044fa1453fbd5394b71","unresolved":false,"context_lines":[{"line_number":139,"context_line":"        self._time_axis \u003d []"},{"line_number":140,"context_line":"        self._duration \u003d self._tstamp_end - self._tstamp_start"},{"line_number":141,"context_line":"        step \u003d self._duration / float(ratio)"},{"line_number":142,"context_line":"        for accuracy in range(5):"},{"line_number":143,"context_line":"            if step \u003e (10 ** -accuracy):"},{"line_number":144,"context_line":"                step \u003d round(step, accuracy)"},{"line_number":145,"context_line":"                break"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba7be1f8_770c483c","line":142,"updated":"2015-03-01 22:14:26.000000000","message":"why 5 and what is this at all? This code requires huge NOTE otherwise it\u0027s unclear.","commit_id":"8c47e8875b0b2237a950f1cf0ae33f61cba82952"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"60e401b1994e12b0593deaf3fe61962dcc9eadf0","unresolved":false,"context_lines":[{"line_number":139,"context_line":"        self._time_axis \u003d []"},{"line_number":140,"context_line":"        self._duration \u003d self._tstamp_end - self._tstamp_start"},{"line_number":141,"context_line":"        step \u003d self._duration / float(ratio)"},{"line_number":142,"context_line":"        for accuracy in range(5):"},{"line_number":143,"context_line":"            if step \u003e (10 ** -accuracy):"},{"line_number":144,"context_line":"                step \u003d round(step, accuracy)"},{"line_number":145,"context_line":"                break"}],"source_content_type":"text/x-python","patch_set":1,"id":"9a80dd14_03c474f3","line":142,"in_reply_to":"ba7be1f8_770c483c","updated":"2015-03-06 17:44:33.000000000","message":"Done: NOTE is added","commit_id":"8c47e8875b0b2237a950f1cf0ae33f61cba82952"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"a4baa00276e9939885c59044fa1453fbd5394b71","unresolved":false,"context_lines":[{"line_number":172,"context_line":"        for ts, started, ended in self._time_axis:"},{"line_number":173,"context_line":"            parallels +\u003d (started - ended)"},{"line_number":174,"context_line":"            data.append([ts, parallels])"},{"line_number":175,"context_line":"        return len(data) \u003e 1 and [{\"key\": self._name, \"values\": data}] or []"},{"line_number":176,"context_line":""},{"line_number":177,"context_line":""},{"line_number":178,"context_line":"class HistogramChart(object):"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba7be1f8_9740dc36","line":175,"updated":"2015-03-01 22:14:26.000000000","message":"You was talking about making stuff GENERIC this thing seems like very hard coded to report mechanism. \n\nI would prefer next: \n\n  return [{\"key\": self._name, \"values\": data}] \n\nThing that do logic if \"values\" are none should be somewhere else.","commit_id":"8c47e8875b0b2237a950f1cf0ae33f61cba82952"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"60e401b1994e12b0593deaf3fe61962dcc9eadf0","unresolved":false,"context_lines":[{"line_number":172,"context_line":"        for ts, started, ended in self._time_axis:"},{"line_number":173,"context_line":"            parallels +\u003d (started - ended)"},{"line_number":174,"context_line":"            data.append([ts, parallels])"},{"line_number":175,"context_line":"        return len(data) \u003e 1 and [{\"key\": self._name, \"values\": data}] or []"},{"line_number":176,"context_line":""},{"line_number":177,"context_line":""},{"line_number":178,"context_line":"class HistogramChart(object):"}],"source_content_type":"text/x-python","patch_set":1,"id":"9a80dd14_43baec6e","line":175,"in_reply_to":"ba7be1f8_9740dc36","updated":"2015-03-06 17:44:33.000000000","message":"Done","commit_id":"8c47e8875b0b2237a950f1cf0ae33f61cba82952"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"a4baa00276e9939885c59044fa1453fbd5394b71","unresolved":false,"context_lines":[{"line_number":211,"context_line":"            {\"method\": \"One Half\","},{"line_number":212,"context_line":"             \"bins\": int(math.ceil(self.size / 2.0))}]"},{"line_number":213,"context_line":""},{"line_number":214,"context_line":"    def add_value(self, value):"},{"line_number":215,"context_line":"        for i, view in enumerate(self._views):"},{"line_number":216,"context_line":"            for bin_i, bin_v in enumerate(view[\"x_axis\"]):"},{"line_number":217,"context_line":"                if value \u003c\u003d bin_v:"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba7be1f8_7771a8a7","line":214,"updated":"2015-03-01 22:14:26.000000000","message":"add_value() should always have same signature otherwise you are doing bad OOP","commit_id":"8c47e8875b0b2237a950f1cf0ae33f61cba82952"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"60e401b1994e12b0593deaf3fe61962dcc9eadf0","unresolved":false,"context_lines":[{"line_number":211,"context_line":"            {\"method\": \"One Half\","},{"line_number":212,"context_line":"             \"bins\": int(math.ceil(self.size / 2.0))}]"},{"line_number":213,"context_line":""},{"line_number":214,"context_line":"    def add_value(self, value):"},{"line_number":215,"context_line":"        for i, view in enumerate(self._views):"},{"line_number":216,"context_line":"            for bin_i, bin_v in enumerate(view[\"x_axis\"]):"},{"line_number":217,"context_line":"                if value \u003c\u003d bin_v:"}],"source_content_type":"text/x-python","patch_set":1,"id":"9a80dd14_63b29095","line":214,"in_reply_to":"ba7be1f8_7771a8a7","updated":"2015-03-06 17:44:33.000000000","message":"Done","commit_id":"8c47e8875b0b2237a950f1cf0ae33f61cba82952"},{"author":{"_account_id":8507,"name":"Mikhail Dubov","email":"mdubov@mirantis.com","username":"msdubov"},"change_message_id":"fc73eb1d97efa24be0d5c98f9824d6dc186c195b","unresolved":false,"context_lines":[{"line_number":19,"context_line":"import six"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"def average(values):"},{"line_number":23,"context_line":"    \"\"\"Find the simple average of a list of values."},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"    :param values: non-empty list of numbers"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_71e1df99","line":22,"updated":"2015-03-11 11:45:39.000000000","message":"Why do we need this code here? This is a complete copy-paste from https://github.com/stackforge/rally/blob/master/rally/benchmark/processing/utils.py#L21-L52","commit_id":"29cfc9090bf3c37297bdb349fa9e8feeac33d2bb"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"c90b487ff1ad2fa0f914fa253b36f37ba8ac43ae","unresolved":false,"context_lines":[{"line_number":19,"context_line":"import six"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"def average(values):"},{"line_number":23,"context_line":"    \"\"\"Find the simple average of a list of values."},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"    :param values: non-empty list of numbers"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_03fda63b","line":22,"in_reply_to":"9a80dd14_71e1df99","updated":"2015-03-11 17:45:08.000000000","message":"Because processing/utils.py will be removed in related patch https://review.openstack.org/#/c/146814/","commit_id":"29cfc9090bf3c37297bdb349fa9e8feeac33d2bb"},{"author":{"_account_id":8507,"name":"Mikhail Dubov","email":"mdubov@mirantis.com","username":"msdubov"},"change_message_id":"fc73eb1d97efa24be0d5c98f9824d6dc186c195b","unresolved":false,"context_lines":[{"line_number":57,"context_line":""},{"line_number":58,"context_line":"    @abc.abstractmethod"},{"line_number":59,"context_line":"    def add_value(self, name, value):"},{"line_number":60,"context_line":"        \"\"\"Add a kind of iteration value.\"\"\""},{"line_number":61,"context_line":""},{"line_number":62,"context_line":"    @abc.abstractmethod"},{"line_number":63,"context_line":"    def render(self, name, value):"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_11018339","line":60,"updated":"2015-03-11 11:45:39.000000000","message":"What do you mean by \"a kind of\"?","commit_id":"29cfc9090bf3c37297bdb349fa9e8feeac33d2bb"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"c90b487ff1ad2fa0f914fa253b36f37ba8ac43ae","unresolved":false,"context_lines":[{"line_number":57,"context_line":""},{"line_number":58,"context_line":"    @abc.abstractmethod"},{"line_number":59,"context_line":"    def add_value(self, name, value):"},{"line_number":60,"context_line":"        \"\"\"Add a kind of iteration value.\"\"\""},{"line_number":61,"context_line":""},{"line_number":62,"context_line":"    @abc.abstractmethod"},{"line_number":63,"context_line":"    def render(self, name, value):"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_a36dba06","line":60,"in_reply_to":"9a80dd14_11018339","updated":"2015-03-11 17:45:08.000000000","message":"Some value (depends on Chart implementation) from iteration, for example this can me an atomic action, or duration, or idle_duration and so on","commit_id":"29cfc9090bf3c37297bdb349fa9e8feeac33d2bb"},{"author":{"_account_id":8507,"name":"Mikhail Dubov","email":"mdubov@mirantis.com","username":"msdubov"},"change_message_id":"fc73eb1d97efa24be0d5c98f9824d6dc186c195b","unresolved":false,"context_lines":[{"line_number":60,"context_line":"        \"\"\"Add a kind of iteration value.\"\"\""},{"line_number":61,"context_line":""},{"line_number":62,"context_line":"    @abc.abstractmethod"},{"line_number":63,"context_line":"    def render(self, name, value):"},{"line_number":64,"context_line":"        \"\"\"Generate chart data for JavaScript.\"\"\""},{"line_number":65,"context_line":""},{"line_number":66,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_f8fe8f04","line":63,"updated":"2015-03-11 11:45:39.000000000","message":"Okay, all the subclasses implement the same render() method, but they return the data in different formats (e.g. StatsTable). Does this really make sense to make it an abstract method in the base class?","commit_id":"29cfc9090bf3c37297bdb349fa9e8feeac33d2bb"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"c90b487ff1ad2fa0f914fa253b36f37ba8ac43ae","unresolved":false,"context_lines":[{"line_number":60,"context_line":"        \"\"\"Add a kind of iteration value.\"\"\""},{"line_number":61,"context_line":""},{"line_number":62,"context_line":"    @abc.abstractmethod"},{"line_number":63,"context_line":"    def render(self, name, value):"},{"line_number":64,"context_line":"        \"\"\"Generate chart data for JavaScript.\"\"\""},{"line_number":65,"context_line":""},{"line_number":66,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_de128157","line":63,"in_reply_to":"9a80dd14_f8fe8f04","updated":"2015-03-11 17:45:08.000000000","message":"StatsTable is something different - this is not actually a chart. Chart can be removed from StatsTable bases","commit_id":"29cfc9090bf3c37297bdb349fa9e8feeac33d2bb"},{"author":{"_account_id":8507,"name":"Mikhail Dubov","email":"mdubov@mirantis.com","username":"msdubov"},"change_message_id":"fc73eb1d97efa24be0d5c98f9824d6dc186c195b","unresolved":false,"context_lines":[{"line_number":140,"context_line":""},{"line_number":141,"context_line":"    def __init__(self):"},{"line_number":142,"context_line":"        super(PieChart, self).__init__()"},{"line_number":143,"context_line":"        self.data \u003d {}"},{"line_number":144,"context_line":""},{"line_number":145,"context_line":"    def add_value(self, name, value):"},{"line_number":146,"context_line":"        try:"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_110b432c","line":143,"updated":"2015-03-11 11:45:39.000000000","message":"Maybe better use collections.defaultdict? Than you would simplify that try ... except logic in L146-150","commit_id":"29cfc9090bf3c37297bdb349fa9e8feeac33d2bb"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"c90b487ff1ad2fa0f914fa253b36f37ba8ac43ae","unresolved":false,"context_lines":[{"line_number":140,"context_line":""},{"line_number":141,"context_line":"    def __init__(self):"},{"line_number":142,"context_line":"        super(PieChart, self).__init__()"},{"line_number":143,"context_line":"        self.data \u003d {}"},{"line_number":144,"context_line":""},{"line_number":145,"context_line":"    def add_value(self, name, value):"},{"line_number":146,"context_line":"        try:"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_1e0339b9","line":143,"in_reply_to":"9a80dd14_110b432c","updated":"2015-03-11 17:45:08.000000000","message":"We can not use defaultdict here because we do not know default value (see line 150)","commit_id":"29cfc9090bf3c37297bdb349fa9e8feeac33d2bb"},{"author":{"_account_id":8507,"name":"Mikhail Dubov","email":"mdubov@mirantis.com","username":"msdubov"},"change_message_id":"fc73eb1d97efa24be0d5c98f9824d6dc186c195b","unresolved":false,"context_lines":[{"line_number":144,"context_line":""},{"line_number":145,"context_line":"    def add_value(self, name, value):"},{"line_number":146,"context_line":"        try:"},{"line_number":147,"context_line":"            amount, count \u003d self.data[name]"},{"line_number":148,"context_line":"            self.data[name] \u003d amount + (value or 0), count + 1"},{"line_number":149,"context_line":"        except KeyError:"},{"line_number":150,"context_line":"            self.data[name] \u003d (value or 0), 1."}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_5525a6a9","line":147,"updated":"2015-03-11 11:45:39.000000000","message":"amount, count - totally unclear for me what these names mean (I actually thought these words mean roughly the same :) ). I think there should be a description of the self.data format somewhere in a docstring.","commit_id":"29cfc9090bf3c37297bdb349fa9e8feeac33d2bb"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"c90b487ff1ad2fa0f914fa253b36f37ba8ac43ae","unresolved":false,"context_lines":[{"line_number":144,"context_line":""},{"line_number":145,"context_line":"    def add_value(self, name, value):"},{"line_number":146,"context_line":"        try:"},{"line_number":147,"context_line":"            amount, count \u003d self.data[name]"},{"line_number":148,"context_line":"            self.data[name] \u003d amount + (value or 0), count + 1"},{"line_number":149,"context_line":"        except KeyError:"},{"line_number":150,"context_line":"            self.data[name] \u003d (value or 0), 1."}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_dee60116","line":147,"in_reply_to":"9a80dd14_5525a6a9","updated":"2015-03-11 17:45:08.000000000","message":"Sure","commit_id":"29cfc9090bf3c37297bdb349fa9e8feeac33d2bb"},{"author":{"_account_id":8507,"name":"Mikhail Dubov","email":"mdubov@mirantis.com","username":"msdubov"},"change_message_id":"fc73eb1d97efa24be0d5c98f9824d6dc186c195b","unresolved":false,"context_lines":[{"line_number":171,"context_line":"        self._duration \u003d duration"},{"line_number":172,"context_line":""},{"line_number":173,"context_line":"        # NOTE(amaretskiy): Determine a chart `step\u0027 - duration between"},{"line_number":174,"context_line":"        #                   wo X points, rounded with some accuracy"},{"line_number":175,"context_line":"        #                   (digits after point) to improve JavaScript"},{"line_number":176,"context_line":"        #                   drawing performance. Accuracy starts from `5\u0027"},{"line_number":177,"context_line":"        #                   and depends on ratio and duration."}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_b5e6e242","line":174,"updated":"2015-03-11 11:45:39.000000000","message":"s/wo/two","commit_id":"29cfc9090bf3c37297bdb349fa9e8feeac33d2bb"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"c90b487ff1ad2fa0f914fa253b36f37ba8ac43ae","unresolved":false,"context_lines":[{"line_number":171,"context_line":"        self._duration \u003d duration"},{"line_number":172,"context_line":""},{"line_number":173,"context_line":"        # NOTE(amaretskiy): Determine a chart `step\u0027 - duration between"},{"line_number":174,"context_line":"        #                   wo X points, rounded with some accuracy"},{"line_number":175,"context_line":"        #                   (digits after point) to improve JavaScript"},{"line_number":176,"context_line":"        #                   drawing performance. Accuracy starts from `5\u0027"},{"line_number":177,"context_line":"        #                   and depends on ratio and duration."}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_5eba11e2","line":174,"in_reply_to":"9a80dd14_b5e6e242","updated":"2015-03-11 17:45:08.000000000","message":"Yes, thanks","commit_id":"29cfc9090bf3c37297bdb349fa9e8feeac33d2bb"},{"author":{"_account_id":8507,"name":"Mikhail Dubov","email":"mdubov@mirantis.com","username":"msdubov"},"change_message_id":"fc73eb1d97efa24be0d5c98f9824d6dc186c195b","unresolved":false,"context_lines":[{"line_number":218,"context_line":""},{"line_number":219,"context_line":"class HistogramChart(Chart):"},{"line_number":220,"context_line":"    \"\"\"Histogram chart.\"\"\""},{"line_number":221,"context_line":"    def __init__(self, histograms):"},{"line_number":222,"context_line":"        self.data \u003d {}"},{"line_number":223,"context_line":"        for iters_passed, min_value, max_value, key, disabled in histograms:"},{"line_number":224,"context_line":"            min_vallue \u003d min_value or 0"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_d55ef611","line":221,"updated":"2015-03-11 11:45:39.000000000","message":"Again, this definitely requires some description. What is the format of this histograms parameter, and what is the format of self.data","commit_id":"29cfc9090bf3c37297bdb349fa9e8feeac33d2bb"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"c90b487ff1ad2fa0f914fa253b36f37ba8ac43ae","unresolved":false,"context_lines":[{"line_number":218,"context_line":""},{"line_number":219,"context_line":"class HistogramChart(Chart):"},{"line_number":220,"context_line":"    \"\"\"Histogram chart.\"\"\""},{"line_number":221,"context_line":"    def __init__(self, histograms):"},{"line_number":222,"context_line":"        self.data \u003d {}"},{"line_number":223,"context_line":"        for iters_passed, min_value, max_value, key, disabled in histograms:"},{"line_number":224,"context_line":"            min_vallue \u003d min_value or 0"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_beb78df4","line":221,"in_reply_to":"9a80dd14_d55ef611","updated":"2015-03-11 17:45:08.000000000","message":"Yes, will be done","commit_id":"29cfc9090bf3c37297bdb349fa9e8feeac33d2bb"},{"author":{"_account_id":8507,"name":"Mikhail Dubov","email":"mdubov@mirantis.com","username":"msdubov"},"change_message_id":"fc73eb1d97efa24be0d5c98f9824d6dc186c195b","unresolved":false,"context_lines":[{"line_number":293,"context_line":""},{"line_number":294,"context_line":"    def add_value(self, name, value):"},{"line_number":295,"context_line":"        if value is not None:"},{"line_number":296,"context_line":"            if name not in self.data:"},{"line_number":297,"context_line":"                self.data[name] \u003d []"},{"line_number":298,"context_line":"            self.data[name].append(value)"},{"line_number":299,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_b50262b2","line":296,"updated":"2015-03-11 11:45:39.000000000","message":"Again, this check will be not necessary if you declare\n\n    self.data \u003d collections.defaultdict(list)","commit_id":"29cfc9090bf3c37297bdb349fa9e8feeac33d2bb"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"c90b487ff1ad2fa0f914fa253b36f37ba8ac43ae","unresolved":false,"context_lines":[{"line_number":293,"context_line":""},{"line_number":294,"context_line":"    def add_value(self, name, value):"},{"line_number":295,"context_line":"        if value is not None:"},{"line_number":296,"context_line":"            if name not in self.data:"},{"line_number":297,"context_line":"                self.data[name] \u003d []"},{"line_number":298,"context_line":"            self.data[name].append(value)"},{"line_number":299,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_9e82c9fe","line":296,"in_reply_to":"9a80dd14_b50262b2","updated":"2015-03-11 17:45:08.000000000","message":"Yes, defaultdict will work here","commit_id":"29cfc9090bf3c37297bdb349fa9e8feeac33d2bb"},{"author":{"_account_id":8840,"name":"Carlos L. Torres","email":"carlos.torres@rackspace.com","username":"carl6796"},"change_message_id":"11c28d92c81c237124984806cf901d6a2a9c1c1d","unresolved":false,"context_lines":[{"line_number":20,"context_line":"import six"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"def average(values):"},{"line_number":24,"context_line":"    \"\"\"Find the simple average of a list of values."},{"line_number":25,"context_line":""},{"line_number":26,"context_line":"    :param values: non-empty list of numbers"}],"source_content_type":"text/x-python","patch_set":6,"id":"9a80dd14_89a50249","line":23,"updated":"2015-03-12 16:28:31.000000000","message":"Why are average, and percentiles functions duplicated again here? Can we re-use the functions in benchmark/processing/utils.py?","commit_id":"65aa00f81f9d3c051ab6f0e727633302305868dc"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"f2a930fb164eee754f1f2e6cf856f4def7df3a43","unresolved":false,"context_lines":[{"line_number":20,"context_line":"import six"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"def average(values):"},{"line_number":24,"context_line":"    \"\"\"Find the simple average of a list of values."},{"line_number":25,"context_line":""},{"line_number":26,"context_line":"    :param values: non-empty list of numbers"}],"source_content_type":"text/x-python","patch_set":6,"id":"9a80dd14_65bf61ab","line":23,"in_reply_to":"9a80dd14_7f715c43","updated":"2015-03-17 12:51:01.000000000","message":"Of course, rebasing will be necessary","commit_id":"65aa00f81f9d3c051ab6f0e727633302305868dc"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"d04bcaa8d2ad0ec208af1c6b7ab54a8e5df03d70","unresolved":false,"context_lines":[{"line_number":20,"context_line":"import six"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"def average(values):"},{"line_number":24,"context_line":"    \"\"\"Find the simple average of a list of values."},{"line_number":25,"context_line":""},{"line_number":26,"context_line":"    :param values: non-empty list of numbers"}],"source_content_type":"text/x-python","patch_set":6,"id":"9a80dd14_9c5e1ee8","line":23,"in_reply_to":"9a80dd14_89a50249","updated":"2015-03-12 16:29:41.000000000","message":"Because utils will be removed completely in upcoming patch","commit_id":"65aa00f81f9d3c051ab6f0e727633302305868dc"},{"author":{"_account_id":8840,"name":"Carlos L. Torres","email":"carlos.torres@rackspace.com","username":"carl6796"},"change_message_id":"e3cf0ab15d3d840c2b8b0a65eb0283cfd618f47d","unresolved":false,"context_lines":[{"line_number":20,"context_line":"import six"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"def average(values):"},{"line_number":24,"context_line":"    \"\"\"Find the simple average of a list of values."},{"line_number":25,"context_line":""},{"line_number":26,"context_line":"    :param values: non-empty list of numbers"}],"source_content_type":"text/x-python","patch_set":6,"id":"9a80dd14_7f715c43","line":23,"in_reply_to":"9a80dd14_9c5e1ee8","updated":"2015-03-12 16:52:13.000000000","message":"Got it, then I should hurry and get my median patch merged, to make sure we included with this patch. https://review.openstack.org/#/c/161037/","commit_id":"65aa00f81f9d3c051ab6f0e727633302305868dc"},{"author":{"_account_id":7369,"name":"Sergey Skripnick","email":"sskripnick@mirantis.com","username":"redixin"},"change_message_id":"5d9bad219368e42f875c83980bec0aef319ba1af","unresolved":false,"context_lines":[{"line_number":116,"context_line":"        # factor of 0.25 and delete (merge with previous) each 4th row."},{"line_number":117,"context_line":"        self.factor \u003d size and float(limit) / size or 1"},{"line_number":118,"context_line":""},{"line_number":119,"context_line":"    def normalize(self, x):"},{"line_number":120,"context_line":"        if not callable(self._normalize):"},{"line_number":121,"context_line":"            return x and round(float(x), 2) or 0.0"},{"line_number":122,"context_line":"        return self._normalize(x)"}],"source_content_type":"text/x-python","patch_set":10,"id":"9a80dd14_b04af524","line":119,"updated":"2015-03-19 16:22:22.000000000","message":"normalize and merge looks a bit overengineered.\n\nI cant see any case for overriding this functions.\n\nBut if this ever needed, we always can do monkey-patch or inherit-override\n\nAlso overriding of this methods is not covered by unit tests, so better to remove this","commit_id":"ace208122d3a42a98edaf4110b0e7e3a98600529"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"72cc4c97b84cd7cd68367c01228efdc78a181a79","unresolved":false,"context_lines":[{"line_number":116,"context_line":"        # factor of 0.25 and delete (merge with previous) each 4th row."},{"line_number":117,"context_line":"        self.factor \u003d size and float(limit) / size or 1"},{"line_number":118,"context_line":""},{"line_number":119,"context_line":"    def normalize(self, x):"},{"line_number":120,"context_line":"        if not callable(self._normalize):"},{"line_number":121,"context_line":"            return x and round(float(x), 2) or 0.0"},{"line_number":122,"context_line":"        return self._normalize(x)"}],"source_content_type":"text/x-python","patch_set":10,"id":"9a80dd14_c15a3d4f","line":119,"in_reply_to":"9a80dd14_b04af524","updated":"2015-03-19 17:15:47.000000000","message":"Agreed, this is redundant","commit_id":"ace208122d3a42a98edaf4110b0e7e3a98600529"},{"author":{"_account_id":8840,"name":"Carlos L. Torres","email":"carlos.torres@rackspace.com","username":"carl6796"},"change_message_id":"011a01d2d3fb3d1f19e3f3615375b2e344efd9b0","unresolved":false,"context_lines":[{"line_number":157,"context_line":"        :returns: chart data [{\"key\": str, \"values\": list}, ...]"},{"line_number":158,"context_line":"        \"\"\""},{"line_number":159,"context_line":"        result \u003d []"},{"line_number":160,"context_line":"        for k, v in self.data.items():"},{"line_number":161,"context_line":"            if v[\"buffered\"]:"},{"line_number":162,"context_line":"                v[\"values\"].append((self.size, v[\"buffered\"]))"},{"line_number":163,"context_line":"            result.append({\"key\": k, \"values\": v[\"values\"]})"}],"source_content_type":"text/x-python","patch_set":10,"id":"9a80dd14_6669a7f7","line":160,"updated":"2015-03-19 17:04:55.000000000","message":"I think instead of items(), we should be using \n\nfor k, v in six.viewitems(self.data)\n\nfor Python2to3 compatibility","commit_id":"ace208122d3a42a98edaf4110b0e7e3a98600529"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"72cc4c97b84cd7cd68367c01228efdc78a181a79","unresolved":false,"context_lines":[{"line_number":157,"context_line":"        :returns: chart data [{\"key\": str, \"values\": list}, ...]"},{"line_number":158,"context_line":"        \"\"\""},{"line_number":159,"context_line":"        result \u003d []"},{"line_number":160,"context_line":"        for k, v in self.data.items():"},{"line_number":161,"context_line":"            if v[\"buffered\"]:"},{"line_number":162,"context_line":"                v[\"values\"].append((self.size, v[\"buffered\"]))"},{"line_number":163,"context_line":"            result.append({\"key\": k, \"values\": v[\"values\"]})"}],"source_content_type":"text/x-python","patch_set":10,"id":"9a80dd14_810da591","line":160,"in_reply_to":"9a80dd14_6669a7f7","updated":"2015-03-19 17:15:47.000000000","message":"For this case items() is absolutely ok, and this is definitely 100% py3 compatible\n\nDifference:\n * items() in python2 returns list\n * items() in python3 returns iterator\n\nIn this case we:\n * iterate result of items() # so iterator is Ok\n * process all values (do not interrupt cycling) # no benefits for iterator in py2\n * having low memory usage # no benefits for iterator in py2","commit_id":"ace208122d3a42a98edaf4110b0e7e3a98600529"},{"author":{"_account_id":8840,"name":"Carlos L. Torres","email":"carlos.torres@rackspace.com","username":"carl6796"},"change_message_id":"011a01d2d3fb3d1f19e3f3615375b2e344efd9b0","unresolved":false,"context_lines":[{"line_number":184,"context_line":"            self.data[name] \u003d (value or 0), 1."},{"line_number":185,"context_line":""},{"line_number":186,"context_line":"    def render(self):"},{"line_number":187,"context_line":"        return [{\"key\": k, \"values\": v[0] / v[1]}"},{"line_number":188,"context_line":"                for k, v in self.data.items()]"},{"line_number":189,"context_line":""},{"line_number":190,"context_line":""}],"source_content_type":"text/x-python","patch_set":10,"id":"9a80dd14_e1b4a137","line":187,"updated":"2015-03-19 17:04:55.000000000","message":"Division here could possible return an integer.\n\nIs this the desired behavior? If not wrap one of the values with float, or use \u0027from __future__ import division\u0027","commit_id":"ace208122d3a42a98edaf4110b0e7e3a98600529"},{"author":{"_account_id":8840,"name":"Carlos L. Torres","email":"carlos.torres@rackspace.com","username":"carl6796"},"change_message_id":"011a01d2d3fb3d1f19e3f3615375b2e344efd9b0","unresolved":false,"context_lines":[{"line_number":185,"context_line":""},{"line_number":186,"context_line":"    def render(self):"},{"line_number":187,"context_line":"        return [{\"key\": k, \"values\": v[0] / v[1]}"},{"line_number":188,"context_line":"                for k, v in self.data.items()]"},{"line_number":189,"context_line":""},{"line_number":190,"context_line":""},{"line_number":191,"context_line":"class LoadProfileChart(Chart):"}],"source_content_type":"text/x-python","patch_set":10,"id":"9a80dd14_e18bc166","line":188,"updated":"2015-03-19 17:04:55.000000000","message":"six.viewitems(self.data), maybe?","commit_id":"ace208122d3a42a98edaf4110b0e7e3a98600529"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"72cc4c97b84cd7cd68367c01228efdc78a181a79","unresolved":false,"context_lines":[{"line_number":185,"context_line":""},{"line_number":186,"context_line":"    def render(self):"},{"line_number":187,"context_line":"        return [{\"key\": k, \"values\": v[0] / v[1]}"},{"line_number":188,"context_line":"                for k, v in self.data.items()]"},{"line_number":189,"context_line":""},{"line_number":190,"context_line":""},{"line_number":191,"context_line":"class LoadProfileChart(Chart):"}],"source_content_type":"text/x-python","patch_set":10,"id":"9a80dd14_e1f74158","line":188,"in_reply_to":"9a80dd14_e18bc166","updated":"2015-03-19 17:15:47.000000000","message":"No, see comment above","commit_id":"ace208122d3a42a98edaf4110b0e7e3a98600529"},{"author":{"_account_id":8840,"name":"Carlos L. Torres","email":"carlos.torres@rackspace.com","username":"carl6796"},"change_message_id":"011a01d2d3fb3d1f19e3f3615375b2e344efd9b0","unresolved":false,"context_lines":[{"line_number":313,"context_line":""},{"line_number":314,"context_line":"    def render(self):"},{"line_number":315,"context_line":"        chart \u003d []"},{"line_number":316,"context_line":"        for name, hist in self.data.items():"},{"line_number":317,"context_line":"            data \u003d []"},{"line_number":318,"context_line":"            for view in hist[\"views\"]:"},{"line_number":319,"context_line":"                value \u003d {\"key\": name,"}],"source_content_type":"text/x-python","patch_set":10,"id":"9a80dd14_215eb9e9","line":316,"updated":"2015-03-19 17:04:55.000000000","message":"Again, maybe for compatibility we should use six.viewitems","commit_id":"ace208122d3a42a98edaf4110b0e7e3a98600529"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"72cc4c97b84cd7cd68367c01228efdc78a181a79","unresolved":false,"context_lines":[{"line_number":313,"context_line":""},{"line_number":314,"context_line":"    def render(self):"},{"line_number":315,"context_line":"        chart \u003d []"},{"line_number":316,"context_line":"        for name, hist in self.data.items():"},{"line_number":317,"context_line":"            data \u003d []"},{"line_number":318,"context_line":"            for view in hist[\"views\"]:"},{"line_number":319,"context_line":"                value \u003d {\"key\": name,"}],"source_content_type":"text/x-python","patch_set":10,"id":"9a80dd14_a188e9c6","line":316,"in_reply_to":"9a80dd14_215eb9e9","updated":"2015-03-19 17:15:47.000000000","message":"No, again :)","commit_id":"ace208122d3a42a98edaf4110b0e7e3a98600529"},{"author":{"_account_id":8840,"name":"Carlos L. Torres","email":"carlos.torres@rackspace.com","username":"carl6796"},"change_message_id":"34170c244745a4eba39a33fe0e89c8083fa8a9fe","unresolved":false,"context_lines":[{"line_number":172,"context_line":"            self.data[name] \u003d (value or 0), 1."},{"line_number":173,"context_line":""},{"line_number":174,"context_line":"    def render(self):"},{"line_number":175,"context_line":"        return [{\"key\": k, \"values\": v[0] / v[1]}"},{"line_number":176,"context_line":"                for k, v in self.data.items()]"},{"line_number":177,"context_line":""},{"line_number":178,"context_line":""}],"source_content_type":"text/x-python","patch_set":12,"id":"9a80dd14_67d16956","line":175,"updated":"2015-03-20 20:59:42.000000000","message":"Depending on the values of v[0] and v[1], the result of the division here could be both integer, and float.","commit_id":"2f59b3730624ff96e4e85c28ccb72542557986b0"},{"author":{"_account_id":8840,"name":"Carlos L. Torres","email":"carlos.torres@rackspace.com","username":"carl6796"},"change_message_id":"fe99897f87dbc5150e237035f7d3cf0c506b6ba9","unresolved":false,"context_lines":[{"line_number":172,"context_line":"            self.data[name] \u003d (value or 0), 1."},{"line_number":173,"context_line":""},{"line_number":174,"context_line":"    def render(self):"},{"line_number":175,"context_line":"        return [{\"key\": k, \"values\": v[0] / v[1]}"},{"line_number":176,"context_line":"                for k, v in self.data.items()]"},{"line_number":177,"context_line":""},{"line_number":178,"context_line":""}],"source_content_type":"text/x-python","patch_set":12,"id":"1a6ced46_5a9318fa","line":175,"in_reply_to":"1a6ced46_7c9ff95f","updated":"2015-03-23 18:05:14.000000000","message":"ok","commit_id":"2f59b3730624ff96e4e85c28ccb72542557986b0"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"2e1f5935ec6e5cec382f04b1b4a4bda768b29e6e","unresolved":false,"context_lines":[{"line_number":172,"context_line":"            self.data[name] \u003d (value or 0), 1."},{"line_number":173,"context_line":""},{"line_number":174,"context_line":"    def render(self):"},{"line_number":175,"context_line":"        return [{\"key\": k, \"values\": v[0] / v[1]}"},{"line_number":176,"context_line":"                for k, v in self.data.items()]"},{"line_number":177,"context_line":""},{"line_number":178,"context_line":""}],"source_content_type":"text/x-python","patch_set":12,"id":"1a6ced46_7c9ff95f","line":175,"in_reply_to":"9a80dd14_67d16956","updated":"2015-03-23 15:45:43.000000000","message":"This will be always float, because we have `1.\u0027 (point is important) as initial value at L172:\n\n self.data[name] \u003d (value or 0), 1.","commit_id":"2f59b3730624ff96e4e85c28ccb72542557986b0"},{"author":{"_account_id":8507,"name":"Mikhail Dubov","email":"mdubov@mirantis.com","username":"msdubov"},"change_message_id":"81284b88319f8469d009d028a8c6bcdd5406e386","unresolved":false,"context_lines":[{"line_number":23,"context_line":"# NOTE(amaretskiy): Functions `average\u0027 and `percentile\u0027 below are copied"},{"line_number":24,"context_line":"#                   from `utils\u0027, because this module is deprecated"},{"line_number":25,"context_line":"#                   and will be completely removed soon"},{"line_number":26,"context_line":"def average(values):"},{"line_number":27,"context_line":"    \"\"\"Find the simple average of a list of values."},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"    :param values: non-empty list of numbers"}],"source_content_type":"text/x-python","patch_set":13,"id":"1a6ced46_034041a4","line":26,"updated":"2015-03-24 11:48:22.000000000","message":"So I believe \u0027average\u0027 and \u0027percentile\u0027 should be left in the processing.utils module. These methods are pretty abstract and will be used not only in charts but in other places as well.\n\nAlso I would prefer to rename \u0027average\u0027 -\u003e \u0027mean\u0027","commit_id":"ef76922257a53d7fdb6e7ff857420152422a2a80"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"d2e4791c20c24c8b695b06519d7de5abe1577a4f","unresolved":false,"context_lines":[{"line_number":23,"context_line":"# NOTE(amaretskiy): Functions `average\u0027 and `percentile\u0027 below are copied"},{"line_number":24,"context_line":"#                   from `utils\u0027, because this module is deprecated"},{"line_number":25,"context_line":"#                   and will be completely removed soon"},{"line_number":26,"context_line":"def average(values):"},{"line_number":27,"context_line":"    \"\"\"Find the simple average of a list of values."},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"    :param values: non-empty list of numbers"}],"source_content_type":"text/x-python","patch_set":13,"id":"1a6ced46_ebdbea18","line":26,"in_reply_to":"1a6ced46_034041a4","updated":"2015-03-24 17:10:23.000000000","message":"Ok","commit_id":"ef76922257a53d7fdb6e7ff857420152422a2a80"},{"author":{"_account_id":8507,"name":"Mikhail Dubov","email":"mdubov@mirantis.com","username":"msdubov"},"change_message_id":"81284b88319f8469d009d028a8c6bcdd5406e386","unresolved":false,"context_lines":[{"line_number":185,"context_line":"        :param name: str name for X axis"},{"line_number":186,"context_line":"        :param tstamp_start: float start timestamp of first iteration"},{"line_number":187,"context_line":"        :param duration: float scenario duration, seconds"},{"line_number":188,"context_line":"        :param ratio: int number of X points"},{"line_number":189,"context_line":"        \"\"\""},{"line_number":190,"context_line":"        super(LoadProfileChart, self).__init__()"},{"line_number":191,"context_line":"        self._name \u003d name"}],"source_content_type":"text/x-python","patch_set":13,"id":"1a6ced46_634ad5ad","line":188,"updated":"2015-03-24 11:48:22.000000000","message":"Wouldn\u0027t \u0027scale\u0027 be a more appropriate name for this parameter?","commit_id":"ef76922257a53d7fdb6e7ff857420152422a2a80"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"d2e4791c20c24c8b695b06519d7de5abe1577a4f","unresolved":false,"context_lines":[{"line_number":185,"context_line":"        :param name: str name for X axis"},{"line_number":186,"context_line":"        :param tstamp_start: float start timestamp of first iteration"},{"line_number":187,"context_line":"        :param duration: float scenario duration, seconds"},{"line_number":188,"context_line":"        :param ratio: int number of X points"},{"line_number":189,"context_line":"        \"\"\""},{"line_number":190,"context_line":"        super(LoadProfileChart, self).__init__()"},{"line_number":191,"context_line":"        self._name \u003d name"}],"source_content_type":"text/x-python","patch_set":13,"id":"1a6ced46_8b02766d","line":188,"in_reply_to":"1a6ced46_634ad5ad","updated":"2015-03-24 17:10:23.000000000","message":"Agreed","commit_id":"ef76922257a53d7fdb6e7ff857420152422a2a80"},{"author":{"_account_id":8507,"name":"Mikhail Dubov","email":"mdubov@mirantis.com","username":"msdubov"},"change_message_id":"81284b88319f8469d009d028a8c6bcdd5406e386","unresolved":false,"context_lines":[{"line_number":202,"context_line":"        #   ratio  duration       step (initial)    accuracy  step"},{"line_number":203,"context_line":"        #   200    30.8043010235  0.154021505117    1         0.2"},{"line_number":204,"context_line":"        #   200    1.25884699821  0.00629423499107  3         0.006"},{"line_number":205,"context_line":"        step \u003d duration / float(ratio)"},{"line_number":206,"context_line":"        for accuracy in range(5):"},{"line_number":207,"context_line":"            if step \u003e (10 ** -accuracy):"},{"line_number":208,"context_line":"                step \u003d round(step, accuracy)"}],"source_content_type":"text/x-python","patch_set":13,"id":"1a6ced46_83c8b123","line":205,"updated":"2015-03-24 11:48:22.000000000","message":"Also possible division by zero here","commit_id":"ef76922257a53d7fdb6e7ff857420152422a2a80"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"d2e4791c20c24c8b695b06519d7de5abe1577a4f","unresolved":false,"context_lines":[{"line_number":202,"context_line":"        #   ratio  duration       step (initial)    accuracy  step"},{"line_number":203,"context_line":"        #   200    30.8043010235  0.154021505117    1         0.2"},{"line_number":204,"context_line":"        #   200    1.25884699821  0.00629423499107  3         0.006"},{"line_number":205,"context_line":"        step \u003d duration / float(ratio)"},{"line_number":206,"context_line":"        for accuracy in range(5):"},{"line_number":207,"context_line":"            if step \u003e (10 ** -accuracy):"},{"line_number":208,"context_line":"                step \u003d round(step, accuracy)"}],"source_content_type":"text/x-python","patch_set":13,"id":"1a6ced46_8be19600","line":205,"in_reply_to":"1a6ced46_83c8b123","updated":"2015-03-24 17:10:23.000000000","message":"Yes, this is possible, but that is a kind of exceptions that we do expect, because value of ratio is a topic of code, not input data.\n\nAny task data can not cause this error.\n\nI think there is no reason to put extra code to explain what is happening if ratio\u003d0 is given.","commit_id":"ef76922257a53d7fdb6e7ff857420152422a2a80"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"a77b399582a4c50a39b0475e55d89f9ed80ec256","unresolved":false,"context_lines":[{"line_number":27,"context_line":"    \"\"\"Abstract class for charts.\"\"\""},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"    @abc.abstractmethod"},{"line_number":30,"context_line":"    def add_value(self, name, value):"},{"line_number":31,"context_line":"        \"\"\"Process specific named value of an iteration."},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"        For example, this can be iteration duration or some atomic action."}],"source_content_type":"text/x-python","patch_set":14,"id":"da9b358b_83adb533","line":30,"updated":"2015-03-28 16:42:53.000000000","message":"I dislike this interface it is unclear and useless. \n\nI already proposed (even before you started this work) another interface: \n\nit was: \n\nclass Chart(object): \n\n  def __init__(self, itertation_to_value_func\u003dNone, **kw):\n    self.Iteration_to_value_func \u003d iteration_to_value_func\n\n  def add_value(self, iteration):\n    # Here we are using self.Iteration_to_value_func \n   # to get for specific graph values from iteration data\n\n  def render(self): \n    return self\n       \nYou didn\u0027t listen me and did the wrong work that is not aligned with Rally road map. \n\nSorry but I have to put -2 until you fix interface.","commit_id":"60c3f23afc106077f68017fe095e14c40ba782ac"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"7506e51de9b86c61531a54e29ca94b5fb94d6998","unresolved":false,"context_lines":[{"line_number":27,"context_line":"    \"\"\"Abstract class for charts.\"\"\""},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"    @abc.abstractmethod"},{"line_number":30,"context_line":"    def add_value(self, name, value):"},{"line_number":31,"context_line":"        \"\"\"Process specific named value of an iteration."},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"        For example, this can be iteration duration or some atomic action."}],"source_content_type":"text/x-python","patch_set":14,"id":"da9b358b_a47871c5","line":30,"in_reply_to":"da9b358b_83adb533","updated":"2015-03-31 15:24:52.000000000","message":"Okay, this will be done.\n\nBut in the example below there is no way to control that child class will call base class __init__:\n\n class Chart(object):\n     def __init__(self, iteration_to_value_func\u003dNone, **kw):\n         self.iteration_to_value_func \u003d iteration_to_value_func\n\n\n @six.add_metaclass(abc.ABCMeta)\n class SomeChart(Chart):\n\n     # This is missed:\n     #\n     #     super(SomeChart, self).__init__(itertation_to_value_func)\n     #\n     def __init__(foo, bar):\n       self.foo \u003d foo\n       self.bar \u003d bar","commit_id":"60c3f23afc106077f68017fe095e14c40ba782ac"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"a77b399582a4c50a39b0475e55d89f9ed80ec256","unresolved":false,"context_lines":[{"line_number":46,"context_line":"    \"\"\"Abstract class for tables.\"\"\""},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"    @abc.abstractmethod"},{"line_number":49,"context_line":"    def add_value(self):"},{"line_number":50,"context_line":"        \"\"\"Process specific named value of an iteration."},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"        For example, this can be iteration duration or some atomic action."}],"source_content_type":"text/x-python","patch_set":14,"id":"da9b358b_a302f93c","line":49,"updated":"2015-03-28 16:42:53.000000000","message":"What is this? add_value() without any argument \n\nThis seems terrible interface.","commit_id":"60c3f23afc106077f68017fe095e14c40ba782ac"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"39f87435c107a06ef13ba98e2bab46b8b68af0ea","unresolved":false,"context_lines":[{"line_number":46,"context_line":"    \"\"\"Abstract class for tables.\"\"\""},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"    @abc.abstractmethod"},{"line_number":49,"context_line":"    def add_value(self):"},{"line_number":50,"context_line":"        \"\"\"Process specific named value of an iteration."},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"        For example, this can be iteration duration or some atomic action."}],"source_content_type":"text/x-python","patch_set":14,"id":"da9b358b_6c001e02","line":49,"in_reply_to":"da9b358b_a302f93c","updated":"2015-03-31 09:36:11.000000000","message":"This is a kind of misprint, not interface","commit_id":"60c3f23afc106077f68017fe095e14c40ba782ac"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"4e40f22a3c0213efb79b2737fbb3afdbc6fe04bc","unresolved":false,"context_lines":[{"line_number":26,"context_line":"class Chart(object):"},{"line_number":27,"context_line":"    \"\"\"Abstract class for charts.\"\"\""},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"    def __init__(self, iteration_to_values):"},{"line_number":30,"context_line":"        \"\"\"Init chart."},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"        :param iteration_to_values: callable that gets values from iteration"}],"source_content_type":"text/x-python","patch_set":15,"id":"9aa53dc9_153a72cc","line":29,"updated":"2015-04-09 13:01:29.000000000","message":"there should be 2 arguments \n\n   __init__(self, iteration_to_values, benchmark_info)","commit_id":"e20016e31013077188aa66431a042c1da464b5a8"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"4e40f22a3c0213efb79b2737fbb3afdbc6fe04bc","unresolved":false,"context_lines":[{"line_number":31,"context_line":""},{"line_number":32,"context_line":"        :param iteration_to_values: callable that gets values from iteration"},{"line_number":33,"context_line":"        \"\"\""},{"line_number":34,"context_line":"        self._get_values \u003d iteration_to_values"},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"    @abc.abstractmethod"},{"line_number":37,"context_line":"    def add_iteration(self, iteration):"}],"source_content_type":"text/x-python","patch_set":15,"id":"9aa53dc9_0157dc26","line":34,"updated":"2015-04-09 13:01:29.000000000","message":"It\u0027s better to use inheritance in this case","commit_id":"e20016e31013077188aa66431a042c1da464b5a8"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"133b8ccccea966d5abe685c0d8b88b2f50bdd165","unresolved":false,"context_lines":[{"line_number":31,"context_line":""},{"line_number":32,"context_line":"        :param iteration_to_values: callable that gets values from iteration"},{"line_number":33,"context_line":"        \"\"\""},{"line_number":34,"context_line":"        self._get_values \u003d iteration_to_values"},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"    @abc.abstractmethod"},{"line_number":37,"context_line":"    def add_iteration(self, iteration):"}],"source_content_type":"text/x-python","patch_set":15,"id":"7a016987_21df4a3b","line":34,"in_reply_to":"9aa53dc9_0157dc26","updated":"2015-05-22 12:49:17.000000000","message":"Please clarify this - should we exclude argument `iteration_to_values\u0027 form __init__() and add specific abstract method instead?","commit_id":"e20016e31013077188aa66431a042c1da464b5a8"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"4e40f22a3c0213efb79b2737fbb3afdbc6fe04bc","unresolved":false,"context_lines":[{"line_number":48,"context_line":"class StackedAreaChart(Chart):"},{"line_number":49,"context_line":"    \"\"\"Chart for generic stacked area.\"\"\""},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"    def __init__(self, iteration_to_values, size\u003dNone, limit\u003d1000):"},{"line_number":52,"context_line":"        \"\"\"Init chart."},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"        :param iteration_to_values: required by base __init__"}],"source_content_type":"text/x-python","patch_set":15,"id":"9aa53dc9_fdda5ae7","line":51,"updated":"2015-04-09 13:01:29.000000000","message":"Mybe: \n\n  iteration_to_value_fn \n\nso it will be clear that it is function ? \n\nAs well, size is required by algorithm so it shouldn\u0027t be optional argument.\n\nBtw, what if we use iterations_count or amount_of_iterations or iterations_amount ?\n\npoints_limit ? or resolution","commit_id":"e20016e31013077188aa66431a042c1da464b5a8"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"4e40f22a3c0213efb79b2737fbb3afdbc6fe04bc","unresolved":false,"context_lines":[{"line_number":49,"context_line":"    \"\"\"Chart for generic stacked area.\"\"\""},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"    def __init__(self, iteration_to_values, size\u003dNone, limit\u003d1000):"},{"line_number":52,"context_line":"        \"\"\"Init chart."},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"        :param iteration_to_values: required by base __init__"},{"line_number":55,"context_line":"        :param size: int times add_iteration() is expected to be called"}],"source_content_type":"text/x-python","patch_set":15,"id":"9aa53dc9_7df52a55","line":52,"updated":"2015-04-09 13:01:29.000000000","message":"Init char - seems like invalid, maybe it makes sense to be more precise?","commit_id":"e20016e31013077188aa66431a042c1da464b5a8"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"4e40f22a3c0213efb79b2737fbb3afdbc6fe04bc","unresolved":false,"context_lines":[{"line_number":51,"context_line":"    def __init__(self, iteration_to_values, size\u003dNone, limit\u003d1000):"},{"line_number":52,"context_line":"        \"\"\"Init chart."},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"        :param iteration_to_values: required by base __init__"},{"line_number":55,"context_line":"        :param size: int times add_iteration() is expected to be called"},{"line_number":56,"context_line":"        :param limit: int, max length of result key values list"},{"line_number":57,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":15,"id":"9aa53dc9_413de4c2","line":54,"updated":"2015-04-09 13:01:29.000000000","message":"This is absolute common phrase that doesn\u0027t cover even such thing like iteration_to_value is callable and what it accept as input and what it returns.","commit_id":"e20016e31013077188aa66431a042c1da464b5a8"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"4e40f22a3c0213efb79b2737fbb3afdbc6fe04bc","unresolved":false,"context_lines":[{"line_number":59,"context_line":"        self.data \u003d {}"},{"line_number":60,"context_line":"        self.size \u003d size"},{"line_number":61,"context_line":"        self.limit \u003d limit"},{"line_number":62,"context_line":"        self.normalize \u003d lambda x: x and round(float(x), 2) or 0.0"},{"line_number":63,"context_line":"        self.merge \u003d lambda a, b: self.normalize((a + self.normalize(b)) / 2)"},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"        # For determining which rows should be merged we are using `factor\u0027"}],"source_content_type":"text/x-python","patch_set":15,"id":"9aa53dc9_e1f75857","line":62,"updated":"2015-04-09 13:01:29.000000000","message":"This doesn\u0027t work for short living benchmark scenarios\n\n  \u003e\u003e\u003e round(float(0.004), 2)\n  0.0\n  \u003e\u003e\u003e round(float(0.003), 2)\n  0.0\n  \u003e\u003e\u003e round(float(0.010), 2)\n  0.01\n  \u003e\u003e\u003e round(float(0.005), 2)\n  0.01\n\n\nWe should get it from self.benchmark_info[\"avg\"]","commit_id":"e20016e31013077188aa66431a042c1da464b5a8"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"4e40f22a3c0213efb79b2737fbb3afdbc6fe04bc","unresolved":false,"context_lines":[{"line_number":65,"context_line":"        # For determining which rows should be merged we are using `factor\u0027"},{"line_number":66,"context_line":"        # e.g. if we have 100 rows and should reduce it to 75 then we have"},{"line_number":67,"context_line":"        # factor of 0.25 and delete (merge with previous) each 4th row."},{"line_number":68,"context_line":"        self.factor \u003d size and float(limit) / size or 1"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"    def add_iteration(self, iteration):"},{"line_number":71,"context_line":"        for name, value in self._get_values(iteration):"}],"source_content_type":"text/x-python","patch_set":15,"id":"9aa53dc9_018fdc75","line":68,"updated":"2015-04-09 13:01:29.000000000","message":"self.factor \u003d size \u003e limit and float(limit) / size or 1","commit_id":"e20016e31013077188aa66431a042c1da464b5a8"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"5eab68bbc5ea0e726a8847406428b59911c7bda5","unresolved":false,"context_lines":[{"line_number":23,"context_line":""},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"@six.add_metaclass(abc.ABCMeta)"},{"line_number":26,"context_line":"class Chart(object):"},{"line_number":27,"context_line":"    \"\"\"Abstract class for charts.\"\"\""},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"    def __init__(self, scenario_info):"}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_8d96773c","line":26,"updated":"2015-05-29 01:47:34.000000000","message":"IMHO: \n\n  - get_values (or better map_iteration_values)\n  - round\n\nshould be private methods (because they shouldn\u0027t be called outside of Chart subclasess)","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"48e0c2ac4c95f9c495dcc561850125fc2c7492d4","unresolved":false,"context_lines":[{"line_number":23,"context_line":""},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"@six.add_metaclass(abc.ABCMeta)"},{"line_number":26,"context_line":"class Chart(object):"},{"line_number":27,"context_line":"    \"\"\"Abstract class for charts.\"\"\""},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"    def __init__(self, scenario_info):"}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_95f0b5fe","line":26,"in_reply_to":"7a016987_8d96773c","updated":"2015-05-29 09:49:26.000000000","message":"For true private methods `__*\u0027 inheritance will not work, so I will just add single leading underscore","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"aa0293fabce6ef09b2f0eb627ae7b6036a0b3ad6","unresolved":false,"context_lines":[{"line_number":23,"context_line":""},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"@six.add_metaclass(abc.ABCMeta)"},{"line_number":26,"context_line":"class Chart(object):"},{"line_number":27,"context_line":"    \"\"\"Abstract class for charts.\"\"\""},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"    def __init__(self, scenario_info):"}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_5a1a6970","line":26,"in_reply_to":"7a016987_95f0b5fe","updated":"2015-05-29 10:25:02.000000000","message":"I was talking about fake private methods with one \"_\"\nDon\u0027t use __","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"5eab68bbc5ea0e726a8847406428b59911c7bda5","unresolved":false,"context_lines":[{"line_number":26,"context_line":"class Chart(object):"},{"line_number":27,"context_line":"    \"\"\"Abstract class for charts.\"\"\""},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"    def __init__(self, scenario_info):"},{"line_number":30,"context_line":"        \"\"\"Initialize chart - set benchmark info."},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"        :param scenario_info: dict, generalized info about iterations"}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_0d74c733","line":29,"updated":"2015-05-29 01:47:34.000000000","message":"why scenario_info? even in docstring you are saying benchmark info.","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"48e0c2ac4c95f9c495dcc561850125fc2c7492d4","unresolved":false,"context_lines":[{"line_number":26,"context_line":"class Chart(object):"},{"line_number":27,"context_line":"    \"\"\"Abstract class for charts.\"\"\""},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"    def __init__(self, scenario_info):"},{"line_number":30,"context_line":"        \"\"\"Initialize chart - set benchmark info."},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"        :param scenario_info: dict, generalized info about iterations"}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_15ef25ea","line":29,"in_reply_to":"7a016987_0d74c733","updated":"2015-05-29 09:49:26.000000000","message":"That is a question of terminology - what is `task\u0027, `benchmark\u0027 and `scenario\u0027.\n\nI think that we have to keep terms in concrete meanings, to prevent confusion.\n\nFor example, look at html report - there is \"Rally benchmark results\" in the title, and we have results for many scenarios - each scenario has meta data - that is our `scenario_info\u0027.","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"aa0293fabce6ef09b2f0eb627ae7b6036a0b3ad6","unresolved":false,"context_lines":[{"line_number":26,"context_line":"class Chart(object):"},{"line_number":27,"context_line":"    \"\"\"Abstract class for charts.\"\"\""},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"    def __init__(self, scenario_info):"},{"line_number":30,"context_line":"        \"\"\"Initialize chart - set benchmark info."},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"        :param scenario_info: dict, generalized info about iterations"}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_fa2b5580","line":29,"in_reply_to":"7a016987_15ef25ea","updated":"2015-05-29 10:25:02.000000000","message":"this should be benchmark info (because benchmark is everything including sla/and other sutff)","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"5eab68bbc5ea0e726a8847406428b59911c7bda5","unresolved":false,"context_lines":[{"line_number":34,"context_line":"        self._scenario_info \u003d scenario_info"},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"    @abc.abstractmethod"},{"line_number":37,"context_line":"    def get_values(self, iteration):"},{"line_number":38,"context_line":"        \"\"\"Get values for processing, from given iteration.\"\"\""},{"line_number":39,"context_line":""},{"line_number":40,"context_line":"    @abc.abstractmethod"}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_4dd07f1f","line":37,"updated":"2015-05-29 01:47:34.000000000","message":"actually seems like it\u0027s move like: \n\n  _map_iteration_values","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"48e0c2ac4c95f9c495dcc561850125fc2c7492d4","unresolved":false,"context_lines":[{"line_number":34,"context_line":"        self._scenario_info \u003d scenario_info"},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"    @abc.abstractmethod"},{"line_number":37,"context_line":"    def get_values(self, iteration):"},{"line_number":38,"context_line":"        \"\"\"Get values for processing, from given iteration.\"\"\""},{"line_number":39,"context_line":""},{"line_number":40,"context_line":"    @abc.abstractmethod"}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_5597dd47","line":37,"in_reply_to":"7a016987_4dd07f1f","updated":"2015-05-29 09:49:26.000000000","message":"Ok","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"5eab68bbc5ea0e726a8847406428b59911c7bda5","unresolved":false,"context_lines":[{"line_number":53,"context_line":""},{"line_number":54,"context_line":"        This will try to round value to some non-zero result,"},{"line_number":55,"context_line":"        starting from 2 digits after point."},{"line_number":56,"context_line":"        Minimal round accuracy allows to draw JavaScript graphs faster."},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"        :param value: numeric value"},{"line_number":59,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_ad7a5386","line":56,"updated":"2015-05-29 01:47:34.000000000","message":"hm? maybe just more pretty?","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"48e0c2ac4c95f9c495dcc561850125fc2c7492d4","unresolved":false,"context_lines":[{"line_number":53,"context_line":""},{"line_number":54,"context_line":"        This will try to round value to some non-zero result,"},{"line_number":55,"context_line":"        starting from 2 digits after point."},{"line_number":56,"context_line":"        Minimal round accuracy allows to draw JavaScript graphs faster."},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"        :param value: numeric value"},{"line_number":59,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_f5d5a9e4","line":56,"in_reply_to":"7a016987_ad7a5386","updated":"2015-05-29 09:49:26.000000000","message":"This definitely affects JS perfomance. Not sure about pretty","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"5eab68bbc5ea0e726a8847406428b59911c7bda5","unresolved":false,"context_lines":[{"line_number":58,"context_line":"        :param value: numeric value"},{"line_number":59,"context_line":"        \"\"\""},{"line_number":60,"context_line":"        if not value:"},{"line_number":61,"context_line":"            return 0."},{"line_number":62,"context_line":"        for i in range(2, 5):"},{"line_number":63,"context_line":"            rounded \u003d round(value, i)"},{"line_number":64,"context_line":"            if rounded:"}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_cd9c6fc2","line":61,"updated":"2015-05-29 01:47:34.000000000","message":"This can be a potential source of hidden bugs. \n\nlet\u0027s do it in proper way: \n\n   if not isinstance(1, (int, float)): \n       raise ValueError","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"48e0c2ac4c95f9c495dcc561850125fc2c7492d4","unresolved":false,"context_lines":[{"line_number":58,"context_line":"        :param value: numeric value"},{"line_number":59,"context_line":"        \"\"\""},{"line_number":60,"context_line":"        if not value:"},{"line_number":61,"context_line":"            return 0."},{"line_number":62,"context_line":"        for i in range(2, 5):"},{"line_number":63,"context_line":"            rounded \u003d round(value, i)"},{"line_number":64,"context_line":"            if rounded:"}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_7537794d","line":61,"in_reply_to":"7a016987_cd9c6fc2","updated":"2015-05-29 09:49:26.000000000","message":"Agreed","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"c523248c70aaabbec7f19966b726f2ccfabdcb81","unresolved":false,"context_lines":[{"line_number":58,"context_line":"        :param value: numeric value"},{"line_number":59,"context_line":"        \"\"\""},{"line_number":60,"context_line":"        if not value:"},{"line_number":61,"context_line":"            return 0."},{"line_number":62,"context_line":"        for i in range(2, 5):"},{"line_number":63,"context_line":"            rounded \u003d round(value, i)"},{"line_number":64,"context_line":"            if rounded:"}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_e12ba180","line":61,"in_reply_to":"7a016987_cd9c6fc2","updated":"2015-05-29 14:03:50.000000000","message":"`if value !\u003d 0\u0027 looks even better","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"5eab68bbc5ea0e726a8847406428b59911c7bda5","unresolved":false,"context_lines":[{"line_number":69,"context_line":"class StackedAreaChart(Chart):"},{"line_number":70,"context_line":"    \"\"\"Abstract class for generic stacked area.\"\"\""},{"line_number":71,"context_line":""},{"line_number":72,"context_line":"    def __init__(self, scenario_info, limit\u003d1000):"},{"line_number":73,"context_line":"        \"\"\"Init chart."},{"line_number":74,"context_line":""},{"line_number":75,"context_line":"        :param scenario_info: dict, benchmark information"}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_0dc28734","line":72,"updated":"2015-05-29 01:47:34.000000000","message":"limit is to abstract name for variable.\n\nWhat about max_points","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"48e0c2ac4c95f9c495dcc561850125fc2c7492d4","unresolved":false,"context_lines":[{"line_number":69,"context_line":"class StackedAreaChart(Chart):"},{"line_number":70,"context_line":"    \"\"\"Abstract class for generic stacked area.\"\"\""},{"line_number":71,"context_line":""},{"line_number":72,"context_line":"    def __init__(self, scenario_info, limit\u003d1000):"},{"line_number":73,"context_line":"        \"\"\"Init chart."},{"line_number":74,"context_line":""},{"line_number":75,"context_line":"        :param scenario_info: dict, benchmark information"}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_b51851d4","line":72,"in_reply_to":"7a016987_0dc28734","updated":"2015-05-29 09:49:26.000000000","message":"Agreed","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"5eab68bbc5ea0e726a8847406428b59911c7bda5","unresolved":false,"context_lines":[{"line_number":73,"context_line":"        \"\"\"Init chart."},{"line_number":74,"context_line":""},{"line_number":75,"context_line":"        :param scenario_info: dict, benchmark information"},{"line_number":76,"context_line":"        :param limit: int, max length of result key values list"},{"line_number":77,"context_line":"        \"\"\""},{"line_number":78,"context_line":"        super(StackedAreaChart, self).__init__(scenario_info)"},{"line_number":79,"context_line":"        self.data \u003d {}"}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_0dd96722","line":76,"updated":"2015-05-29 01:47:34.000000000","message":"max of points that are used to render graph, if there is more values they will be merged","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"48e0c2ac4c95f9c495dcc561850125fc2c7492d4","unresolved":false,"context_lines":[{"line_number":73,"context_line":"        \"\"\"Init chart."},{"line_number":74,"context_line":""},{"line_number":75,"context_line":"        :param scenario_info: dict, benchmark information"},{"line_number":76,"context_line":"        :param limit: int, max length of result key values list"},{"line_number":77,"context_line":"        \"\"\""},{"line_number":78,"context_line":"        super(StackedAreaChart, self).__init__(scenario_info)"},{"line_number":79,"context_line":"        self.data \u003d {}"}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_35010139","line":76,"in_reply_to":"7a016987_0dd96722","updated":"2015-05-29 09:49:26.000000000","message":"Agreed","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"5eab68bbc5ea0e726a8847406428b59911c7bda5","unresolved":false,"context_lines":[{"line_number":77,"context_line":"        \"\"\""},{"line_number":78,"context_line":"        super(StackedAreaChart, self).__init__(scenario_info)"},{"line_number":79,"context_line":"        self.data \u003d {}"},{"line_number":80,"context_line":"        self.size \u003d scenario_info[\"iterations_count\"]"},{"line_number":81,"context_line":"        self.limit \u003d limit"},{"line_number":82,"context_line":"        self.merge \u003d lambda a, b: self.round((a + self.round(b)) / 2)"},{"line_number":83,"context_line":""}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_2df7838c","line":80,"updated":"2015-05-29 01:47:34.000000000","message":"size is unclear variable. \n\nself.total_points ?","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"48e0c2ac4c95f9c495dcc561850125fc2c7492d4","unresolved":false,"context_lines":[{"line_number":77,"context_line":"        \"\"\""},{"line_number":78,"context_line":"        super(StackedAreaChart, self).__init__(scenario_info)"},{"line_number":79,"context_line":"        self.data \u003d {}"},{"line_number":80,"context_line":"        self.size \u003d scenario_info[\"iterations_count\"]"},{"line_number":81,"context_line":"        self.limit \u003d limit"},{"line_number":82,"context_line":"        self.merge \u003d lambda a, b: self.round((a + self.round(b)) / 2)"},{"line_number":83,"context_line":""}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_75b89975","line":80,"in_reply_to":"7a016987_2df7838c","updated":"2015-05-29 09:49:26.000000000","message":"Agreed","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"5eab68bbc5ea0e726a8847406428b59911c7bda5","unresolved":false,"context_lines":[{"line_number":78,"context_line":"        super(StackedAreaChart, self).__init__(scenario_info)"},{"line_number":79,"context_line":"        self.data \u003d {}"},{"line_number":80,"context_line":"        self.size \u003d scenario_info[\"iterations_count\"]"},{"line_number":81,"context_line":"        self.limit \u003d limit"},{"line_number":82,"context_line":"        self.merge \u003d lambda a, b: self.round((a + self.round(b)) / 2)"},{"line_number":83,"context_line":""},{"line_number":84,"context_line":"        # For determining which rows should be merged we are using `factor\u0027"}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_0df04790","line":81,"updated":"2015-05-29 01:47:34.000000000","message":"self.max_points","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"48e0c2ac4c95f9c495dcc561850125fc2c7492d4","unresolved":false,"context_lines":[{"line_number":78,"context_line":"        super(StackedAreaChart, self).__init__(scenario_info)"},{"line_number":79,"context_line":"        self.data \u003d {}"},{"line_number":80,"context_line":"        self.size \u003d scenario_info[\"iterations_count\"]"},{"line_number":81,"context_line":"        self.limit \u003d limit"},{"line_number":82,"context_line":"        self.merge \u003d lambda a, b: self.round((a + self.round(b)) / 2)"},{"line_number":83,"context_line":""},{"line_number":84,"context_line":"        # For determining which rows should be merged we are using `factor\u0027"}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_35afc12b","line":81,"in_reply_to":"7a016987_0df04790","updated":"2015-05-29 09:49:26.000000000","message":"Agreed","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"5eab68bbc5ea0e726a8847406428b59911c7bda5","unresolved":false,"context_lines":[{"line_number":79,"context_line":"        self.data \u003d {}"},{"line_number":80,"context_line":"        self.size \u003d scenario_info[\"iterations_count\"]"},{"line_number":81,"context_line":"        self.limit \u003d limit"},{"line_number":82,"context_line":"        self.merge \u003d lambda a, b: self.round((a + self.round(b)) / 2)"},{"line_number":83,"context_line":""},{"line_number":84,"context_line":"        # For determining which rows should be merged we are using `factor\u0027"},{"line_number":85,"context_line":"        # e.g. if we have 100 rows and should reduce it to 75 then we have"}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_cd7a2ff1","line":82,"updated":"2015-05-29 01:47:34.000000000","message":"Use functions instead of lambdas and properties \n\n   def merge_points(a, b): \n      return  self.round((a + self.round(b)) / 2)\n\nWhy you are doing round(b)? Imho if you are trying to safe resources your round method is less optimal then just do (a + b) / 2 and at the during the render procedure just run 1 times render. \n\nBtw round separated values is fully broken approach. \n\nYou should do this during the process of rendering based on point distribution. \n\nFor example if you have set of values 20.00011 20.0002 20.00990 and 20.00553 it will be interesting to see full graph that shows just are from 20 to 20.01 and in your case you will have just N times 20. \n\nSo do round stuff only during render() and based on limit amount of values that you have in memory.","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"48e0c2ac4c95f9c495dcc561850125fc2c7492d4","unresolved":false,"context_lines":[{"line_number":79,"context_line":"        self.data \u003d {}"},{"line_number":80,"context_line":"        self.size \u003d scenario_info[\"iterations_count\"]"},{"line_number":81,"context_line":"        self.limit \u003d limit"},{"line_number":82,"context_line":"        self.merge \u003d lambda a, b: self.round((a + self.round(b)) / 2)"},{"line_number":83,"context_line":""},{"line_number":84,"context_line":"        # For determining which rows should be merged we are using `factor\u0027"},{"line_number":85,"context_line":"        # e.g. if we have 100 rows and should reduce it to 75 then we have"}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_956af5eb","line":82,"in_reply_to":"7a016987_cd7a2ff1","updated":"2015-05-29 09:49:26.000000000","message":"Reasonable","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"5eab68bbc5ea0e726a8847406428b59911c7bda5","unresolved":false,"context_lines":[{"line_number":87,"context_line":"        self.factor \u003d self.size \u003e limit and float(limit) / self.size or 1"},{"line_number":88,"context_line":""},{"line_number":89,"context_line":"    def add_iteration(self, iteration):"},{"line_number":90,"context_line":"        for name, value in self.get_values(iteration):"},{"line_number":91,"context_line":"            if name not in self.data:"},{"line_number":92,"context_line":"                self.data[name] \u003d dict(values\u003d[], factor\u003d0,"},{"line_number":93,"context_line":"                                       index\u003d0, buffered\u003d0)"}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_d85c2f1b","line":90,"updated":"2015-05-29 01:47:34.000000000","message":"what about iterations that has errors (it\u0027s better to not display them) or use special label \"error\" or something like that","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"48e0c2ac4c95f9c495dcc561850125fc2c7492d4","unresolved":false,"context_lines":[{"line_number":87,"context_line":"        self.factor \u003d self.size \u003e limit and float(limit) / self.size or 1"},{"line_number":88,"context_line":""},{"line_number":89,"context_line":"    def add_iteration(self, iteration):"},{"line_number":90,"context_line":"        for name, value in self.get_values(iteration):"},{"line_number":91,"context_line":"            if name not in self.data:"},{"line_number":92,"context_line":"                self.data[name] \u003d dict(values\u003d[], factor\u003d0,"},{"line_number":93,"context_line":"                                       index\u003d0, buffered\u003d0)"}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_352461c3","line":90,"in_reply_to":"7a016987_d85c2f1b","updated":"2015-05-29 09:49:26.000000000","message":"Agreed","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"5eab68bbc5ea0e726a8847406428b59911c7bda5","unresolved":false,"context_lines":[{"line_number":89,"context_line":"    def add_iteration(self, iteration):"},{"line_number":90,"context_line":"        for name, value in self.get_values(iteration):"},{"line_number":91,"context_line":"            if name not in self.data:"},{"line_number":92,"context_line":"                self.data[name] \u003d dict(values\u003d[], factor\u003d0,"},{"line_number":93,"context_line":"                                       index\u003d0, buffered\u003d0)"},{"line_number":94,"context_line":"            self.data[name][\"index\"] +\u003d 1"},{"line_number":95,"context_line":""}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_987a3787","line":92,"updated":"2015-05-29 01:47:34.000000000","message":"We should have the same amount of points for each atomic_action. \n\nIn other words we must get all atomic actions from benchmark_info. Otherwise this code won\u0027t work properly.","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"48e0c2ac4c95f9c495dcc561850125fc2c7492d4","unresolved":false,"context_lines":[{"line_number":89,"context_line":"    def add_iteration(self, iteration):"},{"line_number":90,"context_line":"        for name, value in self.get_values(iteration):"},{"line_number":91,"context_line":"            if name not in self.data:"},{"line_number":92,"context_line":"                self.data[name] \u003d dict(values\u003d[], factor\u003d0,"},{"line_number":93,"context_line":"                                       index\u003d0, buffered\u003d0)"},{"line_number":94,"context_line":"            self.data[name][\"index\"] +\u003d 1"},{"line_number":95,"context_line":""}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_b02cdf99","line":92,"in_reply_to":"7a016987_987a3787","updated":"2015-05-29 09:49:26.000000000","message":"Agreed","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"5eab68bbc5ea0e726a8847406428b59911c7bda5","unresolved":false,"context_lines":[{"line_number":101,"context_line":"            if self.data[name][\"buffered\"]:"},{"line_number":102,"context_line":"                cur_value \u003d self.merge(self.data[name][\"buffered\"], value)"},{"line_number":103,"context_line":"            else:"},{"line_number":104,"context_line":"                cur_value \u003d self.round(value)"},{"line_number":105,"context_line":""},{"line_number":106,"context_line":"            self.data[name][\"factor\"] +\u003d self.factor"},{"line_number":107,"context_line":""}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_3815833f","line":104,"updated":"2015-05-29 01:47:34.000000000","message":"DON\u0027T DO this there is no economy you are working floats and you won\u0027t speed up anything.\n\nactually this will work slower because you have to call N times function do the range (which creates arrays) and so on.","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"48e0c2ac4c95f9c495dcc561850125fc2c7492d4","unresolved":false,"context_lines":[{"line_number":101,"context_line":"            if self.data[name][\"buffered\"]:"},{"line_number":102,"context_line":"                cur_value \u003d self.merge(self.data[name][\"buffered\"], value)"},{"line_number":103,"context_line":"            else:"},{"line_number":104,"context_line":"                cur_value \u003d self.round(value)"},{"line_number":105,"context_line":""},{"line_number":106,"context_line":"            self.data[name][\"factor\"] +\u003d self.factor"},{"line_number":107,"context_line":""}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_30958f86","line":104,"in_reply_to":"7a016987_3815833f","updated":"2015-05-29 09:49:26.000000000","message":"I will investigate that","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"5eab68bbc5ea0e726a8847406428b59911c7bda5","unresolved":false,"context_lines":[{"line_number":113,"context_line":"            else:"},{"line_number":114,"context_line":"                self.data[name][\"buffered\"] \u003d cur_value"},{"line_number":115,"context_line":""},{"line_number":116,"context_line":"    def render(self):"},{"line_number":117,"context_line":"        \"\"\"Generate chart data ready for drawing."},{"line_number":118,"context_line":""},{"line_number":119,"context_line":"        :returns: [{\"key\": str, \"values\": list},...]"}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_cd190f8a","line":116,"updated":"2015-05-29 01:47:34.000000000","message":"Just one more time round should be done here.","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"9c26d80652ceb1113f0ceccddfffe1e3a49d430a","unresolved":false,"context_lines":[{"line_number":113,"context_line":"            else:"},{"line_number":114,"context_line":"                self.data[name][\"buffered\"] \u003d cur_value"},{"line_number":115,"context_line":""},{"line_number":116,"context_line":"    def render(self):"},{"line_number":117,"context_line":"        \"\"\"Generate chart data ready for drawing."},{"line_number":118,"context_line":""},{"line_number":119,"context_line":"        :returns: [{\"key\": str, \"values\": list},...]"}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_afdc75e4","line":116,"in_reply_to":"7a016987_cd190f8a","updated":"2015-05-29 13:56:06.000000000","message":"Reasonable","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"5eab68bbc5ea0e726a8847406428b59911c7bda5","unresolved":false,"context_lines":[{"line_number":138,"context_line":"class AtomicStackedAreaChart(StackedAreaChart):"},{"line_number":139,"context_line":""},{"line_number":140,"context_line":"    def get_values(self, iteration):"},{"line_number":141,"context_line":"        values \u003d list(iteration[\"atomic_actions\"].items())"},{"line_number":142,"context_line":"        if not iteration[\"error\"]:"},{"line_number":143,"context_line":"            values.append((\"total\", iteration[\"duration\"]))"},{"line_number":144,"context_line":"        return values"}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_3898e3bf","line":141,"updated":"2015-05-29 01:47:34.000000000","message":"this information as we disucssed before should be available from benchmark info","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"48e0c2ac4c95f9c495dcc561850125fc2c7492d4","unresolved":false,"context_lines":[{"line_number":138,"context_line":"class AtomicStackedAreaChart(StackedAreaChart):"},{"line_number":139,"context_line":""},{"line_number":140,"context_line":"    def get_values(self, iteration):"},{"line_number":141,"context_line":"        values \u003d list(iteration[\"atomic_actions\"].items())"},{"line_number":142,"context_line":"        if not iteration[\"error\"]:"},{"line_number":143,"context_line":"            values.append((\"total\", iteration[\"duration\"]))"},{"line_number":144,"context_line":"        return values"}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_90c7a397","line":141,"in_reply_to":"7a016987_3898e3bf","updated":"2015-05-29 09:49:26.000000000","message":"Agreed","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"9c26d80652ceb1113f0ceccddfffe1e3a49d430a","unresolved":false,"context_lines":[{"line_number":151,"context_line":"                for name in self._scenario_info[\"output_names\"]]"},{"line_number":152,"context_line":""},{"line_number":153,"context_line":""},{"line_number":154,"context_line":"# NOTE(amaretskiy): I\u0027m not sure that PieChart is the best name,"},{"line_number":155,"context_line":"#                   since this class simply calculates average values"},{"line_number":156,"context_line":"#                   and these values can be displayed not only by Pie."},{"line_number":157,"context_line":"#                   This class actually represents *model* part and it"}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_efcdcd30","line":154,"updated":"2015-05-29 13:56:06.000000000","message":"@Boris, what do you think about this note?","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"5eab68bbc5ea0e726a8847406428b59911c7bda5","unresolved":false,"context_lines":[{"line_number":188,"context_line":"class AtomicPieChart(PieChart):"},{"line_number":189,"context_line":""},{"line_number":190,"context_line":"    def get_values(self, iteration):"},{"line_number":191,"context_line":"        return iteration[\"atomic_actions\"].items()"},{"line_number":192,"context_line":""},{"line_number":193,"context_line":""},{"line_number":194,"context_line":"class HistogramChart(Chart):"}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_78c77b98","line":191,"updated":"2015-05-29 01:47:34.000000000","message":"what about errors?","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"aa0293fabce6ef09b2f0eb627ae7b6036a0b3ad6","unresolved":false,"context_lines":[{"line_number":188,"context_line":"class AtomicPieChart(PieChart):"},{"line_number":189,"context_line":""},{"line_number":190,"context_line":"    def get_values(self, iteration):"},{"line_number":191,"context_line":"        return iteration[\"atomic_actions\"].items()"},{"line_number":192,"context_line":""},{"line_number":193,"context_line":""},{"line_number":194,"context_line":"class HistogramChart(Chart):"}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_dac6599b","line":191,"in_reply_to":"7a016987_7011c703","updated":"2015-05-29 10:25:02.000000000","message":"Let me explain.\n\nTo get all atomic actions (in worst case) you should iterate over the full list of results (only the last iteration has full set of atomic actions).\n\nThis can be done only in one place: during the benchmark execution we will collect all info and provide it directly via benchmark_info that will allow us to generate reports with additive algorithms.","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"48e0c2ac4c95f9c495dcc561850125fc2c7492d4","unresolved":false,"context_lines":[{"line_number":188,"context_line":"class AtomicPieChart(PieChart):"},{"line_number":189,"context_line":""},{"line_number":190,"context_line":"    def get_values(self, iteration):"},{"line_number":191,"context_line":"        return iteration[\"atomic_actions\"].items()"},{"line_number":192,"context_line":""},{"line_number":193,"context_line":""},{"line_number":194,"context_line":"class HistogramChart(Chart):"}],"source_content_type":"text/x-python","patch_set":16,"id":"7a016987_7011c703","line":191,"in_reply_to":"7a016987_78c77b98","updated":"2015-05-29 09:49:26.000000000","message":"Missed atomic actions are set to 0 in plot.py (next patch), but this probably should be re-considered\n\nhttps://review.openstack.org/#/c/146814/39/rally/benchmark/processing/plot.py,cm","commit_id":"f00049fdb29bf07a78847887918d32ce8cd890b8"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"0c62894749c08f772bddda5b67906cc8eb0a8ff8","unresolved":false,"context_lines":[{"line_number":22,"context_line":"from rally.benchmark.processing import utils"},{"line_number":23,"context_line":""},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"class AtomicChartsMixin(object):"},{"line_number":26,"context_line":""},{"line_number":27,"context_line":"    def get_atomic_actions(self, iteration):"},{"line_number":28,"context_line":"        \"\"\"Fix atomic actions integrity.\"\"\""}],"source_content_type":"text/x-python","patch_set":17,"id":"3afb71cf_d531eded","line":25,"updated":"2015-06-06 19:19:38.000000000","message":"Why not just method? I don\u0027t see any reason to keep this as a mixin...","commit_id":"f422d2131a59dd39d887802fc5dfb92a5f6c6318"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"0c62894749c08f772bddda5b67906cc8eb0a8ff8","unresolved":false,"context_lines":[{"line_number":25,"context_line":"class AtomicChartsMixin(object):"},{"line_number":26,"context_line":""},{"line_number":27,"context_line":"    def get_atomic_actions(self, iteration):"},{"line_number":28,"context_line":"        \"\"\"Fix atomic actions integrity.\"\"\""},{"line_number":29,"context_line":"        if (len(self._benchmark_info[\"atomic\"])"},{"line_number":30,"context_line":"                !\u003d len(iteration[\"atomic_actions\"])):"},{"line_number":31,"context_line":"            for name in self._benchmark_info[\"atomic\"]:"}],"source_content_type":"text/x-python","patch_set":17,"id":"3afb71cf_7557d902","line":28,"updated":"2015-06-06 19:19:38.000000000","message":"I see here a lot of mistakes and anit patterns. \n\n  - Method is called \"get\" but it is actually fixing iteration argument\n\n  - Method is called \"get_atomic_actions\" but it return iteration \n\n  - Docs string are too short and absolutely unclear","commit_id":"f422d2131a59dd39d887802fc5dfb92a5f6c6318"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"0c62894749c08f772bddda5b67906cc8eb0a8ff8","unresolved":false,"context_lines":[{"line_number":26,"context_line":""},{"line_number":27,"context_line":"    def get_atomic_actions(self, iteration):"},{"line_number":28,"context_line":"        \"\"\"Fix atomic actions integrity.\"\"\""},{"line_number":29,"context_line":"        if (len(self._benchmark_info[\"atomic\"])"},{"line_number":30,"context_line":"                !\u003d len(iteration[\"atomic_actions\"])):"},{"line_number":31,"context_line":"            for name in self._benchmark_info[\"atomic\"]:"},{"line_number":32,"context_line":"                if name not in iteration[\"atomic_actions\"]:"}],"source_content_type":"text/x-python","patch_set":17,"id":"3afb71cf_b574319c","line":29,"updated":"2015-06-06 19:19:38.000000000","message":"As far as you like to use word \"pattern\" this is typical anti pattern never do the Mixin\u0027s that depends on base class..\n\nso please make this as a method (as I said on 25 line): \n\n  def get_atomic_actions(self, benchmark_info, iteration): \n\n      ....","commit_id":"f422d2131a59dd39d887802fc5dfb92a5f6c6318"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"0c62894749c08f772bddda5b67906cc8eb0a8ff8","unresolved":false,"context_lines":[{"line_number":31,"context_line":"            for name in self._benchmark_info[\"atomic\"]:"},{"line_number":32,"context_line":"                if name not in iteration[\"atomic_actions\"]:"},{"line_number":33,"context_line":"                    iteration[\"atomic_actions\"][name] \u003d 0"},{"line_number":34,"context_line":"        return list(iteration[\"atomic_actions\"].items())"},{"line_number":35,"context_line":""},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"@six.add_metaclass(abc.ABCMeta)"}],"source_content_type":"text/x-python","patch_set":17,"id":"3afb71cf_d5b68d3c","line":34,"updated":"2015-06-06 19:19:38.000000000","message":"This is no pythonic way to do the things: \n\n\n  def fix_atomic_actions(benchmark_info, iteration):\n      for name in benchmark_info[\"atomic_actions\"]:\n          iteration[\"atomic_actions\"].setdefault(name, 0) \n      return iteration","commit_id":"f422d2131a59dd39d887802fc5dfb92a5f6c6318"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"0c62894749c08f772bddda5b67906cc8eb0a8ff8","unresolved":false,"context_lines":[{"line_number":60,"context_line":"    def _map_iteration_values(self, iteration):"},{"line_number":61,"context_line":"        \"\"\"Get values for processing, from given iteration.\"\"\""},{"line_number":62,"context_line":""},{"line_number":63,"context_line":"    def _round(self, value):"},{"line_number":64,"context_line":"        \"\"\"Smart round."},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"        Minimal round accuracy improves JS graphs perfomance."}],"source_content_type":"text/x-python","patch_set":17,"id":"3afb71cf_55817d49","line":63,"updated":"2015-06-06 19:19:38.000000000","message":"This is totally wrong approach and I won\u0027t merge it, please don\u0027t ignore my comments.","commit_id":"f422d2131a59dd39d887802fc5dfb92a5f6c6318"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"840fb72ebdc2304baf265550086518a0f341465a","unresolved":false,"context_lines":[{"line_number":172,"context_line":"                for name in self._benchmark_info[\"output_names\"]]"},{"line_number":173,"context_line":""},{"line_number":174,"context_line":""},{"line_number":175,"context_line":"# NOTE(amaretskiy): I\u0027m not sure that PieChart is the best name,"},{"line_number":176,"context_line":"#                   since this class simply calculates average values"},{"line_number":177,"context_line":"#                   and these values can be displayed not only by Pie."},{"line_number":178,"context_line":"#                   This class actually represents *model* part and it"}],"source_content_type":"text/x-python","patch_set":17,"id":"5afe65bd_5752b314","line":175,"updated":"2015-06-02 15:31:17.000000000","message":"@Boris, please take a look at this note - what do you think?","commit_id":"f422d2131a59dd39d887802fc5dfb92a5f6c6318"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"ea808a2d8bfafda4d450898dd2cb9e6f98fc5eaa","unresolved":false,"context_lines":[{"line_number":40,"context_line":"        #     we have to merge extra values to existent ones. For determining"},{"line_number":41,"context_line":"        #     which values should be merged, we use `factor\u0027. For example:"},{"line_number":42,"context_line":"        #     we have 100 iterations and should reduce them to 75 points,"},{"line_number":43,"context_line":"        #     so factor is 0.25 and we delete (merge) each 4th value."},{"line_number":44,"context_line":"        self.factor \u003d (self.total_points \u003e max_points"},{"line_number":45,"context_line":"                       and (float(max_points) / self.total_points) or 1)"},{"line_number":46,"context_line":""}],"source_content_type":"text/x-python","patch_set":18,"id":"fa32b979_5082e353","line":43,"updated":"2015-06-15 00:19:26.000000000","message":"This comment is totally unclear I don not understand how did you get that each 4th value should be merged. \n\nE.g. let\u0027s assume that I need to get 10 points on the input I have 300 \n10 / 300 \u003d 0.0333333 so I should merge each?? \n\nPlease take a look at my algorithm one more time it covers this case: \n\nBaseStackedArea: \n\n https://review.openstack.org/#/c/152423/1/rally/benchmark/processing/plot2.py\n\nit may doesn\u0027t work out of box I didn\u0027t test it, but the idea is right.. if you can\u0027t make it work please ping me I will finish that algorithm and cover it with unit tests..","commit_id":"a4bd87dbc06e39e841a2f675a9b6517f8fe12d10"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"ea808a2d8bfafda4d450898dd2cb9e6f98fc5eaa","unresolved":false,"context_lines":[{"line_number":53,"context_line":"            if name not in self.data:"},{"line_number":54,"context_line":"                # NOTE(amaretskiy): It is important to use `None\u0027 to mark"},{"line_number":55,"context_line":"                # that buffer is empty, since `0\u0027 is valid buffered value"},{"line_number":56,"context_line":"                self.data[name] \u003d dict(values\u003d[], factor\u003d0, index\u003d0,"},{"line_number":57,"context_line":"                                       buffered\u003dNone)"},{"line_number":58,"context_line":"            self.data[name][\"index\"] +\u003d 1"},{"line_number":59,"context_line":""}],"source_content_type":"text/x-python","patch_set":18,"id":"fa32b979_90906b97","line":56,"updated":"2015-06-15 00:19:26.000000000","message":"you shouldn\u0027t use dict for creation of dicts use {}.\n{} - is faster and shorter (by amount of chars) way to create dicts..","commit_id":"a4bd87dbc06e39e841a2f675a9b6517f8fe12d10"}],"rally/task/processing/charts.py":[{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"bb5c5d7c13be3507d132e91e790031b52072a668","unresolved":false,"context_lines":[{"line_number":78,"context_line":""},{"line_number":79,"context_line":"    def _map_iteration_values(self, iteration):"},{"line_number":80,"context_line":"        if iteration[\"error\"]:"},{"line_number":81,"context_line":"            return [(\"duration\", 0), (\"idle_duration\", 0)]"},{"line_number":82,"context_line":"        return [(\"duration\", iteration[\"duration\"]),"},{"line_number":83,"context_line":"                (\"idle_duration\", iteration[\"idle_duration\"])]"},{"line_number":84,"context_line":""}],"source_content_type":"text/x-python","patch_set":22,"id":"ba3cc151_00809b48","line":81,"updated":"2015-07-10 06:59:43.000000000","message":"As now this code is very simple we can add here some more interesting logic.\n\nE.g. we can draw errors graph as well. \n\n\n   if iteration[\"error\"]: \n      return [(\"failed_duration\", iteration[\"duration\"] + iteration[\"idle_duration\"]), \n                  (\"duration\", 0), (\"idle_duration\", 0)]\n   else: \n      return  [(\"failed_duration\",  0), \n                  (\"duration\", iteration[\"duration\"]), \n                  (\"idle_duration\",  iteration[\"idle_duration\"])]\n\n\nSo we will be able to display 3 lines (and failed_duration can be shown as red one)","commit_id":"1a7608a8c1423dc6cd0b424fe73015ab3f9db247"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"bb5c5d7c13be3507d132e91e790031b52072a668","unresolved":false,"context_lines":[{"line_number":87,"context_line":""},{"line_number":88,"context_line":"    def _map_iteration_values(self, iteration):"},{"line_number":89,"context_line":"        iteration \u003d self.fix_atomic_actions(iteration)"},{"line_number":90,"context_line":"        return list(iteration[\"atomic_actions\"].items())"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":""},{"line_number":93,"context_line":"class OutputStackedAreaChart(StackedAreaChart):"}],"source_content_type":"text/x-python","patch_set":22,"id":"ba3cc151_e0433712","line":90,"updated":"2015-07-10 06:59:43.000000000","message":"I will change this code in the same way as MainStackedAreaChart, e.g. adding failed_duration graphic and values of it will be iteration duration + idle_duration.","commit_id":"1a7608a8c1423dc6cd0b424fe73015ab3f9db247"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"bb5c5d7c13be3507d132e91e790031b52072a668","unresolved":false,"context_lines":[{"line_number":103,"context_line":"    def add_iteration(self, iteration):"},{"line_number":104,"context_line":"        for name, value in self._map_iteration_values(iteration):"},{"line_number":105,"context_line":"            try:"},{"line_number":106,"context_line":"                sum_, num \u003d self._data[name]"},{"line_number":107,"context_line":"                self._data[name] \u003d sum_ + (value or 0), num + 1"},{"line_number":108,"context_line":"            except KeyError:"},{"line_number":109,"context_line":"                self._data[name] \u003d (value or 0), 1.0"}],"source_content_type":"text/x-python","patch_set":22,"id":"ba3cc151_00b41bd2","line":106,"updated":"2015-07-10 06:59:43.000000000","message":"btw we have streaming algorithm for calculating this","commit_id":"1a7608a8c1423dc6cd0b424fe73015ab3f9db247"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"bb5c5d7c13be3507d132e91e790031b52072a668","unresolved":false,"context_lines":[{"line_number":135,"context_line":"    def _init_charts(self):"},{"line_number":136,"context_line":"        \"\"\"Initialize histograms charts with default values.\"\"\""},{"line_number":137,"context_line":""},{"line_number":138,"context_line":"    def views(self, min_value, max_value):"},{"line_number":139,"context_line":"        \"\"\"Generate initial data for each histogram view.\"\"\""},{"line_number":140,"context_line":"        if not self.base_size:"},{"line_number":141,"context_line":"            return []"}],"source_content_type":"text/x-python","patch_set":22,"id":"ba3cc151_a0f3ef9e","line":138,"updated":"2015-07-10 06:59:43.000000000","message":"This should be protected/private method _views because it\u0027s for internal usage. \n\nAnd I would prefer to call better (with verb) e.g.\n\n  def _init_views(....)","commit_id":"1a7608a8c1423dc6cd0b424fe73015ab3f9db247"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"bb5c5d7c13be3507d132e91e790031b52072a668","unresolved":false,"context_lines":[{"line_number":213,"context_line":"        rows \u003d []"},{"line_number":214,"context_line":"        total \u003d None"},{"line_number":215,"context_line":""},{"line_number":216,"context_line":"        for name, values in super(StatsTable, self).render():"},{"line_number":217,"context_line":"            values \u003d [x[1] for x in values]"},{"line_number":218,"context_line":"            data \u003d ["},{"line_number":219,"context_line":"                name,"}],"source_content_type":"text/x-python","patch_set":22,"id":"ba3cc151_7b183876","line":216,"updated":"2015-07-10 06:59:43.000000000","message":"Maybe I am missing something terribly but seems like it\u0027s not what we want to get here. \n\nYou should analyze each point, not to use values from zipped graph.\n\nPlease use streaming alogrithms which resolves exactly this problem (if some are required add them) and do all logic in add_iteration()","commit_id":"1a7608a8c1423dc6cd0b424fe73015ab3f9db247"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"bb5c5d7c13be3507d132e91e790031b52072a668","unresolved":false,"context_lines":[{"line_number":240,"context_line":""},{"line_number":241,"context_line":"class MainStatsTable(StatsTable):"},{"line_number":242,"context_line":""},{"line_number":243,"context_line":"    def _map_iteration_values(self, iteration):"},{"line_number":244,"context_line":"        iteration \u003d self.fix_atomic_actions(iteration)"},{"line_number":245,"context_line":"        values \u003d list(iteration[\"atomic_actions\"].items())"},{"line_number":246,"context_line":"        values.append((\"total\","}],"source_content_type":"text/x-python","patch_set":22,"id":"ba3cc151_9b389cd6","line":243,"updated":"2015-07-10 06:59:43.000000000","message":"same here don\u0027t use Chart and GraphZipper","commit_id":"1a7608a8c1423dc6cd0b424fe73015ab3f9db247"},{"author":{"_account_id":9545,"name":"Andriy Kurilin","email":"andr.kurilin@gmail.com","username":"akurilin"},"change_message_id":"406ce8acb0cee489c616b166014af303396df91e","unresolved":false,"context_lines":[{"line_number":34,"context_line":"        \"\"\""},{"line_number":35,"context_line":"        self._data \u003d costilius.OrderedDict()  # Container for results"},{"line_number":36,"context_line":"        self._benchmark_info \u003d benchmark_info"},{"line_number":37,"context_line":"        self.base_size \u003d benchmark_info[\"iterations_count\"]"},{"line_number":38,"context_line":"        self.zipped_size \u003d zipped_size"},{"line_number":39,"context_line":""},{"line_number":40,"context_line":"    def add_iteration(self, iteration):"}],"source_content_type":"text/x-python","patch_set":27,"id":"1a4dcd0f_c6324a5f","line":37,"updated":"2015-08-05 18:51:36.000000000","message":"it would be nice to:\n\n1) note in docstring that `benchmark_info` should include \"iterations_count\"\n2) handle situations when \"iterations_count\" is missed.\n\nBtw, since this value is so important, maybe it should be transmitted via separate argument?","commit_id":"a808cb0c1277cf8544328e11e3b98e6a6cafc4c8"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"f27ed5b122bf5135876b3f4036fb2b7027803bba","unresolved":false,"context_lines":[{"line_number":34,"context_line":"        \"\"\""},{"line_number":35,"context_line":"        self._data \u003d costilius.OrderedDict()  # Container for results"},{"line_number":36,"context_line":"        self._benchmark_info \u003d benchmark_info"},{"line_number":37,"context_line":"        self.base_size \u003d benchmark_info[\"iterations_count\"]"},{"line_number":38,"context_line":"        self.zipped_size \u003d zipped_size"},{"line_number":39,"context_line":""},{"line_number":40,"context_line":"    def add_iteration(self, iteration):"}],"source_content_type":"text/x-python","patch_set":27,"id":"1a4dcd0f_a42a7a8e","line":37,"in_reply_to":"1a4dcd0f_c6324a5f","updated":"2015-08-06 10:44:05.000000000","message":"1), 2) - will be done\n\nSince `benchmark_info\u0027 represents task metadata that is expected to be stored in database (after upcoming db refactoring), it is better to use this data as-is, without having its part (iterations_count) as separate argument","commit_id":"a808cb0c1277cf8544328e11e3b98e6a6cafc4c8"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"5f5588c6f9fe6f802c1f0775f9fc03a969d41c6b","unresolved":false,"context_lines":[{"line_number":53,"context_line":"        return [(name, points.get_zipped_graph())"},{"line_number":54,"context_line":"                for name, points in self._data.items()]"},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"    def fix_atomic_actions(self, iteration):"},{"line_number":57,"context_line":"        \"\"\"Set `0\u0027 for missed atomic actions."},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"        This method must be used in all cases related to atomic actions."}],"source_content_type":"text/x-python","patch_set":27,"id":"1a4dcd0f_63b48881","line":56,"updated":"2015-08-05 18:46:26.000000000","message":"This is nit but why this method is public? and not _fix_atomic_actions()","commit_id":"a808cb0c1277cf8544328e11e3b98e6a6cafc4c8"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"f27ed5b122bf5135876b3f4036fb2b7027803bba","unresolved":false,"context_lines":[{"line_number":53,"context_line":"        return [(name, points.get_zipped_graph())"},{"line_number":54,"context_line":"                for name, points in self._data.items()]"},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"    def fix_atomic_actions(self, iteration):"},{"line_number":57,"context_line":"        \"\"\"Set `0\u0027 for missed atomic actions."},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"        This method must be used in all cases related to atomic actions."}],"source_content_type":"text/x-python","patch_set":27,"id":"1a4dcd0f_e40ba228","line":56,"in_reply_to":"1a4dcd0f_63b48881","updated":"2015-08-06 10:44:05.000000000","message":"Will be done","commit_id":"a808cb0c1277cf8544328e11e3b98e6a6cafc4c8"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"5f5588c6f9fe6f802c1f0775f9fc03a969d41c6b","unresolved":false,"context_lines":[{"line_number":94,"context_line":"        values \u003d list(iteration[\"atomic_actions\"].items())"},{"line_number":95,"context_line":"        if iteration[\"error\"]:"},{"line_number":96,"context_line":"            values.append((\"failed_duration\","},{"line_number":97,"context_line":"                           iteration[\"duration\"] + iteration[\"idle_duration\"]))"},{"line_number":98,"context_line":"        else:"},{"line_number":99,"context_line":"            values.append((\"failed_duration\", 0))"},{"line_number":100,"context_line":"        return values"}],"source_content_type":"text/x-python","patch_set":27,"id":"1a4dcd0f_46af1ae2","line":97,"updated":"2015-08-05 18:46:26.000000000","message":"So this should be like: \n\n  iteration[\"duration\"] + iteration[\"idle_duration\"] - sum(atomics_duration)","commit_id":"a808cb0c1277cf8544328e11e3b98e6a6cafc4c8"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"f27ed5b122bf5135876b3f4036fb2b7027803bba","unresolved":false,"context_lines":[{"line_number":94,"context_line":"        values \u003d list(iteration[\"atomic_actions\"].items())"},{"line_number":95,"context_line":"        if iteration[\"error\"]:"},{"line_number":96,"context_line":"            values.append((\"failed_duration\","},{"line_number":97,"context_line":"                           iteration[\"duration\"] + iteration[\"idle_duration\"]))"},{"line_number":98,"context_line":"        else:"},{"line_number":99,"context_line":"            values.append((\"failed_duration\", 0))"},{"line_number":100,"context_line":"        return values"}],"source_content_type":"text/x-python","patch_set":27,"id":"1a4dcd0f_47013804","line":97,"in_reply_to":"1a4dcd0f_46af1ae2","updated":"2015-08-06 10:44:05.000000000","message":"Will be done","commit_id":"a808cb0c1277cf8544328e11e3b98e6a6cafc4c8"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"5f5588c6f9fe6f802c1f0775f9fc03a969d41c6b","unresolved":false,"context_lines":[{"line_number":140,"context_line":"        self._init_charts()"},{"line_number":141,"context_line":""},{"line_number":142,"context_line":"    @abc.abstractmethod"},{"line_number":143,"context_line":"    def _init_charts(self):"},{"line_number":144,"context_line":"        \"\"\"Initialize histograms charts with default values.\"\"\""},{"line_number":145,"context_line":""},{"line_number":146,"context_line":"    def _init_views(self, min_value, max_value):"}],"source_content_type":"text/x-python","patch_set":27,"id":"1a4dcd0f_e66ae680","line":143,"updated":"2015-08-05 18:46:26.000000000","message":"Imho it\u0027s better just to do this inside __init__ of subclasses (they were created specially for this case)","commit_id":"a808cb0c1277cf8544328e11e3b98e6a6cafc4c8"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"f27ed5b122bf5135876b3f4036fb2b7027803bba","unresolved":false,"context_lines":[{"line_number":140,"context_line":"        self._init_charts()"},{"line_number":141,"context_line":""},{"line_number":142,"context_line":"    @abc.abstractmethod"},{"line_number":143,"context_line":"    def _init_charts(self):"},{"line_number":144,"context_line":"        \"\"\"Initialize histograms charts with default values.\"\"\""},{"line_number":145,"context_line":""},{"line_number":146,"context_line":"    def _init_views(self, min_value, max_value):"}],"source_content_type":"text/x-python","patch_set":27,"id":"1a4dcd0f_270c2c3a","line":143,"in_reply_to":"1a4dcd0f_e66ae680","updated":"2015-08-06 10:44:05.000000000","message":"Will be done","commit_id":"a808cb0c1277cf8544328e11e3b98e6a6cafc4c8"},{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"5f5588c6f9fe6f802c1f0775f9fc03a969d41c6b","unresolved":false,"context_lines":[{"line_number":216,"context_line":""},{"line_number":217,"context_line":"    @abc.abstractproperty"},{"line_number":218,"context_line":"    def columns(self):"},{"line_number":219,"context_line":"        \"\"\"A list of str columns names.\"\"\""},{"line_number":220,"context_line":""},{"line_number":221,"context_line":"    @abc.abstractmethod"},{"line_number":222,"context_line":"    def _init_columns(self):"}],"source_content_type":"text/x-python","patch_set":27,"id":"1a4dcd0f_8601a26c","line":219,"updated":"2015-08-05 18:46:26.000000000","message":"This class seems over OOP designed....\n\nPlease make it simpler.. without _process_column and columns method and property..","commit_id":"a808cb0c1277cf8544328e11e3b98e6a6cafc4c8"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"f27ed5b122bf5135876b3f4036fb2b7027803bba","unresolved":false,"context_lines":[{"line_number":216,"context_line":""},{"line_number":217,"context_line":"    @abc.abstractproperty"},{"line_number":218,"context_line":"    def columns(self):"},{"line_number":219,"context_line":"        \"\"\"A list of str columns names.\"\"\""},{"line_number":220,"context_line":""},{"line_number":221,"context_line":"    @abc.abstractmethod"},{"line_number":222,"context_line":"    def _init_columns(self):"}],"source_content_type":"text/x-python","patch_set":27,"id":"1a4dcd0f_672d5494","line":219,"in_reply_to":"1a4dcd0f_8601a26c","updated":"2015-08-06 10:44:05.000000000","message":"Will be done.\n\nHowever I did this so to make abstract class StatsTable flexible enough to provide ability to create new custom statistics tables with minimum code","commit_id":"a808cb0c1277cf8544328e11e3b98e6a6cafc4c8"},{"author":{"_account_id":7369,"name":"Sergey Skripnick","email":"sskripnick@mirantis.com","username":"redixin"},"change_message_id":"cd02fde4436b865e0187c480a56dde413a5bdae5","unresolved":false,"context_lines":[{"line_number":94,"context_line":"    def _map_iteration_values(self, iteration):"},{"line_number":95,"context_line":"        iteration \u003d self._fix_atomic_actions(iteration)"},{"line_number":96,"context_line":"        atomics \u003d list(iteration[\"atomic_actions\"].items())"},{"line_number":97,"context_line":"        if iteration[\"error\"]:"},{"line_number":98,"context_line":"            atomics_sum \u003d sum([a[1] for a in atomics])"},{"line_number":99,"context_line":"            atomics.append((\"failed_duration\","},{"line_number":100,"context_line":"                           (iteration[\"duration\"] + iteration[\"idle_duration\"]"}],"source_content_type":"text/x-python","patch_set":28,"id":"1a4dcd0f_df8072f9","line":97,"updated":"2015-08-07 12:07:26.000000000","message":"This may be simplified:\n\n if error:\n   failed_duration \u003d duration + idle_d - sum(atomics)\n else:\n   failed_duration \u003d 0\n atomics.append((\"failed_duration\", failed_duration))","commit_id":"3dbc6761b64c6789da0bf1d16eda8aaddda0910e"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"3e8fcd2696b93f33e5de8b65e8ca2fe72c1c2bbe","unresolved":false,"context_lines":[{"line_number":94,"context_line":"    def _map_iteration_values(self, iteration):"},{"line_number":95,"context_line":"        iteration \u003d self._fix_atomic_actions(iteration)"},{"line_number":96,"context_line":"        atomics \u003d list(iteration[\"atomic_actions\"].items())"},{"line_number":97,"context_line":"        if iteration[\"error\"]:"},{"line_number":98,"context_line":"            atomics_sum \u003d sum([a[1] for a in atomics])"},{"line_number":99,"context_line":"            atomics.append((\"failed_duration\","},{"line_number":100,"context_line":"                           (iteration[\"duration\"] + iteration[\"idle_duration\"]"}],"source_content_type":"text/x-python","patch_set":28,"id":"1a4dcd0f_9523ab55","line":97,"in_reply_to":"1a4dcd0f_df8072f9","updated":"2015-08-07 12:21:35.000000000","message":"Will be done","commit_id":"3dbc6761b64c6789da0bf1d16eda8aaddda0910e"},{"author":{"_account_id":7369,"name":"Sergey Skripnick","email":"sskripnick@mirantis.com","username":"redixin"},"change_message_id":"cd02fde4436b865e0187c480a56dde413a5bdae5","unresolved":false,"context_lines":[{"line_number":163,"context_line":"    def add_iteration(self, iteration):"},{"line_number":164,"context_line":"        for name, value in self._map_iteration_values(iteration):"},{"line_number":165,"context_line":"            if name not in self._data:"},{"line_number":166,"context_line":"                raise KeyError(\"Unexpected histogram name: %s\" % name)"},{"line_number":167,"context_line":"            for i, view in enumerate(self._data[name][\"views\"]):"},{"line_number":168,"context_line":"                for bin_i, bin_v in enumerate(view[\"x\"]):"},{"line_number":169,"context_line":"                    if value \u003c\u003d bin_v:"}],"source_content_type":"text/x-python","patch_set":28,"id":"1a4dcd0f_3aa724be","line":166,"updated":"2015-08-07 12:07:26.000000000","message":"Histogram name?","commit_id":"3dbc6761b64c6789da0bf1d16eda8aaddda0910e"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"3e8fcd2696b93f33e5de8b65e8ca2fe72c1c2bbe","unresolved":false,"context_lines":[{"line_number":163,"context_line":"    def add_iteration(self, iteration):"},{"line_number":164,"context_line":"        for name, value in self._map_iteration_values(iteration):"},{"line_number":165,"context_line":"            if name not in self._data:"},{"line_number":166,"context_line":"                raise KeyError(\"Unexpected histogram name: %s\" % name)"},{"line_number":167,"context_line":"            for i, view in enumerate(self._data[name][\"views\"]):"},{"line_number":168,"context_line":"                for bin_i, bin_v in enumerate(view[\"x\"]):"},{"line_number":169,"context_line":"                    if value \u003c\u003d bin_v:"}],"source_content_type":"text/x-python","patch_set":28,"id":"1a4dcd0f_95164b4a","line":166,"in_reply_to":"1a4dcd0f_3aa724be","updated":"2015-08-07 12:21:35.000000000","message":"Yes, HistogramChart is actually a set of histograms (this is a kind of complex chart) - this is mentioned in docstring and explanation is extended in next patch set","commit_id":"3dbc6761b64c6789da0bf1d16eda8aaddda0910e"},{"author":{"_account_id":7369,"name":"Sergey Skripnick","email":"sskripnick@mirantis.com","username":"redixin"},"change_message_id":"cd02fde4436b865e0187c480a56dde413a5bdae5","unresolved":false,"context_lines":[{"line_number":232,"context_line":"    def render(self):"},{"line_number":233,"context_line":"        \"\"\"Generate table data ready for displaying."},{"line_number":234,"context_line":""},{"line_number":235,"context_line":"        :returns: {\"cols\": [str, ...], \"rows\": [numeric...]}"},{"line_number":236,"context_line":"        \"\"\""},{"line_number":237,"context_line":""},{"line_number":238,"context_line":""}],"source_content_type":"text/x-python","patch_set":28,"id":"1a4dcd0f_7ad5ace2","line":235,"updated":"2015-08-07 12:07:26.000000000","message":"\"rows\" is just list, or list of lists?","commit_id":"3dbc6761b64c6789da0bf1d16eda8aaddda0910e"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"3e8fcd2696b93f33e5de8b65e8ca2fe72c1c2bbe","unresolved":false,"context_lines":[{"line_number":232,"context_line":"    def render(self):"},{"line_number":233,"context_line":"        \"\"\"Generate table data ready for displaying."},{"line_number":234,"context_line":""},{"line_number":235,"context_line":"        :returns: {\"cols\": [str, ...], \"rows\": [numeric...]}"},{"line_number":236,"context_line":"        \"\"\""},{"line_number":237,"context_line":""},{"line_number":238,"context_line":""}],"source_content_type":"text/x-python","patch_set":28,"id":"1a4dcd0f_b566e7ea","line":235,"in_reply_to":"1a4dcd0f_7ad5ace2","updated":"2015-08-07 12:21:35.000000000","message":"list of lists. This will be corrected","commit_id":"3dbc6761b64c6789da0bf1d16eda8aaddda0910e"},{"author":{"_account_id":9545,"name":"Andriy Kurilin","email":"andr.kurilin@gmail.com","username":"akurilin"},"change_message_id":"0520a2e32b97913a525b33bea89ba2d2355ed1d8","unresolved":false,"context_lines":[{"line_number":59,"context_line":"                for name, points in self._data.items()]"},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"    def _fix_atomic_actions(self, iteration):"},{"line_number":62,"context_line":"        \"\"\"Set `0\u0027 for missed atomic actions."},{"line_number":63,"context_line":""},{"line_number":64,"context_line":"        Since some atomic actions can absent in some iterations"},{"line_number":65,"context_line":"        due to failures, this method must be used in all cases"}],"source_content_type":"text/x-python","patch_set":31,"id":"1a4dcd0f_302d4046","line":62,"updated":"2015-08-12 11:40:36.000000000","message":"please, use equal brackets before and after 0.","commit_id":"9df6b2650f9fede82684aae25e58380eb5f031ab"},{"author":{"_account_id":9545,"name":"Andriy Kurilin","email":"andr.kurilin@gmail.com","username":"akurilin"},"change_message_id":"0520a2e32b97913a525b33bea89ba2d2355ed1d8","unresolved":false,"context_lines":[{"line_number":279,"context_line":"                else:"},{"line_number":280,"context_line":"                    row.append(round(column.result(), 3))"},{"line_number":281,"context_line":""},{"line_number":282,"context_line":"            # Save `total\u0027 - it must be appended last"},{"line_number":283,"context_line":"            if name.lower() \u003d\u003d \"total\":"},{"line_number":284,"context_line":"                total \u003d row"},{"line_number":285,"context_line":"                continue"}],"source_content_type":"text/x-python","patch_set":31,"id":"1a4dcd0f_d0cc1c8b","line":282,"updated":"2015-08-12 11:40:36.000000000","message":"same here for total","commit_id":"9df6b2650f9fede82684aae25e58380eb5f031ab"}],"rally/task/processing/plot.py":[{"author":{"_account_id":9545,"name":"Andriy Kurilin","email":"andr.kurilin@gmail.com","username":"akurilin"},"change_message_id":"0520a2e32b97913a525b33bea89ba2d2355ed1d8","unresolved":false,"context_lines":[{"line_number":18,"context_line":""},{"line_number":19,"context_line":"import six"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"from rally.task.processing import histogram as histo"},{"line_number":22,"context_line":"from rally.task.processing import utils"},{"line_number":23,"context_line":"from rally.ui import utils as ui_utils"},{"line_number":24,"context_line":""}],"source_content_type":"text/x-python","patch_set":31,"id":"1a4dcd0f_d07adc23","line":21,"updated":"2015-08-12 11:40:36.000000000","message":"if it used in all places as \"histo\", I prefer to rename module from histogram to histo.","commit_id":"9df6b2650f9fede82684aae25e58380eb5f031ab"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"9ee091dfce7c32b89285e22b072f8fcd20f7491c","unresolved":false,"context_lines":[{"line_number":18,"context_line":""},{"line_number":19,"context_line":"import six"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"from rally.task.processing import histogram as histo"},{"line_number":22,"context_line":"from rally.task.processing import utils"},{"line_number":23,"context_line":"from rally.ui import utils as ui_utils"},{"line_number":24,"context_line":""}],"source_content_type":"text/x-python","patch_set":31,"id":"1a4dcd0f_70ef48b1","line":21,"in_reply_to":"1a4dcd0f_d07adc23","updated":"2015-08-12 11:45:09.000000000","message":"This is legacy module, it will be removed in next patch with usage of new reports classes","commit_id":"9df6b2650f9fede82684aae25e58380eb5f031ab"}],"rally/task/processing/utils.py":[{"author":{"_account_id":6172,"name":"Boris Pavlovic","email":"boris@pavlovic.me","username":"boris-42"},"change_message_id":"5003a951a9398469e38f385eceaa07a0006cacc8","unresolved":false,"context_lines":[{"line_number":18,"context_line":"from rally.common import costilius"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"def mean(values):"},{"line_number":22,"context_line":"    \"\"\"Find simple average of a list of values."},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"    :param values: non-empty list of numbers"}],"source_content_type":"text/x-python","patch_set":22,"id":"ba3cc151_3b7710a1","line":21,"updated":"2015-07-12 18:49:57.000000000","message":"I would prefer to get rid of these methods (and use streaming algorithms)","commit_id":"1a7608a8c1423dc6cd0b424fe73015ab3f9db247"}],"tests/unit/benchmark/processing/test_charts.py":[{"author":{"_account_id":7369,"name":"Sergey Skripnick","email":"sskripnick@mirantis.com","username":"redixin"},"change_message_id":"5d9bad219368e42f875c83980bec0aef319ba1af","unresolved":false,"context_lines":[{"line_number":207,"context_line":"        table \u003d charts.StatsTable(size\u003d10, cols\u003dcols)"},{"line_number":208,"context_line":"        self.assertEqual(table.render(), {\"cols\": cols, \"rows\": []})"},{"line_number":209,"context_line":""},{"line_number":210,"context_line":"        [table.add_value(\"foo\", i) for i in [42, 2, 4]]"},{"line_number":211,"context_line":"        self.assertEqual(table.render(),"},{"line_number":212,"context_line":"                         {\"cols\": cols,"},{"line_number":213,"context_line":"                          \"rows\": [[\"foo\", 2.0, 16.0, 42.0, 34.4, 38.2,"}],"source_content_type":"text/x-python","patch_set":10,"id":"9a80dd14_f02aad8f","line":210,"updated":"2015-03-19 16:22:22.000000000","message":"it would be nice to add \"total\" and also test case for empty data","commit_id":"ace208122d3a42a98edaf4110b0e7e3a98600529"},{"author":{"_account_id":10475,"name":"Alexander Maretskiy","email":"amaretskiy@mirantis.com","username":"maretskiy"},"change_message_id":"2cc940394fea3b4773c2f0d24e71fcbad8694eb8","unresolved":false,"context_lines":[{"line_number":207,"context_line":"        table \u003d charts.StatsTable(size\u003d10, cols\u003dcols)"},{"line_number":208,"context_line":"        self.assertEqual(table.render(), {\"cols\": cols, \"rows\": []})"},{"line_number":209,"context_line":""},{"line_number":210,"context_line":"        [table.add_value(\"foo\", i) for i in [42, 2, 4]]"},{"line_number":211,"context_line":"        self.assertEqual(table.render(),"},{"line_number":212,"context_line":"                         {\"cols\": cols,"},{"line_number":213,"context_line":"                          \"rows\": [[\"foo\", 2.0, 16.0, 42.0, 34.4, 38.2,"}],"source_content_type":"text/x-python","patch_set":10,"id":"9a80dd14_a500d001","line":210,"in_reply_to":"9a80dd14_f02aad8f","updated":"2015-03-20 12:34:28.000000000","message":"empty data is checked at L208","commit_id":"ace208122d3a42a98edaf4110b0e7e3a98600529"}]}
