Пример #1
0
def data_files(path):
    if path.endswith('/'):
        mimetype = request.accept_mimetypes.best_match([
            'text/html',
            'application/json',
            'application/vnd.jupyter',
        ], 'text/html')
        if mimetype == 'text/html':
            fs = Filesystem(current_app.config['CWD'])
            env = get_jinja2_env(config=current_app.config)
            return env.get_template('landing.j2').render(_nb=os.path.basename(
                current_app.config['IPYNB']), )
        else:
            data_fs = Filesystem(
                Filesystem.join(current_app.config['DATA_DIR'], 'output'))
            path += current_app.config['IPYNB']
            if data_fs.exists(path):
                return send_file(data_fs.open(path, 'rb'),
                                 attachment_filename=os.path.basename(path))
    else:
        data_fs = Filesystem(
            Filesystem.join(current_app.config['DATA_DIR'], 'output'))
        if data_fs.exists(path):
            return send_file(data_fs.open(path, 'rb'),
                             attachment_filename=os.path.basename(path))
    abort(404)
Пример #2
0
def serve(app_path, **kwargs):
    import os
    import sys
    import time
    import appyter
    import functools
    import logging
    logger = logging.getLogger(__name__)
    from subprocess import Popen
    from appyter.ext.fs import Filesystem
    from appyter.context import get_env, get_jinja2_env, find_blueprints, get_appyter_directory
    from appyter.util import join_routes
    from appyter.profiles.default.filters.url_for import url_for
    config = get_env(**kwargs)
    logger.info(kwargs)
    env = get_jinja2_env(config=config)
    with Filesystem('tmpfs://') as tmp_fs:
        logger.info(f"Working directory {tmp_fs.path()}")
        #
        logger.info(f"Pre-rendering pages...")
        with Filesystem(config['CWD']).open(config['IPYNB']) as fr:
            from appyter.parse.nb import nb_from_ipynb_io
            nbtemplate = nb_from_ipynb_io(fr)
        with tmp_fs.open('index.html', 'w') as fw:
            from appyter.render.form import render_form_from_nbtemplate
            fw.write(render_form_from_nbtemplate(env, nbtemplate))
        with tmp_fs.open('index.json', 'w') as fw:
            import json
            from appyter.render.nbinspect import render_nbtemplate_json_from_nbtemplate
            json.dump(render_nbtemplate_json_from_nbtemplate(env, nbtemplate),
                      fw)
        with tmp_fs.open('landing.html', 'w') as fw:
            env.get_template('landing.j2').stream(_nb=os.path.basename(
                config['IPYNB']), ).dump(fw)
        #
        logger.info(f"Generating production config...")
        with tmp_fs.open('supervisord.conf', 'w') as fw:
            env.get_template('production/supervisord.conf.j2').stream(
                _tmp_fs=tmp_fs, sys=sys, str=str).dump(fw)
        with tmp_fs.open('nginx.conf', 'w') as fw:
            env.get_template('production/nginx.conf.j2').stream(
                _tmp_fs=tmp_fs,
                os=os,
                s3_to_url=s3_to_url,
                get_appyter_directory=get_appyter_directory,
                find_blueprints=find_blueprints,
            ).dump(fw)
        logger.info(
            f"Starting production instance at http://{config['HOST']}:{config['PORT']}{config['PREFIX']} ..."
        )
        with Popen(
            ['supervisord', '-n', '-c',
             tmp_fs.path('supervisord.conf')]) as proc:
            try:
                sys.exit(proc.wait())
            except KeyboardInterrupt:
                proc.terminate()
                sys.exit(proc.wait())
Пример #3
0
def nbconstruct(cwd, ipynb, context, output, **kwargs):
    context = json.load(context)
    env = get_jinja2_env(
        config=get_env(cwd=cwd, ipynb=ipynb, mode='construct', **kwargs),
        context=context,
    )
    nbtemplate = nb_from_ipynb_io(Filesystem(cwd).open(ipynb, 'r'))
    nb = render_nb_from_nbtemplate(env, nbtemplate)
    nb_to_ipynb_io(nb, output)
Пример #4
0
def get_fields():
    ''' Helper to get/cache fields even if we're on a different thread
  '''
    global _fields
    if not _fields or current_app.config['DEBUG']:
        fs = Filesystem(current_app.config['CWD'])
        with fs.open(current_app.config['IPYNB'], 'r') as fr:
            env = get_jinja2_env(config=current_app.config)
            nbtemplate = nb_from_ipynb_io(fr)
            _fields = render_nbtemplate_json_from_nbtemplate(env, nbtemplate)
    return _fields
