diff options
| author | 2024-03-08 15:08:44 +0800 | |
|---|---|---|
| committer | 2024-03-08 15:08:44 +0800 | |
| commit | d2c30574a4c65333292a33c4319280244eded1a3 (patch) | |
| tree | 1decaf5eaeee818afb79d369d7cbf3c3555432fa | |
| parent | 46a82e2ae4732e47656d763b40cd16445b6f825c (diff) | |
| download | ipm-d2c30574a4c65333292a33c4319280244eded1a3.tar.gz ipm-d2c30574a4c65333292a33c4319280244eded1a3.zip | |
feat(api): add remove and add cliv0.2.0-alpha.4
| -rw-r--r-- | src/ipm/__main__.py | 71 | ||||
| -rw-r--r-- | src/ipm/api.py | 111 | ||||
| -rw-r--r-- | src/ipm/exceptions.py | 12 |
3 files changed, 115 insertions, 79 deletions
diff --git a/src/ipm/__main__.py b/src/ipm/__main__.py index 6a94ad2..a74311d 100644 --- a/src/ipm/__main__.py +++ b/src/ipm/__main__.py @@ -1,7 +1,8 @@ from pathlib import Path -from . import api -from .exceptions import IPMException -from .logging import status, error, tada +from ipm import api +from ipm.exceptions import IPMException +from ipm.logging import status, error, tada + import typer status.start() @@ -98,8 +99,8 @@ yggdrasil = typer.Typer( ) -@yggdrasil.command() -def add( +@yggdrasil.command("add") +def yggdrasil_add( name: str = typer.Argument(help="世界树名称"), index: str = typer.Argument(help="世界树地址"), ): @@ -127,18 +128,6 @@ def add( # status.stop() -# @main.command() -# def uninstall(package: str = typer.Argument(help="Infini 项目路径")): -# """卸载 Infini 规则包""" -# try: -# if api.uninstall(package, echo=True): -# tada() -# except IpmException as err: -# error(str(err), echo=True) -# finally: -# status.stop() - - @main.command() def require( name: str = typer.Argument(help="Infini 包名"), @@ -175,36 +164,34 @@ def unrequire(name: str = typer.Argument(help="Infini 包名")): status.stop() -# @main.command() -# def add( -# name: str = typer.Argument(help="Infini 包名"), -# index: str = typer.Option(None, help="世界树服务器地址"), -# ): -# """新增环境依赖""" -# try: -# if api.add(name, index=index, echo=True): -# tada() -# except IpmException as err: -# error(str(err), echo=True) -# finally: -# status.stop() +@main.command() +def add(name: str = typer.Argument(help="Infini 包名")): + """新增环境依赖""" + try: + if api.add(Path.cwd(), name, echo=True): + tada() + except IPMException as err: + error(str(err), echo=True) + finally: + status.stop() -# @main.command() -# def remove(name: str = typer.Argument(help="Infini 包名")): -# """删除环境依赖""" -# try: -# if api.remove(name, echo=True): -# tada() -# except IpmException as err: -# error(str(err), echo=True) -# finally: -# status.stop() +@main.command() +def remove(name: str = typer.Argument(help="Infini 包名")): + """删除环境依赖""" + try: + if api.remove(Path.cwd(), name, echo=True): + tada() + except IPMException as err: + error(str(err), echo=True) + finally: + status.stop() -# TODO @main.command() -def update(): ... +def update(): + """更新 Infini 依赖""" + raise NotImplementedError main.add_typer(yggdrasil) diff --git a/src/ipm/api.py b/src/ipm/api.py index a422520..bf2e740 100644 --- a/src/ipm/api.py +++ b/src/ipm/api.py @@ -4,24 +4,22 @@ from ipm.models.lock import ProjectLock from ipm.project.env import new_virtualenv from ipm.project.toml_file import add_yggdrasil, init_infini, init_pyproject from ipm.typing import StrPath -from ipm.utils import freeze, urlparser, loader -from ipm.const import GITIGNORE, INDEX, INDEX_PATH, STORAGE, SRC_HOME -from ipm.logging import status, update, info, success, warning, error, confirm, ask +from ipm.utils import freeze +from ipm.logging import status, update, info, success, warning, error, ask from ipm.exceptions import ( - FileTypeMismatch, + EnvironmentError, TomlLoadFailed, FileNotFoundError, - PackageExsitsError, + NameError, + RuntimeError, ) -from ipm.utils.version import require_update from ipm.models.ipk import InfiniProject, InfiniFrozenPackage - -# from ipm.models.lock import PackageLock, ProjectLock from ipm.models.index import Yggdrasil -import tomlkit import shutil import os +import re +import subprocess import configparser @@ -236,36 +234,75 @@ def unrequire(target_path: StrPath, name: str, echo: bool = False): return True -# def add(name: str, index: str = "", echo: bool = False) -> None: -# info("检查环境中...", echo) -# pkg_lock = PackageLock() -# lock = ProjectLock() -# ipk = InfiniProject() -# info("环境检查完毕.", echo) - -# splited_name = name.split("==") # TODO 支持 >= <= > < 标识 -# name = splited_name[0] - -# if len(splited_name) > 1: -# version = splited_name[1] -# else: -# version = None +def add(target_path, name: str, echo: bool = False) -> bool: + info(f"新增环境依赖项: [bold green]{name}[/bold green]", echo) + status.start() + status.update("检查环境中...") + if not ( + match := re.match(r"^((?:[a-zA-Z_-]|\d)+)(?:([>=<]+\d+(?:[.]\d+)*))?$", name) + ): + raise NameError(f"版本号 [bold red]{name}[/] 不合法.") + if not (toml_path := Path(target_path).joinpath("infini.toml")).exists(): + raise FileNotFoundError( + f"文件 [green]infini.toml[/green] 尚未被初始化, 你可以使用[bold green]`ipm init`[/bold green]来初始化项目." + ) + project = InfiniProject(toml_path.parent) + if not shutil.which("pdm"): + raise EnvironmentError( + "IPM 未能在环境中找到 [bold green]PDM[/] 安装, 请确保 PDM 在环境中被正确安装. " + "你可以使用`[bold green]pipx install pdm[/]`来安装此包管理器." + ) + success("环境检查完毕.", echo) -# if not pkg_lock.has_package(name): -# # TODO pip 环境安装 -# ... + status.update("安装依赖中...") + + name = match.group(1) + version = match.group(2) + project.add(name, version or "*") + if ( + result := subprocess.run( + ["pdm", "add", name], + cwd=target_path, + capture_output=True, + text=True, + ) + ).returncode != 0: + error(result.stderr.strip("\n"), echo) + raise RuntimeError("PDM 异常退出, 指令忽略.") -# info("处理 Infini 项目依赖锁...", echo) -# ipk.add(name, version, dump=True) -# lock.add(name, version, dump=True) -# success("环境依赖新增完成.", echo) + project.dump() + success("项目文件写入完成.", echo) + return True -# def remove(name: str, echo: bool = False): -# info("处理 Infini 项目依赖锁...", echo) -# ipk = InfiniProject() -# lock = ProjectLock() +def remove(target_path: StrPath, name: str, echo: bool = False): + info(f"删除环境依赖项: [bold green]{name}[/bold green]", echo) + status.start() + status.update("检查环境中...") + if not (toml_path := Path(target_path).joinpath("infini.toml")).exists(): + raise FileNotFoundError( + f"文件 [green]infini.toml[/green] 尚未被初始化, 你可以使用[bold green]`ipm init`[/bold green]来初始化项目." + ) + project = InfiniProject(toml_path.parent) + if not shutil.which("pdm"): + raise EnvironmentError( + "IPM 未能在环境中找到 [bold green]PDM[/] 安装, 请确保 PDM 在环境中被正确安装. " + "你可以使用`[bold green]pipx install pdm[/]`来安装此包管理器." + ) + success("环境检查完毕.", echo) + project.remove(name) + + if ( + result := subprocess.run( + ["pdm", "remove", name], + cwd=target_path, + capture_output=True, + text=True, + ) + ).returncode != 0: + error(result.stderr.strip("\n"), echo) + raise RuntimeError("PDM 异常退出, 指令忽略.") -# ipk.remove(name, dump=True) -# lock.remove(name, dump=True) -# success("环境依赖删除完成.", echo) + project.dump() + success("项目文件写入完成.", echo) + return True diff --git a/src/ipm/exceptions.py b/src/ipm/exceptions.py index f7c540f..6dd3cf0 100644 --- a/src/ipm/exceptions.py +++ b/src/ipm/exceptions.py @@ -44,3 +44,15 @@ class FileTypeMismatch(IPMException): class PackageExsitsError(IPMException): """Package already installed""" + + +class EnvironmentError(IPMException): + """Raises when environment is not valid""" + + +class RuntimeError(IPMException, RuntimeError): + """An error occured when calling subprocess""" + + +class NameError(IPMException): + """Provided name is not valid""" |
