)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"bb373f27c19f968c6fa201b438d5926c5bb1ae7f","unresolved":false,"context_lines":[{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Extend comparator support for project list by tags"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"This changes allows operator to use the keystoneclient to filter"},{"line_number":10,"context_line":"projects with tags using comparators including \u0027startswith\u0027,"},{"line_number":11,"context_line":"\u0027endswith\u0027, and \u0027contains\u0027."},{"line_number":12,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":8,"id":"7f515b1d_afde0b3b","line":9,"range":{"start_line":9,"start_character":40,"end_line":9,"end_character":54},"updated":"2017-09-29 17:48:38.000000000","message":"This bit here is confusing since it seems like we\u0027re using keystoneclient in this patch. This patch enables more clients than just python-keystoneclient. Any client writing to keystone HTTP API will be able to consume these new operators.","commit_id":"a4b243b1449403925597267856c44d262e0939dd"}],"keystone/common/controller.py":[{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"bb373f27c19f968c6fa201b438d5926c5bb1ae7f","unresolved":false,"context_lines":[{"line_number":411,"context_line":"        # limited the output if it found there were filters it was unable to"},{"line_number":412,"context_line":"        # handle."},{"line_number":413,"context_line":""},{"line_number":414,"context_line":"        # Bypass filter_by_attributes if a tag filter search was done"},{"line_number":415,"context_line":"        if hints is not None and not any(\u0027tag\u0027 in key[\u0027name\u0027] for"},{"line_number":416,"context_line":"                                         key in hints.filters):"},{"line_number":417,"context_line":"            refs \u003d cls.filter_by_attributes(refs, hints)"}],"source_content_type":"text/x-python","patch_set":8,"id":"7f515b1d_4fef97e8","line":414,"range":{"start_line":414,"start_character":10,"end_line":414,"end_character":69},"updated":"2017-09-29 17:48:38.000000000","message":"This comment describes what can be derived from reading the code. This is a great opportunity to share *why* this logic is important to us (e.g. do we do this because using tags and filters is redundant? do they not work well when used together? etc..)","commit_id":"a4b243b1449403925597267856c44d262e0939dd"}],"keystone/resource/controllers.py":[{"author":{"_account_id":23659,"name":"Jaewoo Park","email":"jaewoopark91@gmail.com","username":"aselius"},"change_message_id":"0c71b86ffb3e6859b75b0fd736cd4e622e2958f1","unresolved":false,"context_lines":[{"line_number":249,"context_line":"        super(ProjectV3, self).__init__()"},{"line_number":250,"context_line":"        self.get_member_from_driver \u003d self.resource_api.get_project"},{"line_number":251,"context_line":""},{"line_number":252,"context_line":"    @classmethod"},{"line_number":253,"context_line":"    def filter_by_attributes(cls, refs, hints):"},{"line_number":254,"context_line":"        \"\"\"Filter a list of references by filter values.\"\"\""},{"line_number":255,"context_line":"        def _attr_match(ref_attr, val_attr):"}],"source_content_type":"text/x-python","patch_set":1,"id":"9f436f4f_b17a61b7","line":252,"updated":"2017-08-21 21:15:19.000000000","message":"having trouble finding how to edit a method inside of a class method. There has to be a better way than overriding the base projectv3 class\u0027s filter method with the same + new code.","commit_id":"883e72013f129ea4273c5e68af9dedebb19c2823"},{"author":{"_account_id":23659,"name":"Jaewoo Park","email":"jaewoopark91@gmail.com","username":"aselius"},"change_message_id":"0c71b86ffb3e6859b75b0fd736cd4e622e2958f1","unresolved":false,"context_lines":[{"line_number":305,"context_line":"            # This is for when you pass in tags and comparators like contains, startswith, endswith. Tags cannot"},{"line_number":306,"context_line":"            # use the current comparator logic in _inexact_attr_match off the box because of the key in ref, and"},{"line_number":307,"context_line":"            # the logic is slightly different because it is a list not a string."},{"line_number":308,"context_line":"            if \u0027tag\u0027 in key:"},{"line_number":309,"context_line":"                filter_value \u003d filter[\u0027value\u0027]"},{"line_number":310,"context_line":"                target_value \u003d ref[\u0027tags\u0027]"},{"line_number":311,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"9f436f4f_d1aa8517","line":308,"updated":"2017-08-21 21:15:19.000000000","message":"3 nested ifs are too complex. Need a better way to do this","commit_id":"883e72013f129ea4273c5e68af9dedebb19c2823"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"bb373f27c19f968c6fa201b438d5926c5bb1ae7f","unresolved":false,"context_lines":[{"line_number":285,"context_line":"        return ProjectV3.wrap_collection(request.context_dict,"},{"line_number":286,"context_line":"                                         refs, hints\u003dhints)"},{"line_number":287,"context_line":""},{"line_number":288,"context_line":"    def _filter_by_tags(self, refs, hints):"},{"line_number":289,"context_line":"        def _tags_any(matches, target_value):"},{"line_number":290,"context_line":"            return any(matches)"},{"line_number":291,"context_line":""}],"source_content_type":"text/x-python","patch_set":8,"id":"7f515b1d_0fa4ffb8","line":288,"range":{"start_line":288,"start_character":8,"end_line":288,"end_character":23},"updated":"2017-09-29 17:48:38.000000000","message":"This looks like it conflicts with the implementation for \u0027tags\u0027, \u0027tags-any\u0027, \u0027not-tags\u0027, and \u0027not-tags-any\u0027 in https://review.openstack.org/#/c/499728/4/keystone/resource/controllers.py\n\nMaybe this can be done with a little reuse so that it\u0027s easier to add support for new operators.","commit_id":"a4b243b1449403925597267856c44d262e0939dd"},{"author":{"_account_id":23659,"name":"Jaewoo Park","email":"jaewoopark91@gmail.com","username":"aselius"},"change_message_id":"b92ffbdb4af47ab8180dd91fcf7e3cd8b23b71d5","unresolved":false,"context_lines":[{"line_number":285,"context_line":"        return ProjectV3.wrap_collection(request.context_dict,"},{"line_number":286,"context_line":"                                         refs, hints\u003dhints)"},{"line_number":287,"context_line":""},{"line_number":288,"context_line":"    def _filter_by_tags(self, refs, hints):"},{"line_number":289,"context_line":"        def _tags_any(matches, target_value):"},{"line_number":290,"context_line":"            return any(matches)"},{"line_number":291,"context_line":""}],"source_content_type":"text/x-python","patch_set":8,"id":"7f515b1d_5c0cba93","line":288,"range":{"start_line":288,"start_character":8,"end_line":288,"end_character":23},"in_reply_to":"7f515b1d_0fa4ffb8","updated":"2017-10-03 22:50:52.000000000","message":"This kept on bugging me on the back of my mind as I wrote this and the tags code simultaneously.. I couldn\u0027t think of an elegant way to combine them together.. but let me think about this again.","commit_id":"a4b243b1449403925597267856c44d262e0939dd"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"bb373f27c19f968c6fa201b438d5926c5bb1ae7f","unresolved":false,"context_lines":[{"line_number":334,"context_line":"        # Only reassign refs if a specific tag filter is applied"},{"line_number":335,"context_line":"        for f in hints.filters:"},{"line_number":336,"context_line":"            if f[\u0027comparator\u0027] is not \u0027equals\u0027 and \u0027tag\u0027 in f[\u0027name\u0027]:"},{"line_number":337,"context_line":"                return [r for r in refs if _found_match("},{"line_number":338,"context_line":"                    f, r)]"},{"line_number":339,"context_line":"        # If it isnt a special case, return given refs parameter"},{"line_number":340,"context_line":"        return refs"},{"line_number":341,"context_line":""}],"source_content_type":"text/x-python","patch_set":8,"id":"7f515b1d_6fa01391","line":338,"range":{"start_line":337,"start_character":16,"end_line":338,"end_character":26},"updated":"2017-09-29 17:48:38.000000000","message":"nit: This looks like it can all fit on a single line.","commit_id":"a4b243b1449403925597267856c44d262e0939dd"}],"keystone/tests/unit/test_v3_resource.py":[{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"bb373f27c19f968c6fa201b438d5926c5bb1ae7f","unresolved":false,"context_lines":[{"line_number":715,"context_line":"    def test_list_projects_with_startswith_comparator_tags(self):"},{"line_number":716,"context_line":"        \"\"\"Call ``GET /projects?tags__startswith\u003d{tags}\u0027\u0027.\"\"\""},{"line_number":717,"context_line":"        project1, tags1 \u003d self._create_project_and_tags(tag_size\u003d1)"},{"line_number":718,"context_line":"        project2, tags2 \u003d self._create_project_and_tags(tag_size\u003d2)"},{"line_number":719,"context_line":"        partial_tag_string \u003d ["},{"line_number":720,"context_line":"            tags1[i][0:len(tags1[0]) / 2] for i in range(len(tags1))]"},{"line_number":721,"context_line":"        resp \u003d self.get(\u0027/projects?tags__startswith\u003d%(values)s\u0027 % {"}],"source_content_type":"text/x-python","patch_set":8,"id":"7f515b1d_0f099f94","line":718,"range":{"start_line":718,"start_character":18,"end_line":718,"end_character":23},"updated":"2017-09-29 17:48:38.000000000","message":"it doesn\u0027t look like this is used s/tags2/_/","commit_id":"a4b243b1449403925597267856c44d262e0939dd"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"bb373f27c19f968c6fa201b438d5926c5bb1ae7f","unresolved":false,"context_lines":[{"line_number":716,"context_line":"        \"\"\"Call ``GET /projects?tags__startswith\u003d{tags}\u0027\u0027.\"\"\""},{"line_number":717,"context_line":"        project1, tags1 \u003d self._create_project_and_tags(tag_size\u003d1)"},{"line_number":718,"context_line":"        project2, tags2 \u003d self._create_project_and_tags(tag_size\u003d2)"},{"line_number":719,"context_line":"        partial_tag_string \u003d ["},{"line_number":720,"context_line":"            tags1[i][0:len(tags1[0]) / 2] for i in range(len(tags1))]"},{"line_number":721,"context_line":"        resp \u003d self.get(\u0027/projects?tags__startswith\u003d%(values)s\u0027 % {"},{"line_number":722,"context_line":"            \u0027values\u0027: partial_tag_string[0]})"},{"line_number":723,"context_line":"        self.assertValidProjectListResponse(resp)"}],"source_content_type":"text/x-python","patch_set":8,"id":"7f515b1d_8f58ef87","line":720,"range":{"start_line":719,"start_character":8,"end_line":720,"end_character":69},"updated":"2017-09-29 17:48:38.000000000","message":"This looks like it builds a list of something (tags, partial tag strings?), but we only ever use the first element of this list on line 722.\n\nIf we only want a piece of a single tag, can\u0027t that be done more simply with:\n\n  # partial_limit is the character limit of the tag we want.\n  # E.g. partial_limit \u003d 2 would return \u0027bl\u0027 for tag \u0027blue\u0027\n  partial_limit \u003d 2\n  partial_tag_string \u003d tags[0][0:partial_limit]\n  # ... do stuff with partial_tag_string\n\nOr are we trying to test every substring of a tag? If that\u0027s the case, I think we\u0027re missing a loop?","commit_id":"a4b243b1449403925597267856c44d262e0939dd"},{"author":{"_account_id":23659,"name":"Jaewoo Park","email":"jaewoopark91@gmail.com","username":"aselius"},"change_message_id":"b92ffbdb4af47ab8180dd91fcf7e3cd8b23b71d5","unresolved":false,"context_lines":[{"line_number":716,"context_line":"        \"\"\"Call ``GET /projects?tags__startswith\u003d{tags}\u0027\u0027.\"\"\""},{"line_number":717,"context_line":"        project1, tags1 \u003d self._create_project_and_tags(tag_size\u003d1)"},{"line_number":718,"context_line":"        project2, tags2 \u003d self._create_project_and_tags(tag_size\u003d2)"},{"line_number":719,"context_line":"        partial_tag_string \u003d ["},{"line_number":720,"context_line":"            tags1[i][0:len(tags1[0]) / 2] for i in range(len(tags1))]"},{"line_number":721,"context_line":"        resp \u003d self.get(\u0027/projects?tags__startswith\u003d%(values)s\u0027 % {"},{"line_number":722,"context_line":"            \u0027values\u0027: partial_tag_string[0]})"},{"line_number":723,"context_line":"        self.assertValidProjectListResponse(resp)"}],"source_content_type":"text/x-python","patch_set":8,"id":"7f515b1d_1ca1a296","line":720,"range":{"start_line":719,"start_character":8,"end_line":720,"end_character":69},"in_reply_to":"7f515b1d_8f58ef87","updated":"2017-10-03 22:50:52.000000000","message":"The former. You are right. There are much simpler ways than having a for loop.","commit_id":"a4b243b1449403925597267856c44d262e0939dd"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"bb373f27c19f968c6fa201b438d5926c5bb1ae7f","unresolved":false,"context_lines":[{"line_number":746,"context_line":"        project2, tags2 \u003d self._create_project_and_tags(tag_size\u003d2)"},{"line_number":747,"context_line":"        partial_tag_string \u003d ["},{"line_number":748,"context_line":"            tags1[i][0:len(tags1[0]) / 2] for i in range(len(tags1))]"},{"line_number":749,"context_line":"        resp \u003d self.get(\u0027/projects?not-tags__startswith\u003d%(values)s\u0027 % {"},{"line_number":750,"context_line":"            \u0027values\u0027: partial_tag_string[0]})"},{"line_number":751,"context_line":"        self.assertValidProjectListResponse(resp)"},{"line_number":752,"context_line":"        project_ids \u003d []"}],"source_content_type":"text/x-python","patch_set":8,"id":"7f515b1d_cfcf0727","line":749,"range":{"start_line":749,"start_character":35,"end_line":749,"end_character":55},"updated":"2017-09-29 17:48:38.000000000","message":"is this defined in the API WG standards somewhere?","commit_id":"a4b243b1449403925597267856c44d262e0939dd"}]}
