aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author苏向夜 <fu050409@163.com>2024-03-08 15:08:44 +0800
committer苏向夜 <fu050409@163.com>2024-03-08 15:08:44 +0800
commitd2c30574a4c65333292a33c4319280244eded1a3 (patch)
tree1decaf5eaeee818afb79d369d7cbf3c3555432fa /src
parent46a82e2ae4732e47656d763b40cd16445b6f825c (diff)
downloadipm-d2c30574a4c65333292a33c4319280244eded1a3.tar.gz
ipm-d2c30574a4c65333292a33c4319280244eded1a3.zip
feat(api): add remove and add cliv0.2.0-alpha.4
Diffstat (limited to 'src')
-rw-r--r--src/ipm/__main__.py71
-rw-r--r--src/ipm/api.py111
-rw-r--r--src/ipm/exceptions.py12
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"""