126 lines
4.5 KiB
Python
126 lines
4.5 KiB
Python
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
|
|
"""
|
|
NOTE: This module shall not be used by external projects. It will be moved
|
|
to neutron-lib in due course, and then it can be used from there.
|
|
"""
|
|
|
|
from neutron.common import utils
|
|
|
|
# Classes implementing extensions will register hooks into this dictionary
|
|
# for "augmenting" the "core way" of building a query for retrieving objects
|
|
# from a model class. Hooks are registered by invoking register_hook().
|
|
_model_query_hooks = {
|
|
# model1 : {
|
|
# hook1: {
|
|
# 'query': query_hook,
|
|
# 'filter': filter_hook,
|
|
# 'result_filters': result_filters
|
|
# },
|
|
# hook2: {
|
|
# 'query': query_hook,
|
|
# 'filter': filter_hook,
|
|
# 'result_filters': result_filters
|
|
# },
|
|
# ...
|
|
# },
|
|
# model2 : {
|
|
# hook1: {
|
|
# 'query': query_hook,
|
|
# 'filter': filter_hook,
|
|
# 'result_filters': result_filters
|
|
# },
|
|
# hook2: {
|
|
# 'query': query_hook,
|
|
# 'filter': filter_hook,
|
|
# 'result_filters': result_filters
|
|
# },
|
|
# ...
|
|
# },
|
|
# ...
|
|
}
|
|
|
|
|
|
def register_hook(model, name, query_hook, filter_hook,
|
|
result_filters=None):
|
|
"""Register a hook to be invoked when a query is executed.
|
|
|
|
:param model: The DB Model that the hook applies to.
|
|
:type model: sqlalchemy orm model
|
|
|
|
:param name: A name for the hook.
|
|
:type name: str
|
|
|
|
:param query_hook: The method to be called to augment the query.
|
|
:type query_hook: callable or None
|
|
|
|
:param filter_hook: A method to be called to augment the query filter.
|
|
:type filter_hook: callable or None
|
|
|
|
:param result_filters: A Method to be called to filter the query result.
|
|
:type result_filters: callable or None
|
|
|
|
Adds the hook components to the _model_query_hooks dict. Models are the
|
|
keys of this dict, whereas the value is another dict mapping hook names
|
|
to callables performing the hook.
|
|
|
|
Each hook has three components:
|
|
"query", used to build the query expression
|
|
"filter", used to build the filter expression
|
|
"result_filters", used for final filtering on the query result
|
|
|
|
Query hooks take as input the query being built and return a
|
|
transformed query expression.
|
|
def mymodel_query_hook(context, original_model, query):
|
|
augmented_query = ...
|
|
return augmented_query
|
|
|
|
Filter hooks take as input the filter expression being built and return
|
|
a transformed filter expression
|
|
def mymodel_filter_hook(context, original_model, filters):
|
|
refined_filters = ...
|
|
return refined_filters
|
|
|
|
Result filter hooks take as input the query expression and the filter
|
|
expression, and return a final transformed query expression.
|
|
def mymodel_result_filter_hook(query, filters):
|
|
final_filters = ...
|
|
return query.filter(final_filters)
|
|
|
|
"""
|
|
if callable(query_hook):
|
|
query_hook = utils.make_weak_ref(query_hook)
|
|
if callable(filter_hook):
|
|
filter_hook = utils.make_weak_ref(filter_hook)
|
|
if callable(result_filters):
|
|
result_filters = utils.make_weak_ref(result_filters)
|
|
_model_query_hooks.setdefault(model, {})[name] = {
|
|
'query': query_hook,
|
|
'filter': filter_hook,
|
|
'result_filters': result_filters
|
|
}
|
|
|
|
|
|
def get_hooks(model):
|
|
"""Retrieve the model query hooks for a model.
|
|
|
|
:param model: The DB Model to look up for query hooks.
|
|
:type model: sqlalchemy orm model
|
|
|
|
:return: list of hooks
|
|
:rtype: list of dict of callable
|
|
|
|
"""
|
|
return _model_query_hooks.get(model, {}).values()
|