示例#1
0
def render_syntax_error(project: 'projects.Project', code: str,
                        error: SyntaxError) -> dict:
    """

    :param project:
    :param code:
    :param error:
    :return:
    """

    stack = [
        dict(filename=error.filename,
             location=None,
             line_number=error.lineno,
             line=error.text.rstrip())
    ]

    render_data = dict(type=error.__class__.__name__,
                       message='{}'.format(error),
                       stack=stack)

    return dict(success=False,
                error=error,
                message=templating.render_template('user-code-error.txt',
                                                   **render_data),
                html_message=templating.render_template(
                    'user-code-error.html', **render_data))
示例#2
0
def render_error(project: 'projects.Project',
                 error: Exception,
                 stack: typing.List[dict] = None) -> dict:
    """
    Renders an Exception to an error response that includes rendered text and
    html error messages for display.

    :param project:
        Currently open project.
    :param error:
        The SyntaxError to be rendered to html and text for display.
    :param stack:
        Optionally specify a parsed stack. If this value is None the standard
        Cauldron stack frames will be rendered.
    :return:
        A dictionary containing the error response with rendered display
        messages for both text and html output.
    """

    data = dict(type=error.__class__.__name__,
                message='{}'.format(error),
                stack=(stack if stack is not None else
                       render_stack.get_formatted_stack_frame(project)))

    return dict(success=False,
                error=error,
                message=templating.render_template('user-code-error.txt',
                                                   **data),
                html_message=templating.render_template(
                    'user-code-error.html', **data))
示例#3
0
def plotly(
        data: list = None,
        layout: dict = None,
        scale: float = 0.5,
        figure: dict = None,
        static: bool = False
) -> str:
    """

    :param data:
    :param layout:
    :param scale:
    :param figure:
    :param static:
    :return:
    """
    environ.abort_thread()

    try:
        import plotly as plotly_lib
    except ImportError:
        plotly_lib = None

    if plotly_lib is None:
        return templating.render_template(
            template_name='import-error.html',
            library_name='Plotly'
        )

    source = figure if figure else {'data': data, 'layout': layout}

    dom = plotly_lib.offline.plot(
        figure_or_data=source,
        output_type='div',
        include_plotlyjs=False
    )

    found = re.search(r'id="(?P<id>[^"]+)"', dom)
    dom_id = found.group('id')

    insert_index = dom.index('"showLink":')
    dom = ''.join([
        dom[:insert_index],
        '"staticPlot": {}, '.format('true' if static else 'false'),
        dom[insert_index:]
    ])

    return templating.render_template(
        'plotly-component.html',
        dom=dom,
        scale=scale,
        min_height=round(100.0 * scale),
        id=dom_id
    )
示例#4
0
def bokeh_plot(model, scale: float = 0.7, responsive: bool = True) -> str:
    """

    :param model:
    :param scale:
    :param responsive:
    :return:
    """

    environ.abort_thread()

    try:
        from bokeh import embed
    except Exception:
        embed = None

    if responsive:
        model.sizing_mode = "scale_width"
        # model.responsive = True
        model.plot_width = 800
        model.plot_height = round((scale * 9 / 16) * 800)

    results = embed.components(model)

    script = results[0] \
        .split('>', 1)[1] \
        .rsplit('</', 1)[0]

    return templating.render_template(
        'bokeh_component.html',
        script=script,
        dom=results[1],
        scale=round(100 * scale) if scale is not None else 1000)
示例#5
0
def list_grid(
        source: list,
        expand_full: bool = False,
        column_count: int = 2,
        row_spacing: float = 1
):
    """

    :param source:
    :param expand_full:
    :param column_count:
    :param row_spacing:
    :return:
    """
    environ.abort_thread()
    max_width = 1400 if expand_full else 900
    column_width = '{}px'.format(
        max(50, int(math.floor(max_width / column_count)))
    )

    return templating.render_template(
        'list_grid.html',
        items=['{}'.format(x) for x in source],
        css_modifier='full' if expand_full else 'limited',
        column_width=column_width,
        row_spacing=row_spacing
    )
示例#6
0
def code_block(
        block: str = None,
        path: str = None,
        language: str = None,
        title: str = None,
        caption: str = None
) -> str:
    """

    :param block:
    :param path:
    :param language:
    :param title:
    :param caption:
    :return:
    """
    environ.abort_thread()

    code_dom = (
        code_file(path, language=language, is_code_block=True)
        if path else
        code(block, language=language, is_code_block=True)
    )

    return templating.render_template(
        'code-block.html',
        code=code_dom,
        title=title,
        caption=caption
    )
