)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":11022,"name":"Rodrigo Duarte Sousa","email":"rodrigodsousa@gmail.com","username":"rodrigods"},"change_message_id":"b27fec7b1eb2a0ec91de339c59c6d8710a4816b4","unresolved":false,"context_lines":[{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Refactor ProviderAPIs object to better design pattern"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Utilize a shared state design pattern (Borg) instead of singlton."},{"line_number":10,"context_line":"This is a significantly better design pattern as it allows the"},{"line_number":11,"context_line":"ProviderAPIRegistry to be non-private and instantiated as needed"},{"line_number":12,"context_line":"but maintain exactly the same state across all the objects (data"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":7,"id":"3f79a3b5_e248acb3","line":9,"range":{"start_line":9,"start_character":56,"end_line":9,"end_character":64},"updated":"2018-08-16 00:33:37.000000000","message":"singleton","commit_id":"5f0882ec6d651185588d2ee4f66e9ebb18c45f1a"}],"keystone/common/provider_api.py":[{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"c3d36e8fb41501cd6de2a59dc08f7316d5d78423","unresolved":false,"context_lines":[{"line_number":19,"context_line":"    locked \u003d False"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"    def __init__(self):"},{"line_number":22,"context_line":"        # NOTE(morgan)L This rebinds __dict__ and allows all instances of"},{"line_number":23,"context_line":"        # the provider API to share a common state. Any changes except"},{"line_number":24,"context_line":"        # rebinding __dict__ will maintain the same state stored on the class"},{"line_number":25,"context_line":"        # not the instance. This design pattern is preferable to"}],"source_content_type":"text/x-python","patch_set":6,"id":"3f79a3b5_6801f605","line":22,"range":{"start_line":22,"start_character":22,"end_line":22,"end_character":23},"updated":"2018-08-15 06:37:57.000000000","message":"nit :","commit_id":"c0d0c7eae8a98f7498a260b10013ec4eb4d14701"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"eef476ca4b2a9523587b3deedaeb26dced286ce0","unresolved":false,"context_lines":[{"line_number":19,"context_line":"    locked \u003d False"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"    def __init__(self):"},{"line_number":22,"context_line":"        # NOTE(morgan)L This rebinds __dict__ and allows all instances of"},{"line_number":23,"context_line":"        # the provider API to share a common state. Any changes except"},{"line_number":24,"context_line":"        # rebinding __dict__ will maintain the same state stored on the class"},{"line_number":25,"context_line":"        # not the instance. This design pattern is preferable to"}],"source_content_type":"text/x-python","patch_set":6,"id":"3f79a3b5_f07959c4","line":22,"range":{"start_line":22,"start_character":22,"end_line":22,"end_character":23},"in_reply_to":"3f79a3b5_6801f605","updated":"2018-08-15 19:49:29.000000000","message":"That should be caught by pep8 imo :P","commit_id":"c0d0c7eae8a98f7498a260b10013ec4eb4d14701"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"c3d36e8fb41501cd6de2a59dc08f7316d5d78423","unresolved":false,"context_lines":[{"line_number":24,"context_line":"        # rebinding __dict__ will maintain the same state stored on the class"},{"line_number":25,"context_line":"        # not the instance. This design pattern is preferable to"},{"line_number":26,"context_line":"        # full singletons where state sharing is the important \"feature\""},{"line_number":27,"context_line":"        # derivd from the \"singleton\""},{"line_number":28,"context_line":"        #"},{"line_number":29,"context_line":"        # Use \"super\" to bypass the __setattr__ preventing changes to the"},{"line_number":30,"context_line":"        # object itself."}],"source_content_type":"text/x-python","patch_set":6,"id":"3f79a3b5_db2332a6","line":27,"updated":"2018-08-15 06:37:57.000000000","message":"I\u0027m not sure off the top of my head how you\u0027d test this, but that might help people understand what\u0027s going on here on a deeper level, myself included :)","commit_id":"c0d0c7eae8a98f7498a260b10013ec4eb4d14701"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"eef476ca4b2a9523587b3deedaeb26dced286ce0","unresolved":false,"context_lines":[{"line_number":24,"context_line":"        # rebinding __dict__ will maintain the same state stored on the class"},{"line_number":25,"context_line":"        # not the instance. This design pattern is preferable to"},{"line_number":26,"context_line":"        # full singletons where state sharing is the important \"feature\""},{"line_number":27,"context_line":"        # derivd from the \"singleton\""},{"line_number":28,"context_line":"        #"},{"line_number":29,"context_line":"        # Use \"super\" to bypass the __setattr__ preventing changes to the"},{"line_number":30,"context_line":"        # object itself."}],"source_content_type":"text/x-python","patch_set":6,"id":"3f79a3b5_f0007904","line":27,"in_reply_to":"3f79a3b5_db2332a6","updated":"2018-08-15 19:49:29.000000000","message":"the test is straight forward: instantiate two of them, make sure that changes to one affect the other.\n\nThat said, this sortof gets down into \"does python work\".\n\n\u003cobj\u003e.__dict__  is where all instance-level changes occur, and are referenced, e.g. when you do setattr(\u003cinstance\u003e, \"attr_name\", \"attr_value\") it is stored in \u003cinstance\u003e.__dict__\n\nIn this case we are rebinding the instance\u0027s __dict__ to the classes\u0027s __dict__. This has to be done first, but since we\u0027re not diving into a super class __init__ we can simply assign it here directly as the sole element in init.\n\nthe only reason we use super() is because of the __setattr__ defined to prevent accidental setting on the object itself (it should be relatively immutable without working really hard to change something).\n\nCan we test this? Absolutely. Does it need a test? maybe. I\u0027ll consider adding one as a followup.","commit_id":"c0d0c7eae8a98f7498a260b10013ec4eb4d14701"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"6f0c0872598ba5f1dfe3020ccad571adcb393ae7","unresolved":false,"context_lines":[{"line_number":19,"context_line":"    locked \u003d False"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"    def __init__(self):"},{"line_number":22,"context_line":"        # NOTE(morgan)L This rebinds __dict__ and allows all instances of"},{"line_number":23,"context_line":"        # the provider API to share a common state. Any changes except"},{"line_number":24,"context_line":"        # rebinding __dict__ will maintain the same state stored on the class"},{"line_number":25,"context_line":"        # not the instance. This design pattern is preferable to"}],"source_content_type":"text/x-python","patch_set":11,"id":"3f79a3b5_c9c44c43","line":22,"range":{"start_line":22,"start_character":22,"end_line":22,"end_character":23},"updated":"2018-08-21 12:20:06.000000000","message":":","commit_id":"4667ad51b3b7b394dab4d2661a0ac7bd38c9fb8b"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"c6f1a35d143e5a04d9e2e02868bb4fc2cfb36022","unresolved":false,"context_lines":[{"line_number":19,"context_line":"    locked \u003d False"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"    def __init__(self):"},{"line_number":22,"context_line":"        # NOTE(morgan)L This rebinds __dict__ and allows all instances of"},{"line_number":23,"context_line":"        # the provider API to share a common state. Any changes except"},{"line_number":24,"context_line":"        # rebinding __dict__ will maintain the same state stored on the class"},{"line_number":25,"context_line":"        # not the instance. This design pattern is preferable to"}],"source_content_type":"text/x-python","patch_set":11,"id":"3f79a3b5_e3dc7575","line":22,"range":{"start_line":22,"start_character":22,"end_line":22,"end_character":23},"in_reply_to":"3f79a3b5_c9c44c43","updated":"2018-08-23 18:02:33.000000000","message":"We need to fix hacking to catch this. We shouldn\u0027t need humans to say \"this doesn\u0027t conform\" ;)","commit_id":"4667ad51b3b7b394dab4d2661a0ac7bd38c9fb8b"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"6f0c0872598ba5f1dfe3020ccad571adcb393ae7","unresolved":false,"context_lines":[{"line_number":24,"context_line":"        # rebinding __dict__ will maintain the same state stored on the class"},{"line_number":25,"context_line":"        # not the instance. This design pattern is preferable to"},{"line_number":26,"context_line":"        # full singletons where state sharing is the important \"feature\""},{"line_number":27,"context_line":"        # derivd from the \"singleton\""},{"line_number":28,"context_line":"        #"},{"line_number":29,"context_line":"        # Use \"super\" to bypass the __setattr__ preventing changes to the"},{"line_number":30,"context_line":"        # object itself."}],"source_content_type":"text/x-python","patch_set":11,"id":"3f79a3b5_a9beb0d1","line":27,"range":{"start_line":27,"start_character":10,"end_line":27,"end_character":16},"updated":"2018-08-21 12:20:06.000000000","message":"derived*","commit_id":"4667ad51b3b7b394dab4d2661a0ac7bd38c9fb8b"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"c6f1a35d143e5a04d9e2e02868bb4fc2cfb36022","unresolved":false,"context_lines":[{"line_number":24,"context_line":"        # rebinding __dict__ will maintain the same state stored on the class"},{"line_number":25,"context_line":"        # not the instance. This design pattern is preferable to"},{"line_number":26,"context_line":"        # full singletons where state sharing is the important \"feature\""},{"line_number":27,"context_line":"        # derivd from the \"singleton\""},{"line_number":28,"context_line":"        #"},{"line_number":29,"context_line":"        # Use \"super\" to bypass the __setattr__ preventing changes to the"},{"line_number":30,"context_line":"        # object itself."}],"source_content_type":"text/x-python","patch_set":11,"id":"3f79a3b5_63d2a55e","line":27,"range":{"start_line":27,"start_character":10,"end_line":27,"end_character":16},"in_reply_to":"3f79a3b5_a9beb0d1","updated":"2018-08-23 18:02:33.000000000","message":"Fixed if we need a new patch.","commit_id":"4667ad51b3b7b394dab4d2661a0ac7bd38c9fb8b"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"19b653ea17e5e993b2728aaffb27f84028206827","unresolved":false,"context_lines":[{"line_number":28,"context_line":"        #"},{"line_number":29,"context_line":"        # Use \"super\" to bypass the __setattr__ preventing changes to the"},{"line_number":30,"context_line":"        # object itself."},{"line_number":31,"context_line":"        super(ProviderAPIRegistry, self).__setattr__("},{"line_number":32,"context_line":"            \u0027__dict__\u0027, self.__shared_object_state)"},{"line_number":33,"context_line":""},{"line_number":34,"context_line":"    def __getattr__(self, item):"},{"line_number":35,"context_line":"        \"\"\"Do attr lookup.\"\"\""}],"source_content_type":"text/x-python","patch_set":11,"id":"3f79a3b5_5b3db4db","line":32,"range":{"start_line":31,"start_character":0,"end_line":32,"end_character":51},"updated":"2018-08-28 18:42:44.000000000","message":"It\u0027s still unclear to my how this allows for shared state. I\u0027m assuming shared state means that callers of PROVIDERS.\u003capi\u003e will receive the same objects regardless, but the drivers are kept in self.__registry? self__shared_object_state isn\u0027t actually used anywhere else except here?","commit_id":"4667ad51b3b7b394dab4d2661a0ac7bd38c9fb8b"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"3ca93ae919266af1575ee3058c65c5b3766bc7ce","unresolved":false,"context_lines":[{"line_number":28,"context_line":"        #"},{"line_number":29,"context_line":"        # Use \"super\" to bypass the __setattr__ preventing changes to the"},{"line_number":30,"context_line":"        # object itself."},{"line_number":31,"context_line":"        super(ProviderAPIRegistry, self).__setattr__("},{"line_number":32,"context_line":"            \u0027__dict__\u0027, self.__shared_object_state)"},{"line_number":33,"context_line":""},{"line_number":34,"context_line":"    def __getattr__(self, item):"},{"line_number":35,"context_line":"        \"\"\"Do attr lookup.\"\"\""}],"source_content_type":"text/x-python","patch_set":11,"id":"3f79a3b5_54590133","line":32,"range":{"start_line":31,"start_character":0,"end_line":32,"end_character":51},"in_reply_to":"3f79a3b5_5b3db4db","updated":"2018-08-28 20:23:19.000000000","message":"ok, this is in how python works. All changes to instances get stored in the self.__dict__, so what we have done is created a dictionary on the class, called __shared_object_state, we then rebind the instances __dict__ to the class attribute __shared_object_state.\n\nthis means that any change we do to the instance is applied to the class __dict__ [and since all instances share the __dict__ change to one instance impacts all instances in memory]\n\nThe __setattr__ is strictly used (in super form) so no one accidentally sets values we don\u0027t expect.\n\nLong term this allows us to instantiate on demand instead of needing to maintain a global ProvidersAPIs, long term.\n\nSo basically what happens here:\n\nObjectX (with rebound __dict__) is instantiated\n\nobjectX.NewAttr \u003d True\n\nObjectY instantiated (same class as ObjectX), and if you set NewAttr \u003d False, both instances reflect the change.","commit_id":"4667ad51b3b7b394dab4d2661a0ac7bd38c9fb8b"}]}
