Example #1
0
def url_for(directory, public=False, **kwargs):
    from appyter.context import get_env
    from appyter.util import safe_join, join_routes
    config = get_env()
    url = None
    if config['DEBUG']:
        try:
            from flask import url_for
            modified_directory = '.'.join(
                ('__main__',
                 directory)) if directory == 'static' else directory
            url = url_for(modified_directory, **kwargs)
        except:
            pass
    #
    if url is None:
        filename = kwargs.get('filename', kwargs.get('path'))
        assert filename is not None
        url = safe_join(config['PREFIX'], directory, filename)
    #
    if public:
        try:
            from flask import request
            url = join_routes(request.url_root, url)[1:]
        except:
            pass
    #
    return url
Example #2
0
 def public_url(self):
   try:
     from flask import request
     return join_routes(request.base_url, self.value)[1:]
   except:
     from appyter.context import get_env
     config = get_env()
     return join_routes(config.get('PUBLIC_URL', 'file:///' + config.get('CWD')), self.value)[1:]
Example #3
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())
Example #4
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)
Example #5
0
def serve(app_path, **kwargs):
    import os
    import asyncio
    import appyter
    from appyter.ext.asyncio.event_emitter import EventEmitter
    from appyter.ext.watchgod.watcher import GlobWatcher
    from appyter.context import get_env
    config = get_env(**kwargs)
    loop = asyncio.get_event_loop()
    emitter = EventEmitter()
    # run the app and reload it when necessary
    loop.create_task(app_runner(emitter, config))
    # the underlying appyter library
    loop.create_task(
        file_watcher(
            emitter,
            'reload',
            appyter.__path__[0],
            watcher_cls=GlobWatcher,
            watcher_kwargs=dict(
                include_dir_glob=['*'],
                include_file_glob=['*.py'],
                exclude_dir_glob=[],
                exclude_file_glob=[],
            ),
        ))
    # the underlying appyter library's templates/ipynb/staticfiles/...
    loop.create_task(
        file_watcher(
            emitter,
            'livereload',
            os.path.join(appyter.__path__[0], 'profiles'),
            watcher_cls=GlobWatcher,
            watcher_kwargs=dict(
                include_dir_glob=['*'],
                include_file_glob=['*'],
                exclude_dir_glob=[],
                exclude_file_glob=['*.py'],
            ),
        ))
    # the appyter itself's filters/blueprints
    loop.create_task(
        file_watcher(
            emitter,
            'reload',
            config['CWD'],
            watcher_cls=GlobWatcher,
            watcher_kwargs=dict(
                include_dir_glob=['filters', 'blueprints'],
                include_file_glob=['*.py'],
                exclude_dir_glob=[],
                exclude_file_glob=[],
            ),
        ))
    # the appyter itself's templates/ipynb/staticfiles/...
    loop.create_task(
        file_watcher(
            emitter,
            'livereload',
            config['CWD'],
            watcher_cls=GlobWatcher,
            watcher_kwargs=dict(
                include_dir_glob=['*'],
                include_file_glob=['*'],
                exclude_dir_glob=[config['DATA_DIR']],
                exclude_file_glob=['*.py'],
            ),
        ))
    loop.create_task(app_messager(emitter, config))
    loop.run_forever()
Example #6
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)
Example #7
0
def create_app(**kwargs):
    ''' Completely initialize the flask application
  '''
    from aiohttp import web
    from aiohttp_wsgi import WSGIHandler
    from aiohttp_remotes import setup, XForwardedRelaxed
    #
    from flask import Flask, Blueprint, current_app, redirect
    from flask_cors import CORS
    #
    from appyter.render.flask_app.socketio import socketio
    from appyter.render.flask_app.core import core
    import appyter.render.flask_app.static
    import appyter.render.flask_app.download
    import appyter.render.flask_app.execution
    if kwargs['debug']:
        import appyter.render.flask_app.livereload
    #
    from appyter.context import get_env, find_blueprints
    from appyter.util import join_routes
    config = get_env(**kwargs)
    #
    if config['DEBUG']:
        logging.basicConfig(
            level=logging.DEBUG,
            format='%(name)s %(message).80s',
        )
    else:
        logging.basicConfig(
            level=logging.WARNING,
            format='%(name)s %(message).80s',
        )
        logging.getLogger(__package__).setLevel(logging.INFO)
    #
    logger.info('Initializing aiohttp...')
    app = web.Application()
    app['config'] = config
    #
    logger.info('Initializing socketio...')
    socketio.attach(app, join_routes(config['PREFIX'], 'socket.io'))
    #
    logger.info('Initializing flask...')
    flask_app = Flask(__name__, static_url_path=None, static_folder=None)
    CORS(flask_app)
    flask_app.config.update(config)
    flask_app.debug = config['DEBUG']
    #
    logger.info('Registering blueprints...')
    flask_app.register_blueprint(core)
    for blueprint_name, blueprint in find_blueprints(
            config=flask_app.config).items():
        if isinstance(blueprint, Blueprint):
            flask_app.register_blueprint(blueprint,
                                         url_prefix='/' +
                                         blueprint_name.strip('/'))
        elif callable(blueprint):
            blueprint(flask_app, url_prefix='/' + blueprint_name.strip('/'))
        else:
            raise Exception('Unrecognized blueprint type: ' + blueprint_name)
    #
    if app['config']['PREFIX'].strip('/'):
        logger.info('Registering prefix redirect')

        async def redirect_to_prefix(request):
            path = request.match_info['path']
            if path == app['config']['PREFIX'].strip('/'): path = ''
            raise web.HTTPFound(
                join_routes(app['config']['PREFIX'], path) + '/')

        app.router.add_get('/{path:[^/]*}', redirect_to_prefix)
    #
    logger.info('Registering flask with aiohttp...')
    wsgi_handler = WSGIHandler(flask_app)
    app.router.add_route(
        '*', join_routes(app['config']['PREFIX'], '{path_info:.*}'),
        wsgi_handler)
    if flask_app.config['PROXY']:
        logger.info('Applying proxy fix middleware...')
        import asyncio
        asyncio.get_event_loop().run_until_complete(
            setup(app, XForwardedRelaxed()))
    return app
Example #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)
Example #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
Example #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)