Пример #5
0
def get_index():
  mimetype = request.accept_mimetypes.best_match([
    'text/html',
    'application/json',
    'application/vnd.jupyter',
  ], 'text/html')
  fs = Filesystem(current_app.config['CWD'])
  if mimetype in {'text/html'}:
    with fs.open(current_app.config['IPYNB'], 'r') as fr:
      env = get_jinja2_env(config=current_app.config)
      nbtemplate = nb_from_ipynb_io(fr)
    return render_form_from_nbtemplate(env, nbtemplate)
  elif mimetype in {'application/json'}:
    with fs.open(current_app.config['IPYNB'], 'r') as fr:
      env = get_jinja2_env(config=current_app.config)
      nbtemplate = nb_from_ipynb_io(fr)
    return jsonify(render_nbtemplate_json_from_nbtemplate(env, nbtemplate))
  elif mimetype in {'application/vnd.jupyter'}:
    return send_file(fs.open(current_app.config['IPYNB'], 'rb'), attachment_filename=current_app.config['IPYNB'], mimetype=mimetype)
  else:
    abort(404)
Пример #6
0
def prepare_results(data):
    results_hash = sha1sum_dict(dict(ipynb=get_ipynb_hash(), data=data))
    data_fs = Filesystem(current_app.config['DATA_DIR'])
    results_path = Filesystem.join('output', results_hash)
    if not data_fs.exists(
            Filesystem.join(results_path, current_app.config['IPYNB'])):
        # prepare files to be linked and update field to use filename
        file_fields = {
            field['args']['name']
            for field in get_fields() if field['field'] == 'FileField'
        }
        links = []
        files = {}
        for file_field in file_fields:
            if fdata := data.get(file_field):
                content_hash, filename = fdata.split('/', maxsplit=1)
                content_hash = sanitize_sha1sum(content_hash)
                filename = secure_filepath(filename)
                links.append((Filesystem.join('input', content_hash),
                              Filesystem.join(results_path, filename)))
                files[filename] = filename
                data[file_field] = filename
        # construct notebook
        env = get_jinja2_env(config=current_app.config,
                             context=data,
                             session=results_hash)
        fs = Filesystem(current_app.config['CWD'])
        with fs.open(current_app.config['IPYNB'], 'r') as fr:
            nbtemplate = nb_from_ipynb_io(fr)
        # in case of constraint failures, we'll fail here
        nb = render_nb_from_nbtemplate(env, nbtemplate, files=files)
        # actually link all input files into output directory
        for src, dest in links:
            data_fs.link(src, dest)
        # write notebook
        nbfile = Filesystem.join(results_path,
                                 os.path.basename(current_app.config['IPYNB']))
        with data_fs.open(nbfile, 'w') as fw:
            nb_to_ipynb_io(nb, fw)
Пример #7
0
def dockerize(ipynb, cwd, output, **kwargs):
    env = get_jinja2_env(config=get_env(cwd=cwd,
                                        ipynb=ipynb,
                                        mode='dockerize',
                                        **kwargs), )
    env.get_template('production/Dockerfile.j2').stream().dump(output)
Пример #8
0
import os, sys
sys.path.insert(0, os.path.realpath('..'))

from appyter.parse.nb import nb_from_ipynb_file
from appyter.render.nbconstruct import render_nb_from_nbtemplate
from appyter.render.form import render_form_from_nbtemplate
from appyter.context import get_jinja2_env, get_env
from appyter.parse.nbtemplate import parse_fields_from_nbtemplate
from appyter.parse.nb import parse_markdown

nbtemplate = nb_from_ipynb_file('example.ipynb')

config = get_env(cwd=os.path.dirname(__file__), ipynb='example.ipynb')
env = get_jinja2_env(config=config)
parse_fields_from_nbtemplate(env, nbtemplate)

env = get_jinja2_env(config=config)
render_form_from_nbtemplate(env, nbtemplate)

