Repository: python-trio/flake8-async (language: python)

Issue:
install_require flake8>=6.0?
Should we update `setup.py` to require flake8>=6.0, or modify tests so they can run on both <6.0 and >=6.0 - so we can make sure that code doesn't break on <6.0? Should be unlikely, but given that this one completely snuck up on me it's probably worth taking into account.


Discussion / hints:
I think it's worth keeping install-time support for older versions of flake8; how about we modify the tests and add a dimension to our test matrix?
Sounds reasonable, will fix :+1: 

Fix patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 094281f..f69863e 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -11,10 +11,10 @@ jobs:
     runs-on: ubuntu-latest
     steps:
     - uses: actions/checkout@v3
-    - name: Set up Python 3.10
+    - name: Set up Python 3.11
       uses: actions/setup-python@v3
       with:
-        python-version: "3.10"
+        python-version: "3.11"
     - name: Install dependencies
       run: |
         python -m pip install --upgrade pip setuptools tox
@@ -28,7 +28,7 @@ jobs:
     runs-on: ubuntu-latest
     strategy:
       matrix:
-        python-version: ["3.8", "3.9", "3.10"]
+        python-version: ["3.8", "3.9", "3.10", "3.11"]
       fail-fast: false
     steps:
     - uses: actions/checkout@v3
@@ -39,9 +39,9 @@ jobs:
     - name: Install dependencies
       run: |
         python -m pip install --upgrade pip setuptools tox
-        python -m tox --notest --recreate -e test
+        python -m tox --notest --recreate -e flake8_5,flake8_6
     - name: Run tests
-      run: python -m tox -e test
+      run: python -m tox -e flake8_5,flake8_6
 
   release:
     runs-on: ubuntu-latest
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index e8eeeaa..1e87005 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -18,11 +18,11 @@ To run our test suite please use tox.
 # Formatting and Linting
 tox -e check
 # Test Running
