1# -*- coding: utf-8 -*-2# Copyright 2011 Takeshi KOMIYA3#4# Licensed under the Apache License, Version 2.0 (the "License");5# you may not use this file except in compliance with the License.6# You may obtain a copy of the License at7#8# http://www.apache.org/licenses/LICENSE-2.09#10# Unless required by applicable law or agreed to in writing, software11# distributed under the License is distributed on an "AS IS" BASIS,12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.13# See the License for the specific language governing permissions and14# limitations under the License.1516from importlib import metadata1718from blockdiag.utils.logging import warning1920loaded_plugins = []21node_handlers = []22general_handlers = {}232425def load(plugins, diagram, **kwargs):26 for name in plugins:27 if name in loaded_plugins:28 warning('plugin "%s" is already loaded. ignored.', name)29 return3031 for ep in metadata.entry_points(group='blockdiag_plugins', name=name):32 module = ep.load()33 loaded_plugins.append(name)34 if hasattr(module, 'setup'):35 module.setup(module, diagram, **kwargs)36 break37 else:38 msg = "unknown plugin: %s" % name39 raise AttributeError(msg)404142def install_general_handler(name, handler):43 if name not in general_handlers:44 general_handlers[name] = []4546 general_handlers[name].append(handler)474849def fire_general_event(name, *args):50 handlers = general_handlers.get(name, [])51 return all(handler(*args) for handler in handlers)525354def install_node_handler(handler):55 if handler not in node_handlers:56 node_handlers.append(handler)575859def fire_node_event(node, name, *args):60 return all(handler.fire(name, node, *args) for handler in node_handlers)616263class NodeHandler(object):64 def __init__(self, diagram, **kwargs):65 self.diagram = diagram66 self.config = kwargs.get('config')6768 def fire(self, name, *args):69 return getattr(self, "on_" + name)(*args)7071 def on_created(self, node):72 return True7374 def on_attr_changing(self, node, attr):75 return True7677 def on_attr_changed(self, node, attr):78 return True7980 def on_build_finished(self, node):81 return True828384def cleanup():85 fire_general_event('cleanup')8687 for name in list(general_handlers.keys()):88 del general_handlers[name]8990 for handler in node_handlers[:]:91 node_handlers.remove(handler)9293 for plugin in loaded_plugins[:]:94 loaded_plugins.remove(plugin)959697def setup(app):98 app.register_cleanup_handler(cleanup)