wangdongxu

jira:NYJ-1460 desc:init

1 -# Byte-compiled / optimized / DLL files  
2 -__pycache__/  
3 -*.py[cod]  
4 -*$py.class  
5 -  
6 -# C extensions  
7 -*.so  
8 -  
9 -# Distribution / packaging  
10 -.Python  
11 -build/  
12 -develop-eggs/  
13 -dist/  
14 -downloads/  
15 -eggs/  
16 -.eggs/  
17 -lib/  
18 -lib64/  
19 -parts/  
20 -sdist/  
21 -var/  
22 -wheels/  
23 -share/python-wheels/  
24 -*.egg-info/  
25 -.installed.cfg  
26 -*.egg  
27 -MANIFEST  
28 -  
29 -# PyInstaller  
30 -# Usually these files are written by a python script from a template  
31 -# before PyInstaller builds the exe, so as to inject date/other infos into it.  
32 -*.manifest  
33 -*.spec  
34 -  
35 -# Installer logs  
36 -pip-log.txt  
37 -pip-delete-this-directory.txt  
38 -  
39 -# Unit test / coverage reports  
40 -htmlcov/  
41 -.tox/  
42 -.nox/  
43 -.coverage  
44 -.coverage.*  
45 -.cache  
46 -nosetests.xml  
47 -coverage.xml  
48 -*.cover  
49 -*.py,cover  
50 -.hypothesis/  
51 -.pytest_cache/  
52 -cover/  
53 -  
54 -# Translations  
55 -*.mo  
56 -*.pot  
57 -  
58 -# Django stuff:  
59 -*.log  
60 -local_settings.py  
61 -db.sqlite3  
62 -db.sqlite3-journal  
63 -  
64 -# Flask stuff:  
65 -instance/  
66 -.webassets-cache  
67 -  
68 -# Scrapy stuff:  
69 -.scrapy  
70 -  
71 -# Sphinx documentation  
72 -docs/_build/  
73 -  
74 -# PyBuilder  
75 -.pybuilder/  
76 -target/  
77 -  
78 -# Jupyter Notebook  
79 -.ipynb_checkpoints  
80 -  
81 -# IPython  
82 -profile_default/  
83 -ipython_config.py  
84 -  
85 -# pyenv  
86 -# For a library or package, you might want to ignore these files since the code is  
87 -# intended to run in multiple environments; otherwise, check them in:  
88 -# .python-version  
89 -  
90 -# pipenv  
91 -# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.  
92 -# However, in case of collaboration, if having platform-specific dependencies or dependencies  
93 -# having no cross-platform support, pipenv may install dependencies that don't work, or not  
94 -# install all needed dependencies.  
95 -#Pipfile.lock  
96 -  
97 -# poetry  
98 -# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.  
99 -# This is especially recommended for binary packages to ensure reproducibility, and is more  
100 -# commonly ignored for libraries.  
101 -#poetry.lock  
102 -  
103 -# pdm  
104 -# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.  
105 -#pdm.lock  
106 -# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it  
107 -# in version control. Use .pdm.toml for personal settings and store shared settings in pyproject.toml.  
108 -.pdm.toml  
109 -  
110 -# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm  
111 -__pypackages__/  
112 -  
113 -# Celery stuff  
114 -celerybeat-schedule  
115 -celerybeat.pid  
116 -  
117 -# SageMath parsed files  
118 -*.sage.py  
119 -  
120 -# Environments  
121 -.env  
122 -.venv  
123 -env/  
124 -venv/  
125 -ENV/  
126 -environment.yml  
127 -  
128 -# Spyder project settings  
129 -.spyderproject  
130 -.spyproject  
131 -  
132 -# Rope project settings  
133 -.ropeproject  
134 -  
135 -# mkdocs documentation  
136 -/site  
137 -  
138 -# mypy  
139 -.mypy_cache/  
140 -.dmypy.json  
141 -dmypy.json  
142 -  
143 -# Pyre type checker  
144 -.pyre/  
145 -  
146 -# pytype static type analyzer  
147 -.pytype/  
148 -  
149 -# Cython debug symbols  
150 -cython_debug/  
151 -  
152 -# PyCharm  
153 -# JetBrains specific template is maintained in a separate JetBrains.gitignore that can  
154 -# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore  
155 -# and can be added to the global gitignore or merged into this file.  
156 -# For a more comprehensive ignore file, see:  
157 -# https://github.com/github/gitignore/blob/main/Python.gitignore  
158 -  
159 -# VS Code 1 +/live-stream-ai-task-workline/modules/wtt_highlight/model_weights/*
  2 +*mov
  3 +/.externalToolBuilders
  4 +/.settings
  5 +.svn
  6 +/.project
  7 +/target
  8 +./target
  9 +/.classpath
  10 +.idea/
  11 +*.iml
  12 +*.iws
  13 +*.ipr
  14 +*.ids
  15 +*.orig
  16 +classes/
  17 +/bin/
  18 +*/.classpath
  19 +*/.project
  20 +*/.settings/*
  21 +######################
  22 +# Project Specific
  23 +######################
  24 +/target/www/**
  25 +/src/test/javascript/coverage/
  26 +/src/test/javascript/PhantomJS*/
  27 +
  28 +######################
  29 +# Node
  30 +######################
  31 +/node/
  32 +node_tmp/
  33 +node_modules/
  34 +npm-debug.log.*
  35 +/.awcache/*
  36 +
  37 +######################
  38 +# SASS
  39 +######################
  40 +.sass-cache/
  41 +
  42 +######################
  43 +# Eclipse
  44 +######################
  45 +*.pydevproject
  46 +.project
  47 +.metadata
  48 +tmp/
  49 +tmp/**/*
  50 +*.tmp
  51 +*.bak
  52 +*.swp
  53 +*~.nib
  54 +local.properties
  55 +.classpath
  56 +.settings/
  57 +.loadpath
  58 +.factorypath
  59 +/src/main/resources/rebel.xml
  60 +
  61 +# External tool builders
  62 +.externalToolBuilders/**
  63 +
  64 +# Locally stored "Eclipse launch configurations"
  65 +*.launch
  66 +
  67 +# CDT-specific
  68 +.cproject
  69 +
  70 +# PDT-specific
  71 +.buildpath
  72 +
  73 +######################
  74 +# Intellij
  75 +######################
  76 +.idea/
  77 +*.iml
  78 +*.iws
  79 +*.ipr
  80 +*.ids
  81 +*.orig
  82 +classes/
  83 +
  84 +######################
  85 +# Visual Studio Code
  86 +######################
160 .vscode/ 87 .vscode/
161 88
  89 +######################
  90 +# Maven
  91 +######################
  92 +/log/
  93 +/target/
  94 +
  95 +######################
  96 +# Gradle
  97 +######################
  98 +.gradle/
  99 +/build/
  100 +
  101 +######################
  102 +# Package Files
  103 +######################
  104 +*.jar
  105 +*.war
  106 +*.ear
  107 +*.db
  108 +
  109 +######################
162 # Windows 110 # Windows
  111 +######################
  112 +# Windows image file caches
163 Thumbs.db 113 Thumbs.db
  114 +
  115 +# Folder com.migu.oes.power.config file
164 Desktop.ini 116 Desktop.ini
165 117
166 -# macOS 118 +######################
  119 +# Mac OSX
  120 +######################
167 .DS_Store 121 .DS_Store
168 -.AppleDouble  
169 -.LSOverride  
170 -  
171 -# Linux 122 +.svn
  123 +
  124 +# Thumbnails
  125 +._*
  126 +
  127 +# Files that might appear on external disk
  128 +.Spotlight-V100
  129 +.Trashes
  130 +
  131 +######################
  132 +# Directories
  133 +######################
  134 +/bin/
  135 +/deploy/
  136 +
  137 +######################
  138 +# Logs
  139 +######################
  140 +*.log*
  141 +
  142 +######################
  143 +# Others
  144 +######################
  145 +*.class
  146 +*.*~
172 *~ 147 *~
173 -.nfs*  
  148 +.merge_file*
  149 +
  150 +######################
  151 +# Gradle Wrapper
  152 +######################
  153 +!gradle/wrapper/gradle-wrapper.jar
  154 +
  155 +######################
  156 +# Maven Wrapper
  157 +######################
  158 +!.mvn/wrapper/maven-wrapper.jar
  159 +
  160 +######################
  161 +# ESLint
  162 +######################
  163 +.eslintcache
  164 +*.lst
  165 +oes-nryy-vo/target/maven-archiver/pom.properties
  166 +oes-nryy-dataservice/target/maven-archiver/pom.properties
  167 +oes-nryy-base/target/maven-archiver/pom.properties
  168 +oes-nryy-copyright/bin/.gitkeep
  169 +oes-nryy-copyright/bin/cbak
  170 +*.original
  171 +*.gz
  172 +oes-nryy-tag/target/oes-nryy-tag-1.0.0/label/bin/service.sh
  173 +oes-nryy-tag/target/maven-archiver/pom.properties
  174 +oes-nryy-data-trans/target/maven-archiver/pom.properties
  175 +oes-nryy-tag/target/oes-nryy-tag-1.0.0/label/bin/cbak
  176 +
  177 +
  178 +######################
  179 +# pp-scene-det
  180 +######################
  181 +__pycache__/
  182 +
  183 +######################
  184 +# live-stream-ai-task-workline
  185 +######################
  186 +modules/basketball/weights
  187 +modules/singer/weights
  188 +weights/
  189 +weights1/
  190 +files/
  191 +*.log
  192 +*.log.*
  193 +cache_data/
  194 +data/
  195 +test/
  196 +# Media files
  197 +*.jpg
  198 +*.jpeg
  199 +*.png
  200 +*.gif
  201 +*.mp4
  202 +*.avi
  203 +*.mov
  204 +*.mkv
  205 +
  206 +# OS
  207 +.DS_Store
  208 +Thumbs.db
  209 +
  1 +from pydantic import BaseModel, Field
  2 +from typing import Generic, TypeVar, Optional
  3 +
  4 +T = TypeVar('T')
  5 +
  6 +
  7 +class RespBean(BaseModel, Generic[T]):
  8 + code: str = Field(default="success", description="code")
  9 + message: str = Field(default="success", description='message')
  10 + data: Optional[T] = Field(description="数据", default=None)
  11 +
  12 +
  13 +def error(message):
  14 + return RespBean(code="error", message=message, data=None)
  15 +
  16 +
  17 +def success(data=None):
  18 + return RespBean(data=data)
  1 +"""API路由聚合模块."""
  2 +
  3 +from fastapi import APIRouter
  4 +
  5 +# 创建主路由
  6 +api_router = APIRouter(prefix="/api/v1")
  7 +
  8 +# 注册各场景路由
  9 +
  10 +def register_router(router: APIRouter, prefix: str):
  11 + api_router.include_router(router, prefix=prefix)
  12 +
  1 +app_name: "Embedding Service"
  2 +app_version: "1.0.0"
  3 +port: 8000
  4 +debug: true
  5 +
  6 +db_es_enable: true
  7 +db_es_url: "http://localhost:9200"
  8 +db_postgres_enable: false
  9 +db_postgres_url: "postgresql://postgres:postgres@localhost:5432/postgres"
  1 +from aabd.base.cfg_loader import load_yaml_by_name_with_env
  2 +from aabd.base.enhance_dict import EnhanceDict, read_prefixed_env_vars
  3 +
  4 +settings = EnhanceDict(load_yaml_by_name_with_env('config'))
  5 +settings.update(read_prefixed_env_vars('APP_'))
  6 +
  1 +"""自定义异常模块."""
  2 +
  3 +
  4 +class EmbeddingServiceError(Exception):
  5 + """Embedding服务基础异常."""
  6 +
  7 + def __init__(self, message: str, code: str = "EMBEDDING_ERROR"):
  8 + self.message = message
  9 + self.code = code
  10 + super().__init__(self.message)
  11 +
  12 +
  13 +class EmbeddingAPIError(EmbeddingServiceError):
  14 + """Embedding API调用异常."""
  15 +
  16 + def __init__(self, message: str, status_code: int = 500):
  17 + super().__init__(message, code="EMBEDDING_API_ERROR")
  18 + self.status_code = status_code
  19 +
  20 +
  21 +class DatabaseError(EmbeddingServiceError):
  22 + """数据库操作异常."""
  23 +
  24 + def __init__(self, message: str):
  25 + super().__init__(message, code="DATABASE_ERROR")
  26 +
  27 +
  28 +class NotFoundError(EmbeddingServiceError):
  29 + """资源不存在异常."""
  30 +
  31 + def __init__(self, message: str):
  32 + super().__init__(message, code="NOT_FOUND")
  33 +
  34 +
  35 +class ValidationError(EmbeddingServiceError):
  36 + """参数校验异常."""
  37 +
  38 + def __init__(self, message: str):
  39 + super().__init__(message, code="VALIDATION_ERROR")
  1 +"""数据库模块,提供统一的向量数据库抽象层.
  2 +
  3 +支持Elasticsearch和PostgreSQL两种后端,通过配置自动切换。
  4 +使用示例:
  5 + from app.db import db_client
  6 +
  7 + # 连接数据库
  8 + await db_client.connect()
  9 +
  10 + # 创建集合
  11 + await db_client.create_collection("face_vectors", vector_dim=512)
  12 +
  13 + # 插入数据
  14 + await db_client.insert("face_vectors", "user_001", vector, {"name": "张三"})
  15 +
  16 + # 向量搜索
  17 + results = await db_client.search("face_vectors", query_vector, top_k=10)
  18 +
  19 + # 断开连接
  20 + await db_client.disconnect()
  21 +"""
  22 +
  23 +from typing import Optional
  24 +
  25 +from app.core.config import settings
  26 +
  27 +es_client = None
  28 +pg_client = None
  29 +
  30 +
  31 +async def connect():
  32 + if settings.db_established:
  33 + from .es_client import get_es_client
  34 + global es_client
  35 + es_client = get_es_client()
  36 + await es_client.connect()
  37 + if settings.db_postgres_enable:
  38 + from .postgres_client import get_pg_client
  39 + global pg_client
  40 + pg_client = get_pg_client()
  41 + await pg_client.connect()
  42 +
  43 +
  44 +async def disconnect():
  45 + global es_client, pg_client
  46 + if es_client is not None:
  47 + await es_client.disconnect()
  48 + es_client = None
  49 + if pg_client is not None:
  50 + await pg_client.disconnect()
  1 +"""数据库抽象基类,定义统一的CRUD接口."""
  2 +
  3 +from abc import ABC, abstractmethod
  4 +from typing import Any, Dict, List, Optional
  5 +
  6 +
  7 +class VectorDBClient(ABC):
  8 + """向量数据库客户端抽象基类.
  9 +
  10 + 定义了统一的向量数据CRUD接口,支持Elasticsearch和PostgreSQL等后端。
  11 + """
  12 +
  13 + @abstractmethod
  14 + async def connect(self) -> None:
  15 + """建立数据库连接."""
  16 + pass
  17 +
  18 + @abstractmethod
  19 + async def disconnect(self) -> None:
  20 + """断开数据库连接."""
  21 + pass
  22 +
  23 + @abstractmethod
  24 + async def health_check(self) -> bool:
  25 + """检查数据库连接健康状态.
  26 +
  27 + Returns:
  28 + bool: 连接正常返回True,否则返回False
  29 + """
  30 + pass
  1 +"""Elasticsearch向量数据库客户端实现."""
  2 +
  3 +from typing import Any, Dict, List, Optional
  4 +
  5 +from app.core.config import settings
  6 +from app.db.base import VectorDBClient
  7 +
  8 +
  9 +class ElasticsearchClient(VectorDBClient):
  10 + """Elasticsearch向量数据库客户端.
  11 +
  12 + 使用Elasticsearch的dense_vector类型存储向量,支持向量相似度搜索。
  13 + """
  14 +
  15 + def __init__(self, es_url: Optional[str] = None):
  16 + """初始化ES客户端.
  17 +
  18 + Args:
  19 + es_url: Elasticsearch连接URL,默认从配置读取
  20 + """
  21 + self.es_url = es_url or settings.get("db_es_url", "http://localhost:9200")
  22 + self._client: Optional[Any] = None
  23 +
  24 + async def connect(self) -> None:
  25 + """建立ES连接."""
  26 + from elasticsearch import AsyncElasticsearch
  27 +
  28 + self._client = AsyncElasticsearch([self.es_url])
  29 + # 验证连接
  30 + await self._client.ping()
  31 +
  32 + async def disconnect(self) -> None:
  33 + """断开ES连接."""
  34 + if self._client:
  35 + await self._client.close()
  36 + self._client = None
  37 +
  38 + async def health_check(self) -> bool:
  39 + """检查ES连接健康状态."""
  40 + if not self._client:
  41 + return False
  42 + try:
  43 + return await self._client.ping()
  44 + except Exception:
  45 + return False
  46 +_es_client: Optional[ElasticsearchClient] = None
  47 +
  48 +
  49 +def get_es_client() -> ElasticsearchClient:
  50 + """获取全局ES客户端实例(单例模式).
  51 +
  52 + Returns:
  53 + ElasticsearchClient: ES客户端实例
  54 + """
  55 + global _es_client
  56 + if _es_client is None:
  57 + _es_client = ElasticsearchClient()
  58 + return _es_client
  1 +"""PostgreSQL向量数据库客户端实现."""
  2 +
  3 +import json
  4 +from typing import Any, Dict, List, Optional
  5 +
  6 +from app.db.base import VectorDBClient
  7 +
  8 +
  9 +class PostgresClient(VectorDBClient):
  10 + """PostgreSQL向量数据库客户端.
  11 +
  12 + 使用pgvector扩展存储向量,支持向量相似度搜索。
  13 + 需要安装pgvector扩展: CREATE EXTENSION IF NOT EXISTS vector;
  14 + """
  15 +
  16 + def __init__(self, pg_url: Optional[str] = None):
  17 + """初始化PG客户端.
  18 +
  19 + Args:
  20 + pg_url: PostgreSQL连接URL,默认从配置读取
  21 + """
  22 + self.pg_url = pg_url
  23 + self._pool: Optional[Any] = None
  24 +
  25 + async def connect(self) -> None:
  26 + """建立PG连接池."""
  27 + import psycopg
  28 + from psycopg_pool import AsyncConnectionPool
  29 +
  30 + self._pool = AsyncConnectionPool(
  31 + conninfo=self.pg_url,
  32 + min_size=1,
  33 + max_size=10,
  34 + )
  35 +
  36 + # 验证连接并启用pgvector
  37 + async with self._pool.connection() as conn:
  38 + await conn.execute("CREATE EXTENSION IF NOT EXISTS vector")
  39 + await conn.commit()
  40 +
  41 + async def disconnect(self) -> None:
  42 + """断开PG连接."""
  43 + if self._pool:
  44 + await self._pool.close()
  45 + self._pool = None
  46 +
  47 + async def health_check(self) -> bool:
  48 + """检查PG连接健康状态."""
  49 + if not self._pool:
  50 + return False
  51 + try:
  52 + async with self._pool.connection() as conn:
  53 + cursor = await conn.execute("SELECT 1")
  54 + result = await cursor.fetchone()
  55 + return result is not None and result[0] == 1
  56 + except Exception:
  57 + return False
  58 +
  59 +
  60 +# 全局PG客户端实例
  61 +_pg_client: Optional[PostgresClient] = None
  62 +
  63 +
  64 +def get_pg_client() -> PostgresClient:
  65 + """获取全局PG客户端实例(单例模式).
  66 +
  67 + Returns:
  68 + PostgresClient: PG客户端实例
  69 + """
  70 + global _pg_client
  71 + if _pg_client is None:
  72 + _pg_client = PostgresClient()
  73 + return _pg_client
  1 +"""FastAPI应用入口."""
  2 +
  3 +from contextlib import asynccontextmanager
  4 +from typing import AsyncGenerator
  5 +
  6 +from fastapi import FastAPI
  7 +from fastapi.middleware.cors import CORSMiddleware
  8 +
  9 +from app.api.router import api_router
  10 +from app.core.exceptions import EmbeddingServiceError
  11 +from app.core.config import settings
  12 +from app.db import connect as db_client_connect, disconnect as db_client_disconnect
  13 +
  14 +@asynccontextmanager
  15 +async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
  16 + """应用生命周期管理."""
  17 + # 启动时建立数据库连接
  18 + try:
  19 + await db_client_connect()
  20 + db_type = settings.get("db_type", "es")
  21 + print(f"✓ {db_type.upper()} database connected")
  22 + except Exception as e:
  23 + print(f"✗ Failed to connect to database: {e}")
  24 + raise
  25 +
  26 + yield
  27 +
  28 + # 关闭时断开数据库连接
  29 + try:
  30 + await db_client_disconnect()
  31 + db_type = settings.get("db_type", "es")
  32 + print(f"✓ {db_type.upper()} database disconnected")
  33 + except Exception as e:
  34 + print(f"✗ Error disconnecting from database: {e}")
  35 +
  36 +
  37 +def create_app() -> FastAPI:
  38 + """创建FastAPI应用."""
  39 +
  40 + app = FastAPI(
  41 + title=settings.app_name,
  42 + version=settings.app_version,
  43 + description="基于向量的CRUD服务,支持多种Embedding场景",
  44 + lifespan=lifespan,
  45 + docs_url="/docs",
  46 + redoc_url="/redoc",
  47 + )
  48 +
  49 + # 配置CORS
  50 + app.add_middleware(
  51 + CORSMiddleware,
  52 + allow_origins=["*"],
  53 + allow_credentials=True,
  54 + allow_methods=["*"],
  55 + allow_headers=["*"],
  56 + )
  57 +
  58 + # 注册路由
  59 + app.include_router(api_router)
  60 +
  61 + # 异常处理
  62 + @app.exception_handler(EmbeddingServiceError)
  63 + async def embedding_service_exception_handler(request, exc):
  64 + from fastapi.responses import JSONResponse
  65 +
  66 + return JSONResponse(
  67 + status_code=500,
  68 + content={"code": exc.code, "message": exc.message},
  69 + )
  70 +
  71 + # @app.get("/health", tags=["健康检查"])
  72 + # async def health_check():
  73 + # """健康检查端点."""
  74 + # db_healthy = await db_client.health_check()
  75 + # db_type = settings.get("db_type", "es")
  76 + # return {
  77 + # "status": "healthy" if db_healthy else "unhealthy",
  78 + # "database": {
  79 + # "type": db_type,
  80 + # "status": "connected" if db_healthy else "disconnected",
  81 + # },
  82 + # }
  83 +
  84 + @app.get("/", tags=["根路径"])
  85 + async def root():
  86 + """根路径."""
  87 + return {
  88 + "name": settings.app_name,
  89 + "version": settings.app_version,
  90 + "docs": "/docs",
  91 + }
  92 +
  93 + return app
  94 +
  95 +
  96 +# 创建应用实例
  97 +app = create_app()
  98 +
  99 +if __name__ == "__main__":
  100 + import uvicorn
  101 +
  102 + uvicorn.run(
  103 + "app.main:app",
  104 + host='0.0.0.0',
  105 + port=settings.port,
  106 + reload=settings.debug,
  107 + )
  1 +from app.db import es_client
  2 +
1 [project] 1 [project]
2 name = "aigc-embedding-service" 2 name = "aigc-embedding-service"
3 version = "0.1.0" 3 version = "0.1.0"
4 -description = "Add your description here" 4 +description = "基于向量的CRUD服务,支持多种Embedding场景"
5 requires-python = ">=3.12" 5 requires-python = ">=3.12"
6 -dependencies = [] 6 +dependencies = [
  7 + "fastapi>=0.115.0",
  8 + "uvicorn[standard]>=0.32.0",
  9 + "pydantic>=2.9.0",
  10 + "pydantic-settings>=2.6.0",
  11 + "httpx>=0.27.0",
  12 + "python-multipart>=0.0.12",
  13 + "aabd>=0.4.1",
  14 + "path>=17.1.1",
  15 + "omegaconf>=2.3.0",
  16 +]
  17 +
  18 +[project.optional-dependencies]
  19 +dev = [
  20 + "pytest>=8.3.0",
  21 + "pytest-asyncio>=0.24.0",
  22 + "black>=24.10.0",
  23 + "ruff>=0.7.0",
  24 + "mypy>=1.13.0",
  25 +]
  26 +es = [
  27 + "elasticsearch>=8.15.0",
  28 +]
  29 +postgres = [
  30 + "psycopg[binary,pool]>=3.2.0",
  31 + "psycopg-pool>=3.3.0",
  32 +]
  33 +
  34 +[tool.black]
  35 +line-length = 100
  36 +target-version = ['py312']
  37 +
  38 +[tool.ruff]
  39 +line-length = 100
  40 +select = ["E", "F", "I", "N", "W", "UP", "B", "C4", "SIM"]
  41 +ignore = ["E501"]
  42 +
  43 +[tool.mypy]
  44 +python_version = "3.12"
  45 +warn_return_any = true
  46 +warn_unused_configs = true
  47 +disallow_untyped_defs = true
  48 +
  49 +[tool.pytest.ini_options]
  50 +asyncio_mode = "auto"
  51 +testpaths = ["tests"]
  52 +python_files = ["test_*.py"]
  53 +python_classes = ["Test*"]
  54 +python_functions = ["test_*"]
This diff could not be displayed because it is too large.