Source code for ipypublish.convert.config_manager

import os
import glob
import importlib
import logging

from six import string_types
from jinja2 import DictLoader
import jsonschema
import nbconvert  # noqa: F401

from ipypublish.utils import (
    pathlib,
    handle_error,
    get_module_path,
    read_file_from_directory,
    read_file_from_module,
)
from ipypublish import export_plugins
from ipypublish import schema
from ipypublish.templates.create_template import create_template

_TEMPLATE_KEY = "new_template"
_EXPORT_SCHEMA_FILE = "export_config.schema.json"
_EXPORT_SCHEMA = None

logger = logging.getLogger("configuration")


[docs]def get_export_config_path(export_key, config_folder_paths=()): # type (string, Tuple[str]) -> Union[string, None] """we search for a plugin name, which matches the supplied plugin name """ for name, jsonpath in iter_all_export_paths(config_folder_paths): if name == export_key: return pathlib.Path(jsonpath) return None
[docs]def iter_all_export_paths(config_folder_paths=(), regex="*.json"): """we iterate through all json files in the supplied plugin_folder_paths, and then in the `export_plugins` folder """ for plugin_folder_path in config_folder_paths: for jsonpath in glob.glob(os.path.join(plugin_folder_path, regex)): name = os.path.splitext(os.path.basename(jsonpath))[0] yield name, pathlib.Path(jsonpath) module_path = get_module_path(export_plugins) for jsonpath in glob.glob(os.path.join(str(module_path), regex)): name = os.path.splitext(os.path.basename(jsonpath))[0] yield name, pathlib.Path(jsonpath)
[docs]def load_export_config(export_config_path): """load the export configuration""" if isinstance(export_config_path, string_types): export_config_path = pathlib.Path(export_config_path) data = read_file_from_directory( export_config_path.parent, export_config_path.name, "export configuration", logger, interp_ext=True, ) # validate against schema global _EXPORT_SCHEMA if _EXPORT_SCHEMA is None: # lazy load schema once _EXPORT_SCHEMA = read_file_from_directory( get_module_path(schema), _EXPORT_SCHEMA_FILE, "export configuration schema", logger, interp_ext=True, ) try: jsonschema.validate(data, _EXPORT_SCHEMA) except jsonschema.ValidationError as err: handle_error( "validation of export config {} failed against {}: {}".format( export_config_path, _EXPORT_SCHEMA_FILE, err.message ), jsonschema.ValidationError, logger=logger, ) return data
[docs]def iter_all_export_infos(config_folder_paths=(), regex="*.json", get_mime=False): """iterate through all export configuration and yield a dict of info""" for name, path in iter_all_export_paths(config_folder_paths, regex): data = load_export_config(path) info = dict( [ ("key", str(name)), ("class", data["exporter"]["class"]), ("path", str(path)), ("description", data["description"]), ] ) if get_mime: info["mime_type"] = create_exporter_cls( data["exporter"]["class"] ).output_mimetype yield info
[docs]def create_exporter_cls(class_str): # type: (str) -> nbconvert.exporters.Exporter """dynamically load export class""" export_class_path = class_str.split(".") module_path = ".".join(export_class_path[0:-1]) class_name = export_class_path[-1] try: export_module = importlib.import_module(module_path) except ModuleNotFoundError: # noqa: F821 handle_error( "module {} containing exporter class {} not found".format( module_path, class_name ), ModuleNotFoundError, logger=logger, ) # noqa: F821 if hasattr(export_module, class_name): export_class = getattr(export_module, class_name) else: handle_error( "module {} does not contain class {}".format(module_path, class_name), ImportError, logger=logger, ) return export_class
[docs]def get_export_extension(export_config_path): """return the file extension of the exporter class""" data = load_export_config(export_config_path) exporter_cls = create_exporter_cls(data["exporter"]["class"]) return exporter_cls.file_extension
[docs]def str_to_jinja(template_str, template_key="jinja_template"): return DictLoader({template_key: template_str})
[docs]def load_template(template_key, template_dict): if template_dict is None: return None if "directory" in template_dict["outline"]: outline_template = read_file_from_directory( template_dict["outline"]["directory"], template_dict["outline"]["file"], "template outline", logger, interp_ext=False, ) outline_name = "{0}/{1}".format( template_dict["outline"]["directory"], template_dict["outline"]["file"] ) else: outline_template = read_file_from_module( template_dict["outline"]["module"], template_dict["outline"]["file"], "template outline", logger, interp_ext=False, ) outline_name = "{0}/{1}".format( template_dict["outline"]["module"], template_dict["outline"]["file"] ) segments = [] for snum, segment in enumerate(template_dict.get("segments", [])): if "file" not in segment: handle_error("'file' expected in segment {}".format(snum), KeyError, logger) if "directory" in segment: seg_data = read_file_from_directory( segment["directory"], segment["file"], "template segment", logger, interp_ext=True, ) elif "module" in segment: seg_data = read_file_from_module( segment["module"], segment["file"], "template segment", logger, interp_ext=True, ) else: handle_error( "'directory' or 'module' expected in segment {}".format(snum), KeyError, logger, ) segments.append(seg_data) template_str = create_template(outline_template, outline_name, segments) return str_to_jinja(template_str, template_key)