use ruff lint and fmt code

This commit is contained in:
涵曦 2024-06-14 01:58:10 +00:00
parent e484164fad
commit 88f0ce7e51
7 changed files with 142 additions and 63 deletions

View File

@ -2,10 +2,10 @@
# It is not intended for manual editing.
[metadata]
groups = ["default"]
groups = ["default", "lint"]
strategy = ["cross_platform"]
lock_version = "4.4.1"
content_hash = "sha256:d771311a452ca58665efe3b74af341cb202d75d83a250896c293ea9c696e5696"
content_hash = "sha256:fa83f8134ccb4a432304dead5fe1303899418558634abaa0824e8d9fdfb1f490"
[[package]]
name = "aiohttp"
@ -648,6 +648,31 @@ files = [
{file = "rich-13.7.1.tar.gz", hash = "sha256:9be308cb1fe2f1f57d67ce99e95af38a1e2bc71ad9813b0e247cf7ffbcc3a432"},
]
[[package]]
name = "ruff"
version = "0.4.8"
requires_python = ">=3.7"
summary = "An extremely fast Python linter and code formatter, written in Rust."
files = [
{file = "ruff-0.4.8-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:7663a6d78f6adb0eab270fa9cf1ff2d28618ca3a652b60f2a234d92b9ec89066"},
{file = "ruff-0.4.8-py3-none-macosx_11_0_arm64.whl", hash = "sha256:eeceb78da8afb6de0ddada93112869852d04f1cd0f6b80fe464fd4e35c330913"},
{file = "ruff-0.4.8-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aad360893e92486662ef3be0a339c5ca3c1b109e0134fcd37d534d4be9fb8de3"},
{file = "ruff-0.4.8-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:284c2e3f3396fb05f5f803c9fffb53ebbe09a3ebe7dda2929ed8d73ded736deb"},
{file = "ruff-0.4.8-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7354f921e3fbe04d2a62d46707e569f9315e1a613307f7311a935743c51a764"},
{file = "ruff-0.4.8-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:72584676164e15a68a15778fd1b17c28a519e7a0622161eb2debdcdabdc71883"},
{file = "ruff-0.4.8-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9678d5c9b43315f323af2233a04d747409d1e3aa6789620083a82d1066a35199"},
{file = "ruff-0.4.8-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704977a658131651a22b5ebeb28b717ef42ac6ee3b11e91dc87b633b5d83142b"},
{file = "ruff-0.4.8-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d05f8d6f0c3cce5026cecd83b7a143dcad503045857bc49662f736437380ad45"},
{file = "ruff-0.4.8-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:6ea874950daca5697309d976c9afba830d3bf0ed66887481d6bca1673fc5b66a"},
{file = "ruff-0.4.8-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:fc95aac2943ddf360376be9aa3107c8cf9640083940a8c5bd824be692d2216dc"},
{file = "ruff-0.4.8-py3-none-musllinux_1_2_i686.whl", hash = "sha256:384154a1c3f4bf537bac69f33720957ee49ac8d484bfc91720cc94172026ceed"},
{file = "ruff-0.4.8-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e9d5ce97cacc99878aa0d084c626a15cd21e6b3d53fd6f9112b7fc485918e1fa"},
{file = "ruff-0.4.8-py3-none-win32.whl", hash = "sha256:6d795d7639212c2dfd01991259460101c22aabf420d9b943f153ab9d9706e6a9"},
{file = "ruff-0.4.8-py3-none-win_amd64.whl", hash = "sha256:e14a3a095d07560a9d6769a72f781d73259655919d9b396c650fc98a8157555d"},
{file = "ruff-0.4.8-py3-none-win_arm64.whl", hash = "sha256:14019a06dbe29b608f6b7cbcec300e3170a8d86efaddb7b23405cb7f7dcaf780"},
{file = "ruff-0.4.8.tar.gz", hash = "sha256:16d717b1d57b2e2fd68bd0bf80fb43931b79d05a7131aa477d66fc40fbd86268"},
]
[[package]]
name = "typing-extensions"
version = "4.9.0"

