Example #1
0
def echo_known_projects(response: Response) -> dict:
    """

    :return:
    """

    def print_path_group(header, paths):
        if not paths:
            return

        environ.log_header(header, level=6, indent_by=2)
        entries = []
        for p in paths:
            parts = p.rstrip(os.sep).split(os.sep)
            name = parts[-1]
            if name.startswith('@'):
                name = name.split(':', 1)[-1]
            entries.append(
                '* "{name}" -> {path}'.format(name=name, path=p)
            )

        environ.log('\n'.join(entries), indent_by=4)

    def project_paths_at(root_path):
        glob_path = os.path.join(root_path, '**', 'cauldron.json')
        return [
            os.path.dirname(x)[(len(root_path) + 1):]
            for x in glob.iglob(glob_path, recursive=True)
        ]

    environ.log_header('Existing Projects')

    print_path_group(
        'Recently Opened',
        environ.configs.fetch('recent_paths', [])
    )

    environ.configs.load()
    aliases = dict(
        home={
            'path': environ.paths.clean(os.path.join('~', 'cauldron'))
        },
        examples={
            'path': environ.paths.package('resources', 'examples')
        }
    )
    aliases.update(environ.configs.fetch('folder_aliases', {}))
    aliases = [(k, p) for k, p in aliases.items()]
    aliases.sort(key=lambda x: x[0])

    for key, data in aliases:
        print_path_group(
            key.capitalize(),
            [
                '@{}:{}'.format(key, x)
                for x in project_paths_at(data['path'])
            ]
        )

    environ.log_blanks()
Example #2
0
def show_help(command_name: str = None, raw_args: str = '') -> Response:
    """ Prints the basic command help to the console """

    response = Response()

    cmds = fetch()
    if command_name and command_name in cmds:
        parser, result = parse.get_parser(cmds[command_name],
                                          parse.explode_line(raw_args), dict())

        if parser is not None:
            out = parser.format_help()
            return response.notify(
                kind='INFO',
                code='COMMAND_DESCRIPTION').kernel(commands=out).console(
                    out, whitespace=1).response

    environ.log_header('Available Commands')
    response.consume(print_module_help())

    return response.fail(code='NO_SUCH_COMMAND',
                         message='Failed to show command help for "{}"'.format(
                             command_name)).console(
                                 """
        For more information on the various commands, enter help on the
        specific command:

            help [COMMAND]
        """,
                                 whitespace_bottom=1).response
Example #3
0
def execute(
        context: cli.CommandContext,
        force: bool = False,
        all_projects: bool = False
) -> Response:
    """

    :param context:
    :param force:
    :param all_projects:
    """

    response = context.response
    environ.log_header('REMOVE RESULTS', level=2)
    environ.log(
        ALL_MESSAGE if all_projects else PROJECT_MESSAGE,
        whitespace=1
    )

    do_it = force
    if not force:
        do_it = query.confirm(
            'Are you sure you want to continue',
            default=False
        )

    if not do_it:
        return response.notify(
            kind='ABORTED',
            code='NO_PURGE',
            message='No files were deleted'
        ).console(
            whitespace=1
        ).response

    if context.remote_connection.active:
        return remote_purge(context)

    path = environ.configs.fetch('results_directory')
    path = path if path else environ.paths.user('results')

    if environ.systems.remove(path):
        response.notify(
            kind='SUCCESS',
            code='RESULTS_PURGED',
            message='All results have been removed'
        ).console(
            whitespace=1
        )
    else:
        response.fail(
            code='PURGE_FAILURE',
            message='Failed to remove results'
        ).console(
            whitespace=1
        )

    return response
Example #4
0
    def print_path_group(header, paths):
        if not paths:
            return

        environ.log_header(header, level=6, indent_by=2)
        entries = []
        for p in paths:
            parts = p.rstrip(os.sep).split(os.sep)
            name = parts[-1]
            if name.startswith('@'):
                name = name.split(':', 1)[-1]
            entries.append('* "{name}" -> {path}'.format(name=name, path=p))

        environ.log('\n'.join(entries), indent_by=4)
