)]}'
{"neutron/db/common_db_mixin.py":[{"author":{"_account_id":261,"name":"Salvatore Orlando","email":"salv.orlando@gmail.com","username":"salvatore-orlando"},"change_message_id":"c7ede146c4bdf4f8dafce007ededb942d6a6b055","unresolved":false,"context_lines":[{"line_number":91,"context_line":"            if query_hook:"},{"line_number":92,"context_line":"                query \u003d query_hook(context, model, query)"},{"line_number":93,"context_line":""},{"line_number":94,"context_line":"            filter_hook \u003d hooks.get(\u0027filter\u0027)"},{"line_number":95,"context_line":"            if isinstance(filter_hook, basestring):"},{"line_number":96,"context_line":"                filter_hook \u003d getattr(self, filter_hook, None)"},{"line_number":97,"context_line":"            if filter_hook:"}],"source_content_type":"text/x-python","patch_set":3,"id":"1abeadc6_a8aaa86e","side":"PARENT","line":94,"updated":"2014-08-28 11:59:58.000000000","message":"Merging the query hook and the filter hook can be ok for me, even if it makes the system a little bit less flexible.\n\nthe reasons for keeping them split was that the condition building hook was meant to build the condition incrementally.","commit_id":"921611cf7a9e1d8626d4ade0cfb911dcb13018f4"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"bf6202921f36acad1ae5bad01676b804bab5e0a1","unresolved":false,"context_lines":[{"line_number":91,"context_line":"            if query_hook:"},{"line_number":92,"context_line":"                query \u003d query_hook(context, model, query)"},{"line_number":93,"context_line":""},{"line_number":94,"context_line":"            filter_hook \u003d hooks.get(\u0027filter\u0027)"},{"line_number":95,"context_line":"            if isinstance(filter_hook, basestring):"},{"line_number":96,"context_line":"                filter_hook \u003d getattr(self, filter_hook, None)"},{"line_number":97,"context_line":"            if filter_hook:"}],"source_content_type":"text/x-python","patch_set":3,"id":"1abeadc6_a74bb629","side":"PARENT","line":94,"in_reply_to":"1abeadc6_a8aaa86e","updated":"2014-08-28 12:39:43.000000000","message":"That\u0027s the part I was missing, and now the motivation is much clearer for me.","commit_id":"921611cf7a9e1d8626d4ade0cfb911dcb13018f4"},{"author":{"_account_id":261,"name":"Salvatore Orlando","email":"salv.orlando@gmail.com","username":"salvatore-orlando"},"change_message_id":"c7ede146c4bdf4f8dafce007ededb942d6a6b055","unresolved":false,"context_lines":[{"line_number":95,"context_line":""},{"line_number":96,"context_line":"        # Execute query hooks registered from mixins and plugins"},{"line_number":97,"context_line":"        for hooks in self._model_query_hooks.get(model, {}).values():"},{"line_number":98,"context_line":"            query_hook \u003d hooks.get(\u0027post_query\u0027)"},{"line_number":99,"context_line":"            if isinstance(query_hook, basestring):"},{"line_number":100,"context_line":"                query_hook \u003d getattr(self, query_hook, None)"},{"line_number":101,"context_line":"            if query_hook:"}],"source_content_type":"text/x-python","patch_set":3,"id":"1abeadc6_48291436","line":98,"updated":"2014-08-28 11:59:58.000000000","message":"Why did you choose post_query?\nThe semantics where:\n\n- query: used to build the query for retrieving an object, doing stuff like joins \n- filter: used to build conditions on model queries\n- result_filter: used to build conditions on list queries","commit_id":"84abd52ae748653fbd3a86576a7460ea16842ff0"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"bf6202921f36acad1ae5bad01676b804bab5e0a1","unresolved":false,"context_lines":[{"line_number":95,"context_line":""},{"line_number":96,"context_line":"        # Execute query hooks registered from mixins and plugins"},{"line_number":97,"context_line":"        for hooks in self._model_query_hooks.get(model, {}).values():"},{"line_number":98,"context_line":"            query_hook \u003d hooks.get(\u0027post_query\u0027)"},{"line_number":99,"context_line":"            if isinstance(query_hook, basestring):"},{"line_number":100,"context_line":"                query_hook \u003d getattr(self, query_hook, None)"},{"line_number":101,"context_line":"            if query_hook:"}],"source_content_type":"text/x-python","patch_set":3,"id":"1abeadc6_e313e3b5","line":98,"in_reply_to":"1abeadc6_48291436","updated":"2014-08-28 12:39:43.000000000","message":"The motives behind my naming scheme was to be as clear as possible as to when each hook is ran.\n\nBasically in the first few iterations I tried to do with my code, I ended up with 4 hooks:\n- query_hook\n- filter_hook (which is the part which dealt with \"building conditions\", which was named \"filters\" and not \"conditions\")\n- pre_filter\n- post_filter\n\nI am fine with reverting back to query_hook and renaming filter_hook to conditions_hook :)","commit_id":"84abd52ae748653fbd3a86576a7460ea16842ff0"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"a0653e62beb4ef7ec8b132a044e01ad913404120","unresolved":false,"context_lines":[{"line_number":95,"context_line":""},{"line_number":96,"context_line":"        # Execute query hooks registered from mixins and plugins"},{"line_number":97,"context_line":"        for hooks in self._model_query_hooks.get(model, {}).values():"},{"line_number":98,"context_line":"            query_hook \u003d hooks.get(\u0027post_query\u0027)"},{"line_number":99,"context_line":"            if isinstance(query_hook, basestring):"},{"line_number":100,"context_line":"                query_hook \u003d getattr(self, query_hook, None)"},{"line_number":101,"context_line":"            if query_hook:"}],"source_content_type":"text/x-python","patch_set":3,"id":"fa98f980_2f2c7e4a","line":98,"in_reply_to":"1abeadc6_e313e3b5","updated":"2014-08-31 14:42:48.000000000","message":"Done","commit_id":"84abd52ae748653fbd3a86576a7460ea16842ff0"},{"author":{"_account_id":261,"name":"Salvatore Orlando","email":"salv.orlando@gmail.com","username":"salvatore-orlando"},"change_message_id":"c7ede146c4bdf4f8dafce007ededb942d6a6b055","unresolved":false,"context_lines":[{"line_number":141,"context_line":"    def _apply_filters_to_query(self, context, model, query, filters):"},{"line_number":142,"context_line":"        if filters:"},{"line_number":143,"context_line":"            query \u003d self._execute_hooks(\u0027pre_filter\u0027, model, context,"},{"line_number":144,"context_line":"                                        query, filters)"},{"line_number":145,"context_line":"            for key, value in filters.iteritems():"},{"line_number":146,"context_line":"                column \u003d getattr(model, key, None)"},{"line_number":147,"context_line":"                if column:"}],"source_content_type":"text/x-python","patch_set":3,"id":"1abeadc6_488674dc","line":144,"updated":"2014-08-28 11:59:58.000000000","message":"The pre-filter hook is probably the one you\u0027re looking to add, is that correct?\n\nThat\u0027s because you don\u0027t just need to filter but also do a join, so it\u0027s not just about adding conditions, but about tweaking the model query.\n\nOne way of solving the problem would be to do everything in the model query hook, but the downside of this is that it will do a query more complex than what is needed in any case whereas we only need it for list operations.\n\nI\u0027d still try and find a way, if possible to merge  these pre and post filter hooks.","commit_id":"84abd52ae748653fbd3a86576a7460ea16842ff0"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"bf6202921f36acad1ae5bad01676b804bab5e0a1","unresolved":false,"context_lines":[{"line_number":141,"context_line":"    def _apply_filters_to_query(self, context, model, query, filters):"},{"line_number":142,"context_line":"        if filters:"},{"line_number":143,"context_line":"            query \u003d self._execute_hooks(\u0027pre_filter\u0027, model, context,"},{"line_number":144,"context_line":"                                        query, filters)"},{"line_number":145,"context_line":"            for key, value in filters.iteritems():"},{"line_number":146,"context_line":"                column \u003d getattr(model, key, None)"},{"line_number":147,"context_line":"                if column:"}],"source_content_type":"text/x-python","patch_set":3,"id":"1abeadc6_27a246ae","line":144,"in_reply_to":"1abeadc6_488674dc","updated":"2014-08-28 12:39:43.000000000","message":"Yes, the pre-filter hook is the new hook I\u0027m looking to add, and yes, it\u0027s not about filtering out results (that can be done in the post-filter hook) but about tweaking the query.\n\nLooking at the 4 hooks I\u0027m proposing, we\u0027ll have:\n- query_hook: used to build the query for retrieving an object, doing stuff like joins\n- conditions_hook: used to build conditions on model queries incrementally\n- pre_filter: used to tweak/manipulate the list queries according to user-entered filters\n- post_filter: used to filter out results according to user-entered filters\n\nIn my eyes, there is no avoiding using a pre_filter to do this. Currently there is no way to tweak/manipulate the query *according to the user\u0027s input*. Sure, joins can be done in the query_hook but that hook is unaware of user inputs, and joining all the Ports to all the IPAllocations for every query is way overkill, since we only need it on specific user queries.","commit_id":"84abd52ae748653fbd3a86576a7460ea16842ff0"},{"author":{"_account_id":261,"name":"Salvatore Orlando","email":"salv.orlando@gmail.com","username":"salvatore-orlando"},"change_message_id":"f8fd4ca41c9eda4a9942f51f176286d5207d41a9","unresolved":false,"context_lines":[{"line_number":38,"context_line":"    @classmethod"},{"line_number":39,"context_line":"    def register_model_query_hook(cls, model, name,"},{"line_number":40,"context_line":"                                  query_hook, conditions_hook,"},{"line_number":41,"context_line":"                                  pre_filter_hook, post_filter_hook):"},{"line_number":42,"context_line":"        \"\"\"Register a hook to be invoked when a query is executed."},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"        Add the hooks to the _model_query_hooks dict. Models are the keys"}],"source_content_type":"text/x-python","patch_set":4,"id":"fa98f980_1ac43691","line":41,"updated":"2014-09-01 15:26:58.000000000","message":"let\u0027s consider using keyword parameters now.\nThis will spare us calling this routine with a lot of None parameters.\n\nThe reason for which these parameters are positional is historical. It goes back to an initial version where there were only query and condition hooks and they were both mandatory.","commit_id":"85c4f35ed62ddbd78c2affee67e845b041276649"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"8f71d9757d75ee7468eb3465e8e770c5ece4fe71","unresolved":false,"context_lines":[{"line_number":38,"context_line":"    @classmethod"},{"line_number":39,"context_line":"    def register_model_query_hook(cls, model, name,"},{"line_number":40,"context_line":"                                  query_hook, conditions_hook,"},{"line_number":41,"context_line":"                                  pre_filter_hook, post_filter_hook):"},{"line_number":42,"context_line":"        \"\"\"Register a hook to be invoked when a query is executed."},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"        Add the hooks to the _model_query_hooks dict. Models are the keys"}],"source_content_type":"text/x-python","patch_set":4,"id":"fa98f980_4e2fb2f6","line":41,"in_reply_to":"fa98f980_1ac43691","updated":"2014-09-02 08:39:52.000000000","message":"I actually like this one a lot - Done :)","commit_id":"85c4f35ed62ddbd78c2affee67e845b041276649"},{"author":{"_account_id":261,"name":"Salvatore Orlando","email":"salv.orlando@gmail.com","username":"salvatore-orlando"},"change_message_id":"f8fd4ca41c9eda4a9942f51f176286d5207d41a9","unresolved":false,"context_lines":[{"line_number":152,"context_line":""},{"line_number":153,"context_line":"    def _apply_filters_to_query(self, context, model, query, filters):"},{"line_number":154,"context_line":"        if filters:"},{"line_number":155,"context_line":"            query \u003d self._execute_hooks(\u0027pre_filter_hook\u0027, model, context,"},{"line_number":156,"context_line":"                                        query, filters)"},{"line_number":157,"context_line":"            for key, value in filters.iteritems():"},{"line_number":158,"context_line":"                column \u003d getattr(model, key, None)"}],"source_content_type":"text/x-python","patch_set":4,"id":"fa98f980_5f06b021","line":155,"updated":"2014-09-01 15:26:58.000000000","message":"I would suggest start using constants for hooks types to make it easier for consumers.","commit_id":"85c4f35ed62ddbd78c2affee67e845b041276649"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"8f71d9757d75ee7468eb3465e8e770c5ece4fe71","unresolved":false,"context_lines":[{"line_number":152,"context_line":""},{"line_number":153,"context_line":"    def _apply_filters_to_query(self, context, model, query, filters):"},{"line_number":154,"context_line":"        if filters:"},{"line_number":155,"context_line":"            query \u003d self._execute_hooks(\u0027pre_filter_hook\u0027, model, context,"},{"line_number":156,"context_line":"                                        query, filters)"},{"line_number":157,"context_line":"            for key, value in filters.iteritems():"},{"line_number":158,"context_line":"                column \u003d getattr(model, key, None)"}],"source_content_type":"text/x-python","patch_set":4,"id":"fa98f980_8e399a43","line":155,"in_reply_to":"fa98f980_5f06b021","updated":"2014-09-02 08:39:52.000000000","message":"Done","commit_id":"85c4f35ed62ddbd78c2affee67e845b041276649"},{"author":{"_account_id":261,"name":"Salvatore Orlando","email":"salv.orlando@gmail.com","username":"salvatore-orlando"},"change_message_id":"183e721c525a87cdd244a5eca7fff56d49bd699a","unresolved":false,"context_lines":[{"line_number":52,"context_line":""},{"line_number":53,"context_line":"        - \u0027query_hook\u0027 takes place immediately after the initial model query"},{"line_number":54,"context_line":"          is executed. The hook receives the context, model and query,"},{"line_number":55,"context_line":"          and returns a transformed query expression."},{"line_number":56,"context_line":"        - \u0027conditions_hook\u0027 also takes place immediately after the initial"},{"line_number":57,"context_line":"          model query and receives the context, model and the conditions"},{"line_number":58,"context_line":"          expression, and returns the transformed conditions expression (which"}],"source_content_type":"text/x-python","patch_set":5,"id":"fa98f980_4838bfd4","line":55,"updated":"2014-09-17 13:17:20.000000000","message":"it is actually not executed after the initial query is executed.\nThe model hooks actually do not execute any query, they just transform them.\n\nThe query_hook \"augments\" the model to which it is applied by adding information from other models through operations such as joins.","commit_id":"17e178fb91333ff026f6f3c2a820c0820cb86ab9"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"429edbba1b91e2617af344391bb3d1804edfa847","unresolved":false,"context_lines":[{"line_number":52,"context_line":""},{"line_number":53,"context_line":"        - \u0027query_hook\u0027 takes place immediately after the initial model query"},{"line_number":54,"context_line":"          is executed. The hook receives the context, model and query,"},{"line_number":55,"context_line":"          and returns a transformed query expression."},{"line_number":56,"context_line":"        - \u0027conditions_hook\u0027 also takes place immediately after the initial"},{"line_number":57,"context_line":"          model query and receives the context, model and the conditions"},{"line_number":58,"context_line":"          expression, and returns the transformed conditions expression (which"}],"source_content_type":"text/x-python","patch_set":5,"id":"baa201ad_6c6fe92b","line":55,"in_reply_to":"fa98f980_4838bfd4","updated":"2014-10-05 12:21:38.000000000","message":"Changed the documentation a bit to be more similar to what you intended to say. How is this?","commit_id":"17e178fb91333ff026f6f3c2a820c0820cb86ab9"},{"author":{"_account_id":261,"name":"Salvatore Orlando","email":"salv.orlando@gmail.com","username":"salvatore-orlando"},"change_message_id":"183e721c525a87cdd244a5eca7fff56d49bd699a","unresolved":false,"context_lines":[{"line_number":54,"context_line":"          is executed. The hook receives the context, model and query,"},{"line_number":55,"context_line":"          and returns a transformed query expression."},{"line_number":56,"context_line":"        - \u0027conditions_hook\u0027 also takes place immediately after the initial"},{"line_number":57,"context_line":"          model query and receives the context, model and the conditions"},{"line_number":58,"context_line":"          expression, and returns the transformed conditions expression (which"},{"line_number":59,"context_line":"          is built incrementally and later used in a filter() call."},{"line_number":60,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"fa98f980_e37c34ee","line":57,"updated":"2014-09-17 13:17:20.000000000","message":"pedantry: takes place after the \"augmented\" model is built, or if you prefer after the query_hook is applied","commit_id":"17e178fb91333ff026f6f3c2a820c0820cb86ab9"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"429edbba1b91e2617af344391bb3d1804edfa847","unresolved":false,"context_lines":[{"line_number":54,"context_line":"          is executed. The hook receives the context, model and query,"},{"line_number":55,"context_line":"          and returns a transformed query expression."},{"line_number":56,"context_line":"        - \u0027conditions_hook\u0027 also takes place immediately after the initial"},{"line_number":57,"context_line":"          model query and receives the context, model and the conditions"},{"line_number":58,"context_line":"          expression, and returns the transformed conditions expression (which"},{"line_number":59,"context_line":"          is built incrementally and later used in a filter() call."},{"line_number":60,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"baa201ad_4c8785d7","line":57,"in_reply_to":"fa98f980_e37c34ee","updated":"2014-10-05 12:21:38.000000000","message":"Done","commit_id":"17e178fb91333ff026f6f3c2a820c0820cb86ab9"},{"author":{"_account_id":261,"name":"Salvatore Orlando","email":"salv.orlando@gmail.com","username":"salvatore-orlando"},"change_message_id":"183e721c525a87cdd244a5eca7fff56d49bd699a","unresolved":false,"context_lines":[{"line_number":58,"context_line":"          expression, and returns the transformed conditions expression (which"},{"line_number":59,"context_line":"          is built incrementally and later used in a filter() call."},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"        - \u0027pre_filter_hook\u0027 and \u0027post_filter_hook\u0027 hooks takes place"},{"line_number":62,"context_line":"          immediately before and after (respectively) the user\u0027s filters are"},{"line_number":63,"context_line":"          matched against the columns as normal query filters. Each hook"},{"line_number":64,"context_line":"          receives the context, query and filters, and return a new query"}],"source_content_type":"text/x-python","patch_set":5,"id":"fa98f980_837528fc","line":61,"updated":"2014-09-17 13:17:20.000000000","message":"sorry about this super pedant note - hooks/hook","commit_id":"17e178fb91333ff026f6f3c2a820c0820cb86ab9"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"429edbba1b91e2617af344391bb3d1804edfa847","unresolved":false,"context_lines":[{"line_number":58,"context_line":"          expression, and returns the transformed conditions expression (which"},{"line_number":59,"context_line":"          is built incrementally and later used in a filter() call."},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"        - \u0027pre_filter_hook\u0027 and \u0027post_filter_hook\u0027 hooks takes place"},{"line_number":62,"context_line":"          immediately before and after (respectively) the user\u0027s filters are"},{"line_number":63,"context_line":"          matched against the columns as normal query filters. Each hook"},{"line_number":64,"context_line":"          receives the context, query and filters, and return a new query"}],"source_content_type":"text/x-python","patch_set":5,"id":"baa201ad_8c6c0d37","line":61,"in_reply_to":"fa98f980_837528fc","updated":"2014-10-05 12:21:38.000000000","message":"Removed the word altogether as the sentence still makes sense.","commit_id":"17e178fb91333ff026f6f3c2a820c0820cb86ab9"}],"neutron/db/db_base_plugin_v2.py":[{"author":{"_account_id":261,"name":"Salvatore Orlando","email":"salv.orlando@gmail.com","username":"salvatore-orlando"},"change_message_id":"c7ede146c4bdf4f8dafce007ededb942d6a6b055","unresolved":false,"context_lines":[{"line_number":1415,"context_line":"            if subnet_ids:"},{"line_number":1416,"context_line":"                query \u003d query.filter(IPAllocation.subnet_id.in_(subnet_ids))"},{"line_number":1417,"context_line":""},{"line_number":1418,"context_line":"        return query"},{"line_number":1419,"context_line":""},{"line_number":1420,"context_line":"    def get_ports(self, context, filters\u003dNone, fields\u003dNone,"},{"line_number":1421,"context_line":"                  sorts\u003dNone, limit\u003dNone, marker\u003dNone,"}],"source_content_type":"text/x-python","patch_set":3,"id":"1abeadc6_a8f9c84f","line":1418,"updated":"2014-08-28 11:59:58.000000000","message":"is there any chance this could work also as a post-filter hook?","commit_id":"84abd52ae748653fbd3a86576a7460ea16842ff0"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"bf6202921f36acad1ae5bad01676b804bab5e0a1","unresolved":false,"context_lines":[{"line_number":1415,"context_line":"            if subnet_ids:"},{"line_number":1416,"context_line":"                query \u003d query.filter(IPAllocation.subnet_id.in_(subnet_ids))"},{"line_number":1417,"context_line":""},{"line_number":1418,"context_line":"        return query"},{"line_number":1419,"context_line":""},{"line_number":1420,"context_line":"    def get_ports(self, context, filters\u003dNone, fields\u003dNone,"},{"line_number":1421,"context_line":"                  sorts\u003dNone, limit\u003dNone, marker\u003dNone,"}],"source_content_type":"text/x-python","patch_set":3,"id":"1abeadc6_87707aa5","line":1418,"in_reply_to":"1abeadc6_a8f9c84f","updated":"2014-08-28 12:39:43.000000000","message":"No, because the filter key is \u0027fixed_ip\u0027 which is a foreign key in the models_v2.Port model. When trying to put this logic in the post-filter hook, _apply_filters_to_query raises an exception because it tries to treat a foreign key as a string.\nThis is why this (and my code) need to run *before* the normal column filtering happens.","commit_id":"84abd52ae748653fbd3a86576a7460ea16842ff0"},{"author":{"_account_id":261,"name":"Salvatore Orlando","email":"salv.orlando@gmail.com","username":"salvatore-orlando"},"change_message_id":"f8fd4ca41c9eda4a9942f51f176286d5207d41a9","unresolved":false,"context_lines":[{"line_number":85,"context_line":"            None,"},{"line_number":86,"context_line":"            None,"},{"line_number":87,"context_line":"            self.get_ports_pre_filter_hook,"},{"line_number":88,"context_line":"            None)"},{"line_number":89,"context_line":""},{"line_number":90,"context_line":"    @classmethod"},{"line_number":91,"context_line":"    def register_dict_extend_funcs(cls, resource, funcs):"}],"source_content_type":"text/x-python","patch_set":4,"id":"fa98f980_9a82e650","line":88,"updated":"2014-09-01 15:26:58.000000000","message":"None parameters are ugly","commit_id":"85c4f35ed62ddbd78c2affee67e845b041276649"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"8f71d9757d75ee7468eb3465e8e770c5ece4fe71","unresolved":false,"context_lines":[{"line_number":85,"context_line":"            None,"},{"line_number":86,"context_line":"            None,"},{"line_number":87,"context_line":"            self.get_ports_pre_filter_hook,"},{"line_number":88,"context_line":"            None)"},{"line_number":89,"context_line":""},{"line_number":90,"context_line":"    @classmethod"},{"line_number":91,"context_line":"    def register_dict_extend_funcs(cls, resource, funcs):"}],"source_content_type":"text/x-python","patch_set":4,"id":"fa98f980_cef3a29d","line":88,"in_reply_to":"fa98f980_9a82e650","updated":"2014-09-02 08:39:52.000000000","message":"Done","commit_id":"85c4f35ed62ddbd78c2affee67e845b041276649"},{"author":{"_account_id":841,"name":"Akihiro Motoki","email":"amotoki@gmail.com","username":"amotoki"},"change_message_id":"8abd1a7b9a0181b83ef2f579aae7866f09596a63","unresolved":false,"context_lines":[{"line_number":82,"context_line":"        self.register_model_query_hook("},{"line_number":83,"context_line":"            models_v2.Port,"},{"line_number":84,"context_line":"            \u0027get_ports\u0027,"},{"line_number":85,"context_line":"            pre_filter_hook\u003dself.get_ports_pre_filter_hook)"},{"line_number":86,"context_line":""},{"line_number":87,"context_line":"    @classmethod"},{"line_number":88,"context_line":"    def register_dict_extend_funcs(cls, resource, funcs):"}],"source_content_type":"text/x-python","patch_set":5,"id":"fa98f980_1b77ee3c","line":85,"updated":"2014-09-17 05:28:58.000000000","message":"I think we need to use a method name to specify a filter so that subclasses can implement their own hook. It is done for other query hooks.","commit_id":"17e178fb91333ff026f6f3c2a820c0820cb86ab9"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"429edbba1b91e2617af344391bb3d1804edfa847","unresolved":false,"context_lines":[{"line_number":82,"context_line":"        self.register_model_query_hook("},{"line_number":83,"context_line":"            models_v2.Port,"},{"line_number":84,"context_line":"            \u0027get_ports\u0027,"},{"line_number":85,"context_line":"            pre_filter_hook\u003dself.get_ports_pre_filter_hook)"},{"line_number":86,"context_line":""},{"line_number":87,"context_line":"    @classmethod"},{"line_number":88,"context_line":"    def register_dict_extend_funcs(cls, resource, funcs):"}],"source_content_type":"text/x-python","patch_set":5,"id":"baa201ad_cc729510","line":85,"in_reply_to":"fa98f980_15116f53","updated":"2014-10-05 12:21:38.000000000","message":"In continuation to what salv wrote, changed most of the calls to register_model_query_hook to make sure they all use function names (strings) and not function \u0027pointers\u0027.\n\n\"Most of the calls\", since the metaplugin tests don\u0027t behave (they use fake plugins, and if I change the hooks there to be class method it messes with the tests and they fail). Instead, I put a TODO there so a metaplugin dev could take a look at it when they have time.","commit_id":"17e178fb91333ff026f6f3c2a820c0820cb86ab9"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"209dec12ab0cf9c77653b19cfde6301eb8b830aa","unresolved":false,"context_lines":[{"line_number":82,"context_line":"        self.register_model_query_hook("},{"line_number":83,"context_line":"            models_v2.Port,"},{"line_number":84,"context_line":"            \u0027get_ports\u0027,"},{"line_number":85,"context_line":"            pre_filter_hook\u003dself.get_ports_pre_filter_hook)"},{"line_number":86,"context_line":""},{"line_number":87,"context_line":"    @classmethod"},{"line_number":88,"context_line":"    def register_dict_extend_funcs(cls, resource, funcs):"}],"source_content_type":"text/x-python","patch_set":5,"id":"fa98f980_02d056c8","line":85,"in_reply_to":"fa98f980_1b77ee3c","updated":"2014-09-17 10:54:28.000000000","message":"Unlike register_dict_extend_funcs (which I have to admit don\u0027t really know), this mechanism is not dependent on the function used, but rather on the DB model object. This is done since some functions might call _model_query() manually to get other models, so we can\u0027t depend on all the calls to go through a single function somewhere. Currently there is a distinction between the different models used to lower the \u0027hook\u0027 counter.","commit_id":"17e178fb91333ff026f6f3c2a820c0820cb86ab9"},{"author":{"_account_id":6854,"name":"YAMAMOTO Takashi","email":"yamamoto@midokura.com","username":"yamamoto"},"change_message_id":"9e67d9cbd2760cf9e6b30fb5786f51e34383c69f","unresolved":false,"context_lines":[{"line_number":82,"context_line":"        self.register_model_query_hook("},{"line_number":83,"context_line":"            models_v2.Port,"},{"line_number":84,"context_line":"            \u0027get_ports\u0027,"},{"line_number":85,"context_line":"            pre_filter_hook\u003dself.get_ports_pre_filter_hook)"},{"line_number":86,"context_line":""},{"line_number":87,"context_line":"    @classmethod"},{"line_number":88,"context_line":"    def register_dict_extend_funcs(cls, resource, funcs):"}],"source_content_type":"text/x-python","patch_set":5,"id":"fa98f980_a2530a38","line":85,"in_reply_to":"fa98f980_1b77ee3c","updated":"2014-09-17 11:02:07.000000000","message":"my understanding is that it\u0027s ok because \"self\" here is an instance of the subclass.","commit_id":"17e178fb91333ff026f6f3c2a820c0820cb86ab9"},{"author":{"_account_id":261,"name":"Salvatore Orlando","email":"salv.orlando@gmail.com","username":"salvatore-orlando"},"change_message_id":"183e721c525a87cdd244a5eca7fff56d49bd699a","unresolved":false,"context_lines":[{"line_number":82,"context_line":"        self.register_model_query_hook("},{"line_number":83,"context_line":"            models_v2.Port,"},{"line_number":84,"context_line":"            \u0027get_ports\u0027,"},{"line_number":85,"context_line":"            pre_filter_hook\u003dself.get_ports_pre_filter_hook)"},{"line_number":86,"context_line":""},{"line_number":87,"context_line":"    @classmethod"},{"line_number":88,"context_line":"    def register_dict_extend_funcs(cls, resource, funcs):"}],"source_content_type":"text/x-python","patch_set":5,"id":"fa98f980_bdc5ef0b","line":85,"in_reply_to":"fa98f980_a2530a38","updated":"2014-09-17 13:17:20.000000000","message":"I tend to agree with Yamamoto here, but I need to quickly test it.\n\nHowever I really would not like to see other plugins doing hooks in different ways.","commit_id":"17e178fb91333ff026f6f3c2a820c0820cb86ab9"},{"author":{"_account_id":841,"name":"Akihiro Motoki","email":"amotoki@gmail.com","username":"amotoki"},"change_message_id":"653ed26c3183e5088cef56be7d3706666b61cfb8","unresolved":false,"context_lines":[{"line_number":82,"context_line":"        self.register_model_query_hook("},{"line_number":83,"context_line":"            models_v2.Port,"},{"line_number":84,"context_line":"            \u0027get_ports\u0027,"},{"line_number":85,"context_line":"            pre_filter_hook\u003dself.get_ports_pre_filter_hook)"},{"line_number":86,"context_line":""},{"line_number":87,"context_line":"    @classmethod"},{"line_number":88,"context_line":"    def register_dict_extend_funcs(cls, resource, funcs):"}],"source_content_type":"text/x-python","patch_set":5,"id":"fa98f980_08c957ac","line":85,"in_reply_to":"fa98f980_a2530a38","updated":"2014-09-17 12:05:15.000000000","message":"Thanks Joh and Takashi. I got it how it works. It is called in the context of the instance method.","commit_id":"17e178fb91333ff026f6f3c2a820c0820cb86ab9"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"f04f5b73e7823192233a37cac977bb7c74df1150","unresolved":false,"context_lines":[{"line_number":82,"context_line":"        self.register_model_query_hook("},{"line_number":83,"context_line":"            models_v2.Port,"},{"line_number":84,"context_line":"            \u0027get_ports\u0027,"},{"line_number":85,"context_line":"            pre_filter_hook\u003dself.get_ports_pre_filter_hook)"},{"line_number":86,"context_line":""},{"line_number":87,"context_line":"    @classmethod"},{"line_number":88,"context_line":"    def register_dict_extend_funcs(cls, resource, funcs):"}],"source_content_type":"text/x-python","patch_set":5,"id":"fa98f980_15116f53","line":85,"in_reply_to":"fa98f980_bdc5ef0b","updated":"2014-09-17 13:23:55.000000000","message":"I can confirm Yamamato\u0027s saying here - ran into this problem while implementing this and it\u0027s ok to use an actual pointer since there is a \u0027self\u0027, ie. it is treated as a bound function.\n\nI expect changing this to a string will also work.","commit_id":"17e178fb91333ff026f6f3c2a820c0820cb86ab9"}],"neutron/db/external_net_db.py":[{"author":{"_account_id":261,"name":"Salvatore Orlando","email":"salv.orlando@gmail.com","username":"salvatore-orlando"},"change_message_id":"c7ede146c4bdf4f8dafce007ededb942d6a6b055","unresolved":false,"context_lines":[{"line_number":59,"context_line":"            conditions \u003d expr.or_(ExternalNetwork.network_id !\u003d expr.null(),"},{"line_number":60,"context_line":"                                  *conditions)"},{"line_number":61,"context_line":""},{"line_number":62,"context_line":"        return query, conditions"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":"    def _network_post_filter_hook(self, context, query, filters):"},{"line_number":65,"context_line":"        vals \u003d filters and filters.get(external_net.EXTERNAL, [])"}],"source_content_type":"text/x-python","patch_set":3,"id":"1abeadc6_68b1708e","line":62,"updated":"2014-08-28 11:59:58.000000000","message":"I see what you did here\n\nI\u0027m not sure I like this. In theory one could have a need to add a condition with a hook without having to do joins.\n\nSo in theory the model attribute should be nullable at least.\nOn the other hand also returning the tuple is a bit ugly.\n\nSummarizing, I might be ok with this change, but I think the previous logic was a bit clearer.\n\nAlso, it seems to me that merging these two hooks is not really the focus of this patch, which instead aims at enabling a different way of doing filters on list operations.\n\nIf we end up with 4 hook functions it wont\u0027 be the end of the world for me.","commit_id":"84abd52ae748653fbd3a86576a7460ea16842ff0"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"a0653e62beb4ef7ec8b132a044e01ad913404120","unresolved":false,"context_lines":[{"line_number":59,"context_line":"            conditions \u003d expr.or_(ExternalNetwork.network_id !\u003d expr.null(),"},{"line_number":60,"context_line":"                                  *conditions)"},{"line_number":61,"context_line":""},{"line_number":62,"context_line":"        return query, conditions"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":"    def _network_post_filter_hook(self, context, query, filters):"},{"line_number":65,"context_line":"        vals \u003d filters and filters.get(external_net.EXTERNAL, [])"}],"source_content_type":"text/x-python","patch_set":3,"id":"fa98f980_4f31c2a1","line":62,"in_reply_to":"1abeadc6_07b38a4d","updated":"2014-08-31 14:42:48.000000000","message":"Done","commit_id":"84abd52ae748653fbd3a86576a7460ea16842ff0"},{"author":{"_account_id":12444,"name":"John Schwarz","email":"jschwarz@redhat.com","username":"jschwarz"},"change_message_id":"bf6202921f36acad1ae5bad01676b804bab5e0a1","unresolved":false,"context_lines":[{"line_number":59,"context_line":"            conditions \u003d expr.or_(ExternalNetwork.network_id !\u003d expr.null(),"},{"line_number":60,"context_line":"                                  *conditions)"},{"line_number":61,"context_line":""},{"line_number":62,"context_line":"        return query, conditions"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":"    def _network_post_filter_hook(self, context, query, filters):"},{"line_number":65,"context_line":"        vals \u003d filters and filters.get(external_net.EXTERNAL, [])"}],"source_content_type":"text/x-python","patch_set":3,"id":"1abeadc6_07b38a4d","line":62,"in_reply_to":"1abeadc6_68b1708e","updated":"2014-08-28 12:39:43.000000000","message":"After reading your other comments, I am fine with reverting back to query_hook and renaming filter_hook to conditions_hook. In short:\n- query_hook\n- conditions_hook\n- pre_filter\n- post_filter","commit_id":"84abd52ae748653fbd3a86576a7460ea16842ff0"}]}
