Beispiel #1
0
def echo_steps(response: Response, project: Project):
    """
    :param response:
    :param project:
    :return:
    """

    if len(project.steps) < 1:
        response.update(steps=[]).notify(
            kind='SUCCESS', code='ECHO_STEPS',
            message='No steps in project').console("""
            [NONE]: This project does not have any steps yet. To add a new
                step use the command:

                steps add [YOUR_STEP_NAME]

                and a new step will be created in this project.
            """,
                                                   whitespace=1)
        return

    response.update(steps=[ps.kernel_serialize()
                           for ps in project.steps]).notify(
                               kind='SUCCESS',
                               code='ECHO_STEPS').console_header(
                                   'Project Steps',
                                   level=3).console('\n'.join([
                                       '* {}'.format(ps.definition.name)
                                       for ps in project.steps
                                   ]),
                                                    indent_by=2,
                                                    whitespace_bottom=1)
Beispiel #2
0
def echo_steps(response: Response, project: Project):
    """
    :param response:
    :param project:
    :return:
    """

    if len(project.steps) < 1:
        response.update(
            steps=[]
        ).notify(
            kind='SUCCESS',
            code='ECHO_STEPS',
            message='No steps in project'
        ).console(
            """
            [NONE]: This project does not have any steps yet. To add a new
                step use the command:

                steps add [YOUR_STEP_NAME]

                and a new step will be created in this project.
            """,
            whitespace=1
        )
        return

    response.update(
        steps=[ps.kernel_serialize() for ps in project.steps]
    ).notify(
        kind='SUCCESS',
        code='ECHO_STEPS'
    ).console_header(
        'Project Steps',
        level=3
    ).console(
        '\n'.join(['* {}'.format(ps.definition.name) for ps in project.steps]),
        indent_by=2,
        whitespace_bottom=1
    )
Beispiel #3
0
def remove_step(response: Response,
                project: 'projects.Project',
                name: str,
                keep_file: bool = False) -> Response:
    """

    :param response:
    :param project:
    :param name:
    :param keep_file:
    :return:
    """

    step = project.remove_step(name)
    if not step:
        return response.fail(
            code='NO_SUCH_STEP',
            message='Step "{}" not found. Unable to remove.'.format(
                name)).kernel(name=name).console(whitespace=1).response

    project.save()
    project.write()

    if not keep_file:
        os.remove(step.source_path)

    res = step_support.synchronize_step_names(project)
    response.consume(res)
    if response.failed:
        return response

    step_renames = res.returned

    removed_name = 'REMOVED--{}'.format(uuid.uuid4())
    step_renames[name] = dict(name=removed_name, title='')

    step_changes = [
        dict(name=removed_name, filename=step.filename, action='removed')
    ]

    return response.update(
        project=project.kernel_serialize(),
        step_changes=step_changes,
        step_renames=step_renames).notify(
            kind='SUCCESS',
            code='STEP_REMOVED',
            message='Removed "{}" step from project'.format(name)).console(
                whitespace=1).response
Beispiel #4
0
def create_step(response: Response,
                project: Project,
                name: str,
                position: typing.Union[str, int],
                title: str = None) -> Response:
    """

    :param response:
    :param project:
    :param name:
    :param position:
    :param title:
    :return:
    """

    name = name.strip('"')
    title = title.strip('"') if title else title
    index = index_from_location(response, project, position)
    if index is None:
        index = len(project.steps)

    name_parts = naming.explode_filename(name, project.naming_scheme)

    if not project.naming_scheme and not name_parts['name']:
        name_parts['name'] = naming.find_default_filename(
            [s.definition.name for s in project.steps])

    name_parts['index'] = index
    name = naming.assemble_filename(scheme=project.naming_scheme, **name_parts)

    res = step_support.synchronize_step_names(project, index)
    response.consume(res)
    if response.failed:
        return response

    step_renames = res.returned
    step_data = {'name': name}

    if title:
        step_data['title'] = title

    result = project.add_step(step_data, index=index)

    if not os.path.exists(result.source_path):
        contents = ('import cauldron as cd\n\n'
                    if result.source_path.endswith('.py') else '')

        with open(result.source_path, 'w+') as f:
            f.write(contents)

    project.save()
    project.write()

    index = project.steps.index(result)

    step_changes = [
        dict(name=result.definition.name,
             filename=result.filename,
             action='added',
             step=writing.step_writer.serialize(result)._asdict(),
             after=None if index < 1 else project.steps[index -
                                                        1].definition.name)
    ]

    return response.update(
        project=project.kernel_serialize(),
        step_name=result.definition.name,
        step_path=result.source_path,
        step_changes=step_changes,
        step_renames=step_renames).notify(
            kind='CREATED',
            code='STEP_CREATED',
            message='"{}" step has been created'.format(
                result.definition.name)).console(whitespace=1).response
