Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ pip install -e .
uniparser --help
```

CLI 完整说明见 [`cli/README.md`](./cli/README.md)。
CLI 完整说明见 [`uniparser_tools/cli/README.md`](./uniparser_tools/cli/README.md)。

## CLI 命令行

Expand All @@ -82,7 +82,7 @@ CLI 完整说明见 [`cli/README.md`](./cli/README.md)。

**`--json` 须写在子命令之前:** `uniparser --json parse paper.pdf`

参数、输出文件、错误码等详见 [`cli/README.md`](./cli/README.md)。
参数、输出文件、错误码等详见 [`uniparser_tools/cli/README.md`](./uniparser_tools/cli/README.md)。

首次使用:

Expand Down Expand Up @@ -489,7 +489,7 @@ uv run python -m uniparser_mcp # 启动 MCP 服务(stdio 模式)
## 项目结构

```
cli/ # uniparser 命令行工具(见 cli/README.md)
uniparser_tools/cli/ # uniparser 命令行工具(见 uniparser_tools/cli/README.md)
├── commands/ # auth, parse, fetch, health, version
└── core/ # 配置、凭证、pipeline、输出

Expand Down Expand Up @@ -518,7 +518,7 @@ playground/

项目提供了丰富的示例和教程,位于 `playground/` 目录下:

- **CLI 命令行**:[`cli/README.md`](./cli/README.md) - `uniparser` 安装、子命令与参数说明
- **CLI 命令行**:[`uniparser_tools/cli/README.md`](./uniparser_tools/cli/README.md) - `uniparser` 安装、子命令与参数说明
- **快速开始**:`playground/01.quick_start.ipynb` - 基础用法教程,包括 PDF 和图片解析、多种格式输出
- **高级用法**:`playground/02.advance.ipynb` - 高级功能教程,包括图片+图题+图注、表格+表题+表注、分子+分子索引、公式+公式索引的提取
- **异步回调**:`playground/04.use_callbacks.py` - 异步回调演示,用于在异步解析任务完成后自动接收通知和结果
Expand Down
5 changes: 0 additions & 5 deletions cli/__main__.py

This file was deleted.

4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ requires-python = ">=3.8"
keywords = ["ocr", "document-parser", "uniparser"]

[project.scripts]
uniparser = "cli.main:cli"
uniparser = "uniparser_tools.cli.main:cli"

[build-system]
requires = ["setuptools>=61.0"]
Expand Down Expand Up @@ -36,7 +36,7 @@ select = ["C", "E", "F", "I", "W"]

[tool.ruff.lint.isort]
lines-after-imports = 2
known-first-party = []
known-first-party = ["uniparser_tools"]
known-third-party = []

[tool.ruff.format]
Expand Down
52 changes: 26 additions & 26 deletions tests/unit/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
import pytest
from click.testing import CliRunner

from cli.core.credentials import ApiKeySource
from cli.core.input import InputKind, resolve_input
from cli.main import cli
from uniparser_tools.cli.core.credentials import ApiKeySource
from uniparser_tools.cli.core.input import InputKind, resolve_input
from uniparser_tools.cli.main import cli
from uniparser_tools.common.constant import ParseMode, ParseModeTextual


Expand All @@ -29,7 +29,7 @@ def env_without_api_key(monkeypatch: pytest.MonkeyPatch) -> None:
@pytest.fixture
def no_config_file(monkeypatch: pytest.MonkeyPatch) -> None:
config_path = Path("/nonexistent/uniparser-cli-test-config/config.yaml")
monkeypatch.setattr("cli.core.credentials.CONFIG_PATH", config_path)
monkeypatch.setattr("uniparser_tools.cli.core.credentials.CONFIG_PATH", config_path)


