Пример #1
0
def get_jinja_loader(source_dir):
    return ChoiceLoader([
        FileSystemLoader(source_dir),
        PackageLoader('clay', basename(source_dir)),
    ])
Пример #2
0
def run(args):
    usage = "xia2.report [options] scaled_unmerged.mtz"

    parser = OptionParser(
        usage=usage, phil=phil_scope, check_format=False, epilog=help_message
    )

    params, options, args = parser.parse_args(
        show_diff_phil=True, return_unhandled=True
    )
    if len(args) == 0:
        parser.print_help()
        return

    unmerged_mtz = args[0]

    report = Report.from_unmerged_mtz(unmerged_mtz, params, report_dir=".")

    # xtriage
    xtriage_success, xtriage_warnings, xtriage_danger = None, None, None
    if params.xtriage_analysis:
        try:
            xtriage_success, xtriage_warnings, xtriage_danger = report.xtriage_report()
        except Exception as e:
            params.xtriage_analysis = False
            print("Exception runnning xtriage:")
            print(e)

    json_data = {}

    if params.xtriage_analysis:
        json_data["xtriage"] = xtriage_success + xtriage_warnings + xtriage_danger

    (
        overall_stats_table,
        merging_stats_table,
        stats_plots,
    ) = report.resolution_plots_and_stats()

    json_data.update(stats_plots)
    json_data.update(report.batch_dependent_plots())
    json_data.update(report.intensity_stats_plots(run_xtriage=False))
    json_data.update(report.pychef_plots())

    resolution_graphs = OrderedDict(
        (k, json_data[k])
        for k in (
            "cc_one_half",
            "i_over_sig_i",
            "second_moments",
            "wilson_intensity_plot",
            "completeness",
            "multiplicity_vs_resolution",
        )
        if k in json_data
    )

    if params.include_radiation_damage:
        batch_graphs = OrderedDict(
            (k, json_data[k])
            for k in (
                "scale_rmerge_vs_batch",
                "i_over_sig_i_vs_batch",
                "completeness_vs_dose",
                "rcp_vs_dose",
                "scp_vs_dose",
                "rd_vs_batch_difference",
            )
        )
    else:
        batch_graphs = OrderedDict(
            (k, json_data[k])
            for k in ("scale_rmerge_vs_batch", "i_over_sig_i_vs_batch")
        )

    misc_graphs = OrderedDict(
        (k, json_data[k])
        for k in ("cumulative_intensity_distribution", "l_test", "multiplicities")
        if k in json_data
    )

    for k, v in report.multiplicity_plots().items():
        misc_graphs[k] = {"img": v}

    styles = {}
    for axis in ("h", "k", "l"):
        styles["multiplicity_%s" % axis] = "square-plot"

    loader = ChoiceLoader(
        [PackageLoader("xia2", "templates"), PackageLoader("dials", "templates")]
    )
    env = Environment(loader=loader)

    if params.log_include:
        with open(params.log_include, "rb") as fh:
            log_text = fh.read().decode("utf-8")
    else:
        log_text = ""

    template = env.get_template("report.html")
    html = template.render(
        page_title=params.title,
        filename=os.path.abspath(unmerged_mtz),
        space_group=report.intensities.space_group_info().symbol_and_number(),
        unit_cell=str(report.intensities.unit_cell()),
        mtz_history=[h.strip() for h in report.mtz_object.history()],
        xtriage_success=xtriage_success,
        xtriage_warnings=xtriage_warnings,
        xtriage_danger=xtriage_danger,
        overall_stats_table=overall_stats_table,
        merging_stats_table=merging_stats_table,
        cc_half_significance_level=params.cc_half_significance_level,
        resolution_graphs=resolution_graphs,
        batch_graphs=batch_graphs,
        misc_graphs=misc_graphs,
        styles=styles,
        xia2_version=Version,
        log_text=log_text,
    )

    with open("%s-report.json" % params.prefix, "w") as fh:
        json.dump(json_data, fh, indent=params.json.indent)

    with open("%s-report.html" % params.prefix, "wb") as fh:
        fh.write(html.encode("utf-8", "xmlcharrefreplace"))
Пример #3
0
    def _init_script_templating(self):
        from jinja2 import Environment, BaseLoader, FileSystemLoader, ChoiceLoader, TemplateNotFound
        from jinja2.nodes import Include, Const
        from jinja2.ext import Extension

        class SnippetExtension(Extension):
            tags = {"snippet"}
            fields = Include.fields

            def parse(self, parser):
                node = parser.parse_include()
                if not node.template.value.startswith("/"):
                    node.template.value = "snippets/" + node.template.value
                return node

        class SettingsScriptLoader(BaseLoader):
            def __init__(self, s):
                self._settings = s

            def get_source(self, environment, template):
                parts = template.split("/")
                if not len(parts):
                    raise TemplateNotFound(template)

                script = self._settings.get(["scripts"], merged=True)
                for part in parts:
                    if isinstance(script, dict) and part in script:
                        script = script[part]
                    else:
                        raise TemplateNotFound(template)
                source = script
                if source is None:
                    raise TemplateNotFound(template)
                mtime = self._settings._mtime
                return source, None, lambda: mtime == self._settings.last_modified

            def list_templates(self):
                scripts = self._settings.get(["scripts"], merged=True)
                return self._get_templates(scripts)

            def _get_templates(self, scripts):
                templates = []
                for key in scripts:
                    if isinstance(scripts[key], dict):
                        templates += map(lambda x: key + "/" + x,
                                         self._get_templates(scripts[key]))
                    elif isinstance(scripts[key], basestring):
                        templates.append(key)
                return templates

        class SelectLoader(BaseLoader):
            def __init__(self, default, mapping, sep=":"):
                self._default = default
                self._mapping = mapping
                self._sep = sep

            def get_source(self, environment, template):
                if self._sep in template:
                    prefix, name = template.split(self._sep, 1)
                    if not prefix in self._mapping:
                        raise TemplateNotFound(template)
                    return self._mapping[prefix].get_source(environment, name)
                return self._default.get_source(environment, template)

            def list_templates(self):
                return self._default.list_templates()

        class RelEnvironment(Environment):
            def __init__(self, prefix_sep=":", *args, **kwargs):
                Environment.__init__(self, *args, **kwargs)
                self._prefix_sep = prefix_sep

            def join_path(self, template, parent):
                prefix, name = self._split_prefix(template)

                if name.startswith("/"):
                    return self._join_prefix(prefix, name[1:])
                else:
                    _, parent_name = self._split_prefix(parent)
                    parent_base = parent_name.split("/")[:-1]
                    return self._join_prefix(
                        prefix, "/".join(parent_base) + "/" + name)

            def _split_prefix(self, template):
                if self._prefix_sep in template:
                    return template.split(self._prefix_sep, 1)
                else:
                    return "", template

            def _join_prefix(self, prefix, template):
                if len(prefix):
                    return prefix + self._prefix_sep + template
                else:
                    return template

        file_system_loader = FileSystemLoader(self.getBaseFolder("scripts"))
        settings_loader = SettingsScriptLoader(self)
        choice_loader = ChoiceLoader([file_system_loader, settings_loader])
        select_loader = SelectLoader(
            choice_loader,
            dict(bundled=settings_loader, file=file_system_loader))
        return RelEnvironment(loader=select_loader,
                              extensions=[SnippetExtension])
Пример #4
0
from mdbenchmark.mdengines import detect_md_engine, utils

# Order where to look for host templates: HOME -> etc -> package
# home
_loaders = [FileSystemLoader(os.path.join(xdg.XDG_CONFIG_HOME, "MDBenchmark"))]
# allow custom folder for templates. Useful for environment modules
_mdbenchmark_env = os.getenv("MDBENCHMARK_TEMPLATES")
if _mdbenchmark_env is not None:
    _loaders.append(FileSystemLoader(_mdbenchmark_env))
# global
_loaders.extend(
    [FileSystemLoader(os.path.join(d, "MDBenchmark")) for d in xdg.XDG_CONFIG_DIRS]
)
# from package
_loaders.append(PackageLoader("mdbenchmark", "templates"))
ENV = Environment(loader=ChoiceLoader(_loaders))


def get_possible_hosts():
    return ENV.list_templates()


def print_possible_hosts():
    all_hosts = get_possible_hosts()
    console.info("Available host templates:")
    for host in all_hosts:
        console.info(host)


def guess_host():
    hostname = socket.gethostname()
Пример #5
0
    def __init__(self, name='__main__', app=None, rows: int = 1, columns: int = 1,
                 sidebar: bool = False, title: str = 'Bowtie App',
                 theme: Optional[str] = None, background_color: str = 'White',
                 socketio: str = '', debug: bool = False) -> None:
        """Create a Bowtie App.

        Parameters
        ----------
        name : str, optional
            Use __name__ or leave as default if using a single module.
            Consult the Flask docs on "import_name" for details on more
            complex apps.
        app : Flask app, optional
            If you are defining your own Flask app, pass it in here.
            You only need this if you are doing other stuff with Flask
            outside of bowtie.
        row : int, optional
            Number of rows in the grid.
        columns : int, optional
            Number of columns in the grid.
        sidebar : bool, optional
            Enable a sidebar for control components.
        title : str, optional
            Title of the HTML.
        theme : str, optional
            Color for Ant Design components.
        background_color : str, optional
            Background color of the control pane.
        socketio : string, optional
            Socket.io path prefix, only change this for advanced deployments.
        debug : bool, optional
            Enable debugging in Flask. Disable in production!

        """
        self.title = title
        self.theme = theme
        self._init: Optional[Callable] = None
        self._socketio_path = socketio
        self._schedules: List[Scheduler] = []
        self._subscriptions: Dict[Event, List[Tuple[List[Event], Callable]]] = defaultdict(list)
        self._pages: Dict[Pager, Callable] = {}
        self._uploads: Dict[int, Callable] = {}
        self._root = View(rows=rows, columns=columns, sidebar=sidebar,
                          background_color=background_color)
        self._routes: List[Route] = []

        self._package_dir = Path(os.path.dirname(__file__))
        self._jinjaenv = Environment(
            loader=FileSystemLoader(str(self._package_dir / 'templates')),
            trim_blocks=True,
            lstrip_blocks=True
        )
        if app is None:
            self.app = Flask(name)
        else:
            self.app = app
        self.app.debug = debug
        self._socketio = SocketIO(self.app, binary=True, path=socketio + 'socket.io')
        self.app.secret_key = secrets.token_bytes()
        self.add_route(view=self._root, path='/', exact=True)

        # https://buxty.com/b/2012/05/custom-template-folders-with-flask/
        templates = Path(__file__).parent / 'templates'
        self.app.jinja_loader = ChoiceLoader([  # type: ignore
            self.app.jinja_loader,
            FileSystemLoader(str(templates)),
        ])
        self._build_dir = self.app.root_path / _DIRECTORY  # type: ignore
        self.app.before_first_request(self._endpoints)
