Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-flake8-pyi for 
openSUSE:Factory checked in at 2023-12-06 23:48:10
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-flake8-pyi (Old)
 and      /work/SRC/openSUSE:Factory/.python-flake8-pyi.new.25432 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-flake8-pyi"

Wed Dec  6 23:48:10 2023 rev:11 rq:1131208 version:23.11.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-flake8-pyi/python-flake8-pyi.changes      
2023-08-28 17:14:05.138216989 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-flake8-pyi.new.25432/python-flake8-pyi.changes
   2023-12-06 23:48:41.936300707 +0100
@@ -1,0 +2,33 @@
+Tue Dec  5 21:07:25 UTC 2023 - Dirk Müller <dmuel...@suse.com>
+
+- update to 23.11.0:
+  * Y058: Use `Iterator` rather than `Generator` as the return
+    value for simple `__iter__` methods, and `AsyncIterator` rather
+    than `AsyncGenerator` as the return value for simple `__aiter__`
+    methods.
+  * Y059: `Generic[]` should always be the last base class, if it
+    is present in the bases of a class.
+  * Y060, which flags redundant inheritance from `Generic[]`.
+  * Y061: Do not use `None` inside a `Literal[]` slice.
+  * For example, use `Literal["foo"] | None` instead of
+    `Literal["foo", None]`.
+  * Y022 and Y037 now flag more imports from `typing_extensions`.
+  * Y034 now attempts to avoid flagging methods inside classes
+    that inherit from `builtins.type`, `abc.ABCMeta` and/or
+    `enum.EnumMeta`.  Classes that have one or more of these as
+    bases are metaclasses, and PEP 673 forbids the use of
+    `typing(_extensions).Self` for metaclasses.
+  * Attempting to import `typing_extensions.Text` now causes Y039
+    to be emitted rather than Y023.
+  * Y053 will no longer be emitted for the argument to
+    `@typing_extensions.deprecated`.
+  * Introduce Y090, which warns if you have an annotation such as
+    `tuple[int]` or `Tuple[int]`. These mean "a tuple of length 1,
+    in which the sole element is of type `int`". This is sometimes
+    what you want, but more usually you'll want `tuple[int, ...]`,
+    which means "a tuple of arbitrary (possibly 0) length, in
+    which all elements are of type `int`".
+  * Y011 now ignores `sentinel` and `_typeshed.sentinel` in
+    default values.
+
+-------------------------------------------------------------------

Old:
----
  flake8_pyi-23.6.0.tar.gz

New:
----
  flake8_pyi-23.11.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-flake8-pyi.spec ++++++
--- /var/tmp/diff_new_pack.ghVi0W/_old  2023-12-06 23:48:42.900335548 +0100
+++ /var/tmp/diff_new_pack.ghVi0W/_new  2023-12-06 23:48:42.904335692 +0100
@@ -16,9 +16,9 @@
 #
 
 
-%define skip_python2 1
+%{?sle15_python_module_pythons}
 Name:           python-flake8-pyi
-Version:        23.6.0
+Version:        23.11.0
 Release:        0
 Summary:        A plugin for flake8 to enable linting .pyi files
 License:        MIT
@@ -30,6 +30,7 @@
 Patch0:         set-tests-python-path.patch
 BuildRequires:  %{python_module ast-decompiler}
 BuildRequires:  %{python_module base >= 3.8.0}
+BuildRequires:  %{python_module hatch_vcs}
 BuildRequires:  %{python_module hatchling}
 BuildRequires:  %{python_module pip}
 BuildRequires:  %{python_module wheel}
@@ -42,6 +43,7 @@
 BuildRequires:  %{python_module pytest}
 BuildRequires:  %{python_module black}
 BuildRequires:  %{python_module flake8-bugbear}
+BuildRequires:  %{python_module pytest-xdist}
 BuildRequires:  %{python_module typing}
 # /SECTION
 BuildRequires:  fdupes

++++++ flake8_pyi-23.6.0.tar.gz -> flake8_pyi-23.11.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/flake8_pyi-23.6.0/.flake8 
new/flake8_pyi-23.11.0/.flake8
--- old/flake8_pyi-23.6.0/.flake8       2020-02-02 01:00:00.000000000 +0100
+++ new/flake8_pyi-23.11.0/.flake8      2020-02-02 01:00:00.000000000 +0100
@@ -24,10 +24,10 @@
 #           produces false positives if you're surrounding things with double 
quotes
 
 [flake8]
+extend-select = B9
 max-line-length = 80
 max-complexity = 12
 noqa-require-code = true
-select = B,C,E,F,W,Y,B9,NQA
 per-file-ignores =
   *.py: B905, B907, B950, E203, E501, W503, W291, W293
   *.pyi: B, E301, E302, E305, E501, E701, E704, W503
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/flake8_pyi-23.6.0/.github/ISSUE_TEMPLATE/bug.md 
new/flake8_pyi-23.11.0/.github/ISSUE_TEMPLATE/bug.md
--- old/flake8_pyi-23.6.0/.github/ISSUE_TEMPLATE/bug.md 1970-01-01 
01:00:00.000000000 +0100
+++ new/flake8_pyi-23.11.0/.github/ISSUE_TEMPLATE/bug.md        2020-02-02 
01:00:00.000000000 +0100
@@ -0,0 +1,5 @@
+---
+name: Bug report
+about: Report a bug
+labels: type-bug
+---
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/flake8_pyi-23.6.0/.github/ISSUE_TEMPLATE/docs.md 
new/flake8_pyi-23.11.0/.github/ISSUE_TEMPLATE/docs.md
--- old/flake8_pyi-23.6.0/.github/ISSUE_TEMPLATE/docs.md        1970-01-01 
01:00:00.000000000 +0100
+++ new/flake8_pyi-23.11.0/.github/ISSUE_TEMPLATE/docs.md       2020-02-02 
01:00:00.000000000 +0100
@@ -0,0 +1,5 @@
+---
+name: Documentation
+about: Report an issue with our docs
+labels: type-documentation
+---
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/flake8_pyi-23.6.0/.github/ISSUE_TEMPLATE/feature.md 
new/flake8_pyi-23.11.0/.github/ISSUE_TEMPLATE/feature.md
--- old/flake8_pyi-23.6.0/.github/ISSUE_TEMPLATE/feature.md     1970-01-01 
01:00:00.000000000 +0100
+++ new/flake8_pyi-23.11.0/.github/ISSUE_TEMPLATE/feature.md    2020-02-02 
01:00:00.000000000 +0100
@@ -0,0 +1,5 @@
+---
+name: Feature request
+about: Suggest a new feature
+labels: type-feature
+---
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/flake8_pyi-23.6.0/.github/workflows/check.yml 
new/flake8_pyi-23.11.0/.github/workflows/check.yml
--- old/flake8_pyi-23.6.0/.github/workflows/check.yml   2020-02-02 
01:00:00.000000000 +0100
+++ new/flake8_pyi-23.11.0/.github/workflows/check.yml  2020-02-02 
01:00:00.000000000 +0100
@@ -29,15 +29,16 @@
     timeout-minutes: 5
     strategy:
       matrix:
-        python-version: ["3.8", "3.11"]
+        python-version: ["3.8", "3.12"]
       fail-fast: false
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - uses: actions/setup-python@v4
         with:
           python-version: ${{ matrix.python-version }}
           cache: pip
           cache-dependency-path: pyproject.toml
+          allow-prereleases: true
       - run: pip install -e .[dev]
       - run: mypy
 
@@ -46,7 +47,7 @@
     runs-on: ubuntu-latest
     timeout-minutes: 5
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - uses: actions/setup-python@v4
         with:
           python-version: "3.11"
@@ -66,7 +67,7 @@
         python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
       fail-fast: false
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - uses: actions/setup-python@v4
         with:
           python-version: ${{ matrix.python-version }}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/flake8_pyi-23.6.0/.github/workflows/publish.yml 
new/flake8_pyi-23.11.0/.github/workflows/publish.yml
--- old/flake8_pyi-23.6.0/.github/workflows/publish.yml 2020-02-02 
01:00:00.000000000 +0100
+++ new/flake8_pyi-23.11.0/.github/workflows/publish.yml        2020-02-02 
01:00:00.000000000 +0100
@@ -12,8 +12,11 @@
   build-n-publish:
     name: Build and publish Python distributions to PyPI
     runs-on: ubuntu-20.04
+    permissions:
+      # needed for PyPI trusted publishing
+      id-token: write
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - name: Set up Python 3.10
         uses: actions/setup-python@v4
         with:
@@ -35,5 +38,3 @@
       - name: Publish distribution to PyPI
         if: startsWith(github.ref, 'refs/tags')
         uses: pypa/gh-action-pypi-publish@release/v1
-        with:
-          password: ${{ secrets.PYPI_API_TOKEN }}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/flake8_pyi-23.6.0/.github/workflows/typeshed_primer.yml 
new/flake8_pyi-23.11.0/.github/workflows/typeshed_primer.yml
--- old/flake8_pyi-23.6.0/.github/workflows/typeshed_primer.yml 2020-02-02 
01:00:00.000000000 +0100
+++ new/flake8_pyi-23.11.0/.github/workflows/typeshed_primer.yml        
2020-02-02 01:00:00.000000000 +0100
@@ -23,16 +23,16 @@
     runs-on: ubuntu-latest
     steps:
       - name: Checkout flake8-pyi on target branch
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
         with:
           ref: ${{ github.base_ref }}
           path: old_plugin
       - name: Checkout flake8-pyi on PR branch
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
         with:
           path: new_plugin
       - name: Checkout typeshed
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
         with:
           repository: python/typeshed
           path: typeshed
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/flake8_pyi-23.6.0/.github/workflows/typeshed_primer_comment.yml 
new/flake8_pyi-23.11.0/.github/workflows/typeshed_primer_comment.yml
--- old/flake8_pyi-23.6.0/.github/workflows/typeshed_primer_comment.yml 
2020-02-02 01:00:00.000000000 +0100
+++ new/flake8_pyi-23.11.0/.github/workflows/typeshed_primer_comment.yml        
2020-02-02 01:00:00.000000000 +0100
@@ -17,7 +17,7 @@
     if: ${{ github.event.workflow_run.conclusion == 'success' }}
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - name: Download errors
         uses: actions/github-script@v6
         with:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/flake8_pyi-23.6.0/.pre-commit-config.yaml 
new/flake8_pyi-23.11.0/.pre-commit-config.yaml
--- old/flake8_pyi-23.6.0/.pre-commit-config.yaml       2020-02-02 
01:00:00.000000000 +0100
+++ new/flake8_pyi-23.11.0/.pre-commit-config.yaml      2020-02-02 
01:00:00.000000000 +0100
@@ -1,6 +1,6 @@
 repos:
   - repo: https://github.com/pre-commit/pre-commit-hooks
-    rev: v4.4.0  # must match pyproject.toml
+    rev: v4.5.0  # must match pyproject.toml
     hooks:
       - id: trailing-whitespace
       - id: end-of-file-fixer
@@ -8,8 +8,8 @@
       - id: check-toml
       - id: check-merge-conflict
       - id: mixed-line-ending
-  - repo: https://github.com/psf/black
-    rev: 23.3.0 # must match pyproject.toml
+  - repo: https://github.com/psf/black-pre-commit-mirror
+    rev: 23.9.1 # must match pyproject.toml
     hooks:
       - id: black
         language_version: python3.8
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/flake8_pyi-23.6.0/CHANGELOG.md 
new/flake8_pyi-23.11.0/CHANGELOG.md
--- old/flake8_pyi-23.6.0/CHANGELOG.md  2020-02-02 01:00:00.000000000 +0100
+++ new/flake8_pyi-23.11.0/CHANGELOG.md 2020-02-02 01:00:00.000000000 +0100
@@ -1,5 +1,48 @@
 # Change Log
 
