)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"aa2f0b469a3ab20cc7ae8dac979d8906e0d08e72","unresolved":false,"context_lines":[{"line_number":6,"context_line":""},{"line_number":7,"context_line":"DB API changes to get non-matching aggregates from metadata"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Added a new DB API to return list of aggregates that doesn\u0027t match metadata"},{"line_number":10,"context_line":"keys that starts with key_prefix with the list of required traits set on the"},{"line_number":11,"context_line":"flavor and image."},{"line_number":12,"context_line":""},{"line_number":13,"context_line":"Change-Id: I7dd54e11288a0ad2569abfc351258e97b5f5803c"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":1,"id":"7faddb67_e8e1929c","line":10,"range":{"start_line":9,"start_character":0,"end_line":10,"end_character":76},"updated":"2019-07-16 16:21:05.000000000","message":"nit: long lines","commit_id":"f5ca916f7c9c5c1ed164444c3fbb2d528afb6d43"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"c609e74c26818fd1f79dedf7b5eaeec4f4d9af46","unresolved":false,"context_lines":[{"line_number":6,"context_line":""},{"line_number":7,"context_line":"DB API changes to get non-matching aggregates from metadata"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Added a new DB API to return list of aggregates that doesn\u0027t match"},{"line_number":10,"context_line":"metadata keys that starts with key_prefix with the list of required"},{"line_number":11,"context_line":"traits set on the flavor and image."},{"line_number":12,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":3,"id":"7faddb67_32fd856e","line":9,"range":{"start_line":9,"start_character":53,"end_line":9,"end_character":60},"updated":"2019-08-07 20:57:39.000000000","message":"don\u0027t","commit_id":"3d814f4f8d199e86a5cad379e81cf5dd5915b85a"},{"author":{"_account_id":27302,"name":"Shilpa Devharakar","email":"shilpa.devharakar@nttdata.com","username":"shilpa.devharakar"},"change_message_id":"be4ab4a2588bf52404b62820a76f6aa6d5ae7f95","unresolved":false,"context_lines":[{"line_number":6,"context_line":""},{"line_number":7,"context_line":"DB API changes to get non-matching aggregates from metadata"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Added a new DB API to return list of aggregates that doesn\u0027t match"},{"line_number":10,"context_line":"metadata keys that starts with key_prefix with the list of required"},{"line_number":11,"context_line":"traits set on the flavor and image."},{"line_number":12,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":3,"id":"7faddb67_4f5acc50","line":9,"range":{"start_line":9,"start_character":53,"end_line":9,"end_character":60},"in_reply_to":"7faddb67_32fd856e","updated":"2019-08-08 12:34:44.000000000","message":"Done","commit_id":"3d814f4f8d199e86a5cad379e81cf5dd5915b85a"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"c609e74c26818fd1f79dedf7b5eaeec4f4d9af46","unresolved":false,"context_lines":[{"line_number":7,"context_line":"DB API changes to get non-matching aggregates from metadata"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Added a new DB API to return list of aggregates that doesn\u0027t match"},{"line_number":10,"context_line":"metadata keys that starts with key_prefix with the list of required"},{"line_number":11,"context_line":"traits set on the flavor and image."},{"line_number":12,"context_line":""},{"line_number":13,"context_line":"Change-Id: I7dd54e11288a0ad2569abfc351258e97b5f5803c"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":3,"id":"7faddb67_f2f60d91","line":10,"range":{"start_line":10,"start_character":19,"end_line":10,"end_character":25},"updated":"2019-08-07 20:57:39.000000000","message":"start","commit_id":"3d814f4f8d199e86a5cad379e81cf5dd5915b85a"},{"author":{"_account_id":27302,"name":"Shilpa Devharakar","email":"shilpa.devharakar@nttdata.com","username":"shilpa.devharakar"},"change_message_id":"be4ab4a2588bf52404b62820a76f6aa6d5ae7f95","unresolved":false,"context_lines":[{"line_number":7,"context_line":"DB API changes to get non-matching aggregates from metadata"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Added a new DB API to return list of aggregates that doesn\u0027t match"},{"line_number":10,"context_line":"metadata keys that starts with key_prefix with the list of required"},{"line_number":11,"context_line":"traits set on the flavor and image."},{"line_number":12,"context_line":""},{"line_number":13,"context_line":"Change-Id: I7dd54e11288a0ad2569abfc351258e97b5f5803c"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":3,"id":"7faddb67_ef56182b","line":10,"range":{"start_line":10,"start_character":19,"end_line":10,"end_character":25},"in_reply_to":"7faddb67_f2f60d91","updated":"2019-08-08 12:34:44.000000000","message":"Done","commit_id":"3d814f4f8d199e86a5cad379e81cf5dd5915b85a"}],"nova/objects/aggregate.py":[{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"3978647b4698d225477e881931a9cc37eda13967","unresolved":false,"context_lines":[{"line_number":452,"context_line":""},{"line_number":453,"context_line":""},{"line_number":454,"context_line":"@db_api.api_context_manager.reader"},{"line_number":455,"context_line":"def _get_non_matching_by_metadata_keys_from_db(context, keys, key_prefix,"},{"line_number":456,"context_line":"                                               value\u003dNone):"},{"line_number":457,"context_line":"    assert(keys is not None and key_prefix is not None)"},{"line_number":458,"context_line":"    query \u003d context.session.query(api_models.Aggregate)"}],"source_content_type":"text/x-python","patch_set":2,"id":"7faddb67_3ab4ed81","line":455,"updated":"2019-07-31 18:39:30.000000000","message":"Good lord a docstring on this method could be useful. This code is not self-documenting.","commit_id":"380645fbec6026e0cb9f2ead54602d1f0eb82193"},{"author":{"_account_id":27302,"name":"Shilpa Devharakar","email":"shilpa.devharakar@nttdata.com","username":"shilpa.devharakar"},"change_message_id":"df9f93f79fbdc94da80271547e6b45ec5646be9b","unresolved":false,"context_lines":[{"line_number":452,"context_line":""},{"line_number":453,"context_line":""},{"line_number":454,"context_line":"@db_api.api_context_manager.reader"},{"line_number":455,"context_line":"def _get_non_matching_by_metadata_keys_from_db(context, keys, key_prefix,"},{"line_number":456,"context_line":"                                               value\u003dNone):"},{"line_number":457,"context_line":"    assert(keys is not None and key_prefix is not None)"},{"line_number":458,"context_line":"    query \u003d context.session.query(api_models.Aggregate)"}],"source_content_type":"text/x-python","patch_set":2,"id":"7faddb67_9bed7ff2","line":455,"in_reply_to":"7faddb67_3ab4ed81","updated":"2019-08-07 12:55:49.000000000","message":"Done, added docstring.","commit_id":"380645fbec6026e0cb9f2ead54602d1f0eb82193"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"3978647b4698d225477e881931a9cc37eda13967","unresolved":false,"context_lines":[{"line_number":460,"context_line":"    if value is not None:"},{"line_number":461,"context_line":"        query \u003d query.filter(api_models.AggregateMetadata.value \u003d\u003d value)"},{"line_number":462,"context_line":"    if len(keys) \u003e 0:"},{"line_number":463,"context_line":"        if key_prefix:"},{"line_number":464,"context_line":"            query \u003d query.filter(api_models.AggregateMetadata.key.like("},{"line_number":465,"context_line":"                key_prefix + r\u0027%\u0027))"},{"line_number":466,"context_line":"        query \u003d query.filter(~api_models.AggregateMetadata.key.in_(keys))"}],"source_content_type":"text/x-python","patch_set":2,"id":"7faddb67_3a370d01","line":463,"updated":"2019-07-31 18:39:30.000000000","message":"Why have a condition on this? You assert it\u0027s not None above. Can it be the empty string?","commit_id":"380645fbec6026e0cb9f2ead54602d1f0eb82193"},{"author":{"_account_id":26458,"name":"Brin Zhang","email":"zhangbailin@inspur.com","username":"zhangbailin"},"change_message_id":"1aac81b0d263d82d764fea54dd2c2643376634fa","unresolved":false,"context_lines":[{"line_number":460,"context_line":"    if value is not None:"},{"line_number":461,"context_line":"        query \u003d query.filter(api_models.AggregateMetadata.value \u003d\u003d value)"},{"line_number":462,"context_line":"    if len(keys) \u003e 0:"},{"line_number":463,"context_line":"        if key_prefix:"},{"line_number":464,"context_line":"            query \u003d query.filter(api_models.AggregateMetadata.key.like("},{"line_number":465,"context_line":"                key_prefix + r\u0027%\u0027))"},{"line_number":466,"context_line":"        query \u003d query.filter(~api_models.AggregateMetadata.key.in_(keys))"}],"source_content_type":"text/x-python","patch_set":2,"id":"7faddb67_7d59b48b","line":463,"in_reply_to":"7faddb67_3a370d01","updated":"2019-08-06 11:06:27.000000000","message":"+1, the assert() has handled key_prefix, this is not None.","commit_id":"380645fbec6026e0cb9f2ead54602d1f0eb82193"},{"author":{"_account_id":27302,"name":"Shilpa Devharakar","email":"shilpa.devharakar@nttdata.com","username":"shilpa.devharakar"},"change_message_id":"df9f93f79fbdc94da80271547e6b45ec5646be9b","unresolved":false,"context_lines":[{"line_number":460,"context_line":"    if value is not None:"},{"line_number":461,"context_line":"        query \u003d query.filter(api_models.AggregateMetadata.value \u003d\u003d value)"},{"line_number":462,"context_line":"    if len(keys) \u003e 0:"},{"line_number":463,"context_line":"        if key_prefix:"},{"line_number":464,"context_line":"            query \u003d query.filter(api_models.AggregateMetadata.key.like("},{"line_number":465,"context_line":"                key_prefix + r\u0027%\u0027))"},{"line_number":466,"context_line":"        query \u003d query.filter(~api_models.AggregateMetadata.key.in_(keys))"}],"source_content_type":"text/x-python","patch_set":2,"id":"7faddb67_5bb947ea","line":463,"in_reply_to":"7faddb67_3a370d01","updated":"2019-08-07 12:55:49.000000000","message":"removed","commit_id":"380645fbec6026e0cb9f2ead54602d1f0eb82193"},{"author":{"_account_id":27302,"name":"Shilpa Devharakar","email":"shilpa.devharakar@nttdata.com","username":"shilpa.devharakar"},"change_message_id":"df9f93f79fbdc94da80271547e6b45ec5646be9b","unresolved":false,"context_lines":[{"line_number":460,"context_line":"    if value is not None:"},{"line_number":461,"context_line":"        query \u003d query.filter(api_models.AggregateMetadata.value \u003d\u003d value)"},{"line_number":462,"context_line":"    if len(keys) \u003e 0:"},{"line_number":463,"context_line":"        if key_prefix:"},{"line_number":464,"context_line":"            query \u003d query.filter(api_models.AggregateMetadata.key.like("},{"line_number":465,"context_line":"                key_prefix + r\u0027%\u0027))"},{"line_number":466,"context_line":"        query \u003d query.filter(~api_models.AggregateMetadata.key.in_(keys))"}],"source_content_type":"text/x-python","patch_set":2,"id":"7faddb67_1bb3cf0c","line":463,"in_reply_to":"7faddb67_7d59b48b","updated":"2019-08-07 12:55:49.000000000","message":"yes, so removed.","commit_id":"380645fbec6026e0cb9f2ead54602d1f0eb82193"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"3978647b4698d225477e881931a9cc37eda13967","unresolved":false,"context_lines":[{"line_number":532,"context_line":"    def get_non_matching_by_metadata_keys(cls, context, keys, key_prefix,"},{"line_number":533,"context_line":"                                          value\u003dNone):"},{"line_number":534,"context_line":"        \"\"\"Return aggregates that are not matching with metadata."},{"line_number":535,"context_line":""},{"line_number":536,"context_line":"        :param context: The security context (admin)"},{"line_number":537,"context_line":"        :param keys: List of keys to match with the aggregate metadata keys"},{"line_number":538,"context_line":"                     that starts with key_prefix."}],"source_content_type":"text/x-python","patch_set":2,"id":"7faddb67_1a0b312a","line":535,"updated":"2019-07-31 18:39:30.000000000","message":"An example would be nice b/c this interface is confusing to me. I\u0027m assuming key_prefix is something like \"trait\" or \"trait:\"? And then a key would be a required trait? And then value would be \"required\" in the case of forbidden aggregates filtering?","commit_id":"380645fbec6026e0cb9f2ead54602d1f0eb82193"},{"author":{"_account_id":27302,"name":"Shilpa Devharakar","email":"shilpa.devharakar@nttdata.com","username":"shilpa.devharakar"},"change_message_id":"df9f93f79fbdc94da80271547e6b45ec5646be9b","unresolved":false,"context_lines":[{"line_number":532,"context_line":"    def get_non_matching_by_metadata_keys(cls, context, keys, key_prefix,"},{"line_number":533,"context_line":"                                          value\u003dNone):"},{"line_number":534,"context_line":"        \"\"\"Return aggregates that are not matching with metadata."},{"line_number":535,"context_line":""},{"line_number":536,"context_line":"        :param context: The security context (admin)"},{"line_number":537,"context_line":"        :param keys: List of keys to match with the aggregate metadata keys"},{"line_number":538,"context_line":"                     that starts with key_prefix."}],"source_content_type":"text/x-python","patch_set":2,"id":"7faddb67_3bb80be4","line":535,"in_reply_to":"7faddb67_1a0b312a","updated":"2019-08-07 12:55:49.000000000","message":"Done, added an example","commit_id":"380645fbec6026e0cb9f2ead54602d1f0eb82193"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"3978647b4698d225477e881931a9cc37eda13967","unresolved":false,"context_lines":[{"line_number":533,"context_line":"                                          value\u003dNone):"},{"line_number":534,"context_line":"        \"\"\"Return aggregates that are not matching with metadata."},{"line_number":535,"context_line":""},{"line_number":536,"context_line":"        :param context: The security context (admin)"},{"line_number":537,"context_line":"        :param keys: List of keys to match with the aggregate metadata keys"},{"line_number":538,"context_line":"                     that starts with key_prefix."},{"line_number":539,"context_line":"        :param value: Value of metadata"}],"source_content_type":"text/x-python","patch_set":2,"id":"7faddb67_baa77d50","line":536,"range":{"start_line":536,"start_character":44,"end_line":536,"end_character":52},"updated":"2019-07-31 18:39:30.000000000","message":"You can remove this - per policy config we don\u0027t know if the user is an admin or not.","commit_id":"380645fbec6026e0cb9f2ead54602d1f0eb82193"},{"author":{"_account_id":27302,"name":"Shilpa Devharakar","email":"shilpa.devharakar@nttdata.com","username":"shilpa.devharakar"},"change_message_id":"df9f93f79fbdc94da80271547e6b45ec5646be9b","unresolved":false,"context_lines":[{"line_number":533,"context_line":"                                          value\u003dNone):"},{"line_number":534,"context_line":"        \"\"\"Return aggregates that are not matching with metadata."},{"line_number":535,"context_line":""},{"line_number":536,"context_line":"        :param context: The security context (admin)"},{"line_number":537,"context_line":"        :param keys: List of keys to match with the aggregate metadata keys"},{"line_number":538,"context_line":"                     that starts with key_prefix."},{"line_number":539,"context_line":"        :param value: Value of metadata"}],"source_content_type":"text/x-python","patch_set":2,"id":"7faddb67_bbc39b57","line":536,"range":{"start_line":536,"start_character":44,"end_line":536,"end_character":52},"in_reply_to":"7faddb67_baa77d50","updated":"2019-08-07 12:55:49.000000000","message":"Done","commit_id":"380645fbec6026e0cb9f2ead54602d1f0eb82193"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"3978647b4698d225477e881931a9cc37eda13967","unresolved":false,"context_lines":[{"line_number":536,"context_line":"        :param context: The security context (admin)"},{"line_number":537,"context_line":"        :param keys: List of keys to match with the aggregate metadata keys"},{"line_number":538,"context_line":"                     that starts with key_prefix."},{"line_number":539,"context_line":"        :param value: Value of metadata"},{"line_number":540,"context_line":"        :param key_prefix: Only compares metadata keys that starts with the"},{"line_number":541,"context_line":"                           key_prefix"},{"line_number":542,"context_line":"        :returns: List of aggregates that doesn\u0027t match metadata keys that"}],"source_content_type":"text/x-python","patch_set":2,"id":"7faddb67_fa5f353e","line":539,"updated":"2019-07-31 18:39:30.000000000","message":"This is optional - so what if a value isn\u0027t provided, what does that mean?","commit_id":"380645fbec6026e0cb9f2ead54602d1f0eb82193"},{"author":{"_account_id":27302,"name":"Shilpa Devharakar","email":"shilpa.devharakar@nttdata.com","username":"shilpa.devharakar"},"change_message_id":"df9f93f79fbdc94da80271547e6b45ec5646be9b","unresolved":false,"context_lines":[{"line_number":536,"context_line":"        :param context: The security context (admin)"},{"line_number":537,"context_line":"        :param keys: List of keys to match with the aggregate metadata keys"},{"line_number":538,"context_line":"                     that starts with key_prefix."},{"line_number":539,"context_line":"        :param value: Value of metadata"},{"line_number":540,"context_line":"        :param key_prefix: Only compares metadata keys that starts with the"},{"line_number":541,"context_line":"                           key_prefix"},{"line_number":542,"context_line":"        :returns: List of aggregates that doesn\u0027t match metadata keys that"}],"source_content_type":"text/x-python","patch_set":2,"id":"7faddb67_fb8ef330","line":539,"in_reply_to":"7faddb67_fa5f353e","updated":"2019-08-07 12:55:49.000000000","message":"Here is generic method, so keeping value optional.\nIn our case, we needed \u0027required\u0027 to be set as value.\n\nRefer test case [1] for further understanding.\n\nhttps://review.opendev.org/#/c/671074/3/nova/tests/functional/db/test_aggregate.py@586","commit_id":"380645fbec6026e0cb9f2ead54602d1f0eb82193"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"3978647b4698d225477e881931a9cc37eda13967","unresolved":false,"context_lines":[{"line_number":537,"context_line":"        :param keys: List of keys to match with the aggregate metadata keys"},{"line_number":538,"context_line":"                     that starts with key_prefix."},{"line_number":539,"context_line":"        :param value: Value of metadata"},{"line_number":540,"context_line":"        :param key_prefix: Only compares metadata keys that starts with the"},{"line_number":541,"context_line":"                           key_prefix"},{"line_number":542,"context_line":"        :returns: List of aggregates that doesn\u0027t match metadata keys that"},{"line_number":543,"context_line":"                  starts with key_prefix with the supplied keys."}],"source_content_type":"text/x-python","patch_set":2,"id":"7faddb67_ba553d20","line":540,"range":{"start_line":540,"start_character":15,"end_line":540,"end_character":25},"updated":"2019-07-31 18:39:30.000000000","message":"This should come before :param value: order-wise.","commit_id":"380645fbec6026e0cb9f2ead54602d1f0eb82193"},{"author":{"_account_id":27302,"name":"Shilpa Devharakar","email":"shilpa.devharakar@nttdata.com","username":"shilpa.devharakar"},"change_message_id":"df9f93f79fbdc94da80271547e6b45ec5646be9b","unresolved":false,"context_lines":[{"line_number":537,"context_line":"        :param keys: List of keys to match with the aggregate metadata keys"},{"line_number":538,"context_line":"                     that starts with key_prefix."},{"line_number":539,"context_line":"        :param value: Value of metadata"},{"line_number":540,"context_line":"        :param key_prefix: Only compares metadata keys that starts with the"},{"line_number":541,"context_line":"                           key_prefix"},{"line_number":542,"context_line":"        :returns: List of aggregates that doesn\u0027t match metadata keys that"},{"line_number":543,"context_line":"                  starts with key_prefix with the supplied keys."}],"source_content_type":"text/x-python","patch_set":2,"id":"7faddb67_bb987b75","line":540,"range":{"start_line":540,"start_character":15,"end_line":540,"end_character":25},"in_reply_to":"7faddb67_ba553d20","updated":"2019-08-07 12:55:49.000000000","message":"Done","commit_id":"380645fbec6026e0cb9f2ead54602d1f0eb82193"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"c609e74c26818fd1f79dedf7b5eaeec4f4d9af46","unresolved":false,"context_lines":[{"line_number":457,"context_line":"    \"\"\"Filter aggregates based on non matching metadata."},{"line_number":458,"context_line":""},{"line_number":459,"context_line":"    Based on keys, key_prefix and value, filter the aggregates that are not"},{"line_number":460,"context_line":"    matching with the metadata."},{"line_number":461,"context_line":"    \"\"\""},{"line_number":462,"context_line":""},{"line_number":463,"context_line":"    assert(keys is not None and key_prefix is not None)"}],"source_content_type":"text/x-python","patch_set":3,"id":"7faddb67_74244ab0","line":460,"updated":"2019-08-07 20:57:39.000000000","message":"This doesn\u0027t really add to my understanding; just seems like a slight rephrase of the method name and param list. Here\u0027s my attempt:\n\n Find aggregates with ${key_prefix}*[\u003d${value}] metadata, but only\n if they have a ${key_prefix}* key not in ${keys}.\n\n :return: Aggregates with any metadata entry:\n   - whose key starts with `key_prefix`; and\n   - whose value is `value` (if `value` is specified); and\n   - whose key is *not* in the `keys` list.","commit_id":"3d814f4f8d199e86a5cad379e81cf5dd5915b85a"},{"author":{"_account_id":27302,"name":"Shilpa Devharakar","email":"shilpa.devharakar@nttdata.com","username":"shilpa.devharakar"},"change_message_id":"be4ab4a2588bf52404b62820a76f6aa6d5ae7f95","unresolved":false,"context_lines":[{"line_number":457,"context_line":"    \"\"\"Filter aggregates based on non matching metadata."},{"line_number":458,"context_line":""},{"line_number":459,"context_line":"    Based on keys, key_prefix and value, filter the aggregates that are not"},{"line_number":460,"context_line":"    matching with the metadata."},{"line_number":461,"context_line":"    \"\"\""},{"line_number":462,"context_line":""},{"line_number":463,"context_line":"    assert(keys is not None and key_prefix is not None)"}],"source_content_type":"text/x-python","patch_set":3,"id":"7faddb67_af2ee0a8","line":460,"in_reply_to":"7faddb67_74244ab0","updated":"2019-08-08 12:34:44.000000000","message":"Done","commit_id":"3d814f4f8d199e86a5cad379e81cf5dd5915b85a"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"39d053926a6a68accf54b43518513457e35bb395","unresolved":false,"context_lines":[{"line_number":465,"context_line":"        - whose key is *not* in the `keys` list."},{"line_number":466,"context_line":"    \"\"\""},{"line_number":467,"context_line":""},{"line_number":468,"context_line":"    assert(keys is not None and key_prefix is not None)"},{"line_number":469,"context_line":"    query \u003d context.session.query(api_models.Aggregate)"},{"line_number":470,"context_line":"    query \u003d query.join(\"_metadata\")"},{"line_number":471,"context_line":"    if value is not None:"}],"source_content_type":"text/x-python","patch_set":5,"id":"7faddb67_fba9b78f","line":468,"range":{"start_line":468,"start_character":0,"end_line":468,"end_character":55},"updated":"2019-08-13 09:57:09.000000000","message":"Do we use asserts like this elsewhere?\n\nLater: Looks like we do but we should probably stop doing this since we can\u0027t rely on it [1].\n\n  $ ag -Q \u0027assert(\u0027 nova/objects/\n  nova/objects/aggregate.py\n  441:    assert(key is not None or value is not None)\n  \n  nova/objects/block_device.py\n  160:                assert(uuid is not None)\n\n[1] https://stackoverflow.com/a/1693127","commit_id":"1141f901c858c6fbe23907aef1d81bd1eef4b09c"},{"author":{"_account_id":27302,"name":"Shilpa Devharakar","email":"shilpa.devharakar@nttdata.com","username":"shilpa.devharakar"},"change_message_id":"26d188f3f31e8ee7d0ffb3174f4c9bf978937a31","unresolved":false,"context_lines":[{"line_number":465,"context_line":"        - whose key is *not* in the `keys` list."},{"line_number":466,"context_line":"    \"\"\""},{"line_number":467,"context_line":""},{"line_number":468,"context_line":"    assert(keys is not None and key_prefix is not None)"},{"line_number":469,"context_line":"    query \u003d context.session.query(api_models.Aggregate)"},{"line_number":470,"context_line":"    query \u003d query.join(\"_metadata\")"},{"line_number":471,"context_line":"    if value is not None:"}],"source_content_type":"text/x-python","patch_set":5,"id":"7faddb67_2f1ce275","line":468,"range":{"start_line":468,"start_character":0,"end_line":468,"end_character":55},"in_reply_to":"7faddb67_fba9b78f","updated":"2019-08-13 15:59:56.000000000","message":"Done, removed","commit_id":"1141f901c858c6fbe23907aef1d81bd1eef4b09c"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"2ce1806c17f96b20dc169a81b4c2dfeb971f0224","unresolved":false,"context_lines":[{"line_number":465,"context_line":"        - whose key is *not* in the `keys` list."},{"line_number":466,"context_line":"    \"\"\""},{"line_number":467,"context_line":""},{"line_number":468,"context_line":"    assert(keys is not None and key_prefix is not None)"},{"line_number":469,"context_line":"    query \u003d context.session.query(api_models.Aggregate)"},{"line_number":470,"context_line":"    query \u003d query.join(\"_metadata\")"},{"line_number":471,"context_line":"    if value is not None:"}],"source_content_type":"text/x-python","patch_set":5,"id":"7faddb67_12feed04","line":468,"range":{"start_line":468,"start_character":0,"end_line":468,"end_character":55},"in_reply_to":"7faddb67_fba9b78f","updated":"2019-08-13 16:07:54.000000000","message":"I don\u0027t see why \"we can\u0027t rely on it\". Are you pointing to the right article? The only thing that one says is that you could save by not doing the extra computation, but in this case that\u0027s negligible.","commit_id":"1141f901c858c6fbe23907aef1d81bd1eef4b09c"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"39d053926a6a68accf54b43518513457e35bb395","unresolved":false,"context_lines":[{"line_number":471,"context_line":"    if value is not None:"},{"line_number":472,"context_line":"        query \u003d query.filter(api_models.AggregateMetadata.value \u003d\u003d value)"},{"line_number":473,"context_line":"    query \u003d query.filter(api_models.AggregateMetadata.key.like("},{"line_number":474,"context_line":"        key_prefix + r\u0027%\u0027))"},{"line_number":475,"context_line":"    query \u003d query.filter(~api_models.AggregateMetadata.key.in_(keys))"},{"line_number":476,"context_line":"    query \u003d query.options(contains_eager(\"_metadata\"))"},{"line_number":477,"context_line":"    query \u003d query.options(joinedload(\"_hosts\"))"}],"source_content_type":"text/x-python","patch_set":5,"id":"7faddb67_bb933f5c","line":474,"range":{"start_line":474,"start_character":21,"end_line":474,"end_character":22},"updated":"2019-08-13 09:57:09.000000000","message":"Is this needed? Doesn\u0027t seem like it:\n\n  \u003e\u003e\u003e \u0027%\u0027\n  \u0027%\u0027\n  \u003e\u003e\u003e r\u0027%\u0027\n  \u0027%\u0027","commit_id":"1141f901c858c6fbe23907aef1d81bd1eef4b09c"},{"author":{"_account_id":27302,"name":"Shilpa Devharakar","email":"shilpa.devharakar@nttdata.com","username":"shilpa.devharakar"},"change_message_id":"26d188f3f31e8ee7d0ffb3174f4c9bf978937a31","unresolved":false,"context_lines":[{"line_number":471,"context_line":"    if value is not None:"},{"line_number":472,"context_line":"        query \u003d query.filter(api_models.AggregateMetadata.value \u003d\u003d value)"},{"line_number":473,"context_line":"    query \u003d query.filter(api_models.AggregateMetadata.key.like("},{"line_number":474,"context_line":"        key_prefix + r\u0027%\u0027))"},{"line_number":475,"context_line":"    query \u003d query.filter(~api_models.AggregateMetadata.key.in_(keys))"},{"line_number":476,"context_line":"    query \u003d query.options(contains_eager(\"_metadata\"))"},{"line_number":477,"context_line":"    query \u003d query.options(joinedload(\"_hosts\"))"}],"source_content_type":"text/x-python","patch_set":5,"id":"7faddb67_cf12ee62","line":474,"range":{"start_line":474,"start_character":21,"end_line":474,"end_character":22},"in_reply_to":"7faddb67_bb933f5c","updated":"2019-08-13 15:59:56.000000000","message":"Done","commit_id":"1141f901c858c6fbe23907aef1d81bd1eef4b09c"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"39d053926a6a68accf54b43518513457e35bb395","unresolved":false,"context_lines":[{"line_number":538,"context_line":"                                  db_aggregates)"},{"line_number":539,"context_line":""},{"line_number":540,"context_line":"    @base.remotable_classmethod"},{"line_number":541,"context_line":"    def get_non_matching_by_metadata_keys(cls, context, keys, key_prefix,"},{"line_number":542,"context_line":"                                          value\u003dNone):"},{"line_number":543,"context_line":"        \"\"\"Return aggregates that are not matching with metadata."},{"line_number":544,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"7faddb67_dbf39b9e","line":541,"range":{"start_line":541,"start_character":56,"end_line":541,"end_character":73},"updated":"2019-08-13 09:57:09.000000000","message":"Because this isn\u0027t obvious to me, why do we need \u0027key_prefix\u0027 when we have \u0027keys\u0027? Is it an optimization or something like that? I\u0027ve have expected this to be called like so:\n\n  aggregate_obj.AggregateList.get_non_matching_by_metadata_keys(\n      self.context,\n      [\u0027HW_CPU_X86_MMX\u0027],  # no \u0027trait:\u0027 since that\u0027s the prefix\n      \u0027trait:\u0027,\n      value\u003d\u0027required\u0027)\n\nBut the code/examples suggest this isn\u0027t what you\u0027re doing here","commit_id":"1141f901c858c6fbe23907aef1d81bd1eef4b09c"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"2ce1806c17f96b20dc169a81b4c2dfeb971f0224","unresolved":false,"context_lines":[{"line_number":538,"context_line":"                                  db_aggregates)"},{"line_number":539,"context_line":""},{"line_number":540,"context_line":"    @base.remotable_classmethod"},{"line_number":541,"context_line":"    def get_non_matching_by_metadata_keys(cls, context, keys, key_prefix,"},{"line_number":542,"context_line":"                                          value\u003dNone):"},{"line_number":543,"context_line":"        \"\"\"Return aggregates that are not matching with metadata."},{"line_number":544,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"7faddb67_f242310f","line":541,"range":{"start_line":541,"start_character":56,"end_line":541,"end_character":73},"in_reply_to":"7faddb67_dbf39b9e","updated":"2019-08-13 16:07:54.000000000","message":"It seems like you\u0027ve said contradicting things, but I\u0027ll answer both:\n\n- We need key_prefix because we\u0027re trying to identify metadata entries *with that `key_prefix`*, that are *not in the list of `keys`*.\n- We could change the calling convention as you suggest (which is still using the key_prefix, which is the contradiction noted above). Then the method would have to prepend the prefix for each key in `keys` (which might then be better named `key_suffixes` or similar). That may make intuitive sense when looking at it from the perspective of a trait:$trait_name formatting, but is kind of artificial if you\u0027re looking at this as a general-purpose method.","commit_id":"1141f901c858c6fbe23907aef1d81bd1eef4b09c"},{"author":{"_account_id":27302,"name":"Shilpa Devharakar","email":"shilpa.devharakar@nttdata.com","username":"shilpa.devharakar"},"change_message_id":"26d188f3f31e8ee7d0ffb3174f4c9bf978937a31","unresolved":false,"context_lines":[{"line_number":538,"context_line":"                                  db_aggregates)"},{"line_number":539,"context_line":""},{"line_number":540,"context_line":"    @base.remotable_classmethod"},{"line_number":541,"context_line":"    def get_non_matching_by_metadata_keys(cls, context, keys, key_prefix,"},{"line_number":542,"context_line":"                                          value\u003dNone):"},{"line_number":543,"context_line":"        \"\"\"Return aggregates that are not matching with metadata."},{"line_number":544,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"7faddb67_8f0cf642","line":541,"range":{"start_line":541,"start_character":56,"end_line":541,"end_character":73},"in_reply_to":"7faddb67_dbf39b9e","updated":"2019-08-13 15:59:56.000000000","message":"Yes for query optimization \u0027key_prefix\u0027 is needed.\nBased on \u0027value\u0027, and \u0027key_prefix\u0027 segregating aggregates with metadata.","commit_id":"1141f901c858c6fbe23907aef1d81bd1eef4b09c"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"39d053926a6a68accf54b43518513457e35bb395","unresolved":false,"context_lines":[{"line_number":543,"context_line":"        \"\"\"Return aggregates that are not matching with metadata."},{"line_number":544,"context_line":""},{"line_number":545,"context_line":"        For example, we have aggregates with metadata as below:"},{"line_number":546,"context_line":"            \u0027agg1\u0027 with trait:HW_CPU_X86_MMX\u003d\"required\""},{"line_number":547,"context_line":"            \u0027agg2\u0027 with trait:HW_CPU_X86_SGX\u003d\"required\""},{"line_number":548,"context_line":"            \u0027agg3\u0027 with trait:HW_CPU_X86_MMX\u003d\"required\""},{"line_number":549,"context_line":"            \u0027agg3\u0027 with trait:HW_CPU_X86_SGX\u003d\"required\""},{"line_number":550,"context_line":"        Assume below request:"},{"line_number":551,"context_line":"            aggregate_obj.AggregateList.get_non_matching_by_metadata_keys("},{"line_number":552,"context_line":"                self.context,"}],"source_content_type":"text/x-python","patch_set":5,"id":"7faddb67_5bdfab0b","line":549,"range":{"start_line":546,"start_character":0,"end_line":549,"end_character":55},"updated":"2019-08-13 09:57:09.000000000","message":"There should be new lines before and after this since it\u0027s not valid rST otherwise","commit_id":"1141f901c858c6fbe23907aef1d81bd1eef4b09c"},{"author":{"_account_id":27302,"name":"Shilpa Devharakar","email":"shilpa.devharakar@nttdata.com","username":"shilpa.devharakar"},"change_message_id":"26d188f3f31e8ee7d0ffb3174f4c9bf978937a31","unresolved":false,"context_lines":[{"line_number":543,"context_line":"        \"\"\"Return aggregates that are not matching with metadata."},{"line_number":544,"context_line":""},{"line_number":545,"context_line":"        For example, we have aggregates with metadata as below:"},{"line_number":546,"context_line":"            \u0027agg1\u0027 with trait:HW_CPU_X86_MMX\u003d\"required\""},{"line_number":547,"context_line":"            \u0027agg2\u0027 with trait:HW_CPU_X86_SGX\u003d\"required\""},{"line_number":548,"context_line":"            \u0027agg3\u0027 with trait:HW_CPU_X86_MMX\u003d\"required\""},{"line_number":549,"context_line":"            \u0027agg3\u0027 with trait:HW_CPU_X86_SGX\u003d\"required\""},{"line_number":550,"context_line":"        Assume below request:"},{"line_number":551,"context_line":"            aggregate_obj.AggregateList.get_non_matching_by_metadata_keys("},{"line_number":552,"context_line":"                self.context,"}],"source_content_type":"text/x-python","patch_set":5,"id":"7faddb67_af07721d","line":549,"range":{"start_line":546,"start_character":0,"end_line":549,"end_character":55},"in_reply_to":"7faddb67_5bdfab0b","updated":"2019-08-13 15:59:56.000000000","message":"Done","commit_id":"1141f901c858c6fbe23907aef1d81bd1eef4b09c"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"39d053926a6a68accf54b43518513457e35bb395","unresolved":false,"context_lines":[{"line_number":548,"context_line":"            \u0027agg3\u0027 with trait:HW_CPU_X86_MMX\u003d\"required\""},{"line_number":549,"context_line":"            \u0027agg3\u0027 with trait:HW_CPU_X86_SGX\u003d\"required\""},{"line_number":550,"context_line":"        Assume below request:"},{"line_number":551,"context_line":"            aggregate_obj.AggregateList.get_non_matching_by_metadata_keys("},{"line_number":552,"context_line":"                self.context,"},{"line_number":553,"context_line":"                [\u0027trait:HW_CPU_X86_MMX\u0027],"},{"line_number":554,"context_line":"                \u0027trait:\u0027,"},{"line_number":555,"context_line":"                value\u003d\u0027required\u0027)"},{"line_number":556,"context_line":"        It will return \u0027agg2\u0027 and \u0027agg3\u0027 as aggregates that are not matching"},{"line_number":557,"context_line":"        with metadata."},{"line_number":558,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"7faddb67_1be933b6","line":555,"range":{"start_line":551,"start_character":0,"end_line":555,"end_character":33},"updated":"2019-08-13 09:57:09.000000000","message":"ditto","commit_id":"1141f901c858c6fbe23907aef1d81bd1eef4b09c"},{"author":{"_account_id":27302,"name":"Shilpa Devharakar","email":"shilpa.devharakar@nttdata.com","username":"shilpa.devharakar"},"change_message_id":"26d188f3f31e8ee7d0ffb3174f4c9bf978937a31","unresolved":false,"context_lines":[{"line_number":548,"context_line":"            \u0027agg3\u0027 with trait:HW_CPU_X86_MMX\u003d\"required\""},{"line_number":549,"context_line":"            \u0027agg3\u0027 with trait:HW_CPU_X86_SGX\u003d\"required\""},{"line_number":550,"context_line":"        Assume below request:"},{"line_number":551,"context_line":"            aggregate_obj.AggregateList.get_non_matching_by_metadata_keys("},{"line_number":552,"context_line":"                self.context,"},{"line_number":553,"context_line":"                [\u0027trait:HW_CPU_X86_MMX\u0027],"},{"line_number":554,"context_line":"                \u0027trait:\u0027,"},{"line_number":555,"context_line":"                value\u003d\u0027required\u0027)"},{"line_number":556,"context_line":"        It will return \u0027agg2\u0027 and \u0027agg3\u0027 as aggregates that are not matching"},{"line_number":557,"context_line":"        with metadata."},{"line_number":558,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"7faddb67_6f017a06","line":555,"range":{"start_line":551,"start_character":0,"end_line":555,"end_character":33},"in_reply_to":"7faddb67_1be933b6","updated":"2019-08-13 15:59:56.000000000","message":"Done","commit_id":"1141f901c858c6fbe23907aef1d81bd1eef4b09c"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"08d0f8f3883e1a3a83c57624585c60411dcab556","unresolved":false,"context_lines":[{"line_number":451,"context_line":"    return query.all()"},{"line_number":452,"context_line":""},{"line_number":453,"context_line":""},{"line_number":454,"context_line":"@db_api.api_context_manager.reader"},{"line_number":455,"context_line":"def _get_non_matching_by_metadata_keys_from_db(context, keys, key_prefix,"},{"line_number":456,"context_line":"                                               value\u003dNone):"},{"line_number":457,"context_line":"    \"\"\"Filter aggregates based on non matching metadata."}],"source_content_type":"text/x-python","patch_set":6,"id":"7faddb67_06c6a817","line":454,"range":{"start_line":454,"start_character":0,"end_line":454,"end_character":34},"updated":"2019-08-14 00:28:53.000000000","message":"i was just about to ask shoudl this be under a reader lock so that it will block if a concurrent request is updating the metadata. i see it already is already using the reader context that is proably enough for this usecase.","commit_id":"9185eda446dfb14f8b671b13317c8befbac89027"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"2423f0a152811386548a2d9f53482e7115147a04","unresolved":false,"context_lines":[{"line_number":452,"context_line":""},{"line_number":453,"context_line":""},{"line_number":454,"context_line":"@db_api.api_context_manager.reader"},{"line_number":455,"context_line":"def _get_non_matching_by_metadata_keys_from_db(context, keys, key_prefix,"},{"line_number":456,"context_line":"                                               value\u003dNone):"},{"line_number":457,"context_line":"    \"\"\"Filter aggregates based on non matching metadata."},{"line_number":458,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"7faddb67_3d5dee14","line":455,"range":{"start_line":455,"start_character":56,"end_line":455,"end_character":60},"updated":"2019-08-14 10:53:40.000000000","message":"ignored_keys would be more descriptive I guess.\n\nIsn\u0027t this function returns aggregates with metadata that has matching key_prefix with matching value, while ignoring some of the keys?\n\nIf yes then I think we don\u0027t need the negation in the name of the function.\n\ndef _get_matching_by_metadata(context, key_prefix, value, ignore_keys)\n\nFor me the non_matching part makes this hard to understand as we do need matching except in some keys.","commit_id":"9185eda446dfb14f8b671b13317c8befbac89027"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"c71384b5a3c741453cfba62bf76d44c87c61952b","unresolved":false,"context_lines":[{"line_number":452,"context_line":""},{"line_number":453,"context_line":""},{"line_number":454,"context_line":"@db_api.api_context_manager.reader"},{"line_number":455,"context_line":"def _get_non_matching_by_metadata_keys_from_db(context, keys, key_prefix,"},{"line_number":456,"context_line":"                                               value\u003dNone):"},{"line_number":457,"context_line":"    \"\"\"Filter aggregates based on non matching metadata."},{"line_number":458,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"7faddb67_850fdc2c","line":455,"range":{"start_line":455,"start_character":56,"end_line":455,"end_character":60},"in_reply_to":"7faddb67_3d5dee14","updated":"2019-08-14 19:38:15.000000000","message":"+1 for\n\n def _get_matching_by_metadata(context, key_prefix, value, ignore_keys)","commit_id":"9185eda446dfb14f8b671b13317c8befbac89027"},{"author":{"_account_id":27302,"name":"Shilpa Devharakar","email":"shilpa.devharakar@nttdata.com","username":"shilpa.devharakar"},"change_message_id":"6f0d5b3c5a8a92ea7a31fe25d2aa177194afeecb","unresolved":false,"context_lines":[{"line_number":452,"context_line":""},{"line_number":453,"context_line":""},{"line_number":454,"context_line":"@db_api.api_context_manager.reader"},{"line_number":455,"context_line":"def _get_non_matching_by_metadata_keys_from_db(context, keys, key_prefix,"},{"line_number":456,"context_line":"                                               value\u003dNone):"},{"line_number":457,"context_line":"    \"\"\"Filter aggregates based on non matching metadata."},{"line_number":458,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"7faddb67_004d1771","line":455,"range":{"start_line":455,"start_character":56,"end_line":455,"end_character":60},"in_reply_to":"7faddb67_850fdc2c","updated":"2019-08-15 00:16:07.000000000","message":"Done","commit_id":"9185eda446dfb14f8b671b13317c8befbac89027"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"2423f0a152811386548a2d9f53482e7115147a04","unresolved":false,"context_lines":[{"line_number":456,"context_line":"                                               value\u003dNone):"},{"line_number":457,"context_line":"    \"\"\"Filter aggregates based on non matching metadata."},{"line_number":458,"context_line":""},{"line_number":459,"context_line":"    Find aggregates with ${key_prefix}*[\u003d${value}] metadata, but only"},{"line_number":460,"context_line":"    if they have a ${key_prefix}* key not in ${keys}."},{"line_number":461,"context_line":""},{"line_number":462,"context_line":"    :return: Aggregates with any metadata entry:"},{"line_number":463,"context_line":"        - whose key starts with `key_prefix`; and"}],"source_content_type":"text/x-python","patch_set":6,"id":"7faddb67_dd829a52","line":460,"range":{"start_line":459,"start_character":1,"end_line":460,"end_character":53},"updated":"2019-08-14 10:53:40.000000000","message":"Find aggregates with at least one ${key_prefix}*[\u003d${value}] metadata where the metadata key are not in the ignored_keys list.","commit_id":"9185eda446dfb14f8b671b13317c8befbac89027"},{"author":{"_account_id":27302,"name":"Shilpa Devharakar","email":"shilpa.devharakar@nttdata.com","username":"shilpa.devharakar"},"change_message_id":"6f0d5b3c5a8a92ea7a31fe25d2aa177194afeecb","unresolved":false,"context_lines":[{"line_number":456,"context_line":"                                               value\u003dNone):"},{"line_number":457,"context_line":"    \"\"\"Filter aggregates based on non matching metadata."},{"line_number":458,"context_line":""},{"line_number":459,"context_line":"    Find aggregates with ${key_prefix}*[\u003d${value}] metadata, but only"},{"line_number":460,"context_line":"    if they have a ${key_prefix}* key not in ${keys}."},{"line_number":461,"context_line":""},{"line_number":462,"context_line":"    :return: Aggregates with any metadata entry:"},{"line_number":463,"context_line":"        - whose key starts with `key_prefix`; and"}],"source_content_type":"text/x-python","patch_set":6,"id":"7faddb67_c0529f12","line":460,"range":{"start_line":459,"start_character":1,"end_line":460,"end_character":53},"in_reply_to":"7faddb67_25186874","updated":"2019-08-15 00:16:07.000000000","message":"Done","commit_id":"9185eda446dfb14f8b671b13317c8befbac89027"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"c71384b5a3c741453cfba62bf76d44c87c61952b","unresolved":false,"context_lines":[{"line_number":456,"context_line":"                                               value\u003dNone):"},{"line_number":457,"context_line":"    \"\"\"Filter aggregates based on non matching metadata."},{"line_number":458,"context_line":""},{"line_number":459,"context_line":"    Find aggregates with ${key_prefix}*[\u003d${value}] metadata, but only"},{"line_number":460,"context_line":"    if they have a ${key_prefix}* key not in ${keys}."},{"line_number":461,"context_line":""},{"line_number":462,"context_line":"    :return: Aggregates with any metadata entry:"},{"line_number":463,"context_line":"        - whose key starts with `key_prefix`; and"}],"source_content_type":"text/x-python","patch_set":6,"id":"7faddb67_25186874","line":460,"range":{"start_line":459,"start_character":1,"end_line":460,"end_character":53},"in_reply_to":"7faddb67_dd829a52","updated":"2019-08-14 19:38:15.000000000","message":"++","commit_id":"9185eda446dfb14f8b671b13317c8befbac89027"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"2423f0a152811386548a2d9f53482e7115147a04","unresolved":false,"context_lines":[{"line_number":463,"context_line":"        - whose key starts with `key_prefix`; and"},{"line_number":464,"context_line":"        - whose value is `value` (if `value` is specified); and"},{"line_number":465,"context_line":"        - whose key is *not* in the `keys` list."},{"line_number":466,"context_line":"    \"\"\""},{"line_number":467,"context_line":""},{"line_number":468,"context_line":"    query \u003d context.session.query(api_models.Aggregate)"},{"line_number":469,"context_line":"    query \u003d query.join(\"_metadata\")"}],"source_content_type":"text/x-python","patch_set":6,"id":"7faddb67_8a7056dc","line":466,"updated":"2019-08-14 10:53:40.000000000","message":"Sorry my brain exploded. \n\nCan we remove some complexity from this? E.g. value param is specified in every caller of this function. So I think that value\u003dNone defaulting and then the extra if can be dropped.\n\nAlso does it make sense to call this function with an empty \u0027keys\u0027 list? I think not. So make that an error.\n\nCan we make the empty key_prefix also an error? At least the current caller supplies a nonempty prefix.\n\nAlso i\u0027m trying to reformulate the query as python code to see if I understand what this is aiming for:\n\n\n    def _get_non_matching_by_metadata_keys_from_db(context, ignore_keys, key_prefix, value):\n\n        if not not_allowed_keys:\n            raise ValueError(...)\n        if not key_prefix:\n            raise ValueError(...)\n\n        result \u003d []\n        for agg in aggregates:\n            meta \u003d agg.metadata\n            prefixed_keys_with_matching_value \u003d {\n                key for key in meta \n                if key.startswith(key_prefix) \n                    and meta[key] \u003d\u003d value}\n            if prefixed_keys_with_matching_value.discard(\n                    ignore_keys):            \n                result.append(agg)\n\n         return result\n\n\nDid I understand the query correctly?","commit_id":"9185eda446dfb14f8b671b13317c8befbac89027"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"c71384b5a3c741453cfba62bf76d44c87c61952b","unresolved":false,"context_lines":[{"line_number":463,"context_line":"        - whose key starts with `key_prefix`; and"},{"line_number":464,"context_line":"        - whose value is `value` (if `value` is specified); and"},{"line_number":465,"context_line":"        - whose key is *not* in the `keys` list."},{"line_number":466,"context_line":"    \"\"\""},{"line_number":467,"context_line":""},{"line_number":468,"context_line":"    query \u003d context.session.query(api_models.Aggregate)"},{"line_number":469,"context_line":"    query \u003d query.join(\"_metadata\")"}],"source_content_type":"text/x-python","patch_set":6,"id":"7faddb67_25462852","line":466,"in_reply_to":"7faddb67_8a7056dc","updated":"2019-08-14 19:38:15.000000000","message":"yes.\n\nAnd I agree with your suggested simplifications. If we were making this remotable and tying it to object versions, there would be some motivation to make it as generic as possible. But since we\u0027re not, it would be cheap to extend it later if necessary.","commit_id":"9185eda446dfb14f8b671b13317c8befbac89027"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"4a1ce5b10fbdf2802aefbc8708b35ab278b22135","unresolved":false,"context_lines":[{"line_number":538,"context_line":"        return base.obj_make_list(context, cls(context), objects.Aggregate,"},{"line_number":539,"context_line":"                                  db_aggregates)"},{"line_number":540,"context_line":""},{"line_number":541,"context_line":"    @base.remotable_classmethod"},{"line_number":542,"context_line":"    def get_non_matching_by_metadata_keys(cls, context, keys, key_prefix,"},{"line_number":543,"context_line":"                                          value\u003dNone):"},{"line_number":544,"context_line":"        \"\"\"Return aggregates that are not matching with metadata."}],"source_content_type":"text/x-python","patch_set":6,"id":"7faddb67_c3664556","line":541,"updated":"2019-08-13 18:41:15.000000000","message":"Why is this remotable? The only reason it would need to be is so it can be called over RPC. Since computes shouldn\u0027t be reading from the API database, this shouldn\u0027t happen. If you remove this, you also don\u0027t need to bump the version.","commit_id":"9185eda446dfb14f8b671b13317c8befbac89027"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"08d0f8f3883e1a3a83c57624585c60411dcab556","unresolved":false,"context_lines":[{"line_number":538,"context_line":"        return base.obj_make_list(context, cls(context), objects.Aggregate,"},{"line_number":539,"context_line":"                                  db_aggregates)"},{"line_number":540,"context_line":""},{"line_number":541,"context_line":"    @base.remotable_classmethod"},{"line_number":542,"context_line":"    def get_non_matching_by_metadata_keys(cls, context, keys, key_prefix,"},{"line_number":543,"context_line":"                                          value\u003dNone):"},{"line_number":544,"context_line":"        \"\"\"Return aggregates that are not matching with metadata."}],"source_content_type":"text/x-python","patch_set":6,"id":"7faddb67_c6e8907d","line":541,"in_reply_to":"7faddb67_6342eead","updated":"2019-08-14 00:28:53.000000000","message":"pre placement we might have needed this to be remoteable to do a late check on the compute node althgh there are cheaper ways to do that but with plamcent i dont see a need for this to ever be called form a compute node even if we allowed upcalls to the api db so yes removing this makes sense.","commit_id":"9185eda446dfb14f8b671b13317c8befbac89027"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"072bb403f4378aa990d28216f198f5f4dd40af86","unresolved":false,"context_lines":[{"line_number":538,"context_line":"        return base.obj_make_list(context, cls(context), objects.Aggregate,"},{"line_number":539,"context_line":"                                  db_aggregates)"},{"line_number":540,"context_line":""},{"line_number":541,"context_line":"    @base.remotable_classmethod"},{"line_number":542,"context_line":"    def get_non_matching_by_metadata_keys(cls, context, keys, key_prefix,"},{"line_number":543,"context_line":"                                          value\u003dNone):"},{"line_number":544,"context_line":"        \"\"\"Return aggregates that are not matching with metadata."}],"source_content_type":"text/x-python","patch_set":6,"id":"7faddb67_6342eead","line":541,"in_reply_to":"7faddb67_c3664556","updated":"2019-08-13 22:34:45.000000000","message":"+1 to make this not remotable","commit_id":"9185eda446dfb14f8b671b13317c8befbac89027"},{"author":{"_account_id":27302,"name":"Shilpa Devharakar","email":"shilpa.devharakar@nttdata.com","username":"shilpa.devharakar"},"change_message_id":"6f0d5b3c5a8a92ea7a31fe25d2aa177194afeecb","unresolved":false,"context_lines":[{"line_number":538,"context_line":"        return base.obj_make_list(context, cls(context), objects.Aggregate,"},{"line_number":539,"context_line":"                                  db_aggregates)"},{"line_number":540,"context_line":""},{"line_number":541,"context_line":"    @base.remotable_classmethod"},{"line_number":542,"context_line":"    def get_non_matching_by_metadata_keys(cls, context, keys, key_prefix,"},{"line_number":543,"context_line":"                                          value\u003dNone):"},{"line_number":544,"context_line":"        \"\"\"Return aggregates that are not matching with metadata."}],"source_content_type":"text/x-python","patch_set":6,"id":"7faddb67_a03d23bc","line":541,"in_reply_to":"7faddb67_c3664556","updated":"2019-08-15 00:16:07.000000000","message":"Done","commit_id":"9185eda446dfb14f8b671b13317c8befbac89027"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"2357d37be323f29eddb8f2a840d37a01c5cb257e","unresolved":false,"context_lines":[{"line_number":539,"context_line":"                                  db_aggregates)"},{"line_number":540,"context_line":""},{"line_number":541,"context_line":"    @base.remotable_classmethod"},{"line_number":542,"context_line":"    def get_non_matching_by_metadata_keys(cls, context, keys, key_prefix,"},{"line_number":543,"context_line":"                                          value\u003dNone):"},{"line_number":544,"context_line":"        \"\"\"Return aggregates that are not matching with metadata."},{"line_number":545,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"7faddb67_a9668754","line":542,"range":{"start_line":542,"start_character":8,"end_line":542,"end_character":40},"updated":"2019-08-14 01:31:54.000000000","message":"i would try and find a better name for this \n\ni belive its finding all aggreate wehre the agggreate metadata keys as filtereed by key_prefix and value are not a subset of keys.\n\nso i would call this something like this\n\nget_by_non_subset_keys.","commit_id":"9185eda446dfb14f8b671b13317c8befbac89027"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"c71384b5a3c741453cfba62bf76d44c87c61952b","unresolved":false,"context_lines":[{"line_number":539,"context_line":"                                  db_aggregates)"},{"line_number":540,"context_line":""},{"line_number":541,"context_line":"    @base.remotable_classmethod"},{"line_number":542,"context_line":"    def get_non_matching_by_metadata_keys(cls, context, keys, key_prefix,"},{"line_number":543,"context_line":"                                          value\u003dNone):"},{"line_number":544,"context_line":"        \"\"\"Return aggregates that are not matching with metadata."},{"line_number":545,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"7faddb67_8566fcec","line":542,"range":{"start_line":542,"start_character":8,"end_line":542,"end_character":40},"in_reply_to":"7faddb67_74ce2684","updated":"2019-08-14 19:38:15.000000000","message":"\u003e I\u0027m not sure there exists a name\n\nI stand corrected: https://review.opendev.org/#/c/671074/6/nova/objects/aggregate.py@455","commit_id":"9185eda446dfb14f8b671b13317c8befbac89027"},{"author":{"_account_id":27302,"name":"Shilpa Devharakar","email":"shilpa.devharakar@nttdata.com","username":"shilpa.devharakar"},"change_message_id":"6f0d5b3c5a8a92ea7a31fe25d2aa177194afeecb","unresolved":false,"context_lines":[{"line_number":539,"context_line":"                                  db_aggregates)"},{"line_number":540,"context_line":""},{"line_number":541,"context_line":"    @base.remotable_classmethod"},{"line_number":542,"context_line":"    def get_non_matching_by_metadata_keys(cls, context, keys, key_prefix,"},{"line_number":543,"context_line":"                                          value\u003dNone):"},{"line_number":544,"context_line":"        \"\"\"Return aggregates that are not matching with metadata."},{"line_number":545,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"7faddb67_007677a5","line":542,"range":{"start_line":542,"start_character":8,"end_line":542,"end_character":40},"in_reply_to":"7faddb67_8566fcec","updated":"2019-08-15 00:16:07.000000000","message":"IMO this correct, keeping for now as is.\nIf further suggestions, lets suggest and vote for same, accordingly will made changes.","commit_id":"9185eda446dfb14f8b671b13317c8befbac89027"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"53f7325ad3916ad18e3e43f18fc457cfc10b7de0","unresolved":false,"context_lines":[{"line_number":539,"context_line":"                                  db_aggregates)"},{"line_number":540,"context_line":""},{"line_number":541,"context_line":"    @base.remotable_classmethod"},{"line_number":542,"context_line":"    def get_non_matching_by_metadata_keys(cls, context, keys, key_prefix,"},{"line_number":543,"context_line":"                                          value\u003dNone):"},{"line_number":544,"context_line":"        \"\"\"Return aggregates that are not matching with metadata."},{"line_number":545,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"7faddb67_74ce2684","line":542,"range":{"start_line":542,"start_character":8,"end_line":542,"end_character":40},"in_reply_to":"7faddb67_a9668754","updated":"2019-08-14 02:39:18.000000000","message":"Once this method is not remotable, we can bikeshed the name in a followon. But tbh I\u0027m not sure there exists a name of any reasonable length, considering we can\u0027t even collectively come up with a docstring that explains it adequately.","commit_id":"9185eda446dfb14f8b671b13317c8befbac89027"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"2423f0a152811386548a2d9f53482e7115147a04","unresolved":false,"context_lines":[{"line_number":554,"context_line":""},{"line_number":555,"context_line":"            aggregate_obj.AggregateList.get_non_matching_by_metadata_keys("},{"line_number":556,"context_line":"                self.context,"},{"line_number":557,"context_line":"                [\u0027trait:HW_CPU_X86_MMX\u0027],"},{"line_number":558,"context_line":"                \u0027trait:\u0027,"},{"line_number":559,"context_line":"                value\u003d\u0027required\u0027)"},{"line_number":560,"context_line":""},{"line_number":561,"context_line":"        It will return \u0027agg2\u0027 and \u0027agg3\u0027 as aggregates that are not matching"}],"source_content_type":"text/x-python","patch_set":6,"id":"7faddb67_c785e708","line":558,"range":{"start_line":557,"start_character":0,"end_line":558,"end_character":25},"updated":"2019-08-14 10:53:40.000000000","message":"Based on this example the key_prefix seems to be a redundant parameter as each key in the \u0027keys\u0027 list specifies the full key with the prefix itself.\n\nOr do we want to force that we only return aggregates that has at least one other \"trait:...\" key that does not match with \u0027trait:HW_CPU_X86_MMX\u0027 ?\n\n//later\n\nI see that this question was asked and answered before. I think it would be nice to explain in the func doc that key_prefix is here for query optimization. (sure can be done in a follow up)","commit_id":"9185eda446dfb14f8b671b13317c8befbac89027"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"16b8ea5e8a46732635f860f3a44a5c4551943c7a","unresolved":false,"context_lines":[{"line_number":574,"context_line":"    :returns: List of aggregates that doesn\u0027t match metadata keys that"},{"line_number":575,"context_line":"              starts with key_prefix with the supplied keys."},{"line_number":576,"context_line":"    \"\"\""},{"line_number":577,"context_line":"    db_aggregates \u003d _get_non_matching_by_metadata_keys_from_db("},{"line_number":578,"context_line":"        context, ignored_keys, key_prefix, value\u003dvalue)"},{"line_number":579,"context_line":"    return base.obj_make_list(context, objects.AggregateList(context),"},{"line_number":580,"context_line":"                              objects.Aggregate, db_aggregates)"}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_608acb64","line":577,"range":{"start_line":577,"start_character":20,"end_line":577,"end_character":62},"updated":"2019-08-15 00:21:50.000000000","message":"At this point the two methods could be combined. The only reason they needed to be separate originally was so one could have the db context and the other could be remotable.","commit_id":"33abbfb92318d7951fc62a86bdea067c2bed8200"},{"author":{"_account_id":27302,"name":"Shilpa Devharakar","email":"shilpa.devharakar@nttdata.com","username":"shilpa.devharakar"},"change_message_id":"8c4eb741082eecdadd1f62211681da8449984c9b","unresolved":false,"context_lines":[{"line_number":574,"context_line":"    :returns: List of aggregates that doesn\u0027t match metadata keys that"},{"line_number":575,"context_line":"              starts with key_prefix with the supplied keys."},{"line_number":576,"context_line":"    \"\"\""},{"line_number":577,"context_line":"    db_aggregates \u003d _get_non_matching_by_metadata_keys_from_db("},{"line_number":578,"context_line":"        context, ignored_keys, key_prefix, value\u003dvalue)"},{"line_number":579,"context_line":"    return base.obj_make_list(context, objects.AggregateList(context),"},{"line_number":580,"context_line":"                              objects.Aggregate, db_aggregates)"}],"source_content_type":"text/x-python","patch_set":7,"id":"7faddb67_de69edf7","line":577,"range":{"start_line":577,"start_character":20,"end_line":577,"end_character":62},"in_reply_to":"7faddb67_608acb64","updated":"2019-08-19 16:17:34.000000000","message":"Keeping private method, since it return aggregates, adding @classmethod.","commit_id":"33abbfb92318d7951fc62a86bdea067c2bed8200"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"6af766ef2ec1b676726b0cd75bd6ccf567b22042","unresolved":false,"context_lines":[{"line_number":453,"context_line":""},{"line_number":454,"context_line":"@db_api.api_context_manager.reader"},{"line_number":455,"context_line":"def _get_non_matching_by_metadata_keys_from_db(context, ignored_keys,"},{"line_number":456,"context_line":"                                               key_prefix, value\u003dNone):"},{"line_number":457,"context_line":"    \"\"\"Filter aggregates based on non matching metadata."},{"line_number":458,"context_line":""},{"line_number":459,"context_line":"    Find aggregates with at least one ${key_prefix}*[\u003d${value}] metadata where"}],"source_content_type":"text/x-python","patch_set":8,"id":"7faddb67_063dba8d","line":456,"range":{"start_line":456,"start_character":59,"end_line":456,"end_character":69},"updated":"2019-08-22 09:35:37.000000000","message":"I still think that we don\u0027t need to default the \u0027value\u0027 param as every current caller provides a value for this param.","commit_id":"4931cb76251037c42951b80ee58fac54a95f3556"},{"author":{"_account_id":27302,"name":"Shilpa Devharakar","email":"shilpa.devharakar@nttdata.com","username":"shilpa.devharakar"},"change_message_id":"26c44b728beca8d90f417ce46a092c6634be8ed4","unresolved":false,"context_lines":[{"line_number":453,"context_line":""},{"line_number":454,"context_line":"@db_api.api_context_manager.reader"},{"line_number":455,"context_line":"def _get_non_matching_by_metadata_keys_from_db(context, ignored_keys,"},{"line_number":456,"context_line":"                                               key_prefix, value\u003dNone):"},{"line_number":457,"context_line":"    \"\"\"Filter aggregates based on non matching metadata."},{"line_number":458,"context_line":""},{"line_number":459,"context_line":"    Find aggregates with at least one ${key_prefix}*[\u003d${value}] metadata where"}],"source_content_type":"text/x-python","patch_set":8,"id":"7faddb67_15563ed0","line":456,"range":{"start_line":456,"start_character":59,"end_line":456,"end_character":69},"in_reply_to":"7faddb67_063dba8d","updated":"2019-08-22 13:23:43.000000000","message":"Done","commit_id":"4931cb76251037c42951b80ee58fac54a95f3556"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"6af766ef2ec1b676726b0cd75bd6ccf567b22042","unresolved":false,"context_lines":[{"line_number":469,"context_line":"    query \u003d query.join(\"_metadata\")"},{"line_number":470,"context_line":"    if value is not None:"},{"line_number":471,"context_line":"        query \u003d query.filter(api_models.AggregateMetadata.value \u003d\u003d value)"},{"line_number":472,"context_line":"    if len(ignored_keys) \u003e 0:"},{"line_number":473,"context_line":"        if key_prefix:"},{"line_number":474,"context_line":"            query \u003d query.filter(api_models.AggregateMetadata.key.like("},{"line_number":475,"context_line":"                key_prefix + \u0027%\u0027))"}],"source_content_type":"text/x-python","patch_set":8,"id":"7faddb67_e6c41e44","line":472,"range":{"start_line":472,"start_character":7,"end_line":472,"end_character":28},"updated":"2019-08-22 09:35:37.000000000","message":"I think we can make the empty ignored_keys an error as well and move the check to the beginning.","commit_id":"4931cb76251037c42951b80ee58fac54a95f3556"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"2ca168c1d1e27583bc4a371b881bd837c582f570","unresolved":false,"context_lines":[{"line_number":469,"context_line":"    query \u003d query.join(\"_metadata\")"},{"line_number":470,"context_line":"    if value is not None:"},{"line_number":471,"context_line":"        query \u003d query.filter(api_models.AggregateMetadata.value \u003d\u003d value)"},{"line_number":472,"context_line":"    if len(ignored_keys) \u003e 0:"},{"line_number":473,"context_line":"        if key_prefix:"},{"line_number":474,"context_line":"            query \u003d query.filter(api_models.AggregateMetadata.key.like("},{"line_number":475,"context_line":"                key_prefix + \u0027%\u0027))"}],"source_content_type":"text/x-python","patch_set":8,"id":"7faddb67_6f648122","line":472,"range":{"start_line":472,"start_character":7,"end_line":472,"end_character":28},"in_reply_to":"7faddb67_e6c41e44","updated":"2019-08-22 12:24:49.000000000","message":"I made a mistake here. if the ignored_key is empty then we have to return every aggregate that has some special form of metadata.","commit_id":"4931cb76251037c42951b80ee58fac54a95f3556"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"2ca168c1d1e27583bc4a371b881bd837c582f570","unresolved":false,"context_lines":[{"line_number":470,"context_line":"    if value is not None:"},{"line_number":471,"context_line":"        query \u003d query.filter(api_models.AggregateMetadata.value \u003d\u003d value)"},{"line_number":472,"context_line":"    if len(ignored_keys) \u003e 0:"},{"line_number":473,"context_line":"        if key_prefix:"},{"line_number":474,"context_line":"            query \u003d query.filter(api_models.AggregateMetadata.key.like("},{"line_number":475,"context_line":"                key_prefix + \u0027%\u0027))"},{"line_number":476,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":8,"id":"7faddb67_0f42ad69","line":473,"range":{"start_line":473,"start_character":7,"end_line":473,"end_character":21},"updated":"2019-08-22 12:24:49.000000000","message":"We can make the empty key_prefix an error since the caller always provide the \"trait:\" key_prefix.","commit_id":"4931cb76251037c42951b80ee58fac54a95f3556"},{"author":{"_account_id":27302,"name":"Shilpa Devharakar","email":"shilpa.devharakar@nttdata.com","username":"shilpa.devharakar"},"change_message_id":"26c44b728beca8d90f417ce46a092c6634be8ed4","unresolved":false,"context_lines":[{"line_number":470,"context_line":"    if value is not None:"},{"line_number":471,"context_line":"        query \u003d query.filter(api_models.AggregateMetadata.value \u003d\u003d value)"},{"line_number":472,"context_line":"    if len(ignored_keys) \u003e 0:"},{"line_number":473,"context_line":"        if key_prefix:"},{"line_number":474,"context_line":"            query \u003d query.filter(api_models.AggregateMetadata.key.like("},{"line_number":475,"context_line":"                key_prefix + \u0027%\u0027))"},{"line_number":476,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":8,"id":"7faddb67_355b3af7","line":473,"range":{"start_line":473,"start_character":7,"end_line":473,"end_character":21},"in_reply_to":"7faddb67_0f42ad69","updated":"2019-08-22 13:23:43.000000000","message":"Done","commit_id":"4931cb76251037c42951b80ee58fac54a95f3556"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"6af766ef2ec1b676726b0cd75bd6ccf567b22042","unresolved":false,"context_lines":[{"line_number":473,"context_line":"        if key_prefix:"},{"line_number":474,"context_line":"            query \u003d query.filter(api_models.AggregateMetadata.key.like("},{"line_number":475,"context_line":"                key_prefix + \u0027%\u0027))"},{"line_number":476,"context_line":"        else:"},{"line_number":477,"context_line":"            raise ValueError(_(\u0027key_prefix mandatory field.\u0027))"},{"line_number":478,"context_line":"        query \u003d query.filter(~api_models.AggregateMetadata.key.in_("},{"line_number":479,"context_line":"            ignored_keys))"},{"line_number":480,"context_line":""}],"source_content_type":"text/x-python","patch_set":8,"id":"7faddb67_06ae1a81","line":477,"range":{"start_line":476,"start_character":0,"end_line":477,"end_character":62},"updated":"2019-08-22 09:35:37.000000000","message":"I would move this check to the beginning of the function to decrease complexity.","commit_id":"4931cb76251037c42951b80ee58fac54a95f3556"},{"author":{"_account_id":27302,"name":"Shilpa Devharakar","email":"shilpa.devharakar@nttdata.com","username":"shilpa.devharakar"},"change_message_id":"26c44b728beca8d90f417ce46a092c6634be8ed4","unresolved":false,"context_lines":[{"line_number":473,"context_line":"        if key_prefix:"},{"line_number":474,"context_line":"            query \u003d query.filter(api_models.AggregateMetadata.key.like("},{"line_number":475,"context_line":"                key_prefix + \u0027%\u0027))"},{"line_number":476,"context_line":"        else:"},{"line_number":477,"context_line":"            raise ValueError(_(\u0027key_prefix mandatory field.\u0027))"},{"line_number":478,"context_line":"        query \u003d query.filter(~api_models.AggregateMetadata.key.in_("},{"line_number":479,"context_line":"            ignored_keys))"},{"line_number":480,"context_line":""}],"source_content_type":"text/x-python","patch_set":8,"id":"7faddb67_d56f4691","line":477,"range":{"start_line":476,"start_character":0,"end_line":477,"end_character":62},"in_reply_to":"7faddb67_06ae1a81","updated":"2019-08-22 13:23:43.000000000","message":"Done","commit_id":"4931cb76251037c42951b80ee58fac54a95f3556"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"ec2a23b10e7c91635a1351c5cd6bed28723f30e1","unresolved":false,"context_lines":[{"line_number":543,"context_line":"    @classmethod"},{"line_number":544,"context_line":"    def get_non_matching_by_metadata_keys(cls, context, ignored_keys,"},{"line_number":545,"context_line":"                                          key_prefix, value):"},{"line_number":546,"context_line":"        \"\"\"Return aggregates that are not matching with metadata."},{"line_number":547,"context_line":""},{"line_number":548,"context_line":"        For example, we have aggregates with metadata as below:"},{"line_number":549,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"7faddb67_775a3650","line":546,"range":{"start_line":546,"start_character":11,"end_line":546,"end_character":65},"updated":"2019-09-05 15:22:13.000000000","message":"This is a super weirdly inverted thing to have. No suggested alternatives, just...it\u0027s weird.","commit_id":"a8316b60164b8b022c65232708b35dfb20a4e8c8"}],"nova/tests/functional/db/test_aggregate.py":[{"author":{"_account_id":25625,"name":"Tetsuro Nakamura","email":"tetsuro.nakamura.bc@hco.ntt.co.jp","username":"tetsuro0907"},"change_message_id":"97d5f6f6be9ba8df894686d011a48efb7cc16e09","unresolved":false,"context_lines":[{"line_number":564,"context_line":""},{"line_number":565,"context_line":"    def test_get_non_matching_by_metadata_keys(self):"},{"line_number":566,"context_line":"        agg \u003d aggregate_obj.Aggregate.get_by_id(self.context, 1)"},{"line_number":567,"context_line":"        agg.metadata \u003d {}"},{"line_number":568,"context_line":"        agg.update_metadata({\u0027trait:HW_CPU_X86_MMX\u0027: \u0027required\u0027})"},{"line_number":569,"context_line":""},{"line_number":570,"context_line":"        agg \u003d aggregate_obj.Aggregate.get_by_id(self.context, 2)"}],"source_content_type":"text/x-python","patch_set":2,"id":"7faddb67_0c898d73","line":567,"range":{"start_line":567,"start_character":8,"end_line":567,"end_character":25},"updated":"2019-08-04 08:17:56.000000000","message":"What did you intend to do with this?\nThe metadata set by default by the test, {\u0027unique_key\u0027: u\u0027unique_value_\u003ci\u003e\u0027} in DB, is not cleared by this, so this actually does nothing here. I don\u0027t think this is needed.\n\nSame on L571, 575.","commit_id":"380645fbec6026e0cb9f2ead54602d1f0eb82193"},{"author":{"_account_id":27302,"name":"Shilpa Devharakar","email":"shilpa.devharakar@nttdata.com","username":"shilpa.devharakar"},"change_message_id":"df9f93f79fbdc94da80271547e6b45ec5646be9b","unresolved":false,"context_lines":[{"line_number":564,"context_line":""},{"line_number":565,"context_line":"    def test_get_non_matching_by_metadata_keys(self):"},{"line_number":566,"context_line":"        agg \u003d aggregate_obj.Aggregate.get_by_id(self.context, 1)"},{"line_number":567,"context_line":"        agg.metadata \u003d {}"},{"line_number":568,"context_line":"        agg.update_metadata({\u0027trait:HW_CPU_X86_MMX\u0027: \u0027required\u0027})"},{"line_number":569,"context_line":""},{"line_number":570,"context_line":"        agg \u003d aggregate_obj.Aggregate.get_by_id(self.context, 2)"}],"source_content_type":"text/x-python","patch_set":2,"id":"7faddb67_7b8c4335","line":567,"range":{"start_line":567,"start_character":8,"end_line":567,"end_character":25},"in_reply_to":"7faddb67_0c898d73","updated":"2019-08-07 12:55:49.000000000","message":"removed","commit_id":"380645fbec6026e0cb9f2ead54602d1f0eb82193"},{"author":{"_account_id":25625,"name":"Tetsuro Nakamura","email":"tetsuro.nakamura.bc@hco.ntt.co.jp","username":"tetsuro0907"},"change_message_id":"97d5f6f6be9ba8df894686d011a48efb7cc16e09","unresolved":false,"context_lines":[{"line_number":581,"context_line":"            value\u003d\u0027required\u0027)"},{"line_number":582,"context_line":""},{"line_number":583,"context_line":"        self.assertEqual(2, len(aggs))"},{"line_number":584,"context_line":"        self.assertItemsEqual([2, 3], [a.id for a in aggs])"},{"line_number":585,"context_line":""},{"line_number":586,"context_line":"    def test_get_non_matching_by_metadata_keys_from_db_assertion(self):"},{"line_number":587,"context_line":"        self.assertRaises("}],"source_content_type":"text/x-python","patch_set":2,"id":"7faddb67_ec38b1a0","line":584,"updated":"2019-08-04 08:17:56.000000000","message":"Good to add more tests like:\n\n1. Aggregates with metadata with non \"required\" value but has a key prefixed by trait:\n\n        agg \u003d aggregate_obj.Aggregate.get_by_id(self.context, 4)\n        agg.update_metadata({\u0027trait:HW_CPU_X86_MMX\u0027: \u0027required\u0027,\n                             \u0027trait:HW_CPU_X86_SGX\u0027: \u0027just_for_marking\u0027})\n\n2. Call the func with multiple keys args\n\n3. Call the func with empty keys args","commit_id":"380645fbec6026e0cb9f2ead54602d1f0eb82193"},{"author":{"_account_id":27302,"name":"Shilpa Devharakar","email":"shilpa.devharakar@nttdata.com","username":"shilpa.devharakar"},"change_message_id":"df9f93f79fbdc94da80271547e6b45ec5646be9b","unresolved":false,"context_lines":[{"line_number":581,"context_line":"            value\u003d\u0027required\u0027)"},{"line_number":582,"context_line":""},{"line_number":583,"context_line":"        self.assertEqual(2, len(aggs))"},{"line_number":584,"context_line":"        self.assertItemsEqual([2, 3], [a.id for a in aggs])"},{"line_number":585,"context_line":""},{"line_number":586,"context_line":"    def test_get_non_matching_by_metadata_keys_from_db_assertion(self):"},{"line_number":587,"context_line":"        self.assertRaises("}],"source_content_type":"text/x-python","patch_set":2,"id":"7faddb67_3b86cb15","line":584,"in_reply_to":"7faddb67_ec38b1a0","updated":"2019-08-07 12:55:49.000000000","message":"1. Done\n2. Added new Test Cases named \u0027test_matching_aggregates_multiple_keys\u0027 and \u0027test_get_non_matching_aggregates_multiple_keys\u0027\n3. Added new Test Case named \u0027test_get_non_matching_by_metadata_keys_empty_keys\u0027","commit_id":"380645fbec6026e0cb9f2ead54602d1f0eb82193"},{"author":{"_account_id":7634,"name":"Takashi Natsume","email":"takanattie@gmail.com","username":"natsumet"},"change_message_id":"a96c07ce6febeb68d671afa9a7af6e6a5cdabe8e","unresolved":false,"context_lines":[{"line_number":661,"context_line":""},{"line_number":662,"context_line":"        self.assertEqual(4, len(aggs))"},{"line_number":663,"context_line":"        self.assertItemsEqual([1, 2, 3, 4], [a.id for a in aggs])"},{"line_number":664,"context_line":""},{"line_number":665,"context_line":"    def test_get_non_matching_by_metadata_keys_from_db_assertion(self):"},{"line_number":666,"context_line":"        self.assertRaises("},{"line_number":667,"context_line":"            AssertionError,"}],"source_content_type":"text/x-python","patch_set":4,"id":"7faddb67_408ccb7e","line":664,"updated":"2019-08-09 04:57:28.000000000","message":"nit: It would be better to add a test case that keys and key_prefix are specified but value is not specified.","commit_id":"373541c2b15006d944641f744618a8473f0574ec"},{"author":{"_account_id":27302,"name":"Shilpa Devharakar","email":"shilpa.devharakar@nttdata.com","username":"shilpa.devharakar"},"change_message_id":"e9ff24f659f4437622b02a89531e80f5dd28d2b9","unresolved":false,"context_lines":[{"line_number":661,"context_line":""},{"line_number":662,"context_line":"        self.assertEqual(4, len(aggs))"},{"line_number":663,"context_line":"        self.assertItemsEqual([1, 2, 3, 4], [a.id for a in aggs])"},{"line_number":664,"context_line":""},{"line_number":665,"context_line":"    def test_get_non_matching_by_metadata_keys_from_db_assertion(self):"},{"line_number":666,"context_line":"        self.assertRaises("},{"line_number":667,"context_line":"            AssertionError,"}],"source_content_type":"text/x-python","patch_set":4,"id":"7faddb67_b477f09f","line":664,"in_reply_to":"7faddb67_408ccb7e","updated":"2019-08-10 09:23:52.000000000","message":"Done, added \u0027test_get_non_matching_by_metadata_keys_with_no_value\u0027","commit_id":"373541c2b15006d944641f744618a8473f0574ec"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"2423f0a152811386548a2d9f53482e7115147a04","unresolved":false,"context_lines":[{"line_number":604,"context_line":""},{"line_number":605,"context_line":"        agg \u003d aggregate_obj.Aggregate.get_by_id(self.context, 4)"},{"line_number":606,"context_line":"        agg.update_metadata({\u0027trait:HW_CPU_X86_MMX\u0027: \u0027required\u0027,"},{"line_number":607,"context_line":"                             \u0027trait:HW_CPU_X86_SGX\u0027: \u0027just_for_marking\u0027})"},{"line_number":608,"context_line":""},{"line_number":609,"context_line":"        aggs \u003d aggregate_obj.AggregateList.get_non_matching_by_metadata_keys("},{"line_number":610,"context_line":"            self.context, [\u0027trait:HW_CPU_X86_MMX\u0027, \u0027trait:HW_CPU_X86_SGX\u0027],"}],"source_content_type":"text/x-python","patch_set":6,"id":"7faddb67_7dd60656","line":607,"updated":"2019-08-14 10:53:40.000000000","message":"Would the following aggregate be returned?\n\n    agg \u003d aggregate_obj.Aggregate.get_by_id(self.context, 5)\n    agg.update_metadata({\u0027trait:HW_CPU_X86_MMX\u0027: \u0027required\u0027,\n                         \u0027trait:HW_CPU_X86_SGX\u0027: \u0027just_for_marking\u0027\n                         \u0027trait:HW_CPU_X86_SSE\u0027: \u0027required\u0027})","commit_id":"9185eda446dfb14f8b671b13317c8befbac89027"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"c71384b5a3c741453cfba62bf76d44c87c61952b","unresolved":false,"context_lines":[{"line_number":604,"context_line":""},{"line_number":605,"context_line":"        agg \u003d aggregate_obj.Aggregate.get_by_id(self.context, 4)"},{"line_number":606,"context_line":"        agg.update_metadata({\u0027trait:HW_CPU_X86_MMX\u0027: \u0027required\u0027,"},{"line_number":607,"context_line":"                             \u0027trait:HW_CPU_X86_SGX\u0027: \u0027just_for_marking\u0027})"},{"line_number":608,"context_line":""},{"line_number":609,"context_line":"        aggs \u003d aggregate_obj.AggregateList.get_non_matching_by_metadata_keys("},{"line_number":610,"context_line":"            self.context, [\u0027trait:HW_CPU_X86_MMX\u0027, \u0027trait:HW_CPU_X86_SGX\u0027],"}],"source_content_type":"text/x-python","patch_set":6,"id":"7faddb67_e55fb0e2","line":607,"in_reply_to":"7faddb67_7dd60656","updated":"2019-08-14 19:38:15.000000000","message":"Yes, because that last one\n- has the right prefix\n- has the right value\n- isn\u0027t in the ignore list\n\n(Confirmed this locally)","commit_id":"9185eda446dfb14f8b671b13317c8befbac89027"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"6af766ef2ec1b676726b0cd75bd6ccf567b22042","unresolved":false,"context_lines":[{"line_number":604,"context_line":""},{"line_number":605,"context_line":"        agg \u003d aggregate_obj.Aggregate.get_by_id(self.context, 4)"},{"line_number":606,"context_line":"        agg.update_metadata({\u0027trait:HW_CPU_X86_MMX\u0027: \u0027required\u0027,"},{"line_number":607,"context_line":"                             \u0027trait:HW_CPU_X86_SGX\u0027: \u0027just_for_marking\u0027})"},{"line_number":608,"context_line":""},{"line_number":609,"context_line":"        aggs \u003d aggregate_obj.AggregateList.get_non_matching_by_metadata_keys("},{"line_number":610,"context_line":"            self.context, [\u0027trait:HW_CPU_X86_MMX\u0027, \u0027trait:HW_CPU_X86_SGX\u0027],"}],"source_content_type":"text/x-python","patch_set":6,"id":"7faddb67_bca39c9a","line":607,"in_reply_to":"7faddb67_e55fb0e2","updated":"2019-08-22 09:35:37.000000000","message":"Awesome :)","commit_id":"9185eda446dfb14f8b671b13317c8befbac89027"}]}
