refactor: 重构项目结构,将geo_tools重命名为app并更新相关引用

- 将主包名从geo_tools改为app
- 更新所有模块中的引用路径
- 迁移并更新测试用例
- 添加项目规则文档
- 保持原有功能不变,仅进行结构调整
This commit is contained in:
2026-04-12 19:49:56 +08:00
parent fcb8e1f255
commit db51d41aef
41 changed files with 4132 additions and 808 deletions

98
app/config/settings.py Normal file
View File

@@ -0,0 +1,98 @@
"""
geo_tools.config.settings
~~~~~~~~~~~~~~~~~~~~~~~~~
全局配置,通过 Pydantic BaseSettings 从环境变量 / .env 文件加载。
使用方式
--------
>>> from geo_tools.config.settings import settings
>>> print(settings.default_crs)
'EPSG:4326'
"""
from __future__ import annotations
import multiprocessing
from pathlib import Path
from pydantic import field_validator, model_validator
from pydantic_settings import BaseSettings, SettingsConfigDict
class GeoToolsSettings(BaseSettings):
"""全局运行时配置。
所有字段均可通过前缀为 ``GEO_TOOLS_`` 的环境变量覆盖,
或在项目根目录创建 ``.env`` 文件(参考 ``.env.example``)。
"""
model_config = SettingsConfigDict(
env_prefix="GEO_TOOLS_",
env_file=".env",
env_file_encoding="utf-8",
case_sensitive=False,
extra="ignore",
)
# ── 目录配置 ──────────────────────────────────────────────
output_dir: Path = Path("output")
"""处理结果输出目录(相对路径相对于当前工作目录)。"""
log_dir: Path = Path("logs")
"""日志文件目录。"""
# ── 坐标系配置 ────────────────────────────────────────────
default_crs: str = "EPSG:4490"
"""默认地理坐标系,使用 EPSG 代码字符串。
常见值:
- ``EPSG:4326`` — WGS84 经纬度
- ``EPSG:4490`` — CGCS2000 经纬度(中国国家标准)
- ``EPSG:3857`` — Web Mercator
"""
# ── 日志配置 ──────────────────────────────────────────────
log_level: str = "ERROR"
"""日志等级DEBUG / INFO / WARNING / ERROR / CRITICAL。"""
log_to_file: bool = True
"""是否同时将日志写出到文件。"""
# ── 性能配置 ──────────────────────────────────────────────
max_workers: int = 0
"""并行处理最大 CPU 核数0 表示自动检测(使用 CPU 核数 - 1"""
# ── 校验器 ────────────────────────────────────────────────
@field_validator("log_level")
@classmethod
def validate_log_level(cls, v: str) -> str:
allowed = {"DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"}
upper = v.upper()
if upper not in allowed:
raise ValueError(f"log_level 必须是 {allowed} 之一,收到:{v!r}")
return upper
@field_validator("default_crs")
@classmethod
def validate_crs(cls, v: str) -> str:
# 简单前缀校验,完整校验在 validators.py 中通过 pyproj 完成
v = v.strip()
if not v:
raise ValueError("default_crs 不能为空")
return v
@model_validator(mode="after")
def resolve_max_workers(self) -> "GeoToolsSettings":
if self.max_workers <= 0:
cpu_count = multiprocessing.cpu_count()
self.max_workers = max(1, cpu_count - 1)
return self
def ensure_dirs(self) -> None:
"""创建输出和日志目录(幂等)。"""
self.output_dir.mkdir(parents=True, exist_ok=True)
self.log_dir.mkdir(parents=True, exist_ok=True)
# 模块级单例,项目内统一引用
settings = GeoToolsSettings()