Beispiel #5
0
def modify_step(response: Response,
                project: Project,
                name: str,
                new_name: str = None,
                position: typing.Union[str, int] = None,
                title: str = None):
    """

    :param response:
    :param project:
    :param name:
    :param new_name:
    :param position:
    :param title:
    :return:
    """

    new_name = new_name if new_name else name
    old_index = project.index_of_step(name)
    new_index = index_from_location(response, project, position, old_index)

    if new_index > old_index:
        # If the current position of the step occurs before the new position
        # of the step, the new index has to be shifted by one to account for
        # the fact that this step will no longer be in this position when it
        # get placed in the position within the project
        new_index -= 1

    old_step = project.remove_step(name)
    if not old_step:
        response.fail(
            code='NO_SUCH_STEP',
            message='Unable to modify unknown step "{}"'.format(name)).console(
                whitespace=1)
        return False

    source_path = old_step.source_path
    if os.path.exists(source_path):
        temp_path = '{}.cauldron_moving'.format(source_path)
        shutil.move(source_path, temp_path)
    else:
        temp_path = None

    res = step_support.synchronize_step_names(project, new_index)
    response.consume(res)
    step_renames = res.returned

    new_name_parts = naming.explode_filename(new_name, project.naming_scheme)
    new_name_parts['index'] = new_index

    if not project.naming_scheme and not new_name_parts['name']:
        new_name_parts['name'] = naming.find_default_filename(
            [s.definition.name for s in project.steps])

    new_name = naming.assemble_filename(scheme=project.naming_scheme,
                                        **new_name_parts)

    step_data = {'name': new_name}
    if title is None:
        if old_step.definition.get('title'):
            step_data['title'] = old_step.definition.title
    else:
        step_data['title'] = title.strip('"')

    new_step = project.add_step(step_data, new_index)

    project.save()

    if not os.path.exists(new_step.source_path):
        if temp_path and os.path.exists(temp_path):
            shutil.move(temp_path, new_step.source_path)
        else:
            with open(new_step.source_path, 'w+') as f:
                f.write('')

    if new_index > 0:
        before_step = project.steps[new_index - 1].definition.name
    else:
        before_step = None

    step_renames[old_step.definition.name] = {
        'name': new_step.definition.name,
        'title': new_step.definition.title
    }

    step_changes = [
        dict(name=new_step.definition.name,
             filename=new_step.filename,
             action='modified',
             after=before_step)
    ]

    response.update(
        project=project.kernel_serialize(),
        step_name=new_step.definition.name,
        step_changes=step_changes,
        step_renames=step_renames).notify(
            kind='SUCCESS',
            code='STEP_MODIFIED',
            message='Step modifications complete').console(whitespace=1)

    project.write()

    return True
Beispiel #6
0
def open_project(
        path: str,
        forget: bool = False,
        results_path: str = None
) -> Response:
    """

    :param path:
    :param forget:
    :param results_path:
    :return:
    """

    response = Response()

    try:
        runner.close()
    except Exception:
        pass

    path = environ.paths.clean(path)

    if not project_exists(response, path):
        return response.fail(
            code='PROJECT_NOT_FOUND',
            message='No project found at: "{}"'.format(path)
        ).console(whitespace=1).response

    if not load_project(response, path):
        return response.fail(
            code='PROJECT_NOT_LOADED',
            message='Unable to load project data'
        ).console(whitespace=1).response

    if not forget and not update_recent_paths(response, path):
        return response.fail(
            code='PROJECT_STATUS_FAILURE',
            message='Unable to update loaded project status'
        ).console(whitespace=1).response

    project = cauldron.project.internal_project
    if results_path:
        project.results_path = results_path

    # Set the top-level display and cache values to the current project values
    # before running the step for availability within the step scripts
    cauldron.shared = cauldron.project.shared

    if not initialize_results(response, project):
        return response.fail(
            code='PROJECT_INIT_FAILURE',
            message='Unable to initialize loaded project'
        ).console(whitespace=1).response

    if not write_results(response, project):
        return response.fail(
            code='PROJECT_WRITE_FAILURE',
            message='Unable to write project notebook data'
        ).console(whitespace=1).response

    runner.add_library_path(project.source_directory)

    return response.update(
        project=project.kernel_serialize()
    ).notify(
        kind='SUCCESS',
        code='PROJECT_OPENED',
        message='Opened project: {}'.format(path)
    ).console_header(
        project.title,
        level=2
    ).console(
        """
        PATH: {path}
         URL: {url}
        """.format(path=path, url=project.baked_url),
        whitespace=1
    ).response