示例#7
0
def run(
        project: 'projects.Project',
        step: 'projects.ProjectStep'
) -> dict:
    """
    Runs the markdown file and renders the contents to the notebook display

    :param project:
    :param step:
    :return:
        A run response dictionary containing
    """

    with open(step.source_path, 'r') as f:
        code = f.read()

    try:
        cauldron.display.markdown(code, **project.shared.fetch(None))
        return {'success': True}
    except Exception as err:
        return dict(
            success=False,
            html_message=templating.render_template(
                'markdown-error.html',
                error=err
            )
        )
示例#8
0
def create(project: 'projects.Project',
           destination_directory,
           destination_filename: str = None) -> file_io.FILE_WRITE_ENTRY:
    """
    Creates a FILE_WRITE_ENTRY for the rendered HTML file for the given
    project that will be saved in the destination directory with the given
    filename.

    :param project:
        The project for which the rendered HTML file will be created
    :param destination_directory:
        The absolute path to the folder where the HTML file will be saved
    :param destination_filename:
        The name of the HTML file to be written in the destination directory.
        Defaults to the project uuid.
    :return:
        A FILE_WRITE_ENTRY for the project's HTML file output
    """

    template_path = environ.paths.resources('web', 'project.html')
    with open(template_path, 'r') as f:
        dom = f.read()

    dom = dom.replace(
        '<!-- CAULDRON:EXPORT -->',
        templating.render_template('notebook-script-header.html',
                                   uuid=project.uuid,
                                   version=environ.version))

    filename = (destination_filename
                if destination_filename else '{}.html'.format(project.uuid))

    html_out_path = os.path.join(destination_directory, filename)

    return file_io.FILE_WRITE_ENTRY(path=html_out_path, contents=dom)
示例#9
0
文件: shell.py 项目: sernst/cauldron
def render_intro():
    return '\n{}\n'.format(
        templating.render_template(
            'shell_introduction.txt',
            version=package_data['version']
        )
    )
示例#10
0
def render_stop_display(step: 'projects.ProjectStep', message: str):
    """Renders a stop action to the Cauldron display."""
    stack = render_stack.get_formatted_stack_frame(
        project=step.project,
        error_stack=False
    )

    try:
        names = [frame['filename'] for frame in stack]
        index = names.index(os.path.realpath(__file__))
        frame = stack[index - 1]
    except Exception:
        frame = {}

    stop_message = (
        '{}'.format(message)
        if message else
        'This step was explicitly stopped prior to its completion'
    )

    dom = templating.render_template(
        'step-stop.html',
        message=stop_message,
        frame=frame
    )
    step.report.append_body(dom)
示例#11
0
def table(data_frame,
          scale: float = 0.7,
          include_index: bool = False,
          max_rows: int = 500) -> str:
    """

    :param data_frame:
    :param scale:
    :param include_index:
    :param max_rows:
    :return:
    """

    environ.abort_thread()

    table_id = 'table-{}-{}'.format(datetime.utcnow().strftime('%H-%M-%S-%f'),
                                    random.randint(0, 1e8))

    df_source = (data_frame.head(max_rows)
                 if len(data_frame) > max_rows else data_frame)

    if include_index:
        df_source = df_source.reset_index()

    column_headers = ['"{}"'.format(x) for x in df_source.columns.tolist()]
    data = df_source.values.tolist()
    json_data = json_internal.dumps(data, cls=encoding.ComplexJsonEncoder)

    return templating.render_template('table.html',
                                      id=table_id,
                                      scale=min(0.95, max(0.05, scale)),
                                      data=json_data,
                                      column_headers=', '.join(column_headers))
示例#12
0
def plotly(data: list = None,
           layout: dict = None,
           scale: float = 0.5,
           figure: dict = None,
           static: bool = False) -> str:
    """

    :param data:
    :param layout:
    :param scale:
    :param figure:
    :param static:
    :return:
    """
    environ.abort_thread()

    try:
        import plotly as plotly_lib
    except ImportError:
        plotly_lib = None

    if plotly_lib is None:
        return templating.render_template(template_name='import-error.html',
                                          library_name='Plotly')

    source = figure if figure else {'data': data, 'layout': layout}

    dom = plotly_lib.offline.plot(figure_or_data=source,
                                  output_type='div',
                                  include_plotlyjs=False)

    found = re.search(r'id="(?P<id>[^"]+)"', dom)
    dom_id = found.group('id')

    insert_index = dom.index('"showLink":')
    dom = ''.join([
        dom[:insert_index],
        '"staticPlot": {}, '.format('true' if static else 'false'),
        dom[insert_index:]
    ])

    return templating.render_template('plotly-component.html',
                                      dom=dom,
                                      scale=scale,
                                      min_height=round(100.0 * scale),
                                      id=dom_id)
示例#13
0
    def test_render_template(self):
        """

        :return:
        """

        result = templating.render_template('unit_test.html', value='hello')
        self.assertEqual(result, 'hello')
