From 14f4cef426db09df140c5ff70c6e15129bb21adf Mon Sep 17 00:00:00 2001 From: 283375 Date: Thu, 2 Nov 2023 01:10:31 +0800 Subject: [PATCH] chore: fix pylint warnings --- pyproject.toml | 11 +++++ requirements.dev.txt | 1 + src/arcaea_offline/calculate/score.py | 16 ++++--- src/arcaea_offline/database.py | 47 ++++++++++++++----- src/arcaea_offline/external/arcaea/common.py | 7 +-- src/arcaea_offline/external/arcaea/online.py | 3 -- .../external/arcaea/packlist.py | 3 -- .../external/arcaea/songlist.py | 6 --- src/arcaea_offline/external/arcaea/st3.py | 13 +++-- .../external/arcsong/arcsong_json.py | 4 +- src/arcaea_offline/models/common.py | 4 ++ src/arcaea_offline/models/config.py | 2 + src/arcaea_offline/models/scores.py | 5 +- src/arcaea_offline/models/songs.py | 4 +- src/arcaea_offline/searcher.py | 2 +- 15 files changed, 80 insertions(+), 48 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 2bf4627..49e8b4d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,3 +30,14 @@ src_paths = ["src/arcaea_offline"] [tool.pyright] 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 +] diff --git a/requirements.dev.txt b/requirements.dev.txt index 892d4ef..ce848f8 100644 --- a/requirements.dev.txt +++ b/requirements.dev.txt @@ -1,3 +1,4 @@ black==23.3.0 isort==5.12.0 pre-commit==3.3.1 +pylint==3.0.2 diff --git a/src/arcaea_offline/calculate/score.py b/src/arcaea_offline/calculate/score.py index 0fa5ebf..f9c4764 100644 --- a/src/arcaea_offline/calculate/score.py +++ b/src/arcaea_offline/calculate/score.py @@ -16,10 +16,9 @@ def calculate_score_range(notes: int, pure: int, far: int): def calculate_score_modifier(score: int) -> Decimal: if score >= 10000000: return Decimal(2) - elif score >= 9800000: + if score >= 9800000: 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: @@ -35,6 +34,7 @@ def calculate_shiny_pure(notes: int, score: int, pure: int, far: int) -> int: @dataclass class ConstantsFromPlayRatingResult: + # pylint: disable=invalid-name EXPlus: Tuple[Decimal, Decimal] EX: 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]): + # pylint: disable=no-value-for-parameter + play_rating = Decimal(play_rating) ranges = [] - for upperScore, lowerScore in [ + for upper_score, lower_score in [ (10000000, 9900000), (9899999, 9800000), (9799999, 9500000), @@ -55,10 +57,10 @@ def calculate_constants_from_play_rating(play_rating: Union[Decimal, str, float, (9199999, 8900000), (8899999, 8600000), ]: - upperScoreModifier = calculate_score_modifier(upperScore) - lowerScoreModifier = calculate_score_modifier(lowerScore) + upper_score_modifier = calculate_score_modifier(upper_score) + lower_score_modifier = calculate_score_modifier(lower_score) ranges.append( - (play_rating - upperScoreModifier, play_rating - lowerScoreModifier) + (play_rating - upper_score_modifier, play_rating - lower_score_modifier) ) return ConstantsFromPlayRatingResult(*ranges) diff --git a/src/arcaea_offline/database.py b/src/arcaea_offline/database.py index f19fa14..7942915 100644 --- a/src/arcaea_offline/database.py +++ b/src/arcaea_offline/database.py @@ -5,12 +5,29 @@ from typing import Iterable, List, Optional, Type, Union from sqlalchemy import Engine, func, inspect, select from sqlalchemy.orm import DeclarativeBase, InstrumentedAttribute, sessionmaker -from .calculate import calculate_score_modifier from .external.arcsong.arcsong_json import ArcSongJsonBuilder from .external.exports import ScoreExport, exporters -from .models.config import * -from .models.scores import * -from .models.songs import * +from .models.config import ConfigBase, Property +from .models.scores 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 logger = logging.getLogger(__name__) @@ -27,18 +44,21 @@ class Database(metaclass=Singleton): if isinstance(self.engine, Engine): return raise ValueError("No sqlalchemy.Engine instance specified before.") - elif isinstance(engine, Engine): - if isinstance(self.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: + + if not isinstance(engine, Engine): raise ValueError( 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 def engine(self) -> Engine: return self.__engine # type: ignore @@ -60,7 +80,8 @@ class Database(metaclass=Singleton): # create tables & views if checkfirst: # > 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 SongsViewBase.metadata.drop_all(self.engine) ScoresViewBase.metadata.drop_all(self.engine) diff --git a/src/arcaea_offline/external/arcaea/common.py b/src/arcaea_offline/external/arcaea/common.py index ccf4688..f130b74 100644 --- a/src/arcaea_offline/external/arcaea/common.py +++ b/src/arcaea_offline/external/arcaea/common.py @@ -39,10 +39,7 @@ def fix_timestamp(timestamp: int) -> Union[int, None]: def to_db_value(val: Any) -> Any: if not val: return None - elif isinstance(val, list): - return json.dumps(val, ensure_ascii=False) - else: - return val + return json.dumps(val, ensure_ascii=False) if isinstance(val, list) else val def is_localized(item: dict, key: str, append_localized: bool = True): @@ -94,7 +91,7 @@ class ArcaeaParser: return file_handle.read() def parse(self) -> List[DeclarativeBase]: - ... + raise NotImplementedError() def write_database(self, session: Session): results = self.parse() diff --git a/src/arcaea_offline/external/arcaea/online.py b/src/arcaea_offline/external/arcaea/online.py index 835b5ff..cb5d4b5 100644 --- a/src/arcaea_offline/external/arcaea/online.py +++ b/src/arcaea_offline/external/arcaea/online.py @@ -37,9 +37,6 @@ class TWebApiRatingMeResult(TypedDict): class ArcaeaOnlineParser(ArcaeaParser): - def __init__(self, filepath): - super().__init__(filepath) - def parse(self) -> List[Score]: api_result_root: TWebApiRatingMeResult = json.loads(self.read_file_text()) diff --git a/src/arcaea_offline/external/arcaea/packlist.py b/src/arcaea_offline/external/arcaea/packlist.py index 0d85e59..82acff0 100644 --- a/src/arcaea_offline/external/arcaea/packlist.py +++ b/src/arcaea_offline/external/arcaea/packlist.py @@ -6,9 +6,6 @@ from .common import ArcaeaParser, is_localized, set_model_localized_attrs class PacklistParser(ArcaeaParser): - def __init__(self, filepath): - super().__init__(filepath) - def parse(self) -> List[Union[Pack, PackLocalized]]: packlist_json_root = json.loads(self.read_file_text()) diff --git a/src/arcaea_offline/external/arcaea/songlist.py b/src/arcaea_offline/external/arcaea/songlist.py index be67e38..4c54da9 100644 --- a/src/arcaea_offline/external/arcaea/songlist.py +++ b/src/arcaea_offline/external/arcaea/songlist.py @@ -6,9 +6,6 @@ from .common import ArcaeaParser, is_localized, set_model_localized_attrs, to_db class SonglistParser(ArcaeaParser): - def __init__(self, filepath): - super().__init__(filepath) - def parse( self, ) -> List[Union[Song, SongLocalized, Difficulty, DifficultyLocalized]]: @@ -61,9 +58,6 @@ class SonglistParser(ArcaeaParser): class SonglistDifficultiesParser(ArcaeaParser): - def __init__(self, filepath): - self.filepath = filepath - def parse(self) -> List[Union[Difficulty, DifficultyLocalized]]: songlist_json_root = json.loads(self.read_file_text()) diff --git a/src/arcaea_offline/external/arcaea/st3.py b/src/arcaea_offline/external/arcaea/st3.py index abe655e..432f3b7 100644 --- a/src/arcaea_offline/external/arcaea/st3.py +++ b/src/arcaea_offline/external/arcaea/st3.py @@ -12,15 +12,13 @@ logger = logging.getLogger(__name__) class St3ScoreParser(ArcaeaParser): - def __init__(self, filepath): - super().__init__(filepath) - def parse(self) -> List[Score]: items = [] with sqlite3.connect(self.filepath) as st3_conn: cursor = st3_conn.cursor() 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() for ( song_id, @@ -48,7 +46,7 @@ class St3ScoreParser(ArcaeaParser): date=fix_timestamp(date), modifier=modifier, 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: logger.info( - f"{repr(parsed_score)} skipped because " - f"potential duplicate item {repr(query_score)} found." + "%r skipped because potential duplicate item %r found.", + parsed_score, + query_score, ) continue session.add(parsed_score) diff --git a/src/arcaea_offline/external/arcsong/arcsong_json.py b/src/arcaea_offline/external/arcsong/arcsong_json.py index 4f2f389..c25c310 100644 --- a/src/arcaea_offline/external/arcsong/arcsong_json.py +++ b/src/arcaea_offline/external/arcsong/arcsong_json.py @@ -122,7 +122,9 @@ class ArcSongJsonBuilder: pack = self.session.scalar(select(Pack).where(Pack.id == song.set)) 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__") song_localized = self.session.scalar( select(SongLocalized).where(SongLocalized.id == song.id) diff --git a/src/arcaea_offline/models/common.py b/src/arcaea_offline/models/common.py index 19880a1..0a6069b 100644 --- a/src/arcaea_offline/models/common.py +++ b/src/arcaea_offline/models/common.py @@ -1,8 +1,12 @@ +# pylint: disable=too-few-public-methods + from sqlalchemy.orm import DeclarativeBase from sqlalchemy.orm.exc import DetachedInstanceError class ReprHelper: + # pylint: disable=no-member + def _repr(self, **kwargs) -> str: """ Helper for __repr__ diff --git a/src/arcaea_offline/models/config.py b/src/arcaea_offline/models/config.py index f201e94..69fd973 100644 --- a/src/arcaea_offline/models/config.py +++ b/src/arcaea_offline/models/config.py @@ -1,3 +1,5 @@ +# pylint: disable=too-few-public-methods + from sqlalchemy import TEXT from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column diff --git a/src/arcaea_offline/models/scores.py b/src/arcaea_offline/models/scores.py index c605e41..3d9fd3a 100644 --- a/src/arcaea_offline/models/scores.py +++ b/src/arcaea_offline/models/scores.py @@ -1,3 +1,5 @@ +# pylint: disable=too-few-public-methods, duplicate-code + from typing import Optional from sqlalchemy import TEXT, case, func, inspect, select, text @@ -37,7 +39,8 @@ class Score(ScoresBase): comment="0: NORMAL, 1: EASY, 2: HARD" ) 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()) diff --git a/src/arcaea_offline/models/songs.py b/src/arcaea_offline/models/songs.py index 65c5ba8..aa31a74 100644 --- a/src/arcaea_offline/models/songs.py +++ b/src/arcaea_offline/models/songs.py @@ -1,3 +1,5 @@ +# pylint: disable=too-few-public-methods, duplicate-code + from typing import Optional from sqlalchemy import TEXT, ForeignKey, func, select @@ -154,7 +156,7 @@ class ChartInfo(SongsBase): ForeignKey("difficulties.rating_class"), primary_key=True ) 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]] diff --git a/src/arcaea_offline/searcher.py b/src/arcaea_offline/searcher.py index 89dd515..55c5c3e 100644 --- a/src/arcaea_offline/searcher.py +++ b/src/arcaea_offline/searcher.py @@ -103,7 +103,7 @@ class Searcher: 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 = self.default_query_parser.parse(query_string) with self.index.searcher() as searcher: