Metadata-Version: 2.1
Name: huidevkit
Version: 0.6.3
Summary: Practical Python development tools
Home-page: https://github.com/HuiDBK/py-tools
Author: hui
Author-email: huidbk@163.com
License: Apache
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: loguru<0.8,>=0.7.0
Requires-Dist: pydantic<3,>=2.1.1
Requires-Dist: pydantic-settings<3,>=2.1.0
Requires-Dist: PyYAML<7,>=6
Requires-Dist: asgiref==3.8.1
Requires-Dist: nest_asyncio==1.6.0
Requires-Dist: tqdm==4.66.4
Requires-Dist: python-dateutil==2.8.2
Requires-Dist: requests>=2.31.0
Requires-Dist: aiohttp>=3.9.5
Requires-Dist: cacheout==0.14.1
Requires-Dist: aiofiles==24.1.0
Requires-Dist: python-jose==3.3.0
Requires-Dist: pillow==11.1.0
Provides-Extra: db-orm
Requires-Dist: sqlalchemy[asyncio]==2.0.20; extra == "db-orm"
Requires-Dist: aiomysql==0.2.0; extra == "db-orm"
Provides-Extra: db-redis
Requires-Dist: redis>=4.5.4; extra == "db-redis"
Provides-Extra: cache-proxy
Requires-Dist: redis>=4.5.4; extra == "cache-proxy"
Requires-Dist: python-memcached==1.62; extra == "cache-proxy"
Requires-Dist: cacheout==0.14.1; extra == "cache-proxy"
Provides-Extra: minio
Requires-Dist: minio==7.1.17; extra == "minio"
Provides-Extra: excel-tools
Requires-Dist: pandas==2.0.3; extra == "excel-tools"
Requires-Dist: openpyxl==3.0.10; extra == "excel-tools"
Provides-Extra: all
Requires-Dist: loguru<0.8,>=0.7.0; extra == "all"
Requires-Dist: asgiref==3.8.1; extra == "all"
Requires-Dist: PyYAML<7,>=6; extra == "all"
Requires-Dist: pydantic<3,>=2.1.1; extra == "all"
Requires-Dist: nest_asyncio==1.6.0; extra == "all"
Requires-Dist: python-jose==3.3.0; extra == "all"
Requires-Dist: tqdm==4.66.4; extra == "all"
Requires-Dist: aiohttp>=3.9.5; extra == "all"
Requires-Dist: aiomysql==0.2.0; extra == "all"
Requires-Dist: pydantic-settings<3,>=2.1.0; extra == "all"
Requires-Dist: redis>=4.5.4; extra == "all"
Requires-Dist: pandas==2.0.3; extra == "all"
Requires-Dist: python-memcached==1.62; extra == "all"
Requires-Dist: aiofiles==24.1.0; extra == "all"
Requires-Dist: minio==7.1.17; extra == "all"
Requires-Dist: requests>=2.31.0; extra == "all"
Requires-Dist: openpyxl==3.0.10; extra == "all"
Requires-Dist: sqlalchemy[asyncio]==2.0.20; extra == "all"
Requires-Dist: pillow==11.1.0; extra == "all"
Requires-Dist: cacheout==0.14.1; extra == "all"
Requires-Dist: python-dateutil==2.8.2; extra == "all"
Provides-Extra: test
Requires-Dist: pytest==7.3.1; extra == "test"

# Py-Tools

Py-Tools 是一个面向 Python 开发者的实用工具集和可复用组件库，重点解决项目初始化和日常开发里高频、重复、容易写散的基础问题。

适合需要统一配置、日志、HTTP 调用和数据库 CRUD 基础封装的 Python 项目。

设计细节可参考掘金专栏：https://juejin.cn/column/7131286129713610766

## 安装

- Python 版本：`>= 3.9`
- 发布包名：`huidevkit`
- 历史版本记录：https://pypi.org/project/huidevkit/#history

> 从 `0.6.0` 开始，包名由 `hui-tools` 调整为 `huidevkit`。历史包名仍可安装，但不再推荐继续使用。

默认安装：

```bash
pip install huidevkit
```

按需安装：

```bash
pip install huidevkit[db-orm, db-redis, excel-tools]
```

全部能力：

```bash
pip install huidevkit[all]
```

## 主要能力

- `py_tools.logging`：基于 `loguru` 的日志初始化与默认配置
- `py_tools.utils.ConfigUtil`：统一读取环境变量、`.env`、YAML 和 Settings
- `py_tools.connections.http`：同步 / 异步 HTTP 客户端、上传文件、流式读取
- `py_tools.connections.db.mysql`：基于 SQLAlchemy 的数据库管理与常见 CRUD 封装
- `py_tools.utils.AsyncUtil`：同步异步互转、后台任务执行
- `py_tools.utils`：时间、文件、JWT、编码、序列化、树结构等通用工具