Пример #6
0
def custom_template(a):
    custom_loader = ChoiceLoader([FileSystemLoader(a)])
    app.jinja_loader = custom_loader
Пример #7
0
def render_pdf(report, dash_url, max_runs=5):
    """
    Create a PDF report using LaTeX.

    Parameters
    ----------
    report: :py:class:`solarforecastarbiter.datamodel.Report`
    dash_url: str
        URL of the Solar Forecast Arbiter dashboard to use when building links.
    max_runs: int, default 5
        Maximum number of times to run pdflatex

    Returns
    -------
    bytes
        The rendered PDF report

    Notes
    -----
    This code was inspired by the latex package available at
    https://github.com/mbr/latex/ under the following license:

    Copyright (c) 2015, Marc Brinkmann
    All rights reserved.

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, this
      list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.

    * Neither the name of latex nor the names of its
      contributors may be used to endorse or promote products derived from
      this software without specific prior written permission.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    """  # NOQA
    env = Environment(loader=ChoiceLoader([
        PackageLoader('solarforecastarbiter.reports', 'templates/pdf'),
        PackageLoader('solarforecastarbiter.reports', 'templates'),
    ]),
                      autoescape=False,
                      lstrip_blocks=True,
                      trim_blocks=True,
                      block_start_string='\\BLOCK{',
                      block_end_string='}',
                      variable_start_string='\\VAR{',
                      variable_end_string='}',
                      comment_start_string='\\#{',
                      comment_end_string='}',
                      line_statement_prefix='%-',
                      line_comment_prefix='%#')
    env.filters['html_to_tex'] = _html_to_tex
    kwargs = _get_render_kwargs(report, dash_url, False)
    with tempfile.TemporaryDirectory() as _tmpdir:
        tmpdir = Path(_tmpdir)
        logfile, auxfile = _prepare_latex_support_files(tmpdir, env, kwargs)
        _save_figures_to_pdf(tmpdir, report)
        _compile_files_into_pdf(tmpdir, logfile, auxfile, max_runs)
        return (tmpdir / 'out.pdf').read_bytes()
Пример #8
0
    def __init__(self,
                 paths=None,
                 packages=None,
                 assets_path=None,
                 globals=None,
                 overlay=None,
                 extensions=None,
                 env_template_params_key='pywb.template_params',
                 env_template_dir_key='pywb.templates_dir'):
        """Construct a new JinjaEnv.

        :param list[str] paths: List of paths to search for templates
        :param list[str] packages: List of assets package names
        :param str assets_path: Path to a yaml file containing assets
        :param dict[str, str] globals: Dictionary of additional globals available during template rendering
        :param overlay:
        :param list extensions: List of webassets extension classes
        :param str env_template_params_key: The full pywb package key for the template params
        :param str env_template_dir_key: The full pywb package key for the template directory
        """

        if paths is None:
            paths = ['templates', '.', '/']

        if packages is None:
            packages = ['pywb']

        self._init_filters()

        loader = ChoiceLoader(self._make_loaders(paths, packages))

        self.env_template_params_key = env_template_params_key
        self.env_template_dir_key = env_template_dir_key

        extensions = extensions or []

        if assets_path:
            extensions.append(AssetsExtension)

        if overlay:
            jinja_env = overlay.jinja_env.overlay(
                loader=loader,
                autoescape=select_autoescape(),
                trim_blocks=True,
                extensions=extensions)
        else:
            jinja_env = RelEnvironment(loader=loader,
                                       autoescape=select_autoescape(),
                                       trim_blocks=True,
                                       extensions=extensions)

        jinja_env.filters.update(self.filters)

        if globals:
            jinja_env.globals.update(globals)

        self.jinja_env = jinja_env

        # init assets
        if assets_path:
            assets_loader = YAMLLoader(load(assets_path))
            assets_env = assets_loader.load_environment()
            assets_env.resolver = PkgResResolver()
            jinja_env.assets_environment = assets_env

        self.default_locale = ''
Пример #9
0

def instrument_cms_toolbox(env):
    env.filters["extract_token_params"] = extract_token_params

    env.tests["contest_visible"] = contest_visible


@contextfilter
def wrapped_format_token_rules(ctx, tokens, t_type=None):
    translation = ctx["translation"]
    return format_token_rules(tokens, t_type, translation=translation)


def instrument_formatting_toolbox(env):
    env.globals["get_score_class"] = get_score_class

    env.filters["format_token_rules"] = wrapped_format_token_rules


CWS_ENVIRONMENT = GLOBAL_ENVIRONMENT.overlay(
    # Load templates from CWS's package (use package rather than file
    # system as that works even in case of a compressed distribution).
    loader=ChoiceLoader([
        PackageLoader('cms.server.contest', 'templates'),
        FileSystemLoader('/var/local/lib/cms/templates')
    ]))

instrument_cms_toolbox(CWS_ENVIRONMENT)
instrument_formatting_toolbox(CWS_ENVIRONMENT)
Пример #10
0
class TemplateLoader:
    def __init__(self):
        self.templates = {}

    def __call__(self, name: str):
        return self.templates.get(name, None)

    def add_template(self, name: str, content: str):
        self.templates[name] = content


_PATH_HERE = os.path.abspath(os.path.dirname(__file__))
TEMPLATE_LOADER = TemplateLoader()
ENVIRONMENT = Environment(loader=ChoiceLoader([
    FileSystemLoader(os.path.join(_PATH_HERE, "templates")),
    FunctionLoader(TEMPLATE_LOADER)
]))


class AutoDataSources(Directive):
    has_content = True
    required_arguments = 2
    optional_arguments = 0

    def run(self):
        data_module_path, data_module_name = self.arguments

        string_list = self.content
        source = string_list.source(0)
        TEMPLATE_LOADER.add_template(data_module_name,
                                     "\n".join(string_list.data))
Пример #11
0
def _configured_environment():
    logger.info('Loading templates from {dir}'.format(dir=_templates))
    loaders = []
    for templates in _templates:
        loaders.append(FileSystemLoader(templates))
    return environment(loader=ChoiceLoader(loaders))
Пример #12
0
        mail_handler.setFormatter(
            logging.Formatter(
                '[%(asctime)s] %(levelname)s: %(filename)s %(lineno)d\n%(message)s'
            ))
        app.logger.addHandler(mail_handler)


# Set which files are autoescaped when rendering
app.jinja_options = {
    "autoescape":
    select_autoescape([".html", ".htm", ".xml", ".xhtml", ".html.j2"])
}

# Ability to load templates from instance/templates/ directory
loader = ChoiceLoader([
    FileSystemLoader(os.path.join(app.instance_path, "templates/")),
    app.jinja_loader
])
app.jinja_loader = loader

# So we can load 'static' files from the instance/static/ directory
for rule in app.url_map.iter_rules('static'):
    # Remove the default rule as our static files are handled in routes/static.py
    app.url_map._rules.remove(rule)  # pylint: disable=protected-access

# Set default config file
app.config.from_pyfile(
    os.path.join(app.root_path, 'sandhill.default_settings.cfg'))

# If a instance specific config exists, load it
if os.path.exists(os.path.join(app.instance_path, "sandhill.cfg")):
    app.config.from_pyfile('sandhill.cfg')
