)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":6484,"name":"Feilong Wang","email":"hustemb@gmail.com","username":"flwang"},"change_message_id":"327b3ae5f7b177150e9e652a3d4951f1dcd30cbd","unresolved":false,"context_lines":[{"line_number":4,"context_line":"Commit:     Steve Lewis \u003cstevelle@gmail.com\u003e"},{"line_number":5,"context_line":"CommitDate: 2015-06-30 17:54:03 -0700"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Add registry support for new v2 API image filters"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Provide support in the Glance registry for querying the image list for"},{"line_number":10,"context_line":"created_at and updated at times using guidance from the API Working"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"ba3cc151_acbaa5be","line":7,"updated":"2015-07-01 04:48:17.000000000","message":"I think \u0027registry support\u0027 is confusing me. The title is look looking add a registry process like v1. Would you mind reword it? Am I missing anything? Cheers.","commit_id":"50ad55a198f58720ba888029f6e1a2ea4235721c"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"1e42d17a994d49637aea239c9948e1c70b668902","unresolved":false,"context_lines":[{"line_number":4,"context_line":"Commit:     Steve Lewis \u003cstevelle@gmail.com\u003e"},{"line_number":5,"context_line":"CommitDate: 2015-06-30 17:54:03 -0700"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Add registry support for new v2 API image filters"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Provide support in the Glance registry for querying the image list for"},{"line_number":10,"context_line":"created_at and updated at times using guidance from the API Working"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"ba3cc151_fcccbe6b","line":7,"updated":"2015-07-01 15:06:41.000000000","message":"Perhaps, \"Support new v2 API image filters in the registry\"?","commit_id":"50ad55a198f58720ba888029f6e1a2ea4235721c"},{"author":{"_account_id":12807,"name":"Steve Lewis (stevelle)","email":"stevelle@gmail.com","username":"stevelle"},"change_message_id":"c137a6f48968abf5394f361e7f7f096b37504620","unresolved":false,"context_lines":[{"line_number":4,"context_line":"Commit:     Steve Lewis \u003cstevelle@gmail.com\u003e"},{"line_number":5,"context_line":"CommitDate: 2015-06-30 17:54:03 -0700"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Add registry support for new v2 API image filters"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Provide support in the Glance registry for querying the image list for"},{"line_number":10,"context_line":"created_at and updated at times using guidance from the API Working"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"ba3cc151_6e39c6f1","line":7,"in_reply_to":"ba3cc151_fcccbe6b","updated":"2015-07-01 22:05:06.000000000","message":"Done","commit_id":"50ad55a198f58720ba888029f6e1a2ea4235721c"},{"author":{"_account_id":455,"name":"Stuart McLaren","email":"stuart.mclaren@hpe.com","username":"stuart-mclaren"},"change_message_id":"dfd40c0b45c9b4f35cfa29856d0b7317efbe3143","unresolved":false,"context_lines":[{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Support new v2 API image filters"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Provide support in the Glance registry for querying the image list for"},{"line_number":10,"context_line":"created_at and updated_at times using guidance from the API Working"},{"line_number":11,"context_line":"Group recommendations for filtering."},{"line_number":12,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":10,"id":"ba8a016a_18b9f0e9","line":9,"updated":"2015-11-16 18:06:30.000000000","message":"\u003cpedantic\u003e\nIs it more the db layer than the registry? (Even if the v2 registry is turned off we\u0027ll get the new behaviour.)\n\u003c/pedantic\u003e","commit_id":"557599e1236ed303da0196c207a1567dfcd0d159"},{"author":{"_account_id":6159,"name":"Flavio Percoco Premoli","display_name":"flaper87","email":"flavio.percoco@flyrlabs.com","username":"flaper87"},"change_message_id":"55c77c67969d7caef10db84ca1ed18686cdc4c79","unresolved":false,"context_lines":[{"line_number":11,"context_line":"Group recommendations for filtering. Filtering is applied at the DB"},{"line_number":12,"context_line":"layer."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"DocImpact"},{"line_number":15,"context_line":"ApiImpact"},{"line_number":16,"context_line":"Change-Id: Ie94295bb82779ec17ab773928c71ae4a9ee8fbcc"},{"line_number":17,"context_line":"Implements bp: v2-additional-filtering"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":11,"id":"ba8a016a_2cca77a2","line":14,"updated":"2015-11-16 19:13:03.000000000","message":"Can you tag this change with `Priority-for: Mitaka` ?","commit_id":"5907ee48e174553ee9d58c65a7e59793072fdb3b"}],"glance/common/utils.py":[{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"1e42d17a994d49637aea239c9948e1c70b668902","unresolved":false,"context_lines":[{"line_number":73,"context_line":""},{"line_number":74,"context_line":"GLANCE_TEST_SOCKET_FD_STR \u003d \u0027GLANCE_TEST_SOCKET_FD\u0027"},{"line_number":75,"context_line":""},{"line_number":76,"context_line":"FILTER_OPERATORS \u003d [\u0027gt:\u0027, \u0027gte:\u0027, \u0027lt:\u0027, \u0027lte:\u0027, \u0027neq:\u0027, \u0027eq:\u0027]"},{"line_number":77,"context_line":""},{"line_number":78,"context_line":""},{"line_number":79,"context_line":"def chunkreadable(iter, chunk_size\u003d65536):"}],"source_content_type":"text/x-python","patch_set":2,"id":"ba3cc151_bcc2b632","line":76,"updated":"2015-07-01 15:06:41.000000000","message":"Can we make this a frozenset?","commit_id":"50ad55a198f58720ba888029f6e1a2ea4235721c"},{"author":{"_account_id":12807,"name":"Steve Lewis (stevelle)","email":"stevelle@gmail.com","username":"stevelle"},"change_message_id":"c137a6f48968abf5394f361e7f7f096b37504620","unresolved":false,"context_lines":[{"line_number":73,"context_line":""},{"line_number":74,"context_line":"GLANCE_TEST_SOCKET_FD_STR \u003d \u0027GLANCE_TEST_SOCKET_FD\u0027"},{"line_number":75,"context_line":""},{"line_number":76,"context_line":"FILTER_OPERATORS \u003d [\u0027gt:\u0027, \u0027gte:\u0027, \u0027lt:\u0027, \u0027lte:\u0027, \u0027neq:\u0027, \u0027eq:\u0027]"},{"line_number":77,"context_line":""},{"line_number":78,"context_line":""},{"line_number":79,"context_line":"def chunkreadable(iter, chunk_size\u003d65536):"}],"source_content_type":"text/x-python","patch_set":2,"id":"ba3cc151_ce1fb26a","line":76,"in_reply_to":"ba3cc151_bcc2b632","updated":"2015-07-01 22:05:06.000000000","message":"eliminated this instead","commit_id":"50ad55a198f58720ba888029f6e1a2ea4235721c"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"1e42d17a994d49637aea239c9948e1c70b668902","unresolved":false,"context_lines":[{"line_number":774,"context_line":"    :param expression: the expression to parse"},{"line_number":775,"context_line":""},{"line_number":776,"context_line":"    :returns a tuple (operator, value) parsed from expression"},{"line_number":777,"context_line":"    \"\"\""},{"line_number":778,"context_line":"    for op in FILTER_OPERATORS:"},{"line_number":779,"context_line":"        if expression.startswith(op):"},{"line_number":780,"context_line":"            # NOTE stevelle decoding escaped values may be needed later"}],"source_content_type":"text/x-python","patch_set":2,"id":"ba3cc151_dcbf7aa8","line":777,"updated":"2015-07-01 15:06:41.000000000","message":"Stupid question: Is it possible for \u0027:\u0027 to be in value portion of a filter query? If not, then why not do\n\n    split \u003d expression.split(\u0027:\u0027, 1)  # Split at most once\n    try:\n        op, value \u003d split\n    except ValueError:   # Too few values to unpack\n        op \u003d \u0027eq\u0027\n        value \u003d split[0]\n\n    if op is not in FILTER_OPERATORS:\n        op \u003d \u0027eq\u0027\n    return op, value\n\nAlso, this makes me wonder, if this currently receives a string like\n\n    get:something\n\nWe would then return (\u0027eq:\u0027, \u0027get:something\u0027)\n\nPerhaps that is more correct since it will cause a hard failure instead of only matching on equality. Thoughts?\n\nAlso note, that if you adapt any of my code, the operator will lose the trailing \u0027:\u0027 which may cause problems if you don\u0027t refactor the rest of this patch.","commit_id":"50ad55a198f58720ba888029f6e1a2ea4235721c"},{"author":{"_account_id":12807,"name":"Steve Lewis (stevelle)","email":"stevelle@gmail.com","username":"stevelle"},"change_message_id":"c137a6f48968abf5394f361e7f7f096b37504620","unresolved":false,"context_lines":[{"line_number":774,"context_line":"    :param expression: the expression to parse"},{"line_number":775,"context_line":""},{"line_number":776,"context_line":"    :returns a tuple (operator, value) parsed from expression"},{"line_number":777,"context_line":"    \"\"\""},{"line_number":778,"context_line":"    for op in FILTER_OPERATORS:"},{"line_number":779,"context_line":"        if expression.startswith(op):"},{"line_number":780,"context_line":"            # NOTE stevelle decoding escaped values may be needed later"}],"source_content_type":"text/x-python","patch_set":2,"id":"ba3cc151_0ca283fd","line":777,"in_reply_to":"ba3cc151_8bd447bd","updated":"2015-07-01 22:05:06.000000000","message":"After tinkering I think I am happy using expression.split with try/except. The test expectations and match constants were all changed to eliminate the \u0027:\u0027 in operators and the FILTER_OPERATORS was eliminated. \n\nThe end result is likely easier to read.","commit_id":"50ad55a198f58720ba888029f6e1a2ea4235721c"},{"author":{"_account_id":12807,"name":"Steve Lewis (stevelle)","email":"stevelle@gmail.com","username":"stevelle"},"change_message_id":"d63fce35d6a98ee55aeb461b952415daa485ec00","unresolved":false,"context_lines":[{"line_number":774,"context_line":"    :param expression: the expression to parse"},{"line_number":775,"context_line":""},{"line_number":776,"context_line":"    :returns a tuple (operator, value) parsed from expression"},{"line_number":777,"context_line":"    \"\"\""},{"line_number":778,"context_line":"    for op in FILTER_OPERATORS:"},{"line_number":779,"context_line":"        if expression.startswith(op):"},{"line_number":780,"context_line":"            # NOTE stevelle decoding escaped values may be needed later"}],"source_content_type":"text/x-python","patch_set":2,"id":"ba3cc151_8bd447bd","line":777,"in_reply_to":"ba3cc151_dcbf7aa8","updated":"2015-07-01 16:25:47.000000000","message":"I wanted to be somewhat generous in what is accepted but we should generate a hard failure, rather than do the wrong thing, for  \n\n   not:something","commit_id":"50ad55a198f58720ba888029f6e1a2ea4235721c"},{"author":{"_account_id":9303,"name":"Abhishek Kekane","email":"akekane@redhat.com","username":"abhishekkekane"},"change_message_id":"5fa2365084c8816cf094f3b3840506131372dc7e","unresolved":false,"context_lines":[{"line_number":810,"context_line":"        return value !\u003d threshold"},{"line_number":811,"context_line":"    if operator \u003d\u003d \u0027eq:\u0027:"},{"line_number":812,"context_line":"        return value \u003d\u003d threshold"},{"line_number":813,"context_line":""},{"line_number":814,"context_line":"    msg \u003d _(\"Unable to filter on a unknown operator.\")"},{"line_number":815,"context_line":"    raise exception.InvalidFilterOperatorValue(msg)"}],"source_content_type":"text/x-python","patch_set":2,"id":"ba3cc151_6a1a2b7f","line":813,"updated":"2015-07-01 13:00:37.000000000","message":"IMO you can optimize this code\n\n1.\nChange FILTER_OPERATORS to {\u0027gt:\u0027: \u0027\u003e\u0027, \u0027gte:\u0027  \u0027\u003e\u003d\u0027, \u0027lt:\u0027 \u0027\u003c\u0027, \u0027lte:\u0027 \u0027\u003c\u003d\u0027, \u0027neq:\u0027 \u0027!\u003d\u0027, \u0027eq:\u0027 \u0027\u003d\u003d\u0027}\n\n2.\nif operator in FILTER_OPERATORS:\n\treturn eval(\"%s %s %s\" % (value, FILTER_OPERATORS[operator], threshold))\n\nmsg \u003d _(\"Unable to filter on a unknown operator.\")\n\nraise exception.InvalidFilterOperatorValue(msg)","commit_id":"50ad55a198f58720ba888029f6e1a2ea4235721c"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"1e42d17a994d49637aea239c9948e1c70b668902","unresolved":false,"context_lines":[{"line_number":810,"context_line":"        return value !\u003d threshold"},{"line_number":811,"context_line":"    if operator \u003d\u003d \u0027eq:\u0027:"},{"line_number":812,"context_line":"        return value \u003d\u003d threshold"},{"line_number":813,"context_line":""},{"line_number":814,"context_line":"    msg \u003d _(\"Unable to filter on a unknown operator.\")"},{"line_number":815,"context_line":"    raise exception.InvalidFilterOperatorValue(msg)"}],"source_content_type":"text/x-python","patch_set":2,"id":"ba3cc151_7cdf4e0d","line":813,"updated":"2015-07-01 15:06:41.000000000","message":"No Abhishek. Let\u0027s please not use eval ever. If we want to optimize this (which I\u0027m not convinced we are actually optimizing just shortening) we should use the operator module, e.g.,\n\n    import operator\n    # ...\n    FILTER_OPERATORS \u003d {\u0027gt:\u0027: operator.gt, \u0027gte:\u0027: operator.ge, ...}\n    def NONEXISTENT_OPERATOR(*args):\n        msg \u003d _(\"...\")\n        raise exception.InvalidFilterOperatorValue(msg)\n\n    def evaluate_filter_op(value, operator, threshold):\n        \"\"\"...\"\"\"\n        operator_func \u003d FILTER_OPERATORS.get(operator, NONEXISTENT_OPERATOR)\n        return operator_func(value, threshold)\n\nBut I don\u0027t think this makes it much clearer. The above is fairly explicit and will be faster than using eval or the operator module. \n\nTo be clear, if people insist on making this code harder to read and shorter for the sake of it being shorter, please do use the operator module and do not use eval. I will -2 the patch if you do use eval. If a person is clever enough they could inject something knowing that we use eval. It will be a security hole.","commit_id":"50ad55a198f58720ba888029f6e1a2ea4235721c"},{"author":{"_account_id":9303,"name":"Abhishek Kekane","email":"akekane@redhat.com","username":"abhishekkekane"},"change_message_id":"84c5d586dd13797e0e3ee86def3cfc437aec71d6","unresolved":false,"context_lines":[{"line_number":810,"context_line":"        return value !\u003d threshold"},{"line_number":811,"context_line":"    if operator \u003d\u003d \u0027eq:\u0027:"},{"line_number":812,"context_line":"        return value \u003d\u003d threshold"},{"line_number":813,"context_line":""},{"line_number":814,"context_line":"    msg \u003d _(\"Unable to filter on a unknown operator.\")"},{"line_number":815,"context_line":"    raise exception.InvalidFilterOperatorValue(msg)"}],"source_content_type":"text/x-python","patch_set":2,"id":"ba3cc151_abbcabdc","line":813,"in_reply_to":"ba3cc151_7cdf4e0d","updated":"2015-07-01 16:08:39.000000000","message":"Hi Ian,\n\nI agree, thank you for pointing it out.","commit_id":"50ad55a198f58720ba888029f6e1a2ea4235721c"},{"author":{"_account_id":12807,"name":"Steve Lewis (stevelle)","email":"stevelle@gmail.com","username":"stevelle"},"change_message_id":"d63fce35d6a98ee55aeb461b952415daa485ec00","unresolved":false,"context_lines":[{"line_number":810,"context_line":"        return value !\u003d threshold"},{"line_number":811,"context_line":"    if operator \u003d\u003d \u0027eq:\u0027:"},{"line_number":812,"context_line":"        return value \u003d\u003d threshold"},{"line_number":813,"context_line":""},{"line_number":814,"context_line":"    msg \u003d _(\"Unable to filter on a unknown operator.\")"},{"line_number":815,"context_line":"    raise exception.InvalidFilterOperatorValue(msg)"}],"source_content_type":"text/x-python","patch_set":2,"id":"ba3cc151_8838cd3e","line":813,"in_reply_to":"ba3cc151_7cdf4e0d","updated":"2015-07-01 16:25:47.000000000","message":"I looked at the operator module but it doesn\u0027t seem like it would make the code much easier to read or less error prone.\n\nI would prefer to preserve the explicit implementation barring more feedback against.","commit_id":"50ad55a198f58720ba888029f6e1a2ea4235721c"},{"author":{"_account_id":11391,"name":"Mikhail Fedosin","email":"mfedosin@redhat.com","username":"fedosinme"},"change_message_id":"5e49c17e4ab99135855a46e640dc3486fda0f50f","unresolved":false,"context_lines":[{"line_number":663,"context_line":"    split \u003d expression.split(\u0027:\u0027, 1)  # Split at most once"},{"line_number":664,"context_line":"    try:"},{"line_number":665,"context_line":"        op, value \u003d split"},{"line_number":666,"context_line":"    except ValueError:  # Too few values to unpack"},{"line_number":667,"context_line":"        op \u003d \u0027eq\u0027"},{"line_number":668,"context_line":"        value \u003d expression"},{"line_number":669,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"da85f559_ca8cd537","line":666,"updated":"2015-11-13 17:46:22.000000000","message":"ValueError may confuse users. I suggest you a better solution that I used in Glare: https://github.com/openstack/glance/blob/master/glance/api/v3/artifacts.py#L702-L709\n\nlike:\n\nleft, sep, right \u003d raw_value.strip().partition(\u0027:\u0027)\n            \nif not sep:\n\n    op \u003d \"eq\"\n\n    value \u003d left.strip()\n\nelse:\n\n    op \u003d left.strip().upper()\n\n    value \u003d right.strip()","commit_id":"8ac65716ceadfa8e6c73010f798526dd69a55025"},{"author":{"_account_id":12807,"name":"Steve Lewis (stevelle)","email":"stevelle@gmail.com","username":"stevelle"},"change_message_id":"cd18a3e0de5826833e221c022e1ddaeba13e8af2","unresolved":false,"context_lines":[{"line_number":663,"context_line":"    split \u003d expression.split(\u0027:\u0027, 1)  # Split at most once"},{"line_number":664,"context_line":"    try:"},{"line_number":665,"context_line":"        op, value \u003d split"},{"line_number":666,"context_line":"    except ValueError:  # Too few values to unpack"},{"line_number":667,"context_line":"        op \u003d \u0027eq\u0027"},{"line_number":668,"context_line":"        value \u003d expression"},{"line_number":669,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"da85f559_a7e8a717","line":666,"in_reply_to":"da85f559_ca8cd537","updated":"2015-11-13 19:38:04.000000000","message":"Use of strip() from artifacts seems unnecessary as these should come from a query string only, but otherwise I like the use of partition.\n\nNote: users wouldn\u0027t see the ValueError as it was handled here.","commit_id":"8ac65716ceadfa8e6c73010f798526dd69a55025"},{"author":{"_account_id":11391,"name":"Mikhail Fedosin","email":"mfedosin@redhat.com","username":"fedosinme"},"change_message_id":"5e49c17e4ab99135855a46e640dc3486fda0f50f","unresolved":false,"context_lines":[{"line_number":696,"context_line":"    if operator \u003d\u003d \u0027neq\u0027:"},{"line_number":697,"context_line":"        return value !\u003d threshold"},{"line_number":698,"context_line":"    if operator \u003d\u003d \u0027eq\u0027:"},{"line_number":699,"context_line":"        return value \u003d\u003d threshold"},{"line_number":700,"context_line":""},{"line_number":701,"context_line":"    msg \u003d _(\"Unable to filter on a unknown operator.\")"},{"line_number":702,"context_line":"    raise exception.InvalidFilterOperatorValue(msg)"}],"source_content_type":"text/x-python","patch_set":7,"id":"da85f559_15d8c21c","line":699,"updated":"2015-11-13 17:46:22.000000000","message":"what about rewriting this as:\n\nimport operator\n\ntry:\n\n    op \u003d getattr(operator, op_value)\n\n    return op(value, threshold)\n\nexcept AttributeError:\n\n    msg \u003d _(\"Unable to filter on a unknown operator.\")\n\n    raise exception.InvalidFilterOperatorValue(msg)","commit_id":"8ac65716ceadfa8e6c73010f798526dd69a55025"},{"author":{"_account_id":12807,"name":"Steve Lewis (stevelle)","email":"stevelle@gmail.com","username":"stevelle"},"change_message_id":"cd18a3e0de5826833e221c022e1ddaeba13e8af2","unresolved":false,"context_lines":[{"line_number":696,"context_line":"    if operator \u003d\u003d \u0027neq\u0027:"},{"line_number":697,"context_line":"        return value !\u003d threshold"},{"line_number":698,"context_line":"    if operator \u003d\u003d \u0027eq\u0027:"},{"line_number":699,"context_line":"        return value \u003d\u003d threshold"},{"line_number":700,"context_line":""},{"line_number":701,"context_line":"    msg \u003d _(\"Unable to filter on a unknown operator.\")"},{"line_number":702,"context_line":"    raise exception.InvalidFilterOperatorValue(msg)"}],"source_content_type":"text/x-python","patch_set":7,"id":"da85f559_071df3bc","line":699,"in_reply_to":"da85f559_15d8c21c","updated":"2015-11-13 19:38:04.000000000","message":"I looked at operator initially and was inclined against it for a few reasons:\n\n- future support of other comparators (e.g. \u0027in\u0027) from the api-wg guidance does not have an equivalent in Lib/operator.py\n\n- operator mismatch (e.g. \u0027ne\u0027 in Lib/operator.py vs \u0027neq\u0027 in api-wg guidance) requires more complex mapping which gets us closer to the above implementation anyway\n\n- while this is more verbose it is simple and obvious in implementation and always returns a boolean value, there are no opportunities for rich comparisons to cause unforeseen bugs.\n\nNote: This topic was first brought up in patch set 2 but I did not list these concerns completely there.","commit_id":"8ac65716ceadfa8e6c73010f798526dd69a55025"},{"author":{"_account_id":5202,"name":"Erno Kuvaja","email":"jokke@usr.fi","username":"jokke"},"change_message_id":"0411a075d7c8e14b2a4afc04b76187c08b37f1be","unresolved":false,"context_lines":[{"line_number":652,"context_line":""},{"line_number":653,"context_line":"def split_filter_op(expression):"},{"line_number":654,"context_line":"    \"\"\""},{"line_number":655,"context_line":"    Split operator from value in an expression."},{"line_number":656,"context_line":"    Designed for use on a comparative-filtering query field."},{"line_number":657,"context_line":"    When no operator is found, default to an equality comparison."},{"line_number":658,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"ba8a016a_89aa7c18","line":655,"updated":"2015-11-16 17:02:23.000000000","message":"Please change this to:\n\n\"\"\"Split operator from value in an expression.\n\n...\n\"\"\"\n\nAs per http://docs.openstack.org/developer/hacking/#docstrings","commit_id":"250738211447490ecbe1f2fd21f6697636c0f66a"},{"author":{"_account_id":12807,"name":"Steve Lewis (stevelle)","email":"stevelle@gmail.com","username":"stevelle"},"change_message_id":"25f8096a88f02be9993494ff3d0f1951dc8d6bd4","unresolved":false,"context_lines":[{"line_number":652,"context_line":""},{"line_number":653,"context_line":"def split_filter_op(expression):"},{"line_number":654,"context_line":"    \"\"\""},{"line_number":655,"context_line":"    Split operator from value in an expression."},{"line_number":656,"context_line":"    Designed for use on a comparative-filtering query field."},{"line_number":657,"context_line":"    When no operator is found, default to an equality comparison."},{"line_number":658,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"ba8a016a_7f9346fb","line":655,"in_reply_to":"ba8a016a_89aa7c18","updated":"2015-11-16 17:16:34.000000000","message":"Done","commit_id":"250738211447490ecbe1f2fd21f6697636c0f66a"},{"author":{"_account_id":5202,"name":"Erno Kuvaja","email":"jokke@usr.fi","username":"jokke"},"change_message_id":"0411a075d7c8e14b2a4afc04b76187c08b37f1be","unresolved":false,"context_lines":[{"line_number":674,"context_line":""},{"line_number":675,"context_line":"def evaluate_filter_op(value, operator, threshold):"},{"line_number":676,"context_line":"    \"\"\""},{"line_number":677,"context_line":"    Evaluate a comparison operator."},{"line_number":678,"context_line":"    Designed for use on a comparative-filtering query field."},{"line_number":679,"context_line":""},{"line_number":680,"context_line":"    :param value: evaluated against the operator, as left side of expression"}],"source_content_type":"text/x-python","patch_set":9,"id":"ba8a016a_c95e4445","line":677,"updated":"2015-11-16 17:02:23.000000000","message":"Ditto","commit_id":"250738211447490ecbe1f2fd21f6697636c0f66a"},{"author":{"_account_id":12807,"name":"Steve Lewis (stevelle)","email":"stevelle@gmail.com","username":"stevelle"},"change_message_id":"25f8096a88f02be9993494ff3d0f1951dc8d6bd4","unresolved":false,"context_lines":[{"line_number":674,"context_line":""},{"line_number":675,"context_line":"def evaluate_filter_op(value, operator, threshold):"},{"line_number":676,"context_line":"    \"\"\""},{"line_number":677,"context_line":"    Evaluate a comparison operator."},{"line_number":678,"context_line":"    Designed for use on a comparative-filtering query field."},{"line_number":679,"context_line":""},{"line_number":680,"context_line":"    :param value: evaluated against the operator, as left side of expression"}],"source_content_type":"text/x-python","patch_set":9,"id":"ba8a016a_3fbcde6b","line":677,"in_reply_to":"ba8a016a_c95e4445","updated":"2015-11-16 17:16:34.000000000","message":"Done","commit_id":"250738211447490ecbe1f2fd21f6697636c0f66a"},{"author":{"_account_id":5202,"name":"Erno Kuvaja","email":"jokke@usr.fi","username":"jokke"},"change_message_id":"0411a075d7c8e14b2a4afc04b76187c08b37f1be","unresolved":false,"context_lines":[{"line_number":696,"context_line":"        return value \u003c\u003d threshold"},{"line_number":697,"context_line":"    if operator \u003d\u003d \u0027neq\u0027:"},{"line_number":698,"context_line":"        return value !\u003d threshold"},{"line_number":699,"context_line":"    if operator \u003d\u003d \u0027eq\u0027:"},{"line_number":700,"context_line":"        return value \u003d\u003d threshold"},{"line_number":701,"context_line":""},{"line_number":702,"context_line":"    msg \u003d _(\"Unable to filter on a unknown operator.\")"}],"source_content_type":"text/x-python","patch_set":9,"id":"ba8a016a_8c77ea01","line":699,"updated":"2015-11-16 17:02:23.000000000","message":"Please use elif ... elif ... elif ... else here, not that it makes this any more efficient, but it\u0027s more consistent, pythonic and clear for the reader what\u0027s going on at the first glance.","commit_id":"250738211447490ecbe1f2fd21f6697636c0f66a"},{"author":{"_account_id":12807,"name":"Steve Lewis (stevelle)","email":"stevelle@gmail.com","username":"stevelle"},"change_message_id":"25f8096a88f02be9993494ff3d0f1951dc8d6bd4","unresolved":false,"context_lines":[{"line_number":696,"context_line":"        return value \u003c\u003d threshold"},{"line_number":697,"context_line":"    if operator \u003d\u003d \u0027neq\u0027:"},{"line_number":698,"context_line":"        return value !\u003d threshold"},{"line_number":699,"context_line":"    if operator \u003d\u003d \u0027eq\u0027:"},{"line_number":700,"context_line":"        return value \u003d\u003d threshold"},{"line_number":701,"context_line":""},{"line_number":702,"context_line":"    msg \u003d _(\"Unable to filter on a unknown operator.\")"}],"source_content_type":"text/x-python","patch_set":9,"id":"ba8a016a_5fc1a2e3","line":699,"in_reply_to":"ba8a016a_8c77ea01","updated":"2015-11-16 17:16:34.000000000","message":"Done","commit_id":"250738211447490ecbe1f2fd21f6697636c0f66a"},{"author":{"_account_id":17976,"name":"Drew Varner","email":"avarner@linux.vnet.ibm.com","username":"avarner"},"change_message_id":"daceb8fadcc6dfbb12ae498866718eba463ffbf1","unresolved":false,"context_lines":[{"line_number":662,"context_line":"    left, sep, right \u003d expression.partition(\u0027:\u0027)"},{"line_number":663,"context_line":"    if sep:"},{"line_number":664,"context_line":"        op \u003d left"},{"line_number":665,"context_line":"        value \u003d right"},{"line_number":666,"context_line":"    else:"},{"line_number":667,"context_line":"        op \u003d \u0027eq\u0027  # default operator when no separator"},{"line_number":668,"context_line":"        value \u003d left"}],"source_content_type":"text/x-python","patch_set":12,"id":"ba8a016a_4c881be8","line":665,"updated":"2015-11-16 19:28:12.000000000","message":"I suggest replacing \"value\" with \"threshold\", for consistency with evaluate_filter_op.","commit_id":"dfa2ef3cf503f923fec97cbf2a22dd80d07090fc"},{"author":{"_account_id":12807,"name":"Steve Lewis (stevelle)","email":"stevelle@gmail.com","username":"stevelle"},"change_message_id":"879409b4ea41b0f920593f3242412865d8110297","unresolved":false,"context_lines":[{"line_number":662,"context_line":"    left, sep, right \u003d expression.partition(\u0027:\u0027)"},{"line_number":663,"context_line":"    if sep:"},{"line_number":664,"context_line":"        op \u003d left"},{"line_number":665,"context_line":"        value \u003d right"},{"line_number":666,"context_line":"    else:"},{"line_number":667,"context_line":"        op \u003d \u0027eq\u0027  # default operator when no separator"},{"line_number":668,"context_line":"        value \u003d left"}],"source_content_type":"text/x-python","patch_set":12,"id":"ba8a016a_722b74ec","line":665,"in_reply_to":"ba8a016a_4c881be8","updated":"2015-11-16 19:56:21.000000000","message":"Not a bad idea. \n\nIt isn\u0027t a threshold yet, and naming it so does provide implicit coupling with the following method but that may not be bad as they are conceptually and practically related.\n\nI\u0027ll bank this one as something to revise in any future change set.","commit_id":"dfa2ef3cf503f923fec97cbf2a22dd80d07090fc"}],"glance/db/sqlalchemy/api.py":[{"author":{"_account_id":11391,"name":"Mikhail Fedosin","email":"mfedosin@redhat.com","username":"fedosinme"},"change_message_id":"5e49c17e4ab99135855a46e640dc3486fda0f50f","unresolved":false,"context_lines":[{"line_number":52,"context_line":"from glance.db.sqlalchemy import models"},{"line_number":53,"context_line":"from glance import i18n"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"BASE \u003d models.BASE"},{"line_number":57,"context_line":"sa_logger \u003d None"},{"line_number":58,"context_line":"LOG \u003d logging.getLogger(__name__)"}],"source_content_type":"text/x-python","patch_set":7,"id":"da85f559_eadaf916","line":55,"updated":"2015-11-13 17:46:22.000000000","message":"Unnecessary line :)","commit_id":"8ac65716ceadfa8e6c73010f798526dd69a55025"},{"author":{"_account_id":12807,"name":"Steve Lewis (stevelle)","email":"stevelle@gmail.com","username":"stevelle"},"change_message_id":"cd18a3e0de5826833e221c022e1ddaeba13e8af2","unresolved":false,"context_lines":[{"line_number":52,"context_line":"from glance.db.sqlalchemy import models"},{"line_number":53,"context_line":"from glance import i18n"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"BASE \u003d models.BASE"},{"line_number":57,"context_line":"sa_logger \u003d None"},{"line_number":58,"context_line":"LOG \u003d logging.getLogger(__name__)"}],"source_content_type":"text/x-python","patch_set":7,"id":"da85f559_84ec8190","line":55,"in_reply_to":"da85f559_eadaf916","updated":"2015-11-13 19:38:04.000000000","message":"Done","commit_id":"8ac65716ceadfa8e6c73010f798526dd69a55025"}],"glance/db/sqlalchemy/migrate_repo/versions/042_add_image_created_updated_idx.py":[{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"1e42d17a994d49637aea239c9948e1c70b668902","unresolved":false,"context_lines":[{"line_number":29,"context_line":"    updated_index.create(migrate_engine)"},{"line_number":30,"context_line":""},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"def downgrade(migrate_engine):"},{"line_number":33,"context_line":"    meta \u003d MetaData()"},{"line_number":34,"context_line":"    meta.bind \u003d migrate_engine"},{"line_number":35,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"ba3cc151_1ccac24e","line":32,"updated":"2015-07-01 15:06:41.000000000","message":"We no longer do downgrades in OpenSTack. This is unnecessary.","commit_id":"50ad55a198f58720ba888029f6e1a2ea4235721c"},{"author":{"_account_id":12807,"name":"Steve Lewis (stevelle)","email":"stevelle@gmail.com","username":"stevelle"},"change_message_id":"c137a6f48968abf5394f361e7f7f096b37504620","unresolved":false,"context_lines":[{"line_number":29,"context_line":"    updated_index.create(migrate_engine)"},{"line_number":30,"context_line":""},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"def downgrade(migrate_engine):"},{"line_number":33,"context_line":"    meta \u003d MetaData()"},{"line_number":34,"context_line":"    meta.bind \u003d migrate_engine"},{"line_number":35,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"ba3cc151_6cd1d6f9","line":32,"in_reply_to":"ba3cc151_1ccac24e","updated":"2015-07-01 22:05:06.000000000","message":"Done","commit_id":"50ad55a198f58720ba888029f6e1a2ea4235721c"}],"glance/tests/functional/db/base.py":[{"author":{"_account_id":17976,"name":"Drew Varner","email":"avarner@linux.vnet.ibm.com","username":"avarner"},"change_message_id":"daceb8fadcc6dfbb12ae498866718eba463ffbf1","unresolved":false,"context_lines":[{"line_number":488,"context_line":"                                           filters\u003d{\u0027poo\u0027: \u0027bear\u0027})"},{"line_number":489,"context_line":"        self.assertEqual(0, len(images))"},{"line_number":490,"context_line":""},{"line_number":491,"context_line":"    def test_image_get_all_with_filter_comparative_created_at(self):"},{"line_number":492,"context_line":"        anchor \u003d timeutils.isotime(self.fixtures[0][\u0027created_at\u0027])"},{"line_number":493,"context_line":"        time_expr \u003d \u0027lt:\u0027 + anchor"},{"line_number":494,"context_line":""}],"source_content_type":"text/x-python","patch_set":12,"id":"ba8a016a_8f87d560","line":491,"updated":"2015-11-16 19:28:12.000000000","message":"I\u0027m a bit new here - where do these two functions get called from?","commit_id":"dfa2ef3cf503f923fec97cbf2a22dd80d07090fc"},{"author":{"_account_id":12807,"name":"Steve Lewis (stevelle)","email":"stevelle@gmail.com","username":"stevelle"},"change_message_id":"879409b4ea41b0f920593f3242412865d8110297","unresolved":false,"context_lines":[{"line_number":488,"context_line":"                                           filters\u003d{\u0027poo\u0027: \u0027bear\u0027})"},{"line_number":489,"context_line":"        self.assertEqual(0, len(images))"},{"line_number":490,"context_line":""},{"line_number":491,"context_line":"    def test_image_get_all_with_filter_comparative_created_at(self):"},{"line_number":492,"context_line":"        anchor \u003d timeutils.isotime(self.fixtures[0][\u0027created_at\u0027])"},{"line_number":493,"context_line":"        time_expr \u003d \u0027lt:\u0027 + anchor"},{"line_number":494,"context_line":""}],"source_content_type":"text/x-python","patch_set":12,"id":"ba8a016a_92d85855","line":491,"in_reply_to":"ba8a016a_8f87d560","updated":"2015-11-16 19:56:21.000000000","message":"The functional db tests are exercised for each storage engine, and the trail to see this is a bit convoluted. Follow the source through the superclass and you can sort it out maybe. Another way to see this in practice it to break the assert in a test here and observe the results from running the tests.","commit_id":"dfa2ef3cf503f923fec97cbf2a22dd80d07090fc"}],"glance/tests/functional/v2/test_images.py":[{"author":{"_account_id":455,"name":"Stuart McLaren","email":"stuart.mclaren@hpe.com","username":"stuart-mclaren"},"change_message_id":"dfd40c0b45c9b4f35cfa29856d0b7317efbe3143","unresolved":false,"context_lines":[{"line_number":2459,"context_line":"        response \u003d requests.get(path, headers\u003dself._headers())"},{"line_number":2460,"context_line":"        self.assertEqual(200, response.status_code)"},{"line_number":2461,"context_line":"        body \u003d jsonutils.loads(response.text)"},{"line_number":2462,"context_line":"        self.assertEqual(0, len(body[\u0027images\u0027]))"},{"line_number":2463,"context_line":"        self.assertEqual(url_template % images[0][\u0027created_at\u0027],"},{"line_number":2464,"context_line":"                         urllib.parse.unquote(body[\u0027first\u0027]))"},{"line_number":2465,"context_line":""}],"source_content_type":"text/x-python","patch_set":10,"id":"ba8a016a_fdd09ecb","line":2462,"updated":"2015-11-16 18:06:30.000000000","message":"Would it be worth additionally doing:\n\npath \u003d self._url(url_template % images[6][\u0027created_at\u0027])\n\nto test the other extreme? It might make it harder for someone to break this functionality in the future :-)\n\n(same below)\n\nnit: I\u0027d be happy to see the test re-named to reflect the new filters (I\u0027m not sure what test_images_container means?)","commit_id":"557599e1236ed303da0196c207a1567dfcd0d159"},{"author":{"_account_id":12807,"name":"Steve Lewis (stevelle)","email":"stevelle@gmail.com","username":"stevelle"},"change_message_id":"aa33a8ad1072169a8587b80a728bb4602c7f3275","unresolved":false,"context_lines":[{"line_number":2459,"context_line":"        response \u003d requests.get(path, headers\u003dself._headers())"},{"line_number":2460,"context_line":"        self.assertEqual(200, response.status_code)"},{"line_number":2461,"context_line":"        body \u003d jsonutils.loads(response.text)"},{"line_number":2462,"context_line":"        self.assertEqual(0, len(body[\u0027images\u0027]))"},{"line_number":2463,"context_line":"        self.assertEqual(url_template % images[0][\u0027created_at\u0027],"},{"line_number":2464,"context_line":"                         urllib.parse.unquote(body[\u0027first\u0027]))"},{"line_number":2465,"context_line":""}],"source_content_type":"text/x-python","patch_set":10,"id":"ba8a016a_eefd466f","line":2462,"in_reply_to":"ba8a016a_fdd09ecb","updated":"2015-11-16 19:05:43.000000000","message":"I originally tried images[6] but that actually made the tests more fragile, sadly.\n\nI can\u0027t ensure either that in the test fixtures the images have different time stamps due to the low precision of the recorded timestamps. \n\nGiven that, I could not ensure that splitting the images was possible without introducing a sleep during the test. The unit tests should test the boundaries, so I focused these functional tests on ensuring that the filter was being exercised through the API.","commit_id":"557599e1236ed303da0196c207a1567dfcd0d159"},{"author":{"_account_id":17976,"name":"Drew Varner","email":"avarner@linux.vnet.ibm.com","username":"avarner"},"change_message_id":"aa376300600e49fb96cf1464c4120d925a281224","unresolved":false,"context_lines":[{"line_number":2465,"context_line":""},{"line_number":2466,"context_line":"        # Image list filters by updated_at time"},{"line_number":2467,"context_line":"        url_template \u003d \u0027/v2/images?updated_at\u003dlt:%s\u0027"},{"line_number":2468,"context_line":"        path \u003d self._url(url_template % images[2][\u0027updated_at\u0027])"},{"line_number":2469,"context_line":"        response \u003d requests.get(path, headers\u003dself._headers())"},{"line_number":2470,"context_line":"        self.assertEqual(200, response.status_code)"},{"line_number":2471,"context_line":"        body \u003d jsonutils.loads(response.text)"}],"source_content_type":"text/x-python","patch_set":13,"id":"ba8a016a_0640aaa4","line":2468,"updated":"2015-11-16 21:58:13.000000000","message":"Is images[2] guaranteed to have the lowest values of updated_at ? I can see how this should usually work in practice, since they\u0027d all have exactly the same updated_at, but if I insert a 2 second sleep on line 2442, I expect this would fail.","commit_id":"976106dd321ef28b437e3b22a63585b5715ab5fc"},{"author":{"_account_id":12807,"name":"Steve Lewis (stevelle)","email":"stevelle@gmail.com","username":"stevelle"},"change_message_id":"4183f6b72cc94b782d2c81af9a9e536f0737a71e","unresolved":false,"context_lines":[{"line_number":2465,"context_line":""},{"line_number":2466,"context_line":"        # Image list filters by updated_at time"},{"line_number":2467,"context_line":"        url_template \u003d \u0027/v2/images?updated_at\u003dlt:%s\u0027"},{"line_number":2468,"context_line":"        path \u003d self._url(url_template % images[2][\u0027updated_at\u0027])"},{"line_number":2469,"context_line":"        response \u003d requests.get(path, headers\u003dself._headers())"},{"line_number":2470,"context_line":"        self.assertEqual(200, response.status_code)"},{"line_number":2471,"context_line":"        body \u003d jsonutils.loads(response.text)"}],"source_content_type":"text/x-python","patch_set":13,"id":"ba8a016a_b31d5bbf","line":2468,"in_reply_to":"ba8a016a_0640aaa4","updated":"2015-11-16 22:14:20.000000000","message":"The only guarantee I would suggest is that images[2] has an updated_at which is \u003c\u003d that of images[3] and \u003e\u003d that of images[1].  \n\nI haven\u0027t experienced failures from using images[2] and it seems possible that a failure could occur in the assert on 2472 but I have not experienced one yet.\n\nI guess I would like to ask if the test should use images[0] also, or the assert should test len(body[\u0027image\u0027]) \u003c\u003d 3","commit_id":"976106dd321ef28b437e3b22a63585b5715ab5fc"},{"author":{"_account_id":17976,"name":"Drew Varner","email":"avarner@linux.vnet.ibm.com","username":"avarner"},"change_message_id":"c564ec9161bc8a33db84d38a08c4b55a596f7f6c","unresolved":false,"context_lines":[{"line_number":2465,"context_line":""},{"line_number":2466,"context_line":"        # Image list filters by updated_at time"},{"line_number":2467,"context_line":"        url_template \u003d \u0027/v2/images?updated_at\u003dlt:%s\u0027"},{"line_number":2468,"context_line":"        path \u003d self._url(url_template % images[2][\u0027updated_at\u0027])"},{"line_number":2469,"context_line":"        response \u003d requests.get(path, headers\u003dself._headers())"},{"line_number":2470,"context_line":"        self.assertEqual(200, response.status_code)"},{"line_number":2471,"context_line":"        body \u003d jsonutils.loads(response.text)"}],"source_content_type":"text/x-python","patch_set":13,"id":"ba8a016a_c9b0728e","line":2468,"in_reply_to":"ba8a016a_b31d5bbf","updated":"2015-11-16 22:52:52.000000000","message":"\u003c\u003d 2 should be fine.","commit_id":"976106dd321ef28b437e3b22a63585b5715ab5fc"},{"author":{"_account_id":12807,"name":"Steve Lewis (stevelle)","email":"stevelle@gmail.com","username":"stevelle"},"change_message_id":"1a4a83b87195accbc1e2e365406af50ce36ed520","unresolved":false,"context_lines":[{"line_number":2465,"context_line":""},{"line_number":2466,"context_line":"        # Image list filters by updated_at time"},{"line_number":2467,"context_line":"        url_template \u003d \u0027/v2/images?updated_at\u003dlt:%s\u0027"},{"line_number":2468,"context_line":"        path \u003d self._url(url_template % images[2][\u0027updated_at\u0027])"},{"line_number":2469,"context_line":"        response \u003d requests.get(path, headers\u003dself._headers())"},{"line_number":2470,"context_line":"        self.assertEqual(200, response.status_code)"},{"line_number":2471,"context_line":"        body \u003d jsonutils.loads(response.text)"}],"source_content_type":"text/x-python","patch_set":13,"id":"ba8a016a_e7b0fd8d","line":2468,"in_reply_to":"ba8a016a_c9b0728e","updated":"2015-11-16 23:49:50.000000000","message":"Using assertGreaterEqual since we are on 2.7.\n\nShould have said 3 instead of 2 for length limit.","commit_id":"976106dd321ef28b437e3b22a63585b5715ab5fc"}]}