-tox -e test
-# Run checks and tests against Python 3.8, 3.9 and 3.10
-tox -e ALL
-# Tip: Use -p (run tests in parallel) and --develop (install package with -e) to save time when modifying and rerunning
-tox -e ALL -p --develop
+tox -e py311
+# Run checks and all test environments (tox -a for a complete list)
+tox
+# Tip: Use -p (run tests in parallel), --develop (install package with -e), and -q to save time when modifying and rerunning
+tox -p --develop
 ```
 
 ## Meta-tests
diff --git a/setup.py b/setup.py
index b479774..9a156f7 100644
--- a/setup.py
+++ b/setup.py
@@ -22,7 +22,7 @@ def local_file(name: str) -> Path:
     name="flake8-trio",
     version=__version__,
     author="Zac Hatfield-Dodds and Contributors",
-    author_email="me@cooperlees.com",
+    author_email="zac@zhd.dev",
     py_modules=["flake8_trio"],
     url="https://github.com/Zac-HD/flake8-trio",
     license="MIT",
@@ -40,6 +40,7 @@ def local_file(name: str) -> Path:
         "Programming Language :: Python :: 3.8",
         "Programming Language :: Python :: 3.9",
         "Programming Language :: Python :: 3.10",
+        "Programming Language :: Python :: 3.11",
     ],
     long_description=(
         local_file("README.md").open().read()
diff --git a/tox.ini b/tox.ini
index d1b39de..c92524d 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,8 +1,7 @@
 # The test environment and commands
 [tox]
 # default environments to run without `-e`
-# `tox -e ALL` runs all environments
-envlist = check, test
+envlist = check, py{38,39,310,311}-{flake8_5,flake8_6}
 
 [testenv:check]
 description = Format code and run linters (quick)
@@ -31,12 +30,15 @@ ignore_errors =
 commands =
     shed
     flake8 --exclude .*,tests/trio*.py
-    pyright --pythonversion 3.10 --warnings
+    pyright --pythonversion 3.11 --warnings
 
-# generate py38-test py39-test and test
-[testenv:{py38-, py39-,}test]
+# create a default testenv, whose behaviour will depend on the name it's called with.
+# for CI you can call with `-e flake8_5,flake8_6` and let the CI handle python version
+[testenv]
 description = Runs pytest, optionally with posargs
 deps =
+    flake8_6: flake8>=6.0
+    flake8_5: flake8>=5.0,<6.0
     pytest
     pytest-cov
     #pytest-xdist
@@ -50,12 +52,14 @@ commands =
 # Settings for other tools
 [pytest]
 addopts =
-    -Werror
     --tb=native
     --cov=flake8_trio
     --cov-branch
     --cov-report=term-missing:skip-covered
     --cov-fail-under=100
+filterwarnings =
+    error
+
 
 [flake8]
 ignore = E501,W503
diff --git a/typings/flake8/__init__.pyi b/typings/flake8/__init__.pyi
new file mode 100644
index 0000000..6334cd2
--- /dev/null
+++ b/typings/flake8/__init__.pyi
@@ -0,0 +1,40 @@
+"""
+This type stub file was generated by pyright.
+"""
+
+import logging
+import sys
+from __future__ import annotations
+from typing import Tuple, Dict
+
+"""Top-level module for Flake8.
+
+This module
+
+- initializes logging for the command-line tool
+- tracks the version of the package
+- provides a way to configure logging for the command-line tool
+
+.. autofunction:: flake8.configure_logging
+
+"""
+LOG: logging.Logger = ...
+__version__: str = ...
+__version_info__: Tuple[int, ...] = ...
+_VERBOSITY_TO_LOG_LEVEL: Dict[int, int] = ...
+LOG_FORMAT: str = ...
+
+def configure_logging(
+    verbosity: int, filename: str | None = ..., logformat: str = ...
+) -> None:
+    """Configure logging for flake8.
+
+    :param verbosity:
+        How verbose to be in logging information.
+    :param filename:
+        Name of the file to append log information to.
+        If ``None`` this will log to ``sys.stderr``.
+        If the name is "stdout" or "stderr" this will log to the appropriate
+        stream.
+    """
+    ...
diff --git a/typings/flake8/options/manager.pyi b/typings/flake8/options/manager.pyi
index a3ab30b..166df6c 100644
--- a/typings/flake8/options/manager.pyi
+++ b/typings/flake8/options/manager.pyi
@@ -1,5 +1,6 @@
 """
 This type stub file was generated by pyright.
+Generated for flake8 5, so OptionManager signature is incorrect for flake8 6
 """
 
 import argparse


Test patch:
diff --git a/tests/test_flake8_trio.py b/tests/test_flake8_trio.py
index de38071..04772ef 100644
--- a/tests/test_flake8_trio.py
+++ b/tests/test_flake8_trio.py
@@ -11,6 +11,7 @@
 from typing import DefaultDict, Iterable, List, Sequence, Tuple, Type
 
 import pytest
+from flake8 import __version_info__ as flake8_version_info
 from flake8.options.manager import OptionManager
 
 # import trio  # type: ignore
@@ -32,6 +33,14 @@ class ParseError(Exception):
     ...
 
 
+# flake8 6 added a required named parameter formatter_names
+def _default_option_manager():
+    kwargs = {}
+    if flake8_version_info[0] >= 6:
+        kwargs["formatter_names"] = ["default"]
+    return OptionManager(version="", plugin_versions="", parents=[], **kwargs)
+
+
 # check for presence of _pyXX, skip if version is later, and prune parameter
 def check_version(test: str) -> str:
     python_version = re.search(r"(?<=_PY)\d*", test)
@@ -159,12 +168,7 @@ def read_file(test_file: str):
 
 def assert_expected_errors(plugin: Plugin, include: Iterable[str], *expected: Error):
     # initialize default option values
-    om = OptionManager(
-        version="",
-        plugin_versions="",
-        parents=[],
-        formatter_names=["default"],  # type: ignore
-    )
+    om = _default_option_manager()
     plugin.add_options(om)
     plugin.parse_options(om.parse_args(args=[""]))
 
@@ -366,12 +370,7 @@ def test_107_permutations():
 def test_113_options():
     # get default errors
     plugin = read_file("trio113.py")
-    om = OptionManager(
-        version="",
-        plugin_versions="",
-        parents=[],
-        formatter_names=["default"],  # type: ignore
-    )
+    om = _default_option_manager()
     plugin.add_options(om)
     plugin.parse_options(om.parse_args(args=["--startable-in-context-manager=''"]))
     default = {repr(e) for e in plugin.run() if e.code == "TRIO113"}