🧑‍💻 使用 uv 管理项目 (#502)

* 🧑‍💻 使用 uv 管理项目

* 📝 更新 CONTRIBUTING.md

* 🔥 移除 Dependabot

*  修改默认安装的依赖组

* 💚 使用 uv 运行 CI

*  将特殊适配的适配器移动到 dev 依赖组

* 🚨 make mypy happy
This commit is contained in:
呵呵です
2024-10-27 18:46:46 +08:00
committed by GitHub
parent b2d5a1e729
commit 1d33872c9b
10 changed files with 3222 additions and 4520 deletions

View File

@@ -1,12 +0,0 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "pip" # See documentation for possible values
directory: "/" # Location of package manifests
target-branch: "main"
schedule:
interval: "daily"

View File

@@ -14,22 +14,23 @@ jobs:
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Install poetry - uses: astral-sh/setup-uv@v3
run: pipx install poetry name: Setup UV
shell: bash
- uses: actions/setup-python@v4
with: with:
python-version: '3.11' enable-cache: true
cache: "poetry"
- run: poetry install - name: "Set up Python"
uses: actions/setup-python@v5
with:
python-version-file: ".python-version"
- run: uv sync
shell: bash shell: bash
- name: Get Version - name: Get Version
id: version id: version
run: | run: |
echo "VERSION=$(poetry version -s)" >> $GITHUB_OUTPUT echo "VERSION=$(uvx pdm show --version)" >> $GITHUB_OUTPUT
echo "TAG_VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT echo "TAG_VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
echo "TAG_NAME=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT echo "TAG_NAME=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
@@ -38,10 +39,10 @@ jobs:
run: exit 1 run: exit 1
- name: Build Package - name: Build Package
run: poetry build run: uv build
- name: Publish Package to PyPI - name: Publish Package to PyPI
uses: pypa/gh-action-pypi-publish@release/v1 run: uv publish
- name: Publish Package to GitHub Release - name: Publish Package to GitHub Release
run: gh release create ${{ steps.version.outputs.TAG_NAME }} dist/*.tar.gz dist/*.whl -t "🔖 ${{ steps.version.outputs.TAG_NAME }}" --generate-notes run: gh release create ${{ steps.version.outputs.TAG_NAME }} dist/*.tar.gz dist/*.whl -t "🔖 ${{ steps.version.outputs.TAG_NAME }}" --generate-notes

View File

@@ -1,32 +1,33 @@
name: TypeCheck name: TypeCheck
on: on:
push: push:
jobs: jobs:
TypeCheck: TypeCheck:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Install poetry - uses: astral-sh/setup-uv@v3
run: pipx install poetry name: Setup UV
shell: bash with:
enable-cache: true
- uses: actions/setup-python@v5 - name: "Set up Python"
with: uses: actions/setup-python@v5
python-version: '3.10' with:
cache: 'poetry' python-version-file: ".python-version"
- run: poetry install - run: uv sync
shell: bash shell: bash
- name: Run Mypy - name: Run Mypy
shell: bash shell: bash
run: | run: |
poetry run mypy ./nonebot_plugin_tetris_stats uv run mypy ./nonebot_plugin_tetris_stats
- name: Run BasedPyright - name: Run BasedPyright
shell: bash shell: bash
run: | run: |
poetry run basedpyright ./nonebot_plugin_tetris_stats/ uv run basedpyright ./nonebot_plugin_tetris_stats/

1
.python-version Normal file
View File

@@ -0,0 +1 @@
3.10

View File

@@ -4,28 +4,19 @@
### For Developers with Basic Python Knowledge ### For Developers with Basic Python Knowledge
First, you need [Python **3.10**](https://www.python.org/) and [Poetry](https://python-poetry.org/). First, you need install [uv](https://docs.astral.sh/uv/).
Then, you need to clone this repository to your local machine using the `git clone` command, and install dependencies using `poetry install --sync`. Then:
### For Developers with Limited Python Knowledge
Here are **my recommended** best practices:
```bash ```bash
# Install uv
# Please refer to https://docs.astral.sh/uv/getting-started/installation/
# Set up the basic Python environment # Set up the basic Python environment
uv python install 3.10 uv python install 3.10
uv tool install poetry
# Clone the repository # Clone the repository
git clone https://github.com/A-Minos/nonebot-plugin-tetris-stats.git git clone https://github.com/A-Minos/nonebot-plugin-tetris-stats.git
cd nonebot-plugin-tetris-stats cd nonebot-plugin-tetris-stats
# Install dependencies # Install dependencies
uv run --no-project --python 3.10 poetry env use python uv sync
poetry install --sync
``` ```
## Development ## Development

View File

@@ -2,30 +2,19 @@
## 配置环境 ## 配置环境
### 对于有一定 Python 基础的开发者 首先你需要安装 [uv](https://docs.astral.sh/uv/)。
然后:
首先你需要 [Python **3.10**](https://www.python.org/) 以及 [Poetry](https://python-poetry.org/)。
然后你需要使用`git clone`命令将本仓库克隆到本地,然后使用`poetry install --sync`安装依赖。
### 对于基础不是很好的开发者
以下是**我认为的**最佳实践:
```bash ```bash
# 安装 uv
# 请参考 https://docs.astral.sh/uv/getting-started/installation/
# 配置基础 Python 环境 # 配置基础 Python 环境
uv python install 3.10 uv python install 3.10
uv tool install poetry
# 克隆仓库 # 克隆仓库
git clone https://github.com/A-Minos/nonebot-plugin-tetris-stats.git git clone https://github.com/A-Minos/nonebot-plugin-tetris-stats.git
cd nonebot-plugin-tetris-stats cd nonebot-plugin-tetris-stats
# 安装依赖 # 安装依赖
uv run --no-project --python 3.10 poetry env use python uv sync
poetry install --sync
``` ```
## 开发 ## 开发

View File

@@ -1,4 +1,3 @@
from functools import partial
from typing import Literal from typing import Literal
from nonebot.compat import PYDANTIC_V2 from nonebot.compat import PYDANTIC_V2
@@ -9,13 +8,9 @@ from ..base import SuccessModel
if PYDANTIC_V2: if PYDANTIC_V2:
from pydantic import field_validator from pydantic import field_validator
custom_validator = partial(field_validator, mode='before')
else: else:
from pydantic import validator from pydantic import validator
custom_validator = partial(validator, pre=True, always=True) # type: ignore[assignment, arg-type]
class PastInner(BaseModel): class PastInner(BaseModel):
season: str season: str
@@ -86,12 +81,23 @@ class NeverRatedData(BaseData):
percentile: Literal[-1] percentile: Literal[-1]
percentile_rank: Literal['z'] percentile_rank: Literal['z']
@custom_validator('apm', 'pps', 'vs') if PYDANTIC_V2:
@classmethod
def _(cls, value: float | None) -> float: @field_validator('apm', 'pps', 'vs', mode='before')
if value is None: @classmethod
return 0 def _(cls, value: float | None) -> float:
return value if value is None:
return 0
return value
else:
@validator('apm', 'pps', 'vs', pre=True, always=True)
@classmethod
def _(cls, value: float | None) -> float:
if value is None:
return 0
return value
class RatedData(BaseData): class RatedData(BaseData):

4318
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,145 +1,153 @@
[tool.poetry] [project]
name = 'nonebot-plugin-tetris-stats' name = "nonebot-plugin-tetris-stats"
version = "1.5.5" version = "1.5.5"
description = '一款基于 NoneBot2 的用于查询 Tetris 相关游戏数据的插件' description = "一款基于 NoneBot2 的用于查询 Tetris 相关游戏数据的插件"
authors = ['scdhh <wallfjjd@gmail.com>'] readme = "README.md"
readme = 'README.md' authors = [{ name = "shoucandanghehe", email = "wallfjjd@gmail.com" }]
homepage = 'https://github.com/shoucandanghehe/nonebot-plugin-tetris-stats' requires-python = ">=3.10"
repository = 'https://github.com/shoucandanghehe/nonebot-plugin-tetris-stats' dependencies = [
license = 'AGPL-3.0' "aiocache>=0.12.3",
"aiofiles>=24.1.0",
"arclet-alconna<2",
"async-lru>=2.0.4",
"httpx>=0.27.2",
"jinja2>=3.1.4",
"lxml>=5.3.0",
"msgspec>=0.18.6",
"nonebot-plugin-alconna>=0.53.1",
"nonebot-plugin-apscheduler>=0.5.0",
"nonebot-plugin-localstore>=0.7.1",
"nonebot-plugin-orm>=0.7.6",
"nonebot-plugin-session>=0.3.2",
"nonebot-plugin-session-orm>=0.2.0",
"nonebot-plugin-user>=0.4.4",
"nonebot-plugin-userinfo>=0.2.6",
"nonebot2[fastapi]>=2.3.3",
"pandas>=2.2.3",
"pillow>=11.0.0",
"playwright>=1.48.0",
"rich>=13.9.3",
"yarl>=1.16.0",
]
classifiers = [
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
]
keywords = ["nonebot2"]
[tool.poetry.dependencies] [project.urls]
python = '^3.10' Homepage = "https://github.com/A-Minos/nonebot-plugin-tetris-stats"
nonebot2 = { extras = ['fastapi'], version = '^2.3.0' } Repository = "https://github.com/A-Minos/nonebot-plugin-tetris-stats"
nonebot-plugin-alconna = '>=0.48.0' Issues = "https://github.com/A-Minos/nonebot-plugin-tetris-stats/issues"
nonebot-plugin-apscheduler = '>=0.4,<0.6'
nonebot-plugin-localstore = '>=0.6,<0.8'
nonebot-plugin-orm = '>=0.1.1,<0.8.0'
nonebot-plugin-session = '^0.3.1'
nonebot-plugin-session-orm = '^0.2.0'
nonebot-plugin-user = '>=0.2,<0.5'
nonebot-plugin-userinfo = '^0.2.4'
aiocache = '^0.12.2'
aiofiles = '>=23.2.1,<25.0.0'
arclet-alconna = '<2.0.0'
async-lru = '^2.0.4'
httpx = '^0.27.0'
jinja2 = '^3.1.3'
lxml = '^5.1.0'
msgspec = '^0.18.6'
pandas = '>=1.4.3,<3.0.0'
pillow = '>=10.3,<12.0'
playwright = '^1.41.2'
rich = '^13.7.1'
yarl = '^1.9.4'
[tool.poetry.group.dev.dependencies]
basedpyright = '^1.17.0'
mypy = '>=1.9'
pandas-stubs = '>=1.5.2,<3.0.0'
ruff = '>=0.3.0'
types-aiofiles = '>=23.2.0.20240106,<25.0.0.0'
types-lxml = '^2024.2.9'
types-pillow = '^10.2.0.20240423'
types-ujson = '^5.9.0'
nonebot2 = { extras = ['all'], version = '^2.3.0' }
nonebot-adapter-discord = '^0.1.3'
nonebot-adapter-kaiheila = '^0.3.4'
nonebot-adapter-onebot = '^2.4.1'
nonebot-adapter-qq = '^1.4.4'
nonebot-adapter-satori = '>=0.11.4,<0.13.0'
nonebot-plugin-orm = { extras = ['default'], version = '>=0.3,<0.8' }
[tool.poetry.group.debug.dependencies]
matplotlib = '^3.9.2'
memory-profiler = '^0.61.0'
objprint = '^0.2.2'
pyqt6 = '^6.7.1'
viztracer = '>=0.16.2,<0.18.0'
[build-system] [build-system]
requires = ['poetry-core>=1.0.0'] requires = ["hatchling"]
build-backend = 'poetry.core.masonry.api' build-backend = "hatchling.build"
[dependency-groups]
dev = [
"basedpyright>=1.19.1",
"mypy>=1.13.0",
"nonebot-adapter-discord>=0.1.8",
"nonebot-adapter-kaiheila>=0.3.4",
"nonebot-adapter-onebot>=2.4.6",
"nonebot-adapter-qq>=1.5.3",
"ruff>=0.7.1",
]
typecheck = [
"pandas-stubs>=2.2.3.241009",
"types-aiofiles>=24.1.0.20240626",
"types-lxml>=2024.9.16",
"types-pillow>=10.2.0.20240822",
]
test = ["nonebot-adapter-satori>=0.12.6", "nonebot-plugin-orm[default]>=0.7.6", "nonebot2[aiohttp,fastapi]>=2.3.3"]
debug = ["matplotlib>=3.9.2", "memory-profiler>=0.61.0", "objprint>=0.2.3", "pyqt6>=6.7.1", "viztracer>=0.17.0"]
[tool.uv]
default-groups = ["dev", "typecheck"]
[tool.ruff] [tool.ruff]
line-length = 120 line-length = 120
target-version = 'py310' target-version = "py310"
[tool.ruff.lint] [tool.ruff.lint]
select = [ select = [
'F', # pyflakes "F", # pyflakes
'E', # pycodestyle errors "E", # pycodestyle errors
'W', # pycodestyle warnings "W", # pycodestyle warnings
'C90', # mccabe "C90", # mccabe
'I', # isort "I", # isort
'N', # PEP8-naming "N", # PEP8-naming
'UP', # pyupgrade "UP", # pyupgrade
'YTT', # flake8-2020 "YTT", # flake8-2020
'ANN', # flake8-annotations "ANN", # flake8-annotations
'ASYNC', # flake8-async "ASYNC", # flake8-async
'S', # flake8-bandit "S", # flake8-bandit
'BLE', # flake8-blind-except "BLE", # flake8-blind-except
'FBT', # flake8-boolean-trap "FBT", # flake8-boolean-trap
'B', # flake8-bugbear "B", # flake8-bugbear
'A', # flake8-builtins "A", # flake8-builtins
'COM', # flake8-commas "COM", # flake8-commas
'C4', # flake8-comprehensions "C4", # flake8-comprehensions
'DTZ', # flake8-datetimez "DTZ", # flake8-datetimez
'T10', # flake8-debugger "T10", # flake8-debugger
'EM', # flake8-errmsg "EM", # flake8-errmsg
'FA', # flake8-future-annotations "FA", # flake8-future-annotations
'ISC', # flake8-implicit-str-concat "ISC", # flake8-implicit-str-concat
'ICN', # flake8-import-conventions "ICN", # flake8-import-conventions
'PIE', # flake8-pie "PIE", # flake8-pie
'T20', # flake8-print "T20", # flake8-print
'PYI', # flake8-pyi "PYI", # flake8-pyi
'Q', # flake8-quotes "Q", # flake8-quotes
'RSE', # flake8-raise "RSE", # flake8-raise
'RET', # flake8-return "RET", # flake8-return
'SLF', # flake8-self "SLF", # flake8-self
'SLOT', # flake8-slots "SLOT", # flake8-slots
'SIM', # flake8-simplify "SIM", # flake8-simplify
'TID', # flake8-tidy-imports "TID", # flake8-tidy-imports
'TCH', # flake8-type-checking "TCH", # flake8-type-checking
'ARG', # flake8-unused-arguments "ARG", # flake8-unused-arguments
'PTH', # flake8-use-pathlib "PTH", # flake8-use-pathlib
'ERA', # eradicate "ERA", # eradicate
'PD', # pandas-vet "PD", # pandas-vet
'PGH', # pygrep-hooks "PGH", # pygrep-hooks
'PL', # pylint "PL", # pylint
'TRY', # tryceratops "TRY", # tryceratops
'FLY', # flynt "FLY", # flynt
'FAST', # FastAPI "FAST", # FastAPI
'PERF', # Perflint "PERF", # Perflint
'FURB', # refurb "FURB", # refurb
'RUF', # Ruff-specific rules "RUF", # Ruff-specific rules
] ]
ignore = [ ignore = [
'E501', # 过长的行由 ruff format 处理, 剩余的都是字符串 "E501", # 过长的行由 ruff format 处理, 剩余的都是字符串
'ANN101', # 由 type checker 自动推断 "ANN101", # 由 type checker 自动推断
'ANN102', # 由 type checker 自动推断 "ANN102", # 由 type checker 自动推断
'ANN202', # 向 NoneBot 注册的函数 "ANN202", # 向 NoneBot 注册的函数
'TRY003', "TRY003",
'COM812', # 强制尾随逗号 "COM812", # 强制尾随逗号
'TID252', # 相对导入 "TID252", # 相对导入
'ISC001', # format warning "ISC001", # format warning
] ]
flake8-quotes = { inline-quotes = 'single', multiline-quotes = 'double' } flake8-quotes = { inline-quotes = "single", multiline-quotes = "double" }
[tool.ruff.lint.flake8-annotations] [tool.ruff.lint.flake8-annotations]
mypy-init-return = true mypy-init-return = true
[tool.ruff.lint.flake8-builtins] [tool.ruff.lint.flake8-builtins]
builtins-ignorelist = ['id'] builtins-ignorelist = ["id"]
[tool.ruff.format] [tool.ruff.format]
quote-style = 'single' quote-style = "single"
[tool.basedpyright] [tool.basedpyright]
pythonVersion = '3.10' pythonVersion = "3.10"
pythonPlatform = 'All' pythonPlatform = "All"
defineConstant = { PYDANTIC_V2 = true } defineConstant = { PYDANTIC_V2 = true }
typeCheckingMode = 'standard' typeCheckingMode = "standard"
[tool.nonebot] [tool.nonebot]
plugins = ['nonebot_plugin_tetris_stats'] plugins = ["nonebot_plugin_tetris_stats"]

3035
uv.lock generated Normal file

File diff suppressed because it is too large Load Diff