tools.py 2.94 KB

import subprocess
import logging
import yaml
import markdown

# setup logger for this module
logger = logging.getLogger(__name__)

# ---------------------------------------------------------------------------
# load data from yaml file
# ---------------------------------------------------------------------------
def load_yaml(filename, default=None):
    try:
        f = open(filename, 'r', encoding='utf-8')
    except IOError:
        logger.error('Can\'t open file "{}"'.format(filename))
        return default
    else:
        with f:
            try:
                return yaml.load(f)
            except yaml.YAMLError as e:
                mark = e.problem_mark
                logger.error('In YAML file "{0}" near line {1}, column {2}.'.format(filename, mark.line, mark.column+1))
                return default

# ---------------------------------------------------------------------------
# Runs a script and returns its stdout parsed as yaml, or None on error.
# Note: requires python 3.5+
# ---------------------------------------------------------------------------
def run_script(script, stdin='', timeout=5):
    try:
        p = subprocess.run([script],
            input=stdin,
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,
            universal_newlines=True,
            timeout=timeout,
            )
    except FileNotFoundError:
        logger.error('Script not found: "{0}".'.format(script))
    except PermissionError:
        logger.error('Script "{0}" not executable (wrong permissions?).'.format(script))
    except subprocess.TimeoutExpired:
        logger.error('Timeout {0}s exceeded while running script "{1}"'.format(timeout, script))
    else:
        if p.returncode != 0:
            logger.error('Script "{0}" returned error code {1}.'.format(script, p.returncode))
        else:
            try:
                output = yaml.load(p.stdout)
            except:
                logger.error('Error parsing yaml output of script "{0}"'.format(script))
            else:
                return output

def md_to_html(text, ref=None, files={}):
    if ref is not None:
        # given q['ref'] and q['files'] replaces references to files by a
        # GET to /file?ref=???;name=???
        for k in files:
            text = text.replace(k, '/file?ref={};name={}'.format(ref, k))
    return markdown.markdown(text, extensions=[
        'markdown.extensions.tables',
        'markdown.extensions.fenced_code',
        'markdown.extensions.codehilite',
        'markdown.extensions.def_list',
        'markdown.extensions.sane_lists'
    ])

def md_to_html_review(text, q):
    for k,f in q['files'].items():
        text = text.replace(k, '/absfile?name={}'.format(q['files'][k]))
    return markdown.markdown(text, extensions=[
        'markdown.extensions.tables',
        'markdown.extensions.fenced_code',
        'markdown.extensions.codehilite',
        'markdown.extensions.def_list',
        'markdown.extensions.sane_lists'
    ])