mirror of
https://github.com/283375/arcaea-offline.git
synced 2025-04-17 21:30:18 +00:00
chore: fix pylint warnings
This commit is contained in:
parent
92fcc53015
commit
14f4cef426
@ -30,3 +30,14 @@ src_paths = ["src/arcaea_offline"]
|
|||||||
|
|
||||||
[tool.pyright]
|
[tool.pyright]
|
||||||
ignore = ["build/"]
|
ignore = ["build/"]
|
||||||
|
|
||||||
|
[tool.pylint.main]
|
||||||
|
jobs = 0
|
||||||
|
|
||||||
|
[tool.pylint.logging]
|
||||||
|
disable = [
|
||||||
|
"missing-module-docstring",
|
||||||
|
"missing-class-docstring",
|
||||||
|
"missing-function-docstring",
|
||||||
|
"not-callable", # false positive to sqlalchemy `func.*`, remove this when pylint-dev/pylint(#8138) closed
|
||||||
|
]
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
black==23.3.0
|
black==23.3.0
|
||||||
isort==5.12.0
|
isort==5.12.0
|
||||||
pre-commit==3.3.1
|
pre-commit==3.3.1
|
||||||
|
pylint==3.0.2
|
||||||
|
@ -16,10 +16,9 @@ def calculate_score_range(notes: int, pure: int, far: int):
|
|||||||
def calculate_score_modifier(score: int) -> Decimal:
|
def calculate_score_modifier(score: int) -> Decimal:
|
||||||
if score >= 10000000:
|
if score >= 10000000:
|
||||||
return Decimal(2)
|
return Decimal(2)
|
||||||
elif score >= 9800000:
|
if score >= 9800000:
|
||||||
return Decimal(1) + (Decimal(score - 9800000) / 200000)
|
return Decimal(1) + (Decimal(score - 9800000) / 200000)
|
||||||
else:
|
return Decimal(score - 9500000) / 300000
|
||||||
return Decimal(score - 9500000) / 300000
|
|
||||||
|
|
||||||
|
|
||||||
def calculate_play_rating(constant: int, score: int) -> Decimal:
|
def calculate_play_rating(constant: int, score: int) -> Decimal:
|
||||||
@ -35,6 +34,7 @@ def calculate_shiny_pure(notes: int, score: int, pure: int, far: int) -> int:
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class ConstantsFromPlayRatingResult:
|
class ConstantsFromPlayRatingResult:
|
||||||
|
# pylint: disable=invalid-name
|
||||||
EXPlus: Tuple[Decimal, Decimal]
|
EXPlus: Tuple[Decimal, Decimal]
|
||||||
EX: Tuple[Decimal, Decimal]
|
EX: Tuple[Decimal, Decimal]
|
||||||
AA: Tuple[Decimal, Decimal]
|
AA: Tuple[Decimal, Decimal]
|
||||||
@ -44,10 +44,12 @@ class ConstantsFromPlayRatingResult:
|
|||||||
|
|
||||||
|
|
||||||
def calculate_constants_from_play_rating(play_rating: Union[Decimal, str, float, int]):
|
def calculate_constants_from_play_rating(play_rating: Union[Decimal, str, float, int]):
|
||||||
|
# pylint: disable=no-value-for-parameter
|
||||||
|
|
||||||
play_rating = Decimal(play_rating)
|
play_rating = Decimal(play_rating)
|
||||||
|
|
||||||
ranges = []
|
ranges = []
|
||||||
for upperScore, lowerScore in [
|
for upper_score, lower_score in [
|
||||||
(10000000, 9900000),
|
(10000000, 9900000),
|
||||||
(9899999, 9800000),
|
(9899999, 9800000),
|
||||||
(9799999, 9500000),
|
(9799999, 9500000),
|
||||||
@ -55,10 +57,10 @@ def calculate_constants_from_play_rating(play_rating: Union[Decimal, str, float,
|
|||||||
(9199999, 8900000),
|
(9199999, 8900000),
|
||||||
(8899999, 8600000),
|
(8899999, 8600000),
|
||||||
]:
|
]:
|
||||||
upperScoreModifier = calculate_score_modifier(upperScore)
|
upper_score_modifier = calculate_score_modifier(upper_score)
|
||||||
lowerScoreModifier = calculate_score_modifier(lowerScore)
|
lower_score_modifier = calculate_score_modifier(lower_score)
|
||||||
ranges.append(
|
ranges.append(
|
||||||
(play_rating - upperScoreModifier, play_rating - lowerScoreModifier)
|
(play_rating - upper_score_modifier, play_rating - lower_score_modifier)
|
||||||
)
|
)
|
||||||
|
|
||||||
return ConstantsFromPlayRatingResult(*ranges)
|
return ConstantsFromPlayRatingResult(*ranges)
|
||||||
|
@ -5,12 +5,29 @@ from typing import Iterable, List, Optional, Type, Union
|
|||||||
from sqlalchemy import Engine, func, inspect, select
|
from sqlalchemy import Engine, func, inspect, select
|
||||||
from sqlalchemy.orm import DeclarativeBase, InstrumentedAttribute, sessionmaker
|
from sqlalchemy.orm import DeclarativeBase, InstrumentedAttribute, sessionmaker
|
||||||
|
|
||||||
from .calculate import calculate_score_modifier
|
|
||||||
from .external.arcsong.arcsong_json import ArcSongJsonBuilder
|
from .external.arcsong.arcsong_json import ArcSongJsonBuilder
|
||||||
from .external.exports import ScoreExport, exporters
|
from .external.exports import ScoreExport, exporters
|
||||||
from .models.config import *
|
from .models.config import ConfigBase, Property
|
||||||
from .models.scores import *
|
from .models.scores import (
|
||||||
from .models.songs import *
|
CalculatedPotential,
|
||||||
|
Score,
|
||||||
|
ScoreBest,
|
||||||
|
ScoreCalculated,
|
||||||
|
ScoresBase,
|
||||||
|
ScoresViewBase,
|
||||||
|
)
|
||||||
|
from .models.songs import (
|
||||||
|
Chart,
|
||||||
|
ChartInfo,
|
||||||
|
Difficulty,
|
||||||
|
DifficultyLocalized,
|
||||||
|
Pack,
|
||||||
|
PackLocalized,
|
||||||
|
Song,
|
||||||
|
SongLocalized,
|
||||||
|
SongsBase,
|
||||||
|
SongsViewBase,
|
||||||
|
)
|
||||||
from .singleton import Singleton
|
from .singleton import Singleton
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -27,18 +44,21 @@ class Database(metaclass=Singleton):
|
|||||||
if isinstance(self.engine, Engine):
|
if isinstance(self.engine, Engine):
|
||||||
return
|
return
|
||||||
raise ValueError("No sqlalchemy.Engine instance specified before.")
|
raise ValueError("No sqlalchemy.Engine instance specified before.")
|
||||||
elif isinstance(engine, Engine):
|
|
||||||
if isinstance(self.engine, Engine):
|
if not isinstance(engine, Engine):
|
||||||
logger.warning(
|
|
||||||
f"A sqlalchemy.Engine instance {self.engine} has been specified "
|
|
||||||
f"and will be replaced to {engine}"
|
|
||||||
)
|
|
||||||
self.engine = engine
|
|
||||||
else:
|
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"A sqlalchemy.Engine instance expected, not {repr(engine)}"
|
f"A sqlalchemy.Engine instance expected, not {repr(engine)}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if isinstance(self.engine, Engine):
|
||||||
|
logger.warning(
|
||||||
|
"A sqlalchemy.Engine instance %r has been specified "
|
||||||
|
"and will be replaced to %r",
|
||||||
|
self.engine,
|
||||||
|
engine,
|
||||||
|
)
|
||||||
|
self.engine = engine
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def engine(self) -> Engine:
|
def engine(self) -> Engine:
|
||||||
return self.__engine # type: ignore
|
return self.__engine # type: ignore
|
||||||
@ -60,7 +80,8 @@ class Database(metaclass=Singleton):
|
|||||||
# create tables & views
|
# create tables & views
|
||||||
if checkfirst:
|
if checkfirst:
|
||||||
# > https://github.com/kvesteri/sqlalchemy-utils/issues/396
|
# > https://github.com/kvesteri/sqlalchemy-utils/issues/396
|
||||||
# > view.create_view() causes DuplicateTableError on Base.metadata.create_all(checkfirst=True)
|
# > view.create_view() causes DuplicateTableError on
|
||||||
|
# > Base.metadata.create_all(checkfirst=True)
|
||||||
# so if `checkfirst` is True, drop these views before creating
|
# so if `checkfirst` is True, drop these views before creating
|
||||||
SongsViewBase.metadata.drop_all(self.engine)
|
SongsViewBase.metadata.drop_all(self.engine)
|
||||||
ScoresViewBase.metadata.drop_all(self.engine)
|
ScoresViewBase.metadata.drop_all(self.engine)
|
||||||
|
7
src/arcaea_offline/external/arcaea/common.py
vendored
7
src/arcaea_offline/external/arcaea/common.py
vendored
@ -39,10 +39,7 @@ def fix_timestamp(timestamp: int) -> Union[int, None]:
|
|||||||
def to_db_value(val: Any) -> Any:
|
def to_db_value(val: Any) -> Any:
|
||||||
if not val:
|
if not val:
|
||||||
return None
|
return None
|
||||||
elif isinstance(val, list):
|
return json.dumps(val, ensure_ascii=False) if isinstance(val, list) else val
|
||||||
return json.dumps(val, ensure_ascii=False)
|
|
||||||
else:
|
|
||||||
return val
|
|
||||||
|
|
||||||
|
|
||||||
def is_localized(item: dict, key: str, append_localized: bool = True):
|
def is_localized(item: dict, key: str, append_localized: bool = True):
|
||||||
@ -94,7 +91,7 @@ class ArcaeaParser:
|
|||||||
return file_handle.read()
|
return file_handle.read()
|
||||||
|
|
||||||
def parse(self) -> List[DeclarativeBase]:
|
def parse(self) -> List[DeclarativeBase]:
|
||||||
...
|
raise NotImplementedError()
|
||||||
|
|
||||||
def write_database(self, session: Session):
|
def write_database(self, session: Session):
|
||||||
results = self.parse()
|
results = self.parse()
|
||||||
|
3
src/arcaea_offline/external/arcaea/online.py
vendored
3
src/arcaea_offline/external/arcaea/online.py
vendored
@ -37,9 +37,6 @@ class TWebApiRatingMeResult(TypedDict):
|
|||||||
|
|
||||||
|
|
||||||
class ArcaeaOnlineParser(ArcaeaParser):
|
class ArcaeaOnlineParser(ArcaeaParser):
|
||||||
def __init__(self, filepath):
|
|
||||||
super().__init__(filepath)
|
|
||||||
|
|
||||||
def parse(self) -> List[Score]:
|
def parse(self) -> List[Score]:
|
||||||
api_result_root: TWebApiRatingMeResult = json.loads(self.read_file_text())
|
api_result_root: TWebApiRatingMeResult = json.loads(self.read_file_text())
|
||||||
|
|
||||||
|
@ -6,9 +6,6 @@ from .common import ArcaeaParser, is_localized, set_model_localized_attrs
|
|||||||
|
|
||||||
|
|
||||||
class PacklistParser(ArcaeaParser):
|
class PacklistParser(ArcaeaParser):
|
||||||
def __init__(self, filepath):
|
|
||||||
super().__init__(filepath)
|
|
||||||
|
|
||||||
def parse(self) -> List[Union[Pack, PackLocalized]]:
|
def parse(self) -> List[Union[Pack, PackLocalized]]:
|
||||||
packlist_json_root = json.loads(self.read_file_text())
|
packlist_json_root = json.loads(self.read_file_text())
|
||||||
|
|
||||||
|
@ -6,9 +6,6 @@ from .common import ArcaeaParser, is_localized, set_model_localized_attrs, to_db
|
|||||||
|
|
||||||
|
|
||||||
class SonglistParser(ArcaeaParser):
|
class SonglistParser(ArcaeaParser):
|
||||||
def __init__(self, filepath):
|
|
||||||
super().__init__(filepath)
|
|
||||||
|
|
||||||
def parse(
|
def parse(
|
||||||
self,
|
self,
|
||||||
) -> List[Union[Song, SongLocalized, Difficulty, DifficultyLocalized]]:
|
) -> List[Union[Song, SongLocalized, Difficulty, DifficultyLocalized]]:
|
||||||
@ -61,9 +58,6 @@ class SonglistParser(ArcaeaParser):
|
|||||||
|
|
||||||
|
|
||||||
class SonglistDifficultiesParser(ArcaeaParser):
|
class SonglistDifficultiesParser(ArcaeaParser):
|
||||||
def __init__(self, filepath):
|
|
||||||
self.filepath = filepath
|
|
||||||
|
|
||||||
def parse(self) -> List[Union[Difficulty, DifficultyLocalized]]:
|
def parse(self) -> List[Union[Difficulty, DifficultyLocalized]]:
|
||||||
songlist_json_root = json.loads(self.read_file_text())
|
songlist_json_root = json.loads(self.read_file_text())
|
||||||
|
|
||||||
|
13
src/arcaea_offline/external/arcaea/st3.py
vendored
13
src/arcaea_offline/external/arcaea/st3.py
vendored
@ -12,15 +12,13 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
class St3ScoreParser(ArcaeaParser):
|
class St3ScoreParser(ArcaeaParser):
|
||||||
def __init__(self, filepath):
|
|
||||||
super().__init__(filepath)
|
|
||||||
|
|
||||||
def parse(self) -> List[Score]:
|
def parse(self) -> List[Score]:
|
||||||
items = []
|
items = []
|
||||||
with sqlite3.connect(self.filepath) as st3_conn:
|
with sqlite3.connect(self.filepath) as st3_conn:
|
||||||
cursor = st3_conn.cursor()
|
cursor = st3_conn.cursor()
|
||||||
db_scores = cursor.execute(
|
db_scores = cursor.execute(
|
||||||
"SELECT songId, songDifficulty, score, perfectCount, nearCount, missCount, date, modifier FROM scores"
|
"SELECT songId, songDifficulty, score, perfectCount, nearCount, missCount, "
|
||||||
|
"date, modifier FROM scores"
|
||||||
).fetchall()
|
).fetchall()
|
||||||
for (
|
for (
|
||||||
song_id,
|
song_id,
|
||||||
@ -48,7 +46,7 @@ class St3ScoreParser(ArcaeaParser):
|
|||||||
date=fix_timestamp(date),
|
date=fix_timestamp(date),
|
||||||
modifier=modifier,
|
modifier=modifier,
|
||||||
clear_type=clear_type,
|
clear_type=clear_type,
|
||||||
comment=f"Parsed from st3",
|
comment="Parsed from st3",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -67,8 +65,9 @@ class St3ScoreParser(ArcaeaParser):
|
|||||||
|
|
||||||
if query_score and skip_duplicate:
|
if query_score and skip_duplicate:
|
||||||
logger.info(
|
logger.info(
|
||||||
f"{repr(parsed_score)} skipped because "
|
"%r skipped because potential duplicate item %r found.",
|
||||||
f"potential duplicate item {repr(query_score)} found."
|
parsed_score,
|
||||||
|
query_score,
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
session.add(parsed_score)
|
session.add(parsed_score)
|
||||||
|
@ -122,7 +122,9 @@ class ArcSongJsonBuilder:
|
|||||||
|
|
||||||
pack = self.session.scalar(select(Pack).where(Pack.id == song.set))
|
pack = self.session.scalar(select(Pack).where(Pack.id == song.set))
|
||||||
if not pack:
|
if not pack:
|
||||||
logger.warning(f'Cannot find pack "{song.set}", using placeholder instead.')
|
logger.warning(
|
||||||
|
'Cannot find pack "%s", using placeholder instead.', song.set
|
||||||
|
)
|
||||||
pack = Pack(id="unknown", name="Unknown", description="__PLACEHOLDER__")
|
pack = Pack(id="unknown", name="Unknown", description="__PLACEHOLDER__")
|
||||||
song_localized = self.session.scalar(
|
song_localized = self.session.scalar(
|
||||||
select(SongLocalized).where(SongLocalized.id == song.id)
|
select(SongLocalized).where(SongLocalized.id == song.id)
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
|
# pylint: disable=too-few-public-methods
|
||||||
|
|
||||||
from sqlalchemy.orm import DeclarativeBase
|
from sqlalchemy.orm import DeclarativeBase
|
||||||
from sqlalchemy.orm.exc import DetachedInstanceError
|
from sqlalchemy.orm.exc import DetachedInstanceError
|
||||||
|
|
||||||
|
|
||||||
class ReprHelper:
|
class ReprHelper:
|
||||||
|
# pylint: disable=no-member
|
||||||
|
|
||||||
def _repr(self, **kwargs) -> str:
|
def _repr(self, **kwargs) -> str:
|
||||||
"""
|
"""
|
||||||
Helper for __repr__
|
Helper for __repr__
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# pylint: disable=too-few-public-methods
|
||||||
|
|
||||||
from sqlalchemy import TEXT
|
from sqlalchemy import TEXT
|
||||||
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
|
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# pylint: disable=too-few-public-methods, duplicate-code
|
||||||
|
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from sqlalchemy import TEXT, case, func, inspect, select, text
|
from sqlalchemy import TEXT, case, func, inspect, select, text
|
||||||
@ -37,7 +39,8 @@ class Score(ScoresBase):
|
|||||||
comment="0: NORMAL, 1: EASY, 2: HARD"
|
comment="0: NORMAL, 1: EASY, 2: HARD"
|
||||||
)
|
)
|
||||||
clear_type: Mapped[Optional[int]] = mapped_column(
|
clear_type: Mapped[Optional[int]] = mapped_column(
|
||||||
comment="0: TRACK LOST, 1: NORMAL CLEAR, 2: FULL RECALL, 3: PURE MEMORY, 4: EASY CLEAR, 5: HARD CLEAR"
|
comment="0: TRACK LOST, 1: NORMAL CLEAR, 2: FULL RECALL, "
|
||||||
|
"3: PURE MEMORY, 4: EASY CLEAR, 5: HARD CLEAR"
|
||||||
)
|
)
|
||||||
comment: Mapped[Optional[str]] = mapped_column(TEXT())
|
comment: Mapped[Optional[str]] = mapped_column(TEXT())
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# pylint: disable=too-few-public-methods, duplicate-code
|
||||||
|
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from sqlalchemy import TEXT, ForeignKey, func, select
|
from sqlalchemy import TEXT, ForeignKey, func, select
|
||||||
@ -154,7 +156,7 @@ class ChartInfo(SongsBase):
|
|||||||
ForeignKey("difficulties.rating_class"), primary_key=True
|
ForeignKey("difficulties.rating_class"), primary_key=True
|
||||||
)
|
)
|
||||||
constant: Mapped[int] = mapped_column(
|
constant: Mapped[int] = mapped_column(
|
||||||
comment="real_constant * 10. For example, Crimson Throne [FTR] is 10.4, then store 104 here."
|
comment="real_constant * 10. For example, Crimson Throne [FTR] is 10.4, then store 104."
|
||||||
)
|
)
|
||||||
notes: Mapped[Optional[int]]
|
notes: Mapped[Optional[int]]
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ class Searcher:
|
|||||||
|
|
||||||
return list(results)
|
return list(results)
|
||||||
|
|
||||||
def search(self, string: str, *, limit: int = 10, fuzzy_distance: int = 10):
|
def search(self, string: str, *, limit: int = 10):
|
||||||
query_string = f"{string}"
|
query_string = f"{string}"
|
||||||
query = self.default_query_parser.parse(query_string)
|
query = self.default_query_parser.parse(query_string)
|
||||||
with self.index.searcher() as searcher:
|
with self.index.searcher() as searcher:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user