mirror of
https://github.com/RapidAI/RapidOCR.git
synced 2026-11-13 22:40:53 +08:00
tests: add error catch
This commit is contained in:
1 parent
b4000d171b
commit
191bcc7e89
3 files changed
+102
-16
No files matched your search
@@ -1228,6 +1228,22 @@ lang_mapping:
|
||||
cn: "天城文"
|
||||
en: "Devanagari"
|
||||
aliases: []
|
||||
cyrillic:
|
||||
cn: "西里尔语"
|
||||
en: "Cyrillic"
|
||||
aliases: []
|
||||
ch_doc:
|
||||
cn: "中文文档"
|
||||
en: "Chinese Document"
|
||||
aliases: []
|
||||
gl:
|
||||
cn: "加利西亚语"
|
||||
en: "Galician"
|
||||
aliases: []
|
||||
lb:
|
||||
cn: "卢森堡语"
|
||||
en: "Luxembourgish"
|
||||
aliases: []
|
||||
abq:
|
||||
cn: "阿布哈兹语"
|
||||
en: "Abkhaz"
|
||||
@@ -1243,7 +1259,7 @@ lang_mapping:
|
||||
ar:
|
||||
cn: "阿拉伯语"
|
||||
en: "Arabic"
|
||||
aliases: []
|
||||
aliases: ["arabic"]
|
||||
ava:
|
||||
cn: "阿瓦尔语"
|
||||
en: "Avaric"
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
# @Contact: liekkaskono@163.com
|
||||
import pytest
|
||||
from rapidocr import ModelType, OCRVersion
|
||||
from rapidocr.inference_engine.base import InferSession
|
||||
from rapidocr.inference_engine.base import FileInfo, InferSession
|
||||
from rapidocr.utils.model_resolver import (
|
||||
MODEL_ROUTES,
|
||||
list_supported_langs,
|
||||
route_to_model_key,
|
||||
)
|
||||
from rapidocr.utils.typings import TaskType
|
||||
from rapidocr.utils.typings import EngineType, TaskType
|
||||
from tools.validate_model_routes import validate_model_routes
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ def test_model_routes_schema_is_valid():
|
||||
validate_model_routes(MODEL_ROUTES)
|
||||
|
||||
|
||||
def test_every_route_resolves_and_exists_in_a_model_registry():
|
||||
def test_every_route_resolves_in_each_available_model_registry():
|
||||
registries = InferSession.model_info
|
||||
for version, version_cfg in MODEL_ROUTES.items():
|
||||
if version == "_defs":
|
||||
@@ -34,11 +34,27 @@ def test_every_route_resolves_and_exists_in_a_model_registry():
|
||||
model_enum = ModelType(model_type)
|
||||
for route in routes:
|
||||
model_key = route["model_key"]
|
||||
assert any(
|
||||
model_key in (registry.get(version, {}).get(task, {}) or {})
|
||||
for engine, registry in registries.items()
|
||||
if engine != "model_routes"
|
||||
), model_key
|
||||
available_engines = 0
|
||||
for engine, registry in registries.items():
|
||||
if engine not in {item.value for item in EngineType}:
|
||||
continue
|
||||
model_dict = registry.get(version, {}).get(task, {}) or {}
|
||||
if model_key not in model_dict:
|
||||
continue
|
||||
|
||||
available_engines += 1
|
||||
model_info = InferSession.get_model_url(
|
||||
FileInfo(
|
||||
engine_type=EngineType(engine),
|
||||
ocr_version=version_enum,
|
||||
task_type=task_enum,
|
||||
lang_type=route["supported_langs"][0],
|
||||
model_type=model_enum,
|
||||
)
|
||||
)
|
||||
assert model_info == model_dict[model_key]
|
||||
|
||||
assert available_engines > 0, model_key
|
||||
for lang in route["supported_langs"]:
|
||||
assert (
|
||||
route_to_model_key(
|
||||
@@ -48,6 +64,35 @@ def test_every_route_resolves_and_exists_in_a_model_registry():
|
||||
)
|
||||
|
||||
|
||||
def test_model_routes_reject_unknown_enum_values():
|
||||
with pytest.raises(ValueError, match="Invalid OCR version"):
|
||||
validate_model_routes({"PP-OCRv7": {}})
|
||||
|
||||
with pytest.raises(ValueError, match="Invalid task"):
|
||||
validate_model_routes({"PP-OCRv6": {"recognize": {}}})
|
||||
|
||||
with pytest.raises(ValueError, match="Invalid model type"):
|
||||
validate_model_routes({"PP-OCRv6": {"rec": {"large": []}}})
|
||||
|
||||
|
||||
def test_model_routes_accept_native_python_containers():
|
||||
validate_model_routes(
|
||||
{
|
||||
"PP-OCRv6": {
|
||||
"rec": {
|
||||
"small": [
|
||||
{
|
||||
"lang": "multi",
|
||||
"model_key": "multi_PP-OCRv6_rec_small",
|
||||
"supported_langs": ["ch", "en"],
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"task_type,expected_key",
|
||||
[
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
from collections.abc import Mapping, Sequence
|
||||
from typing import Any
|
||||
|
||||
from omegaconf import OmegaConf
|
||||
from rapidocr.utils.typings import ModelType, OCRVersion, TaskType
|
||||
|
||||
|
||||
def validate_model_routes(model_routes: Any) -> None:
|
||||
"""Validate the engine-neutral route schema explicitly."""
|
||||
if not OmegaConf.is_dict(model_routes):
|
||||
if not _is_mapping(model_routes):
|
||||
raise ValueError("Invalid model_routes: expected a mapping")
|
||||
|
||||
for path, routes in _iter_model_route_lists(model_routes):
|
||||
@@ -17,7 +19,8 @@ def _iter_model_route_lists(model_routes: Any):
|
||||
for version, version_cfg in model_routes.items():
|
||||
if version == "_defs":
|
||||
continue
|
||||
if not OmegaConf.is_dict(version_cfg):
|
||||
_validate_enum("OCR version", version, OCRVersion)
|
||||
if not _is_mapping(version_cfg):
|
||||
raise ValueError(f"Invalid model route version: {version}")
|
||||
if "aliases" in version_cfg:
|
||||
_validate_aliases(f"{version}.aliases", version_cfg["aliases"])
|
||||
@@ -25,18 +28,40 @@ def _iter_model_route_lists(model_routes: Any):
|
||||
for task, task_cfg in version_cfg.items():
|
||||
if task == "aliases":
|
||||
continue
|
||||
if not OmegaConf.is_dict(task_cfg):
|
||||
_validate_enum("task", task, TaskType)
|
||||
if not _is_mapping(task_cfg):
|
||||
raise ValueError(f"Invalid model route task: {version}.{task}")
|
||||
if "aliases" in task_cfg:
|
||||
_validate_aliases(f"{version}.{task}.aliases", task_cfg["aliases"])
|
||||
|
||||
for model_type, routes in task_cfg.items():
|
||||
if model_type != "aliases":
|
||||
_validate_enum("model type", model_type, ModelType)
|
||||
yield f"{version}.{task}.{model_type}", routes
|
||||
|
||||
|
||||
def _validate_enum(label: str, value: str, enum_type: Any) -> None:
|
||||
try:
|
||||
enum_type(value)
|
||||
except ValueError as exc:
|
||||
valid_values = ", ".join(item.value for item in enum_type)
|
||||
raise ValueError(
|
||||
f"Invalid {label} {value!r}; expected one of: {valid_values}"
|
||||
) from exc
|
||||
|
||||
|
||||
def _is_mapping(value: Any) -> bool:
|
||||
return OmegaConf.is_dict(value) or isinstance(value, Mapping)
|
||||
|
||||
|
||||
def _is_sequence(value: Any) -> bool:
|
||||
return OmegaConf.is_list(value) or (
|
||||
isinstance(value, Sequence) and not isinstance(value, (str, bytes))
|
||||
)
|
||||
|
||||
|
||||
def _validate_aliases(path: str, aliases: Any) -> None:
|
||||
if not OmegaConf.is_dict(aliases):
|
||||
if not _is_mapping(aliases):
|
||||
raise ValueError(f"Invalid aliases: {path}")
|
||||
|
||||
for alias, target in aliases.items():
|
||||
@@ -47,13 +72,13 @@ def _validate_aliases(path: str, aliases: Any) -> None:
|
||||
|
||||
|
||||
def _validate_model_route_list(path: str, routes: Any) -> None:
|
||||
if not OmegaConf.is_list(routes):
|
||||
if not _is_sequence(routes):
|
||||
raise ValueError(f"Invalid model route list: {path}")
|
||||
|
||||
seen = set()
|
||||
seen_languages = set()
|
||||
for route in routes:
|
||||
if not OmegaConf.is_dict(route):
|
||||
if not _is_mapping(route):
|
||||
raise ValueError(f"Invalid model route entry: {path}")
|
||||
|
||||
required = {"lang", "model_key", "supported_langs"}
|
||||
@@ -72,7 +97,7 @@ def _validate_model_route_list(path: str, routes: Any) -> None:
|
||||
seen.add(model_key)
|
||||
|
||||
supported_langs = route["supported_langs"]
|
||||
if not OmegaConf.is_list(supported_langs) or not supported_langs:
|
||||
if not _is_sequence(supported_langs) or not supported_langs:
|
||||
raise ValueError(f"Empty supported languages: {model_key}")
|
||||
|
||||
for lang in supported_langs:
|
||||
|
||||
Reference in new issue
Block a user