def create_app(config="CTFd.config.Config"): app = CTFdFlask(__name__) with app.app_context(): app.config.from_object(config) app.theme_loader = ThemeLoader(os.path.join(app.root_path, "themes"), followlinks=True) # Weird nested solution for accessing plugin templates app.plugin_loader = jinja2.PrefixLoader({ "plugins": jinja2.FileSystemLoader(searchpath=os.path.join( app.root_path, "plugins"), followlinks=True) }) # Load from themes first but fallback to loading from the plugin folder app.jinja_loader = jinja2.ChoiceLoader( [app.theme_loader, app.plugin_loader]) from CTFd.models import ( # noqa: F401 db, Teams, Solves, Challenges, Fails, Flags, Tags, Files, Tracking, ) url = create_database() # This allows any changes to the SQLALCHEMY_DATABASE_URI to get pushed back in # This is mostly so we can force MySQL's charset app.config["SQLALCHEMY_DATABASE_URI"] = str(url) # Register database db.init_app(app) # Register Flask-Migrate migrations.init_app(app, db) # Alembic sqlite support is lacking so we should just create_all anyway if url.drivername.startswith("sqlite"): # Enable foreign keys for SQLite. This must be before the # db.create_all call because tests use the in-memory SQLite # database (each connection, including db creation, is a new db). # https://docs.sqlalchemy.org/en/13/dialects/sqlite.html#foreign-key-support from sqlalchemy.engine import Engine from sqlalchemy import event @event.listens_for(Engine, "connect") def set_sqlite_pragma(dbapi_connection, connection_record): cursor = dbapi_connection.cursor() cursor.execute("PRAGMA foreign_keys=ON") cursor.close() db.create_all() stamp_latest_revision() else: # This creates tables instead of db.create_all() # Allows migrations to happen properly upgrade() from CTFd.models import ma ma.init_app(app) app.db = db app.VERSION = __version__ app.CHANNEL = __channel__ from CTFd.cache import cache cache.init_app(app) app.cache = cache reverse_proxy = app.config.get("REVERSE_PROXY") if reverse_proxy: if type(reverse_proxy) is str and "," in reverse_proxy: proxyfix_args = [int(i) for i in reverse_proxy.split(",")] app.wsgi_app = ProxyFix(app.wsgi_app, *proxyfix_args) else: app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_port=1, x_prefix=1) version = utils.get_config("ctf_version") # Upgrading from an older version of CTFd if version and (StrictVersion(version) < StrictVersion(__version__)): if confirm_upgrade(): run_upgrade() else: exit() if not version: utils.set_config("ctf_version", __version__) if not utils.get_config("ctf_theme"): utils.set_config("ctf_theme", "core") update_check(force=True) init_request_processors(app) init_template_filters(app) init_template_globals(app) # Importing here allows tests to use sensible names (e.g. api instead of api_bp) from CTFd.views import views from CTFd.teams import teams from CTFd.users import users from CTFd.challenges import challenges from CTFd.scoreboard import scoreboard from CTFd.auth import auth from CTFd.admin import admin from CTFd.api import api from CTFd.events import events from CTFd.errors import page_not_found, forbidden, general_error, gateway_error app.register_blueprint(views) app.register_blueprint(teams) app.register_blueprint(users) app.register_blueprint(challenges) app.register_blueprint(scoreboard) app.register_blueprint(auth) app.register_blueprint(api) app.register_blueprint(events) app.register_blueprint(admin) app.register_error_handler(404, page_not_found) app.register_error_handler(403, forbidden) app.register_error_handler(500, general_error) app.register_error_handler(502, gateway_error) init_logs(app) init_events(app) init_plugins(app) return app
import os import json import jinja2 from filters import slash_to_dash, extract_month, map_month, extract_day data_path = "data" dummy_data_path = "dummy_data" docs_path = "docs/" static_folder_path = "https://digital-land-design.herokuapp.com/static" # jinja setup multi_loader = jinja2.ChoiceLoader([ jinja2.FileSystemLoader(searchpath="./templates"), jinja2.PrefixLoader({ 'govuk-jinja-components': jinja2.PackageLoader('govuk_jinja_components') }) ]) env = jinja2.Environment(loader=multi_loader) # load any filters the templates need env.filters["slash_to_dash"] = slash_to_dash env.filters["extract_day"] = extract_day env.filters["get_month"] = extract_month env.filters["map_month"] = map_month # retrieve page templates collections_template = env.get_template("collections.html") collections_log_template = env.get_template("collections-log.html") collections_log_date_template = env.get_template("collections-log-date.html")
def __init__(self): Flask.__init__(self, __name__) self.jinja_loader = jinja2.ChoiceLoader( [self.jinja_loader, jinja2.PrefixLoader({}, delimiter='.')])
def __init__(self, *args, **kwargs): super(JinjaRenderer, self).__init__(*args, **kwargs) loaders = [] prefix_loaders = {} paths = list(settings.SITE.get_settings_subdirs(SUBDIR_NAME)) if settings.SITE.is_local_project_dir: p = join(settings.SITE.project_dir, SUBDIR_NAME) if isdir(p): paths.append(p) #~ logger.info("20130717 web.py paths %s",paths) if len(paths) > 0: loaders.append(jinja2.FileSystemLoader(paths)) def func(name, m): #~ logger.info("20130717 jinja loader %s %s",name,SUBDIR_NAME) if isdir(join(dirname(m.__file__), SUBDIR_NAME)): loader = jinja2.PackageLoader(name, SUBDIR_NAME) loaders.append(loader) prefix_loaders[name] = loader settings.SITE.for_each_app(func) loaders.insert(0, jinja2.PrefixLoader(prefix_loaders, delimiter=":")) #~ loaders = reversed(loaders) #~ print 20130109, loaders self.jinja_env = jinja2.Environment( #~ extensions=['jinja2.ext.i18n'], loader=jinja2.ChoiceLoader(loaders)) #~ jinja_env = jinja2.Environment(trim_blocks=False) #~ from django.utils import translation #~ jinja_env.install_gettext_translations(translation) def as_table(action_spec): a = settings.SITE.modules.resolve(action_spec) ar = a.request(user=AnonymousUser.instance()) return self.as_table(ar) def as_table2(ar): # 20150810 # ar.renderer = settings.SITE.plugins.bootstrap3.renderer ar.renderer = self t = xghtml.Table() ar.dump2html(t, ar.sliced_data_iterator) #~ print ar.get_total_count() return E.tostring(t.as_element()) #~ return E.tostring(E.ul(*[E.li(ar.summary_row(obj)) for obj in ar]),method="html") def as_ul(action_spec): a = settings.SITE.actors.resolve(action_spec) ar = a.request(user=AnonymousUser.instance()) # 20150810 ar.renderer = self # ar.renderer = settings.SITE.plugins.bootstrap3.renderer return E.tostring(E.ul(*[obj.as_list_item(ar) for obj in ar])) # from lino.core.requests import BaseRequest self.jinja_env.globals.update( settings=settings, site=settings.SITE, dtos=format_date.fds, # obsolete dtosl=format_date.fdl, # obsolete as_ul=as_ul, as_table=as_table2, iif=iif, str=str, len=len, E=E, ar=None, # _=_, now=datetime.datetime.now(), mtos=settings.SITE.decfmt, # obsolete decfmt=settings.SITE.decfmt, fds=format_date.fds, fdm=format_date.fdm, fdl=format_date.fdl, fdf=format_date.fdf, fdmy=format_date.fdmy, babelattr=settings.SITE.babelattr, babelitem=settings.SITE.babelitem, # obsolete tr=settings.SITE.babelitem, # dd=dd, rt=rt, escape=cgi.escape, Counter=Counter, SumCollector=SumCollector, # lino=self.modules, # experimental # site_config=self.site_config, ) def translate(s): return ugettext(str(s)) self.jinja_env.globals.update(_=translate) def ptranslate(ctx, s): return pgettext(ctx.decode('utf8'), s.decode('utf8')) self.jinja_env.globals.update(pgettext=pgettext)
def __init__( self, name, opts, ): self.name = name self.opts = opts self.jinjenv = jinja2.Environment( trim_blocks=True, lstrip_blocks=True, undefined=jinja2.StrictUndefined, loader=jinja2.PrefixLoader({ "protocols": jinja2.PrefixLoader({ "conv": jinja2.PrefixLoader({ "builtin": jinja2.PackageLoader('libkludge', 'protocols/conv'), }), "result": jinja2.PrefixLoader({ "builtin": jinja2.PackageLoader('libkludge', 'protocols/result'), }), "param": jinja2.PrefixLoader({ "builtin": jinja2.PackageLoader('libkludge', 'protocols/param'), }), "self": jinja2.PrefixLoader({ "builtin": jinja2.PackageLoader('libkludge', 'protocols/self'), }), "repr": jinja2.PrefixLoader({ "builtin": jinja2.PackageLoader('libkludge', 'protocols/repr'), }), }), "types": jinja2.PrefixLoader({ "builtin": jinja2.PackageLoader('libkludge', 'types'), }), "generate": jinja2.PackageLoader('libkludge', 'generate/templates'), }), ) setattr(self.jinjenv, 'opts', opts) self.type_mgr = TypeMgr(self) self.namespace_mgr = NamespaceMgr(self.type_mgr) self.cpp_flags = [] self.linker_flags = [] self.cpp_defines = [] self.cpp_include_dirs = [] self.cpp_includes = [] self.cpp_source_files = [] self.cpp_topmosts = [] self.cpp_prologs = [] self.cpp_epilogs = [] self.exception_prolog = None self.exception_epilog = None self.lib_dirs = [] self.libs = [] self.kl_requires = [] self.kl_prologs = [] self.kl_epilogs = [] self.dfg_preset_dir = None self.dfg_preset_path = None self.decls = [] self.tests = [] self.cpp_type_expr_to_record = {} self.func_promotions = {} self.root_namespace = Namespace(self, None, [], None) for root_namespace_method in inspect.getmembers( self.root_namespace, predicate=inspect.ismethod, ): setattr(self, root_namespace_method[0], root_namespace_method[1]) tys = [ 'bool', 'char', 'int8_t', 'unsigned char', 'uint8_t', 'short', 'int16_t', 'unsigned short', 'uint16_t', 'int', 'int32_t', 'unsigned', 'uint32_t', 'long long', 'int64_t', 'unsigned long long', 'uint64_t', 'size_t', 'ptrdiff_t', 'intptr_t', 'float', 'double', 'std::string', 'char const *', 'void *', ] tys_d = [] for ty in tys: tys_d.append(ty) tys_d.append('std::vector< ' + ty + ' >') tys_d_d = [] for ty in tys_d: tys_d_d.append(ty) tys_d_d.append(ty + ' *') tys_d_d.append(ty + ' &') tys_d_d.append(ty + ' const *') tys_d_d.append(ty + ' const &') cpp_type_expr_parser = self.cpp_type_expr_parser self.kludge_ext_cpp_type_exprs = [] for ty in tys_d_d: self.kludge_ext_cpp_type_exprs.append( cpp_type_expr_parser.parse(ty))
def create_app(config="CTFd.config.Config"): app = CTFdFlask(__name__) with app.app_context(): app.config.from_object(config) loaders = [] # We provide a `DictLoader` which may be used to override templates app.overridden_templates = {} loaders.append(jinja2.DictLoader(app.overridden_templates)) # A `ThemeLoader` with no `theme_name` will load from the current theme loaders.append(ThemeLoader()) # If `THEME_FALLBACK` is set and true, we add another loader which will # load from the `DEFAULT_THEME` - this mirrors the order implemented by # `config.ctf_theme_candidates()` if bool(app.config.get("THEME_FALLBACK")): loaders.append(ThemeLoader(theme_name=DEFAULT_THEME)) # All themes including admin can be accessed by prefixing their name prefix_loader_dict = {ADMIN_THEME: ThemeLoader(theme_name=ADMIN_THEME)} for theme_name in CTFd.utils.config.get_themes(): prefix_loader_dict[theme_name] = ThemeLoader(theme_name=theme_name) loaders.append(jinja2.PrefixLoader(prefix_loader_dict)) # Plugin templates are also accessed via prefix but we just point a # normal `FileSystemLoader` at the plugin tree rather than validating # each plugin here (that happens later in `init_plugins()`). We # deliberately don't add this to `prefix_loader_dict` defined above # because to do so would break template loading from a theme called # `prefix` (even though that'd be weird). plugin_loader = jinja2.FileSystemLoader(searchpath=os.path.join( app.root_path, "plugins"), followlinks=True) loaders.append(jinja2.PrefixLoader({"plugins": plugin_loader})) # Use a choice loader to find the first match from our list of loaders app.jinja_loader = jinja2.ChoiceLoader(loaders) from CTFd.models import ( # noqa: F401 db, Teams, Solves, Challenges, Fails, Flags, Tags, Files, Tracking, ) url = create_database() # This allows any changes to the SQLALCHEMY_DATABASE_URI to get pushed back in # This is mostly so we can force MySQL's charset app.config["SQLALCHEMY_DATABASE_URI"] = str(url) # Register database db.init_app(app) # Register Flask-Migrate migrations.init_app(app, db) # Alembic sqlite support is lacking so we should just create_all anyway if url.drivername.startswith("sqlite"): # Enable foreign keys for SQLite. This must be before the # db.create_all call because tests use the in-memory SQLite # database (each connection, including db creation, is a new db). # https://docs.sqlalchemy.org/en/13/dialects/sqlite.html#foreign-key-support from sqlalchemy.engine import Engine from sqlalchemy import event @event.listens_for(Engine, "connect") def set_sqlite_pragma(dbapi_connection, connection_record): cursor = dbapi_connection.cursor() cursor.execute("PRAGMA foreign_keys=ON") cursor.close() db.create_all() stamp_latest_revision() else: # This creates tables instead of db.create_all() # Allows migrations to happen properly upgrade() from CTFd.models import ma ma.init_app(app) app.db = db app.VERSION = __version__ app.CHANNEL = __channel__ from CTFd.cache import cache cache.init_app(app) app.cache = cache reverse_proxy = app.config.get("REVERSE_PROXY") if reverse_proxy: if type(reverse_proxy) is str and "," in reverse_proxy: proxyfix_args = [int(i) for i in reverse_proxy.split(",")] app.wsgi_app = ProxyFix(app.wsgi_app, *proxyfix_args) else: app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_port=1, x_prefix=1) version = utils.get_config("ctf_version") # Upgrading from an older version of CTFd if version and (StrictVersion(version) < StrictVersion(__version__)): if confirm_upgrade(): run_upgrade() else: exit() if not version: utils.set_config("ctf_version", __version__) if not utils.get_config("ctf_theme"): utils.set_config("ctf_theme", DEFAULT_THEME) update_check(force=True) init_request_processors(app) init_template_filters(app) init_template_globals(app) # Importing here allows tests to use sensible names (e.g. api instead of api_bp) from CTFd.views import views from CTFd.teams import teams from CTFd.users import users from CTFd.challenges import challenges from CTFd.scoreboard import scoreboard from CTFd.auth import auth from CTFd.admin import admin from CTFd.api import api from CTFd.events import events from CTFd.errors import render_error app.register_blueprint(views) app.register_blueprint(teams) app.register_blueprint(users) app.register_blueprint(challenges) app.register_blueprint(scoreboard) app.register_blueprint(auth) app.register_blueprint(api) app.register_blueprint(events) app.register_blueprint(admin) for code in {403, 404, 500, 502}: app.register_error_handler(code, render_error) init_logs(app) init_events(app) init_plugins(app) return app
def _get_contents(self, permit_undefined_jinja, config): ''' Get the contents of our [meta.yaml|conda.yaml] file. If jinja is installed, then the template.render function is called before standard conda macro processors. permit_undefined_jinja: If True, *any* use of undefined jinja variables will evaluate to an emtpy string, without emitting an error. ''' try: import jinja2 except ImportError: print("There was an error importing jinja2.", file=sys.stderr) print("Please run `conda install jinja2` to enable jinja template support", file=sys.stderr) # noqa with open(self.meta_path) as fd: return fd.read() from conda_build.jinja_context import context_processor, UndefinedNeverFail, FilteredLoader path, filename = os.path.split(self.meta_path) loaders = [ # search relative to '<conda_root>/Lib/site-packages/conda_build/templates' jinja2.PackageLoader('conda_build'), # search relative to RECIPE_DIR jinja2.FileSystemLoader(path) ] # search relative to current conda environment directory conda_env_path = os.environ.get('CONDA_DEFAULT_ENV') # path to current conda environment if conda_env_path and os.path.isdir(conda_env_path): conda_env_path = os.path.abspath(conda_env_path) conda_env_path = conda_env_path.replace('\\', '/') # need unix-style path env_loader = jinja2.FileSystemLoader(conda_env_path) loaders.append(jinja2.PrefixLoader({'$CONDA_DEFAULT_ENV': env_loader})) undefined_type = jinja2.StrictUndefined if permit_undefined_jinja: # The UndefinedNeverFail class keeps a global list of all undefined names # Clear any leftover names from the last parse. UndefinedNeverFail.all_undefined_names = [] undefined_type = UndefinedNeverFail loader = FilteredLoader(jinja2.ChoiceLoader(loaders), config=config) env = jinja2.Environment(loader=loader, undefined=undefined_type) env.globals.update(ns_cfg(config)) env.globals.update(context_processor(self, path, config=config, permit_undefined_jinja=permit_undefined_jinja)) try: template = env.get_or_select_template(filename) rendered = template.render(environment=env) if permit_undefined_jinja: self.undefined_jinja_vars = UndefinedNeverFail.all_undefined_names else: self.undefined_jinja_vars = [] return rendered except jinja2.TemplateError as ex: if "'None' has not attribute" in str(ex): ex = "Failed to run jinja context function" sys.exit("Error: Failed to render jinja template in {}:\n{}" .format(self.meta_path, str(ex)))
# # You should have received a copy of the GNU Lesser General Public License # along with StarCluster. If not, see <http://www.gnu.org/licenses/>. import jinja2 import pkg_resources __all__ = [ 'config', 'sge', 'condor', 'user_msgs', ] _web_tmpl_loader = jinja2.Environment(loader=jinja2.PrefixLoader({ 'web': jinja2.PackageLoader('starcluster.templates', 'web'), })) get_web_template = _web_tmpl_loader.get_template _tmpl_loader = jinja2.Environment( loader=jinja2.PackageLoader('starcluster', 'templates')) get_template = _tmpl_loader.get_template def get_resource(pkg_data_path, stream=True): pkg_res_meth = pkg_resources.resource_filename if stream: pkg_res_meth = pkg_resources.resource_stream return pkg_res_meth('starcluster.templates', pkg_data_path)
def __init__(self, **kwargs): """ Constructor for the UVM Exporter class Parameters ---------- user_template_dir: str Path to a directory where user-defined template overrides are stored. user_template_context: dict Additional context variables to load into the template namespace. """ user_template_dir = kwargs.pop("user_template_dir", None) self.user_template_context = kwargs.pop("user_template_context", dict()) # Check for stray kwargs if kwargs: raise TypeError("got an unexpected keyword argument '%s'" % list(kwargs.keys())[0]) if user_template_dir: loader = jj.ChoiceLoader([ jj.FileSystemLoader(user_template_dir), jj.FileSystemLoader( os.path.join(os.path.dirname(__file__), "templates")), jj.PrefixLoader( { 'user': jj.FileSystemLoader(user_template_dir), 'base': jj.FileSystemLoader( os.path.join(os.path.dirname(__file__), "templates")) }, delimiter=":") ]) else: loader = jj.ChoiceLoader([ jj.FileSystemLoader( os.path.join(os.path.dirname(__file__), "templates")), jj.PrefixLoader( { 'base': jj.FileSystemLoader( os.path.join(os.path.dirname(__file__), "templates")) }, delimiter=":") ]) self.jj_env = jj.Environment(loader=loader, undefined=jj.StrictUndefined) # Define variables used during export # Top-level node self.top = None # Dictionary of group-like nodes (addrmap, regfile) and their bus # widths. # key = node path # value = max accesswidth/memwidth used in node's descendants self.bus_width_db = {} # Dictionary of root-level type definitions # key = definition type name # value = representative object # components, this is the original_def (which can be None in some cases) self.namespace_db = {} self.reuse_class_definitions = True
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.jinja_loader = jinja2.ChoiceLoader( [self.jinja_loader, jinja2.PrefixLoader({}, delimiter='.')])
def __init__(self, **kwargs): """ Constructor for the Verilog Exporter class Parameters ---------- user_template_dir: str Path to a directory where user-defined template overrides are stored. user_template_context: dict Additional context variables to load into the template namespace. """ user_template_dir = kwargs.pop("user_template_dir", None) self.user_template_context = kwargs.pop("user_template_context", dict()) self.signal_overrides = {} self.strict = False # strict RDL rules rather than helpful impliciti behaviour # Check for stray kwargs if kwargs: raise TypeError("got an unexpected keyword argument '%s'" % list(kwargs.keys())[0]) if user_template_dir: loader = jj.ChoiceLoader([ jj.FileSystemLoader(user_template_dir), jj.FileSystemLoader( os.path.join(os.path.dirname(__file__), "templates")), jj.PrefixLoader( { 'user': jj.FileSystemLoader(user_template_dir), 'base': jj.FileSystemLoader( os.path.join(os.path.dirname(__file__), "templates")) }, delimiter=":") ]) else: loader = jj.ChoiceLoader([ jj.FileSystemLoader( os.path.join(os.path.dirname(__file__), "templates")), jj.PrefixLoader( { 'base': jj.FileSystemLoader( os.path.join(os.path.dirname(__file__), "templates")) }, delimiter=":") ]) self.jj_env = jj.Environment(loader=loader, undefined=jj.StrictUndefined) # Define custom filters and tests def add_filter(func): self.jj_env.filters[func.__name__] = func def add_test(func, name=None): name = name or func.__name__.replace('is_', '') self.jj_env.tests[name] = func add_filter(self.full_array_dimensions) add_filter(self.full_array_ranges) add_filter(self.full_array_indexes) add_filter(self.bit_range) add_test(self.has_intr, 'intr') add_test(self.has_halt, 'halt') add_test(self.has_we, 'with_we') add_test(self.is_hw_writable) add_test(self.is_hw_readable) add_test(self.is_up_counter) add_test(self.is_down_counter) # Top-level node self.top = None # Dictionary of group-like nodes (addrmap, regfile) and their bus # widths. # key = node path # value = max accesswidth/memwidth used in node's descendants self.bus_width_db = {} # Dictionary of root-level type definitions # key = definition type name # value = representative object # components, this is the original_def (which can be None in some cases) self.namespace_db = {}
def load_workflows(self): """Attempts to load the workflow config files from the workflows directory which is defined in app.config['WORKFLOWS_DIR']. Each config file is loaded and the display name stored""" # Where to store workflow settings self.wfsettings = {} # Ensure that we have a directory if not os.path.isdir(self.config['WORKFLOWS_DIR']): self.logger.error("Workflows: The config option WORKFLOWS_DIR is not a directory!") return # List all entries in the directory and iterate over them entries = os.listdir(self.config['WORKFLOWS_DIR']) found = False for entry in entries: # Ignore the . and .. entries, along with any hidden files if entry.startswith('.'): continue # Get the fully qualified path of the file fqp = os.path.join(self.config['WORKFLOWS_DIR'], entry) # If it's a directory... if os.path.isdir(fqp): # This is or rather should be a workflow directory found = True self.logger.info("Workflows: Loading workflow '" + entry + "'") views_file = os.path.join(fqp, "views.py") self.logger.info("Loading " + entry + " from " + views_file) try: view_module = imp.load_source(entry, views_file) self.logger.info("Workflows: Finished loading workflow '" + entry + "'") except Exception as ex: self.logger.warn("Workflows: Could not load from file " + views_file + ": " + str(type(ex)) + " - " + str(ex)) self.logger.warn(traceback.format_exc()) continue # Warn if we didn't find any workflows if not found: self.logger.warn("Workflows: The WORKFLOWS_DIR directory is empty (no workflows exist)") # Set up template loading. Firstly build a list of FileSystemLoaders # that will process templates in each workflows' templates directory loader_data = {} wflist = self.wf_functions + self.wf_system_functions for workflow in wflist: template_dir = os.path.join(self.config['WORKFLOWS_DIR'], workflow['workflow'], 'templates') loader_data[workflow['workflow']] = jinja2.FileSystemLoader(template_dir) # Create a ChoiceLoader, which by default will use the default # template loader, and if that fails, uses a PrefixLoader which # can check the workflow template directories choice_loader = jinja2.ChoiceLoader( [ self.jinja_loader, jinja2.PrefixLoader(loader_data, '::') ]) self.jinja_loader = choice_loader
import jinja2 from flask import url_for from flask_debugtoolbar.panels import DebugPanel template_loader = jinja2.PrefixLoader( {'sql': jinja2.PackageLoader(__name__, 'templates/sql')}) class SqlSenderPanel(DebugPanel): name = 'SqlSender' has_content = True def __init__(self, jinja_env, context=None): if context is None: context = {} DebugPanel.__init__(self, jinja_env, context=context) self.jinja_env.loader = jinja2.ChoiceLoader( [self.jinja_env.loader, template_loader]) self.data = None def nav_title(self): return 'Sql Sender' def title(self): return 'Sql Sender' def url(self): return '' def nav_subtitle(self):