class TestCliConfig:
Expand Down Expand Up @@ -60,12 +60,12 @@ def test_parse_with_config_file_api_key(
config_dir.mkdir()
config_path = config_dir / "config.yaml"
config_path.write_text("api_key: file-key\n", encoding="utf-8")
monkeypatch.setattr("cli.core.credentials.CONFIG_DIR", config_dir)
monkeypatch.setattr("cli.core.credentials.CONFIG_PATH", config_path)
monkeypatch.setattr("uniparser_tools.cli.core.credentials.CONFIG_DIR", config_dir)
monkeypatch.setattr("uniparser_tools.cli.core.credentials.CONFIG_PATH", config_path)

mock_client = MagicMock()
mock_client.trigger_file.return_value = {"status": "error", "description": "stop early"}
monkeypatch.setattr("cli.commands.parse.make_client", lambda ctx: (mock_client, None))
monkeypatch.setattr("uniparser_tools.cli.commands.parse.make_client", lambda ctx: (mock_client, None))

pdf = tmp_path / "paper.pdf"
pdf.write_bytes(b"%PDF-1.4")
Expand Down Expand Up @@ -147,7 +147,7 @@ def test_parse_success_writes_trigger_meta_and_json_token(
]
mock_client.get_formatted.return_value = {"status": "success", "content": "# Hi"}

monkeypatch.setattr("cli.commands.parse.make_client", lambda ctx: (mock_client, None))
monkeypatch.setattr("uniparser_tools.cli.commands.parse.make_client", lambda ctx: (mock_client, None))

out = tmp_path / "out"
result = runner.invoke(
Expand Down Expand Up @@ -179,7 +179,7 @@ def test_parse_default_trigger_kwargs(

mock_client = MagicMock()
mock_client.trigger_file.return_value = {"status": "error", "description": "stop"}
monkeypatch.setattr("cli.commands.parse.make_client", lambda ctx: (mock_client, None))
monkeypatch.setattr("uniparser_tools.cli.commands.parse.make_client", lambda ctx: (mock_client, None))

out = tmp_path / "out"
runner.invoke(
Expand Down Expand Up @@ -210,7 +210,7 @@ def test_parse_molecule_disable_override(

mock_client = MagicMock()
mock_client.trigger_file.return_value = {"status": "error", "description": "stop"}
monkeypatch.setattr("cli.commands.parse.make_client", lambda ctx: (mock_client, None))
monkeypatch.setattr("uniparser_tools.cli.commands.parse.make_client", lambda ctx: (mock_client, None))

out = tmp_path / "out"
runner.invoke(
Expand Down Expand Up @@ -258,7 +258,7 @@ def test_fetch_success(
]
mock_client.get_formatted.return_value = {"status": "success", "content": "body"}

monkeypatch.setattr("cli.commands.fetch.make_client", lambda ctx: (mock_client, None))
monkeypatch.setattr("uniparser_tools.cli.commands.fetch.make_client", lambda ctx: (mock_client, None))

out = tmp_path / "fetch-out"
result = runner.invoke(
Expand All @@ -279,7 +279,7 @@ def test_health_json(self, runner: CliRunner, monkeypatch: pytest.MonkeyPatch) -
monkeypatch.setenv("UNIPARSER_API_KEY", "test-key")
mock_client = MagicMock()
mock_client.health.return_value = {"status": "success"}
monkeypatch.setattr("cli.commands.health.make_client", lambda ctx: (mock_client, None))
monkeypatch.setattr("uniparser_tools.cli.commands.health.make_client", lambda ctx: (mock_client, None))

result = runner.invoke(cli, ["--json", "health"], env={**os.environ, "UNIPARSER_API_KEY": "test-key"})
assert result.exit_code == 0
Expand All @@ -289,7 +289,7 @@ def test_version_human(self, runner: CliRunner, monkeypatch: pytest.MonkeyPatch)
monkeypatch.setenv("UNIPARSER_API_KEY", "test-key")
mock_client = MagicMock()
mock_client.version.return_value = {"status": "success", "version": "1.0"}
monkeypatch.setattr("cli.commands.version.make_client", lambda ctx: (mock_client, None))
monkeypatch.setattr("uniparser_tools.cli.commands.version.make_client", lambda ctx: (mock_client, None))

result = runner.invoke(cli, ["version"], env={**os.environ, "UNIPARSER_API_KEY": "test-key"})
assert result.exit_code == 0
Expand All @@ -299,7 +299,7 @@ def test_version_without_api_key(
self, runner: CliRunner, monkeypatch: pytest.MonkeyPatch, no_config_file: None
) -> None:
monkeypatch.setattr(
"cli.commands.version.resolve_api_key_source",
"uniparser_tools.cli.commands.version.resolve_api_key_source",
lambda ctx: ApiKeySource(api_key=None, source=""),
)
env = {k: v for k, v in os.environ.items() if k != "UNIPARSER_API_KEY"}
Expand All @@ -312,7 +312,7 @@ def test_version_json_without_api_key(
self, runner: CliRunner, monkeypatch: pytest.MonkeyPatch, no_config_file: None
) -> None:
monkeypatch.setattr(
"cli.commands.version.resolve_api_key_source",
"uniparser_tools.cli.commands.version.resolve_api_key_source",
lambda ctx: ApiKeySource(api_key=None, source=""),
)
env = {k: v for k, v in os.environ.items() if k != "UNIPARSER_API_KEY"}
Expand Down Expand Up @@ -350,8 +350,8 @@ def test_auth_saves_api_key(
monkeypatch.delenv("UNIPARSER_API_KEY", raising=False)
config_dir = tmp_path / ".uniparser"
config_path = config_dir / "config.yaml"
monkeypatch.setattr("cli.core.credentials.CONFIG_DIR", config_dir)
monkeypatch.setattr("cli.core.credentials.CONFIG_PATH", config_path)
monkeypatch.setattr("uniparser_tools.cli.core.credentials.CONFIG_DIR", config_dir)
monkeypatch.setattr("uniparser_tools.cli.core.credentials.CONFIG_PATH", config_path)

result = runner.invoke(cli, ["auth"], input="my-secret-key\n")
assert result.exit_code == 0, result.stderr
Expand All @@ -371,8 +371,8 @@ def test_auth_keeps_existing_on_enter(
config_dir.mkdir()
config_path = config_dir / "config.yaml"
config_path.write_text("api_key: existing-key\n", encoding="utf-8")
monkeypatch.setattr("cli.core.credentials.CONFIG_DIR", config_dir)
monkeypatch.setattr("cli.core.credentials.CONFIG_PATH", config_path)
monkeypatch.setattr("uniparser_tools.cli.core.credentials.CONFIG_DIR", config_dir)
monkeypatch.setattr("uniparser_tools.cli.core.credentials.CONFIG_PATH", config_path)

result = runner.invoke(cli, ["auth"], input="\n")
assert result.exit_code == 0, result.stderr
Expand All @@ -387,8 +387,8 @@ def test_auth_interactive_shows_env_source(
tmp_path: Path,
) -> None:
config_dir = tmp_path / ".uniparser"
monkeypatch.setattr("cli.core.credentials.CONFIG_DIR", config_dir)
monkeypatch.setattr("cli.core.credentials.CONFIG_PATH", config_dir / "config.yaml")
monkeypatch.setattr("uniparser_tools.cli.core.credentials.CONFIG_DIR", config_dir)
monkeypatch.setattr("uniparser_tools.cli.core.credentials.CONFIG_PATH", config_dir / "config.yaml")
env = {k: v for k, v in os.environ.items() if k != "UNIPARSER_API_KEY"}
env["UNIPARSER_API_KEY"] = "env-key"

Expand All @@ -408,8 +408,8 @@ def test_auth_show_masked(
config_dir.mkdir()
config_path = config_dir / "config.yaml"
config_path.write_text("api_key: abcdefghijklmnop\n", encoding="utf-8")
monkeypatch.setattr("cli.core.credentials.CONFIG_DIR", config_dir)
monkeypatch.setattr("cli.core.credentials.CONFIG_PATH", config_path)
monkeypatch.setattr("uniparser_tools.cli.core.credentials.CONFIG_DIR", config_dir)
monkeypatch.setattr("uniparser_tools.cli.core.credentials.CONFIG_PATH", config_path)

result = runner.invoke(cli, ["auth", "--show"])
assert result.exit_code == 0
Expand All @@ -426,7 +426,7 @@ def test_auth_show_env_source(self, runner: CliRunner, monkeypatch: pytest.Monke

def test_auth_show_without_config(self, runner: CliRunner, monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.delenv("UNIPARSER_API_KEY", raising=False)
monkeypatch.setattr("cli.core.credentials.read_api_key_from_config", lambda: None)
monkeypatch.setattr("uniparser_tools.cli.core.credentials.read_api_key_from_config", lambda: None)
env = {k: v for k, v in os.environ.items() if k != "UNIPARSER_API_KEY"}

result = runner.invoke(cli, ["auth", "--show"], env=env)
Expand All @@ -445,8 +445,8 @@ def test_auth_verify_success(
config_dir.mkdir()
config_path = config_dir / "config.yaml"
config_path.write_text("api_key: configured\n", encoding="utf-8")
monkeypatch.setattr("cli.core.credentials.CONFIG_DIR", config_dir)
monkeypatch.setattr("cli.core.credentials.CONFIG_PATH", config_path)
monkeypatch.setattr("uniparser_tools.cli.core.credentials.CONFIG_DIR", config_dir)
monkeypatch.setattr("uniparser_tools.cli.core.credentials.CONFIG_PATH", config_path)

result = runner.invoke(cli, ["auth", "--verify"])
assert result.exit_code == 0
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/test_parse_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from __future__ import annotations

from cli.core.parse_options import (
from uniparser_tools.cli.core.parse_options import (
PARSE_MODE_ALIASES,
SCIENTIFIC_PAPER_DEFAULTS,
TEXTUAL_ALIASES,
Expand Down
Loading
Loading