Beispiel #7
0
def create_step(
        response: Response,
        project: Project,
        name: str,
        position: typing.Union[str, int],
        title: str = None
) -> Response:
    """

    :param response:
    :param project:
    :param name:
    :param position:
    :param title:
    :return:
    """

    name = name.strip('"')
    title = title.strip('"') if title else title
    index = index_from_location(response, project, position)
    if index is None:
        index = len(project.steps)

    name_parts = naming.explode_filename(name, project.naming_scheme)

    if not project.naming_scheme and not name_parts['name']:
        name_parts['name'] = naming.find_default_filename(
            [s.definition.name for s in project.steps]
        )

    name_parts['index'] = index
    name = naming.assemble_filename(
        scheme=project.naming_scheme,
        **name_parts
    )

    res = step_support.synchronize_step_names(project, index)
    response.consume(res)
    if response.failed:
        return response

    step_renames = res.returned
    step_data = {'name': name}

    if title:
        step_data['title'] = title

    result = project.add_step(step_data, index=index)

    if not os.path.exists(result.source_path):
        contents = (
            'import cauldron as cd\n\n'
            if result.source_path.endswith('.py')
            else ''
        )

        with open(result.source_path, 'w+') as f:
            f.write(contents)

    project.save()
    project.write()

    index = project.steps.index(result)

    step_changes = [dict(
        name=result.definition.name,
        filename=result.filename,
        action='added',
        step=writing.step_writer.serialize(result)._asdict(),
        after=None if index < 1 else project.steps[index - 1].definition.name
    )]

    return response.update(
        project=project.kernel_serialize(),
        step_name=result.definition.name,
        step_path=result.source_path,
        step_changes=step_changes,
        step_renames=step_renames
    ).notify(
        kind='CREATED',
        code='STEP_CREATED',
        message='"{}" step has been created'.format(result.definition.name)
    ).console(
        whitespace=1
    ).response
Beispiel #8
0
def modify_step(
        response: Response,
        project: Project,
        name: str,
        new_name: str = None,
        position: typing.Union[str, int] = None,
        title: str = None
):
    """

    :param response:
    :param project:
    :param name:
    :param new_name:
    :param position:
    :param title:
    :return:
    """

    new_name = new_name if new_name else name
    old_index = project.index_of_step(name)
    new_index = index_from_location(response, project, position, old_index)

    if new_index > old_index:
        # If the current position of the step occurs before the new position
        # of the step, the new index has to be shifted by one to account for
        # the fact that this step will no longer be in this position when it
        # get placed in the position within the project
        new_index -= 1

    old_step = project.remove_step(name)
    if not old_step:
        response.fail(
            code='NO_SUCH_STEP',
            message='Unable to modify unknown step "{}"'.format(name)
        ).console(
            whitespace=1
        )
        return False

    source_path = old_step.source_path
    if os.path.exists(source_path):
        temp_path = '{}.cauldron_moving'.format(source_path)
        shutil.move(source_path, temp_path)
    else:
        temp_path = None

    res = step_support.synchronize_step_names(project, new_index)
    response.consume(res)
    step_renames = res.returned

    new_name_parts = naming.explode_filename(new_name, project.naming_scheme)
    new_name_parts['index'] = new_index

    if not project.naming_scheme and not new_name_parts['name']:
        new_name_parts['name'] = naming.find_default_filename(
            [s.definition.name for s in project.steps]
        )

    new_name = naming.assemble_filename(
        scheme=project.naming_scheme,
        **new_name_parts
    )

    step_data = {'name': new_name}
    if title is None:
        if old_step.definition.title:
            step_data['title'] = old_step.definition.title
    else:
        step_data['title'] = title.strip('"')

    new_step = project.add_step(step_data, new_index)

    project.save()

    if not os.path.exists(new_step.source_path):
        if temp_path and os.path.exists(temp_path):
            shutil.move(temp_path, new_step.source_path)
        else:
            with open(new_step.source_path, 'w+') as f:
                f.write('')

    if new_index > 0:
        before_step = project.steps[new_index - 1].definition.name
    else:
        before_step = None

    step_renames[old_step.definition.name] = {
        'name': new_step.definition.name,
        'title': new_step.definition.title
    }

    step_changes = [dict(
        name=new_step.definition.name,
        filename=new_step.filename,
        action='modified',
        after=before_step
    )]

    response.update(
        project=project.kernel_serialize(),
        step_name=new_step.definition.name,
        step_changes=step_changes,
        step_renames=step_renames
    ).notify(
        kind='SUCCESS',
        code='STEP_MODIFIED',
        message='Step modifications complete'
    ).console(
        whitespace=1
    )

    project.write()

    return True