View File

@ -24,3 +24,29 @@ requires = ["pdm-backend"]
build-backend = "pdm.backend"
[tool.pdm]
[tool.pdm.dev-dependencies]
lint = [
"ruff>=0.4.8",
]
[tool.ruff]
select = [
"B", # flake8-bugbear
"C4", # flake8-comprehensions
"E", # pycodestyle - Error
"F", # Pyflakes
"I", # isort
"W", # pycodestyle - Warning
"UP", # pyupgrade
]
ignore = [
"E501", # line-too-long
"W191", # tab-indentation
]
include = ["**/*.py", "**/*.pyi", "**/pyproject.toml"]
[tool.ruff.pydocstyle]
convention = "google"
[tool.pdm.scripts]
lint = "ruff check ."
fmt = "ruff format ."

View File

@ -374,6 +374,24 @@ requests==2.31.0 \
rich==13.7.1 \
--hash=sha256:4edbae314f59eb482f54e9e30bf00d33350aaa94f4bfcd4e9e3110e64d0d7222 \
--hash=sha256:9be308cb1fe2f1f57d67ce99e95af38a1e2bc71ad9813b0e247cf7ffbcc3a432
ruff==0.4.8 \
--hash=sha256:14019a06dbe29b608f6b7cbcec300e3170a8d86efaddb7b23405cb7f7dcaf780 \
--hash=sha256:16d717b1d57b2e2fd68bd0bf80fb43931b79d05a7131aa477d66fc40fbd86268 \
--hash=sha256:284c2e3f3396fb05f5f803c9fffb53ebbe09a3ebe7dda2929ed8d73ded736deb \
--hash=sha256:384154a1c3f4bf537bac69f33720957ee49ac8d484bfc91720cc94172026ceed \
--hash=sha256:6d795d7639212c2dfd01991259460101c22aabf420d9b943f153ab9d9706e6a9 \
--hash=sha256:6ea874950daca5697309d976c9afba830d3bf0ed66887481d6bca1673fc5b66a \
--hash=sha256:704977a658131651a22b5ebeb28b717ef42ac6ee3b11e91dc87b633b5d83142b \
--hash=sha256:72584676164e15a68a15778fd1b17c28a519e7a0622161eb2debdcdabdc71883 \
--hash=sha256:7663a6d78f6adb0eab270fa9cf1ff2d28618ca3a652b60f2a234d92b9ec89066 \
--hash=sha256:9678d5c9b43315f323af2233a04d747409d1e3aa6789620083a82d1066a35199 \
--hash=sha256:a7354f921e3fbe04d2a62d46707e569f9315e1a613307f7311a935743c51a764 \
--hash=sha256:aad360893e92486662ef3be0a339c5ca3c1b109e0134fcd37d534d4be9fb8de3 \
--hash=sha256:d05f8d6f0c3cce5026cecd83b7a143dcad503045857bc49662f736437380ad45 \
--hash=sha256:e14a3a095d07560a9d6769a72f781d73259655919d9b396c650fc98a8157555d \
--hash=sha256:e9d5ce97cacc99878aa0d084c626a15cd21e6b3d53fd6f9112b7fc485918e1fa \
--hash=sha256:eeceb78da8afb6de0ddada93112869852d04f1cd0f6b80fe464fd4e35c330913 \
--hash=sha256:fc95aac2943ddf360376be9aa3107c8cf9640083940a8c5bd824be692d2216dc
typing-extensions==4.9.0; python_version < "3.11" \
--hash=sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783 \
--hash=sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd

View File