示例#14
0
    def dumps(self) -> str:
        """Writes the step information to an HTML-formatted string"""
        code_file_path = os.path.join(self.project.source_directory,
                                      self.filename)
        code = dict(filename=self.filename,
                    path=code_file_path,
                    code=render.code_file(code_file_path))

        if not self.is_running:
            # If no longer running, make sure to flush the stdout buffer so
            # any print statements at the end of the step get included in
            # the body
            self.report.flush_stdout()

        # Create a copy of the body for dumping
        body = self.report.body[:]

        if self.is_running:
            # If still running add a temporary copy of anything not flushed
            # from the stdout buffer to the copy of the body for display. Do
            # not flush the buffer though until the step is done running or
            # it gets flushed by another display call.
            body.append(self.report.read_stdout())

        body = ''.join(body)

        has_body = len(body) > 0 and (
            body.find('<div') != -1 or body.find('<span') != -1
            or body.find('<p') != -1 or body.find('<pre') != -1
            or body.find('<h') != -1 or body.find('<ol') != -1
            or body.find('<ul') != -1 or body.find('<li') != -1)

        std_err = (self.report.read_stderr() if self.is_running else
                   self.report.flush_stderr()).strip('\n').rstrip()

        dom = templating.render_template(
            'step-body.html',
            last_display_update=self.report.last_update_time,
            elapsed_time=self.get_elapsed_timestamp(),
            code=code,
            body=body,
            has_body=has_body,
            id=self.definition.name,
            title=self.report.title,
            subtitle=self.report.subtitle,
            summary=self.report.summary,
            error=self.error,
            index=self.index,
            is_running=self.is_running,
            progress_message=self.progress_message,
            progress=int(round(max(0, min(100, 100 * self.progress)))),
            sub_progress_message=self.sub_progress_message,
            sub_progress=int(round(max(0, min(100, 100 * self.sub_progress)))),
            std_err=std_err)

        if not self.is_running:
            self.dom = dom
        return dom
示例#15
0
def render_error(project: 'projects.Project', error: Exception) -> dict:
    """

    :param project:
    :param error:
    :return:
    """

    render_data = dict(
        type=error.__class__.__name__,
        message='{}'.format(error),
        stack=[format_stack_frame(f, project) for f in get_stack_frames()])

    return dict(success=False,
                error=error,
                message=templating.render_template('user-code-error.txt',
                                                   **render_data),
                html_message=templating.render_template(
                    'user-code-error.html', **render_data))
示例#16
0
def elapsed_time(seconds: float) -> str:
    """Displays the elapsed time since the current step started running."""
    environ.abort_thread()
    parts = ('{}'.format(timedelta(seconds=seconds)).rsplit('.', 1))
    hours, minutes, seconds = parts[0].split(':')
    return templating.render_template(
        'elapsed_time.html',
        hours=hours.zfill(2),
        minutes=minutes.zfill(2),
        seconds=seconds.zfill(2),
        microseconds=parts[-1] if len(parts) > 1 else '')
示例#17
0
def latex(source: str, inline: bool = False) -> str:
    """

    :param source:
    :param inline:
    :return:
    """
    environ.abort_thread()

    return templating.render_template('katex.html',
                                      source=render_utils.format_latex(source),
                                      inline=inline)
示例#18
0
def json(**kwargs) -> str:
    """

    :param kwargs:
    :return:
    """
    environ.abort_thread()

    return templating.render_template(
        'json_include.html',
        data=json_internal.dumps(kwargs, cls=encoding.ComplexJsonEncoder)
    )
示例#19
0
def status(
        data: dict,
        values: bool = True,
        types: bool = True
) -> str:
    """

    :param data:
    :param values:
    :param types:
    :return:
    """
    environ.abort_thread()

    out = []
    keys = list(data.keys())
    keys.sort()

    for key in keys:
        value = data[key]
        value_type = getattr(
            value,
            '__class__',
            {'__name__': 'Unknown'}
        ).__name__

        if hasattr(value, 'head'):
            try:
                value = value.head(5)
            except Exception:
                pass
        elif isinstance(value, dict):
            temp_value = []
            for k, v in value.items():
                temp_value.append('{}: {}'.format(k, v))
            value = '\n'.join(temp_value)
        elif isinstance(value, (list, tuple)):
            value = '\n'.join(['{}'.format(v) for v in value])

        value = '<pre>{}</pre>'.format(
            render_utils.html_escape('{}'.format(value))[:600]
        )

        out.append(templating.render_template(
            'status-variable.template.html',
            name=key,
            values=values,
            types=types,
            type=value_type,
            value=value
        ))

    return ''.join(out)
示例#20
0
def json(**kwargs) -> str:
    """

    :param kwargs:
    :return:
    """
    environ.abort_thread()

    return templating.render_template('json_include.html',
                                      data=json_internal.dumps(
                                          kwargs,
                                          cls=encoding.ComplexJsonEncoder))
