Skip to content

Commit 8be9c0d

Browse files
authored
Merge pull request #124 from netromdk/py3.11
Python 3.11 support
2 parents 63f5e92 + 9eb0122 commit 8be9c0d

File tree

13 files changed

+702
-37
lines changed

13 files changed

+702
-37
lines changed

.github/workflows/test.yml

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,9 @@ jobs:
1313
runs-on: ${{ matrix.os }}
1414
strategy:
1515
matrix:
16-
# Start Linux jobs last since they are fastest to start and complete, and start 3.10 first,
17-
# since it pairs wiht macOS+Windows jobs, and 2.7+3.5 last since they only run tests and
18-
# don't use venv. (3.4 is not supported on GitHub anymore)
19-
python-version: ['3.10', 3.6, 3.7, 3.8, 3.9, 2.7, 3.5]
16+
# Start Linux jobs last since they are fastest to start and complete, and start 3.11 first,
17+
# since it pairs wiht macOS+Windows jobs.
18+
python-version: ['3.11', '3.10', 3.6, 3.7, 3.8, 3.9, 2.7]
2019
os: [windows-latest, macos-latest, ubuntu-latest]
2120

2221
# Choose test script depending on OS.
@@ -28,14 +27,10 @@ jobs:
2827
- os: windows-latest
2928
test_script_name: ./misc/actions/test.ps1
3029

31-
# Only test on macOS and Windows with Python 3.10.
30+
# Only test on macOS and Windows with Python 3.11.
3231
exclude:
3332
- os: macos-latest
3433
python-version: 2.7
35-
- os: macos-latest
36-
python-version: 3.4
37-
- os: macos-latest
38-
python-version: 3.5
3934
- os: macos-latest
4035
python-version: 3.6
4136
- os: macos-latest
@@ -44,12 +39,10 @@ jobs:
4439
python-version: 3.8
4540
- os: macos-latest
4641
python-version: 3.9
42+
- os: macos-latest
43+
python-version: '3.10'
4744
- os: windows-latest
4845
python-version: 2.7
49-
- os: windows-latest
50-
python-version: 3.4
51-
- os: windows-latest
52-
python-version: 3.5
5346
- os: windows-latest
5447
python-version: 3.6
5548
- os: windows-latest
@@ -58,6 +51,8 @@ jobs:
5851
python-version: 3.8
5952
- os: windows-latest
6053
python-version: 3.9
54+
- os: windows-latest
55+
python-version: '3.10'
6156

6257
steps:
6358
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8