@ -3,8 +3,7 @@ from __future__ import annotations
import argparse
import json
import os
from dataclasses import dataclass, field
from typing import Any, Iterable
from dataclasses import dataclass
from xiaomusic.utils import validate_proxy
@ -13,7 +12,7 @@ COOKIE_TEMPLATE = "deviceId={device_id}; serviceToken={service_token}; userId={u
HARDWARE_COMMAND_DICT = {
# hardware: (tts_command, wakeup_command, volume_command)
"LX06": ("5-1", "5-5", "2-1"),
"L05B": ("5-3", "5-4", "2-1"),
"L05B": ("5-3", "5-4", "2-1"),
"S12": ("5-1", "5-5", "2-1"), # 第一代小爱型号MDZ-25-DA
"S12A": ("5-1", "5-5", "2-1"),
"LX01": ("5-1", "5-5", "2-1"),

View File

@ -1,25 +1,21 @@
#!/usr/bin/env python3
import os
import sys
import traceback
import asyncio
from threading import Thread
from flask import Flask, request, send_from_directory
from waitress import serve
from threading import Thread
from xiaomusic.config import (
KEY_WORD_DICT,
)
from xiaomusic import (
__version__,
)
from xiaomusic.config import (
KEY_WORD_DICT,
)
# 隐藏 flask 启动告警
# https://gist.github.com/jerblack/735b9953ba1ab6234abb43174210d356
#from flask import cli
#cli.show_server_banner = lambda *_: None
# from flask import cli
# cli.show_server_banner = lambda *_: None
app = Flask(__name__)
host = "0.0.0.0"
@ -33,6 +29,7 @@ log = None
def allcmds():
return KEY_WORD_DICT
@app.route("/getversion", methods=["GET"])
def getversion():
log.debug("getversion %s", __version__)
@ -40,6 +37,7 @@ def getversion():
"version": __version__,
}
@app.route("/getvolume", methods=["GET"])
def getvolume():
volume = xiaomusic.get_volume_ret()
@ -47,15 +45,18 @@ def getvolume():
"volume": volume,
}
@app.route("/searchmusic", methods=["GET"])
def searchmusic():
name = request.args.get('name')
name = request.args.get("name")
return xiaomusic.searchmusic(name)
@app.route("/playingmusic", methods=["GET"])
def playingmusic():
return xiaomusic.playingmusic()
@app.route("/", methods=["GET"])
def redirect_to_index():
return send_from_directory("static", "index.html")
@ -71,6 +72,7 @@ async def do_cmd():
return {"ret": "OK"}
return {"ret": "Unknow cmd"}
@app.route("/getsetting", methods=["GET"])
async def getsetting():
config = xiaomusic.getconfig()
@ -88,6 +90,7 @@ async def getsetting():
}
return data
@app.route("/savesetting", methods=["POST"])
async def savesetting():
data = request.get_json()
@ -95,14 +98,17 @@ async def savesetting():
await xiaomusic.saveconfig(data)
return "save success"
@app.route("/musiclist", methods=["GET"])
async def musiclist():
return xiaomusic.get_music_list()
@app.route("/curplaylist", methods=["GET"])
async def curplaylist():
return xiaomusic.get_cur_play_list()
def static_path_handler(filename):
log.debug(filename)
log.debug(static_path)
@ -110,9 +116,11 @@ def static_path_handler(filename):
log.debug(absolute_path)
return send_from_directory(absolute_path, filename)
def run_app():
serve(app, host=host, port=port)
def StartHTTPServer(_port, _static_path, _xiaomusic):
global port, static_path, xiaomusic, log
port = _port

View File

@ -1,13 +1,11 @@
#!/usr/bin/env python3
from __future__ import annotations
import os
import re
import socket
from http.cookies import SimpleCookie
from typing import AsyncIterator
from urllib.parse import urlparse
import difflib
import re
from collections.abc import AsyncIterator
from http.cookies import SimpleCookie
from urllib.parse import urlparse
from requests.utils import cookiejar_from_dict
@ -62,6 +60,7 @@ def validate_proxy(proxy_str: str) -> bool:
return True
# 模糊搜索
def fuzzyfinder(user_input, collection):
return difflib.get_close_matches(user_input, collection, 10, cutoff=0.1)