+## 23.11.0
+
+New error codes:
+* Y058: Use `Iterator` rather than `Generator` as the return value
+  for simple `__iter__` methods, and `AsyncIterator` rather than
+  `AsyncGenerator` as the return value for simple `__aiter__` methods.
+* Y059: `Generic[]` should always be the last base class, if it is
+  present in the bases of a class.
+* Y060, which flags redundant inheritance from `Generic[]`.
+* Y061: Do not use `None` inside a `Literal[]` slice.
+  For example, use `Literal["foo"] | None` instead of `Literal["foo", None]`.
+
+Other changes:
+* The undocumented `pyi.__version__` and `pyi.PyiTreeChecker.version`
+  attributes has been removed. Use `flake8 --version` from the command line, or
+  `importlib.metadata.version("flake8_pyi")` at runtime, to determine the
+  version of `flake8-pyi` installed at runtime.
+* Y038 now flags `from typing_extensions import AbstractSet` as well as
+  `from typing import AbstractSet`.
+* Y022 and Y037 now flag more imports from `typing_extensions`.
+* Y034 now attempts to avoid flagging methods inside classes that inherit from
+  `builtins.type`, `abc.ABCMeta` and/or `enum.EnumMeta`. Classes that have one
+  or more of these as bases are metaclasses, and PEP 673
+  [forbids the use of 
`typing(_extensions).Self`](https://peps.python.org/pep-0673/#valid-locations-for-self)
+  for metaclasses. While reliably determining whether a class is a metaclass in
+  all cases would be impossible for flake8-pyi, the new heuristics should
+  reduce the number of false positives from this check.
+* Attempting to import `typing_extensions.Text` now causes Y039 to be emitted
+  rather than Y023.
+* Y053 will no longer be emitted for the argument to 
`@typing_extensions.deprecated`.
+
+## 23.10.0
+
+* Introduce Y090, which warns if you have an annotation such as `tuple[int]` or
+  `Tuple[int]`. These mean "a tuple of length 1, in which the sole element is
+  of type `int`". This is sometimes what you want, but more usually you'll want
+  `tuple[int, ...]`, which means "a tuple of arbitrary (possibly 0) length, in
+  which all elements are of type `int`".
+
+  This error code is disabled by default due to the risk of false-positive
+  errors. To enable it, use the `--extend-select=Y090` option.
+* Y011 now ignores `sentinel` and `_typeshed.sentinel` in default values.
+
 ## 23.6.0
 
 Features:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/flake8_pyi-23.6.0/CONTRIBUTING.md 
new/flake8_pyi-23.11.0/CONTRIBUTING.md
--- old/flake8_pyi-23.6.0/CONTRIBUTING.md       2020-02-02 01:00:00.000000000 
+0100
+++ new/flake8_pyi-23.11.0/CONTRIBUTING.md      2020-02-02 01:00:00.000000000 
+0100
@@ -51,8 +51,7 @@
 
 Releasing a new version is easy:
 
-- Make a PR that updates the version header in `CHANGELOG.md`
-  and the `__version__` attribute in `pyi.py`.
+- Make a PR that updates the version header in `CHANGELOG.md`.
 - Merge the PR and wait for tests to complete.
 - Draft a release using the GitHub UI. The tag name should be
   identical to the version (e.g., `22.1.0`) and the release notes
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/flake8_pyi-23.6.0/ERRORCODES.md 
new/flake8_pyi-23.11.0/ERRORCODES.md
--- old/flake8_pyi-23.6.0/ERRORCODES.md 2020-02-02 01:00:00.000000000 +0100
+++ new/flake8_pyi-23.11.0/ERRORCODES.md        2020-02-02 01:00:00.000000000 
+0100
@@ -1,6 +1,6 @@
 ## List of warnings
 
-The following warnings are currently emitted:
+The following warnings are currently emitted by default:
 
 | Code | Description
 |------|-------------
@@ -39,9 +39,9 @@
 | Y034 | Y034 detects common errors where certain methods are annotated as 
having a fixed return type, despite returning `self` at runtime. Such methods 
should be annotated with `typing_extensions.Self`. This check looks 
for:<br><br>&nbsp;&nbsp;**1.**&nbsp;&nbsp;Any in-place BinOp dunder methods 
(`__iadd__`, `__ior__`, etc.) that do not return 
`Self`.<br>&nbsp;&nbsp;**2.**&nbsp;&nbsp;`__new__`, `__enter__` and 
`__aenter__` methods that return the class's name 
unparameterised.<br>&nbsp;&nbsp;**3.**&nbsp;&nbsp;`__iter__` methods that 
return `Iterator`, even if the class inherits directly from 
`Iterator`.<br>&nbsp;&nbsp;**4.**&nbsp;&nbsp;`__aiter__` methods that return 
`AsyncIterator`, even if the class inherits directly from 
`AsyncIterator`.<br><br>This check excludes methods decorated with `@overload` 
or `@abstractmethod`.
 | Y035 | `__all__`, `__match_args__` and `__slots__` in a stub file should 
always have values, as these special variables in a `.pyi` file have identical 
semantics in a stub as at runtime. E.g. write `__all__ = ["foo", "bar"]` 
instead of `__all__: list[str]`.
 | Y036 | Y036 detects common errors in `__exit__` and `__aexit__` methods. For 
example, the first argument in an `__exit__` method should either be annotated 
with `object`, `_typeshed.Unused` (a special alias for `object`) or 
`type[BaseException] \| None`.
-| Y037 | Use PEP 604 syntax instead of `typing.Union` and `typing.Optional`. 
E.g. use `str \| int` instead of `Union[str, int]`, and use `str \| None` 
instead of `Optional[str]`.
-| Y038 | Use `from collections.abc import Set as AbstractSet` instead of `from 
typing import AbstractSet`.
-| Y039 | Use `str` instead of `typing.Text`.
+| Y037 | Use PEP 604 syntax instead of `typing(_extensions).Union` and 
`typing(_extensions).Optional`. E.g. use `str \| int` instead of `Union[str, 
int]`, and use `str \| None` instead of `Optional[str]`.
+| Y038 | Use `from collections.abc import Set as AbstractSet` instead of `from 
typing import AbstractSet` or `from typing_extensions import AbstractSet`.
+| Y039 | Use `str` instead of `typing.Text` or `typing_extensions.Text`.
 | Y040 | Never explicitly inherit from `object`, as all classes implicitly 
inherit from `object` in Python 3.
 | Y041 | Y041 detects redundant numeric unions in the context of parameter 
annotations. For example, PEP 484 specifies that type checkers should allow 
`int` objects to be passed to a function, even if the function states that it 
accepts a `float`. As such, `int` is redundant in the union `int \| float` in 
the context of a parameter annotation. In the same way, `int` is sometimes 
redundant in the union `int \| complex`, and `float` is sometimes redundant in 
the union `float \| complex`.
 | Y042 | Type alias names should use CamelCase rather than snake_case.
@@ -60,3 +60,22 @@
 | Y055 | Unions of the form `type[X] \| type[Y]` can be simplified to `type[X 
\| Y]`. Similarly, `Union[type[X], type[Y]]` can be simplified to 
`type[Union[X, Y]]`.
 | Y056 | Do not call methods such as `.append()`, `.extend()` or `.remove()` 
on `__all__`. Different type checkers have varying levels of support for 
calling these methods on `__all__`. Use `+=` instead, which is known to be 
supported by all major type checkers.
 | Y057 | Do not use `typing.ByteString` or `collections.abc.ByteString`. These 
types have unclear semantics, and are deprecated; use  
`typing_extensions.Buffer` or a union such as `bytes \| bytearray \| 
memoryview` instead. See [PEP 688](https://peps.python.org/pep-0688/) for more 
details.
+| Y058 | Use `Iterator` rather than `Generator` as the return value for simple 
`__iter__` methods, and `AsyncIterator` rather than `AsyncGenerator` as the 
return value for simple `__aiter__` methods. Using `(Async)Iterator` for these 
methods is simpler and more elegant, and reflects the fact that the precise 
kind of iterator returned from an `__iter__` method is usually an 
implementation detail that could change at any time, and should not be relied 
upon.
+| Y059 | `Generic[]` should always be the last base class, if it is present in 
a class's bases tuple. At runtime, if `Generic[]` is not the final class in a 
the bases tuple, this [can cause the class creation to 
fail](https://github.com/python/cpython/issues/106102). In a stub file, 
however, this rule is enforced purely for stylistic consistency.
+| Y060 | Redundant inheritance from `Generic[]`. For example, `class 
Foo(Iterable[_T], Generic[_T]): ...` can be written more simply as `class 
Foo(Iterable[_T]): ...`.<br><br>To avoid false-positive errors, and to avoid 
complexity in the implementation, this check is deliberately conservative: it 
only flags classes where all subscripted bases have identical code inside their 
subscript slices.
+| Y061 | Do not use `None` inside a `Literal[]` slice. For example, use 
`Literal["foo"] \| None` instead of `Literal["foo", None]`. While both are 
legal according to [PEP 586](https://peps.python.org/pep-0586/), the former is 
preferred for stylistic consistency.
+
+## Warnings disabled by default
+
+The following error codes are also provided, but are disabled by default due to
+the risk of false-positive errors. To enable these error codes, use
+`--extend-select={code1,code2,...}` on the command line or in your flake8
+configuration file.
+
+Note that `--extend-select` **will not work** if you have
+`--select` specified on the command line or in your configuration file. We
+recommend only using `--extend-select`, never `--select`.
+
+| Code | Description
+|------|------------
+| Y090 | `tuple[int]` means "a tuple of length 1, in which the sole element is 
of type `int`". Consider using `tuple[int, ...]` instead, which means "a tuple 
of arbitrary (possibly 0) length, in which all elements are of type `int`".
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/flake8_pyi-23.6.0/PKG-INFO 
new/flake8_pyi-23.11.0/PKG-INFO
--- old/flake8_pyi-23.6.0/PKG-INFO      2020-02-02 01:00:00.000000000 +0100
+++ new/flake8_pyi-23.11.0/PKG-INFO     2020-02-02 01:00:00.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: flake8-pyi
-Version: 23.6.0
+Version: 23.11.0
 Summary: A plugin for flake8 to enable linting .pyi stub files.
 Project-URL: Homepage, https://github.com/PyCQA/flake8-pyi
 Project-URL: Source, https://github.com/PyCQA/flake8-pyi
@@ -32,13 +32,14 @@
 Requires-Dist: flake8<7.0.0,>=6.0.0
 Requires-Dist: pyflakes>=2.1.1
 Provides-Extra: dev
-Requires-Dist: black==23.3.0; extra == 'dev'
-Requires-Dist: flake8-bugbear==23.6.5; extra == 'dev'
+Requires-Dist: black==23.9.1; extra == 'dev'
+Requires-Dist: flake8-bugbear==23.9.16; extra == 'dev'
 Requires-Dist: flake8-noqa==1.3.2; extra == 'dev'
 Requires-Dist: isort==5.12.0; extra == 'dev'
-Requires-Dist: mypy==1.4.1; extra == 'dev'
-Requires-Dist: pre-commit-hooks==4.4.0; extra == 'dev'
-Requires-Dist: pytest==7.4.0; extra == 'dev'
+Requires-Dist: mypy==1.6.0; extra == 'dev'
+Requires-Dist: pre-commit-hooks==4.5.0; extra == 'dev'
+Requires-Dist: pytest-xdist==3.3.1; extra == 'dev'
+Requires-Dist: pytest==7.4.2; extra == 'dev'
 Requires-Dist: types-pyflakes<4; extra == 'dev'
 Description-Content-Type: text/markdown
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/flake8_pyi-23.6.0/pyi.py 
new/flake8_pyi-23.11.0/pyi.py
--- old/flake8_pyi-23.6.0/pyi.py        2020-02-02 01:00:00.000000000 +0100
+++ new/flake8_pyi-23.11.0/pyi.py       2020-02-02 01:00:00.000000000 +0100
@@ -12,7 +12,7 @@
 from copy import deepcopy
 from dataclasses import dataclass
 from functools import partial
-from itertools import chain, zip_longest
+from itertools import chain, groupby, zip_longest
 from keyword import iskeyword
 from typing import TYPE_CHECKING, Any, ClassVar, NamedTuple, Union
 
@@ -37,8 +37,6 @@
     # and mypy thinks typing_extensions is part of the stdlib.
     from typing_extensions import Literal, TypeAlias, TypeGuard
 
-__version__ = "23.6.0"
-
 LOG = logging.getLogger("flake8.pyi")
 
 if sys.version_info >= (3, 12):
@@ -64,102 +62,89 @@
     name: str
 
 
+def all_equal(iterable: Iterable[object]) -> bool:
+    """Returns True if all the elements are equal to each other.
+
+    Adapted from the CPython itertools documentation."""
+    g = groupby(iterable)
+    next(g, True)
+    return not next(g, False)
+
+
 _MAPPING_SLICE = "KeyType, ValueType"
-_TYPE_SLICE = "MyClass"
-_COUNTER_SLICE = "KeyType"
-_COROUTINE_SLICE = "YieldType, SendType, ReturnType"
-_ASYNCGEN_SLICE = "YieldType, SendType"
 
 # Y022: Use stdlib imports instead of aliases from typing/typing_extensions
 _BAD_Y022_IMPORTS: dict[str, tuple[str, str | None]] = {
-    # typing aliases for collections
-    "typing.Counter": ("collections.Counter", _COUNTER_SLICE),
-    "typing.Deque": ("collections.deque", "T"),
-    "typing.DefaultDict": ("collections.defaultdict", _MAPPING_SLICE),
-    "typing.ChainMap": ("collections.ChainMap", _MAPPING_SLICE),
-    "typing.OrderedDict": ("collections.OrderedDict", _MAPPING_SLICE),
-    # typing aliases for builtins
-    "typing.Dict": ("dict", _MAPPING_SLICE),
-    "typing.FrozenSet": ("frozenset", "T"),
-    "typing.List": ("list", "T"),
-    "typing.Set": ("set", "T"),
-    "typing.Tuple": ("tuple", "Foo, Bar"),
-    "typing.Type": ("type", _TYPE_SLICE),
-    # typing aliases for contextlib
-    "typing.ContextManager": ("contextlib.AbstractContextManager", "T"),
-    "typing.AsyncContextManager": ("contextlib.AbstractAsyncContextManager", 
"T"),
-    # typing aliases for re
-    "typing.Match": ("re.Match", "T"),
-    "typing.Pattern": ("re.Pattern", "T"),
-    # typing_extensions aliases for collections
-    "typing_extensions.Counter": ("collections.Counter", _COUNTER_SLICE),
-    "typing_extensions.Deque": ("collections.deque", "T"),
-    "typing_extensions.DefaultDict": ("collections.defaultdict", 
_MAPPING_SLICE),
-    "typing_extensions.ChainMap": ("collections.ChainMap", _MAPPING_SLICE),
-    "typing_extensions.OrderedDict": ("collections.OrderedDict", 
_MAPPING_SLICE),
-    # One typing_extensions alias for a builtin
-    "typing_extensions.Type": ("type", _TYPE_SLICE),
-    # Typing_extensions aliases for contextlib
-    "typing_extensions.ContextManager": ("contextlib.AbstractContextManager", 
"T"),
-    "typing_extensions.AsyncContextManager": (
-        "contextlib.AbstractAsyncContextManager",
-        "T",
-    ),
-    # typing aliases for collections.abc
-    # typing.AbstractSet and typing.ByteString are deliberately omitted
+    # Aliases for collections
+    "Counter": ("collections.Counter", "KeyType"),
+    "Deque": ("collections.deque", "T"),
+    "DefaultDict": ("collections.defaultdict", _MAPPING_SLICE),
+    "ChainMap": ("collections.ChainMap", _MAPPING_SLICE),
+    "OrderedDict": ("collections.OrderedDict", _MAPPING_SLICE),
+    # Aliases for builtins
+    "Dict": ("dict", _MAPPING_SLICE),
+    "FrozenSet": ("frozenset", "T"),
+    "List": ("list", "T"),
+    "Set": ("set", "T"),
+    "Tuple": ("tuple", "Foo, Bar"),
+    "Type": ("type", "MyClass"),
+    # Aliases for contextlib
+    "ContextManager": ("contextlib.AbstractContextManager", "T"),
+    "AsyncContextManager": ("contextlib.AbstractAsyncContextManager", "T"),
+    # Aliases for re
+    "Match": ("re.Match", "T"),
+    "Pattern": ("re.Pattern", "T"),
+    # Aliases for collections.abc
+    # AbstractSet and ByteString are deliberately omitted
     # (special-cased elsewhere).
     # If the second element of the tuple is `None`,
     # it signals that the object shouldn't be parameterized
-    "typing.Collection": ("collections.abc.Collection", "T"),
-    "typing.ItemsView": ("collections.abc.ItemsView", _MAPPING_SLICE),
-    "typing.KeysView": ("collections.abc.KeysView", "KeyType"),
-    "typing.Mapping": ("collections.abc.Mapping", _MAPPING_SLICE),
-    "typing.MappingView": ("collections.abc.MappingView", None),
-    "typing.MutableMapping": ("collections.abc.MutableMapping", 
_MAPPING_SLICE),
-    "typing.MutableSequence": ("collections.abc.MutableSequence", "T"),
-    "typing.MutableSet": ("collections.abc.MutableSet", "T"),
-    "typing.Sequence": ("collections.abc.Sequence", "T"),
-    "typing.ValuesView": ("collections.abc.ValuesView", "ValueType"),
-    "typing.Iterable": ("collections.abc.Iterable", "T"),
-    "typing.Iterator": ("collections.abc.Iterator", "T"),
-    "typing.Generator": (
-        "collections.abc.Generator",
-        "YieldType, SendType, ReturnType",
-    ),
-    "typing.Hashable": ("collections.abc.Hashable", None),
-    "typing.Reversible": ("collections.abc.Reversible", "T"),
-    "typing.Sized": ("collections.abc.Sized", None),
-    "typing.Coroutine": ("collections.abc.Coroutine", _COROUTINE_SLICE),
-    "typing.AsyncGenerator": ("collections.abc.AsyncGenerator", 
_ASYNCGEN_SLICE),
-    "typing.AsyncIterator": ("collections.abc.AsyncIterator", "T"),
-    "typing.AsyncIterable": ("collections.abc.AsyncIterable", "T"),
-    "typing.Awaitable": ("collections.abc.Awaitable", "T"),
-    "typing.Callable": ("collections.abc.Callable", None),
-    "typing.Container": ("collections.abc.Container", "T"),
-    # typing_extensions aliases for collections.abc
-    "typing_extensions.Awaitable": ("collections.abc.Awaitable", "T"),
-    "typing_extensions.Coroutine": ("collections.abc.Coroutine", 
_COROUTINE_SLICE),
-    "typing_extensions.AsyncIterable": ("collections.abc.AsyncIterable", "T"),
-    "typing_extensions.AsyncIterator": ("collections.abc.AsyncIterator", "T"),
-    "typing_extensions.AsyncGenerator": (
-        "collections.abc.AsyncGenerator",
-        _ASYNCGEN_SLICE,
-    ),
+    "Collection": ("collections.abc.Collection", "T"),
+    "ItemsView": ("collections.abc.ItemsView", _MAPPING_SLICE),
+    "KeysView": ("collections.abc.KeysView", "KeyType"),
+    "Mapping": ("collections.abc.Mapping", _MAPPING_SLICE),
+    "MappingView": ("collections.abc.MappingView", None),
+    "MutableMapping": ("collections.abc.MutableMapping", _MAPPING_SLICE),
+    "MutableSequence": ("collections.abc.MutableSequence", "T"),
+    "MutableSet": ("collections.abc.MutableSet", "T"),
+    "Sequence": ("collections.abc.Sequence", "T"),
+    "ValuesView": ("collections.abc.ValuesView", "ValueType"),
+    "Iterable": ("collections.abc.Iterable", "T"),
+    "Iterator": ("collections.abc.Iterator", "T"),
+    "Generator": ("collections.abc.Generator", "YieldType, SendType, 
ReturnType"),
+    "Hashable": ("collections.abc.Hashable", None),
+    "Reversible": ("collections.abc.Reversible", "T"),
+    "Sized": ("collections.abc.Sized", None),
+    "Coroutine": ("collections.abc.Coroutine", "YieldType, SendType, 
ReturnType"),
+    "AsyncGenerator": ("collections.abc.AsyncGenerator", "YieldType, 
SendType"),
+    "AsyncIterator": ("collections.abc.AsyncIterator", "T"),
+    "AsyncIterable": ("collections.abc.AsyncIterable", "T"),
+    "Awaitable": ("collections.abc.Awaitable", "T"),
+    "Callable": ("collections.abc.Callable", None),
+    "Container": ("collections.abc.Container", "T"),
 }
 
 # Y023: Import things from typing instead of typing_extensions
 # if they're available from the typing module on 3.7+
 _BAD_TYPINGEXTENSIONS_Y023_IMPORTS = frozenset(
     {
+        "AnyStr",
+        "BinaryIO",
+        "ForwardRef",
+        "Generic",
+        "IO",
         "Protocol",
+        "TextIO",
         "runtime_checkable",
         "NewType",
         "overload",
-        "Text",
         "NoReturn",
         # ClassVar deliberately omitted,
         # as it's the only one in this group that should be parameterised.
         # It is special-cased elsewhere.
+        #
+        # Text is also deliberately omitted,
+        # as you shouldn't be importing it from anywhere! (Y039)
     }
 )
 
@@ -284,6 +269,7 @@
 
 
 _TYPING_MODULES = frozenset({"typing", "typing_extensions"})
+_TYPING_OR_COLLECTIONS_ABC = _TYPING_MODULES | {"collections.abc"}
 
 
 def _is_object(node: ast.AST | None, name: str, *, from_: Container[str]) -> 
bool:
@@ -295,8 +281,7 @@
         where <parent> is a string that can be found within the `from_` 
collection of
         strings.
 
-    >>> modules = _TYPING_MODULES | {"collections.abc"}
-    >>> _is_AsyncIterator = partial(_is_object, name="AsyncIterator", 
from_=modules)
+    >>> _is_AsyncIterator = partial(_is_object, name="AsyncIterator", 
from_=_TYPING_OR_COLLECTIONS_ABC)
     >>> _is_AsyncIterator(_ast_node_for("AsyncIterator"))
     True
     >>> _is_AsyncIterator(_ast_node_for("typing.AsyncIterator"))
@@ -323,12 +308,15 @@
 _is_BaseException = partial(_is_object, name="BaseException", 
from_={"builtins"})
 _is_TypeAlias = partial(_is_object, name="TypeAlias", from_=_TYPING_MODULES)
 _is_NamedTuple = partial(_is_object, name="NamedTuple", from_=_TYPING_MODULES)
+_is_deprecated = partial(
+    _is_object, name="deprecated", from_={"typing_extensions", "warnings"}
+)
 _is_TypedDict = partial(
     _is_object, name="TypedDict", from_=_TYPING_MODULES | {"mypy_extensions"}
 )
 _is_Literal = partial(_is_object, name="Literal", from_=_TYPING_MODULES)
 _is_abstractmethod = partial(_is_object, name="abstractmethod", from_={"abc"})
-_is_Any = partial(_is_object, name="Any", from_={"typing"})
+_is_Any = partial(_is_object, name="Any", from_=_TYPING_MODULES)
 _is_overload = partial(_is_object, name="overload", from_=_TYPING_MODULES)
 _is_final = partial(_is_object, name="final", from_=_TYPING_MODULES)
 _is_Self = partial(_is_object, name="Self", from_=({"_typeshed"} | 
_TYPING_MODULES))
@@ -336,13 +324,18 @@
 _is_builtins_object = partial(_is_object, name="object", from_={"builtins"})
 _is_builtins_type = partial(_is_object, name="type", from_={"builtins"})
 _is_Unused = partial(_is_object, name="Unused", from_={"_typeshed"})
-_is_Iterable = partial(_is_object, name="Iterable", from_={"typing", 
"collections.abc"})
+_is_Iterable = partial(_is_object, name="Iterable", 
from_=_TYPING_OR_COLLECTIONS_ABC)
 _is_AsyncIterable = partial(
-    _is_object, name="AsyncIterable", from_={"collections.abc"} | 
_TYPING_MODULES
+    _is_object, name="AsyncIterable", from_=_TYPING_OR_COLLECTIONS_ABC
 )
 _is_Protocol = partial(_is_object, name="Protocol", from_=_TYPING_MODULES)
 _is_NoReturn = partial(_is_object, name="NoReturn", from_=_TYPING_MODULES)
 _is_Final = partial(_is_object, name="Final", from_=_TYPING_MODULES)
+_is_Generator = partial(_is_object, name="Generator", 
from_=_TYPING_OR_COLLECTIONS_ABC)
+_is_AsyncGenerator = partial(
+    _is_object, name="AsyncGenerator", from_=_TYPING_OR_COLLECTIONS_ABC
+)
+_is_Generic = partial(_is_object, name="Generic", from_=_TYPING_MODULES)
 
 
 def _is_object_or_Unused(node: ast.expr | None) -> bool:
@@ -473,7 +466,7 @@
     if not isinstance(node, ast.Subscript):
         return None
     return _get_name_of_class_if_from_modules(
-        node.value, modules=_TYPING_MODULES | {"collections.abc"}
+        node.value, modules=_TYPING_OR_COLLECTIONS_ABC
     )
 
 
@@ -500,6 +493,11 @@
     method: ast.FunctionDef | ast.AsyncFunctionDef, *, classdef: ast.ClassDef
 ) -> bool:
     """Return `True` if `function` should be rewritten with 
`typing_extensions.Self`."""
+    # PEP 673 forbids the use of `typing(_extensions).Self` in metaclasses.
+    # Do our best to avoid false positives here:
+    if _is_metaclass(classdef):
+        return False
+
     # Much too complex for our purposes to worry
     # about overloaded functions or abstractmethods
     if any(
@@ -693,9 +691,12 @@
         "sys.version",
         "sys.version_info",
         "sys.winver",
+        "_typeshed.sentinel",
     }
 )
 
+_ALLOWED_SIMPLE_ATTRIBUTES_IN_DEFAULTS = frozenset({"sentinel"})
+
 
 def _is_valid_default_value_with_annotation(
     node: ast.expr, *, allow_containers: bool = True
@@ -784,6 +785,8 @@
         return (fullname in _ALLOWED_ATTRIBUTES_IN_DEFAULTS) or (
             fullname in _ALLOWED_MATH_ATTRIBUTES_IN_DEFAULTS
         )
+    elif isinstance(node, ast.Name):
+        return node.id in _ALLOWED_SIMPLE_ATTRIBUTES_IN_DEFAULTS
 
     return False
 
@@ -834,6 +837,86 @@
     return any(_is_enum_base(base) for base in node.bases)
 
 
+_COMMON_METACLASSES = {
+    "type": "builtins",
+    "ABCMeta": "abc",
+    "EnumMeta": "enum",
+    "EnumType": "enum",
+}
+
+
+def _is_metaclass_base(node: ast.expr) -> bool:
+    if isinstance(node, ast.Name):
+        return node.id in _COMMON_METACLASSES
+    return (
+        isinstance(node, ast.Attribute)
+        and node.attr in _COMMON_METACLASSES
+        and _is_name(node.value, _COMMON_METACLASSES[node.attr])
+    )
+
+
+def _is_metaclass(node: ast.ClassDef) -> bool:
+    """Best-effort attempt to determine if a class is a metaclass or not."""
+    return any(_is_metaclass_base(base) for base in node.bases)
+
+
+def _check_import_or_attribute(
+    node: ast.Attribute | ast.ImportFrom, module_name: str, object_name: str
+) -> str | None:
+    """If `node` represents a bad import, return the approriate error message.
+
+    Else, return None.
+    """
+    fullname = f"{module_name}.{object_name}"
+
+    # Y057 errors
+    if fullname in {"typing.ByteString", "collections.abc.ByteString"}:
+        return Y057.format(module=module_name)
+
+    # Y024 errors
+    if fullname == "collections.namedtuple":
+        return Y024
+
+    if module_name in _TYPING_MODULES:
+        # Y022 errors
+        if object_name in _BAD_Y022_IMPORTS:
+            good_cls_name, slice_contents = _BAD_Y022_IMPORTS[object_name]
+            params = "" if slice_contents is None else f"[{slice_contents}]"
+            return Y022.format(
+                good_syntax=f'"{good_cls_name}{params}"',
+                bad_syntax=f'"{fullname}{params}"',
+            )
+
+        # Y037 errors
+        if object_name == "Optional":
+            return Y037.format(
+                old_syntax=fullname, example='"int | None" instead of 
"Optional[int]"'
+            )
+        if object_name == "Union":
+            return Y037.format(
+                old_syntax=fullname, example='"int | str" instead of 
"Union[int, str]"'
+            )
+
+        # Y039 errors
+        if object_name == "Text":
+            return Y039.format(module=module_name)
+
+    # Y023 errors
+    if module_name == "typing_extensions":
+        if object_name in _BAD_TYPINGEXTENSIONS_Y023_IMPORTS:
+            return Y023.format(
+                good_syntax=f'"typing.{object_name}"',
+                bad_syntax=f'"typing_extensions.{object_name}"',
+            )
+        if object_name == "ClassVar":
+            return Y023.format(
+                good_syntax='"typing.ClassVar[T]"',
+                bad_syntax='"typing_extensions.ClassVar[T]"',
+            )
+
+    return None
+
+
 @dataclass
 class NestingCounter:
     """Class to help the PyiVisitor keep track of internal state"""
@@ -878,6 +961,7 @@
     all_name_occurrences: Counter[str]
 
     string_literals_allowed: NestingCounter
+    long_strings_allowed: NestingCounter
     in_function: NestingCounter
     in_class: NestingCounter
     visiting_arg: NestingCounter
@@ -895,6 +979,7 @@
         self.typealias_decls = defaultdict(list)
         self.all_name_occurrences = Counter()
         self.string_literals_allowed = NestingCounter()
+        self.long_strings_allowed = NestingCounter()
         self.in_function = NestingCounter()
         self.in_class = NestingCounter()
         self.visiting_arg = NestingCounter()
@@ -902,67 +987,12 @@
     def __repr__(self) -> str:
         return f"{self.__class__.__name__}(filename={self.filename!r})"
 
-    def _check_import_or_attribute(
-        self, node: ast.Attribute | ast.ImportFrom, module_name: str, 
object_name: str
-    ) -> None:
-        fullname = f"{module_name}.{object_name}"
-
-        # Y057 errors
-        if fullname in {"typing.ByteString", "collections.abc.ByteString"}:
-            error_message = Y057.format(module=module_name)
-
-        # Y022 errors
-        elif fullname in _BAD_Y022_IMPORTS:
-            good_cls_name, slice_contents = _BAD_Y022_IMPORTS[fullname]
-            params = "" if slice_contents is None else f"[{slice_contents}]"
-            error_message = Y022.format(
-                good_syntax=f'"{good_cls_name}{params}"',
-                bad_syntax=f'"{fullname}{params}"',
-            )
-
-        # Y023 errors
-        elif module_name == "typing_extensions":
-            if object_name in _BAD_TYPINGEXTENSIONS_Y023_IMPORTS:
-                error_message = Y023.format(
-                    good_syntax=f'"typing.{object_name}"',
-                    bad_syntax=f'"typing_extensions.{object_name}"',
-                )
-            elif object_name == "ClassVar":
-                error_message = Y023.format(
-                    good_syntax='"typing.ClassVar[T]"',
-                    bad_syntax='"typing_extensions.ClassVar[T]"',
-                )
-            else:
-                return
-
-        # Y024 errors
-        elif fullname == "collections.namedtuple":
-            error_message = Y024
-
-        # Y037 errors
-        elif fullname == "typing.Optional":
-            error_message = Y037.format(
-                old_syntax=fullname, example='"int | None" instead of 
"Optional[int]"'
-            )
-        elif fullname == "typing.Union":
-            error_message = Y037.format(
-                old_syntax=fullname, example='"int | str" instead of 
"Union[int, str]"'
-            )
-
-        # Y039 errors
-        elif fullname == "typing.Text":
-            error_message = Y039
-
-        else:
-            return
-
-        self.error(node, error_message)
-
     def visit_Attribute(self, node: ast.Attribute) -> None:
         self.generic_visit(node)
-        self._check_import_or_attribute(
+        if error_msg := _check_import_or_attribute(
             node=node, module_name=unparse(node.value), object_name=node.attr
-        )
+        ):
+            self.error(node, error_msg)
 
     def visit_ImportFrom(self, node: ast.ImportFrom) -> None:
         self.generic_visit(node)
@@ -986,10 +1016,11 @@
             self.error(node, Y025)
 
         for object_name in imported_names:
-            self._check_import_or_attribute(node, module_name, object_name)
+            if error_msg := _check_import_or_attribute(node, module_name, 
object_name):
+                self.error(node, error_msg)
 
-        if module_name == "typing" and "AbstractSet" in imported_names:
-            self.error(node, Y038)
+        if module_name in _TYPING_MODULES and "AbstractSet" in imported_names:
+            self.error(node, Y038.format(module=module_name))
 
     def _check_for_typevarlike_assignments(
         self, node: ast.Assign, function: ast.expr, object_name: str
@@ -1130,6 +1161,11 @@
             if _is_bad_TypedDict(node):
                 self.error(node, Y031)
             return
+        elif _is_deprecated(function):
+            with self.string_literals_allowed.enabled(), 
self.long_strings_allowed.enabled():
+                for arg in chain(node.args, node.keywords):
+                    self.visit(arg)
+            return
         elif (
             isinstance(function, ast.Attribute)
             and isinstance(function.value, ast.Name)
@@ -1150,7 +1186,10 @@
     def visit_Constant(self, node: ast.Constant) -> None:
         if isinstance(node.value, str) and not 
self.string_literals_allowed.active:
             self.error(node, Y020)
-        elif isinstance(node.value, (str, bytes)):
+        elif (
+            isinstance(node.value, (str, bytes))
+            and not self.long_strings_allowed.active
+        ):
             if len(node.value) > 50:
                 self.error(node, Y053)
         elif isinstance(node.value, (int, float, complex)):
@@ -1260,23 +1299,23 @@
 
     def _check_for_Y051_violations(self, analysis: UnionAnalysis) -> None:
         """Search for redundant unions such as `str | Literal["foo"]`, etc."""
-        literal_classes_present: defaultdict[str, list[_SliceContents]]
-        literal_classes_present = defaultdict(list)
+        seen_builtins: set[type] = set()
         for literal in analysis.combined_literal_members:
-            interesting_builtins = {str, bytes, int, bool}
+            if not isinstance(literal, ast.Constant):
+                continue
+            typ = type(literal.value)
+            typename = typ.__name__
             if (
-                isinstance(literal, ast.Constant)
-                and type(literal.value) in interesting_builtins
+                typ in {str, bytes, int, bool}
+                and typename in analysis.builtins_classes_in_union
+                and typ not in seen_builtins
             ):
-                
literal_classes_present[type(literal.value).__name__].append(literal)
-        for cls, literals in literal_classes_present.items():
-            if cls in analysis.builtins_classes_in_union:
-                first_literal_present = literals[0]
+                seen_builtins.add(typ)
                 self.error(
-                    first_literal_present,
+                    literal,
                     Y051.format(
-                        
literal_subtype=f"Literal[{unparse(first_literal_present)}]",
-                        builtin_supertype=cls,
+                        literal_subtype=f"Literal[{unparse(literal)}]",
+                        builtin_supertype=typename,
                     ),
                 )
 
@@ -1355,21 +1394,56 @@
 
         self._check_union_members(members, is_pep_604_union=True)
 
+    def _Y090_error(self, node: ast.Subscript) -> None:
+        current_code = unparse(node)
+        typ = unparse(node.slice)
+        copied_node = deepcopy(node)
+        new_slice = ast.Tuple(elts=[copied_node.slice, ast.Constant(...)])
+        if sys.version_info >= (3, 9):
+            copied_node.slice = new_slice
+        else:
+            copied_node.slice = ast.Index(new_slice)
+        suggestion = unparse(copied_node)
+        self.error(node, Y090.format(original=current_code, typ=typ, 
new=suggestion))
+
     def visit_Subscript(self, node: ast.Subscript) -> None:
         subscripted_object = node.value
         subscripted_object_name = _get_name_of_class_if_from_modules(
-            subscripted_object, modules=_TYPING_MODULES
+            subscripted_object, modules=_TYPING_MODULES | {"builtins"}
         )
         self.visit(subscripted_object)
         if subscripted_object_name == "Literal":
             with self.string_literals_allowed.enabled():
-                self.visit(node.slice)
+                self._visit_typing_Literal(node)
             return
 
         if isinstance(node.slice, ast.Tuple):
             self._visit_slice_tuple(node.slice, subscripted_object_name)
         else:
             self.visit(node.slice)
+            if subscripted_object_name in {"tuple", "Tuple"}:
+                self._Y090_error(node)
+
+    def _visit_typing_Literal(self, node: ast.Subscript) -> None:
+        if isinstance(node.slice, ast.Constant) and _is_None(node.slice):
+            # Special case for `Literal[None]`
+            self.error(node.slice, Y061.format(suggestion="None"))
+        elif isinstance(node.slice, ast.Tuple):
+            elts = node.slice.elts
+            for i, elt in enumerate(elts):
+                if _is_None(elt):
+                    elts_without_none = elts[:i] + [
+                        elt for elt in elts[i + 1 :] if not _is_None(elt)
+                    ]
+                    if len(elts_without_none) == 1:
+                        new_literal_slice = unparse(elts_without_none[0])
+                    else:
+                        new_slice_node = ast.Tuple(elts=elts_without_none)
+                        new_literal_slice = unparse(new_slice_node).strip("()")
+                    suggestion = f"Literal[{new_literal_slice}] | None"
+                    self.error(elt, Y061.format(suggestion=suggestion))
+                    break  # Only report the first `None`
+        self.visit(node.slice)
 
     def _visit_slice_tuple(self, node: ast.Tuple, parent: str | None) -> None:
         if parent == "Union":
@@ -1516,6 +1590,32 @@
         else:
             self.error(node, Y007)
 
+    def _check_class_bases(self, bases: list[ast.expr]) -> None:
+        Y040_encountered = False
+        Y059_encountered = False
+        Generic_basenode: ast.Subscript | None = None
+        subscript_bases: list[ast.Subscript] = []
+        num_bases = len(bases)
+
+        for i, base_node in enumerate(bases, start=1):
+            if not Y040_encountered and _is_builtins_object(base_node):
+                self.error(base_node, Y040)
+                Y040_encountered = True
+            if isinstance(base_node, ast.Subscript):
+                subscript_bases.append(base_node)
+                if _is_Generic(base_node.value):
+                    Generic_basenode = base_node
+                    if i < num_bases and not Y059_encountered:
+                        Y059_encountered = True
+                        self.error(base_node, Y059)
+
+        if Generic_basenode is not None:
+            assert subscript_bases
+            if len(subscript_bases) > 1 and all_equal(
+                ast.dump(subscript_base.slice) for subscript_base in 
subscript_bases
+            ):
+                self.error(Generic_basenode, Y060)
+
     def visit_ClassDef(self, node: ast.ClassDef) -> None:
         if node.name.startswith("_") and not self.in_class.active:
             for base in node.bases:
@@ -1532,8 +1632,7 @@
             self.generic_visit(node)
         self.current_class_node = old_class_node
 
-        if any(_is_builtins_object(base_node) for base_node in node.bases):
-            self.error(node, Y040)
+        self._check_class_bases(node.bases)
 
         # empty class body should contain "..." not "pass"
         if len(node.body) == 1:
@@ -1683,6 +1782,15 @@
         )
         self.error(node, error_message)
 
+    def _Y058_error(
+        self, node: ast.FunctionDef, args: list[ast.arg], example_returns: str
+    ) -> None:
+        assert node.name in {"__iter__", "__aiter__"}
+        good_cls = "Iterator" if node.name == "__iter__" else "AsyncIterator"
+        example = f"def {node.name}({args[0].arg}) -> {example_returns}: ..."
+        msg = Y058.format(iter_method=node.name, good_cls=good_cls, 
example=example)
+        self.error(node, msg)
+
     def _check_iter_returns(
         self, node: ast.FunctionDef, returns: ast.expr | None
     ) -> None:
@@ -1693,6 +1801,24 @@
                 iter_method="__iter__", good_cls="Iterator", bad_cls="Iterable"
             )
             self.error(node, msg)
+            return
+        non_kw_only_args = node.args.posonlyargs + node.args.args
+        if len(non_kw_only_args) == 1 and not node.args.kwonlyargs:
+            if _is_Generator(returns):
+                self._Y058_error(node, non_kw_only_args, "Iterator")
+            elif (
+                isinstance(returns, ast.Subscript)
+                and _is_Generator(returns.value)
+                and isinstance(returns.slice, ast.Tuple)
+            ):
+                elts = returns.slice.elts
+                if (
+                    len(elts) == 3
+                    and (_is_Any(elts[1]) or _is_None(elts[1]))
+                    and (_is_Any(elts[2]) or _is_None(elts[2]))
+                ):
+                    example_returns = 
f"Iterator[{unparse(returns.slice.elts[0])}]"
+                    self._Y058_error(node, non_kw_only_args, example_returns)
 
     def _check_aiter_returns(
         self, node: ast.FunctionDef, returns: ast.expr | None
@@ -1706,6 +1832,20 @@
                 bad_cls="AsyncIterable",
             )
             self.error(node, msg)
+            return
+        non_kw_only_args = node.args.posonlyargs + node.args.args
+        if len(non_kw_only_args) == 1 and not node.args.kwonlyargs:
+            if _is_AsyncGenerator(returns):
+                self._Y058_error(node, non_kw_only_args, "AsyncIterator")
+            elif (
+                isinstance(returns, ast.Subscript)
+                and _is_AsyncGenerator(returns.value)
+                and isinstance(returns.slice, ast.Tuple)
+            ):
+                elts = returns.slice.elts
+                if len(elts) == 2 and (_is_Any(elts[1]) or _is_None(elts[1])):
+                    example_returns = 
f"AsyncIterator[{unparse(returns.slice.elts[0])}]"
+                    self._Y058_error(node, non_kw_only_args, example_returns)
 
     def _visit_synchronous_method(self, node: ast.FunctionDef) -> None:
         method_name = node.name
@@ -1788,7 +1928,7 @@
             return True
         if sys.version_info < (3, 12):
             return False
-        return any(  # type: ignore[unreachable]
+        return any(  # type: ignore[unreachable,unused-ignore]
             isinstance(param, ast.TypeVar) and param.name == tvar_name
             for param in method.type_params
         )
@@ -1986,8 +2126,6 @@
 @dataclass
 class PyiTreeChecker:
     name: ClassVar[str] = "flake8-pyi"
-    version: ClassVar[str] = __version__
-
     tree: ast.Module
     lines: list[str]
     filename: str = "(none)"
@@ -2002,6 +2140,7 @@
     def add_options(parser: OptionManager) -> None:
         """This is brittle, there's multiple levels of caching of defaults."""
         parser.parser.set_defaults(filename="*.py,*.pyi")
+        parser.extend_default_ignore(DISABLED_BY_DEFAULT)
         parser.add_option(
             "--no-pyi-aware-file-checker",
             default=False,
@@ -2074,9 +2213,9 @@
 Y037 = "Y037 Use PEP 604 union types instead of {old_syntax} (e.g. {example})."
 Y038 = (
     'Y038 Use "from collections.abc import Set as AbstractSet" '
-    'instead of "from typing import AbstractSet" (PEP 585 syntax)'
+    'instead of "from {module} import AbstractSet" (PEP 585 syntax)'
 )
-Y039 = 'Y039 Use "str" instead of "typing.Text"'
+Y039 = 'Y039 Use "str" instead of "{module}.Text"'
 Y040 = 'Y040 Do not inherit from "object" explicitly, as it is redundant in 
Python 3'
 Y041 = (
     'Y041 Use "{implicit_supertype}" '
@@ -2109,3 +2248,20 @@
 Y057 = (
     "Y057 Do not use {module}.ByteString, which has unclear semantics and is 
deprecated"
 )
+Y058 = (
+    'Y058 Use "{good_cls}" as the return value for simple "{iter_method}" 
methods, '
+    'e.g. "{example}"'
+)
+Y059 = 'Y059 "Generic[]" should always be the last base class'
+Y060 = (
+    'Y060 Redundant inheritance from "Generic[]"; '
+    "class would be inferred as generic anyway"
+)
+Y061 = 'Y061 None inside "Literal[]" expression. Replace with "{suggestion}"'
+Y090 = (
+    'Y090 "{original}" means '
+    '"a tuple of length 1, in which the sole element is of type {typ!r}". '
+    'Perhaps you meant "{new}"?'
+)
+
+DISABLED_BY_DEFAULT = ["Y090"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/flake8_pyi-23.6.0/pyproject.toml 
new/flake8_pyi-23.11.0/pyproject.toml
--- old/flake8_pyi-23.6.0/pyproject.toml        2020-02-02 01:00:00.000000000 
+0100
+++ new/flake8_pyi-23.11.0/pyproject.toml       2020-02-02 01:00:00.000000000 
+0100
@@ -1,5 +1,5 @@
 [build-system]
-requires = ["hatchling"]
+requires = ["hatchling", "hatch-vcs"]
 build-backend = "hatchling.build"
 
 [project]
@@ -60,13 +60,14 @@
 
 [project.optional-dependencies]
 dev = [
-    "black==23.3.0",            # Must match .pre-commit-config.yaml
-    "flake8-bugbear==23.6.5",
+    "black==23.9.1",            # Must match .pre-commit-config.yaml
+    "flake8-bugbear==23.9.16",
     "flake8-noqa==1.3.2",
     "isort==5.12.0",            # Must match .pre-commit-config.yaml
-    "mypy==1.4.1",
-    "pre-commit-hooks==4.4.0",  # Must match .pre-commit-config.yaml
-    "pytest==7.4.0",
+    "mypy==1.6.0",
+    "pre-commit-hooks==4.5.0",  # Must match .pre-commit-config.yaml
+    "pytest==7.4.2",
+    "pytest-xdist==3.3.1",
     "types-pyflakes<4",
 ]
 
@@ -74,12 +75,15 @@
 "flake8.extension" = {Y0 = "pyi:PyiTreeChecker"}
 
 [tool.hatch.version]
-path = "pyi.py"
+source = "vcs"
+
+[tool.hatch.version.raw-options]
+local_scheme = "no-local-version"
 
 [tool.isort]
 profile = "black"
 combine_as_imports = true
-skip = ["tests/imports.pyi"]
+skip = ["tests/imports.pyi", "tests/pep604_union_types.pyi"]
 skip_gitignore = true
 
 [tool.black]
@@ -101,4 +105,5 @@
 ignore_missing_imports = true
 
 [tool.pytest.ini_options]
-addopts = "--doctest-modules"
+addopts = "--doctest-modules -nauto"
+filterwarnings = ["error"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/flake8_pyi-23.6.0/tests/classdefs.pyi 
new/flake8_pyi-23.11.0/tests/classdefs.pyi
--- old/flake8_pyi-23.6.0/tests/classdefs.pyi   2020-02-02 01:00:00.000000000 
+0100
+++ new/flake8_pyi-23.11.0/tests/classdefs.pyi  2020-02-02 01:00:00.000000000 
+0100
@@ -3,10 +3,21 @@
 import abc
 import builtins
 import collections.abc
+import enum
 import typing
-from abc import abstractmethod
-from collections.abc import AsyncIterable, AsyncIterator, Iterable, Iterator
-from typing import Any, overload
+from abc import ABCMeta, abstractmethod
+from collections.abc import (
+    AsyncGenerator,
+    AsyncIterable,
+    AsyncIterator,
+    Container,
+    Generator,
+    Iterable,
+    Iterator,
+    Mapping,
+)
+from enum import EnumMeta
+from typing import Any, Generic, TypeVar, overload
 
 import typing_extensions
 from _typeshed import Self
@@ -94,12 +105,54 @@
 class IteratorReturningIterable:
     def __iter__(self) -> Iterable[str]: ...  # Y045 "__iter__" methods should 
return an Iterator, not an Iterable
 
+class IteratorReturningSimpleGenerator1:
+    def __iter__(self) -> Generator: ...  # Y058 Use "Iterator" as the return 
value for simple "__iter__" methods, e.g. "def __iter__(self) -> Iterator: ..."
+
+class IteratorReturningSimpleGenerator2:
+    def __iter__(self) -> collections.abc.Generator[str, Any, None]: ...  # 
Y058 Use "Iterator" as the return value for simple "__iter__" methods, e.g. 
"def __iter__(self) -> Iterator[str]: ..."
+
+class IteratorReturningComplexGenerator:
+    def __iter__(self) -> Generator[str, int, bytes]: ...
+
 class BadAsyncIterator(collections.abc.AsyncIterator[str]):
     def __aiter__(self) -> typing.AsyncIterator[str]: ...  # Y034 "__aiter__" 
methods in classes like "BadAsyncIterator" usually return "self" at runtime. 
Consider using "typing_extensions.Self" in "BadAsyncIterator.__aiter__", e.g. 
"def __aiter__(self) -> Self: ..."  # Y022 Use 
"collections.abc.AsyncIterator[T]" instead of "typing.AsyncIterator[T]" (PEP 
585 syntax)
 
 class AsyncIteratorReturningAsyncIterable:
     def __aiter__(self) -> AsyncIterable[str]: ...  # Y045 "__aiter__" methods 
should return an AsyncIterator, not an AsyncIterable
 
+class AsyncIteratorReturningSimpleAsyncGenerator1:
+    def __aiter__(self) -> AsyncGenerator: ...  # Y058 Use "AsyncIterator" as 
the return value for simple "__aiter__" methods, e.g. "def __aiter__(self) -> 
AsyncIterator: ..."
+
+class AsyncIteratorReturningSimpleAsyncGenerator2:
+    def __aiter__(self) -> collections.abc.AsyncGenerator[str, Any]: ...  # 
Y058 Use "AsyncIterator" as the return value for simple "__aiter__" methods, 
e.g. "def __aiter__(self) -> AsyncIterator[str]: ..."
+
+class AsyncIteratorReturningComplexAsyncGenerator:
+    def __aiter__(self) -> AsyncGenerator[str, int]: ...
+
+class MetaclassInWhichSelfCannotBeUsed(type):
+    def __new__(cls) -> MetaclassInWhichSelfCannotBeUsed: ...
+    def __enter__(self) -> MetaclassInWhichSelfCannotBeUsed: ...
+    async def __aenter__(self) -> MetaclassInWhichSelfCannotBeUsed: ...
+    def __isub__(self, other: MetaclassInWhichSelfCannotBeUsed) -> 
MetaclassInWhichSelfCannotBeUsed: ...
+
+class MetaclassInWhichSelfCannotBeUsed2(EnumMeta):
+    def __new__(cls) -> MetaclassInWhichSelfCannotBeUsed2: ...
+    def __enter__(self) -> MetaclassInWhichSelfCannotBeUsed2: ...
+    async def __aenter__(self) -> MetaclassInWhichSelfCannotBeUsed2: ...
+    def __isub__(self, other: MetaclassInWhichSelfCannotBeUsed2) -> 
MetaclassInWhichSelfCannotBeUsed2: ...
+
+class MetaclassInWhichSelfCannotBeUsed3(enum.EnumType):
+    def __new__(cls) -> MetaclassInWhichSelfCannotBeUsed3: ...
+    def __enter__(self) -> MetaclassInWhichSelfCannotBeUsed3: ...
+    async def __aenter__(self) -> MetaclassInWhichSelfCannotBeUsed3: ...
+    def __isub__(self, other: MetaclassInWhichSelfCannotBeUsed3) -> 
MetaclassInWhichSelfCannotBeUsed3: ...
+
+class MetaclassInWhichSelfCannotBeUsed4(ABCMeta):
+    def __new__(cls) -> MetaclassInWhichSelfCannotBeUsed4: ...
+    def __enter__(self) -> MetaclassInWhichSelfCannotBeUsed4: ...
+    async def __aenter__(self) -> MetaclassInWhichSelfCannotBeUsed4: ...
+    def __isub__(self, other: MetaclassInWhichSelfCannotBeUsed4) -> 
MetaclassInWhichSelfCannotBeUsed4: ...
+
 class Abstract(Iterator[str]):
     @abstractmethod
     def __iter__(self) -> Iterator[str]: ...
@@ -134,3 +187,43 @@
 def __eq__(self, other: Any) -> bool: ...
 def __ne__(self, other: Any) -> bool: ...
 def __imul__(self, other: Any) -> list[str]: ...
+
+_S = TypeVar("_S")
+_T = TypeVar("_T")
+
+class BadGeneric(Generic[_T], int): ...  # Y059 "Generic[]" should always be 
the last base class
+class GoodGeneric(Generic[_T]): ...
+
+class BadGeneric2(int, typing.Generic[_T], str): ...  # Y059 "Generic[]" 
should always be the last base class
+class GoodGeneric2(int, typing.Generic[_T]): ...
+
+class BadGeneric3(typing_extensions.Generic[_T], int, str): ...  # Y059 
"Generic[]" should always be the last base class
+class GoodGeneric3(int, str, typing_extensions.Generic[_T]): ...
+
+class BadGeneric4(Generic[_T], Iterable[int], str): ...  # Y059 "Generic[]" 
should always be the last base class
+class GoodGeneric4(Iterable[int], str, Generic[_T]): ...
+
+class RedundantGeneric1(Iterable[_T], Generic[_T]): ...  # Y060 Redundant 
inheritance from "Generic[]"; class would be inferred as generic anyway
+class Corrected1(Iterable[_T]): ...
+
+class RedundantGeneric2(Generic[_S], GoodGeneric[_S]): ...  # Y059 "Generic[]" 
should always be the last base class  # Y060 Redundant inheritance from 
"Generic[]"; class would be inferred as generic anyway
+class Corrected2(GoodGeneric[_S]): ...
+
+class RedundantGeneric3(int, Iterator[_T], str, float, memoryview, bytes, 
Generic[_T]): ...  # Y060 Redundant inheritance from "Generic[]"; class would 
be inferred as generic anyway
+class Corrected3(int, Iterator[_T], str, float, memoryview, bytes): ...
+
+class RedundantGeneric4(Iterable[_T], Iterator[_T], Generic[_T]): ...  # Y060 
Redundant inheritance from "Generic[]"; class would be inferred as generic 
anyway
+class Corrected4(Iterable[_T], Iterator[_T]): ...
+
+class BadAndRedundantGeneric(object, Generic[_T], Container[_T]): ...  # Y040 
Do not inherit from "object" explicitly, as it is redundant in Python 3  # Y059 
"Generic[]" should always be the last base class  # Y060 Redundant inheritance 
from "Generic[]"; class would be inferred as generic anyway
+class Corrected5(Container[_T]): ...
+
+# Strictly speaking this inheritance from Generic is "redundant",
+# but people may consider it more readable to explicitly inherit from Generic,
+# so we deliberately don't flag it with Y060
+class GoodGeneric5(Container[_S], Iterator[_T], Generic[_S, _T]): ...
+
+# And these definitely arent't redundant,
+# since the order of the type variables is changed via the inheritance from 
Generic:
+class GoodGeneric6(Container[_S], Iterator[_T], Generic[_T, _S]): ...
+class GoodGeneric7(Mapping[_S, _T], Generic[_T, _S]): ...
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/flake8_pyi-23.6.0/tests/defaults.pyi 
new/flake8_pyi-23.11.0/tests/defaults.pyi
--- old/flake8_pyi-23.6.0/tests/defaults.pyi    2020-02-02 01:00:00.000000000 
+0100
+++ new/flake8_pyi-23.11.0/tests/defaults.pyi   2020-02-02 01:00:00.000000000 
+0100
@@ -2,7 +2,8 @@
 import os
 import sys
 
-from _typeshed import SupportsRead, SupportsWrite
+import _typeshed
+from _typeshed import SupportsRead, SupportsWrite, sentinel
 
 def f1(x: int = ...) -> None: ...
 def f2(x: int = 3) -> None: ...
@@ -68,6 +69,8 @@
 def f34(x: str = sys.version) -> None: ...
 def f35(x: tuple[int, ...] = sys.version_info) -> None: ...
 def f36(x: str = sys.winver) -> None: ...
+def f361(x: str | None = sentinel) -> None: ...
+def f362(x: str | None = _typeshed.sentinel) -> None: ...
 
 def f37(x: str = 
"a_very_long_stringgggggggggggggggggggggggggggggggggggggggggggggg") -> None: 
...  # Y053 String and bytes literals >50 characters long are not permitted
 def f38(x: bytes = 
b"a_very_long_byte_stringggggggggggggggggggggggggggggggggggggg") -> None: ...  
# Y053 String and bytes literals >50 characters long are not permitted
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/flake8_pyi-23.6.0/tests/disabled_by_default.pyi 
new/flake8_pyi-23.11.0/tests/disabled_by_default.pyi
--- old/flake8_pyi-23.6.0/tests/disabled_by_default.pyi 1970-01-01 
01:00:00.000000000 +0100
+++ new/flake8_pyi-23.11.0/tests/disabled_by_default.pyi        2020-02-02 
01:00:00.000000000 +0100
@@ -0,0 +1,9 @@
+# This test file checks that disabled-by-default error codes aren't triggered,
+# unless they're explicitly enabled
+from typing import (  # Y022 Use "tuple[Foo, Bar]" instead of 
"typing.Tuple[Foo, Bar]" (PEP 585 syntax)
+    Tuple,
+)
+
+# These would trigger Y090, but it's disabled by default
+x: tuple[int]
+y: Tuple[str]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/flake8_pyi-23.6.0/tests/imports.pyi 
new/flake8_pyi-23.11.0/tests/imports.pyi
--- old/flake8_pyi-23.6.0/tests/imports.pyi     2020-02-02 01:00:00.000000000 
+0100
+++ new/flake8_pyi-23.11.0/tests/imports.pyi    2020-02-02 01:00:00.000000000 
+0100
@@ -80,17 +80,8 @@
 from typing import Counter  # Y022 Use "collections.Counter[KeyType]" instead 
of "typing.Counter[KeyType]" (PEP 585 syntax)
 from typing import AsyncContextManager  # Y022 Use 
"contextlib.AbstractAsyncContextManager[T]" instead of 
"typing.AsyncContextManager[T]" (PEP 585 syntax)
 from typing import ChainMap  # Y022 Use "collections.ChainMap[KeyType, 
ValueType]" instead of "typing.ChainMap[KeyType, ValueType]" (PEP 585 syntax)
-from typing_extensions import Type  # Y022 Use "type[MyClass]" instead of 
"typing_extensions.Type[MyClass]" (PEP 585 syntax)
-from typing_extensions import DefaultDict  # Y022 Use 
"collections.defaultdict[KeyType, ValueType]" instead of 
"typing_extensions.DefaultDict[KeyType, ValueType]" (PEP 585 syntax)
-from typing_extensions import ChainMap  # Y022 Use 
"collections.ChainMap[KeyType, ValueType]" instead of 
"typing_extensions.ChainMap[KeyType, ValueType]" (PEP 585 syntax)
-from typing_extensions import AsyncContextManager  # Y022 Use 
"contextlib.AbstractAsyncContextManager[T]" instead of 
"typing_extensions.AsyncContextManager[T]" (PEP 585 syntax)
-from typing_extensions import Awaitable  # Y022 Use 
"collections.abc.Awaitable[T]" instead of "typing_extensions.Awaitable[T]" (PEP 
585 syntax)
-from typing_extensions import ContextManager  # Y022 Use 
"contextlib.AbstractContextManager[T]" instead of 
"typing_extensions.ContextManager[T]" (PEP 585 syntax)
-from typing_extensions import AsyncGenerator  # Y022 Use 
"collections.abc.AsyncGenerator[YieldType, SendType]" instead of 
"typing_extensions.AsyncGenerator[YieldType, SendType]" (PEP 585 syntax)
-from typing_extensions import Coroutine  # Y022 Use 
"collections.abc.Coroutine[YieldType, SendType, ReturnType]" instead of 
"typing_extensions.Coroutine[YieldType, SendType, ReturnType]" (PEP 585 syntax)
 from typing import ContextManager  # Y022 Use 
"contextlib.AbstractContextManager[T]" instead of "typing.ContextManager[T]" 
(PEP 585 syntax)
 from typing import OrderedDict  # Y022 Use "collections.OrderedDict[KeyType, 
ValueType]" instead of "typing.OrderedDict[KeyType, ValueType]" (PEP 585 syntax)
-from typing_extensions import OrderedDict  # Y022 Use 
"collections.OrderedDict[KeyType, ValueType]" instead of 
"typing_extensions.OrderedDict[KeyType, ValueType]" (PEP 585 syntax)
 from typing import Callable  # Y022 Use "collections.abc.Callable" instead of 
"typing.Callable" (PEP 585 syntax)
 from typing import Container  # Y022 Use "collections.abc.Container[T]" 
instead of "typing.Container[T]" (PEP 585 syntax)
 from typing import Hashable  # Y022 Use "collections.abc.Hashable" instead of 
"typing.Hashable" (PEP 585 syntax)
@@ -116,6 +107,37 @@
 from typing import Generator  # Y022 Use "collections.abc.Generator[YieldType, 
SendType, ReturnType]" instead of "typing.Generator[YieldType, SendType, 
ReturnType]" (PEP 585 syntax)
 from typing import Match  # Y022 Use "re.Match[T]" instead of 
"typing.Match[T]" (PEP 585 syntax)
 from typing import Pattern  # Y022 Use "re.Pattern[T]" instead of 
"typing.Pattern[T]" (PEP 585 syntax)
+from typing_extensions import Dict  # Y022 Use "dict[KeyType, ValueType]" 
instead of "typing_extensions.Dict[KeyType, ValueType]" (PEP 585 syntax)
+from typing_extensions import Counter  # Y022 Use 
"collections.Counter[KeyType]" instead of "typing_extensions.Counter[KeyType]" 
(PEP 585 syntax)
+from typing_extensions import AsyncContextManager  # Y022 Use 
"contextlib.AbstractAsyncContextManager[T]" instead of 
"typing_extensions.AsyncContextManager[T]" (PEP 585 syntax)
+from typing_extensions import ChainMap  # Y022 Use 
"collections.ChainMap[KeyType, ValueType]" instead of 
"typing_extensions.ChainMap[KeyType, ValueType]" (PEP 585 syntax)
+from typing_extensions import ContextManager  # Y022 Use 
"contextlib.AbstractContextManager[T]" instead of 
"typing_extensions.ContextManager[T]" (PEP 585 syntax)
+from typing_extensions import OrderedDict  # Y022 Use 
"collections.OrderedDict[KeyType, ValueType]" instead of 
"typing_extensions.OrderedDict[KeyType, ValueType]" (PEP 585 syntax)
+from typing_extensions import Callable  # Y022 Use "collections.abc.Callable" 
instead of "typing_extensions.Callable" (PEP 585 syntax)
+from typing_extensions import Container  # Y022 Use 
"collections.abc.Container[T]" instead of "typing_extensions.Container[T]" (PEP 
585 syntax)
+from typing_extensions import Hashable  # Y022 Use "collections.abc.Hashable" 
instead of "typing_extensions.Hashable" (PEP 585 syntax)
+from typing_extensions import ItemsView  # Y022 Use 
"collections.abc.ItemsView[KeyType, ValueType]" instead of 
"typing_extensions.ItemsView[KeyType, ValueType]" (PEP 585 syntax)
+from typing_extensions import Iterable  # Y022 Use 
"collections.abc.Iterable[T]" instead of "typing_extensions.Iterable[T]" (PEP 
585 syntax)
+from typing_extensions import Iterator  # Y022 Use 
"collections.abc.Iterator[T]" instead of "typing_extensions.Iterator[T]" (PEP 
585 syntax)
+from typing_extensions import KeysView  # Y022 Use 
"collections.abc.KeysView[KeyType]" instead of 
"typing_extensions.KeysView[KeyType]" (PEP 585 syntax)
+from typing_extensions import Mapping  # Y022 Use 
"collections.abc.Mapping[KeyType, ValueType]" instead of 
"typing_extensions.Mapping[KeyType, ValueType]" (PEP 585 syntax)
+from typing_extensions import MappingView  # Y022 Use 
"collections.abc.MappingView" instead of "typing_extensions.MappingView" (PEP 
585 syntax)
+from typing_extensions import MutableMapping  # Y022 Use 
"collections.abc.MutableMapping[KeyType, ValueType]" instead of 
"typing_extensions.MutableMapping[KeyType, ValueType]" (PEP 585 syntax)
+from typing_extensions import MutableSequence  # Y022 Use 
"collections.abc.MutableSequence[T]" instead of 
"typing_extensions.MutableSequence[T]" (PEP 585 syntax)
+from typing_extensions import MutableSet  # Y022 Use 
"collections.abc.MutableSet[T]" instead of "typing_extensions.MutableSet[T]" 
(PEP 585 syntax)
+from typing_extensions import Sequence  # Y022 Use 
"collections.abc.Sequence[T]" instead of "typing_extensions.Sequence[T]" (PEP 
585 syntax)
+from typing_extensions import Sized  # Y022 Use "collections.abc.Sized" 
instead of "typing_extensions.Sized" (PEP 585 syntax)
+from typing_extensions import ValuesView  # Y022 Use 
"collections.abc.ValuesView[ValueType]" instead of 
"typing_extensions.ValuesView[ValueType]" (PEP 585 syntax)
+from typing_extensions import Awaitable  # Y022 Use 
"collections.abc.Awaitable[T]" instead of "typing_extensions.Awaitable[T]" (PEP 
585 syntax)
+from typing_extensions import AsyncIterator  # Y022 Use 
"collections.abc.AsyncIterator[T]" instead of 
"typing_extensions.AsyncIterator[T]" (PEP 585 syntax)
+from typing_extensions import AsyncIterable  # Y022 Use 
"collections.abc.AsyncIterable[T]" instead of 
"typing_extensions.AsyncIterable[T]" (PEP 585 syntax)
+from typing_extensions import Coroutine  # Y022 Use 
"collections.abc.Coroutine[YieldType, SendType, ReturnType]" instead of 
"typing_extensions.Coroutine[YieldType, SendType, ReturnType]" (PEP 585 syntax)
+from typing_extensions import Collection  # Y022 Use 
"collections.abc.Collection[T]" instead of "typing_extensions.Collection[T]" 
(PEP 585 syntax)
+from typing_extensions import AsyncGenerator  # Y022 Use 
"collections.abc.AsyncGenerator[YieldType, SendType]" instead of 
"typing_extensions.AsyncGenerator[YieldType, SendType]" (PEP 585 syntax)
+from typing_extensions import Reversible  # Y022 Use 
"collections.abc.Reversible[T]" instead of "typing_extensions.Reversible[T]" 
(PEP 585 syntax)
+from typing_extensions import Generator  # Y022 Use 
"collections.abc.Generator[YieldType, SendType, ReturnType]" instead of 
"typing_extensions.Generator[YieldType, SendType, ReturnType]" (PEP 585 syntax)
+from typing_extensions import Match  # Y022 Use "re.Match[T]" instead of 
"typing_extensions.Match[T]" (PEP 585 syntax)
+from typing_extensions import Pattern  # Y022 Use "re.Pattern[T]" instead of 
"typing_extensions.Pattern[T]" (PEP 585 syntax)
 
 # BAD IMPORTS (Y023 code)
 from typing_extensions import ClassVar  # Y023 Use "typing.ClassVar[T]" 
instead of "typing_extensions.ClassVar[T]"
@@ -125,7 +147,9 @@
 from collections import namedtuple  # Y024 Use "typing.NamedTuple" instead of 
"collections.namedtuple"
 from collections.abc import Set  # Y025 Use "from collections.abc import Set 
as AbstractSet" to avoid confusion with "builtins.set"
 from typing import AbstractSet  # Y038 Use "from collections.abc import Set as 
AbstractSet" instead of "from typing import AbstractSet" (PEP 585 syntax)
+from typing_extensions import AbstractSet  # Y038 Use "from collections.abc 
import Set as AbstractSet" instead of "from typing_extensions import 
AbstractSet" (PEP 585 syntax)
 from typing import Text  # Y039 Use "str" instead of "typing.Text"
+from typing_extensions import Text  # Y039 Use "str" instead of 
"typing_extensions.Text"
 from typing import ByteString  # Y057 Do not use typing.ByteString, which has 
unclear semantics and is deprecated
 from collections.abc import ByteString  # Y057 Do not use 
collections.abc.ByteString, which has unclear semantics and is deprecated
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/flake8_pyi-23.6.0/tests/literals.pyi 
new/flake8_pyi-23.11.0/tests/literals.pyi
--- old/flake8_pyi-23.6.0/tests/literals.pyi    1970-01-01 01:00:00.000000000 
+0100
+++ new/flake8_pyi-23.11.0/tests/literals.pyi   2020-02-02 01:00:00.000000000 
+0100
@@ -0,0 +1,5 @@
+from typing import Literal
+
+Literal[None]  # Y061 None inside "Literal[]" expression. Replace with "None"
+Literal[True, None]  # Y061 None inside "Literal[]" expression. Replace with 
"Literal[True] | None"
+Literal[1, None, "foo", None]  # Y061 None inside "Literal[]" expression. 
Replace with "Literal[1, 'foo'] | None"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/flake8_pyi-23.6.0/tests/pep604_union_types.pyi 
new/flake8_pyi-23.11.0/tests/pep604_union_types.pyi
--- old/flake8_pyi-23.6.0/tests/pep604_union_types.pyi  2020-02-02 
01:00:00.000000000 +0100
+++ new/flake8_pyi-23.11.0/tests/pep604_union_types.pyi 2020-02-02 
01:00:00.000000000 +0100
@@ -1,8 +1,14 @@
+# flags: --extend-ignore=F401,F811
+#
+# Note: DO NOT RUN ISORT ON THIS FILE.
+# It's excluded in our pyproject.toml.
+
 import typing
-from typing import (  # Y037 Use PEP 604 union types instead of 
typing.Optional (e.g. "int | None" instead of "Optional[int]"). # Y037 Use PEP 
604 union types instead of typing.Union (e.g. "int | str" instead of 
"Union[int, str]").
-    Optional,
-    Union,
-)
+import typing_extensions
+from typing import Optional  # Y037 Use PEP 604 union types instead of 
typing.Optional (e.g. "int | None" instead of "Optional[int]").
+from typing import Union  # Y037 Use PEP 604 union types instead of 
typing.Union (e.g. "int | str" instead of "Union[int, str]").
+from typing_extensions import Optional  # Y037 Use PEP 604 union types instead 
of typing_extensions.Optional (e.g. "int | None" instead of "Optional[int]").
+from typing_extensions import Union  # Y037 Use PEP 604 union types instead of 
typing_extensions.Union (e.g. "int | str" instead of "Union[int, str]").
 
 x1: Optional[str]
 x2: Optional
@@ -14,6 +20,10 @@
 y2: typing.Optional  # Y037 Use PEP 604 union types instead of typing.Optional 
(e.g. "int | None" instead of "Optional[int]").
 y3: typing.Union[str, int]  # Y037 Use PEP 604 union types instead of 
typing.Union (e.g. "int | str" instead of "Union[int, str]").
 y4: typing.Union  # Y037 Use PEP 604 union types instead of typing.Union (e.g. 
"int | str" instead of "Union[int, str]").
+y5: typing_extensions.Optional[str]  # Y037 Use PEP 604 union types instead of 
typing_extensions.Optional (e.g. "int | None" instead of "Optional[int]").
+y6: typing_extensions.Optional  # Y037 Use PEP 604 union types instead of 
typing_extensions.Optional (e.g. "int | None" instead of "Optional[int]").
+y7: typing_extensions.Union[str, int]  # Y037 Use PEP 604 union types instead 
of typing_extensions.Union (e.g. "int | str" instead of "Union[int, str]").
+y8: typing_extensions.Union  # Y037 Use PEP 604 union types instead of 
typing_extensions.Union (e.g. "int | str" instead of "Union[int, str]").
 
 
 def f1(x: Optional[str] = ...) -> None: ...
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/flake8_pyi-23.6.0/tests/single_element_tuples.pyi 
new/flake8_pyi-23.11.0/tests/single_element_tuples.pyi
--- old/flake8_pyi-23.6.0/tests/single_element_tuples.pyi       1970-01-01 
01:00:00.000000000 +0100
+++ new/flake8_pyi-23.11.0/tests/single_element_tuples.pyi      2020-02-02 
01:00:00.000000000 +0100
@@ -0,0 +1,8 @@
+# flags: --extend-select=Y090
+import builtins
+import typing
+
+a: tuple[int]  # Y090 "tuple[int]" means "a tuple of length 1, in which the 
sole element is of type 'int'". Perhaps you meant "tuple[int, ...]"?
+b: typing.Tuple[builtins.str]  # Y022 Use "tuple[Foo, Bar]" instead of 
"typing.Tuple[Foo, Bar]" (PEP 585 syntax)  # Y090 "typing.Tuple[builtins.str]" 
means "a tuple of length 1, in which the sole element is of type 
'builtins.str'". Perhaps you meant "typing.Tuple[builtins.str, ...]"?
+c: tuple[int, ...]
+d: typing.Tuple[builtins.str, builtins.complex]  # Y022 Use "tuple[Foo, Bar]" 
instead of "typing.Tuple[Foo, Bar]" (PEP 585 syntax)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/flake8_pyi-23.6.0/tests/test_pyi_files.py 
new/flake8_pyi-23.11.0/tests/test_pyi_files.py
--- old/flake8_pyi-23.6.0/tests/test_pyi_files.py       2020-02-02 
01:00:00.000000000 +0100
+++ new/flake8_pyi-23.11.0/tests/test_pyi_files.py      2020-02-02 
01:00:00.000000000 +0100
@@ -35,30 +35,50 @@
             expected_output += f"{path}:{lineno}: {match.group(1)}{message}\n"
 
     bad_flag_msg = (
-        "--ignore flags in test files override the .flake8 config file. "
-        "Use --extend-ignore instead."
-    )
+        "--{flag} flags in test files override the .flake8 config file. "
+        "Use --extend-{flag} instead."
+    ).format
+
     for flag in flags:
         option = flag.split("=")[0]
-        assert option != "--ignore", bad_flag_msg
+        assert option not in {"--ignore", "--select"}, bad_flag_msg(option[2:])
+
+    # Silence DeprecationWarnings from our dependencies (pyflakes, 
flake8-bugbear, etc.)
+    #
+    # For DeprecationWarnings coming from flake8-pyi itself,
+    # print the first occurence of each warning to stderr.
+    # This will fail CI the same as `-Werror:::pyi`,
+    # but the test failure report that pytest gives is much easier to read
+    # if we use `-Wdefault:::pyi`
+    flake8_invocation = [
+        sys.executable,
+        "-Wignore",
+        "-Wdefault:::pyi",
+        "-m",
+        "flake8",
+        "-j0",
+    ]
 
     run_results = [
         # Passing a file on command line
         subprocess.run(
-            ["flake8", "-j0", *flags, path],
+            [*flake8_invocation, *flags, path],
             env={**os.environ, "PYTHONPATH": "."},
-            stdout=subprocess.PIPE,
+            capture_output=True,
+            text=True,
         ),
         # Passing "-" as the file, and reading from stdin instead
         subprocess.run(
-            ["flake8", "-j0", "--stdin-display-name", path, *flags, "-"],
+            [*flake8_invocation, "--stdin-display-name", path, *flags, "-"],
             env={**os.environ, "PYTHONPATH": "."},
-            input=file_contents.encode("utf-8"),
-            stdout=subprocess.PIPE,
+            input=file_contents,
+            capture_output=True,
+            text=True,
         ),
     ]
 
     for run_result in run_results:
-        output = run_result.stdout.decode("utf-8")
-        output = re.sub(":[0-9]+: ", ": ", output)  # ignore column numbers
+        output = re.sub(":[0-9]+: ", ": ", run_result.stdout)  # ignore column 
numbers
+        if run_result.stderr:
+            output += "\n" + run_result.stderr
         assert output == expected_output

++++++ set-tests-python-path.patch ++++++
--- /var/tmp/diff_new_pack.ghVi0W/_old  2023-12-06 23:48:42.992338873 +0100
+++ /var/tmp/diff_new_pack.ghVi0W/_new  2023-12-06 23:48:42.996339018 +0100
@@ -1,29 +1,24 @@
-Index: flake8_pyi-23.6.0/tests/test_pyi_files.py
+Index: flake8_pyi-23.11.0/tests/test_pyi_files.py
 ===================================================================
---- flake8_pyi-23.6.0.orig/tests/test_pyi_files.py
-+++ flake8_pyi-23.6.0/tests/test_pyi_files.py
-@@ -42,16 +42,21 @@ def test_pyi_file(path: str) -> None:
+--- flake8_pyi-23.11.0.orig/tests/test_pyi_files.py
++++ flake8_pyi-23.11.0/tests/test_pyi_files.py
+@@ -43,6 +43,9 @@ def test_pyi_file(path: str) -> None:
          option = flag.split("=")[0]
-         assert option != "--ignore", bad_flag_msg
+         assert option not in {"--ignore", "--select"}, 
bad_flag_msg(option[2:])
  
 +    pythonpath = os.environ.get("PYTHONPATH")
 +    pythonpath = f"PYTHONPATH={pythonpath}:."
 +
-     run_results = [
-         # Passing a file on command line
-         subprocess.run(
--            ["flake8", "-j0", *flags, path],
-+            " ".join([pythonpath, "flake8", "-j0", *flags, path]),
-+            shell=True,
-             env={**os.environ, "PYTHONPATH": "."},
-             stdout=subprocess.PIPE,
-         ),
-         # Passing "-" as the file, and reading from stdin instead
-         subprocess.run(
--            ["flake8", "-j0", "--stdin-display-name", path, *flags, "-"],
-+            " ".join([pythonpath, "flake8", "-j0", "--stdin-display-name", 
path, *flags, "-"]),
-+            shell=True,
-             env={**os.environ, "PYTHONPATH": "."},
-             input=file_contents.encode("utf-8"),
-             stdout=subprocess.PIPE,
+     # Silence DeprecationWarnings from our dependencies (pyflakes, 
flake8-bugbear, etc.)
+     #
+     # For DeprecationWarnings coming from flake8-pyi itself,
+@@ -51,6 +54,8 @@ def test_pyi_file(path: str) -> None:
+     # but the test failure report that pytest gives is much easier to read
+     # if we use `-Wdefault:::pyi`
+     flake8_invocation = [
++        "env",
++        pythonpath,
+         sys.executable,
+         "-Wignore",
+         "-Wdefault:::pyi",
 

Reply via email to