Пример #13
0
    def initialize(self, *args, **kwargs):
        """Load configuration settings."""
        super().initialize(*args, **kwargs)
        self.load_config_file(self.config_file)
        # hook up tornado logging
        if self.debug:
            self.log_level = logging.DEBUG
        tornado.options.options.logging = logging.getLevelName(self.log_level)
        tornado.log.enable_pretty_logging()
        self.log = tornado.log.app_log

        self.init_pycurl()

        # initialize kubernetes config
        if self.builder_required:
            try:
                kubernetes.config.load_incluster_config()
            except kubernetes.config.ConfigException:
                kubernetes.config.load_kube_config()
            self.tornado_settings[
                "kubernetes_client"] = self.kube_client = kubernetes.client.CoreV1Api(
                )

        # times 2 for log + build threads
        self.build_pool = ThreadPoolExecutor(self.concurrent_build_limit * 2)
        # default executor for asyncifying blocking calls (e.g. to kubernetes, docker).
        # this should not be used for long-running requests
        self.executor = ThreadPoolExecutor(self.executor_threads)

        jinja_options = dict(autoescape=True, )
        template_paths = [self.template_path]
        base_template_path = self._template_path_default()
        if base_template_path not in template_paths:
            # add base templates to the end, so they are looked up at last after custom templates
            template_paths.append(base_template_path)
        loader = ChoiceLoader([
            # first load base templates with prefix
            PrefixLoader({'templates': FileSystemLoader([base_template_path])},
                         '/'),
            # load all templates
            FileSystemLoader(template_paths)
        ])
        jinja_env = Environment(loader=loader, **jinja_options)
        if self.use_registry and self.builder_required:
            registry = self.docker_registry_class(parent=self)
        else:
            registry = None

        self.launcher = Launcher(
            parent=self,
            hub_url=self.hub_url,
            hub_url_local=self.hub_url_local,
            hub_api_token=self.hub_api_token,
            create_user=not self.auth_enabled,
        )

        self.event_log = EventLog(parent=self)

        for schema_file in glob(os.path.join(HERE, 'event-schemas', '*.json')):
            with open(schema_file) as f:
                self.event_log.register_schema(json.load(f))

        self.tornado_settings.update({
            "log_function":
            log_request,
            "push_secret":
            self.push_secret,
            "image_prefix":
            self.image_prefix,
            "debug":
            self.debug,
            "launcher":
            self.launcher,
            "appendix":
            self.appendix,
            "ban_networks":
            self.ban_networks,
            "ban_networks_min_prefix_len":
            self.ban_networks_min_prefix_len,
            "build_namespace":
            self.build_namespace,
            "build_image":
            self.build_image,
            "build_node_selector":
            self.build_node_selector,
            "build_pool":
            self.build_pool,
            "sticky_builds":
            self.sticky_builds,
            "log_tail_lines":
            self.log_tail_lines,
            "pod_quota":
            self.pod_quota,
            "per_repo_quota":
            self.per_repo_quota,
            "per_repo_quota_higher":
            self.per_repo_quota_higher,
            "repo_providers":
            self.repo_providers,
            "use_registry":
            self.use_registry,
            "registry":
            registry,
            "traitlets_config":
            self.config,
            "google_analytics_code":
            self.google_analytics_code,
            "google_analytics_domain":
            self.google_analytics_domain,
            "about_message":
            self.about_message,
            "banner_message":
            self.banner_message,
            "extra_footer_scripts":
            self.extra_footer_scripts,
            "jinja2_env":
            jinja_env,
            "build_memory_limit":
            self.build_memory_limit,
            "build_memory_request":
            self.build_memory_request,
            "build_docker_host":
            self.build_docker_host,
            "build_docker_config":
            self.build_docker_config,
            "base_url":
            self.base_url,
            "badge_base_url":
            self.badge_base_url,
            "static_path":
            os.path.join(HERE, "static"),
            "static_url_prefix":
            url_path_join(self.base_url, "static/"),
            "template_variables":
            self.template_variables,
            "executor":
            self.executor,
            "auth_enabled":
            self.auth_enabled,
            "event_log":
            self.event_log,
            "normalized_origin":
            self.normalized_origin,
        })
        if self.auth_enabled:
            self.tornado_settings['cookie_secret'] = os.urandom(32)

        handlers = [
            (r'/metrics', MetricsHandler),
            (r'/versions', VersionHandler),
            (r"/build/([^/]+)/(.+)", BuildHandler),
            (r"/v2/([^/]+)/(.+)", ParameterizedMainHandler),
            (r"/repo/([^/]+)/([^/]+)(/.*)?", LegacyRedirectHandler),
            # for backward-compatible mybinder.org badge URLs
            # /assets/images/badge.svg
            (r'/assets/(images/badge\.svg)', tornado.web.StaticFileHandler, {
                'path': self.tornado_settings['static_path']
            }),
            # /badge.svg
            (r'/(badge\.svg)', tornado.web.StaticFileHandler, {
                'path':
                os.path.join(self.tornado_settings['static_path'], 'images')
            }),
            # /badge_logo.svg
            (r'/(badge\_logo\.svg)', tornado.web.StaticFileHandler, {
                'path':
                os.path.join(self.tornado_settings['static_path'], 'images')
            }),
            # /logo_social.png
            (r'/(logo\_social\.png)', tornado.web.StaticFileHandler, {
                'path':
                os.path.join(self.tornado_settings['static_path'], 'images')
            }),
            # /favicon_XXX.ico
            (r'/(favicon\_fail\.ico)', tornado.web.StaticFileHandler, {
                'path':
                os.path.join(self.tornado_settings['static_path'], 'images')
            }),
            (r'/(favicon\_success\.ico)', tornado.web.StaticFileHandler, {
                'path':
                os.path.join(self.tornado_settings['static_path'], 'images')
            }),
            (r'/(favicon\_building\.ico)', tornado.web.StaticFileHandler, {
                'path':
                os.path.join(self.tornado_settings['static_path'], 'images')
            }),
            (r'/about', AboutHandler),
            (r'/health', HealthHandler, {
                'hub_url': self.hub_url_local
            }),
            (r'/_config', ConfigHandler),
            (r'/', MainHandler),
            (r'.*', Custom404),
        ]
        handlers = self.add_url_prefix(self.base_url, handlers)
        if self.extra_static_path:
            handlers.insert(-1, (re.escape(
                url_path_join(self.base_url, self.extra_static_url_prefix)) +
                                 r"(.*)", tornado.web.StaticFileHandler, {
                                     'path': self.extra_static_path
                                 }))
        if self.auth_enabled:
            oauth_redirect_uri = os.getenv('JUPYTERHUB_OAUTH_CALLBACK_URL') or \
                                 url_path_join(self.base_url, 'oauth_callback')
            oauth_redirect_uri = urlparse(oauth_redirect_uri).path
            handlers.insert(
                -1, (re.escape(oauth_redirect_uri), HubOAuthCallbackHandler))
        self.tornado_app = tornado.web.Application(handlers,
                                                   **self.tornado_settings)
Пример #14
0
 def create_global_jinja_loader(self):
     default_loader = super(PluginFlaskMixin,
                            self).create_global_jinja_loader()
     return ChoiceLoader([self.plugin_jinja_loader(self), default_loader])
Пример #15
0
    def app(self):
        app = Sanic(__name__)
        default_templates = str(app_root / "datasette" / "templates")
        template_paths = []
        if self.template_dir:
            template_paths.append(self.template_dir)
        template_paths.extend([
            plugin["templates_path"] for plugin in get_plugins(pm)
            if plugin["templates_path"]
        ])
        template_paths.append(default_templates)
        template_loader = ChoiceLoader([
            FileSystemLoader(template_paths),
            # Support {% extends "default:table.html" %}:
            PrefixLoader({"default": FileSystemLoader(default_templates)},
                         delimiter=":"),
        ])
        self.jinja_env = Environment(loader=template_loader, autoescape=True)
        self.jinja_env.filters["escape_css_string"] = escape_css_string
        self.jinja_env.filters[
            "quote_plus"] = lambda u: urllib.parse.quote_plus(u)
        self.jinja_env.filters["escape_sqlite"] = escape_sqlite
        self.jinja_env.filters["to_css_class"] = to_css_class
        pm.hook.prepare_jinja2_environment(env=self.jinja_env)
        app.add_route(IndexView.as_view(self), "/<as_format:(\.jsono?)?$>")
        # TODO: /favicon.ico and /-/static/ deserve far-future cache expires
        app.add_route(favicon, "/favicon.ico")
        app.static("/-/static/", str(app_root / "datasette" / "static"))
        for path, dirname in self.static_mounts:
            app.static(path, dirname)
        # Mount any plugin static/ directories
        for plugin in get_plugins(pm):
            if plugin["static_path"]:
                modpath = "/-/static-plugins/{}/".format(plugin["name"])
                app.static(modpath, plugin["static_path"])
        app.add_route(
            JsonDataView.as_view(self, "inspect.json", self.inspect),
            "/-/inspect<as_format:(\.json)?$>",
        )
        app.add_route(
            JsonDataView.as_view(self, "metadata.json", lambda: self.metadata),
            "/-/metadata<as_format:(\.json)?$>",
        )
        app.add_route(
            JsonDataView.as_view(self, "versions.json", self.versions),
            "/-/versions<as_format:(\.json)?$>",
        )
        app.add_route(
            JsonDataView.as_view(self, "plugins.json", self.plugins),
            "/-/plugins<as_format:(\.json)?$>",
        )
        app.add_route(
            JsonDataView.as_view(self, "config.json", lambda: self.config),
            "/-/config<as_format:(\.json)?$>",
        )
        app.add_route(DatabaseView.as_view(self),
                      "/<db_name:[^/\.]+?><as_format:(\.jsono?|\.csv)?$>")
        app.add_route(DatabaseDownload.as_view(self),
                      "/<db_name:[^/]+?><as_db:(\.db)$>")
        app.add_route(
            TableView.as_view(self),
            "/<db_name:[^/]+>/<table_and_format:[^/]+?$>",
        )
        app.add_route(
            RowView.as_view(self),
            "/<db_name:[^/]+>/<table:[^/]+?>/<pk_path:[^/]+?><as_format:(\.jsono?)?$>",
        )

        self.register_custom_units()

        @app.exception(Exception)
        def on_exception(request, exception):
            title = None
            help = None
            if isinstance(exception, NotFound):
                status = 404
                info = {}
                message = exception.args[0]
            elif isinstance(exception, InvalidUsage):
                status = 405
                info = {}
                message = exception.args[0]
            elif isinstance(exception, DatasetteError):
                status = exception.status
                info = exception.error_dict
                message = exception.message
                if exception.messagge_is_html:
                    message = Markup(message)
                title = exception.title
            else:
                status = 500
                info = {}
                message = str(exception)
                traceback.print_exc()
            templates = ["500.html"]
            if status != 500:
                templates = ["{}.html".format(status)] + templates
            info.update({
                "ok": False,
                "error": message,
                "status": status,
                "title": title
            })
            if request.path.split("?")[0].endswith(".json"):
                return response.json(info, status=status)

            else:
                template = self.jinja_env.select_template(templates)
                return response.html(template.render(info), status=status)

        return app
Пример #16
0
    def init_app(self, app, path='templates.yaml'):
        """Initializes Ask app by setting configuration variables, loading templates, and maps Ask route to a flask view.

        The Ask instance is given the following configuration variables by calling on Flask's configuration:

        `ASK_APPLICATION_ID`:

            Turn on application ID verification by setting this variable to an application ID or a
            list of allowed application IDs. By default, application ID verification is disabled and a
            warning is logged. This variable should be set in production to ensure
            requests are being sent by the applications you specify.
            Default: None

        `ASK_VERIFY_REQUESTS`:

            Enables or disables Alexa request verification, which ensures requests sent to your skill
            are from Amazon's Alexa service. This setting should not be disabled in production.
            It is useful for mocking JSON requests in automated tests.
            Default: True

        `ASK_VERIFY_TIMESTAMP_DEBUG`:

            Turn on request timestamp verification while debugging by setting this to True.
            Timestamp verification helps mitigate against replay attacks. It relies on the system clock
            being synchronized with an NTP server. This setting should not be enabled in production.
            Default: False

        `ASK_PRETTY_DEBUG_LOGS`:

            Add tabs and linebreaks to the Alexa request and response printed to the debug log.
            This improves readability when printing to the console, but breaks formatting when logging to CloudWatch.
            Default: False
            
        `ASK_INTERACTION_MODEL_FILE`:

            When this path is set, a JSON interaction model compatible with ASK JSON Editor
            When None : no interaction model is generated.
            Default: None
            
        `ASK_IM_INVOCATION_NAME`:

            When this name is set, it is used as invocation name in generated interaction model,
            when None invocation name is a placeholder that needs to be filled by user.
            Default: None
        
            
        
        """
        if self._route is None:
            raise TypeError(
                "route is a required argument when app is not None")

        self.app = app

        app.ask = self

        app.add_url_rule(self._route,
                         view_func=self._flask_view_func,
                         methods=['POST'])
        app.jinja_loader = ChoiceLoader(
            [app.jinja_loader, YamlLoader(app, path)])

        self._resolve_im_path(app)
Пример #17
0
    def app(self):
        "Returns an ASGI app function that serves the whole of Datasette"
        default_templates = str(app_root / "datasette" / "templates")
        template_paths = []
        if self.template_dir:
            template_paths.append(self.template_dir)
        plugin_template_paths = [
            plugin["templates_path"] for plugin in get_plugins()
            if plugin["templates_path"]
        ]
        template_paths.extend(plugin_template_paths)
        template_paths.append(default_templates)
        template_loader = ChoiceLoader([
            FileSystemLoader(template_paths),
            # Support {% extends "default:table.html" %}:
            PrefixLoader({"default": FileSystemLoader(default_templates)},
                         delimiter=":"),
        ])
        self.jinja_env = Environment(loader=template_loader,
                                     autoescape=True,
                                     enable_async=True)
        self.jinja_env.filters["escape_css_string"] = escape_css_string
        self.jinja_env.filters[
            "quote_plus"] = lambda u: urllib.parse.quote_plus(u)
        self.jinja_env.filters["escape_sqlite"] = escape_sqlite
        self.jinja_env.filters["to_css_class"] = to_css_class
        # pylint: disable=no-member
        pm.hook.prepare_jinja2_environment(env=self.jinja_env)

        self.register_renderers()

        routes = []

        def add_route(view, regex):
            routes.append((regex, view))

        # Generate a regex snippet to match all registered renderer file extensions
        renderer_regex = "|".join(r"\." + key for key in self.renderers.keys())

        add_route(IndexView.as_asgi(self), r"/(?P<as_format>(\.jsono?)?$)")
        # TODO: /favicon.ico and /-/static/ deserve far-future cache expires
        add_route(favicon, "/favicon.ico")

        add_route(asgi_static(app_root / "datasette" / "static"),
                  r"/-/static/(?P<path>.*)$")
        for path, dirname in self.static_mounts:
            add_route(asgi_static(dirname), r"/" + path + "/(?P<path>.*)$")

        # Mount any plugin static/ directories
        for plugin in get_plugins():
            if plugin["static_path"]:
                add_route(
                    asgi_static(plugin["static_path"]),
                    "/-/static-plugins/{}/(?P<path>.*)$".format(
                        plugin["name"]),
                )
                # Support underscores in name in addition to hyphens, see https://github.com/simonw/datasette/issues/611
                add_route(
                    asgi_static(plugin["static_path"]),
                    "/-/static-plugins/{}/(?P<path>.*)$".format(
                        plugin["name"].replace("-", "_")),
                )
        add_route(
            JsonDataView.as_asgi(self, "metadata.json",
                                 lambda: self._metadata),
            r"/-/metadata(?P<as_format>(\.json)?)$",
        )
        add_route(
            JsonDataView.as_asgi(self, "versions.json", self.versions),
            r"/-/versions(?P<as_format>(\.json)?)$",
        )
        add_route(
            JsonDataView.as_asgi(self, "plugins.json", self.plugins),
            r"/-/plugins(?P<as_format>(\.json)?)$",
        )
        add_route(
            JsonDataView.as_asgi(self, "config.json", lambda: self._config),
            r"/-/config(?P<as_format>(\.json)?)$",
        )
        add_route(
            JsonDataView.as_asgi(self, "threads.json", self.threads),
            r"/-/threads(?P<as_format>(\.json)?)$",
        )
        add_route(
            JsonDataView.as_asgi(self, "databases.json",
                                 self.connected_databases),
            r"/-/databases(?P<as_format>(\.json)?)$",
        )
        add_route(DatabaseDownload.as_asgi(self),
                  r"/(?P<db_name>[^/]+?)(?P<as_db>\.db)$")
        add_route(
            DatabaseView.as_asgi(self),
            r"/(?P<db_name>[^/]+?)(?P<as_format>" + renderer_regex +
            r"|.jsono|\.csv)?$",
        )
        add_route(
            TableView.as_asgi(self),
            r"/(?P<db_name>[^/]+)/(?P<table_and_format>[^/]+?$)",
        )
        add_route(
            RowView.as_asgi(self),
            r"/(?P<db_name>[^/]+)/(?P<table>[^/]+?)/(?P<pk_path>[^/]+?)(?P<as_format>"
            + renderer_regex + r")?$",
        )
        self.register_custom_units()

        async def setup_db():
            # First time server starts up, calculate table counts for immutable databases
            for dbname, database in self.databases.items():
                if not database.is_mutable:
                    await database.table_counts(limit=60 * 60 * 1000)

        asgi = AsgiLifespan(AsgiTracer(DatasetteRouter(self, routes)),
                            on_startup=setup_db)
        for wrapper in pm.hook.asgi_wrapper(datasette=self):
            asgi = wrapper(asgi)
        return asgi
