)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":4190,"name":"lifeless","email":"robertc@robertcollins.net","username":"lifeless"},"change_message_id":"0deed3166c103fef6fdc05bab9d5779a13b357ae","unresolved":false,"context_lines":[{"line_number":13,"context_line":""},{"line_number":14,"context_line":"However, the project requirements check does not use this"},{"line_number":15,"context_line":"information yet and treats say oslo.db and oslo.db[mysql]"},{"line_number":16,"context_line":"lines in reqs/test-reqs the same and errors out. So Nova"},{"line_number":17,"context_line":"for example (I4131e534d4cb12e4888d398fa4fb7c922e369210) is"},{"line_number":18,"context_line":"not able to add oslo.db[fixtures] to its test-requirements"},{"line_number":19,"context_line":"as oslo.db is already in requirements. When we check"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"fa80f949_6e63931b","line":16,"updated":"2015-11-03 22:21:27.000000000","message":"Yeah, this is tricky. However we are fixing pip to deal with this better.","commit_id":"62b16c6c92b487e7fa49900ee2364ff0945ec316"},{"author":{"_account_id":5638,"name":"Davanum Srinivas","email":"davanum@gmail.com","username":"dims-v"},"change_message_id":"7a191fd1b975d27b0ee28ae22692eaa840096400","unresolved":false,"context_lines":[{"line_number":13,"context_line":""},{"line_number":14,"context_line":"However, the project requirements check does not use this"},{"line_number":15,"context_line":"information yet and treats say oslo.db and oslo.db[mysql]"},{"line_number":16,"context_line":"lines in reqs/test-reqs the same and errors out. So Nova"},{"line_number":17,"context_line":"for example (I4131e534d4cb12e4888d398fa4fb7c922e369210) is"},{"line_number":18,"context_line":"not able to add oslo.db[fixtures] to its test-requirements"},{"line_number":19,"context_line":"as oslo.db is already in requirements. When we check"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"fa80f949_02b1768f","line":16,"in_reply_to":"fa80f949_6e63931b","updated":"2015-11-04 03:56:40.000000000","message":"Ack","commit_id":"62b16c6c92b487e7fa49900ee2364ff0945ec316"}],"jenkins/scripts/project-requirements-change.py":[{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"a34f0b00acea176fb9386d03db90a237e2ca4ed2","unresolved":false,"context_lines":[{"line_number":50,"context_line":""},{"line_number":51,"context_line":"    def _has_duplicates(self, bag1, bag2):"},{"line_number":52,"context_line":"        for (r1, line) in bag1:"},{"line_number":53,"context_line":"            for r2 in bag2:"},{"line_number":54,"context_line":"                if r1 \u003d\u003d r2:"},{"line_number":55,"context_line":"                    return True"},{"line_number":56,"context_line":"        return False"}],"source_content_type":"text/x-python","patch_set":4,"id":"fa80f949_f13a09e7","line":53,"updated":"2015-11-03 21:05:54.000000000","message":"Could this be simplified? I don\u0027t know what type bag2 is, does it support __contains__?\n\n  if r1 in bag2:","commit_id":"62b16c6c92b487e7fa49900ee2364ff0945ec316"},{"author":{"_account_id":5638,"name":"Davanum Srinivas","email":"davanum@gmail.com","username":"dims-v"},"change_message_id":"7a191fd1b975d27b0ee28ae22692eaa840096400","unresolved":false,"context_lines":[{"line_number":50,"context_line":""},{"line_number":51,"context_line":"    def _has_duplicates(self, bag1, bag2):"},{"line_number":52,"context_line":"        for (r1, line) in bag1:"},{"line_number":53,"context_line":"            for r2 in bag2:"},{"line_number":54,"context_line":"                if r1 \u003d\u003d r2:"},{"line_number":55,"context_line":"                    return True"},{"line_number":56,"context_line":"        return False"}],"source_content_type":"text/x-python","patch_set":4,"id":"fa80f949_b8e45a3b","line":53,"in_reply_to":"fa80f949_f13a09e7","updated":"2015-11-04 03:56:40.000000000","message":"i got rid of this :)","commit_id":"62b16c6c92b487e7fa49900ee2364ff0945ec316"},{"author":{"_account_id":4190,"name":"lifeless","email":"robertc@robertcollins.net","username":"lifeless"},"change_message_id":"0deed3166c103fef6fdc05bab9d5779a13b357ae","unresolved":false,"context_lines":[{"line_number":78,"context_line":"                    # Comments and other unprocessed lines"},{"line_number":79,"context_line":"                    continue"},{"line_number":80,"context_line":"                if name in reqs:"},{"line_number":81,"context_line":"                    print(\"Requirement %s present in multiple files\" % name)"},{"line_number":82,"context_line":"                    if strict and not \u0027-py\u0027 in fname:"},{"line_number":83,"context_line":"                        if (self._has_duplicates(entries, reqs[name]) and"},{"line_number":84,"context_line":"                                not self.failed):"}],"source_content_type":"text/x-python","patch_set":4,"id":"fa80f949_8e4fd791","line":81,"updated":"2015-11-03 22:21:27.000000000","message":"How about we just drop this check? I\u0027m not sure it actually adds value, since we know that the other jobs on the project succeeded.","commit_id":"62b16c6c92b487e7fa49900ee2364ff0945ec316"},{"author":{"_account_id":5638,"name":"Davanum Srinivas","email":"davanum@gmail.com","username":"dims-v"},"change_message_id":"7a191fd1b975d27b0ee28ae22692eaa840096400","unresolved":false,"context_lines":[{"line_number":78,"context_line":"                    # Comments and other unprocessed lines"},{"line_number":79,"context_line":"                    continue"},{"line_number":80,"context_line":"                if name in reqs:"},{"line_number":81,"context_line":"                    print(\"Requirement %s present in multiple files\" % name)"},{"line_number":82,"context_line":"                    if strict and not \u0027-py\u0027 in fname:"},{"line_number":83,"context_line":"                        if (self._has_duplicates(entries, reqs[name]) and"},{"line_number":84,"context_line":"                                not self.failed):"}],"source_content_type":"text/x-python","patch_set":4,"id":"fa80f949_e27eb2ad","line":81,"in_reply_to":"fa80f949_8e4fd791","updated":"2015-11-04 03:56:40.000000000","message":"from line 80 through 88? Done","commit_id":"62b16c6c92b487e7fa49900ee2364ff0945ec316"},{"author":{"_account_id":4190,"name":"lifeless","email":"robertc@robertcollins.net","username":"lifeless"},"change_message_id":"0deed3166c103fef6fdc05bab9d5779a13b357ae","unresolved":false,"context_lines":[{"line_number":140,"context_line":"    return (r1.package \u003d\u003d r2.package and"},{"line_number":141,"context_line":"            r1.location \u003d\u003d r2.location and"},{"line_number":142,"context_line":"            r1.specifiers \u003d\u003d r2.specifiers and"},{"line_number":143,"context_line":"            r1.markers \u003d\u003d r2.markers)"},{"line_number":144,"context_line":""},{"line_number":145,"context_line":""},{"line_number":146,"context_line":"def main():"}],"source_content_type":"text/x-python","patch_set":4,"id":"fa80f949_d148225e","line":143,"updated":"2015-11-03 22:21:27.000000000","message":"This is missing the comment field, which I believe we still want to force convergence on.","commit_id":"62b16c6c92b487e7fa49900ee2364ff0945ec316"},{"author":{"_account_id":5638,"name":"Davanum Srinivas","email":"davanum@gmail.com","username":"dims-v"},"change_message_id":"7a191fd1b975d27b0ee28ae22692eaa840096400","unresolved":false,"context_lines":[{"line_number":140,"context_line":"    return (r1.package \u003d\u003d r2.package and"},{"line_number":141,"context_line":"            r1.location \u003d\u003d r2.location and"},{"line_number":142,"context_line":"            r1.specifiers \u003d\u003d r2.specifiers and"},{"line_number":143,"context_line":"            r1.markers \u003d\u003d r2.markers)"},{"line_number":144,"context_line":""},{"line_number":145,"context_line":""},{"line_number":146,"context_line":"def main():"}],"source_content_type":"text/x-python","patch_set":4,"id":"fa80f949_42445e73","line":143,"in_reply_to":"fa80f949_d148225e","updated":"2015-11-04 03:56:40.000000000","message":"ok","commit_id":"62b16c6c92b487e7fa49900ee2364ff0945ec316"},{"author":{"_account_id":4190,"name":"lifeless","email":"robertc@robertcollins.net","username":"lifeless"},"change_message_id":"0deed3166c103fef6fdc05bab9d5779a13b357ae","unresolved":false,"context_lines":[{"line_number":232,"context_line":"                            print(\"Requirement %s does not match \""},{"line_number":233,"context_line":"                                  \"openstack/requirements value %s\" % ("},{"line_number":234,"context_line":"                                str(r1), str(r2)))"},{"line_number":235,"context_line":"                            failed \u003d True"},{"line_number":236,"context_line":""},{"line_number":237,"context_line":"    # report the results"},{"line_number":238,"context_line":"    if failed or head_reqs.failed or branch_reqs.failed:"}],"source_content_type":"text/x-python","patch_set":4,"id":"fa80f949_b1b9de30","line":235,"updated":"2015-11-03 22:21:27.000000000","message":"This introduces a new bug: its possible to have just one line of a multiline requirement (where we need different versions for different pythons).\n\nWhat I think you need to do is \n\n for r1, r2 in zip(reqs, global_reqs[name]):\n    if not _compare_requirements(...)...\n       ...\n if len(r1) !\u003d len(global_reqs[name]:\n    failed \u003d True","commit_id":"62b16c6c92b487e7fa49900ee2364ff0945ec316"},{"author":{"_account_id":5638,"name":"Davanum Srinivas","email":"davanum@gmail.com","username":"dims-v"},"change_message_id":"7a191fd1b975d27b0ee28ae22692eaa840096400","unresolved":false,"context_lines":[{"line_number":232,"context_line":"                            print(\"Requirement %s does not match \""},{"line_number":233,"context_line":"                                  \"openstack/requirements value %s\" % ("},{"line_number":234,"context_line":"                                str(r1), str(r2)))"},{"line_number":235,"context_line":"                            failed \u003d True"},{"line_number":236,"context_line":""},{"line_number":237,"context_line":"    # report the results"},{"line_number":238,"context_line":"    if failed or head_reqs.failed or branch_reqs.failed:"}],"source_content_type":"text/x-python","patch_set":4,"id":"fa80f949_98e71640","line":235,"in_reply_to":"fa80f949_b1b9de30","updated":"2015-11-04 03:56:40.000000000","message":"ok i tested with Routes and figured out a solution. thanks!","commit_id":"62b16c6c92b487e7fa49900ee2364ff0945ec316"},{"author":{"_account_id":4190,"name":"lifeless","email":"robertc@robertcollins.net","username":"lifeless"},"change_message_id":"95e5ff83ef964aa9afe0e714dfa5b2386d9f3119","unresolved":false,"context_lines":[{"line_number":232,"context_line":"                        print(\"Requirement %s does not match \""},{"line_number":233,"context_line":"                              \"openstack/requirements value %s\" % ("},{"line_number":234,"context_line":"                                  str(req), str(global_reqs[name])))"},{"line_number":235,"context_line":"                        failed \u003d True"},{"line_number":236,"context_line":""},{"line_number":237,"context_line":"    # report the results"},{"line_number":238,"context_line":"    if failed or head_reqs.failed or branch_reqs.failed:"}],"source_content_type":"text/x-python","patch_set":5,"id":"fa80f949_f86ae219","line":235,"updated":"2015-11-04 04:36:36.000000000","message":"This is missing the reverse check.\n\nSpecifically I\u0027m worried about a patch to a project that deletes one line of a multi-line ruleset. We should error in that case.","commit_id":"75fcc1d1e4f8c9ac964c790e32f7df21696fa4df"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"456d52c9112f21c3ff2b19b79d2902e3e4d664e8","unresolved":false,"context_lines":[{"line_number":239,"context_line":"                if len(reqs) !\u003d len(global_reqs[name]):"},{"line_number":240,"context_line":"                    print(\"Requirement %s does not match \""},{"line_number":241,"context_line":"                          \"openstack/requirements value %s\" % ("},{"line_number":242,"context_line":"                              str(req), str(global_reqs[name])))"},{"line_number":243,"context_line":"                    failed \u003d True"},{"line_number":244,"context_line":""},{"line_number":245,"context_line":"    # report the results"}],"source_content_type":"text/x-python","patch_set":6,"id":"da85f559_1a80218b","line":242,"updated":"2015-11-12 20:41:42.000000000","message":"Should str(req) be str(reqs)?","commit_id":"4b7bd70271b5c76dc9cfa9073969c6def709a6b8"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"c1649fb019c78b400f260dc55e150cb3dd3ba243","unresolved":false,"context_lines":[{"line_number":120,"context_line":"    from openstack_requirements import requirement  # noqa"},{"line_number":121,"context_line":""},{"line_number":122,"context_line":""},{"line_number":123,"context_line":"def _compare_requirements(r1, r2):"},{"line_number":124,"context_line":"    return (r1.package \u003d\u003d r2.package and"},{"line_number":125,"context_line":"            r1.location \u003d\u003d r2.location and"},{"line_number":126,"context_line":"            r1.specifiers \u003d\u003d r2.specifiers and"}],"source_content_type":"text/x-python","patch_set":7,"id":"da85f559_e55c9ef2","line":123,"updated":"2015-11-12 20:53:47.000000000","message":"We don\u0027t include the extra field here, and it would be useful to have a comment explaining why if you have to re-spin this for another reason.","commit_id":"ebbbfd6d8758efc859711cf7d3f91e2ebcc8a802"},{"author":{"_account_id":4190,"name":"lifeless","email":"robertc@robertcollins.net","username":"lifeless"},"change_message_id":"0b3eb6fdc9fa19c6ddf9465b9ff0edfcfc79a46d","unresolved":false,"context_lines":[{"line_number":225,"context_line":"                # only in the extras field, otherwise reqs will have just one"},{"line_number":226,"context_line":"                # entry for oslo.db. So we should make sure that every"},{"line_number":227,"context_line":"                # Requirement in the reqs Set matches an entry in the global"},{"line_number":228,"context_line":"                # Requirement Set."},{"line_number":229,"context_line":"                for req in reqs:"},{"line_number":230,"context_line":"                    if not _is_requirement_in_global_reqs(req,"},{"line_number":231,"context_line":"                                                          global_reqs[name]):"}],"source_content_type":"text/x-python","patch_set":7,"id":"da85f559_39c4bc3e","line":228,"updated":"2015-11-16 00:21:38.000000000","message":"I think this is still subtly wrong, and its why I suggested *not* doing a set based approach but rather a zip based one.\n\nSay we have routes with 2 different constraints.\nThen we have a test dependency on routes with extras, which much share the constraints.\n\nThat would be 4 routes entries, 2 in global-requirements.\n\nSo, we need:\n - the total number of entries to be a positive integral multiple (call it N) of the number of entries in global-requirements.\n - we need each entry (pkg, location, specificiers, markers) in global requirements to occur exactly N times (that is we can\u0027t have the first entry occur once, and the second occur three times)\n - each group to be contained fully within a single file\n   (so that things are actually consistent)\n\nWe can permit:\n - multiple groups in one file (we don\u0027t need to second guess pip, and pip will improve over time)\n\nI realise we\u0027re going around this a few times - sorry, it is complex and having no test suite is urgh.\n\nHere are some tests for you:\n\ng-r:\n routes\u003e1;python_version\u003d\u003d\u00272.7\u0027\n routes\u003e2;python_version\u003d\u003d\u00273.4\u0027\n\ncase 1: should work\nrequirements.txt:\n routes\u003e1;python_version\u003d\u003d\u00272.7\u0027\n routes\u003e2;python_version\u003d\u003d\u00273.4\u0027\ntest-requirements.txt:\n routes[foo]\u003e1;python_version\u003d\u003d\u00272.7\u0027\n routes[foo]\u003e2;python_version\u003d\u003d\u00273.4\u0027\n\ncase 2: should error\nrequirements.txt:\n routes\u003e1;python_version\u003d\u003d\u00272.7\u0027\n routes\u003e2;python_version\u003d\u003d\u00273.4\u0027\ntest-requirements.txt:\n routes[bar]\u003e1;python_version\u003d\u003d\u00272.7\u0027\n routes[foo]\u003e2;python_version\u003d\u003d\u00273.4\u0027\n\ncase 3: should error\nrequirements.txt:\n routes\u003e1;python_version\u003d\u003d\u00272.7\u0027\n routes\u003e2;python_version\u003d\u003d\u00273.4\u0027\n routes[foo]\u003e1;python_version\u003d\u003d\u00272.7\u0027\ntest-requirements.txt:\n routes[foo]\u003e2;python_version\u003d\u003d\u00273.4\u0027\n\ncase 4: should error\nrequirements.txt:\n routes\u003e1;python_version\u003d\u003d\u00272.7\u0027\n routes\u003e2;python_version\u003d\u003d\u00273.4\u0027\ntest-requirements.txt:\n routes[foo]\u003e2;python_version\u003d\u003d\u00273.4\u0027\n\ncase 5: should error\nrequirements.txt:\n routes\u003e1;python_version\u003d\u003d\u00272.7\u0027\n routes\u003e2;python_version\u003d\u003d\u00273.4\u0027\ntest-requirements.txt:\n routes\u003e1;python_version\u003d\u003d\u00272.7\u0027\n routes[foo]\u003e2;python_version\u003d\u003d\u00273.4\u0027\n\ncase 6: should error\nrequirements.txt:\n routes\u003e1;python_version\u003d\u003d\u00272.7\u0027\n routes\u003e2;python_version\u003d\u003d\u00273.4\u0027\ntest-requirements.txt:\n routes[foo];python_version\u003d\u003d\u00272.7\u0027\n routes[foo];python_version\u003d\u003d\u00273.4\u0027\n\nI\u0027ve probably missed a corner case or two, though I hope not :)","commit_id":"ebbbfd6d8758efc859711cf7d3f91e2ebcc8a802"},{"author":{"_account_id":4190,"name":"lifeless","email":"robertc@robertcollins.net","username":"lifeless"},"change_message_id":"61b2f80917495db918dafc6e80d8a79dd16985d6","unresolved":false,"context_lines":[{"line_number":61,"context_line":"                # Comments and other unprocessed lines"},{"line_number":62,"context_line":"                continue"},{"line_number":63,"context_line":"            list \u003d [r for (r, line) in entries]"},{"line_number":64,"context_line":"            if len(list) !\u003d len(set(list)):"},{"line_number":65,"context_line":"                print(\"Requirements file has duplicate entries \""},{"line_number":66,"context_line":"                      \"for package %s : %r.\" % (name, list))"},{"line_number":67,"context_line":"                self.failed \u003d True"}],"source_content_type":"text/x-python","patch_set":8,"id":"9a8ffd7b_a401ae3b","line":64,"updated":"2015-11-30 20:52:53.000000000","message":"This will need to strip out the comment field before comparing I think.\n\nAlso, please don\u0027t use a  builtin as a variable name - breaks readers brains.","commit_id":"4e34665026769836f4e4bad6f2f27c30f4ad8d0b"},{"author":{"_account_id":5638,"name":"Davanum Srinivas","email":"davanum@gmail.com","username":"dims-v"},"change_message_id":"d0d9d5a4c7d4da8dec4dfec78071354b7dcbc219","unresolved":false,"context_lines":[{"line_number":61,"context_line":"                # Comments and other unprocessed lines"},{"line_number":62,"context_line":"                continue"},{"line_number":63,"context_line":"            list \u003d [r for (r, line) in entries]"},{"line_number":64,"context_line":"            if len(list) !\u003d len(set(list)):"},{"line_number":65,"context_line":"                print(\"Requirements file has duplicate entries \""},{"line_number":66,"context_line":"                      \"for package %s : %r.\" % (name, list))"},{"line_number":67,"context_line":"                self.failed \u003d True"}],"source_content_type":"text/x-python","patch_set":8,"id":"9a8ffd7b_3f3a93e8","line":64,"in_reply_to":"9a8ffd7b_a401ae3b","updated":"2015-12-01 02:07:05.000000000","message":"Let me look into this","commit_id":"4e34665026769836f4e4bad6f2f27c30f4ad8d0b"},{"author":{"_account_id":4190,"name":"lifeless","email":"robertc@robertcollins.net","username":"lifeless"},"change_message_id":"61b2f80917495db918dafc6e80d8a79dd16985d6","unresolved":false,"context_lines":[{"line_number":222,"context_line":"                    failed \u003d True"},{"line_number":223,"context_line":"                    raise Exception("},{"line_number":224,"context_line":"                        \"Requirement %s not in openstack/requirements\" %"},{"line_number":225,"context_line":"                        str(reqs))"},{"line_number":226,"context_line":"                if reqs \u003d\u003d global_reqs[name]:"},{"line_number":227,"context_line":"                    continue"},{"line_number":228,"context_line":"                for req in reqs:"}],"source_content_type":"text/x-python","patch_set":8,"id":"9a8ffd7b_20ba816f","line":225,"updated":"2015-11-30 20:52:53.000000000","message":"This raise means that we only find out about one error - please use print() instead - one goal for this code is to report all the errors.","commit_id":"4e34665026769836f4e4bad6f2f27c30f4ad8d0b"},{"author":{"_account_id":5638,"name":"Davanum Srinivas","email":"davanum@gmail.com","username":"dims-v"},"change_message_id":"d0d9d5a4c7d4da8dec4dfec78071354b7dcbc219","unresolved":false,"context_lines":[{"line_number":222,"context_line":"                    failed \u003d True"},{"line_number":223,"context_line":"                    raise Exception("},{"line_number":224,"context_line":"                        \"Requirement %s not in openstack/requirements\" %"},{"line_number":225,"context_line":"                        str(reqs))"},{"line_number":226,"context_line":"                if reqs \u003d\u003d global_reqs[name]:"},{"line_number":227,"context_line":"                    continue"},{"line_number":228,"context_line":"                for req in reqs:"}],"source_content_type":"text/x-python","patch_set":8,"id":"9a8ffd7b_df7d87b2","line":225,"in_reply_to":"9a8ffd7b_20ba816f","updated":"2015-12-01 02:07:05.000000000","message":"Ack i\u0027ll fix this","commit_id":"4e34665026769836f4e4bad6f2f27c30f4ad8d0b"},{"author":{"_account_id":4190,"name":"lifeless","email":"robertc@robertcollins.net","username":"lifeless"},"change_message_id":"61b2f80917495db918dafc6e80d8a79dd16985d6","unresolved":false,"context_lines":[{"line_number":228,"context_line":"                for req in reqs:"},{"line_number":229,"context_line":"                    if req.extras:"},{"line_number":230,"context_line":"                        for extra in req.extras:"},{"line_number":231,"context_line":"                            counts[extra] \u003d counts.get(extra, 0) + 1"},{"line_number":232,"context_line":"                    else:"},{"line_number":233,"context_line":"                        counts[\u0027\u0027] \u003d counts.get(\u0027\u0027, 0) + 1"},{"line_number":234,"context_line":"                    if not _is_requirement_in_global_reqs("}],"source_content_type":"text/x-python","patch_set":8,"id":"9a8ffd7b_e392439f","line":231,"updated":"2015-11-30 20:52:53.000000000","message":"This counting approach is still fragile I think:\n\n foo[bar] \u003e1 ; python_version\u003d\u003d2\n foo[bar] \u003e1 ; python_version\u003d\u003d2\n\nwith\n foo \u003e1 ;python_version\u003d\u003d3\n foo \u003c\u003d1 ; python_version\u003d\u003d2\n\nin g-r \n\nwill have the right count but still not error on anything else.\n\n:/\n\n(this is why I keep saying that set based approaches are going to be a lot harder to get right than zip based approaches).\n\nI think perhaps my critique is unclear, so let me try to make it clearer.\n\nA set based approach is looking at counts / is-in style checks.\n\nA zip based approach sorts into a canonical form both the reference (g-r) and the under-check requirements file, and then walks through in-order with any variation an error.\n\nFor instance:\n\n for name, reqs in freqs.items()\n    if name not in g-r:\n        print ...\n        failed \u003d True\n        continue\n    for reqs in partition_by_extras(reqs):\n        if len(reqs) !\u003d len(gr_reqs[name])):\n            print ...\n            failed \u003d True\n            continue\n        for gr_req, freq in zip(reqs, gr_reqs[name]):\n            if compare_without_extras(gr_req, freq):\n                 print ...\n                 failed \u003d True","commit_id":"4e34665026769836f4e4bad6f2f27c30f4ad8d0b"},{"author":{"_account_id":5638,"name":"Davanum Srinivas","email":"davanum@gmail.com","username":"dims-v"},"change_message_id":"d0d9d5a4c7d4da8dec4dfec78071354b7dcbc219","unresolved":false,"context_lines":[{"line_number":228,"context_line":"                for req in reqs:"},{"line_number":229,"context_line":"                    if req.extras:"},{"line_number":230,"context_line":"                        for extra in req.extras:"},{"line_number":231,"context_line":"                            counts[extra] \u003d counts.get(extra, 0) + 1"},{"line_number":232,"context_line":"                    else:"},{"line_number":233,"context_line":"                        counts[\u0027\u0027] \u003d counts.get(\u0027\u0027, 0) + 1"},{"line_number":234,"context_line":"                    if not _is_requirement_in_global_reqs("}],"source_content_type":"text/x-python","patch_set":8,"id":"9a8ffd7b_1f746fcd","line":231,"in_reply_to":"9a8ffd7b_e392439f","updated":"2015-12-01 02:07:05.000000000","message":"line 65 will catch the condition where \"foo[bar] \u003e1 ; python_version\u003d\u003d2\" is specified twice in a file.","commit_id":"4e34665026769836f4e4bad6f2f27c30f4ad8d0b"},{"author":{"_account_id":11904,"name":"Sean McGinnis","email":"sean.mcginnis@gmail.com","username":"SeanM"},"change_message_id":"1b83db331917980bd772a521c09092092d0ec4d8","unresolved":false,"context_lines":[{"line_number":222,"context_line":"                    continue"},{"line_number":223,"context_line":"                if name not in global_reqs:"},{"line_number":224,"context_line":"                    failed \u003d True"},{"line_number":225,"context_line":"                    raise Exception("},{"line_number":226,"context_line":"                        \"Requirement %s not in openstack/requirements\" %"},{"line_number":227,"context_line":"                        str(reqs))"},{"line_number":228,"context_line":"                if reqs \u003d\u003d global_reqs[name]:"}],"source_content_type":"text/x-python","patch_set":10,"id":"7a740942_30b12490","line":225,"updated":"2015-12-10 20:13:40.000000000","message":"Comment from lifeless in patch set 8 not addressed yet. Should use print() instead.","commit_id":"d7dcd33c74d8fa97b002ec081a8c41df0bac69b3"}]}
