Пример #1
0
def fetch(query: c.BaseTemplate):
    """
    Fetch/download a template from a depot.

    Only a template spec is required. A template spec is the name and version
    of the template formatted as name@version ([email protected]). Semantic version
    ranges are accepted (e.g., libblrs@^1.0.0). The version parameter is also
    optional (e.g., libblrs)

    Additional parameters are available according to the depot.

    Visit https://pros.cs.purdue.edu/v5/cli/conductor.html to learn more
    """

    template_file = None
    if os.path.exists(query.identifier):
        template_file = query.identifier
    elif os.path.exists(query.name) and query.version is None:
        template_file = query.name
    elif query.metadata.get('origin', None) == 'local':
        if 'location' not in query.metadata:
            logger(__name__).error(
                '--location option is required for the local depot. Specify --location <file>'
            )
            logger(__name__).debug(f'Query options provided: {query.metadata}')
            return -1
        template_file = query.metadata['location']

    if template_file and (os.path.splitext(template_file)[1] in ['.zip']
                          or os.path.exists(
                              os.path.join(template_file, 'template.pros'))):
        template = ExternalTemplate(template_file)
        query.metadata['location'] = template_file
        depot = c.LocalDepot()
        logger(__name__).debug(f'Template file found: {template_file}')
    else:
        if template_file:
            logger(__name__).debug(
                f'Template file exists but is not a valid template: {template_file}'
            )
        template = c.Conductor().resolve_template(query, allow_offline=False)
        logger(__name__).debug(f'Template from resolved query: {template}')
        if template is None:
            logger(__name__).error(f'There are no templates matching {query}!')
            return -1
        depot = c.Conductor().get_depot(template.metadata['origin'])
        logger(__name__).debug(f'Found depot: {depot}')
    # query.metadata contain all of the extra args that also go to the depot. There's no way for us to determine
    # whether the arguments are for the template or for the depot, so they share them
    logger(__name__).debug(
        f'Additional depot and template args: {query.metadata}')
    c.Conductor().fetch_template(depot, template, **query.metadata)
Пример #2
0
def apply(project: c.Project, query: c.BaseTemplate, **kwargs):
    """
    Upgrade or install a template to a PROS project

    Visit https://pros.cs.purdue.edu/v5/cli/conductor.html to learn more
    """
    return c.Conductor().apply_template(project, identifier=query, **kwargs)
Пример #3
0
def info_project(project: c.Project, ls_upgrades):
    """
    Display information about a PROS project

    Visit https://pros.cs.purdue.edu/v5/cli/conductor to learn more
    """
    class ProjectReport(object):
        def __init__(self, project: c.Project):
            self.project = {
                "target":
                project.target,
                "location":
                os.path.abspath(project.location),
                "name":
                project.name,
                "templates": [{
                    "name": t.name,
                    "version": t.version,
                    "origin": t.origin
                } for t in project.templates.values()]
            }

        def __str__(self):
            import tabulate
            s = f'PROS Project for {self.project["target"]} at: {self.project["location"]}' \
                f' ({self.project["name"]})' if self.project["name"] else ''
            s += '\n'
            rows = [t.values() for t in self.project["templates"]]
            headers = [
                h.capitalize() for h in self.project["templates"][0].keys()
            ]
            s += tabulate.tabulate(rows, headers=headers)
            return s

        def __getstate__(self):
            return self.__dict__

    report = ProjectReport(project)
    _conductor = c.Conductor()
    if ls_upgrades:
        for template in report.project['templates']:
            import semantic_version as semver
            templates = _conductor.resolve_templates(
                c.BaseTemplate.create_query(name=template["name"],
                                            version=f'>{template["version"]}',
                                            target=project.target))
            template["upgrades"] = sorted({t.version
                                           for t in templates},
                                          key=lambda v: semver.Version(v),
                                          reverse=True)

    ui.finalize('project-report', report)
Пример #4
0
def uninstall_template(project: c.Project,
                       query: c.BaseTemplate,
                       remove_user: bool,
                       remove_empty_directories: bool = False):
    """
    Uninstall a template from a PROS project

    Visit https://pros.cs.purdue.edu/v5/cli/conductor.html to learn more
    """
    c.Conductor().remove_template(
        project,
        query,
        remove_user=remove_user,
        remove_empty_directories=remove_empty_directories)