示例#21
0
文件: texts.py 项目: sernst/cauldron
def latex(source: str, inline: bool = False) -> str:
    """

    :param source:
    :param inline:
    :return:
    """
    environ.abort_thread()

    return templating.render_template(
        'katex.html',
        source=render_utils.format_latex(source),
        inline=inline
    )
示例#22
0
def render_error(
        project: 'projects.Project',
        error: Exception,
        stack: typing.List[dict] = None
) -> dict:
    """
    Renders an Exception to an error response that includes rendered text and
    html error messages for display.

    :param project:
        Currently open project.
    :param error:
        The SyntaxError to be rendered to html and text for display.
    :param stack:
        Optionally specify a parsed stack. If this value is None the standard
        Cauldron stack frames will be rendered.
    :return:
        A dictionary containing the error response with rendered display
        messages for both text and html output.
    """

    data = dict(
        type=error.__class__.__name__,
        message='{}'.format(error),
        stack=(
            stack
            if stack is not None else
            render_stack.get_formatted_stack_frame(project)
        )
    )

    return dict(
        success=False,
        error=error,
        message=templating.render_template('user-code-error.txt', **data),
        html_message=templating.render_template('user-code-error.html', **data)
    )
示例#23
0
def elapsed_time(seconds: float) -> str:
    """Displays the elapsed time since the current step started running."""
    environ.abort_thread()
    parts = (
        '{}'.format(timedelta(seconds=seconds))
        .rsplit('.', 1)
    )
    hours, minutes, seconds = parts[0].split(':')
    return templating.render_template(
        'elapsed_time.html',
        hours=hours.zfill(2),
        minutes=minutes.zfill(2),
        seconds=seconds.zfill(2),
        microseconds=parts[-1] if len(parts) > 1 else ''
    )
示例#24
0
def load_step_file(source_path: str) -> str:
    """
    Loads the source for a step file at the given path location and then
    renders it in a template to add additional footer data.

    The footer is used to force the display to flush the print buffer and
    breathe the step to open things up for resolution. This shouldn't be
    necessary, but it seems there's an async race condition with print
    buffers that is hard to reproduce and so this is in place to fix the
    problem.
    """

    return templating.render_template(
        template_name='embedded-step.py.txt',
        source_contents=get_file_contents(source_path))
示例#25
0
def image(
        rendered_path: str,
        width: int = None,
        height: int = None,
        justify: str = None
) -> str:
    """Renders an image block"""
    environ.abort_thread()
    return templating.render_template(
        'image.html',
        path=rendered_path,
        width=width,
        height=height,
        justification=(justify or 'left').lower()
    )
示例#26
0
def table(
        data_frame,
        scale: float = 0.7,
        include_index: bool = False,
        max_rows: int = 500
) -> str:
    """

    :param data_frame:
    :param scale:
    :param include_index:
    :param max_rows:
    :return:
    """
    environ.abort_thread()

    table_id = 'table-{}-{}'.format(
        datetime.utcnow().strftime('%H-%M-%S-%f'),
        random.randint(0, 1e8)
    )

    df_source = (
        data_frame.head(max_rows)
        if len(data_frame) > max_rows else
        data_frame
    )

    if include_index:
        df_source = df_source.reset_index()

    try:
        column_headers = ['"{}"'.format(x) for x in df_source.columns.tolist()]
        data = df_source.values.tolist()
    except AttributeError:
        # If no columns are found assume that it is a Series instead of a
        # DataFrame and reformat the data to match the expected structure.
        column_headers = ['"{}"'.format(df_source.name)]
        data = df_source.values.reshape([len(df_source), 1]).tolist()

    json_data = json_internal.dumps(data, cls=encoding.ComplexJsonEncoder)

    return templating.render_template(
        'table.html',
        id=table_id,
        scale=min(0.95, max(0.05, scale)),
        data=json_data,
        column_headers=', '.join(column_headers)
    )
示例#27
0
def load_step_file(source_path: str) -> str:
    """
    Loads the source for a step file at the given path location and then
    renders it in a template to add additional footer data.

    The footer is used to force the display to flush the print buffer and
    breathe the step to open things up for resolution. This shouldn't be
    necessary, but it seems there's an async race condition with print
    buffers that is hard to reproduce and so this is in place to fix the
    problem.
    """

    return templating.render_template(
        template_name='embedded-step.py.txt',
        source_contents=get_file_contents(source_path)
    )
示例#28
0
def listing(source: list,
            ordered: bool = False,
            expand_full: bool = False) -> str:
    """

    :param source:
    :param ordered:
    :param expand_full:
    :return:
    """
    environ.abort_thread()

    return templating.render_template(
        'listing.html',
        type='ol' if ordered else 'ul',
        items=['{}'.format(x) for x in source],
        css_modifier='full' if expand_full else 'limited')
示例#29
0
文件: html.py 项目: sernst/cauldron
def create(
        project: 'projects.Project',
        destination_directory,
        destination_filename: str = None
) -> file_io.FILE_WRITE_ENTRY:
    """
    Creates a FILE_WRITE_ENTRY for the rendered HTML file for the given
    project that will be saved in the destination directory with the given
    filename.

    :param project:
        The project for which the rendered HTML file will be created
    :param destination_directory:
        The absolute path to the folder where the HTML file will be saved
    :param destination_filename:
        The name of the HTML file to be written in the destination directory.
        Defaults to the project uuid.
    :return:
        A FILE_WRITE_ENTRY for the project's HTML file output
    """

    template_path = environ.paths.resources('web', 'project.html')
    with open(template_path, 'r') as f:
        dom = f.read()

    dom = dom.replace(
        '<!-- CAULDRON:EXPORT -->',
        templating.render_template(
            'notebook-script-header.html',
            uuid=project.uuid,
            version=environ.version
        )
    )

    filename = (
        destination_filename
        if destination_filename else
        '{}.html'.format(project.uuid)
    )

    html_out_path = os.path.join(destination_directory, filename)

    return file_io.FILE_WRITE_ENTRY(
        path=html_out_path,
        contents=dom
    )
示例#30
0
def status(data: dict, values: bool = True, types: bool = True) -> str:
    """

    :param data:
    :param values:
    :param types:
    :return:
    """
    environ.abort_thread()

    out = []
    keys = list(data.keys())
    keys.sort()

    for key in keys:
        value = data[key]
        value_type = getattr(value, '__class__', {
            '__name__': 'Unknown'
        }).__name__

        if hasattr(value, 'head'):
            try:
                value = value.head(5)
            except Exception:
                pass
        elif isinstance(value, dict):
            temp_value = []
            for k, v in value.items():
                temp_value.append('{}: {}'.format(k, v))
            value = '\n'.join(temp_value)
        elif isinstance(value, (list, tuple)):
            value = '\n'.join(['{}'.format(v) for v in value])

        value = '<pre>{}</pre>'.format(
            render_utils.html_escape('{}'.format(value))[:600])

        out.append(
            templating.render_template('status-variable.template.html',
                                       name=key,
                                       values=values,
                                       types=types,
                                       type=value_type,
                                       value=value))

    return ''.join(out)
示例#31
0
def to_write_list(project: 'projects.Project') -> typing.List[tuple]:
    """

    :param project:
    :return:
    """

    project_component = components.project_component.create_many(
        project,
        project.settings.fetch('web_includes', [])
    )

    steps_data = [step_writer.serialize(s) for s in project.steps]
    file_writes = [item for sd in steps_data for item in sd.file_writes]
    file_writes.extend(project_component.files)

    def to_step_dict(step: step_writer.STEP_DATA) -> dict:
        out = step._asdict()
        del out['file_writes']
        return out

    project_includes = [inc._asdict() for inc in project_component.includes]

    file_writes.append(file_io.FILE_WRITE_ENTRY(
        path=project.output_path,
        contents=templating.render_template(
            'report.js.template',
            DATA=json.dumps({
                'steps': [to_step_dict(sd) for sd in steps_data],
                'includes': project_includes,
                'settings': project.settings.fetch(None),
                'cauldron_version': list(environ.version_info)
            })
        )
    ))

    file_writes.extend(list_asset_writes(project))
    file_writes.append(html.create(
        project,
        project.results_path,
        'display.html'
    ))

    return file_writes
示例#32
0
def render_stop_display(step: 'projects.ProjectStep', message: str):
    """Renders a stop action to the Cauldron display."""
    stack = render_stack.get_formatted_stack_frame(project=step.project,
                                                   error_stack=False)

    try:
        names = [frame['filename'] for frame in stack]
        index = names.index(os.path.realpath(__file__))
        frame = stack[index - 1]
    except Exception:
        frame = {}

    stop_message = ('{}'.format(message) if message else
                    'This step was explicitly stopped prior to its completion')

    dom = templating.render_template('step-stop.html',
                                     message=stop_message,
                                     frame=frame)
    step.report.append_body(dom)
示例#33
0
def listing(
        source: list,
        ordered: bool = False,
        expand_full: bool = False
) -> str:
    """

    :param source:
    :param ordered:
    :param expand_full:
    :return:
    """
    environ.abort_thread()

    return templating.render_template(
        'listing.html',
        type='ol' if ordered else 'ul',
        items=['{}'.format(x) for x in source],
        css_modifier='full' if expand_full else 'limited'
    )
示例#34
0
def run(project: 'projects.Project', step: 'projects.ProjectStep') -> dict:
    """
    Runs the markdown file and renders the contents to the notebook display

    :param project:
    :param step:
    :return:
        A run response dictionary containing
    """

    with open(step.source_path, 'r') as f:
        code = f.read()

    try:
        cauldron.display.markdown(code, **project.shared.fetch(None))
        return {'success': True}
    except Exception as err:
        return dict(success=False,
                    html_message=templating.render_template(
                        'markdown-error.html', error=err))