CONTRIBUTING.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ Dependencies can also be directly installed via:
1616
% pip install -r misc/.analysis-requirements.txt
1717
```
1818

19+
**Note:** Until the release of Vermin 1.6, it is recommended to use Python 3.10 or lower when
20+
running analysis checks. This is because Pylint requires an update but doing so makes it
21+
incompatible with certain versions of Python 2.x. In Vermin 1.6, support for Python 2.7 will be
22+
removed and dependencies will be updated such that Python 3.11 can be used for analysis checks.
23+
1924
Unittests can be run without installing any dependencies: `make test`
2025

2126
## Detection Rules

README.rst

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ vanilla Python, and it doesn't have any external dependencies, it works with v2.
3737
required but detection of 2.x functionality will remain functional.
3838

3939
It functions by parsing Python code into an abstract syntax tree (AST), which it traverses and
40-
matches against internal dictionaries with **3427** rules, covering v2.0-2.7 and v3.0-3.10, divided
40+
matches against internal dictionaries with **3427** rules, covering v2.0-2.7 and v3.0-3.11, divided
4141
into **144** modules, **2356** classes/functions/constants members of modules, **801** kwargs of
4242
functions, **4** strftime directives, **3** bytes format directives, **2** array typecodes, **3**
4343
codecs error handler names, **20** codecs encodings, **75** builtin generic annotation types, **9**
@@ -136,18 +136,20 @@ Features detected include v2/v3 ``print expr`` and ``print(expr)``, ``long``, f-
136136
(``async`` and ``await``), asynchronous generators (``await`` and ``yield`` in same function),
137137
asynchronous comprehensions, ``await`` in comprehensions, asynchronous ``for``-loops, boolean
138138
constants, named expressions, keyword-only parameters, positional-only parameters, ``nonlocal``,
139-
``yield from``, exception context cause (``raise .. from ..``), ``set`` literals, ``set``
140-
comprehensions, ``dict`` comprehensions, infix matrix multiplication, ``"..".format(..)``, imports
141-
(``import X``, ``from X import Y``, ``from X import *``), function calls wrt. name and kwargs,
142-
``strftime`` + ``strptime`` directives used, function and variable annotations (also ``Final`` and
143-
``Literal``), ``continue`` in ``finally`` block, modular inverse ``pow()``, array typecodes, codecs
144-
error handler names, encodings, ``%`` formatting and directives for bytes and bytearray, ``with``
145-
statement, multiple context expressions in a ``with`` statement, unpacking assignment, generalized
146-
unpacking, ellipsis literal (`...`) out of slices, dictionary union (``{..} | {..}``), dictionary
147-
union merge (``a = {..}; a |= {..}``), builtin generic type annotations (``list[str]``), function
148-
decorators, class decorators, relaxed decorators, pattern matching with ``match``, and union types
149-
written as ``X | Y``. It tries to detect and ignore user-defined functions, classes, arguments, and
150-
variables with names that clash with library-defined symbols.
139+
``yield from``, exception context cause (``raise .. from ..``), ``except*``, ``set`` literals,
140+
``set`` comprehensions, ``dict`` comprehensions, infix matrix multiplication, ``"..".format(..)``,
141+
imports (``import X``, ``from X import Y``, ``from X import *``), function calls wrt. name and
142+
kwargs, ``strftime`` + ``strptime`` directives used, function and variable annotations (also
143+
``Final`` and ``Literal``), ``continue`` in ``finally`` block, modular inverse ``pow()``, array
144+
typecodes, codecs error handler names, encodings, ``%`` formatting and directives for bytes and
145+
bytearray, ``with`` statement, asynchronous ``with`` statement, multiple context expressions in a
146+
``with`` statement, multiple context expressions in a ``with`` statement grouped with parenthesis,
147+
unpacking assignment, generalized unpacking, ellipsis literal (``...``) out of slices, dictionary
148+
union (``{..} | {..}``), dictionary union merge (``a = {..}; a |= {..}``), builtin generic type
149+
annotations (``list[str]``), function decorators, class decorators, relaxed decorators, pattern
150+
matching with ``match``, and union types written as ``X | Y``. It tries to detect and ignore
151+
user-defined functions, classes, arguments, and variables with names that clash with library-defined
152+
symbols.
151153

152154
Caveats
153155
=======

tests/builtin_classes.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,9 @@ def test_memoryview(self):
3030

3131
def test_long(self):
3232
self.assertOnlyIn((2, 0), self.detect("long()"))
33+
34+
def test_ExceptionGroup(self):
35+
self.assertOnlyIn((3, 11), self.detect("ExceptionGroup()"))
36+
37+
def test_BaseExceptionGroup(self):
38+
self.assertOnlyIn((3, 11), self.detect("BaseExceptionGroup()"))

tests/class.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ def test_ABC_of_abc(self):
2222
def test_BooleanOptionalAction_of_argparse(self):
2323
self.assertOnlyIn((3, 9), self.detect("from argparse import BooleanOptionalAction"))
2424

25+
def test_Barrier_of_asyncio(self):
26+
self.assertOnlyIn((3, 11), self.detect("from asyncio import Barrier"))
27+
2528
def test_BufferedProtocol_of_asyncio(self):
2629
self.assertOnlyIn((3, 7), self.detect("from asyncio import BufferedProtocol"))
2730

@@ -34,6 +37,9 @@ def test_ThreadedChildWatcher_of_asyncio(self):
3437
def test_PidfdChildWatcher_of_asyncio(self):
3538
self.assertOnlyIn((3, 9), self.detect("from asyncio import PidfdChildWatcher"))
3639

40+
def test_Runner_of_asyncio(self):
41+
self.assertOnlyIn((3, 11), self.detect("from asyncio import Runner"))
42+
3743
def test_Calendar_of_calendar(self):
3844
self.assertOnlyIn(((2, 5), (3, 0)), self.detect("from calendar import Calendar"))
3945

@@ -160,6 +166,9 @@ def test_Deque_of_typing(self):
160166
def test_ForwardRef_of_typing(self):
161167
self.assertOnlyIn((3, 7), self.detect("from typing import ForwardRef"))
162168

169+
def test_NamedTuple_of_typing(self):
170+
self.assertOnlyIn((3, 11), self.detect("from typing import NamedTuple"))
171+
163172
def test_OrderedDict_of_typing(self):
164173
self.assertOnlyIn((3, 7), self.detect("from typing import OrderedDict"))
165174

@@ -293,6 +302,12 @@ def test_c_bool_of_ctypes(self):
293302
def test_c_ssize_t_of_ctypes(self):
294303
self.assertOnlyIn(((2, 7), (3, 2)), self.detect("from ctypes import c_ssize_t"))
295304

305+
def test_BigEndianUnion_of_ctypes(self):
306+
self.assertOnlyIn((3, 11), self.detect("from ctypes import BigEndianUnion"))
307+
308+
def test_LittleEndianUnion_of_ctypes(self):
309+
self.assertOnlyIn((3, 11), self.detect("from ctypes import LittleEndianUnion"))
310+
296311
def test_HtmlDiff_of_difflib(self):
297312
self.assertOnlyIn(((2, 4), (3, 0)), self.detect("from difflib import HtmlDiff"))
298313

@@ -311,6 +326,9 @@ def test_LoggerAdapter_of_logging(self):
311326
def test_NullHandler_of_logging(self):
312327
self.assertOnlyIn(((2, 7), (3, 1)), self.detect("from logging import NullHandler"))
313328

329+
def test_StreamHandler_of_logging(self):
330+
self.assertOnlyIn(((2, 6), (3, 0)), self.detect("from logging import StreamHandler"))
331+
314332
def test_QueueHandler_of_logging_handlers(self):
315333
self.assertOnlyIn((3, 2), self.detect("from logging.handlers import QueueHandler"))
316334

@@ -450,12 +468,21 @@ def test_DecodedGenerator_of_email_generator(self):
450468
def test_BytesGenerator_of_email_generator(self):
451469
self.assertOnlyIn((3, 2), self.detect("from email.generator import BytesGenerator"))
452470

471+
def test_EnumCheck_of_enum(self):
472+
self.assertOnlyIn((3, 11), self.detect("from enum import EnumCheck"))
473+
453474
def test_Flag_of_enum(self):
454475
self.assertOnlyIn((3, 6), self.detect("from enum import Flag"))
455476

477+
def test_FlagBoundary_of_enum(self):
478+
self.assertOnlyIn((3, 11), self.detect("from enum import FlagBoundary"))
479+
456480
def test_IntFlag_of_enum(self):
457481
self.assertOnlyIn((3, 6), self.detect("from enum import IntFlag"))
458482

483+
def test_StrEnum_of_enum(self):
484+
self.assertOnlyIn((3, 11), self.detect("from enum import StrEnum"))
485+
459486
def test_auto_of_enum(self):
460487
self.assertOnlyIn((3, 6), self.detect("from enum import auto"))
461488

@@ -465,6 +492,9 @@ def test_FTP_TLS_of_ftplib(self):
465492
def test_partialmethod_of_functools(self):
466493
self.assertOnlyIn((3, 4), self.detect("from functools import partialmethod"))
467494

495+
def test_HTTPMethod_of_http(self):
496+
self.assertOnlyIn((3, 11), self.detect("from http import HTTPMethod"))
497+
468498
def test_HTTPStatus_of_http(self):
469499
self.assertOnlyIn((3, 5), self.detect("from http import HTTPStatus"))
470500

@@ -525,6 +555,9 @@ def test_ExtensionFileLoader_of_importlib_machinery(self):
525555
def test_ModuleSpec_of_importlib_machinery(self):
526556
self.assertOnlyIn((3, 4), self.detect("from importlib.machinery import ModuleSpec"))
527557

558+
def test_NamespaceLoader_of_importlib_machinery(self):
559+
self.assertOnlyIn((3, 11), self.detect("from importlib.machinery import NamespaceLoader"))
560+
528561
def test_EntryPoints_of_importlib_metadata(self):
529562
self.assertOnlyIn((3, 10), self.detect("from importlib.metadata import EntryPoints"))
530563

@@ -537,6 +570,9 @@ def test_Bytecode_of_dis(self):
537570
def test_Instruction_of_dis(self):
538571
self.assertOnlyIn((3, 4), self.detect("from dis import Instruction"))
539572

573+
def test_Positions_of_dis(self):
574+
self.assertOnlyIn((3, 11), self.detect("from dis import Positions"))
575+
540576
def test_DocTest_of_doctest(self):
541577
self.assertOnlyIn(((2, 4), (3, 0)), self.detect("from doctest import DocTest"))
542578

@@ -572,6 +608,9 @@ def test_ParamSpec_of_typing(self):
572608
def test_SMTP_SSL_of_smtplib(self):
573609
self.assertOnlyIn(((2, 6), (3, 0)), self.detect("from smtplib import SMTP_SSL"))
574610

611+
def test_Blob_of_sqlite3(self):
612+
self.assertOnlyIn((3, 11), self.detect("from sqlite3 import Blob"))
613+
575614
def test_LMTP_of_smtplib(self):
576615
self.assertOnlyIn(((2, 6), (3, 0)), self.detect("from smtplib import LMTP"))
577616

0 commit comments

Comments
 (0)