)]}'
{"cinder/objects/base.py":[{"author":{"_account_id":11803,"name":"Ryan Rossiter","email":"rlrossit@us.ibm.com","username":"rlrossiter"},"change_message_id":"9ebae158cae6e32435f698d52fb75e94b8f99f3c","unresolved":false,"context_lines":[{"line_number":227,"context_line":"        # We\u0027re using obj_extra_fields to provide aliases for some fields while"},{"line_number":228,"context_line":"        # in transition period. This override is to make these aliases pass"},{"line_number":229,"context_line":"        # \"\u0027foo\u0027 in obj\" tests."},{"line_number":230,"context_line":"        return name in self.obj_extra_fields or super(CinderObject,"},{"line_number":231,"context_line":"                                                      self).__contains__(name)"},{"line_number":232,"context_line":""},{"line_number":233,"context_line":""}],"source_content_type":"text/x-python","patch_set":14,"id":"fa69d971_39323ff3","line":230,"updated":"2016-01-05 14:42:13.000000000","message":"You should use a try except AttributeError that returns false in case the object doesn\u0027t have obj_extra_fields, similar to how super() works.","commit_id":"dd4e1465c527aa52b270a97b5b59e4fd0f76b8af"},{"author":{"_account_id":11600,"name":"Michał Dulko","email":"michal.dulko@gmail.com","username":"dulek"},"change_message_id":"e8bd74a57611aa3a733db26241fbceb799a87557","unresolved":false,"context_lines":[{"line_number":227,"context_line":"        # We\u0027re using obj_extra_fields to provide aliases for some fields while"},{"line_number":228,"context_line":"        # in transition period. This override is to make these aliases pass"},{"line_number":229,"context_line":"        # \"\u0027foo\u0027 in obj\" tests."},{"line_number":230,"context_line":"        return name in self.obj_extra_fields or super(CinderObject,"},{"line_number":231,"context_line":"                                                      self).__contains__(name)"},{"line_number":232,"context_line":""},{"line_number":233,"context_line":""}],"source_content_type":"text/x-python","patch_set":14,"id":"fa69d971_ea46037a","line":230,"in_reply_to":"fa69d971_39323ff3","updated":"2016-01-05 15:37:37.000000000","message":"But that\u0027s defined in base VersionedObject class [1] - it shouldn\u0027t be missing from an object.\n\n[1] https://github.com/openstack/oslo.versionedobjects/blob/master/oslo_versionedobjects/base.py#L270","commit_id":"dd4e1465c527aa52b270a97b5b59e4fd0f76b8af"},{"author":{"_account_id":11803,"name":"Ryan Rossiter","email":"rlrossit@us.ibm.com","username":"rlrossiter"},"change_message_id":"ff7cc3345505748e229f6db69e3c4c3c2303036e","unresolved":false,"context_lines":[{"line_number":227,"context_line":"        # We\u0027re using obj_extra_fields to provide aliases for some fields while"},{"line_number":228,"context_line":"        # in transition period. This override is to make these aliases pass"},{"line_number":229,"context_line":"        # \"\u0027foo\u0027 in obj\" tests."},{"line_number":230,"context_line":"        return name in self.obj_extra_fields or super(CinderObject,"},{"line_number":231,"context_line":"                                                      self).__contains__(name)"},{"line_number":232,"context_line":""},{"line_number":233,"context_line":""}],"source_content_type":"text/x-python","patch_set":14,"id":"fa69d971_d32737b4","line":230,"in_reply_to":"fa69d971_ea46037a","updated":"2016-01-05 17:13:58.000000000","message":"Huh I never knew that. I thought that was something added on some of the Cinder objects. Never mind then!","commit_id":"dd4e1465c527aa52b270a97b5b59e4fd0f76b8af"}],"cinder/objects/volume.py":[{"author":{"_account_id":8247,"name":"Thang Pham","email":"thang.g.pham@gmail.com","username":"thang.pham"},"change_message_id":"c9a593d5579352eb8452c91e1e114d2f19dacfbc","unresolved":false,"context_lines":[{"line_number":105,"context_line":"    def name(self):"},{"line_number":106,"context_line":"        return CONF.volume_name_template % self.name_id"},{"line_number":107,"context_line":""},{"line_number":108,"context_line":"    # NOTE(dulek): Two properties below are for compatibility with dict"},{"line_number":109,"context_line":"    # representation of volume. The format there is different (list of dicts)"},{"line_number":110,"context_line":"    # so we need a conversion."},{"line_number":111,"context_line":"    @property"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba8a016a_9d998b7b","line":108,"updated":"2015-11-19 20:17:36.000000000","message":"We should make a TODO to eventually remove this workaround.","commit_id":"b25467c5c543be2218cd1bfd673bb17eab8e3c4e"},{"author":{"_account_id":11600,"name":"Michał Dulko","email":"michal.dulko@gmail.com","username":"dulek"},"change_message_id":"eedf84c8c729da42e72d5b064da93b3982c6ca01","unresolved":false,"context_lines":[{"line_number":105,"context_line":"    def name(self):"},{"line_number":106,"context_line":"        return CONF.volume_name_template % self.name_id"},{"line_number":107,"context_line":""},{"line_number":108,"context_line":"    # NOTE(dulek): Two properties below are for compatibility with dict"},{"line_number":109,"context_line":"    # representation of volume. The format there is different (list of dicts)"},{"line_number":110,"context_line":"    # so we need a conversion."},{"line_number":111,"context_line":"    @property"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba8a016a_638e882f","line":108,"in_reply_to":"ba8a016a_9d998b7b","updated":"2015-11-19 21:01:09.000000000","message":"Done","commit_id":"b25467c5c543be2218cd1bfd673bb17eab8e3c4e"},{"author":{"_account_id":11803,"name":"Ryan Rossiter","email":"rlrossit@us.ibm.com","username":"rlrossiter"},"change_message_id":"e09979f7f2d4116b1cac60c99b3aa9a75f7c3e0f","unresolved":false,"context_lines":[{"line_number":28,"context_line":""},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"@base.CinderObjectRegistry.register"},{"line_number":31,"context_line":"class Volume(base.CinderPersistentObject, base.CinderObjectDictCompat,"},{"line_number":32,"context_line":"             base.CinderObject, base.CinderComparableObject):"},{"line_number":33,"context_line":"    # Version 1.0: Initial version"},{"line_number":34,"context_line":"    # Version 1.1: Added metadata, admin_metadata, volume_attachment, and"}],"source_content_type":"text/x-python","patch_set":13,"id":"fa69d971_3cafb495","line":31,"updated":"2016-01-04 19:53:24.000000000","message":"I don\u0027t think DictCompat should be on the inheritance list before CinderObject. You don\u0027t want DictCompat to move up on the MRO on the object, especially because DictCompat is essentially tech debt.","commit_id":"68d5b78fc4b5d0004b56ee2fb2fc9b702fda0d1b"},{"author":{"_account_id":11600,"name":"Michał Dulko","email":"michal.dulko@gmail.com","username":"dulek"},"change_message_id":"397a3163a43da0d3e58ef86f7163342b1cde9ba7","unresolved":false,"context_lines":[{"line_number":28,"context_line":""},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"@base.CinderObjectRegistry.register"},{"line_number":31,"context_line":"class Volume(base.CinderPersistentObject, base.CinderObjectDictCompat,"},{"line_number":32,"context_line":"             base.CinderObject, base.CinderComparableObject):"},{"line_number":33,"context_line":"    # Version 1.0: Initial version"},{"line_number":34,"context_line":"    # Version 1.1: Added metadata, admin_metadata, volume_attachment, and"}],"source_content_type":"text/x-python","patch_set":13,"id":"fa69d971_c267744b","line":31,"in_reply_to":"fa69d971_3ab9f179","updated":"2016-01-05 10:37:49.000000000","message":"Thank you for elaborating on this one. This makes sense and I\u0027ve moved overridden __contains__ to CinderObject as it certainly fits there more.\n\nThis won\u0027t affect anything as every object deriving from CinderObjectDictCompat derives from CinderObject also.","commit_id":"68d5b78fc4b5d0004b56ee2fb2fc9b702fda0d1b"},{"author":{"_account_id":11600,"name":"Michał Dulko","email":"michal.dulko@gmail.com","username":"dulek"},"change_message_id":"e7c3c04f9bfcbb1f88738b3806870227e6bfc80e","unresolved":false,"context_lines":[{"line_number":28,"context_line":""},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"@base.CinderObjectRegistry.register"},{"line_number":31,"context_line":"class Volume(base.CinderPersistentObject, base.CinderObjectDictCompat,"},{"line_number":32,"context_line":"             base.CinderObject, base.CinderComparableObject):"},{"line_number":33,"context_line":"    # Version 1.0: Initial version"},{"line_number":34,"context_line":"    # Version 1.1: Added metadata, admin_metadata, volume_attachment, and"}],"source_content_type":"text/x-python","patch_set":13,"id":"fa69d971_92a007a1","line":31,"in_reply_to":"fa69d971_3cafb495","updated":"2016-01-04 20:31:12.000000000","message":"Ah, right. I\u0027ve did that to get \"\u0027prop\u0027 in obj\" tests to correctly return True for obj_extra_fields (see [1]). __contains__ is also defined on CinderObject, but behaves differently than on dicts, so that why I\u0027ve needed to move this up.\n\nIn general the aim of the patch is to have compatibility with older dict-like behavior of Volume object because I don\u0027t think we can fix all the ~70 Cinder drivers at once and bugs that result from missing fields are constantly reported.\n\nCan you point me to a way how to do this in a better way?\n\n[1] https://github.com/openstack/cinder/blob/master/cinder/objects/base.py#L267-L272\n[2] https://github.com/openstack/oslo.versionedobjects/blob/master/oslo_versionedobjects/base.py#L316-L320","commit_id":"68d5b78fc4b5d0004b56ee2fb2fc9b702fda0d1b"},{"author":{"_account_id":11803,"name":"Ryan Rossiter","email":"rlrossit@us.ibm.com","username":"rlrossiter"},"change_message_id":"9da22fc1fd1dd2934287a34cc47065f3ffa70c6b","unresolved":false,"context_lines":[{"line_number":28,"context_line":""},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"@base.CinderObjectRegistry.register"},{"line_number":31,"context_line":"class Volume(base.CinderPersistentObject, base.CinderObjectDictCompat,"},{"line_number":32,"context_line":"             base.CinderObject, base.CinderComparableObject):"},{"line_number":33,"context_line":"    # Version 1.0: Initial version"},{"line_number":34,"context_line":"    # Version 1.1: Added metadata, admin_metadata, volume_attachment, and"}],"source_content_type":"text/x-python","patch_set":13,"id":"fa69d971_3ab9f179","line":31,"in_reply_to":"fa69d971_92a007a1","updated":"2016-01-04 21:59:12.000000000","message":"Hmm that is a tough one. So I guess I would argue that because __contains__ is something set on CinderObject (or rather VersionedObject) with the given behavior currently, shouldn\u0027t the new __contains__ be set on CinderObject? Because in o.vo VersionedObject\u0027s __contains__ is doing self.obj_attr_is_set(), and now CinderObjectDictCompat is now trying to take over that and more. Is obj_extra_fields something that randomly needs to be set on the RPC dicts that isn\u0027t wanted on the object itself? Or is it just tack-on stuff that CinderObject needs? (Basically what I\u0027m asking is, which Python object is obj_extra_fields most related to?)\n\nI would think CinderObject would look like:\n\n    def __contains__(self, name):\n        try:\n            return name in self.obj_extra_fields or super(CinderObject,\n                self).__contains__(name)\n        except AttributeError:\n            return False\n\n\nAnd yeah, I know the DictCompat thing isn\u0027t going to be solved quickly/easily (Rome wasn\u0027t conquered in a day, though I think conquering Rome would be easier than eliminating DictCompat), but adding to its tech debt mountain should be avoided if possible :/","commit_id":"68d5b78fc4b5d0004b56ee2fb2fc9b702fda0d1b"},{"author":{"_account_id":11803,"name":"Ryan Rossiter","email":"rlrossit@us.ibm.com","username":"rlrossiter"},"change_message_id":"9ebae158cae6e32435f698d52fb75e94b8f99f3c","unresolved":false,"context_lines":[{"line_number":206,"context_line":"        # Get data from db_volume object that was queried by joined query"},{"line_number":207,"context_line":"        # from DB"},{"line_number":208,"context_line":"        if \u0027metadata\u0027 in expected_attrs:"},{"line_number":209,"context_line":"            volume.metadata \u003d {}"},{"line_number":210,"context_line":"            metadata \u003d db_volume.get(\u0027volume_metadata\u0027, [])"},{"line_number":211,"context_line":"            volume.metadata \u003d {item[\u0027key\u0027]: item[\u0027value\u0027] for item in metadata}"},{"line_number":212,"context_line":"        if \u0027admin_metadata\u0027 in expected_attrs:"}],"source_content_type":"text/x-python","patch_set":14,"id":"fa69d971_7998b7c0","line":209,"updated":"2016-01-05 14:42:13.000000000","message":"If you feel like it, you can remove all of these empty dict assignments and the beginning of these ifs. Since volume.metadata is guaranteed to be set now (it will evaluate to {} in the dict comprehension if metadata \u003d\u003d [].","commit_id":"dd4e1465c527aa52b270a97b5b59e4fd0f76b8af"},{"author":{"_account_id":11803,"name":"Ryan Rossiter","email":"rlrossit@us.ibm.com","username":"rlrossiter"},"change_message_id":"9ebae158cae6e32435f698d52fb75e94b8f99f3c","unresolved":false,"context_lines":[{"line_number":210,"context_line":"            metadata \u003d db_volume.get(\u0027volume_metadata\u0027, [])"},{"line_number":211,"context_line":"            volume.metadata \u003d {item[\u0027key\u0027]: item[\u0027value\u0027] for item in metadata}"},{"line_number":212,"context_line":"        if \u0027admin_metadata\u0027 in expected_attrs:"},{"line_number":213,"context_line":"            volume.admin_metadata \u003d {}"},{"line_number":214,"context_line":"            metadata \u003d db_volume.get(\u0027volume_admin_metadata\u0027, [])"},{"line_number":215,"context_line":"            volume.admin_metadata \u003d {item[\u0027key\u0027]: item[\u0027value\u0027]"},{"line_number":216,"context_line":"                                     for item in metadata}"}],"source_content_type":"text/x-python","patch_set":14,"id":"fa69d971_99956b88","line":213,"updated":"2016-01-05 14:42:13.000000000","message":"Same here","commit_id":"dd4e1465c527aa52b270a97b5b59e4fd0f76b8af"},{"author":{"_account_id":11803,"name":"Ryan Rossiter","email":"rlrossit@us.ibm.com","username":"rlrossiter"},"change_message_id":"9ebae158cae6e32435f698d52fb75e94b8f99f3c","unresolved":false,"context_lines":[{"line_number":215,"context_line":"            volume.admin_metadata \u003d {item[\u0027key\u0027]: item[\u0027value\u0027]"},{"line_number":216,"context_line":"                                     for item in metadata}"},{"line_number":217,"context_line":"        if \u0027glance_metadata\u0027 in expected_attrs:"},{"line_number":218,"context_line":"            volume.glance_metadata \u003d {}"},{"line_number":219,"context_line":"            metadata \u003d db_volume.get(\u0027volume_glance_metadata\u0027, [])"},{"line_number":220,"context_line":"            volume.glance_metadata \u003d {item[\u0027key\u0027]: item[\u0027value\u0027]"},{"line_number":221,"context_line":"                                      for item in metadata}"}],"source_content_type":"text/x-python","patch_set":14,"id":"fa69d971_598b7368","line":218,"updated":"2016-01-05 14:42:13.000000000","message":"Same here","commit_id":"dd4e1465c527aa52b270a97b5b59e4fd0f76b8af"}],"cinder/scheduler/rpcapi.py":[{"author":{"_account_id":1736,"name":"Ivan Kolodyazhny","email":"e0ne@e0ne.info","username":"e0ne"},"change_message_id":"3ef76ba5e2cfa4999d672e2275fa1059162625ea","unresolved":false,"context_lines":[{"line_number":112,"context_line":"        cctxt \u003d self.client.prepare(version\u003dversion)"},{"line_number":113,"context_line":"        return cctxt.cast(ctxt, \u0027migrate_volume_to_host\u0027, **msg_args)"},{"line_number":114,"context_line":""},{"line_number":115,"context_line":"    def retype(self, ctxt, topic, volume_id, request_spec\u003dNone,"},{"line_number":116,"context_line":"               filter_properties\u003dNone, volume\u003dNone):"},{"line_number":117,"context_line":"        request_spec_p \u003d jsonutils.to_primitive(request_spec)"},{"line_number":118,"context_line":"        msg_args \u003d {\u0027topic\u0027: topic, \u0027volume_id\u0027: volume_id,"}],"source_content_type":"text/x-python","patch_set":10,"id":"7a740942_9e056212","line":115,"updated":"2015-12-11 14:03:18.000000000","message":"Do we need this change?","commit_id":"31cefac4ecf3f034aa2fd8374a7b86a04ce8aebb"}],"cinder/tests/unit/test_volume.py":[{"author":{"_account_id":8247,"name":"Thang Pham","email":"thang.g.pham@gmail.com","username":"thang.pham"},"change_message_id":"c9a593d5579352eb8452c91e1e114d2f19dacfbc","unresolved":false,"context_lines":[{"line_number":562,"context_line":"            \u0027replication_status\u0027: \u0027disabled\u0027,"},{"line_number":563,"context_line":"            \u0027replication_extended_status\u0027: None,"},{"line_number":564,"context_line":"            \u0027replication_driver_data\u0027: None,"},{"line_number":565,"context_line":"            \u0027metadata\u0027: [],"},{"line_number":566,"context_line":"            \u0027volume_attachment\u0027: [],"},{"line_number":567,"context_line":"        }"},{"line_number":568,"context_line":"        self.assertDictMatch(expected, msg[\u0027payload\u0027])"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba8a016a_fdae977f","line":565,"updated":"2015-11-19 20:17:36.000000000","message":"metadata should be a dict, right?","commit_id":"b25467c5c543be2218cd1bfd673bb17eab8e3c4e"},{"author":{"_account_id":11600,"name":"Michał Dulko","email":"michal.dulko@gmail.com","username":"dulek"},"change_message_id":"eedf84c8c729da42e72d5b064da93b3982c6ca01","unresolved":false,"context_lines":[{"line_number":562,"context_line":"            \u0027replication_status\u0027: \u0027disabled\u0027,"},{"line_number":563,"context_line":"            \u0027replication_extended_status\u0027: None,"},{"line_number":564,"context_line":"            \u0027replication_driver_data\u0027: None,"},{"line_number":565,"context_line":"            \u0027metadata\u0027: [],"},{"line_number":566,"context_line":"            \u0027volume_attachment\u0027: [],"},{"line_number":567,"context_line":"        }"},{"line_number":568,"context_line":"        self.assertDictMatch(expected, msg[\u0027payload\u0027])"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba8a016a_c398947a","line":565,"in_reply_to":"ba8a016a_fdae977f","updated":"2015-11-19 21:01:09.000000000","message":"Nope, that\u0027s asserting a notification, which metadata field is fetched from volume_metadata.\n\nWe don\u0027t know if someone isn\u0027t relying on this being a list, so I wouldn\u0027t change that. So… this commit actually fixes a regression in notifications.","commit_id":"b25467c5c543be2218cd1bfd673bb17eab8e3c4e"}]}
