Team Ai
Apppublic

openenv/echo_env

sourceHugging Faceupdated 1d agoView on Hugging Face
6likes
import_env.py146 linesDownload Raw Back to commands
1"""Import third-party environments into OpenEnv wrappers."""2 3from __future__ import annotations4 5import shutil6from pathlib import Path7from typing import Annotated8 9import typer10from openenv.cli.importers import DEFAULT_IMPORTERS, ImporterRegistry11 12from .._cli_utils import console13from .init import _generate_uv_lock, _validate_env_name14 15 16def _select_match(17    registry: ImporterRegistry,18    source: Path,19    source_type: str | None,20    env_class: str | None,21):22    try:23        matches = registry.detect(source, source_type=source_type)24    except ValueError as e:25        raise typer.BadParameter(str(e)) from e26    if not matches:27        supported = ", ".join(registry.supported_types)28        raise typer.BadParameter(29            f"No supported environment found in {source}. Supported source types: {supported}."30        )31 32    if env_class:33        matches = [34            match35            for match in matches36            if match[1].class_name == env_class or match[1].qualified_name == env_class37        ]38        if not matches:39            raise typer.BadParameter(f"No detected environment matched {env_class!r}.")40 41    detected_types = {importer.source_type for importer, _ in matches}42    if source_type is None and len(detected_types) > 1:43        raise typer.BadParameter(44            "Multiple source formats were detected. Re-run with --type "45            f"({'/'.join(sorted(detected_types))})."46        )47 48    if len(matches) > 1:49        choices = ", ".join(detected.qualified_name for _, detected in matches)50        raise typer.BadParameter(51            f"Multiple environment entrypoints were detected ({choices}). "52            "Re-run with --env-class."53        )54 55    return matches[0]56 57 58def import_env(59    source: Annotated[60        str,61        typer.Argument(help="Local source repository or directory to import"),62    ],63    name: Annotated[64        str,65        typer.Option("--name", "-n", help="Name for the generated OpenEnv package"),66    ],67    output_dir: Annotated[68        str,69        typer.Option(70            "--output-dir",71            "-o",72            help="Directory where the generated package will be created",73        ),74    ],75    env_class: Annotated[76        str | None,77        typer.Option(78            "--env-class",79            help="Environment class name or module:Class when detection is ambiguous",80        ),81    ] = None,82    source_type: Annotated[83        str | None,84        typer.Option(85            "--type",86            help="Optional source type override, such as 'ors'",87        ),88    ] = None,89) -> None:90    """Deterministically import a third-party environment into OpenEnv."""91    env_name = _validate_env_name(name)92    source_path = Path(source).expanduser().resolve()93    if not source_path.exists() or not source_path.is_dir():94        raise typer.BadParameter(f"Source must be an existing directory: {source_path}")95 96    base_dir = Path(output_dir).expanduser().resolve()97    env_dir = base_dir / env_name98    try:99        env_dir.relative_to(source_path)100    except ValueError:101        pass102    else:103        raise typer.BadParameter("Output directory must not be inside the source tree")104 105    if env_dir.exists():106        if env_dir.is_file():107            raise typer.BadParameter(f"Path '{env_dir}' exists and is a file")108        if any(env_dir.iterdir()):109            raise typer.BadParameter(110                f"Directory '{env_dir}' already exists and is not empty."111            )112 113    registry = ImporterRegistry(DEFAULT_IMPORTERS)114    importer, detected = _select_match(115        registry,116        source_path,117        source_type=source_type,118        env_class=env_class,119    )120 121    try:122        env_dir.mkdir(parents=True, exist_ok=True)123        console.print(124            "[bold cyan]Importing environment[/bold cyan] "125            f"{detected.qualified_name} as '{env_name}' ({importer.source_type})"126        )127        importer.generate(128            source=source_path,129            destination=env_dir,130            env_name=env_name,131            detected=detected,132        )133 134        console.print("[bold green]OK[/bold green] Generated OpenEnv wrapper")135        if _generate_uv_lock(env_dir):136            console.print("[green]OK[/green] Generated uv.lock")137        else:138            console.print("[yellow]Warning:[/yellow] Could not generate uv.lock")139 140        console.print(f"[bold green]Environment created at: {env_dir}[/bold green]")141    except Exception as e:142        if env_dir.exists() and env_dir.is_dir():143            shutil.rmtree(env_dir, ignore_errors=True)144        console.print(f"[bold red]Error:[/bold red] {e}")145        raise typer.Exit(1) from e146