From fded5a826523426ac46aada6729e95f856c20974 Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Thu, 26 Nov 2020 09:12:28 +0000 Subject: [PATCH 001/105] Try using workflow commands rather than checks API. --- flake8_github_action/__init__.py | 98 +++++------------------------- flake8_github_action/__main__.py | 22 +------ flake8_github_action/annotation.py | 7 +++ 3 files changed, 23 insertions(+), 104 deletions(-) diff --git a/flake8_github_action/__init__.py b/flake8_github_action/__init__.py index 7d71057..c9308cf 100644 --- a/flake8_github_action/__init__.py +++ b/flake8_github_action/__init__.py @@ -28,16 +28,7 @@ # stdlib import json -from typing import List, Tuple, Union - -# 3rd party -import click -import dulwich.errors -from apeye import URL -from domdf_python_tools.iterative import chunks -from domdf_python_tools.secrets import Secret -from dulwich.repo import Repo -from requests import Response +from typing import List # this package from flake8_github_action.annotation import Annotation @@ -54,57 +45,14 @@ def action( - token: Union[str, Secret], - repo: Union[str, URL, None] = None, *args, - ) -> Tuple[Response, int]: + ) -> int: r""" Action! - :param token: The token to authenticate with the GitHub API. - :param repo: The repository name (in the format /) or the complete GitHub URL. :param \*args: flake8 command line arguments. """ - if not isinstance(token, Secret): - token = Secret(token) - - dulwich_repo = Repo('.') - - if repo is None: - try: - config = dulwich_repo.get_config() - repo = URL(config.get(("remote", "origin"), "url").decode("UTF-8")) - except dulwich.errors.NotGitRepository as e: - raise click.UsageError(str(e)) - - elif not isinstance(repo, URL): - repo = URL(repo) - - if repo.suffix == ".git": - repo = repo.with_suffix('') - - repo_name = repo.name - - # first case is for full url, second for github/hello_world - github_username = repo.parent.name or repo.domain.domain - - check = Checks( - owner=github_username, - repository_name=repo_name, - check_name="Flake8", - head_sha=dulwich_repo.head().decode("UTF-8"), - token=token.value, - ) - - # check_run_id = check.create_check_run() - check_run_id = check.find_run_for_action() - check.update_check_run( - check_run_id, - status="in_progress", - output={"title": "Flake8 checks", "summary": "Output from Flake8"}, - ) - flake8_app = Application() flake8_app.run(args) flake8_app.exit() @@ -115,34 +63,16 @@ def action( for filename, raw_annotations in json_annotations: annotations.extend(Annotation.from_flake8json(filename, ann) for ann in raw_annotations) + if flake8_app.result_count: + ret = 1 + else: + ret = 0 + if annotations: - # Github limits updates to 50 annotations at a time - annotation_chunks = list(chunks(annotations, 50)) - - if flake8_app.result_count: - conclusion = "failure" - ret = 1 - else: - conclusion = "success" - ret = 0 - - for chunk in annotation_chunks[:-1]: - check.update_check_run( - check_run_id, - conclusion=conclusion, - output={ - "title": "Flake8 checks", - "summary": "Output from Flake8", - "annotations": [a.to_dict() for a in chunk], - }, - ) - - output = { - "title": "Flake8 checks", - "summary": "Output from Flake8", - "annotations": [a.to_dict() for a in annotation_chunks[-1]], - } - - return check.complete_check_run(check_run_id, conclusion=conclusion, output=output), ret - - return check.complete_check_run(check_run_id, conclusion="success"), 0 + for annotation in annotations: + print(annotation.to_str()) + + return ret + + + diff --git a/flake8_github_action/__main__.py b/flake8_github_action/__main__.py index 6803876..f646b5e 100644 --- a/flake8_github_action/__main__.py +++ b/flake8_github_action/__main__.py @@ -42,24 +42,6 @@ token_var = "GITHUB_TOKEN" -@click.option( - "-t", - "--token", - type=click.STRING, - help=( - "The token to authenticate with the GitHub API. " - f"Can also be provided via the '{token_var}' environment variable." - ), - envvar=token_var, - required=True, - ) -@click.option( - "-r", - "--repo", - type=click.STRING, - default=None, - help="The repository name (in the format /) or the complete GitHub URL.", - ) @click.option( "--annotate-only", is_flag=True, @@ -68,7 +50,7 @@ ) @click.command(context_settings={"ignore_unknown_options": True, "allow_extra_args": True, **CONTEXT_SETTINGS}) @click.pass_context -def main(ctx: click.Context, token: str, repo: Union[str, URL, None] = None, annotate_only: bool = False,): +def main(ctx: click.Context, repo: Union[str, URL, None] = None, annotate_only: bool = False,): """ Run flake8 and add the errors as annotations on GitHub. """ @@ -76,7 +58,7 @@ def main(ctx: click.Context, token: str, repo: Union[str, URL, None] = None, ann # this package from flake8_github_action import action - response, ret = action(token, repo, *ctx.args) + response, ret = action(repo, *ctx.args) # if response.status_code == 200: # sys.exit(0) diff --git a/flake8_github_action/annotation.py b/flake8_github_action/annotation.py index cdd5f68..3939532 100644 --- a/flake8_github_action/annotation.py +++ b/flake8_github_action/annotation.py @@ -108,3 +108,10 @@ def from_flake8json(cls, filename: str, data: Mapping[str, Any]): annotation_level="warning", message="{code}: {text}".format_map(data) ) + + def to_str(self) -> str: + return ( + f"::{self.annotation_level} " + f"file={self.path},line={self.start_line},col={self.start_column}" + f"::{self.message}" + ) From ab3f5d5199fefa03a375f61f21815007ab53f9ec Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Thu, 26 Nov 2020 09:14:20 +0000 Subject: [PATCH 002/105] Remove old but of code left behind. --- flake8_github_action/__main__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flake8_github_action/__main__.py b/flake8_github_action/__main__.py index f646b5e..066d98c 100644 --- a/flake8_github_action/__main__.py +++ b/flake8_github_action/__main__.py @@ -50,7 +50,7 @@ ) @click.command(context_settings={"ignore_unknown_options": True, "allow_extra_args": True, **CONTEXT_SETTINGS}) @click.pass_context -def main(ctx: click.Context, repo: Union[str, URL, None] = None, annotate_only: bool = False,): +def main(ctx: click.Context, annotate_only: bool = False,): """ Run flake8 and add the errors as annotations on GitHub. """ @@ -58,7 +58,7 @@ def main(ctx: click.Context, repo: Union[str, URL, None] = None, annotate_only: # this package from flake8_github_action import action - response, ret = action(repo, *ctx.args) + response, ret = action(*ctx.args) # if response.status_code == 200: # sys.exit(0) From bf97018fed8146958cdf50548683fc5b0f6bf8cc Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Thu, 26 Nov 2020 09:32:34 +0000 Subject: [PATCH 003/105] Refactor to simplify code. --- flake8_github_action/__init__.py | 30 +----- flake8_github_action/__main__.py | 28 +----- flake8_github_action/checks.py | 146 ----------------------------- flake8_github_action/flake8_app.py | 62 ++++++++---- requirements.txt | 4 - 5 files changed, 51 insertions(+), 219 deletions(-) delete mode 100644 flake8_github_action/checks.py diff --git a/flake8_github_action/__init__.py b/flake8_github_action/__init__.py index c9308cf..6c8407e 100644 --- a/flake8_github_action/__init__.py +++ b/flake8_github_action/__init__.py @@ -26,13 +26,11 @@ # OR OTHER DEALINGS IN THE SOFTWARE. # -# stdlib -import json -from typing import List +# 3rd party +from typing_extensions import NoReturn # this package from flake8_github_action.annotation import Annotation -from flake8_github_action.checks import Checks from flake8_github_action.flake8_app import Application __author__: str = "Dominic Davis-Foster" @@ -44,9 +42,7 @@ __all__ = ["action"] -def action( - *args, - ) -> int: +def action(*args, ) -> NoReturn: r""" Action! @@ -56,23 +52,3 @@ def action( flake8_app = Application() flake8_app.run(args) flake8_app.exit() - - annotations: List[Annotation] = [] - - json_annotations = json.loads(flake8_app.formatter.output_fd.getvalue()).items() - for filename, raw_annotations in json_annotations: - annotations.extend(Annotation.from_flake8json(filename, ann) for ann in raw_annotations) - - if flake8_app.result_count: - ret = 1 - else: - ret = 0 - - if annotations: - for annotation in annotations: - print(annotation.to_str()) - - return ret - - - diff --git a/flake8_github_action/__main__.py b/flake8_github_action/__main__.py index 066d98c..7cfe4db 100644 --- a/flake8_github_action/__main__.py +++ b/flake8_github_action/__main__.py @@ -28,45 +28,27 @@ # stdlib import sys -from typing import Union # 3rd party import click -from apeye import URL - -__all__ = ["main"] - -# 3rd party from consolekit import CONTEXT_SETTINGS -token_var = "GITHUB_TOKEN" +__all__ = ["main"] -@click.option( - "--annotate-only", - is_flag=True, - default=False, - help="Only add the annotations (exit 0 regardless of flake8 output).", - ) @click.command(context_settings={"ignore_unknown_options": True, "allow_extra_args": True, **CONTEXT_SETTINGS}) @click.pass_context -def main(ctx: click.Context, annotate_only: bool = False,): +def main(ctx: click.Context): """ Run flake8 and add the errors as annotations on GitHub. + + All options and arguments are passed through to flake8. """ # this package from flake8_github_action import action - response, ret = action(*ctx.args) - - # if response.status_code == 200: - # sys.exit(0) - - if annotate_only: - sys.exit(0) - else: - sys.exit(ret) + action(*ctx.args) if __name__ == "__main__": diff --git a/flake8_github_action/checks.py b/flake8_github_action/checks.py deleted file mode 100644 index 61d7452..0000000 --- a/flake8_github_action/checks.py +++ /dev/null @@ -1,146 +0,0 @@ -#!/usr/bin/env python3 -# -# checks.py -""" -Provides access to GitHub's Check's API. -""" -# -# Copyright (c) 2020 Dominic Davis-Foster -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# - -# stdlib -import os -from datetime import datetime - -# 3rd party -import apeye -import attr -from domdf_python_tools.secrets import Secret -from requests import Response -from typing_extensions import Literal - -__all__ = ["Checks"] - -API_GITHUB_COM = api = apeye.RequestsURL("https://api.github.com") - -common_headers = { - "accept": "application/vnd.github.v3+json", - "User-Agent": "github.com/domdfcoding/flake8-github-action", - } - - -@attr.s -class Checks: - """ - Provides access to GitHub's Check's API. - """ - - #: The owner of the repository - owner: str = attr.ib() - - #: The name of the repository - repository_name: str = attr.ib() - - #: The name of the check - check_name: str = attr.ib() - - #: The commit SHA to associate the check with. - head_sha: str = attr.ib() - - #: The token used to authenticate with the GitHub api. - token: Secret = attr.ib(converter=Secret) - - def find_run_for_action(self) -> int: - """ - Returns the check run ID that corresponds to the current GitHub Actions run. - """ - - url = API_GITHUB_COM / "repos" / self.owner / self.repository_name / "commits" / self.head_sha / "check-runs" - headers = {**common_headers, "Authorization": f"token {self.token.value}"} - - workflow_name = os.environ.get("GITHUB_WORKFLOW") - - for check_run in url.get(headers=headers).json()["check_runs"]: - if check_run["name"] == workflow_name: - return check_run["id"] - - raise ValueError(f"Can't find a check run for workflow with name {workflow_name}") - - def create_check_run(self) -> int: - """ - Create a check and return its ID. - """ - - # Create the check run - body_json = { - "name": self.check_name, - "head_sha": self.head_sha, - "status": "in_progress", - "started_at": datetime.now().strftime("%Y-%m-%dT%H:%M:%SZ") - } - - headers = {**common_headers, "Authorization": f"token {self.token.value}"} - url = api / "repos" / self.owner / self.repository_name / "check-runs" - - response = url.post(json=body_json, headers=headers) - - check_run_id = response.json()["id"] - # check_suite_id = response.json()["check_suite"]["id"] - - return check_run_id - - def update_check_run(self, check_run_id: int, **kwargs) -> Response: - r""" - Update a check. - - :param check_run_id: - :param \*\*kwargs: - """ - - # Create the check run - body_json = {"name": self.check_name, **kwargs} - - headers = {**common_headers, "Authorization": f"token {self.token.value}"} - url = api / "repos" / self.owner / self.repository_name / "check-runs" / str(check_run_id) - - return url.patch(json=body_json, headers=headers) - - def complete_check_run( - self, - check_run_id: int, - conclusion: Literal["success", "failure", "cancelled", "skipped", "timed_out", "action_required"], - **kwargs - ) -> Response: - r""" - Update a check and mark it as complete. - - :param check_run_id: - :param conclusion: - :param \*\*kwargs: - """ - - return self.update_check_run( - check_run_id, - status="completed", - conclusion=conclusion, - completed_at=datetime.now().strftime("%Y-%m-%dT%H:%M:%SZ"), - **kwargs, - ) diff --git a/flake8_github_action/flake8_app.py b/flake8_github_action/flake8_app.py index 15bf2a5..8260680 100644 --- a/flake8_github_action/flake8_app.py +++ b/flake8_github_action/flake8_app.py @@ -32,16 +32,21 @@ # # stdlib +import json from functools import partial from gettext import ngettext from io import StringIO -from typing import Optional, Tuple, Type +from typing import List, Optional, Tuple, Type # 3rd party import click import flake8.main.application # type: ignore from flake8.formatting.base import BaseFormatter # type: ignore from flake8_json_reporter.reporters import DefaultJSON # type: ignore +from typing_extensions import NoReturn + +# this package +from flake8_github_action.annotation import Annotation __all__ = ["Application", "JsonFormatter"] @@ -54,7 +59,7 @@ class Application(flake8.main.application.Application): Subclass of Flake8's ``Application``. """ - def exit(self) -> None: + def exit(self) -> NoReturn: """ Handle finalization and exiting the program. @@ -62,23 +67,23 @@ def exit(self) -> None: It will check certain options and exit appropriately. """ - # if self.options.count: - if True: - files_checked = self.file_checker_manager.statistics["files"] - files_with_errors = self.file_checker_manager.statistics["files_with_errors"] - if self.result_count: - click.echo( - f"Found {self.result_count} {_error(self.result_count)} " - f"in {files_with_errors} {_file(files_with_errors)} " - f"(checked {files_checked} source {_file(files_checked)})" - ) - else: - click.echo(f"Success: no issues found in {files_checked} source {_file(files_checked)}") - - # if self.options.exit_zero: - # raise SystemExit(self.catastrophic_failure) - # else: - # raise SystemExit((self.result_count > 0) or self.catastrophic_failure) + if self.options.count: + if True: + files_checked = self.file_checker_manager.statistics["files"] + files_with_errors = self.file_checker_manager.statistics["files_with_errors"] + if self.result_count: + click.echo( + f"Found {self.result_count} {_error(self.result_count)} " + f"in {files_with_errors} {_file(files_with_errors)} " + f"(checked {files_checked} source {_file(files_checked)})" + ) + else: + click.echo(f"Success: no issues found in {files_checked} source {_file(files_checked)}") + + if self.options.exit_zero: + raise SystemExit(self.catastrophic_failure) + else: + raise SystemExit((self.result_count > 0) or self.catastrophic_failure) def report_errors(self) -> None: """ @@ -122,6 +127,22 @@ def make_formatter(self, formatter_class: Optional[Type[BaseFormatter]] = None) self.formatter = JsonFormatter(self.options) + def report(self): + """ + Report errors, statistics, and benchmarks. + """ + + super().report() + + annotations: List[Annotation] = [] + + json_annotations = json.loads(self.formatter.output_fd.getvalue()).items() + for filename, raw_annotations in json_annotations: + annotations.extend(Annotation.from_flake8json(filename, ann) for ann in raw_annotations) + + for annotation in annotations: + print(annotation.to_str()) + class JsonFormatter(DefaultJSON): @@ -129,3 +150,6 @@ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.output_fd = StringIO() + + + diff --git a/requirements.txt b/requirements.txt index 4794f8a..69ba8f2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,10 +1,6 @@ -apeye>=0.4.0 attrs>=20.3.0 click>=7.1.2 consolekit>=0.6.0 -domdf-python-tools>=1.7.0 -dulwich>=0.20.13 flake8>=3.8.4 flake8-json>=19.8.0 -requests>=2.25.0 typing-extensions>=3.7.4.3 From faff711b1ebedcba8a65e11955221bb8b6938c14 Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Thu, 26 Nov 2020 09:35:04 +0000 Subject: [PATCH 004/105] Print filenames to give some reference in the GitHub Actions Log. --- .github/workflows/flake8.yml | 2 +- flake8_github_action/flake8_app.py | 13 ++++--------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/.github/workflows/flake8.yml b/.github/workflows/flake8.yml index 43cec72..4b7ae3e 100644 --- a/.github/workflows/flake8.yml +++ b/.github/workflows/flake8.yml @@ -29,6 +29,6 @@ jobs: python -m pip install . - name: "Run Flake8" - run: "python -m flake8_github_action flake8_github_action" + run: "python -m flake8_github_action flake8_github_action --exit-zero" env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/flake8_github_action/flake8_app.py b/flake8_github_action/flake8_app.py index 8260680..d4619b3 100644 --- a/flake8_github_action/flake8_app.py +++ b/flake8_github_action/flake8_app.py @@ -134,14 +134,12 @@ def report(self): super().report() - annotations: List[Annotation] = [] - json_annotations = json.loads(self.formatter.output_fd.getvalue()).items() - for filename, raw_annotations in json_annotations: - annotations.extend(Annotation.from_flake8json(filename, ann) for ann in raw_annotations) - for annotation in annotations: - print(annotation.to_str()) + for filename, raw_annotations in json_annotations: + print(filename) + for annotation in raw_annotations: + print(Annotation.from_flake8json(filename, annotation).to_str()) class JsonFormatter(DefaultJSON): @@ -150,6 +148,3 @@ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.output_fd = StringIO() - - - From dca16759fa7244cf0321d7398c639fc4ad15dadd Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Thu, 26 Nov 2020 09:36:48 +0000 Subject: [PATCH 005/105] Only print filename if there are annotations for it. --- flake8_github_action/flake8_app.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/flake8_github_action/flake8_app.py b/flake8_github_action/flake8_app.py index d4619b3..9e2df46 100644 --- a/flake8_github_action/flake8_app.py +++ b/flake8_github_action/flake8_app.py @@ -137,7 +137,9 @@ def report(self): json_annotations = json.loads(self.formatter.output_fd.getvalue()).items() for filename, raw_annotations in json_annotations: - print(filename) + if raw_annotations: + print(filename) + for annotation in raw_annotations: print(Annotation.from_flake8json(filename, annotation).to_str()) @@ -148,3 +150,6 @@ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.output_fd = StringIO() + + + From ab2d039d8d638e8ce86517f4891f68285c6b36bf Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Thu, 26 Nov 2020 09:54:29 +0000 Subject: [PATCH 006/105] Move check formatting into custom Formatter --- flake8_github_action/__init__.py | 1 - flake8_github_action/__main__.py | 4 + flake8_github_action/annotation.py | 117 ----------------------------- flake8_github_action/flake8_app.py | 62 +++++++++------ requirements.txt | 2 - 5 files changed, 42 insertions(+), 144 deletions(-) delete mode 100644 flake8_github_action/annotation.py diff --git a/flake8_github_action/__init__.py b/flake8_github_action/__init__.py index 6c8407e..996b86c 100644 --- a/flake8_github_action/__init__.py +++ b/flake8_github_action/__init__.py @@ -30,7 +30,6 @@ from typing_extensions import NoReturn # this package -from flake8_github_action.annotation import Annotation from flake8_github_action.flake8_app import Application __author__: str = "Dominic Davis-Foster" diff --git a/flake8_github_action/__main__.py b/flake8_github_action/__main__.py index 7cfe4db..9012f7e 100644 --- a/flake8_github_action/__main__.py +++ b/flake8_github_action/__main__.py @@ -53,3 +53,7 @@ def main(ctx: click.Context): if __name__ == "__main__": sys.exit(main(obj={})) + + + + diff --git a/flake8_github_action/annotation.py b/flake8_github_action/annotation.py deleted file mode 100644 index 3939532..0000000 --- a/flake8_github_action/annotation.py +++ /dev/null @@ -1,117 +0,0 @@ -#!/usr/bin/env python3 -# -# annotation.py -""" -Class to model a GitHub Check Annotation. -""" -# -# Copyright © 2020 Dominic Davis-Foster -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -# OR OTHER DEALINGS IN THE SOFTWARE. -# - -# stdlib -from typing import Any, Mapping, MutableMapping - -# 3rd party -import attr -from typing_extensions import Literal - -__all__ = ["Annotation"] - - -@attr.s -class Annotation: - """ - Class to model a GitHub Check Annotation. - """ - - #: The path of the file to add an annotation to. For example, ``assets/css/main.css``. - path: str = attr.ib() - - #: The start line of the annotation. - start_line: int = attr.ib() - - #: The end line of the annotation. - end_line: int = attr.ib() - - #: The level of the annotation. Can be one of notice, warning, or failure. - annotation_level: Literal["notice", "warning", "failure"] = attr.ib() - - #: A short description of the feedback for these lines of code. The maximum size is 64 KB. - message: str = attr.ib() - - start_column: int = attr.ib(default=None) - """ - The start column of the annotation. - Annotations only support start_column and end_column on the same line. - Omit this parameter if start_line and end_line have different values. - """ - - end_column: int = attr.ib(default=None) - """ - The end column of the annotation. - Annotations only support start_column and end_column on the same line. - Omit this parameter if start_line and end_line have different values. - """ - - #: The title that represents the annotation. The maximum size is 255 characters. - title: str = attr.ib(default=None) - - #: Details about this annotation. The maximum size is 64 KB. - raw_details: str = attr.ib(default=None) - - def to_dict(self) -> MutableMapping[str, Any]: - data = { - "path": self.path, - "start_line": self.start_line, - "end_line": self.end_line, - "annotation_level": self.annotation_level, - "message": self.message, - } - - for attr in [ - "start_column", - "end_column", - "title", - "raw_details", - ]: - if getattr(self, attr) is not None: - data[attr] = getattr(self, attr) - - return data - - @classmethod - def from_flake8json(cls, filename: str, data: Mapping[str, Any]): - return cls( - path=filename, - start_line=data["line_number"], - end_line=data["line_number"], - start_column=data["column_number"], - end_column=data["column_number"], - annotation_level="warning", - message="{code}: {text}".format_map(data) - ) - - def to_str(self) -> str: - return ( - f"::{self.annotation_level} " - f"file={self.path},line={self.start_line},col={self.start_column}" - f"::{self.message}" - ) diff --git a/flake8_github_action/flake8_app.py b/flake8_github_action/flake8_app.py index 9e2df46..0e591a7 100644 --- a/flake8_github_action/flake8_app.py +++ b/flake8_github_action/flake8_app.py @@ -30,25 +30,23 @@ # Copyright (C) 2012-2016 Ian Cordasco # MIT Licensed # +# "GitHubFormatter" based on https://gitlab.com/pycqa/flake8-json +# Copyright (C) 2017-2018 Ian Stapleton Cordasco +# MIT Licensed +# # stdlib -import json from functools import partial from gettext import ngettext -from io import StringIO -from typing import List, Optional, Tuple, Type +from typing import Optional, Tuple, Type # 3rd party import click import flake8.main.application # type: ignore from flake8.formatting.base import BaseFormatter # type: ignore -from flake8_json_reporter.reporters import DefaultJSON # type: ignore from typing_extensions import NoReturn -# this package -from flake8_github_action.annotation import Annotation - -__all__ = ["Application", "JsonFormatter"] +__all__ = ["Application", "GitHubFormatter"] _error = partial(ngettext, "error", "errors") _file = partial(ngettext, "file", "files") @@ -125,31 +123,47 @@ def make_formatter(self, formatter_class: Optional[Type[BaseFormatter]] = None) Initialize a formatter based on the parsed options. """ - self.formatter = JsonFormatter(self.options) + self.formatter = GitHubFormatter(self.options) - def report(self): - """ - Report errors, statistics, and benchmarks. - """ - super().report() +class GitHubFormatter(BaseFormatter): - json_annotations = json.loads(self.formatter.output_fd.getvalue()).items() + def write_line(self, line): + """ + Override write for convenience. + """ + self.write(line, None) - for filename, raw_annotations in json_annotations: - if raw_annotations: - print(filename) + def start(self): + super().start() + self.files_reported_count = 0 - for annotation in raw_annotations: - print(Annotation.from_flake8json(filename, annotation).to_str()) + def beginning(self, filename): + """ + We're starting a new file. + """ + self.reported_errors_count = 0 -class JsonFormatter(DefaultJSON): + def finished(self, filename): + """ + We've finished processing a file. + """ - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) + self.files_reported_count += 1 - self.output_fd = StringIO() + def format(self, violation): + """ + Format a violation. + """ + if self.reported_errors_count == 0: + self.write_line(violation.filename) + self.write_line( + f"::warning " + f"file={violation.filename},line={violation.line_number},col={violation.column_number}" + f"::{violation.code}: {violation.text}" + ) + self.reported_errors_count += 1 diff --git a/requirements.txt b/requirements.txt index 69ba8f2..435ada9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,4 @@ -attrs>=20.3.0 click>=7.1.2 consolekit>=0.6.0 flake8>=3.8.4 -flake8-json>=19.8.0 typing-extensions>=3.7.4.3 From aca6fcebc2ba9909ca5667e111642960ec490820 Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Thu, 26 Nov 2020 10:35:11 +0000 Subject: [PATCH 007/105] Refactor into just a flake8 formatter. --- .github/workflows/flake8.yml | 3 +- .isort.cfg | 1 + flake8_github_action/__init__.py | 22 +--- flake8_github_action/__main__.py | 59 ---------- flake8_github_action/flake8_app.py | 169 ----------------------------- flake8_github_action/reporters | 86 +++++++++++++++ repo_helper.yml | 4 + requirements.txt | 3 - setup.cfg | 3 + tox.ini | 7 +- 10 files changed, 100 insertions(+), 257 deletions(-) delete mode 100644 flake8_github_action/__main__.py delete mode 100644 flake8_github_action/flake8_app.py create mode 100644 flake8_github_action/reporters diff --git a/.github/workflows/flake8.yml b/.github/workflows/flake8.yml index 4b7ae3e..604ff9d 100644 --- a/.github/workflows/flake8.yml +++ b/.github/workflows/flake8.yml @@ -26,9 +26,10 @@ jobs: python -VV python -m site python -m pip install --upgrade pip setuptools wheel + python -m pip install flake8-prettycount python -m pip install . - name: "Run Flake8" - run: "python -m flake8_github_action flake8_github_action --exit-zero" + run: "python -m flake8_prettycount flake8_github_action --exit-zero" env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.isort.cfg b/.isort.cfg index 7800ed5..0705ab5 100644 --- a/.isort.cfg +++ b/.isort.cfg @@ -21,6 +21,7 @@ known_third_party = dulwich flake8 flake8_json + flake8_prettycount github github3_py requests diff --git a/flake8_github_action/__init__.py b/flake8_github_action/__init__.py index 996b86c..de442eb 100644 --- a/flake8_github_action/__init__.py +++ b/flake8_github_action/__init__.py @@ -2,7 +2,7 @@ # # __init__.py """ -GitHub Action to run flake8. +GitHub Actions integration for flake8. """ # # Copyright © 2020 Dominic Davis-Foster @@ -26,28 +26,8 @@ # OR OTHER DEALINGS IN THE SOFTWARE. # -# 3rd party -from typing_extensions import NoReturn - -# this package -from flake8_github_action.flake8_app import Application - __author__: str = "Dominic Davis-Foster" __copyright__: str = "2020 Dominic Davis-Foster" __license__: str = "MIT License" __version__: str = "0.0.0" __email__: str = "dominic@davis-foster.co.uk" - -__all__ = ["action"] - - -def action(*args, ) -> NoReturn: - r""" - Action! - - :param \*args: flake8 command line arguments. - """ - - flake8_app = Application() - flake8_app.run(args) - flake8_app.exit() diff --git a/flake8_github_action/__main__.py b/flake8_github_action/__main__.py deleted file mode 100644 index 9012f7e..0000000 --- a/flake8_github_action/__main__.py +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/env python3 -# -# __main__.py -""" -CLI entry point. -""" -# -# Copyright (c) 2020 Dominic Davis-Foster -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# - -# stdlib -import sys - -# 3rd party -import click -from consolekit import CONTEXT_SETTINGS - -__all__ = ["main"] - - -@click.command(context_settings={"ignore_unknown_options": True, "allow_extra_args": True, **CONTEXT_SETTINGS}) -@click.pass_context -def main(ctx: click.Context): - """ - Run flake8 and add the errors as annotations on GitHub. - - All options and arguments are passed through to flake8. - """ - - # this package - from flake8_github_action import action - - action(*ctx.args) - - -if __name__ == "__main__": - sys.exit(main(obj={})) - - - - diff --git a/flake8_github_action/flake8_app.py b/flake8_github_action/flake8_app.py deleted file mode 100644 index 0e591a7..0000000 --- a/flake8_github_action/flake8_app.py +++ /dev/null @@ -1,169 +0,0 @@ -#!/usr/bin/env python3 -# -# flake8_app.py -""" -Subclass of Flake8's ``Application``. -""" -# -# Copyright (c) 2020 Dominic Davis-Foster -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# -# "Application" based on Flake8 -# Copyright (C) 2011-2013 Tarek Ziade -# Copyright (C) 2012-2016 Ian Cordasco -# MIT Licensed -# -# "GitHubFormatter" based on https://gitlab.com/pycqa/flake8-json -# Copyright (C) 2017-2018 Ian Stapleton Cordasco -# MIT Licensed -# - -# stdlib -from functools import partial -from gettext import ngettext -from typing import Optional, Tuple, Type - -# 3rd party -import click -import flake8.main.application # type: ignore -from flake8.formatting.base import BaseFormatter # type: ignore -from typing_extensions import NoReturn - -__all__ = ["Application", "GitHubFormatter"] - -_error = partial(ngettext, "error", "errors") -_file = partial(ngettext, "file", "files") - - -class Application(flake8.main.application.Application): - """ - Subclass of Flake8's ``Application``. - """ - - def exit(self) -> NoReturn: - """ - Handle finalization and exiting the program. - - This should be the last thing called on the application instance. - It will check certain options and exit appropriately. - """ - - if self.options.count: - if True: - files_checked = self.file_checker_manager.statistics["files"] - files_with_errors = self.file_checker_manager.statistics["files_with_errors"] - if self.result_count: - click.echo( - f"Found {self.result_count} {_error(self.result_count)} " - f"in {files_with_errors} {_file(files_with_errors)} " - f"(checked {files_checked} source {_file(files_checked)})" - ) - else: - click.echo(f"Success: no issues found in {files_checked} source {_file(files_checked)}") - - if self.options.exit_zero: - raise SystemExit(self.catastrophic_failure) - else: - raise SystemExit((self.result_count > 0) or self.catastrophic_failure) - - def report_errors(self) -> None: - """ - Report all the errors found by flake8 3.0. - - This also updates the :attr:`result_count` attribute with the total - number of errors, warnings, and other messages found. - """ - - flake8.main.application.LOG.info("Reporting errors") - - files_with_errors = results_reported = results_found = 0 - - for checker in self.file_checker_manager._all_checkers: - results_ = sorted(checker.results, key=lambda tup: (tup[1], tup[2])) - filename = checker.display_name - - with self.file_checker_manager.style_guide.processing_file(filename): - results_reported_for_file = self.file_checker_manager._handle_results(filename, results_) - if results_reported_for_file: - results_reported += results_reported_for_file - files_with_errors += 1 - - results_found += len(results_) - - results: Tuple[int, int] = (results_found, results_reported) - - self.total_result_count, self.result_count = results - flake8.main.application.LOG.info( - "Found a total of %d violations and reported %d", - self.total_result_count, - self.result_count, - ) - - self.file_checker_manager.statistics["files_with_errors"] = files_with_errors - - def make_formatter(self, formatter_class: Optional[Type[BaseFormatter]] = None) -> None: - """ - Initialize a formatter based on the parsed options. - """ - - self.formatter = GitHubFormatter(self.options) - - -class GitHubFormatter(BaseFormatter): - - def write_line(self, line): - """ - Override write for convenience. - """ - self.write(line, None) - - def start(self): - super().start() - self.files_reported_count = 0 - - def beginning(self, filename): - """ - We're starting a new file. - """ - - self.reported_errors_count = 0 - - def finished(self, filename): - """ - We've finished processing a file. - """ - - self.files_reported_count += 1 - - def format(self, violation): - """ - Format a violation. - """ - - if self.reported_errors_count == 0: - self.write_line(violation.filename) - - self.write_line( - f"::warning " - f"file={violation.filename},line={violation.line_number},col={violation.column_number}" - f"::{violation.code}: {violation.text}" - ) - - self.reported_errors_count += 1 diff --git a/flake8_github_action/reporters b/flake8_github_action/reporters new file mode 100644 index 0000000..af15c20 --- /dev/null +++ b/flake8_github_action/reporters @@ -0,0 +1,86 @@ +#!/usr/bin/env python3 +# +# flake8_app.py +""" +Subclass of Flake8's ``Application``. +""" +# +# Copyright (c) 2020 Dominic Davis-Foster +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +# "GitHubFormatter" based on https://gitlab.com/pycqa/flake8-json +# Copyright (C) 2017-2018 Ian Stapleton Cordasco +# MIT Licensed +# + +# stdlib +from functools import partial +from gettext import ngettext + +# 3rd party +from flake8.formatting.base import BaseFormatter # type: ignore + +__all__ = ["GitHubFormatter"] + +_error = partial(ngettext, "error", "errors") +_file = partial(ngettext, "file", "files") + + +class GitHubFormatter(BaseFormatter): + + def write_line(self, line): + """ + Override write for convenience. + """ + self.write(line, None) + + def start(self): + super().start() + self.files_reported_count = 0 + + def beginning(self, filename): + """ + We're starting a new file. + """ + + self.reported_errors_count = 0 + + def finished(self, filename): + """ + We've finished processing a file. + """ + + self.files_reported_count += 1 + + def format(self, violation): + """ + Format a violation. + """ + + if self.reported_errors_count == 0: + self.write_line(violation.filename) + + self.write_line( + f"::warning " + f"file={violation.filename},line={violation.line_number},col={violation.column_number}" + f"::{violation.code}: {violation.text}" + ) + + self.reported_errors_count += 1 diff --git a/repo_helper.yml b/repo_helper.yml index 44922c0..718d4cb 100644 --- a/repo_helper.yml +++ b/repo_helper.yml @@ -27,3 +27,7 @@ keywords: - flake8 - github - github-actions + +entry_points: + flake8.report: + - github = flake8_github_action.reporters:GitHubFormatter diff --git a/requirements.txt b/requirements.txt index 435ada9..4163a01 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1 @@ -click>=7.1.2 -consolekit>=0.6.0 flake8>=3.8.4 -typing-extensions>=3.7.4.3 diff --git a/setup.cfg b/setup.cfg index 9da3b7f..afe129e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -47,3 +47,6 @@ python_version = 3.6 namespace_packages = True check_untyped_defs = True warn_unused_ignores = True + +[options.entry_points] +flake8.report = github = flake8_github_action.reporters:GitHubFormatter diff --git a/tox.ini b/tox.ini index a0b0a1f..584497e 100644 --- a/tox.ini +++ b/tox.ini @@ -70,7 +70,7 @@ deps = git+https://github.com/PyCQA/pydocstyle@5118faa7173b0e5bbc230c4adf628758e13605bf git+https://github.com/domdfcoding/flake8-quotes.git git+https://github.com/domdfcoding/flake8-rst-docstrings.git - git+https://github.com/domdfcoding/flake8-rst-docstrings-sphinx.git + git+https://github.com/domdfcoding/flake8-rst-docstrings-sphinx.git@v2 pygments>=2.7.1 commands = python3 -m flake8_rst_docstrings_sphinx flake8_github_action --allow-toolbox @@ -131,6 +131,5 @@ addopts = --color yes --durations 25 timeout = 300 [dep_checker] -name_mapping = - flake8_json = flake8_json_reporter - attrs = attr +allowed_unused = + flake8 From a4a750b56e85f72b649e8e33342f6aeb4e72e76f Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Thu, 26 Nov 2020 10:44:50 +0000 Subject: [PATCH 008/105] Consolidate in __init__.py --- .github/workflows/flake8.yml | 2 +- flake8_github_action/__init__.py | 58 +++++++++++++++++++++ flake8_github_action/reporters | 86 -------------------------------- repo_helper.yml | 2 +- setup.cfg | 2 +- 5 files changed, 61 insertions(+), 89 deletions(-) delete mode 100644 flake8_github_action/reporters diff --git a/.github/workflows/flake8.yml b/.github/workflows/flake8.yml index 604ff9d..05e5ef7 100644 --- a/.github/workflows/flake8.yml +++ b/.github/workflows/flake8.yml @@ -30,6 +30,6 @@ jobs: python -m pip install . - name: "Run Flake8" - run: "python -m flake8_prettycount flake8_github_action --exit-zero" + run: "python -m flake8_prettycount flake8_github_action --exit-zero --format github" env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/flake8_github_action/__init__.py b/flake8_github_action/__init__.py index de442eb..999b4c1 100644 --- a/flake8_github_action/__init__.py +++ b/flake8_github_action/__init__.py @@ -26,8 +26,66 @@ # OR OTHER DEALINGS IN THE SOFTWARE. # +# stdlib +from functools import partial +from gettext import ngettext + +# 3rd party +from flake8.formatting.base import BaseFormatter # type: ignore + __author__: str = "Dominic Davis-Foster" __copyright__: str = "2020 Dominic Davis-Foster" __license__: str = "MIT License" __version__: str = "0.0.0" __email__: str = "dominic@davis-foster.co.uk" + +__all__ = ["GitHubFormatter"] + +_error = partial(ngettext, "error", "errors") +_file = partial(ngettext, "file", "files") + + +class GitHubFormatter(BaseFormatter): + + def write_line(self, line): + """ + Override write for convenience. + """ + self.write(line, None) + + def start(self): + super().start() + self.files_reported_count = 0 + + def beginning(self, filename): + """ + We're starting a new file. + """ + + self.reported_errors_count = 0 + + def finished(self, filename): + """ + We've finished processing a file. + """ + + self.files_reported_count += 1 + + def format(self, violation): + """ + Format a violation. + """ + + if self.reported_errors_count == 0: + self.write_line(violation.filename) + + self.write_line( + f"::warning " + f"file={violation.filename},line={violation.line_number},col={violation.column_number}" + f"::{violation.code}: {violation.text}" + ) + + self.reported_errors_count += 1 + + + diff --git a/flake8_github_action/reporters b/flake8_github_action/reporters deleted file mode 100644 index af15c20..0000000 --- a/flake8_github_action/reporters +++ /dev/null @@ -1,86 +0,0 @@ -#!/usr/bin/env python3 -# -# flake8_app.py -""" -Subclass of Flake8's ``Application``. -""" -# -# Copyright (c) 2020 Dominic Davis-Foster -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# -# "GitHubFormatter" based on https://gitlab.com/pycqa/flake8-json -# Copyright (C) 2017-2018 Ian Stapleton Cordasco -# MIT Licensed -# - -# stdlib -from functools import partial -from gettext import ngettext - -# 3rd party -from flake8.formatting.base import BaseFormatter # type: ignore - -__all__ = ["GitHubFormatter"] - -_error = partial(ngettext, "error", "errors") -_file = partial(ngettext, "file", "files") - - -class GitHubFormatter(BaseFormatter): - - def write_line(self, line): - """ - Override write for convenience. - """ - self.write(line, None) - - def start(self): - super().start() - self.files_reported_count = 0 - - def beginning(self, filename): - """ - We're starting a new file. - """ - - self.reported_errors_count = 0 - - def finished(self, filename): - """ - We've finished processing a file. - """ - - self.files_reported_count += 1 - - def format(self, violation): - """ - Format a violation. - """ - - if self.reported_errors_count == 0: - self.write_line(violation.filename) - - self.write_line( - f"::warning " - f"file={violation.filename},line={violation.line_number},col={violation.column_number}" - f"::{violation.code}: {violation.text}" - ) - - self.reported_errors_count += 1 diff --git a/repo_helper.yml b/repo_helper.yml index 718d4cb..1f1f5ba 100644 --- a/repo_helper.yml +++ b/repo_helper.yml @@ -30,4 +30,4 @@ keywords: entry_points: flake8.report: - - github = flake8_github_action.reporters:GitHubFormatter + - github = flake8_github_action:GitHubFormatter diff --git a/setup.cfg b/setup.cfg index afe129e..585e058 100644 --- a/setup.cfg +++ b/setup.cfg @@ -49,4 +49,4 @@ check_untyped_defs = True warn_unused_ignores = True [options.entry_points] -flake8.report = github = flake8_github_action.reporters:GitHubFormatter +flake8.report = github = flake8_github_action:GitHubFormatter From f3a48e216e82138c3a576b1c7aef78973696f31d Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Thu, 26 Nov 2020 10:49:00 +0000 Subject: [PATCH 009/105] Add usage info to README.rst --- .github/workflows/flake8.yml | 4 +--- README.rst | 42 ++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/.github/workflows/flake8.yml b/.github/workflows/flake8.yml index 05e5ef7..167e2c0 100644 --- a/.github/workflows/flake8.yml +++ b/.github/workflows/flake8.yml @@ -30,6 +30,4 @@ jobs: python -m pip install . - name: "Run Flake8" - run: "python -m flake8_prettycount flake8_github_action --exit-zero --format github" - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: "python -m flake8_prettycount flake8_github_action --format github" diff --git a/README.rst b/README.rst index a295278..50da323 100644 --- a/README.rst +++ b/README.rst @@ -94,3 +94,45 @@ Installation .. start installation .. end installation + + +Use with GitHub Actions +---------------------------- + +Example workflow: + +.. code-block:: yaml + + --- + + name: Flake8 + + on: + push: + pull_request: + branches: ["master"] + + jobs: + Run: + name: "Flake8" + runs-on: "ubuntu-18.04" + + steps: + - name: Checkout 🛎️ + uses: "actions/checkout@v2" + + - name: Setup Python 🐍 + uses: "actions/setup-python@v2" + with: + python-version: "3.8" + + - name: Install dependencies 🔧 + run: | + python -VV + python -m site + python -m pip install --upgrade pip setuptools wheel + python -m pip install flake8 + python -m pip install git+https://github.com/domdfcoding/flake8-github-actions + + - name: "Run Flake8" + run: "flake8 --format github" From 7b87b2e34d14dbb7d5f7a85719bb7790fff26ef2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 26 Nov 2020 10:51:22 +0000 Subject: [PATCH 010/105] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- flake8_github_action/__init__.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/flake8_github_action/__init__.py b/flake8_github_action/__init__.py index 999b4c1..5ac1d35 100644 --- a/flake8_github_action/__init__.py +++ b/flake8_github_action/__init__.py @@ -86,6 +86,3 @@ def format(self, violation): ) self.reported_errors_count += 1 - - - From 476f3d504e010fbac3ef3a10847e6e986f55956a Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Thu, 26 Nov 2020 10:53:20 +0000 Subject: [PATCH 011/105] Updated files with 'repo_helper'. (#2) Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> From 0aefe28b2b8389e67185cc20af51eb4a37e1f4e5 Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Thu, 26 Nov 2020 11:00:23 +0000 Subject: [PATCH 012/105] Fix typo's indentation. --- flake8_github_action/__init__.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/flake8_github_action/__init__.py b/flake8_github_action/__init__.py index 5ac1d35..85ad6ee 100644 --- a/flake8_github_action/__init__.py +++ b/flake8_github_action/__init__.py @@ -79,10 +79,10 @@ def format(self, violation): if self.reported_errors_count == 0: self.write_line(violation.filename) - self.write_line( - f"::warning " - f"file={violation.filename},line={violation.line_number},col={violation.column_number}" - f"::{violation.code}: {violation.text}" - ) + self.write_line( + f"::warning " + f"file={violation.filename},line={violation.line_number},col={violation.column_number}" + f"::{violation.code}: {violation.text}" + ) self.reported_errors_count += 1 From a5040c84a25d5919afa20917778968db1b2a669a Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Thu, 26 Nov 2020 11:10:02 +0000 Subject: [PATCH 013/105] Updated config files. --- .github/workflows/octocheese.yml | 18 ++++++++++++++++++ README.rst | 14 ++++++++++++-- repo_helper.yml | 3 +-- setup.py | 2 +- 4 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/octocheese.yml diff --git a/.github/workflows/octocheese.yml b/.github/workflows/octocheese.yml new file mode 100644 index 0000000..82e3cad --- /dev/null +++ b/.github/workflows/octocheese.yml @@ -0,0 +1,18 @@ +# This file is managed by 'repo_helper'. Don't edit it directly. +--- + +name: "GitHub Releases" +on: + push: + schedule: + - cron: 0 12 * * 2,4,6 + +jobs: + Run: + runs-on: ubuntu-latest + steps: + - uses: domdfcoding/octocheese@master + with: + pypi_name: "flake8-github-action" + env: + GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} diff --git a/README.rst b/README.rst index 50da323..2f9ff6b 100644 --- a/README.rst +++ b/README.rst @@ -4,7 +4,7 @@ flake8-github-action .. start short_desc -**GitHub Action to run flake8.** +**GitHub Actions integration for flake8.** .. end short_desc @@ -17,7 +17,8 @@ flake8-github-action * - Tests - |travis| |actions_windows| |actions_macos| |codefactor| |pre_commit_ci| - + * - PyPI + - |pypi-version| |supported-versions| |supported-implementations| |wheel| * - Activity - |commits-latest| |commits-since| |maintained| * - Other @@ -93,6 +94,15 @@ Installation -------------- .. start installation + +``flake8-github-action`` can be installed from PyPI. + +To install with ``pip``: + +.. code-block:: bash + + $ python -m pip install flake8-github-action + .. end installation diff --git a/repo_helper.yml b/repo_helper.yml index 1f1f5ba..a93e075 100644 --- a/repo_helper.yml +++ b/repo_helper.yml @@ -7,12 +7,11 @@ email: 'dominic@davis-foster.co.uk' username: 'domdfcoding' version: '0.0.0' license: 'MIT' -short_desc: 'GitHub Action to run flake8.' +short_desc: 'GitHub Actions integration for flake8.' enable_conda: false enable_tests: false enable_docs: false -on_pypi: False python_versions: - 3.6 diff --git a/setup.py b/setup.py index 4a67ad2..499308a 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ from __pkginfo__ import * # pylint: disable=wildcard-import setup( - description="GitHub Action to run flake8.", + description="GitHub Actions integration for flake8.", extras_require=extras_require, install_requires=install_requires, py_modules=[], From 9f856db34a80e615daa6499185f4942cfd97467e Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Thu, 26 Nov 2020 11:11:30 +0000 Subject: [PATCH 014/105] Updated config files. --- .bumpversion.cfg | 2 +- .github/ISSUE_TEMPLATE/bug_report.md | 2 +- .github/ISSUE_TEMPLATE/feature_request.md | 2 +- .github/workflows/octocheese.yml | 2 +- .isort.cfg | 2 +- .pre-commit-config.yaml | 4 +- CONTRIBUTING.rst | 2 +- MANIFEST.in | 4 +- README.rst | 58 +++++++++---------- .../__init__.py | 0 repo_helper.yml | 4 +- setup.cfg | 10 ++-- tox.ini | 10 ++-- 13 files changed, 51 insertions(+), 51 deletions(-) rename {flake8_github_action => flake8_github_actions}/__init__.py (100%) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 24ffa82..acf4684 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -9,4 +9,4 @@ tag = True [bumpversion:file:README.rst] -[bumpversion:file:flake8_github_action/__init__.py] +[bumpversion:file:flake8_github_actions/__init__.py] diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 671951b..68a2fcb 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -38,7 +38,7 @@ THE ISSUE WILL BE CLOSED IF INSUFFICIENT INFORMATION IS PROVIDED. * Operating System: * Python: - * flake8-github-action: + * flake8-github-actions: ## Installation source diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index e2e6b5d..e19bfc2 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -20,7 +20,7 @@ assignees: domdfcoding * Operating System: * Python: - * flake8-github-action: + * flake8-github-actions: ## Other Additional Information: diff --git a/.github/workflows/octocheese.yml b/.github/workflows/octocheese.yml index 82e3cad..51e5be3 100644 --- a/.github/workflows/octocheese.yml +++ b/.github/workflows/octocheese.yml @@ -13,6 +13,6 @@ jobs: steps: - uses: domdfcoding/octocheese@master with: - pypi_name: "flake8-github-action" + pypi_name: "flake8-github-actions" env: GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} diff --git a/.isort.cfg b/.isort.cfg index 0705ab5..ef5ef93 100644 --- a/.isort.cfg +++ b/.isort.cfg @@ -26,4 +26,4 @@ known_third_party = github3_py requests typing_extensions -known_first_party = flake8_github_action +known_first_party = flake8_github_actions diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e40722b..d19c1a6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -38,7 +38,7 @@ repos: rev: v0.1.3 hooks: - id: ensure-dunder-all - files: ^flake8_github_action/.*\.py$ + files: ^flake8_github_actions/.*\.py$ - repo: https://github.com/pre-commit/pygrep-hooks rev: v1.7.0 @@ -69,6 +69,6 @@ repos: hooks: - id: dep_checker args: - - flake8_github_action + - flake8_github_actions # Custom hooks can be added below this comment diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index bd9ebf4..c91477a 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -4,7 +4,7 @@ Contributing .. This file based on https://github.com/PyGithub/PyGithub/blob/master/CONTRIBUTING.md -``flake8-github-action`` uses `tox `_ to automate testing and packaging, and `pre-commit `_ to maintain code quality. +``flake8-github-actions`` uses `tox `_ to automate testing and packaging, and `pre-commit `_ to maintain code quality. Install ``pre-commit`` with ``pip`` and install the git hook: diff --git a/MANIFEST.in b/MANIFEST.in index 0bde31e..51376c6 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -2,5 +2,5 @@ include __pkginfo__.py include LICENSE include requirements.txt prune **/__pycache__ -recursive-include flake8_github_action *.pyi -include flake8_github_action/py.typed +recursive-include flake8_github_actions *.pyi +include flake8_github_actions/py.typed diff --git a/README.rst b/README.rst index 2f9ff6b..6a32991 100644 --- a/README.rst +++ b/README.rst @@ -26,55 +26,55 @@ flake8-github-action -.. |travis| image:: https://github.com/domdfcoding/flake8-github-action/workflows/Linux%20Tests/badge.svg - :target: https://github.com/domdfcoding/flake8-github-action/actions?query=workflow%3A%22Linux+Tests%22 +.. |travis| image:: https://github.com/domdfcoding/flake8-github-actions/workflows/Linux%20Tests/badge.svg + :target: https://github.com/domdfcoding/flake8-github-actions/actions?query=workflow%3A%22Linux+Tests%22 :alt: Linux Test Status -.. |actions_windows| image:: https://github.com/domdfcoding/flake8-github-action/workflows/Windows%20Tests/badge.svg - :target: https://github.com/domdfcoding/flake8-github-action/actions?query=workflow%3A%22Windows+Tests%22 +.. |actions_windows| image:: https://github.com/domdfcoding/flake8-github-actions/workflows/Windows%20Tests/badge.svg + :target: https://github.com/domdfcoding/flake8-github-actions/actions?query=workflow%3A%22Windows+Tests%22 :alt: Windows Test Status -.. |actions_macos| image:: https://github.com/domdfcoding/flake8-github-action/workflows/macOS%20Tests/badge.svg - :target: https://github.com/domdfcoding/flake8-github-action/actions?query=workflow%3A%22macOS+Tests%22 +.. |actions_macos| image:: https://github.com/domdfcoding/flake8-github-actions/workflows/macOS%20Tests/badge.svg + :target: https://github.com/domdfcoding/flake8-github-actions/actions?query=workflow%3A%22macOS+Tests%22 :alt: macOS Test Status -.. |requires| image:: https://requires.io/github/domdfcoding/flake8-github-action/requirements.svg?branch=master - :target: https://requires.io/github/domdfcoding/flake8-github-action/requirements/?branch=master +.. |requires| image:: https://requires.io/github/domdfcoding/flake8-github-actions/requirements.svg?branch=master + :target: https://requires.io/github/domdfcoding/flake8-github-actions/requirements/?branch=master :alt: Requirements Status -.. |codefactor| image:: https://img.shields.io/codefactor/grade/github/domdfcoding/flake8-github-action?logo=codefactor - :target: https://www.codefactor.io/repository/github/domdfcoding/flake8-github-action +.. |codefactor| image:: https://img.shields.io/codefactor/grade/github/domdfcoding/flake8-github-actions?logo=codefactor + :target: https://www.codefactor.io/repository/github/domdfcoding/flake8-github-actions :alt: CodeFactor Grade -.. |pypi-version| image:: https://img.shields.io/pypi/v/flake8-github-action - :target: https://pypi.org/project/flake8-github-action/ +.. |pypi-version| image:: https://img.shields.io/pypi/v/flake8-github-actions + :target: https://pypi.org/project/flake8-github-actions/ :alt: PyPI - Package Version -.. |supported-versions| image:: https://img.shields.io/pypi/pyversions/flake8-github-action?logo=python&logoColor=white - :target: https://pypi.org/project/flake8-github-action/ +.. |supported-versions| image:: https://img.shields.io/pypi/pyversions/flake8-github-actions?logo=python&logoColor=white + :target: https://pypi.org/project/flake8-github-actions/ :alt: PyPI - Supported Python Versions -.. |supported-implementations| image:: https://img.shields.io/pypi/implementation/flake8-github-action - :target: https://pypi.org/project/flake8-github-action/ +.. |supported-implementations| image:: https://img.shields.io/pypi/implementation/flake8-github-actions + :target: https://pypi.org/project/flake8-github-actions/ :alt: PyPI - Supported Implementations -.. |wheel| image:: https://img.shields.io/pypi/wheel/flake8-github-action - :target: https://pypi.org/project/flake8-github-action/ +.. |wheel| image:: https://img.shields.io/pypi/wheel/flake8-github-actions + :target: https://pypi.org/project/flake8-github-actions/ :alt: PyPI - Wheel -.. |license| image:: https://img.shields.io/github/license/domdfcoding/flake8-github-action - :target: https://github.com/domdfcoding/flake8-github-action/blob/master/LICENSE +.. |license| image:: https://img.shields.io/github/license/domdfcoding/flake8-github-actions + :target: https://github.com/domdfcoding/flake8-github-actions/blob/master/LICENSE :alt: License -.. |language| image:: https://img.shields.io/github/languages/top/domdfcoding/flake8-github-action +.. |language| image:: https://img.shields.io/github/languages/top/domdfcoding/flake8-github-actions :alt: GitHub top language -.. |commits-since| image:: https://img.shields.io/github/commits-since/domdfcoding/flake8-github-action/v0.0.0 - :target: https://github.com/domdfcoding/flake8-github-action/pulse +.. |commits-since| image:: https://img.shields.io/github/commits-since/domdfcoding/flake8-github-actions/v0.0.0 + :target: https://github.com/domdfcoding/flake8-github-actions/pulse :alt: GitHub commits since tagged version -.. |commits-latest| image:: https://img.shields.io/github/last-commit/domdfcoding/flake8-github-action - :target: https://github.com/domdfcoding/flake8-github-action/commit/master +.. |commits-latest| image:: https://img.shields.io/github/last-commit/domdfcoding/flake8-github-actions + :target: https://github.com/domdfcoding/flake8-github-actions/commit/master :alt: GitHub last commit .. |maintained| image:: https://img.shields.io/maintenance/yes/2020 @@ -84,8 +84,8 @@ flake8-github-action :target: https://github.com/pre-commit/pre-commit :alt: pre-commit -.. |pre_commit_ci| image:: https://results.pre-commit.ci/badge/github/domdfcoding/flake8-github-action/master.svg - :target: https://results.pre-commit.ci/latest/github/domdfcoding/flake8-github-action/master +.. |pre_commit_ci| image:: https://results.pre-commit.ci/badge/github/domdfcoding/flake8-github-actions/master.svg + :target: https://results.pre-commit.ci/latest/github/domdfcoding/flake8-github-actions/master :alt: pre-commit.ci status .. end shields @@ -95,13 +95,13 @@ Installation .. start installation -``flake8-github-action`` can be installed from PyPI. +``flake8-github-actions`` can be installed from PyPI. To install with ``pip``: .. code-block:: bash - $ python -m pip install flake8-github-action + $ python -m pip install flake8-github-actions .. end installation diff --git a/flake8_github_action/__init__.py b/flake8_github_actions/__init__.py similarity index 100% rename from flake8_github_action/__init__.py rename to flake8_github_actions/__init__.py diff --git a/repo_helper.yml b/repo_helper.yml index a93e075..098f875 100644 --- a/repo_helper.yml +++ b/repo_helper.yml @@ -1,6 +1,6 @@ # Configuration for 'repo_helper' (https://github.com/domdfcoding/repo_helper) --- -modname: 'flake8-github-action' +modname: 'flake8-github-actions' copyright_years: '2020' author: 'Dominic Davis-Foster' email: 'dominic@davis-foster.co.uk' @@ -29,4 +29,4 @@ keywords: entry_points: flake8.report: - - github = flake8_github_action:GitHubFormatter + - github = flake8_github_actions:GitHubFormatter diff --git a/setup.cfg b/setup.cfg index 585e058..dc7c80d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -7,7 +7,7 @@ # * options.entry_points [metadata] -name = flake8-github-action +name = flake8-github-actions author = Dominic Davis-Foster author_email = dominic@davis-foster.co.uk license = MIT License @@ -15,10 +15,10 @@ keywords = flake8, github, github-actions long_description = file: README.rst long_description_content_type = text/x-rst platforms = Windows, macOS, Linux -url = https://github.com/domdfcoding/flake8-github-action +url = https://github.com/domdfcoding/flake8-github-actions project_urls = - Issue_Tracker = https://github.com/domdfcoding/flake8-github-action/issues - Source_Code = https://github.com/domdfcoding/flake8-github-action + Issue_Tracker = https://github.com/domdfcoding/flake8-github-actions/issues + Source_Code = https://github.com/domdfcoding/flake8-github-actions classifiers = License :: OSI Approved :: MIT License Operating System :: OS Independent @@ -49,4 +49,4 @@ check_untyped_defs = True warn_unused_ignores = True [options.entry_points] -flake8.report = github = flake8_github_action:GitHubFormatter +flake8.report = github = flake8_github_actions:GitHubFormatter diff --git a/tox.ini b/tox.ini index 584497e..c618d2c 100644 --- a/tox.ini +++ b/tox.ini @@ -72,7 +72,7 @@ deps = git+https://github.com/domdfcoding/flake8-rst-docstrings.git git+https://github.com/domdfcoding/flake8-rst-docstrings-sphinx.git@v2 pygments>=2.7.1 -commands = python3 -m flake8_rst_docstrings_sphinx flake8_github_action --allow-toolbox +commands = python3 -m flake8_rst_docstrings_sphinx flake8_github_actions --allow-toolbox [testenv:mypy] basepython = python3.6 @@ -81,7 +81,7 @@ changedir = {toxinidir} deps = mypy==0.790 lxml -commands = mypy flake8_github_action {posargs} +commands = mypy flake8_github_actions {posargs} [testenv:pyup] basepython = python3.6 @@ -89,7 +89,7 @@ skip_install = True ignore_errors = True changedir = {toxinidir} deps = pyupgrade-directories -commands = pyup_dirs flake8_github_action --py36-plus --recursive +commands = pyup_dirs flake8_github_actions --py36-plus --recursive [flake8] max-line-length = 120 @@ -123,8 +123,8 @@ exclude_lines = [check-wheel-contents] ignore = W002 -toplevel = flake8_github_action -package = flake8_github_action +toplevel = flake8_github_actions +package = flake8_github_actions [pytest] addopts = --color yes --durations 25 From 0dcd70ec729af64c23c50490ee22ba1ebcb977ca Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Thu, 26 Nov 2020 11:15:16 +0000 Subject: [PATCH 015/105] Updated files with 'repo_helper'. (#4) Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- README.rst | 1 - tox.ini | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 6a32991..cd271a6 100644 --- a/README.rst +++ b/README.rst @@ -105,7 +105,6 @@ To install with ``pip``: .. end installation - Use with GitHub Actions ---------------------------- diff --git a/tox.ini b/tox.ini index c618d2c..42e9900 100644 --- a/tox.ini +++ b/tox.ini @@ -71,8 +71,9 @@ deps = git+https://github.com/domdfcoding/flake8-quotes.git git+https://github.com/domdfcoding/flake8-rst-docstrings.git git+https://github.com/domdfcoding/flake8-rst-docstrings-sphinx.git@v2 + git+https://github.com/domdfcoding/flake8-github-actions pygments>=2.7.1 -commands = python3 -m flake8_rst_docstrings_sphinx flake8_github_actions --allow-toolbox +commands = python3 -m flake8_rst_docstrings_sphinx flake8_github_actions --allow-toolbox {posargs} [testenv:mypy] basepython = python3.6 From c202ea3fc497c6d6a4fc38b4d7ad8ce2e85dc82c Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Thu, 26 Nov 2020 19:56:45 +0000 Subject: [PATCH 016/105] Bump version v0.0.0 -> v0.1.0 --- .bumpversion.cfg | 2 +- README.rst | 2 +- __pkginfo__.py | 2 +- flake8_github_actions/__init__.py | 2 +- repo_helper.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index acf4684..d697d85 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.0.0 +current_version = 0.1.0 commit = True tag = True diff --git a/README.rst b/README.rst index cd271a6..45d6710 100644 --- a/README.rst +++ b/README.rst @@ -69,7 +69,7 @@ flake8-github-action .. |language| image:: https://img.shields.io/github/languages/top/domdfcoding/flake8-github-actions :alt: GitHub top language -.. |commits-since| image:: https://img.shields.io/github/commits-since/domdfcoding/flake8-github-actions/v0.0.0 +.. |commits-since| image:: https://img.shields.io/github/commits-since/domdfcoding/flake8-github-actions/v0.1.0 :target: https://github.com/domdfcoding/flake8-github-actions/pulse :alt: GitHub commits since tagged version diff --git a/__pkginfo__.py b/__pkginfo__.py index f107a7e..c20c43a 100644 --- a/__pkginfo__.py +++ b/__pkginfo__.py @@ -26,7 +26,7 @@ 2020 Dominic Davis-Foster """ -__version__ = "0.0.0" +__version__ = "0.1.0" repo_root = pathlib.Path(__file__).parent install_requires = (repo_root / "requirements.txt").read_text(encoding="utf-8").split('\n') diff --git a/flake8_github_actions/__init__.py b/flake8_github_actions/__init__.py index 85ad6ee..3dcd63d 100644 --- a/flake8_github_actions/__init__.py +++ b/flake8_github_actions/__init__.py @@ -36,7 +36,7 @@ __author__: str = "Dominic Davis-Foster" __copyright__: str = "2020 Dominic Davis-Foster" __license__: str = "MIT License" -__version__: str = "0.0.0" +__version__: str = "0.1.0" __email__: str = "dominic@davis-foster.co.uk" __all__ = ["GitHubFormatter"] diff --git a/repo_helper.yml b/repo_helper.yml index 098f875..100bf7f 100644 --- a/repo_helper.yml +++ b/repo_helper.yml @@ -5,7 +5,7 @@ copyright_years: '2020' author: 'Dominic Davis-Foster' email: 'dominic@davis-foster.co.uk' username: 'domdfcoding' -version: '0.0.0' +version: '0.1.0' license: 'MIT' short_desc: 'GitHub Actions integration for flake8.' From 343eeca22a9781af698193292cec4114e1ea2d72 Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Thu, 26 Nov 2020 20:36:13 +0000 Subject: [PATCH 017/105] Updated config files. --- .github/workflows/octocheese.yml | 1 + README.rst | 2 +- tox.ini | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/octocheese.yml b/.github/workflows/octocheese.yml index 51e5be3..def92f0 100644 --- a/.github/workflows/octocheese.yml +++ b/.github/workflows/octocheese.yml @@ -9,6 +9,7 @@ on: jobs: Run: + if: !startsWith(github.ref, 'refs/tags/') runs-on: ubuntu-latest steps: - uses: domdfcoding/octocheese@master diff --git a/README.rst b/README.rst index 45d6710..8aa3fe7 100644 --- a/README.rst +++ b/README.rst @@ -141,7 +141,7 @@ Example workflow: python -m site python -m pip install --upgrade pip setuptools wheel python -m pip install flake8 - python -m pip install git+https://github.com/domdfcoding/flake8-github-actions + python -m pip install flake8-github-actions - name: "Run Flake8" run: "flake8 --format github" diff --git a/tox.ini b/tox.ini index 42e9900..c7a3ba5 100644 --- a/tox.ini +++ b/tox.ini @@ -62,6 +62,7 @@ deps = flake8-builtins>=1.5.3 flake8-docstrings>=1.5.0 flake8-dunder-all>=0.1.1 + flake8-github-actions>=0.1.0 flake8-pyi>=20.10.0 flake8-pytest-style>=1.3.0 flake8-sphinx-links>=0.0.4 @@ -71,7 +72,6 @@ deps = git+https://github.com/domdfcoding/flake8-quotes.git git+https://github.com/domdfcoding/flake8-rst-docstrings.git git+https://github.com/domdfcoding/flake8-rst-docstrings-sphinx.git@v2 - git+https://github.com/domdfcoding/flake8-github-actions pygments>=2.7.1 commands = python3 -m flake8_rst_docstrings_sphinx flake8_github_actions --allow-toolbox {posargs} From 36a7e504cac02edaae6f7d602352717afa3b22b7 Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Thu, 26 Nov 2020 21:28:08 +0000 Subject: [PATCH 018/105] Fix octocheese action. --- .github/workflows/octocheese.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/octocheese.yml b/.github/workflows/octocheese.yml index def92f0..16d4cdd 100644 --- a/.github/workflows/octocheese.yml +++ b/.github/workflows/octocheese.yml @@ -9,7 +9,6 @@ on: jobs: Run: - if: !startsWith(github.ref, 'refs/tags/') runs-on: ubuntu-latest steps: - uses: domdfcoding/octocheese@master @@ -17,3 +16,4 @@ jobs: pypi_name: "flake8-github-actions" env: GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} + if: startsWith(github.ref, 'refs/tags/') != true From 1c3ad5e60c1f8472ddf4e00bac8b83bd28dd06a2 Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Fri, 27 Nov 2020 09:14:30 +0000 Subject: [PATCH 019/105] Updated README.rst --- README.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index 8aa3fe7..0b456be 100644 --- a/README.rst +++ b/README.rst @@ -1,6 +1,6 @@ -##################### -flake8-github-action -##################### +####################### +flake8-github-actions +####################### .. start short_desc From d38dba5363578c757bb39b611ef7143dc17c9c9b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 21 Dec 2020 22:25:38 +0000 Subject: [PATCH 020/105] [pre-commit.ci] pre-commit autoupdate (#5) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d19c1a6..c17e9f3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,7 +5,7 @@ exclude: ^$ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v3.3.0 + rev: v3.4.0 hooks: - id: check-added-large-files - id: check-ast From ede24fdd060263da4e8aa6e29a45b9b5a053ea77 Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Wed, 23 Dec 2020 23:01:13 +0000 Subject: [PATCH 021/105] Updated files with 'repo_helper'. (#6) Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .github/dependabot.yml | 10 ++++++++ .github/workflows/flake8.yml | 5 ++-- .github/workflows/mypy.yml | 37 +++++++++++++++++++++++++++ .github/workflows/octocheese.yml | 1 + .github/workflows/python_ci.yml | 19 +++++++++----- .github/workflows/python_ci_linux.yml | 29 +++++++++++++-------- .github/workflows/python_ci_macos.yml | 19 +++++++++----- .pre-commit-config.yaml | 3 +++ README.rst | 36 ++++++++++++++++---------- flake8_github_actions/__init__.py | 7 +++-- setup.cfg | 4 +-- tox.ini | 27 ++++++++++--------- 12 files changed, 138 insertions(+), 59 deletions(-) create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/mypy.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..e769ad3 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,10 @@ +# This file is managed by 'repo_helper'. Don't edit it directly. +--- +version: 2 +updates: +- package-ecosystem: pip + directory: / + schedule: + interval: weekly + reviewers: + - domdfcoding diff --git a/.github/workflows/flake8.yml b/.github/workflows/flake8.yml index 167e2c0..177294b 100644 --- a/.github/workflows/flake8.yml +++ b/.github/workflows/flake8.yml @@ -26,8 +26,7 @@ jobs: python -VV python -m site python -m pip install --upgrade pip setuptools wheel - python -m pip install flake8-prettycount - python -m pip install . + python -m pip install tox - name: "Run Flake8" - run: "python -m flake8_prettycount flake8_github_action --format github" + run: "python -m tox -e lint -- --format github" diff --git a/.github/workflows/mypy.yml b/.github/workflows/mypy.yml new file mode 100644 index 0000000..6be64e3 --- /dev/null +++ b/.github/workflows/mypy.yml @@ -0,0 +1,37 @@ +# This file is managed by 'repo_helper'. Don't edit it directly. +--- +name: mypy + +on: + push: + pull_request: + branches: ["master"] + +jobs: + Run: + name: "mypy / ${{ matrix.os }}" + runs-on: ${{ matrix.os }} + + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + fail-fast: false + + steps: + - name: Checkout 🛎️ + uses: "actions/checkout@v2" + + - name: Setup Python 🐍 + uses: "actions/setup-python@v2" + with: + python-version: "3.6" + + - name: Install dependencies 🔧 + run: | + python -VV + python -m site + python -m pip install --upgrade pip setuptools wheel + python -m pip install tox + + - name: "Run mypy" + run: "python -m tox -e mypy" diff --git a/.github/workflows/octocheese.yml b/.github/workflows/octocheese.yml index 16d4cdd..155d407 100644 --- a/.github/workflows/octocheese.yml +++ b/.github/workflows/octocheese.yml @@ -4,6 +4,7 @@ name: "GitHub Releases" on: push: + branches: ["master"] schedule: - cron: 0 12 * * 2,4,6 diff --git a/.github/workflows/python_ci.yml b/.github/workflows/python_ci.yml index 7578c5a..d0fe702 100644 --- a/.github/workflows/python_ci.yml +++ b/.github/workflows/python_ci.yml @@ -1,6 +1,6 @@ # This file is managed by 'repo_helper'. Don't edit it directly. --- -name: Windows Tests +name: Windows on: push: @@ -9,15 +9,20 @@ on: jobs: tests: - name: "Python ${{ matrix.python-version }}" + name: "windows-2019 / Python ${{ matrix.config.python-version }}" runs-on: "windows-2019" + continue-on-error: ${{ matrix.config.experimental }} env: USING_COVERAGE: '3.6,3.7,3.8,3.9' strategy: fail-fast: False matrix: - python-version: ["3.6","3.7","3.8","3.9"] + config: + - {python-version: "3.6", testenvs: "py36,build", experimental: False} + - {python-version: "3.7", testenvs: "py37,build", experimental: False} + - {python-version: "3.8", testenvs: "py38,build", experimental: False} + - {python-version: "3.9", testenvs: "py39,build", experimental: False} steps: - name: Checkout 🛎️ @@ -26,14 +31,14 @@ jobs: - name: Setup Python 🐍 uses: "actions/setup-python@v2" with: - python-version: "${{ matrix.python-version }}" + python-version: "${{ matrix.config.python-version }}" - name: Install dependencies 🔧 run: | python -VV python -m site python -m pip install --upgrade pip setuptools wheel - python -m pip install --upgrade tox tox-gh-actions virtualenv + python -m pip install --upgrade tox virtualenv - - name: "Run Tests for Python ${{ matrix.python-version }}" - run: "python -m tox" + - name: "Run Tests for Python ${{ matrix.config.python-version }}" + run: python -m tox -e "${{ matrix.config.testenvs }}" diff --git a/.github/workflows/python_ci_linux.yml b/.github/workflows/python_ci_linux.yml index bf1d4c8..41eb8fd 100644 --- a/.github/workflows/python_ci_linux.yml +++ b/.github/workflows/python_ci_linux.yml @@ -1,6 +1,6 @@ # This file is managed by 'repo_helper'. Don't edit it directly. --- -name: Linux Tests +name: Linux on: push: @@ -9,15 +9,20 @@ on: jobs: tests: - name: "Python ${{ matrix.python-version }}" - runs-on: "ubuntu-18.04" + name: "ubuntu-20.04 / Python ${{ matrix.config.python-version }}" + runs-on: "ubuntu-20.04" + continue-on-error: ${{ matrix.config.experimental }} env: USING_COVERAGE: '3.6,3.7,3.8,3.9' strategy: fail-fast: False matrix: - python-version: ["3.6","3.7","3.8","3.9"] + config: + - {python-version: "3.6", testenvs: "py36,build", experimental: False} + - {python-version: "3.7", testenvs: "py37,build", experimental: False} + - {python-version: "3.8", testenvs: "py38,build", experimental: False} + - {python-version: "3.9", testenvs: "py39,build", experimental: False} steps: - name: Checkout 🛎️ @@ -26,44 +31,48 @@ jobs: - name: Setup Python 🐍 uses: "actions/setup-python@v2" with: - python-version: "${{ matrix.python-version }}" + python-version: "${{ matrix.config.python-version }}" - name: Install dependencies 🔧 run: | python -VV python -m site python -m pip install --upgrade pip setuptools wheel - python -m pip install --upgrade tox tox-gh-actions virtualenv + python -m pip install --upgrade tox virtualenv - - name: "Run Tests for Python ${{ matrix.python-version }}" - run: "python -m tox" + - name: "Run Tests for Python ${{ matrix.config.python-version }}" + run: python -m tox -e "${{ matrix.config.testenvs }}" Deploy: needs: tests - runs-on: "ubuntu-18.04" + runs-on: "ubuntu-20.04" steps: - name: Checkout 🛎️ uses: "actions/checkout@v2" + if: startsWith(github.ref, 'refs/tags/') - name: Setup Python 🐍 uses: "actions/setup-python@v2" with: python-version: 3.8 + if: startsWith(github.ref, 'refs/tags/') - name: Install dependencies 🔧 run: | python -m pip install --upgrade pip setuptools wheel python -m pip install --upgrade tox + if: startsWith(github.ref, 'refs/tags/') - name: Build distributions 📦 run: | tox -e build + if: startsWith(github.ref, 'refs/tags/') - - name: Upload distribution 📦 to PyPI + - name: Upload distribution to PyPI 🚀 if: startsWith(github.ref, 'refs/tags/') uses: pypa/gh-action-pypi-publish@master with: diff --git a/.github/workflows/python_ci_macos.yml b/.github/workflows/python_ci_macos.yml index dbdba84..fc9cd1d 100644 --- a/.github/workflows/python_ci_macos.yml +++ b/.github/workflows/python_ci_macos.yml @@ -1,6 +1,6 @@ # This file is managed by 'repo_helper'. Don't edit it directly. --- -name: macOS Tests +name: macOS on: push: @@ -9,15 +9,20 @@ on: jobs: tests: - name: "Python ${{ matrix.python-version }}" + name: "macos-latest / Python ${{ matrix.config.python-version }}" runs-on: "macos-latest" + continue-on-error: ${{ matrix.config.experimental }} env: USING_COVERAGE: '3.6,3.7,3.8,3.9' strategy: fail-fast: False matrix: - python-version: ["3.6","3.7","3.8","3.9"] + config: + - {python-version: "3.6", testenvs: "py36,build", experimental: False} + - {python-version: "3.7", testenvs: "py37,build", experimental: False} + - {python-version: "3.8", testenvs: "py38,build", experimental: False} + - {python-version: "3.9", testenvs: "py39,build", experimental: False} steps: - name: Checkout 🛎️ @@ -26,14 +31,14 @@ jobs: - name: Setup Python 🐍 uses: "actions/setup-python@v2" with: - python-version: "${{ matrix.python-version }}" + python-version: "${{ matrix.config.python-version }}" - name: Install dependencies 🔧 run: | python -VV python -m site python -m pip install --upgrade pip setuptools wheel - python -m pip install --upgrade tox tox-gh-actions virtualenv + python -m pip install --upgrade tox virtualenv - - name: "Run Tests for Python ${{ matrix.python-version }}" - run: "python -m tox" + - name: "Run Tests for Python ${{ matrix.config.python-version }}" + run: python -m tox -e "${{ matrix.config.testenvs }}" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c17e9f3..7ab04e4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -44,6 +44,9 @@ repos: rev: v1.7.0 hooks: - id: python-no-eval + - id: rst-backticks + - id: rst-directive-colons + - id: rst-inline-touching-normal - repo: https://github.com/asottile/pyupgrade rev: v2.7.4 diff --git a/README.rst b/README.rst index 0b456be..95dc758 100644 --- a/README.rst +++ b/README.rst @@ -16,28 +16,36 @@ flake8-github-actions :widths: 10 90 * - Tests - - |travis| |actions_windows| |actions_macos| |codefactor| |pre_commit_ci| + - |actions_linux| |actions_windows| |actions_macos| * - PyPI - |pypi-version| |supported-versions| |supported-implementations| |wheel| * - Activity - - |commits-latest| |commits-since| |maintained| + - |commits-latest| |commits-since| |maintained| |pypi-downloads| + * - QA + - |codefactor| |actions_flake8| |actions_mypy| |pre_commit_ci| * - Other - - |license| |language| |requires| |pre_commit| + - |license| |language| |requires| - - -.. |travis| image:: https://github.com/domdfcoding/flake8-github-actions/workflows/Linux%20Tests/badge.svg - :target: https://github.com/domdfcoding/flake8-github-actions/actions?query=workflow%3A%22Linux+Tests%22 +.. |actions_linux| image:: https://github.com/domdfcoding/flake8-github-actions/workflows/Linux/badge.svg + :target: https://github.com/domdfcoding/flake8-github-actions/actions?query=workflow%3A%22Linux%22 :alt: Linux Test Status -.. |actions_windows| image:: https://github.com/domdfcoding/flake8-github-actions/workflows/Windows%20Tests/badge.svg - :target: https://github.com/domdfcoding/flake8-github-actions/actions?query=workflow%3A%22Windows+Tests%22 +.. |actions_windows| image:: https://github.com/domdfcoding/flake8-github-actions/workflows/Windows/badge.svg + :target: https://github.com/domdfcoding/flake8-github-actions/actions?query=workflow%3A%22Windows%22 :alt: Windows Test Status -.. |actions_macos| image:: https://github.com/domdfcoding/flake8-github-actions/workflows/macOS%20Tests/badge.svg - :target: https://github.com/domdfcoding/flake8-github-actions/actions?query=workflow%3A%22macOS+Tests%22 +.. |actions_macos| image:: https://github.com/domdfcoding/flake8-github-actions/workflows/macOS/badge.svg + :target: https://github.com/domdfcoding/flake8-github-actions/actions?query=workflow%3A%22macOS%22 :alt: macOS Test Status +.. |actions_flake8| image:: https://github.com/domdfcoding/flake8-github-actions/workflows/Flake8/badge.svg + :target: https://github.com/domdfcoding/flake8-github-actions/actions?query=workflow%3A%22Flake8%22 + :alt: Flake8 Status + +.. |actions_mypy| image:: https://github.com/domdfcoding/flake8-github-actions/workflows/mypy/badge.svg + :target: https://github.com/domdfcoding/flake8-github-actions/actions?query=workflow%3A%22mypy%22 + :alt: mypy status + .. |requires| image:: https://requires.io/github/domdfcoding/flake8-github-actions/requirements.svg?branch=master :target: https://requires.io/github/domdfcoding/flake8-github-actions/requirements/?branch=master :alt: Requirements Status @@ -80,9 +88,9 @@ flake8-github-actions .. |maintained| image:: https://img.shields.io/maintenance/yes/2020 :alt: Maintenance -.. |pre_commit| image:: https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white - :target: https://github.com/pre-commit/pre-commit - :alt: pre-commit +.. |pypi-downloads| image:: https://img.shields.io/pypi/dm/flake8-github-actions + :target: https://pypi.org/project/flake8-github-actions/ + :alt: PyPI - Downloads .. |pre_commit_ci| image:: https://results.pre-commit.ci/badge/github/domdfcoding/flake8-github-actions/master.svg :target: https://results.pre-commit.ci/latest/github/domdfcoding/flake8-github-actions/master diff --git a/flake8_github_actions/__init__.py b/flake8_github_actions/__init__.py index 3dcd63d..e0ae709 100644 --- a/flake8_github_actions/__init__.py +++ b/flake8_github_actions/__init__.py @@ -46,6 +46,9 @@ class GitHubFormatter(BaseFormatter): + """ + Custom Flake8 formatter for GitHub actions. + """ def write_line(self, line): """ @@ -53,7 +56,7 @@ def write_line(self, line): """ self.write(line, None) - def start(self): + def start(self): # noqa: D102 super().start() self.files_reported_count = 0 @@ -71,7 +74,7 @@ def finished(self, filename): self.files_reported_count += 1 - def format(self, violation): + def format(self, violation): # noqa: A003 # pylint: disable=redefined-builtin """ Format a violation. """ diff --git a/setup.cfg b/setup.cfg index dc7c80d..c977fdd 100644 --- a/setup.cfg +++ b/setup.cfg @@ -17,8 +17,8 @@ long_description_content_type = text/x-rst platforms = Windows, macOS, Linux url = https://github.com/domdfcoding/flake8-github-actions project_urls = - Issue_Tracker = https://github.com/domdfcoding/flake8-github-actions/issues - Source_Code = https://github.com/domdfcoding/flake8-github-actions + Issue Tracker = https://github.com/domdfcoding/flake8-github-actions/issues + Source Code = https://github.com/domdfcoding/flake8-github-actions classifiers = License :: OSI Approved :: MIT License Operating System :: OS Independent diff --git a/tox.ini b/tox.ini index c7a3ba5..c2ad804 100644 --- a/tox.ini +++ b/tox.ini @@ -2,7 +2,6 @@ # You may add new sections, but any changes made to the following sections will be lost: # * tox # * envlists -# * gh-actions # * testenv # * testenv:docs # * testenv:build @@ -19,24 +18,17 @@ [tox] envlist = py36, py37, py38, py39, mypy, build skip_missing_interpreters = True -requires = pip>=20.2.1 +requires = + pip>=20.3.3 + tox-envlist>=0.1.0 isolated_build = True [envlists] test = py36, py37, py38, py39 qa = mypy, lint -[gh-actions] -python = - 3.6: py36, build, mypy - 3.7: py37, build - 3.8: py38, build - 3.9: py39, build - [testenv] -setenv = - PIP_USE_FEATURE = 2020-resolver - PYTHONDEVMODE = 1 +setenv = PYTHONDEVMODE = 1 commands = python --version [testenv:build] @@ -94,8 +86,8 @@ commands = pyup_dirs flake8_github_actions --py36-plus --recursive [flake8] max-line-length = 120 -select = E301 E303 E304 E305 E306 E502 W291 W293 W391 E226 E225 E241 E231 W292 E265 E111 E112 E113 E121 E122 E125 E127 E128 E129 E131 E133 E201 E202 E203 E211 E222 E223 E224 E225 E227 E228 E242 E251 E261 E262 E271 E272 E402 E703 E711 E712 E713 E714 E721 W504 E302 YTT101 YTT102 YTT103 YTT201 YTT202 YTT203 YTT204 YTT301 YTT302 YTT303 STRFTIME001 STRFTIME002 SXL001 PT001 PT002 PT003 PT005 PT006 PT007 PT008 PT009 PT010 PT011 PT012 PT013 PT014 PT015 PT016 PT017 PT018 PT019 PT020 PT021 RST201 RST202 RST203 RST204 RST205 RST206 RST207 RST208 RST210 RST211 RST212 RST213 RST214 RST215 RST216 RST217 RST218 RST219 RST299 RST301 RST302 RST303 RST304 RST305 RST306 RST399 RST401 RST499 RST900 RST901 RST902 RST903 Q001 Q002 Q003 A001 A002 A003 TYP001 TYP002 TYP003 TYP004 TYP005 TYP006 Y001,Y002 Y003 Y004 Y005 Y006 Y007 Y008 Y009 Y010 Y011 Y012 Y013 Y014 Y015 Y090 Y091 D100 D101 D102 D103 D104 D106 D201 D204 D207 D208 D209 D210 D211 D212 D213 D214 D215 D300 D301 D400 D402 D403 D404 D415 D417 DALL000 -exclude = .git,__pycache__,doc-source,old,build,dist,make_conda_recipe.py,__pkginfo__.py,setup.py,.tox,venv +select = E111 E112 E113 E121 E122 E125 E127 E128 E129 E131 E133 E201 E202 E203 E211 E222 E223 E224 E225 E225 E226 E227 E228 E231 E241 E242 E251 E261 E262 E265 E271 E272 E301 E302 E303 E304 E305 E306 E402 E502 E703 E711 E712 E713 E714 E721 W291 W292 W293 W391 W504 YTT101 YTT102 YTT103 YTT201 YTT202 YTT203 YTT204 YTT301 YTT302 YTT303 STRFTIME001 STRFTIME002 SXL001 PT001 PT002 PT003 PT005 PT006 PT007 PT008 PT009 PT010 PT011 PT012 PT013 PT014 PT015 PT016 PT017 PT018 PT019 PT020 PT021 RST201 RST202 RST203 RST204 RST205 RST206 RST207 RST208 RST210 RST211 RST212 RST213 RST214 RST215 RST216 RST217 RST218 RST219 RST299 RST301 RST302 RST303 RST304 RST305 RST306 RST399 RST401 RST499 RST900 RST901 RST902 RST903 Q001 Q002 Q003 A001 A002 A003 TYP001 TYP002 TYP003 TYP004 TYP005 TYP006 Y001,Y002 Y003 Y004 Y005 Y006 Y007 Y008 Y009 Y010 Y011 Y012 Y013 Y014 Y015 Y090 Y091 D100 D101 D102 D103 D104 D106 D201 D204 D207 D208 D209 D210 D211 D212 D213 D214 D215 D300 D301 D400 D402 D403 D404 D415 D417 DALL000 +exclude = doc-source,.git,__pycache__,old,build,dist,__pkginfo__.py,setup.py,.tox,venv rst-directives = TODO envvar @@ -131,6 +123,13 @@ package = flake8_github_actions addopts = --color yes --durations 25 timeout = 300 +[gh-actions] +python = + 3.6: py36, build, mypy + 3.7: py37, build + 3.8: py38, build + 3.9: py39, build + [dep_checker] allowed_unused = flake8 From 3d015e9495447c8405488169f314d1572e92a12a Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Wed, 30 Dec 2020 08:52:03 +0000 Subject: [PATCH 022/105] Update flake8 config. --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index c2ad804..249b022 100644 --- a/tox.ini +++ b/tox.ini @@ -63,7 +63,7 @@ deps = git+https://github.com/PyCQA/pydocstyle@5118faa7173b0e5bbc230c4adf628758e13605bf git+https://github.com/domdfcoding/flake8-quotes.git git+https://github.com/domdfcoding/flake8-rst-docstrings.git - git+https://github.com/domdfcoding/flake8-rst-docstrings-sphinx.git@v2 + git+https://github.com/domdfcoding/flake8-rst-docstrings-sphinx.git pygments>=2.7.1 commands = python3 -m flake8_rst_docstrings_sphinx flake8_github_actions --allow-toolbox {posargs} From 1e4148f1c20e193db11870fa6b5d339abd49de48 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 5 Jan 2021 08:57:14 +0000 Subject: [PATCH 023/105] [pre-commit.ci] pre-commit autoupdate (#7) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7ab04e4..eaf6133 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -35,7 +35,7 @@ repos: - id: bind-requirements - repo: https://github.com/domdfcoding/flake8-dunder-all - rev: v0.1.3 + rev: v0.1.4 hooks: - id: ensure-dunder-all files: ^flake8_github_actions/.*\.py$ From d1ed1cae9465f219b09303443bac95804bdc446f Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Tue, 5 Jan 2021 19:45:08 +0000 Subject: [PATCH 024/105] Updated files with 'repo_helper'. --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 95dc758..74dfce9 100644 --- a/README.rst +++ b/README.rst @@ -85,7 +85,7 @@ flake8-github-actions :target: https://github.com/domdfcoding/flake8-github-actions/commit/master :alt: GitHub last commit -.. |maintained| image:: https://img.shields.io/maintenance/yes/2020 +.. |maintained| image:: https://img.shields.io/maintenance/yes/2021 :alt: Maintenance .. |pypi-downloads| image:: https://img.shields.io/pypi/dm/flake8-github-actions From 5102527d02c1f117b4fba28f58f11f84d6a0c57c Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Sun, 10 Jan 2021 11:41:00 +0000 Subject: [PATCH 025/105] Use Plural class from domdf_python_tools --- .pylintrc | 2 +- flake8_github_actions/__init__.py | 9 +++------ requirements.txt | 1 + tox.ini | 4 +--- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/.pylintrc b/.pylintrc index cfee0f1..12063c9 100644 --- a/.pylintrc +++ b/.pylintrc @@ -66,7 +66,7 @@ confidence= # no Warning level messages displayed, use"--disable=all --enable=classes # --disable=W" disable=all -enable=assert-on-tuple,astroid-error,bad-except-order,bad-inline-option,bad-option-value,bad-reversed-sequence,bare-except,binary-op-exception,boolean-datetime,catching-non-exception,cell-var-from-loop,confusing-with-statement,consider-merging-isinstance,consider-using-enumerate,consider-using-ternary,continue-in-finally,cyclic-import,deprecated-pragma,django-not-available,duplicate-except,duplicate-key,eval-used,exec-used,expression-not-assigned,fatal,file-ignored,fixme,global-at-module-level,global-statement,global-variable-not-assigned,global-variable-undefined,http-response-with-content-type-json,http-response-with-json-dumps,invalid-all-object,invalid-characters-in-docstring,len-as-condition,literal-comparison,locally-disabled,locally-enabled,lost-exception,lowercase-l-suffix,misplaced-bare-raise,missing-kwoa,mixed-line-endings,model-has-unicode,model-missing-unicode,model-no-explicit-unicode,model-unicode-not-callable,multiple-imports,multiple-statements,new-db-field-with-default,non-ascii-bytes-literals,nonexistent-operator,not-an-iterable,not-in-loop,notimplemented-raised,overlapping-except,parse-error,pointless-statement,pointless-string-statement,raising-bad-type,raising-non-exception,raw-checker-failed,redefine-in-handler,redefined-argument-from-local,redefined-builtin,redundant-content-type-for-json-response,reimported,relative-import,return-outside-function,simplifiable-if-statement,singleton-comparison,syntax-error,trailing-comma-tuple,trailing-newlines,unbalanced-tuple-unpacking,undefined-all-variable,undefined-loop-variable,unexpected-line-ending-format,unidiomatic-typecheck,unnecessary-lambda,unnecessary-pass,unnecessary-semicolon,unneeded-not,unpacking-non-sequence,unreachable,unrecognized-inline-option,used-before-assignment,useless-else-on-loop,using-constant-test,wildcard-import,yield-outside-function,useless-return +enable=assert-on-tuple,astroid-error,bad-except-order,bad-inline-option,bad-option-value,bad-reversed-sequence,bare-except,binary-op-exception,boolean-datetime,catching-non-exception,cell-var-from-loop,confusing-with-statement,consider-merging-isinstance,consider-using-enumerate,consider-using-ternary,continue-in-finally,cyclic-import,deprecated-pragma,django-not-available,duplicate-except,duplicate-key,eval-used,exec-used,expression-not-assigned,fatal,file-ignored,fixme,global-at-module-level,global-statement,global-variable-not-assigned,global-variable-undefined,http-response-with-content-type-json,http-response-with-json-dumps,invalid-all-object,invalid-characters-in-docstring,len-as-condition,literal-comparison,locally-disabled,locally-enabled,lost-exception,lowercase-l-suffix,misplaced-bare-raise,missing-kwoa,mixed-line-endings,model-has-unicode,model-missing-unicode,model-no-explicit-unicode,model-unicode-not-callable,multiple-imports,multiple-statements,new-db-field-with-default,non-ascii-bytes-literals,nonexistent-operator,not-in-loop,notimplemented-raised,overlapping-except,parse-error,pointless-statement,pointless-string-statement,raising-bad-type,raising-non-exception,raw-checker-failed,redefine-in-handler,redefined-argument-from-local,redefined-builtin,redundant-content-type-for-json-response,reimported,relative-import,return-outside-function,simplifiable-if-statement,singleton-comparison,syntax-error,trailing-comma-tuple,trailing-newlines,unbalanced-tuple-unpacking,undefined-all-variable,undefined-loop-variable,unexpected-line-ending-format,unidiomatic-typecheck,unnecessary-lambda,unnecessary-pass,unnecessary-semicolon,unneeded-not,unpacking-non-sequence,unreachable,unrecognized-inline-option,used-before-assignment,useless-else-on-loop,using-constant-test,wildcard-import,yield-outside-function,useless-return [REPORTS] diff --git a/flake8_github_actions/__init__.py b/flake8_github_actions/__init__.py index e0ae709..97d3f1e 100644 --- a/flake8_github_actions/__init__.py +++ b/flake8_github_actions/__init__.py @@ -26,11 +26,8 @@ # OR OTHER DEALINGS IN THE SOFTWARE. # -# stdlib -from functools import partial -from gettext import ngettext - # 3rd party +from domdf_python_tools.words import Plural from flake8.formatting.base import BaseFormatter # type: ignore __author__: str = "Dominic Davis-Foster" @@ -41,8 +38,8 @@ __all__ = ["GitHubFormatter"] -_error = partial(ngettext, "error", "errors") -_file = partial(ngettext, "file", "files") +_error = Plural("error", "errors") +_file = Plural("file", "files") class GitHubFormatter(BaseFormatter): diff --git a/requirements.txt b/requirements.txt index 4163a01..575ad80 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ +domdf-python-tools>=2.0.0 flake8>=3.8.4 diff --git a/tox.ini b/tox.ini index 249b022..6715c10 100644 --- a/tox.ini +++ b/tox.ini @@ -71,9 +71,7 @@ commands = python3 -m flake8_rst_docstrings_sphinx flake8_github_actions --allow basepython = python3.6 ignore_errors = True changedir = {toxinidir} -deps = - mypy==0.790 - lxml +deps = mypy==0.790 commands = mypy flake8_github_actions {posargs} [testenv:pyup] From 0be97e53c66ef47d8ce311805f28080fae7cbb5d Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Sun, 10 Jan 2021 11:42:56 +0000 Subject: [PATCH 026/105] Added classifiers and test on Python 3.10 --- .github/workflows/python_ci.yml | 3 ++- .github/workflows/python_ci_linux.yml | 3 ++- .github/workflows/python_ci_macos.yml | 3 ++- flake8_github_actions/py.typed | 0 repo_helper.yml | 6 ++++++ setup.cfg | 4 ++++ tox.ini | 4 ++-- 7 files changed, 18 insertions(+), 5 deletions(-) create mode 100644 flake8_github_actions/py.typed diff --git a/.github/workflows/python_ci.yml b/.github/workflows/python_ci.yml index d0fe702..bd53f38 100644 --- a/.github/workflows/python_ci.yml +++ b/.github/workflows/python_ci.yml @@ -13,7 +13,7 @@ jobs: runs-on: "windows-2019" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-alpha.4' strategy: fail-fast: False @@ -23,6 +23,7 @@ jobs: - {python-version: "3.7", testenvs: "py37,build", experimental: False} - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} + - {python-version: "3.10.0-alpha.4", testenvs: "py310-dev,build", experimental: True} steps: - name: Checkout 🛎️ diff --git a/.github/workflows/python_ci_linux.yml b/.github/workflows/python_ci_linux.yml index 41eb8fd..7ef579f 100644 --- a/.github/workflows/python_ci_linux.yml +++ b/.github/workflows/python_ci_linux.yml @@ -13,7 +13,7 @@ jobs: runs-on: "ubuntu-20.04" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-alpha.4' strategy: fail-fast: False @@ -23,6 +23,7 @@ jobs: - {python-version: "3.7", testenvs: "py37,build", experimental: False} - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} + - {python-version: "3.10.0-alpha.4", testenvs: "py310-dev,build", experimental: True} steps: - name: Checkout 🛎️ diff --git a/.github/workflows/python_ci_macos.yml b/.github/workflows/python_ci_macos.yml index fc9cd1d..d697548 100644 --- a/.github/workflows/python_ci_macos.yml +++ b/.github/workflows/python_ci_macos.yml @@ -13,7 +13,7 @@ jobs: runs-on: "macos-latest" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-alpha.4' strategy: fail-fast: False @@ -23,6 +23,7 @@ jobs: - {python-version: "3.7", testenvs: "py37,build", experimental: False} - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} + - {python-version: "3.10.0-alpha.4", testenvs: "py310-dev,build", experimental: True} steps: - name: Checkout 🛎️ diff --git a/flake8_github_actions/py.typed b/flake8_github_actions/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/repo_helper.yml b/repo_helper.yml index 100bf7f..b809caa 100644 --- a/repo_helper.yml +++ b/repo_helper.yml @@ -18,6 +18,7 @@ python_versions: - 3.7 - 3.8 - 3.9 + - 3.10-dev additional_ignore: - action.py @@ -30,3 +31,8 @@ keywords: entry_points: flake8.report: - github = flake8_github_actions:GitHubFormatter + +classifiers: + - 'Environment :: Console' + - 'Framework :: Flake8' + - 'Intended Audience :: Developers' diff --git a/setup.cfg b/setup.cfg index c977fdd..2149b6e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -20,6 +20,9 @@ project_urls = Issue Tracker = https://github.com/domdfcoding/flake8-github-actions/issues Source Code = https://github.com/domdfcoding/flake8-github-actions classifiers = + Environment :: Console + Framework :: Flake8 + Intended Audience :: Developers License :: OSI Approved :: MIT License Operating System :: OS Independent Programming Language :: Python @@ -29,6 +32,7 @@ classifiers = Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: Implementation :: CPython + Typing :: Typed [options] python_requires = >=3.6.1 diff --git a/tox.ini b/tox.ini index 6715c10..cf73cc4 100644 --- a/tox.ini +++ b/tox.ini @@ -16,7 +16,7 @@ # * pytest [tox] -envlist = py36, py37, py38, py39, mypy, build +envlist = py36, py37, py38, py39, py310-dev, mypy, build skip_missing_interpreters = True requires = pip>=20.3.3 @@ -24,7 +24,7 @@ requires = isolated_build = True [envlists] -test = py36, py37, py38, py39 +test = py36, py37, py38, py39, py310-dev qa = mypy, lint [testenv] From fb143da07cc69696922670e90b04bb9b725e0720 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 11 Jan 2021 18:24:31 +0000 Subject: [PATCH 027/105] [pre-commit.ci] pre-commit autoupdate (#8) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index eaf6133..d00f031 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -35,7 +35,7 @@ repos: - id: bind-requirements - repo: https://github.com/domdfcoding/flake8-dunder-all - rev: v0.1.4 + rev: v0.1.5 hooks: - id: ensure-dunder-all files: ^flake8_github_actions/.*\.py$ From 0b6231d92b7433d01c307e53dfe4b60701809685 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 18 Jan 2021 20:34:19 +0000 Subject: [PATCH 028/105] [pre-commit.ci] pre-commit autoupdate (#9) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d00f031..407caa5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -62,7 +62,7 @@ repos: - id: forbid-crlf - repo: https://github.com/domdfcoding/yapf-isort - rev: v0.5.4 + rev: v0.5.5 hooks: - id: yapf-isort exclude: ^(doc-source/conf|__pkginfo__|make_conda_recipe|setup)\.py$ From 4f50e4456565d645a93a569544506db469bcb57b Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Tue, 19 Jan 2021 22:57:30 +0000 Subject: [PATCH 029/105] Updated files with 'repo_helper'. (#10) Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .github/workflows/mypy.yml | 2 +- .pre-commit-config.yaml | 5 +++++ tox.ini | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/mypy.yml b/.github/workflows/mypy.yml index 6be64e3..a15d210 100644 --- a/.github/workflows/mypy.yml +++ b/.github/workflows/mypy.yml @@ -14,7 +14,7 @@ jobs: strategy: matrix: - os: [ubuntu-latest, windows-latest, macos-latest] + os: ['windows-2019', 'macos-latest', 'ubuntu-20.04'] fail-fast: false steps: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 407caa5..bd680ef 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -40,6 +40,11 @@ repos: - id: ensure-dunder-all files: ^flake8_github_actions/.*\.py$ + - repo: https://github.com/domdfcoding/flake2lint + rev: v0.2.0 + hooks: + - id: flake2lint + - repo: https://github.com/pre-commit/pygrep-hooks rev: v1.7.0 hooks: diff --git a/tox.ini b/tox.ini index cf73cc4..b7ed5c4 100644 --- a/tox.ini +++ b/tox.ini @@ -111,6 +111,7 @@ exclude_lines = if TYPE_CHECKING: if typing.TYPE_CHECKING: if __name__ == .__main__.: + \.\.\. [check-wheel-contents] ignore = W002 From 150440a230630e1fb3984f67c92f609a59defd1a Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Thu, 28 Jan 2021 22:59:06 +0000 Subject: [PATCH 030/105] Updated files with 'repo_helper'. (#11) Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .github/workflows/mypy.yml | 2 +- .isort.cfg | 29 ---------------------- .pre-commit-config.yaml | 8 +++---- CONTRIBUTING.rst | 10 ++++---- formate.toml | 49 ++++++++++++++++++++++++++++++++++++++ pyproject.toml | 2 +- tox.ini | 25 +++++++++---------- 7 files changed, 72 insertions(+), 53 deletions(-) delete mode 100644 .isort.cfg create mode 100644 formate.toml diff --git a/.github/workflows/mypy.yml b/.github/workflows/mypy.yml index a15d210..afee01e 100644 --- a/.github/workflows/mypy.yml +++ b/.github/workflows/mypy.yml @@ -31,7 +31,7 @@ jobs: python -VV python -m site python -m pip install --upgrade pip setuptools wheel - python -m pip install tox + python -m pip install --upgrade tox virtualenv - name: "Run mypy" run: "python -m tox -e mypy" diff --git a/.isort.cfg b/.isort.cfg deleted file mode 100644 index ef5ef93..0000000 --- a/.isort.cfg +++ /dev/null @@ -1,29 +0,0 @@ -[settings] -line_length = 115 -force_to_top = True -indent = " " -multi_line_output = 8 -import_heading_stdlib = stdlib -import_heading_thirdparty = 3rd party -import_heading_firstparty = this package -import_heading_localfolder = this package -balanced_wrapping = False -lines_between_types = 0 -use_parentheses = True -remove_redundant_aliases = True -default_section = THIRDPARTY -known_third_party = - apeye - attrs - click - consolekit - domdf_python_tools - dulwich - flake8 - flake8_json - flake8_prettycount - github - github3_py - requests - typing_extensions -known_first_party = flake8_github_actions diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index bd680ef..4c54cd3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -66,11 +66,11 @@ repos: - id: remove-crlf - id: forbid-crlf - - repo: https://github.com/domdfcoding/yapf-isort - rev: v0.5.5 + - repo: https://github.com/repo-helper/formate + rev: v0.2.0 hooks: - - id: yapf-isort - exclude: ^(doc-source/conf|__pkginfo__|make_conda_recipe|setup)\.py$ + - id: formate + exclude: ^(doc-source/conf|__pkginfo__|make_conda_recipe|setup)\.(_)?py$ - repo: https://github.com/domdfcoding/dep_checker rev: v0.4.1 diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index c91477a..98e5ffa 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -4,7 +4,8 @@ Contributing .. This file based on https://github.com/PyGithub/PyGithub/blob/master/CONTRIBUTING.md -``flake8-github-actions`` uses `tox `_ to automate testing and packaging, and `pre-commit `_ to maintain code quality. +``flake8-github-actions`` uses `tox `_ to automate testing and packaging, +and `pre-commit `_ to maintain code quality. Install ``pre-commit`` with ``pip`` and install the git hook: @@ -17,13 +18,13 @@ Install ``pre-commit`` with ``pip`` and install the git hook: Coding style -------------- -`yapf-isort `_ is used for code formatting. +`formate `_ is used for code formatting. It can be run manually via ``pre-commit``: .. code-block:: bash - $ pre-commit run yapf-isort -a + $ pre-commit run formate -a Or, to run the complete autoformatting suite: @@ -36,7 +37,8 @@ Or, to run the complete autoformatting suite: Automated tests ------------------- -Tests are run with ``tox`` and ``pytest``. To run tests for a specific Python version, such as Python 3.6, run: +Tests are run with ``tox`` and ``pytest``. +To run tests for a specific Python version, such as Python 3.6: .. code-block:: bash diff --git a/formate.toml b/formate.toml new file mode 100644 index 0000000..3d35c0e --- /dev/null +++ b/formate.toml @@ -0,0 +1,49 @@ +[hooks] +dynamic_quotes = 10 +collections-import-rewrite = 20 +reformat-generics = 40 +noqa-reformat = 60 +ellipsis-reformat = 70 + +[config] +indent = "\t" +line_length = 115 + +[hooks.yapf] +priority = 30 + +[hooks.isort] +priority = 50 + +[hooks.yapf.kwargs] +yapf_style = ".style.yapf" + +[hooks.isort.kwargs] +line_length = 115 +indent = "\"\t\t\"" +multi_line_output = 8 +import_heading_stdlib = "stdlib" +import_heading_thirdparty = "3rd party" +import_heading_firstparty = "this package" +import_heading_localfolder = "this package" +balanced_wrapping = false +lines_between_types = 0 +use_parentheses = true +remove_redundant_aliases = true +default_section = "THIRDPARTY" +known_third_party = [ + "apeye", + "attrs", + "click", + "consolekit", + "domdf_python_tools", + "dulwich", + "flake8", + "flake8_json", + "flake8_prettycount", + "github", + "github3_py", + "requests", + "typing_extensions", +] +known_first_party = "flake8_github_actions" diff --git a/pyproject.toml b/pyproject.toml index c6e758f..fba467d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,3 @@ [build-system] -requires = ["setuptools>=40.6.0", "wheel>=0.34.2"] +requires = [ "setuptools>=40.6.0", "wheel>=0.34.2",] build-backend = "setuptools.build_meta" diff --git a/tox.ini b/tox.ini index b7ed5c4..7a76e23 100644 --- a/tox.ini +++ b/tox.ini @@ -8,10 +8,7 @@ # * testenv:lint # * testenv:mypy # * testenv:pyup -# * testenv:coverage # * flake8 -# * coverage:run -# * coverage:report # * check-wheel-contents # * pytest @@ -84,7 +81,7 @@ commands = pyup_dirs flake8_github_actions --py36-plus --recursive [flake8] max-line-length = 120 -select = E111 E112 E113 E121 E122 E125 E127 E128 E129 E131 E133 E201 E202 E203 E211 E222 E223 E224 E225 E225 E226 E227 E228 E231 E241 E242 E251 E261 E262 E265 E271 E272 E301 E302 E303 E304 E305 E306 E402 E502 E703 E711 E712 E713 E714 E721 W291 W292 W293 W391 W504 YTT101 YTT102 YTT103 YTT201 YTT202 YTT203 YTT204 YTT301 YTT302 YTT303 STRFTIME001 STRFTIME002 SXL001 PT001 PT002 PT003 PT005 PT006 PT007 PT008 PT009 PT010 PT011 PT012 PT013 PT014 PT015 PT016 PT017 PT018 PT019 PT020 PT021 RST201 RST202 RST203 RST204 RST205 RST206 RST207 RST208 RST210 RST211 RST212 RST213 RST214 RST215 RST216 RST217 RST218 RST219 RST299 RST301 RST302 RST303 RST304 RST305 RST306 RST399 RST401 RST499 RST900 RST901 RST902 RST903 Q001 Q002 Q003 A001 A002 A003 TYP001 TYP002 TYP003 TYP004 TYP005 TYP006 Y001,Y002 Y003 Y004 Y005 Y006 Y007 Y008 Y009 Y010 Y011 Y012 Y013 Y014 Y015 Y090 Y091 D100 D101 D102 D103 D104 D106 D201 D204 D207 D208 D209 D210 D211 D212 D213 D214 D215 D300 D301 D400 D402 D403 D404 D415 D417 DALL000 +select = E111 E112 E113 E121 E122 E125 E127 E128 E129 E131 E133 E201 E202 E203 E211 E222 E223 E224 E225 E225 E226 E227 E228 E231 E241 E242 E251 E261 E262 E265 E271 E272 E301 E303 E304 E305 E306 E402 E502 E703 E711 E712 E713 E714 E721 W291 W292 W293 W391 W504 YTT101 YTT102 YTT103 YTT201 YTT202 YTT203 YTT204 YTT301 YTT302 YTT303 STRFTIME001 STRFTIME002 SXL001 PT001 PT002 PT003 PT005 PT006 PT007 PT008 PT009 PT010 PT011 PT012 PT013 PT014 PT015 PT016 PT017 PT018 PT019 PT020 PT021 RST201 RST202 RST203 RST204 RST205 RST206 RST207 RST208 RST210 RST211 RST212 RST213 RST214 RST215 RST216 RST217 RST218 RST219 RST299 RST301 RST302 RST303 RST304 RST305 RST306 RST399 RST401 RST499 RST900 RST901 RST902 RST903 Q001 Q002 Q003 A001 A002 A003 TYP001 TYP002 TYP003 TYP004 TYP005 TYP006 Y001,Y002 Y003 Y004 Y005 Y006 Y007 Y008 Y009 Y010 Y011 Y012 Y013 Y014 Y015 Y090 Y091 E302 D100 D101 D102 D103 D104 D106 D201 D204 D207 D208 D209 D210 D211 D212 D213 D214 D215 D300 D301 D400 D402 D403 D404 D415 D417 DALL000 exclude = doc-source,.git,__pycache__,old,build,dist,__pkginfo__.py,setup.py,.tox,venv rst-directives = TODO @@ -92,13 +89,22 @@ rst-directives = extras-require per-file-ignores = tests/*: D100 D101 D102 D103 D104 D106 D201 D204 D207 D208 D209 D210 D211 D212 D213 D214 D215 D300 D301 D400 D402 D403 D404 D415 D417 DALL000 - */*.pyi: D100 D101 D102 D103 D104 D106 D201 D204 D207 D208 D209 D210 D211 D212 D213 D214 D215 D300 D301 D400 D402 D403 D404 D415 D417 DALL000 + */*.pyi: E302 D100 D101 D102 D103 D104 D106 D201 D204 D207 D208 D209 D210 D211 D212 D213 D214 D215 D300 D301 D400 D402 D403 D404 D415 D417 DALL000 pytest-parametrize-names-type = csv inline-quotes = " multiline-quotes = """ docstring-quotes = """ count = True +[check-wheel-contents] +ignore = W002 +toplevel = flake8_github_actions +package = flake8_github_actions + +[pytest] +addopts = --color yes --durations 25 +timeout = 300 + [coverage:run] plugins = coverage_pyver_pragma @@ -113,15 +119,6 @@ exclude_lines = if __name__ == .__main__.: \.\.\. -[check-wheel-contents] -ignore = W002 -toplevel = flake8_github_actions -package = flake8_github_actions - -[pytest] -addopts = --color yes --durations 25 -timeout = 300 - [gh-actions] python = 3.6: py36, build, mypy From 94e6c070b62dbf5cd4c2333bf4b003682688d5fd Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Fri, 29 Jan 2021 21:23:56 +0000 Subject: [PATCH 031/105] Updated files with 'repo_helper'. --- .pre-commit-config.yaml | 4 ++-- formate.toml | 4 ++-- tox.ini | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4c54cd3..d60f0a5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -25,7 +25,7 @@ repos: - id: end-of-file-fixer - repo: https://github.com/domdfcoding/pre-commit-hooks - rev: v0.1.6 + rev: v0.2.0 hooks: - id: requirements-txt-sorter args: @@ -67,7 +67,7 @@ repos: - id: forbid-crlf - repo: https://github.com/repo-helper/formate - rev: v0.2.0 + rev: v0.2.5 hooks: - id: formate exclude: ^(doc-source/conf|__pkginfo__|make_conda_recipe|setup)\.(_)?py$ diff --git a/formate.toml b/formate.toml index 3d35c0e..be02f67 100644 --- a/formate.toml +++ b/formate.toml @@ -4,6 +4,7 @@ collections-import-rewrite = 20 reformat-generics = 40 noqa-reformat = 60 ellipsis-reformat = 70 +squish_stubs = 80 [config] indent = "\t" @@ -19,8 +20,7 @@ priority = 50 yapf_style = ".style.yapf" [hooks.isort.kwargs] -line_length = 115 -indent = "\"\t\t\"" +indent = "\t\t" multi_line_output = 8 import_heading_stdlib = "stdlib" import_heading_thirdparty = "3rd party" diff --git a/tox.ini b/tox.ini index 7a76e23..33a0fc1 100644 --- a/tox.ini +++ b/tox.ini @@ -81,7 +81,7 @@ commands = pyup_dirs flake8_github_actions --py36-plus --recursive [flake8] max-line-length = 120 -select = E111 E112 E113 E121 E122 E125 E127 E128 E129 E131 E133 E201 E202 E203 E211 E222 E223 E224 E225 E225 E226 E227 E228 E231 E241 E242 E251 E261 E262 E265 E271 E272 E301 E303 E304 E305 E306 E402 E502 E703 E711 E712 E713 E714 E721 W291 W292 W293 W391 W504 YTT101 YTT102 YTT103 YTT201 YTT202 YTT203 YTT204 YTT301 YTT302 YTT303 STRFTIME001 STRFTIME002 SXL001 PT001 PT002 PT003 PT005 PT006 PT007 PT008 PT009 PT010 PT011 PT012 PT013 PT014 PT015 PT016 PT017 PT018 PT019 PT020 PT021 RST201 RST202 RST203 RST204 RST205 RST206 RST207 RST208 RST210 RST211 RST212 RST213 RST214 RST215 RST216 RST217 RST218 RST219 RST299 RST301 RST302 RST303 RST304 RST305 RST306 RST399 RST401 RST499 RST900 RST901 RST902 RST903 Q001 Q002 Q003 A001 A002 A003 TYP001 TYP002 TYP003 TYP004 TYP005 TYP006 Y001,Y002 Y003 Y004 Y005 Y006 Y007 Y008 Y009 Y010 Y011 Y012 Y013 Y014 Y015 Y090 Y091 E302 D100 D101 D102 D103 D104 D106 D201 D204 D207 D208 D209 D210 D211 D212 D213 D214 D215 D300 D301 D400 D402 D403 D404 D415 D417 DALL000 +select = E111 E112 E113 E121 E122 E125 E127 E128 E129 E131 E133 E201 E202 E203 E211 E222 E223 E224 E225 E225 E226 E227 E228 E231 E241 E242 E251 E261 E262 E265 E271 E272 E303 E304 E306 E402 E502 E703 E711 E712 E713 E714 E721 W291 W292 W293 W391 W504 YTT101 YTT102 YTT103 YTT201 YTT202 YTT203 YTT204 YTT301 YTT302 YTT303 STRFTIME001 STRFTIME002 SXL001 PT001 PT002 PT003 PT005 PT006 PT007 PT008 PT009 PT010 PT011 PT012 PT013 PT014 PT015 PT016 PT017 PT018 PT019 PT020 PT021 RST201 RST202 RST203 RST204 RST205 RST206 RST207 RST208 RST210 RST211 RST212 RST213 RST214 RST215 RST216 RST217 RST218 RST219 RST299 RST301 RST302 RST303 RST304 RST305 RST306 RST399 RST401 RST499 RST900 RST901 RST902 RST903 Q001 Q002 Q003 A001 A002 A003 TYP001 TYP002 TYP003 TYP004 TYP005 TYP006 Y001,Y002 Y003 Y004 Y005 Y006 Y007 Y008 Y009 Y010 Y011 Y012 Y013 Y014 Y015 Y090 Y091 E301 E302 E305 D100 D101 D102 D103 D104 D106 D201 D204 D207 D208 D209 D210 D211 D212 D213 D214 D215 D300 D301 D400 D402 D403 D404 D415 D417 DALL000 exclude = doc-source,.git,__pycache__,old,build,dist,__pkginfo__.py,setup.py,.tox,venv rst-directives = TODO @@ -89,7 +89,7 @@ rst-directives = extras-require per-file-ignores = tests/*: D100 D101 D102 D103 D104 D106 D201 D204 D207 D208 D209 D210 D211 D212 D213 D214 D215 D300 D301 D400 D402 D403 D404 D415 D417 DALL000 - */*.pyi: E302 D100 D101 D102 D103 D104 D106 D201 D204 D207 D208 D209 D210 D211 D212 D213 D214 D215 D300 D301 D400 D402 D403 D404 D415 D417 DALL000 + */*.pyi: E301 E302 E305 D100 D101 D102 D103 D104 D106 D201 D204 D207 D208 D209 D210 D211 D212 D213 D214 D215 D300 D301 D400 D402 D403 D404 D415 D417 DALL000 pytest-parametrize-names-type = csv inline-quotes = " multiline-quotes = """ From 481597c0be4d3e02b96e66380e0525d308e56b0d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 1 Feb 2021 20:50:33 +0000 Subject: [PATCH 032/105] [pre-commit.ci] pre-commit autoupdate (#12) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d60f0a5..52f0f98 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -54,7 +54,7 @@ repos: - id: rst-inline-touching-normal - repo: https://github.com/asottile/pyupgrade - rev: v2.7.4 + rev: v2.9.0 hooks: - id: pyupgrade args: From 93c5861b5d26807cb53a20e4a65886a09872401e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 8 Feb 2021 19:13:50 +0000 Subject: [PATCH 033/105] [pre-commit.ci] pre-commit autoupdate (#13) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 52f0f98..69416f4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -46,7 +46,7 @@ repos: - id: flake2lint - repo: https://github.com/pre-commit/pygrep-hooks - rev: v1.7.0 + rev: v1.7.1 hooks: - id: python-no-eval - id: rst-backticks @@ -54,7 +54,7 @@ repos: - id: rst-inline-touching-normal - repo: https://github.com/asottile/pyupgrade - rev: v2.9.0 + rev: v2.10.0 hooks: - id: pyupgrade args: @@ -67,7 +67,7 @@ repos: - id: forbid-crlf - repo: https://github.com/repo-helper/formate - rev: v0.2.5 + rev: v0.3.1 hooks: - id: formate exclude: ^(doc-source/conf|__pkginfo__|make_conda_recipe|setup)\.(_)?py$ From a0b93686156c6b551d1633efb0c3965f50f931a5 Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Mon, 8 Feb 2021 21:48:07 +0000 Subject: [PATCH 034/105] Use importcheck and run tests on RustPython and pypy --- .github/workflows/python_ci.yml | 4 +-- .github/workflows/python_ci_linux.yml | 5 +-- .github/workflows/python_ci_macos.yml | 5 +-- .github/workflows/rustpython_ci_linux.yml | 43 +++++++++++++++++++++++ pyproject.toml | 3 ++ repo_helper.yml | 14 ++++---- setup.cfg | 1 + tox.ini | 9 +++-- 8 files changed, 69 insertions(+), 15 deletions(-) create mode 100644 .github/workflows/rustpython_ci_linux.yml diff --git a/.github/workflows/python_ci.yml b/.github/workflows/python_ci.yml index bd53f38..7480051 100644 --- a/.github/workflows/python_ci.yml +++ b/.github/workflows/python_ci.yml @@ -13,7 +13,7 @@ jobs: runs-on: "windows-2019" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-alpha.4' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-alpha.5' strategy: fail-fast: False @@ -23,7 +23,7 @@ jobs: - {python-version: "3.7", testenvs: "py37,build", experimental: False} - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - - {python-version: "3.10.0-alpha.4", testenvs: "py310-dev,build", experimental: True} + - {python-version: "3.10.0-alpha.5", testenvs: "py310-dev,build", experimental: True} steps: - name: Checkout 🛎️ diff --git a/.github/workflows/python_ci_linux.yml b/.github/workflows/python_ci_linux.yml index 7ef579f..212ca69 100644 --- a/.github/workflows/python_ci_linux.yml +++ b/.github/workflows/python_ci_linux.yml @@ -13,7 +13,7 @@ jobs: runs-on: "ubuntu-20.04" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-alpha.4' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-alpha.5,pypy-3.6' strategy: fail-fast: False @@ -23,7 +23,8 @@ jobs: - {python-version: "3.7", testenvs: "py37,build", experimental: False} - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - - {python-version: "3.10.0-alpha.4", testenvs: "py310-dev,build", experimental: True} + - {python-version: "3.10.0-alpha.5", testenvs: "py310-dev,build", experimental: True} + - {python-version: "pypy-3.6", testenvs: "pypy3,build", experimental: False} steps: - name: Checkout 🛎️ diff --git a/.github/workflows/python_ci_macos.yml b/.github/workflows/python_ci_macos.yml index d697548..de589e6 100644 --- a/.github/workflows/python_ci_macos.yml +++ b/.github/workflows/python_ci_macos.yml @@ -13,7 +13,7 @@ jobs: runs-on: "macos-latest" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-alpha.4' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-alpha.5,pypy-3.6' strategy: fail-fast: False @@ -23,7 +23,8 @@ jobs: - {python-version: "3.7", testenvs: "py37,build", experimental: False} - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - - {python-version: "3.10.0-alpha.4", testenvs: "py310-dev,build", experimental: True} + - {python-version: "3.10.0-alpha.5", testenvs: "py310-dev,build", experimental: True} + - {python-version: "pypy-3.6", testenvs: "pypy3,build", experimental: False} steps: - name: Checkout 🛎️ diff --git a/.github/workflows/rustpython_ci_linux.yml b/.github/workflows/rustpython_ci_linux.yml new file mode 100644 index 0000000..8578c73 --- /dev/null +++ b/.github/workflows/rustpython_ci_linux.yml @@ -0,0 +1,43 @@ +# This file is managed by 'repo_helper'. Don't edit it directly. +--- +name: RustPython + +on: + push: + +jobs: + tests: + name: "ubuntu-20.04 / RustPython" + runs-on: "ubuntu-20.04" + env: + USING_COVERAGE: 'rustpython' + CARGO_TERM_COLOR: always + + steps: + - name: Checkout 🛎️ + uses: "actions/checkout@v2" + + - name: Setup RustPython 🦀 🐍 + run: | + git clone https://github.com/RustPython/RustPython + cargo install --path ./RustPython + rm -rf ./RustPython + + - name: Install dependencies 🔧 + run: | + python -VV + python -m site + python -m pip install --upgrade pip setuptools wheel + python -m pip install --upgrade tox virtualenv + + - name: "Run Tests for RustPython" + run: python -m tox -e rustpython + + + + - name: "Upload tempdir on failure" + uses: actions/upload-artifact@v2 + if: failure() + with: + name: "pytest-tempdir" + path: /tmp/pytest-of-runner/pytest-0 diff --git a/pyproject.toml b/pyproject.toml index fba467d..e549897 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,6 @@ [build-system] requires = [ "setuptools>=40.6.0", "wheel>=0.34.2",] build-backend = "setuptools.build_meta" + +[tool.importcheck] +always = ["flake8_github_actions"] diff --git a/repo_helper.yml b/repo_helper.yml index b809caa..272054a 100644 --- a/repo_helper.yml +++ b/repo_helper.yml @@ -14,11 +14,13 @@ enable_tests: false enable_docs: false python_versions: - - 3.6 - - 3.7 - - 3.8 - - 3.9 + - '3.6' + - '3.7' + - '3.8' + - '3.9' - 3.10-dev + - pypy3 + - rustpython additional_ignore: - action.py @@ -29,8 +31,8 @@ keywords: - github-actions entry_points: - flake8.report: - - github = flake8_github_actions:GitHubFormatter + flake8.report: + - github = flake8_github_actions:GitHubFormatter classifiers: - 'Environment :: Console' diff --git a/setup.cfg b/setup.cfg index 2149b6e..3433ab4 100644 --- a/setup.cfg +++ b/setup.cfg @@ -32,6 +32,7 @@ classifiers = Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: Implementation :: CPython + Programming Language :: Python :: Implementation :: PyPy Typing :: Typed [options] diff --git a/tox.ini b/tox.ini index 33a0fc1..d2bc22e 100644 --- a/tox.ini +++ b/tox.ini @@ -13,7 +13,7 @@ # * pytest [tox] -envlist = py36, py37, py38, py39, py310-dev, mypy, build +envlist = py36, py37, py38, py39, py310-dev, pypy3, rustpython, mypy, build skip_missing_interpreters = True requires = pip>=20.3.3 @@ -21,12 +21,15 @@ requires = isolated_build = True [envlists] -test = py36, py37, py38, py39, py310-dev +test = py36, py37, py38, py39, py310-dev, pypy3, rustpython qa = mypy, lint [testenv] setenv = PYTHONDEVMODE = 1 -commands = python --version +deps = importcheck>=0.1.0 +commands = + python --version + python -m importcheck {posargs} [testenv:build] skip_install = True From cef52fdd160139e53e054e09d07121ebccf4e145 Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Mon, 8 Feb 2021 23:18:12 +0000 Subject: [PATCH 035/105] Updated files with 'repo_helper'. (#14) Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 1 + pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 69416f4..5ad3ecc 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -59,6 +59,7 @@ repos: - id: pyupgrade args: - --py36-plus + - --keep-runtime-typing - repo: https://github.com/Lucas-C/pre-commit-hooks rev: v1.1.9 diff --git a/pyproject.toml b/pyproject.toml index e549897..575f636 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,4 +3,4 @@ requires = [ "setuptools>=40.6.0", "wheel>=0.34.2",] build-backend = "setuptools.build_meta" [tool.importcheck] -always = ["flake8_github_actions"] +always = [ "flake8_github_actions",] From b13986aee630d0276c444be65b4cffd918e9ed7d Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Tue, 9 Feb 2021 22:47:31 +0000 Subject: [PATCH 036/105] Back out testing on RustPython for now. --- .github/workflows/rustpython_ci_linux.yml | 43 ----------------------- repo_helper.yml | 1 - tox.ini | 4 +-- 3 files changed, 2 insertions(+), 46 deletions(-) delete mode 100644 .github/workflows/rustpython_ci_linux.yml diff --git a/.github/workflows/rustpython_ci_linux.yml b/.github/workflows/rustpython_ci_linux.yml deleted file mode 100644 index 8578c73..0000000 --- a/.github/workflows/rustpython_ci_linux.yml +++ /dev/null @@ -1,43 +0,0 @@ -# This file is managed by 'repo_helper'. Don't edit it directly. ---- -name: RustPython - -on: - push: - -jobs: - tests: - name: "ubuntu-20.04 / RustPython" - runs-on: "ubuntu-20.04" - env: - USING_COVERAGE: 'rustpython' - CARGO_TERM_COLOR: always - - steps: - - name: Checkout 🛎️ - uses: "actions/checkout@v2" - - - name: Setup RustPython 🦀 🐍 - run: | - git clone https://github.com/RustPython/RustPython - cargo install --path ./RustPython - rm -rf ./RustPython - - - name: Install dependencies 🔧 - run: | - python -VV - python -m site - python -m pip install --upgrade pip setuptools wheel - python -m pip install --upgrade tox virtualenv - - - name: "Run Tests for RustPython" - run: python -m tox -e rustpython - - - - - name: "Upload tempdir on failure" - uses: actions/upload-artifact@v2 - if: failure() - with: - name: "pytest-tempdir" - path: /tmp/pytest-of-runner/pytest-0 diff --git a/repo_helper.yml b/repo_helper.yml index 272054a..5f75ee1 100644 --- a/repo_helper.yml +++ b/repo_helper.yml @@ -20,7 +20,6 @@ python_versions: - '3.9' - 3.10-dev - pypy3 - - rustpython additional_ignore: - action.py diff --git a/tox.ini b/tox.ini index d2bc22e..bd1ddc4 100644 --- a/tox.ini +++ b/tox.ini @@ -13,7 +13,7 @@ # * pytest [tox] -envlist = py36, py37, py38, py39, py310-dev, pypy3, rustpython, mypy, build +envlist = py36, py37, py38, py39, py310-dev, pypy3, mypy, build skip_missing_interpreters = True requires = pip>=20.3.3 @@ -21,7 +21,7 @@ requires = isolated_build = True [envlists] -test = py36, py37, py38, py39, py310-dev, pypy3, rustpython +test = py36, py37, py38, py39, py310-dev, pypy3 qa = mypy, lint [testenv] From 740c17445045c4179e252ab440dd606d91dc2b4c Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Thu, 25 Feb 2021 18:08:18 +0000 Subject: [PATCH 037/105] Relax minimum required Python version. --- repo_helper.yml | 2 ++ setup.cfg | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/repo_helper.yml b/repo_helper.yml index 5f75ee1..355cad2 100644 --- a/repo_helper.yml +++ b/repo_helper.yml @@ -37,3 +37,5 @@ classifiers: - 'Environment :: Console' - 'Framework :: Flake8' - 'Intended Audience :: Developers' + +requires_python: 3.6 diff --git a/setup.cfg b/setup.cfg index 3433ab4..293e1bc 100644 --- a/setup.cfg +++ b/setup.cfg @@ -36,7 +36,7 @@ classifiers = Typing :: Typed [options] -python_requires = >=3.6.1 +python_requires = >=3.6 zip_safe = False include_package_data = True packages = find: From 75dc5817494e5005ffe7bd72b73e21685d3a767f Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Thu, 25 Feb 2021 18:11:52 +0000 Subject: [PATCH 038/105] Updated files with 'repo_helper'. (#17) Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .github/workflows/python_ci.yml | 3 ++- .pre-commit-config.yaml | 4 ++-- .pylintrc | 2 +- pyproject.toml | 22 ++++++++++++++++++++++ setup.py | 3 +++ tox.ini | 17 ++++++++++------- 6 files changed, 40 insertions(+), 11 deletions(-) diff --git a/.github/workflows/python_ci.yml b/.github/workflows/python_ci.yml index 7480051..841c930 100644 --- a/.github/workflows/python_ci.yml +++ b/.github/workflows/python_ci.yml @@ -13,7 +13,7 @@ jobs: runs-on: "windows-2019" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-alpha.5' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-alpha.5,pypy-3.6' strategy: fail-fast: False @@ -24,6 +24,7 @@ jobs: - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - {python-version: "3.10.0-alpha.5", testenvs: "py310-dev,build", experimental: True} + - {python-version: "pypy-3.6", testenvs: "pypy3,build", experimental: False} steps: - name: Checkout 🛎️ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5ad3ecc..43a1b94 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -41,7 +41,7 @@ repos: files: ^flake8_github_actions/.*\.py$ - repo: https://github.com/domdfcoding/flake2lint - rev: v0.2.0 + rev: v0.3.0 hooks: - id: flake2lint @@ -68,7 +68,7 @@ repos: - id: forbid-crlf - repo: https://github.com/repo-helper/formate - rev: v0.3.1 + rev: v0.4.2 hooks: - id: formate exclude: ^(doc-source/conf|__pkginfo__|make_conda_recipe|setup)\.(_)?py$ diff --git a/.pylintrc b/.pylintrc index 12063c9..a21206a 100644 --- a/.pylintrc +++ b/.pylintrc @@ -66,7 +66,7 @@ confidence= # no Warning level messages displayed, use"--disable=all --enable=classes # --disable=W" disable=all -enable=assert-on-tuple,astroid-error,bad-except-order,bad-inline-option,bad-option-value,bad-reversed-sequence,bare-except,binary-op-exception,boolean-datetime,catching-non-exception,cell-var-from-loop,confusing-with-statement,consider-merging-isinstance,consider-using-enumerate,consider-using-ternary,continue-in-finally,cyclic-import,deprecated-pragma,django-not-available,duplicate-except,duplicate-key,eval-used,exec-used,expression-not-assigned,fatal,file-ignored,fixme,global-at-module-level,global-statement,global-variable-not-assigned,global-variable-undefined,http-response-with-content-type-json,http-response-with-json-dumps,invalid-all-object,invalid-characters-in-docstring,len-as-condition,literal-comparison,locally-disabled,locally-enabled,lost-exception,lowercase-l-suffix,misplaced-bare-raise,missing-kwoa,mixed-line-endings,model-has-unicode,model-missing-unicode,model-no-explicit-unicode,model-unicode-not-callable,multiple-imports,multiple-statements,new-db-field-with-default,non-ascii-bytes-literals,nonexistent-operator,not-in-loop,notimplemented-raised,overlapping-except,parse-error,pointless-statement,pointless-string-statement,raising-bad-type,raising-non-exception,raw-checker-failed,redefine-in-handler,redefined-argument-from-local,redefined-builtin,redundant-content-type-for-json-response,reimported,relative-import,return-outside-function,simplifiable-if-statement,singleton-comparison,syntax-error,trailing-comma-tuple,trailing-newlines,unbalanced-tuple-unpacking,undefined-all-variable,undefined-loop-variable,unexpected-line-ending-format,unidiomatic-typecheck,unnecessary-lambda,unnecessary-pass,unnecessary-semicolon,unneeded-not,unpacking-non-sequence,unreachable,unrecognized-inline-option,used-before-assignment,useless-else-on-loop,using-constant-test,wildcard-import,yield-outside-function,useless-return +enable=assert-on-tuple,astroid-error,bad-except-order,bad-inline-option,bad-option-value,bad-reversed-sequence,bare-except,binary-op-exception,boolean-datetime,catching-non-exception,cell-var-from-loop,confusing-with-statement,consider-merging-isinstance,consider-using-enumerate,consider-using-ternary,continue-in-finally,cyclic-import,deprecated-pragma,django-not-available,duplicate-except,duplicate-key,eval-used,exec-used,expression-not-assigned,fatal,file-ignored,fixme,global-at-module-level,global-statement,global-variable-not-assigned,global-variable-undefined,http-response-with-content-type-json,http-response-with-json-dumps,invalid-all-object,invalid-characters-in-docstring,len-as-condition,literal-comparison,locally-disabled,locally-enabled,lost-exception,lowercase-l-suffix,misplaced-bare-raise,missing-kwoa,mixed-line-endings,model-has-unicode,model-missing-unicode,model-no-explicit-unicode,model-unicode-not-callable,multiple-imports,new-db-field-with-default,non-ascii-bytes-literals,nonexistent-operator,not-in-loop,notimplemented-raised,overlapping-except,parse-error,pointless-statement,pointless-string-statement,raising-bad-type,raising-non-exception,raw-checker-failed,redefine-in-handler,redefined-argument-from-local,redefined-builtin,redundant-content-type-for-json-response,reimported,relative-import,return-outside-function,simplifiable-if-statement,singleton-comparison,syntax-error,trailing-comma-tuple,trailing-newlines,unbalanced-tuple-unpacking,undefined-all-variable,undefined-loop-variable,unexpected-line-ending-format,unidiomatic-typecheck,unnecessary-lambda,unnecessary-pass,unnecessary-semicolon,unneeded-not,unpacking-non-sequence,unreachable,unrecognized-inline-option,used-before-assignment,useless-else-on-loop,using-constant-test,wildcard-import,yield-outside-function,useless-return [REPORTS] diff --git a/pyproject.toml b/pyproject.toml index 575f636..969c374 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,5 +2,27 @@ requires = [ "setuptools>=40.6.0", "wheel>=0.34.2",] build-backend = "setuptools.build_meta" +[project] +name = "flake8-github-actions" +version = "0.1.0" +description = "GitHub Actions integration for flake8." +readme = "README.rst" +keywords = [ "flake8", "github", "github-actions",] +dynamic = [ "requires-python", "classifiers", "dependencies",] +[[project.authors]] +email = "dominic@davis-foster.co.uk" +name = "Dominic Davis-Foster" + [tool.importcheck] always = [ "flake8_github_actions",] + +[project.license] +file = "LICENSE" + +[project.urls] +Homepage = "https://github.com/domdfcoding/flake8-github-actions" +"Issue Tracker" = "https://github.com/domdfcoding/flake8-github-actions/issues" +"Source Code" = "https://github.com/domdfcoding/flake8-github-actions" + +[project.entry-points."flake8.report"] +github = "flake8_github_actions:GitHubFormatter" diff --git a/setup.py b/setup.py index 499308a..762f9ac 100644 --- a/setup.py +++ b/setup.py @@ -2,6 +2,7 @@ # This file is managed by 'repo_helper'. Don't edit it directly. # stdlib +import shutil import sys # 3rd party @@ -19,3 +20,5 @@ py_modules=[], version=__version__, ) + +shutil.rmtree("flake8_github_actions.egg-info", ignore_errors=True) diff --git a/tox.ini b/tox.ini index bd1ddc4..fe2f060 100644 --- a/tox.ini +++ b/tox.ini @@ -15,10 +15,11 @@ [tox] envlist = py36, py37, py38, py39, py310-dev, pypy3, mypy, build skip_missing_interpreters = True +isolated_build = True requires = pip>=20.3.3 - tox-envlist>=0.1.0 -isolated_build = True + tox-envlist>=0.2.1 + tox-pip-version>=0.0.7 [envlists] test = py36, py37, py38, py39, py310-dev, pypy3 @@ -47,7 +48,7 @@ commands = basepython = python3.6 changedir = {toxinidir} ignore_errors = True -skip_install = True +skip_install = False deps = flake8 >=3.8.2 flake8-2020 >= 1.6.0 @@ -60,6 +61,8 @@ deps = flake8-sphinx-links>=0.0.4 flake8-strftime>=0.1.1 flake8-typing-imports>=1.10.0 + flake8-encodings>=0.1.0 + flake8-slots>=0.1.0 git+https://github.com/PyCQA/pydocstyle@5118faa7173b0e5bbc230c4adf628758e13605bf git+https://github.com/domdfcoding/flake8-quotes.git git+https://github.com/domdfcoding/flake8-rst-docstrings.git @@ -71,7 +74,7 @@ commands = python3 -m flake8_rst_docstrings_sphinx flake8_github_actions --allow basepython = python3.6 ignore_errors = True changedir = {toxinidir} -deps = mypy==0.790 +deps = mypy==0.800 commands = mypy flake8_github_actions {posargs} [testenv:pyup] @@ -84,15 +87,15 @@ commands = pyup_dirs flake8_github_actions --py36-plus --recursive [flake8] max-line-length = 120 -select = E111 E112 E113 E121 E122 E125 E127 E128 E129 E131 E133 E201 E202 E203 E211 E222 E223 E224 E225 E225 E226 E227 E228 E231 E241 E242 E251 E261 E262 E265 E271 E272 E303 E304 E306 E402 E502 E703 E711 E712 E713 E714 E721 W291 W292 W293 W391 W504 YTT101 YTT102 YTT103 YTT201 YTT202 YTT203 YTT204 YTT301 YTT302 YTT303 STRFTIME001 STRFTIME002 SXL001 PT001 PT002 PT003 PT005 PT006 PT007 PT008 PT009 PT010 PT011 PT012 PT013 PT014 PT015 PT016 PT017 PT018 PT019 PT020 PT021 RST201 RST202 RST203 RST204 RST205 RST206 RST207 RST208 RST210 RST211 RST212 RST213 RST214 RST215 RST216 RST217 RST218 RST219 RST299 RST301 RST302 RST303 RST304 RST305 RST306 RST399 RST401 RST499 RST900 RST901 RST902 RST903 Q001 Q002 Q003 A001 A002 A003 TYP001 TYP002 TYP003 TYP004 TYP005 TYP006 Y001,Y002 Y003 Y004 Y005 Y006 Y007 Y008 Y009 Y010 Y011 Y012 Y013 Y014 Y015 Y090 Y091 E301 E302 E305 D100 D101 D102 D103 D104 D106 D201 D204 D207 D208 D209 D210 D211 D212 D213 D214 D215 D300 D301 D400 D402 D403 D404 D415 D417 DALL000 +select = E111 E112 E113 E121 E122 E125 E127 E128 E129 E131 E133 E201 E202 E203 E211 E222 E223 E224 E225 E225 E226 E227 E228 E231 E241 E242 E251 E261 E262 E265 E271 E272 E303 E304 E306 E402 E502 E703 E711 E712 E713 E714 E721 W291 W292 W293 W391 W504 YTT101 YTT102 YTT103 YTT201 YTT202 YTT203 YTT204 YTT301 YTT302 YTT303 STRFTIME001 STRFTIME002 SXL001 PT001 PT002 PT003 PT005 PT006 PT007 PT008 PT009 PT010 PT011 PT012 PT013 PT014 PT015 PT016 PT017 PT018 PT019 PT020 PT021 RST201 RST202 RST203 RST204 RST205 RST206 RST207 RST208 RST210 RST211 RST212 RST213 RST214 RST215 RST216 RST217 RST218 RST219 RST299 RST301 RST302 RST303 RST304 RST305 RST306 RST399 RST401 RST499 RST900 RST901 RST902 RST903 Q001 Q002 Q003 A001 A002 A003 TYP001 TYP002 TYP003 TYP004 TYP005 TYP006 ENC001 ENC002 ENC003 ENC004 Y001,Y002 Y003 Y004 Y005 Y006 Y007 Y008 Y009 Y010 Y011 Y012 Y013 Y014 Y015 Y090 Y091 E301 E302 E305 D100 D101 D102 D103 D104 D106 D201 D204 D207 D208 D209 D210 D211 D212 D213 D214 D215 D300 D301 D400 D402 D403 D404 D415 D417 DALL000 SLOT000 SLOT001 SLOT002 SLOT003 exclude = doc-source,.git,__pycache__,old,build,dist,__pkginfo__.py,setup.py,.tox,venv rst-directives = TODO envvar extras-require per-file-ignores = - tests/*: D100 D101 D102 D103 D104 D106 D201 D204 D207 D208 D209 D210 D211 D212 D213 D214 D215 D300 D301 D400 D402 D403 D404 D415 D417 DALL000 - */*.pyi: E301 E302 E305 D100 D101 D102 D103 D104 D106 D201 D204 D207 D208 D209 D210 D211 D212 D213 D214 D215 D300 D301 D400 D402 D403 D404 D415 D417 DALL000 + tests/*: D100 D101 D102 D103 D104 D106 D201 D204 D207 D208 D209 D210 D211 D212 D213 D214 D215 D300 D301 D400 D402 D403 D404 D415 D417 DALL000 SLOT000 SLOT001 SLOT002 SLOT003 + */*.pyi: E301 E302 E305 D100 D101 D102 D103 D104 D106 D201 D204 D207 D208 D209 D210 D211 D212 D213 D214 D215 D300 D301 D400 D402 D403 D404 D415 D417 DALL000 SLOT000 SLOT001 SLOT002 SLOT003 pytest-parametrize-names-type = csv inline-quotes = " multiline-quotes = """ From f0520b9c120c7c60ee9af1ec2f38d98b281e23d2 Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Thu, 25 Feb 2021 20:58:56 +0000 Subject: [PATCH 039/105] Bump version v0.1.0 -> v0.1.1 --- .bumpversion.cfg | 2 +- README.rst | 2 +- __pkginfo__.py | 2 +- flake8_github_actions/__init__.py | 2 +- repo_helper.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index d697d85..dc409b8 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.1.0 +current_version = 0.1.1 commit = True tag = True diff --git a/README.rst b/README.rst index 74dfce9..cfff325 100644 --- a/README.rst +++ b/README.rst @@ -77,7 +77,7 @@ flake8-github-actions .. |language| image:: https://img.shields.io/github/languages/top/domdfcoding/flake8-github-actions :alt: GitHub top language -.. |commits-since| image:: https://img.shields.io/github/commits-since/domdfcoding/flake8-github-actions/v0.1.0 +.. |commits-since| image:: https://img.shields.io/github/commits-since/domdfcoding/flake8-github-actions/v0.1.1 :target: https://github.com/domdfcoding/flake8-github-actions/pulse :alt: GitHub commits since tagged version diff --git a/__pkginfo__.py b/__pkginfo__.py index c20c43a..dfbcb37 100644 --- a/__pkginfo__.py +++ b/__pkginfo__.py @@ -26,7 +26,7 @@ 2020 Dominic Davis-Foster """ -__version__ = "0.1.0" +__version__ = "0.1.1" repo_root = pathlib.Path(__file__).parent install_requires = (repo_root / "requirements.txt").read_text(encoding="utf-8").split('\n') diff --git a/flake8_github_actions/__init__.py b/flake8_github_actions/__init__.py index 97d3f1e..537b78d 100644 --- a/flake8_github_actions/__init__.py +++ b/flake8_github_actions/__init__.py @@ -33,7 +33,7 @@ __author__: str = "Dominic Davis-Foster" __copyright__: str = "2020 Dominic Davis-Foster" __license__: str = "MIT License" -__version__: str = "0.1.0" +__version__: str = "0.1.1" __email__: str = "dominic@davis-foster.co.uk" __all__ = ["GitHubFormatter"] diff --git a/repo_helper.yml b/repo_helper.yml index 355cad2..735ca85 100644 --- a/repo_helper.yml +++ b/repo_helper.yml @@ -5,7 +5,7 @@ copyright_years: '2020' author: 'Dominic Davis-Foster' email: 'dominic@davis-foster.co.uk' username: 'domdfcoding' -version: '0.1.0' +version: '0.1.1' license: 'MIT' short_desc: 'GitHub Actions integration for flake8.' From d257c3fee597b1bac34cbd797901ebf8b1b28cc7 Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Thu, 25 Feb 2021 21:37:19 +0000 Subject: [PATCH 040/105] Add tests. --- .github/workflows/python_ci.yml | 12 +++++- .github/workflows/python_ci_linux.yml | 55 +++++++++++++++++++++++++- .github/workflows/python_ci_macos.yml | 12 +++++- .pre-commit-config.yaml | 2 +- README.rst | 6 ++- formate.toml | 7 ++++ pyproject.toml | 5 +-- repo_helper.yml | 7 +++- tests/bad_code.py | 13 +++++++ tests/conftest.py | 1 + tests/requirements.txt | 9 +++++ tests/test_output.py | 15 +++++++ tests/test_output_/test_output.txt | 7 ++++ tox.ini | 56 ++++++++++++++++++--------- 14 files changed, 175 insertions(+), 32 deletions(-) create mode 100644 tests/bad_code.py create mode 100644 tests/conftest.py create mode 100644 tests/requirements.txt create mode 100644 tests/test_output.py create mode 100644 tests/test_output_/test_output.txt diff --git a/.github/workflows/python_ci.yml b/.github/workflows/python_ci.yml index 841c930..054b63f 100644 --- a/.github/workflows/python_ci.yml +++ b/.github/workflows/python_ci.yml @@ -13,7 +13,7 @@ jobs: runs-on: "windows-2019" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-alpha.5,pypy-3.6' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-alpha.5,pypy-3.6,pypy-3.7' strategy: fail-fast: False @@ -24,7 +24,8 @@ jobs: - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - {python-version: "3.10.0-alpha.5", testenvs: "py310-dev,build", experimental: True} - - {python-version: "pypy-3.6", testenvs: "pypy3,build", experimental: False} + - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} + - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: False} steps: - name: Checkout 🛎️ @@ -44,3 +45,10 @@ jobs: - name: "Run Tests for Python ${{ matrix.config.python-version }}" run: python -m tox -e "${{ matrix.config.testenvs }}" + + - name: "Upload Coverage 🚀" + uses: actions/upload-artifact@v2 + if: ${{ always() }} + with: + name: "coverage-${{ matrix.config.python-version }}" + path: .coverage diff --git a/.github/workflows/python_ci_linux.yml b/.github/workflows/python_ci_linux.yml index 212ca69..ae631f8 100644 --- a/.github/workflows/python_ci_linux.yml +++ b/.github/workflows/python_ci_linux.yml @@ -13,7 +13,7 @@ jobs: runs-on: "ubuntu-20.04" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-alpha.5,pypy-3.6' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-alpha.5,pypy-3.6,pypy-3.7' strategy: fail-fast: False @@ -24,7 +24,8 @@ jobs: - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - {python-version: "3.10.0-alpha.5", testenvs: "py310-dev,build", experimental: True} - - {python-version: "pypy-3.6", testenvs: "pypy3,build", experimental: False} + - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} + - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: False} steps: - name: Checkout 🛎️ @@ -41,11 +42,61 @@ jobs: python -m site python -m pip install --upgrade pip setuptools wheel python -m pip install --upgrade tox virtualenv + python -m pip install --upgrade coverage_pyver_pragma - name: "Run Tests for Python ${{ matrix.config.python-version }}" run: python -m tox -e "${{ matrix.config.testenvs }}" + - name: "Upload Coverage 🚀" + uses: actions/upload-artifact@v2 + if: ${{ always() }} + with: + name: "coverage-${{ matrix.config.python-version }}" + path: .coverage + + + Coverage: + needs: tests + runs-on: "ubuntu-20.04" + steps: + - name: Checkout 🛎️ + uses: "actions/checkout@v2" + + - name: Setup Python 🐍 + uses: "actions/setup-python@v2" + with: + python-version: 3.8 + - name: Install dependencies 🔧 + run: | + python -m pip install --upgrade pip setuptools wheel + python -m pip install --upgrade "coveralls>=3.0.0" coverage_pyver_pragma + + - name: "Download Coverage 🪂" + uses: actions/download-artifact@v2 + with: + path: coverage + + - name: Display structure of downloaded files + run: ls -R + working-directory: coverage + + - name: Combine Coverage 👷 + run: | + shopt -s globstar + python -m coverage combine coverage/**/.coverage + + - name: "Upload Combined Coverage Artefact 🚀" + uses: actions/upload-artifact@v2 + with: + name: "combined-coverage" + path: .coverage + + - name: "Upload Combined Coverage to Coveralls" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + coveralls --service=github Deploy: needs: tests diff --git a/.github/workflows/python_ci_macos.yml b/.github/workflows/python_ci_macos.yml index de589e6..0d0c451 100644 --- a/.github/workflows/python_ci_macos.yml +++ b/.github/workflows/python_ci_macos.yml @@ -13,7 +13,7 @@ jobs: runs-on: "macos-latest" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-alpha.5,pypy-3.6' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-alpha.5,pypy-3.6,pypy-3.7' strategy: fail-fast: False @@ -24,7 +24,8 @@ jobs: - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - {python-version: "3.10.0-alpha.5", testenvs: "py310-dev,build", experimental: True} - - {python-version: "pypy-3.6", testenvs: "pypy3,build", experimental: False} + - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} + - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: False} steps: - name: Checkout 🛎️ @@ -44,3 +45,10 @@ jobs: - name: "Run Tests for Python ${{ matrix.config.python-version }}" run: python -m tox -e "${{ matrix.config.testenvs }}" + + - name: "Upload Coverage 🚀" + uses: actions/upload-artifact@v2 + if: ${{ always() }} + with: + name: "coverage-${{ matrix.config.python-version }}" + path: .coverage diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 43a1b94..2d1263b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,7 +1,7 @@ # This file is managed by 'repo_helper'. Don't edit it directly. --- -exclude: ^$ +exclude: ^tests/bad_code.py$ repos: - repo: https://github.com/pre-commit/pre-commit-hooks diff --git a/README.rst b/README.rst index cfff325..de7615c 100644 --- a/README.rst +++ b/README.rst @@ -16,7 +16,7 @@ flake8-github-actions :widths: 10 90 * - Tests - - |actions_linux| |actions_windows| |actions_macos| + - |actions_linux| |actions_windows| |actions_macos| |coveralls| * - PyPI - |pypi-version| |supported-versions| |supported-implementations| |wheel| * - Activity @@ -50,6 +50,10 @@ flake8-github-actions :target: https://requires.io/github/domdfcoding/flake8-github-actions/requirements/?branch=master :alt: Requirements Status +.. |coveralls| image:: https://img.shields.io/coveralls/github/domdfcoding/flake8-github-actions/master?logo=coveralls + :target: https://coveralls.io/github/domdfcoding/flake8-github-actions?branch=master + :alt: Coverage + .. |codefactor| image:: https://img.shields.io/codefactor/grade/github/domdfcoding/flake8-github-actions?logo=codefactor :target: https://www.codefactor.io/repository/github/domdfcoding/flake8-github-actions :alt: CodeFactor Grade diff --git a/formate.toml b/formate.toml index be02f67..047fea9 100644 --- a/formate.toml +++ b/formate.toml @@ -35,7 +35,10 @@ known_third_party = [ "apeye", "attrs", "click", + "coincidence", "consolekit", + "coverage", + "coverage_pyver_pragma", "domdf_python_tools", "dulwich", "flake8", @@ -43,6 +46,10 @@ known_third_party = [ "flake8_prettycount", "github", "github3_py", + "pytest", + "pytest_cov", + "pytest_randomly", + "pytest_timeout", "requests", "typing_extensions", ] diff --git a/pyproject.toml b/pyproject.toml index 969c374..10d2d94 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "flake8-github-actions" -version = "0.1.0" +version = "0.1.1" description = "GitHub Actions integration for flake8." readme = "README.rst" keywords = [ "flake8", "github", "github-actions",] @@ -13,9 +13,6 @@ dynamic = [ "requires-python", "classifiers", "dependencies",] email = "dominic@davis-foster.co.uk" name = "Dominic Davis-Foster" -[tool.importcheck] -always = [ "flake8_github_actions",] - [project.license] file = "LICENSE" diff --git a/repo_helper.yml b/repo_helper.yml index 735ca85..d0eb214 100644 --- a/repo_helper.yml +++ b/repo_helper.yml @@ -10,7 +10,6 @@ license: 'MIT' short_desc: 'GitHub Actions integration for flake8.' enable_conda: false -enable_tests: false enable_docs: false python_versions: @@ -19,7 +18,8 @@ python_versions: - '3.8' - '3.9' - 3.10-dev - - pypy3 + - pypy36 + - pypy37 additional_ignore: - action.py @@ -39,3 +39,6 @@ classifiers: - 'Intended Audience :: Developers' requires_python: 3.6 + +pre_commit_exclude: "^tests/bad_code.py$" +min_coverage: 100 diff --git a/tests/bad_code.py b/tests/bad_code.py new file mode 100644 index 0000000..ba3f389 --- /dev/null +++ b/tests/bad_code.py @@ -0,0 +1,13 @@ +# type: ignore +import warnings + + +from __future__ import annotations + + + + + +print(name) + +break \ No newline at end of file diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..81ca008 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1 @@ +pytest_plugins = ("coincidence", ) diff --git a/tests/requirements.txt b/tests/requirements.txt new file mode 100644 index 0000000..ee085e8 --- /dev/null +++ b/tests/requirements.txt @@ -0,0 +1,9 @@ +coincidence>=0.1.0 +coverage>=5.1 +coverage-pyver-pragma>=0.0.6 +domdf-python-tools[testing]>=2.0.1 +iniconfig!=1.1.0,>=1.0.1 +pytest>=6.0.0 +pytest-cov>=2.8.1 +pytest-randomly>=3.3.1 +pytest-timeout>=1.4.2 diff --git a/tests/test_output.py b/tests/test_output.py new file mode 100644 index 0000000..bb9efc0 --- /dev/null +++ b/tests/test_output.py @@ -0,0 +1,15 @@ +# 3rd party +import pytest +from coincidence.regressions import FileRegressionFixture, check_file_regression +from domdf_python_tools.paths import PathPlus +from flake8.main import cli # type: ignore + +bad_code = PathPlus(__file__).parent / "bad_code.py" + + +def test_output(file_regression: FileRegressionFixture, capsys): + with pytest.raises(SystemExit): + cli.main([str(bad_code), "--select", "F401,F404,F821,F701,E303", "--format", "github"]) + + check_file_regression(capsys.readouterr().out, file_regression) + assert not capsys.readouterr().err diff --git a/tests/test_output_/test_output.txt b/tests/test_output_/test_output.txt new file mode 100644 index 0000000..51dbf80 --- /dev/null +++ b/tests/test_output_/test_output.txt @@ -0,0 +1,7 @@ +/home/domdf/Python/01 GitHub Repos/01 Flake8 Plugins/flake8-github-actions/tests/bad_code.py +::warning file=/home/domdf/Python/01 GitHub Repos/01 Flake8 Plugins/flake8-github-actions/tests/bad_code.py,line=2,col=1::F401: 'warnings' imported but unused +::warning file=/home/domdf/Python/01 GitHub Repos/01 Flake8 Plugins/flake8-github-actions/tests/bad_code.py,line=5,col=1::F404: from __future__ imports must occur at the beginning of the file +::warning file=/home/domdf/Python/01 GitHub Repos/01 Flake8 Plugins/flake8-github-actions/tests/bad_code.py,line=11,col=1::E303: too many blank lines (5) +::warning file=/home/domdf/Python/01 GitHub Repos/01 Flake8 Plugins/flake8-github-actions/tests/bad_code.py,line=11,col=7::F821: undefined name 'name' +::warning file=/home/domdf/Python/01 GitHub Repos/01 Flake8 Plugins/flake8-github-actions/tests/bad_code.py,line=13,col=1::F701: 'break' outside loop +5 diff --git a/tox.ini b/tox.ini index fe2f060..756cfd6 100644 --- a/tox.ini +++ b/tox.ini @@ -8,12 +8,15 @@ # * testenv:lint # * testenv:mypy # * testenv:pyup +# * testenv:coverage # * flake8 +# * coverage:run +# * coverage:report # * check-wheel-contents # * pytest [tox] -envlist = py36, py37, py38, py39, py310-dev, pypy3, mypy, build +envlist = py36, py37, py38, py39, py310-dev, pypy36, pypy37, mypy, build skip_missing_interpreters = True isolated_build = True requires = @@ -22,15 +25,16 @@ requires = tox-pip-version>=0.0.7 [envlists] -test = py36, py37, py38, py39, py310-dev, pypy3 +test = py36, py37, py38, py39, py310-dev, pypy36, pypy37 qa = mypy, lint +cov = py36, coverage [testenv] setenv = PYTHONDEVMODE = 1 -deps = importcheck>=0.1.0 +deps = -r{toxinidir}/tests/requirements.txt commands = python --version - python -m importcheck {posargs} + python -m pytest --cov=flake8_github_actions -r aR tests/ {posargs} [testenv:build] skip_install = True @@ -68,14 +72,16 @@ deps = git+https://github.com/domdfcoding/flake8-rst-docstrings.git git+https://github.com/domdfcoding/flake8-rst-docstrings-sphinx.git pygments>=2.7.1 -commands = python3 -m flake8_rst_docstrings_sphinx flake8_github_actions --allow-toolbox {posargs} +commands = python3 -m flake8_rst_docstrings_sphinx flake8_github_actions tests --allow-toolbox {posargs} [testenv:mypy] basepython = python3.6 ignore_errors = True changedir = {toxinidir} -deps = mypy==0.800 -commands = mypy flake8_github_actions {posargs} +deps = + mypy==0.800 + -r{toxinidir}/tests/requirements.txt +commands = mypy flake8_github_actions tests {posargs} [testenv:pyup] basepython = python3.6 @@ -83,7 +89,21 @@ skip_install = True ignore_errors = True changedir = {toxinidir} deps = pyupgrade-directories -commands = pyup_dirs flake8_github_actions --py36-plus --recursive +commands = pyup_dirs flake8_github_actions tests --py36-plus --recursive + +[testenv:coverage] +basepython = python3.6 +skip_install = True +ignore_errors = True +whitelist_externals = /bin/bash +changedir = {toxinidir} +deps = + coverage>=5 + coverage_pyver_pragma>=0.0.6 +commands = + /bin/bash -c "rm -rf htmlcov" + coverage html + /bin/bash -c "DISPLAY=:0 firefox 'htmlcov/index.html'" [flake8] max-line-length = 120 @@ -102,19 +122,11 @@ multiline-quotes = """ docstring-quotes = """ count = True -[check-wheel-contents] -ignore = W002 -toplevel = flake8_github_actions -package = flake8_github_actions - -[pytest] -addopts = --color yes --durations 25 -timeout = 300 - [coverage:run] plugins = coverage_pyver_pragma [coverage:report] +fail_under = 80 exclude_lines = raise AssertionError raise NotImplementedError @@ -123,7 +135,15 @@ exclude_lines = if TYPE_CHECKING: if typing.TYPE_CHECKING: if __name__ == .__main__.: - \.\.\. + +[check-wheel-contents] +ignore = W002 +toplevel = flake8_github_actions +package = flake8_github_actions + +[pytest] +addopts = --color yes --durations 25 +timeout = 300 [gh-actions] python = From 5fca45326f771bbc6ab63bf582c8b447a4c5faaf Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Thu, 25 Feb 2021 22:33:48 +0000 Subject: [PATCH 041/105] Fix tests. --- repo_helper.yml | 3 ++ tests/test_output.py | 3 +- tests/test_output_/test_output.txt | 12 +++---- tox.ini | 55 +++++++++++++++--------------- 4 files changed, 38 insertions(+), 35 deletions(-) diff --git a/repo_helper.yml b/repo_helper.yml index d0eb214..8977e35 100644 --- a/repo_helper.yml +++ b/repo_helper.yml @@ -42,3 +42,6 @@ requires_python: 3.6 pre_commit_exclude: "^tests/bad_code.py$" min_coverage: 100 + +tox_unmanaged: + - "testenv:lint" diff --git a/tests/test_output.py b/tests/test_output.py index bb9efc0..c91e9cd 100644 --- a/tests/test_output.py +++ b/tests/test_output.py @@ -11,5 +11,6 @@ def test_output(file_regression: FileRegressionFixture, capsys): with pytest.raises(SystemExit): cli.main([str(bad_code), "--select", "F401,F404,F821,F701,E303", "--format", "github"]) - check_file_regression(capsys.readouterr().out, file_regression) + stdout = capsys.readouterr().out.replace(str(bad_code), "bad_code.py") + check_file_regression(stdout, file_regression) assert not capsys.readouterr().err diff --git a/tests/test_output_/test_output.txt b/tests/test_output_/test_output.txt index 51dbf80..e8450c4 100644 --- a/tests/test_output_/test_output.txt +++ b/tests/test_output_/test_output.txt @@ -1,7 +1,7 @@ -/home/domdf/Python/01 GitHub Repos/01 Flake8 Plugins/flake8-github-actions/tests/bad_code.py -::warning file=/home/domdf/Python/01 GitHub Repos/01 Flake8 Plugins/flake8-github-actions/tests/bad_code.py,line=2,col=1::F401: 'warnings' imported but unused -::warning file=/home/domdf/Python/01 GitHub Repos/01 Flake8 Plugins/flake8-github-actions/tests/bad_code.py,line=5,col=1::F404: from __future__ imports must occur at the beginning of the file -::warning file=/home/domdf/Python/01 GitHub Repos/01 Flake8 Plugins/flake8-github-actions/tests/bad_code.py,line=11,col=1::E303: too many blank lines (5) -::warning file=/home/domdf/Python/01 GitHub Repos/01 Flake8 Plugins/flake8-github-actions/tests/bad_code.py,line=11,col=7::F821: undefined name 'name' -::warning file=/home/domdf/Python/01 GitHub Repos/01 Flake8 Plugins/flake8-github-actions/tests/bad_code.py,line=13,col=1::F701: 'break' outside loop +bad_code.py +::warning file=bad_code.py,line=2,col=1::F401: 'warnings' imported but unused +::warning file=bad_code.py,line=5,col=1::F404: from __future__ imports must occur at the beginning of the file +::warning file=bad_code.py,line=11,col=1::E303: too many blank lines (5) +::warning file=bad_code.py,line=11,col=7::F821: undefined name 'name' +::warning file=bad_code.py,line=13,col=1::F701: 'break' outside loop 5 diff --git a/tox.ini b/tox.ini index 756cfd6..0b5d507 100644 --- a/tox.ini +++ b/tox.ini @@ -5,7 +5,6 @@ # * testenv # * testenv:docs # * testenv:build -# * testenv:lint # * testenv:mypy # * testenv:pyup # * testenv:coverage @@ -48,32 +47,6 @@ commands = twine check dist/*.tar.gz dist/*.whl check-wheel-contents dist/ -[testenv:lint] -basepython = python3.6 -changedir = {toxinidir} -ignore_errors = True -skip_install = False -deps = - flake8 >=3.8.2 - flake8-2020 >= 1.6.0 - flake8-builtins>=1.5.3 - flake8-docstrings>=1.5.0 - flake8-dunder-all>=0.1.1 - flake8-github-actions>=0.1.0 - flake8-pyi>=20.10.0 - flake8-pytest-style>=1.3.0 - flake8-sphinx-links>=0.0.4 - flake8-strftime>=0.1.1 - flake8-typing-imports>=1.10.0 - flake8-encodings>=0.1.0 - flake8-slots>=0.1.0 - git+https://github.com/PyCQA/pydocstyle@5118faa7173b0e5bbc230c4adf628758e13605bf - git+https://github.com/domdfcoding/flake8-quotes.git - git+https://github.com/domdfcoding/flake8-rst-docstrings.git - git+https://github.com/domdfcoding/flake8-rst-docstrings-sphinx.git - pygments>=2.7.1 -commands = python3 -m flake8_rst_docstrings_sphinx flake8_github_actions tests --allow-toolbox {posargs} - [testenv:mypy] basepython = python3.6 ignore_errors = True @@ -126,7 +99,7 @@ count = True plugins = coverage_pyver_pragma [coverage:report] -fail_under = 80 +fail_under = 100 exclude_lines = raise AssertionError raise NotImplementedError @@ -145,6 +118,32 @@ package = flake8_github_actions addopts = --color yes --durations 25 timeout = 300 +[testenv:lint] +basepython = python3.6 +changedir = {toxinidir} +ignore_errors = True +skip_install = False +deps = + flake8 >=3.8.2 + flake8-2020 >= 1.6.0 + flake8-builtins>=1.5.3 + flake8-docstrings>=1.5.0 + flake8-dunder-all>=0.1.1 + flake8-github-actions>=0.1.0 + flake8-pyi>=20.10.0 + flake8-pytest-style>=1.3.0 + flake8-sphinx-links>=0.0.4 + flake8-strftime>=0.1.1 + flake8-typing-imports>=1.10.0 + flake8-encodings>=0.1.0 + flake8-slots>=0.1.0 + git+https://github.com/PyCQA/pydocstyle@5118faa7173b0e5bbc230c4adf628758e13605bf + git+https://github.com/domdfcoding/flake8-quotes.git + git+https://github.com/domdfcoding/flake8-rst-docstrings.git + git+https://github.com/domdfcoding/flake8-rst-docstrings-sphinx.git + pygments>=2.7.1 +commands = python3 -m flake8_rst_docstrings_sphinx flake8_github_actions tests --allow-toolbox --extend-exclude bad_code.py {posargs} + [gh-actions] python = 3.6: py36, build, mypy From f81ece170ff870e593d476bc107af718e8db7c82 Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Fri, 26 Feb 2021 22:00:44 +0000 Subject: [PATCH 042/105] Remove redundant Plural instances --- flake8_github_actions/__init__.py | 8 ++------ requirements.txt | 1 - 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/flake8_github_actions/__init__.py b/flake8_github_actions/__init__.py index 537b78d..c6f2a45 100644 --- a/flake8_github_actions/__init__.py +++ b/flake8_github_actions/__init__.py @@ -5,7 +5,7 @@ GitHub Actions integration for flake8. """ # -# Copyright © 2020 Dominic Davis-Foster +# Copyright © 2020-2021 Dominic Davis-Foster # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -27,20 +27,16 @@ # # 3rd party -from domdf_python_tools.words import Plural from flake8.formatting.base import BaseFormatter # type: ignore __author__: str = "Dominic Davis-Foster" -__copyright__: str = "2020 Dominic Davis-Foster" +__copyright__: str = "2020-2021 Dominic Davis-Foster" __license__: str = "MIT License" __version__: str = "0.1.1" __email__: str = "dominic@davis-foster.co.uk" __all__ = ["GitHubFormatter"] -_error = Plural("error", "errors") -_file = Plural("file", "files") - class GitHubFormatter(BaseFormatter): """ diff --git a/requirements.txt b/requirements.txt index 575ad80..4163a01 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1 @@ -domdf-python-tools>=2.0.0 flake8>=3.8.4 From 808d99f4a0da085b2d6631d4957b9697a49f0ffd Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Sun, 28 Feb 2021 22:22:43 +0000 Subject: [PATCH 043/105] Add image showing an example of the annotations --- example_annotations.png | Bin 0 -> 95585 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 example_annotations.png diff --git a/example_annotations.png b/example_annotations.png new file mode 100644 index 0000000000000000000000000000000000000000..f821ec45d31bf68bade28b672da43e2d4778d156 GIT binary patch literal 95585 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%0AtsJjU- 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

  • hNoJp2$S}c1sEp0-rfy zqE0;woGIzsc?t?esJOCpy4p2QJw}doXz3-lpP+6Nv{V~BZYBsahcep+lh;V2Tj*py!@l1qectN0dYBbG7MZSEMKeLO{XIz^TzXGR9P+) zKmmB*DdghZ+NSLy%A}83>$asMHc29&I|nk)xJT&F{7TFbaU^^$2a}cE&BBNLxA&ml zq`DNBf&J8~LSV{XpQ$<7dHM)?aHu~IPP-j_Lm;R=D^LvS1si;+ioGfH0Xi2O2fzD1 zIrMqH!36{{Qxs_^M*3LWWk30IczX7#BtV$o0n;TuFETqd@U+4 zpXh{fhv!v>o{u%d(uS47u=W;Q1*>chlC&_;qNJSc9T{jCP<^U5j{fG1m1rP;O1a`J z$g;Duwq^|R7k~QbZ5f@Wib_Ia1p9}{$B?a^v$JEdH=F|t+W#^K(j+)S#8--^HU<(1 z1{bPgnK*)44bc6?L8l~T$n4@4K5`CSA^ zaiuasN!WkfAVxMzK7j?&fCX;Q_JP%Px$a0qLA$OpGc(=vzJ9XcaU2l|iB(@_!+k8h zCfDo9qNaNJ%_~#nPr@`D+aq}rCsPcJjFr|}-s?B*AXTkDsZN*yFJdbId)G5Da=7Yl zG2D>44QO#ZUdFWx5hZ4-Ak} zJWZVn4@KDZZN~a3Ye1g~%VwWrs^Zg>>eqZt8w9tBUYzO-@d)=4I#q{=Z1twl{*9AY zxRUHVuKc7tM7+Gy7-+gmv{xxqz{zEX7Ts+G8u#20n!&$QAb+_m6evnc@rgyCSeja% z`!&|)c%6RLJOX4G{fSGwC#¬6QLkBn&*aNrn6IdOKi}jpyb1S7jmOqgCK_^QtmR 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 z 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 literal 0 HcmV?d00001 From 512f8a6c2e80d88c81a2f868e955c3b46e6497a2 Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Sun, 28 Feb 2021 22:25:59 +0000 Subject: [PATCH 044/105] Add the example output image to the readme. --- README.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.rst b/README.rst index de7615c..ec60254 100644 --- a/README.rst +++ b/README.rst @@ -157,3 +157,8 @@ Example workflow: - name: "Run Flake8" run: "flake8 --format github" + + +The annotations will look something like: + +.. image:: https://raw.githubusercontent.com/domdfcoding/flake8-github-actions/master/example_annotations.png From e8980a4b2cc2f60e378a2a61628efe2ccb20d68a Mon Sep 17 00:00:00 2001 From: "imgbot[bot]" <31301654+imgbot[bot]@users.noreply.github.com> Date: Sun, 28 Feb 2021 23:23:57 +0000 Subject: [PATCH 045/105] [ImgBot] Optimize images (#19) /example_annotations.png -- 93.34kb -> 80.48kb (13.78%) Signed-off-by: ImgBotApp Co-authored-by: ImgBotApp --- example_annotations.png | Bin 95585 -> 82415 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/example_annotations.png b/example_annotations.png index f821ec45d31bf68bade28b672da43e2d4778d156..50d3f0d19534aa414ce3d01257276227a5487bed 100644 GIT binary patch literal 82415 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%0DJHd2D7Afl<%qj4jT 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%0AtsJjU- ziWnxI+r;7a8tD*#wFkK0LRY6^`ogB4S^%(WBtkVAN3(khv6Sgkhl|PpAlF|%rqJvc zr}FhMnoNNJ3KTT#=NOOMRHsF_b`kF%_5@5R7Hcg%d{|j)8^VGQ@FajR)^10U^}qWU-d_J1s5_)lTOe-8hn zz5(a!h>&epB!iKW(Yz>-c-o&Xzo$=o+dIGqQPWpS(XaCiA0ONcv0p>SY2JsAmQcm@#D|pV(#EJIYq@LziSM7e=g?7kE&>Z zzI!;5B|8noPH}K<7?A7zTR}v0RdO0n08a=0iigKxBvabY&reWLkcdw36opEY^7s4j zp&x_V1&Uv)JY6o)`>wSHs;cE~*Fk#DnE|#A6^!7riHfTU5mS8+@sV#l#%tfta(=?=U0&`_?AW|ud>h!TN&5z~rZF_oZx<&UKrNHpnP z0OaOtdy5E}EUm)FL7wG^Qe}Q#|MZ6%KK~D-VF`XV|L_=cTsUsowyM|V+9y+U=0K&K#4& zKt4xE+{W=YIw41Zm+5(t=KYl6>UyW7#bc)T8jqw@zp_HPlySlvt7i!Jk|=w3N!=I4 zIL{URzDgN|V!b)I1YQBifn0Yey!pl%s7!~vfLiM7jkj3>tGJwYs5BUElPleFgS{*< zY>@OhKWsoYb8&Fw8Rh2XS*>+OxFZ*d9z2+?u;_#G7LClh(*00Z^PTkyp09V?p3nCd zDg`3`hMaK@)91{jp{P^hy_uu293n@HxKg8*5)}?Gh?LZ@p8iU$)YnX+<>pD1W*-%A z{M_7(==7YmfB!%~cHzvh@}PmP)}hp>{B#QDA1fc$ocxl2$qtZ~uOm|>nuS_xT~X|r zm6k(;sUl-DGcyYdh9Cgwtpd|3Dki3!BDlZa69eWqZ4UuNZfZf#!Dz8(%<}$SY%*mZ zArVo?du8R*fh)K=yZ^z#rpyGf8$h?KL6NXzR#mwS#oJ?RU_eG{b$!PZ;qc%RAo5nm z6k1waKfBb(GMOw{THdD{F4k`O5*#%-*&P^`5NdUdAP?c-I4?jG-T{gFqJ3a@zDVd* zUF6Ba?gd9a8u>P1d&VUG0nBGPG*{z`fCg{JsH?FnCGRYhe2Mb!0_Z}P=8%dF22oe2 zGl~$udDimxN8mMNA{k(5X>C09P$Bc-;T1;i+4FPv)R(pnMt%T_@9!Dl6X2tKVB}RI z!HMZPR9$P-tF@h&yy<&f+1uM!$ZJ6ZnVi4hbm?!Pr6mIf_zk-wmVbLgk-&zLB=mN} z{nY&>7+`Co&upjW3umTZX0ZOHfWp_5qm2|c1@ZBX5$#S| z^$n%Byzm(pMq73rG~ImS27$5wG2cAcOiqu6e;gU*Lkza)Oo)q%i*P#}$Uh~!(uHue{QS7Op8vA^XhCvk@1vtT z!1A`{gS1TdaA}v`uQ@AqVi@ClH99&v0|Q6~)NS<^zJ1pXwT`o82P4&2ftG&S-yu!n6V)e{#N2pFP2DXXw>4i2?sjMDafdnB^={O2|k zyH-wiw)@^}jBimcJ3dL%8RGlV1(4K46R9Tw`{H?9>W0Xd{BI6_9Rmz32y>hS!U&bsGgAAx za_DILkzs=iDDx$A@KO_<^YU;syb{u%F4ClZ6XlJfYp?O&-jnkw1GtWhl*pa_JUAT4 zG(RI{Wnlq|wkEZ>rKF@dIlqOlkcGy@X)+M$30S=b>&^_7q)n0H>+_%4jLa)|zr-%l z3PChlV?LoRw=?hG9BSs|u%$CPfX6eMq=MT*Bf>0s14<8Cv-`m9xJ!|D7(%w3hbe1j z$9}N{{Jk_^_?YzKvYLRTsn%p+M|6>gM=~Hp)RoX2=C(VV6tYTAR!w;|Tg{x=8Icx} zC!g^o6Ozst6od<~k?x7QBWK(nk@^by?Lp-<0PtT>V0v#Oto5yfwQPUB0FayM~$yi-Sz(kYas(ec7XyLLrLsN*CB*7{D^Ckg7eH?-?3m&&(fd zaZp)0ZcQQ=`pgUHX#4i*BVduv?QUTO`Qk*9YKF?W-Tia_O8n1Kk<&ILGgI9?KqinyFJMS z?4^xkYHUgZH6!W9_DYUgz6kw6SZP5M6CtT}AvJZvqiDTi%t^=YM5=QBWO>-UorobsBw+gwjN@8|`0G=NtRpXgmC6Tx7iTBcwS=sy4#$ zche;a799kP9OuyZuw*cN6M-ny-~>5;`t+jkddKeGy?d6HmLOArt;L=ji968$0q=D8 z9oTp%X^7FDH=&RExlzH0m5q0(Oz{P~p#?$HO!HX;RJ znT0~v5I;6hDYfgz_-4$^ZaFp5P+nUuE>JxMMf=Jp`n`Q10t4t?woJgF3!S0U1kQ%! zW~jx6lss|o8=Jv^U#uWRrxFn8?HrhEKp&iZa-XZUy-eHv<5p8MnwdFWcfR9VV$j4$ zGmNFIS=(098|}=@Oyks!E073w)ipMQMhbr0 z&MM`u@MIB7EW+4l0-(hMRXPd^3JtFNZ^2YlsF1DS8O&}qfFJ8>tszn?n~svFO>9{T%A_w6RHlr4p!0K2-7uF3nkL@)jbspRX&o zohs2TF}PTdQQn#Gb}NJe43&&`!AA8i+hM%Tc}8#tfV~7b6-<0KUt`R&8XK6|=d3;h`Jw1rIxfO3kPj~kxS62(ij~ZPj?zgUqN41WQwrP>rR8!c!m6eq@ zU_f2I3nnf$Zt?4j=avu`*Q>VaU{eJFHO?c8LwOYy&eLTkc4QXD|8N>^NRj3=3<5S3 zm&<>?;4Rd<(h1s4UtgY)&0p8GnoU1Lxqy>d=2no5LYz`b89Q^q+g#FPF9Nd-o(yXlKmeG$DTkL_#gy!Yt zah&ys{`oI1z>_CWK%iBo$+N@5Ixkc~dHKtK9`U>Ik4TpPD?vfOtMj88`#CI{UxkDu z%6_g!!taVk?zX^xxh3dE>CCS`@ul!FP%Q+c%~$`A_5c5y{~F-`e#z5!C+z7=gjh);-BS-zN8d_c2UiXspSua$%cmwZd6x^VZ%>nn$qYG|pdp+?~ z#O?%mL}+52SRaz%;K+RFf;~N>FF!0#ct;@Em4A@dx%HTfLWF5bhK=*tJxlF!; zXHP0HgM|6d_F#IOXka_D8-S`Zh{v%6}GlDjzkQ?YP4!=-jO& z%;;Q2LaM1rF)uj`f3jbnUtOwFYUDf}6~+7E_usb$+TqH*Y6;)dNaL{TbCs=)W_FSy z9#AtKN@y3F_kotl*ENU#gfX~JsN80ks?KO=I5LFCu{?n~*W*lz)Z120SM{^gJ>=#> zZ5SafnW~@7r~ZihtQXNf4ELaOzjN*^?a1#;jcB-91eQntF{ZQ#Jp9W`i|1VmZjq;h zO(l!eapysecyqV^dei7t-gh(K;uPYuy{olAChpKYgLn^M4%5dJLOIU1JqdzK!0lGC z<+TZrPWqzfeS$CC9cN9dt>5{B)Sk&_mJanO)T?Md6L{h7exwh9j0J=+rqaYxy0?#b zYeD+oSXih^Tt+417KPTGN}F^lMh8S#CcqTwFmY6177kZJ~ALFcx1|YuURFtXhl z|90{#&msdJg>Q|onqFK}y|j53wpp^TO)GR*BKfK!HF(OshQAzLYT{NclMeX7a-qS}(d;o8&inR?!)*R7TB1D=$(CWwf8r$t9GFDd#^Un9@yfZpx zEqBVAb^9@XXn!|D^)mXYLHdhzou$;TG19tc8aXAS{bDHk`f3K3NRx4dkZ$a{tcE59 zg+(9-7Xe*u8gjKIHRK_7LIAP-_@4^VMhE0(KSvfE`V-n2<4Z9|iQuPEga^W;9+Tj^>@`G0{ zJgxVa(^(XWkIxa*usl#tGny8Vmi{-OZ-f|5Zs!ISJJlAarQV97E^0OkM9{=bujAEq zF+9;8XGYoyN7jM*6silvOy-#~VXvI9wavodd!e;LAqNyM3C+-k>=1TjUXZ*AX3sL-Q6LLba!`m9XN28-{*PmZ~Wf(z2n~B9fLm( zjD6PG?7h!gpE*Bs&K0aT`=fOCzC4+SjnR~--VdT@{ETZy%xbb|Pwb9=FtZX-mMEu+ zfnPHu4j%IHX(=XA^i@A|b}koJ4UcgYWL=%%b$)VyMD6(n6%p2O{SCHlfdbtcg$v_- z#yLkLB$u;&VU1&VAOOp&&@xS=*;g$X*DP>{ku0K#X<~`tyfr!?dGK8r*=Y8nwLMZx z*y^mHa^P+w0A#KV)W4MPCs8t&sVL3NWr!6`Jqgi*oiNmehFOeVn?m1JO=vCX9WS}G zrqTG{a6eL&);WB~)Xm8JHC+0{(ckI_8&&kd%g?{fD1z9nrNx*r3fx=>pRaQYiZ0Z{ zoZf!<#lec$8VCYL!-+TBy8^)Cfy$s@Sf>_jxfO5<$$%be43QZ9G5%H5;K{_sSdy zuF*zy{Nd} z_vrt{J1m`XJ#}B&{Bm>7>H~P{T9gVVEtKZBv+AJSbE75)nUI|pVs;vy#T&j z;ux=^PH}splB-(r_oBUCc7r9OK;O@9@U4>koAb*`<;eTJA>l})FDx3!Z}RlOd-h*1 z^FpTyNrU4D1kj~N{DiB_JNC}N=KP34ySjv!PU~GbmZv+xdWv z_Y-(9g}>+-F)1oE&EGRFcr9IafOb&z?e$c+Xlf;iE%Kf4i_ecm3BGZOYDGVQjLK0V zy%h>HhVRE1+EQZ7NX=~q4`Qv?IdGv@84u$~LM%NYAJa`Vh)xv~dLYBcrs4bNNA-6U zE(3{Kq~?+pr4)q)&8N^iX?-MNB^BXCJgGr0aamPC=v|Lqgf@N92WhqgNa0F+|6o^9 zvV)Og#tTwVO_F*nr5l0e$cP2KcDErY7Pc5M!J8sY)%AW9HDuyfL`m`X$p{VuehWuS4*Rt*j1 zF}PwuR9JqH&u?6U=~LGyXBLE77ixJHV9r(kM|mu!CGf)w-!-WV3w!28$ku`+}b2E)z;CC~?oGjy+A z9T}~c5gBX#tZ|O1RzlKMw4b$}J%6pGsI91YdTKn0j5jfxF+;U8&K~77oHfz$#&4ej zT>DMsOY$N@%26rEY_-F|7lJ^DL?gujdPJtS_G0&cmrbfqa@PDHm~^B2Fk zQWE*I_M?|?irK5r)ir;o%}n4)SZ179#_%W63gcP&ve{NA0<2XO6$#xtukO2jN=7OFTKqp*WO0s3%c$ose`Naz*9$m^$(52 z!b3=G%B8zX(X@79Hb-4GT8wG>Sti<#E&m+#r9LS=WhpjmQ~tRE)8!>jruqe!dzJ#7 zyfxWMr^}u}%iDF3YwnyuaY^fY^QoQEdK$WrtIY8J`3O>T2SzEjgGi%!bGrA)kg=|+ zlPi(_BoQ>}h6Rltw-6ZXK7;B*HC!FC^qg;sjKad-O^y;%FhS9hNJwBp%vJq>Tf z0qbsQ#*B)&<}sg(!43~3tT@eCil3IRz}6s@kZ@y*g7mp_P#Uoj9mf;)@&VI`2 zAfFG@AB04tBZ&1q1mD`ifO(a+HgZjrR%|*;5=H~ZzmQ!lJ|IR{VnP8* zm-D-y0ls)K{j2madNRGkf*htFk@YVOJ58KRY)SOLd$8^ug()feswCv+N0VlRRC28$!AMJE#H?Sm03%YWX?n7y9&3fmA}DnfbQRiLUv8|z` zNwH3xzP4@`w?(??FzKE6-w8T-6u*W|Ds{N-8z#FIs}i}JrsnZ*uWSBBao*pDq)yh2 zq5OoN`CE7pt_<-P=lIii4(hV$;AQpoP0RAnRcc+D{%Yg*Qw<~8Gmeb?*H7EuKdkSN zc+^|FN|g{9*)~%dzr%Vuti7gPD?7F{BlY)*BSy4Vk7zR1=6@&+vB#BrYC21GU`k$d zF=cpAqLGnL+l?{KzBlRW$Px@g6W-$3&UD(b*|unFC#*V^;jjJHK+ke;%qkHj3fpiI z4Y1MGBgmt-oJc#7f@t2=4$c-K2Z&fVxHw?y{5ej$6yL{Vq;3ejC(9R7n`5(2`3I{< zmcO8n6DG8Y;i|f$4Mwz_?#JB_G6GljROrJl%U2n0E7ouIyyK(huVR%nPcfj&7UxyW z+tsK{%xr0geb{XjK0lg|n&fOUGm%rUCCc9#NYFq>;<4BXkNt5lW8dcx z8|lMagj3H0V%gJM4iKfnD_9!d_ZdEJ{Ziy{qeD)IO@D!s^o?s zFngumWtp_Jtdn<`4B2T6ZDexrF|2GQ@w(>7&Kz{TdkSgH!e=%rT-8>+ZGHY8?u~>Y zJ|yJ#dzEnNbcLw;)>Roi9yHXwgS9rn{q(je{~W{3FB=A4y!<@hll59wzTMz0c>P%P z?kR>i&fh;jMoa(a4-fnl|IVNj;8xFOYkB|l?;9Vy{I72`VEKFU z|Lcwa_elSKqv&1X`*JNR2U|NATRWSHA=v)STadnnSw$+~W#9Fc6;m0DRB*b$rKx|u zL9IZuNQJJu&GSB%tJA^CP|eH*x_5SN;q4&T>*{Kd2NL2T;J7*&yWm+g^%R$Ayr=Wv zz|j^^@}EQ|gxUuw8|C2fRxlcB>WgcCp_?+qk9WVYnD*bkZBIV^E-fj0vOT{sumw6i z+mjUm!R~e62aBt?3Kq(pYP_58mR4+!hS%6Pm^fs3Kpa~OSu~=o6Ak=lr#4vPk|o#_ zMfz7E0~_)Q$EsFVjD#`7Lay-U->sNs?QMbr?)%F%5uKto`ts89)J>HK5@LGwj%&mI zBRB>wt87=l^}{^O_NJ$&FDS?#`gZjUFw@XjR(Gerxt`;zx=SoXR2v(D-mTyr?K@d% z8$lG2$H}$&mX-bOWz_fJzTQTt;$g(MG{<_^&Q^Ez=G&_e*_&>+?^w}uwk`uOUVa{o z3BFz9N)%1~`IF%OCG)|I_uyRdHNw*~)0@3#yu;+|k1=R!j2YE=QX2u57BqMv7SHWS z{V?Kq4g=!kPVF)a|G};YP_3)GK&We4w>M(F;3_zps;!+Rw%5cWYshSUecf(g#W1*A!cj`?D|QF-HL2YT&eLz7o0^A7ml5mLXNPu#;GPqnk_ZW7`6{ifb1Nj|6L{TjelaC4RLL{TesB|C&-HPlOjE)Ot}(m4 zn5%DqQgUnER@TV?CGI0ixVcgH@i+e?|6wzHU(mv6F!4+j9V&rgL$6&=zxy=^Kr(S$ zhR1CW)eF%CJZ?1P<(W^%E957NBu7ks{mP7r3Z!WD4GHl#`k*ae2xkcOkWFna zoV#Yy#WZ4#)#kP`+uI*kDZvRJ5@OKTq$t`t*eSEq^`Sx>4y{njCo6+?wsm3rc+t?> z$@4kS`4&ok(hJGm5uDa9{Gow;JhTr zi#G7e+L}!kz+%9uIc?1znd=b8HqyPHE78ZEt--0@4e-YaS3LXFH9HkXe$Y_i@h%M`aef!E

  • hNoJp2$S}c1sEp0-rfy zqE0;woGIzsc?t?esJOCpy4p2QJw}doXz3-lpP+6Nv{V~BZYBsahcep+lh;V2Tj*py!@l1qectN0dYBbG7MZSEMKeLO{XIz^TzXGR9P+) zKmmB*DdghZ+NSLy%A}83>$asMHc29&I|nk)xJT&F{7TFbaU^^$2a}cE&BBNLxA&ml zq`DNBf&J8~LSV{XpQ$<7dHM)?aHu~IPP-j_Lm;R=D^LvS1si;+ioGfH0Xi2O2fzD1 zIrMqH!36{{Qxs_^M*3LWWk30IczX7#BtV$o0n;TuFETqd@U+4 zpXh{fhv!v>o{u%d(uS47u=W;Q1*>chlC&_;qNJSc9T{jCP<^U5j{fG1m1rP;O1a`J z$g;Duwq^|R7k~QbZ5f@Wib_Ia1p9}{$B?a^v$JEdH=F|t+W#^K(j+)S#8--^HU<(1 z1{bPgnK*)44bc6?L8l~T$n4@4K5`CSA^ zaiuasN!WkfAVxMzK7j?&fCX;Q_JP%Px$a0qLA$OpGc(=vzJ9XcaU2l|iB(@_!+k8h zCfDo9qNaNJ%_~#nPr@`D+aq}rCsPcJjFr|}-s?B*AXTkDsZN*yFJdbId)G5Da=7Yl zG2D>44QO#ZUdFWx5hZ4-Ak} zJWZVn4@KDZZN~a3Ye1g~%VwWrs^Zg>>eqZt8w9tBUYzO-@d)=4I#q{=Z1twl{*9AY zxRUHVuKc7tM7+Gy7-+gmv{xxqz{zEX7Ts+G8u#20n!&$QAb+_m6evnc@rgyCSeja% z`!&|)c%6RLJOX4G{fSGwC#¬6QLkBn&*aNrn6IdOKi}jpyb1S7jmOqgCK_^QtmR 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 z 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 From 383d3ce68bf815021791e5d3885a9f4131ec0ed4 Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Mon, 1 Mar 2021 12:05:26 +0000 Subject: [PATCH 046/105] Updated files with 'repo_helper'. (#18) Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .bumpversion.cfg | 2 ++ tox.ini | 8 ++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index dc409b8..a9a8d80 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -10,3 +10,5 @@ tag = True [bumpversion:file:README.rst] [bumpversion:file:flake8_github_actions/__init__.py] + +[bumpversion:file:pyproject.toml] diff --git a/tox.ini b/tox.ini index 0b5d507..64b0181 100644 --- a/tox.ini +++ b/tox.ini @@ -80,15 +80,15 @@ commands = [flake8] max-line-length = 120 -select = E111 E112 E113 E121 E122 E125 E127 E128 E129 E131 E133 E201 E202 E203 E211 E222 E223 E224 E225 E225 E226 E227 E228 E231 E241 E242 E251 E261 E262 E265 E271 E272 E303 E304 E306 E402 E502 E703 E711 E712 E713 E714 E721 W291 W292 W293 W391 W504 YTT101 YTT102 YTT103 YTT201 YTT202 YTT203 YTT204 YTT301 YTT302 YTT303 STRFTIME001 STRFTIME002 SXL001 PT001 PT002 PT003 PT005 PT006 PT007 PT008 PT009 PT010 PT011 PT012 PT013 PT014 PT015 PT016 PT017 PT018 PT019 PT020 PT021 RST201 RST202 RST203 RST204 RST205 RST206 RST207 RST208 RST210 RST211 RST212 RST213 RST214 RST215 RST216 RST217 RST218 RST219 RST299 RST301 RST302 RST303 RST304 RST305 RST306 RST399 RST401 RST499 RST900 RST901 RST902 RST903 Q001 Q002 Q003 A001 A002 A003 TYP001 TYP002 TYP003 TYP004 TYP005 TYP006 ENC001 ENC002 ENC003 ENC004 Y001,Y002 Y003 Y004 Y005 Y006 Y007 Y008 Y009 Y010 Y011 Y012 Y013 Y014 Y015 Y090 Y091 E301 E302 E305 D100 D101 D102 D103 D104 D106 D201 D204 D207 D208 D209 D210 D211 D212 D213 D214 D215 D300 D301 D400 D402 D403 D404 D415 D417 DALL000 SLOT000 SLOT001 SLOT002 SLOT003 -exclude = doc-source,.git,__pycache__,old,build,dist,__pkginfo__.py,setup.py,.tox,venv +select = E111 E112 E113 E121 E122 E125 E127 E128 E129 E131 E133 E201 E202 E203 E211 E222 E223 E224 E225 E225 E226 E227 E228 E231 E241 E242 E251 E261 E262 E265 E271 E272 E303 E304 E306 E402 E502 E703 E711 E712 E713 E714 E721 W291 W292 W293 W391 W504 YTT101 YTT102 YTT103 YTT201 YTT202 YTT203 YTT204 YTT301 YTT302 YTT303 STRFTIME001 STRFTIME002 SXL001 PT001 PT002 PT003 PT005 PT006 PT007 PT008 PT009 PT010 PT011 PT012 PT013 PT014 PT015 PT016 PT017 PT018 PT019 PT020 PT021 RST201 RST202 RST203 RST204 RST205 RST206 RST207 RST208 RST210 RST211 RST212 RST213 RST214 RST215 RST216 RST217 RST218 RST219 RST299 RST301 RST302 RST303 RST304 RST305 RST306 RST399 RST401 RST499 RST900 RST901 RST902 RST903 Q001 Q002 Q003 A001 A002 A003 TYP001 TYP002 TYP003 TYP004 TYP005 TYP006 ENC001 ENC002 ENC003 ENC004 Y001,Y002 Y003 Y004 Y005 Y006 Y007 Y008 Y009 Y010 Y011 Y012 Y013 Y014 Y015 Y090 Y091 E301 E302 E305 D100 D101 D102 D103 D104 D106 D201 D204 D207 D208 D209 D210 D211 D212 D213 D214 D215 D300 D301 D400 D402 D403 D404 D415 D417 DALL000 SLOT000 SLOT001 SLOT002 +extend-exclude = doc-source,old,build,dist,__pkginfo__.py,setup.py,venv rst-directives = TODO envvar extras-require per-file-ignores = - tests/*: D100 D101 D102 D103 D104 D106 D201 D204 D207 D208 D209 D210 D211 D212 D213 D214 D215 D300 D301 D400 D402 D403 D404 D415 D417 DALL000 SLOT000 SLOT001 SLOT002 SLOT003 - */*.pyi: E301 E302 E305 D100 D101 D102 D103 D104 D106 D201 D204 D207 D208 D209 D210 D211 D212 D213 D214 D215 D300 D301 D400 D402 D403 D404 D415 D417 DALL000 SLOT000 SLOT001 SLOT002 SLOT003 + tests/*: D100 D101 D102 D103 D104 D106 D201 D204 D207 D208 D209 D210 D211 D212 D213 D214 D215 D300 D301 D400 D402 D403 D404 D415 D417 DALL000 SLOT000 SLOT001 SLOT002 + */*.pyi: E301 E302 E305 D100 D101 D102 D103 D104 D106 D201 D204 D207 D208 D209 D210 D211 D212 D213 D214 D215 D300 D301 D400 D402 D403 D404 D415 D417 DALL000 SLOT000 SLOT001 SLOT002 pytest-parametrize-names-type = csv inline-quotes = " multiline-quotes = """ From 156151cb0a9084822623e762cefe9b3302a77d3b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 1 Mar 2021 12:30:13 +0000 Subject: [PATCH 047/105] [pre-commit.ci] pre-commit autoupdate (#16) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> From 6fd87d3aa1fb861b1c003fde28c266bfa6dae8de Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 5 Mar 2021 07:49:48 +0000 Subject: [PATCH 048/105] [pre-commit.ci] pre-commit autoupdate (#20) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2d1263b..a4c3863 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -46,7 +46,7 @@ repos: - id: flake2lint - repo: https://github.com/pre-commit/pygrep-hooks - rev: v1.7.1 + rev: v1.8.0 hooks: - id: python-no-eval - id: rst-backticks From 1b595806db8577b378d9f5240913dbec9ceef08c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 8 Mar 2021 19:20:02 +0000 Subject: [PATCH 049/105] [pre-commit.ci] pre-commit autoupdate (#21) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a4c3863..d4cb454 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -25,7 +25,7 @@ repos: - id: end-of-file-fixer - repo: https://github.com/domdfcoding/pre-commit-hooks - rev: v0.2.0 + rev: v0.2.1 hooks: - id: requirements-txt-sorter args: @@ -41,7 +41,7 @@ repos: files: ^flake8_github_actions/.*\.py$ - repo: https://github.com/domdfcoding/flake2lint - rev: v0.3.0 + rev: v0.4.0 hooks: - id: flake2lint @@ -74,7 +74,7 @@ repos: exclude: ^(doc-source/conf|__pkginfo__|make_conda_recipe|setup)\.(_)?py$ - repo: https://github.com/domdfcoding/dep_checker - rev: v0.4.1 + rev: v0.5.0 hooks: - id: dep_checker args: From b3c02f044d478b606710db4ee4cf2d2a1d8c5fb9 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 15 Mar 2021 21:34:58 +0000 Subject: [PATCH 050/105] [pre-commit.ci] pre-commit autoupdate (#22) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d4cb454..15f6405 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -68,7 +68,7 @@ repos: - id: forbid-crlf - repo: https://github.com/repo-helper/formate - rev: v0.4.2 + rev: v0.4.3 hooks: - id: formate exclude: ^(doc-source/conf|__pkginfo__|make_conda_recipe|setup)\.(_)?py$ From a32f1a9eb9c7c8a141b723392fce039e80bcdfbc Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Thu, 18 Mar 2021 22:42:52 +0000 Subject: [PATCH 051/105] Test on Python 3.10 alpha 6 --- .github/workflows/python_ci.yml | 6 +++--- .github/workflows/python_ci_linux.yml | 6 +++--- .github/workflows/python_ci_macos.yml | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/python_ci.yml b/.github/workflows/python_ci.yml index 054b63f..839ba25 100644 --- a/.github/workflows/python_ci.yml +++ b/.github/workflows/python_ci.yml @@ -13,7 +13,7 @@ jobs: runs-on: "windows-2019" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-alpha.5,pypy-3.6,pypy-3.7' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-alpha.6,pypy-3.6,pypy-3.7' strategy: fail-fast: False @@ -23,9 +23,9 @@ jobs: - {python-version: "3.7", testenvs: "py37,build", experimental: False} - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - - {python-version: "3.10.0-alpha.5", testenvs: "py310-dev,build", experimental: True} + - {python-version: "3.10.0-alpha.6", testenvs: "py310-dev,build", experimental: True} - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} - - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: False} + - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} steps: - name: Checkout 🛎️ diff --git a/.github/workflows/python_ci_linux.yml b/.github/workflows/python_ci_linux.yml index ae631f8..09f7fd3 100644 --- a/.github/workflows/python_ci_linux.yml +++ b/.github/workflows/python_ci_linux.yml @@ -13,7 +13,7 @@ jobs: runs-on: "ubuntu-20.04" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-alpha.5,pypy-3.6,pypy-3.7' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-alpha.6,pypy-3.6,pypy-3.7' strategy: fail-fast: False @@ -23,9 +23,9 @@ jobs: - {python-version: "3.7", testenvs: "py37,build", experimental: False} - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - - {python-version: "3.10.0-alpha.5", testenvs: "py310-dev,build", experimental: True} + - {python-version: "3.10.0-alpha.6", testenvs: "py310-dev,build", experimental: True} - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} - - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: False} + - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} steps: - name: Checkout 🛎️ diff --git a/.github/workflows/python_ci_macos.yml b/.github/workflows/python_ci_macos.yml index 0d0c451..0e6d80c 100644 --- a/.github/workflows/python_ci_macos.yml +++ b/.github/workflows/python_ci_macos.yml @@ -13,7 +13,7 @@ jobs: runs-on: "macos-latest" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-alpha.5,pypy-3.6,pypy-3.7' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-alpha.6,pypy-3.6,pypy-3.7' strategy: fail-fast: False @@ -23,9 +23,9 @@ jobs: - {python-version: "3.7", testenvs: "py37,build", experimental: False} - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - - {python-version: "3.10.0-alpha.5", testenvs: "py310-dev,build", experimental: True} + - {python-version: "3.10.0-alpha.6", testenvs: "py310-dev,build", experimental: True} - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} - - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: False} + - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} steps: - name: Checkout 🛎️ From 9243e2394abdbff28d13991dbdc101b1f187a67d Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Thu, 18 Mar 2021 22:49:30 +0000 Subject: [PATCH 052/105] Updated files with 'repo_helper'. (#23) Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .github/ISSUE_TEMPLATE/bug_report.md | 5 ++++- .pre-commit-config.yaml | 4 ++-- __pkginfo__.py | 3 +-- tests/requirements.txt | 2 +- tox.ini | 8 ++++---- 5 files changed, 12 insertions(+), 10 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 68a2fcb..facfb08 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -17,7 +17,10 @@ THE ISSUE WILL BE CLOSED IF INSUFFICIENT INFORMATION IS PROVIDED. ## Steps to Reproduce - + 1. 2. diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 15f6405..12d347d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -35,7 +35,7 @@ repos: - id: bind-requirements - repo: https://github.com/domdfcoding/flake8-dunder-all - rev: v0.1.5 + rev: v0.1.7 hooks: - id: ensure-dunder-all files: ^flake8_github_actions/.*\.py$ @@ -54,7 +54,7 @@ repos: - id: rst-inline-touching-normal - repo: https://github.com/asottile/pyupgrade - rev: v2.10.0 + rev: v2.10.1 hooks: - id: pyupgrade args: diff --git a/__pkginfo__.py b/__pkginfo__.py index dfbcb37..ac2fb70 100644 --- a/__pkginfo__.py +++ b/__pkginfo__.py @@ -27,7 +27,6 @@ """ __version__ = "0.1.1" - repo_root = pathlib.Path(__file__).parent install_requires = (repo_root / "requirements.txt").read_text(encoding="utf-8").split('\n') -extras_require = {"all": []} +extras_require = {} diff --git a/tests/requirements.txt b/tests/requirements.txt index ee085e8..9486568 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,6 +1,6 @@ coincidence>=0.1.0 coverage>=5.1 -coverage-pyver-pragma>=0.0.6 +coverage-pyver-pragma>=0.2.1 domdf-python-tools[testing]>=2.0.1 iniconfig!=1.1.0,>=1.0.1 pytest>=6.0.0 diff --git a/tox.ini b/tox.ini index 64b0181..a66e5a1 100644 --- a/tox.ini +++ b/tox.ini @@ -39,11 +39,11 @@ commands = skip_install = True changedir = {toxinidir} deps = - twine>=3.2.0 - pep517>=0.9.1 + build[virtualenv]>=0.3.1 check-wheel-contents>=0.1.0 + twine>=3.2.0 commands = - python -m pep517.build --source --binary "{toxinidir}" + python -m build --sdist --wheel "{toxinidir}" twine check dist/*.tar.gz dist/*.whl check-wheel-contents dist/ @@ -72,7 +72,7 @@ whitelist_externals = /bin/bash changedir = {toxinidir} deps = coverage>=5 - coverage_pyver_pragma>=0.0.6 + coverage_pyver_pragma>=0.2.1 commands = /bin/bash -c "rm -rf htmlcov" coverage html From 28993f18eb5009dd672f8829b8ee20208a6edb2b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 22 Mar 2021 20:57:42 +0000 Subject: [PATCH 053/105] [pre-commit.ci] pre-commit autoupdate (#24) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 12d347d..5eb7894 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -54,7 +54,7 @@ repos: - id: rst-inline-touching-normal - repo: https://github.com/asottile/pyupgrade - rev: v2.10.1 + rev: v2.11.0 hooks: - id: pyupgrade args: From 30d024dba597f91a5e8f3fa84421fb31e9925b3a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 29 Mar 2021 18:45:25 +0000 Subject: [PATCH 054/105] [pre-commit.ci] pre-commit autoupdate (#25) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5eb7894..6cb6082 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -74,7 +74,7 @@ repos: exclude: ^(doc-source/conf|__pkginfo__|make_conda_recipe|setup)\.(_)?py$ - repo: https://github.com/domdfcoding/dep_checker - rev: v0.5.0 + rev: v0.6.0 hooks: - id: dep_checker args: From 396aeaabc08225170607b0c2ec76d5286061e494 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 5 Apr 2021 18:50:56 +0000 Subject: [PATCH 055/105] [pre-commit.ci] pre-commit autoupdate (#26) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6cb6082..1d814fe 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -74,7 +74,7 @@ repos: exclude: ^(doc-source/conf|__pkginfo__|make_conda_recipe|setup)\.(_)?py$ - repo: https://github.com/domdfcoding/dep_checker - rev: v0.6.0 + rev: v0.6.1 hooks: - id: dep_checker args: From 0b90c853a64f899d1ca03e6d4e971ce85d2a528e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 12 Apr 2021 19:25:34 +0100 Subject: [PATCH 056/105] [pre-commit.ci] pre-commit autoupdate (#27) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1d814fe..99afad9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -54,7 +54,7 @@ repos: - id: rst-inline-touching-normal - repo: https://github.com/asottile/pyupgrade - rev: v2.11.0 + rev: v2.12.0 hooks: - id: pyupgrade args: From b25c9d20ae208c921e25e2b9f49083c703599c8c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 20 Apr 2021 08:49:38 +0100 Subject: [PATCH 057/105] [pre-commit.ci] pre-commit autoupdate (#28) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/domdfcoding/dep_checker: v0.6.1 → v0.6.2](https://github.com/domdfcoding/dep_checker/compare/v0.6.1...v0.6.2) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 99afad9..45b174a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -74,7 +74,7 @@ repos: exclude: ^(doc-source/conf|__pkginfo__|make_conda_recipe|setup)\.(_)?py$ - repo: https://github.com/domdfcoding/dep_checker - rev: v0.6.1 + rev: v0.6.2 hooks: - id: dep_checker args: From 429053dad1aab0db34c4e6864e732fcbcddbc6be Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Wed, 11 Aug 2021 07:21:27 +0100 Subject: [PATCH 058/105] Updated files with 'repo_helper'. (#30) Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .bumpversion.cfg | 11 +++++++-- .github/ISSUE_TEMPLATE/bug_report.md | 2 +- .github/stale.yml | 2 +- .github/workflows/flake8.yml | 23 +++++++++++++++--- .github/workflows/mypy.yml | 22 ++++++++++++++--- .github/workflows/octocheese.yml | 4 +--- .github/workflows/python_ci.yml | 31 ++++++++++++++++++++---- .github/workflows/python_ci_linux.yml | 34 ++++++++++++++++++++++----- .github/workflows/python_ci_macos.yml | 31 ++++++++++++++++++++---- .pre-commit-config.yaml | 15 ++++++++---- .pylintrc | 2 +- README.rst | 6 +---- __pkginfo__.py | 18 +------------- formate.toml | 1 + pyproject.toml | 24 ++++++++++++++++++- setup.cfg | 2 ++ setup.py | 6 ++++- tests/requirements.txt | 5 ++-- tox.ini | 12 ++++++++-- 19 files changed, 188 insertions(+), 63 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index a9a8d80..97245ee 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -5,10 +5,17 @@ tag = True [bumpversion:file:repo_helper.yml] -[bumpversion:file:__pkginfo__.py] - [bumpversion:file:README.rst] [bumpversion:file:flake8_github_actions/__init__.py] +search = : str = "{current_version}" +replace = : str = "{new_version}" + [bumpversion:file:pyproject.toml] +search = version = "{current_version}" +replace = version = "{new_version}" + +[bumpversion:file:setup.cfg] +search = version = {current_version} +replace = version = {new_version} diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index facfb08..5551752 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -44,7 +44,7 @@ If possible, please include a small, self-contained reproduction. * flake8-github-actions: ## Installation source - + ## Other Additional Information: diff --git a/.github/stale.yml b/.github/stale.yml index bb7ca3f..e5625b7 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -28,7 +28,7 @@ exemptMilestones: false exemptAssignees: false # Label to use when marking as stale -staleLabel: wontfix +staleLabel: stale # Comment to post when marking as stale. Set to `false` to disable markComment: > diff --git a/.github/workflows/flake8.yml b/.github/workflows/flake8.yml index 177294b..f46a179 100644 --- a/.github/workflows/flake8.yml +++ b/.github/workflows/flake8.yml @@ -4,8 +4,13 @@ name: Flake8 on: push: + branches-ignore: + - 'repo-helper-update' + - 'pre-commit-ci-update-config' pull_request: - branches: ["master"] + +permissions: + contents: read jobs: Run: @@ -16,12 +21,23 @@ jobs: - name: Checkout 🛎️ uses: "actions/checkout@v2" + - name: Check for changed files + uses: dorny/paths-filter@v2 + id: changes + with: + list-files: "json" + filters: | + code: + - '!(doc-source/**|CONTRIBUTING.rst|.imgbotconfig|.pre-commit-config.yaml|.pylintrc|.readthedocs.yml)' + - name: Setup Python 🐍 + if: steps.changes.outputs.code == 'true' uses: "actions/setup-python@v2" with: - python-version: "3.8" + python-version: "3.6" - name: Install dependencies 🔧 + if: steps.changes.outputs.code == 'true' run: | python -VV python -m site @@ -29,4 +45,5 @@ jobs: python -m pip install tox - name: "Run Flake8" - run: "python -m tox -e lint -- --format github" + if: steps.changes.outputs.code == 'true' + run: "python -m tox -e lint -s false -- --format github" diff --git a/.github/workflows/mypy.yml b/.github/workflows/mypy.yml index afee01e..d6d4200 100644 --- a/.github/workflows/mypy.yml +++ b/.github/workflows/mypy.yml @@ -4,8 +4,13 @@ name: mypy on: push: + branches-ignore: + - 'repo-helper-update' + - 'pre-commit-ci-update-config' pull_request: - branches: ["master"] + +permissions: + contents: read jobs: Run: @@ -14,14 +19,24 @@ jobs: strategy: matrix: - os: ['windows-2019', 'macos-latest', 'ubuntu-20.04'] + os: ['ubuntu-20.04', 'windows-2019'] fail-fast: false steps: - name: Checkout 🛎️ uses: "actions/checkout@v2" + - name: Check for changed files + uses: dorny/paths-filter@v2 + id: changes + with: + list-files: "json" + filters: | + code: + - '!(doc-source/**|CONTRIBUTING.rst|.imgbotconfig|.pre-commit-config.yaml|.pylintrc|.readthedocs.yml)' + - name: Setup Python 🐍 + if: steps.changes.outputs.code == 'true' uses: "actions/setup-python@v2" with: python-version: "3.6" @@ -34,4 +49,5 @@ jobs: python -m pip install --upgrade tox virtualenv - name: "Run mypy" - run: "python -m tox -e mypy" + if: steps.changes.outputs.code == 'true' + run: "python -m tox -e mypy -s false" diff --git a/.github/workflows/octocheese.yml b/.github/workflows/octocheese.yml index 155d407..208a753 100644 --- a/.github/workflows/octocheese.yml +++ b/.github/workflows/octocheese.yml @@ -3,10 +3,8 @@ name: "GitHub Releases" on: - push: - branches: ["master"] schedule: - - cron: 0 12 * * 2,4,6 + - cron: 0 12 * * * jobs: Run: diff --git a/.github/workflows/python_ci.yml b/.github/workflows/python_ci.yml index 839ba25..044d73e 100644 --- a/.github/workflows/python_ci.yml +++ b/.github/workflows/python_ci.yml @@ -4,8 +4,15 @@ name: Windows on: push: + branches-ignore: + - 'repo-helper-update' + - 'pre-commit-ci-update-config' + pull_request: - branches: ["master"] + +permissions: + actions: write + contents: read jobs: tests: @@ -13,7 +20,7 @@ jobs: runs-on: "windows-2019" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-alpha.6,pypy-3.6,pypy-3.7' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-rc.1,pypy-3.6,pypy-3.7' strategy: fail-fast: False @@ -23,7 +30,7 @@ jobs: - {python-version: "3.7", testenvs: "py37,build", experimental: False} - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - - {python-version: "3.10.0-alpha.6", testenvs: "py310-dev,build", experimental: True} + - {python-version: "3.10.0-rc.1", testenvs: "py310-dev,build", experimental: True} - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} @@ -31,12 +38,25 @@ jobs: - name: Checkout 🛎️ uses: "actions/checkout@v2" + - name: Check for changed files + if: startsWith(github.ref, 'refs/tags/') != true + uses: dorny/paths-filter@v2 + id: changes + with: + list-files: "json" + filters: | + code: + - '!(doc-source/**|CONTRIBUTING.rst|.imgbotconfig|.pre-commit-config.yaml|.pylintrc|.readthedocs.yml)' + - name: Setup Python 🐍 + id: setup-python + if: ${{ steps.changes.outputs.code == 'true' || steps.changes.outcome == 'skipped' }} uses: "actions/setup-python@v2" with: python-version: "${{ matrix.config.python-version }}" - name: Install dependencies 🔧 + if: steps.setup-python.outcome == 'success' run: | python -VV python -m site @@ -44,11 +64,12 @@ jobs: python -m pip install --upgrade tox virtualenv - name: "Run Tests for Python ${{ matrix.config.python-version }}" - run: python -m tox -e "${{ matrix.config.testenvs }}" + if: steps.setup-python.outcome == 'success' + run: python -m tox -e "${{ matrix.config.testenvs }}" -s false - name: "Upload Coverage 🚀" uses: actions/upload-artifact@v2 - if: ${{ always() }} + if: ${{ always() && steps.setup-python.outcome == 'success' }} with: name: "coverage-${{ matrix.config.python-version }}" path: .coverage diff --git a/.github/workflows/python_ci_linux.yml b/.github/workflows/python_ci_linux.yml index 09f7fd3..d6c5600 100644 --- a/.github/workflows/python_ci_linux.yml +++ b/.github/workflows/python_ci_linux.yml @@ -4,8 +4,16 @@ name: Linux on: push: + branches-ignore: + - 'repo-helper-update' + - 'pre-commit-ci-update-config' + tags: + - '*' pull_request: - branches: ["master"] + +permissions: + actions: write + contents: read jobs: tests: @@ -13,7 +21,7 @@ jobs: runs-on: "ubuntu-20.04" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-alpha.6,pypy-3.6,pypy-3.7' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-rc.1,pypy-3.6,pypy-3.7' strategy: fail-fast: False @@ -23,7 +31,7 @@ jobs: - {python-version: "3.7", testenvs: "py37,build", experimental: False} - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - - {python-version: "3.10.0-alpha.6", testenvs: "py310-dev,build", experimental: True} + - {python-version: "3.10.0-rc.1", testenvs: "py310-dev,build", experimental: True} - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} @@ -31,12 +39,25 @@ jobs: - name: Checkout 🛎️ uses: "actions/checkout@v2" + - name: Check for changed files + if: startsWith(github.ref, 'refs/tags/') != true + uses: dorny/paths-filter@v2 + id: changes + with: + list-files: "json" + filters: | + code: + - '!(doc-source/**|CONTRIBUTING.rst|.imgbotconfig|.pre-commit-config.yaml|.pylintrc|.readthedocs.yml)' + - name: Setup Python 🐍 + id: setup-python + if: ${{ steps.changes.outputs.code == 'true' || steps.changes.outcome == 'skipped' }} uses: "actions/setup-python@v2" with: python-version: "${{ matrix.config.python-version }}" - name: Install dependencies 🔧 + if: steps.setup-python.outcome == 'success' run: | python -VV python -m site @@ -45,11 +66,12 @@ jobs: python -m pip install --upgrade coverage_pyver_pragma - name: "Run Tests for Python ${{ matrix.config.python-version }}" - run: python -m tox -e "${{ matrix.config.testenvs }}" + if: steps.setup-python.outcome == 'success' + run: python -m tox -e "${{ matrix.config.testenvs }}" -s false - name: "Upload Coverage 🚀" uses: actions/upload-artifact@v2 - if: ${{ always() }} + if: ${{ always() && steps.setup-python.outcome == 'success' }} with: name: "coverage-${{ matrix.config.python-version }}" path: .coverage @@ -127,7 +149,7 @@ jobs: - name: Upload distribution to PyPI 🚀 if: startsWith(github.ref, 'refs/tags/') - uses: pypa/gh-action-pypi-publish@master + uses: pypa/gh-action-pypi-publish@v1.4.2 with: user: __token__ password: ${{ secrets.PYPI_TOKEN }} diff --git a/.github/workflows/python_ci_macos.yml b/.github/workflows/python_ci_macos.yml index 0e6d80c..d24547c 100644 --- a/.github/workflows/python_ci_macos.yml +++ b/.github/workflows/python_ci_macos.yml @@ -4,8 +4,15 @@ name: macOS on: push: + branches-ignore: + - 'repo-helper-update' + - 'pre-commit-ci-update-config' + pull_request: - branches: ["master"] + +permissions: + actions: write + contents: read jobs: tests: @@ -13,7 +20,7 @@ jobs: runs-on: "macos-latest" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-alpha.6,pypy-3.6,pypy-3.7' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-rc.1,pypy-3.6,pypy-3.7' strategy: fail-fast: False @@ -23,7 +30,7 @@ jobs: - {python-version: "3.7", testenvs: "py37,build", experimental: False} - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - - {python-version: "3.10.0-alpha.6", testenvs: "py310-dev,build", experimental: True} + - {python-version: "3.10.0-rc.1", testenvs: "py310-dev,build", experimental: True} - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} @@ -31,12 +38,25 @@ jobs: - name: Checkout 🛎️ uses: "actions/checkout@v2" + - name: Check for changed files + if: startsWith(github.ref, 'refs/tags/') != true + uses: dorny/paths-filter@v2 + id: changes + with: + list-files: "json" + filters: | + code: + - '!(doc-source/**|CONTRIBUTING.rst|.imgbotconfig|.pre-commit-config.yaml|.pylintrc|.readthedocs.yml)' + - name: Setup Python 🐍 + id: setup-python + if: ${{ steps.changes.outputs.code == 'true' || steps.changes.outcome == 'skipped' }} uses: "actions/setup-python@v2" with: python-version: "${{ matrix.config.python-version }}" - name: Install dependencies 🔧 + if: steps.setup-python.outcome == 'success' run: | python -VV python -m site @@ -44,11 +64,12 @@ jobs: python -m pip install --upgrade tox virtualenv - name: "Run Tests for Python ${{ matrix.config.python-version }}" - run: python -m tox -e "${{ matrix.config.testenvs }}" + if: steps.setup-python.outcome == 'success' + run: python -m tox -e "${{ matrix.config.testenvs }}" -s false - name: "Upload Coverage 🚀" uses: actions/upload-artifact@v2 - if: ${{ always() }} + if: ${{ always() && steps.setup-python.outcome == 'success' }} with: name: "coverage-${{ matrix.config.python-version }}" path: .coverage diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 45b174a..8111913 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,6 +4,11 @@ exclude: ^tests/bad_code.py$ repos: + - repo: https://github.com/repo-helper/pyproject-parser + rev: v0.4.1 + hooks: + - id: reformat-pyproject + - repo: https://github.com/pre-commit/pre-commit-hooks rev: v3.4.0 hooks: @@ -31,7 +36,7 @@ repos: args: - --allow-git - id: check-docstring-first - exclude: ^(doc-source/conf|__pkginfo__|make_conda_recipe|setup|tests/.*)\.py$ + exclude: ^(doc-source/conf|__pkginfo__|setup|tests/.*)\.py$ - id: bind-requirements - repo: https://github.com/domdfcoding/flake8-dunder-all @@ -41,7 +46,7 @@ repos: files: ^flake8_github_actions/.*\.py$ - repo: https://github.com/domdfcoding/flake2lint - rev: v0.4.0 + rev: v0.4.1 hooks: - id: flake2lint @@ -62,16 +67,16 @@ repos: - --keep-runtime-typing - repo: https://github.com/Lucas-C/pre-commit-hooks - rev: v1.1.9 + rev: v1.1.10 hooks: - id: remove-crlf - id: forbid-crlf - repo: https://github.com/repo-helper/formate - rev: v0.4.3 + rev: v0.4.9 hooks: - id: formate - exclude: ^(doc-source/conf|__pkginfo__|make_conda_recipe|setup)\.(_)?py$ + exclude: ^(doc-source/conf|__pkginfo__|setup)\.(_)?py$ - repo: https://github.com/domdfcoding/dep_checker rev: v0.6.2 diff --git a/.pylintrc b/.pylintrc index a21206a..81ecba0 100644 --- a/.pylintrc +++ b/.pylintrc @@ -66,7 +66,7 @@ confidence= # no Warning level messages displayed, use"--disable=all --enable=classes # --disable=W" disable=all -enable=assert-on-tuple,astroid-error,bad-except-order,bad-inline-option,bad-option-value,bad-reversed-sequence,bare-except,binary-op-exception,boolean-datetime,catching-non-exception,cell-var-from-loop,confusing-with-statement,consider-merging-isinstance,consider-using-enumerate,consider-using-ternary,continue-in-finally,cyclic-import,deprecated-pragma,django-not-available,duplicate-except,duplicate-key,eval-used,exec-used,expression-not-assigned,fatal,file-ignored,fixme,global-at-module-level,global-statement,global-variable-not-assigned,global-variable-undefined,http-response-with-content-type-json,http-response-with-json-dumps,invalid-all-object,invalid-characters-in-docstring,len-as-condition,literal-comparison,locally-disabled,locally-enabled,lost-exception,lowercase-l-suffix,misplaced-bare-raise,missing-kwoa,mixed-line-endings,model-has-unicode,model-missing-unicode,model-no-explicit-unicode,model-unicode-not-callable,multiple-imports,new-db-field-with-default,non-ascii-bytes-literals,nonexistent-operator,not-in-loop,notimplemented-raised,overlapping-except,parse-error,pointless-statement,pointless-string-statement,raising-bad-type,raising-non-exception,raw-checker-failed,redefine-in-handler,redefined-argument-from-local,redefined-builtin,redundant-content-type-for-json-response,reimported,relative-import,return-outside-function,simplifiable-if-statement,singleton-comparison,syntax-error,trailing-comma-tuple,trailing-newlines,unbalanced-tuple-unpacking,undefined-all-variable,undefined-loop-variable,unexpected-line-ending-format,unidiomatic-typecheck,unnecessary-lambda,unnecessary-pass,unnecessary-semicolon,unneeded-not,unpacking-non-sequence,unreachable,unrecognized-inline-option,used-before-assignment,useless-else-on-loop,using-constant-test,wildcard-import,yield-outside-function,useless-return +enable=assert-on-tuple,astroid-error,bad-except-order,bad-inline-option,bad-option-value,bad-reversed-sequence,bare-except,binary-op-exception,boolean-datetime,catching-non-exception,cell-var-from-loop,confusing-with-statement,consider-merging-isinstance,consider-using-enumerate,consider-using-ternary,continue-in-finally,deprecated-pragma,django-not-available,duplicate-except,duplicate-key,eval-used,exec-used,expression-not-assigned,fatal,file-ignored,fixme,global-at-module-level,global-statement,global-variable-not-assigned,global-variable-undefined,http-response-with-content-type-json,http-response-with-json-dumps,invalid-all-object,invalid-characters-in-docstring,len-as-condition,literal-comparison,locally-disabled,locally-enabled,lost-exception,lowercase-l-suffix,misplaced-bare-raise,missing-kwoa,mixed-line-endings,model-has-unicode,model-missing-unicode,model-no-explicit-unicode,model-unicode-not-callable,multiple-imports,new-db-field-with-default,non-ascii-bytes-literals,nonexistent-operator,not-in-loop,notimplemented-raised,overlapping-except,parse-error,pointless-statement,pointless-string-statement,raising-bad-type,raising-non-exception,raw-checker-failed,redefine-in-handler,redefined-argument-from-local,redefined-builtin,redundant-content-type-for-json-response,reimported,relative-import,return-outside-function,simplifiable-if-statement,singleton-comparison,syntax-error,trailing-comma-tuple,trailing-newlines,unbalanced-tuple-unpacking,undefined-all-variable,undefined-loop-variable,unexpected-line-ending-format,unidiomatic-typecheck,unnecessary-lambda,unnecessary-pass,unnecessary-semicolon,unneeded-not,unpacking-non-sequence,unreachable,unrecognized-inline-option,used-before-assignment,useless-else-on-loop,using-constant-test,wildcard-import,yield-outside-function,useless-return [REPORTS] diff --git a/README.rst b/README.rst index ec60254..2da476a 100644 --- a/README.rst +++ b/README.rst @@ -22,7 +22,7 @@ flake8-github-actions * - Activity - |commits-latest| |commits-since| |maintained| |pypi-downloads| * - QA - - |codefactor| |actions_flake8| |actions_mypy| |pre_commit_ci| + - |codefactor| |actions_flake8| |actions_mypy| * - Other - |license| |language| |requires| @@ -96,10 +96,6 @@ flake8-github-actions :target: https://pypi.org/project/flake8-github-actions/ :alt: PyPI - Downloads -.. |pre_commit_ci| image:: https://results.pre-commit.ci/badge/github/domdfcoding/flake8-github-actions/master.svg - :target: https://results.pre-commit.ci/latest/github/domdfcoding/flake8-github-actions/master - :alt: pre-commit.ci status - .. end shields Installation diff --git a/__pkginfo__.py b/__pkginfo__.py index ac2fb70..ea4ef04 100644 --- a/__pkginfo__.py +++ b/__pkginfo__.py @@ -11,22 +11,6 @@ # This script based on https://github.com/rocky/python-uncompyle6/blob/master/__pkginfo__.py # -# stdlib -import pathlib +__all__ = ["extras_require"] -__all__ = [ - "__copyright__", - "__version__", - "repo_root", - "install_requires", - "extras_require", - ] - -__copyright__ = """ -2020 Dominic Davis-Foster -""" - -__version__ = "0.1.1" -repo_root = pathlib.Path(__file__).parent -install_requires = (repo_root / "requirements.txt").read_text(encoding="utf-8").split('\n') extras_require = {} diff --git a/formate.toml b/formate.toml index 047fea9..be69675 100644 --- a/formate.toml +++ b/formate.toml @@ -46,6 +46,7 @@ known_third_party = [ "flake8_prettycount", "github", "github3_py", + "importlib_metadata", "pytest", "pytest_cov", "pytest_randomly", diff --git a/pyproject.toml b/pyproject.toml index 10d2d94..48f32b1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,9 +9,11 @@ description = "GitHub Actions integration for flake8." readme = "README.rst" keywords = [ "flake8", "github", "github-actions",] dynamic = [ "requires-python", "classifiers", "dependencies",] + [[project.authors]] -email = "dominic@davis-foster.co.uk" name = "Dominic Davis-Foster" +email = "dominic@davis-foster.co.uk" + [project.license] file = "LICENSE" @@ -21,5 +23,25 @@ Homepage = "https://github.com/domdfcoding/flake8-github-actions" "Issue Tracker" = "https://github.com/domdfcoding/flake8-github-actions/issues" "Source Code" = "https://github.com/domdfcoding/flake8-github-actions" +[tool.whey] +base-classifiers = [ + "Environment :: Console", + "Framework :: Flake8", + "Intended Audience :: Developers", + "Typing :: Typed", +] +python-versions = [ "3.6", "3.7", "3.8", "3.9",] +python-implementations = [ "CPython", "PyPy",] +platforms = [ "Windows", "macOS", "Linux",] +license-key = "MIT" +package = "flake8_github_actions" + +[tool.mypy] +python_version = "3.6" +namespace_packages = true +check_untyped_defs = true +warn_unused_ignores = true +no_implicit_optional = true + [project.entry-points."flake8.report"] github = "flake8_github_actions:GitHubFormatter" diff --git a/setup.cfg b/setup.cfg index 293e1bc..3acd655 100644 --- a/setup.cfg +++ b/setup.cfg @@ -8,6 +8,7 @@ [metadata] name = flake8-github-actions +version = 0.1.1 author = Dominic Davis-Foster author_email = dominic@davis-foster.co.uk license = MIT License @@ -52,6 +53,7 @@ python_version = 3.6 namespace_packages = True check_untyped_defs = True warn_unused_ignores = True +no_implicit_optional = True [options.entry_points] flake8.report = github = flake8_github_actions:GitHubFormatter diff --git a/setup.py b/setup.py index 762f9ac..8dec7a1 100644 --- a/setup.py +++ b/setup.py @@ -2,6 +2,7 @@ # This file is managed by 'repo_helper'. Don't edit it directly. # stdlib +import pathlib import shutil import sys @@ -13,12 +14,15 @@ # this package from __pkginfo__ import * # pylint: disable=wildcard-import +repo_root = pathlib.Path(__file__).parent +install_requires = (repo_root / "requirements.txt").read_text(encoding="UTF-8").split('\n') + setup( description="GitHub Actions integration for flake8.", extras_require=extras_require, install_requires=install_requires, + name="flake8-github-actions", py_modules=[], - version=__version__, ) shutil.rmtree("flake8_github_actions.egg-info", ignore_errors=True) diff --git a/tests/requirements.txt b/tests/requirements.txt index 9486568..ee69d13 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,9 +1,10 @@ -coincidence>=0.1.0 +coincidence>=0.2.0 coverage>=5.1 coverage-pyver-pragma>=0.2.1 domdf-python-tools[testing]>=2.0.1 +importlib-metadata>=3.6.0 iniconfig!=1.1.0,>=1.0.1 pytest>=6.0.0 pytest-cov>=2.8.1 -pytest-randomly>=3.3.1 +pytest-randomly>=3.7.0 pytest-timeout>=1.4.2 diff --git a/tox.ini b/tox.ini index a66e5a1..d078dbf 100644 --- a/tox.ini +++ b/tox.ini @@ -52,7 +52,7 @@ basepython = python3.6 ignore_errors = True changedir = {toxinidir} deps = - mypy==0.800 + mypy==0.812 -r{toxinidir}/tests/requirements.txt commands = mypy flake8_github_actions tests {posargs} @@ -69,6 +69,10 @@ basepython = python3.6 skip_install = True ignore_errors = True whitelist_externals = /bin/bash +passenv = + COV_PYTHON_VERSION + COV_PLATFORM + COV_PYTHON_IMPLEMENTATION changedir = {toxinidir} deps = coverage>=5 @@ -80,12 +84,15 @@ commands = [flake8] max-line-length = 120 -select = E111 E112 E113 E121 E122 E125 E127 E128 E129 E131 E133 E201 E202 E203 E211 E222 E223 E224 E225 E225 E226 E227 E228 E231 E241 E242 E251 E261 E262 E265 E271 E272 E303 E304 E306 E402 E502 E703 E711 E712 E713 E714 E721 W291 W292 W293 W391 W504 YTT101 YTT102 YTT103 YTT201 YTT202 YTT203 YTT204 YTT301 YTT302 YTT303 STRFTIME001 STRFTIME002 SXL001 PT001 PT002 PT003 PT005 PT006 PT007 PT008 PT009 PT010 PT011 PT012 PT013 PT014 PT015 PT016 PT017 PT018 PT019 PT020 PT021 RST201 RST202 RST203 RST204 RST205 RST206 RST207 RST208 RST210 RST211 RST212 RST213 RST214 RST215 RST216 RST217 RST218 RST219 RST299 RST301 RST302 RST303 RST304 RST305 RST306 RST399 RST401 RST499 RST900 RST901 RST902 RST903 Q001 Q002 Q003 A001 A002 A003 TYP001 TYP002 TYP003 TYP004 TYP005 TYP006 ENC001 ENC002 ENC003 ENC004 Y001,Y002 Y003 Y004 Y005 Y006 Y007 Y008 Y009 Y010 Y011 Y012 Y013 Y014 Y015 Y090 Y091 E301 E302 E305 D100 D101 D102 D103 D104 D106 D201 D204 D207 D208 D209 D210 D211 D212 D213 D214 D215 D300 D301 D400 D402 D403 D404 D415 D417 DALL000 SLOT000 SLOT001 SLOT002 +select = E111 E112 E113 E121 E122 E125 E127 E128 E129 E131 E133 E201 E202 E203 E211 E222 E223 E224 E225 E225 E226 E227 E228 E231 E241 E242 E251 E261 E262 E265 E271 E272 E303 E304 E306 E402 E502 E703 E711 E712 E713 E714 E721 W291 W292 W293 W391 W504 YTT101 YTT102 YTT103 YTT201 YTT202 YTT203 YTT204 YTT301 YTT302 YTT303 STRFTIME001 STRFTIME002 SXL001 PT001 PT002 PT003 PT006 PT007 PT008 PT009 PT010 PT011 PT012 PT013 PT014 PT015 PT016 PT017 PT018 PT019 PT020 PT021 RST201 RST202 RST203 RST204 RST205 RST206 RST207 RST208 RST210 RST211 RST212 RST213 RST214 RST215 RST216 RST217 RST218 RST219 RST299 RST301 RST302 RST303 RST304 RST305 RST306 RST399 RST401 RST499 RST900 RST901 RST902 RST903 Q001 Q002 Q003 A001 A002 A003 TYP001 TYP002 TYP003 TYP004 TYP005 TYP006 ENC001 ENC002 ENC003 ENC004 ENC011 ENC012 ENC021 ENC022 ENC023 ENC024 ENC025 ENC026 Y001,Y002 Y003 Y004 Y005 Y006 Y007 Y008 Y009 Y010 Y011 Y012 Y013 Y014 Y015 Y090 Y091 NQA001 NQA002 NQA003 NQA004 NQA005 NQA102 NQA103 E301 E302 E305 D100 D101 D102 D103 D104 D106 D201 D204 D207 D208 D209 D210 D211 D212 D213 D214 D215 D300 D301 D400 D402 D403 D404 D415 D417 DALL000 SLOT000 SLOT001 SLOT002 extend-exclude = doc-source,old,build,dist,__pkginfo__.py,setup.py,venv rst-directives = TODO envvar extras-require + license + license-info +rst-roles = choosealicense per-file-ignores = tests/*: D100 D101 D102 D103 D104 D106 D201 D204 D207 D208 D209 D210 D211 D212 D213 D214 D215 D300 D301 D400 D402 D403 D404 D415 D417 DALL000 SLOT000 SLOT001 SLOT002 */*.pyi: E301 E302 E305 D100 D101 D102 D103 D104 D106 D201 D204 D207 D208 D209 D210 D211 D212 D213 D214 D215 D300 D301 D400 D402 D403 D404 D415 D417 DALL000 SLOT000 SLOT001 SLOT002 @@ -94,6 +101,7 @@ inline-quotes = " multiline-quotes = """ docstring-quotes = """ count = True +min_python_version = 3.6 [coverage:run] plugins = coverage_pyver_pragma From d41a2d92648ea4b13ad5382b0cf6471948ec9fe8 Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Wed, 11 Aug 2021 10:19:31 +0100 Subject: [PATCH 059/105] Changes re: transfer to org --- README.rst | 46 +++++++++++++++++++++++----------------------- pyproject.toml | 6 +++--- repo_helper.yml | 3 ++- 3 files changed, 28 insertions(+), 27 deletions(-) diff --git a/README.rst b/README.rst index 2da476a..bfcd863 100644 --- a/README.rst +++ b/README.rst @@ -26,36 +26,36 @@ flake8-github-actions * - Other - |license| |language| |requires| -.. |actions_linux| image:: https://github.com/domdfcoding/flake8-github-actions/workflows/Linux/badge.svg - :target: https://github.com/domdfcoding/flake8-github-actions/actions?query=workflow%3A%22Linux%22 +.. |actions_linux| image:: https://github.com/python-formate/flake8-github-actions/workflows/Linux/badge.svg + :target: https://github.com/python-formate/flake8-github-actions/actions?query=workflow%3A%22Linux%22 :alt: Linux Test Status -.. |actions_windows| image:: https://github.com/domdfcoding/flake8-github-actions/workflows/Windows/badge.svg - :target: https://github.com/domdfcoding/flake8-github-actions/actions?query=workflow%3A%22Windows%22 +.. |actions_windows| image:: https://github.com/python-formate/flake8-github-actions/workflows/Windows/badge.svg + :target: https://github.com/python-formate/flake8-github-actions/actions?query=workflow%3A%22Windows%22 :alt: Windows Test Status -.. |actions_macos| image:: https://github.com/domdfcoding/flake8-github-actions/workflows/macOS/badge.svg - :target: https://github.com/domdfcoding/flake8-github-actions/actions?query=workflow%3A%22macOS%22 +.. |actions_macos| image:: https://github.com/python-formate/flake8-github-actions/workflows/macOS/badge.svg + :target: https://github.com/python-formate/flake8-github-actions/actions?query=workflow%3A%22macOS%22 :alt: macOS Test Status -.. |actions_flake8| image:: https://github.com/domdfcoding/flake8-github-actions/workflows/Flake8/badge.svg - :target: https://github.com/domdfcoding/flake8-github-actions/actions?query=workflow%3A%22Flake8%22 +.. |actions_flake8| image:: https://github.com/python-formate/flake8-github-actions/workflows/Flake8/badge.svg + :target: https://github.com/python-formate/flake8-github-actions/actions?query=workflow%3A%22Flake8%22 :alt: Flake8 Status -.. |actions_mypy| image:: https://github.com/domdfcoding/flake8-github-actions/workflows/mypy/badge.svg - :target: https://github.com/domdfcoding/flake8-github-actions/actions?query=workflow%3A%22mypy%22 +.. |actions_mypy| image:: https://github.com/python-formate/flake8-github-actions/workflows/mypy/badge.svg + :target: https://github.com/python-formate/flake8-github-actions/actions?query=workflow%3A%22mypy%22 :alt: mypy status -.. |requires| image:: https://requires.io/github/domdfcoding/flake8-github-actions/requirements.svg?branch=master - :target: https://requires.io/github/domdfcoding/flake8-github-actions/requirements/?branch=master +.. |requires| image:: https://requires.io/github/python-formate/flake8-github-actions/requirements.svg?branch=master + :target: https://requires.io/github/python-formate/flake8-github-actions/requirements/?branch=master :alt: Requirements Status -.. |coveralls| image:: https://img.shields.io/coveralls/github/domdfcoding/flake8-github-actions/master?logo=coveralls - :target: https://coveralls.io/github/domdfcoding/flake8-github-actions?branch=master +.. |coveralls| image:: https://img.shields.io/coveralls/github/python-formate/flake8-github-actions/master?logo=coveralls + :target: https://coveralls.io/github/python-formate/flake8-github-actions?branch=master :alt: Coverage -.. |codefactor| image:: https://img.shields.io/codefactor/grade/github/domdfcoding/flake8-github-actions?logo=codefactor - :target: https://www.codefactor.io/repository/github/domdfcoding/flake8-github-actions +.. |codefactor| image:: https://img.shields.io/codefactor/grade/github/python-formate/flake8-github-actions?logo=codefactor + :target: https://www.codefactor.io/repository/github/python-formate/flake8-github-actions :alt: CodeFactor Grade .. |pypi-version| image:: https://img.shields.io/pypi/v/flake8-github-actions @@ -74,19 +74,19 @@ flake8-github-actions :target: https://pypi.org/project/flake8-github-actions/ :alt: PyPI - Wheel -.. |license| image:: https://img.shields.io/github/license/domdfcoding/flake8-github-actions - :target: https://github.com/domdfcoding/flake8-github-actions/blob/master/LICENSE +.. |license| image:: https://img.shields.io/github/license/python-formate/flake8-github-actions + :target: https://github.com/python-formate/flake8-github-actions/blob/master/LICENSE :alt: License -.. |language| image:: https://img.shields.io/github/languages/top/domdfcoding/flake8-github-actions +.. |language| image:: https://img.shields.io/github/languages/top/python-formate/flake8-github-actions :alt: GitHub top language -.. |commits-since| image:: https://img.shields.io/github/commits-since/domdfcoding/flake8-github-actions/v0.1.1 - :target: https://github.com/domdfcoding/flake8-github-actions/pulse +.. |commits-since| image:: https://img.shields.io/github/commits-since/python-formate/flake8-github-actions/v0.1.1 + :target: https://github.com/python-formate/flake8-github-actions/pulse :alt: GitHub commits since tagged version -.. |commits-latest| image:: https://img.shields.io/github/last-commit/domdfcoding/flake8-github-actions - :target: https://github.com/domdfcoding/flake8-github-actions/commit/master +.. |commits-latest| image:: https://img.shields.io/github/last-commit/python-formate/flake8-github-actions + :target: https://github.com/python-formate/flake8-github-actions/commit/master :alt: GitHub last commit .. |maintained| image:: https://img.shields.io/maintenance/yes/2021 diff --git a/pyproject.toml b/pyproject.toml index 48f32b1..d68e6f3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,9 +19,9 @@ email = "dominic@davis-foster.co.uk" file = "LICENSE" [project.urls] -Homepage = "https://github.com/domdfcoding/flake8-github-actions" -"Issue Tracker" = "https://github.com/domdfcoding/flake8-github-actions/issues" -"Source Code" = "https://github.com/domdfcoding/flake8-github-actions" +Homepage = "https://github.com/python-formate/flake8-github-actions" +"Issue Tracker" = "https://github.com/python-formate/flake8-github-actions/issues" +"Source Code" = "https://github.com/python-formate/flake8-github-actions" [tool.whey] base-classifiers = [ diff --git a/repo_helper.yml b/repo_helper.yml index 8977e35..fb7e18d 100644 --- a/repo_helper.yml +++ b/repo_helper.yml @@ -4,7 +4,8 @@ modname: 'flake8-github-actions' copyright_years: '2020' author: 'Dominic Davis-Foster' email: 'dominic@davis-foster.co.uk' -username: 'domdfcoding' +username: "python-formate" +assignee: "domdfcoding" version: '0.1.1' license: 'MIT' short_desc: 'GitHub Actions integration for flake8.' From db637c5fa8515fd1f99e0e115a98601e86d280bb Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Wed, 11 Aug 2021 09:25:13 +0000 Subject: [PATCH 060/105] Updated files with 'repo_helper'. (#31) Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- setup.cfg | 13 +++---------- tox.ini | 2 +- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/setup.cfg b/setup.cfg index 3acd655..cefd0ea 100644 --- a/setup.cfg +++ b/setup.cfg @@ -16,10 +16,10 @@ keywords = flake8, github, github-actions long_description = file: README.rst long_description_content_type = text/x-rst platforms = Windows, macOS, Linux -url = https://github.com/domdfcoding/flake8-github-actions +url = https://github.com/python-formate/flake8-github-actions project_urls = - Issue Tracker = https://github.com/domdfcoding/flake8-github-actions/issues - Source Code = https://github.com/domdfcoding/flake8-github-actions + Issue Tracker = https://github.com/python-formate/flake8-github-actions/issues + Source Code = https://github.com/python-formate/flake8-github-actions classifiers = Environment :: Console Framework :: Flake8 @@ -48,12 +48,5 @@ exclude = tests tests.* -[mypy] -python_version = 3.6 -namespace_packages = True -check_untyped_defs = True -warn_unused_ignores = True -no_implicit_optional = True - [options.entry_points] flake8.report = github = flake8_github_actions:GitHubFormatter diff --git a/tox.ini b/tox.ini index d078dbf..90309b3 100644 --- a/tox.ini +++ b/tox.ini @@ -52,7 +52,7 @@ basepython = python3.6 ignore_errors = True changedir = {toxinidir} deps = - mypy==0.812 + mypy==0.910 -r{toxinidir}/tests/requirements.txt commands = mypy flake8_github_actions tests {posargs} From 63a357bcd78e63995697bed0cbb0768816b0badd Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Wed, 11 Aug 2021 10:27:23 +0100 Subject: [PATCH 061/105] Add "Beta" classifier --- pyproject.toml | 1 + repo_helper.yml | 1 + setup.cfg | 1 + 3 files changed, 3 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index d68e6f3..0a7350e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,6 +25,7 @@ Homepage = "https://github.com/python-formate/flake8-github-actions" [tool.whey] base-classifiers = [ + "Development Status :: 4 - Beta", "Environment :: Console", "Framework :: Flake8", "Intended Audience :: Developers", diff --git a/repo_helper.yml b/repo_helper.yml index fb7e18d..87950d0 100644 --- a/repo_helper.yml +++ b/repo_helper.yml @@ -35,6 +35,7 @@ entry_points: - github = flake8_github_actions:GitHubFormatter classifiers: + - 'Development Status :: 4 - Beta' - 'Environment :: Console' - 'Framework :: Flake8' - 'Intended Audience :: Developers' diff --git a/setup.cfg b/setup.cfg index cefd0ea..cda371f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -21,6 +21,7 @@ project_urls = Issue Tracker = https://github.com/python-formate/flake8-github-actions/issues Source Code = https://github.com/python-formate/flake8-github-actions classifiers = + Development Status :: 4 - Beta Environment :: Console Framework :: Flake8 Intended Audience :: Developers From 478776036ab21c63409b8f720725951df6eeaf05 Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Wed, 11 Aug 2021 10:27:42 +0100 Subject: [PATCH 062/105] Rearrange repo_helper.yml --- repo_helper.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/repo_helper.yml b/repo_helper.yml index 87950d0..0364eef 100644 --- a/repo_helper.yml +++ b/repo_helper.yml @@ -10,8 +10,11 @@ version: '0.1.1' license: 'MIT' short_desc: 'GitHub Actions integration for flake8.' +min_coverage: 100 enable_conda: false enable_docs: false +requires_python: 3.6 +pre_commit_exclude: "^tests/bad_code.py$" python_versions: - '3.6' @@ -40,10 +43,5 @@ classifiers: - 'Framework :: Flake8' - 'Intended Audience :: Developers' -requires_python: 3.6 - -pre_commit_exclude: "^tests/bad_code.py$" -min_coverage: 100 - tox_unmanaged: - "testenv:lint" From e8949b2637fffd64d78737311b340f08aafd69ce Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Mon, 13 Sep 2021 22:44:57 +0100 Subject: [PATCH 063/105] Updated files with 'repo_helper'. (#32) Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .github/workflows/flake8.yml | 1 + .github/workflows/mypy.yml | 1 + .github/workflows/python_ci.yml | 1 + .github/workflows/python_ci_linux.yml | 1 + .github/workflows/python_ci_macos.yml | 1 + .pre-commit-config.yaml | 2 +- README.rst | 4 ++-- 7 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/flake8.yml b/.github/workflows/flake8.yml index f46a179..84e9436 100644 --- a/.github/workflows/flake8.yml +++ b/.github/workflows/flake8.yml @@ -7,6 +7,7 @@ on: branches-ignore: - 'repo-helper-update' - 'pre-commit-ci-update-config' + - 'imgbot' pull_request: permissions: diff --git a/.github/workflows/mypy.yml b/.github/workflows/mypy.yml index d6d4200..5a7324b 100644 --- a/.github/workflows/mypy.yml +++ b/.github/workflows/mypy.yml @@ -7,6 +7,7 @@ on: branches-ignore: - 'repo-helper-update' - 'pre-commit-ci-update-config' + - 'imgbot' pull_request: permissions: diff --git a/.github/workflows/python_ci.yml b/.github/workflows/python_ci.yml index 044d73e..7c26618 100644 --- a/.github/workflows/python_ci.yml +++ b/.github/workflows/python_ci.yml @@ -7,6 +7,7 @@ on: branches-ignore: - 'repo-helper-update' - 'pre-commit-ci-update-config' + - 'imgbot' pull_request: diff --git a/.github/workflows/python_ci_linux.yml b/.github/workflows/python_ci_linux.yml index d6c5600..9e8075d 100644 --- a/.github/workflows/python_ci_linux.yml +++ b/.github/workflows/python_ci_linux.yml @@ -7,6 +7,7 @@ on: branches-ignore: - 'repo-helper-update' - 'pre-commit-ci-update-config' + - 'imgbot' tags: - '*' pull_request: diff --git a/.github/workflows/python_ci_macos.yml b/.github/workflows/python_ci_macos.yml index d24547c..a7c3563 100644 --- a/.github/workflows/python_ci_macos.yml +++ b/.github/workflows/python_ci_macos.yml @@ -7,6 +7,7 @@ on: branches-ignore: - 'repo-helper-update' - 'pre-commit-ci-update-config' + - 'imgbot' pull_request: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8111913..22d9b89 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,7 +5,7 @@ exclude: ^tests/bad_code.py$ repos: - repo: https://github.com/repo-helper/pyproject-parser - rev: v0.4.1 + rev: v0.4.2 hooks: - id: reformat-pyproject diff --git a/README.rst b/README.rst index bfcd863..f4e5904 100644 --- a/README.rst +++ b/README.rst @@ -46,8 +46,8 @@ flake8-github-actions :target: https://github.com/python-formate/flake8-github-actions/actions?query=workflow%3A%22mypy%22 :alt: mypy status -.. |requires| image:: https://requires.io/github/python-formate/flake8-github-actions/requirements.svg?branch=master - :target: https://requires.io/github/python-formate/flake8-github-actions/requirements/?branch=master +.. |requires| image:: https://dependency-dash.herokuapp.com/github/python-formate/flake8-github-actions/badge.svg + :target: https://dependency-dash.herokuapp.com/github/python-formate/flake8-github-actions/ :alt: Requirements Status .. |coveralls| image:: https://img.shields.io/coveralls/github/python-formate/flake8-github-actions/master?logo=coveralls From 3f7e069dc9052bc8e79843f2c889c7e592967ca5 Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Sun, 19 Sep 2021 09:43:39 +0000 Subject: [PATCH 064/105] Updated files with 'repo_helper'. (#33) Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .github/workflows/python_ci.yml | 4 ++-- .github/workflows/python_ci_linux.yml | 4 ++-- .github/workflows/python_ci_macos.yml | 4 ++-- .pre-commit-config.yaml | 9 +++++++-- pyproject.toml | 21 +++++++++++++++++++++ 5 files changed, 34 insertions(+), 8 deletions(-) diff --git a/.github/workflows/python_ci.yml b/.github/workflows/python_ci.yml index 7c26618..5248f2d 100644 --- a/.github/workflows/python_ci.yml +++ b/.github/workflows/python_ci.yml @@ -21,7 +21,7 @@ jobs: runs-on: "windows-2019" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-rc.1,pypy-3.6,pypy-3.7' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-rc.2,pypy-3.6,pypy-3.7' strategy: fail-fast: False @@ -31,7 +31,7 @@ jobs: - {python-version: "3.7", testenvs: "py37,build", experimental: False} - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - - {python-version: "3.10.0-rc.1", testenvs: "py310-dev,build", experimental: True} + - {python-version: "3.10.0-rc.2", testenvs: "py310-dev,build", experimental: True} - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} diff --git a/.github/workflows/python_ci_linux.yml b/.github/workflows/python_ci_linux.yml index 9e8075d..9ed15b0 100644 --- a/.github/workflows/python_ci_linux.yml +++ b/.github/workflows/python_ci_linux.yml @@ -22,7 +22,7 @@ jobs: runs-on: "ubuntu-20.04" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-rc.1,pypy-3.6,pypy-3.7' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-rc.2,pypy-3.6,pypy-3.7' strategy: fail-fast: False @@ -32,7 +32,7 @@ jobs: - {python-version: "3.7", testenvs: "py37,build", experimental: False} - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - - {python-version: "3.10.0-rc.1", testenvs: "py310-dev,build", experimental: True} + - {python-version: "3.10.0-rc.2", testenvs: "py310-dev,build", experimental: True} - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} diff --git a/.github/workflows/python_ci_macos.yml b/.github/workflows/python_ci_macos.yml index a7c3563..dd5571a 100644 --- a/.github/workflows/python_ci_macos.yml +++ b/.github/workflows/python_ci_macos.yml @@ -21,7 +21,7 @@ jobs: runs-on: "macos-latest" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-rc.1,pypy-3.6,pypy-3.7' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-rc.2,pypy-3.6,pypy-3.7' strategy: fail-fast: False @@ -31,7 +31,7 @@ jobs: - {python-version: "3.7", testenvs: "py37,build", experimental: False} - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - - {python-version: "3.10.0-rc.1", testenvs: "py310-dev,build", experimental: True} + - {python-version: "3.10.0-rc.2", testenvs: "py310-dev,build", experimental: True} - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 22d9b89..5d7014d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -51,7 +51,7 @@ repos: - id: flake2lint - repo: https://github.com/pre-commit/pygrep-hooks - rev: v1.8.0 + rev: v1.9.0 hooks: - id: python-no-eval - id: rst-backticks @@ -72,7 +72,12 @@ repos: - id: remove-crlf - id: forbid-crlf - - repo: https://github.com/repo-helper/formate + - repo: https://github.com/python-formate/snippet-fmt + rev: v0.1.1 + hooks: + - id: snippet-fmt + + - repo: https://github.com/python-formate/formate rev: v0.4.9 hooks: - id: formate diff --git a/pyproject.toml b/pyproject.toml index 0a7350e..532f36d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,6 +43,27 @@ namespace_packages = true check_untyped_defs = true warn_unused_ignores = true no_implicit_optional = true +show_error_codes = true + +[tool.snippet-fmt] +directives = [ "code-block",] [project.entry-points."flake8.report"] github = "flake8_github_actions:GitHubFormatter" + +[tool.dependency-dash."requirements.txt"] +order = 10 + +[tool.dependency-dash."tests/requirements.txt"] +order = 20 +include = false + +[tool.snippet-fmt.languages.python] +reformat = true + +[tool.snippet-fmt.languages.TOML] +reformat = true + +[tool.snippet-fmt.languages.ini] + +[tool.snippet-fmt.languages.json] From 3d9ddf02369a3b870dea9750dfaf465edd7d4492 Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Mon, 20 Sep 2021 15:16:43 +0000 Subject: [PATCH 065/105] Updated files with 'repo_helper'. (#34) Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5d7014d..752f4f6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -73,7 +73,7 @@ repos: - id: forbid-crlf - repo: https://github.com/python-formate/snippet-fmt - rev: v0.1.1 + rev: v0.1.3 hooks: - id: snippet-fmt From 64480a51f9b30c4d93ab5174535f681f4ae295f6 Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Wed, 22 Dec 2021 07:01:46 +0000 Subject: [PATCH 066/105] [repo-helper] Configuration Update (#35) * Updated files with 'repo_helper'. * Updated files with 'repo_helper'. Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .github/workflows/cleanup.yml | 14 -------------- .github/workflows/python_ci.yml | 4 ++-- .github/workflows/python_ci_linux.yml | 9 +++++++-- .github/workflows/python_ci_macos.yml | 5 ++--- .pre-commit-config.yaml | 2 +- pyproject.toml | 3 ++- tox.ini | 8 +++++++- 7 files changed, 21 insertions(+), 24 deletions(-) delete mode 100644 .github/workflows/cleanup.yml diff --git a/.github/workflows/cleanup.yml b/.github/workflows/cleanup.yml deleted file mode 100644 index 741c0bd..0000000 --- a/.github/workflows/cleanup.yml +++ /dev/null @@ -1,14 +0,0 @@ -# This file is managed by 'repo_helper'. Don't edit it directly. ---- -name: Artefact Cleaner -on: - schedule: - - cron: 0 9 1 * * -jobs: - Clean: - runs-on: ubuntu-latest - steps: - - name: cleanup - uses: glassechidna/artifact-cleaner@v2 - with: - minimumAge: 1000000.0 diff --git a/.github/workflows/python_ci.yml b/.github/workflows/python_ci.yml index 5248f2d..469f90a 100644 --- a/.github/workflows/python_ci.yml +++ b/.github/workflows/python_ci.yml @@ -21,7 +21,7 @@ jobs: runs-on: "windows-2019" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-rc.2,pypy-3.6,pypy-3.7' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,pypy-3.6,pypy-3.7' strategy: fail-fast: False @@ -31,7 +31,7 @@ jobs: - {python-version: "3.7", testenvs: "py37,build", experimental: False} - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - - {python-version: "3.10.0-rc.2", testenvs: "py310-dev,build", experimental: True} + - {python-version: "3.10", testenvs: "py310-dev,build", experimental: True} - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} diff --git a/.github/workflows/python_ci_linux.yml b/.github/workflows/python_ci_linux.yml index 9ed15b0..36524ca 100644 --- a/.github/workflows/python_ci_linux.yml +++ b/.github/workflows/python_ci_linux.yml @@ -22,7 +22,7 @@ jobs: runs-on: "ubuntu-20.04" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-rc.2,pypy-3.6,pypy-3.7' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,pypy-3.6,pypy-3.7' strategy: fail-fast: False @@ -32,7 +32,7 @@ jobs: - {python-version: "3.7", testenvs: "py37,build", experimental: False} - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - - {python-version: "3.10.0-rc.2", testenvs: "py310-dev,build", experimental: True} + - {python-version: "3.10", testenvs: "py310-dev,build", experimental: True} - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} @@ -101,21 +101,26 @@ jobs: path: coverage - name: Display structure of downloaded files + id: show run: ls -R working-directory: coverage + continue-on-error: true - name: Combine Coverage 👷 + if: ${{ steps.show.outcome != 'failure' }} run: | shopt -s globstar python -m coverage combine coverage/**/.coverage - name: "Upload Combined Coverage Artefact 🚀" + if: ${{ steps.show.outcome != 'failure' }} uses: actions/upload-artifact@v2 with: name: "combined-coverage" path: .coverage - name: "Upload Combined Coverage to Coveralls" + if: ${{ steps.show.outcome != 'failure' }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | diff --git a/.github/workflows/python_ci_macos.yml b/.github/workflows/python_ci_macos.yml index dd5571a..5401e8d 100644 --- a/.github/workflows/python_ci_macos.yml +++ b/.github/workflows/python_ci_macos.yml @@ -21,7 +21,7 @@ jobs: runs-on: "macos-latest" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10.0-rc.2,pypy-3.6,pypy-3.7' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,pypy-3.7' strategy: fail-fast: False @@ -31,8 +31,7 @@ jobs: - {python-version: "3.7", testenvs: "py37,build", experimental: False} - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - - {python-version: "3.10.0-rc.2", testenvs: "py310-dev,build", experimental: True} - - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} + - {python-version: "3.10", testenvs: "py310-dev,build", experimental: True} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} steps: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 752f4f6..8d2e06a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -30,7 +30,7 @@ repos: - id: end-of-file-fixer - repo: https://github.com/domdfcoding/pre-commit-hooks - rev: v0.2.1 + rev: v0.3.0 hooks: - id: requirements-txt-sorter args: diff --git a/pyproject.toml b/pyproject.toml index 532f36d..fc17f9a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,8 @@ version = "0.1.1" description = "GitHub Actions integration for flake8." readme = "README.rst" keywords = [ "flake8", "github", "github-actions",] -dynamic = [ "requires-python", "classifiers", "dependencies",] +dynamic = [ "classifiers", "dependencies",] +requires-python = ">=3.6" [[project.authors]] name = "Dominic Davis-Foster" diff --git a/tox.ini b/tox.ini index 90309b3..92bbe1e 100644 --- a/tox.ini +++ b/tox.ini @@ -29,7 +29,9 @@ qa = mypy, lint cov = py36, coverage [testenv] -setenv = PYTHONDEVMODE = 1 +setenv = + PYTHONDEVMODE=1 + PIP_DISABLE_PIP_VERSION_CHECK=1 deps = -r{toxinidir}/tests/requirements.txt commands = python --version @@ -102,6 +104,10 @@ multiline-quotes = """ docstring-quotes = """ count = True min_python_version = 3.6 +unused-arguments-ignore-abstract-functions = True +unused-arguments-ignore-overload-functions = True +unused-arguments-ignore-magic-methods = True +unused-arguments-ignore-variadic-names = True [coverage:run] plugins = coverage_pyver_pragma From 608797cf4f945eeab6a2c907f8bbb3b2ec5539ef Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Tue, 11 Jan 2022 07:19:41 +0000 Subject: [PATCH 067/105] Updated files with 'repo_helper'. (#36) Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- README.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8d2e06a..8dbc6c2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -73,7 +73,7 @@ repos: - id: forbid-crlf - repo: https://github.com/python-formate/snippet-fmt - rev: v0.1.3 + rev: v0.1.4 hooks: - id: snippet-fmt diff --git a/README.rst b/README.rst index f4e5904..e80399a 100644 --- a/README.rst +++ b/README.rst @@ -89,7 +89,7 @@ flake8-github-actions :target: https://github.com/python-formate/flake8-github-actions/commit/master :alt: GitHub last commit -.. |maintained| image:: https://img.shields.io/maintenance/yes/2021 +.. |maintained| image:: https://img.shields.io/maintenance/yes/2022 :alt: Maintenance .. |pypi-downloads| image:: https://img.shields.io/pypi/dm/flake8-github-actions From 58f1df3316993e01fcb2afdf4988bd4c90c489b8 Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Fri, 14 Jan 2022 16:04:48 +0000 Subject: [PATCH 068/105] Updated files with 'repo_helper'. (#37) Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- __pkginfo__.py | 16 ---------------- setup.py | 3 +-- tox.ini | 2 +- 3 files changed, 2 insertions(+), 19 deletions(-) delete mode 100644 __pkginfo__.py diff --git a/__pkginfo__.py b/__pkginfo__.py deleted file mode 100644 index ea4ef04..0000000 --- a/__pkginfo__.py +++ /dev/null @@ -1,16 +0,0 @@ -# This file is managed by 'repo_helper'. Don't edit it directly. -# Copyright © 2020 Dominic Davis-Foster -# -# This file is distributed under the same license terms as the program it came with. -# There will probably be a file called LICEN[S/C]E in the same directory as this file. -# -# In any case, this program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# -# This script based on https://github.com/rocky/python-uncompyle6/blob/master/__pkginfo__.py -# - -__all__ = ["extras_require"] - -extras_require = {} diff --git a/setup.py b/setup.py index 8dec7a1..92d44e9 100644 --- a/setup.py +++ b/setup.py @@ -11,8 +11,7 @@ sys.path.append('.') -# this package -from __pkginfo__ import * # pylint: disable=wildcard-import +extras_require = {} repo_root = pathlib.Path(__file__).parent install_requires = (repo_root / "requirements.txt").read_text(encoding="UTF-8").split('\n') diff --git a/tox.ini b/tox.ini index 92bbe1e..59a4d1d 100644 --- a/tox.ini +++ b/tox.ini @@ -54,7 +54,7 @@ basepython = python3.6 ignore_errors = True changedir = {toxinidir} deps = - mypy==0.910 + mypy==0.931 -r{toxinidir}/tests/requirements.txt commands = mypy flake8_github_actions tests {posargs} From cf85491a4fbfad2f0eaaa74a9195251c86244d40 Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Fri, 14 Jan 2022 17:14:50 +0000 Subject: [PATCH 069/105] Switch build backend to whey --- .bumpversion.cfg | 4 ---- MANIFEST.in | 6 ------ pyproject.toml | 6 +++--- repo_helper.yml | 1 + setup.cfg | 43 ------------------------------------------- setup.py | 27 --------------------------- 6 files changed, 4 insertions(+), 83 deletions(-) delete mode 100644 MANIFEST.in delete mode 100644 setup.py diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 97245ee..68d6abb 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -15,7 +15,3 @@ replace = : str = "{new_version}" [bumpversion:file:pyproject.toml] search = version = "{current_version}" replace = version = "{new_version}" - -[bumpversion:file:setup.cfg] -search = version = {current_version} -replace = version = {new_version} diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 51376c6..0000000 --- a/MANIFEST.in +++ /dev/null @@ -1,6 +0,0 @@ -include __pkginfo__.py -include LICENSE -include requirements.txt -prune **/__pycache__ -recursive-include flake8_github_actions *.pyi -include flake8_github_actions/py.typed diff --git a/pyproject.toml b/pyproject.toml index fc17f9a..5749d87 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,15 +1,15 @@ [build-system] -requires = [ "setuptools>=40.6.0", "wheel>=0.34.2",] -build-backend = "setuptools.build_meta" +requires = [ "whey",] +build-backend = "whey" [project] name = "flake8-github-actions" version = "0.1.1" description = "GitHub Actions integration for flake8." readme = "README.rst" +requires-python = ">=3.6" keywords = [ "flake8", "github", "github-actions",] dynamic = [ "classifiers", "dependencies",] -requires-python = ">=3.6" [[project.authors]] name = "Dominic Davis-Foster" diff --git a/repo_helper.yml b/repo_helper.yml index 0364eef..230faea 100644 --- a/repo_helper.yml +++ b/repo_helper.yml @@ -15,6 +15,7 @@ enable_conda: false enable_docs: false requires_python: 3.6 pre_commit_exclude: "^tests/bad_code.py$" +use_whey: true python_versions: - '3.6' diff --git a/setup.cfg b/setup.cfg index cda371f..1d938dd 100644 --- a/setup.cfg +++ b/setup.cfg @@ -6,48 +6,5 @@ # * mypy # * options.entry_points -[metadata] -name = flake8-github-actions -version = 0.1.1 -author = Dominic Davis-Foster -author_email = dominic@davis-foster.co.uk -license = MIT License -keywords = flake8, github, github-actions -long_description = file: README.rst -long_description_content_type = text/x-rst -platforms = Windows, macOS, Linux -url = https://github.com/python-formate/flake8-github-actions -project_urls = - Issue Tracker = https://github.com/python-formate/flake8-github-actions/issues - Source Code = https://github.com/python-formate/flake8-github-actions -classifiers = - Development Status :: 4 - Beta - Environment :: Console - Framework :: Flake8 - Intended Audience :: Developers - License :: OSI Approved :: MIT License - Operating System :: OS Independent - Programming Language :: Python - Programming Language :: Python :: 3 :: Only - Programming Language :: Python :: 3.6 - Programming Language :: Python :: 3.7 - Programming Language :: Python :: 3.8 - Programming Language :: Python :: 3.9 - Programming Language :: Python :: Implementation :: CPython - Programming Language :: Python :: Implementation :: PyPy - Typing :: Typed - -[options] -python_requires = >=3.6 -zip_safe = False -include_package_data = True -packages = find: - -[options.packages.find] -exclude = - doc-source - tests - tests.* - [options.entry_points] flake8.report = github = flake8_github_actions:GitHubFormatter diff --git a/setup.py b/setup.py deleted file mode 100644 index 92d44e9..0000000 --- a/setup.py +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env python -# This file is managed by 'repo_helper'. Don't edit it directly. - -# stdlib -import pathlib -import shutil -import sys - -# 3rd party -from setuptools import setup - -sys.path.append('.') - -extras_require = {} - -repo_root = pathlib.Path(__file__).parent -install_requires = (repo_root / "requirements.txt").read_text(encoding="UTF-8").split('\n') - -setup( - description="GitHub Actions integration for flake8.", - extras_require=extras_require, - install_requires=install_requires, - name="flake8-github-actions", - py_modules=[], - ) - -shutil.rmtree("flake8_github_actions.egg-info", ignore_errors=True) From f8fb783d1fbac2ba4ae0316965c71046541cc12b Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Fri, 14 Jan 2022 18:58:07 +0000 Subject: [PATCH 070/105] Test on Python 3.11 --- .github/workflows/python_ci.yml | 5 +++-- .github/workflows/python_ci_linux.yml | 5 +++-- .github/workflows/python_ci_macos.yml | 5 +++-- pyproject.toml | 2 +- repo_helper.yml | 3 ++- tox.ini | 14 ++++++++++++-- 6 files changed, 24 insertions(+), 10 deletions(-) diff --git a/.github/workflows/python_ci.yml b/.github/workflows/python_ci.yml index 469f90a..7f79b3a 100644 --- a/.github/workflows/python_ci.yml +++ b/.github/workflows/python_ci.yml @@ -21,7 +21,7 @@ jobs: runs-on: "windows-2019" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,pypy-3.6,pypy-3.7' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-alpha.3,pypy-3.6,pypy-3.7' strategy: fail-fast: False @@ -31,7 +31,8 @@ jobs: - {python-version: "3.7", testenvs: "py37,build", experimental: False} - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - - {python-version: "3.10", testenvs: "py310-dev,build", experimental: True} + - {python-version: "3.10", testenvs: "py310,build", experimental: False} + - {python-version: "3.11.0-alpha.3", testenvs: "py311-dev,build", experimental: True} - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} diff --git a/.github/workflows/python_ci_linux.yml b/.github/workflows/python_ci_linux.yml index 36524ca..7689c38 100644 --- a/.github/workflows/python_ci_linux.yml +++ b/.github/workflows/python_ci_linux.yml @@ -22,7 +22,7 @@ jobs: runs-on: "ubuntu-20.04" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,pypy-3.6,pypy-3.7' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-alpha.3,pypy-3.6,pypy-3.7' strategy: fail-fast: False @@ -32,7 +32,8 @@ jobs: - {python-version: "3.7", testenvs: "py37,build", experimental: False} - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - - {python-version: "3.10", testenvs: "py310-dev,build", experimental: True} + - {python-version: "3.10", testenvs: "py310,build", experimental: False} + - {python-version: "3.11.0-alpha.3", testenvs: "py311-dev,build", experimental: True} - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} diff --git a/.github/workflows/python_ci_macos.yml b/.github/workflows/python_ci_macos.yml index 5401e8d..eaa4f46 100644 --- a/.github/workflows/python_ci_macos.yml +++ b/.github/workflows/python_ci_macos.yml @@ -21,7 +21,7 @@ jobs: runs-on: "macos-latest" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,pypy-3.7' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-alpha.3,pypy-3.7' strategy: fail-fast: False @@ -31,7 +31,8 @@ jobs: - {python-version: "3.7", testenvs: "py37,build", experimental: False} - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - - {python-version: "3.10", testenvs: "py310-dev,build", experimental: True} + - {python-version: "3.10", testenvs: "py310,build", experimental: False} + - {python-version: "3.11.0-alpha.3", testenvs: "py311-dev,build", experimental: True} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} steps: diff --git a/pyproject.toml b/pyproject.toml index 5749d87..3dc5cd1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,7 +32,7 @@ base-classifiers = [ "Intended Audience :: Developers", "Typing :: Typed", ] -python-versions = [ "3.6", "3.7", "3.8", "3.9",] +python-versions = [ "3.6", "3.7", "3.8", "3.9", "3.10",] python-implementations = [ "CPython", "PyPy",] platforms = [ "Windows", "macOS", "Linux",] license-key = "MIT" diff --git a/repo_helper.yml b/repo_helper.yml index 230faea..b01b4f2 100644 --- a/repo_helper.yml +++ b/repo_helper.yml @@ -22,7 +22,8 @@ python_versions: - '3.7' - '3.8' - '3.9' - - 3.10-dev + - "3.10" + - 3.11-dev - pypy36 - pypy37 diff --git a/tox.ini b/tox.ini index 59a4d1d..36f9ab5 100644 --- a/tox.ini +++ b/tox.ini @@ -15,7 +15,17 @@ # * pytest [tox] -envlist = py36, py37, py38, py39, py310-dev, pypy36, pypy37, mypy, build +envlist = + py36 + py37 + py38 + py39 + py310 + py311-dev + pypy36 + pypy37 + mypy + build skip_missing_interpreters = True isolated_build = True requires = @@ -24,7 +34,7 @@ requires = tox-pip-version>=0.0.7 [envlists] -test = py36, py37, py38, py39, py310-dev, pypy36, pypy37 +test = py36, py37, py38, py39, py310, py311-dev, pypy36, pypy37 qa = mypy, lint cov = py36, coverage From 6088e4cd6823e65481eb6faf94b3557aa318a57a Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Mon, 17 Jan 2022 09:53:04 +0000 Subject: [PATCH 071/105] Run tests with warnings as errors. --- tox.ini | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tox.ini b/tox.ini index 36f9ab5..9284c85 100644 --- a/tox.ini +++ b/tox.ini @@ -141,6 +141,10 @@ package = flake8_github_actions [pytest] addopts = --color yes --durations 25 timeout = 300 +filterwarnings = + error + ignore:SelectableGroups dict interface is deprecated. Use select.:DeprecationWarning:flake8 + ignore:can't resolve package from __spec__ or __package__, falling back on __name__ and __path__:ImportWarning [testenv:lint] basepython = python3.6 From 40f1dedc70653820151b7aee20bdcc1bec0e1acd Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Mon, 17 Jan 2022 09:55:49 +0000 Subject: [PATCH 072/105] Test on PyPy 3.8 --- .github/workflows/python_ci.yml | 3 ++- .github/workflows/python_ci_linux.yml | 3 ++- .github/workflows/python_ci_macos.yml | 3 ++- repo_helper.yml | 1 + tox.ini | 3 ++- 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/workflows/python_ci.yml b/.github/workflows/python_ci.yml index 7f79b3a..3c9d8af 100644 --- a/.github/workflows/python_ci.yml +++ b/.github/workflows/python_ci.yml @@ -21,7 +21,7 @@ jobs: runs-on: "windows-2019" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-alpha.3,pypy-3.6,pypy-3.7' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-alpha.3,pypy-3.6,pypy-3.7,pypy-3.8' strategy: fail-fast: False @@ -35,6 +35,7 @@ jobs: - {python-version: "3.11.0-alpha.3", testenvs: "py311-dev,build", experimental: True} - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} + - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: True} steps: - name: Checkout 🛎️ diff --git a/.github/workflows/python_ci_linux.yml b/.github/workflows/python_ci_linux.yml index 7689c38..91e6d11 100644 --- a/.github/workflows/python_ci_linux.yml +++ b/.github/workflows/python_ci_linux.yml @@ -22,7 +22,7 @@ jobs: runs-on: "ubuntu-20.04" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-alpha.3,pypy-3.6,pypy-3.7' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-alpha.3,pypy-3.6,pypy-3.7,pypy-3.8' strategy: fail-fast: False @@ -36,6 +36,7 @@ jobs: - {python-version: "3.11.0-alpha.3", testenvs: "py311-dev,build", experimental: True} - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} + - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: True} steps: - name: Checkout 🛎️ diff --git a/.github/workflows/python_ci_macos.yml b/.github/workflows/python_ci_macos.yml index eaa4f46..66d826a 100644 --- a/.github/workflows/python_ci_macos.yml +++ b/.github/workflows/python_ci_macos.yml @@ -21,7 +21,7 @@ jobs: runs-on: "macos-latest" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-alpha.3,pypy-3.7' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-alpha.3,pypy-3.7,pypy-3.8' strategy: fail-fast: False @@ -34,6 +34,7 @@ jobs: - {python-version: "3.10", testenvs: "py310,build", experimental: False} - {python-version: "3.11.0-alpha.3", testenvs: "py311-dev,build", experimental: True} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} + - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: True} steps: - name: Checkout 🛎️ diff --git a/repo_helper.yml b/repo_helper.yml index b01b4f2..1667385 100644 --- a/repo_helper.yml +++ b/repo_helper.yml @@ -26,6 +26,7 @@ python_versions: - 3.11-dev - pypy36 - pypy37 + - pypy38 additional_ignore: - action.py diff --git a/tox.ini b/tox.ini index 9284c85..59b94c0 100644 --- a/tox.ini +++ b/tox.ini @@ -24,6 +24,7 @@ envlist = py311-dev pypy36 pypy37 + pypy38 mypy build skip_missing_interpreters = True @@ -34,7 +35,7 @@ requires = tox-pip-version>=0.0.7 [envlists] -test = py36, py37, py38, py39, py310, py311-dev, pypy36, pypy37 +test = py36, py37, py38, py39, py310, py311-dev, pypy36, pypy37, pypy38 qa = mypy, lint cov = py36, coverage From 2afccf40bff11658dee844f3f465cf5a76c51dcc Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Fri, 4 Feb 2022 15:39:57 +0000 Subject: [PATCH 073/105] Update flake8 and dep_checker config. --- pyproject.toml | 3 +++ tox.ini | 30 +++++++++++------------------- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 3dc5cd1..98fff8c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,6 +49,9 @@ show_error_codes = true [tool.snippet-fmt] directives = [ "code-block",] +[tool.dep_checker] +allowed_unused = [ "flake8",] + [project.entry-points."flake8.report"] github = "flake8_github_actions:GitHubFormatter" diff --git a/tox.ini b/tox.ini index 59b94c0..9fe9afb 100644 --- a/tox.ini +++ b/tox.ini @@ -153,33 +153,25 @@ changedir = {toxinidir} ignore_errors = True skip_install = False deps = - flake8 >=3.8.2 - flake8-2020 >= 1.6.0 + flake8>=3.8.2 + flake8-2020>=1.6.0 flake8-builtins>=1.5.3 flake8-docstrings>=1.5.0 flake8-dunder-all>=0.1.1 + flake8-encodings>=0.1.0 flake8-github-actions>=0.1.0 + flake8-noqa>=1.1.0 flake8-pyi>=20.10.0 flake8-pytest-style>=1.3.0 + flake8-quotes>=3.3.0 + flake8-slots>=0.1.0 flake8-sphinx-links>=0.0.4 flake8-strftime>=0.1.1 flake8-typing-imports>=1.10.0 - flake8-encodings>=0.1.0 - flake8-slots>=0.1.0 - git+https://github.com/PyCQA/pydocstyle@5118faa7173b0e5bbc230c4adf628758e13605bf - git+https://github.com/domdfcoding/flake8-quotes.git - git+https://github.com/domdfcoding/flake8-rst-docstrings.git git+https://github.com/domdfcoding/flake8-rst-docstrings-sphinx.git + git+https://github.com/domdfcoding/flake8-rst-docstrings.git + git+https://github.com/python-formate/flake8-unused-arguments.git@magic-methods + pydocstyle>=6.0.0 pygments>=2.7.1 -commands = python3 -m flake8_rst_docstrings_sphinx flake8_github_actions tests --allow-toolbox --extend-exclude bad_code.py {posargs} - -[gh-actions] -python = - 3.6: py36, build, mypy - 3.7: py37, build - 3.8: py38, build - 3.9: py39, build - -[dep_checker] -allowed_unused = - flake8 + importlib_metadata<4.5.0; python_version<'3.8' +commands = python3 -m flake8_rst_docstrings_sphinx flake8_github_actions tests --allow-toolbox --extend-exclude bad_code.py {posargs} {posargs} From b86e9a839ed36b87e3a26c4ce3dfa71b089eeec4 Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Fri, 4 Feb 2022 16:39:01 +0000 Subject: [PATCH 074/105] [repo-helper] Configuration Update (#38) * Updated files with 'repo_helper'. * Updated files with 'repo_helper'. Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .github/milestones.py | 28 +++++++++++++++++++++++++++ .github/workflows/python_ci.yml | 5 +++-- .github/workflows/python_ci_linux.yml | 19 +++++++++++++----- .github/workflows/python_ci_macos.yml | 5 +++-- .pre-commit-config.yaml | 4 ++-- tox.ini | 3 +-- 6 files changed, 51 insertions(+), 13 deletions(-) create mode 100755 .github/milestones.py diff --git a/.github/milestones.py b/.github/milestones.py new file mode 100755 index 0000000..5e868dc --- /dev/null +++ b/.github/milestones.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python + +# stdlib +import os +import sys + +# 3rd party +from github3 import GitHub +from github3.repos import Repository +from packaging.version import InvalidVersion, Version + +latest_tag = os.environ["GITHUB_REF_NAME"] + +try: + current_version = Version(latest_tag) +except InvalidVersion: + sys.exit() + +gh: GitHub = GitHub(token=os.environ["GITHUB_TOKEN"]) +repo: Repository = gh.repository(*os.environ["GITHUB_REPOSITORY"].split('/', 1)) + +for milestone in repo.milestones(state="open"): + try: + milestone_version = Version(milestone.title) + except InvalidVersion: + continue + if milestone_version == current_version: + sys.exit(not milestone.update(state="closed")) diff --git a/.github/workflows/python_ci.yml b/.github/workflows/python_ci.yml index 3c9d8af..bb2372c 100644 --- a/.github/workflows/python_ci.yml +++ b/.github/workflows/python_ci.yml @@ -13,6 +13,7 @@ on: permissions: actions: write + issues: write contents: read jobs: @@ -21,7 +22,7 @@ jobs: runs-on: "windows-2019" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-alpha.3,pypy-3.6,pypy-3.7,pypy-3.8' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-alpha.5,pypy-3.6,pypy-3.7,pypy-3.8' strategy: fail-fast: False @@ -32,7 +33,7 @@ jobs: - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - {python-version: "3.10", testenvs: "py310,build", experimental: False} - - {python-version: "3.11.0-alpha.3", testenvs: "py311-dev,build", experimental: True} + - {python-version: "3.11.0-alpha.5", testenvs: "py311-dev,build", experimental: True} - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: True} diff --git a/.github/workflows/python_ci_linux.yml b/.github/workflows/python_ci_linux.yml index 91e6d11..0f8525e 100644 --- a/.github/workflows/python_ci_linux.yml +++ b/.github/workflows/python_ci_linux.yml @@ -14,6 +14,7 @@ on: permissions: actions: write + issues: write contents: read jobs: @@ -22,7 +23,7 @@ jobs: runs-on: "ubuntu-20.04" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-alpha.3,pypy-3.6,pypy-3.7,pypy-3.8' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-alpha.5,pypy-3.6,pypy-3.7,pypy-3.8' strategy: fail-fast: False @@ -33,7 +34,7 @@ jobs: - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - {python-version: "3.10", testenvs: "py310,build", experimental: False} - - {python-version: "3.11.0-alpha.3", testenvs: "py311-dev,build", experimental: True} + - {python-version: "3.11.0-alpha.5", testenvs: "py311-dev,build", experimental: True} - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: True} @@ -139,21 +140,21 @@ jobs: - name: Setup Python 🐍 uses: "actions/setup-python@v2" + if: startsWith(github.ref, 'refs/tags/') with: python-version: 3.8 - if: startsWith(github.ref, 'refs/tags/') - name: Install dependencies 🔧 + if: startsWith(github.ref, 'refs/tags/') run: | python -m pip install --upgrade pip setuptools wheel python -m pip install --upgrade tox - if: startsWith(github.ref, 'refs/tags/') - name: Build distributions 📦 + if: startsWith(github.ref, 'refs/tags/') run: | tox -e build - if: startsWith(github.ref, 'refs/tags/') - name: Upload distribution to PyPI 🚀 if: startsWith(github.ref, 'refs/tags/') @@ -162,3 +163,11 @@ jobs: user: __token__ password: ${{ secrets.PYPI_TOKEN }} skip_existing: true + + - name: Close milestone 🚪 + if: startsWith(github.ref, 'refs/tags/') + run: | + python -m pip install --upgrade github3.py packaging + python milestones.py + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/python_ci_macos.yml b/.github/workflows/python_ci_macos.yml index 66d826a..c72ebe9 100644 --- a/.github/workflows/python_ci_macos.yml +++ b/.github/workflows/python_ci_macos.yml @@ -13,6 +13,7 @@ on: permissions: actions: write + issues: write contents: read jobs: @@ -21,7 +22,7 @@ jobs: runs-on: "macos-latest" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-alpha.3,pypy-3.7,pypy-3.8' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-alpha.5,pypy-3.7,pypy-3.8' strategy: fail-fast: False @@ -32,7 +33,7 @@ jobs: - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - {python-version: "3.10", testenvs: "py310,build", experimental: False} - - {python-version: "3.11.0-alpha.3", testenvs: "py311-dev,build", experimental: True} + - {python-version: "3.11.0-alpha.5", testenvs: "py311-dev,build", experimental: True} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: True} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8dbc6c2..20263f9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -40,7 +40,7 @@ repos: - id: bind-requirements - repo: https://github.com/domdfcoding/flake8-dunder-all - rev: v0.1.7 + rev: v0.1.8 hooks: - id: ensure-dunder-all files: ^flake8_github_actions/.*\.py$ @@ -67,7 +67,7 @@ repos: - --keep-runtime-typing - repo: https://github.com/Lucas-C/pre-commit-hooks - rev: v1.1.10 + rev: v1.1.11 hooks: - id: remove-crlf - id: forbid-crlf diff --git a/tox.ini b/tox.ini index 9fe9afb..962fd8b 100644 --- a/tox.ini +++ b/tox.ini @@ -30,9 +30,8 @@ envlist = skip_missing_interpreters = True isolated_build = True requires = - pip>=20.3.3 + pip>=21 tox-envlist>=0.2.1 - tox-pip-version>=0.0.7 [envlists] test = py36, py37, py38, py39, py310, py311-dev, pypy36, pypy37, pypy38 From 6eabcb08c384a284e0a01bc5cfab3f575fa22a3f Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Tue, 22 Mar 2022 11:46:40 +0000 Subject: [PATCH 075/105] [repo-helper] Configuration Update (#39) * Updated files with 'repo_helper'. * Updated files with 'repo_helper'. Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .github/workflows/python_ci.yml | 4 ++-- .github/workflows/python_ci_linux.yml | 6 +++--- .github/workflows/python_ci_macos.yml | 4 ++-- setup.cfg | 10 ---------- 4 files changed, 7 insertions(+), 17 deletions(-) delete mode 100644 setup.cfg diff --git a/.github/workflows/python_ci.yml b/.github/workflows/python_ci.yml index bb2372c..6c6265a 100644 --- a/.github/workflows/python_ci.yml +++ b/.github/workflows/python_ci.yml @@ -22,7 +22,7 @@ jobs: runs-on: "windows-2019" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-alpha.5,pypy-3.6,pypy-3.7,pypy-3.8' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-alpha.6,pypy-3.6,pypy-3.7,pypy-3.8' strategy: fail-fast: False @@ -33,7 +33,7 @@ jobs: - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - {python-version: "3.10", testenvs: "py310,build", experimental: False} - - {python-version: "3.11.0-alpha.5", testenvs: "py311-dev,build", experimental: True} + - {python-version: "3.11.0-alpha.6", testenvs: "py311-dev,build", experimental: True} - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: True} diff --git a/.github/workflows/python_ci_linux.yml b/.github/workflows/python_ci_linux.yml index 0f8525e..95cb579 100644 --- a/.github/workflows/python_ci_linux.yml +++ b/.github/workflows/python_ci_linux.yml @@ -23,7 +23,7 @@ jobs: runs-on: "ubuntu-20.04" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-alpha.5,pypy-3.6,pypy-3.7,pypy-3.8' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-alpha.6,pypy-3.6,pypy-3.7,pypy-3.8' strategy: fail-fast: False @@ -34,7 +34,7 @@ jobs: - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - {python-version: "3.10", testenvs: "py310,build", experimental: False} - - {python-version: "3.11.0-alpha.5", testenvs: "py311-dev,build", experimental: True} + - {python-version: "3.11.0-alpha.6", testenvs: "py311-dev,build", experimental: True} - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: True} @@ -168,6 +168,6 @@ jobs: if: startsWith(github.ref, 'refs/tags/') run: | python -m pip install --upgrade github3.py packaging - python milestones.py + python .github/milestones.py env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/python_ci_macos.yml b/.github/workflows/python_ci_macos.yml index c72ebe9..eaab17c 100644 --- a/.github/workflows/python_ci_macos.yml +++ b/.github/workflows/python_ci_macos.yml @@ -22,7 +22,7 @@ jobs: runs-on: "macos-latest" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-alpha.5,pypy-3.7,pypy-3.8' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-alpha.6,pypy-3.7,pypy-3.8' strategy: fail-fast: False @@ -33,7 +33,7 @@ jobs: - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - {python-version: "3.10", testenvs: "py310,build", experimental: False} - - {python-version: "3.11.0-alpha.5", testenvs: "py311-dev,build", experimental: True} + - {python-version: "3.11.0-alpha.6", testenvs: "py311-dev,build", experimental: True} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: True} diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 1d938dd..0000000 --- a/setup.cfg +++ /dev/null @@ -1,10 +0,0 @@ -# This file is managed by 'repo_helper'. -# You may add new sections, but any changes made to the following sections will be lost: -# * metadata -# * options -# * options.packages.find -# * mypy -# * options.entry_points - -[options.entry_points] -flake8.report = github = flake8_github_actions:GitHubFormatter From 859a1075ee96031b27cdde05d9c654fc1c680c65 Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Sun, 8 May 2022 15:31:13 +0100 Subject: [PATCH 076/105] Updated files with 'repo_helper'. (#40) Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .github/stale.yml | 10 +++++----- .github/workflows/python_ci.yml | 4 ++-- .github/workflows/python_ci_linux.yml | 4 ++-- .github/workflows/python_ci_macos.yml | 4 ++-- .pre-commit-config.yaml | 6 +++--- justfile | 23 +++++++++++++++++++++++ tox.ini | 2 +- 7 files changed, 38 insertions(+), 15 deletions(-) create mode 100644 justfile diff --git a/.github/stale.yml b/.github/stale.yml index e5625b7..bb7fa62 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -7,7 +7,7 @@ daysUntilStale: 180 # Number of days of inactivity before an Issue or Pull Request with the stale label is closed. # Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale. -daysUntilClose: 180 +daysUntilClose: false # Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled) onlyLabels: [] @@ -31,10 +31,10 @@ exemptAssignees: false staleLabel: stale # Comment to post when marking as stale. Set to `false` to disable -markComment: > - This issue has been automatically marked as stale because it has not had - recent activity. It will be closed if no further activity occurs. Thank you - for your contributions. +markComment: false +# This issue has been automatically marked as stale because it has not had +# recent activity. It will be closed if no further activity occurs. Thank you +# for your contributions. # Comment to post when removing the stale label. # unmarkComment: > diff --git a/.github/workflows/python_ci.yml b/.github/workflows/python_ci.yml index 6c6265a..1bcd9a4 100644 --- a/.github/workflows/python_ci.yml +++ b/.github/workflows/python_ci.yml @@ -22,7 +22,7 @@ jobs: runs-on: "windows-2019" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-alpha.6,pypy-3.6,pypy-3.7,pypy-3.8' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-alpha.7,pypy-3.6,pypy-3.7,pypy-3.8' strategy: fail-fast: False @@ -33,7 +33,7 @@ jobs: - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - {python-version: "3.10", testenvs: "py310,build", experimental: False} - - {python-version: "3.11.0-alpha.6", testenvs: "py311-dev,build", experimental: True} + - {python-version: "3.11.0-alpha.7", testenvs: "py311-dev,build", experimental: True} - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: True} diff --git a/.github/workflows/python_ci_linux.yml b/.github/workflows/python_ci_linux.yml index 95cb579..ea6aed8 100644 --- a/.github/workflows/python_ci_linux.yml +++ b/.github/workflows/python_ci_linux.yml @@ -23,7 +23,7 @@ jobs: runs-on: "ubuntu-20.04" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-alpha.6,pypy-3.6,pypy-3.7,pypy-3.8' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-alpha.7,pypy-3.6,pypy-3.7,pypy-3.8' strategy: fail-fast: False @@ -34,7 +34,7 @@ jobs: - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - {python-version: "3.10", testenvs: "py310,build", experimental: False} - - {python-version: "3.11.0-alpha.6", testenvs: "py311-dev,build", experimental: True} + - {python-version: "3.11.0-alpha.7", testenvs: "py311-dev,build", experimental: True} - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: True} diff --git a/.github/workflows/python_ci_macos.yml b/.github/workflows/python_ci_macos.yml index eaab17c..d9eb795 100644 --- a/.github/workflows/python_ci_macos.yml +++ b/.github/workflows/python_ci_macos.yml @@ -22,7 +22,7 @@ jobs: runs-on: "macos-latest" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-alpha.6,pypy-3.7,pypy-3.8' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-alpha.7,pypy-3.7,pypy-3.8' strategy: fail-fast: False @@ -33,7 +33,7 @@ jobs: - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - {python-version: "3.10", testenvs: "py310,build", experimental: False} - - {python-version: "3.11.0-alpha.6", testenvs: "py311-dev,build", experimental: True} + - {python-version: "3.11.0-alpha.7", testenvs: "py311-dev,build", experimental: True} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: True} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 20263f9..1bb075d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,7 +5,7 @@ exclude: ^tests/bad_code.py$ repos: - repo: https://github.com/repo-helper/pyproject-parser - rev: v0.4.2 + rev: v0.4.3 hooks: - id: reformat-pyproject @@ -67,7 +67,7 @@ repos: - --keep-runtime-typing - repo: https://github.com/Lucas-C/pre-commit-hooks - rev: v1.1.11 + rev: v1.1.13 hooks: - id: remove-crlf - id: forbid-crlf @@ -78,7 +78,7 @@ repos: - id: snippet-fmt - repo: https://github.com/python-formate/formate - rev: v0.4.9 + rev: v0.4.10 hooks: - id: formate exclude: ^(doc-source/conf|__pkginfo__|setup)\.(_)?py$ diff --git a/justfile b/justfile new file mode 100644 index 0000000..f3b215e --- /dev/null +++ b/justfile @@ -0,0 +1,23 @@ +default: lint + +pdf-docs: latex-docs + make -C doc-source/build/latex/ + +latex-docs: + SPHINX_BUILDER=latex tox -e docs + +unused-imports: + tox -e lint -- --select F401 + +incomplete-defs: + #!/usr/bin/env bash + tox -e mypy -- --disallow-incomplete-defs --disallow-untyped-defs | grep "Function is missing a .* annotation" || exit 0 + +vdiff: + git diff $(repo-helper show version -q)..HEAD + +bare-ignore: + greppy '# type:? *ignore(?!\[|\w)' -s + +lint: unused-imports incomplete-defs bare-ignore + tox -n qa diff --git a/tox.ini b/tox.ini index 962fd8b..2c633eb 100644 --- a/tox.ini +++ b/tox.ini @@ -64,7 +64,7 @@ basepython = python3.6 ignore_errors = True changedir = {toxinidir} deps = - mypy==0.931 + mypy==0.942 -r{toxinidir}/tests/requirements.txt commands = mypy flake8_github_actions tests {posargs} From f95e08223cdf305e7a80ed7498a559982b165d86 Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Mon, 6 Jun 2022 16:15:48 +0100 Subject: [PATCH 077/105] [repo-helper] Configuration Update (#41) * Updated files with 'repo_helper'. * Updated files with 'repo_helper'. Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .github/workflows/python_ci.yml | 4 ++-- .github/workflows/python_ci_linux.yml | 4 ++-- .github/workflows/python_ci_macos.yml | 4 ++-- .pre-commit-config.yaml | 6 +++--- justfile | 3 +-- tox.ini | 9 +++++++++ 6 files changed, 19 insertions(+), 11 deletions(-) diff --git a/.github/workflows/python_ci.yml b/.github/workflows/python_ci.yml index 1bcd9a4..5609cf9 100644 --- a/.github/workflows/python_ci.yml +++ b/.github/workflows/python_ci.yml @@ -22,7 +22,7 @@ jobs: runs-on: "windows-2019" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-alpha.7,pypy-3.6,pypy-3.7,pypy-3.8' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-beta.3,pypy-3.6,pypy-3.7,pypy-3.8' strategy: fail-fast: False @@ -33,7 +33,7 @@ jobs: - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - {python-version: "3.10", testenvs: "py310,build", experimental: False} - - {python-version: "3.11.0-alpha.7", testenvs: "py311-dev,build", experimental: True} + - {python-version: "3.11.0-beta.3", testenvs: "py311-dev,build", experimental: True} - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: True} diff --git a/.github/workflows/python_ci_linux.yml b/.github/workflows/python_ci_linux.yml index ea6aed8..8ce3f5b 100644 --- a/.github/workflows/python_ci_linux.yml +++ b/.github/workflows/python_ci_linux.yml @@ -23,7 +23,7 @@ jobs: runs-on: "ubuntu-20.04" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-alpha.7,pypy-3.6,pypy-3.7,pypy-3.8' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-beta.3,pypy-3.6,pypy-3.7,pypy-3.8' strategy: fail-fast: False @@ -34,7 +34,7 @@ jobs: - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - {python-version: "3.10", testenvs: "py310,build", experimental: False} - - {python-version: "3.11.0-alpha.7", testenvs: "py311-dev,build", experimental: True} + - {python-version: "3.11.0-beta.3", testenvs: "py311-dev,build", experimental: True} - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: True} diff --git a/.github/workflows/python_ci_macos.yml b/.github/workflows/python_ci_macos.yml index d9eb795..c8d35c5 100644 --- a/.github/workflows/python_ci_macos.yml +++ b/.github/workflows/python_ci_macos.yml @@ -22,7 +22,7 @@ jobs: runs-on: "macos-latest" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-alpha.7,pypy-3.7,pypy-3.8' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-beta.3,pypy-3.7,pypy-3.8' strategy: fail-fast: False @@ -33,7 +33,7 @@ jobs: - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - {python-version: "3.10", testenvs: "py310,build", experimental: False} - - {python-version: "3.11.0-alpha.7", testenvs: "py311-dev,build", experimental: True} + - {python-version: "3.11.0-beta.3", testenvs: "py311-dev,build", experimental: True} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: True} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1bb075d..5bdd2c4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,7 +5,7 @@ exclude: ^tests/bad_code.py$ repos: - repo: https://github.com/repo-helper/pyproject-parser - rev: v0.4.3 + rev: v0.6.1 hooks: - id: reformat-pyproject @@ -40,7 +40,7 @@ repos: - id: bind-requirements - repo: https://github.com/domdfcoding/flake8-dunder-all - rev: v0.1.8 + rev: v0.2.1 hooks: - id: ensure-dunder-all files: ^flake8_github_actions/.*\.py$ @@ -67,7 +67,7 @@ repos: - --keep-runtime-typing - repo: https://github.com/Lucas-C/pre-commit-hooks - rev: v1.1.13 + rev: v1.2.0 hooks: - id: remove-crlf - id: forbid-crlf diff --git a/justfile b/justfile index f3b215e..e8ed871 100644 --- a/justfile +++ b/justfile @@ -10,8 +10,7 @@ unused-imports: tox -e lint -- --select F401 incomplete-defs: - #!/usr/bin/env bash - tox -e mypy -- --disallow-incomplete-defs --disallow-untyped-defs | grep "Function is missing a .* annotation" || exit 0 + tox -e lint -- --select MAN vdiff: git diff $(repo-helper show version -q)..HEAD diff --git a/tox.ini b/tox.ini index 2c633eb..31fa935 100644 --- a/tox.ini +++ b/tox.ini @@ -5,6 +5,7 @@ # * testenv # * testenv:docs # * testenv:build +# * testenv:perflint # * testenv:mypy # * testenv:pyup # * testenv:coverage @@ -59,6 +60,14 @@ commands = twine check dist/*.tar.gz dist/*.whl check-wheel-contents dist/ +[testenv:perflint] +basepython = python3.6 +changedir = {toxinidir} +ignore_errors = True +skip_install = True +deps = perflint +commands = python3 -m perflint flake8_github_actions {posargs} + [testenv:mypy] basepython = python3.6 ignore_errors = True From 15d0282c144c88357476d79ed3330b72688e7113 Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Wed, 3 Aug 2022 07:27:39 +0100 Subject: [PATCH 078/105] Cap flake8 version to <5 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 4163a01..73b78ce 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -flake8>=3.8.4 +flake8<5,>=3.8.4 From 82c1860f4f5bf079c0122f569d72786e38fd8196 Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Tue, 16 Aug 2022 16:03:41 +0000 Subject: [PATCH 079/105] [repo-helper] Configuration Update (#42) * Updated files with 'repo_helper'. * Updated files with 'repo_helper'. * Updated files with 'repo_helper'. Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .github/workflows/mypy.yml | 2 +- .github/workflows/python_ci.yml | 6 +++--- .github/workflows/python_ci_linux.yml | 6 +++--- .github/workflows/python_ci_macos.yml | 6 +++--- .pre-commit-config.yaml | 10 +++++----- tox.ini | 3 ++- 6 files changed, 17 insertions(+), 16 deletions(-) diff --git a/.github/workflows/mypy.yml b/.github/workflows/mypy.yml index 5a7324b..db8ab06 100644 --- a/.github/workflows/mypy.yml +++ b/.github/workflows/mypy.yml @@ -47,7 +47,7 @@ jobs: python -VV python -m site python -m pip install --upgrade pip setuptools wheel - python -m pip install --upgrade tox virtualenv + python -m pip install --upgrade tox virtualenv!=20.16.0 - name: "Run mypy" if: steps.changes.outputs.code == 'true' diff --git a/.github/workflows/python_ci.yml b/.github/workflows/python_ci.yml index 5609cf9..7072755 100644 --- a/.github/workflows/python_ci.yml +++ b/.github/workflows/python_ci.yml @@ -22,7 +22,7 @@ jobs: runs-on: "windows-2019" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-beta.3,pypy-3.6,pypy-3.7,pypy-3.8' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-rc.1,pypy-3.6,pypy-3.7,pypy-3.8' strategy: fail-fast: False @@ -33,7 +33,7 @@ jobs: - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - {python-version: "3.10", testenvs: "py310,build", experimental: False} - - {python-version: "3.11.0-beta.3", testenvs: "py311-dev,build", experimental: True} + - {python-version: "3.11.0-rc.1", testenvs: "py311-dev,build", experimental: True} - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: True} @@ -65,7 +65,7 @@ jobs: python -VV python -m site python -m pip install --upgrade pip setuptools wheel - python -m pip install --upgrade tox virtualenv + python -m pip install --upgrade tox virtualenv!=20.16.0 - name: "Run Tests for Python ${{ matrix.config.python-version }}" if: steps.setup-python.outcome == 'success' diff --git a/.github/workflows/python_ci_linux.yml b/.github/workflows/python_ci_linux.yml index 8ce3f5b..57bbe65 100644 --- a/.github/workflows/python_ci_linux.yml +++ b/.github/workflows/python_ci_linux.yml @@ -23,7 +23,7 @@ jobs: runs-on: "ubuntu-20.04" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-beta.3,pypy-3.6,pypy-3.7,pypy-3.8' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-rc.1,pypy-3.6,pypy-3.7,pypy-3.8' strategy: fail-fast: False @@ -34,7 +34,7 @@ jobs: - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - {python-version: "3.10", testenvs: "py310,build", experimental: False} - - {python-version: "3.11.0-beta.3", testenvs: "py311-dev,build", experimental: True} + - {python-version: "3.11.0-rc.1", testenvs: "py311-dev,build", experimental: True} - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: True} @@ -66,7 +66,7 @@ jobs: python -VV python -m site python -m pip install --upgrade pip setuptools wheel - python -m pip install --upgrade tox virtualenv + python -m pip install --upgrade tox virtualenv!=20.16.0 python -m pip install --upgrade coverage_pyver_pragma - name: "Run Tests for Python ${{ matrix.config.python-version }}" diff --git a/.github/workflows/python_ci_macos.yml b/.github/workflows/python_ci_macos.yml index c8d35c5..95e1eaf 100644 --- a/.github/workflows/python_ci_macos.yml +++ b/.github/workflows/python_ci_macos.yml @@ -22,7 +22,7 @@ jobs: runs-on: "macos-latest" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-beta.3,pypy-3.7,pypy-3.8' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-rc.1,pypy-3.7,pypy-3.8' strategy: fail-fast: False @@ -33,7 +33,7 @@ jobs: - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - {python-version: "3.10", testenvs: "py310,build", experimental: False} - - {python-version: "3.11.0-beta.3", testenvs: "py311-dev,build", experimental: True} + - {python-version: "3.11.0-rc.1", testenvs: "py311-dev,build", experimental: True} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: True} @@ -64,7 +64,7 @@ jobs: python -VV python -m site python -m pip install --upgrade pip setuptools wheel - python -m pip install --upgrade tox virtualenv + python -m pip install --upgrade tox virtualenv!=20.16.0 - name: "Run Tests for Python ${{ matrix.config.python-version }}" if: steps.setup-python.outcome == 'success' diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5bdd2c4..90cf32f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,7 +5,7 @@ exclude: ^tests/bad_code.py$ repos: - repo: https://github.com/repo-helper/pyproject-parser - rev: v0.6.1 + rev: v0.7.0 hooks: - id: reformat-pyproject @@ -30,7 +30,7 @@ repos: - id: end-of-file-fixer - repo: https://github.com/domdfcoding/pre-commit-hooks - rev: v0.3.0 + rev: v0.4.0 hooks: - id: requirements-txt-sorter args: @@ -40,13 +40,13 @@ repos: - id: bind-requirements - repo: https://github.com/domdfcoding/flake8-dunder-all - rev: v0.2.1 + rev: v0.2.2 hooks: - id: ensure-dunder-all files: ^flake8_github_actions/.*\.py$ - repo: https://github.com/domdfcoding/flake2lint - rev: v0.4.1 + rev: v0.4.2 hooks: - id: flake2lint @@ -84,7 +84,7 @@ repos: exclude: ^(doc-source/conf|__pkginfo__|setup)\.(_)?py$ - repo: https://github.com/domdfcoding/dep_checker - rev: v0.6.2 + rev: v0.7.0 hooks: - id: dep_checker args: diff --git a/tox.ini b/tox.ini index 31fa935..d33fdfd 100644 --- a/tox.ini +++ b/tox.ini @@ -31,8 +31,9 @@ envlist = skip_missing_interpreters = True isolated_build = True requires = - pip>=21 + pip>=21,!=22.2 tox-envlist>=0.2.1 + virtualenv!=20.16.0 [envlists] test = py36, py37, py38, py39, py310, py311-dev, pypy36, pypy37, pypy38 From cdcc446b393557ba431b4c23736cc087a1989537 Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Sat, 3 Sep 2022 08:37:12 +0100 Subject: [PATCH 080/105] Updated files with 'repo_helper'. (#44) Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .github/workflows/flake8.yml | 2 +- .pre-commit-config.yaml | 2 +- README.rst | 4 ++-- tox.ini | 2 ++ 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/flake8.yml b/.github/workflows/flake8.yml index 84e9436..4b47d24 100644 --- a/.github/workflows/flake8.yml +++ b/.github/workflows/flake8.yml @@ -16,7 +16,7 @@ permissions: jobs: Run: name: "Flake8" - runs-on: "ubuntu-18.04" + runs-on: "ubuntu-20.04" steps: - name: Checkout 🛎️ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 90cf32f..aba907e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -67,7 +67,7 @@ repos: - --keep-runtime-typing - repo: https://github.com/Lucas-C/pre-commit-hooks - rev: v1.2.0 + rev: v1.3.1 hooks: - id: remove-crlf - id: forbid-crlf diff --git a/README.rst b/README.rst index e80399a..3883c8b 100644 --- a/README.rst +++ b/README.rst @@ -46,8 +46,8 @@ flake8-github-actions :target: https://github.com/python-formate/flake8-github-actions/actions?query=workflow%3A%22mypy%22 :alt: mypy status -.. |requires| image:: https://dependency-dash.herokuapp.com/github/python-formate/flake8-github-actions/badge.svg - :target: https://dependency-dash.herokuapp.com/github/python-formate/flake8-github-actions/ +.. |requires| image:: https://dependency-dash.repo-helper.uk/github/python-formate/flake8-github-actions/badge.svg + :target: https://dependency-dash.repo-helper.uk/github/python-formate/flake8-github-actions/ :alt: Requirements Status .. |coveralls| image:: https://img.shields.io/coveralls/github/python-formate/flake8-github-actions/master?logo=coveralls diff --git a/tox.ini b/tox.ini index d33fdfd..8fa2f09 100644 --- a/tox.ini +++ b/tox.ini @@ -44,6 +44,7 @@ cov = py36, coverage setenv = PYTHONDEVMODE=1 PIP_DISABLE_PIP_VERSION_CHECK=1 + SETUPTOOLS_USE_DISTUTILS=stdlib deps = -r{toxinidir}/tests/requirements.txt commands = python --version @@ -95,6 +96,7 @@ passenv = COV_PYTHON_VERSION COV_PLATFORM COV_PYTHON_IMPLEMENTATION + * changedir = {toxinidir} deps = coverage>=5 From 6b24152a21a92676eb32b2ecc67558f3ead926ee Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Tue, 1 Nov 2022 10:35:33 +0000 Subject: [PATCH 081/105] Update flake8 config. --- .github/workflows/flake8.yml | 2 +- tox.ini | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/flake8.yml b/.github/workflows/flake8.yml index 4b47d24..7633ccd 100644 --- a/.github/workflows/flake8.yml +++ b/.github/workflows/flake8.yml @@ -35,7 +35,7 @@ jobs: if: steps.changes.outputs.code == 'true' uses: "actions/setup-python@v2" with: - python-version: "3.6" + python-version: "3.8" - name: Install dependencies 🔧 if: steps.changes.outputs.code == 'true' diff --git a/tox.ini b/tox.ini index 8fa2f09..718f8a4 100644 --- a/tox.ini +++ b/tox.ini @@ -159,20 +159,20 @@ filterwarnings = ignore:can't resolve package from __spec__ or __package__, falling back on __name__ and __path__:ImportWarning [testenv:lint] -basepython = python3.6 +basepython = python3.8 changedir = {toxinidir} ignore_errors = True skip_install = False deps = - flake8>=3.8.2 + flake8>=3.8.2,<5 flake8-2020>=1.6.0 flake8-builtins>=1.5.3 flake8-docstrings>=1.5.0 flake8-dunder-all>=0.1.1 flake8-encodings>=0.1.0 flake8-github-actions>=0.1.0 - flake8-noqa>=1.1.0 - flake8-pyi>=20.10.0 + flake8-noqa>=1.1.0,<=1.2.2 + flake8-pyi>=20.10.0,<=22.8.0 flake8-pytest-style>=1.3.0 flake8-quotes>=3.3.0 flake8-slots>=0.1.0 @@ -182,7 +182,8 @@ deps = git+https://github.com/domdfcoding/flake8-rst-docstrings-sphinx.git git+https://github.com/domdfcoding/flake8-rst-docstrings.git git+https://github.com/python-formate/flake8-unused-arguments.git@magic-methods + git+https://github.com/python-formate/flake8-missing-annotations.git pydocstyle>=6.0.0 pygments>=2.7.1 importlib_metadata<4.5.0; python_version<'3.8' -commands = python3 -m flake8_rst_docstrings_sphinx flake8_github_actions tests --allow-toolbox --extend-exclude bad_code.py {posargs} {posargs} +commands = python3 -m flake8_rst_docstrings_sphinx flake8_github_actions tests --allow-toolbox --extend-exclude bad_code.py {posargs} From 68f4e8dad9bbfd7cb527a490b29f5bc8371e3b59 Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Tue, 1 Nov 2022 11:23:09 +0000 Subject: [PATCH 082/105] Updated files with 'repo_helper'. (#45) Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .github/workflows/flake8.yml | 4 ++-- .github/workflows/mypy.yml | 6 +++--- .github/workflows/python_ci.yml | 8 ++++---- .github/workflows/python_ci_linux.yml | 16 ++++++++-------- .github/workflows/python_ci_macos.yml | 8 ++++---- .pre-commit-config.yaml | 3 +++ pyproject.toml | 2 +- tox.ini | 12 ++++++------ 8 files changed, 31 insertions(+), 28 deletions(-) diff --git a/.github/workflows/flake8.yml b/.github/workflows/flake8.yml index 7633ccd..2761d45 100644 --- a/.github/workflows/flake8.yml +++ b/.github/workflows/flake8.yml @@ -20,7 +20,7 @@ jobs: steps: - name: Checkout 🛎️ - uses: "actions/checkout@v2" + uses: "actions/checkout@v3" - name: Check for changed files uses: dorny/paths-filter@v2 @@ -33,7 +33,7 @@ jobs: - name: Setup Python 🐍 if: steps.changes.outputs.code == 'true' - uses: "actions/setup-python@v2" + uses: "actions/setup-python@v4" with: python-version: "3.8" diff --git a/.github/workflows/mypy.yml b/.github/workflows/mypy.yml index db8ab06..6caf60d 100644 --- a/.github/workflows/mypy.yml +++ b/.github/workflows/mypy.yml @@ -25,7 +25,7 @@ jobs: steps: - name: Checkout 🛎️ - uses: "actions/checkout@v2" + uses: "actions/checkout@v3" - name: Check for changed files uses: dorny/paths-filter@v2 @@ -38,9 +38,9 @@ jobs: - name: Setup Python 🐍 if: steps.changes.outputs.code == 'true' - uses: "actions/setup-python@v2" + uses: "actions/setup-python@v4" with: - python-version: "3.6" + python-version: "3.8" - name: Install dependencies 🔧 run: | diff --git a/.github/workflows/python_ci.yml b/.github/workflows/python_ci.yml index 7072755..0f01a07 100644 --- a/.github/workflows/python_ci.yml +++ b/.github/workflows/python_ci.yml @@ -22,7 +22,7 @@ jobs: runs-on: "windows-2019" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-rc.1,pypy-3.6,pypy-3.7,pypy-3.8' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11,pypy-3.6,pypy-3.7,pypy-3.8' strategy: fail-fast: False @@ -33,14 +33,14 @@ jobs: - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - {python-version: "3.10", testenvs: "py310,build", experimental: False} - - {python-version: "3.11.0-rc.1", testenvs: "py311-dev,build", experimental: True} + - {python-version: "3.11", testenvs: "py311-dev,build", experimental: True} - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: True} steps: - name: Checkout 🛎️ - uses: "actions/checkout@v2" + uses: "actions/checkout@v3" - name: Check for changed files if: startsWith(github.ref, 'refs/tags/') != true @@ -55,7 +55,7 @@ jobs: - name: Setup Python 🐍 id: setup-python if: ${{ steps.changes.outputs.code == 'true' || steps.changes.outcome == 'skipped' }} - uses: "actions/setup-python@v2" + uses: "actions/setup-python@v4" with: python-version: "${{ matrix.config.python-version }}" diff --git a/.github/workflows/python_ci_linux.yml b/.github/workflows/python_ci_linux.yml index 57bbe65..5be0dd6 100644 --- a/.github/workflows/python_ci_linux.yml +++ b/.github/workflows/python_ci_linux.yml @@ -23,7 +23,7 @@ jobs: runs-on: "ubuntu-20.04" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-rc.1,pypy-3.6,pypy-3.7,pypy-3.8' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11,pypy-3.6,pypy-3.7,pypy-3.8' strategy: fail-fast: False @@ -34,14 +34,14 @@ jobs: - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - {python-version: "3.10", testenvs: "py310,build", experimental: False} - - {python-version: "3.11.0-rc.1", testenvs: "py311-dev,build", experimental: True} + - {python-version: "3.11", testenvs: "py311-dev,build", experimental: True} - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: True} steps: - name: Checkout 🛎️ - uses: "actions/checkout@v2" + uses: "actions/checkout@v3" - name: Check for changed files if: startsWith(github.ref, 'refs/tags/') != true @@ -56,7 +56,7 @@ jobs: - name: Setup Python 🐍 id: setup-python if: ${{ steps.changes.outputs.code == 'true' || steps.changes.outcome == 'skipped' }} - uses: "actions/setup-python@v2" + uses: "actions/setup-python@v4" with: python-version: "${{ matrix.config.python-version }}" @@ -86,10 +86,10 @@ jobs: runs-on: "ubuntu-20.04" steps: - name: Checkout 🛎️ - uses: "actions/checkout@v2" + uses: "actions/checkout@v3" - name: Setup Python 🐍 - uses: "actions/setup-python@v2" + uses: "actions/setup-python@v4" with: python-version: 3.8 @@ -135,11 +135,11 @@ jobs: runs-on: "ubuntu-20.04" steps: - name: Checkout 🛎️ - uses: "actions/checkout@v2" + uses: "actions/checkout@v3" if: startsWith(github.ref, 'refs/tags/') - name: Setup Python 🐍 - uses: "actions/setup-python@v2" + uses: "actions/setup-python@v4" if: startsWith(github.ref, 'refs/tags/') with: python-version: 3.8 diff --git a/.github/workflows/python_ci_macos.yml b/.github/workflows/python_ci_macos.yml index 95e1eaf..ef9f7ce 100644 --- a/.github/workflows/python_ci_macos.yml +++ b/.github/workflows/python_ci_macos.yml @@ -22,7 +22,7 @@ jobs: runs-on: "macos-latest" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11.0-rc.1,pypy-3.7,pypy-3.8' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11,pypy-3.7,pypy-3.8' strategy: fail-fast: False @@ -33,13 +33,13 @@ jobs: - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - {python-version: "3.10", testenvs: "py310,build", experimental: False} - - {python-version: "3.11.0-rc.1", testenvs: "py311-dev,build", experimental: True} + - {python-version: "3.11", testenvs: "py311-dev,build", experimental: True} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: True} steps: - name: Checkout 🛎️ - uses: "actions/checkout@v2" + uses: "actions/checkout@v3" - name: Check for changed files if: startsWith(github.ref, 'refs/tags/') != true @@ -54,7 +54,7 @@ jobs: - name: Setup Python 🐍 id: setup-python if: ${{ steps.changes.outputs.code == 'true' || steps.changes.outcome == 'skipped' }} - uses: "actions/setup-python@v2" + uses: "actions/setup-python@v4" with: python-version: "${{ matrix.config.python-version }}" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index aba907e..46e22b1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,6 +3,9 @@ exclude: ^tests/bad_code.py$ +ci: + autoupdate_schedule: quarterly + repos: - repo: https://github.com/repo-helper/pyproject-parser rev: v0.7.0 diff --git a/pyproject.toml b/pyproject.toml index 98fff8c..ab6ac32 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,7 +39,7 @@ license-key = "MIT" package = "flake8_github_actions" [tool.mypy] -python_version = "3.6" +python_version = "3.8" namespace_packages = true check_untyped_defs = true warn_unused_ignores = true diff --git a/tox.ini b/tox.ini index 718f8a4..938b2e5 100644 --- a/tox.ini +++ b/tox.ini @@ -38,7 +38,7 @@ requires = [envlists] test = py36, py37, py38, py39, py310, py311-dev, pypy36, pypy37, pypy38 qa = mypy, lint -cov = py36, coverage +cov = py38, coverage [testenv] setenv = @@ -63,7 +63,7 @@ commands = check-wheel-contents dist/ [testenv:perflint] -basepython = python3.6 +basepython = python3.8 changedir = {toxinidir} ignore_errors = True skip_install = True @@ -71,16 +71,16 @@ deps = perflint commands = python3 -m perflint flake8_github_actions {posargs} [testenv:mypy] -basepython = python3.6 +basepython = python3.8 ignore_errors = True changedir = {toxinidir} deps = - mypy==0.942 + mypy==0.971 -r{toxinidir}/tests/requirements.txt commands = mypy flake8_github_actions tests {posargs} [testenv:pyup] -basepython = python3.6 +basepython = python3.8 skip_install = True ignore_errors = True changedir = {toxinidir} @@ -88,7 +88,7 @@ deps = pyupgrade-directories commands = pyup_dirs flake8_github_actions tests --py36-plus --recursive [testenv:coverage] -basepython = python3.6 +basepython = python3.8 skip_install = True ignore_errors = True whitelist_externals = /bin/bash From 082290a1484709e9cd70017bafb27797e96cbe73 Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Tue, 1 Nov 2022 13:46:48 +0000 Subject: [PATCH 083/105] Test on PyPy 3.9 --- .github/workflows/python_ci.yml | 5 +++-- .github/workflows/python_ci_linux.yml | 5 +++-- .github/workflows/python_ci_macos.yml | 5 +++-- pyproject.toml | 2 +- repo_helper.yml | 4 +++- tox.ini | 5 +++-- 6 files changed, 16 insertions(+), 10 deletions(-) diff --git a/.github/workflows/python_ci.yml b/.github/workflows/python_ci.yml index 0f01a07..fe4f85e 100644 --- a/.github/workflows/python_ci.yml +++ b/.github/workflows/python_ci.yml @@ -22,7 +22,7 @@ jobs: runs-on: "windows-2019" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11,pypy-3.6,pypy-3.7,pypy-3.8' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11,pypy-3.6,pypy-3.7,pypy-3.8,pypy-3.9' strategy: fail-fast: False @@ -33,10 +33,11 @@ jobs: - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - {python-version: "3.10", testenvs: "py310,build", experimental: False} - - {python-version: "3.11", testenvs: "py311-dev,build", experimental: True} + - {python-version: "3.11", testenvs: "py311,build", experimental: False} - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: True} + - {python-version: "pypy-3.9", testenvs: "pypy39", experimental: True} steps: - name: Checkout 🛎️ diff --git a/.github/workflows/python_ci_linux.yml b/.github/workflows/python_ci_linux.yml index 5be0dd6..ac30f10 100644 --- a/.github/workflows/python_ci_linux.yml +++ b/.github/workflows/python_ci_linux.yml @@ -23,7 +23,7 @@ jobs: runs-on: "ubuntu-20.04" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11,pypy-3.6,pypy-3.7,pypy-3.8' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11,pypy-3.6,pypy-3.7,pypy-3.8,pypy-3.9' strategy: fail-fast: False @@ -34,10 +34,11 @@ jobs: - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - {python-version: "3.10", testenvs: "py310,build", experimental: False} - - {python-version: "3.11", testenvs: "py311-dev,build", experimental: True} + - {python-version: "3.11", testenvs: "py311,build", experimental: False} - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: True} + - {python-version: "pypy-3.9", testenvs: "pypy39", experimental: True} steps: - name: Checkout 🛎️ diff --git a/.github/workflows/python_ci_macos.yml b/.github/workflows/python_ci_macos.yml index ef9f7ce..ba39bd3 100644 --- a/.github/workflows/python_ci_macos.yml +++ b/.github/workflows/python_ci_macos.yml @@ -22,7 +22,7 @@ jobs: runs-on: "macos-latest" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11,pypy-3.7,pypy-3.8' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11,pypy-3.7,pypy-3.8,pypy-3.9' strategy: fail-fast: False @@ -33,9 +33,10 @@ jobs: - {python-version: "3.8", testenvs: "py38,build", experimental: False} - {python-version: "3.9", testenvs: "py39,build", experimental: False} - {python-version: "3.10", testenvs: "py310,build", experimental: False} - - {python-version: "3.11", testenvs: "py311-dev,build", experimental: True} + - {python-version: "3.11", testenvs: "py311,build", experimental: False} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: True} + - {python-version: "pypy-3.9", testenvs: "pypy39", experimental: True} steps: - name: Checkout 🛎️ diff --git a/pyproject.toml b/pyproject.toml index ab6ac32..895c05e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,7 +32,7 @@ base-classifiers = [ "Intended Audience :: Developers", "Typing :: Typed", ] -python-versions = [ "3.6", "3.7", "3.8", "3.9", "3.10",] +python-versions = [ "3.6", "3.7", "3.8", "3.9", "3.10", "3.11",] python-implementations = [ "CPython", "PyPy",] platforms = [ "Windows", "macOS", "Linux",] license-key = "MIT" diff --git a/repo_helper.yml b/repo_helper.yml index 1667385..6a39287 100644 --- a/repo_helper.yml +++ b/repo_helper.yml @@ -23,10 +23,12 @@ python_versions: - '3.8' - '3.9' - "3.10" - - 3.11-dev + - "3.11" +# - 3.12-dev # Flake8<5 incompatible - pypy36 - pypy37 - pypy38 + - pypy39 additional_ignore: - action.py diff --git a/tox.ini b/tox.ini index 938b2e5..e3235c7 100644 --- a/tox.ini +++ b/tox.ini @@ -22,10 +22,11 @@ envlist = py38 py39 py310 - py311-dev + py311 pypy36 pypy37 pypy38 + pypy39 mypy build skip_missing_interpreters = True @@ -36,7 +37,7 @@ requires = virtualenv!=20.16.0 [envlists] -test = py36, py37, py38, py39, py310, py311-dev, pypy36, pypy37, pypy38 +test = py36, py37, py38, py39, py310, py311, pypy36, pypy37, pypy38, pypy39 qa = mypy, lint cov = py38, coverage From 032f026a11ff90a2f26df32653f135366c3eda9e Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Fri, 9 Dec 2022 18:03:48 +0000 Subject: [PATCH 084/105] [repo-helper] Configuration Update (#47) * Updated files with 'repo_helper'. * Updated files with 'repo_helper'. Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .github/workflows/flake8.yml | 2 +- .github/workflows/mypy.yml | 2 +- .github/workflows/python_ci.yml | 4 ++-- .github/workflows/python_ci_linux.yml | 10 +++++----- .github/workflows/python_ci_macos.yml | 4 ++-- tox.ini | 1 + 6 files changed, 12 insertions(+), 11 deletions(-) diff --git a/.github/workflows/flake8.yml b/.github/workflows/flake8.yml index 2761d45..8221173 100644 --- a/.github/workflows/flake8.yml +++ b/.github/workflows/flake8.yml @@ -43,7 +43,7 @@ jobs: python -VV python -m site python -m pip install --upgrade pip setuptools wheel - python -m pip install tox + python -m pip install tox~=3.0 - name: "Run Flake8" if: steps.changes.outputs.code == 'true' diff --git a/.github/workflows/mypy.yml b/.github/workflows/mypy.yml index 6caf60d..9b28b5f 100644 --- a/.github/workflows/mypy.yml +++ b/.github/workflows/mypy.yml @@ -47,7 +47,7 @@ jobs: python -VV python -m site python -m pip install --upgrade pip setuptools wheel - python -m pip install --upgrade tox virtualenv!=20.16.0 + python -m pip install --upgrade tox~=3.0 virtualenv!=20.16.0 - name: "Run mypy" if: steps.changes.outputs.code == 'true' diff --git a/.github/workflows/python_ci.yml b/.github/workflows/python_ci.yml index fe4f85e..caa3535 100644 --- a/.github/workflows/python_ci.yml +++ b/.github/workflows/python_ci.yml @@ -66,14 +66,14 @@ jobs: python -VV python -m site python -m pip install --upgrade pip setuptools wheel - python -m pip install --upgrade tox virtualenv!=20.16.0 + python -m pip install --upgrade tox~=3.0 virtualenv!=20.16.0 - name: "Run Tests for Python ${{ matrix.config.python-version }}" if: steps.setup-python.outcome == 'success' run: python -m tox -e "${{ matrix.config.testenvs }}" -s false - name: "Upload Coverage 🚀" - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 if: ${{ always() && steps.setup-python.outcome == 'success' }} with: name: "coverage-${{ matrix.config.python-version }}" diff --git a/.github/workflows/python_ci_linux.yml b/.github/workflows/python_ci_linux.yml index ac30f10..de73765 100644 --- a/.github/workflows/python_ci_linux.yml +++ b/.github/workflows/python_ci_linux.yml @@ -67,7 +67,7 @@ jobs: python -VV python -m site python -m pip install --upgrade pip setuptools wheel - python -m pip install --upgrade tox virtualenv!=20.16.0 + python -m pip install --upgrade tox~=3.0 virtualenv!=20.16.0 python -m pip install --upgrade coverage_pyver_pragma - name: "Run Tests for Python ${{ matrix.config.python-version }}" @@ -75,7 +75,7 @@ jobs: run: python -m tox -e "${{ matrix.config.testenvs }}" -s false - name: "Upload Coverage 🚀" - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 if: ${{ always() && steps.setup-python.outcome == 'success' }} with: name: "coverage-${{ matrix.config.python-version }}" @@ -100,7 +100,7 @@ jobs: python -m pip install --upgrade "coveralls>=3.0.0" coverage_pyver_pragma - name: "Download Coverage 🪂" - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: path: coverage @@ -118,7 +118,7 @@ jobs: - name: "Upload Combined Coverage Artefact 🚀" if: ${{ steps.show.outcome != 'failure' }} - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: "combined-coverage" path: .coverage @@ -149,7 +149,7 @@ jobs: if: startsWith(github.ref, 'refs/tags/') run: | python -m pip install --upgrade pip setuptools wheel - python -m pip install --upgrade tox + python -m pip install --upgrade tox~=3.0 - name: Build distributions 📦 if: startsWith(github.ref, 'refs/tags/') diff --git a/.github/workflows/python_ci_macos.yml b/.github/workflows/python_ci_macos.yml index ba39bd3..ba341e8 100644 --- a/.github/workflows/python_ci_macos.yml +++ b/.github/workflows/python_ci_macos.yml @@ -65,14 +65,14 @@ jobs: python -VV python -m site python -m pip install --upgrade pip setuptools wheel - python -m pip install --upgrade tox virtualenv!=20.16.0 + python -m pip install --upgrade tox~=3.0 virtualenv!=20.16.0 - name: "Run Tests for Python ${{ matrix.config.python-version }}" if: steps.setup-python.outcome == 'success' run: python -m tox -e "${{ matrix.config.testenvs }}" -s false - name: "Upload Coverage 🚀" - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 if: ${{ always() && steps.setup-python.outcome == 'success' }} with: name: "coverage-${{ matrix.config.python-version }}" diff --git a/tox.ini b/tox.ini index e3235c7..1b0e5ad 100644 --- a/tox.ini +++ b/tox.ini @@ -34,6 +34,7 @@ isolated_build = True requires = pip>=21,!=22.2 tox-envlist>=0.2.1 + tox~=3.0 virtualenv!=20.16.0 [envlists] From c5865936eb36cb9a509affc450d80edc84d340f6 Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Tue, 7 Feb 2023 16:50:47 +0000 Subject: [PATCH 085/105] Lint --- flake8_github_actions/__init__.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/flake8_github_actions/__init__.py b/flake8_github_actions/__init__.py index c6f2a45..6bb2be0 100644 --- a/flake8_github_actions/__init__.py +++ b/flake8_github_actions/__init__.py @@ -26,6 +26,9 @@ # OR OTHER DEALINGS IN THE SOFTWARE. # +# stdlib +from typing import Any + # 3rd party from flake8.formatting.base import BaseFormatter # type: ignore @@ -35,7 +38,7 @@ __version__: str = "0.1.1" __email__: str = "dominic@davis-foster.co.uk" -__all__ = ["GitHubFormatter"] +__all__ = ("GitHubFormatter", ) class GitHubFormatter(BaseFormatter): @@ -43,31 +46,33 @@ class GitHubFormatter(BaseFormatter): Custom Flake8 formatter for GitHub actions. """ - def write_line(self, line): + reported_errors_count: int + + def write_line(self, line: str) -> None: """ Override write for convenience. """ self.write(line, None) - def start(self): # noqa: D102 + def start(self) -> None: # noqa: D102 super().start() self.files_reported_count = 0 - def beginning(self, filename): + def beginning(self, filename: Any) -> None: """ We're starting a new file. """ self.reported_errors_count = 0 - def finished(self, filename): + def finished(self, filename: Any) -> None: """ We've finished processing a file. """ self.files_reported_count += 1 - def format(self, violation): # noqa: A003 # pylint: disable=redefined-builtin + def format(self, violation) -> None: # noqa: A003 # pylint: disable=redefined-builtin """ Format a violation. """ From de15cdc005af608bfa0f6d85b14f91c2388d6ac0 Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Thu, 18 May 2023 16:25:39 +0100 Subject: [PATCH 086/105] Updated files with 'repo_helper'. (#48) Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 6 +++--- README.rst | 2 +- tox.ini | 10 ++++++++++ 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 46e22b1..3618176 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -54,7 +54,7 @@ repos: - id: flake2lint - repo: https://github.com/pre-commit/pygrep-hooks - rev: v1.9.0 + rev: v1.10.0 hooks: - id: python-no-eval - id: rst-backticks @@ -70,7 +70,7 @@ repos: - --keep-runtime-typing - repo: https://github.com/Lucas-C/pre-commit-hooks - rev: v1.3.1 + rev: v1.5.1 hooks: - id: remove-crlf - id: forbid-crlf @@ -87,7 +87,7 @@ repos: exclude: ^(doc-source/conf|__pkginfo__|setup)\.(_)?py$ - repo: https://github.com/domdfcoding/dep_checker - rev: v0.7.0 + rev: v0.7.1 hooks: - id: dep_checker args: diff --git a/README.rst b/README.rst index 3883c8b..4b31256 100644 --- a/README.rst +++ b/README.rst @@ -89,7 +89,7 @@ flake8-github-actions :target: https://github.com/python-formate/flake8-github-actions/commit/master :alt: GitHub last commit -.. |maintained| image:: https://img.shields.io/maintenance/yes/2022 +.. |maintained| image:: https://img.shields.io/maintenance/yes/2023 :alt: Maintenance .. |pypi-downloads| image:: https://img.shields.io/pypi/dm/flake8-github-actions diff --git a/tox.ini b/tox.ini index 1b0e5ad..099166e 100644 --- a/tox.ini +++ b/tox.ini @@ -3,6 +3,8 @@ # * tox # * envlists # * testenv +# * testenv:.package +# * testenv:py312-dev # * testenv:docs # * testenv:build # * testenv:perflint @@ -52,7 +54,15 @@ commands = python --version python -m pytest --cov=flake8_github_actions -r aR tests/ {posargs} +[testenv:.package] +setenv = + PYTHONDEVMODE=1 + PIP_DISABLE_PIP_VERSION_CHECK=1 + [testenv:build] +setenv = + PYTHONDEVMODE=1 + PIP_DISABLE_PIP_VERSION_CHECK=1 skip_install = True changedir = {toxinidir} deps = From bf7104e17645fa2f84a3f1cec0b0097c36df8dc3 Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Mon, 21 Aug 2023 15:06:21 +0000 Subject: [PATCH 087/105] Updated files with 'repo_helper'. (#49) Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .github/workflows/python_ci.yml | 4 ++-- .github/workflows/python_ci_linux.yml | 2 +- .github/workflows/python_ci_macos.yml | 2 +- .pre-commit-config.yaml | 6 +++--- tox.ini | 5 ++++- 5 files changed, 11 insertions(+), 8 deletions(-) diff --git a/.github/workflows/python_ci.yml b/.github/workflows/python_ci.yml index caa3535..0ab2bd2 100644 --- a/.github/workflows/python_ci.yml +++ b/.github/workflows/python_ci.yml @@ -34,10 +34,10 @@ jobs: - {python-version: "3.9", testenvs: "py39,build", experimental: False} - {python-version: "3.10", testenvs: "py310,build", experimental: False} - {python-version: "3.11", testenvs: "py311,build", experimental: False} - - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} + - {python-version: "pypy-3.6", testenvs: "pypy36", experimental: False} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: True} - - {python-version: "pypy-3.9", testenvs: "pypy39", experimental: True} + - {python-version: "pypy-3.9", testenvs: "pypy39,build", experimental: True} steps: - name: Checkout 🛎️ diff --git a/.github/workflows/python_ci_linux.yml b/.github/workflows/python_ci_linux.yml index de73765..b07f4e5 100644 --- a/.github/workflows/python_ci_linux.yml +++ b/.github/workflows/python_ci_linux.yml @@ -38,7 +38,7 @@ jobs: - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: True} - - {python-version: "pypy-3.9", testenvs: "pypy39", experimental: True} + - {python-version: "pypy-3.9", testenvs: "pypy39,build", experimental: True} steps: - name: Checkout 🛎️ diff --git a/.github/workflows/python_ci_macos.yml b/.github/workflows/python_ci_macos.yml index ba341e8..ccaec95 100644 --- a/.github/workflows/python_ci_macos.yml +++ b/.github/workflows/python_ci_macos.yml @@ -36,7 +36,7 @@ jobs: - {python-version: "3.11", testenvs: "py311,build", experimental: False} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: True} - - {python-version: "pypy-3.9", testenvs: "pypy39", experimental: True} + - {python-version: "pypy-3.9", testenvs: "pypy39,build", experimental: True} steps: - name: Checkout 🛎️ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3618176..6169edf 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,7 +8,7 @@ ci: repos: - repo: https://github.com/repo-helper/pyproject-parser - rev: v0.7.0 + rev: v0.9.0 hooks: - id: reformat-pyproject @@ -43,7 +43,7 @@ repos: - id: bind-requirements - repo: https://github.com/domdfcoding/flake8-dunder-all - rev: v0.2.2 + rev: v0.3.0 hooks: - id: ensure-dunder-all files: ^flake8_github_actions/.*\.py$ @@ -81,7 +81,7 @@ repos: - id: snippet-fmt - repo: https://github.com/python-formate/formate - rev: v0.4.10 + rev: v0.5.0 hooks: - id: formate exclude: ^(doc-source/conf|__pkginfo__|setup)\.(_)?py$ diff --git a/tox.ini b/tox.ini index 099166e..240c974 100644 --- a/tox.ini +++ b/tox.ini @@ -63,12 +63,14 @@ setenv = setenv = PYTHONDEVMODE=1 PIP_DISABLE_PIP_VERSION_CHECK=1 + PIP_PREFER_BINARY=1 skip_install = True changedir = {toxinidir} deps = build[virtualenv]>=0.3.1 check-wheel-contents>=0.1.0 twine>=3.2.0 + cryptography<40; implementation_name == "pypy" and python_version <= "3.7" commands = python -m build --sdist --wheel "{toxinidir}" twine check dist/*.tar.gz dist/*.whl @@ -120,7 +122,7 @@ commands = [flake8] max-line-length = 120 -select = E111 E112 E113 E121 E122 E125 E127 E128 E129 E131 E133 E201 E202 E203 E211 E222 E223 E224 E225 E225 E226 E227 E228 E231 E241 E242 E251 E261 E262 E265 E271 E272 E303 E304 E306 E402 E502 E703 E711 E712 E713 E714 E721 W291 W292 W293 W391 W504 YTT101 YTT102 YTT103 YTT201 YTT202 YTT203 YTT204 YTT301 YTT302 YTT303 STRFTIME001 STRFTIME002 SXL001 PT001 PT002 PT003 PT006 PT007 PT008 PT009 PT010 PT011 PT012 PT013 PT014 PT015 PT016 PT017 PT018 PT019 PT020 PT021 RST201 RST202 RST203 RST204 RST205 RST206 RST207 RST208 RST210 RST211 RST212 RST213 RST214 RST215 RST216 RST217 RST218 RST219 RST299 RST301 RST302 RST303 RST304 RST305 RST306 RST399 RST401 RST499 RST900 RST901 RST902 RST903 Q001 Q002 Q003 A001 A002 A003 TYP001 TYP002 TYP003 TYP004 TYP005 TYP006 ENC001 ENC002 ENC003 ENC004 ENC011 ENC012 ENC021 ENC022 ENC023 ENC024 ENC025 ENC026 Y001,Y002 Y003 Y004 Y005 Y006 Y007 Y008 Y009 Y010 Y011 Y012 Y013 Y014 Y015 Y090 Y091 NQA001 NQA002 NQA003 NQA004 NQA005 NQA102 NQA103 E301 E302 E305 D100 D101 D102 D103 D104 D106 D201 D204 D207 D208 D209 D210 D211 D212 D213 D214 D215 D300 D301 D400 D402 D403 D404 D415 D417 DALL000 SLOT000 SLOT001 SLOT002 +select = E111 E112 E113 E121 E122 E125 E127 E128 E129 E131 E133 E201 E202 E203 E211 E222 E223 E224 E225 E225 E226 E227 E228 E231 E241 E242 E251 E261 E262 E265 E271 E272 E303 E304 E306 E402 E502 E703 E711 E712 E713 E714 E721 W291 W292 W293 W391 W504 YTT101 YTT102 YTT103 YTT201 YTT202 YTT203 YTT204 YTT301 YTT302 YTT303 STRFTIME001 STRFTIME002 SXL001 PT001 PT002 PT003 PT006 PT007 PT008 PT009 PT010 PT011 PT012 PT013 PT014 PT015 PT016 PT017 PT018 PT019 PT020 PT021 RST201 RST202 RST203 RST204 RST205 RST206 RST207 RST208 RST210 RST211 RST212 RST213 RST214 RST215 RST216 RST217 RST218 RST219 RST299 RST301 RST302 RST303 RST304 RST305 RST306 RST399 RST401 RST499 RST900 RST901 RST902 RST903 Q001 Q002 Q003 A001 A002 TYP001 TYP002 TYP003 TYP004 TYP005 TYP006 ENC001 ENC002 ENC003 ENC004 ENC011 ENC012 ENC021 ENC022 ENC023 ENC024 ENC025 ENC026 Y001,Y002 Y003 Y004 Y005 Y006 Y007 Y008 Y009 Y010 Y011 Y012 Y013 Y014 Y015 Y090 Y091 NQA001 NQA002 NQA003 NQA004 NQA005 NQA102 NQA103 E301 E302 E305 D100 D101 D102 D103 D104 D106 D201 D204 D207 D208 D209 D210 D211 D212 D213 D214 D215 D300 D301 D400 D402 D403 D404 D415 D417 DALL000 SLOT000 SLOT001 SLOT002 extend-exclude = doc-source,old,build,dist,__pkginfo__.py,setup.py,venv rst-directives = TODO @@ -148,6 +150,7 @@ plugins = coverage_pyver_pragma [coverage:report] fail_under = 100 +show_missing = True exclude_lines = raise AssertionError raise NotImplementedError From 1d370f65ed8b440959f4ef152da34fa6f0ab21b6 Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Fri, 8 Dec 2023 10:59:22 +0000 Subject: [PATCH 088/105] Updated files with 'repo_helper'. (#50) Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .github/workflows/python_ci.yml | 4 ++-- .github/workflows/python_ci_linux.yml | 4 ++-- .github/workflows/python_ci_macos.yml | 4 ++-- tox.ini | 5 ++++- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/workflows/python_ci.yml b/.github/workflows/python_ci.yml index 0ab2bd2..484a571 100644 --- a/.github/workflows/python_ci.yml +++ b/.github/workflows/python_ci.yml @@ -35,8 +35,8 @@ jobs: - {python-version: "3.10", testenvs: "py310,build", experimental: False} - {python-version: "3.11", testenvs: "py311,build", experimental: False} - {python-version: "pypy-3.6", testenvs: "pypy36", experimental: False} - - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} - - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: True} + - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: False} + - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: False} - {python-version: "pypy-3.9", testenvs: "pypy39,build", experimental: True} steps: diff --git a/.github/workflows/python_ci_linux.yml b/.github/workflows/python_ci_linux.yml index b07f4e5..cb4614c 100644 --- a/.github/workflows/python_ci_linux.yml +++ b/.github/workflows/python_ci_linux.yml @@ -36,8 +36,8 @@ jobs: - {python-version: "3.10", testenvs: "py310,build", experimental: False} - {python-version: "3.11", testenvs: "py311,build", experimental: False} - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} - - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} - - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: True} + - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: False} + - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: False} - {python-version: "pypy-3.9", testenvs: "pypy39,build", experimental: True} steps: diff --git a/.github/workflows/python_ci_macos.yml b/.github/workflows/python_ci_macos.yml index ccaec95..5c4be8c 100644 --- a/.github/workflows/python_ci_macos.yml +++ b/.github/workflows/python_ci_macos.yml @@ -34,8 +34,8 @@ jobs: - {python-version: "3.9", testenvs: "py39,build", experimental: False} - {python-version: "3.10", testenvs: "py310,build", experimental: False} - {python-version: "3.11", testenvs: "py311,build", experimental: False} - - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: True} - - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: True} + - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: False} + - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: False} - {python-version: "pypy-3.9", testenvs: "pypy39,build", experimental: True} steps: diff --git a/tox.ini b/tox.ini index 240c974..f870c2c 100644 --- a/tox.ini +++ b/tox.ini @@ -4,7 +4,9 @@ # * envlists # * testenv # * testenv:.package +# * testenv:py313-dev # * testenv:py312-dev +# * testenv:py312 # * testenv:docs # * testenv:build # * testenv:perflint @@ -69,7 +71,8 @@ changedir = {toxinidir} deps = build[virtualenv]>=0.3.1 check-wheel-contents>=0.1.0 - twine>=3.2.0 + twine>=3.2.0; python_version < "3.13" + twine@git+https://github.com/pypa/twine; python_version >= "3.13" cryptography<40; implementation_name == "pypy" and python_version <= "3.7" commands = python -m build --sdist --wheel "{toxinidir}" From 2fd4d86cf01e7f2d51423cfd80e399f03f212294 Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Wed, 31 Jan 2024 11:01:51 +0000 Subject: [PATCH 089/105] Updated files with 'repo_helper'. (#52) Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .github/workflows/flake8.yml | 4 ++-- .github/workflows/mypy.yml | 4 ++-- .github/workflows/python_ci.yml | 4 ++-- .github/workflows/python_ci_linux.yml | 12 ++++++------ .github/workflows/python_ci_macos.yml | 4 ++-- README.rst | 2 +- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/flake8.yml b/.github/workflows/flake8.yml index 8221173..0a8c0c3 100644 --- a/.github/workflows/flake8.yml +++ b/.github/workflows/flake8.yml @@ -20,7 +20,7 @@ jobs: steps: - name: Checkout 🛎️ - uses: "actions/checkout@v3" + uses: "actions/checkout@v4" - name: Check for changed files uses: dorny/paths-filter@v2 @@ -33,7 +33,7 @@ jobs: - name: Setup Python 🐍 if: steps.changes.outputs.code == 'true' - uses: "actions/setup-python@v4" + uses: "actions/setup-python@v5" with: python-version: "3.8" diff --git a/.github/workflows/mypy.yml b/.github/workflows/mypy.yml index 9b28b5f..10c6f30 100644 --- a/.github/workflows/mypy.yml +++ b/.github/workflows/mypy.yml @@ -25,7 +25,7 @@ jobs: steps: - name: Checkout 🛎️ - uses: "actions/checkout@v3" + uses: "actions/checkout@v4" - name: Check for changed files uses: dorny/paths-filter@v2 @@ -38,7 +38,7 @@ jobs: - name: Setup Python 🐍 if: steps.changes.outputs.code == 'true' - uses: "actions/setup-python@v4" + uses: "actions/setup-python@v5" with: python-version: "3.8" diff --git a/.github/workflows/python_ci.yml b/.github/workflows/python_ci.yml index 484a571..ff26c01 100644 --- a/.github/workflows/python_ci.yml +++ b/.github/workflows/python_ci.yml @@ -41,7 +41,7 @@ jobs: steps: - name: Checkout 🛎️ - uses: "actions/checkout@v3" + uses: "actions/checkout@v4" - name: Check for changed files if: startsWith(github.ref, 'refs/tags/') != true @@ -56,7 +56,7 @@ jobs: - name: Setup Python 🐍 id: setup-python if: ${{ steps.changes.outputs.code == 'true' || steps.changes.outcome == 'skipped' }} - uses: "actions/setup-python@v4" + uses: "actions/setup-python@v5" with: python-version: "${{ matrix.config.python-version }}" diff --git a/.github/workflows/python_ci_linux.yml b/.github/workflows/python_ci_linux.yml index cb4614c..ca6aad0 100644 --- a/.github/workflows/python_ci_linux.yml +++ b/.github/workflows/python_ci_linux.yml @@ -42,7 +42,7 @@ jobs: steps: - name: Checkout 🛎️ - uses: "actions/checkout@v3" + uses: "actions/checkout@v4" - name: Check for changed files if: startsWith(github.ref, 'refs/tags/') != true @@ -57,7 +57,7 @@ jobs: - name: Setup Python 🐍 id: setup-python if: ${{ steps.changes.outputs.code == 'true' || steps.changes.outcome == 'skipped' }} - uses: "actions/setup-python@v4" + uses: "actions/setup-python@v5" with: python-version: "${{ matrix.config.python-version }}" @@ -87,10 +87,10 @@ jobs: runs-on: "ubuntu-20.04" steps: - name: Checkout 🛎️ - uses: "actions/checkout@v3" + uses: "actions/checkout@v4" - name: Setup Python 🐍 - uses: "actions/setup-python@v4" + uses: "actions/setup-python@v5" with: python-version: 3.8 @@ -136,11 +136,11 @@ jobs: runs-on: "ubuntu-20.04" steps: - name: Checkout 🛎️ - uses: "actions/checkout@v3" + uses: "actions/checkout@v4" if: startsWith(github.ref, 'refs/tags/') - name: Setup Python 🐍 - uses: "actions/setup-python@v4" + uses: "actions/setup-python@v5" if: startsWith(github.ref, 'refs/tags/') with: python-version: 3.8 diff --git a/.github/workflows/python_ci_macos.yml b/.github/workflows/python_ci_macos.yml index 5c4be8c..0f926e2 100644 --- a/.github/workflows/python_ci_macos.yml +++ b/.github/workflows/python_ci_macos.yml @@ -40,7 +40,7 @@ jobs: steps: - name: Checkout 🛎️ - uses: "actions/checkout@v3" + uses: "actions/checkout@v4" - name: Check for changed files if: startsWith(github.ref, 'refs/tags/') != true @@ -55,7 +55,7 @@ jobs: - name: Setup Python 🐍 id: setup-python if: ${{ steps.changes.outputs.code == 'true' || steps.changes.outcome == 'skipped' }} - uses: "actions/setup-python@v4" + uses: "actions/setup-python@v5" with: python-version: "${{ matrix.config.python-version }}" diff --git a/README.rst b/README.rst index 4b31256..5214262 100644 --- a/README.rst +++ b/README.rst @@ -89,7 +89,7 @@ flake8-github-actions :target: https://github.com/python-formate/flake8-github-actions/commit/master :alt: GitHub last commit -.. |maintained| image:: https://img.shields.io/maintenance/yes/2023 +.. |maintained| image:: https://img.shields.io/maintenance/yes/2024 :alt: Maintenance .. |pypi-downloads| image:: https://img.shields.io/pypi/dm/flake8-github-actions From 7eaea7baaae6230b540598a0febbafada6a36087 Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 11:49:30 +0000 Subject: [PATCH 090/105] Bump pre-commit hooks. (#53) Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6169edf..7f1c3db 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,7 +8,7 @@ ci: repos: - repo: https://github.com/repo-helper/pyproject-parser - rev: v0.9.0 + rev: v0.9.1 hooks: - id: reformat-pyproject @@ -43,13 +43,13 @@ repos: - id: bind-requirements - repo: https://github.com/domdfcoding/flake8-dunder-all - rev: v0.3.0 + rev: v0.3.1 hooks: - id: ensure-dunder-all files: ^flake8_github_actions/.*\.py$ - repo: https://github.com/domdfcoding/flake2lint - rev: v0.4.2 + rev: v0.4.3 hooks: - id: flake2lint @@ -76,18 +76,18 @@ repos: - id: forbid-crlf - repo: https://github.com/python-formate/snippet-fmt - rev: v0.1.4 + rev: v0.1.5 hooks: - id: snippet-fmt - repo: https://github.com/python-formate/formate - rev: v0.5.0 + rev: v0.7.0 hooks: - id: formate exclude: ^(doc-source/conf|__pkginfo__|setup)\.(_)?py$ - repo: https://github.com/domdfcoding/dep_checker - rev: v0.7.1 + rev: v0.8.0 hooks: - id: dep_checker args: From 5afc7d28904b24ff94609883fcc70132db60d81f Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 16:47:07 +0000 Subject: [PATCH 091/105] Updated files with 'repo_helper'. (#54) Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .github/workflows/python_ci.yml | 2 +- .github/workflows/python_ci_linux.yml | 6 +++--- .github/workflows/python_ci_macos.yml | 2 +- formate.toml | 2 +- tox.ini | 3 +-- 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/.github/workflows/python_ci.yml b/.github/workflows/python_ci.yml index ff26c01..6dae1d8 100644 --- a/.github/workflows/python_ci.yml +++ b/.github/workflows/python_ci.yml @@ -73,7 +73,7 @@ jobs: run: python -m tox -e "${{ matrix.config.testenvs }}" -s false - name: "Upload Coverage 🚀" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: ${{ always() && steps.setup-python.outcome == 'success' }} with: name: "coverage-${{ matrix.config.python-version }}" diff --git a/.github/workflows/python_ci_linux.yml b/.github/workflows/python_ci_linux.yml index ca6aad0..ed7c64a 100644 --- a/.github/workflows/python_ci_linux.yml +++ b/.github/workflows/python_ci_linux.yml @@ -75,7 +75,7 @@ jobs: run: python -m tox -e "${{ matrix.config.testenvs }}" -s false - name: "Upload Coverage 🚀" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: ${{ always() && steps.setup-python.outcome == 'success' }} with: name: "coverage-${{ matrix.config.python-version }}" @@ -100,7 +100,7 @@ jobs: python -m pip install --upgrade "coveralls>=3.0.0" coverage_pyver_pragma - name: "Download Coverage 🪂" - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: path: coverage @@ -118,7 +118,7 @@ jobs: - name: "Upload Combined Coverage Artefact 🚀" if: ${{ steps.show.outcome != 'failure' }} - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: "combined-coverage" path: .coverage diff --git a/.github/workflows/python_ci_macos.yml b/.github/workflows/python_ci_macos.yml index 0f926e2..13199f4 100644 --- a/.github/workflows/python_ci_macos.yml +++ b/.github/workflows/python_ci_macos.yml @@ -72,7 +72,7 @@ jobs: run: python -m tox -e "${{ matrix.config.testenvs }}" -s false - name: "Upload Coverage 🚀" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: ${{ always() && steps.setup-python.outcome == 'success' }} with: name: "coverage-${{ matrix.config.python-version }}" diff --git a/formate.toml b/formate.toml index be69675..5a4f26a 100644 --- a/formate.toml +++ b/formate.toml @@ -54,4 +54,4 @@ known_third_party = [ "requests", "typing_extensions", ] -known_first_party = "flake8_github_actions" +known_first_party = [ "flake8_github_actions",] diff --git a/tox.ini b/tox.ini index f870c2c..fa49a4b 100644 --- a/tox.ini +++ b/tox.ini @@ -71,8 +71,7 @@ changedir = {toxinidir} deps = build[virtualenv]>=0.3.1 check-wheel-contents>=0.1.0 - twine>=3.2.0; python_version < "3.13" - twine@git+https://github.com/pypa/twine; python_version >= "3.13" + twine>=3.2.0 cryptography<40; implementation_name == "pypy" and python_version <= "3.7" commands = python -m build --sdist --wheel "{toxinidir}" From badcc500f192cbc572310a597d7ad724e1d38c4a Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Mon, 18 Mar 2024 13:59:25 +0000 Subject: [PATCH 092/105] Update dependabot config (#55) * Updated files with 'repo_helper'. * Updated files with 'repo_helper'. * Updated files with 'repo_helper'. --------- Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .dependabot/config.yml | 9 --------- .github/dependabot.yml | 1 + 2 files changed, 1 insertion(+), 9 deletions(-) delete mode 100644 .dependabot/config.yml diff --git a/.dependabot/config.yml b/.dependabot/config.yml deleted file mode 100644 index 4584924..0000000 --- a/.dependabot/config.yml +++ /dev/null @@ -1,9 +0,0 @@ -# This file is managed by 'repo_helper'. Don't edit it directly. ---- -version: 1 -update_configs: -- package_manager: python - directory: / - update_schedule: weekly - default_reviewers: - - domdfcoding diff --git a/.github/dependabot.yml b/.github/dependabot.yml index e769ad3..454225a 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -6,5 +6,6 @@ updates: directory: / schedule: interval: weekly + open-pull-requests-limit: 0 reviewers: - domdfcoding From 0aa5fb712164bd11267fc2d48cafc694fd74586a Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Tue, 16 Apr 2024 14:31:48 +0100 Subject: [PATCH 093/105] [repo-helper] Configuration Update (#56) * Updated files with 'repo_helper'. * Updated files with 'repo_helper'. * Updated files with 'repo_helper'. --------- Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- formate.toml | 16 ++++++++-------- pyproject.toml | 27 +++++++++++++-------------- tox.ini | 4 ++-- 4 files changed, 24 insertions(+), 25 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7f1c3db..a6efb57 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,7 +8,7 @@ ci: repos: - repo: https://github.com/repo-helper/pyproject-parser - rev: v0.9.1 + rev: v0.11.0 hooks: - id: reformat-pyproject diff --git a/formate.toml b/formate.toml index 5a4f26a..0ca5060 100644 --- a/formate.toml +++ b/formate.toml @@ -6,21 +6,17 @@ noqa-reformat = 60 ellipsis-reformat = 70 squish_stubs = 80 -[config] -indent = "\t" -line_length = 115 - [hooks.yapf] priority = 30 -[hooks.isort] -priority = 50 - [hooks.yapf.kwargs] yapf_style = ".style.yapf" +[hooks.isort] +priority = 50 + [hooks.isort.kwargs] -indent = "\t\t" +indent = " " multi_line_output = 8 import_heading_stdlib = "stdlib" import_heading_thirdparty = "3rd party" @@ -55,3 +51,7 @@ known_third_party = [ "typing_extensions", ] known_first_party = [ "flake8_github_actions",] + +[config] +indent = " " +line_length = 115 diff --git a/pyproject.toml b/pyproject.toml index 895c05e..afb6b82 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,7 +15,6 @@ dynamic = [ "classifiers", "dependencies",] name = "Dominic Davis-Foster" email = "dominic@davis-foster.co.uk" - [project.license] file = "LICENSE" @@ -24,6 +23,9 @@ Homepage = "https://github.com/python-formate/flake8-github-actions" "Issue Tracker" = "https://github.com/python-formate/flake8-github-actions/issues" "Source Code" = "https://github.com/python-formate/flake8-github-actions" +[project.entry-points."flake8.report"] +github = "flake8_github_actions:GitHubFormatter" + [tool.whey] base-classifiers = [ "Development Status :: 4 - Beta", @@ -49,19 +51,6 @@ show_error_codes = true [tool.snippet-fmt] directives = [ "code-block",] -[tool.dep_checker] -allowed_unused = [ "flake8",] - -[project.entry-points."flake8.report"] -github = "flake8_github_actions:GitHubFormatter" - -[tool.dependency-dash."requirements.txt"] -order = 10 - -[tool.dependency-dash."tests/requirements.txt"] -order = 20 -include = false - [tool.snippet-fmt.languages.python] reformat = true @@ -71,3 +60,13 @@ reformat = true [tool.snippet-fmt.languages.ini] [tool.snippet-fmt.languages.json] + +[tool.dep_checker] +allowed_unused = [ "flake8",] + +[tool.dependency-dash."requirements.txt"] +order = 10 + +[tool.dependency-dash."tests/requirements.txt"] +order = 20 +include = false diff --git a/tox.ini b/tox.ini index fa49a4b..d6d6e27 100644 --- a/tox.ini +++ b/tox.ini @@ -158,8 +158,8 @@ exclude_lines = raise NotImplementedError if 0: if False: - if TYPE_CHECKING: - if typing.TYPE_CHECKING: + if TYPE_CHECKING + if typing.TYPE_CHECKING if __name__ == .__main__.: [check-wheel-contents] From 7e2dd9402a52ef14ac1446264c26d10ffd4fb5e0 Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Wed, 24 Apr 2024 14:03:51 +0100 Subject: [PATCH 094/105] Updated files with 'repo_helper'. (#57) Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .github/workflows/python_ci_macos.yml | 4 ++-- .pre-commit-config.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/python_ci_macos.yml b/.github/workflows/python_ci_macos.yml index 13199f4..076e0b0 100644 --- a/.github/workflows/python_ci_macos.yml +++ b/.github/workflows/python_ci_macos.yml @@ -18,8 +18,8 @@ permissions: jobs: tests: - name: "macos-latest / Python ${{ matrix.config.python-version }}" - runs-on: "macos-latest" + name: "macos-13 / Python ${{ matrix.config.python-version }}" + runs-on: "macos-13" continue-on-error: ${{ matrix.config.experimental }} env: USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11,pypy-3.7,pypy-3.8,pypy-3.9' diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a6efb57..7ae2f88 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -43,7 +43,7 @@ repos: - id: bind-requirements - repo: https://github.com/domdfcoding/flake8-dunder-all - rev: v0.3.1 + rev: v0.4.1 hooks: - id: ensure-dunder-all files: ^flake8_github_actions/.*\.py$ From 388746b9e236e76aef98d6ad8070f9a0c5fece13 Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Thu, 25 Apr 2024 16:40:40 +0100 Subject: [PATCH 095/105] Set UNSAFE_PYO3_SKIP_VERSION_CHECK=1 for Python 3.13. (#58) Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- tox.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/tox.ini b/tox.ini index d6d6e27..54d7804 100644 --- a/tox.ini +++ b/tox.ini @@ -66,6 +66,7 @@ setenv = PYTHONDEVMODE=1 PIP_DISABLE_PIP_VERSION_CHECK=1 PIP_PREFER_BINARY=1 + UNSAFE_PYO3_SKIP_VERSION_CHECK=1 skip_install = True changedir = {toxinidir} deps = From 2c5d9b5ae46d2a15fe1018b91b3cf40a5fcf18b9 Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Thu, 1 Aug 2024 15:52:46 +0100 Subject: [PATCH 096/105] Updated files with 'repo_helper'. (#59) Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .github/workflows/python_ci.yml | 2 +- pyproject.toml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/python_ci.yml b/.github/workflows/python_ci.yml index 6dae1d8..0236186 100644 --- a/.github/workflows/python_ci.yml +++ b/.github/workflows/python_ci.yml @@ -37,7 +37,7 @@ jobs: - {python-version: "pypy-3.6", testenvs: "pypy36", experimental: False} - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: False} - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: False} - - {python-version: "pypy-3.9", testenvs: "pypy39,build", experimental: True} + - {python-version: "pypy-3.9-v7.3.15", testenvs: "pypy39,build", experimental: True} steps: - name: Checkout 🛎️ diff --git a/pyproject.toml b/pyproject.toml index afb6b82..c44f47a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,13 +11,13 @@ requires-python = ">=3.6" keywords = [ "flake8", "github", "github-actions",] dynamic = [ "classifiers", "dependencies",] +[project.license] +file = "LICENSE" + [[project.authors]] name = "Dominic Davis-Foster" email = "dominic@davis-foster.co.uk" -[project.license] -file = "LICENSE" - [project.urls] Homepage = "https://github.com/python-formate/flake8-github-actions" "Issue Tracker" = "https://github.com/python-formate/flake8-github-actions/issues" From 6df2e22307d57bb395e524415555b80a7645b345 Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Tue, 8 Oct 2024 15:52:28 +0100 Subject: [PATCH 097/105] Updated files with 'repo_helper'. (#60) Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 6 +++--- tox.ini | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7ae2f88..d9288f5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,7 +8,7 @@ ci: repos: - repo: https://github.com/repo-helper/pyproject-parser - rev: v0.11.0 + rev: v0.11.1 hooks: - id: reformat-pyproject @@ -42,7 +42,7 @@ repos: exclude: ^(doc-source/conf|__pkginfo__|setup|tests/.*)\.py$ - id: bind-requirements - - repo: https://github.com/domdfcoding/flake8-dunder-all + - repo: https://github.com/python-formate/flake8-dunder-all rev: v0.4.1 hooks: - id: ensure-dunder-all @@ -86,7 +86,7 @@ repos: - id: formate exclude: ^(doc-source/conf|__pkginfo__|setup)\.(_)?py$ - - repo: https://github.com/domdfcoding/dep_checker + - repo: https://github.com/python-coincidence/dep_checker rev: v0.8.0 hooks: - id: dep_checker diff --git a/tox.ini b/tox.ini index 54d7804..9183307 100644 --- a/tox.ini +++ b/tox.ini @@ -5,6 +5,7 @@ # * testenv # * testenv:.package # * testenv:py313-dev +# * testenv:py313 # * testenv:py312-dev # * testenv:py312 # * testenv:docs From 3f058ca2f24104afa8bcd0b1404af56b1025798a Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Mon, 4 Nov 2024 15:19:53 +0000 Subject: [PATCH 098/105] Test on newer Python and Flake8 --- .github/workflows/python_ci.yml | 24 +++++---- .github/workflows/python_ci_linux.yml | 24 +++++---- .github/workflows/python_ci_macos.yml | 22 ++++---- pyproject.toml | 2 +- repo_helper.yml | 54 ++++++++++++++++---- requirements.txt | 2 +- tests/test_output.py | 11 +++- tox.ini | 72 ++++++++++++++++++++++----- 8 files changed, 151 insertions(+), 60 deletions(-) diff --git a/.github/workflows/python_ci.yml b/.github/workflows/python_ci.yml index 0236186..ae4c782 100644 --- a/.github/workflows/python_ci.yml +++ b/.github/workflows/python_ci.yml @@ -22,22 +22,24 @@ jobs: runs-on: "windows-2019" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11,pypy-3.6,pypy-3.7,pypy-3.8,pypy-3.9' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11,3.12,3.13,pypy-3.6,pypy-3.7,pypy-3.8,pypy-3.9' strategy: fail-fast: False matrix: config: - - {python-version: "3.6", testenvs: "py36,build", experimental: False} - - {python-version: "3.7", testenvs: "py37,build", experimental: False} - - {python-version: "3.8", testenvs: "py38,build", experimental: False} - - {python-version: "3.9", testenvs: "py39,build", experimental: False} - - {python-version: "3.10", testenvs: "py310,build", experimental: False} - - {python-version: "3.11", testenvs: "py311,build", experimental: False} - - {python-version: "pypy-3.6", testenvs: "pypy36", experimental: False} - - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: False} - - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: False} - - {python-version: "pypy-3.9-v7.3.15", testenvs: "pypy39,build", experimental: True} + - {python-version: "3.6", testenvs: "py36-flake8{4,5},build", experimental: False} + - {python-version: "3.7", testenvs: "py37-flake8{4,5},build", experimental: False} + - {python-version: "3.8", testenvs: "py38-flake8{4,5,6,7},build", experimental: False} + - {python-version: "3.9", testenvs: "py39-flake8{4,5,6,7},build", experimental: False} + - {python-version: "3.10", testenvs: "py310-flake8{4,5,6,7},build", experimental: False} + - {python-version: "3.11", testenvs: "py311-flake8{4,5,6,7},build", experimental: False} + - {python-version: "3.12", testenvs: "py312-flake8{6,7},build", experimental: False} + - {python-version: "3.13", testenvs: "py313-flake8{6,7},build", experimental: False} + - {python-version: "pypy-3.6", testenvs: "pypy36-flake8{4,5}", experimental: False} + - {python-version: "pypy-3.7", testenvs: "pypy37-flake8{4,5},build", experimental: False} + - {python-version: "pypy-3.8", testenvs: "pypy38-flake8{4,5,6,7},build", experimental: False} + - {python-version: "pypy-3.9-v7.3.15", testenvs: "pypy39-flake8{4,5,6,7},build", experimental: True} steps: - name: Checkout 🛎️ diff --git a/.github/workflows/python_ci_linux.yml b/.github/workflows/python_ci_linux.yml index ed7c64a..3da41d3 100644 --- a/.github/workflows/python_ci_linux.yml +++ b/.github/workflows/python_ci_linux.yml @@ -23,22 +23,24 @@ jobs: runs-on: "ubuntu-20.04" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11,pypy-3.6,pypy-3.7,pypy-3.8,pypy-3.9' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11,3.12,3.13,pypy-3.6,pypy-3.7,pypy-3.8,pypy-3.9' strategy: fail-fast: False matrix: config: - - {python-version: "3.6", testenvs: "py36,build", experimental: False} - - {python-version: "3.7", testenvs: "py37,build", experimental: False} - - {python-version: "3.8", testenvs: "py38,build", experimental: False} - - {python-version: "3.9", testenvs: "py39,build", experimental: False} - - {python-version: "3.10", testenvs: "py310,build", experimental: False} - - {python-version: "3.11", testenvs: "py311,build", experimental: False} - - {python-version: "pypy-3.6", testenvs: "pypy36,build", experimental: False} - - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: False} - - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: False} - - {python-version: "pypy-3.9", testenvs: "pypy39,build", experimental: True} + - {python-version: "3.6", testenvs: "py36-flake8{4,5},build", experimental: False} + - {python-version: "3.7", testenvs: "py37-flake8{4,5},build", experimental: False} + - {python-version: "3.8", testenvs: "py38-flake8{4,5,6,7},build", experimental: False} + - {python-version: "3.9", testenvs: "py39-flake8{4,5,6,7},build", experimental: False} + - {python-version: "3.10", testenvs: "py310-flake8{4,5,6,7},build", experimental: False} + - {python-version: "3.11", testenvs: "py311-flake8{4,5,6,7},build", experimental: False} + - {python-version: "3.12", testenvs: "py312-flake8{6,7},build", experimental: False} + - {python-version: "3.13", testenvs: "py313-flake8{6,7},build", experimental: False} + - {python-version: "pypy-3.6", testenvs: "pypy36-flake8{4,5},build", experimental: False} + - {python-version: "pypy-3.7", testenvs: "pypy37-flake8{4,5},build", experimental: False} + - {python-version: "pypy-3.8", testenvs: "pypy38-flake8{4,5,6,7},build", experimental: False} + - {python-version: "pypy-3.9", testenvs: "pypy39-flake8{4,5,6,7},build", experimental: True} steps: - name: Checkout 🛎️ diff --git a/.github/workflows/python_ci_macos.yml b/.github/workflows/python_ci_macos.yml index 076e0b0..9fb8c60 100644 --- a/.github/workflows/python_ci_macos.yml +++ b/.github/workflows/python_ci_macos.yml @@ -22,21 +22,23 @@ jobs: runs-on: "macos-13" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11,pypy-3.7,pypy-3.8,pypy-3.9' + USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11,3.12,3.13,pypy-3.7,pypy-3.8,pypy-3.9' strategy: fail-fast: False matrix: config: - - {python-version: "3.6", testenvs: "py36,build", experimental: False} - - {python-version: "3.7", testenvs: "py37,build", experimental: False} - - {python-version: "3.8", testenvs: "py38,build", experimental: False} - - {python-version: "3.9", testenvs: "py39,build", experimental: False} - - {python-version: "3.10", testenvs: "py310,build", experimental: False} - - {python-version: "3.11", testenvs: "py311,build", experimental: False} - - {python-version: "pypy-3.7", testenvs: "pypy37,build", experimental: False} - - {python-version: "pypy-3.8", testenvs: "pypy38,build", experimental: False} - - {python-version: "pypy-3.9", testenvs: "pypy39,build", experimental: True} + - {python-version: "3.6", testenvs: "py36-flake8{4,5},build", experimental: False} + - {python-version: "3.7", testenvs: "py37-flake8{4,5},build", experimental: False} + - {python-version: "3.8", testenvs: "py38-flake8{4,5,6,7},build", experimental: False} + - {python-version: "3.9", testenvs: "py39-flake8{4,5,6,7},build", experimental: False} + - {python-version: "3.10", testenvs: "py310-flake8{4,5,6,7},build", experimental: False} + - {python-version: "3.11", testenvs: "py311-flake8{4,5,6,7},build", experimental: False} + - {python-version: "3.12", testenvs: "py312-flake8{6,7},build", experimental: False} + - {python-version: "3.13", testenvs: "py313-flake8{6,7},build", experimental: False} + - {python-version: "pypy-3.7", testenvs: "pypy37-flake8{4,5},build", experimental: False} + - {python-version: "pypy-3.8", testenvs: "pypy38-flake8{4,5,6,7},build", experimental: False} + - {python-version: "pypy-3.9", testenvs: "pypy39-flake8{4,5,6,7},build", experimental: True} steps: - name: Checkout 🛎️ diff --git a/pyproject.toml b/pyproject.toml index c44f47a..46f37c8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,7 +34,7 @@ base-classifiers = [ "Intended Audience :: Developers", "Typing :: Typed", ] -python-versions = [ "3.6", "3.7", "3.8", "3.9", "3.10", "3.11",] +python-versions = [ "3.6", "3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13",] python-implementations = [ "CPython", "PyPy",] platforms = [ "Windows", "macOS", "Linux",] license-key = "MIT" diff --git a/repo_helper.yml b/repo_helper.yml index 6a39287..2d2b625 100644 --- a/repo_helper.yml +++ b/repo_helper.yml @@ -18,17 +18,42 @@ pre_commit_exclude: "^tests/bad_code.py$" use_whey: true python_versions: - - '3.6' - - '3.7' - - '3.8' - - '3.9' - - "3.10" - - "3.11" -# - 3.12-dev # Flake8<5 incompatible - - pypy36 - - pypy37 - - pypy38 - - pypy39 + 3.6: + matrix_exclude: + flake8: + - 6 + - 7 + 3.7: + matrix_exclude: + flake8: + - 6 + - 7 + 3.8: + 3.9: + "3.10": + 3.11: + 3.12: + matrix_exclude: + flake8: + - 4 + - 5 + 3.13: + matrix_exclude: + flake8: + - 4 + - 5 + pypy36: + matrix_exclude: + flake8: + - 6 + - 7 + pypy37: + matrix_exclude: + flake8: + - 6 + - 7 + pypy38: + pypy39: additional_ignore: - action.py @@ -50,3 +75,10 @@ classifiers: tox_unmanaged: - "testenv:lint" + +third_party_version_matrix: + flake8: + - 4 + - 5 + - 6 + - 7 diff --git a/requirements.txt b/requirements.txt index 73b78ce..4163a01 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -flake8<5,>=3.8.4 +flake8>=3.8.4 diff --git a/tests/test_output.py b/tests/test_output.py index c91e9cd..79ce5a1 100644 --- a/tests/test_output.py +++ b/tests/test_output.py @@ -1,6 +1,7 @@ # 3rd party import pytest from coincidence.regressions import FileRegressionFixture, check_file_regression +from domdf_python_tools.compat import importlib_metadata from domdf_python_tools.paths import PathPlus from flake8.main import cli # type: ignore @@ -8,8 +9,14 @@ def test_output(file_regression: FileRegressionFixture, capsys): - with pytest.raises(SystemExit): - cli.main([str(bad_code), "--select", "F401,F404,F821,F701,E303", "--format", "github"]) + args = [str(bad_code), "--select", "F401,F404,F821,F701,E303", "--format", "github"] + + if int(importlib_metadata.version("flake8").split('.')[0]) >= 5: + cli.main(args) + + else: + with pytest.raises(SystemExit): + cli.main(args) stdout = capsys.readouterr().out.replace(str(bad_code), "bad_code.py") check_file_regression(stdout, file_regression) diff --git a/tox.ini b/tox.ini index 9183307..f01efdf 100644 --- a/tox.ini +++ b/tox.ini @@ -22,16 +22,18 @@ [tox] envlist = - py36 - py37 - py38 - py39 - py310 - py311 - pypy36 - pypy37 - pypy38 - pypy39 + py36-flake8{4,5} + py37-flake8{4,5} + py38-flake8{4,5,6,7} + py39-flake8{4,5,6,7} + py310-flake8{4,5,6,7} + py311-flake8{4,5,6,7} + py312-flake8{6,7} + py313-flake8{6,7} + pypy36-flake8{4,5} + pypy37-flake8{4,5} + pypy38-flake8{4,5,6,7} + pypy39-flake8{4,5,6,7} mypy build skip_missing_interpreters = True @@ -43,16 +45,33 @@ requires = virtualenv!=20.16.0 [envlists] -test = py36, py37, py38, py39, py310, py311, pypy36, pypy37, pypy38, pypy39 +test = + py36-flake8{4,5} + py37-flake8{4,5} + py38-flake8{4,5,6,7} + py39-flake8{4,5,6,7} + py310-flake8{4,5,6,7} + py311-flake8{4,5,6,7} + py312-flake8{6,7} + py313-flake8{6,7} + pypy36-flake8{4,5} + pypy37-flake8{4,5} + pypy38-flake8{4,5,6,7} + pypy39-flake8{4,5,6,7} qa = mypy, lint -cov = py38, coverage +cov = py38-flake84, coverage [testenv] setenv = PYTHONDEVMODE=1 PIP_DISABLE_PIP_VERSION_CHECK=1 SETUPTOOLS_USE_DISTUTILS=stdlib -deps = -r{toxinidir}/tests/requirements.txt +deps = + -r{toxinidir}/tests/requirements.txt + flake84: flake8~=4.0 + flake85: flake8~=5.0 + flake86: flake8~=6.0 + flake87: flake8~=7.0 commands = python --version python -m pytest --cov=flake8_github_actions -r aR tests/ {posargs} @@ -62,6 +81,19 @@ setenv = PYTHONDEVMODE=1 PIP_DISABLE_PIP_VERSION_CHECK=1 +[testenv:py313] +download = True +setenv = + PYTHONDEVMODE=1 + PIP_DISABLE_PIP_VERSION_CHECK=1 + UNSAFE_PYO3_SKIP_VERSION_CHECK=1 + +[testenv:py312] +download = True +setenv = + PYTHONDEVMODE=1 + PIP_DISABLE_PIP_VERSION_CHECK=1 + [testenv:build] setenv = PYTHONDEVMODE=1 @@ -176,6 +208,20 @@ filterwarnings = error ignore:SelectableGroups dict interface is deprecated. Use select.:DeprecationWarning:flake8 ignore:can't resolve package from __spec__ or __package__, falling back on __name__ and __path__:ImportWarning + ignore:ast.Str is deprecated and will be removed in Python 3.14; use ast.Constant instead:DeprecationWarning + +[testenv:py312-flake8{4,5,6,7}] +download = True +setenv = + PYTHONDEVMODE=1 + PIP_DISABLE_PIP_VERSION_CHECK=1 + +[testenv:py313-flake8{4,5,6,7}] +download = True +setenv = + PYTHONDEVMODE=1 + PIP_DISABLE_PIP_VERSION_CHECK=1 + UNSAFE_PYO3_SKIP_VERSION_CHECK=1 [testenv:lint] basepython = python3.8 From b571897b599522eeff93175d6c2f23bd36657e93 Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Wed, 5 Feb 2025 10:08:14 +0000 Subject: [PATCH 099/105] Updated files with 'repo_helper'. (#61) Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- README.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d9288f5..3e8cfc9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -81,7 +81,7 @@ repos: - id: snippet-fmt - repo: https://github.com/python-formate/formate - rev: v0.7.0 + rev: v0.8.0 hooks: - id: formate exclude: ^(doc-source/conf|__pkginfo__|setup)\.(_)?py$ diff --git a/README.rst b/README.rst index 5214262..a965bec 100644 --- a/README.rst +++ b/README.rst @@ -89,7 +89,7 @@ flake8-github-actions :target: https://github.com/python-formate/flake8-github-actions/commit/master :alt: GitHub last commit -.. |maintained| image:: https://img.shields.io/maintenance/yes/2024 +.. |maintained| image:: https://img.shields.io/maintenance/yes/2025 :alt: Maintenance .. |pypi-downloads| image:: https://img.shields.io/pypi/dm/flake8-github-actions From e141251fa5efa1ba23e64890427f7062314c81c2 Mon Sep 17 00:00:00 2001 From: Dominic Davis-Foster Date: Tue, 8 Apr 2025 10:29:24 +0100 Subject: [PATCH 100/105] Drop support for Python 3.6 --- .github/workflows/python_ci.yml | 4 +--- .github/workflows/python_ci_linux.yml | 4 +--- .github/workflows/python_ci_macos.yml | 3 +-- pyproject.toml | 2 +- repo_helper.yml | 10 ---------- tox.ini | 4 ---- 6 files changed, 4 insertions(+), 23 deletions(-) diff --git a/.github/workflows/python_ci.yml b/.github/workflows/python_ci.yml index ae4c782..705c8b4 100644 --- a/.github/workflows/python_ci.yml +++ b/.github/workflows/python_ci.yml @@ -22,13 +22,12 @@ jobs: runs-on: "windows-2019" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11,3.12,3.13,pypy-3.6,pypy-3.7,pypy-3.8,pypy-3.9' + USING_COVERAGE: '3.7,3.8,3.9,3.10,3.11,3.12,3.13,pypy-3.7,pypy-3.8,pypy-3.9' strategy: fail-fast: False matrix: config: - - {python-version: "3.6", testenvs: "py36-flake8{4,5},build", experimental: False} - {python-version: "3.7", testenvs: "py37-flake8{4,5},build", experimental: False} - {python-version: "3.8", testenvs: "py38-flake8{4,5,6,7},build", experimental: False} - {python-version: "3.9", testenvs: "py39-flake8{4,5,6,7},build", experimental: False} @@ -36,7 +35,6 @@ jobs: - {python-version: "3.11", testenvs: "py311-flake8{4,5,6,7},build", experimental: False} - {python-version: "3.12", testenvs: "py312-flake8{6,7},build", experimental: False} - {python-version: "3.13", testenvs: "py313-flake8{6,7},build", experimental: False} - - {python-version: "pypy-3.6", testenvs: "pypy36-flake8{4,5}", experimental: False} - {python-version: "pypy-3.7", testenvs: "pypy37-flake8{4,5},build", experimental: False} - {python-version: "pypy-3.8", testenvs: "pypy38-flake8{4,5,6,7},build", experimental: False} - {python-version: "pypy-3.9-v7.3.15", testenvs: "pypy39-flake8{4,5,6,7},build", experimental: True} diff --git a/.github/workflows/python_ci_linux.yml b/.github/workflows/python_ci_linux.yml index 3da41d3..4ef0e94 100644 --- a/.github/workflows/python_ci_linux.yml +++ b/.github/workflows/python_ci_linux.yml @@ -23,13 +23,12 @@ jobs: runs-on: "ubuntu-20.04" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11,3.12,3.13,pypy-3.6,pypy-3.7,pypy-3.8,pypy-3.9' + USING_COVERAGE: '3.7,3.8,3.9,3.10,3.11,3.12,3.13,pypy-3.7,pypy-3.8,pypy-3.9' strategy: fail-fast: False matrix: config: - - {python-version: "3.6", testenvs: "py36-flake8{4,5},build", experimental: False} - {python-version: "3.7", testenvs: "py37-flake8{4,5},build", experimental: False} - {python-version: "3.8", testenvs: "py38-flake8{4,5,6,7},build", experimental: False} - {python-version: "3.9", testenvs: "py39-flake8{4,5,6,7},build", experimental: False} @@ -37,7 +36,6 @@ jobs: - {python-version: "3.11", testenvs: "py311-flake8{4,5,6,7},build", experimental: False} - {python-version: "3.12", testenvs: "py312-flake8{6,7},build", experimental: False} - {python-version: "3.13", testenvs: "py313-flake8{6,7},build", experimental: False} - - {python-version: "pypy-3.6", testenvs: "pypy36-flake8{4,5},build", experimental: False} - {python-version: "pypy-3.7", testenvs: "pypy37-flake8{4,5},build", experimental: False} - {python-version: "pypy-3.8", testenvs: "pypy38-flake8{4,5,6,7},build", experimental: False} - {python-version: "pypy-3.9", testenvs: "pypy39-flake8{4,5,6,7},build", experimental: True} diff --git a/.github/workflows/python_ci_macos.yml b/.github/workflows/python_ci_macos.yml index 9fb8c60..61b2264 100644 --- a/.github/workflows/python_ci_macos.yml +++ b/.github/workflows/python_ci_macos.yml @@ -22,13 +22,12 @@ jobs: runs-on: "macos-13" continue-on-error: ${{ matrix.config.experimental }} env: - USING_COVERAGE: '3.6,3.7,3.8,3.9,3.10,3.11,3.12,3.13,pypy-3.7,pypy-3.8,pypy-3.9' + USING_COVERAGE: '3.7,3.8,3.9,3.10,3.11,3.12,3.13,pypy-3.7,pypy-3.8,pypy-3.9' strategy: fail-fast: False matrix: config: - - {python-version: "3.6", testenvs: "py36-flake8{4,5},build", experimental: False} - {python-version: "3.7", testenvs: "py37-flake8{4,5},build", experimental: False} - {python-version: "3.8", testenvs: "py38-flake8{4,5,6,7},build", experimental: False} - {python-version: "3.9", testenvs: "py39-flake8{4,5,6,7},build", experimental: False} diff --git a/pyproject.toml b/pyproject.toml index 46f37c8..8fe3167 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,7 +34,7 @@ base-classifiers = [ "Intended Audience :: Developers", "Typing :: Typed", ] -python-versions = [ "3.6", "3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13",] +python-versions = [ "3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13",] python-implementations = [ "CPython", "PyPy",] platforms = [ "Windows", "macOS", "Linux",] license-key = "MIT" diff --git a/repo_helper.yml b/repo_helper.yml index 2d2b625..b23d943 100644 --- a/repo_helper.yml +++ b/repo_helper.yml @@ -18,11 +18,6 @@ pre_commit_exclude: "^tests/bad_code.py$" use_whey: true python_versions: - 3.6: - matrix_exclude: - flake8: - - 6 - - 7 3.7: matrix_exclude: flake8: @@ -42,11 +37,6 @@ python_versions: flake8: - 4 - 5 - pypy36: - matrix_exclude: - flake8: - - 6 - - 7 pypy37: matrix_exclude: flake8: diff --git a/tox.ini b/tox.ini index f01efdf..6969262 100644 --- a/tox.ini +++ b/tox.ini @@ -22,7 +22,6 @@ [tox] envlist = - py36-flake8{4,5} py37-flake8{4,5} py38-flake8{4,5,6,7} py39-flake8{4,5,6,7} @@ -30,7 +29,6 @@ envlist = py311-flake8{4,5,6,7} py312-flake8{6,7} py313-flake8{6,7} - pypy36-flake8{4,5} pypy37-flake8{4,5} pypy38-flake8{4,5,6,7} pypy39-flake8{4,5,6,7} @@ -46,7 +44,6 @@ requires = [envlists] test = - py36-flake8{4,5} py37-flake8{4,5} py38-flake8{4,5,6,7} py39-flake8{4,5,6,7} @@ -54,7 +51,6 @@ test = py311-flake8{4,5,6,7} py312-flake8{6,7} py313-flake8{6,7} - pypy36-flake8{4,5} pypy37-flake8{4,5} pypy38-flake8{4,5,6,7} pypy39-flake8{4,5,6,7} From 5a846cdbc59f07364ca10e12522d1161e1079fb0 Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Tue, 8 Apr 2025 14:31:38 +0100 Subject: [PATCH 101/105] Bump Ubuntu to 22.04 (#62) Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .github/workflows/mypy.yml | 2 +- .github/workflows/python_ci_linux.yml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/mypy.yml b/.github/workflows/mypy.yml index 10c6f30..bd74787 100644 --- a/.github/workflows/mypy.yml +++ b/.github/workflows/mypy.yml @@ -20,7 +20,7 @@ jobs: strategy: matrix: - os: ['ubuntu-20.04', 'windows-2019'] + os: ['ubuntu-22.04', 'windows-2019'] fail-fast: false steps: diff --git a/.github/workflows/python_ci_linux.yml b/.github/workflows/python_ci_linux.yml index 4ef0e94..6a5c928 100644 --- a/.github/workflows/python_ci_linux.yml +++ b/.github/workflows/python_ci_linux.yml @@ -19,8 +19,8 @@ permissions: jobs: tests: - name: "ubuntu-20.04 / Python ${{ matrix.config.python-version }}" - runs-on: "ubuntu-20.04" + name: "ubuntu-22.04 / Python ${{ matrix.config.python-version }}" + runs-on: "ubuntu-22.04" continue-on-error: ${{ matrix.config.experimental }} env: USING_COVERAGE: '3.7,3.8,3.9,3.10,3.11,3.12,3.13,pypy-3.7,pypy-3.8,pypy-3.9' @@ -84,7 +84,7 @@ jobs: Coverage: needs: tests - runs-on: "ubuntu-20.04" + runs-on: "ubuntu-22.04" steps: - name: Checkout 🛎️ uses: "actions/checkout@v4" @@ -133,7 +133,7 @@ jobs: Deploy: needs: tests - runs-on: "ubuntu-20.04" + runs-on: "ubuntu-22.04" steps: - name: Checkout 🛎️ uses: "actions/checkout@v4" From bf1268f4ba4fa6047bd4d94a1b0973de2d97f186 Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Wed, 9 Apr 2025 11:41:52 +0100 Subject: [PATCH 102/105] Run Flake8 CI on Ubuntu 22.04 (#63) Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .github/workflows/flake8.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/flake8.yml b/.github/workflows/flake8.yml index 0a8c0c3..af1b394 100644 --- a/.github/workflows/flake8.yml +++ b/.github/workflows/flake8.yml @@ -16,7 +16,7 @@ permissions: jobs: Run: name: "Flake8" - runs-on: "ubuntu-20.04" + runs-on: "ubuntu-22.04" steps: - name: Checkout 🛎️ From e9a8f4bbf0651bff3de15de65c8a33670b34aca5 Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Thu, 17 Apr 2025 16:55:08 +0100 Subject: [PATCH 103/105] Updated files with 'repo_helper'. (#64) Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .github/workflows/python_ci_macos.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/python_ci_macos.yml b/.github/workflows/python_ci_macos.yml index 61b2264..93ee2d5 100644 --- a/.github/workflows/python_ci_macos.yml +++ b/.github/workflows/python_ci_macos.yml @@ -18,8 +18,8 @@ permissions: jobs: tests: - name: "macos-13 / Python ${{ matrix.config.python-version }}" - runs-on: "macos-13" + name: "macos-${{ matrix.config.os-ver }} / Python ${{ matrix.config.python-version }}" + runs-on: "macos-${{ matrix.config.os-ver }}" continue-on-error: ${{ matrix.config.experimental }} env: USING_COVERAGE: '3.7,3.8,3.9,3.10,3.11,3.12,3.13,pypy-3.7,pypy-3.8,pypy-3.9' @@ -28,16 +28,16 @@ jobs: fail-fast: False matrix: config: - - {python-version: "3.7", testenvs: "py37-flake8{4,5},build", experimental: False} - - {python-version: "3.8", testenvs: "py38-flake8{4,5,6,7},build", experimental: False} - - {python-version: "3.9", testenvs: "py39-flake8{4,5,6,7},build", experimental: False} - - {python-version: "3.10", testenvs: "py310-flake8{4,5,6,7},build", experimental: False} - - {python-version: "3.11", testenvs: "py311-flake8{4,5,6,7},build", experimental: False} - - {python-version: "3.12", testenvs: "py312-flake8{6,7},build", experimental: False} - - {python-version: "3.13", testenvs: "py313-flake8{6,7},build", experimental: False} - - {python-version: "pypy-3.7", testenvs: "pypy37-flake8{4,5},build", experimental: False} - - {python-version: "pypy-3.8", testenvs: "pypy38-flake8{4,5,6,7},build", experimental: False} - - {python-version: "pypy-3.9", testenvs: "pypy39-flake8{4,5,6,7},build", experimental: True} + - {python-version: "3.7", os-ver: "13", testenvs: "py37-flake8{4,5},build", experimental: False} + - {python-version: "3.8", os-ver: "14", testenvs: "py38-flake8{4,5,6,7},build", experimental: False} + - {python-version: "3.9", os-ver: "14", testenvs: "py39-flake8{4,5,6,7},build", experimental: False} + - {python-version: "3.10", os-ver: "14", testenvs: "py310-flake8{4,5,6,7},build", experimental: False} + - {python-version: "3.11", os-ver: "14", testenvs: "py311-flake8{4,5,6,7},build", experimental: False} + - {python-version: "3.12", os-ver: "14", testenvs: "py312-flake8{6,7},build", experimental: False} + - {python-version: "3.13", os-ver: "14", testenvs: "py313-flake8{6,7},build", experimental: False} + - {python-version: "pypy-3.7", os-ver: "13", testenvs: "pypy37-flake8{4,5},build", experimental: False} + - {python-version: "pypy-3.8", os-ver: "14", testenvs: "pypy38-flake8{4,5,6,7},build", experimental: False} + - {python-version: "pypy-3.9", os-ver: "14", testenvs: "pypy39-flake8{4,5,6,7},build", experimental: True} steps: - name: Checkout 🛎️ From 27d67784a7711cbc71940f586fca8b76fb2722a0 Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Thu, 8 May 2025 21:36:12 +0100 Subject: [PATCH 104/105] Updated files with 'repo_helper'. (#65) Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- .github/workflows/python_ci.yml | 1 + .github/workflows/python_ci_linux.yml | 2 ++ .github/workflows/python_ci_macos.yml | 1 + .pre-commit-config.yaml | 2 +- 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/python_ci.yml b/.github/workflows/python_ci.yml index 705c8b4..cb345af 100644 --- a/.github/workflows/python_ci.yml +++ b/.github/workflows/python_ci.yml @@ -78,3 +78,4 @@ jobs: with: name: "coverage-${{ matrix.config.python-version }}" path: .coverage + include-hidden-files: true diff --git a/.github/workflows/python_ci_linux.yml b/.github/workflows/python_ci_linux.yml index 6a5c928..375441c 100644 --- a/.github/workflows/python_ci_linux.yml +++ b/.github/workflows/python_ci_linux.yml @@ -80,6 +80,7 @@ jobs: with: name: "coverage-${{ matrix.config.python-version }}" path: .coverage + include-hidden-files: true Coverage: @@ -122,6 +123,7 @@ jobs: with: name: "combined-coverage" path: .coverage + include-hidden-files: true - name: "Upload Combined Coverage to Coveralls" if: ${{ steps.show.outcome != 'failure' }} diff --git a/.github/workflows/python_ci_macos.yml b/.github/workflows/python_ci_macos.yml index 93ee2d5..ea5934c 100644 --- a/.github/workflows/python_ci_macos.yml +++ b/.github/workflows/python_ci_macos.yml @@ -78,3 +78,4 @@ jobs: with: name: "coverage-${{ matrix.config.python-version }}" path: .coverage + include-hidden-files: true diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3e8cfc9..e730967 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,7 +8,7 @@ ci: repos: - repo: https://github.com/repo-helper/pyproject-parser - rev: v0.11.1 + rev: v0.13.0 hooks: - id: reformat-pyproject From a8721450b76683325d84a10ec3c2fb72823feaed Mon Sep 17 00:00:00 2001 From: "repo-helper[bot]" <74742576+repo-helper[bot]@users.noreply.github.com> Date: Thu, 22 May 2025 16:33:24 +0100 Subject: [PATCH 105/105] Update contributing guide. (#66) Co-authored-by: repo-helper[bot] <74742576+repo-helper[bot]@users.noreply.github.com> --- CONTRIBUTING.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 98e5ffa..81ce059 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -38,11 +38,11 @@ Automated tests ------------------- Tests are run with ``tox`` and ``pytest``. -To run tests for a specific Python version, such as Python 3.6: +To run tests for a specific Python version, such as Python 3.10: .. code-block:: bash - $ tox -e py36 + $ tox -e py310 To run tests for all Python versions, simply run: