You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ORPA-pyOpenRPA/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/jupyter_nbextensions_config.../__init__.py

281 lines
10 KiB

# -*- coding: utf-8 -*-
# - Copyright (c) 2001-2016, IPython-Contrib Development Team
# - Copyright (c) 2016-, jupyter-contrib development team
"""Jupyter server extension to enable, disable and configure nbextensions."""
from __future__ import unicode_literals
import io
import json
import logging
import os.path
import posixpath
import re
import yaml
from notebook import version_info as nb_version_info
from notebook.base.handlers import APIHandler, IPythonHandler
from notebook.utils import url_path_join as ujoin
from notebook.utils import path2url
from tornado import web
# attempt to use LibYaml if available
try:
from yaml import CSafeLoader as SafeLoader
except ImportError:
from yaml import SafeLoader
if nb_version_info < (5, 2, 0):
from notebook.base.handlers import json_errors
else:
# for notebook >= 5.2.0, instead of using json_errors, we must subclass
# APIHandler. Since we already do this, just do nothing extra
def json_errors(method):
return method
__version__ = '0.4.1'
absolute_url_re = re.compile(r'^(f|ht)tps?://')
def _process_nbextension_spec(spec, relative_url_base=''):
"""
Sanity-check and preprocess a spec loaded from a yaml descriptor file.
Returns *either* a processed dict *or* a string error message describing
why the spec was not suitable.
"""
if not isinstance(spec, dict):
return 'spec is not a dict, but an instance of {}'.format(type(spec))
if 'Type' not in spec:
return 'spec has no Type key'
valid_types = {'IPython Notebook Extension', 'Jupyter Notebook Extension'}
if str(spec['Type']).strip() not in valid_types:
return 'spec has invalid value for Type key: {!r}'.format(spec['Type'])
if 'Main' not in spec and 'require' not in spec:
return 'spec has neither "Main" nor "require" key'
# strip .js file extension from Main to give require path
if 'require' not in spec:
spec['require'] = os.path.splitext(spec['Main'])[0]
spec.setdefault('Name', spec['require'])
spec.setdefault('Compatibility', '?.x')
spec.setdefault('Section', 'notebook')
# generate relative URLs within the nbextensions namespace,
# from urls relative to the yaml file
for from_key, to_key in {
'Link': 'readme', 'Icon': 'icon', 'Main': 'require'}.items():
# check for the to_key first, use from_key as backup
# str needed in python 3, otherwise it ends up bytes
from_val = str(spec.get(to_key, ''))
if not from_val:
from_val = str(spec.get(from_key, ''))
if not from_val:
continue
if absolute_url_re.match(from_val):
spec[to_key] = from_val
else:
spec[to_key] = posixpath.normpath(
ujoin(relative_url_base, from_val))
return spec
def get_configurable_nbextensions(
nbextension_dirs, exclude_dirs=('mathjax',), as_dict=False, log=None):
"""Build a list of configurable nbextensions based on YAML descriptor files.
descriptor files must:
- be located under one of nbextension_dirs
- have the file extension '.yaml' or '.yml'
- contain (at minimum) the following keys:
- Type: must be 'IPython Notebook Extension' or
'Jupyter Notebook Extension'
- Main: relative url of the nbextension's main javascript file
"""
extension_dict = {}
# Traverse through nbextension subdirectories to find all yaml files
# However, don't check directories twice. See
# github.com/Jupyter-contrib/jupyter_nbextensions_configurator/issues/25
already_checked = set()
for root_nbext_dir in nbextension_dirs:
if root_nbext_dir in already_checked:
continue
else:
already_checked.add(root_nbext_dir)
if log:
log.debug(
'Looking for nbextension yaml descriptor files in {}'.format(
root_nbext_dir))
for direct, dirs, files in os.walk(root_nbext_dir, followlinks=True):
# filter to exclude directories
dirs[:] = [d for d in dirs if d not in exclude_dirs]
for filename in files:
if os.path.splitext(filename)[1] not in ['.yml', '.yaml']:
continue
yaml_path = os.path.join(direct, filename)
yaml_relpath = os.path.relpath(yaml_path, root_nbext_dir)
with io.open(yaml_path, 'r', encoding='utf-8') as stream:
try:
extension = yaml.load(stream, Loader=SafeLoader)
except yaml.YAMLError:
if log:
log.warning(
'Failed to load yaml file {}'.format(
yaml_relpath))
continue
extension = _process_nbextension_spec(
extension,
relative_url_base=path2url(os.path.dirname(yaml_relpath)))
if not isinstance(extension, dict):
continue
require = extension['require']
if log:
if require in extension_dict:
msg = 'nbextension {!r} has duplicate listings'.format(
extension['require'])
msg += ' in both {!r} and {!r}'.format(
yaml_path, extension_dict[require]['yaml_path'])
log.warning(msg)
extension['duplicate'] = True
else:
log.debug('Found nbextension {!r} in {}'.format(
extension['Name'], yaml_relpath))
extension_dict[require] = {
'yaml_path': yaml_path, 'extension': extension}
if as_dict:
return extension_dict
return [val['extension'] for val in extension_dict.values()]
class ConfiguratorLogger(logging.LoggerAdapter):
"""Logging adapter to prepend the serverextension name to log messages."""
def __init__(self, logger):
super(ConfiguratorLogger, self).__init__(logger, {})
def process(self, msg, kwargs):
return '[{}] {}'.format(__name__, msg), kwargs
class NBExtensionHandlerJSON(APIHandler):
"""
Returns a json list describing the configurable nbextensions.
Based on part of notebook.services.config.handlers.ConfigHandler
"""
@APIHandler.log.getter
def log(self):
return ConfiguratorLogger(super(NBExtensionHandlerJSON, self).log)
@web.authenticated
@json_errors
def get(self):
self.set_header("Content-Type", 'application/json')
nbapp_webapp = self.application
nbextension_dirs = nbapp_webapp.settings['nbextensions_path']
extension_list = get_configurable_nbextensions(
nbextension_dirs=nbextension_dirs, log=self.log)
self.finish(json.dumps(extension_list))
class NBExtensionHandlerPage(IPythonHandler):
"""Renders the nbextension configuration interface."""
@IPythonHandler.log.getter
def log(self):
return ConfiguratorLogger(super(NBExtensionHandlerPage, self).log)
@web.authenticated
def get(self):
"""Render the nbextension configuration interface."""
self.finish(self.render_template(
'nbextensions_configurator.html',
page_title='Nbextensions Configuration',
**self.application.settings
))
class RenderExtensionHandler(IPythonHandler):
"""Renders markdown files as pages."""
@IPythonHandler.log.getter
def log(self):
return ConfiguratorLogger(super(RenderExtensionHandler, self).log)
@web.authenticated
def get(self, path):
"""Render given markdown file."""
if not path.endswith('.md'):
# for all non-markdown items, we redirect to the actual file
return self.redirect(self.base_url + path)
self.finish(self.render_template(
'rendermd.html',
md_url=path,
page_title=path,
**self.application.settings
))
def load_jupyter_server_extension(nbapp):
"""Load and initialise the server extension."""
logger = ConfiguratorLogger(nbapp.log)
logger.debug('Loading {}'.format(__version__))
webapp = nbapp.web_app
# ensure our template gets into search path
templates_dir = os.path.join(os.path.dirname(__file__), 'templates')
logger.debug(' Editing templates path to add {}'.format(templates_dir))
rootloader = webapp.settings['jinja2_env'].loader
for loader in getattr(rootloader, 'loaders', [rootloader]):
if hasattr(loader, 'searchpath') and \
templates_dir not in loader.searchpath:
loader.searchpath.append(templates_dir)
base_url = webapp.settings['base_url']
# make sure our static files are available
static_files_path = os.path.normpath(os.path.join(
os.path.dirname(__file__), 'static'))
logger.debug(
' Editing nbextensions path to add {}'.format(static_files_path))
if static_files_path not in webapp.settings['nbextensions_path']:
webapp.settings['nbextensions_path'].append(static_files_path)
# add our new custom handlers
logger.debug(' Adding new handlers')
new_handlers = [(ujoin(base_url, '/nbextensions/' + u), h) for u, h in [
(r"?", NBExtensionHandlerPage),
(r"nbextensions_configurator/list$", NBExtensionHandlerJSON),
(r"nbextensions_configurator/rendermd/(.*)", RenderExtensionHandler),
]]
webapp.add_handlers(".*$", new_handlers)
logger.info('enabled {}'.format(__version__))
def _jupyter_nbextension_paths():
return [
dict(
section="notebook",
src="static/nbextensions_configurator",
dest="nbextensions_configurator",
require='nbextensions_configurator/config_menu/main',
),
dict(
section="tree",
src="static/nbextensions_configurator",
dest="nbextensions_configurator",
require='nbextensions_configurator/tree_tab/main',
),
]
def _jupyter_server_extension_paths():
return [{
'module': __name__
}]