env = get_jinja2_env(
    context={
        'number_1': 8,
        'operator': 'subtract',
    },
    config=config,
)
render_nb_from_nbtemplate(env, nbtemplate)
Пример #9
0
def init(_globals, verbose=False, ipynb='app.ipynb', mode='magic', **kwargs):
    ''' Initialize appyter magic.

  Sets up a jinj2 environment and injects %%appyter magic into your environment.
  
  :param _globals: (Dict[str, Any]) A callable with your globals for the purpose of injection, basically just: `lambda _=globals: _()`
  :param verbose: (Optional[bool]) Expand exception reporting to be more verbose
  '''
    import os
    import jinja2
    import jinja2.meta
    import traceback
    from appyter.context import get_env, get_jinja2_env
    env = get_jinja2_env(
        config=get_env(verbose=verbose, ipynb=ipynb, mode=mode, **kwargs))
    from IPython.core.magic import register_cell_magic
    from IPython.display import display, Markdown, HTML
    '''
  register_cell_magic allows function to execute an entire cell with the following call structure:
  ```python
  %%my_magic whatever
  all
  my
  data
  ```
  Results in a call:
  ```python
  my_magic(
    "whatever",
    """all
    my
    data"""
  )
  ```
  '''
    @register_cell_magic
    def appyter(line, cell):
        ''' Appyter Cell Magic: See Steps for more information.
    Compile jinja2 into source code, and then evaluate that
    source code.
    '''
        '''
    Step 1. Render cell with jinja2, removing empty lines.
    execute or display the results, modifying a copy of the
    current python globals dict.
    '''
        global_internal = _globals()
        cell_type = line.split('_')
        try:
            cell_lines = cell.splitlines()
            try:
                undeclared = jinja2.meta.find_undeclared_variables(
                    env.parse(cell))
                if undeclared:
                    for lineno, cell_line in enumerate(cell_lines):
                        if any(v in cell_line for v in undeclared):
                            display(
                                HTML(
                                    f"<div style='color: red'>{lineno}: {cell_line}</div>"
                                ))
                    raise Exception(f"undeclared variable(s) {undeclared}")
                template = env.from_string(cell)
                template_rendered = template.render()
            except Exception as e:
                if getattr(e, 'lineno', None) is not None:
                    display(
                        HTML(
                            f"<div style='color: red'>{e.lineno}: {cell_lines[e.lineno-1]}</div>"
                        ))
                raise e
            #
            rendered_template_lines = list(
                filter(None, map(str.rstrip, template_rendered.splitlines())))
            try:
                if len(rendered_template_lines) > 0:
                    if cell_type == ['markdown']:
                        display(Markdown(template_rendered))
                    elif 'code' in cell_type:
                        rendered = '\n'.join(rendered_template_lines[:-1])
                        rendered_last = rendered_template_lines[-1]
                        display(
                            Markdown('```python\n%s\n```' % ('\n'.join(
                                (rendered, rendered_last)))))
                        #
                        if 'eval' in cell_type:
                            exec(rendered, global_internal)
                            #
                            try:
                                display(eval(rendered_last, global_internal))
                            except Exception as e:
                                setattr(e, 'lineno',
                                        len(rendered_template_lines))
                                raise e
                        elif 'exec' in cell_type:
                            exec('\n'.join((rendered, rendered_last)),
                                 global_internal)
                    else:
                        raise Exception('Unrecognized appyter cell_type')
                #
            except Exception as e:
                if getattr(e, 'lineno', None) is not None:
                    display(
                        HTML(
                            f"<div style='color: red'>{e.lineno}: {rendered_template_lines[e.lineno-1]}</div>"
                        ))
                raise e
        except Exception as e:
            display(HTML(f"<div style='color: red'>Error: {e}</div>"))
            if verbose:
                traceback.print_exc()
            return
        '''
    Step 2. Check for new variables in the internal global
    and pass them to the python global scope. Check for
    new variables in the jinja2 template and pass them to the
    template environment global so they are available in
    future jinja2 calls.
    '''
        for k, v in global_internal.items():
            if not k.startswith('_'):
                _globals()[k] = v

        for k, v in template.module.__dict__.items():
            if not k.startswith('_'):
                env.globals[k] = v
Пример #10
0
def nbinspect(cwd, ipynb, output, **kwargs):
    env = get_jinja2_env(
        config=get_env(cwd=cwd, ipynb=ipynb, mode='inspect', **kwargs))
    nbtemplate = nb_from_ipynb_io(Filesystem(cwd).open(ipynb, 'r'))
    fields = render_nbtemplate_json_from_nbtemplate(env, nbtemplate)
    json.dump(fields, output)