main:移除 src 目录结构,更新模块引用路径

变更内容:
- 删除 `src` 子目录,将模块引用路径从 `src.functional_scaffold` 更新为 `functional_scaffold`。
- 修改相关代码、文档、测试用例及配置文件中的路径引用,包括 `README.md`、`Dockerfile`、`uvicorn` 启动命令等。
- 优化项目目录结构,提升代码维护性和可读性。
This commit is contained in:
2026-02-03 11:29:37 +08:00
parent 545616a5fe
commit 8ca2f64f7e
16 changed files with 52 additions and 63 deletions

View File

@@ -70,7 +70,7 @@ pip install -e ".[dev]"
```bash
./scripts/run_dev.sh
uvicorn src.functional_scaffold.main:app --reload --port 8000
uvicorn functional_scaffold.main:app --reload --port 8000
```
测试与质量:

View File

@@ -2,12 +2,12 @@
本文件为 Claude Code (claude.ai/code) 在此代码仓库中工作时提供指导。
为了方便团队交流,项目的自然语言使用中文,包括代码注释和文档等
## 项目概述
**FunctionalScaffold函数式脚手架** 是一个算法工程化 Serverless 解决方案的脚手架生成器。
- 为了方便团队交流,项目的自然语言使用中文,包括代码注释和文档等
### 核心目标
解决三大痛点:
@@ -88,10 +88,10 @@ pip install -e ".[dev]"
./scripts/run_dev.sh
# 方式2直接运行开发模式自动重载
uvicorn src.functional_scaffold.main:app --reload --port 8000
uvicorn functional_scaffold.main:app --reload --port 8000
# 方式3生产模式
uvicorn src.functional_scaffold.main:app --host 0.0.0.0 --port 8000 --workers 4
uvicorn functional_scaffold.main:app --host 0.0.0.0 --port 8000 --workers 4
```
访问地址:

View File

@@ -58,7 +58,7 @@ pip install -e ".[dev]"
./scripts/run_dev.sh
# 方式2直接运行
uvicorn src.functional_scaffold.main:app --reload --port 8000
uvicorn functional_scaffold.main:app --reload --port 8000
```
4. 访问 API 文档

View File

@@ -18,6 +18,10 @@ RUN pip install --no-cache-dir -r requirements-dev.txt
# 复制应用代码和配置
COPY src/ ./src/
COPY config/ ./config/
COPY pyproject.toml .
# 安装包(使用 editable 模式)
RUN pip install --no-cache-dir -e .
# 创建非 root 用户
RUN useradd -m -u 1000 appuser && chown -R appuser:appuser /app
@@ -31,4 +35,4 @@ HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/healthz')"
# 启动命令
CMD ["uvicorn", "src.functional_scaffold.main:app", "--host", "0.0.0.0", "--port", "8000"]
CMD ["uvicorn", "functional_scaffold.main:app", "--host", "0.0.0.0", "--port", "8000"]

View File

@@ -25,7 +25,7 @@ Resources:
CAPort: 8000
CustomContainerConfig:
Image: 'registry.cn-hangzhou.aliyuncs.com/your-namespace/functional-scaffold:latest'
Command: '["uvicorn", "src.functional_scaffold.main:app", "--host", "0.0.0.0", "--port", "8000"]'
Command: '["uvicorn", "functional_scaffold.main:app", "--host", "0.0.0.0", "--port", "8000"]'
EnvironmentVariables:
APP_ENV: production
LOG_LEVEL: INFO

View File