Example #5
0
    def print_path_group(header, paths):
        if not paths:
            return

        environ.log_header(header, level=6, indent_by=2)
        entries = []
        for p in paths:
            parts = p.rstrip(os.sep).split(os.sep)
            name = parts[-1]
            if name.startswith('@'):
                name = name.split(':', 1)[-1]
            entries.append(
                '* "{name}" -> {path}'.format(name=name, path=p)
            )

        environ.log('\n'.join(entries), indent_by=4)
Example #6
0
def echo_known_projects(response: Response) -> dict:
    """

    :return:
    """
    def print_path_group(header, paths):
        if not paths:
            return

        environ.log_header(header, level=6, indent_by=2)
        entries = []
        for p in paths:
            parts = p.rstrip(os.sep).split(os.sep)
            name = parts[-1]
            if name.startswith('@'):
                name = name.split(':', 1)[-1]
            entries.append('* "{name}" -> {path}'.format(name=name, path=p))

        environ.log('\n'.join(entries), indent_by=4)

    def project_paths_at(root_path):
        glob_path = os.path.join(root_path, '**', 'cauldron.json')
        return [
            os.path.dirname(x)[(len(root_path) + 1):]
            for x in glob.iglob(glob_path, recursive=True)
        ]

    environ.log_header('Existing Projects')

    print_path_group('Recently Opened',
                     environ.configs.fetch('recent_paths', []))

    environ.configs.load()
    aliases = dict(
        home={'path': environ.paths.clean(os.path.join('~', 'cauldron'))},
        examples={'path': environ.paths.package('resources', 'examples')})
    aliases.update(environ.configs.fetch('folder_aliases', {}))
    aliases = [(k, p) for k, p in aliases.items()]
    aliases.sort(key=lambda x: x[0])

    for key, data in aliases:
        print_path_group(
            key.capitalize(),
            ['@{}:{}'.format(key, x) for x in project_paths_at(data['path'])])

    environ.log_blanks()
Example #7
0
def list_snapshots(project: Project):
    """

    :param project:
    :return:
    """

    snapshots = get_snapshot_listing(project)

    if not snapshots:
        environ.log('No snapshots found')
        return None

    entries = []
    for item in snapshots:
        entries.append('* {}'.format(item['name']))

    environ.log_header('EXISTING SNAPSHOTS')
    environ.log(entries, whitespace_bottom=1, indent_by=3)
Example #8
0
    def on_progress(message: ResponseMessage):
        if message.kind == 'SKIP':
            return

        if len(synchronized) < 1:
            environ.log_header(
                text='SYNCHRONIZING',
                level=2,
                whitespace=1
            )

        if message.code == 'STARTED':
            synchronized.append(message)

        chunk_count = message.data.get('chunk_count', 0)

        if message.code == 'DONE' and chunk_count < 2:
            return

        message.console()
Example #9
0
def create_snapshot(
        project: Project,
        *args: typing.List[str],
        show: bool = True
):
    """

    :param project:
    :param show:
    :return:
    """

    if len(args) < 1:
        snapshot_name = datetime.now().strftime('%Y%b%d-%H-%M-%S')
    else:
        snapshot_name = args[0]

    snapshot_directory = project.snapshot_path()
    if not os.path.exists(snapshot_directory):
        os.makedirs(snapshot_directory)

    snapshot_name = snapshot_name.replace(' ', '-')
    snapshot_directory = project.snapshot_path(snapshot_name)
    environ.systems.remove(snapshot_directory)

    shutil.copytree(project.output_directory, snapshot_directory)

    url = project.snapshot_url(snapshot_name)

    environ.log_header('Snapshot URL', 5)
    environ.log(
        '* {}'.format(url),
        whitespace_bottom=1,
        indent_by=2
    )

    if show:
        webbrowser.open(url)
