From bb5d339dbe81306a638ffc5b7735d549a0b9c770 Mon Sep 17 00:00:00 2001 From: Huarch Date: Fri, 12 Jun 2026 15:28:49 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=A0=E9=99=A4=E4=B8=8D=E5=86=8D=E9=9C=80?= =?UTF-8?q?=E8=A6=81=E7=9A=84=E6=9E=84=E5=BB=BA=E5=92=8C=E6=89=93=E5=8C=85?= =?UTF-8?q?=E5=B7=A5=E4=BD=9C=E6=B5=81=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/copilot-instructions.md | 82 ------------------ .github/workflows/build-package.yml | 128 ---------------------------- 2 files changed, 210 deletions(-) delete mode 100644 .github/copilot-instructions.md delete mode 100644 .github/workflows/build-package.yml diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md deleted file mode 100644 index 23396a2..0000000 --- a/.github/copilot-instructions.md +++ /dev/null @@ -1,82 +0,0 @@ -# Copilot Instructions for TJWater Server - -This repository contains the backend code for the TJWater Server, a water distribution network management system built with FastAPI. - -## High-Level Architecture - -The application follows a layered architecture: - -- **Entry Point**: `app/main.py` initializes the FastAPI application, database connections (PostgreSQL & TimescaleDB), and middleware. -- **API Layer**: `app/api/v1` contains the route handlers. -- **Service Layer**: `app/services` contains business logic and orchestration. -- **Infrastructure Layer**: `app/infra` handles database connections (`db`), audit logging (`audit`), and external integrations. -- **Domain Layer**: `app/domain` likely contains core domain models. -- **Native/Algorithms**: `app/native` and `app/algorithms` handle specialized water network calculations (possibly using EPANET/WNTR). - -## Build, Test, and Run Commands - -### Environment Setup - -- Dependencies are listed in `requirements.txt`. -- Configuration is managed via environment variables (see `.env.example` if available, or `app/core/config.py`). -- **Important**: Ensure `.env` is configured with correct database credentials for both PostgreSQL and TimescaleDB. - -If first time setting up, you may want to create a Conda environment: - -```bash -conda create -n server python=3.12 -conda activate server -pip install uv -uv pip install -r requirements.txt -conda install -c conda-forge pymetis -``` - -### Running the Server - -The preferred way to run the server locally is using the helper script which sets up the Python path correctly: - -```bash -conda activate server -python scripts/run_server.py -``` - -Alternatively, you can run directly with uvicorn (ensure PYTHONPATH includes the root): - -```bash -conda activate server -uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload -``` - -### Running Tests - -Use `pytest` to run tests. The `tests/conftest.py` handles path setup. - -```bash -# Run all tests -pytest - -# Run a specific test file -pytest tests/unit/test_specific_file.py - -# Run a specific test case -pytest tests/unit/test_specific_file.py::test_function_name -``` - -### Building (Optional) - -The project includes scripts to compile Python modules to `.pyd` files using Cython (see `scripts/build_pyd.py`). This is likely for distribution/performance but not required for standard development. - -## Key Conventions - -- **Async/Await**: The codebase heavily uses `async` and `await` for I/O operations, especially database interactions. -- **Database Management**: - - Connections are managed globally in `app.infra.db` and initialized in `lifespan` (app/main.py). - - Use `app.infra.db.dynamic_manager` for project-specific database connections (multi-tenancy/dynamic projects). -- **Pydantic**: extensively used for data validation and settings management. -- **Scripts**: The `scripts/` directory contains many utility scripts for maintenance, data processing, and server management. Check there before writing new operational scripts. -- **Water Network Modeling**: Interactions with water network models often involve `epanet` or `wntr` libraries. Be aware of domain-specific terminology (nodes, links, junctions, tanks). - -## Code Style - -- Follow standard PEP 8 guidelines. -- No specific linter configuration was found, so default to standard Python formatting. diff --git a/.github/workflows/build-package.yml b/.github/workflows/build-package.yml deleted file mode 100644 index efdb759..0000000 --- a/.github/workflows/build-package.yml +++ /dev/null @@ -1,128 +0,0 @@ -name: Build And Package - -on: - push: - tags: - - "v*" - -jobs: - build-package: - runs-on: ${{ matrix.os }} - env: - FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, windows-latest] - - steps: - - name: Checkout source - uses: actions/checkout@v5 - - - name: Setup Python - uses: actions/setup-python@v6 - with: - python-version: "3.12" - - - name: Install system build tools - if: runner.os == 'Linux' - run: | - sudo apt-get update - sudo apt-get install -y build-essential - - - name: Install compile dependencies - run: | - python -m pip install --upgrade pip - pip install cython setuptools wheel - - - name: Run Cython compile - run: | - python scripts/compile.py - - - name: Prepare package and archive - run: | - python - <<'PY' - import os - import shutil - import tarfile - import zipfile - import sys - from pathlib import Path - - root = Path.cwd() - package_dir = root / "package" - dist_dir = root / "dist" - - for d in [package_dir, dist_dir]: - if d.exists(): - shutil.rmtree(d) - d.mkdir(parents=True, exist_ok=True) - - # Define directories with compiled artifacts - compile_dirs = ["app/services", "app/native/wndb", "app/algorithms"] - # Global ignore list - ignore_names = { - ".git", - ".github", - "__pycache__", - ".pytest_cache", - ".mypy_cache", - ".venv", - "venv", - "temp", - "tests", - "package", - "dist", - } - - def ignore_func(directory, names): - rel_dir = os.path.relpath(directory, root).replace("\\", "/") - is_in_compile_path = any(rel_dir.startswith(d) for d in compile_dirs) - - ignored = [] - for name in names: - if name in ignore_names or name.endswith(".pyc"): - ignored.append(name) - # Exclude source .py files only in compiled directories - elif is_in_compile_path and name.endswith(".py"): - ignored.append(name) - return ignored - - for item in root.iterdir(): - if item.name in ignore_names: - continue - target = package_dir / item.name - if item.is_dir(): - shutil.copytree(item, target, ignore=ignore_func) - else: - shutil.copy2(item, target) - - # Safety guard: ensure no .github directory remains - github_paths = [p for p in package_dir.rglob(".github") if p.is_dir()] - for p in github_paths: - shutil.rmtree(p, ignore_errors=True) - - sha = os.environ["GITHUB_SHA"] - run_os = os.environ["RUNNER_OS"].lower() - - if run_os == "windows": - archive_path = dist_dir / f"tjwater-server-{run_os}-{sha}.zip" - with zipfile.ZipFile(archive_path, "w", compression=zipfile.ZIP_DEFLATED) as zf: - for f in package_dir.rglob("*"): - if f.is_file(): - zf.write(f, f.relative_to(package_dir)) - else: - archive_path = dist_dir / f"tjwater-server-{run_os}-{sha}.tar.gz" - with tarfile.open(archive_path, "w:gz") as tf: - tf.add(package_dir, arcname=".") - - print(f"Archive created: {archive_path}") - PY - shell: bash - - - name: Upload package artifact - uses: actions/upload-artifact@v5 - with: - name: tjwater-server-package-${{ runner.os }} - path: dist/* - retention-days: 14