顶层 `py_tools` 包默认不聚合所有子模块，请从对应子模块导入。

## 常用示例

README 只保留最常用、最能体现封装价值的示例。

### 1. 快速初始化项目日志

```python
from py_tools.constants import BASE_DIR
from py_tools.logging import logger, setup_logging


setup_logging(log_dir=BASE_DIR / "logs")
logger.info("service started")
logger.error("something happened")
```

对应示例：[demo/logging/logging_demo.py](demo/logging/logging_demo.py)

### 2. 统一读取配置

```python
from pydantic_settings import SettingsConfigDict

from py_tools.utils import BaseConfigSettings, ConfigUtil


class AppSettings(BaseConfigSettings):
    app_name: str = "py-tools-demo"
    app_port: int = 8000
    debug: bool = False

    model_config = SettingsConfigDict(env_prefix="", env_file=".env", extra="ignore")


settings = ConfigUtil.load_merged_settings(
    AppSettings,
    yaml_file="config.yaml",
    env_file=".env",
    app_name="runtime-app",
)
print(settings.model_dump())
```

默认优先级：

`显式传参(kwargs) > 环境变量 > .env > yaml > 默认值`

对应示例：[demo/utils/config_util_demo.py](demo/utils/config_util_demo.py)

### 3. HTTP 客户端

```python
import asyncio

from py_tools.connections.http import AsyncHttpClient


async def main():
    url = "https://juejin.cn/"

    resp = await AsyncHttpClient().get(url).execute()
    text_data = await AsyncHttpClient().get(url, params={"test": "hui"}).text()
    json_data = await AsyncHttpClient().post(url, data={"test": "hui"}).json()
    byte_data = await AsyncHttpClient().get(url).bytes()

    print(text_data)
    print(resp.status)
    print(json_data)
    print(byte_data[:10])

    async for chunk in AsyncHttpClient().get(url).stream(chunk_size=512):
        print(chunk)
        break


asyncio.run(main())
```

对应示例：[demo/connections/http_client_demo.py](demo/connections/http_client_demo.py)

上传文件：

```python
import asyncio

from py_tools.connections.http import AsyncHttpClient


async def main():
    upload_file_ret = await AsyncHttpClient().upload_file(
        "https://httpbin.org/post",
        file="test.txt",
    ).json()
    print(upload_file_ret)


asyncio.run(main())
```

### 4. 数据库 CRUD 封装

```python
import asyncio

from sqlalchemy import String
from sqlalchemy.orm import Mapped, mapped_column

from py_tools.connections.db.mysql import BaseOrmTable, DBManager, SQLAlchemyManager


class UserFileTable(BaseOrmTable):
    __tablename__ = "user_file"

    filename: Mapped[str] = mapped_column(String(100), default="")
    oss_key: Mapped[str] = mapped_column(String(100), default="")


class UserFileManager(DBManager):
    orm_table = UserFileTable


db_client = SQLAlchemyManager(
    host="127.0.0.1",
    port=3306,
    user="root",
    password="123456",
    db_name="db_demo",
)


async def main():
    db_client.init_mysql_engine()
    DBManager.init_db_client(db_client)

    file_id = await UserFileManager().add({"filename": "demo.txt", "oss_key": "demo-key"})
    file_obj = await UserFileManager().query_by_id(file_id)
    file_list = await UserFileManager().query_all(cols=["id", "filename", "oss_key"])

    await UserFileManager().update(
        values={"filename": "demo-updated.txt"},
        conds=[UserFileTable.id == file_id],
    )
    await UserFileManager().delete_by_id(file_id)

    print(file_obj)
    print(file_list)


asyncio.run(main())
```

对应示例：

- [demo/connections/sqlalchemy_demo/demo.py](demo/connections/sqlalchemy_demo/demo.py)
- [demo/connections/sqlalchemy_demo/manager.py](demo/connections/sqlalchemy_demo/manager.py)
- [demo/connections/sqlalchemy_demo/table.py](demo/connections/sqlalchemy_demo/table.py)

## 更多示例

示例统一放在 `demo/` 目录，避免文档示例与代码示例重复维护。

- 示例索引：[demo/README.md](demo/README.md)
- Async 工具：[demo/utils/async_util_demo.py](demo/utils/async_util_demo.py)
- WebSocket：[demo/connections/websocket_demo.py](demo/connections/websocket_demo.py)
- FastAPI WebSocket：[demo/connections/fastapi_websocket_demo.py](demo/connections/fastapi_websocket_demo.py)
- 编码工具：[demo/utils/encode_util_demo.py](demo/utils/encode_util_demo.py)

## 开发与验证

```bash
pip install -e .[test]
python -m pytest -q
ruff check .
```

## 贡献

1. Fork 并克隆仓库
2. 安装依赖
3. 运行测试与静态检查
4. 提交 Pull Request
