| Name | zheliku-tool JSON |
| Version |
0.1.4
JSON |
| download |
| home_page | None |
| Summary | Lightweight timing decorator & context manager with loguru-like formatting, sync/async. |
| upload_time | 2025-11-03 17:35:57 |
| maintainer | None |
| docs_url | None |
| author | zheliku |
| requires_python | >=3.12 |
| license | None |
| keywords |
logging
timer
performance
decorator
asyncio
|
| VCS |
 |
| bugtrack_url |
|
| requirements |
No requirements were recorded.
|
| Travis-CI |
No Travis.
|
| coveralls test coverage |
No coveralls.
|
# ⏱️ zheliku-tool
> 🔧 高精度 Python 函数计时与日志记录工具
> 基于标准库 `logging` 实现,兼容同步/异步函数、上下文管理器与滚动日志,
> 支持环境变量开关、loguru 风格格式、跨平台使用。
---
## 🌟 功能概述
`zheliku-tool` 提供了一个轻量级的计时装饰器与上下文管理器 `TimeLogger`,
让你可以一行代码轻松记录任意函数或代码块的执行耗时。
特点:
* ✅ 同步、异步函数统一支持
* ✅ 上下文管理器 (`with` / `async with`)
* ✅ 日志格式与 [loguru](https://github.com/Delgan/loguru) 兼容,带毫秒时间
* ✅ 自动创建日志目录,支持滚动文件
* ✅ 可通过环境变量一键开关
* ✅ 支持自定义文件名、日志目录与等级
* ✅ 提供片段计时器与函数式 API
* ✅ 无外部依赖,仅使用 Python 标准库
---
## 📦 安装
```bash
# 使用 uv(推荐)
uv add zheliku-tool
# 或使用 pip
pip install zheliku-tool
```
安装后导入:
```python
from zheliku_tool import TimeLogger, time_log
```
---
## 🧭 快速开始
### ✅ 1. 装饰器用法
```python
from zheliku_tool import TimeLogger
@TimeLogger(log_file="run.log")
def preprocess(data):
# 模拟耗时计算
import time;
time.sleep(0.02)
return [d ** 2 for d in data]
preprocess([1, 2, 3])
```
日志输出示例(默认格式):
```
2025-11-03 15:00:21.512 | INFO | __main__.preprocess:7 - Ran preprocess in 20.132 ms (module=__main__, file=example.py, abs='/path/example.py', line=7, pid=3901, thread=MainThread)
```
---
### ✅ 2. 异步函数
```python
import asyncio
from zheliku_tool import TimeLogger
@TimeLogger(log_file="async.log", level=logging.DEBUG)
async def fetch_data():
await asyncio.sleep(0.01)
return "done"
asyncio.run(fetch_data())
```
---
### ✅ 3. 上下文管理器
```python
from zheliku_tool import TimeLogger
with TimeLogger(logger_name="load_stage", log_file="stages.log"):
# 一段代码的耗时
sum(i * i for i in range(10_000))
```
异步上下文同理:
```python
async with TimeLogger(logger_name="async_stage", log_file="stages.log"):
await asyncio.sleep(0.05)
```
---
### ✅ 4. 函数式上下文 API(更简洁)
```python
from zheliku_tool import time_log
with time_log("evaluate", log_file="run.log"):
result = sum(range(1000))
```
等价于:
```python
with TimeLogger(logger_name="evaluate", log_file="run.log"):
result = sum(range(1000))
```
---
### ✅ 5. 手动片段计时(代码内部多段耗时)
```python
from zheliku_tool import TimeLogger
def train_step():
seg = TimeLogger.start("train")
# 执行部分任务
import time;
time.sleep(0.03)
elapsed = seg.stop()
print(f"train_step 耗时 {elapsed:.2f} ms")
```
---
## ⚙️ 参数说明
| 参数名 | 类型 | 默认值 | 说明 | |
|----------------|-----------------------|-----------------------|-----------------------------------------------|----------------------|
| `level` | `int` | `logging.INFO` | 日志等级(支持 `DEBUG/INFO/WARNING/ERROR`) | |
| `enable` | `bool` | `True` | 是否启用计时,`False` 时直接调用函数不记录 | |
| `log_dir` | `str \| Path` | `None` | 日志目录(未提供时自动取函数所在文件夹) |
| `log_file` | `str \| Path` | `None` | 日志文件路径,可相对/绝对 |
| `extra_msg` | `str` | `None` | 附加备注文本 | |
| `fmt` | `str` | 内置默认 | `logging` 输出格式 | |
| `datefmt` | `str` | `"%Y-%m-%d %H:%M:%S"` | 时间格式 | |
| `logger_name` | `str` | `None` | 自定义 logger 名(默认 `<module>.<qualname>:<line>`) | |
| `rotate` | `bool` | `False` | 是否使用滚动日志 | |
| `max_bytes` | `int` | `10*1024*1024` | 滚动阈值(字节) | |
| `backup_count` | `int` | `3` | 滚动保留文件数 | |
---
## 🧩 环境变量控制
> 所有环境变量均可在运行前通过 `export` 或 `.env` 文件设置。
> 优先级高于代码参数。
| 环境变量 | 说明 |
|---------------------------------------------------------|-----------------------------------|
| `TIME_LOG_ENABLE` / `TIMER_LOG_ENABLE` / `TIMER_ENABLE` | 是否启用日志(`0`、`false` 表示关闭) |
| `TIME_LOG_LEVEL` / `TIMER_LOG_LEVEL` / `TIMER_LEVEL` | 设置全局日志等级,如 `DEBUG`、`INFO`、`ERROR` |
### 示例:
```bash
export TIME_LOG_ENABLE=0 # 全局关闭日志
export TIMER_LOG_LEVEL=DEBUG
```
---
## 🧰 日志落地规则
1. 如果提供 `log_file`:
* **绝对路径**:直接使用;
* **相对路径**:基于 `log_dir`(若提供)或源文件目录。
2. 如果未提供 `log_file`:
* 自动生成 `<源文件同名>.log`;
* 目录为 `log_dir` 或源文件目录。
3. 会自动创建不存在的目录。
4. 同一路径复用同一个 `FileHandler`,不会重复写入。
---
## 📖 输出格式
默认格式(可自定义):
```
%(asctime)s.%(msecs)03d | %(levelname)-8s | %(name)s - %(message)s
```
对应输出示例:
```
2025-11-03 14:59:01.512 | INFO | mymodule.train:42 - Ran train in 14.832 ms (module=mymodule, file=train.py, abs='/project/train.py', line=42, pid=1234, thread=MainThread)
```
---
## 🚀 高级用法
### 🔄 滚动日志
自动切分日志文件,防止文件过大:
```python
@TimeLogger(log_file="pipeline.log", rotate=True, max_bytes=1024 * 100, backup_count=5)
def pipeline():
...
```
---
### 🔍 临时禁用
```python
@TimeLogger(enable=False)
def quick_func():
pass # 不会产生日志
```
---
### 🔧 动态控制(环境变量)
无需改代码,运行前即可启用/禁用:
```bash
TIME_LOG_ENABLE=0 uv run python your_script.py
```
---
### 🧠 线程/进程安全性
* 日志文件写入使用标准库 `FileHandler`;
* 同一 logger 不会重复绑定;
* 可在多线程下安全使用(每条日志独立写入)。
---
## 🧪 单元测试覆盖(pytest)
完整测试文件见 `tests/test_time_tool.py`,包括:
* 同步/异步装饰器
* 同步/异步上下文
* 路径解析
* 滚动日志
* 环境变量开关
* 重复 handler 检测
* 片段计时器
* 函数式上下文管理
运行测试:
```bash
uv run pytest -v
```
---
## 📜 许可证
MIT License © 2025 [zheliku](https://github.com/zheliku)
Raw data
{
"_id": null,
"home_page": null,
"name": "zheliku-tool",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.12",
"maintainer_email": null,
"keywords": "logging, timer, performance, decorator, asyncio",
"author": "zheliku",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/8d/ec/7e1e4663239160607e7ce3314ce8441e22c9f30a5a61ad32219b025c6f8e/zheliku_tool-0.1.4.tar.gz",
"platform": null,
"description": "# \u23f1\ufe0f zheliku-tool\n\n> \ud83d\udd27 \u9ad8\u7cbe\u5ea6 Python \u51fd\u6570\u8ba1\u65f6\u4e0e\u65e5\u5fd7\u8bb0\u5f55\u5de5\u5177\n> \u57fa\u4e8e\u6807\u51c6\u5e93 `logging` \u5b9e\u73b0\uff0c\u517c\u5bb9\u540c\u6b65/\u5f02\u6b65\u51fd\u6570\u3001\u4e0a\u4e0b\u6587\u7ba1\u7406\u5668\u4e0e\u6eda\u52a8\u65e5\u5fd7\uff0c\n> \u652f\u6301\u73af\u5883\u53d8\u91cf\u5f00\u5173\u3001loguru \u98ce\u683c\u683c\u5f0f\u3001\u8de8\u5e73\u53f0\u4f7f\u7528\u3002\n\n---\n\n## \ud83c\udf1f \u529f\u80fd\u6982\u8ff0\n\n`zheliku-tool` \u63d0\u4f9b\u4e86\u4e00\u4e2a\u8f7b\u91cf\u7ea7\u7684\u8ba1\u65f6\u88c5\u9970\u5668\u4e0e\u4e0a\u4e0b\u6587\u7ba1\u7406\u5668 `TimeLogger`\uff0c\n\u8ba9\u4f60\u53ef\u4ee5\u4e00\u884c\u4ee3\u7801\u8f7b\u677e\u8bb0\u5f55\u4efb\u610f\u51fd\u6570\u6216\u4ee3\u7801\u5757\u7684\u6267\u884c\u8017\u65f6\u3002\n\n\u7279\u70b9\uff1a\n\n* \u2705 \u540c\u6b65\u3001\u5f02\u6b65\u51fd\u6570\u7edf\u4e00\u652f\u6301\n* \u2705 \u4e0a\u4e0b\u6587\u7ba1\u7406\u5668 (`with` / `async with`)\n* \u2705 \u65e5\u5fd7\u683c\u5f0f\u4e0e [loguru](https://github.com/Delgan/loguru) \u517c\u5bb9\uff0c\u5e26\u6beb\u79d2\u65f6\u95f4\n* \u2705 \u81ea\u52a8\u521b\u5efa\u65e5\u5fd7\u76ee\u5f55\uff0c\u652f\u6301\u6eda\u52a8\u6587\u4ef6\n* \u2705 \u53ef\u901a\u8fc7\u73af\u5883\u53d8\u91cf\u4e00\u952e\u5f00\u5173\n* \u2705 \u652f\u6301\u81ea\u5b9a\u4e49\u6587\u4ef6\u540d\u3001\u65e5\u5fd7\u76ee\u5f55\u4e0e\u7b49\u7ea7\n* \u2705 \u63d0\u4f9b\u7247\u6bb5\u8ba1\u65f6\u5668\u4e0e\u51fd\u6570\u5f0f API\n* \u2705 \u65e0\u5916\u90e8\u4f9d\u8d56\uff0c\u4ec5\u4f7f\u7528 Python \u6807\u51c6\u5e93\n\n---\n\n## \ud83d\udce6 \u5b89\u88c5\n\n```bash\n# \u4f7f\u7528 uv\uff08\u63a8\u8350\uff09\nuv add zheliku-tool\n\n# \u6216\u4f7f\u7528 pip\npip install zheliku-tool\n```\n\n\u5b89\u88c5\u540e\u5bfc\u5165\uff1a\n\n```python\nfrom zheliku_tool import TimeLogger, time_log\n```\n\n---\n\n## \ud83e\udded \u5feb\u901f\u5f00\u59cb\n\n### \u2705 1. \u88c5\u9970\u5668\u7528\u6cd5\n\n```python\nfrom zheliku_tool import TimeLogger\n\n\n@TimeLogger(log_file=\"run.log\")\ndef preprocess(data):\n # \u6a21\u62df\u8017\u65f6\u8ba1\u7b97\n import time;\n time.sleep(0.02)\n return [d ** 2 for d in data]\n\n\npreprocess([1, 2, 3])\n```\n\n\u65e5\u5fd7\u8f93\u51fa\u793a\u4f8b\uff08\u9ed8\u8ba4\u683c\u5f0f\uff09\uff1a\n\n```\n2025-11-03 15:00:21.512 | INFO | __main__.preprocess:7 - Ran preprocess in 20.132 ms (module=__main__, file=example.py, abs='/path/example.py', line=7, pid=3901, thread=MainThread)\n```\n\n---\n\n### \u2705 2. \u5f02\u6b65\u51fd\u6570\n\n```python\nimport asyncio\nfrom zheliku_tool import TimeLogger\n\n\n@TimeLogger(log_file=\"async.log\", level=logging.DEBUG)\nasync def fetch_data():\n await asyncio.sleep(0.01)\n return \"done\"\n\n\nasyncio.run(fetch_data())\n```\n\n---\n\n### \u2705 3. \u4e0a\u4e0b\u6587\u7ba1\u7406\u5668\n\n```python\nfrom zheliku_tool import TimeLogger\n\nwith TimeLogger(logger_name=\"load_stage\", log_file=\"stages.log\"):\n # \u4e00\u6bb5\u4ee3\u7801\u7684\u8017\u65f6\n sum(i * i for i in range(10_000))\n```\n\n\u5f02\u6b65\u4e0a\u4e0b\u6587\u540c\u7406\uff1a\n\n```python\nasync with TimeLogger(logger_name=\"async_stage\", log_file=\"stages.log\"):\n await asyncio.sleep(0.05)\n```\n\n---\n\n### \u2705 4. \u51fd\u6570\u5f0f\u4e0a\u4e0b\u6587 API\uff08\u66f4\u7b80\u6d01\uff09\n\n```python\nfrom zheliku_tool import time_log\n\nwith time_log(\"evaluate\", log_file=\"run.log\"):\n result = sum(range(1000))\n```\n\n\u7b49\u4ef7\u4e8e\uff1a\n\n```python\nwith TimeLogger(logger_name=\"evaluate\", log_file=\"run.log\"):\n result = sum(range(1000))\n```\n\n---\n\n### \u2705 5. \u624b\u52a8\u7247\u6bb5\u8ba1\u65f6\uff08\u4ee3\u7801\u5185\u90e8\u591a\u6bb5\u8017\u65f6\uff09\n\n```python\nfrom zheliku_tool import TimeLogger\n\n\ndef train_step():\n seg = TimeLogger.start(\"train\")\n # \u6267\u884c\u90e8\u5206\u4efb\u52a1\n import time;\n time.sleep(0.03)\n elapsed = seg.stop()\n print(f\"train_step \u8017\u65f6 {elapsed:.2f} ms\")\n```\n\n---\n\n## \u2699\ufe0f \u53c2\u6570\u8bf4\u660e\n\n| \u53c2\u6570\u540d | \u7c7b\u578b | \u9ed8\u8ba4\u503c | \u8bf4\u660e | |\n|----------------|-----------------------|-----------------------|-----------------------------------------------|----------------------|\n| `level` | `int` | `logging.INFO` | \u65e5\u5fd7\u7b49\u7ea7\uff08\u652f\u6301 `DEBUG/INFO/WARNING/ERROR`\uff09 | |\n| `enable` | `bool` | `True` | \u662f\u5426\u542f\u7528\u8ba1\u65f6\uff0c`False` \u65f6\u76f4\u63a5\u8c03\u7528\u51fd\u6570\u4e0d\u8bb0\u5f55 | |\n| `log_dir` | `str \\| Path` | `None` | \u65e5\u5fd7\u76ee\u5f55\uff08\u672a\u63d0\u4f9b\u65f6\u81ea\u52a8\u53d6\u51fd\u6570\u6240\u5728\u6587\u4ef6\u5939\uff09 |\n| `log_file` | `str \\| Path` | `None` | \u65e5\u5fd7\u6587\u4ef6\u8def\u5f84\uff0c\u53ef\u76f8\u5bf9/\u7edd\u5bf9 |\n| `extra_msg` | `str` | `None` | \u9644\u52a0\u5907\u6ce8\u6587\u672c | |\n| `fmt` | `str` | \u5185\u7f6e\u9ed8\u8ba4 | `logging` \u8f93\u51fa\u683c\u5f0f | |\n| `datefmt` | `str` | `\"%Y-%m-%d %H:%M:%S\"` | \u65f6\u95f4\u683c\u5f0f | |\n| `logger_name` | `str` | `None` | \u81ea\u5b9a\u4e49 logger \u540d\uff08\u9ed8\u8ba4 `<module>.<qualname>:<line>`\uff09 | |\n| `rotate` | `bool` | `False` | \u662f\u5426\u4f7f\u7528\u6eda\u52a8\u65e5\u5fd7 | |\n| `max_bytes` | `int` | `10*1024*1024` | \u6eda\u52a8\u9608\u503c\uff08\u5b57\u8282\uff09 | |\n| `backup_count` | `int` | `3` | \u6eda\u52a8\u4fdd\u7559\u6587\u4ef6\u6570 | |\n\n---\n\n## \ud83e\udde9 \u73af\u5883\u53d8\u91cf\u63a7\u5236\n\n> \u6240\u6709\u73af\u5883\u53d8\u91cf\u5747\u53ef\u5728\u8fd0\u884c\u524d\u901a\u8fc7 `export` \u6216 `.env` \u6587\u4ef6\u8bbe\u7f6e\u3002\n> \u4f18\u5148\u7ea7\u9ad8\u4e8e\u4ee3\u7801\u53c2\u6570\u3002\n\n| \u73af\u5883\u53d8\u91cf | \u8bf4\u660e |\n|---------------------------------------------------------|-----------------------------------|\n| `TIME_LOG_ENABLE` / `TIMER_LOG_ENABLE` / `TIMER_ENABLE` | \u662f\u5426\u542f\u7528\u65e5\u5fd7\uff08`0`\u3001`false` \u8868\u793a\u5173\u95ed\uff09 |\n| `TIME_LOG_LEVEL` / `TIMER_LOG_LEVEL` / `TIMER_LEVEL` | \u8bbe\u7f6e\u5168\u5c40\u65e5\u5fd7\u7b49\u7ea7\uff0c\u5982 `DEBUG`\u3001`INFO`\u3001`ERROR` |\n\n### \u793a\u4f8b\uff1a\n\n```bash\nexport TIME_LOG_ENABLE=0 # \u5168\u5c40\u5173\u95ed\u65e5\u5fd7\nexport TIMER_LOG_LEVEL=DEBUG\n```\n\n---\n\n## \ud83e\uddf0 \u65e5\u5fd7\u843d\u5730\u89c4\u5219\n\n1. \u5982\u679c\u63d0\u4f9b `log_file`\uff1a\n\n * **\u7edd\u5bf9\u8def\u5f84**\uff1a\u76f4\u63a5\u4f7f\u7528\uff1b\n * **\u76f8\u5bf9\u8def\u5f84**\uff1a\u57fa\u4e8e `log_dir`\uff08\u82e5\u63d0\u4f9b\uff09\u6216\u6e90\u6587\u4ef6\u76ee\u5f55\u3002\n2. \u5982\u679c\u672a\u63d0\u4f9b `log_file`\uff1a\n\n * \u81ea\u52a8\u751f\u6210 `<\u6e90\u6587\u4ef6\u540c\u540d>.log`\uff1b\n * \u76ee\u5f55\u4e3a `log_dir` \u6216\u6e90\u6587\u4ef6\u76ee\u5f55\u3002\n3. \u4f1a\u81ea\u52a8\u521b\u5efa\u4e0d\u5b58\u5728\u7684\u76ee\u5f55\u3002\n4. \u540c\u4e00\u8def\u5f84\u590d\u7528\u540c\u4e00\u4e2a `FileHandler`\uff0c\u4e0d\u4f1a\u91cd\u590d\u5199\u5165\u3002\n\n---\n\n## \ud83d\udcd6 \u8f93\u51fa\u683c\u5f0f\n\n\u9ed8\u8ba4\u683c\u5f0f\uff08\u53ef\u81ea\u5b9a\u4e49\uff09\uff1a\n\n```\n%(asctime)s.%(msecs)03d | %(levelname)-8s | %(name)s - %(message)s\n```\n\n\u5bf9\u5e94\u8f93\u51fa\u793a\u4f8b\uff1a\n\n```\n2025-11-03 14:59:01.512 | INFO | mymodule.train:42 - Ran train in 14.832 ms (module=mymodule, file=train.py, abs='/project/train.py', line=42, pid=1234, thread=MainThread)\n```\n\n---\n\n## \ud83d\ude80 \u9ad8\u7ea7\u7528\u6cd5\n\n### \ud83d\udd04 \u6eda\u52a8\u65e5\u5fd7\n\n\u81ea\u52a8\u5207\u5206\u65e5\u5fd7\u6587\u4ef6\uff0c\u9632\u6b62\u6587\u4ef6\u8fc7\u5927\uff1a\n\n```python\n@TimeLogger(log_file=\"pipeline.log\", rotate=True, max_bytes=1024 * 100, backup_count=5)\ndef pipeline():\n ...\n```\n\n---\n\n### \ud83d\udd0d \u4e34\u65f6\u7981\u7528\n\n```python\n@TimeLogger(enable=False)\ndef quick_func():\n pass # \u4e0d\u4f1a\u4ea7\u751f\u65e5\u5fd7\n```\n\n---\n\n### \ud83d\udd27 \u52a8\u6001\u63a7\u5236\uff08\u73af\u5883\u53d8\u91cf\uff09\n\n\u65e0\u9700\u6539\u4ee3\u7801\uff0c\u8fd0\u884c\u524d\u5373\u53ef\u542f\u7528/\u7981\u7528\uff1a\n\n```bash\nTIME_LOG_ENABLE=0 uv run python your_script.py\n```\n\n---\n\n### \ud83e\udde0 \u7ebf\u7a0b/\u8fdb\u7a0b\u5b89\u5168\u6027\n\n* \u65e5\u5fd7\u6587\u4ef6\u5199\u5165\u4f7f\u7528\u6807\u51c6\u5e93 `FileHandler`\uff1b\n* \u540c\u4e00 logger \u4e0d\u4f1a\u91cd\u590d\u7ed1\u5b9a\uff1b\n* \u53ef\u5728\u591a\u7ebf\u7a0b\u4e0b\u5b89\u5168\u4f7f\u7528\uff08\u6bcf\u6761\u65e5\u5fd7\u72ec\u7acb\u5199\u5165\uff09\u3002\n\n---\n\n## \ud83e\uddea \u5355\u5143\u6d4b\u8bd5\u8986\u76d6\uff08pytest\uff09\n\n\u5b8c\u6574\u6d4b\u8bd5\u6587\u4ef6\u89c1 `tests/test_time_tool.py`\uff0c\u5305\u62ec\uff1a\n\n* \u540c\u6b65/\u5f02\u6b65\u88c5\u9970\u5668\n* \u540c\u6b65/\u5f02\u6b65\u4e0a\u4e0b\u6587\n* \u8def\u5f84\u89e3\u6790\n* \u6eda\u52a8\u65e5\u5fd7\n* \u73af\u5883\u53d8\u91cf\u5f00\u5173\n* \u91cd\u590d handler \u68c0\u6d4b\n* \u7247\u6bb5\u8ba1\u65f6\u5668\n* \u51fd\u6570\u5f0f\u4e0a\u4e0b\u6587\u7ba1\u7406\n\n\u8fd0\u884c\u6d4b\u8bd5\uff1a\n\n```bash\nuv run pytest -v\n```\n\n---\n\n## \ud83d\udcdc \u8bb8\u53ef\u8bc1\n\nMIT License \u00a9 2025 [zheliku](https://github.com/zheliku)\n\n",
"bugtrack_url": null,
"license": null,
"summary": "Lightweight timing decorator & context manager with loguru-like formatting, sync/async.",
"version": "0.1.4",
"project_urls": {
"Changelog": "https://github.com/zheliku/zheliku-tool/master/CHANGELOG.md",
"Homepage": "https://github.com/zheliku/zheliku-tool",
"Issues": "https://github.com/zheliku/zheliku-tool/issues",
"Repository": "https://github.com/zheliku/zheliku-tool.git"
},
"split_keywords": [
"logging",
" timer",
" performance",
" decorator",
" asyncio"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "ddb19adca4dade8dce8bd5f43737826fc309285747749c3d6395ee17c4259acf",
"md5": "a9b99a91d0730fd5bd5f94bb61843655",
"sha256": "53ee39c11feba0ebe7ebe9a0ec0ed015123ed8d888076cf26167eb3add950d49"
},
"downloads": -1,
"filename": "zheliku_tool-0.1.4-py3-none-any.whl",
"has_sig": false,
"md5_digest": "a9b99a91d0730fd5bd5f94bb61843655",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.12",
"size": 11227,
"upload_time": "2025-11-03T17:35:56",
"upload_time_iso_8601": "2025-11-03T17:35:56.623263Z",
"url": "https://files.pythonhosted.org/packages/dd/b1/9adca4dade8dce8bd5f43737826fc309285747749c3d6395ee17c4259acf/zheliku_tool-0.1.4-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "8dec7e1e4663239160607e7ce3314ce8441e22c9f30a5a61ad32219b025c6f8e",
"md5": "72b4f90ed4da6a4093197544a1cb8772",
"sha256": "05ea1c4288ca22363e4b4b114f77147ecbacd69a1da46581fb3f4ce560d3f79e"
},
"downloads": -1,
"filename": "zheliku_tool-0.1.4.tar.gz",
"has_sig": false,
"md5_digest": "72b4f90ed4da6a4093197544a1cb8772",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.12",
"size": 14671,
"upload_time": "2025-11-03T17:35:57",
"upload_time_iso_8601": "2025-11-03T17:35:57.600334Z",
"url": "https://files.pythonhosted.org/packages/8d/ec/7e1e4663239160607e7ce3314ce8441e22c9f30a5a61ad32219b025c6f8e/zheliku_tool-0.1.4.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-11-03 17:35:57",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "zheliku",
"github_project": "zheliku-tool",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "zheliku-tool"
}