示例#35
0
def to_write_list(project: 'projects.Project') -> typing.List[tuple]:
    """

    :param project:
    :return:
    """

    project_component = components.project_component.create_many(
        project, project.settings.fetch('web_includes', []))

    steps_data = [step_writer.serialize(s) for s in project.steps]
    file_writes = [item for sd in steps_data for item in sd.file_writes]
    file_writes.extend(project_component.files)

    def to_step_dict(step: step_writer.STEP_DATA) -> dict:
        out = step._asdict()
        del out['file_writes']
        return out

    project_includes = [inc._asdict() for inc in project_component.includes]

    file_writes.append(
        file_io.FILE_WRITE_ENTRY(
            path=project.output_path,
            contents=templating.render_template(
                'report.js.template',
                DATA=json.dumps({
                    'steps': [to_step_dict(sd) for sd in steps_data],
                    'includes':
                    project_includes,
                    'settings':
                    project.settings.fetch(None),
                    'cauldron_version':
                    list(environ.version_info)
                }))))

    file_writes.extend(list_asset_writes(project))
    file_writes.append(
        html.create(project, project.results_path, 'display.html'))

    return file_writes
示例#36
0
    def stop(self, message: str = None, silent: bool = False):
        """
        Stops the execution of the current step immediately without raising
        an error. Use this to abort the step running process if you want
        to return early.

        :param message:
            A custom display message to include in the display for the stop
            action. This message is ignored if silent is set to True.
        :param silent:
            When True nothing will be shown in the notebook display when the
            step is stopped. When False, the notebook display will include
            information relating to the stopped action.
        """

        step = self._step

        if not step:
            return

        if not silent:
            stack = render_stack.get_formatted_stack_frame(
                project=step.project, error_stack=False)

            try:
                names = [frame['filename'] for frame in stack]
                index = names.index(os.path.realpath(__file__))
                frame = stack[index - 1]
            except Exception:
                frame = {}

            stop_message = (
                '{}'.format(message) if message else
                'This step was explicitly stopped prior to its completion')

            dom = templating.render_template('step-stop.html',
                                             message=stop_message,
                                             frame=frame)
            step.report.append_body(dom)

        raise UserAbortError()
示例#37
0
def table(data_frame,
          scale: float = 0.7,
          include_index: bool = False,
          max_rows: int = 500) -> str:
    """

    :param data_frame:
    :param scale:
    :param include_index:
    :param max_rows:
    :return:
    """

    environ.abort_thread()

    table_id = 'table-{}-{}'.format(datetime.utcnow().strftime('%H-%M-%S-%f'),
                                    random.randint(0, 1e8))

    df_source = (data_frame.head(max_rows)
                 if len(data_frame) > max_rows else data_frame)

    if include_index:
        df_source = df_source.reset_index()

    try:
        column_headers = ['"{}"'.format(x) for x in df_source.columns.tolist()]
        data = df_source.values.tolist()
    except AttributeError:
        # If no columns are found assume that it is a Series instead of a
        # DataFrame and reformat the data to match the expected structure.
        column_headers = ['"{}"'.format(df_source.name)]
        data = df_source.values.reshape([len(df_source), 1]).tolist()

    json_data = json_internal.dumps(data, cls=encoding.ComplexJsonEncoder)

    return templating.render_template('table.html',
                                      id=table_id,
                                      scale=min(0.95, max(0.05, scale)),
                                      data=json_data,
                                      column_headers=', '.join(column_headers))
示例#38
0
def code_block(block: str = None,
               path: str = None,
               language: str = None,
               title: str = None,
               caption: str = None) -> str:
    """

    :param block:
    :param path:
    :param language:
    :param title:
    :param caption:
    :return:
    """

    code_dom = (code_file(path, language=language, is_code_block=True) if path
                else code(block, language=language, is_code_block=True))

    return templating.render_template('code-block.html',
                                      code=code_dom,
                                      title=title,
                                      caption=caption)
示例#39
0
def render_tree(inspected_data: dict):
    """

    :param inspected_data:
    :return:
    """

    environ.abort_thread()

    def to_jstree_node(d: dict) -> dict:
        children = d.get('structure', [])
        if isinstance(children, (list, tuple)):
            children = [to_jstree_node(x) for x in children]
        else:
            children = []

        return dict(text='{} ({})'.format(d['key'], d['type']),
                    children=children)

    data = [to_jstree_node(v) for v in inspected_data['structure']]

    return templating.render_template('tree.html', data=data)
