chore: scaffold yunke-server

Create pyproject.toml (FastAPI + SQLAlchemy + Playwright + APScheduler +
Redis + cryptography stack), .env.example, app/__init__.py and a
pydantic-settings Settings singleton (get_settings), and a root
.gitignore covering Python, Node, env, IDE and the local media dir.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
浅念
2026-08-01 10:59:37 +08:00
parent cd8d36fd00
commit 2031607beb
5 changed files with 103 additions and 0 deletions
+21
View File
@@ -0,0 +1,21 @@
# Python
__pycache__/
*.pyc
*.pyo
*.pyd
.venv/
*.egg-info/
# Node
node_modules/
dist/
# Env
.env
# IDE
.vscode/
.idea/
# Local media storage
media/
+9
View File
@@ -0,0 +1,9 @@
YUNKE_BASE_URL=https://crm2.yunkecn.com
YUNKE_USERNAME=
YUNKE_PASSWORD=
DB_URL=mysql+asyncmy://user:pass@localhost:3306/yunke
REDIS_URL=redis://localhost:6379/0
MEDIA_DIR=./media
# Fernet key (e.g. from cryptography.fernet.Fernet.generate_key()) used to encrypt
# stored credentials. Required for real runs; left blank for tests.
ENCRYPTION_KEY=
View File
+30
View File
@@ -0,0 +1,30 @@
from functools import lru_cache
from pathlib import Path
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
"""Application settings sourced from environment / .env file."""
model_config = SettingsConfigDict(
env_file=".env",
env_file_encoding="utf-8",
extra="ignore",
)
yunke_base_url: str = "https://crm2.yunkecn.com"
yunke_username: str = ""
yunke_password: str = ""
db_url: str = "mysql+asyncmy://user:pass@localhost:3306/yunke"
redis_url: str = "redis://localhost:6379/0"
media_dir: Path = Path("./media")
# Fernet key for encrypting stored credentials. Required for real runs;
# empty default lets tests construct Settings without a key.
encryption_key: str = ""
@lru_cache
def get_settings() -> Settings:
"""Return the process-wide Settings singleton."""
return Settings()
+43
View File
@@ -0,0 +1,43 @@
[project]
name = "yunke-server"
version = "0.1.0"
description = "云客数据本地化系统 - Python backend"
requires-python = ">=3.11"
dependencies = [
"fastapi",
"uvicorn[standard]",
"sqlalchemy[asyncio]",
"asyncmy",
"alembic",
"redis",
"httpx",
"playwright",
"apscheduler",
"pydantic",
"pydantic-settings",
"cryptography",
]
[project.optional-dependencies]
dev = [
"pytest",
"pytest-asyncio",
"respx",
"ruff",
]
[build-system]
requires = ["setuptools>=68"]
build-backend = "setuptools.build_meta"
[tool.setuptools.packages.find]
where = ["."]
include = ["app*"]
[tool.pytest.ini_options]
asyncio_mode = "auto"
testpaths = ["tests"]
[tool.ruff]
line-length = 100
target-version = "py311"