Пример #18
0
def generate_xia2_html(xinfo, filename="xia2.html", params=None, args=[]):
    assert params is None or len(args) == 0
    if params is None:
        from xia2.Modules.Analysis import phil_scope

        interp = phil_scope.command_line_argument_interpreter()
        params, unhandled = interp.process_and_fetch(
            args, custom_processor="collect_remaining")
        params = params.extract()

    xia2_txt = os.path.join(os.path.abspath(os.path.curdir), "xia2.txt")
    assert os.path.isfile(xia2_txt), xia2_txt

    with open(xia2_txt, "r") as f:
        xia2_output = html.escape(f.read())

    styles = {}

    columns = []
    columns.append([
        "",
        "Wavelength (Å)",
        "Resolution range (Å)",
        "Completeness (%)",
        "Multiplicity",
        "CC-half",
        "I/sigma",
        "Rmerge(I)",
        # anomalous statistics
        "Anomalous completeness (%)",
        "Anomalous multiplicity",
    ])

    individual_dataset_reports = {}

    for cname, xcryst in xinfo.get_crystals().items():
        reflection_files = xcryst.get_scaled_merged_reflections()
        for wname, unmerged_mtz in reflection_files["mtz_unmerged"].items():
            xwav = xcryst.get_xwavelength(wname)

            from xia2.Modules.MultiCrystalAnalysis import batch_phil_scope

            scope = phil.parse(batch_phil_scope)
            scaler = xcryst._scaler
            try:
                for si in scaler._sweep_information.values():
                    batch_params = scope.extract().batch[0]
                    batch_params.id = si["sname"]
                    batch_params.range = si["batches"]
                    params.batch.append(batch_params)
            except AttributeError:
                for si in scaler._sweep_handler._sweep_information.values():
                    batch_params = scope.extract().batch[0]
                    batch_params.id = si.get_sweep_name()
                    batch_params.range = si.get_batch_range()
                    params.batch.append(batch_params)

            report_path = xinfo.path.joinpath(cname, "report")
            report_path.mkdir(parents=True, exist_ok=True)
            report = Report.from_unmerged_mtz(unmerged_mtz,
                                              params,
                                              report_dir=str(report_path))

            xtriage_success, xtriage_warnings, xtriage_danger = None, None, None
            if params.xtriage_analysis:
                try:
                    (
                        xtriage_success,
                        xtriage_warnings,
                        xtriage_danger,
                    ) = report.xtriage_report()
                except Exception as e:
                    params.xtriage_analysis = False
                    logger.debug("Exception running xtriage:")
                    logger.debug(e, exc_info=True)

            (
                overall_stats_table,
                merging_stats_table,
                stats_plots,
            ) = report.resolution_plots_and_stats()

            d = {}
            d["merging_statistics_table"] = merging_stats_table
            d["overall_statistics_table"] = overall_stats_table

            individual_dataset_reports[wname] = d

            json_data = {}

            if params.xtriage_analysis:
                json_data["xtriage"] = (xtriage_success + xtriage_warnings +
                                        xtriage_danger)

            json_data.update(stats_plots)
            json_data.update(report.batch_dependent_plots())
            json_data.update(report.intensity_stats_plots(run_xtriage=False))
            json_data.update(report.pychef_plots())
            json_data.update(report.pychef_plots(n_bins=1))

            from scitbx.array_family import flex

            max_points = 500
            for g in (
                    "scale_rmerge_vs_batch",
                    "completeness_vs_dose",
                    "rcp_vs_dose",
                    "scp_vs_dose",
                    "rd_vs_batch_difference",
            ):
                for i, data in enumerate(json_data[g]["data"]):
                    x = data["x"]
                    n = len(x)
                    if n > max_points:
                        step = n // max_points
                        sel = (flex.int_range(n) % step) == 0
                        data["x"] = list(flex.int(data["x"]).select(sel))
                        data["y"] = list(flex.double(data["y"]).select(sel))

            resolution_graphs = OrderedDict((k + "_" + wname, json_data[k])
                                            for k in (
                                                "cc_one_half",
                                                "i_over_sig_i",
                                                "second_moments",
                                                "wilson_intensity_plot",
                                                "completeness",
                                                "multiplicity_vs_resolution",
                                            ) if k in json_data)

            if params.include_radiation_damage:
                batch_graphs = OrderedDict((k + "_" + wname, json_data[k])
                                           for k in (
                                               "scale_rmerge_vs_batch",
                                               "i_over_sig_i_vs_batch",
                                               "completeness_vs_dose",
                                               "rcp_vs_dose",
                                               "scp_vs_dose",
                                               "rd_vs_batch_difference",
                                           ))
            else:
                batch_graphs = OrderedDict((k + "_" + wname, json_data[k])
                                           for k in ("scale_rmerge_vs_batch",
                                                     "i_over_sig_i_vs_batch"))

            misc_graphs = OrderedDict((k, json_data[k]) for k in (
                "cumulative_intensity_distribution",
                "l_test",
                "multiplicities",
            ) if k in json_data)

            for k, v in report.multiplicity_plots().items():
                misc_graphs[k + "_" + wname] = {"img": v}

            d["resolution_graphs"] = resolution_graphs
            d["batch_graphs"] = batch_graphs
            d["misc_graphs"] = misc_graphs
            d["xtriage"] = {
                "success": xtriage_success,
                "warnings": xtriage_warnings,
                "danger": xtriage_danger,
            }

            merging_stats = report.merging_stats
            merging_stats_anom = report.merging_stats_anom

            overall = merging_stats.overall
            overall_anom = merging_stats_anom.overall
            outer_shell = merging_stats.bins[-1]
            outer_shell_anom = merging_stats_anom.bins[-1]

            column = [
                wname,
                str(xwav.get_wavelength()),
                "%.2f - %.2f (%.2f - %.2f)" %
                (overall.d_max, overall.d_min, outer_shell.d_max,
                 outer_shell.d_min),
                "%.2f (%.2f)" %
                (overall.completeness * 100, outer_shell.completeness * 100),
                f"{overall.mean_redundancy:.2f} ({outer_shell.mean_redundancy:.2f})",
                f"{overall.cc_one_half:.4f} ({outer_shell.cc_one_half:.4f})",
                "%.2f (%.2f)" %
                (overall.i_over_sigma_mean, outer_shell.i_over_sigma_mean),
                f"{overall.r_merge:.4f} ({outer_shell.r_merge:.4f})",
                # anomalous statistics
                "%.2f (%.2f)" % (
                    overall_anom.anom_completeness * 100,
                    outer_shell_anom.anom_completeness * 100,
                ),
                "%.2f (%.2f)" % (overall_anom.mean_redundancy,
                                 outer_shell_anom.mean_redundancy),
            ]
            columns.append(column)

    table = [[c[i] for c in columns] for i in range(len(columns[0]))]

    from cctbx import sgtbx

    space_groups = xcryst.get_likely_spacegroups()
    space_groups = [
        sgtbx.space_group_info(symbol=str(symbol)) for symbol in space_groups
    ]
    space_group = space_groups[0].symbol_and_number()
    alternative_space_groups = [
        sg.symbol_and_number() for sg in space_groups[1:]
    ]
    unit_cell = str(report.intensities.unit_cell())

    # reflection files

    for cname, xcryst in xinfo.get_crystals().items():
        # hack to replace path to reflection files with DataFiles directory
        data_dir = os.path.join(os.path.abspath(os.path.curdir), "DataFiles")
        g = glob.glob(os.path.join(data_dir, "*"))
        reflection_files = xcryst.get_scaled_merged_reflections()
        for k, rfile in reflection_files.items():
            if isinstance(rfile, str):
                for datafile in g:
                    if os.path.basename(datafile) == os.path.basename(rfile):
                        reflection_files[k] = datafile
                        break
            else:
                for kk in rfile:
                    for datafile in g:
                        if os.path.basename(datafile) == os.path.basename(
                                rfile[kk]):
                            reflection_files[k][kk] = datafile
                            break

        headers = ["Dataset", "File name"]
        merged_mtz = reflection_files["mtz"]
        mtz_files = [
            headers,
            [
                "All datasets",
                '<a href="%s">%s</a>' %
                (os.path.relpath(merged_mtz), os.path.basename(merged_mtz)),
            ],
        ]

        for wname, unmerged_mtz in reflection_files["mtz_unmerged"].items():
            mtz_files.append([
                wname,
                '<a href="%s">%s</a>' % (os.path.relpath(unmerged_mtz),
                                         os.path.basename(unmerged_mtz)),
            ])

        sca_files = [headers]
        if "sca" in reflection_files:
            for wname, merged_sca in reflection_files["sca"].items():
                sca_files.append([
                    wname,
                    '<a href="%s">%s</a>' % (os.path.relpath(merged_sca),
                                             os.path.basename(merged_sca)),
                ])

        unmerged_sca_files = [headers]
        if "sca_unmerged" in reflection_files:
            for wname, unmerged_sca in reflection_files["sca_unmerged"].items(
            ):
                unmerged_sca_files.append([
                    wname,
                    '<a href="%s">%s</a>' % (
                        os.path.relpath(unmerged_sca),
                        os.path.basename(unmerged_sca),
                    ),
                ])

    # other files
    other_files = []
    other_files.append(["File name", "Description"])
    for other_file, description in sorted([
        ("xia2.cif", "Crystallographic information file"),
        ("xia2.mmcif", "Macromolecular crystallographic information file"),
        ("shelxt.hkl", "merged structure factors for SHELXT"),
        ("shelxt.ins", "SHELXT instruction file"),
    ] + [(fn, "XPREP input file")
         for fn in os.listdir(os.path.join(data_dir)) if fn.endswith(".p4p")]):
        if os.path.exists(os.path.join(data_dir, other_file)):
            other_files.append([
                '<a href="DataFiles/{filename}">{filename}</a>'.format(
                    filename=other_file),
                description,
            ])

    # log files
    log_files_table = []
    log_dir = os.path.join(os.path.abspath(os.path.curdir), "LogFiles")
    g = glob.glob(os.path.join(log_dir, "*.log"))
    for logfile in g:
        html_file = make_logfile_html(logfile)
        html_file = os.path.splitext(logfile)[0] + ".html"
        if os.path.exists(html_file):
            log_files_table.append([
                os.path.basename(logfile),
                '<a href="%s">original</a>' % os.path.relpath(logfile),
                '<a href="%s">html</a>' % os.path.relpath(html_file),
            ])
        else:
            log_files_table.append([
                os.path.basename(logfile),
                '<a href="%s">original</a>' % os.path.relpath(logfile),
                " ",
            ])

    references = {
        cdict["acta"]: cdict.get("url")
        for cdict in Citations.get_citations_dicts()
    }

    from jinja2 import Environment, ChoiceLoader, PackageLoader

    loader = ChoiceLoader([
        PackageLoader("xia2", "templates"),
        PackageLoader("dials", "templates")
    ])
    env = Environment(loader=loader)

    template = env.get_template("xia2.html")
    html_source = template.render(
        page_title="xia2 processing report",
        xia2_output=xia2_output,
        space_group=space_group,
        alternative_space_groups=alternative_space_groups,
        unit_cell=unit_cell,
        overall_stats_table=table,
        cc_half_significance_level=params.cc_half_significance_level,
        mtz_files=mtz_files,
        sca_files=sca_files,
        unmerged_sca_files=unmerged_sca_files,
        other_files=other_files,
        log_files_table=log_files_table,
        individual_dataset_reports=individual_dataset_reports,
        references=references,
        styles=styles,
    )

    with open("%s-report.json" % os.path.splitext(filename)[0], "w") as fh:
        json.dump(json_data, fh, indent=2)

    with open(filename, "wb") as f:
        f.write(html_source.encode("utf-8", "xmlcharrefreplace"))
Пример #19
0
app.config["DEBUG"] = True
if not TESTING["status"]:
    SC, jwt = config_auth(app)
else:
    logger.warning("TESTING: No auth will be enabled.")

# Apply wrappers to the app that will compress responses and enable CORS.
Compress(app)
CORS(app)

# The directory path to this location (works in any file system).
HERE = Path(__file__).parent.absolute()

# Instantiate a jinja2 env.
env = Environment(
    loader=ChoiceLoader([app.jinja_loader, auth.jinja_loader, indra_loader]))


# Overwrite url_for function in jinja to handle DEPLOYMENT prefix gracefully.
def url_for(*args, **kwargs):
    """Generate a url for a given endpoint, applying the DEPLOYMENT prefix."""
    res = base_url_for(*args, **kwargs)
    if DEPLOYMENT is not None:
        if not res.startswith(f"/{DEPLOYMENT}"):
            res = f"/{DEPLOYMENT}" + res
    return res


env.globals.update(url_for=url_for)

Пример #20
0
from django.db.utils import DatabaseError
from django.core.exceptions import ValidationError

from mozdns.utils import get_zones

from core.search.compiler.django_compile import compile_to_django
from core.search.compiler.django_compile import search_type
from core.search.compiler.invschema import SEARCH_SCHEMA, HELP_SEARCH_SCHEMA

import simplejson as json
from gettext import gettext as _

from jinja2 import Environment, PackageLoader, ChoiceLoader

env = Environment(loader=ChoiceLoader([
    PackageLoader('mozdns.record', 'templates'),
    PackageLoader('core.search', 'templates')
]))

MAX_NUM_OBJECTS = 5000


def request_to_search(request):
    search = request.GET.get("search", None)
    adv_search = request.GET.get("advanced_search", "")

    if adv_search:
        if search:
            search += " AND " + adv_search
        else:
            search = adv_search
    return search
Пример #21
0
    },
    FHOST_MIME_BLACKLIST=[
        "application/x-dosexec", "application/java-archive",
        "application/java-vm"
    ],
    FHOST_UPLOAD_BLACKLIST=None,
    NSFW_DETECT=False,
    NSFW_THRESHOLD=0.608,
    URL_ALPHABET=
    "DEQhd2uFteibPwq0SWBInTpA_jcZL5GKz3YCR14Ulk87Jors9vNHgfaOmMXy6Vx-",
)

if not app.config["TESTING"]:
    app.config.from_pyfile("config.py")
    app.jinja_loader = ChoiceLoader([
        FileSystemLoader(str(Path(app.instance_path) / "templates")),
        app.jinja_loader
    ])

    if app.config["DEBUG"]:
        app.config["FHOST_USE_X_ACCEL_REDIRECT"] = False

if app.config["NSFW_DETECT"]:
    from nsfw_detect import NSFWDetector
    nsfw = NSFWDetector()

try:
    mimedetect = Magic(mime=True, mime_encoding=False)
except:
    print("""Error: You have installed the wrong version of the 'magic' module.
Please install python-magic.""")
    sys.exit(1)