Beispiel #9
0
def open_project(
        path: str,
        forget: bool = False,
        results_path: str = None
) -> Response:
    """

    :param path:
    :param forget:
    :param results_path:
    :return:
    """

    response = Response()

    try:
        # Try to close any open projects before opening a new one.
        runner.close()
    except Exception:  # pragma: no cover
        pass

    path = environ.paths.clean(path)

    if not project_exists(response, path):
        return response.fail(
            code='PROJECT_NOT_FOUND',
            message='No project found at: "{}"'.format(path)
        ).console(whitespace=1).response

    if not load_project(response, path):
        return response.fail(
            code='PROJECT_NOT_LOADED',
            message='Unable to load project data'
        ).console(whitespace=1).response

    if not forget and not update_recent_paths(response, path):
        return response.fail(
            code='PROJECT_STATUS_FAILURE',
            message='Unable to update loaded project status'
        ).console(whitespace=1).response

    project = cauldron.project.get_internal_project()
    if results_path:
        project.results_path = results_path

    # Set the top-level display and cache values to the current project values
    # before running the step for availability within the step scripts
    cauldron.shared = cauldron.project.shared

    if not initialize_results(response, project):
        return response.fail(
            code='PROJECT_INIT_FAILURE',
            message='Unable to initialize loaded project'
        ).console(whitespace=1).response

    if not write_results(response, project):
        return response.fail(
            code='PROJECT_WRITE_FAILURE',
            message='Unable to write project notebook data'
        ).console(whitespace=1).response

    # Should no longer be needed because the source directory is included
    # in the library directories as of v0.4.7
    # runner.add_library_path(project.source_directory)
    runner.reload_libraries(project.library_directories)

    return response.update(
        project=project.kernel_serialize()
    ).notify(
        kind='SUCCESS',
        code='PROJECT_OPENED',
        message='Opened project: {}'.format(path)
    ).console_header(
        project.title,
        level=2
    ).console(
        """
        PATH: {path}
         URL: {url}
        """.format(path=path, url=project.baked_url),
        whitespace=1
    ).response
Beispiel #10
0
def remove_step(
        response: Response,
        project: 'projects.Project',
        name: str,
        keep_file: bool = False
) -> Response:
    """

    :param response:
    :param project:
    :param name:
    :param keep_file:
    :return:
    """

    step = project.remove_step(name)
    if not step:
        return response.fail(
            code='NO_SUCH_STEP',
            message='Step "{}" not found. Unable to remove.'.format(name)
        ).kernel(
            name=name
        ).console(
            whitespace=1
        ).response

    project.save()
    project.write()

    if not keep_file:
        os.remove(step.source_path)

    res = step_support.synchronize_step_names(project)
    response.consume(res)
    if response.failed:
        return response

    step_renames = res.returned

    removed_name = 'REMOVED--{}'.format(uuid.uuid4())
    step_renames[name] = dict(
        name=removed_name,
        title=''
    )

    step_changes = [dict(
        name=removed_name,
        filename=step.filename,
        action='removed'
    )]

    return response.update(
        project=project.kernel_serialize(),
        step_changes=step_changes,
        step_renames=step_renames
    ).notify(
        kind='SUCCESS',
        code='STEP_REMOVED',
        message='Removed "{}" step from project'.format(name)
    ).console(
        whitespace=1
    ).response