diff --git a/.circleci/config.yml b/.circleci/config.yml index 96e88466..8f73efb1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -17,12 +17,9 @@ jobs: steps: - checkout - run: python --version ; pip --version ; pwd ; ls -l - - run: pip install black codespell flake8 ruff + - run: pip install black codespell ruff - run: codespell -L queenland,uint - # stop the build if there are Python syntax errors or undefined names - - run: flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics - # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide - - run: flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + - run: ruff . - run: black . --check diff --git a/STYLE_GUIDE.rst b/STYLE_GUIDE.rst index 14f91df5..a25c04ff 100644 --- a/STYLE_GUIDE.rst +++ b/STYLE_GUIDE.rst @@ -1,12 +1,11 @@ STYLE GUIDE ============== -As a rough style guide, please lint your code with black, codespell, and flake8:: +As a rough style guide, please lint your code with black, codespell, and ruff:: - pip install black codespell flake8 + pip install black codespell ruff codespell -L queenland,uint - flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics - flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + ruff . black . --check More up-to-date checks may be detailed in `.circleci/config.yml`. diff --git a/docs/source/conf.py b/docs/source/conf.py index ead7fdd3..4fc4f46e 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -10,7 +10,9 @@ # All configuration values have a default; values that are commented out # serve to show the default. -import sys, os +import os +import sys + import sc2reader autodoc_member_order = "bysource" diff --git a/examples/sc2autosave.py b/examples/sc2autosave.py index dae7bff1..59c573f0 100755 --- a/examples/sc2autosave.py +++ b/examples/sc2autosave.py @@ -192,8 +192,9 @@ def run(args): replay = sc2reader.load_replay(path, load_level=2) except KeyboardInterrupt: raise - except: + except Exception as e: # Failure to parse + args.log.write(f"{e!r}") file_name = os.path.basename(path) directory = make_directory(args, ("parse_error",)) new_path = os.path.join(directory, file_name) diff --git a/examples/sc2store.py b/examples/sc2store.py index 6aff2a98..77d0e71b 100755 --- a/examples/sc2store.py +++ b/examples/sc2store.py @@ -11,8 +11,6 @@ from pprint import PrettyPrinter -pprint = PrettyPrinter(indent=2).pprint - from sqlalchemy import create_engine from sqlalchemy import Column, ForeignKey, distinct, Table from sqlalchemy import Integer, String, Sequence, DateTime @@ -23,6 +21,8 @@ from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.ext.associationproxy import association_proxy +pprint = PrettyPrinter(indent=2).pprint + Base = declarative_base() party_member = Table( diff --git a/ruff.toml b/ruff.toml new file mode 100644 index 00000000..57d86cdc --- /dev/null +++ b/ruff.toml @@ -0,0 +1,7 @@ +ignore = [ + "F401", # module imported but unused; consider using `importlib.util.find_spec` to test for availability + "F403", # Run `removestar` on this codebase + "F405", # Run `removestar` on this codebase + "F841", # Run `ruff --select=F841 --fix .` +] +line-length=129 diff --git a/sc2reader/constants.py b/sc2reader/constants.py index db34afa7..a1ae473f 100644 --- a/sc2reader/constants.py +++ b/sc2reader/constants.py @@ -1,3 +1,6 @@ +import json +import pkgutil + # These are found in Repack-MPQ/fileset.{locale}#Mods#Core.SC2Mod#{locale}.SC2Data/LocalizedData/Editor/EditorCategoryStrings.txt # EDSTR_CATEGORY_Race # EDSTR_PLAYERPROPS_RACE @@ -101,9 +104,6 @@ } -import json -import pkgutil - attributes_json = pkgutil.get_data("sc2reader.data", "attributes.json").decode("utf8") attributes_dict = json.loads(attributes_json) LOBBY_PROPERTIES = dict() diff --git a/sc2reader/engine/plugins/context.py b/sc2reader/engine/plugins/context.py index 4adfc0e1..6b0d05dc 100644 --- a/sc2reader/engine/plugins/context.py +++ b/sc2reader/engine/plugins/context.py @@ -263,7 +263,7 @@ def handleUnitTypeChangeEvent(self, event, replay): replay.datapack.change_type(event.unit, event.unit_type_name, event.frame) else: self.logger.error( - "Unit {} type changed at {} [{}] before it was born!".format( + "Unit {} type changed at {} before it was born!".format( event.unit_id, Length(seconds=event.second) ) ) diff --git a/sc2reader/engine/plugins/selection.py b/sc2reader/engine/plugins/selection.py index 006ac78e..4dcc80c2 100644 --- a/sc2reader/engine/plugins/selection.py +++ b/sc2reader/engine/plugins/selection.py @@ -76,7 +76,9 @@ def _deselect(self, selection, mode, data): if mode == "Mask": # Deselect objects according to deselect mask - sfilter = lambda bit_u: not bit_u[0] + def sfilter(bit_u): + return not bit_u[0] + mask = data + [False] * (selection_size - data_size) new_selection = [u for (bit, u) in filter(sfilter, zip(mask, selection))] error = data_size > selection_size diff --git a/sc2reader/factories/plugins/replay.py b/sc2reader/factories/plugins/replay.py index 7f645eb3..16e31ed0 100644 --- a/sc2reader/factories/plugins/replay.py +++ b/sc2reader/factories/plugins/replay.py @@ -85,7 +85,6 @@ def toDict(replay): "is_ladder": getattr(replay, "is_ladder", False), "is_private": getattr(replay, "is_private", False), "filename": getattr(replay, "filename", None), - "file_time": getattr(replay, "file_time", None), "frames": getattr(replay, "frames", None), "build": getattr(replay, "build", None), "release": getattr(replay, "release_string", None), diff --git a/sc2reader/factories/sc2factory.py b/sc2reader/factories/sc2factory.py index c020459f..c5298eb3 100644 --- a/sc2reader/factories/sc2factory.py +++ b/sc2reader/factories/sc2factory.py @@ -266,13 +266,13 @@ def load_remote_resource_contents(self, remote_resource, **options): return resource def cache_has(self, cache_key): - raise NotImplemented() + raise NotImplementedError() def cache_get(self, cache_key): - raise NotImplemented() + raise NotImplementedError() def cache_set(self, cache_key, value): - raise NotImplemented() + raise NotImplementedError() class FileCachedSC2Factory(CachedSC2Factory): diff --git a/sc2reader/resources.py b/sc2reader/resources.py index 924f7bde..e74a9d7c 100644 --- a/sc2reader/resources.py +++ b/sc2reader/resources.py @@ -1491,8 +1491,8 @@ def __init__(self, header_file, filename=None, **options): # Parse localization hashes l18n_struct = self.data[0][4][8] - for l in l18n_struct: - parsed_hash = utils.parse_hash(l[1][0]) - self.localization_urls[l[0]] = utils.get_resource_url( + for h in l18n_struct: + parsed_hash = utils.parse_hash(h[1][0]) + self.localization_urls[h[0]] = utils.get_resource_url( parsed_hash["server"], parsed_hash["hash"], parsed_hash["type"] ) diff --git a/sc2reader/scripts/sc2replayer.py b/sc2reader/scripts/sc2replayer.py index d78410b0..c569c5ad 100755 --- a/sc2reader/scripts/sc2replayer.py +++ b/sc2reader/scripts/sc2replayer.py @@ -32,7 +32,8 @@ def getch(): from msvcrt import getch except ImportError as e: # We can't make getch happen, just dump events to the screen - getch = lambda: True + def getch(): + return True import argparse diff --git a/sc2reader/utils.py b/sc2reader/utils.py index 514ca807..9dcb5735 100644 --- a/sc2reader/utils.py +++ b/sc2reader/utils.py @@ -163,11 +163,14 @@ def get_files( # If an extension is supplied, use it to do a type check if extension: - type_check = ( - lambda path: os.path.splitext(path)[1][1:].lower() == extension.lower() - ) + + def type_check(path): + return os.path.splitext(path)[1][1:].lower() == extension.lower() + else: - type_check = lambda n: True + + def type_check(n): + return True # os.walk can't handle file paths, only directories if os.path.isfile(path): @@ -315,7 +318,6 @@ def toDict(replay): "is_ladder": getattr(replay, "is_ladder", False), "is_private": getattr(replay, "is_private", False), "filename": getattr(replay, "filename", None), - "file_time": getattr(replay, "file_time", None), "frames": getattr(replay, "frames", None), "build": getattr(replay, "build", None), "release": getattr(replay, "release_string", None),