示例#40
0
文件: plots.py 项目: sernst/cauldron
def bokeh_plot(
        model,
        scale: float = 0.7,
        responsive: bool = True
) -> str:
    """

    :param model:
    :param scale:
    :param responsive:
    :return:
    """

    environ.abort_thread()

    try:
        from bokeh import embed
    except Exception:
        embed = None

    if responsive:
        model.sizing_mode = "scale_width"
        # model.responsive = True
        model.plot_width = 800
        model.plot_height = round((scale * 9 / 16) * 800)

    results = embed.components(model)

    script = results[0] \
        .split('>', 1)[1] \
        .rsplit('</', 1)[0]

    return templating.render_template(
        'bokeh_component.html',
        script=script,
        dom=results[1],
        scale=round(100 * scale) if scale is not None else 1000
    )
示例#41
0
def list_grid(source: list,
              expand_full: bool = False,
              column_count: int = 2,
              row_spacing: float = 1):
    """

    :param source:
    :param expand_full:
    :param column_count:
    :param row_spacing:
    :return:
    """
    environ.abort_thread()
    max_width = 1400 if expand_full else 900
    column_width = '{}px'.format(
        max(50, int(math.floor(max_width / column_count))))

    return templating.render_template(
        'list_grid.html',
        items=['{}'.format(x) for x in source],
        css_modifier='full' if expand_full else 'limited',
        column_width=column_width,
        row_spacing=row_spacing)
示例#42
0
def render_tree(inspected_data: dict):
    """

    :param inspected_data:
    :return:
    """

    environ.abort_thread()

    def to_jstree_node(d: dict) -> dict:
        children = d.get('structure', [])
        if isinstance(children, (list, tuple)):
            children = [to_jstree_node(x) for x in children]
        else:
            children = []

        return dict(
            text='{} ({})'.format(d['key'], d['type']),
            children=children
        )

    data = [to_jstree_node(v) for v in inspected_data['structure']]

    return templating.render_template('tree.html', data=data)
示例#43
0
def markdown(source: str = None,
             source_path: str = None,
             preserve_lines: bool = False,
             font_size: float = None,
             **kwargs) -> dict:
    """
    Renders a markdown file with support for Jinja2 templating. Any keyword
    arguments will be passed to Jinja2 for templating prior to rendering the
    markdown to HTML for display within the notebook.

    :param source:
        A string of markdown text that should be rendered to HTML for 
        notebook display.
    :param source_path:
        The path to a markdown file that should be rendered to HTML for
        notebook display.
    :param preserve_lines:
        If True, all line breaks will be treated as hard breaks. Use this
        for pre-formatted markdown text where newlines should be retained
        during rendering.
    :param font_size:
        Specifies a relative font size adjustment. The default value is 1.0,
        which preserves the inherited font size values. Set it to a value
        below 1.0 for smaller font-size rendering and greater than 1.0 for
        larger font size rendering.
    :return:
        The HTML results of rendering the specified markdown string or file.
    """

    environ.abort_thread()

    library_includes = []

    rendered = textwrap.dedent(
        templating.render_file(source_path, **kwargs)
        if source_path else templating.render(source or '', **kwargs))

    if md is None:
        raise ImportError('Unable to import the markdown package')

    offset = 0
    while offset < len(rendered):
        bound_chars = '$$'
        start_index = rendered.find(bound_chars, offset)

        if start_index < 0:
            break

        inline = rendered[start_index + 2] != '$'
        bound_chars = '$$' if inline else '$$$'
        end_index = rendered.find(bound_chars, start_index + len(bound_chars))

        if end_index < 0:
            break
        end_index += len(bound_chars)

        chunk = rendered[start_index: end_index] \
            .strip('$') \
            .strip() \
            .replace('@', '\\')

        if inline:
            chunk = chunk.replace('\\', '\\\\')

        chunk = latex(chunk, inline)
        rendered = '{pre}{gap}{latex}{gap}{post}'.format(
            pre=rendered[:start_index],
            latex=chunk,
            post=rendered[end_index:],
            gap='' if inline else '\n\n')

        if 'katex' not in library_includes:
            library_includes.append('katex')

        offset = end_index

    extensions = [
        'markdown.extensions.extra', 'markdown.extensions.admonition',
        'markdown.extensions.sane_lists',
        'markdown.extensions.nl2br' if preserve_lines else None
    ]

    body = templating.render_template(
        'markdown-block.html',
        text=md.markdown(rendered,
                         extensions=[e for e in extensions if e is not None]),
        font_size=font_size)

    pattern = re.compile('src="(?P<url>[^"]+)"')
    body = pattern.sub('data-src="\g<url>"', body)
    return dict(body=body,
                library_includes=library_includes,
                rendered=rendered)
示例#44
0
文件: texts.py 项目: sernst/cauldron
def markdown(
        source: str = None,
        source_path: str = None,
        preserve_lines: bool = False,
        font_size: float = None,
        **kwargs
) -> dict:
    """
    Renders a markdown file with support for Jinja2 templating. Any keyword
    arguments will be passed to Jinja2 for templating prior to rendering the
    markdown to HTML for display within the notebook.

    :param source:
        A string of markdown text that should be rendered to HTML for 
        notebook display.
    :param source_path:
        The path to a markdown file that should be rendered to HTML for
        notebook display.
    :param preserve_lines:
        If True, all line breaks will be treated as hard breaks. Use this
        for pre-formatted markdown text where newlines should be retained
        during rendering.
    :param font_size:
        Specifies a relative font size adjustment. The default value is 1.0,
        which preserves the inherited font size values. Set it to a value
        below 1.0 for smaller font-size rendering and greater than 1.0 for
        larger font size rendering.
    :return:
        The HTML results of rendering the specified markdown string or file.
    """

    environ.abort_thread()

    library_includes = []

    rendered = textwrap.dedent(
        templating.render_file(source_path, **kwargs)
        if source_path else
        templating.render(source or '', **kwargs)
    )

    if md is None:
        raise ImportError('Unable to import the markdown package')

    offset = 0
    while offset < len(rendered):
        bound_chars = '$$'
        start_index = rendered.find(bound_chars, offset)

        if start_index < 0:
            break

        inline = rendered[start_index + 2] != '$'
        bound_chars = '$$' if inline else '$$$'
        end_index = rendered.find(
            bound_chars,
            start_index + len(bound_chars)
        )

        if end_index < 0:
            break
        end_index += len(bound_chars)

        chunk = rendered[start_index: end_index] \
            .strip('$') \
            .strip() \
            .replace('@', '\\')

        if inline:
            chunk = chunk.replace('\\', '\\\\')

        chunk = latex(chunk, inline)
        rendered = '{pre}{gap}{latex}{gap}{post}'.format(
            pre=rendered[:start_index],
            latex=chunk,
            post=rendered[end_index:],
            gap='' if inline else '\n\n'
        )

        if 'katex' not in library_includes:
            library_includes.append('katex')

        offset = end_index

    extensions = [
        'markdown.extensions.extra',
        'markdown.extensions.admonition',
        'markdown.extensions.sane_lists',
        'markdown.extensions.nl2br' if preserve_lines else None
    ]

    body = templating.render_template(
        'markdown-block.html',
        text=md.markdown(rendered, extensions=[
            e for e in extensions if e is not None
        ]),
        font_size=font_size
    )

    pattern = re.compile('src="(?P<url>[^"]+)"')
    body = pattern.sub(r'data-src="\g<url>"', body)
    return dict(
        body=body,
        library_includes=library_includes,
        rendered=rendered
    )
示例#45
0
def render_intro():
    return '\n{}\n'.format(
        templating.render_template('shell_introduction.txt',
                                   version=package_data['version']))
示例#46
0
文件: steps.py 项目: sernst/cauldron
    def dumps(self) -> str:
        """Writes the step information to an HTML-formatted string"""
        code_file_path = os.path.join(
            self.project.source_directory,
            self.filename
        )
        code = dict(
            filename=self.filename,
            path=code_file_path,
            code=render.code_file(code_file_path)
        )

        if not self.is_running:
            # If no longer running, make sure to flush the stdout buffer so
            # any print statements at the end of the step get included in
            # the body
            self.report.flush_stdout()

        # Create a copy of the body for dumping
        body = self.report.body[:]

        if self.is_running:
            # If still running add a temporary copy of anything not flushed
            # from the stdout buffer to the copy of the body for display. Do
            # not flush the buffer though until the step is done running or
            # it gets flushed by another display call.
            body.append(self.report.read_stdout())

        body = ''.join(body)

        has_body = len(body) > 0 and (
            body.find('<div') != -1 or
            body.find('<span') != -1 or
            body.find('<p') != -1 or
            body.find('<pre') != -1 or
            body.find('<h') != -1 or
            body.find('<ol') != -1 or
            body.find('<ul') != -1 or
            body.find('<li') != -1
        )

        std_err = (
            self.report.read_stderr()
            if self.is_running else
            self.report.flush_stderr()
        ).strip('\n').rstrip()

        # The step will be visible in the display if any of the following
        # conditions are true.
        is_visible = self.is_visible or self.is_running or self.error

        dom = templating.render_template(
            'step-body.html',
            last_display_update=self.report.last_update_time,
            elapsed_time=self.get_elapsed_timestamp(),
            code=code,
            body=body,
            has_body=has_body,
            id=self.definition.name,
            title=self.report.title,
            subtitle=self.report.subtitle,
            summary=self.report.summary,
            error=self.error,
            index=self.index,
            is_running=self.is_running,
            is_visible=is_visible,
            progress_message=self.progress_message,
            progress=int(round(max(0, min(100, 100 * self.progress)))),
            sub_progress_message=self.sub_progress_message,
            sub_progress=int(round(max(0, min(100, 100 * self.sub_progress)))),
            std_err=std_err
        )

        if not self.is_running:
            self.dom = dom
        return dom