feat(M0): 工程地基 - Go API + Python 采集骨架 + CI + 数据契约

- api/: Go(chi) 只读 API 骨架, /healthz + 版本化路由(占位), Dockerfile, 单测
- ingestion/: Python 采集/ETL 包骨架, units 单位归一化(纯函数+测试), adapter 协议
- docker-compose.yml: postgres + redis + minio + api
- .github/workflows/ci.yml: Go build/vet/test + Python ruff/pytest
- docs/data-contract.md(两端共享契约) + docs/disclaimer.md(不提供购买声明)
- migrations/ 占位(M1 起填充)

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
2026-06-08 06:18:31 +00:00
parent 729127661e
commit 786b7d3721
22 changed files with 572 additions and 0 deletions
View File
+47
View File
@@ -0,0 +1,47 @@
from decimal import Decimal
import pytest
from opengoods.units import (
UnitError,
canonical_unit_code,
kcal_to_kj,
kj_to_kcal,
normalize,
)
def test_normalize_mass_kg_to_g():
result = normalize("1.5", "kg")
assert result.dimension == "mass"
assert result.canonical_unit == "g"
assert result.canonical_value == Decimal("1500.0")
def test_normalize_volume_litre_alias():
result = normalize(2, "")
assert result.dimension == "volume"
assert result.canonical_value == Decimal("2000")
assert result.canonical_unit == "ml"
def test_normalize_energy_kcal_to_kj():
result = normalize("539", "kcal")
assert result.dimension == "energy"
assert result.canonical_unit == "kJ"
assert result.canonical_value == Decimal("539") * Decimal("4.184")
def test_canonical_unit_code_alias():
assert canonical_unit_code("公斤") == "kg"
assert canonical_unit_code(" G ") == "g"
def test_unknown_unit_raises():
with pytest.raises(UnitError):
normalize(1, "parsec")
def test_energy_roundtrip():
assert kcal_to_kj(1) == Decimal("4.184")
assert kj_to_kcal(Decimal("4.184")) == Decimal("1")