@@ -412,7 +412,7 @@ class MLPredictor(BaseAlgorithm):
```python
# tests/test_text_processor.py
import pytest
from src.functional_scaffold.algorithms.text_processor import TextProcessor
from functional_scaffold.algorithms.text_processor import TextProcessor
class TestTextProcessor:
"""文本处理算法测试"""

View File

@@ -34,7 +34,7 @@ pip install -e ".[dev]"
```bash
# 开发模式(自动重载)
uvicorn src.functional_scaffold.main:app --reload --port 8000
uvicorn functional_scaffold.main:app --reload --port 8000
# docker 开发者模式
cd deployment && docker compose up -d
```

View File

@@ -94,7 +94,7 @@ curl -X POST http://localhost:8111/invoke \
{job="functional-scaffold-app", level="ERROR"} |= "59017bdd-5963-40b1-a325-5088593382c0"
# 特定 request_id 的特定 logger
{job="functional-scaffold-app", logger="src.functional_scaffold.algorithms.base"} |= "59017bdd-5963-40b1-a325-5088593382c0"
{job="functional-scaffold-app", logger="functional_scaffold.algorithms.base"} |= "59017bdd-5963-40b1-a325-5088593382c0"
```
### 故障排查

16
main.py
View File

@@ -1,16 +0,0 @@
# 这是一个示例 Python 脚本。
# 按 ⌃R 执行或将其替换为您的代码。
# 按 双击 ⇧ 在所有地方搜索类、文件、工具窗口、操作和设置。
def print_hi(name):
# 在下面的代码行中使用断点来调试脚本。
print(f'Hi, {name}') # 按 ⌘F8 切换断点。
# 按装订区域中的绿色按钮以运行脚本。
if __name__ == '__main__':
print_hi('PyCharm')
# 访问 https://www.jetbrains.com/help/pycharm/ 获取 PyCharm 帮助

View File