Example #10
0
def execute(
        context: cli.CommandContext,
        action: str,
        arguments: list,
        no_show: bool = False
) -> Response:
    """

    :param context:
    :param action:
    :param arguments:
    :param no_show:
    :return:
    """

    show = not no_show

    if not action:
        return context.response.fail(
            code='NO_ACTION_ARG',
            message='An action is required for the snapshot command'
        ).console(
            whitespace=1
        ).response

    action = action.strip().lower()
    project = cauldron.project.internal_project

    if not project:
        return context.response.fail(
            code='NO_OPEN_PROJECT',
            message='No open project'
        ).console(
            '[ERROR]: No open project. Use the "open" command to open one.'
        )

    if action == 'remove':
        return actions.remove_snapshot(project, *arguments)

    if action == 'add':
        return actions.create_snapshot(project, *arguments, show=show)

    if action == 'list':
        return actions.list_snapshots(project)

    if action == 'open':
        name = arguments[0]
        result = actions.open_snapshot(project, name)
        if result is None:
            environ.log('[ERROR]: No snapshot found named "{}"'.format(name))
            return context.response

        environ.log_header('SNAPSHOT: {}'.format(name))
        environ.log(
            """
            URL: {url}
            LAST MODIFIED: {modified}
            """.format(
                url=result['url'],
                modified=datetime.fromtimestamp(
                    result['last_modified']
                ).strftime('%H:%M %b %d, %Y')
            ),
            whitespace=1
        )

        if show:
            webbrowser.open(result['url'])
Example #11
0
def run_local(
        context: cli.CommandContext,
        project: projects.Project,
        project_steps: typing.List[projects.ProjectStep],
        force: bool,
        continue_after: bool,
        single_step: bool,
        limit: int,
        print_status: bool,
        skip_library_reload: bool = False
) -> environ.Response:
    """
    Execute the run command locally within this cauldron environment

    :param context:
    :param project:
    :param project_steps:
    :param force:
    :param continue_after:
    :param single_step:
    :param limit:
    :param print_status:
    :param skip_library_reload:
        Whether or not to skip reloading all project libraries prior to
        execution of the project. By default this is False in which case
        the project libraries are reloaded prior to execution.
    :return:
    """
    skip_reload = (
        skip_library_reload
        or environ.modes.has(environ.modes.TESTING)
    )
    if not skip_reload:
        runner.reload_libraries()

    environ.log_header('RUNNING', 5)

    steps_run = []

    if single_step:
        # If the user specifies the single step flag, only run one step. Force
        # the step to be run if they specified it explicitly

        ps = project_steps[0] if len(project_steps) > 0 else None
        force = force or (single_step and bool(ps is not None))
        steps_run = runner.section(
            response=context.response,
            project=project,
            starting=ps,
            limit=1,
            force=force
        )

    elif continue_after or len(project_steps) == 0:
        # If the continue after flag is set, start with the specified step
        # and run the rest of the project after that. Or, if no steps were
        # specified, run the entire project with the specified flags.

        ps = project_steps[0] if len(project_steps) > 0 else None
        steps_run = runner.complete(
            context.response,
            project,
            ps,
            force=force,
            limit=limit
        )
    else:
        for ps in project_steps:
            steps_run += runner.section(
                response=context.response,
                project=project,
                starting=ps,
                limit=max(1, limit),
                force=force or (limit < 1 and len(project_steps) < 2),
                skips=steps_run + []
            )

    project.write()
    environ.log_blanks()

    step_changes = []
    for ps in steps_run:
        step_changes.append(dict(
            name=ps.definition.name,
            action='updated',
            step=writing.step_writer.serialize(ps)._asdict()
        ))

    context.response.update(step_changes=step_changes)

    if print_status or context.response.failed:
        context.response.update(project=project.kernel_serialize())

    return context.response
