)]}'
{"smaug/api/v1/plans.py":[{"author":{"_account_id":2023,"name":"Saggi Mizrahi","email":"ficoos+osreview@gmail.com","username":"ficoos"},"change_message_id":"1e1fe253c4f4d89280bbb31125de234d30815f50","unresolved":false,"context_lines":[{"line_number":45,"context_line":"    smaug.policy.enforce(context, _action, target)"},{"line_number":46,"context_line":""},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"class ViewBuilder(object):"},{"line_number":49,"context_line":"    \"\"\"Model a server API response as a python dictionary.\"\"\""},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"    _collection_name \u003d \"plans\""}],"source_content_type":"text/x-python","patch_set":2,"id":"5a5ae5dd_412fbe3e","line":48,"range":{"start_line":48,"start_character":6,"end_line":48,"end_character":17},"updated":"2016-02-08 13:18:11.000000000","message":"I assume every py file will have it\u0027s own view builder.\nSo please name it _ViewBuider so it\u0027s clear this is module private.","commit_id":"6c5316735429f3affbd9232dd52120e8685d6618"},{"author":{"_account_id":17151,"name":"chenying","email":"chenyingko@gmail.com","username":"chenying"},"change_message_id":"8a360c9450f8a951f5d72cd997fec092a744ca66","unresolved":false,"context_lines":[{"line_number":45,"context_line":"    smaug.policy.enforce(context, _action, target)"},{"line_number":46,"context_line":""},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"class ViewBuilder(object):"},{"line_number":49,"context_line":"    \"\"\"Model a server API response as a python dictionary.\"\"\""},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"    _collection_name \u003d \"plans\""}],"source_content_type":"text/x-python","patch_set":2,"id":"dae33548_d004eac7","line":48,"range":{"start_line":48,"start_character":6,"end_line":48,"end_character":17},"in_reply_to":"5a5ae5dd_412fbe3e","updated":"2016-02-14 07:25:17.000000000","message":"Done","commit_id":"6c5316735429f3affbd9232dd52120e8685d6618"},{"author":{"_account_id":2023,"name":"Saggi Mizrahi","email":"ficoos+osreview@gmail.com","username":"ficoos"},"change_message_id":"1e1fe253c4f4d89280bbb31125de234d30815f50","unresolved":false,"context_lines":[{"line_number":117,"context_line":"        plan \u003d body[\u0027plan\u0027]"},{"line_number":118,"context_line":"        LOG.debug(\u0027Create plan request plan: %s\u0027, plan)"},{"line_number":119,"context_line":""},{"line_number":120,"context_line":"        if not plan[\"provider_id\"]:"},{"line_number":121,"context_line":"            msg \u003d _(\"provider_id must be provided when creating \""},{"line_number":122,"context_line":"                    \"a plan.\")"},{"line_number":123,"context_line":"            raise exception.InvalidInput(reason\u003dmsg)"}],"source_content_type":"text/x-python","patch_set":2,"id":"5a5ae5dd_642c4899","line":120,"range":{"start_line":120,"start_character":8,"end_line":120,"end_character":34},"updated":"2016-02-08 13:18:11.000000000","message":"The current code will fail with the wrong exception if the key is not provided.\n\n if not plan.get(\"provider_id\")\n\nCovers the current case and the case where the key is mot in the dict.","commit_id":"6c5316735429f3affbd9232dd52120e8685d6618"},{"author":{"_account_id":17151,"name":"chenying","email":"chenyingko@gmail.com","username":"chenying"},"change_message_id":"8a360c9450f8a951f5d72cd997fec092a744ca66","unresolved":false,"context_lines":[{"line_number":117,"context_line":"        plan \u003d body[\u0027plan\u0027]"},{"line_number":118,"context_line":"        LOG.debug(\u0027Create plan request plan: %s\u0027, plan)"},{"line_number":119,"context_line":""},{"line_number":120,"context_line":"        if not plan[\"provider_id\"]:"},{"line_number":121,"context_line":"            msg \u003d _(\"provider_id must be provided when creating \""},{"line_number":122,"context_line":"                    \"a plan.\")"},{"line_number":123,"context_line":"            raise exception.InvalidInput(reason\u003dmsg)"}],"source_content_type":"text/x-python","patch_set":2,"id":"dae33548_70699e8b","line":120,"range":{"start_line":120,"start_character":8,"end_line":120,"end_character":34},"in_reply_to":"5a5ae5dd_642c4899","updated":"2016-02-14 07:25:17.000000000","message":"Done","commit_id":"6c5316735429f3affbd9232dd52120e8685d6618"},{"author":{"_account_id":2023,"name":"Saggi Mizrahi","email":"ficoos+osreview@gmail.com","username":"ficoos"},"change_message_id":"1e1fe253c4f4d89280bbb31125de234d30815f50","unresolved":false,"context_lines":[{"line_number":155,"context_line":"        plan \u003d body[\u0027plan\u0027]"},{"line_number":156,"context_line":"        update_dict \u003d {}"},{"line_number":157,"context_line":""},{"line_number":158,"context_line":"        valid_update_keys \u003d ("},{"line_number":159,"context_line":"            \u0027name\u0027,"},{"line_number":160,"context_line":"            \u0027resources\u0027,"},{"line_number":161,"context_line":"            \u0027status\u0027,"},{"line_number":162,"context_line":"        )"},{"line_number":163,"context_line":""},{"line_number":164,"context_line":"        for key in valid_update_keys:"},{"line_number":165,"context_line":"            if key in plan:"}],"source_content_type":"text/x-python","patch_set":2,"id":"5a5ae5dd_c4fbbc77","line":162,"range":{"start_line":158,"start_character":0,"end_line":162,"end_character":9},"updated":"2016-02-08 13:18:11.000000000","message":"use a set\n\n valid_update_keys \u003d {\n     \u0027name\u0027,\n     \u0027resources\u0027,\n     \u0027status\u0027,\n }","commit_id":"6c5316735429f3affbd9232dd52120e8685d6618"},{"author":{"_account_id":17151,"name":"chenying","email":"chenyingko@gmail.com","username":"chenying"},"change_message_id":"8a360c9450f8a951f5d72cd997fec092a744ca66","unresolved":false,"context_lines":[{"line_number":155,"context_line":"        plan \u003d body[\u0027plan\u0027]"},{"line_number":156,"context_line":"        update_dict \u003d {}"},{"line_number":157,"context_line":""},{"line_number":158,"context_line":"        valid_update_keys \u003d ("},{"line_number":159,"context_line":"            \u0027name\u0027,"},{"line_number":160,"context_line":"            \u0027resources\u0027,"},{"line_number":161,"context_line":"            \u0027status\u0027,"},{"line_number":162,"context_line":"        )"},{"line_number":163,"context_line":""},{"line_number":164,"context_line":"        for key in valid_update_keys:"},{"line_number":165,"context_line":"            if key in plan:"}],"source_content_type":"text/x-python","patch_set":2,"id":"dae33548_906c229e","line":162,"range":{"start_line":158,"start_character":0,"end_line":162,"end_character":9},"in_reply_to":"5a5ae5dd_c4fbbc77","updated":"2016-02-14 07:25:17.000000000","message":"Done","commit_id":"6c5316735429f3affbd9232dd52120e8685d6618"},{"author":{"_account_id":2023,"name":"Saggi Mizrahi","email":"ficoos+osreview@gmail.com","username":"ficoos"},"change_message_id":"1e1fe253c4f4d89280bbb31125de234d30815f50","unresolved":false,"context_lines":[{"line_number":161,"context_line":"            \u0027status\u0027,"},{"line_number":162,"context_line":"        )"},{"line_number":163,"context_line":""},{"line_number":164,"context_line":"        for key in valid_update_keys:"},{"line_number":165,"context_line":"            if key in plan:"},{"line_number":166,"context_line":"                update_dict[key] \u003d plan[key]"},{"line_number":167,"context_line":""},{"line_number":168,"context_line":"        self.validate_name_and_description(update_dict)"}],"source_content_type":"text/x-python","patch_set":2,"id":"5a5ae5dd_e46b581c","line":165,"range":{"start_line":164,"start_character":0,"end_line":165,"end_character":27},"updated":"2016-02-08 13:18:11.000000000","message":"for key in valid_update_keys.intersection(plan):","commit_id":"6c5316735429f3affbd9232dd52120e8685d6618"},{"author":{"_account_id":17151,"name":"chenying","email":"chenyingko@gmail.com","username":"chenying"},"change_message_id":"8a360c9450f8a951f5d72cd997fec092a744ca66","unresolved":false,"context_lines":[{"line_number":161,"context_line":"            \u0027status\u0027,"},{"line_number":162,"context_line":"        )"},{"line_number":163,"context_line":""},{"line_number":164,"context_line":"        for key in valid_update_keys:"},{"line_number":165,"context_line":"            if key in plan:"},{"line_number":166,"context_line":"                update_dict[key] \u003d plan[key]"},{"line_number":167,"context_line":""},{"line_number":168,"context_line":"        self.validate_name_and_description(update_dict)"}],"source_content_type":"text/x-python","patch_set":2,"id":"dae33548_306f1694","line":165,"range":{"start_line":164,"start_character":0,"end_line":165,"end_character":27},"in_reply_to":"5a5ae5dd_e46b581c","updated":"2016-02-14 07:25:17.000000000","message":"Done","commit_id":"6c5316735429f3affbd9232dd52120e8685d6618"},{"author":{"_account_id":2023,"name":"Saggi Mizrahi","email":"ficoos+osreview@gmail.com","username":"ficoos"},"change_message_id":"1e1fe253c4f4d89280bbb31125de234d30815f50","unresolved":false,"context_lines":[{"line_number":166,"context_line":"                update_dict[key] \u003d plan[key]"},{"line_number":167,"context_line":""},{"line_number":168,"context_line":"        self.validate_name_and_description(update_dict)"},{"line_number":169,"context_line":"        if update_dict[\"resources\"]:"},{"line_number":170,"context_line":"            self.validate_plan_resources(update_dict)"},{"line_number":171,"context_line":""},{"line_number":172,"context_line":"        try:"}],"source_content_type":"text/x-python","patch_set":2,"id":"5a5ae5dd_84f064ca","line":169,"range":{"start_line":169,"start_character":11,"end_line":169,"end_character":36},"updated":"2016-02-08 13:18:11.000000000","message":"again, use update_dict.get() if not sure about a key\u0027s existence","commit_id":"6c5316735429f3affbd9232dd52120e8685d6618"},{"author":{"_account_id":17151,"name":"chenying","email":"chenyingko@gmail.com","username":"chenying"},"change_message_id":"8a360c9450f8a951f5d72cd997fec092a744ca66","unresolved":false,"context_lines":[{"line_number":166,"context_line":"                update_dict[key] \u003d plan[key]"},{"line_number":167,"context_line":""},{"line_number":168,"context_line":"        self.validate_name_and_description(update_dict)"},{"line_number":169,"context_line":"        if update_dict[\"resources\"]:"},{"line_number":170,"context_line":"            self.validate_plan_resources(update_dict)"},{"line_number":171,"context_line":""},{"line_number":172,"context_line":"        try:"}],"source_content_type":"text/x-python","patch_set":2,"id":"dae33548_105812fa","line":169,"range":{"start_line":169,"start_character":11,"end_line":169,"end_character":36},"in_reply_to":"5a5ae5dd_84f064ca","updated":"2016-02-14 07:25:17.000000000","message":"Done","commit_id":"6c5316735429f3affbd9232dd52120e8685d6618"},{"author":{"_account_id":2023,"name":"Saggi Mizrahi","email":"ficoos+osreview@gmail.com","username":"ficoos"},"change_message_id":"1e1fe253c4f4d89280bbb31125de234d30815f50","unresolved":false,"context_lines":[{"line_number":200,"context_line":"            msg \u003d _(\"The plan cannot be updated during protection.\")"},{"line_number":201,"context_line":"            raise exception.InvalidPlan(reason\u003dmsg)"},{"line_number":202,"context_line":""},{"line_number":203,"context_line":"        if isinstance(plan, objects_base.SmaugObject):"},{"line_number":204,"context_line":"            plan.update(fields)"},{"line_number":205,"context_line":"            plan.save()"},{"line_number":206,"context_line":"            LOG.info(_LI(\"Plan updated successfully.\"), resource\u003dplan)"}],"source_content_type":"text/x-python","patch_set":2,"id":"5a5ae5dd_a4b3204c","line":203,"range":{"start_line":203,"start_character":0,"end_line":203,"end_character":54},"updated":"2016-02-08 13:18:11.000000000","message":"Shouldn\u0027t we throw an error if this condition fails?","commit_id":"6c5316735429f3affbd9232dd52120e8685d6618"},{"author":{"_account_id":17151,"name":"chenying","email":"chenyingko@gmail.com","username":"chenying"},"change_message_id":"8a360c9450f8a951f5d72cd997fec092a744ca66","unresolved":false,"context_lines":[{"line_number":200,"context_line":"            msg \u003d _(\"The plan cannot be updated during protection.\")"},{"line_number":201,"context_line":"            raise exception.InvalidPlan(reason\u003dmsg)"},{"line_number":202,"context_line":""},{"line_number":203,"context_line":"        if isinstance(plan, objects_base.SmaugObject):"},{"line_number":204,"context_line":"            plan.update(fields)"},{"line_number":205,"context_line":"            plan.save()"},{"line_number":206,"context_line":"            LOG.info(_LI(\"Plan updated successfully.\"), resource\u003dplan)"}],"source_content_type":"text/x-python","patch_set":2,"id":"dae33548_b06206ac","line":203,"range":{"start_line":203,"start_character":0,"end_line":203,"end_character":54},"in_reply_to":"5a5ae5dd_a4b3204c","updated":"2016-02-14 07:25:17.000000000","message":"Done","commit_id":"6c5316735429f3affbd9232dd52120e8685d6618"},{"author":{"_account_id":2023,"name":"Saggi Mizrahi","email":"ficoos+osreview@gmail.com","username":"ficoos"},"change_message_id":"1e1fe253c4f4d89280bbb31125de234d30815f50","unresolved":false,"context_lines":[{"line_number":205,"context_line":"            plan.save()"},{"line_number":206,"context_line":"            LOG.info(_LI(\"Plan updated successfully.\"), resource\u003dplan)"},{"line_number":207,"context_line":""},{"line_number":208,"context_line":"    def validate_plan_resources(self, plan):"},{"line_number":209,"context_line":"        resources_list \u003d plan[\"resources\"]"},{"line_number":210,"context_line":"        if (resources_list is not None) and (isinstance(resources_list, list))\\"},{"line_number":211,"context_line":"                and (len(resources_list) \u003e 0):"}],"source_content_type":"text/x-python","patch_set":2,"id":"5a5ae5dd_647a088a","line":208,"range":{"start_line":208,"start_character":8,"end_line":208,"end_character":31},"updated":"2016-02-08 13:18:11.000000000","message":"Is this really public?","commit_id":"6c5316735429f3affbd9232dd52120e8685d6618"},{"author":{"_account_id":2023,"name":"Saggi Mizrahi","email":"ficoos+osreview@gmail.com","username":"ficoos"},"change_message_id":"1e1fe253c4f4d89280bbb31125de234d30815f50","unresolved":false,"context_lines":[{"line_number":206,"context_line":"            LOG.info(_LI(\"Plan updated successfully.\"), resource\u003dplan)"},{"line_number":207,"context_line":""},{"line_number":208,"context_line":"    def validate_plan_resources(self, plan):"},{"line_number":209,"context_line":"        resources_list \u003d plan[\"resources\"]"},{"line_number":210,"context_line":"        if (resources_list is not None) and (isinstance(resources_list, list))\\"},{"line_number":211,"context_line":"                and (len(resources_list) \u003e 0):"},{"line_number":212,"context_line":"            for resource in resources_list:"}],"source_content_type":"text/x-python","patch_set":2,"id":"5a5ae5dd_e41ef80a","line":209,"range":{"start_line":209,"start_character":25,"end_line":209,"end_character":42},"updated":"2016-02-08 13:18:11.000000000","message":"use\n\n plan.get(\"resources\")\n\nif you are not sure it exists.","commit_id":"6c5316735429f3affbd9232dd52120e8685d6618"},{"author":{"_account_id":17151,"name":"chenying","email":"chenyingko@gmail.com","username":"chenying"},"change_message_id":"8a360c9450f8a951f5d72cd997fec092a744ca66","unresolved":false,"context_lines":[{"line_number":206,"context_line":"            LOG.info(_LI(\"Plan updated successfully.\"), resource\u003dplan)"},{"line_number":207,"context_line":""},{"line_number":208,"context_line":"    def validate_plan_resources(self, plan):"},{"line_number":209,"context_line":"        resources_list \u003d plan[\"resources\"]"},{"line_number":210,"context_line":"        if (resources_list is not None) and (isinstance(resources_list, list))\\"},{"line_number":211,"context_line":"                and (len(resources_list) \u003e 0):"},{"line_number":212,"context_line":"            for resource in resources_list:"}],"source_content_type":"text/x-python","patch_set":2,"id":"dae33548_70523edf","line":209,"range":{"start_line":209,"start_character":25,"end_line":209,"end_character":42},"in_reply_to":"5a5ae5dd_e41ef80a","updated":"2016-02-14 07:25:17.000000000","message":"Done","commit_id":"6c5316735429f3affbd9232dd52120e8685d6618"},{"author":{"_account_id":2023,"name":"Saggi Mizrahi","email":"ficoos+osreview@gmail.com","username":"ficoos"},"change_message_id":"1e1fe253c4f4d89280bbb31125de234d30815f50","unresolved":false,"context_lines":[{"line_number":207,"context_line":""},{"line_number":208,"context_line":"    def validate_plan_resources(self, plan):"},{"line_number":209,"context_line":"        resources_list \u003d plan[\"resources\"]"},{"line_number":210,"context_line":"        if (resources_list is not None) and (isinstance(resources_list, list))\\"},{"line_number":211,"context_line":"                and (len(resources_list) \u003e 0):"},{"line_number":212,"context_line":"            for resource in resources_list:"},{"line_number":213,"context_line":"                if isinstance(resource, dict) and (len(resource) \u003d\u003d 2) \\"}],"source_content_type":"text/x-python","patch_set":2,"id":"5a5ae5dd_01fd466d","line":210,"range":{"start_line":210,"start_character":78,"end_line":210,"end_character":79},"updated":"2016-02-08 13:18:11.000000000","message":"Use () for the whole condition instead of \\\n\nhttps://www.python.org/dev/peps/pep-0008/#multiline-if-statements","commit_id":"6c5316735429f3affbd9232dd52120e8685d6618"},{"author":{"_account_id":2023,"name":"Saggi Mizrahi","email":"ficoos+osreview@gmail.com","username":"ficoos"},"change_message_id":"1e1fe253c4f4d89280bbb31125de234d30815f50","unresolved":false,"context_lines":[{"line_number":207,"context_line":""},{"line_number":208,"context_line":"    def validate_plan_resources(self, plan):"},{"line_number":209,"context_line":"        resources_list \u003d plan[\"resources\"]"},{"line_number":210,"context_line":"        if (resources_list is not None) and (isinstance(resources_list, list))\\"},{"line_number":211,"context_line":"                and (len(resources_list) \u003e 0):"},{"line_number":212,"context_line":"            for resource in resources_list:"},{"line_number":213,"context_line":"                if isinstance(resource, dict) and (len(resource) \u003d\u003d 2) \\"}],"source_content_type":"text/x-python","patch_set":2,"id":"5a5ae5dd_04c9d4ab","line":210,"range":{"start_line":210,"start_character":11,"end_line":210,"end_character":78},"updated":"2016-02-08 13:18:11.000000000","message":"isinstance covers both of these conditions, namely:\n\n isinstance(None, list) \u003d\u003d False","commit_id":"6c5316735429f3affbd9232dd52120e8685d6618"},{"author":{"_account_id":17151,"name":"chenying","email":"chenyingko@gmail.com","username":"chenying"},"change_message_id":"8a360c9450f8a951f5d72cd997fec092a744ca66","unresolved":false,"context_lines":[{"line_number":207,"context_line":""},{"line_number":208,"context_line":"    def validate_plan_resources(self, plan):"},{"line_number":209,"context_line":"        resources_list \u003d plan[\"resources\"]"},{"line_number":210,"context_line":"        if (resources_list is not None) and (isinstance(resources_list, list))\\"},{"line_number":211,"context_line":"                and (len(resources_list) \u003e 0):"},{"line_number":212,"context_line":"            for resource in resources_list:"},{"line_number":213,"context_line":"                if isinstance(resource, dict) and (len(resource) \u003d\u003d 2) \\"}],"source_content_type":"text/x-python","patch_set":2,"id":"dae33548_905542c8","line":210,"range":{"start_line":210,"start_character":11,"end_line":210,"end_character":78},"in_reply_to":"5a5ae5dd_04c9d4ab","updated":"2016-02-14 07:25:17.000000000","message":"Done","commit_id":"6c5316735429f3affbd9232dd52120e8685d6618"},{"author":{"_account_id":2023,"name":"Saggi Mizrahi","email":"ficoos+osreview@gmail.com","username":"ficoos"},"change_message_id":"1e1fe253c4f4d89280bbb31125de234d30815f50","unresolved":false,"context_lines":[{"line_number":208,"context_line":"    def validate_plan_resources(self, plan):"},{"line_number":209,"context_line":"        resources_list \u003d plan[\"resources\"]"},{"line_number":210,"context_line":"        if (resources_list is not None) and (isinstance(resources_list, list))\\"},{"line_number":211,"context_line":"                and (len(resources_list) \u003e 0):"},{"line_number":212,"context_line":"            for resource in resources_list:"},{"line_number":213,"context_line":"                if isinstance(resource, dict) and (len(resource) \u003d\u003d 2) \\"},{"line_number":214,"context_line":"                        and (\"id\" in resource) and (\"type\" in resource):"}],"source_content_type":"text/x-python","patch_set":2,"id":"5a5ae5dd_2443b014","line":211,"range":{"start_line":211,"start_character":20,"end_line":211,"end_character":45},"updated":"2016-02-08 13:18:11.000000000","message":"You could just do:\n\n resource_list.count \u003e 0\n\nsince you know it\u0027s a list\n\nBut you can just skip it, you know it\u0027s not None so the `for loop` will just skip if the list is empty.","commit_id":"6c5316735429f3affbd9232dd52120e8685d6618"},{"author":{"_account_id":2023,"name":"Saggi Mizrahi","email":"ficoos+osreview@gmail.com","username":"ficoos"},"change_message_id":"1e1fe253c4f4d89280bbb31125de234d30815f50","unresolved":false,"context_lines":[{"line_number":210,"context_line":"        if (resources_list is not None) and (isinstance(resources_list, list))\\"},{"line_number":211,"context_line":"                and (len(resources_list) \u003e 0):"},{"line_number":212,"context_line":"            for resource in resources_list:"},{"line_number":213,"context_line":"                if isinstance(resource, dict) and (len(resource) \u003d\u003d 2) \\"},{"line_number":214,"context_line":"                        and (\"id\" in resource) and (\"type\" in resource):"},{"line_number":215,"context_line":"                    pass"},{"line_number":216,"context_line":"                else:"},{"line_number":217,"context_line":"                    msg \u003d _(\" resource in list must be a dict when creating\""}],"source_content_type":"text/x-python","patch_set":2,"id":"5a5ae5dd_21eac274","line":214,"range":{"start_line":213,"start_character":50,"end_line":214,"end_character":71},"updated":"2016-02-08 13:18:11.000000000","message":"{\"id\", \"type\"}.issubset(resource)","commit_id":"6c5316735429f3affbd9232dd52120e8685d6618"},{"author":{"_account_id":17151,"name":"chenying","email":"chenyingko@gmail.com","username":"chenying"},"change_message_id":"8a360c9450f8a951f5d72cd997fec092a744ca66","unresolved":false,"context_lines":[{"line_number":210,"context_line":"        if (resources_list is not None) and (isinstance(resources_list, list))\\"},{"line_number":211,"context_line":"                and (len(resources_list) \u003e 0):"},{"line_number":212,"context_line":"            for resource in resources_list:"},{"line_number":213,"context_line":"                if isinstance(resource, dict) and (len(resource) \u003d\u003d 2) \\"},{"line_number":214,"context_line":"                        and (\"id\" in resource) and (\"type\" in resource):"},{"line_number":215,"context_line":"                    pass"},{"line_number":216,"context_line":"                else:"},{"line_number":217,"context_line":"                    msg \u003d _(\" resource in list must be a dict when creating\""}],"source_content_type":"text/x-python","patch_set":2,"id":"dae33548_3048b62d","line":214,"range":{"start_line":213,"start_character":50,"end_line":214,"end_character":71},"in_reply_to":"5a5ae5dd_21eac274","updated":"2016-02-14 07:25:17.000000000","message":"{\"id\", \"type\"}.issubset(resource) When resource has anohter third key, It also is true.","commit_id":"6c5316735429f3affbd9232dd52120e8685d6618"},{"author":{"_account_id":13070,"name":"Eran Gampel","email":"eran@gampel.net","username":"Gampel"},"change_message_id":"f5336cc9a79358c1b6037ac753f645c616b85742","unresolved":false,"context_lines":[{"line_number":192,"context_line":"        return plan"},{"line_number":193,"context_line":""},{"line_number":194,"context_line":"    def _plan_update(self, context, plan, fields):"},{"line_number":195,"context_line":"        if plan[\u0027status\u0027] \u003d\u003d \u0027started\u0027:"},{"line_number":196,"context_line":"            LOG.info(_LI(\"Unable to update plan, \""},{"line_number":197,"context_line":"                         \"because it is in protection.\"), resource\u003dplan)"},{"line_number":198,"context_line":"            msg \u003d _(\"The plan cannot be updated during protection.\")"}],"source_content_type":"text/x-python","patch_set":3,"id":"dae33548_58b58ecb","line":195,"range":{"start_line":195,"start_character":11,"end_line":195,"end_character":39},"updated":"2016-02-15 08:50:27.000000000","message":"Started means that we called start()\n\nDo we want to enforce Update on  plan only when it is in Suspended state?\nIf yes then the message below should reflect that","commit_id":"3ef199b27db2136ce137ea170fc9eaaf33aede79"},{"author":{"_account_id":17151,"name":"chenying","email":"chenyingko@gmail.com","username":"chenying"},"change_message_id":"ca2bc4e5efc34409531faa3b3029dbd91f896487","unresolved":false,"context_lines":[{"line_number":192,"context_line":"        return plan"},{"line_number":193,"context_line":""},{"line_number":194,"context_line":"    def _plan_update(self, context, plan, fields):"},{"line_number":195,"context_line":"        if plan[\u0027status\u0027] \u003d\u003d \u0027started\u0027:"},{"line_number":196,"context_line":"            LOG.info(_LI(\"Unable to update plan, \""},{"line_number":197,"context_line":"                         \"because it is in protection.\"), resource\u003dplan)"},{"line_number":198,"context_line":"            msg \u003d _(\"The plan cannot be updated during protection.\")"}],"source_content_type":"text/x-python","patch_set":3,"id":"dae33548_916ff191","line":195,"range":{"start_line":195,"start_character":11,"end_line":195,"end_character":39},"in_reply_to":"dae33548_58b58ecb","updated":"2016-02-15 09:52:44.000000000","message":"OK I understood. That means plan only can be updated in suspended state.","commit_id":"3ef199b27db2136ce137ea170fc9eaaf33aede79"},{"author":{"_account_id":13070,"name":"Eran Gampel","email":"eran@gampel.net","username":"Gampel"},"change_message_id":"f5336cc9a79358c1b6037ac753f645c616b85742","unresolved":false,"context_lines":[{"line_number":195,"context_line":"        if plan[\u0027status\u0027] \u003d\u003d \u0027started\u0027:"},{"line_number":196,"context_line":"            LOG.info(_LI(\"Unable to update plan, \""},{"line_number":197,"context_line":"                         \"because it is in protection.\"), resource\u003dplan)"},{"line_number":198,"context_line":"            msg \u003d _(\"The plan cannot be updated during protection.\")"},{"line_number":199,"context_line":"            raise exception.InvalidPlan(reason\u003dmsg)"},{"line_number":200,"context_line":""},{"line_number":201,"context_line":"        if isinstance(plan, objects_base.SmaugObject):"}],"source_content_type":"text/x-python","patch_set":3,"id":"dae33548_78fe926c","line":198,"range":{"start_line":198,"start_character":22,"end_line":198,"end_character":66},"updated":"2016-02-15 08:50:27.000000000","message":"This does not mean to my understanding that it is currently in Protect it means that it is started and running \n\nWhen we call protect we serialize the plan into the checkpoint so there is no problem updating the plan","commit_id":"3ef199b27db2136ce137ea170fc9eaaf33aede79"},{"author":{"_account_id":17151,"name":"chenying","email":"chenyingko@gmail.com","username":"chenying"},"change_message_id":"ca2bc4e5efc34409531faa3b3029dbd91f896487","unresolved":false,"context_lines":[{"line_number":195,"context_line":"        if plan[\u0027status\u0027] \u003d\u003d \u0027started\u0027:"},{"line_number":196,"context_line":"            LOG.info(_LI(\"Unable to update plan, \""},{"line_number":197,"context_line":"                         \"because it is in protection.\"), resource\u003dplan)"},{"line_number":198,"context_line":"            msg \u003d _(\"The plan cannot be updated during protection.\")"},{"line_number":199,"context_line":"            raise exception.InvalidPlan(reason\u003dmsg)"},{"line_number":200,"context_line":""},{"line_number":201,"context_line":"        if isinstance(plan, objects_base.SmaugObject):"}],"source_content_type":"text/x-python","patch_set":3,"id":"dae33548_d173394c","line":198,"range":{"start_line":198,"start_character":22,"end_line":198,"end_character":66},"in_reply_to":"dae33548_78fe926c","updated":"2016-02-15 09:52:44.000000000","message":"I will modify the messages.","commit_id":"3ef199b27db2136ce137ea170fc9eaaf33aede79"},{"author":{"_account_id":16203,"name":"zengyingzhe","email":"zengyingzhe@huawei.com","username":"zengyingzhe"},"change_message_id":"0a54319ae17581c02f0ebc7b859456b9fa65de29","unresolved":false,"context_lines":[{"line_number":57,"context_line":"    def detail(self, request, plan):"},{"line_number":58,"context_line":"        \"\"\"Detailed view of a single plan.\"\"\""},{"line_number":59,"context_line":"        plan_ref \u003d {"},{"line_number":60,"context_line":"            \u0027plan\u0027: {"},{"line_number":61,"context_line":"                \u0027id\u0027: plan.get(\u0027id\u0027),"},{"line_number":62,"context_line":"                \u0027name\u0027: plan.get(\u0027name\u0027),"},{"line_number":63,"context_line":"                \u0027resources\u0027: plan.get(\u0027resources\u0027),"}],"source_content_type":"text/x-python","patch_set":5,"id":"dae33548_26f0fcfd","line":60,"updated":"2016-02-17 06:54:10.000000000","message":"missing status","commit_id":"25c3e44c4527ef5d34102a91f7c4ec04e033e53a"},{"author":{"_account_id":16203,"name":"zengyingzhe","email":"zengyingzhe@huawei.com","username":"zengyingzhe"},"change_message_id":"0a54319ae17581c02f0ebc7b859456b9fa65de29","unresolved":false,"context_lines":[{"line_number":161,"context_line":"            \u0027status\u0027,"},{"line_number":162,"context_line":"        }"},{"line_number":163,"context_line":"        for key in valid_update_keys.intersection(plan):"},{"line_number":164,"context_line":"            update_dict[key] \u003d plan[key]"},{"line_number":165,"context_line":""},{"line_number":166,"context_line":"        self.validate_name_and_description(update_dict)"},{"line_number":167,"context_line":"        if update_dict.get(\"resources\"):"}],"source_content_type":"text/x-python","patch_set":5,"id":"dae33548_4665401c","line":164,"range":{"start_line":164,"start_character":12,"end_line":164,"end_character":23},"updated":"2016-02-17 06:54:10.000000000","message":"Could have a check if update_dict is empty, if it\u0027s, then no need to run the below logic anymore.","commit_id":"25c3e44c4527ef5d34102a91f7c4ec04e033e53a"},{"author":{"_account_id":17151,"name":"chenying","email":"chenyingko@gmail.com","username":"chenying"},"change_message_id":"bf79a1a8d08a1921602e00220cc59ff922049ebd","unresolved":false,"context_lines":[{"line_number":161,"context_line":"            \u0027status\u0027,"},{"line_number":162,"context_line":"        }"},{"line_number":163,"context_line":"        for key in valid_update_keys.intersection(plan):"},{"line_number":164,"context_line":"            update_dict[key] \u003d plan[key]"},{"line_number":165,"context_line":""},{"line_number":166,"context_line":"        self.validate_name_and_description(update_dict)"},{"line_number":167,"context_line":"        if update_dict.get(\"resources\"):"}],"source_content_type":"text/x-python","patch_set":5,"id":"dae33548_dd6abeb2","line":164,"range":{"start_line":164,"start_character":12,"end_line":164,"end_character":23},"in_reply_to":"dae33548_4665401c","updated":"2016-02-17 07:24:17.000000000","message":"update_dict must include resources parameter. If update_dict is none, that mean update  resources  with none.","commit_id":"25c3e44c4527ef5d34102a91f7c4ec04e033e53a"},{"author":{"_account_id":17151,"name":"chenying","email":"chenyingko@gmail.com","username":"chenying"},"change_message_id":"b5e3fe19a48f547d4f5612e090b6c269a2d3b178","unresolved":false,"context_lines":[{"line_number":161,"context_line":"            \u0027status\u0027,"},{"line_number":162,"context_line":"        }"},{"line_number":163,"context_line":"        for key in valid_update_keys.intersection(plan):"},{"line_number":164,"context_line":"            update_dict[key] \u003d plan[key]"},{"line_number":165,"context_line":""},{"line_number":166,"context_line":"        self.validate_name_and_description(update_dict)"},{"line_number":167,"context_line":"        if update_dict.get(\"resources\"):"}],"source_content_type":"text/x-python","patch_set":5,"id":"dae33548_708639dc","line":164,"range":{"start_line":164,"start_character":12,"end_line":164,"end_character":23},"in_reply_to":"dae33548_dd6abeb2","updated":"2016-02-17 08:07:05.000000000","message":"If update_dict is none I add a raising a exception.","commit_id":"25c3e44c4527ef5d34102a91f7c4ec04e033e53a"},{"author":{"_account_id":16203,"name":"zengyingzhe","email":"zengyingzhe@huawei.com","username":"zengyingzhe"},"change_message_id":"0a54319ae17581c02f0ebc7b859456b9fa65de29","unresolved":false,"context_lines":[{"line_number":180,"context_line":"        retval \u003d self._view_builder.detail(req, plan)"},{"line_number":181,"context_line":"        return retval"},{"line_number":182,"context_line":""},{"line_number":183,"context_line":"    def _paln_get(self, context, plan_id):"},{"line_number":184,"context_line":"        plan \u003d objects.Plan.get_by_id(context, plan_id)"},{"line_number":185,"context_line":"        try:"},{"line_number":186,"context_line":"            check_policy(context, \u0027get\u0027, plan)"}],"source_content_type":"text/x-python","patch_set":5,"id":"dae33548_4bbee965","line":183,"range":{"start_line":183,"start_character":8,"end_line":183,"end_character":17},"updated":"2016-02-17 06:54:10.000000000","message":"_plan_get","commit_id":"25c3e44c4527ef5d34102a91f7c4ec04e033e53a"},{"author":{"_account_id":17151,"name":"chenying","email":"chenyingko@gmail.com","username":"chenying"},"change_message_id":"bf79a1a8d08a1921602e00220cc59ff922049ebd","unresolved":false,"context_lines":[{"line_number":180,"context_line":"        retval \u003d self._view_builder.detail(req, plan)"},{"line_number":181,"context_line":"        return retval"},{"line_number":182,"context_line":""},{"line_number":183,"context_line":"    def _paln_get(self, context, plan_id):"},{"line_number":184,"context_line":"        plan \u003d objects.Plan.get_by_id(context, plan_id)"},{"line_number":185,"context_line":"        try:"},{"line_number":186,"context_line":"            check_policy(context, \u0027get\u0027, plan)"}],"source_content_type":"text/x-python","patch_set":5,"id":"dae33548_1d61c6d3","line":183,"range":{"start_line":183,"start_character":8,"end_line":183,"end_character":17},"in_reply_to":"dae33548_4bbee965","updated":"2016-02-17 07:24:17.000000000","message":"Done","commit_id":"25c3e44c4527ef5d34102a91f7c4ec04e033e53a"},{"author":{"_account_id":16203,"name":"zengyingzhe","email":"zengyingzhe@huawei.com","username":"zengyingzhe"},"change_message_id":"0a54319ae17581c02f0ebc7b859456b9fa65de29","unresolved":false,"context_lines":[{"line_number":192,"context_line":"        return plan"},{"line_number":193,"context_line":""},{"line_number":194,"context_line":"    def _plan_update(self, context, plan, fields):"},{"line_number":195,"context_line":"        if plan[\u0027status\u0027] !\u003d \u0027suspended\u0027:"},{"line_number":196,"context_line":"            LOG.info(_LI(\"Unable to update plan, \""},{"line_number":197,"context_line":"                         \"because it is in %s state.\"), plan[\u0027status\u0027])"},{"line_number":198,"context_line":"            msg \u003d _(\"The plan can be only updated in suspended status.\")"}],"source_content_type":"text/x-python","patch_set":5,"id":"dae33548_06fb3848","line":195,"range":{"start_line":195,"start_character":30,"end_line":195,"end_character":39},"updated":"2016-02-17 06:54:10.000000000","message":"In create method, the initial status is \u0027suspending\u0027, different from here.\nsuggest defining a uniform status constant, rather than use string directly.","commit_id":"25c3e44c4527ef5d34102a91f7c4ec04e033e53a"},{"author":{"_account_id":17151,"name":"chenying","email":"chenyingko@gmail.com","username":"chenying"},"change_message_id":"bf79a1a8d08a1921602e00220cc59ff922049ebd","unresolved":false,"context_lines":[{"line_number":192,"context_line":"        return plan"},{"line_number":193,"context_line":""},{"line_number":194,"context_line":"    def _plan_update(self, context, plan, fields):"},{"line_number":195,"context_line":"        if plan[\u0027status\u0027] !\u003d \u0027suspended\u0027:"},{"line_number":196,"context_line":"            LOG.info(_LI(\"Unable to update plan, \""},{"line_number":197,"context_line":"                         \"because it is in %s state.\"), plan[\u0027status\u0027])"},{"line_number":198,"context_line":"            msg \u003d _(\"The plan can be only updated in suspended status.\")"}],"source_content_type":"text/x-python","patch_set":5,"id":"dae33548_fd8b4266","line":195,"range":{"start_line":195,"start_character":30,"end_line":195,"end_character":39},"in_reply_to":"dae33548_06fb3848","updated":"2016-02-17 07:24:17.000000000","message":"I will modify the status value in create method.","commit_id":"25c3e44c4527ef5d34102a91f7c4ec04e033e53a"},{"author":{"_account_id":16203,"name":"zengyingzhe","email":"zengyingzhe@huawei.com","username":"zengyingzhe"},"change_message_id":"46469d8d7668097a4dfcd3b586d8bae6d1341032","unresolved":false,"context_lines":[{"line_number":206,"context_line":"        if isinstance(plan, objects_base.SmaugObject):"},{"line_number":207,"context_line":"            plan.update(fields)"},{"line_number":208,"context_line":"            plan.save()"},{"line_number":209,"context_line":"            LOG.info(_LI(\"Plan updated successfully.\"), resource\u003dplan)"},{"line_number":210,"context_line":"        else:"},{"line_number":211,"context_line":"            msg \u003d _(\"The parameter plan must be a object of \""},{"line_number":212,"context_line":"                    \"SmaugObject class.\")"}],"source_content_type":"text/x-python","patch_set":9,"id":"bae84128_745f7b41","line":209,"updated":"2016-02-22 04:02:27.000000000","message":"Please add a TODO here, cause if plan\u0027s state is changed to \u0027start\u0027, need to call the start operation for this plan.","commit_id":"86fc2a3cb4d63a6746ac80af2aa080573de88aad"},{"author":{"_account_id":17151,"name":"chenying","email":"chenyingko@gmail.com","username":"chenying"},"change_message_id":"7126d96a026cdd03e6d17d5d978fcb99de695095","unresolved":false,"context_lines":[{"line_number":206,"context_line":"        if isinstance(plan, objects_base.SmaugObject):"},{"line_number":207,"context_line":"            plan.update(fields)"},{"line_number":208,"context_line":"            plan.save()"},{"line_number":209,"context_line":"            LOG.info(_LI(\"Plan updated successfully.\"), resource\u003dplan)"},{"line_number":210,"context_line":"        else:"},{"line_number":211,"context_line":"            msg \u003d _(\"The parameter plan must be a object of \""},{"line_number":212,"context_line":"                    \"SmaugObject class.\")"}],"source_content_type":"text/x-python","patch_set":9,"id":"bae84128_9bc98a7b","line":209,"in_reply_to":"bae84128_745f7b41","updated":"2016-02-22 07:08:57.000000000","message":"Done","commit_id":"86fc2a3cb4d63a6746ac80af2aa080573de88aad"},{"author":{"_account_id":16203,"name":"zengyingzhe","email":"zengyingzhe@huawei.com","username":"zengyingzhe"},"change_message_id":"46469d8d7668097a4dfcd3b586d8bae6d1341032","unresolved":false,"context_lines":[{"line_number":220,"context_line":"                        {\"id\", \"type\"}.issubset(resource)):"},{"line_number":221,"context_line":"                    pass"},{"line_number":222,"context_line":"                else:"},{"line_number":223,"context_line":"                    msg \u003d _(\" resource in list must be a dict when creating\""},{"line_number":224,"context_line":"                            \" a plan.The key of resource are id and type.\")"},{"line_number":225,"context_line":"                    raise exception.InvalidInput(reason\u003dmsg)"},{"line_number":226,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":9,"id":"bae84128_34833306","line":223,"range":{"start_line":223,"start_character":29,"end_line":223,"end_character":30},"updated":"2016-02-22 04:02:27.000000000","message":"redundant space character.","commit_id":"86fc2a3cb4d63a6746ac80af2aa080573de88aad"},{"author":{"_account_id":17151,"name":"chenying","email":"chenyingko@gmail.com","username":"chenying"},"change_message_id":"7126d96a026cdd03e6d17d5d978fcb99de695095","unresolved":false,"context_lines":[{"line_number":220,"context_line":"                        {\"id\", \"type\"}.issubset(resource)):"},{"line_number":221,"context_line":"                    pass"},{"line_number":222,"context_line":"                else:"},{"line_number":223,"context_line":"                    msg \u003d _(\" resource in list must be a dict when creating\""},{"line_number":224,"context_line":"                            \" a plan.The key of resource are id and type.\")"},{"line_number":225,"context_line":"                    raise exception.InvalidInput(reason\u003dmsg)"},{"line_number":226,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":9,"id":"bae84128_bba44eb9","line":223,"range":{"start_line":223,"start_character":29,"end_line":223,"end_character":30},"in_reply_to":"bae84128_34833306","updated":"2016-02-22 07:08:57.000000000","message":"Done","commit_id":"86fc2a3cb4d63a6746ac80af2aa080573de88aad"},{"author":{"_account_id":16203,"name":"zengyingzhe","email":"zengyingzhe@huawei.com","username":"zengyingzhe"},"change_message_id":"46469d8d7668097a4dfcd3b586d8bae6d1341032","unresolved":false,"context_lines":[{"line_number":221,"context_line":"                    pass"},{"line_number":222,"context_line":"                else:"},{"line_number":223,"context_line":"                    msg \u003d _(\" resource in list must be a dict when creating\""},{"line_number":224,"context_line":"                            \" a plan.The key of resource are id and type.\")"},{"line_number":225,"context_line":"                    raise exception.InvalidInput(reason\u003dmsg)"},{"line_number":226,"context_line":"        else:"},{"line_number":227,"context_line":"            msg \u003d _(\"list resources must be provided when creating \""}],"source_content_type":"text/x-python","patch_set":9,"id":"bae84128_549fd74f","line":224,"range":{"start_line":224,"start_character":41,"end_line":224,"end_character":44},"updated":"2016-02-22 04:02:27.000000000","message":"keys","commit_id":"86fc2a3cb4d63a6746ac80af2aa080573de88aad"},{"author":{"_account_id":17151,"name":"chenying","email":"chenyingko@gmail.com","username":"chenying"},"change_message_id":"7126d96a026cdd03e6d17d5d978fcb99de695095","unresolved":false,"context_lines":[{"line_number":221,"context_line":"                    pass"},{"line_number":222,"context_line":"                else:"},{"line_number":223,"context_line":"                    msg \u003d _(\" resource in list must be a dict when creating\""},{"line_number":224,"context_line":"                            \" a plan.The key of resource are id and type.\")"},{"line_number":225,"context_line":"                    raise exception.InvalidInput(reason\u003dmsg)"},{"line_number":226,"context_line":"        else:"},{"line_number":227,"context_line":"            msg \u003d _(\"list resources must be provided when creating \""}],"source_content_type":"text/x-python","patch_set":9,"id":"bae84128_1bac5a9f","line":224,"range":{"start_line":224,"start_character":41,"end_line":224,"end_character":44},"in_reply_to":"bae84128_549fd74f","updated":"2016-02-22 07:08:57.000000000","message":"Done","commit_id":"86fc2a3cb4d63a6746ac80af2aa080573de88aad"}],"smaug/tests/unit/api/v1/test_plans.py":[{"author":{"_account_id":13070,"name":"Eran Gampel","email":"eran@gampel.net","username":"Gampel"},"change_message_id":"0cc2f6e14c5f43b31a52e1044da4b543ab070396","unresolved":false,"context_lines":[{"line_number":95,"context_line":"        self.assertRaises(exc.HTTPBadRequest, self.controller.update,\r"},{"line_number":96,"context_line":"                          req, \"1\", body)\r"},{"line_number":97,"context_line":"\r"},{"line_number":98,"context_line":"    def test_plan_update_InvalidId(self):\r"},{"line_number":99,"context_line":"        plan \u003d self._plan_in_request_body()\r"},{"line_number":100,"context_line":"        body \u003d {\"plan\": plan}\r"},{"line_number":101,"context_line":"        req \u003d fakes.HTTPRequest.blank(\u0027/v1/plans\u0027)\r"}],"source_content_type":"text/x-python","patch_set":7,"id":"dae33548_2a37c8ff","line":98,"range":{"start_line":98,"start_character":8,"end_line":98,"end_character":34},"updated":"2016-02-18 12:46:22.000000000","message":"Consider adding a test that try to update a Plan in state suspended, should get error","commit_id":"95f303cd6d5be7d64f94e5dca9505595070dc2ca"},{"author":{"_account_id":17151,"name":"chenying","email":"chenyingko@gmail.com","username":"chenying"},"change_message_id":"4737e04a0b8717c461b36f937cdc147a486954fc","unresolved":false,"context_lines":[{"line_number":95,"context_line":"        self.assertRaises(exc.HTTPBadRequest, self.controller.update,\r"},{"line_number":96,"context_line":"                          req, \"1\", body)\r"},{"line_number":97,"context_line":"\r"},{"line_number":98,"context_line":"    def test_plan_update_InvalidId(self):\r"},{"line_number":99,"context_line":"        plan \u003d self._plan_in_request_body()\r"},{"line_number":100,"context_line":"        body \u003d {\"plan\": plan}\r"},{"line_number":101,"context_line":"        req \u003d fakes.HTTPRequest.blank(\u0027/v1/plans\u0027)\r"}],"source_content_type":"text/x-python","patch_set":7,"id":"dae33548_b6503e0c","line":98,"range":{"start_line":98,"start_character":8,"end_line":98,"end_character":34},"in_reply_to":"dae33548_2a37c8ff","updated":"2016-02-19 03:02:39.000000000","message":"I have added a unit test.","commit_id":"95f303cd6d5be7d64f94e5dca9505595070dc2ca"}]}