@@ -48,3 +48,4 @@ python_files = ["test_*.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
addopts = "-v --strict-markers"
pythonpath = ["src"]

View File

@@ -21,4 +21,4 @@ pip install -e ".[dev]"
# 启动服务
echo "Starting server on http://localhost:8000"
echo "API docs available at http://localhost:8000/docs"
uvicorn src.functional_scaffold.main:app --reload --host 0.0.0.0 --port 8000
uvicorn functional_scaffold.main:app --reload --host 0.0.0.0 --port 8000

View File

@@ -2,7 +2,7 @@
import pytest
from fastapi.testclient import TestClient
from src.functional_scaffold.main import app
from functional_scaffold.main import app
@pytest.fixture

View File

@@ -1,7 +1,7 @@
"""算法单元测试"""
import pytest
from src.functional_scaffold.algorithms.prime_checker import PrimeChecker
from functional_scaffold.algorithms.prime_checker import PrimeChecker
class TestPrimeChecker:

View File

@@ -6,12 +6,12 @@ import pytest
from unittest.mock import AsyncMock, MagicMock, patch
from fastapi import status
from src.functional_scaffold.core.job_manager import (
from functional_scaffold.core.job_manager import (
JobManager,
get_job_manager,
shutdown_job_manager,
)
from src.functional_scaffold.api.models import JobStatus
from functional_scaffold.api.models import JobStatus
class TestJobManager:
@@ -203,7 +203,7 @@ class TestJobsAPI:
def test_create_job_success(self, client):
"""测试成功创建任务"""
with patch(
"src.functional_scaffold.api.routes.get_job_manager", new_callable=AsyncMock
"functional_scaffold.api.routes.get_job_manager", new_callable=AsyncMock
) as mock_get_manager:
mock_manager = MagicMock()
mock_manager.is_available.return_value = True
@@ -237,7 +237,7 @@ class TestJobsAPI:
def test_create_job_algorithm_not_found(self, client):
"""测试创建任务时算法不存在"""
with patch(
"src.functional_scaffold.api.routes.get_job_manager", new_callable=AsyncMock
"functional_scaffold.api.routes.get_job_manager", new_callable=AsyncMock
) as mock_get_manager:
mock_manager = MagicMock()
mock_manager.is_available.return_value = True
@@ -259,7 +259,7 @@ class TestJobsAPI:
def test_create_job_service_unavailable(self, client):
"""测试服务不可用时创建任务"""
with patch(
"src.functional_scaffold.api.routes.get_job_manager", new_callable=AsyncMock
"functional_scaffold.api.routes.get_job_manager", new_callable=AsyncMock
) as mock_get_manager:
mock_manager = MagicMock()
mock_manager.is_available.return_value = False
@@ -278,7 +278,7 @@ class TestJobsAPI:
def test_get_job_status_success(self, client):
"""测试成功查询任务状态"""
with patch(
"src.functional_scaffold.api.routes.get_job_manager", new_callable=AsyncMock
"functional_scaffold.api.routes.get_job_manager", new_callable=AsyncMock
) as mock_get_manager:
mock_manager = MagicMock()
mock_manager.is_available.return_value = True
@@ -308,7 +308,7 @@ class TestJobsAPI:
def test_get_job_status_not_found(self, client):
"""测试查询不存在的任务"""
with patch(
"src.functional_scaffold.api.routes.get_job_manager", new_callable=AsyncMock
"functional_scaffold.api.routes.get_job_manager", new_callable=AsyncMock
) as mock_get_manager:
mock_manager = MagicMock()
mock_manager.is_available.return_value = True
@@ -324,7 +324,7 @@ class TestJobsAPI:
def test_get_job_status_service_unavailable(self, client):
"""测试服务不可用时查询任务"""
with patch(
"src.functional_scaffold.api.routes.get_job_manager", new_callable=AsyncMock
"functional_scaffold.api.routes.get_job_manager", new_callable=AsyncMock
) as mock_get_manager:
mock_manager = MagicMock()
mock_manager.is_available.return_value = False
@@ -395,7 +395,7 @@ class TestWebhook:
manager._http_client = mock_http
# 使用较短的重试间隔进行测试
with patch("src.functional_scaffold.core.job_manager.settings") as mock_settings:
with patch("functional_scaffold.core.job_manager.settings") as mock_settings:
mock_settings.webhook_max_retries = 2
mock_settings.webhook_timeout = 1

View File

@@ -25,7 +25,7 @@ class TestMetricsManager:
@pytest.fixture
def manager(self, mock_redis):
"""创建测试用的 MetricsManager"""
from src.functional_scaffold.core.metrics_unified import (
from functional_scaffold.core.metrics_unified import (
MetricsManager,
reset_metrics_manager,
)
@@ -108,7 +108,7 @@ class TestConvenienceFunctions:
@pytest.fixture(autouse=True)
def setup(self):
"""每个测试前重置管理器"""
from src.functional_scaffold.core.metrics_unified import reset_metrics_manager
from functional_scaffold.core.metrics_unified import reset_metrics_manager
reset_metrics_manager()
@@ -119,7 +119,7 @@ class TestConvenienceFunctions:
mock_instance.ping.return_value = True
mock_redis_class.return_value = mock_instance
from src.functional_scaffold.core.metrics_unified import incr, reset_metrics_manager
from functional_scaffold.core.metrics_unified import incr, reset_metrics_manager
reset_metrics_manager()
incr("http_requests_total", {"method": "GET", "endpoint": "/", "status": "success"})
@@ -133,7 +133,7 @@ class TestConvenienceFunctions:
mock_instance.ping.return_value = True
mock_redis_class.return_value = mock_instance
from src.functional_scaffold.core.metrics_unified import reset_metrics_manager, set
from functional_scaffold.core.metrics_unified import reset_metrics_manager, set
reset_metrics_manager()
set("http_requests_in_progress", {}, 10)
@@ -149,7 +149,7 @@ class TestConvenienceFunctions:
mock_instance.pipeline.return_value = mock_pipeline
mock_redis_class.return_value = mock_instance
from src.functional_scaffold.core.metrics_unified import observe, reset_metrics_manager
from functional_scaffold.core.metrics_unified import observe, reset_metrics_manager
reset_metrics_manager()
observe("http_request_duration_seconds", {"method": "GET", "endpoint": "/"}, 0.1)
@@ -168,7 +168,7 @@ class TestExport:
mock_instance.hgetall.return_value = {"method=GET,endpoint=/,status=success": "10"}
mock_redis_class.return_value = mock_instance
from src.functional_scaffold.core.metrics_unified import export, reset_metrics_manager
from functional_scaffold.core.metrics_unified import export, reset_metrics_manager
reset_metrics_manager()
output = export()
@@ -192,7 +192,7 @@ class TestExport:
mock_instance.hget.return_value = "3"
mock_redis_class.return_value = mock_instance
from src.functional_scaffold.core.metrics_unified import export, reset_metrics_manager
from functional_scaffold.core.metrics_unified import export, reset_metrics_manager
reset_metrics_manager()
output = export()
@@ -206,7 +206,7 @@ class TestEnvVarSubstitution:
def test_substitute_env_vars(self):
"""测试环境变量替换"""
import os
from src.functional_scaffold.core.metrics_unified import MetricsManager
from functional_scaffold.core.metrics_unified import MetricsManager
# 设置测试环境变量
os.environ["TEST_VAR"] = "test_value"
@@ -235,7 +235,7 @@ class TestTrackAlgorithmExecution:
mock_instance.pipeline.return_value = mock_pipeline
mock_redis_class.return_value = mock_instance
from src.functional_scaffold.core.metrics_unified import (
from functional_scaffold.core.metrics_unified import (
reset_metrics_manager,
track_algorithm_execution,
)
@@ -258,7 +258,7 @@ class TestTrackAlgorithmExecution:
mock_instance.pipeline.return_value = mock_pipeline
mock_redis_class.return_value = mock_instance
from src.functional_scaffold.core.metrics_unified import (
from functional_scaffold.core.metrics_unified import (
reset_metrics_manager,
track_algorithm_execution,
)

View File

@@ -4,7 +4,7 @@ import pytest
from unittest.mock import patch, MagicMock
from fastapi.testclient import TestClient
from src.functional_scaffold.main import app, normalize_path
from functional_scaffold.main import app, normalize_path
class TestNormalizePath:
@@ -32,10 +32,10 @@ class TestNormalizePath:
class TestMetricsMiddleware:
"""测试指标中间件"""
@patch("src.functional_scaffold.main.incr")
@patch("src.functional_scaffold.main.observe")
@patch("src.functional_scaffold.main.gauge_incr")
@patch("src.functional_scaffold.main.gauge_decr")
@patch("functional_scaffold.main.incr")
@patch("functional_scaffold.main.observe")
@patch("functional_scaffold.main.gauge_incr")
@patch("functional_scaffold.main.gauge_decr")
def test_skip_health_endpoints(self, mock_gauge_decr, mock_gauge_incr, mock_observe, mock_incr):
"""测试跳过健康检查端点"""
client = TestClient(app)
@@ -51,10 +51,10 @@ class TestMetricsMiddleware:
mock_gauge_incr.assert_not_called()
mock_gauge_decr.assert_not_called()
@patch("src.functional_scaffold.main.incr")
@patch("src.functional_scaffold.main.observe")
@patch("src.functional_scaffold.main.gauge_incr")
@patch("src.functional_scaffold.main.gauge_decr")
@patch("functional_scaffold.main.incr")
@patch("functional_scaffold.main.observe")
@patch("functional_scaffold.main.gauge_incr")
@patch("functional_scaffold.main.gauge_decr")
def test_record_normal_endpoints(self, mock_gauge_decr, mock_gauge_incr, mock_observe, mock_incr):
"""测试记录普通端点"""
client = TestClient(app)
@@ -72,11 +72,11 @@ class TestMetricsMiddleware:
incr_call_args = mock_incr.call_args
assert incr_call_args[0][1]["endpoint"] == "/invoke"
@patch("src.functional_scaffold.main.incr")
@patch("src.functional_scaffold.main.observe")
@patch("src.functional_scaffold.main.gauge_incr")
@patch("src.functional_scaffold.main.gauge_decr")
@patch("src.functional_scaffold.core.job_manager.get_job_manager")
@patch("functional_scaffold.main.incr")
@patch("functional_scaffold.main.observe")
@patch("functional_scaffold.main.gauge_incr")
@patch("functional_scaffold.main.gauge_decr")
@patch("functional_scaffold.core.job_manager.get_job_manager")
def test_normalize_job_path(self, mock_get_manager, mock_gauge_decr, mock_gauge_incr, mock_observe, mock_incr):
"""测试规范化任务路径"""
# Mock job manager