Пример #22
0
def make_flask_stack(conf, **app_conf):
    """ This has to pass the flask app through all the same middleware that
    Pylons used """

    root = os.path.dirname(
        os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

    debug = asbool(app_conf.get('debug', app_conf.get('DEBUG', False)))
    testing = asbool(app_conf.get('testing', app_conf.get('TESTING', False)))

    app = flask_app = CKANFlask(__name__)
    app.debug = debug
    app.testing = testing
    app.template_folder = os.path.join(root, 'templates')
    app.app_ctx_globals_class = CKAN_AppCtxGlobals
    app.url_rule_class = CKAN_Rule
    app.jinja_loader = ChoiceLoader([
        app.jinja_loader,
        CkanextTemplateLoader()
    ])

    # Update Flask config with the CKAN values. We use the common config
    # object as values might have been modified on `load_environment`
    if config:
        app.config.update(config)
    else:
        app.config.update(conf)
        app.config.update(app_conf)

    # Do all the Flask-specific stuff before adding other middlewares

    # Secret key needed for flask-debug-toolbar and sessions
    if not app.config.get('SECRET_KEY'):
        app.config['SECRET_KEY'] = config.get('beaker.session.secret')
    if not app.config.get('SECRET_KEY'):
        raise RuntimeError(u'You must provide a value for the secret key'
                           ' with the SECRET_KEY config option')

    if debug:
        from flask_debugtoolbar import DebugToolbarExtension
        app.config['DEBUG_TB_INTERCEPT_REDIRECTS'] = False
        DebugToolbarExtension(app)

    # Use Beaker as the Flask session interface
    class BeakerSessionInterface(SessionInterface):
        def open_session(self, app, request):
            if 'beaker.session' in request.environ:
                return request.environ['beaker.session']

        def save_session(self, app, session, response):
            session.save()

    namespace = 'beaker.session.'
    session_opts = dict([(k.replace('beaker.', ''), v)
                        for k, v in config.iteritems()
                        if k.startswith(namespace)])
    if (not session_opts.get('session.data_dir') and
            session_opts.get('session.type', 'file') == 'file'):
        cache_dir = app_conf.get('cache_dir') or app_conf.get('cache.dir')
        session_opts['session.data_dir'] = '{data_dir}/sessions'.format(
                data_dir=cache_dir)

    app.wsgi_app = SessionMiddleware(app.wsgi_app, session_opts)
    app.session_interface = BeakerSessionInterface()

    # Add Jinja2 extensions and filters
    extensions = [
        'jinja2.ext.do', 'jinja2.ext.with_',
        jinja_extensions.SnippetExtension,
        jinja_extensions.CkanExtend,
        jinja_extensions.CkanInternationalizationExtension,
        jinja_extensions.LinkForExtension,
        jinja_extensions.ResourceExtension,
        jinja_extensions.UrlForStaticExtension,
        jinja_extensions.UrlForExtension
    ]
    for extension in extensions:
        app.jinja_env.add_extension(extension)
    app.jinja_env.filters['empty_and_escape'] = \
        jinja_extensions.empty_and_escape

    # Common handlers for all requests
    app.before_request(ckan_before_request)
    app.after_request(ckan_after_request)

    # Template context processors
    app.context_processor(helper_functions)
    app.context_processor(c_object)

    @app.context_processor
    def ungettext_alias():
        u'''
        Provide `ungettext` as an alias of `ngettext` for backwards
        compatibility
        '''
        return dict(ungettext=ungettext)

    # Babel
    app.config[u'BABEL_TRANSLATION_DIRECTORIES'] = os.path.join(root, u'i18n')
    app.config[u'BABEL_DOMAIN'] = 'ckan'

    babel = Babel(app)

    babel.localeselector(get_locale)

    @app.route('/hello', methods=['GET'])
    def hello_world():
        return 'Hello World, this is served by Flask'

    @app.route('/hello', methods=['POST'])
    def hello_world_post():
        return 'Hello World, this was posted to Flask'

    # Auto-register all blueprints defined in the `views` folder
    _register_core_blueprints(app)

    # Set up each IBlueprint extension as a Flask Blueprint
    for plugin in PluginImplementations(IBlueprint):
        if hasattr(plugin, 'get_blueprint'):
            app.register_extension_blueprint(plugin.get_blueprint())

    # Start other middleware
    for plugin in PluginImplementations(IMiddleware):
        app = plugin.make_middleware(app, config)

    # Fanstatic
    if debug:
        fanstatic_config = {
            'versioning': True,
            'recompute_hashes': True,
            'minified': False,
            'bottom': True,
            'bundle': False,
        }
    else:
        fanstatic_config = {
            'versioning': True,
            'recompute_hashes': False,
            'minified': True,
            'bottom': True,
            'bundle': True,
        }
    root_path = config.get('ckan.root_path', None)
    if root_path:
        root_path = re.sub('/{{LANG}}', '', root_path)
        fanstatic_config['base_url'] = root_path
    app = Fanstatic(app, **fanstatic_config)

    for plugin in PluginImplementations(IMiddleware):
        try:
            app = plugin.make_error_log_middleware(app, config)
        except AttributeError:
            log.critical('Middleware class {0} is missing the method'
                         'make_error_log_middleware.'
                         .format(plugin.__class__.__name__))

    # Initialize repoze.who
    who_parser = WhoConfig(conf['here'])
    who_parser.parse(open(app_conf['who.config_file']))

    app = PluggableAuthenticationMiddleware(
        app,
        who_parser.identifiers,
        who_parser.authenticators,
        who_parser.challengers,
        who_parser.mdproviders,
        who_parser.request_classifier,
        who_parser.challenge_decider,
        logging.getLogger('repoze.who'),
        logging.WARN,  # ignored
        who_parser.remote_user_key
    )

    # Update the main CKAN config object with the Flask specific keys
    # that were set here or autogenerated
    flask_config_keys = set(flask_app.config.keys()) - set(config.keys())
    for key in flask_config_keys:
        config[key] = flask_app.config[key]

    # Add a reference to the actual Flask app so it's easier to access
    app._wsgi_app = flask_app

    return app
Пример #23
0
    def init_app(self, app, plugins_base=None, plugins_folder="plugins"):
        self.plugins_folder = plugins_folder
        self.plugins_abspath = join(
            plugins_base or getattr(app, "root_path", getcwd()),
            self.plugins_folder,
        )

        #: Scan and load plugins for :attr:`plugins_folder` and third-plugins
        self.logger.debug(
            "Start plugins initialization, local plugins path: %s, third party"
            "-plugins: %s" % (self.plugins_abspath, self.plugin_packages))
        self.__scan_third_plugins()
        self.__scan_affiliated_plugins()

        #: Try to update `self.__plugins`
        #:
        #: ..versionadded:: 3.7.0
        self.__preprocess_all_plugins()

        #: Analysis and run plugins. First, register template variable
        app.jinja_env.globals.update(
            emit_tep=self.emit_tep,
            emit_assets=self.emit_assets,
            emit_config=self.emit_config,
            emit_dcp=self._dcp_manager.emit,
        )

        #: Custom add multiple template folders.
        #: Maybe you can use :class:`~jinja2.PackageLoader`.
        app.jinja_loader = ChoiceLoader([
            app.jinja_loader,
            FileSystemLoader(self.__get_valid_tpl),
        ])

        #: Add a static rule for plugins
        app.add_url_rule(
            self.static_url_path + "/<string:plugin_name>/<path:filename>",
            endpoint=self.static_endpoint,
            view_func=self._send_plugin_static_file,
        )

        #: Register the hook extension point processor
        for hep, handler in iteritems(self.__het_allow_hooks):
            _deco_func = getattr(app, hep)
            _deco_func(handler)

        #: Register the blueprint extension point
        #:
        #: .. versionchanged:: 3.6.2
        #:     flask 2.0 nested blueprints,
        #:     but only blueprints of other plugins can be nested
        _plugin_bps = {}  # {name:{blueprint}, }
        _nested_bps = {}  # {parent:[{blueprint}, ], }
        for bep in self.get_enabled_beps:
            bp = bep["blueprint"]
            parent = bep.get("parent")
            if parent:
                _nested_bps.setdefault(parent, []).append(bep)
            else:
                _plugin_bps[bp.name] = bep
        for parent, beps in iteritems(_nested_bps):
            if parent not in _plugin_bps:
                raise PEPError("No parent blueprint found named %s" % parent)
            pbp = _plugin_bps[parent]["blueprint"]
            for bep in beps:
                bp = bep["blueprint"]
                prefix = bep["prefix"]
                pbp.register_blueprint(bp, url_prefix=prefix)
        for bep in _plugin_bps.values():
            bp = bep["blueprint"]
            prefix = bep["prefix"]
            app.register_blueprint(bp, url_prefix=prefix)

        #: Register the viewfunc extension point
        #:
        #: .. versionadded:: 3.1.0
        #:
        #: .. versionchanged:: 3.6.0
        #:     allow blueprint name
        for vep in self.get_enabled_veps:
            rule, viewfunc, endpoint, options, _bp = vep
            if _bp:
                if _bp in app.blueprints:
                    s = app.blueprints[_bp].make_setup_state(app, {})
                    s.add_url_rule(rule, endpoint, viewfunc, **options)
                else:
                    raise PEPError(
                        "The required blueprint({}) was not found when "
                        "registering vep with {}".format(_bp, rule))
            else:
                app.add_url_rule(rule, endpoint, viewfunc, **options)

        #: Register the class-based view extension point
        #:
        #: .. versionadded:: 3.5.0
        for cvep in self.get_enabled_cveps:
            viewclass, options = cvep
            viewclass.register(app, **options)

        #: Register the template filters
        #:
        #: .. versionadded:: 3.2.0
        for tf in self.get_enabled_filters:
            if tf and tf[0] not in app.jinja_env.filters:
                app.add_template_filter(tf[-1], tf[0])

        #: Register the error handlers
        #:
        #: .. versionadded:: 3.2.0
        for (err_code_exc, errview) in self.get_enabled_errhandlers:
            app.register_error_handler(err_code_exc, errview)

        #: Register the template context processors
        #:
        #: .. versionadded:: 3.2.0
        app.template_context_processors[None].append(
            lambda:
            {k: v
             for tcp in self.get_enabled_tcps for k, v in iteritems(tcp)})

        #: register extension with app
        app.extensions = getattr(app, "extensions", None) or {}
        app.extensions["pluginkit"] = self
Пример #24
0
login.login_view = 'auth.login'

# Blueprints - подгрузка модулей, которые находятся в папках auth, sections и tasks
from app.auth import bp as auth_bp
from app.sections import bp as sections_bp
from app.tasks import bp as tasks_bp
from app.users import bp as users_bp

app.register_blueprint(auth_bp)
app.register_blueprint(sections_bp, url_prefix="/sections")
app.register_blueprint(tasks_bp, url_prefix="/tasks")
app.register_blueprint(users_bp)

# Добавим путь для шаблонов динамических полей
loader = FileSystemLoader("app/dynamic_fields/templates/")
my_loader = ChoiceLoader([app.jinja_loader, loader])
app.jinja_loader = my_loader

# Функция load_user необходима для LoginManager
from app.models import Users


@login.user_loader
def load_user(id):
    return Users.query.get(int(id))


# Добавляем список языков и функцию сейчашнего времени в глобальные
# переменные jinja, чтобы их можно было использовать в шаблонах
app.jinja_env.globals.update(now=datetime.utcnow)
app.jinja_env.globals['LANGUAGES'] = app.config['LANGUAGES']
Пример #25
0
    Internal template writer - handles template rendering and blog setup.

    :copyright: Copyright 2011-2017 by Vlad Riscutia and contributors (see
    CONTRIBUTORS file)
    :license: FreeBSD, see LICENSE file
'''

from jinja2 import ChoiceLoader, Environment, FileSystemLoader, PackageLoader
import os
import shutil
from tinkerer import paths, utils

# jinja environment
env = Environment(loader=ChoiceLoader([
    # first choice is _templates subdir from blog root
    FileSystemLoader(paths.templates),
    # if template is not there, use tinkerer builtin
    PackageLoader("tinkerer", "__templates")
]))


def render(template, destination, context={}, safe=False):
    '''
    Renders the given template at the given destination with the given context.
    '''
    with open(destination, "wb") as dest:
        dest.write(env.get_template(template).render(context).encode("utf8"))


def render_safe(template, destination, context={}):
    '''
    Similar to render but only renders the template if the destination doesn't
from chalice import Response
from jinja2 import ChoiceLoader
from jinja2 import Environment
from jinja2 import FileSystemLoader

jinja_env = Environment(loader=ChoiceLoader([
    FileSystemLoader("chalicelib/templates"),
]))


def add_template_filter(f, name=None):
    jinja_env.filters[name or f.__name__] = f


def add_template_global(f, name=None):
    jinja_env.globals[name or f.__name__] = f


def render_template(template_path, **context):
    template = jinja_env.get_or_select_template(template_path)
    return template.render(context)


def render_to_response(template_path, **context):
    return Response(
        render_template(template_path, **context),
        status_code=200,
        headers={
            "Content-Type": "text/html",
            "Access-Control-Allow-Origin": "*"
        },
Пример #27
0
    def initialize(self, *args, **kwargs):
        """Load configuration settings."""
        super().initialize(*args, **kwargs)
        self.load_config_file(self.config_file)
        # hook up tornado logging
        if self.debug:
            self.log_level = logging.DEBUG
        tornado.options.options.logging = logging.getLevelName(self.log_level)
        tornado.log.enable_pretty_logging()
        self.log = tornado.log.app_log

        self.init_pycurl()

        # initialize kubernetes config
        if self.builder_required:
            try:
                kubernetes.config.load_incluster_config()
            except kubernetes.config.ConfigException:
                kubernetes.config.load_kube_config()
            self.tornado_settings[
                "kubernetes_client"] = self.kube_client = kubernetes.client.CoreV1Api(
                )

        # times 2 for log + build threads
        self.build_pool = ThreadPoolExecutor(self.concurrent_build_limit * 2)
        # default executor for asyncifying blocking calls (e.g. to kubernetes, docker).
        # this should not be used for long-running requests
        self.executor = ThreadPoolExecutor(self.executor_threads)

        jinja_options = dict(autoescape=True, )
        template_paths = [self.template_path]
        base_template_path = self._template_path_default()
        if base_template_path not in template_paths:
            # add base templates to the end, so they are looked up at last after custom templates
            template_paths.append(base_template_path)
        loader = ChoiceLoader([
            # first load base templates with prefix
            PrefixLoader({'templates': FileSystemLoader([base_template_path])},
                         '/'),
            # load all templates
            FileSystemLoader(template_paths)
        ])
        jinja_env = Environment(loader=loader, **jinja_options)
        if self.use_registry and self.builder_required:
            registry = DockerRegistry(self.docker_auth_host,
                                      self.docker_token_url,
                                      self.docker_registry_host)
        else:
            registry = None

        self.launcher = Launcher(
            parent=self,
            hub_url=self.hub_url,
            hub_api_token=self.hub_api_token,
            create_user=not self.auth_enabled,
        )

        self.event_log = EventLog(parent=self)

        self.tornado_settings.update({
            "docker_push_secret":
            self.docker_push_secret,
            "docker_image_prefix":
            self.docker_image_prefix,
            "debug":
            self.debug,
            'launcher':
            self.launcher,
            'appendix':
            self.appendix,
            "build_namespace":
            self.build_namespace,
            "builder_image_spec":
            self.builder_image_spec,
            'build_node_selector':
            self.build_node_selector,
            'build_pool':
            self.build_pool,
            'log_tail_lines':
            self.log_tail_lines,
            'per_repo_quota':
            self.per_repo_quota,
            'repo_providers':
            self.repo_providers,
            'use_registry':
            self.use_registry,
            'registry':
            registry,
            'traitlets_config':
            self.config,
            'google_analytics_code':
            self.google_analytics_code,
            'google_analytics_domain':
            self.google_analytics_domain,
            'extra_footer_scripts':
            self.extra_footer_scripts,
            'jinja2_env':
            jinja_env,
            'build_memory_limit':
            self.build_memory_limit,
            'build_docker_host':
            self.build_docker_host,
            'base_url':
            self.base_url,
            "static_path":
            os.path.join(os.path.dirname(__file__), "static"),
            'static_url_prefix':
            url_path_join(self.base_url, 'static/'),
            'template_variables':
            self.template_variables,
            'executor':
            self.executor,
            'auth_enabled':
            self.auth_enabled,
            'use_named_servers':
            self.use_named_servers,
            'event_log':
            self.event_log
        })
        if self.auth_enabled:
            self.tornado_settings['cookie_secret'] = os.urandom(32)

        handlers = [
            (r'/metrics', MetricsHandler),
            (r"/build/([^/]+)/(.+)", BuildHandler),
            (r"/v2/([^/]+)/(.+)", ParameterizedMainHandler),
            (r"/repo/([^/]+)/([^/]+)(/.*)?", LegacyRedirectHandler),
            # for backward-compatible mybinder.org badge URLs
            # /assets/images/badge.svg
            (r'/assets/(images/badge\.svg)', tornado.web.StaticFileHandler, {
                'path': self.tornado_settings['static_path']
            }),
            # /badge.svg
            (r'/(badge\.svg)', tornado.web.StaticFileHandler, {
                'path':
                os.path.join(self.tornado_settings['static_path'], 'images')
            }),
            # /favicon_XXX.ico
            (r'/(favicon\_fail\.ico)', tornado.web.StaticFileHandler, {
                'path':
                os.path.join(self.tornado_settings['static_path'], 'images')
            }),
            (r'/(favicon\_success\.ico)', tornado.web.StaticFileHandler, {
                'path':
                os.path.join(self.tornado_settings['static_path'], 'images')
            }),
            (r'/(favicon\_building\.ico)', tornado.web.StaticFileHandler, {
                'path':
                os.path.join(self.tornado_settings['static_path'], 'images')
            }),
            (r'/', MainHandler),
            (r'.*', Custom404),
        ]
        if self.extra_static_path:
            handlers.insert(-1,
                            (re.escape(self.extra_static_url_prefix) + r"(.*)",
                             tornado.web.StaticFileHandler, {
                                 'path': self.extra_static_path
                             }))
        handlers = self.add_url_prefix(self.base_url, handlers)
        if self.auth_enabled:
            oauth_redirect_uri = os.getenv('JUPYTERHUB_OAUTH_CALLBACK_URL') or \
                                 url_path_join(self.base_url, 'oauth_callback')
            oauth_redirect_uri = urlparse(oauth_redirect_uri).path
            handlers.insert(-1, (oauth_redirect_uri, HubOAuthCallbackHandler))
        self.tornado_app = tornado.web.Application(handlers,
                                                   **self.tornado_settings)
Пример #28
0
from functools import wraps
import json

from jinja2 import Environment, PackageLoader, ChoiceLoader

from twisted.internet import defer

from klein import Klein

from mongoengine import connect

from supperfeed.build import Recipe
from supperfeed.importer import importRecipe

supperLoader = ChoiceLoader([
    PackageLoader('supperfeed', '.'),
    # ...
])

env = Environment(
    loader=supperLoader,
    block_start_string='<%',
    block_end_string='%>',
    comment_start_string='<#',
    comment_end_string='#>',
    variable_start_string='<<',
    variable_end_string='>>',
)


def jsonResponse(f):
    """
Пример #29
0
Файл: app.py Проект: atakan/moin
def create_app_ext(flask_config_file=None,
                   flask_config_dict=None,
                   moin_config_class=None,
                   warn_default=True,
                   **kwargs):
    """
    Factory for moin wsgi apps

    :param flask_config_file: a flask config file name (may have a MOINCFG class),
                              if not given, a config pointed to by MOINCFG env var
                              will be loaded (if possible).
    :param flask_config_dict: a dict used to update flask config (applied after
                              flask_config_file was loaded [if given])
    :param moin_config_class: if you give this, it'll be instantiated as app.cfg,
                              otherwise it'll use MOINCFG from flask config. If that
                              also is not there, it'll use the DefaultConfig built
                              into MoinMoin.
    :param warn_default: emit a warning if moin falls back to its builtin default
                         config (maybe user forgot to specify MOINCFG?)
    :param kwargs: if you give additional keyword args, the keys/values will get patched
                   into the moin configuration class (before its instance is created)
    """
    clock = Clock()
    clock.start('create_app total')
    app = Flask('moin')

    clock.start('create_app load config')
    if flask_config_file:
        app.config.from_pyfile(path.abspath(flask_config_file))
    else:
        if not app.config.from_envvar('MOINCFG', silent=True):
            # no MOINCFG env variable set, try stuff in cwd:
            flask_config_file = path.abspath('wikiconfig_local.py')
            if not path.exists(flask_config_file):
                flask_config_file = path.abspath('wikiconfig.py')
                if not path.exists(flask_config_file):
                    # we should be here only because wiki admin is performing `moin create-instance`
                    if 'create-instance' in sys.argv:
                        config_path = path.dirname(config.__file__)
                        flask_config_file = path.join(config_path,
                                                      'wikiconfig.py')
                    else:
                        flask_config_file = None
            else:
                logging.warning(
                    "Use of wikiconfig_editme.py is deprecated, merge into wikiconfig.py."
                )
            if flask_config_file:
                app.config.from_pyfile(path.abspath(flask_config_file))
    if flask_config_dict:
        app.config.update(flask_config_dict)
    Config = moin_config_class
    if not Config:
        Config = app.config.get('MOINCFG')
    if not Config:
        if warn_default:
            logging.warning("using builtin default configuration")
        from moin.config.default import DefaultConfig as Config
    for key, value in kwargs.items():
        setattr(Config, key, value)
    if Config.secrets is None:
        # reuse the secret configured for flask (which is required for sessions)
        Config.secrets = app.config.get('SECRET_KEY')
    app.cfg = Config()
    clock.stop('create_app load config')
    clock.start('create_app register')
    # register converters
    from werkzeug.routing import BaseConverter

    class ItemNameConverter(BaseConverter):
        """Like the default :class:`UnicodeConverter`, but it also matches
        slashes (except at the beginning AND end).
        This is useful for wikis and similar applications::

            Rule('/<itemname:wikipage>')
            Rule('/<itemname:wikipage>/edit')
        """
        regex = '[^/]+?(/[^/]+?)*'
        weight = 200

    app.url_map.converters['itemname'] = ItemNameConverter
    # register modules, before/after request functions
    from moin.apps.frontend import frontend
    frontend.before_request(before_wiki)
    frontend.teardown_request(teardown_wiki)
    app.register_blueprint(frontend)
    from moin.apps.admin import admin
    admin.before_request(before_wiki)
    admin.teardown_request(teardown_wiki)
    app.register_blueprint(admin, url_prefix='/+admin')
    from moin.apps.feed import feed
    feed.before_request(before_wiki)
    feed.teardown_request(teardown_wiki)
    app.register_blueprint(feed, url_prefix='/+feed')
    from moin.apps.misc import misc
    misc.before_request(before_wiki)
    misc.teardown_request(teardown_wiki)
    app.register_blueprint(misc, url_prefix='/+misc')
    from moin.apps.serve import serve
    app.register_blueprint(serve, url_prefix='/+serve')
    clock.stop('create_app register')
    clock.start('create_app flask-cache')
    # the 'simple' caching uses a dict and is not thread safe according to the docs.
    cache = Cache(config={'CACHE_TYPE': 'simple'})
    cache.init_app(app)
    app.cache = cache
    clock.stop('create_app flask-cache')
    # init storage
    clock.start('create_app init backends')
    init_backends(app)
    clock.stop('create_app init backends')
    clock.start('create_app flask-babel')
    i18n_init(app)
    clock.stop('create_app flask-babel')
    # configure templates
    clock.start('create_app flask-theme')
    setup_themes(app)
    if app.cfg.template_dirs:
        app.jinja_env.loader = ChoiceLoader([
            FileSystemLoader(app.cfg.template_dirs),
            app.jinja_env.loader,
        ])
    app.register_error_handler(403, themed_error)
    clock.stop('create_app flask-theme')
    clock.stop('create_app total')
    del clock
    return app
Пример #30
0
def create_app(config_obj, configfiles=None, init_for_operation=True):
    '''
    apply configuration object, then configuration files
    '''
    global app
    app = Flask('members')
    app.config.from_object(config_obj)
    if configfiles:
        # backwards compatibility
        if type(configfiles) == str:
            configfiles = [configfiles]
        for configfile in configfiles:
            appconfig = getitems(configfile, 'app')
            app.config.update(appconfig)

    # tell jinja to remove linebreaks
    app.jinja_env.trim_blocks = True
    app.jinja_env.lstrip_blocks = True

    # define product name (don't import nav until after app.jinja_env.globals['_productname'] set)
    app.jinja_env.globals['_productname'] = app.config['THISAPP_PRODUCTNAME']
    app.jinja_env.globals['_productname_text'] = app.config['THISAPP_PRODUCTNAME_TEXT']
    for configkey in ['SECURITY_EMAIL_SUBJECT_PASSWORD_RESET',
                      'SECURITY_EMAIL_SUBJECT_PASSWORD_CHANGE_NOTICE',
                      'SECURITY_EMAIL_SUBJECT_PASSWORD_NOTICE',
                      ]:
        app.config[configkey] = app.config[configkey].format(productname=app.config['THISAPP_PRODUCTNAME_TEXT'])

    # initialize database
    from .model import db
    db.init_app(app)

    # initialize uploads
    if init_for_operation:
        init_uploads(app)

    # handle <interest> in URL - https://flask.palletsprojects.com/en/1.1.x/patterns/urlprocessors/
    @app.url_value_preprocessor
    def pull_interest(endpoint, values):
        try:
            g.interest = values.pop('interest', None)
        except AttributeError:
            g.interest = None
        finally:
            if not g.interest:
                g.interest = request.args.get('interest', None)

    # add loutilities tables-assets for js/css/template loading
    # see https://adambard.com/blog/fresh-flask-setup/
    #    and https://webassets.readthedocs.io/en/latest/environment.html#webassets.env.Environment.load_path
    # loutilities.__file__ is __init__.py file inside loutilities; os.path.split gets package directory
    loutilitiespath = os.path.join(os.path.split(loutilities.__file__)[0], 'tables-assets', 'static')

    @app.route('/loutilities/static/<path:filename>')
    def loutilities_static(filename):
        return send_from_directory(loutilitiespath, filename)

    # bring in js, css assets here, because app needs to be created first
    from .assets import asset_env, asset_bundles
    with app.app_context():
        # needs to be set before update_local_tables called and before UserSecurity() instantiated
        g.loutility = Application.query.filter_by(application=app.config['APP_LOUTILITY']).one()

        # update LocalUser and LocalInterest tables
        if init_for_operation:
            update_local_tables()

        # js/css files
        asset_env.append_path(app.static_folder)
        asset_env.append_path(loutilitiespath, '/loutilities/static')

        # templates
        loader = ChoiceLoader([
            app.jinja_loader,
            PackageLoader('loutilities', 'tables-assets/templates')
        ])
        app.jinja_loader = loader

    # initialize assets
    asset_env.init_app(app)
    asset_env.register(asset_bundles)

    # Set up Flask-Mail [configuration in <application>.cfg] and security mailer
    mail = Mail(app)

    def security_send_mail(subject, recipient, template, **context):
        # this may be called from view which doesn't reference interest
        # if so pick up user's first interest to get from_email address
        if not g.interest:
            g.interest = context['user'].interests[0].interest if context['user'].interests else None
        if g.interest:
            from_email = localinterest().from_email
        # use default if user didn't have any interests
        else:
            from_email = current_app.config['SECURITY_EMAIL_SENDER']
            # copied from flask_security.utils.send_mail
            if isinstance(from_email, LocalProxy):
                from_email = from_email._get_current_object()
        ctx = ('security/email', template)
        html = render_template('%s/%s.html' % ctx, **context)
        text = render_template('%s/%s.txt' % ctx, **context)
        sendmail(subject, from_email, recipient, html=html, text=text)

    # Set up Flask-Security
    global user_datastore, security
    user_datastore = SQLAlchemyUserDatastore(db, User, Role)
    security = UserSecurity(app, user_datastore, send_mail=security_send_mail)

    # activate views
    from .views import userrole as userroleviews
    from loutilities.user.views import bp as userrole
    app.register_blueprint(userrole)
    from .views.frontend import bp as frontend
    app.register_blueprint(frontend)
    from .views.admin import bp as admin
    app.register_blueprint(admin)

    # need to force app context else get
    #    RuntimeError: Working outside of application context.
    #    RuntimeError: Attempted to generate a URL without the application context being pushed.
    # see http://kronosapiens.github.io/blog/2014/08/14/understanding-contexts-in-flask.html
    with app.app_context():
        # import navigation after views created
        from . import nav

        # turn on logging
        from .applogging import setlogging
        setlogging()
        
        # set up scoped session
        from sqlalchemy.orm import scoped_session, sessionmaker
        # see https://github.com/pallets/flask-sqlalchemy/blob/706982bb8a096220d29e5cef156950237753d89f/flask_sqlalchemy/__init__.py#L990
        db.session = scoped_session(sessionmaker(autocommit=False,
                                                 autoflush=False,
                                                 binds=db.get_binds(app)))
        db.query = db.session.query_property()

        # handle favicon request for old browsers
        app.add_url_rule('/favicon.ico', endpoint='favicon',
                        redirect_to=url_for('static', filename='favicon.ico'))

    # ----------------------------------------------------------------------
    @app.before_request
    def before_request():
        g.loutility = Application.query.filter_by(application=app.config['APP_LOUTILITY']).one()

        if current_user.is_authenticated:
            user = current_user
            email = user.email

            # used in layout.jinja2
            app.jinja_env.globals['user_interests'] = sorted([{'interest': i.interest, 'description': i.description}
                                                              for i in user.interests if g.loutility in i.applications],
                                                             key=lambda a: a['description'].lower())
            session['user_email'] = email

        else:
            # used in layout.jinja2
            pubinterests = Interest.query.filter_by(public=True).all()
            app.jinja_env.globals['user_interests'] = sorted([{'interest': i.interest, 'description': i.description}
                                                              for i in pubinterests if g.loutility in i.applications],
                                                             key=lambda a: a['description'].lower())
            session.pop('user_email', None)

    # ----------------------------------------------------------------------
    @app.after_request
    def after_request(response):
        # # check if there are any changes needed to LocalUser table
        # userupdated = User.query.order_by(desc('updated_at')).first().updated_at
        # localuserupdated = LocalUser.query.order_by(desc('updated_at')).first().updated_at
        # interestupdated = Interest.query.order_by(desc('updated_at')).first().updated_at
        # localinterestupdated = LocalInterest.query.order_by(desc('updated_at')).first().updated_at
        # if userupdated > localuserupdated or interestupdated > localinterestupdated:
        #     update_local_tables()

        if not app.config['DEBUG']:
            app.logger.info(
                '{}: {} {} {}'.format(request.remote_addr, request.method, request.url, response.status_code))
        return response

    # app back to caller
    return app