)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"a3a38f56e3236b945c60a56084fecb1893ecabf4","unresolved":false,"context_lines":[{"line_number":4,"context_line":"Commit:     Eric Fried \u003cefried@us.ibm.com\u003e"},{"line_number":5,"context_line":"CommitDate: 2017-10-24 09:16:10 -0500"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Parse numbered \u0026 unnumbered resources \u0026 traits"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"In anticipation of accepting numbered groupings to placement\u0027s"},{"line_number":10,"context_line":"GET /allocation_candidates API, this change adds a util method to parse"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":3,"id":"3f4b6375_5e5b6e53","line":7,"range":{"start_line":7,"start_character":0,"end_line":7,"end_character":5},"updated":"2017-10-30 16:20:38.000000000","message":"since this is specific to the placement server, could you prefix this with \"placement: \"","commit_id":"ce694f8560123d199947a4c3f9dd4f54eec4e783"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"63262fdd88114e8e0aaa3e7a321cd1904b2d52ef","unresolved":false,"context_lines":[{"line_number":4,"context_line":"Commit:     Eric Fried \u003cefried@us.ibm.com\u003e"},{"line_number":5,"context_line":"CommitDate: 2017-10-24 09:16:10 -0500"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Parse numbered \u0026 unnumbered resources \u0026 traits"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"In anticipation of accepting numbered groupings to placement\u0027s"},{"line_number":10,"context_line":"GET /allocation_candidates API, this change adds a util method to parse"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":3,"id":"3f4b6375_634c4e76","line":7,"range":{"start_line":7,"start_character":0,"end_line":7,"end_character":5},"in_reply_to":"3f4b6375_5e5b6e53","updated":"2017-10-31 18:59:24.000000000","message":"Will do.","commit_id":"ce694f8560123d199947a4c3f9dd4f54eec4e783"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"343320853555e6415a8cd73a26f2b37756690c91","unresolved":false,"context_lines":[{"line_number":9,"context_line":"In anticipation of accepting numbered groupings in placement\u0027s GET"},{"line_number":10,"context_line":"/allocation_candidates API, this change adds a util method to parse a"},{"line_number":11,"context_line":"single traits list query parameter value; and another to parse an entire"},{"line_number":12,"context_line":"querystring into a list of ResourceGroup instances.  ResourceGroup is a"},{"line_number":13,"context_line":"new util class representing a grouping of resources and required traits,"},{"line_number":14,"context_line":"along with an attribute that indicates whether the requested resources"},{"line_number":15,"context_line":"and traits must come from the same resource provider (corresponding to a"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"3f4b6375_58bebbd4","line":12,"range":{"start_line":12,"start_character":27,"end_line":12,"end_character":40},"updated":"2017-10-31 20:41:53.000000000","message":"s/ResourceGroup/RequestGroup/g","commit_id":"1d97262d72c51ef01d6dc60680ac477268ade645"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"812d439137acba665204a864298b8f95d48beeeb","unresolved":false,"context_lines":[{"line_number":9,"context_line":"In anticipation of accepting numbered groupings in placement\u0027s GET"},{"line_number":10,"context_line":"/allocation_candidates API, this change adds a util method to parse a"},{"line_number":11,"context_line":"single traits list query parameter value; and another to parse an entire"},{"line_number":12,"context_line":"querystring into a list of ResourceGroup instances.  ResourceGroup is a"},{"line_number":13,"context_line":"new util class representing a grouping of resources and required traits,"},{"line_number":14,"context_line":"along with an attribute that indicates whether the requested resources"},{"line_number":15,"context_line":"and traits must come from the same resource provider (corresponding to a"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"3f4b6375_b3b7103b","line":12,"range":{"start_line":12,"start_character":27,"end_line":12,"end_character":40},"in_reply_to":"3f4b6375_58bebbd4","updated":"2017-10-31 21:06:59.000000000","message":"Gah, thanks, I\u0027m gonna keep doing that forever.","commit_id":"1d97262d72c51ef01d6dc60680ac477268ade645"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"343320853555e6415a8cd73a26f2b37756690c91","unresolved":false,"context_lines":[{"line_number":10,"context_line":"/allocation_candidates API, this change adds a util method to parse a"},{"line_number":11,"context_line":"single traits list query parameter value; and another to parse an entire"},{"line_number":12,"context_line":"querystring into a list of ResourceGroup instances.  ResourceGroup is a"},{"line_number":13,"context_line":"new util class representing a grouping of resources and required traits,"},{"line_number":14,"context_line":"along with an attribute that indicates whether the requested resources"},{"line_number":15,"context_line":"and traits must come from the same resource provider (corresponding to a"},{"line_number":16,"context_line":"\"numbered\" resource group in the query string) or from any RP in the"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"3f4b6375_38b53fef","line":13,"range":{"start_line":13,"start_character":42,"end_line":13,"end_character":51},"updated":"2017-10-31 20:41:53.000000000","message":"requested resources and required traits","commit_id":"1d97262d72c51ef01d6dc60680ac477268ade645"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"812d439137acba665204a864298b8f95d48beeeb","unresolved":false,"context_lines":[{"line_number":10,"context_line":"/allocation_candidates API, this change adds a util method to parse a"},{"line_number":11,"context_line":"single traits list query parameter value; and another to parse an entire"},{"line_number":12,"context_line":"querystring into a list of ResourceGroup instances.  ResourceGroup is a"},{"line_number":13,"context_line":"new util class representing a grouping of resources and required traits,"},{"line_number":14,"context_line":"along with an attribute that indicates whether the requested resources"},{"line_number":15,"context_line":"and traits must come from the same resource provider (corresponding to a"},{"line_number":16,"context_line":"\"numbered\" resource group in the query string) or from any RP in the"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"3f4b6375_337d606e","line":13,"range":{"start_line":13,"start_character":42,"end_line":13,"end_character":51},"in_reply_to":"3f4b6375_38b53fef","updated":"2017-10-31 21:06:59.000000000","message":"Done","commit_id":"1d97262d72c51ef01d6dc60680ac477268ade645"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"343320853555e6415a8cd73a26f2b37756690c91","unresolved":false,"context_lines":[{"line_number":12,"context_line":"querystring into a list of ResourceGroup instances.  ResourceGroup is a"},{"line_number":13,"context_line":"new util class representing a grouping of resources and required traits,"},{"line_number":14,"context_line":"along with an attribute that indicates whether the requested resources"},{"line_number":15,"context_line":"and traits must come from the same resource provider (corresponding to a"},{"line_number":16,"context_line":"\"numbered\" resource group in the query string) or from any RP in the"},{"line_number":17,"context_line":"same tree or aggregate (the \"unnumbered\" group)."},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"Change-Id: I720630155e9aa53e049e932b9722aaa4ff4247db"},{"line_number":20,"context_line":"blueprint: granular-resource-requests"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"3f4b6375_38aadf84","line":17,"range":{"start_line":15,"start_character":53,"end_line":17,"end_character":48},"updated":"2017-10-31 20:41:53.000000000","message":"I\u0027d just remove this :)","commit_id":"1d97262d72c51ef01d6dc60680ac477268ade645"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"812d439137acba665204a864298b8f95d48beeeb","unresolved":false,"context_lines":[{"line_number":12,"context_line":"querystring into a list of ResourceGroup instances.  ResourceGroup is a"},{"line_number":13,"context_line":"new util class representing a grouping of resources and required traits,"},{"line_number":14,"context_line":"along with an attribute that indicates whether the requested resources"},{"line_number":15,"context_line":"and traits must come from the same resource provider (corresponding to a"},{"line_number":16,"context_line":"\"numbered\" resource group in the query string) or from any RP in the"},{"line_number":17,"context_line":"same tree or aggregate (the \"unnumbered\" group)."},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"Change-Id: I720630155e9aa53e049e932b9722aaa4ff4247db"},{"line_number":20,"context_line":"blueprint: granular-resource-requests"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"3f4b6375_13802446","line":17,"range":{"start_line":15,"start_character":53,"end_line":17,"end_character":48},"in_reply_to":"3f4b6375_38aadf84","updated":"2017-10-31 21:06:59.000000000","message":"Done","commit_id":"1d97262d72c51ef01d6dc60680ac477268ade645"}],"nova/api/openstack/placement/util.py":[{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"8d037dbcb572e6effca2df34b255784c655e9ac0","unresolved":false,"context_lines":[{"line_number":387,"context_line":""},{"line_number":388,"context_line":"    # Ensure any group with \u0027required\u0027 also has \u0027resources\u0027."},{"line_number":389,"context_line":"    orphans \u003d [(\u0027required%s\u0027 % suff)"},{"line_number":390,"context_line":"               for suff, group"},{"line_number":391,"context_line":"               in list(by_suffix.items()) + [(\u0027\u0027, ret[\u0027unnumbered\u0027])]"},{"line_number":392,"context_line":"               if \u0027required\u0027 in group and \u0027resources\u0027 not in group]"},{"line_number":393,"context_line":"    if orphans:"}],"source_content_type":"text/x-python","patch_set":3,"id":"3f4b6375_5e092e2f","line":390,"range":{"start_line":390,"start_character":19,"end_line":390,"end_character":23},"updated":"2017-10-30 16:35:55.000000000","message":"ident?","commit_id":"ce694f8560123d199947a4c3f9dd4f54eec4e783"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"63262fdd88114e8e0aaa3e7a321cd1904b2d52ef","unresolved":false,"context_lines":[{"line_number":387,"context_line":""},{"line_number":388,"context_line":"    # Ensure any group with \u0027required\u0027 also has \u0027resources\u0027."},{"line_number":389,"context_line":"    orphans \u003d [(\u0027required%s\u0027 % suff)"},{"line_number":390,"context_line":"               for suff, group"},{"line_number":391,"context_line":"               in list(by_suffix.items()) + [(\u0027\u0027, ret[\u0027unnumbered\u0027])]"},{"line_number":392,"context_line":"               if \u0027required\u0027 in group and \u0027resources\u0027 not in group]"},{"line_number":393,"context_line":"    if orphans:"}],"source_content_type":"text/x-python","patch_set":3,"id":"3f4b6375_0326bab8","line":390,"range":{"start_line":390,"start_character":19,"end_line":390,"end_character":23},"in_reply_to":"3f4b6375_5e092e2f","updated":"2017-10-31 18:59:24.000000000","message":"I\u0027d rather think of it as a suffix in this context.  The \u0027ident\u0027 thing was internal to the scheduler util side.","commit_id":"ce694f8560123d199947a4c3f9dd4f54eec4e783"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"343320853555e6415a8cd73a26f2b37756690c91","unresolved":false,"context_lines":[{"line_number":34,"context_line":""},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"class RequestGroup(object):"},{"line_number":37,"context_line":"    def __init__(self, use_same_provider, resources\u003dNone,"},{"line_number":38,"context_line":"                 required_traits\u003dNone):"},{"line_number":39,"context_line":"        \"\"\"Create agrouping of resource and trait requests."},{"line_number":40,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"3f4b6375_1885e3cf","line":37,"range":{"start_line":37,"start_character":23,"end_line":37,"end_character":40},"updated":"2017-10-31 20:41:53.000000000","message":"just a nit, but I\u0027d suggest using all kwargs for these arguments. I especially prefer to use kwargs for boolean arguments, since doing something like:\n\n RequestGroup(False)\n\ndoesn\u0027t tell me as much as:\n\n RequestGroup(use_same_provider\u003dFalse)","commit_id":"1d97262d72c51ef01d6dc60680ac477268ade645"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"812d439137acba665204a864298b8f95d48beeeb","unresolved":false,"context_lines":[{"line_number":34,"context_line":""},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"class RequestGroup(object):"},{"line_number":37,"context_line":"    def __init__(self, use_same_provider, resources\u003dNone,"},{"line_number":38,"context_line":"                 required_traits\u003dNone):"},{"line_number":39,"context_line":"        \"\"\"Create agrouping of resource and trait requests."},{"line_number":40,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"3f4b6375_b3495061","line":37,"range":{"start_line":37,"start_character":23,"end_line":37,"end_character":40},"in_reply_to":"3f4b6375_1885e3cf","updated":"2017-10-31 21:06:59.000000000","message":"Like.","commit_id":"1d97262d72c51ef01d6dc60680ac477268ade645"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"343320853555e6415a8cd73a26f2b37756690c91","unresolved":false,"context_lines":[{"line_number":39,"context_line":"        \"\"\"Create agrouping of resource and trait requests."},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"        :param use_same_provider:"},{"line_number":42,"context_line":"            If True, this RequestGroup it represents requests for resources and"},{"line_number":43,"context_line":"            traits which must be satisfied by a single resource provider.  If"},{"line_number":44,"context_line":"            False, represents a request for resources and traits in any"},{"line_number":45,"context_line":"            resource provider in the same tree (or, eventually, also RPs in the"}],"source_content_type":"text/x-python","patch_set":4,"id":"3f4b6375_d88e2b31","line":42,"range":{"start_line":42,"start_character":39,"end_line":42,"end_character":42},"updated":"2017-10-31 20:41:53.000000000","message":"s/it //","commit_id":"1d97262d72c51ef01d6dc60680ac477268ade645"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"812d439137acba665204a864298b8f95d48beeeb","unresolved":false,"context_lines":[{"line_number":39,"context_line":"        \"\"\"Create agrouping of resource and trait requests."},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"        :param use_same_provider:"},{"line_number":42,"context_line":"            If True, this RequestGroup it represents requests for resources and"},{"line_number":43,"context_line":"            traits which must be satisfied by a single resource provider.  If"},{"line_number":44,"context_line":"            False, represents a request for resources and traits in any"},{"line_number":45,"context_line":"            resource provider in the same tree (or, eventually, also RPs in the"}],"source_content_type":"text/x-python","patch_set":4,"id":"3f4b6375_938bf466","line":42,"range":{"start_line":42,"start_character":39,"end_line":42,"end_character":42},"in_reply_to":"3f4b6375_d88e2b31","updated":"2017-10-31 21:06:59.000000000","message":"Done","commit_id":"1d97262d72c51ef01d6dc60680ac477268ade645"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"343320853555e6415a8cd73a26f2b37756690c91","unresolved":false,"context_lines":[{"line_number":42,"context_line":"            If True, this RequestGroup it represents requests for resources and"},{"line_number":43,"context_line":"            traits which must be satisfied by a single resource provider.  If"},{"line_number":44,"context_line":"            False, represents a request for resources and traits in any"},{"line_number":45,"context_line":"            resource provider in the same tree (or, eventually, also RPs in the"},{"line_number":46,"context_line":"            same aggregate)."},{"line_number":47,"context_line":"        :param resources: A dict of { resource_class: amount, ... }"},{"line_number":48,"context_line":"        :param required_traits: A set of { trait_name, ... }"},{"line_number":49,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":4,"id":"3f4b6375_788e1728","line":46,"range":{"start_line":45,"start_character":46,"end_line":46,"end_character":28},"updated":"2017-10-31 20:41:53.000000000","message":"remove this and just say \"resource provider in the same tree or a sharing provider\". (sharing provider functionality *already* exists in AllocationCandidates.get_by_filters(), so there\u0027s no reason to say \"eventually\"... :)","commit_id":"1d97262d72c51ef01d6dc60680ac477268ade645"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"812d439137acba665204a864298b8f95d48beeeb","unresolved":false,"context_lines":[{"line_number":42,"context_line":"            If True, this RequestGroup it represents requests for resources and"},{"line_number":43,"context_line":"            traits which must be satisfied by a single resource provider.  If"},{"line_number":44,"context_line":"            False, represents a request for resources and traits in any"},{"line_number":45,"context_line":"            resource provider in the same tree (or, eventually, also RPs in the"},{"line_number":46,"context_line":"            same aggregate)."},{"line_number":47,"context_line":"        :param resources: A dict of { resource_class: amount, ... }"},{"line_number":48,"context_line":"        :param required_traits: A set of { trait_name, ... }"},{"line_number":49,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":4,"id":"3f4b6375_b3903097","line":46,"range":{"start_line":45,"start_character":46,"end_line":46,"end_character":28},"in_reply_to":"3f4b6375_788e1728","updated":"2017-10-31 21:06:59.000000000","message":"Done","commit_id":"1d97262d72c51ef01d6dc60680ac477268ade645"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"343320853555e6415a8cd73a26f2b37756690c91","unresolved":false,"context_lines":[{"line_number":301,"context_line":""},{"line_number":302,"context_line":"    :param val: A traits query parameter value: a comma-separated string of"},{"line_number":303,"context_line":"                trait names."},{"line_number":304,"context_line":"    :return: A list of trait names."},{"line_number":305,"context_line":"    :raises `webob.exc.HTTPBadRequest` if the val parameter is not in the"},{"line_number":306,"context_line":"            expected format."},{"line_number":307,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":4,"id":"3f4b6375_f8ca074d","line":304,"range":{"start_line":304,"start_character":15,"end_line":304,"end_character":19},"updated":"2017-10-31 20:41:53.000000000","message":"this function returns a set, actually.","commit_id":"1d97262d72c51ef01d6dc60680ac477268ade645"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"812d439137acba665204a864298b8f95d48beeeb","unresolved":false,"context_lines":[{"line_number":301,"context_line":""},{"line_number":302,"context_line":"    :param val: A traits query parameter value: a comma-separated string of"},{"line_number":303,"context_line":"                trait names."},{"line_number":304,"context_line":"    :return: A list of trait names."},{"line_number":305,"context_line":"    :raises `webob.exc.HTTPBadRequest` if the val parameter is not in the"},{"line_number":306,"context_line":"            expected format."},{"line_number":307,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":4,"id":"3f4b6375_f33fc8b2","line":304,"range":{"start_line":304,"start_character":15,"end_line":304,"end_character":19},"in_reply_to":"3f4b6375_f8ca074d","updated":"2017-10-31 21:06:59.000000000","message":"Thanks, holdover from previous rev.","commit_id":"1d97262d72c51ef01d6dc60680ac477268ade645"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"343320853555e6415a8cd73a26f2b37756690c91","unresolved":false,"context_lines":[{"line_number":305,"context_line":"    :raises `webob.exc.HTTPBadRequest` if the val parameter is not in the"},{"line_number":306,"context_line":"            expected format."},{"line_number":307,"context_line":"    \"\"\""},{"line_number":308,"context_line":"    ret \u003d {substr.strip() for substr in val.split(\u0027,\u0027)}"},{"line_number":309,"context_line":"    if not all(trait for trait in ret):"},{"line_number":310,"context_line":"        msg \u003d _(\u0027Malformed traits parameter. Expected query string value \u0027"},{"line_number":311,"context_line":"                \u0027of the form: HW_CPU_X86_VMX,CUSTOM_MAGIC. \u0027"}],"source_content_type":"text/x-python","patch_set":4,"id":"3f4b6375_98a673ab","line":308,"range":{"start_line":308,"start_character":10,"end_line":308,"end_character":11},"updated":"2017-10-31 20:41:53.000000000","message":"for those of us with old eyes, would you mind using set() here instead of {}? :)","commit_id":"1d97262d72c51ef01d6dc60680ac477268ade645"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"812d439137acba665204a864298b8f95d48beeeb","unresolved":false,"context_lines":[{"line_number":305,"context_line":"    :raises `webob.exc.HTTPBadRequest` if the val parameter is not in the"},{"line_number":306,"context_line":"            expected format."},{"line_number":307,"context_line":"    \"\"\""},{"line_number":308,"context_line":"    ret \u003d {substr.strip() for substr in val.split(\u0027,\u0027)}"},{"line_number":309,"context_line":"    if not all(trait for trait in ret):"},{"line_number":310,"context_line":"        msg \u003d _(\u0027Malformed traits parameter. Expected query string value \u0027"},{"line_number":311,"context_line":"                \u0027of the form: HW_CPU_X86_VMX,CUSTOM_MAGIC. \u0027"}],"source_content_type":"text/x-python","patch_set":4,"id":"3f4b6375_53d45c47","line":308,"range":{"start_line":308,"start_character":10,"end_line":308,"end_character":11},"in_reply_to":"3f4b6375_98a673ab","updated":"2017-10-31 21:06:59.000000000","message":"Done","commit_id":"1d97262d72c51ef01d6dc60680ac477268ade645"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"343320853555e6415a8cd73a26f2b37756690c91","unresolved":false,"context_lines":[{"line_number":330,"context_line":"    For each group, a RequestGroup instance is created containing that group\u0027s"},{"line_number":331,"context_line":"    resources and required traits.  For the (single) group with no suffix, the"},{"line_number":332,"context_line":"    RequestGroup.use_same_provider attribute is False; for the numbered groups"},{"line_number":333,"context_line":"    it is True."},{"line_number":334,"context_line":""},{"line_number":335,"context_line":"    The return is a list of these RequestGroup instances."},{"line_number":336,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"3f4b6375_38e65fea","line":333,"updated":"2017-10-31 20:41:53.000000000","message":"++ bingo.","commit_id":"1d97262d72c51ef01d6dc60680ac477268ade645"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"343320853555e6415a8cd73a26f2b37756690c91","unresolved":false,"context_lines":[{"line_number":376,"context_line":"              \"CUSTOM_PHYSNET_PRIVATE\","},{"line_number":377,"context_line":"          ],"},{"line_number":378,"context_line":"      ),"},{"line_number":379,"context_line":"    ]"},{"line_number":380,"context_line":""},{"line_number":381,"context_line":"    :param qsdict: The MultiDict representing the querystring on a GET."},{"line_number":382,"context_line":"    :return: A list of RequestGroup instances."}],"source_content_type":"text/x-python","patch_set":4,"id":"3f4b6375_18028370","line":379,"updated":"2017-10-31 20:41:53.000000000","message":"Excellent docstring example. ++","commit_id":"1d97262d72c51ef01d6dc60680ac477268ade645"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"343320853555e6415a8cd73a26f2b37756690c91","unresolved":false,"context_lines":[{"line_number":402,"context_line":"        if prefix \u003d\u003d QS_RESOURCES:"},{"line_number":403,"context_line":"            request_group.resources \u003d normalize_resources_qs_param(val)"},{"line_number":404,"context_line":"        elif prefix \u003d\u003d QS_REQUIRED:"},{"line_number":405,"context_line":"            request_group.required_traits \u003d normalize_traits_qs_param(val)"},{"line_number":406,"context_line":""},{"line_number":407,"context_line":"    # Ensure any group with \u0027required\u0027 also has \u0027resources\u0027."},{"line_number":408,"context_line":"    orphans \u003d [(\u0027required%s\u0027 % (suff or \u0027\u0027))"}],"source_content_type":"text/x-python","patch_set":4,"id":"3f4b6375_38341f4a","line":405,"updated":"2017-10-31 20:41:53.000000000","message":"++ above is readable and much-improved over previous iterations.","commit_id":"1d97262d72c51ef01d6dc60680ac477268ade645"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"343320853555e6415a8cd73a26f2b37756690c91","unresolved":false,"context_lines":[{"line_number":409,"context_line":"               for suff, group in by_suffix.items()"},{"line_number":410,"context_line":"               if group.required_traits and not group.resources]"},{"line_number":411,"context_line":"    if orphans:"},{"line_number":412,"context_line":"        msg \u003d _(\u0027All traits parameters must be associated with resources.  \u0027"},{"line_number":413,"context_line":"                \u0027Found the following orphaned traits keys: %s\u0027)"},{"line_number":414,"context_line":"        raise webob.exc.HTTPBadRequest(msg % \u0027, \u0027.join(orphans))"},{"line_number":415,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"3f4b6375_f83d672c","line":412,"range":{"start_line":412,"start_character":21,"end_line":412,"end_character":27},"updated":"2017-10-31 20:41:53.000000000","message":"required?","commit_id":"1d97262d72c51ef01d6dc60680ac477268ade645"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"812d439137acba665204a864298b8f95d48beeeb","unresolved":false,"context_lines":[{"line_number":409,"context_line":"               for suff, group in by_suffix.items()"},{"line_number":410,"context_line":"               if group.required_traits and not group.resources]"},{"line_number":411,"context_line":"    if orphans:"},{"line_number":412,"context_line":"        msg \u003d _(\u0027All traits parameters must be associated with resources.  \u0027"},{"line_number":413,"context_line":"                \u0027Found the following orphaned traits keys: %s\u0027)"},{"line_number":414,"context_line":"        raise webob.exc.HTTPBadRequest(msg % \u0027, \u0027.join(orphans))"},{"line_number":415,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"3f4b6375_b31b9071","line":412,"range":{"start_line":412,"start_character":21,"end_line":412,"end_character":27},"in_reply_to":"3f4b6375_f83d672c","updated":"2017-10-31 21:06:59.000000000","message":"This is a hedge against the future when e.g. \u0027preferred\u0027 joins \u0027required\u0027 in the bucket of \u0027traits parameters\u0027.  The real key (\u0027required[$N]\u0027) will appear in the %s.","commit_id":"1d97262d72c51ef01d6dc60680ac477268ade645"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"3eebf87b7903d7b732e3af22dbcc150204bbc9aa","unresolved":false,"context_lines":[{"line_number":36,"context_line":"class RequestGroup(object):"},{"line_number":37,"context_line":"    def __init__(self, use_same_provider\u003dTrue, resources\u003dNone,"},{"line_number":38,"context_line":"                 required_traits\u003dNone):"},{"line_number":39,"context_line":"        \"\"\"Create agrouping of resource and trait requests."},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"        :param use_same_provider:"},{"line_number":42,"context_line":"            If True, (the default) this RequestGroup represents requests for"}],"source_content_type":"text/x-python","patch_set":6,"id":"3f4b6375_81bf09fa","line":39,"range":{"start_line":39,"start_character":18,"end_line":39,"end_character":27},"updated":"2017-11-01 14:35:46.000000000","message":"a grouping","commit_id":"5c21a2cd2fc34a3fd6e9cf846f0dcb8b79aa288f"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"d2e42e764e03b2f0bd688afa3a674fc1b816c3bb","unresolved":false,"context_lines":[{"line_number":20,"context_line":"from oslo_utils import uuidutils"},{"line_number":21,"context_line":"import webob"},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"from nova.api.openstack.placement import lib as pl"},{"line_number":24,"context_line":"# NOTE(cdent): avoid cyclical import conflict between util and"},{"line_number":25,"context_line":"# microversion"},{"line_number":26,"context_line":"import nova.api.openstack.placement.microversion"}],"source_content_type":"text/x-python","patch_set":8,"id":"3f4b6375_032413ae","line":23,"updated":"2017-11-02 18:31:19.000000000","message":"you complained about me using short variable names and then use \"pl\" for this. :) How about calling it placement_lib.","commit_id":"e50ef260741ce6cccef980bcc7c4d3d20a07d54d"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"acc54efd3a221fa1db351a7ef0d5067b7de9da0c","unresolved":false,"context_lines":[{"line_number":20,"context_line":"from oslo_utils import uuidutils"},{"line_number":21,"context_line":"import webob"},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"from nova.api.openstack.placement import lib as pl"},{"line_number":24,"context_line":"# NOTE(cdent): avoid cyclical import conflict between util and"},{"line_number":25,"context_line":"# microversion"},{"line_number":26,"context_line":"import nova.api.openstack.placement.microversion"}],"source_content_type":"text/x-python","patch_set":8,"id":"3f4b6375_5ceae80e","line":23,"in_reply_to":"3f4b6375_032413ae","updated":"2017-11-02 20:12:08.000000000","message":"For an import it\u0027s different :)\n\nBut okay.","commit_id":"e50ef260741ce6cccef980bcc7c4d3d20a07d54d"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"d2e42e764e03b2f0bd688afa3a674fc1b816c3bb","unresolved":false,"context_lines":[{"line_number":28,"context_line":""},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"# Querystring-related constants"},{"line_number":31,"context_line":"QS_RESOURCES \u003d \u0027resources\u0027"},{"line_number":32,"context_line":"QS_REQUIRED \u003d \u0027required\u0027"},{"line_number":33,"context_line":"QS_KEY_PATTERN \u003d re.compile("},{"line_number":34,"context_line":"    r\"^(%s)([1-9][0-9]*)?$\" % \u0027|\u0027.join((QS_RESOURCES, QS_REQUIRED)))"}],"source_content_type":"text/x-python","patch_set":8,"id":"3f4b6375_83e00328","line":31,"range":{"start_line":31,"start_character":0,"end_line":31,"end_character":12},"updated":"2017-11-02 18:31:19.000000000","message":"unless these are used outside of this module (I don\u0027t believe they are), prefix with _ to indicate they are only used here.","commit_id":"e50ef260741ce6cccef980bcc7c4d3d20a07d54d"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"acc54efd3a221fa1db351a7ef0d5067b7de9da0c","unresolved":false,"context_lines":[{"line_number":28,"context_line":""},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"# Querystring-related constants"},{"line_number":31,"context_line":"QS_RESOURCES \u003d \u0027resources\u0027"},{"line_number":32,"context_line":"QS_REQUIRED \u003d \u0027required\u0027"},{"line_number":33,"context_line":"QS_KEY_PATTERN \u003d re.compile("},{"line_number":34,"context_line":"    r\"^(%s)([1-9][0-9]*)?$\" % \u0027|\u0027.join((QS_RESOURCES, QS_REQUIRED)))"}],"source_content_type":"text/x-python","patch_set":8,"id":"3f4b6375_9c5180dc","line":31,"range":{"start_line":31,"start_character":0,"end_line":31,"end_character":12},"in_reply_to":"3f4b6375_83e00328","updated":"2017-11-02 20:12:08.000000000","message":"Good call, done.","commit_id":"e50ef260741ce6cccef980bcc7c4d3d20a07d54d"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"d2e42e764e03b2f0bd688afa3a674fc1b816c3bb","unresolved":false,"context_lines":[{"line_number":367,"context_line":""},{"line_number":368,"context_line":"    def get_request_group(suffix):"},{"line_number":369,"context_line":"        if suffix not in by_suffix:"},{"line_number":370,"context_line":"            by_suffix[suffix] \u003d pl.RequestGroup(use_same_provider\u003dbool(suffix))"},{"line_number":371,"context_line":"        return by_suffix[suffix]"},{"line_number":372,"context_line":""},{"line_number":373,"context_line":"    for key, val in qsdict.items():"}],"source_content_type":"text/x-python","patch_set":8,"id":"3f4b6375_03809345","line":370,"range":{"start_line":370,"start_character":32,"end_line":370,"end_character":34},"updated":"2017-11-02 18:31:19.000000000","message":"since using the longer \"placement_lib\" would cause this line to overrun, you could do the following, which is easy to read:\n\n rg \u003d placement_lib.RequestGroup(use_same_provider\u003dbool(suffix))\n by_suffix[suffix] \u003d rg","commit_id":"e50ef260741ce6cccef980bcc7c4d3d20a07d54d"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"acc54efd3a221fa1db351a7ef0d5067b7de9da0c","unresolved":false,"context_lines":[{"line_number":367,"context_line":""},{"line_number":368,"context_line":"    def get_request_group(suffix):"},{"line_number":369,"context_line":"        if suffix not in by_suffix:"},{"line_number":370,"context_line":"            by_suffix[suffix] \u003d pl.RequestGroup(use_same_provider\u003dbool(suffix))"},{"line_number":371,"context_line":"        return by_suffix[suffix]"},{"line_number":372,"context_line":""},{"line_number":373,"context_line":"    for key, val in qsdict.items():"}],"source_content_type":"text/x-python","patch_set":8,"id":"3f4b6375_7c4ec438","line":370,"range":{"start_line":370,"start_character":32,"end_line":370,"end_character":34},"in_reply_to":"3f4b6375_03809345","updated":"2017-11-02 20:12:08.000000000","message":"Done","commit_id":"e50ef260741ce6cccef980bcc7c4d3d20a07d54d"}],"nova/tests/unit/api/openstack/placement/test_util.py":[{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"276acd45b23ee492130c3dbb8b0e3336d7508735","unresolved":false,"context_lines":[{"line_number":419,"context_line":"        # This will raise if we\u0027re comparing something different - just do the"},{"line_number":420,"context_line":"        # normal comparison in that case."},{"line_number":421,"context_line":"        try:"},{"line_number":422,"context_line":"            expected[\u0027numbered\u0027].sort()"},{"line_number":423,"context_line":"            observed[\u0027numbered\u0027].sort()"},{"line_number":424,"context_line":"        except Exception:"},{"line_number":425,"context_line":"            pass"},{"line_number":426,"context_line":"        super(TestParseQsResourcesAndTraits, self).assertEqual("}],"source_content_type":"text/x-python","patch_set":2,"id":"3f4b6375_db5714ca","line":423,"range":{"start_line":422,"start_character":0,"end_line":423,"end_character":39},"updated":"2017-10-24 01:39:42.000000000","message":"Looks like this ain\u0027t good enough for py3.","commit_id":"c6d6ff622737a7f0ebf0b2fad00702f5d3b46615"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"343320853555e6415a8cd73a26f2b37756690c91","unresolved":false,"context_lines":[{"line_number":385,"context_line":"            \u0027STORAGE_DISK_SSD\u0027,"},{"line_number":386,"context_line":"        )"},{"line_number":387,"context_line":"        self.assertEqual("},{"line_number":388,"context_line":"            list(traits),"},{"line_number":389,"context_line":"            util.normalize_traits_qs_param(\u0027%s, %s,%s , %s ,  %s  \u0027 % traits))"},{"line_number":390,"context_line":""},{"line_number":391,"context_line":"    def test_400_all_empty(self):"}],"source_content_type":"text/x-python","patch_set":4,"id":"3f4b6375_981b13c9","line":388,"updated":"2017-10-31 20:41:53.000000000","message":"heh. or you could just make traits a ... list to begin with :P","commit_id":"1d97262d72c51ef01d6dc60680ac477268ade645"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"812d439137acba665204a864298b8f95d48beeeb","unresolved":false,"context_lines":[{"line_number":385,"context_line":"            \u0027STORAGE_DISK_SSD\u0027,"},{"line_number":386,"context_line":"        )"},{"line_number":387,"context_line":"        self.assertEqual("},{"line_number":388,"context_line":"            list(traits),"},{"line_number":389,"context_line":"            util.normalize_traits_qs_param(\u0027%s, %s,%s , %s ,  %s  \u0027 % traits))"},{"line_number":390,"context_line":""},{"line_number":391,"context_line":"    def test_400_all_empty(self):"}],"source_content_type":"text/x-python","patch_set":4,"id":"3f4b6375_d3bf2cfa","line":388,"in_reply_to":"3f4b6375_981b13c9","updated":"2017-10-31 21:06:59.000000000","message":"Whoah, missed this, it will probably fail.  Whole reason I made \u0027em sets was for testability so I didn\u0027t have to sort.  Fixing...","commit_id":"1d97262d72c51ef01d6dc60680ac477268ade645"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"343320853555e6415a8cd73a26f2b37756690c91","unresolved":false,"context_lines":[{"line_number":491,"context_line":"        ]"},{"line_number":492,"context_line":"        self.assertEqual(expected, self.do_parse(qs))"},{"line_number":493,"context_line":""},{"line_number":494,"context_line":"    def test_the_whole_megillah(self):"},{"line_number":495,"context_line":"        qs \u003d (\u0027resources\u003dVCPU:3,MEMORY_MB:4096,DISK_GB:10\u0027"},{"line_number":496,"context_line":"              \u0027\u0026required\u003dHW_CPU_X86_VMX,CUSTOM_MEM_FLASH,STORAGE_DISK_SSD\u0027"},{"line_number":497,"context_line":"              \u0027\u0026resources1\u003dSRIOV_NET_VF:2\u0027"}],"source_content_type":"text/x-python","patch_set":4,"id":"3f4b6375_18d3a3d7","line":494,"range":{"start_line":494,"start_character":8,"end_line":494,"end_character":31},"updated":"2017-10-31 20:41:53.000000000","message":"cute, but prefer a more descriptive test name :)","commit_id":"1d97262d72c51ef01d6dc60680ac477268ade645"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"812d439137acba665204a864298b8f95d48beeeb","unresolved":false,"context_lines":[{"line_number":491,"context_line":"        ]"},{"line_number":492,"context_line":"        self.assertEqual(expected, self.do_parse(qs))"},{"line_number":493,"context_line":""},{"line_number":494,"context_line":"    def test_the_whole_megillah(self):"},{"line_number":495,"context_line":"        qs \u003d (\u0027resources\u003dVCPU:3,MEMORY_MB:4096,DISK_GB:10\u0027"},{"line_number":496,"context_line":"              \u0027\u0026required\u003dHW_CPU_X86_VMX,CUSTOM_MEM_FLASH,STORAGE_DISK_SSD\u0027"},{"line_number":497,"context_line":"              \u0027\u0026resources1\u003dSRIOV_NET_VF:2\u0027"}],"source_content_type":"text/x-python","patch_set":4,"id":"3f4b6375_732d1845","line":494,"range":{"start_line":494,"start_character":8,"end_line":494,"end_character":31},"in_reply_to":"3f4b6375_18d3a3d7","updated":"2017-10-31 21:06:59.000000000","message":"Done","commit_id":"1d97262d72c51ef01d6dc60680ac477268ade645"}]}