Example #12
0
def run_local(context: cli.CommandContext, project: projects.Project,
              project_steps: typing.List[projects.ProjectStep], force: bool,
              continue_after: bool, single_step: bool, limit: int,
              print_status: bool) -> environ.Response:
    """
    Execute the run command locally within this cauldron environment

    :param context:
    :param project:
    :param project_steps:
    :param force:
    :param continue_after:
    :param single_step:
    :param limit:
    :param print_status:
    :return:
    """

    runner.reload_libraries()

    environ.log_header('RUNNING', 5)

    steps_run = []

    if single_step:
        # If the user specifies the single step flag, only run one step. Force
        # the step to be run if they specified it explicitly

        ps = project_steps[0] if len(project_steps) > 0 else None
        force = force or (single_step and bool(ps is not None))
        steps_run = runner.section(response=context.response,
                                   project=project,
                                   starting=ps,
                                   limit=1,
                                   force=force)

    elif continue_after or len(project_steps) == 0:
        # If the continue after flag is set, start with the specified step
        # and run the rest of the project after that. Or, if no steps were
        # specified, run the entire project with the specified flags.

        ps = project_steps[0] if len(project_steps) > 0 else None
        steps_run = runner.complete(context.response,
                                    project,
                                    ps,
                                    force=force,
                                    limit=limit)
    else:
        for ps in project_steps:
            steps_run += runner.section(response=context.response,
                                        project=project,
                                        starting=ps,
                                        limit=max(1, limit),
                                        force=force or
                                        (limit < 1 and len(project_steps) < 2),
                                        skips=steps_run + [])

    project.write()
    environ.log_blanks()

    step_changes = []
    for ps in steps_run:
        step_changes.append(
            dict(name=ps.definition.name,
                 action='updated',
                 step=writing.step_writer.serialize(ps)._asdict()))

    context.response.update(step_changes=step_changes)

    if print_status or context.response.failed:
        context.response.update(project=project.kernel_serialize())

    return context.response
Example #13
0
def execute(
        context: cli.CommandContext,
        command: str = None,
        name: str = None,
        path: str = None,
        temporary: bool = False
):
    """

    :return:
    """

    response = context.response

    if name:
        name = name.replace(' ', '_').strip('"').strip()

    if path:
        path = environ.paths.clean(path.strip('"'))
        if not os.path.isdir(path):
            path = os.path.dirname(path)
            environ.log(
                """
                [WARNING]: The specified path was not a directory. Aliases must
                    be directories, so the directory containing the specified
                    file will be used instead:

                    {}
                """.format(path),
                whitespace=1
            )

    environ.configs.load()
    temporary_aliases = environ.configs.session.get('folder_aliases', {})
    persistent_aliases = environ.configs.persistent.get('folder_aliases', {})

    if not name and command in ['add', 'remove']:
        return response.fail(
            code='MISSING_ARG',
            message='You need to specify the name of the alias'
        ).console(
            whitespace=1
        ).response

    if command == 'list':
        items = []
        aliases = dict(
            list(temporary_aliases.items()) +
            list(persistent_aliases.items())
        )

        for k, v in aliases.items():
            items.append('{}\n   {}'.format(k, v['path']))
        environ.log_header('EXISTING ALIASES')
        environ.log(items)
        return response

    aliases = temporary_aliases if temporary else persistent_aliases

    if command == 'add':
        aliases[name] = dict(
            path=path
        )
        environ.configs.put(
            persists=not bool(temporary),
            folder_aliases=aliases
        )
        return response.notify(
            kind='ADDED',
            code='ALIAS_ADDED',
            message='The alias "{}" has been saved'.format(name)
        ).console(
            whitespace=1
        ).response

    if command == 'remove':
        if name in aliases:
            del aliases[name]
        environ.configs.put(
            persists=not bool(temporary),
            folder_aliases=aliases
        )

        return response.notify(
            kind='REMOVED',
            code='ALIAS_REMOVED',
            message='The alias "{}" has been removed'.format(name)
        ).console(
            whitespace=1
        ).response

    return response.fail(
        code='UNKNOWN_COMMAND',
        message='Unrecognized alias command "{}"'.format(command)
    ).console(
        whitespace=1
    ).response