)]}'
{"openstack/resource.py":[{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"5d139a8e2704e6278c969902e7b3d22f4f245643","unresolved":false,"context_lines":[{"line_number":367,"context_line":"        # CaseInsensitiveDict is not directly JSON serializable, so at"},{"line_number":368,"context_line":"        # this point we only want to send along its underlying dictionary."},{"line_number":369,"context_line":"        if isinstance(attrs, utils.CaseInsensitiveDict):"},{"line_number":370,"context_line":"            attrs \u003d attrs._dict"},{"line_number":371,"context_line":""},{"line_number":372,"context_line":"        if cls.resource_key:"},{"line_number":373,"context_line":"            body \u003d {cls.resource_key: attrs}"}],"source_content_type":"text/x-python","patch_set":1,"id":"da86d52c_70536a6c","line":370,"updated":"2015-02-17 01:33:41.000000000","message":"Does calling\n\n    dict(attrs)\n\nNot work here? Do we have to access a private attribute?","commit_id":"b2165346f33f9612f148c1c319f0369f98951678"},{"author":{"_account_id":8257,"name":"Brian Curtin","email":"brian@python.org","username":"briancurtin"},"change_message_id":"1f01bc61b6023f09b216fa65bb5e799d2f269f72","unresolved":false,"context_lines":[{"line_number":367,"context_line":"        # CaseInsensitiveDict is not directly JSON serializable, so at"},{"line_number":368,"context_line":"        # this point we only want to send along its underlying dictionary."},{"line_number":369,"context_line":"        if isinstance(attrs, utils.CaseInsensitiveDict):"},{"line_number":370,"context_line":"            attrs \u003d attrs._dict"},{"line_number":371,"context_line":""},{"line_number":372,"context_line":"        if cls.resource_key:"},{"line_number":373,"context_line":"            body \u003d {cls.resource_key: attrs}"}],"source_content_type":"text/x-python","patch_set":1,"id":"da86d52c_13d6b827","line":370,"in_reply_to":"da86d52c_70536a6c","updated":"2015-02-17 02:33:47.000000000","message":"Yeah, I didn\u0027t like that, but that\u0027s much better.","commit_id":"b2165346f33f9612f148c1c319f0369f98951678"},{"author":{"_account_id":8736,"name":"Terry Howe","email":"terrylhowe@gmail.com","username":"terrylhowe"},"change_message_id":"bf376a4197041b28abbbef6e7b8eee48c11c6f65","unresolved":false,"context_lines":[{"line_number":424,"context_line":"        # CaseInsensitiveDict is not directly JSON serializable, so at"},{"line_number":425,"context_line":"        # this point we only want to send along its underlying dictionary."},{"line_number":426,"context_line":"        if isinstance(attrs, utils.CaseInsensitiveDict):"},{"line_number":427,"context_line":"            attrs \u003d dict(attrs)"},{"line_number":428,"context_line":""},{"line_number":429,"context_line":"        if cls.resource_key:"},{"line_number":430,"context_line":"            body \u003d {cls.resource_key: attrs}"}],"source_content_type":"text/x-python","patch_set":4,"id":"ba7be1f8_ea8f9521","line":427,"updated":"2015-02-21 01:43:11.000000000","message":"What I\u0027d like to see is all the headers in self._attrs[\u0027headers\u0027] and that point to the case insensitive dict.  That way it is on headers only.  We can just pop \u0027headers\u0027 before making the body.  The only other change needed would be some change to prop like derive off resource.prop and make resource.propHeader or something that would always access through [\u0027headers\u0027].","commit_id":"d61db8e3fa03e40f3f7d6f653eeeddd6ee4e63b0"},{"author":{"_account_id":8257,"name":"Brian Curtin","email":"brian@python.org","username":"briancurtin"},"change_message_id":"d42fa1e274bbc0730289054026edcd4977580f45","unresolved":false,"context_lines":[{"line_number":424,"context_line":"        # CaseInsensitiveDict is not directly JSON serializable, so at"},{"line_number":425,"context_line":"        # this point we only want to send along its underlying dictionary."},{"line_number":426,"context_line":"        if isinstance(attrs, utils.CaseInsensitiveDict):"},{"line_number":427,"context_line":"            attrs \u003d dict(attrs)"},{"line_number":428,"context_line":""},{"line_number":429,"context_line":"        if cls.resource_key:"},{"line_number":430,"context_line":"            body \u003d {cls.resource_key: attrs}"}],"source_content_type":"text/x-python","patch_set":4,"id":"ba7be1f8_d31285b3","line":427,"in_reply_to":"ba7be1f8_332cc147","updated":"2015-02-21 17:34:47.000000000","message":"The bodies don\u0027t need to, but there\u0027s nothing harmed by it at the moment since we\u0027ve always had to build the body properties as case-sensitive anyway, and we\u0027re always getting them as we expect. I think we can grow this to incorporate headers being stored separately as part 2 of this change.","commit_id":"d61db8e3fa03e40f3f7d6f653eeeddd6ee4e63b0"},{"author":{"_account_id":8736,"name":"Terry Howe","email":"terrylhowe@gmail.com","username":"terrylhowe"},"change_message_id":"f333b54a6ed6110b30a277972764a505aeea7eed","unresolved":false,"context_lines":[{"line_number":424,"context_line":"        # CaseInsensitiveDict is not directly JSON serializable, so at"},{"line_number":425,"context_line":"        # this point we only want to send along its underlying dictionary."},{"line_number":426,"context_line":"        if isinstance(attrs, utils.CaseInsensitiveDict):"},{"line_number":427,"context_line":"            attrs \u003d dict(attrs)"},{"line_number":428,"context_line":""},{"line_number":429,"context_line":"        if cls.resource_key:"},{"line_number":430,"context_line":"            body \u003d {cls.resource_key: attrs}"}],"source_content_type":"text/x-python","patch_set":4,"id":"ba7be1f8_332cc147","line":427,"in_reply_to":"ba7be1f8_d0319eed","updated":"2015-02-21 16:50:40.000000000","message":"I like the idea of knowing what is a header and what is body.  Once they are mixed, you can\u0027t tell what is what.\n\nI didn\u0027t think bodies needed to be case insensitive at all. \n\nAnyway, I threw out https://review.openstack.org/158068 for some discussion.","commit_id":"d61db8e3fa03e40f3f7d6f653eeeddd6ee4e63b0"},{"author":{"_account_id":8736,"name":"Terry Howe","email":"terrylhowe@gmail.com","username":"terrylhowe"},"change_message_id":"1d372311c0c08ba2412edfe90c1b055808d7da40","unresolved":false,"context_lines":[{"line_number":424,"context_line":"        # CaseInsensitiveDict is not directly JSON serializable, so at"},{"line_number":425,"context_line":"        # this point we only want to send along its underlying dictionary."},{"line_number":426,"context_line":"        if isinstance(attrs, utils.CaseInsensitiveDict):"},{"line_number":427,"context_line":"            attrs \u003d dict(attrs)"},{"line_number":428,"context_line":""},{"line_number":429,"context_line":"        if cls.resource_key:"},{"line_number":430,"context_line":"            body \u003d {cls.resource_key: attrs}"}],"source_content_type":"text/x-python","patch_set":4,"id":"ba7be1f8_f6f2e96d","line":427,"in_reply_to":"ba7be1f8_d31285b3","updated":"2015-02-23 22:56:54.000000000","message":"Do you want to pull these changes out of resource and just merge in the util changes?","commit_id":"d61db8e3fa03e40f3f7d6f653eeeddd6ee4e63b0"},{"author":{"_account_id":8257,"name":"Brian Curtin","email":"brian@python.org","username":"briancurtin"},"change_message_id":"58156ac3b7e09d30fd5f0d4cd1d6058447b713cc","unresolved":false,"context_lines":[{"line_number":424,"context_line":"        # CaseInsensitiveDict is not directly JSON serializable, so at"},{"line_number":425,"context_line":"        # this point we only want to send along its underlying dictionary."},{"line_number":426,"context_line":"        if isinstance(attrs, utils.CaseInsensitiveDict):"},{"line_number":427,"context_line":"            attrs \u003d dict(attrs)"},{"line_number":428,"context_line":""},{"line_number":429,"context_line":"        if cls.resource_key:"},{"line_number":430,"context_line":"            body \u003d {cls.resource_key: attrs}"}],"source_content_type":"text/x-python","patch_set":4,"id":"ba7be1f8_d0319eed","line":427,"in_reply_to":"ba7be1f8_ea8f9521","updated":"2015-02-21 04:09:51.000000000","message":"Do we gain anything out of a move like that? I know we thought about splitting them several months ago, but we didn\u0027t seem to need it. That seems like it\u0027s just adding more complexity or indirection to end up with the same result, especially since we need the CaseInsensitveDict piece one way or another.\n\nAt the end of the day, we receive some converted JSON and we create a Resource out of it. The way we end up using them, the instance being made from headers or a response body doesn\u0027t seem to matter.","commit_id":"d61db8e3fa03e40f3f7d6f653eeeddd6ee4e63b0"}],"openstack/utils.py":[{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"5d139a8e2704e6278c969902e7b3d22f4f245643","unresolved":false,"context_lines":[{"line_number":39,"context_line":"            self._keys \u003d dict((key.lower(), key) for key in parent)"},{"line_number":40,"context_line":"        else:"},{"line_number":41,"context_line":"            self._keys \u003d {}"},{"line_number":42,"context_line":"        self._dict \u003d parent or {}"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"    def __getitem__(self, key):"},{"line_number":45,"context_line":"        if key is None:"}],"source_content_type":"text/x-python","patch_set":1,"id":"da86d52c_7088cac6","line":42,"updated":"2015-02-17 01:33:41.000000000","message":"You\u0027ll probably want to be able to test equality too. Feel free to crib from https://github.com/kennethreitz/requests/blob/master/requests/structures.py#L14","commit_id":"b2165346f33f9612f148c1c319f0369f98951678"},{"author":{"_account_id":8257,"name":"Brian Curtin","email":"brian@python.org","username":"briancurtin"},"change_message_id":"1f01bc61b6023f09b216fa65bb5e799d2f269f72","unresolved":false,"context_lines":[{"line_number":39,"context_line":"            self._keys \u003d dict((key.lower(), key) for key in parent)"},{"line_number":40,"context_line":"        else:"},{"line_number":41,"context_line":"            self._keys \u003d {}"},{"line_number":42,"context_line":"        self._dict \u003d parent or {}"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"    def __getitem__(self, key):"},{"line_number":45,"context_line":"        if key is None:"}],"source_content_type":"text/x-python","patch_set":1,"id":"da86d52c_d3bee0ad","line":42,"in_reply_to":"da86d52c_7088cac6","updated":"2015-02-17 02:33:47.000000000","message":"We don\u0027t seem to need this right now.","commit_id":"b2165346f33f9612f148c1c319f0369f98951678"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"5d139a8e2704e6278c969902e7b3d22f4f245643","unresolved":false,"context_lines":[{"line_number":42,"context_line":"        self._dict \u003d parent or {}"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"    def __getitem__(self, key):"},{"line_number":45,"context_line":"        if key is None:"},{"line_number":46,"context_line":"            raise KeyError(\"key is None\")"},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"        return self._dict[self._keys[key.lower()]]"}],"source_content_type":"text/x-python","patch_set":1,"id":"da86d52c_d08df6d4","line":45,"updated":"2015-02-17 01:33:41.000000000","message":"Are we sure we want to raise an exception when key is None?\n\nWhat if we rewrote this to:\n\n    if getattr(key, \u0027lower\u0027, None):\n        key \u003d key.lower()\n\n    return self._dict[self._keys[None]]\n\nWe\u0027d have to be more careful in __init__ too though (and setitem).","commit_id":"b2165346f33f9612f148c1c319f0369f98951678"},{"author":{"_account_id":8257,"name":"Brian Curtin","email":"brian@python.org","username":"briancurtin"},"change_message_id":"1f01bc61b6023f09b216fa65bb5e799d2f269f72","unresolved":false,"context_lines":[{"line_number":42,"context_line":"        self._dict \u003d parent or {}"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"    def __getitem__(self, key):"},{"line_number":45,"context_line":"        if key is None:"},{"line_number":46,"context_line":"            raise KeyError(\"key is None\")"},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"        return self._dict[self._keys[key.lower()]]"}],"source_content_type":"text/x-python","patch_set":1,"id":"da86d52c_d3a7c0a5","line":45,"in_reply_to":"da86d52c_d08df6d4","updated":"2015-02-17 02:33:47.000000000","message":"I think we do, but that\u0027s based on how this is specifically used, not as a general purpose solution. Part of this was to avoid having to be more careful elsewhere and just keep this to what we need it to do.\n\nFor example, resource.prop.__get__ tries to do a __getitem__ looking for the property\u0027s `name` and `alias`, and that __get__ handles KeyError. Since alias defaults to None, and is often None, we have to make sure we don\u0027t actually try to access either the _dict or _keys with None, otherwise we\u0027ll then have to handle KeyError ourselves as well. In the end it\u0027s just a way to short-circuit into a situation we\u0027re built for.","commit_id":"b2165346f33f9612f148c1c319f0369f98951678"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"5d139a8e2704e6278c969902e7b3d22f4f245643","unresolved":false,"context_lines":[{"line_number":70,"context_line":"            return False"},{"line_number":71,"context_line":""},{"line_number":72,"context_line":"    def __iter__(self):"},{"line_number":73,"context_line":"        return self._dict.__iter__()"},{"line_number":74,"context_line":""},{"line_number":75,"context_line":"    def __len__(self):"},{"line_number":76,"context_line":"        return len(self._dict)"}],"source_content_type":"text/x-python","patch_set":1,"id":"da86d52c_d0dfb6d4","line":73,"updated":"2015-02-17 01:33:41.000000000","message":"Why not return\n\n    iter(self._dict)","commit_id":"b2165346f33f9612f148c1c319f0369f98951678"},{"author":{"_account_id":8257,"name":"Brian Curtin","email":"brian@python.org","username":"briancurtin"},"change_message_id":"1f01bc61b6023f09b216fa65bb5e799d2f269f72","unresolved":false,"context_lines":[{"line_number":70,"context_line":"            return False"},{"line_number":71,"context_line":""},{"line_number":72,"context_line":"    def __iter__(self):"},{"line_number":73,"context_line":"        return self._dict.__iter__()"},{"line_number":74,"context_line":""},{"line_number":75,"context_line":"    def __len__(self):"},{"line_number":76,"context_line":"        return len(self._dict)"}],"source_content_type":"text/x-python","patch_set":1,"id":"da86d52c_33e73ce6","line":73,"in_reply_to":"da86d52c_d0dfb6d4","updated":"2015-02-17 02:33:47.000000000","message":"Done","commit_id":"b2165346f33f9612f148c1c319f0369f98951678"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"5d139a8e2704e6278c969902e7b3d22f4f245643","unresolved":false,"context_lines":[{"line_number":76,"context_line":"        return len(self._dict)"},{"line_number":77,"context_line":""},{"line_number":78,"context_line":"    def __repr__(self):"},{"line_number":79,"context_line":"        return self._dict.__repr__()"},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"    def copy(self):"},{"line_number":82,"context_line":"        return self._dict.copy()"}],"source_content_type":"text/x-python","patch_set":1,"id":"da86d52c_f0ed9a8f","line":79,"updated":"2015-02-17 01:33:41.000000000","message":"What about\n\n   repr(self._dict)","commit_id":"b2165346f33f9612f148c1c319f0369f98951678"},{"author":{"_account_id":8257,"name":"Brian Curtin","email":"brian@python.org","username":"briancurtin"},"change_message_id":"1f01bc61b6023f09b216fa65bb5e799d2f269f72","unresolved":false,"context_lines":[{"line_number":76,"context_line":"        return len(self._dict)"},{"line_number":77,"context_line":""},{"line_number":78,"context_line":"    def __repr__(self):"},{"line_number":79,"context_line":"        return self._dict.__repr__()"},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"    def copy(self):"},{"line_number":82,"context_line":"        return self._dict.copy()"}],"source_content_type":"text/x-python","patch_set":1,"id":"da86d52c_13e078cb","line":79,"in_reply_to":"da86d52c_f0ed9a8f","updated":"2015-02-17 02:33:47.000000000","message":"Done","commit_id":"b2165346f33f9612f148c1c319f0369f98951678"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"5d139a8e2704e6278c969902e7b3d22f4f245643","unresolved":false,"context_lines":[{"line_number":79,"context_line":"        return self._dict.__repr__()"},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"    def copy(self):"},{"line_number":82,"context_line":"        return self._dict.copy()"}],"source_content_type":"text/x-python","patch_set":1,"id":"da86d52c_90d53eb9","line":82,"updated":"2015-02-17 01:33:41.000000000","message":"Shouldn\u0027t copy return an instance of CaseInsensitiveDict, e.g.,\n\n    CaseInsensitiveDict(self._dict.copy())","commit_id":"b2165346f33f9612f148c1c319f0369f98951678"},{"author":{"_account_id":8257,"name":"Brian Curtin","email":"brian@python.org","username":"briancurtin"},"change_message_id":"1f01bc61b6023f09b216fa65bb5e799d2f269f72","unresolved":false,"context_lines":[{"line_number":79,"context_line":"        return self._dict.__repr__()"},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"    def copy(self):"},{"line_number":82,"context_line":"        return self._dict.copy()"}],"source_content_type":"text/x-python","patch_set":1,"id":"da86d52c_33b01cdd","line":82,"in_reply_to":"da86d52c_90d53eb9","updated":"2015-02-17 02:33:47.000000000","message":"Done","commit_id":"b2165346f33f9612f148c1c319f0369f98951678"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"8b4f1320fb32e2fbc82135dabd2a23469633dd48","unresolved":false,"context_lines":[{"line_number":65,"context_line":"            raise KeyError(\"key is None\")"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"        try:"},{"line_number":68,"context_line":"            return self._dict.__contains__(self._keys[key.lower()])"},{"line_number":69,"context_line":"        except KeyError:"},{"line_number":70,"context_line":"            return False"},{"line_number":71,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"da86d52c_8adfb5d5","line":68,"updated":"2015-02-17 15:01:17.000000000","message":"Sorry I missed this. Can we maybe simplify this to something like:\n\n    try:\n        key \u003d self._keys[key.lower()]\n    except KeyError:\n        return False\n\n    return key in self._dict","commit_id":"56ff5371061e5fbc5d0780ca353180ae5f4365c7"},{"author":{"_account_id":8257,"name":"Brian Curtin","email":"brian@python.org","username":"briancurtin"},"change_message_id":"3a47d867d7561000a99f14a35af4fa211ade3c9c","unresolved":false,"context_lines":[{"line_number":65,"context_line":"            raise KeyError(\"key is None\")"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"        try:"},{"line_number":68,"context_line":"            return self._dict.__contains__(self._keys[key.lower()])"},{"line_number":69,"context_line":"        except KeyError:"},{"line_number":70,"context_line":"            return False"},{"line_number":71,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"da86d52c_70f19494","line":68,"in_reply_to":"da86d52c_8adfb5d5","updated":"2015-02-17 15:36:29.000000000","message":"Good catch, done","commit_id":"56ff5371061e5fbc5d0780ca353180ae5f4365c7"},{"author":{"_account_id":8736,"name":"Terry Howe","email":"terrylhowe@gmail.com","username":"terrylhowe"},"change_message_id":"c0663a7c8a202dc05ad3411beffd00c2ed704b3d","unresolved":false,"context_lines":[{"line_number":24,"context_line":""},{"line_number":25,"context_line":""},{"line_number":26,"context_line":"class CaseInsensitiveDict(collections.MutableMapping):"},{"line_number":27,"context_line":"    \"\"\"A case insensitive dict for handling properties"},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"    In order to have resource.prop work properly for header keys,"},{"line_number":30,"context_line":"    the attribute dictionary in resource.Resource has to"}],"source_content_type":"text/x-python","patch_set":3,"id":"da86d52c_2220a448","line":27,"updated":"2015-02-17 19:57:54.000000000","message":"It is a little odd that our Resource which is a mutable map is having it attributes be another mutable map.","commit_id":"c67ce44100bd945d8125382cd3002e59f226024a"},{"author":{"_account_id":8257,"name":"Brian Curtin","email":"brian@python.org","username":"briancurtin"},"change_message_id":"5678825d63ef967168032b87a4e13a6dbc2e271c","unresolved":false,"context_lines":[{"line_number":24,"context_line":""},{"line_number":25,"context_line":""},{"line_number":26,"context_line":"class CaseInsensitiveDict(collections.MutableMapping):"},{"line_number":27,"context_line":"    \"\"\"A case insensitive dict for handling properties"},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"    In order to have resource.prop work properly for header keys,"},{"line_number":30,"context_line":"    the attribute dictionary in resource.Resource has to"}],"source_content_type":"text/x-python","patch_set":3,"id":"ba7be1f8_4a5d0121","line":27,"in_reply_to":"da86d52c_2220a448","updated":"2015-02-21 01:14:54.000000000","message":"I looked at making Resource itself handled this, but I don\u0027t know if I did it wrong or there\u0027s too much other logic I was having to mix this in with, but I couldn\u0027t get it working. It may need a larger refactoring, but functionality-wise the behavior will end up the same either way.\n\nOne benefit this brings by being on its own will be when I add support for user-generated metadata in object_store. Any of the metadata methods will have to support arbitrary strings which will have to be passed into something like this separate from the props on Container/Object. I briefly looked into what that API will look like but I got sidetracked into this issue before case-sensitivity came up there, which it would have.","commit_id":"c67ce44100bd945d8125382cd3002e59f226024a"}]}
