)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":6788,"name":"Rossella Sblendido","email":"rsblendido@suse.com","username":"rossella-o"},"change_message_id":"524b98871f6ac8718af56f07919794af090aaec0","unresolved":false,"context_lines":[{"line_number":9,"context_line":"Sometimes object users need access to corresponding models that are used"},{"line_number":10,"context_line":"to persist object data. While it\u0027s not encouraged, and object consumers"},{"line_number":11,"context_line":"should try to rely solely on object API and fields, we should fulfill"},{"line_number":12,"context_line":"this special need, at least for now."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"Change-Id: I130609194f15b89df89e5606fb8193849edd14d8"},{"line_number":15,"context_line":"Partially-Implements: blueprint adopt-oslo-versioned-objects-for-db"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"bacf61ea_1951fe0e","line":12,"range":{"start_line":12,"start_character":5,"end_line":12,"end_character":17},"updated":"2016-07-29 14:10:43.000000000","message":"can you please specify who has this special need? It\u0027s not so straightforward to understand the motivations for this change","commit_id":"bc8273113fae25514bad2b29606bf1937381e17a"},{"author":{"_account_id":8726,"name":"Victor Morales","email":"chipahuac@hotmail.com","username":"electrocucaracha"},"change_message_id":"85a2ea3b037511fde97f42aaf5389a7733f93c05","unresolved":false,"context_lines":[{"line_number":11,"context_line":"should try to rely solely on object API and fields, we should fulfill"},{"line_number":12,"context_line":"this special need, at least for now."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"One of use cases to access the corresponding database model are"},{"line_number":15,"context_line":"functions registered by plugins to extend core resources. Those"},{"line_number":16,"context_line":"functions are passed into register_dict_extend_funcs and expect the"},{"line_number":17,"context_line":"model as one of its arguments."}],"source_content_type":"text/x-gerrit-commit-message","patch_set":8,"id":"3ac371cc_9d6ed3c7","line":14,"range":{"start_line":14,"start_character":60,"end_line":14,"end_character":63},"updated":"2016-08-15 14:19:58.000000000","message":"s/are/is ?","commit_id":"3024503a93343921f39d863527ef5bd110c273cc"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"b69e07afa6e4873c45ca1740f6c3c410ab113b8e","unresolved":false,"context_lines":[{"line_number":11,"context_line":"should try to rely solely on object API and fields, we should fulfill"},{"line_number":12,"context_line":"this special need, at least for now."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"One of use cases to access the corresponding database model are"},{"line_number":15,"context_line":"functions registered by plugins to extend core resources. Those"},{"line_number":16,"context_line":"functions are passed into register_dict_extend_funcs and expect the"},{"line_number":17,"context_line":"model as one of its arguments."}],"source_content_type":"text/x-gerrit-commit-message","patch_set":8,"id":"3ac371cc_bde1e89c","line":14,"range":{"start_line":14,"start_character":60,"end_line":14,"end_character":63},"in_reply_to":"3ac371cc_9d6ed3c7","updated":"2016-08-16 07:32:12.000000000","message":"Done","commit_id":"3024503a93343921f39d863527ef5bd110c273cc"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"028d3d1a0cf5ab5afdea3024cadc02c1ee7f29a6","unresolved":false,"context_lines":[{"line_number":9,"context_line":"Sometimes object users need access to corresponding models that are used"},{"line_number":10,"context_line":"to persist object data. While it\u0027s not encouraged, and object consumers"},{"line_number":11,"context_line":"should try to rely solely on object API and fields, we should fulfill"},{"line_number":12,"context_line":"this special need, at least for now."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"One of use cases to access the corresponding database model are"},{"line_number":15,"context_line":"functions registered by plugins to extend core resources. Those"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":14,"id":"9a89bdaa_c2ff8065","line":12,"updated":"2016-09-06 15:09:25.000000000","message":"Do you have an example? Maybe we could think about other solution that would be sufficient for consumers.","commit_id":"c41dff73e6b290edf8e50c1e33859265d07602ec"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"e8bc10d9022439263f357ce4fe0839d12a433c2a","unresolved":false,"context_lines":[{"line_number":9,"context_line":"Sometimes object users need access to corresponding models that are used"},{"line_number":10,"context_line":"to persist object data. While it\u0027s not encouraged, and object consumers"},{"line_number":11,"context_line":"should try to rely solely on object API and fields, we should fulfill"},{"line_number":12,"context_line":"this special need, at least for now."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"One of use cases to access the corresponding database model are"},{"line_number":15,"context_line":"functions registered by plugins to extend core resources. Those"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":14,"id":"9a89bdaa_296c1507","line":12,"in_reply_to":"9a89bdaa_09959131","updated":"2016-09-08 12:08:03.000000000","message":"I meant something more specific, like a patch that needs this. If some functions require models that carry data, maybe we could have a helper function where you pass an object and it returns such populated model.","commit_id":"c41dff73e6b290edf8e50c1e33859265d07602ec"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"cb676bfbac1e3d2ef369ae2449d8028dca88690f","unresolved":false,"context_lines":[{"line_number":9,"context_line":"Sometimes object users need access to corresponding models that are used"},{"line_number":10,"context_line":"to persist object data. While it\u0027s not encouraged, and object consumers"},{"line_number":11,"context_line":"should try to rely solely on object API and fields, we should fulfill"},{"line_number":12,"context_line":"this special need, at least for now."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"One of use cases to access the corresponding database model are"},{"line_number":15,"context_line":"functions registered by plugins to extend core resources. Those"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":14,"id":"9a89bdaa_d2fd0eb2","line":12,"in_reply_to":"9a89bdaa_296c1507","updated":"2016-09-08 12:40:54.000000000","message":"This patch already includes changes that make use of db_obj property. Specifically, for subnetpools and allowed address pairs.\n\nWhat\u0027s your concern here? Exposing it as part of public object API?","commit_id":"c41dff73e6b290edf8e50c1e33859265d07602ec"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"2becdf96f7870b610dfdda29b6b2dca89d63604d","unresolved":false,"context_lines":[{"line_number":9,"context_line":"Sometimes object users need access to corresponding models that are used"},{"line_number":10,"context_line":"to persist object data. While it\u0027s not encouraged, and object consumers"},{"line_number":11,"context_line":"should try to rely solely on object API and fields, we should fulfill"},{"line_number":12,"context_line":"this special need, at least for now."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"One of use cases to access the corresponding database model are"},{"line_number":15,"context_line":"functions registered by plugins to extend core resources. Those"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":14,"id":"9a89bdaa_0f402c06","line":12,"in_reply_to":"9a89bdaa_8cbd2a04","updated":"2016-09-08 13:39:35.000000000","message":"The new API is for transition time. There are ideas on how to evolve plugin interface (lines 19+). We will revisit the API once we don\u0027t use it throughout in-tree plugin code.","commit_id":"c41dff73e6b290edf8e50c1e33859265d07602ec"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"54fab81c8bdd11cde510b95feaeb40dfde46a5ba","unresolved":false,"context_lines":[{"line_number":9,"context_line":"Sometimes object users need access to corresponding models that are used"},{"line_number":10,"context_line":"to persist object data. While it\u0027s not encouraged, and object consumers"},{"line_number":11,"context_line":"should try to rely solely on object API and fields, we should fulfill"},{"line_number":12,"context_line":"this special need, at least for now."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"One of use cases to access the corresponding database model are"},{"line_number":15,"context_line":"functions registered by plugins to extend core resources. Those"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":14,"id":"9a89bdaa_09959131","line":12,"in_reply_to":"9a89bdaa_c2ff8065","updated":"2016-09-08 12:03:14.000000000","message":"The example is described in lines 14-17.","commit_id":"c41dff73e6b290edf8e50c1e33859265d07602ec"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"bb9936805f2544b216c0b06da1da167d19610dc3","unresolved":false,"context_lines":[{"line_number":9,"context_line":"Sometimes object users need access to corresponding models that are used"},{"line_number":10,"context_line":"to persist object data. While it\u0027s not encouraged, and object consumers"},{"line_number":11,"context_line":"should try to rely solely on object API and fields, we should fulfill"},{"line_number":12,"context_line":"this special need, at least for now."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"One of use cases to access the corresponding database model are"},{"line_number":15,"context_line":"functions registered by plugins to extend core resources. Those"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":14,"id":"9a89bdaa_8cbd2a04","line":12,"in_reply_to":"9a89bdaa_d2fd0eb2","updated":"2016-09-08 13:24:27.000000000","message":"Yes. What I like about objects is they behave like facade and they hide the db stuff encapsulated inside of them. If we need to expose db model for transition phase, it would be good to have the API as thin as possible or find a different solution. Don\u0027t get me wrong, I\u0027m not saying we shouldn\u0027t do this patch. I\u0027m just thinking out loud as I don\u0027t think I still fully understand this patch.","commit_id":"c41dff73e6b290edf8e50c1e33859265d07602ec"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"028d3d1a0cf5ab5afdea3024cadc02c1ee7f29a6","unresolved":false,"context_lines":[{"line_number":29,"context_line":"should avoid model refresh when it\u0027s not needed, while still keeping it"},{"line_number":30,"context_line":"reflecting object state pending update."},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"Also, now that we have models stored on objects, switched back to"},{"line_number":33,"context_line":"passing models in places where we previously, by mistake, started"},{"line_number":34,"context_line":"passing objects instead of models into extensions."},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"Specifically, the switch for allowed address pairs occurred with"},{"line_number":37,"context_line":"I3c937267ce789ed510373616713b3fa9517c18ac. For subnetpools, it happened"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":14,"id":"9a89bdaa_86ed8327","line":34,"range":{"start_line":32,"start_character":0,"end_line":34,"end_character":50},"updated":"2016-09-06 15:09:25.000000000","message":"I don\u0027t get this sentence. Are you missing a verb there?","commit_id":"c41dff73e6b290edf8e50c1e33859265d07602ec"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"54fab81c8bdd11cde510b95feaeb40dfde46a5ba","unresolved":false,"context_lines":[{"line_number":29,"context_line":"should avoid model refresh when it\u0027s not needed, while still keeping it"},{"line_number":30,"context_line":"reflecting object state pending update."},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"Also, now that we have models stored on objects, switched back to"},{"line_number":33,"context_line":"passing models in places where we previously, by mistake, started"},{"line_number":34,"context_line":"passing objects instead of models into extensions."},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"Specifically, the switch for allowed address pairs occurred with"},{"line_number":37,"context_line":"I3c937267ce789ed510373616713b3fa9517c18ac. For subnetpools, it happened"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":14,"id":"9a89bdaa_c9a729a5","line":34,"range":{"start_line":32,"start_character":0,"end_line":34,"end_character":50},"in_reply_to":"9a89bdaa_86ed8327","updated":"2016-09-08 12:03:14.000000000","message":"Done","commit_id":"c41dff73e6b290edf8e50c1e33859265d07602ec"}],"neutron/objects/base.py":[{"author":{"_account_id":7787,"name":"Kevin Benton","email":"kevin@benton.pub","username":"blak111"},"change_message_id":"9195e8a0bc653e25d3ad9769745d99395cbfa655","unresolved":false,"context_lines":[{"line_number":295,"context_line":"            # expire the model so that consumers always get access to the"},{"line_number":296,"context_line":"            # latest state of the model that could change from the time it was"},{"line_number":297,"context_line":"            # stored"},{"line_number":298,"context_line":"            self.obj_context.session.expire(self._neutron_db_obj)"},{"line_number":299,"context_line":"        return self._neutron_db_obj"},{"line_number":300,"context_line":""},{"line_number":301,"context_line":"    def from_db_object(self, db_obj):"}],"source_content_type":"text/x-python","patch_set":6,"id":"bacf61ea_82f75958","line":298,"updated":"2016-08-03 20:42:27.000000000","message":"Is this still necessary now that we have populate_existing called? If we unconditionally expire like this we are going to experience a linear number of DB queries now if someone does get_objects and then calls the dict_extend function on each one.\n\nCan we instead have it just expire the object if any of the fields change that are relationships in the object? (e.g. only expire a port object if fixed_ips changes)","commit_id":"516376f2c8b0cd79f407f685a2d8b9269f25b2cf"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"523ab778282841ceed5b2b6f154601a9bc1adc0f","unresolved":false,"context_lines":[{"line_number":295,"context_line":"            # expire the model so that consumers always get access to the"},{"line_number":296,"context_line":"            # latest state of the model that could change from the time it was"},{"line_number":297,"context_line":"            # stored"},{"line_number":298,"context_line":"            self.obj_context.session.expire(self._neutron_db_obj)"},{"line_number":299,"context_line":"        return self._neutron_db_obj"},{"line_number":300,"context_line":""},{"line_number":301,"context_line":"    def from_db_object(self, db_obj):"}],"source_content_type":"text/x-python","patch_set":6,"id":"bacf61ea_648fbc23","line":298,"in_reply_to":"bacf61ea_82f75958","updated":"2016-08-04 08:29:18.000000000","message":"I *hope* I did it correct in the new patchset, without leaving a hole where the model would not reflect the object state.","commit_id":"516376f2c8b0cd79f407f685a2d8b9269f25b2cf"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"fc898682b204031c543de8d08e4402a9048f0ec3","unresolved":false,"context_lines":[{"line_number":544,"context_line":""},{"line_number":545,"context_line":"    @contextlib.contextmanager"},{"line_number":546,"context_line":"    def _maybe_expire_db_obj(self):"},{"line_number":547,"context_line":"        synth_changed \u003d bool(self._get_changed_object_fields())"},{"line_number":548,"context_line":"        yield"},{"line_number":549,"context_line":"        if synth_changed and self._neutron_db_obj is not None:"},{"line_number":550,"context_line":"            # expire the model so that consumers always get access to the"}],"source_content_type":"text/x-python","patch_set":8,"id":"3ac371cc_b55fe3e3","line":547,"range":{"start_line":547,"start_character":34,"end_line":547,"end_character":60},"updated":"2016-08-17 15:12:51.000000000","message":"This is wrong. _get_changed_object_fields return non-synthetic fields, thus making this function moot.","commit_id":"3024503a93343921f39d863527ef5bd110c273cc"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"a9b48eb8f43194eba4b5e7661b9423e949c742f7","unresolved":false,"context_lines":[{"line_number":544,"context_line":""},{"line_number":545,"context_line":"    @contextlib.contextmanager"},{"line_number":546,"context_line":"    def _maybe_expire_db_obj(self):"},{"line_number":547,"context_line":"        synth_changed \u003d bool(self._get_changed_object_fields())"},{"line_number":548,"context_line":"        yield"},{"line_number":549,"context_line":"        if synth_changed and self._neutron_db_obj is not None:"},{"line_number":550,"context_line":"            # expire the model so that consumers always get access to the"}],"source_content_type":"text/x-python","patch_set":8,"id":"3ac371cc_75c60b69","line":547,"range":{"start_line":547,"start_character":34,"end_line":547,"end_character":60},"in_reply_to":"3ac371cc_b55fe3e3","updated":"2016-08-17 15:27:41.000000000","message":"let me rephrase: _get_changed_object_fields will return a synthetic field *if* it\u0027s an Object (which isn\u0027t necessarily true). It might return other, non-synthetic fields as well.","commit_id":"3024503a93343921f39d863527ef5bd110c273cc"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"028d3d1a0cf5ab5afdea3024cadc02c1ee7f29a6","unresolved":false,"context_lines":[{"line_number":267,"context_line":""},{"line_number":268,"context_line":"            # expire db_obj relationships when synthetic fields are touched"},{"line_number":269,"context_line":"            if cls.synthetic_fields:"},{"line_number":270,"context_line":"                cls.create \u003d _expire_db_obj(cls.create)"},{"line_number":271,"context_line":"                cls.update \u003d _expire_db_obj(cls.update)"},{"line_number":272,"context_line":""},{"line_number":273,"context_line":"        if (hasattr(cls, \u0027has_standard_attributes\u0027) and"}],"source_content_type":"text/x-python","patch_set":14,"id":"9a89bdaa_ab3c10e3","line":270,"range":{"start_line":270,"start_character":16,"end_line":270,"end_character":55},"updated":"2016-09-06 15:09:25.000000000","message":"It would be easier to decorate NeutronDbObject.create() and update() methods and replace L225 with\n\n if cls.synthetic_fields and self._get_changed_synthetic_fields():\n     self._expire_db_obj()\n\nThen you would get a proper function into that decorator instead of unbound method.","commit_id":"c41dff73e6b290edf8e50c1e33859265d07602ec"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"6046430258549b58e9f185576a89fbd2212ef362","unresolved":false,"context_lines":[{"line_number":267,"context_line":""},{"line_number":268,"context_line":"            # expire db_obj relationships when synthetic fields are touched"},{"line_number":269,"context_line":"            if cls.synthetic_fields:"},{"line_number":270,"context_line":"                cls.create \u003d _expire_db_obj(cls.create)"},{"line_number":271,"context_line":"                cls.update \u003d _expire_db_obj(cls.update)"},{"line_number":272,"context_line":""},{"line_number":273,"context_line":"        if (hasattr(cls, \u0027has_standard_attributes\u0027) and"}],"source_content_type":"text/x-python","patch_set":14,"id":"9a89bdaa_46461bc0","line":270,"range":{"start_line":270,"start_character":16,"end_line":270,"end_character":55},"in_reply_to":"9a89bdaa_ab3c10e3","updated":"2016-09-06 15:13:56.000000000","message":"If I decorate them, overridden methods will not guarantee that the decorator is triggered BEFORE any changes to the object happen.","commit_id":"c41dff73e6b290edf8e50c1e33859265d07602ec"},{"author":{"_account_id":15518,"name":"Artur Korzeniewski","email":"artur.korzen@wp.pl","username":"akorzeni"},"change_message_id":"70efd238aa4533d11595027ce22c7f47c80a297f","unresolved":false,"context_lines":[{"line_number":546,"context_line":"        updates \u003d self._get_changed_persistent_fields()"},{"line_number":547,"context_line":"        updates \u003d self._validate_changed_fields(updates)"},{"line_number":548,"context_line":""},{"line_number":549,"context_line":"        if updates:"},{"line_number":550,"context_line":"            with db_api.autonested_transaction(self.obj_context.session):"},{"line_number":551,"context_line":"                db_obj \u003d obj_db_api.update_object("},{"line_number":552,"context_line":"                    self.obj_context, self.db_model,"}],"source_content_type":"text/x-python","patch_set":23,"id":"9a89bdaa_04f88148","side":"PARENT","line":549,"range":{"start_line":549,"start_character":8,"end_line":549,"end_character":19},"updated":"2016-09-12 13:12:42.000000000","message":"I\u0027m not sure why this is removed?","commit_id":"9f0647e181f5f7ad67e76b839fb2098f7b48efea"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"5951be61493b26a21507c7feb4a2acba096e018e","unresolved":false,"context_lines":[{"line_number":546,"context_line":"        updates \u003d self._get_changed_persistent_fields()"},{"line_number":547,"context_line":"        updates \u003d self._validate_changed_fields(updates)"},{"line_number":548,"context_line":""},{"line_number":549,"context_line":"        if updates:"},{"line_number":550,"context_line":"            with db_api.autonested_transaction(self.obj_context.session):"},{"line_number":551,"context_line":"                db_obj \u003d obj_db_api.update_object("},{"line_number":552,"context_line":"                    self.obj_context, self.db_model,"}],"source_content_type":"text/x-python","patch_set":23,"id":"9a89bdaa_24182584","side":"PARENT","line":549,"range":{"start_line":549,"start_character":8,"end_line":549,"end_character":19},"in_reply_to":"9a89bdaa_04f88148","updated":"2016-09-12 13:16:11.000000000","message":"Have you read the commit message? :)\n\nWe need it because otherwise our db_obj does not reflect the latest state of the object; we also will trigger expunge() on a model that is already detached, which will fail.","commit_id":"9f0647e181f5f7ad67e76b839fb2098f7b48efea"},{"author":{"_account_id":11816,"name":"mike bayer","display_name":"Mike Bayer","email":"mike_mp@zzzcomputing.com","username":"zzzeek","status":"Red Hat"},"change_message_id":"7e2593125465322dead251409edd61b0d7d3c1a2","unresolved":false,"context_lines":[{"line_number":233,"context_line":"            # some relationship based fields may be changed since we"},{"line_number":234,"context_line":"            # captured the model, let\u0027s refresh it for the latest database"},{"line_number":235,"context_line":"            # state"},{"line_number":236,"context_line":"            self.obj_context.session.refresh(self.db_obj)"},{"line_number":237,"context_line":"        # detach the model so that consequent fetches don\u0027t reuse it"},{"line_number":238,"context_line":"        self.obj_context.session.expunge(self.db_obj)"},{"line_number":239,"context_line":"        return res"}],"source_content_type":"text/x-python","patch_set":23,"id":"9a89bdaa_7a70c272","line":236,"updated":"2016-09-13 13:04:35.000000000","message":"so keep in mind this will load every relationship that is not lazy\u003dTrue in the model, but won\u0027t load any that are by default lazy.","commit_id":"70d3f1a2590797f31e10f4f76ef7b5a651c0b68d"},{"author":{"_account_id":11816,"name":"mike bayer","display_name":"Mike Bayer","email":"mike_mp@zzzcomputing.com","username":"zzzeek","status":"Red Hat"},"change_message_id":"843c3d7959693935313a2474efa639c988e71d70","unresolved":false,"context_lines":[{"line_number":233,"context_line":"            # some relationship based fields may be changed since we"},{"line_number":234,"context_line":"            # captured the model, let\u0027s refresh it for the latest database"},{"line_number":235,"context_line":"            # state"},{"line_number":236,"context_line":"            self.obj_context.session.refresh(self.db_obj)"},{"line_number":237,"context_line":"        # detach the model so that consequent fetches don\u0027t reuse it"},{"line_number":238,"context_line":"        self.obj_context.session.expunge(self.db_obj)"},{"line_number":239,"context_line":"        return res"}],"source_content_type":"text/x-python","patch_set":23,"id":"7a8ec9b2_85504460","line":236,"in_reply_to":"7a8ec9b2_dd740eff","updated":"2016-09-14 17:09:48.000000000","message":"there\u0027s a loader strategy called \"immediateload()\" which instructs a lazy relationship to load immediately after the regular load, but session.refresh() doesn\u0027t give an entry to this.    The most blunt way would be right after session.refresh(), to iterate through those attributes and just hit them.   \"those attributes\" can of course be found through the usual inspect() channels you\u0027ve seen now :).   session.refresh() could also be enhanced to support loader options perhaps that would be a lot nicer, but still a way to target those attributes would have to be involved.","commit_id":"70d3f1a2590797f31e10f4f76ef7b5a651c0b68d"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"588c6ed14f42b7ff715bde76413746129e77d2d2","unresolved":false,"context_lines":[{"line_number":233,"context_line":"            # some relationship based fields may be changed since we"},{"line_number":234,"context_line":"            # captured the model, let\u0027s refresh it for the latest database"},{"line_number":235,"context_line":"            # state"},{"line_number":236,"context_line":"            self.obj_context.session.refresh(self.db_obj)"},{"line_number":237,"context_line":"        # detach the model so that consequent fetches don\u0027t reuse it"},{"line_number":238,"context_line":"        self.obj_context.session.expunge(self.db_obj)"},{"line_number":239,"context_line":"        return res"}],"source_content_type":"text/x-python","patch_set":23,"id":"7a8ec9b2_dd740eff","line":236,"in_reply_to":"9a89bdaa_7a70c272","updated":"2016-09-14 08:59:03.000000000","message":"Is there a way to enforce loading all lazy relationships too? It may be handy in the future depending on how far neutron extensions may want to reuse the model for their dirty business.","commit_id":"70d3f1a2590797f31e10f4f76ef7b5a651c0b68d"},{"author":{"_account_id":11816,"name":"mike bayer","display_name":"Mike Bayer","email":"mike_mp@zzzcomputing.com","username":"zzzeek","status":"Red Hat"},"change_message_id":"8383d6c45d9c14d8b395b442071e2a9c4798695e","unresolved":false,"context_lines":[{"line_number":234,"context_line":"            # captured the model, let\u0027s refresh it for the latest database"},{"line_number":235,"context_line":"            # state"},{"line_number":236,"context_line":"            self.obj_context.session.refresh(self.db_obj)"},{"line_number":237,"context_line":"        # detach the model so that consequent fetches don\u0027t reuse it"},{"line_number":238,"context_line":"        self.obj_context.session.expunge(self.db_obj)"},{"line_number":239,"context_line":"        return res"},{"line_number":240,"context_line":"    return decorator"}],"source_content_type":"text/x-python","patch_set":23,"id":"9a89bdaa_750a9527","line":237,"updated":"2016-09-13 13:07:17.000000000","message":"oh one more note, you seem to have a collection called \"synthetic changed fields\". If you can relate those to attribute names on \"db_obj\", you can pass them into refresh() via attribute_names thus limiting what data is loaded.  Also you can just look to see what fields aren\u0027t actually loaded and limit to those, if you only care about \"unloaded\" fields.  I\u0027m not sure when we\u0027d see this refresh() running but we wouldn\u0027t want all neutron operations to be sprinkled with tons of extra SELECT statements that aren\u0027t needed (not sure if that\u0027s the effect here).","commit_id":"70d3f1a2590797f31e10f4f76ef7b5a651c0b68d"},{"author":{"_account_id":11816,"name":"mike bayer","display_name":"Mike Bayer","email":"mike_mp@zzzcomputing.com","username":"zzzeek","status":"Red Hat"},"change_message_id":"843c3d7959693935313a2474efa639c988e71d70","unresolved":false,"context_lines":[{"line_number":234,"context_line":"            # captured the model, let\u0027s refresh it for the latest database"},{"line_number":235,"context_line":"            # state"},{"line_number":236,"context_line":"            self.obj_context.session.refresh(self.db_obj)"},{"line_number":237,"context_line":"        # detach the model so that consequent fetches don\u0027t reuse it"},{"line_number":238,"context_line":"        self.obj_context.session.expunge(self.db_obj)"},{"line_number":239,"context_line":"        return res"},{"line_number":240,"context_line":"    return decorator"}],"source_content_type":"text/x-python","patch_set":23,"id":"7a8ec9b2_d08ccc81","line":237,"in_reply_to":"7a8ec9b2_7d25bac0","updated":"2016-09-14 17:09:48.000000000","message":"\u003e Here, we need to reload even those already loaded, because they may not reflect the actual state of the database (related models could be inserted by object implementation in between the parent model is inserted and captured, \n\nso on MySQL you\u0027re on REPEATABLE READ which means you\u0027d only get inserts/deletes, not updates, so this would apply only to many-to-many or one-to-many collections, not a many to one.","commit_id":"70d3f1a2590797f31e10f4f76ef7b5a651c0b68d"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"588c6ed14f42b7ff715bde76413746129e77d2d2","unresolved":false,"context_lines":[{"line_number":234,"context_line":"            # captured the model, let\u0027s refresh it for the latest database"},{"line_number":235,"context_line":"            # state"},{"line_number":236,"context_line":"            self.obj_context.session.refresh(self.db_obj)"},{"line_number":237,"context_line":"        # detach the model so that consequent fetches don\u0027t reuse it"},{"line_number":238,"context_line":"        self.obj_context.session.expunge(self.db_obj)"},{"line_number":239,"context_line":"        return res"},{"line_number":240,"context_line":"    return decorator"}],"source_content_type":"text/x-python","patch_set":23,"id":"7a8ec9b2_7d25bac0","line":237,"in_reply_to":"9a89bdaa_750a9527","updated":"2016-09-14 08:59:03.000000000","message":"Here, we need to reload even those already loaded, because they may not reflect the actual state of the database (related models could be inserted by object implementation in between the parent model is inserted and captured, and when we are ready to \u0027closure\u0027/\u0027capture\u0027 the model state on the object.\n\nBut yeah, we can reload just changed relationships. Thanks for the suggestion.\n\nJust looked at the latter, and it seems like it may take some refactoring in the object definition to expose that info (it\u0027s mostly exposed through fields_need_translation class attribute, but it\u0027s only for those cases where fields are directly mapped to relationships. For cases like is_default in security group object mapping to default_security_group relationship in the model, we don\u0027t have the info yet. I will add a todo here to consider this optimization.","commit_id":"70d3f1a2590797f31e10f4f76ef7b5a651c0b68d"},{"author":{"_account_id":11816,"name":"mike bayer","display_name":"Mike Bayer","email":"mike_mp@zzzcomputing.com","username":"zzzeek","status":"Red Hat"},"change_message_id":"7e2593125465322dead251409edd61b0d7d3c1a2","unresolved":false,"context_lines":[{"line_number":235,"context_line":"            # state"},{"line_number":236,"context_line":"            self.obj_context.session.refresh(self.db_obj)"},{"line_number":237,"context_line":"        # detach the model so that consequent fetches don\u0027t reuse it"},{"line_number":238,"context_line":"        self.obj_context.session.expunge(self.db_obj)"},{"line_number":239,"context_line":"        return res"},{"line_number":240,"context_line":"    return decorator"},{"line_number":241,"context_line":""}],"source_content_type":"text/x-python","patch_set":23,"id":"9a89bdaa_3ab63af9","line":238,"updated":"2016-09-13 13:04:35.000000000","message":"the enginefacade conversion is likely going to wind up changing this because you get a new Session on every transaction w/ enginefacade.","commit_id":"70d3f1a2590797f31e10f4f76ef7b5a651c0b68d"},{"author":{"_account_id":11816,"name":"mike bayer","display_name":"Mike Bayer","email":"mike_mp@zzzcomputing.com","username":"zzzeek","status":"Red Hat"},"change_message_id":"7e2593125465322dead251409edd61b0d7d3c1a2","unresolved":false,"context_lines":[{"line_number":327,"context_line":""},{"line_number":328,"context_line":"    def __init__(self, *args, **kwargs):"},{"line_number":329,"context_line":"        super(NeutronDbObject, self).__init__(*args, **kwargs)"},{"line_number":330,"context_line":"        self._neutron_db_obj \u003d None"},{"line_number":331,"context_line":""},{"line_number":332,"context_line":"    @property"},{"line_number":333,"context_line":"    def db_obj(self):"}],"source_content_type":"text/x-python","patch_set":23,"id":"9a89bdaa_f5e225d4","line":330,"updated":"2016-09-13 13:04:35.000000000","message":"This is a nit.   the attribute name \"_neutron_db_obj\" confuses me because we are already a NeutronDbObj.","commit_id":"70d3f1a2590797f31e10f4f76ef7b5a651c0b68d"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"588c6ed14f42b7ff715bde76413746129e77d2d2","unresolved":false,"context_lines":[{"line_number":327,"context_line":""},{"line_number":328,"context_line":"    def __init__(self, *args, **kwargs):"},{"line_number":329,"context_line":"        super(NeutronDbObject, self).__init__(*args, **kwargs)"},{"line_number":330,"context_line":"        self._neutron_db_obj \u003d None"},{"line_number":331,"context_line":""},{"line_number":332,"context_line":"    @property"},{"line_number":333,"context_line":"    def db_obj(self):"}],"source_content_type":"text/x-python","patch_set":23,"id":"7a8ec9b2_78d148fb","line":330,"in_reply_to":"9a89bdaa_f5e225d4","updated":"2016-09-14 08:59:03.000000000","message":"Renamed into _captured_db_model","commit_id":"70d3f1a2590797f31e10f4f76ef7b5a651c0b68d"},{"author":{"_account_id":8726,"name":"Victor Morales","email":"chipahuac@hotmail.com","username":"electrocucaracha"},"change_message_id":"ae38ada384c802dbaf512a52d7935ed14733398c","unresolved":false,"context_lines":[{"line_number":468,"context_line":"            return [str(val) for val in value]"},{"line_number":469,"context_line":"        return str(value)"},{"line_number":470,"context_line":""},{"line_number":471,"context_line":"    def _get_changed_persistent_fields(self):"},{"line_number":472,"context_line":"        fields \u003d self.obj_get_changes()"},{"line_number":473,"context_line":"        for field in self.synthetic_fields:"},{"line_number":474,"context_line":"            if field in fields:"},{"line_number":475,"context_line":"                del fields[field]"},{"line_number":476,"context_line":"        return fields"},{"line_number":477,"context_line":""},{"line_number":478,"context_line":"    def _get_changed_synthetic_fields(self):"},{"line_number":479,"context_line":"        fields \u003d self.obj_get_changes()"},{"line_number":480,"context_line":"        for field in self._get_changed_persistent_fields():"},{"line_number":481,"context_line":"            if field in fields:"},{"line_number":482,"context_line":"                del fields[field]"},{"line_number":483,"context_line":"        return fields"},{"line_number":484,"context_line":""},{"line_number":485,"context_line":"    def _validate_changed_fields(self, fields):"},{"line_number":486,"context_line":"        fields \u003d fields.copy()"}],"source_content_type":"text/x-python","patch_set":23,"id":"9a89bdaa_81f46c5b","line":483,"range":{"start_line":471,"start_character":0,"end_line":483,"end_character":21},"updated":"2016-09-12 19:09:17.000000000","message":"nit: What about having a single function here?\n\n    def _get_changed_fields(self, persistent_fields\u003dTrue):\n        changes \u003d self.obj_get_changes()\n        if persistent_fields:\n            fields \u003d self.synthetic_fields\n        else:\n            fields \u003d self._get_changed_persistent_fields()\n        for field in fields:\n            if field in changes:\n                del changes[field]\n        return changes","commit_id":"70d3f1a2590797f31e10f4f76ef7b5a651c0b68d"},{"author":{"_account_id":8726,"name":"Victor Morales","email":"chipahuac@hotmail.com","username":"electrocucaracha"},"change_message_id":"8a179293984708e648c42c3214c6312176bb9162","unresolved":false,"context_lines":[{"line_number":468,"context_line":"            return [str(val) for val in value]"},{"line_number":469,"context_line":"        return str(value)"},{"line_number":470,"context_line":""},{"line_number":471,"context_line":"    def _get_changed_persistent_fields(self):"},{"line_number":472,"context_line":"        fields \u003d self.obj_get_changes()"},{"line_number":473,"context_line":"        for field in self.synthetic_fields:"},{"line_number":474,"context_line":"            if field in fields:"},{"line_number":475,"context_line":"                del fields[field]"},{"line_number":476,"context_line":"        return fields"},{"line_number":477,"context_line":""},{"line_number":478,"context_line":"    def _get_changed_synthetic_fields(self):"},{"line_number":479,"context_line":"        fields \u003d self.obj_get_changes()"},{"line_number":480,"context_line":"        for field in self._get_changed_persistent_fields():"},{"line_number":481,"context_line":"            if field in fields:"},{"line_number":482,"context_line":"                del fields[field]"},{"line_number":483,"context_line":"        return fields"},{"line_number":484,"context_line":""},{"line_number":485,"context_line":"    def _validate_changed_fields(self, fields):"},{"line_number":486,"context_line":"        fields \u003d fields.copy()"}],"source_content_type":"text/x-python","patch_set":23,"id":"7a8ec9b2_045f1a73","line":483,"range":{"start_line":471,"start_character":0,"end_line":483,"end_character":21},"in_reply_to":"9a89bdaa_1e6978be","updated":"2016-09-13 18:09:33.000000000","message":"Ouch :$","commit_id":"70d3f1a2590797f31e10f4f76ef7b5a651c0b68d"},{"author":{"_account_id":8788,"name":"Miguel Angel Ajo","email":"mangelajo@redhat.com","username":"mangelajo"},"change_message_id":"77da64d06704b362f81dde42336213d894ae8ce9","unresolved":false,"context_lines":[{"line_number":468,"context_line":"            return [str(val) for val in value]"},{"line_number":469,"context_line":"        return str(value)"},{"line_number":470,"context_line":""},{"line_number":471,"context_line":"    def _get_changed_persistent_fields(self):"},{"line_number":472,"context_line":"        fields \u003d self.obj_get_changes()"},{"line_number":473,"context_line":"        for field in self.synthetic_fields:"},{"line_number":474,"context_line":"            if field in fields:"},{"line_number":475,"context_line":"                del fields[field]"},{"line_number":476,"context_line":"        return fields"},{"line_number":477,"context_line":""},{"line_number":478,"context_line":"    def _get_changed_synthetic_fields(self):"},{"line_number":479,"context_line":"        fields \u003d self.obj_get_changes()"},{"line_number":480,"context_line":"        for field in self._get_changed_persistent_fields():"},{"line_number":481,"context_line":"            if field in fields:"},{"line_number":482,"context_line":"                del fields[field]"},{"line_number":483,"context_line":"        return fields"},{"line_number":484,"context_line":""},{"line_number":485,"context_line":"    def _validate_changed_fields(self, fields):"},{"line_number":486,"context_line":"        fields \u003d fields.copy()"}],"source_content_type":"text/x-python","patch_set":23,"id":"9a89bdaa_1e6978be","line":483,"range":{"start_line":471,"start_character":0,"end_line":483,"end_character":21},"in_reply_to":"9a89bdaa_81f46c5b","updated":"2016-09-13 09:48:57.000000000","message":"@victor, I still see you reference _get_changed_persistent_fields in your case :)","commit_id":"70d3f1a2590797f31e10f4f76ef7b5a651c0b68d"},{"author":{"_account_id":11816,"name":"mike bayer","display_name":"Mike Bayer","email":"mike_mp@zzzcomputing.com","username":"zzzeek","status":"Red Hat"},"change_message_id":"7e2593125465322dead251409edd61b0d7d3c1a2","unresolved":false,"context_lines":[{"line_number":586,"context_line":"        updates \u003d self._get_changed_persistent_fields()"},{"line_number":587,"context_line":"        updates \u003d self._validate_changed_fields(updates)"},{"line_number":588,"context_line":""},{"line_number":589,"context_line":"        with db_api.autonested_transaction(self.obj_context.session):"},{"line_number":590,"context_line":"            db_obj \u003d obj_db_api.update_object("},{"line_number":591,"context_line":"                self.obj_context, self.db_model,"},{"line_number":592,"context_line":"                self.modify_fields_to_db(updates),"}],"source_content_type":"text/x-python","patch_set":23,"id":"9a89bdaa_9569d98e","line":589,"updated":"2016-09-13 13:04:35.000000000","message":"I\u0027ve had to help with problems with this API feature what\u0027s the rationale?   A SAVEPOINT should be used for all updates?","commit_id":"70d3f1a2590797f31e10f4f76ef7b5a651c0b68d"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"588c6ed14f42b7ff715bde76413746129e77d2d2","unresolved":false,"context_lines":[{"line_number":586,"context_line":"        updates \u003d self._get_changed_persistent_fields()"},{"line_number":587,"context_line":"        updates \u003d self._validate_changed_fields(updates)"},{"line_number":588,"context_line":""},{"line_number":589,"context_line":"        with db_api.autonested_transaction(self.obj_context.session):"},{"line_number":590,"context_line":"            db_obj \u003d obj_db_api.update_object("},{"line_number":591,"context_line":"                self.obj_context, self.db_model,"},{"line_number":592,"context_line":"                self.modify_fields_to_db(updates),"}],"source_content_type":"text/x-python","patch_set":23,"id":"7a8ec9b2_983c5431","line":589,"in_reply_to":"9a89bdaa_9569d98e","updated":"2016-09-14 08:59:03.000000000","message":"The rationale is that from_db_object called in line 595 may itself trigger some queries, so we need the data captured there to reflect the state of the database at the moment when the model was updated in line 590.","commit_id":"70d3f1a2590797f31e10f4f76ef7b5a651c0b68d"}],"neutron/objects/db/api.py":[{"author":{"_account_id":11816,"name":"mike bayer","display_name":"Mike Bayer","email":"mike_mp@zzzcomputing.com","username":"zzzeek","status":"Red Hat"},"change_message_id":"5d6482644eb3660f2a7f9145ddfb3ec2727f3755","unresolved":false,"context_lines":[{"line_number":29,"context_line":"def get_object(context, model, **kwargs):"},{"line_number":30,"context_line":"    query \u003d _get_filter_query(context, model, **kwargs)"},{"line_number":31,"context_line":"    # TODO(ihrachys): consider moving population into base query builder"},{"line_number":32,"context_line":"    query \u003d query.populate_existing()"},{"line_number":33,"context_line":"    return query.first()"},{"line_number":34,"context_line":""},{"line_number":35,"context_line":""}],"source_content_type":"text/x-python","patch_set":13,"id":"9a89bdaa_8bfe9536","line":32,"updated":"2016-09-05 19:39:23.000000000","message":"calling populate_existing() unconditionally will cause any pending changes in the affected objects to be lost.  The \"autoflush\" feature is implicitly disabled by populate_existing() and there are an endless number of subtle data loss bugs that can be demonstrated with this technique, such as: http://paste.openstack.org/show/566908/.","commit_id":"9acafccf2d45b36065f77a380fced6502263ff21"},{"author":{"_account_id":11816,"name":"mike bayer","display_name":"Mike Bayer","email":"mike_mp@zzzcomputing.com","username":"zzzeek","status":"Red Hat"},"change_message_id":"5d6482644eb3660f2a7f9145ddfb3ec2727f3755","unresolved":false,"context_lines":[{"line_number":54,"context_line":"            filters\u003dfilters,"},{"line_number":55,"context_line":"            # TODO(ihrachys): consider enforcing population in base query"},{"line_number":56,"context_line":"            # builder"},{"line_number":57,"context_line":"            populate_existing\u003dTrue,"},{"line_number":58,"context_line":"            **(_pager.to_kwargs(context, model) if _pager else {}))"},{"line_number":59,"context_line":""},{"line_number":60,"context_line":""}],"source_content_type":"text/x-python","patch_set":13,"id":"9a89bdaa_ab9439e2","line":57,"updated":"2016-09-05 19:39:23.000000000","message":"same issue here","commit_id":"9acafccf2d45b36065f77a380fced6502263ff21"}],"neutron/tests/unit/objects/test_base.py":[{"author":{"_account_id":8726,"name":"Victor Morales","email":"chipahuac@hotmail.com","username":"electrocucaracha"},"change_message_id":"81d0e560ec2a6d9c12e799a6f8a20e9f20359592","unresolved":false,"context_lines":[{"line_number":1142,"context_line":""},{"line_number":1143,"context_line":"        obj.create()"},{"line_number":1144,"context_line":"        self.assertIsNotNone(obj.db_obj)"},{"line_number":1145,"context_line":""},{"line_number":1146,"context_line":"        fields_to_update \u003d self.get_updatable_fields(self.obj_fields[1])"},{"line_number":1147,"context_line":"        if fields_to_update:"},{"line_number":1148,"context_line":"            old_model \u003d copy.deepcopy(obj.db_obj)"}],"source_content_type":"text/x-python","patch_set":6,"id":"bacf61ea_4f5ba82e","line":1145,"updated":"2016-07-29 15:12:33.000000000","message":"can be possible to validate that the session was forced to expire?\n\nhttps://review.openstack.org/#/c/348279/6/neutron/objects/base.py@298","commit_id":"516376f2c8b0cd79f407f685a2d8b9269f25b2cf"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"f0864b7a093b8642665f6eeb40125709d6f393cd","unresolved":false,"context_lines":[{"line_number":1142,"context_line":""},{"line_number":1143,"context_line":"        obj.create()"},{"line_number":1144,"context_line":"        self.assertIsNotNone(obj.db_obj)"},{"line_number":1145,"context_line":""},{"line_number":1146,"context_line":"        fields_to_update \u003d self.get_updatable_fields(self.obj_fields[1])"},{"line_number":1147,"context_line":"        if fields_to_update:"},{"line_number":1148,"context_line":"            old_model \u003d copy.deepcopy(obj.db_obj)"}],"source_content_type":"text/x-python","patch_set":6,"id":"bacf61ea_7bb46b81","line":1145,"in_reply_to":"bacf61ea_4f5ba82e","updated":"2016-07-29 15:44:35.000000000","message":"Property behaviour is validated in lines 1070+ and 1091+","commit_id":"516376f2c8b0cd79f407f685a2d8b9269f25b2cf"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"45e4d22ee2112ca34bffb21c2793b1aaf9d5095c","unresolved":false,"context_lines":[{"line_number":1142,"context_line":""},{"line_number":1143,"context_line":"            # reset the object so that we can compare it to other clean objects"},{"line_number":1144,"context_line":"            obj.obj_reset_changes([field])"},{"line_number":1145,"context_line":""},{"line_number":1146,"context_line":"        return obj"},{"line_number":1147,"context_line":""},{"line_number":1148,"context_line":"    def _test_get_with_synthetic_fields(self, getter):"}],"source_content_type":"text/x-python","patch_set":8,"id":"3ac371cc_caed99b8","line":1145,"updated":"2016-08-17 16:27:25.000000000","message":"Unrelated change.","commit_id":"3024503a93343921f39d863527ef5bd110c273cc"}]}
