PEP8, MyPy, Pylint; Makefile glob bugfix
This commit is contained in:
parent
426bd118aa
commit
74ccfec742
4 changed files with 231 additions and 34 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -5,5 +5,6 @@ lyrics.txt
|
||||||
input
|
input
|
||||||
|
|
||||||
__pycache__/
|
__pycache__/
|
||||||
|
.mypy_cache/
|
||||||
.vscode/
|
.vscode/
|
||||||
.idea/
|
.idea/
|
||||||
|
|
|
@ -16,9 +16,9 @@ from typing import Optional, Any
|
||||||
import re
|
import re
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup # type: ignore
|
||||||
|
|
||||||
from mutagen.id3 import ID3
|
from mutagen.id3 import ID3 # type: ignore
|
||||||
from mutagen.id3 import TPE1, TIT2, TALB
|
from mutagen.id3 import TPE1, TIT2, TALB
|
||||||
from mutagen.id3 import TYER, TRCK
|
from mutagen.id3 import TYER, TRCK
|
||||||
from mutagen.id3 import USLT, APIC
|
from mutagen.id3 import USLT, APIC
|
||||||
|
@ -31,8 +31,6 @@ USERAGENT = (
|
||||||
|
|
||||||
LYRICS_ROW = '.main-page>.row>.col-xs-12'
|
LYRICS_ROW = '.main-page>.row>.col-xs-12'
|
||||||
|
|
||||||
EDITMSG = 'edit'
|
|
||||||
|
|
||||||
safename_re = re.compile(
|
safename_re = re.compile(
|
||||||
r'[^A-Za-z0-9А-ЯЁа-яё \'".,()\[\]&!#$@_~=*+-]'
|
r'[^A-Za-z0-9А-ЯЁа-яё \'".,()\[\]&!#$@_~=*+-]'
|
||||||
)
|
)
|
||||||
|
@ -53,6 +51,18 @@ class ParseResult(TypedDict):
|
||||||
cover_mime: Optional[str]
|
cover_mime: Optional[str]
|
||||||
|
|
||||||
|
|
||||||
|
class ParseError(Exception):
|
||||||
|
|
||||||
|
EDIT = 'edit'
|
||||||
|
|
||||||
|
def __init__(self, parsing_obj: str) -> None:
|
||||||
|
|
||||||
|
super().__init__(
|
||||||
|
f'Unable to parse {parsing_obj}'
|
||||||
|
)
|
||||||
|
self.parsing_obj = parsing_obj
|
||||||
|
|
||||||
|
|
||||||
parsed = ParseResult(
|
parsed = ParseResult(
|
||||||
title='', artist='',
|
title='', artist='',
|
||||||
album='', year=0,
|
album='', year=0,
|
||||||
|
@ -63,16 +73,6 @@ parsed = ParseResult(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class ParseError(Exception):
|
|
||||||
|
|
||||||
def __init__(self, parsing_obj: str) -> None:
|
|
||||||
|
|
||||||
super().__init__(
|
|
||||||
f'Unable to parse {parsing_obj}'
|
|
||||||
)
|
|
||||||
self.parsing_obj = parsing_obj
|
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
|
|
||||||
global parsed
|
global parsed
|
||||||
|
@ -108,9 +108,11 @@ def main() -> None:
|
||||||
|
|
||||||
print(err)
|
print(err)
|
||||||
|
|
||||||
|
# pylint: disable=no-member
|
||||||
if isinstance(err, ParseError) \
|
if isinstance(err, ParseError) \
|
||||||
and err.parsing_obj == EDITMSG:
|
and err.parsing_obj == ParseError.EDIT:
|
||||||
pass
|
pass
|
||||||
|
# pylint: enable=no-member
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print(
|
print(
|
||||||
|
@ -121,10 +123,10 @@ def main() -> None:
|
||||||
|
|
||||||
manual_info_input(False)
|
manual_info_input(False)
|
||||||
|
|
||||||
#print(parsed)
|
tagmp3(file, copy)
|
||||||
tagmp3(file, parsed, copy)
|
|
||||||
|
|
||||||
|
|
||||||
|
# pylint: disable=redefined-builtin
|
||||||
def input(msg: str = '', def_: Any = '') -> str:
|
def input(msg: str = '', def_: Any = '') -> str:
|
||||||
|
|
||||||
subprocess.call(
|
subprocess.call(
|
||||||
|
@ -143,6 +145,7 @@ def input(msg: str = '', def_: Any = '') -> str:
|
||||||
.removesuffix('\r')
|
.removesuffix('\r')
|
||||||
except Exception:
|
except Exception:
|
||||||
return def_
|
return def_
|
||||||
|
# pylint: enable=redefined-builtin
|
||||||
|
|
||||||
|
|
||||||
def input_num(msg: str, def_: int = 0) -> int:
|
def input_num(msg: str, def_: int = 0) -> int:
|
||||||
|
@ -189,10 +192,10 @@ def conv_title(file: str) -> str:
|
||||||
def search_azurl(title: str) -> str:
|
def search_azurl(title: str) -> str:
|
||||||
|
|
||||||
print('Searching...')
|
print('Searching...')
|
||||||
|
|
||||||
page = session.get(
|
page = session.get(
|
||||||
'https://searx.dc09.ru/search',
|
'https://searx.dc09.ru/search',
|
||||||
params={
|
params={ # type: ignore
|
||||||
'q': f'{title} site:azlyrics.com',
|
'q': f'{title} site:azlyrics.com',
|
||||||
'language': 'ru-RU',
|
'language': 'ru-RU',
|
||||||
'safesearch': 0,
|
'safesearch': 0,
|
||||||
|
@ -207,7 +210,7 @@ def search_azurl(title: str) -> str:
|
||||||
|
|
||||||
if link is None:
|
if link is None:
|
||||||
raise ParseError('song URL')
|
raise ParseError('song URL')
|
||||||
|
|
||||||
return str(link.get('href'))
|
return str(link.get('href'))
|
||||||
|
|
||||||
|
|
||||||
|
@ -219,7 +222,7 @@ def parse_azlyrics(link: str) -> None:
|
||||||
|
|
||||||
page = session.get(link)
|
page = session.get(link)
|
||||||
soup = BeautifulSoup(page.text, 'html.parser')
|
soup = BeautifulSoup(page.text, 'html.parser')
|
||||||
|
|
||||||
lyrics = soup.select_one(
|
lyrics = soup.select_one(
|
||||||
f'{LYRICS_ROW}>div'
|
f'{LYRICS_ROW}>div'
|
||||||
':not(.div-share)'
|
':not(.div-share)'
|
||||||
|
@ -262,7 +265,7 @@ def parse_azlyrics(link: str) -> None:
|
||||||
)
|
)
|
||||||
if album_re is None:
|
if album_re is None:
|
||||||
raise ParseError('album name')
|
raise ParseError('album name')
|
||||||
|
|
||||||
parsed['album'] = album_re[1]
|
parsed['album'] = album_re[1]
|
||||||
parsed['year'] = int(album_re[2])
|
parsed['year'] = int(album_re[2])
|
||||||
|
|
||||||
|
@ -279,7 +282,7 @@ def parse_azlyrics(link: str) -> None:
|
||||||
parsed['cover_mime'] = req.headers.get(
|
parsed['cover_mime'] = req.headers.get(
|
||||||
'Content-Type', 'image/jpeg'
|
'Content-Type', 'image/jpeg'
|
||||||
)
|
)
|
||||||
|
|
||||||
tracklist_elem = soup.select_one('.songlist-panel')
|
tracklist_elem = soup.select_one('.songlist-panel')
|
||||||
if tracklist_elem is not None:
|
if tracklist_elem is not None:
|
||||||
|
|
||||||
|
@ -305,7 +308,7 @@ def parse_azlyrics(link: str) -> None:
|
||||||
if current_url[0] in track_href:
|
if current_url[0] in track_href:
|
||||||
parsed['track_no'] = (i + 1)
|
parsed['track_no'] = (i + 1)
|
||||||
break
|
break
|
||||||
|
|
||||||
print('Succesfully parsed')
|
print('Succesfully parsed')
|
||||||
print('Title:', parsed['title'])
|
print('Title:', parsed['title'])
|
||||||
print('Artist:', parsed['artist'])
|
print('Artist:', parsed['artist'])
|
||||||
|
@ -314,9 +317,9 @@ def parse_azlyrics(link: str) -> None:
|
||||||
print('Correct something?')
|
print('Correct something?')
|
||||||
|
|
||||||
if input('[y/N] ').lower == 'y':
|
if input('[y/N] ').lower == 'y':
|
||||||
raise ParseError('edit')
|
raise ParseError(ParseError.EDIT)
|
||||||
else:
|
|
||||||
print()
|
print()
|
||||||
|
|
||||||
|
|
||||||
def manual_info_input(overwrite_lyrics: bool = True) -> None:
|
def manual_info_input(overwrite_lyrics: bool = True) -> None:
|
||||||
|
@ -378,18 +381,19 @@ def manual_info_input(overwrite_lyrics: bool = True) -> None:
|
||||||
)
|
)
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
logging.exception(err)
|
logging.exception(err)
|
||||||
|
|
||||||
print()
|
print()
|
||||||
|
|
||||||
|
|
||||||
def tagmp3(
|
def tagmp3(
|
||||||
file: str,
|
file: str,
|
||||||
parsed: ParseResult,
|
|
||||||
copy: bool) -> None:
|
copy: bool) -> None:
|
||||||
|
|
||||||
|
global parsed
|
||||||
|
|
||||||
oldpath = Path(file)
|
oldpath = Path(file)
|
||||||
newpath = oldpath
|
newpath = oldpath
|
||||||
|
|
||||||
if copy:
|
if copy:
|
||||||
|
|
||||||
newdir = (
|
newdir = (
|
||||||
|
@ -414,7 +418,7 @@ def tagmp3(
|
||||||
cover = newdir / f'cover{ext}'
|
cover = newdir / f'cover{ext}'
|
||||||
with cover.open('wb') as f:
|
with cover.open('wb') as f:
|
||||||
f.write(parsed['cover'])
|
f.write(parsed['cover'])
|
||||||
|
|
||||||
id3 = ID3(str(newpath))
|
id3 = ID3(str(newpath))
|
||||||
id3['TPE1'] = TPE1(text=parsed['artist'])
|
id3['TPE1'] = TPE1(text=parsed['artist'])
|
||||||
id3['TIT2'] = TIT2(text=parsed['title'])
|
id3['TIT2'] = TIT2(text=parsed['title'])
|
||||||
|
|
7
Makefile
7
Makefile
|
@ -1,5 +1,6 @@
|
||||||
clean:
|
clean:
|
||||||
rm -rf __pycache__/
|
rm -rf __pycache__/
|
||||||
|
rm -rf .mypy_cache/
|
||||||
rm -f lyrics.txt input
|
rm -f lyrics.txt input
|
||||||
|
|
||||||
run:
|
run:
|
||||||
|
@ -15,8 +16,8 @@ tags:
|
||||||
./id3tag.sh
|
./id3tag.sh
|
||||||
|
|
||||||
pyformat:
|
pyformat:
|
||||||
python3 -m autopep8 --in-place ./*.py
|
python3 -m autopep8 --in-place .*.py
|
||||||
|
|
||||||
pycheck:
|
pycheck:
|
||||||
python3 -m mypy ./*.py
|
python3 -m mypy .*.py
|
||||||
python3 -m pylint -j $(nproc) ./*.py
|
python3 -m pylint -j4 .*.py
|
||||||
|
|
191
pylintrc
Normal file
191
pylintrc
Normal file
|
@ -0,0 +1,191 @@
|
||||||
|
[MAIN]
|
||||||
|
analyse-fallback-blocks=no
|
||||||
|
extension-pkg-allow-list=
|
||||||
|
extension-pkg-whitelist=
|
||||||
|
fail-on=
|
||||||
|
fail-under=10
|
||||||
|
ignore=CVS
|
||||||
|
ignore-paths=
|
||||||
|
ignore-patterns=^\.#
|
||||||
|
ignored-modules=
|
||||||
|
jobs=4
|
||||||
|
limit-inference-results=100
|
||||||
|
load-plugins=
|
||||||
|
persistent=yes
|
||||||
|
py-version=3.10
|
||||||
|
recursive=no
|
||||||
|
suggestion-mode=yes
|
||||||
|
unsafe-load-any-extension=no
|
||||||
|
|
||||||
|
[REPORTS]
|
||||||
|
evaluation=max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10))
|
||||||
|
msg-template=
|
||||||
|
reports=no
|
||||||
|
score=yes
|
||||||
|
|
||||||
|
[MESSAGES CONTROL]
|
||||||
|
confidence=HIGH,
|
||||||
|
CONTROL_FLOW,
|
||||||
|
INFERENCE,
|
||||||
|
INFERENCE_FAILURE,
|
||||||
|
UNDEFINED
|
||||||
|
disable=raw-checker-failed,
|
||||||
|
bad-inline-option,
|
||||||
|
locally-disabled,
|
||||||
|
file-ignored,
|
||||||
|
suppressed-message,
|
||||||
|
useless-suppression,
|
||||||
|
deprecated-pragma,
|
||||||
|
use-symbolic-message-instead,
|
||||||
|
too-many-branches,
|
||||||
|
too-many-statements,
|
||||||
|
too-many-locals,
|
||||||
|
broad-except,
|
||||||
|
global-variable-not-assigned
|
||||||
|
enable=c-extension-no-member
|
||||||
|
|
||||||
|
[SIMILARITIES]
|
||||||
|
ignore-comments=yes
|
||||||
|
ignore-docstrings=yes
|
||||||
|
ignore-imports=yes
|
||||||
|
ignore-signatures=yes
|
||||||
|
min-similarity-lines=4
|
||||||
|
|
||||||
|
[MISCELLANEOUS]
|
||||||
|
notes=FIXME,
|
||||||
|
XXX,
|
||||||
|
TODO
|
||||||
|
notes-rgx=
|
||||||
|
|
||||||
|
[DESIGN]
|
||||||
|
exclude-too-few-public-methods=
|
||||||
|
ignored-parents=
|
||||||
|
max-args=5
|
||||||
|
max-attributes=7
|
||||||
|
max-bool-expr=5
|
||||||
|
max-branches=12
|
||||||
|
max-locals=15
|
||||||
|
max-parents=7
|
||||||
|
max-public-methods=20
|
||||||
|
max-returns=6
|
||||||
|
max-statements=50
|
||||||
|
min-public-methods=2
|
||||||
|
|
||||||
|
[STRING]
|
||||||
|
check-quote-consistency=no
|
||||||
|
check-str-concat-over-line-jumps=no
|
||||||
|
|
||||||
|
[CLASSES]
|
||||||
|
check-protected-access-in-special-methods=no
|
||||||
|
defining-attr-methods=__init__,
|
||||||
|
__new__,
|
||||||
|
setUp,
|
||||||
|
__post_init__
|
||||||
|
exclude-protected=_asdict,
|
||||||
|
_fields,
|
||||||
|
_replace,
|
||||||
|
_source,
|
||||||
|
_make
|
||||||
|
valid-classmethod-first-arg=cls
|
||||||
|
valid-metaclass-classmethod-first-arg=cls
|
||||||
|
|
||||||
|
[FORMAT]
|
||||||
|
expected-line-ending-format=
|
||||||
|
ignore-long-lines=^\s*(# )?<?https?://\S+>?$
|
||||||
|
indent-after-paren=4
|
||||||
|
indent-string=' '
|
||||||
|
max-line-length=100
|
||||||
|
max-module-lines=1000
|
||||||
|
single-line-class-stmt=no
|
||||||
|
single-line-if-stmt=no
|
||||||
|
|
||||||
|
[IMPORTS]
|
||||||
|
allow-any-import-level=
|
||||||
|
allow-wildcard-with-all=no
|
||||||
|
deprecated-modules=
|
||||||
|
ext-import-graph=
|
||||||
|
import-graph=
|
||||||
|
int-import-graph=
|
||||||
|
known-standard-library=
|
||||||
|
known-third-party=enchant
|
||||||
|
preferred-modules=
|
||||||
|
|
||||||
|
[VARIABLES]
|
||||||
|
additional-builtins=
|
||||||
|
allow-global-unused-variables=yes
|
||||||
|
allowed-redefined-builtins=
|
||||||
|
callbacks=cb_,
|
||||||
|
_cb
|
||||||
|
dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_
|
||||||
|
ignored-argument-names=_.*|^ignored_|^unused_
|
||||||
|
init-import=no
|
||||||
|
redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io
|
||||||
|
|
||||||
|
[LOGGING]
|
||||||
|
logging-format-style=old
|
||||||
|
logging-modules=logging
|
||||||
|
|
||||||
|
[EXCEPTIONS]
|
||||||
|
overgeneral-exceptions=BaseException,
|
||||||
|
Exception
|
||||||
|
|
||||||
|
[BASIC]
|
||||||
|
argument-naming-style=snake_case
|
||||||
|
attr-naming-style=snake_case
|
||||||
|
bad-names=foo,
|
||||||
|
bar,
|
||||||
|
baz,
|
||||||
|
toto,
|
||||||
|
tutu,
|
||||||
|
tata
|
||||||
|
bad-names-rgxs=
|
||||||
|
class-attribute-naming-style=any
|
||||||
|
class-const-naming-style=UPPER_CASE
|
||||||
|
class-naming-style=PascalCase
|
||||||
|
const-naming-style=any
|
||||||
|
docstring-min-length=-1
|
||||||
|
function-naming-style=snake_case
|
||||||
|
good-names=i,
|
||||||
|
j,
|
||||||
|
k,
|
||||||
|
f,
|
||||||
|
ex,
|
||||||
|
Run,
|
||||||
|
_
|
||||||
|
good-names-rgxs=
|
||||||
|
include-naming-hint=no
|
||||||
|
inlinevar-naming-style=any
|
||||||
|
method-naming-style=snake_case
|
||||||
|
module-naming-style=snake_case
|
||||||
|
name-group=
|
||||||
|
no-docstring-rgx=^_
|
||||||
|
property-classes=abc.abstractproperty
|
||||||
|
variable-naming-style=snake_case
|
||||||
|
|
||||||
|
[SPELLING]
|
||||||
|
max-spelling-suggestions=4
|
||||||
|
spelling-dict=
|
||||||
|
spelling-ignore-comment-directives=fmt: on,fmt: off,noqa:,noqa,nosec,isort:skip,mypy:
|
||||||
|
spelling-ignore-words=
|
||||||
|
spelling-private-dict-file=
|
||||||
|
spelling-store-unknown-words=no
|
||||||
|
|
||||||
|
[TYPECHECK]
|
||||||
|
contextmanager-decorators=contextlib.contextmanager
|
||||||
|
generated-members=
|
||||||
|
ignore-none=yes
|
||||||
|
ignore-on-opaque-inference=yes
|
||||||
|
ignored-checks-for-mixins=no-member,
|
||||||
|
not-async-context-manager,
|
||||||
|
not-context-manager,
|
||||||
|
attribute-defined-outside-init
|
||||||
|
ignored-classes=optparse.Values,thread._local,_thread._local,argparse.Namespace
|
||||||
|
missing-member-hint=yes
|
||||||
|
missing-member-hint-distance=1
|
||||||
|
missing-member-max-choices=1
|
||||||
|
mixin-class-rgx=.*[Mm]ixin
|
||||||
|
signature-mutators=
|
||||||
|
|
||||||
|
[REFACTORING]
|
||||||
|
max-nested-blocks=5
|
||||||
|
never-returning-functions=sys.exit,argparse.parse_error
|
Reference in a new issue