feat: add OCR port family protocols
This commit is contained in:
@@ -14,6 +14,10 @@ from .types import (
|
||||
ChatRequest,
|
||||
EmbeddingTransportResult,
|
||||
LLMResponse,
|
||||
OcrLayoutResult,
|
||||
OcrLayoutTransportResult,
|
||||
OcrTextResult,
|
||||
OcrTextTransportResult,
|
||||
SourceConfig,
|
||||
SourceStats,
|
||||
TransportResult,
|
||||
@@ -53,6 +57,39 @@ class EmbeddingTransport(Protocol):
|
||||
) -> EmbeddingTransportResult: ...
|
||||
|
||||
|
||||
@runtime_checkable
|
||||
class OcrTextPort(Protocol):
|
||||
"""OCR 文本转录端口(D9;对应 MonkeyOCR POST /ocr/text)。"""
|
||||
|
||||
async def recognize_text(self, image: bytes) -> OcrTextResult: ...
|
||||
|
||||
|
||||
@runtime_checkable
|
||||
class OcrLayoutPort(Protocol):
|
||||
"""OCR 版面解析端口(D9;对应 MonkeyOCR POST /parse → GET ZIP)。"""
|
||||
|
||||
async def parse_layout(self, image: bytes) -> OcrLayoutResult: ...
|
||||
|
||||
|
||||
@runtime_checkable
|
||||
class OcrTransport(Protocol):
|
||||
"""一次原始 OCR 调用的协议细节(M3 设计 §3.2);不含任何治理。
|
||||
|
||||
check_health 是探测不是调用: 2xx → True,异常 → False,
|
||||
CancelledError 穿透;由消费方(启动门)决定成败语义。
|
||||
"""
|
||||
|
||||
async def recognize_text(
|
||||
self, *, image: bytes, source: SourceConfig, call_id: str
|
||||
) -> OcrTextTransportResult: ...
|
||||
|
||||
async def parse_layout(
|
||||
self, *, image: bytes, source: SourceConfig, call_id: str
|
||||
) -> OcrLayoutTransportResult: ...
|
||||
|
||||
async def check_health(self, *, source: SourceConfig) -> bool: ...
|
||||
|
||||
|
||||
@runtime_checkable
|
||||
class Permit(Protocol):
|
||||
"""限流入场许可;settle/release 均幂等,finally 中必然执行。"""
|
||||
|
||||
@@ -199,3 +199,32 @@ class TestGateUpdate:
|
||||
GateUpdate(
|
||||
applied=True, state=GateState.CLOSED, epoch=0, failure_count=-1, retry_after_s=0.0
|
||||
)
|
||||
|
||||
|
||||
class TestOcrPorts:
|
||||
"""M3 三个 OCR Protocol(设计 §3.2): runtime_checkable 结构判定。"""
|
||||
|
||||
def test_ocr_ports_runtime_checkable(self):
|
||||
from polygateway.ports import OcrLayoutPort, OcrTextPort, OcrTransport
|
||||
|
||||
class GoodClient:
|
||||
async def recognize_text(self, image): ...
|
||||
async def parse_layout(self, image): ...
|
||||
|
||||
class GoodTransport:
|
||||
async def recognize_text(self, *, image, source, call_id): ...
|
||||
async def parse_layout(self, *, image, source, call_id): ...
|
||||
async def check_health(self, *, source): ...
|
||||
|
||||
assert isinstance(GoodClient(), OcrTextPort)
|
||||
assert isinstance(GoodClient(), OcrLayoutPort)
|
||||
assert isinstance(GoodTransport(), OcrTransport)
|
||||
|
||||
def test_missing_method_rejected(self):
|
||||
from polygateway.ports import OcrTransport
|
||||
|
||||
class NoHealth:
|
||||
async def recognize_text(self, *, image, source, call_id): ...
|
||||
async def parse_layout(self, *, image, source, call_id): ...
|
||||
|
||||
assert not isinstance(NoHealth(), OcrTransport)
|
||||
|
||||
Reference in New Issue
Block a user