Source code for conda_project.cli.commands

# -*- coding: utf-8 -*-
# Copyright (C) 2022-2024 Anaconda, Inc
# SPDX-License-Identifier: BSD-3-Clause

# Copyright (C) 2022 Anaconda, Inc
# SPDX-License-Identifier: BSD-3-Clause
import logging
import sys
from argparse import Namespace
from functools import wraps
from typing import Any, Callable, NoReturn

from ..exceptions import CommandNotFoundError, CondaProjectError
from ..project import Command, CondaProject, Environment

logger = logging.getLogger(__name__)


def _load_project(args: Namespace):
    if args.project_archive is not None:
        _storage_options = (
            []
            if args.archive_storage_options is None
            else args.archive_storage_options.split(",")
        )

        storage_options = {}
        for option in _storage_options:
            k, v = option.split("=")
            storage_options[k] = v

        project = CondaProject.from_archive(
            args.project_archive,
            storage_options=storage_options,
            output_directory=args.directory,
        )
    else:
        project = CondaProject(args.directory)

    return project


[docs] def handle_errors(func: Callable[[Namespace], Any]) -> Callable[[Namespace], int]: """Wrap a subcommand function to catch exceptions and return an appropriate error code.""" @wraps(func) def wrapper(args: Namespace) -> int: try: ret = func(args) if ret: return 0 else: return 1 except CondaProjectError as e: print(f"{e.__class__.__name__}: {e}", file=sys.stderr) return 1 return wrapper
[docs] @handle_errors def init(args: Namespace) -> bool: project = CondaProject.init( directory=args.directory, name=args.name, dependencies=args.dependencies, channels=args.channel, platforms=args.platforms.split(","), conda_configs=( [] if args.conda_configs is None else args.conda_configs.split(",") ), lock_dependencies=args.lock, from_environment=args.from_environment, verbose=True, ) if args.install: project.default_environment.install(verbose=True) return True
[docs] def create(args: Namespace) -> int: logger.warning( "The 'create' subcommand is an alias for 'init' and may be removed in a future version." ) return init(args)
[docs] @handle_errors def lock(args: Namespace) -> bool: project = _load_project(args) if args.environment: to_lock = [project.environments[args.environment]] else: to_lock = project.environments.values() for env in to_lock: env.lock(force=args.force, verbose=True) return True
[docs] @handle_errors def check(args: Namespace) -> bool: project = _load_project(args) return project.check(verbose=True)
def _get_environment_from_args(project: CondaProject, args: Namespace) -> Environment: if args.environment and args.for_command: raise CondaProjectError("You must specify one of environment or --for-command") if args.for_command: env = project.commands[args.for_command].environment environment = env.name if env is not None else None else: environment = args.environment env = ( project.environments[environment] if environment else project.default_environment ) return env
[docs] @handle_errors def install(args: Namespace) -> bool: project = _load_project(args) if args.all: for _, env in project.environments: env.install(force=args.force, verbose=True) else: env = _get_environment_from_args(project, args) env.install(force=args.force, as_platform=args.as_platform, verbose=True) return True
[docs] def prepare(args: Namespace) -> int: logger.warning( "The 'prepare' subcommand is an alias for 'install' and may be removed in a future version." ) return install(args)
[docs] @handle_errors def add(args: Namespace) -> bool: project = _load_project(args) env = ( project.environments[args.environment] if args.environment else project.default_environment ) env.add(args.dependencies, args.channel, verbose=True) return True
[docs] @handle_errors def remove(args: Namespace) -> bool: project = _load_project(args) env = ( project.environments[args.environment] if args.environment else project.default_environment ) env.remove(args.dependencies, verbose=True) return True
[docs] @handle_errors def clean(args: Namespace) -> bool: project = CondaProject(args.directory) if args.all: for env in project.environments.values(): env.clean(verbose=True) else: env = ( project.environments[args.environment] if args.environment else project.default_environment ) env.clean(verbose=True) return True
[docs] @handle_errors def run(args: Namespace) -> NoReturn: project = _load_project(args) if args.command: try: to_run = project.commands[args.command] except CommandNotFoundError: to_run = Command( name=str(args.command), cmd=args.command, environment=project.default_environment, project=project, ) else: to_run = project.default_command to_run.run( environment=args.environment, external_environment=args.external_environment, extra_args=args.extra_args, verbose=True, )
[docs] @handle_errors def activate(args: Namespace) -> bool: project = _load_project(args) if args.environment: env = project.environments[args.environment] else: env = project.default_environment env.activate(verbose=True) return True