openenv/echo_env
6
1# SPDX-License-Identifier: BSD-3-Clause2 3"""CLI utilities for OpenEnv command-line interface."""4 5from pathlib import Path6from typing import List7 8from rich.console import Console9 10# Create a console instance for CLI output11console = Console()12 13 14def _extract_hf_username(user_info: object) -> str | None:15 """Extract a username from the supported Hugging Face whoami shapes."""16 if isinstance(user_info, dict):17 return (18 user_info.get("name")19 or user_info.get("fullname")20 or user_info.get("username")21 )22 23 return (24 getattr(user_info, "name", None)25 or getattr(user_info, "fullname", None)26 or getattr(user_info, "username", None)27 )28 29 30def validate_env_structure(env_dir: Path, strict: bool = False) -> List[str]:31 """32 Validate that the directory follows OpenEnv environment structure.33 34 Args:35 env_dir (`Path`):36 Path to the environment directory.37 strict (`bool`, *optional*, defaults to `False`):38 If `True`, enforce all optional requirements.39 40 Returns:41 `list` of validation warnings (empty if all checks pass).42 43 Raises:44 `FileNotFoundError`: If required files are missing.45 """46 warnings = []47 48 # Required files49 required_files = [50 "openenv.yaml",51 "__init__.py",52 "client.py",53 "models.py",54 "README.md",55 ]56 57 for file in required_files:58 if not (env_dir / file).exists():59 raise FileNotFoundError(f"Required file missing: {file}")60 61 # Dockerfile: must exist in server/ or at env root62 has_root_dockerfile = (env_dir / "Dockerfile").exists()63 has_server_dockerfile = (env_dir / "server" / "Dockerfile").exists()64 65 if not has_root_dockerfile and not has_server_dockerfile:66 raise FileNotFoundError(67 "Required file missing: server/Dockerfile or Dockerfile at env root"68 )69 70 # When no root Dockerfile, require the traditional server/ layout71 if not has_root_dockerfile:72 server_dir = env_dir / "server"73 if not server_dir.exists() or not server_dir.is_dir():74 raise FileNotFoundError("Required directory missing: server/")75 76 for file in ["server/__init__.py", "server/app.py"]:77 if not (env_dir / file).exists():78 raise FileNotFoundError(f"Required file missing: {file}")79 80 # Check for dependency management (pyproject.toml required)81 has_pyproject = (env_dir / "pyproject.toml").exists()82 83 if not has_pyproject:84 raise FileNotFoundError(85 "No dependency specification found. 'pyproject.toml' is required."86 )87 88 # Warnings for recommended structure89 90 if not (env_dir / "outputs").exists():91 warnings.append("Recommended directory missing: outputs/")92 93 return warnings94 