Пример #5
0
def new_project(ctx: click.Context,
                path: str,
                target: str,
                version: str,
                force_user: bool = False,
                force_system: bool = False,
                no_default_libs: bool = False,
                compile_after: bool = True,
                build_cache: bool = None,
                **kwargs):
    """
    Create a new PROS project

    Visit https://pros.cs.purdue.edu/v5/cli/conductor.html to learn more
    """
    if version.lower() == 'latest' or not version:
        version = '>0'
    if not force_system and c.Project.find_project(path) is not None:
        logger(__name__).error(
            'A project already exists in this location! Delete it first',
            extra={'sentry': False})
        ctx.exit(-1)
    try:
        _conductor = c.Conductor()
        if target is None:
            target = _conductor.default_target
        project = _conductor.new_project(path,
                                         target=target,
                                         version=version,
                                         force_user=force_user,
                                         force_system=force_system,
                                         no_default_libs=no_default_libs,
                                         **kwargs)
        ui.echo('New PROS Project was created:', output_machine=False)
        ctx.invoke(info_project, project=project)

        if compile_after or build_cache:
            with ui.Notification():
                ui.echo('Building project...')
                ctx.exit(project.compile([], scan_build=build_cache))

    except Exception as e:
        pros.common.logger(__name__).exception(e)
        ctx.exit(-1)
Пример #6
0
def purge_template(query: c.BaseTemplate, force):
    if not query:
        force = click.confirm(
            'Are you sure you want to remove all cached templates? This action is non-reversable!',
            abort=True)
    cond = c.Conductor()
    templates = cond.resolve_templates(query, allow_online=False)
    if len(templates) == 0:
        click.echo('No matching templates were found matching the spec.')
        return 0
    click.echo(
        f'The following template(s) will be removed {[t.identifier for t in templates]}'
    )
    if len(templates) > 1 and not force:
        click.confirm(f'Are you sure you want to remove multiple templates?',
                      abort=True)
    for template in templates:
        if isinstance(template, c.LocalTemplate):
            cond.purge_template(template)
Пример #7
0
def query_templates(ctx, query: c.BaseTemplate, allow_offline: bool,
                    allow_online: bool, force_refresh: bool, limit: int):
    """
    Query local and remote templates based on a spec

    Visit https://pros.cs.purdue.edu/v5/cli/conductor.html to learn more
    """
    if limit < 0:
        limit = 15
    templates = c.Conductor().resolve_templates(
        query,
        allow_offline=allow_offline,
        allow_online=allow_online,
        force_refresh=force_refresh)[:limit]

    render_templates = {}
    for template in templates:
        key = (template.identifier, template.origin)
        if key in render_templates:
            if isinstance(template, c.LocalTemplate):
                render_templates[key]['local'] = True
        else:
            render_templates[key] = {
                'name': template.name,
                'version': template.version,
                'location': template.origin,
                'target': template.target,
                'local': isinstance(template, c.LocalTemplate)
            }
    import semantic_version as semver
    render_templates = sorted(render_templates.values(),
                              key=lambda k: k['local'])  # tertiary key
    render_templates = sorted(render_templates,
                              key=lambda k: semver.Version(k['version']),
                              reverse=True)  # secondary key
    render_templates = sorted(render_templates,
                              key=lambda k: k['name'])  # primary key
    ui.finalize('template-query', render_templates)
Пример #8
0
def info_project(project: c.Project, ls_upgrades):
    """
    Display information about a PROS project

    Visit https://pros.cs.purdue.edu/v5/cli/conductor.html to learn more
    """

    from pros.conductor.project import ProjectReport
    report = ProjectReport(project)
    _conductor = c.Conductor()
    if ls_upgrades:
        for template in report.project['templates']:
            import semantic_version as semver
            templates = _conductor.resolve_templates(
                c.BaseTemplate.create_query(name=template["name"],
                                            version=f'>{template["version"]}',
                                            target=project.target))
            template["upgrades"] = sorted({t.version
                                           for t in templates},
                                          key=lambda v: semver.Version(v),
                                          reverse=True)

    ui.finalize('project-report', report)
Пример #9
0
 def __init__(self, project: c.Project, conductor: Optional[c.Conductor] = None):
     self.project = project
     self.conductor = conductor or c.Conductor()
     self.actions: List[Action] = []
Пример #10
0
    """
    Uninstall a template from a PROS project

    Visit https://pros.cs.purdue.edu/v5/cli/conductor.html to learn more
    """
    c.Conductor().remove_template(
        project,
        query,
        remove_user=remove_user,
        remove_empty_directories=remove_empty_directories)


@conductor.command('new-project', aliases=['new', 'create-project'])
@click.argument('path', type=click.Path())
@click.argument('target',
                default=c.Conductor().default_target,
                type=click.Choice(['v5', 'cortex']))
@click.argument('version', default='latest')
@click.option('--force-user',
              'force_user',
              default=False,
              is_flag=True,
              help='Replace all user files in a template')
@click.option('--force-system',
              '-f',
              'force_system',
              default=False,
              is_flag=True,
              help="Force all system files to be inserted into the project")
@click.option(
    '--force-refresh',