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:
+21
@@ -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/
|
||||||
@@ -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=
|
||||||
@@ -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()
|
||||||
@@ -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"
|
||||||
Reference in New Issue
Block a user