)]}'
{"dragonflow/controller/df_base_app.py":[{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"21e8a1d33fed077ec1696ffed86da385acc28cb3","unresolved":false,"context_lines":[{"line_number":32,"context_line":"        self.nb_api \u003d nb_api"},{"line_number":33,"context_line":"        self._register_events()"},{"line_number":34,"context_line":""},{"line_number":35,"context_line":"    def _register_events(self):"},{"line_number":36,"context_line":"        for attr_name in dir(self):"},{"line_number":37,"context_line":"            try:"},{"line_number":38,"context_line":"                attr \u003d getattr(self, attr_name)"}],"source_content_type":"text/x-python","patch_set":21,"id":"fa31d9ce_645738ca","line":35,"updated":"2017-02-15 11:40:44.000000000","message":"A docstring is definitely needed for this magic","commit_id":"16f6a0e86ae4babe56a2f0e26bd03c4feee4f94b"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"c578e4b42f705946fe1fc8496fc11d947a4ab8bf","unresolved":false,"context_lines":[{"line_number":32,"context_line":"        self.nb_api \u003d nb_api"},{"line_number":33,"context_line":"        self._register_events()"},{"line_number":34,"context_line":""},{"line_number":35,"context_line":"    def _register_events(self):"},{"line_number":36,"context_line":"        for attr_name in dir(self):"},{"line_number":37,"context_line":"            try:"},{"line_number":38,"context_line":"                attr \u003d getattr(self, attr_name)"}],"source_content_type":"text/x-python","patch_set":21,"id":"fa31d9ce_aa9384ff","line":35,"in_reply_to":"fa31d9ce_645738ca","updated":"2017-02-16 12:38:48.000000000","message":"Will here and on the decorator below","commit_id":"16f6a0e86ae4babe56a2f0e26bd03c4feee4f94b"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"21e8a1d33fed077ec1696ffed86da385acc28cb3","unresolved":false,"context_lines":[{"line_number":36,"context_line":"        for attr_name in dir(self):"},{"line_number":37,"context_line":"            try:"},{"line_number":38,"context_line":"                attr \u003d getattr(self, attr_name)"},{"line_number":39,"context_line":"                args \u003d list(attr._register_args)"},{"line_number":40,"context_line":"            except (AttributeError, TypeError):"},{"line_number":41,"context_line":"                continue"},{"line_number":42,"context_line":""}],"source_content_type":"text/x-python","patch_set":21,"id":"fa31d9ce_243aa099","line":39,"range":{"start_line":39,"start_character":16,"end_line":39,"end_character":20},"updated":"2017-02-15 11:40:44.000000000","message":"Maybe rename to \u0027events\u0027?","commit_id":"16f6a0e86ae4babe56a2f0e26bd03c4feee4f94b"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"c578e4b42f705946fe1fc8496fc11d947a4ab8bf","unresolved":false,"context_lines":[{"line_number":36,"context_line":"        for attr_name in dir(self):"},{"line_number":37,"context_line":"            try:"},{"line_number":38,"context_line":"                attr \u003d getattr(self, attr_name)"},{"line_number":39,"context_line":"                args \u003d list(attr._register_args)"},{"line_number":40,"context_line":"            except (AttributeError, TypeError):"},{"line_number":41,"context_line":"                continue"},{"line_number":42,"context_line":""}],"source_content_type":"text/x-python","patch_set":21,"id":"fa31d9ce_6afb4c48","line":39,"range":{"start_line":39,"start_character":16,"end_line":39,"end_character":20},"in_reply_to":"fa31d9ce_243aa099","updated":"2017-02-16 12:38:48.000000000","message":"I don\u0027t think events is quite the right meaning","commit_id":"16f6a0e86ae4babe56a2f0e26bd03c4feee4f94b"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"21e8a1d33fed077ec1696ffed86da385acc28cb3","unresolved":false,"context_lines":[{"line_number":168,"context_line":"                                  app_name\u003dself.__class__.__name__)"},{"line_number":169,"context_line":""},{"line_number":170,"context_line":""},{"line_number":171,"context_line":"def register_event(model, event):"},{"line_number":172,"context_line":"    if event not in model.get_events():"},{"line_number":173,"context_line":"        raise RuntimeError("},{"line_number":174,"context_line":"            _LE(\u0027{0} is not an event of {1}\u0027).format(event, model),"}],"source_content_type":"text/x-python","patch_set":21,"id":"fa31d9ce_a475b064","line":171,"updated":"2017-02-15 11:40:44.000000000","message":"A docstring is definitely needed for this magic","commit_id":"16f6a0e86ae4babe56a2f0e26bd03c4feee4f94b"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"21e8a1d33fed077ec1696ffed86da385acc28cb3","unresolved":false,"context_lines":[{"line_number":177,"context_line":"    def decorator(func):"},{"line_number":178,"context_line":"        if not hasattr(func, \u0027_register_args\u0027):"},{"line_number":179,"context_line":"            func._register_args \u003d []"},{"line_number":180,"context_line":"        func._register_args.append((model, event))"},{"line_number":181,"context_line":"        return func"},{"line_number":182,"context_line":"    return decorator"}],"source_content_type":"text/x-python","patch_set":21,"id":"fa31d9ce_44d6b44f","line":180,"range":{"start_line":180,"start_character":13,"end_line":180,"end_character":27},"updated":"2017-02-15 11:40:44.000000000","message":"Maybe rename to \u0027_registered_events\u0027 ?","commit_id":"16f6a0e86ae4babe56a2f0e26bd03c4feee4f94b"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"c578e4b42f705946fe1fc8496fc11d947a4ab8bf","unresolved":false,"context_lines":[{"line_number":177,"context_line":"    def decorator(func):"},{"line_number":178,"context_line":"        if not hasattr(func, \u0027_register_args\u0027):"},{"line_number":179,"context_line":"            func._register_args \u003d []"},{"line_number":180,"context_line":"        func._register_args.append((model, event))"},{"line_number":181,"context_line":"        return func"},{"line_number":182,"context_line":"    return decorator"}],"source_content_type":"text/x-python","patch_set":21,"id":"fa31d9ce_2aaf942c","line":180,"range":{"start_line":180,"start_character":13,"end_line":180,"end_character":27},"in_reply_to":"fa31d9ce_44d6b44f","updated":"2017-02-16 12:38:48.000000000","message":"I think _register_jobs is a bit more appropriate, will consider better names","commit_id":"16f6a0e86ae4babe56a2f0e26bd03c4feee4f94b"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"35018642302198747702786b5a8d5cd2863c9887","unresolved":false,"context_lines":[{"line_number":31,"context_line":"        self.nb_api \u003d nb_api"},{"line_number":32,"context_line":"        self._register_events()"},{"line_number":33,"context_line":""},{"line_number":34,"context_line":"    def _register_events(self):"},{"line_number":35,"context_line":"        for attr_name in dir(self):"},{"line_number":36,"context_line":"            try:"},{"line_number":37,"context_line":"                attr \u003d getattr(self, attr_name)"}],"source_content_type":"text/x-python","patch_set":30,"id":"da36d5c6_4a1c41c1","line":34,"updated":"2017-02-23 03:03:14.000000000","message":"Still no docstring","commit_id":"beb80311fb6b5c6cc42c61f9aabcec06d4b6d291"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"35018642302198747702786b5a8d5cd2863c9887","unresolved":false,"context_lines":[{"line_number":168,"context_line":"                                  app_name\u003dself.__class__.__name__)"},{"line_number":169,"context_line":""},{"line_number":170,"context_line":""},{"line_number":171,"context_line":"def register_event(model, event):"},{"line_number":172,"context_line":"    if event not in model.get_events():"},{"line_number":173,"context_line":"        raise RuntimeError("},{"line_number":174,"context_line":"            _LE(\u0027{0} is not an event of {1}\u0027).format(event, model),"}],"source_content_type":"text/x-python","patch_set":30,"id":"da36d5c6_ea6fb528","line":171,"updated":"2017-02-23 03:03:14.000000000","message":"docstring still missing","commit_id":"beb80311fb6b5c6cc42c61f9aabcec06d4b6d291"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"35018642302198747702786b5a8d5cd2863c9887","unresolved":false,"context_lines":[{"line_number":177,"context_line":"    def decorator(func):"},{"line_number":178,"context_line":"        if not hasattr(func, \u0027_register_args\u0027):"},{"line_number":179,"context_line":"            func._register_args \u003d []"},{"line_number":180,"context_line":"        func._register_args.append((model, event))"},{"line_number":181,"context_line":"        return func"},{"line_number":182,"context_line":"    return decorator"}],"source_content_type":"text/x-python","patch_set":30,"id":"da36d5c6_4a736115","line":180,"range":{"start_line":180,"start_character":13,"end_line":180,"end_character":27},"updated":"2017-02-23 03:03:14.000000000","message":"jobs doesn\u0027t capture this fully, but it\u0027s better than args. Please rename here and above.","commit_id":"beb80311fb6b5c6cc42c61f9aabcec06d4b6d291"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"598138b8e031f67bc0d14405fac14e13bedc51e8","unresolved":false,"context_lines":[{"line_number":32,"context_line":"        self.nb_api \u003d nb_api"},{"line_number":33,"context_line":"        self._register_events()"},{"line_number":34,"context_line":""},{"line_number":35,"context_line":"    def _register_events(self):"},{"line_number":36,"context_line":"        for attr_name in dir(self):"},{"line_number":37,"context_line":"            try:"},{"line_number":38,"context_line":"                attr \u003d getattr(self, attr_name)"}],"source_content_type":"text/x-python","patch_set":37,"id":"da36d5c6_0449c78e","line":35,"updated":"2017-02-28 11:23:35.000000000","message":"I still can\u0027t see a docstring.","commit_id":"4d3f2ef46f82e65f9822a6ccbf4a3a29f77ef91d"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"38e7ba85e586ea3c315704d9561d6a288db58d8a","unresolved":false,"context_lines":[{"line_number":32,"context_line":"        self.nb_api \u003d nb_api"},{"line_number":33,"context_line":"        self._register_events()"},{"line_number":34,"context_line":""},{"line_number":35,"context_line":"    def _register_events(self):"},{"line_number":36,"context_line":"        for attr_name in dir(self):"},{"line_number":37,"context_line":"            try:"},{"line_number":38,"context_line":"                attr \u003d getattr(self, attr_name)"}],"source_content_type":"text/x-python","patch_set":37,"id":"ba2be162_a1746dcf","line":35,"in_reply_to":"da36d5c6_0449c78e","updated":"2017-03-01 09:51:59.000000000","message":"Done","commit_id":"4d3f2ef46f82e65f9822a6ccbf4a3a29f77ef91d"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"598138b8e031f67bc0d14405fac14e13bedc51e8","unresolved":false,"context_lines":[{"line_number":183,"context_line":"                                  app_name\u003dself.__class__.__name__)"},{"line_number":184,"context_line":""},{"line_number":185,"context_line":""},{"line_number":186,"context_line":"def register_event(model, event):"},{"line_number":187,"context_line":"    if event not in model.get_events():"},{"line_number":188,"context_line":"        raise RuntimeError("},{"line_number":189,"context_line":"            _LE(\u0027{0} is not an event of {1}\u0027).format(event, model),"}],"source_content_type":"text/x-python","patch_set":37,"id":"da36d5c6_845db74a","line":186,"updated":"2017-02-28 11:23:35.000000000","message":"I still can\u0027t see a docstring.","commit_id":"4d3f2ef46f82e65f9822a6ccbf4a3a29f77ef91d"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"38e7ba85e586ea3c315704d9561d6a288db58d8a","unresolved":false,"context_lines":[{"line_number":183,"context_line":"                                  app_name\u003dself.__class__.__name__)"},{"line_number":184,"context_line":""},{"line_number":185,"context_line":""},{"line_number":186,"context_line":"def register_event(model, event):"},{"line_number":187,"context_line":"    if event not in model.get_events():"},{"line_number":188,"context_line":"        raise RuntimeError("},{"line_number":189,"context_line":"            _LE(\u0027{0} is not an event of {1}\u0027).format(event, model),"}],"source_content_type":"text/x-python","patch_set":37,"id":"ba2be162_c1816191","line":186,"in_reply_to":"da36d5c6_845db74a","updated":"2017-03-01 09:51:59.000000000","message":"Done","commit_id":"4d3f2ef46f82e65f9822a6ccbf4a3a29f77ef91d"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"598138b8e031f67bc0d14405fac14e13bedc51e8","unresolved":false,"context_lines":[{"line_number":192,"context_line":"    def decorator(func):"},{"line_number":193,"context_line":"        if not hasattr(func, \u0027_register_args\u0027):"},{"line_number":194,"context_line":"            func._register_args \u003d []"},{"line_number":195,"context_line":"        func._register_args.append((model, event))"},{"line_number":196,"context_line":"        return func"},{"line_number":197,"context_line":"    return decorator"}],"source_content_type":"text/x-python","patch_set":37,"id":"da36d5c6_e454b322","line":195,"range":{"start_line":195,"start_character":13,"end_line":195,"end_character":27},"updated":"2017-02-28 11:23:35.000000000","message":"I still don\u0027t like this name.","commit_id":"4d3f2ef46f82e65f9822a6ccbf4a3a29f77ef91d"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"38e7ba85e586ea3c315704d9561d6a288db58d8a","unresolved":false,"context_lines":[{"line_number":192,"context_line":"    def decorator(func):"},{"line_number":193,"context_line":"        if not hasattr(func, \u0027_register_args\u0027):"},{"line_number":194,"context_line":"            func._register_args \u003d []"},{"line_number":195,"context_line":"        func._register_args.append((model, event))"},{"line_number":196,"context_line":"        return func"},{"line_number":197,"context_line":"    return decorator"}],"source_content_type":"text/x-python","patch_set":37,"id":"ba2be162_e17e65ad","line":195,"range":{"start_line":195,"start_character":13,"end_line":195,"end_character":27},"in_reply_to":"da36d5c6_e454b322","updated":"2017-03-01 09:51:59.000000000","message":"Done","commit_id":"4d3f2ef46f82e65f9822a6ccbf4a3a29f77ef91d"},{"author":{"_account_id":6598,"name":"Berezovsky Irena","email":"irenab.dev@gmail.com","username":"irenab"},"change_message_id":"cd69684b0f4815e003b6248ce8f47cf3026a59b1","unresolved":false,"context_lines":[{"line_number":42,"context_line":"                # NOTE (dimak) list() is needed here because sometimes we have"},{"line_number":43,"context_line":"                # attributes that are mocks (during tests), who will have the"},{"line_number":44,"context_line":"                # _register_events attribute (and any other attribute too)."},{"line_number":45,"context_line":"                # list(mock.Mock()) yiels and empty list so this works out"},{"line_number":46,"context_line":"                # with little effort."},{"line_number":47,"context_line":"                args \u003d list(attr._register_events)"},{"line_number":48,"context_line":"            except (AttributeError, TypeError):"}],"source_content_type":"text/x-python","patch_set":38,"id":"ba2be162_d6403e59","line":45,"range":{"start_line":45,"start_character":42,"end_line":45,"end_character":45},"updated":"2017-03-01 12:03:34.000000000","message":"an?","commit_id":"98e2f952cea81608f31f82c3409d3e50881fcf21"},{"author":{"_account_id":7805,"name":"Li Ma","email":"skywalker.nick@gmail.com","username":"Nick"},"change_message_id":"15628f65830beb1a3f35e0feb7a8cb60bac96f83","unresolved":false,"context_lines":[{"line_number":42,"context_line":"                # NOTE (dimak) list() is needed here because sometimes we have"},{"line_number":43,"context_line":"                # attributes that are mocks (during tests), who will have the"},{"line_number":44,"context_line":"                # _register_events attribute (and any other attribute too)."},{"line_number":45,"context_line":"                # list(mock.Mock()) yiels and empty list so this works out"},{"line_number":46,"context_line":"                # with little effort."},{"line_number":47,"context_line":"                args \u003d list(attr._register_events)"},{"line_number":48,"context_line":"            except (AttributeError, TypeError):"}],"source_content_type":"text/x-python","patch_set":38,"id":"ba2be162_08e1b5fe","line":45,"range":{"start_line":45,"start_character":36,"end_line":45,"end_character":41},"updated":"2017-03-02 00:47:43.000000000","message":"yields?","commit_id":"98e2f952cea81608f31f82c3409d3e50881fcf21"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"dd7eb68c433086a26b5eab9201c253d13e6c8886","unresolved":false,"context_lines":[{"line_number":42,"context_line":"                # NOTE (dimak) list() is needed here because sometimes we have"},{"line_number":43,"context_line":"                # attributes that are mocks (during tests), who will have the"},{"line_number":44,"context_line":"                # _register_events attribute (and any other attribute too)."},{"line_number":45,"context_line":"                # list(mock.Mock()) yiels and empty list so this works out"},{"line_number":46,"context_line":"                # with little effort."},{"line_number":47,"context_line":"                args \u003d list(attr._register_events)"},{"line_number":48,"context_line":"            except (AttributeError, TypeError):"}],"source_content_type":"text/x-python","patch_set":38,"id":"ba2be162_0cda9b78","line":45,"range":{"start_line":45,"start_character":36,"end_line":45,"end_character":41},"in_reply_to":"ba2be162_08e1b5fe","updated":"2017-03-02 08:29:59.000000000","message":"Fixing","commit_id":"98e2f952cea81608f31f82c3409d3e50881fcf21"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"f19fec8b1a0b68ed0bb0509fedc7442347de48c1","unresolved":false,"context_lines":[{"line_number":45,"context_line":"                # list(mock.Mock()) yiels and empty list so this works out"},{"line_number":46,"context_line":"                # with little effort."},{"line_number":47,"context_line":"                args \u003d list(attr._register_events)"},{"line_number":48,"context_line":"            except (AttributeError, TypeError):"},{"line_number":49,"context_line":"                continue"},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"            for model, event in args:"}],"source_content_type":"text/x-python","patch_set":38,"id":"ba2be162_76020e0d","line":48,"range":{"start_line":48,"start_character":20,"end_line":48,"end_character":45},"updated":"2017-03-02 02:30:06.000000000","message":"can you also explain in which case AttributeError or TypeError will be raised. And why it is OK to pass them?","commit_id":"98e2f952cea81608f31f82c3409d3e50881fcf21"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"dd7eb68c433086a26b5eab9201c253d13e6c8886","unresolved":false,"context_lines":[{"line_number":45,"context_line":"                # list(mock.Mock()) yiels and empty list so this works out"},{"line_number":46,"context_line":"                # with little effort."},{"line_number":47,"context_line":"                args \u003d list(attr._register_events)"},{"line_number":48,"context_line":"            except (AttributeError, TypeError):"},{"line_number":49,"context_line":"                continue"},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"            for model, event in args:"}],"source_content_type":"text/x-python","patch_set":38,"id":"ba2be162_cc13230c","line":48,"range":{"start_line":48,"start_character":20,"end_line":48,"end_character":45},"in_reply_to":"ba2be162_76020e0d","updated":"2017-03-02 08:29:59.000000000","message":"Added comment","commit_id":"98e2f952cea81608f31f82c3409d3e50881fcf21"}],"dragonflow/controller/ryu_base_app.py":[{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"520cfd64d5503706e789ba13326182ed4351869b","unresolved":false,"context_lines":[{"line_number":64,"context_line":"    def load(self, *args, **kwargs):"},{"line_number":65,"context_line":"        self.dispatcher.load(*args, **kwargs)"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"    def register_model(self, model):"},{"line_number":68,"context_line":"        table_name \u003d model.table_name"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"        model.register_created("}],"source_content_type":"text/x-python","patch_set":17,"id":"1a430d35_e3a3bf9c","line":67,"range":{"start_line":67,"start_character":8,"end_line":67,"end_character":22},"updated":"2017-02-04 21:00:41.000000000","message":"1. The events are dynamically defined on the model. Maybe register according to what\u0027s there?\n2. Where is this method called? How does it connect to the rest of the picture?","commit_id":"7c85e154b7bab5130d559c4639552106cf140556"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"6fc9ee63706baf544f69f4a1a0758991ba3289c8","unresolved":false,"context_lines":[{"line_number":64,"context_line":"    def load(self, *args, **kwargs):"},{"line_number":65,"context_line":"        self.dispatcher.load(*args, **kwargs)"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"    def register_model(self, model):"},{"line_number":68,"context_line":"        table_name \u003d model.table_name"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"        model.register_created("}],"source_content_type":"text/x-python","patch_set":17,"id":"fa31d9ce_2d0ec334","line":67,"range":{"start_line":67,"start_character":8,"end_line":67,"end_character":22},"in_reply_to":"1a430d35_5e9fea4f","updated":"2017-02-10 08:44:18.000000000","message":"Yes, that sounds better. There will be no \u0027magic\u0027 functions, just handlers. They will be clearly marked.\n\nJust one issue - will we be able to maintain the order of event handling? e.g. if l2_app appears before l3_app in the app-list, then l2_app handles its events before l3_app?","commit_id":"7c85e154b7bab5130d559c4639552106cf140556"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"2c6209e94b58ad05f7dfd290e9976d89daa84fdd","unresolved":false,"context_lines":[{"line_number":64,"context_line":"    def load(self, *args, **kwargs):"},{"line_number":65,"context_line":"        self.dispatcher.load(*args, **kwargs)"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"    def register_model(self, model):"},{"line_number":68,"context_line":"        table_name \u003d model.table_name"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"        model.register_created("}],"source_content_type":"text/x-python","patch_set":17,"id":"1a430d35_5e9fea4f","line":67,"range":{"start_line":67,"start_character":8,"end_line":67,"end_character":22},"in_reply_to":"1a430d35_cc2b4bea","updated":"2017-02-06 11:15:40.000000000","message":"Had another bizarre idea, instead of using ryu base app to dispatch, we can not register here at all, and let each app that wants to register for events do:\n\n@models.Lport.register_created\ndef lport_added(...):\n    ....\n\nThen we don\u0027t need a dispatcher in ryu base app at all, and we don\u0027t have to name methods in a specific pattern.","commit_id":"7c85e154b7bab5130d559c4639552106cf140556"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"4c0422f6723e2d3a5f7e780bebad629c9fe06a80","unresolved":false,"context_lines":[{"line_number":64,"context_line":"    def load(self, *args, **kwargs):"},{"line_number":65,"context_line":"        self.dispatcher.load(*args, **kwargs)"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"    def register_model(self, model):"},{"line_number":68,"context_line":"        table_name \u003d model.table_name"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"        model.register_created("}],"source_content_type":"text/x-python","patch_set":17,"id":"1a430d35_ef3c7e31","line":67,"range":{"start_line":67,"start_character":8,"end_line":67,"end_character":22},"in_reply_to":"1a430d35_e3a3bf9c","updated":"2017-02-05 06:45:16.000000000","message":"This method is called in a subsequent patch from df_local_controller\u0027s initialize.\n\nWe can switch the naming scheme to ${table_name}_${event} e.g. \n\n  * chassis_created\n  * chassis_updated\n  * chassis_deleted\n\nThe pro is that we\u0027ll be able to treat all events equaly in ryu apps, the downside is that we\u0027ll have to rename existing apps...","commit_id":"7c85e154b7bab5130d559c4639552106cf140556"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"546647263fd8d788b93dd2e40fa97f19479d16cf","unresolved":false,"context_lines":[{"line_number":64,"context_line":"    def load(self, *args, **kwargs):"},{"line_number":65,"context_line":"        self.dispatcher.load(*args, **kwargs)"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"    def register_model(self, model):"},{"line_number":68,"context_line":"        table_name \u003d model.table_name"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"        model.register_created("}],"source_content_type":"text/x-python","patch_set":17,"id":"1a430d35_cc2b4bea","line":67,"range":{"start_line":67,"start_character":8,"end_line":67,"end_character":22},"in_reply_to":"1a430d35_ef3c7e31","updated":"2017-02-05 15:21:38.000000000","message":"Sounds like a plan :)","commit_id":"7c85e154b7bab5130d559c4639552106cf140556"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"8206915659e2e24513977bbf225e22956cbb50d3","unresolved":false,"context_lines":[{"line_number":64,"context_line":"    def load(self, *args, **kwargs):"},{"line_number":65,"context_line":"        self.dispatcher.load(*args, **kwargs)"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"    def register_model(self, model):"},{"line_number":68,"context_line":"        for event in model.get_events():"},{"line_number":69,"context_line":"            callback_name \u003d \u0027{table_name}_{event}\u0027.format("},{"line_number":70,"context_line":"                table_name\u003dmodel.table_name,"}],"source_content_type":"text/x-python","patch_set":19,"id":"fa31d9ce_0df3bf0b","line":67,"updated":"2017-02-10 08:49:08.000000000","message":"From PS17:\n\n\u003e\u003e\u003e\u003e Omer Anson 4. Feb 23:00\n\n\u003e\u003e\u003e\u003e 1. The events are dynamically defined on the model. Maybe register according to what\u0027s there?\n2. Where is this method called? How does it connect to the rest of the picture?\n\n\u003e\u003e\u003e Dima Kuznetsov\n5. Feb 08:45\n\n\u003e\u003e\u003e This method is called in a subsequent patch from df_local_controller\u0027s initialize.\n\n\u003e\u003e\u003e We can switch the naming scheme to ${table_name}_${event} e.g. \n\n\u003e\u003e\u003e  * chassis_created\n\u003e\u003e\u003e  * chassis_updated\n\u003e\u003e\u003e  * chassis_deleted\n\n\u003e\u003e\u003e The pro is that we\u0027ll be able to treat all events equaly in ryu apps, the downside is that we\u0027ll have to rename existing apps...\n\u003e\u003e Omer Anson\n5. Feb 17:21\n\n\u003e\u003e Sounds like a plan :)\n\n\u003e Dima Kuznetsov\n6. Feb 13:15\n\n\u003e Had another bizarre idea, instead of using ryu base app to dispatch, we can not register here at all, and let each app that wants to register for events do:\n\n\u003e @models.Lport.register_created\ndef lport_added(...):\n    ....\n\n\u003e Then we don\u0027t need a dispatcher in ryu base app at all, and we don\u0027t have to name methods in a specific pattern.\n\nYes, that sounds better. There will be no \u0027magic\u0027 functions, just handlers. They will be clearly marked.\n\nJust one issue - will we be able to maintain the order of event handling? e.g. if l2_app appears before l3_app in the app-list, then l2_app handles its events before l3_app?","commit_id":"af35b97d1052ce7f8fbdecec591da4ccf10a3315"}],"dragonflow/tests/unit/test_model_framework.py":[{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"35018642302198747702786b5a8d5cd2863c9887","unresolved":false,"context_lines":[{"line_number":201,"context_line":"                m(origin, *args, **kwargs)"},{"line_number":202,"context_line":""},{"line_number":203,"context_line":"        TestApp("},{"line_number":204,"context_line":"            api\u003dmock.MagicMock(),"},{"line_number":205,"context_line":"            db_store\u003dmock.MagicMock(),"},{"line_number":206,"context_line":"            vswitch_api\u003dmock.MagicMock(),"},{"line_number":207,"context_line":"            nb_api\u003dmock.MagicMock(),"},{"line_number":208,"context_line":"        )"},{"line_number":209,"context_line":""},{"line_number":210,"context_line":"        o \u003d ModelTest()"}],"source_content_type":"text/x-python","patch_set":30,"id":"da36d5c6_2a4d4dc4","line":207,"range":{"start_line":204,"start_character":0,"end_line":207,"end_character":36},"updated":"2017-02-23 03:03:14.000000000","message":"nit: I think you can use sentinel here rather than creating a new MagicMock for each parameter, which is then not used / tested.","commit_id":"beb80311fb6b5c6cc42c61f9aabcec06d4b6d291"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"f19fec8b1a0b68ed0bb0509fedc7442347de48c1","unresolved":false,"context_lines":[{"line_number":196,"context_line":"        m \u003d mock.MagicMock()"},{"line_number":197,"context_line":""},{"line_number":198,"context_line":"        class TestApp(df_base_app.DFlowApp):"},{"line_number":199,"context_line":"            @df_base_app.register_event(ModelTest, \u0027created\u0027)"},{"line_number":200,"context_line":"            def test_created_callback(self, origin, *args, **kwargs):"},{"line_number":201,"context_line":"                m(origin, *args, **kwargs)"},{"line_number":202,"context_line":""}],"source_content_type":"text/x-python","patch_set":38,"id":"ba2be162_514c3470","line":199,"range":{"start_line":199,"start_character":52,"end_line":199,"end_character":59},"updated":"2017-03-02 02:30:06.000000000","message":"Is here where we can apply the event constant name?","commit_id":"98e2f952cea81608f31f82c3409d3e50881fcf21"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"dd7eb68c433086a26b5eab9201c253d13e6c8886","unresolved":false,"context_lines":[{"line_number":196,"context_line":"        m \u003d mock.MagicMock()"},{"line_number":197,"context_line":""},{"line_number":198,"context_line":"        class TestApp(df_base_app.DFlowApp):"},{"line_number":199,"context_line":"            @df_base_app.register_event(ModelTest, \u0027created\u0027)"},{"line_number":200,"context_line":"            def test_created_callback(self, origin, *args, **kwargs):"},{"line_number":201,"context_line":"                m(origin, *args, **kwargs)"},{"line_number":202,"context_line":""}],"source_content_type":"text/x-python","patch_set":38,"id":"ba2be162_6c2dd745","line":199,"range":{"start_line":199,"start_character":52,"end_line":199,"end_character":59},"in_reply_to":"ba2be162_514c3470","updated":"2017-03-02 08:29:59.000000000","message":"Changing","commit_id":"98e2f952cea81608f31f82c3409d3e50881fcf21"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"38c1a9d7df6b3f4bdad3fb62b0f93b6b45b3bd59","unresolved":false,"context_lines":[{"line_number":224,"context_line":"        m \u003d mock.MagicMock()"},{"line_number":225,"context_line":""},{"line_number":226,"context_line":"        class TestApp(df_base_app.DFlowApp):"},{"line_number":227,"context_line":"            @df_base_app.register_event(ModelTest, mixins.EVENT_CREATED)"},{"line_number":228,"context_line":"            def test_created_callback(self, origin, *args, **kwargs):"},{"line_number":229,"context_line":"                m(origin, *args, **kwargs)"},{"line_number":230,"context_line":""}],"source_content_type":"text/x-python","patch_set":39,"id":"ba2be162_57713a75","line":227,"range":{"start_line":227,"start_character":58,"end_line":227,"end_character":71},"updated":"2017-03-03 08:13:24.000000000","message":"Maybe it is time to move the constants to a file named \"constant\" or \"common\". It looks strange to access constant from a mixin file, and I think there will be lots of usage of the constants.","commit_id":"0821cf1ad2c305c4dd7b6d879987b6d2c98da922"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"09f3cf9d1bff85b1860914fc1871816b6c1203fe","unresolved":false,"context_lines":[{"line_number":224,"context_line":"        m \u003d mock.MagicMock()"},{"line_number":225,"context_line":""},{"line_number":226,"context_line":"        class TestApp(df_base_app.DFlowApp):"},{"line_number":227,"context_line":"            @df_base_app.register_event(ModelTest, mixins.EVENT_CREATED)"},{"line_number":228,"context_line":"            def test_created_callback(self, origin, *args, **kwargs):"},{"line_number":229,"context_line":"                m(origin, *args, **kwargs)"},{"line_number":230,"context_line":""}],"source_content_type":"text/x-python","patch_set":39,"id":"ba2be162_86252d0a","line":227,"range":{"start_line":227,"start_character":58,"end_line":227,"end_character":71},"in_reply_to":"ba2be162_57713a75","updated":"2017-03-03 18:20:58.000000000","message":"I agree, will propose a patch and base this one on it.","commit_id":"0821cf1ad2c305c4dd7b6d879987b6d2c98da922"}]}