View File

@ -3,45 +3,43 @@ import asyncio
import json
import logging
import os
import queue
import random
import re
import time
import urllib.parse
import traceback
import mutagen
import queue
from xiaomusic.httpserver import StartHTTPServer
import urllib.parse
from pathlib import Path
import mutagen
from aiohttp import ClientSession, ClientTimeout
from miservice import MiAccount, MiIOService, MiNAService, miio_command
from rich import print
from rich.logging import RichHandler
from xiaomusic.config import (
COOKIE_TEMPLATE,
LATEST_ASK_API,
KEY_WORD_DICT,
KEY_WORD_ARG_BEFORE_DICT,
KEY_MATCH_ORDER,
SUPPORT_MUSIC_TYPE,
Config,
)
from xiaomusic.utils import (
parse_cookie_string,
fuzzyfinder,
)
from xiaomusic import (
__version__,
)
from xiaomusic.config import (
COOKIE_TEMPLATE,
KEY_MATCH_ORDER,
KEY_WORD_ARG_BEFORE_DICT,
KEY_WORD_DICT,
LATEST_ASK_API,
SUPPORT_MUSIC_TYPE,
Config,
)
from xiaomusic.httpserver import StartHTTPServer
from xiaomusic.utils import (
fuzzyfinder,
parse_cookie_string,
)
EOF = object()
PLAY_TYPE_ONE = 0 # 单曲循环
PLAY_TYPE_ALL = 1 # 全部循环
class XiaoMusic:
def __init__(self, config: Config):
self.config = config
@ -76,7 +74,7 @@ class XiaoMusic:
self._all_music = {}
self._play_list = []
self._cur_play_list = ""
self._music_list = {} # 播放列表 key 为目录名, value 为 play_list
self._music_list = {} # 播放列表 key 为目录名, value 为 play_list
self._playing = False
# 关机定时器
@ -86,7 +84,7 @@ class XiaoMusic:
logging.basicConfig(
format=f"[{__version__}]\t%(message)s",
datefmt="[%X]",
handlers=[RichHandler(rich_tracebacks=True)]
handlers=[RichHandler(rich_tracebacks=True)],
)
self.log = logging.getLogger("xiaomusic")
self.log.setLevel(logging.DEBUG if config.verbose else logging.INFO)
@ -290,7 +288,10 @@ class XiaoMusic:
def is_downloading(self):
if not self.download_proc:
return False
if self.download_proc.returncode != None and self.download_proc.returncode < 0:
if (
self.download_proc.returncode is not None
and self.download_proc.returncode < 0
):
return False
return True
@ -379,7 +380,7 @@ class XiaoMusic:
self._music_list = {}
self._music_list["全部"] = self._play_list
for dir_name,musics in all_music_by_dir.items():
for dir_name, musics in all_music_by_dir.items():
self._music_list[dir_name] = list(musics.keys())
self.log.debug("dir_name:%s, list:%s", dir_name, self._music_list[dir_name])
pass
@ -396,7 +397,7 @@ class XiaoMusic:
def get_next_music(self):
play_list_len = len(self._play_list)
if play_list_len == 0:
self.log.warning(f"没有随机到歌曲")
self.log.warning("没有随机到歌曲")
return ""
# 随机选择一个文件
index = 0
@ -411,7 +412,7 @@ class XiaoMusic:
filename = self.get_filename(name)
if len(filename) <= 0:
self._play_list.pop(next_index)
self.log.info(f'pop not exist music:{name}')
self.log.info(f"pop not exist music:{name}")
return self.get_next_music()
return name
@ -430,7 +431,7 @@ class XiaoMusic:
self.log.info(f"歌曲 {self.cur_music} : {filename} 的时长 {sec}")
if self._next_timer:
self._next_timer.cancel()
self.log.info(f"定时器已取消")
self.log.info("定时器已取消")
self._timeout = sec
async def _do_next():
@ -450,11 +451,11 @@ class XiaoMusic:
await self.init_all_data(session)
task = asyncio.create_task(self.poll_latest_ask())
assert task is not None # to keep the reference to task, do not remove this
filtered_keywords = [keyword for keyword in KEY_MATCH_ORDER if "#" not in keyword]
filtered_keywords = [
keyword for keyword in KEY_MATCH_ORDER if "#" not in keyword
]
joined_keywords = "/".join(filtered_keywords)
self.log.info(
f"Running xiaomusic now, 用`{joined_keywords}`开头来控制"
)
self.log.info(f"Running xiaomusic now, 用`{joined_keywords}`开头来控制")
while True:
self.polling_event.set()
@ -561,30 +562,30 @@ class XiaoMusic:
if self.play_type == PLAY_TYPE_ALL or name == "":
name = self.get_next_music()
if name == "":
await self.do_tts(f"本地没有歌曲")
await self.do_tts("本地没有歌曲")
return
await self.play(arg1=name)
# 单曲循环
async def set_play_type_one(self, **kwargs):
self.play_type = PLAY_TYPE_ONE
await self.do_tts(f"已经设置为单曲循环")
await self.do_tts("已经设置为单曲循环")
# 全部循环
async def set_play_type_all(self, **kwargs):
self.play_type = PLAY_TYPE_ALL
await self.do_tts(f"已经设置为全部循环")
await self.do_tts("已经设置为全部循环")
# 随机播放
async def random_play(self, **kwargs):
self.play_type = PLAY_TYPE_ALL
random.shuffle(self._play_list)
await self.do_tts(f"已经设置为随机播放")
await self.do_tts("已经设置为随机播放")
# 刷新列表
async def gen_music_list(self, **kwargs):
self._gen_all_music_list()
await self.do_tts(f"生成播放列表完毕")
await self.do_tts("生成播放列表完毕")
# 播放一个播放列表
async def play_music_list(self, **kwargs):
@ -608,14 +609,14 @@ class XiaoMusic:
self._playing = False
if self._next_timer:
self._next_timer.cancel()
self.log.info(f"定时器已取消")
self.log.info("定时器已取消")
self.cur_music = ""
await self.force_stop_xiaoai()
async def stop_after_minute(self, **kwargs):
if self._stop_timer:
self._stop_timer.cancel()
self.log.info(f"关机定时器已取消")
self.log.info("关机定时器已取消")
minute = int(kwargs["arg1"])
async def _do_stop():
@ -635,7 +636,9 @@ class XiaoMusic:
async def get_volume(self, **kwargs):
playing_info = await self.mina_service.player_get_status(self.device_id)
self.log.debug("get_volume. playing_info:%s", playing_info)
self._volume = json.loads(playing_info.get("data", {}).get("info", "{}")).get("volume", 5)
self._volume = json.loads(playing_info.get("data", {}).get("info", "{}")).get(
"volume", 5
)
self.log.info("get_volume. volume:%s", self._volume)
def get_volume_ret(self):
@ -680,7 +683,7 @@ class XiaoMusic:
async def saveconfig(self, data):
# 默认暂时配置保存到 music 目录下
filename = os.path.join(self.music_path, "setting.json")
with open(filename, 'w', encoding='utf-8') as f:
with open(filename, "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=4)
self.update_config_from_setting(data)
await self.call_main_thread_function(self.reinit)
@ -725,12 +728,13 @@ class XiaoMusic:
async def call_main_thread_function(self, func, arg1=None):
loop = asyncio.get_event_loop()
future = loop.create_future()
def callback(ret):
nonlocal future
loop.call_soon_threadsafe(future.set_result, ret)
self.queue.put((func, callback, arg1))
self.last_record = None
self.new_record_event.set()
result = await future
return result