diff --git a/.github/actions/set-up-legacy-python/action.yml b/.github/actions/set-up-legacy-python/action.yml index 791c7db8..af693ff9 100644 --- a/.github/actions/set-up-legacy-python/action.yml +++ b/.github/actions/set-up-legacy-python/action.yml @@ -22,6 +22,6 @@ runs: command: pip install -U pip - name: Install dependencies run: | - python -m pip install flake8 pytest setuptools wheel + python -m pip install flake8 pyright pytest setuptools wheel if [ -f requirements.txt ]; then pip install -r requirements.txt; fi shell: bash diff --git a/.github/workflows/python-tests.yml b/.github/workflows/python-tests.yml index 2bc891cb..3cfe0c02 100644 --- a/.github/workflows/python-tests.yml +++ b/.github/workflows/python-tests.yml @@ -30,7 +30,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - python -m pip install flake8 pyright pyflakes pytest setuptools wheel + python -m pip install flake8 pyright pytest setuptools wheel if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - name: Lint with flake8 run: | @@ -38,9 +38,6 @@ jobs: - name: Lint with pyright (type checking) run: | pyright cfbs - - name: Lint with pyflakes - run: | - pyflakes cfbs - name: Test with pytest run: | pytest @@ -73,10 +70,13 @@ jobs: python-version: ${{ matrix.python-version }} - name: Lint with flake8 run: | - flake8 . --ignore=E203,W503,E722,E731 --max-complexity=100 --max-line-length=160 + python -m flake8 . --ignore=E203,W503,E722,E731 --max-complexity=100 --max-line-length=160 + - name: Lint with pyright (type checking) + run: | + python -m pyright cfbs - name: Test with pytest run: | - pytest + python -m pytest - name: Install run: | python setup.py sdist bdist_wheel diff --git a/cfbs/analyze.py b/cfbs/analyze.py index 1784d3b9..0341bb4e 100644 --- a/cfbs/analyze.py +++ b/cfbs/analyze.py @@ -73,12 +73,14 @@ def checksums_files( files_dir_path, checksums_dict=None, files_dict=None, - ignored_path_components=[], + ignored_path_components=None, ): if checksums_dict is None: checksums_dict = copy.deepcopy(DEFAULT_CHECKSUMS_DICT) if files_dict is None: files_dict = copy.deepcopy(DEFAULT_FILES_DICT) + if ignored_path_components is None: + ignored_path_components = [] for root, _, files in os.walk(files_dir_path): for name in files: @@ -230,7 +232,7 @@ def mpf_normalized_path(path, is_parentpath: bool, masterfiles_dir): `path` should be a path inside the masterfiles directory (or inside the parent directory, if `is_parentpath` is `True`). """ # downloaded MPF release information filepaths always have forward slashes - norm_path = path.replace(os.sep, "/") + norm_path = path.replace(os.sep, "/") # type: str if is_parentpath: if norm_path.startswith(masterfiles_dir + "/"): diff --git a/cfbs/args.py b/cfbs/args.py index a90e3520..f9f53139 100644 --- a/cfbs/args.py +++ b/cfbs/args.py @@ -1,6 +1,6 @@ import argparse import os -from typing import List, Union +from typing import List, Optional # noqa: F401 from cfbs import commands from cfbs.utils import cache, CFBSExitError @@ -9,31 +9,33 @@ class ArgsTypesNamespace(argparse.Namespace): """Manual type hints to args attributes""" - command: Union[str, None] - args: List[str] - loglevel: str - manual: bool - version: bool - force: bool - non_interactive: bool - index: Union[str, None] - check: bool - checksum: Union[str, None] - keep_order: bool - git: Union[bool, None] - git_user_name: Union[str, None] - git_user_email: Union[str, None] - git_commit_message: Union[str, None] - ignore_versions_json: bool - omit_download: bool - check_against_git: bool - minimum_version: Union[str, None] - to_json: Union[str, None] - reference_version: Union[str, None] - masterfiles_dir: Union[str, None] - ignored_path_components: List[str] - offline: bool - masterfiles: Union[str, None] + # PEP 484 style type hints for compatibility with Python 3.5. + # This commit can be reverted, and type hints returned to the PEP 526 style type hints, once the supported Python version becomes 3.6+. + command = None # type: Optional[str] + args = [] # type: List[str] + loglevel = "warning" # type: str + manual = False # type: bool + version = False # type: bool + force = False # type: bool + non_interactive = False # type: bool + index = None # type: Optional[str] + check = False # type: bool + checksum = None # type: Optional[str] + keep_order = False # type: bool + git = None # type: Optional[bool] + git_user_name = None # type: Optional[str] + git_user_email = None # type: Optional[str] + git_commit_message = None # type: Optional[str] + ignore_versions_json = False # type: bool + omit_download = False # type: bool + check_against_git = False # type: bool + minimum_version = None # type: Optional[str] + to_json = None # type: Optional[str] + reference_version = None # type: Optional[str] + masterfiles_dir = None # type: Optional[str] + ignored_path_components = None # type: Optional[List[str]] + offline = False # type: bool + masterfiles = None # type: Optional[str] def get_args(): diff --git a/cfbs/cfbs_types.py b/cfbs/cfbs_types.py index 0e9bf0ea..b5421556 100644 --- a/cfbs/cfbs_types.py +++ b/cfbs/cfbs_types.py @@ -1,10 +1,36 @@ -from typing import List, NamedTuple, Union +from typing import List, NamedTuple, Optional CFBSCommandExitCode = int -class CFBSCommandGitResult(NamedTuple): - return_code: int - do_commit: bool = True - commit_message: Union[str, None] = None - commit_files: List[str] = [] +# The usual, not `class`-based, method of defining a `typing.NamedTuple` type does not support default values, +# and it seems that the `class`-based method's constructor does not work with the Python 3.5 PEP 484[1] comment type hints. +# Thus, for compatibility with Python 3.5, a more verbose definition of `CFBSCommandGitResult` is used. +# This commit can be reverted, and type hints returned to the PEP 526 style type hints[2], once the supported Python version becomes 3.6+. +# References: +# [1]: https://peps.python.org/pep-0484/#type-comments +# [2]: https://peps.python.org/pep-0526/#class-and-instance-variable-annotations +_CFBSCommandGitResult = NamedTuple( + "_CFBSCommandGitResult", + [ + ("return_code", int), + ("do_commit", bool), + ("commit_message", Optional[str]), + ("commit_files", List[str]), + ], +) + + +class CFBSCommandGitResult(_CFBSCommandGitResult): + def __new__( + cls, + return_code: int, + do_commit: bool = True, + commit_message: Optional[str] = None, + commit_files: Optional[List[str]] = None, + ): + if commit_files is None: + commit_files = [] + return super(CFBSCommandGitResult, cls).__new__( + cls, return_code, do_commit, commit_message, commit_files + ) diff --git a/cfbs/commands.py b/cfbs/commands.py index cd8a80d2..d2b26eeb 100644 --- a/cfbs/commands.py +++ b/cfbs/commands.py @@ -205,7 +205,7 @@ def init_command( "description": description, "build": [], } - ) + ) # type: OrderedDict[str, str | List | bool] if index: config["index"] = index