)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"3d89669ab8877555044f878f9a3bcbb62e48fe45","unresolved":false,"context_lines":[{"line_number":4,"context_line":"Commit:     Dima Kuznetsov \u003cdima.kuznetsov@toganetworks.com\u003e"},{"line_number":5,"context_line":"CommitDate: 2017-02-20 16:58:19 +0200"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"[07/12] Proposition of model definition and construction"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Partially-Implements: blueprint refactor-nb-api"},{"line_number":10,"context_line":"Change-Id: I7ead9de47fe9fc4425044e8750200e867cf389a8"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":39,"id":"da36d5c6_7cee8e23","line":7,"range":{"start_line":7,"start_character":0,"end_line":7,"end_character":56},"updated":"2017-02-21 00:51:44.000000000","message":"It would be better to elaborate more in the commit msg.","commit_id":"2fb811923f2e7f7a8861d8ec5332c904736b794f"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"1977c900c756fb00639bea4e6bc08f6c6579be45","unresolved":false,"context_lines":[{"line_number":4,"context_line":"Commit:     Dima Kuznetsov \u003cdima.kuznetsov@toganetworks.com\u003e"},{"line_number":5,"context_line":"CommitDate: 2017-02-20 16:58:19 +0200"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"[07/12] Proposition of model definition and construction"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Partially-Implements: blueprint refactor-nb-api"},{"line_number":10,"context_line":"Change-Id: I7ead9de47fe9fc4425044e8750200e867cf389a8"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":39,"id":"da36d5c6_a1d617c3","line":7,"range":{"start_line":7,"start_character":0,"end_line":7,"end_character":56},"in_reply_to":"da36d5c6_7cee8e23","updated":"2017-02-21 08:15:26.000000000","message":"Agree, will add some description","commit_id":"2fb811923f2e7f7a8861d8ec5332c904736b794f"},{"author":{"_account_id":6598,"name":"Berezovsky Irena","email":"irenab.dev@gmail.com","username":"irenab"},"change_message_id":"db45c71e773467cece4a6393d1977f49f82e7db0","unresolved":false,"context_lines":[{"line_number":4,"context_line":"Commit:     Dima Kuznetsov \u003cdima.kuznetsov@toganetworks.com\u003e"},{"line_number":5,"context_line":"CommitDate: 2017-02-20 16:58:19 +0200"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"[07/12] Proposition of model definition and construction"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Partially-Implements: blueprint refactor-nb-api"},{"line_number":10,"context_line":"Change-Id: I7ead9de47fe9fc4425044e8750200e867cf389a8"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":39,"id":"da36d5c6_d1ff5cff","line":7,"range":{"start_line":7,"start_character":0,"end_line":7,"end_character":56},"in_reply_to":"da36d5c6_7cee8e23","updated":"2017-02-21 08:16:00.000000000","message":"This patch is about adding common properties,  not about model definition and construction","commit_id":"2fb811923f2e7f7a8861d8ec5332c904736b794f"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"02fdcc7743a9767b2722df045a7d6d3371020c3e","unresolved":false,"context_lines":[{"line_number":4,"context_line":"Commit:     Dima Kuznetsov \u003cdima.kuznetsov@toganetworks.com\u003e"},{"line_number":5,"context_line":"CommitDate: 2017-02-20 16:58:19 +0200"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"[07/12] Proposition of model definition and construction"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Partially-Implements: blueprint refactor-nb-api"},{"line_number":10,"context_line":"Change-Id: I7ead9de47fe9fc4425044e8750200e867cf389a8"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":39,"id":"da36d5c6_54fa7abe","line":7,"range":{"start_line":7,"start_character":0,"end_line":7,"end_character":56},"in_reply_to":"da36d5c6_d1ff5cff","updated":"2017-02-21 08:58:52.000000000","message":"I\u0027ve reworded to the describe the change better.","commit_id":"2fb811923f2e7f7a8861d8ec5332c904736b794f"}],"dragonflow/db/models/mixins.py":[{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"9e41d78cf73b47ee214447a3503ba5683cc9d00f","unresolved":false,"context_lines":[{"line_number":20,"context_line":"    topic \u003d fields.StringField(required\u003dTrue)"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"EVENT_CREATED \u003d \u0027created\u0027"},{"line_number":24,"context_line":"EVENT_UPDATED \u003d \u0027updated\u0027"},{"line_number":25,"context_line":"EVENT_DELETED \u003d \u0027deleted\u0027"},{"line_number":26,"context_line":""},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"@mf.construct_nb_db_model("}],"source_content_type":"text/x-python","patch_set":49,"id":"da36d5c6_d476b8a2","line":25,"range":{"start_line":23,"start_character":0,"end_line":25,"end_character":25},"updated":"2017-02-27 03:34:44.000000000","message":"maybe add a \"constants\" module under dragonflow.db.models, so that some common field name such as topic, id, version, unique_id, can reside in the module.","commit_id":"c847d9f0d4bd78277fe3e3b99f093d4525e3e97c"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"1281d1f996fa9e4ad65cd1cc6679bef2f5d11217","unresolved":false,"context_lines":[{"line_number":20,"context_line":"    topic \u003d fields.StringField(required\u003dTrue)"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"EVENT_CREATED \u003d \u0027created\u0027"},{"line_number":24,"context_line":"EVENT_UPDATED \u003d \u0027updated\u0027"},{"line_number":25,"context_line":"EVENT_DELETED \u003d \u0027deleted\u0027"},{"line_number":26,"context_line":""},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"@mf.construct_nb_db_model("}],"source_content_type":"text/x-python","patch_set":49,"id":"da36d5c6_d90d04e9","line":25,"range":{"start_line":23,"start_character":0,"end_line":25,"end_character":25},"in_reply_to":"da36d5c6_d476b8a2","updated":"2017-02-27 12:43:21.000000000","message":"Honestly I don\u0027t foresee access to fields by name (getattr et al), as for events, I suggested Omer to automatically place the all the events on the class and expose them as attributes but I don\u0027t see his reply.\n\nI think that for now it is quite sufficient and we can change that if we see a way that works out better.","commit_id":"c847d9f0d4bd78277fe3e3b99f093d4525e3e97c"}],"dragonflow/db/models2.py":[{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"b5120e54178b696debe1bd2add7d489189352456","unresolved":false,"context_lines":[{"line_number":37,"context_line":""},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"@mf.construct_nb_db_model(nb_crud\u003dcrud.UniqueKeyNbApiCRUD)"},{"line_number":40,"context_line":"class NbDbUniqueKeyMixin(mf.ModelBase):"},{"line_number":41,"context_line":"    unique_key \u003d fields.IntField(required\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":5,"id":"ba5201f7_a7d70e22","line":40,"range":{"start_line":40,"start_character":28,"end_line":40,"end_character":37},"updated":"2017-01-10 08:56:20.000000000","message":"Why does the mixin also have to extend ModelBase? If possible, I\u0027d be happy to waive this requirement.","commit_id":"95cbcfc5da06d4069d5549c84d7691eb8f435bf9"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"221e34968cfa912a328fcccbedf4e69ea58f5767","unresolved":false,"context_lines":[{"line_number":37,"context_line":""},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"@mf.construct_nb_db_model(nb_crud\u003dcrud.UniqueKeyNbApiCRUD)"},{"line_number":40,"context_line":"class NbDbUniqueKeyMixin(mf.ModelBase):"},{"line_number":41,"context_line":"    unique_key \u003d fields.IntField(required\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":5,"id":"ba5201f7_58555f1b","line":40,"range":{"start_line":40,"start_character":28,"end_line":40,"end_character":37},"in_reply_to":"ba5201f7_a7d70e22","updated":"2017-01-10 10:15:59.000000000","message":"A. Because I want to supersede its NB CRUD helper.\nB. Due to python\u0027s funny MRO, if we want to override any method of ModelBase, we have to derive from it (or put mixin before the the actual base): \n\n class NewModel(Mixin1, ..., MixinK, ModelBase):\n     pass\n\nB is not a mixin case but A is implemented using B..","commit_id":"95cbcfc5da06d4069d5549c84d7691eb8f435bf9"},{"author":{"_account_id":6598,"name":"Berezovsky Irena","email":"irenab.dev@gmail.com","username":"irenab"},"change_message_id":"cac40e4212df578fd332b60497b178b25608edf6","unresolved":false,"context_lines":[{"line_number":31,"context_line":""},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"@mf.construct_nb_db_model"},{"line_number":34,"context_line":"class NbDbModelBase(NbModelBase):"},{"line_number":35,"context_line":"    name \u003d fields.StringField()"},{"line_number":36,"context_line":"    version \u003d fields.IntField()"},{"line_number":37,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"ba5201f7_05ba520a","line":34,"range":{"start_line":34,"start_character":6,"end_line":34,"end_character":32},"updated":"2017-01-11 11:29:56.000000000","message":"please provide short docstring explaining the purpose of this class","commit_id":"326c34778d75715be6b916d9b848715468e1e9e8"},{"author":{"_account_id":6598,"name":"Berezovsky Irena","email":"irenab.dev@gmail.com","username":"irenab"},"change_message_id":"e9c8266bd6aae01010a9c6b495134dd45ea20a93","unresolved":false,"context_lines":[{"line_number":45,"context_line":"class UniqueKeyMixin(mf.MixinBase):"},{"line_number":46,"context_line":"    unique_key \u003d fields.IntField(required\u003dTrue)"},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"    def on_create_pre(self):"},{"line_number":49,"context_line":"        nb_api \u003d api_nb.NbApi.get_instance(True)"},{"line_number":50,"context_line":"        self.unique_key \u003d nb_api.driver.allocate_unique_key(self.table_name)"},{"line_number":51,"context_line":"        super(UniqueKeyMixin, self).on_create()"}],"source_content_type":"text/x-python","patch_set":13,"id":"5a3905b3_d3e7833e","line":48,"range":{"start_line":48,"start_character":8,"end_line":48,"end_character":21},"updated":"2017-01-19 16:45:33.000000000","message":"maybe pre_create?","commit_id":"da5a7b494922d6096e44b21a0a95d3c08f3d8c28"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"7e49377ffc28bbfe6d817f56d4f13a8e8079ac8a","unresolved":false,"context_lines":[{"line_number":48,"context_line":"    def on_create_pre(self):"},{"line_number":49,"context_line":"        nb_api \u003d api_nb.NbApi.get_instance()"},{"line_number":50,"context_line":"        self.unique_key \u003d nb_api.driver.allocate_unique_key(self.table_name)"},{"line_number":51,"context_line":"        super(UniqueKeyMixin, self).on_create()"}],"source_content_type":"text/x-python","patch_set":16,"id":"5a3905b3_1299657c","line":51,"range":{"start_line":51,"start_character":36,"end_line":51,"end_character":45},"updated":"2017-01-23 20:50:22.000000000","message":"typo - on_create_pre?\n\nAlso, why not put this at the beginning of the method?","commit_id":"9c7860e3464757ce745beb2de9abf4e28cd87683"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"82a15451f7c9d7395802da8a7a291c0beac7e5b5","unresolved":false,"context_lines":[{"line_number":48,"context_line":"    def on_create_pre(self):"},{"line_number":49,"context_line":"        nb_api \u003d api_nb.NbApi.get_instance()"},{"line_number":50,"context_line":"        self.unique_key \u003d nb_api.driver.allocate_unique_key(self.table_name)"},{"line_number":51,"context_line":"        super(UniqueKeyMixin, self).on_create()"}],"source_content_type":"text/x-python","patch_set":16,"id":"3a461143_b710b85a","line":51,"range":{"start_line":51,"start_character":36,"end_line":51,"end_character":45},"in_reply_to":"5a3905b3_1299657c","updated":"2017-01-29 14:13:51.000000000","message":"Done","commit_id":"9c7860e3464757ce745beb2de9abf4e28cd87683"}],"dragonflow/db/models2/__init__.py":[{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"8c81d84507ceb29060692caa62f278155c691cee","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":45,"id":"da36d5c6_b9d6c24c","updated":"2017-02-24 15:41:16.000000000","message":"Please rename package to something more meaningful than models2. Maybe: \u0027models_base\u0027 (Yes, it\u0027s not very good either)?\nMaybe \u0027models\u0027, and have temporary code in __init__.py that populated the package with the objects in models.py? (and rename models.py)?","commit_id":"32f3fd8442cedc577938d7c25c1be3f97ec8a5fb"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"db203300a24d25270cceca7f17efbd7c0f58625e","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":45,"id":"da36d5c6_dc9d08bd","in_reply_to":"da36d5c6_b9d6c24c","updated":"2017-02-26 07:37:38.000000000","message":"My plan was to get rid of models.py and rename this package to models, I\u0027ll consider renaming it now and doing something about the old models.","commit_id":"32f3fd8442cedc577938d7c25c1be3f97ec8a5fb"}],"dragonflow/db/models2/mixins.py":[{"author":{"_account_id":6598,"name":"Berezovsky Irena","email":"irenab.dev@gmail.com","username":"irenab"},"change_message_id":"db45c71e773467cece4a6393d1977f49f82e7db0","unresolved":false,"context_lines":[{"line_number":14,"context_line":"from dragonflow.db import api_nb"},{"line_number":15,"context_line":"import dragonflow.db.model_framework as mf"},{"line_number":16,"context_line":""},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"@mf.construct_nb_db_model(indexes\u003d{\u0027topic\u0027: \u0027topic\u0027})"},{"line_number":19,"context_line":"class TopicMixin(mf.MixinBase):"},{"line_number":20,"context_line":"    topic \u003d fields.StringField(required\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":39,"id":"da36d5c6_e122cfb8","line":17,"updated":"2017-02-21 08:16:00.000000000","message":"I do not think the Mixin suffix is required","commit_id":"2fb811923f2e7f7a8861d8ec5332c904736b794f"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"02fdcc7743a9767b2722df045a7d6d3371020c3e","unresolved":false,"context_lines":[{"line_number":14,"context_line":"from dragonflow.db import api_nb"},{"line_number":15,"context_line":"import dragonflow.db.model_framework as mf"},{"line_number":16,"context_line":""},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"@mf.construct_nb_db_model(indexes\u003d{\u0027topic\u0027: \u0027topic\u0027})"},{"line_number":19,"context_line":"class TopicMixin(mf.MixinBase):"},{"line_number":20,"context_line":"    topic \u003d fields.StringField(required\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":39,"id":"da36d5c6_f408cedb","line":17,"in_reply_to":"da36d5c6_e122cfb8","updated":"2017-02-21 08:58:52.000000000","message":"I agree, once those classes all reside in the mixin module it is not necessary to have them end in Mixin suffix.","commit_id":"2fb811923f2e7f7a8861d8ec5332c904736b794f"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"3d89669ab8877555044f878f9a3bcbb62e48fe45","unresolved":false,"context_lines":[{"line_number":25,"context_line":"    pass"},{"line_number":26,"context_line":""},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"class VersionMixin(mf.MixinBase):"},{"line_number":29,"context_line":"    version \u003d fields.IntField()"},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"    def is_newer_than(self, other):"},{"line_number":32,"context_line":"        if other is None or self.version \u003e other.version:"},{"line_number":33,"context_line":"            return True"},{"line_number":34,"context_line":"        else:"},{"line_number":35,"context_line":"            return False"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"class NameMixin(mf.MixinBase):"},{"line_number":39,"context_line":"    name \u003d fields.StringField()"},{"line_number":40,"context_line":""},{"line_number":41,"context_line":""},{"line_number":42,"context_line":"class UniqueKeyMixin(mf.MixinBase):"}],"source_content_type":"text/x-python","patch_set":39,"id":"da36d5c6_7c876e61","line":39,"range":{"start_line":28,"start_character":0,"end_line":39,"end_character":31},"updated":"2017-02-21 00:51:44.000000000","message":"Instead of separate Mixins, can there be a mixin which holds all/some of these ones?","commit_id":"2fb811923f2e7f7a8861d8ec5332c904736b794f"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"1977c900c756fb00639bea4e6bc08f6c6579be45","unresolved":false,"context_lines":[{"line_number":25,"context_line":"    pass"},{"line_number":26,"context_line":""},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"class VersionMixin(mf.MixinBase):"},{"line_number":29,"context_line":"    version \u003d fields.IntField()"},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"    def is_newer_than(self, other):"},{"line_number":32,"context_line":"        if other is None or self.version \u003e other.version:"},{"line_number":33,"context_line":"            return True"},{"line_number":34,"context_line":"        else:"},{"line_number":35,"context_line":"            return False"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"class NameMixin(mf.MixinBase):"},{"line_number":39,"context_line":"    name \u003d fields.StringField()"},{"line_number":40,"context_line":""},{"line_number":41,"context_line":""},{"line_number":42,"context_line":"class UniqueKeyMixin(mf.MixinBase):"}],"source_content_type":"text/x-python","patch_set":39,"id":"da36d5c6_e1ff2f32","line":39,"range":{"start_line":28,"start_character":0,"end_line":39,"end_character":31},"in_reply_to":"da36d5c6_7c876e61","updated":"2017-02-21 08:15:26.000000000","message":"I think having those separately allows for better granularity.\n\nIn the old model we had topic/version on objects that don\u0027t support them which made the code a bit awkward. I with more granular mixins it is easier to keep models clean of extra fields.","commit_id":"2fb811923f2e7f7a8861d8ec5332c904736b794f"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"4eb283c3d9e67a7319c1c8277d62d9dc32abe69a","unresolved":false,"context_lines":[{"line_number":20,"context_line":"    topic \u003d fields.StringField(required\u003dTrue)"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"@mf.construct_nb_db_model(events\u003d{\u0027created\u0027, \u0027updated\u0027, \u0027deleted\u0027})"},{"line_number":24,"context_line":"class BasicEvents(mf.MixinBase):"},{"line_number":25,"context_line":"    pass"},{"line_number":26,"context_line":""}],"source_content_type":"text/x-python","patch_set":45,"id":"da36d5c6_a06bd01c","line":23,"range":{"start_line":23,"start_character":34,"end_line":23,"end_character":65},"updated":"2017-02-25 07:47:23.000000000","message":"Will these events used by other modules? is there any chance to use these as constant?","commit_id":"32f3fd8442cedc577938d7c25c1be3f97ec8a5fb"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"db203300a24d25270cceca7f17efbd7c0f58625e","unresolved":false,"context_lines":[{"line_number":20,"context_line":"    topic \u003d fields.StringField(required\u003dTrue)"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"@mf.construct_nb_db_model(events\u003d{\u0027created\u0027, \u0027updated\u0027, \u0027deleted\u0027})"},{"line_number":24,"context_line":"class BasicEvents(mf.MixinBase):"},{"line_number":25,"context_line":"    pass"},{"line_number":26,"context_line":""}],"source_content_type":"text/x-python","patch_set":45,"id":"da36d5c6_fc79ec93","line":23,"range":{"start_line":23,"start_character":34,"end_line":23,"end_character":65},"in_reply_to":"da36d5c6_a06bd01c","updated":"2017-02-26 07:37:38.000000000","message":"I\u0027ll make them constants","commit_id":"32f3fd8442cedc577938d7c25c1be3f97ec8a5fb"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"a0993efcbcd4888150f9cbbe7e83fcb64c87ccb3","unresolved":false,"context_lines":[{"line_number":20,"context_line":"    topic \u003d fields.StringField(required\u003dTrue)"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"@mf.construct_nb_db_model(events\u003d{\u0027created\u0027, \u0027updated\u0027, \u0027deleted\u0027})"},{"line_number":24,"context_line":"class BasicEvents(mf.MixinBase):"},{"line_number":25,"context_line":"    pass"},{"line_number":26,"context_line":""}],"source_content_type":"text/x-python","patch_set":45,"id":"da36d5c6_c6e61c43","line":23,"range":{"start_line":23,"start_character":34,"end_line":23,"end_character":65},"in_reply_to":"da36d5c6_a06bd01c","updated":"2017-02-25 11:52:04.000000000","message":"If I understand correctly, these events will be \u0027emitted\u0027, and then applications can listen to them and act upon them. (as in patch https://review.openstack.org/#/c/406602/ ).","commit_id":"32f3fd8442cedc577938d7c25c1be3f97ec8a5fb"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"db203300a24d25270cceca7f17efbd7c0f58625e","unresolved":false,"context_lines":[{"line_number":20,"context_line":"    topic \u003d fields.StringField(required\u003dTrue)"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"@mf.construct_nb_db_model(events\u003d{\u0027created\u0027, \u0027updated\u0027, \u0027deleted\u0027})"},{"line_number":24,"context_line":"class BasicEvents(mf.MixinBase):"},{"line_number":25,"context_line":"    pass"},{"line_number":26,"context_line":""}],"source_content_type":"text/x-python","patch_set":45,"id":"da36d5c6_1c6de0cb","line":23,"range":{"start_line":23,"start_character":34,"end_line":23,"end_character":65},"in_reply_to":"da36d5c6_c6e61c43","updated":"2017-02-26 07:37:38.000000000","message":"But in some occasions a constant can be quite useful.\n\nMaybe I can add some framework code that adds EVENT_NAME attribute to a class that defines such event.","commit_id":"32f3fd8442cedc577938d7c25c1be3f97ec8a5fb"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"4eb283c3d9e67a7319c1c8277d62d9dc32abe69a","unresolved":false,"context_lines":[{"line_number":29,"context_line":"    version \u003d fields.IntField()"},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"    def is_newer_than(self, other):"},{"line_number":32,"context_line":"        if other is None or self.version \u003e other.version:"},{"line_number":33,"context_line":"            return True"},{"line_number":34,"context_line":"        else:"},{"line_number":35,"context_line":"            return False"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"class Name(mf.MixinBase):"}],"source_content_type":"text/x-python","patch_set":45,"id":"da36d5c6_207fe0e0","line":35,"range":{"start_line":32,"start_character":0,"end_line":35,"end_character":24},"updated":"2017-02-25 07:47:23.000000000","message":"nit: you can just \"return other is None or self.version \u003e other.version\"","commit_id":"32f3fd8442cedc577938d7c25c1be3f97ec8a5fb"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"db203300a24d25270cceca7f17efbd7c0f58625e","unresolved":false,"context_lines":[{"line_number":29,"context_line":"    version \u003d fields.IntField()"},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"    def is_newer_than(self, other):"},{"line_number":32,"context_line":"        if other is None or self.version \u003e other.version:"},{"line_number":33,"context_line":"            return True"},{"line_number":34,"context_line":"        else:"},{"line_number":35,"context_line":"            return False"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"class Name(mf.MixinBase):"}],"source_content_type":"text/x-python","patch_set":45,"id":"da36d5c6_9c61d0d5","line":35,"range":{"start_line":32,"start_character":0,"end_line":35,"end_character":24},"in_reply_to":"da36d5c6_207fe0e0","updated":"2017-02-26 07:37:38.000000000","message":"I\u0027ll change that, thanks.","commit_id":"32f3fd8442cedc577938d7c25c1be3f97ec8a5fb"}],"dragonflow/db/models3.py":[{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"793f0d3b6c38e24e1fd160961b3505e1468adce6","unresolved":false,"context_lines":[{"line_number":33,"context_line":"            self._add_attr(key, value)"},{"line_number":34,"context_line":""},{"line_number":35,"context_line":"    def _add_attr(self, key, value):"},{"line_number":36,"context_line":"        self._dict[key] \u003d value"},{"line_number":37,"context_line":"        setattr(self, key, value)"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"    def __iter__(self):"},{"line_number":40,"context_line":"        for key, value in six.iteritems(self._dict):"}],"source_content_type":"text/x-python","patch_set":2,"id":"da4df55a_6f8040c1","line":37,"range":{"start_line":36,"start_character":0,"end_line":37,"end_character":33},"updated":"2016-12-27 02:18:28.000000000","message":"Will it be redundant to both have key-value in _dict and in instance attribute?","commit_id":"51420eaec25f4ec99f505924860b1acbd6de08a2"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"3f97ed23ce1251a7cce13923cf19e31cbbaaacdc","unresolved":false,"context_lines":[{"line_number":33,"context_line":"            self._add_attr(key, value)"},{"line_number":34,"context_line":""},{"line_number":35,"context_line":"    def _add_attr(self, key, value):"},{"line_number":36,"context_line":"        self._dict[key] \u003d value"},{"line_number":37,"context_line":"        setattr(self, key, value)"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"    def __iter__(self):"},{"line_number":40,"context_line":"        for key, value in six.iteritems(self._dict):"}],"source_content_type":"text/x-python","patch_set":2,"id":"da4df55a_830b7c8d","line":37,"range":{"start_line":36,"start_character":0,"end_line":37,"end_character":33},"in_reply_to":"da4df55a_6f8040c1","updated":"2016-12-27 07:26:17.000000000","message":"Attributes are nicer to access, _dict is easier to iterate (rather than dir(self) and filter out)","commit_id":"51420eaec25f4ec99f505924860b1acbd6de08a2"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"a390c1db4d2d5887c8f859840e862f7f4a228a82","unresolved":false,"context_lines":[{"line_number":33,"context_line":"            self._add_attr(key, value)"},{"line_number":34,"context_line":""},{"line_number":35,"context_line":"    def _add_attr(self, key, value):"},{"line_number":36,"context_line":"        self._dict[key] \u003d value"},{"line_number":37,"context_line":"        setattr(self, key, value)"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"    def __iter__(self):"},{"line_number":40,"context_line":"        for key, value in six.iteritems(self._dict):"}],"source_content_type":"text/x-python","patch_set":2,"id":"ba5201f7_b0085893","line":37,"range":{"start_line":36,"start_character":0,"end_line":37,"end_character":33},"in_reply_to":"da4df55a_830b7c8d","updated":"2016-12-29 03:44:40.000000000","message":"Why not try to override the default __get__ method? That way, you might not need to maintain (key, value) in 2 objects","commit_id":"51420eaec25f4ec99f505924860b1acbd6de08a2"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"c9304652e6c9f1c6f463454546208ea8b8aa4223","unresolved":false,"context_lines":[{"line_number":66,"context_line":"    def _extract_key(self, obj, index):"},{"line_number":67,"context_line":"        return tuple(getattr(obj, field) for field in index)"},{"line_number":68,"context_line":""},{"line_number":69,"context_line":"    def get(self, model, index, key):"},{"line_number":70,"context_line":"        index \u003d _normalize(index)"},{"line_number":71,"context_line":"        key \u003d _normalize(key)"},{"line_number":72,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"da4df55a_fe405f36","line":69,"range":{"start_line":69,"start_character":0,"end_line":69,"end_character":37},"updated":"2016-12-27 08:35:36.000000000","message":"Regarding the API, how can we make index\u0027s default be the ID?","commit_id":"51420eaec25f4ec99f505924860b1acbd6de08a2"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"793f0d3b6c38e24e1fd160961b3505e1468adce6","unresolved":false,"context_lines":[{"line_number":70,"context_line":"        index \u003d _normalize(index)"},{"line_number":71,"context_line":"        key \u003d _normalize(key)"},{"line_number":72,"context_line":""},{"line_number":73,"context_line":"        for obj in self._store.get(model, ()):"},{"line_number":74,"context_line":"            if self._extract_key(obj, index) \u003d\u003d key:"},{"line_number":75,"context_line":"                return obj"},{"line_number":76,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"da4df55a_4fbe1c66","line":73,"range":{"start_line":73,"start_character":42,"end_line":73,"end_character":44},"updated":"2016-12-27 02:18:28.000000000","message":"Should this be []?","commit_id":"51420eaec25f4ec99f505924860b1acbd6de08a2"},{"author":{"_account_id":23766,"name":"Dima Kuznetsov","email":"dima.kuznetsov@toganetworks.com","username":"dimak"},"change_message_id":"3f97ed23ce1251a7cce13923cf19e31cbbaaacdc","unresolved":false,"context_lines":[{"line_number":70,"context_line":"        index \u003d _normalize(index)"},{"line_number":71,"context_line":"        key \u003d _normalize(key)"},{"line_number":72,"context_line":""},{"line_number":73,"context_line":"        for obj in self._store.get(model, ()):"},{"line_number":74,"context_line":"            if self._extract_key(obj, index) \u003d\u003d key:"},{"line_number":75,"context_line":"                return obj"},{"line_number":76,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"da4df55a_a397a038","line":73,"range":{"start_line":73,"start_character":42,"end_line":73,"end_character":44},"in_reply_to":"da4df55a_4fbe1c66","updated":"2016-12-27 07:26:17.000000000","message":"I wouldn\u0027t pay too much attention to this class, just needed this until we refactor DbStore :)\n\nThis aside I prefer tuples when I don\u0027t plan on adding or removing elements.","commit_id":"51420eaec25f4ec99f505924860b1acbd6de08a2"},{"author":{"_account_id":11159,"name":"Hong Hui Xiao","email":"honghui_xiao@yeah.net","username":"HongHuiXiao"},"change_message_id":"793f0d3b6c38e24e1fd160961b3505e1468adce6","unresolved":false,"context_lines":[{"line_number":77,"context_line":"        raise KeyError(key)"},{"line_number":78,"context_line":""},{"line_number":79,"context_line":"    def store(self, obj):"},{"line_number":80,"context_line":"        self._store.setdefault(type(obj), []).append(obj)"},{"line_number":81,"context_line":""},{"line_number":82,"context_line":""},{"line_number":83,"context_line":"db_store \u003d MockDbStore()"}],"source_content_type":"text/x-python","patch_set":2,"id":"da4df55a_af7068dd","line":80,"range":{"start_line":80,"start_character":0,"end_line":80,"end_character":57},"updated":"2016-12-27 02:18:28.000000000","message":"why not just use collections.defaultdict(list)?","commit_id":"51420eaec25f4ec99f505924860b1acbd6de08a2"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"c9304652e6c9f1c6f463454546208ea8b8aa4223","unresolved":false,"context_lines":[{"line_number":204,"context_line":"            instance, RefWrapper(self._model, key, lazy\u003dself._lazy))"},{"line_number":205,"context_line":""},{"line_number":206,"context_line":""},{"line_number":207,"context_line":"class IpAddressField(fields.BaseField):"},{"line_number":208,"context_line":"    pass"},{"line_number":209,"context_line":""},{"line_number":210,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"da4df55a_1ec36339","line":207,"updated":"2016-12-27 08:35:36.000000000","message":"How do you do the conversion to and from netaddr.IPAddress?","commit_id":"51420eaec25f4ec99f505924860b1acbd6de08a2"},{"author":{"_account_id":20229,"name":"Omer Anson","email":"omer.anson@toganetworks.com","username":"oanson"},"change_message_id":"c9304652e6c9f1c6f463454546208ea8b8aa4223","unresolved":false,"context_lines":[{"line_number":258,"context_line":""},{"line_number":259,"context_line":""},{"line_number":260,"context_line":"@construct_nb_db_model"},{"line_number":261,"context_line":"class LogicalSwitch(NbDbUniqueKeyMixin, NbDbModelBase):"},{"line_number":262,"context_line":"    subnets \u003d fields.ListField(Subnet)"},{"line_number":263,"context_line":"    mtu \u003d fields.IntField()"},{"line_number":264,"context_line":"    external \u003d fields.BoolField()"}],"source_content_type":"text/x-python","patch_set":2,"id":"da4df55a_093a4bcc","line":261,"range":{"start_line":261,"start_character":20,"end_line":261,"end_character":53},"updated":"2016-12-27 08:35:36.000000000","message":"Shouldn\u0027t the order be reveresed? First the base, then the mixin?","commit_id":"51420eaec25f4ec99f505924860b1acbd6de08a2"}]}
