Source code for flask_unchained.hooks.init_extensions_hook
import networkx as nx
from collections import namedtuple
from typing import *
from .register_extensions_hook import RegisterExtensionsHook
from ..flask_unchained import FlaskUnchained
ExtensionTuple = namedtuple('ExtensionTuple',
('name', 'extension', 'dependencies'))
[docs]class InitExtensionsHook(RegisterExtensionsHook):
"""
Initializes extensions found in bundles with the current app.
"""
name = 'init_extensions'
"""
The name of this hook.
"""
bundle_module_names = ['extensions']
"""
The default module this hook loads from.
Override by setting the ``extensions_module_names`` attribute on your
bundle class.
"""
run_after = ['register_extensions']
[docs] def process_objects(self,
app: FlaskUnchained,
extensions: Dict[str, object],
) -> None:
"""
Initialize each extension with ``extension.init_app(app)``.
"""
for extension_tuple in self.resolve_extension_order(extensions):
name, extension, _ = extension_tuple
if name in self.unchained.extensions:
extension = self.unchained.extensions[name]
extension.init_app(app)
if name not in self.unchained.extensions:
self.unchained.extensions[name] = extension
[docs] def update_shell_context(self, ctx: Dict[str, Any]) -> None:
"""
Add extensions to the CLI shell context.
"""
ctx.update(self.unchained.extensions)
def resolve_extension_order(self,
extensions: Dict[str, object],
) -> List[ExtensionTuple]:
extension_tuples = []
for name, extension in extensions.items():
dependencies = []
if isinstance(extension, (list, tuple)):
extension, dependencies = extension
extension_tuples.append(ExtensionTuple(name, extension, dependencies))
dag = nx.DiGraph()
for extension_tuple in extension_tuples:
dag.add_node(extension_tuple.name, extension_tuple=extension_tuple)
for dep_name in extension_tuple.dependencies:
dag.add_edge(extension_tuple.name, dep_name)
try:
extension_order = reversed(list(nx.topological_sort(dag)))
except nx.NetworkXUnfeasible:
msg = 'Circular dependency detected between extensions'
problem_graph = ', '.join(f'{a} -> {b}'
for a, b in nx.find_cycle(dag))
raise Exception(f'{msg}: {problem_graph}')
rv = []
for ext_name in extension_order:
try:
rv.append(dag.nodes[ext_name]['extension_tuple'])
except KeyError as e:
if 'extension_tuple' not in str(e):
raise e
raise Exception(f'Could not locate extension named {ext_name!r}')
return rv