Skip to content

Add Python 3.13 support #267

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/analyze.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.12']
python-version: ['3.13']

steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
# Start Linux jobs last since they are fastest to start and complete, and start 3.12 first,
# Start Linux jobs last since they are fastest to start and complete, and start 3.13 first,
# since it pairs wiht macOS+Windows jobs, and 3.5 and 3.6 last since they only run tests and
# don't use venv. 3.4 is not supported on GitHub anymore and 3.5 and 3.6 for x64 isn't
# produced for ubuntu 22.04.
python-version: ['3.12', '3.11', '3.10', 3.9, 3.8, 3.7, 3.6, 3.5]
python-version: ['3.13', '3.12', '3.11', '3.10', 3.9, 3.8, 3.7, 3.6, 3.5]
os: [windows-latest, macos-latest, ubuntu-latest]

# Choose test script depending on OS.
Expand Down
16 changes: 8 additions & 8 deletions misc/.analysis-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ bracex==2.3.post1
build==0.10.0
certifi==2023.7.22
charset-normalizer==3.1.0
click==8.1.4
click==8.1.8
click-option-group==0.5.6
colorama==0.4.6
defusedxml==0.7.1
dill==0.3.6
dill==0.3.9
docutils==0.20.1
face==22.0.0
flake8==6.0.0
gitdb==4.0.10
GitPython==3.1.36
gitdb==4.0.12
GitPython==3.1.44
glom==22.1.0
idna==3.4
isort==5.12.0
Expand All @@ -28,7 +28,7 @@ mdurl==0.1.2
packaging==23.1
pbr==5.11.1
peewee==3.16.2
pep517==0.13.0
pep517==0.13.1
platformdirs==3.5.3
pycodestyle==2.10.0
pyflakes==3.0.1
Expand All @@ -38,17 +38,17 @@ pyparsing==3.0.9
pyproject_hooks==1.0.0
pyroma==4.2
python-lsp-jsonrpc==1.0.0
PyYAML==6.0.1
PyYAML==6.0.2
referencing==0.29.1
requests==2.31.0
rich==13.4.2
rpds-py==0.8.10
ruamel.yaml==0.17.35
ruamel.yaml.clib==0.2.8
ruamel.yaml.clib==0.2.12
semgrep==1.31.1
setuptools==68.2.2
six==1.16.0
smmap==5.0.0
smmap==5.0.2
stevedore==5.1.0
toml==0.10.2
tomli==2.0.1
Expand Down
9 changes: 9 additions & 0 deletions tests/array_typecodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,12 @@ def test_typecode_q(self, source, min_versions):
])
def test_typecode_Q(self, source, min_versions):
self.assertDetectMinVersions(source, min_versions)

@VerminTest.parameterized_args([
("from array import array\narray('w')", (3, 13)),
("import array\narray.array('w')", (3, 13)),
("from array import array\narray('w', [1, 2])", (3, 13)),
("from array import array as a\na('w', [1, 2])", (3, 13)),
])
def test_typecode_w(self, source, min_versions):
self.assertDetectMinVersions(source, min_versions)
3 changes: 3 additions & 0 deletions tests/builtin_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ def test_PermissionError(self):

def test_ProcessLookupError(self):
self.assertOnlyIn((3, 3), self.detect("ProcessLookupError()"))

def test_PythonFinalizationError(self):
self.assertOnlyIn((3, 13), self.detect("PythonFinalizationError()"))

def test_RecursionError(self):
self.assertOnlyIn((3, 5), self.detect("RecursionError()"))
Expand Down
12 changes: 12 additions & 0 deletions tests/class.py
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,9 @@ def test_BytesGenerator_of_email_generator(self):
def test_EnumCheck_of_enum(self):
self.assertOnlyIn((3, 11), self.detect("from enum import EnumCheck"))

def test_EnumDict_of_enum(self):
self.assertOnlyIn((3, 13), self.detect("from enum import EnumDict"))

def test_Flag_of_enum(self):
self.assertOnlyIn((3, 6), self.detect("from enum import Flag"))

Expand Down Expand Up @@ -639,6 +642,15 @@ def test_UID_of_plistlib(self):
def test_NormalDist_of_statistics(self):
self.assertOnlyIn((3, 8), self.detect("from statistics import NormalDist"))

def test_NoDefault_of_typing(self):
self.assertOnlyIn((3, 13), self.detect("from typing import NoDefault"))

def test_ReadOnly_of_typing(self):
self.assertOnlyIn((3, 13), self.detect("from typing import ReadOnly"))

def test_TypeIs_of_typing(self):
self.assertOnlyIn((3, 13), self.detect("from typing import TypeIs"))

def test_TypedDict_of_typing(self):
self.assertOnlyIn((3, 8), self.detect("from typing import TypedDict"))
self.assertTrue(self.config.add_backport("typing"))
Expand Down
63 changes: 63 additions & 0 deletions tests/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,54 @@ def test_step_of_range(self):

def test_stop_of_range(self):
self.assertOnlyIn((3, 3), self.detect("range.stop"))

def test__field_types_of_ast_AST(self):
self.assertOnlyIn((3, 13), self.detect("from ast import AST\nAST._field_types"))

def test__align__of_ctypes_Structure(self):
self.assertOnlyIn((3, 13), self.detect("from ctypes import Structure\nStructure._align_"))

def test_start_offset_of_dis_Instruction(self):
self.assertOnlyIn((3, 13), self.detect("from dis import Instruction\nInstruction.start_offset"))

def test_cache_offset_of_dis_Instruction(self):
self.assertOnlyIn((3, 13), self.detect("from dis import Instruction\nInstruction.cache_offset"))

def test_end_offset_of_dis_Instruction(self):
self.assertOnlyIn((3, 13), self.detect("from dis import Instruction\nInstruction.end_offset"))

def test_baseopname_of_dis_Instruction(self):
self.assertOnlyIn((3, 13), self.detect("from dis import Instruction\nInstruction.baseopname"))

def test_baseopcode_of_dis_Instruction(self):
self.assertOnlyIn((3, 13), self.detect("from dis import Instruction\nInstruction.baseopcode"))

def test_jump_target_of_dis_Instruction(self):
self.assertOnlyIn((3, 13), self.detect("from dis import Instruction\nInstruction.jump_target"))

def test_oparg_of_dis_Instruction(self):
self.assertOnlyIn((3, 13), self.detect("from dis import Instruction\nInstruction.oparg"))

def test_line_number_of_dis_Instruction(self):
self.assertOnlyIn((3, 13), self.detect("from dis import Instruction\nInstruction.line_number"))

def test_cache_info_of_dis_Instruction(self):
self.assertOnlyIn((3, 13), self.detect("from dis import Instruction\nInstruction.cache_info"))

def test_skips_of_doctest_DocTestRunner(self):
self.assertOnlyIn((3, 13), self.detect("from doctest import DocTestRunner\nDocTestRunner.skips"))

def test_skipped_of_doctest_DocTestRunner(self):
self.assertOnlyIn((3, 13), self.detect("from doctest import DocTestRunner\nDocTestRunner.skipped"))

def test_verify_generated_headers_of_email_policy_Policy(self):
self.assertOnlyIn((3, 13), self.detect("from email.policy import Policy\nPolicy.verify_generated_headers"))

def test_mode_of_lzma_LZMAFile(self):
self.assertOnlyIn((3, 13), self.detect("from lzma import LZMAFile\nLZMAFile.mode"))

def test_name_of_lzma_LZMAFile(self):
self.assertOnlyIn((3, 13), self.detect("from lzma import LZMAFile\nLZMAFile.name"))

def test_flags_of_sys(self):
self.assertOnlyIn(((2, 6), (3, 0)), self.detect("from sys import flags"))
Expand All @@ -68,6 +116,18 @@ def test_supports_bytes_environ_of_os(self):
def test_environb_of_os(self):
self.assertOnlyIn((3, 2), self.detect("from os import environb"))

def test_TFD_NONBLOCK_of_os(self):
self.assertOnlyIn((3, 13), self.detect("from os import TFD_NONBLOCK"))

def test_TFD_CLOEXEC_of_os(self):
self.assertOnlyIn((3, 13), self.detect("from os import TFD_CLOEXEC"))

def test_TFD_TIMER_ABSTIME_of_os(self):
self.assertOnlyIn((3, 13), self.detect("from os import TFD_TIMER_ABSTIME"))

def test_TFD_TIMER_CANCEL_ON_SET_of_os(self):
self.assertOnlyIn((3, 13), self.detect("from os import TFD_TIMER_CANCEL_ON_SET"))

def test_PRIO_PROCESS_of_os(self):
self.assertOnlyIn((3, 3), self.detect("from os import PRIO_PROCESS"))

Expand Down Expand Up @@ -179,6 +239,9 @@ def test_api_version_of_sys(self):
def test_version_info_of_sys(self):
self.assertOnlyIn(((2, 0), (3, 0)), self.detect("from sys import version_info"))

def test_exc_type_str_of_traceback_TracebackException(self):
self.assertOnlyIn((3, 13), self.detect("from traceback import TracebackException\nTracebackException.exc_type_str"))

def test_sentinel_of_multiprocessing_Process(self):
self.assertOnlyIn((3, 3),
self.detect("from multiprocessing import Process\np = Process()\np.sentinel"))
Expand Down
12 changes: 12 additions & 0 deletions tests/exception.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
from .testutils import VerminTest

class VerminExceptionMemberTests(VerminTest):
def test_QueueShutDown_of_asyncio(self):
self.assertOnlyIn((3, 13), self.detect("from asyncio import QueueShutDown"))

def test_SSLCertVerificationError_of_ssl(self):
self.assertOnlyIn((3, 7), self.detect("from ssl import SSLCertVerificationError"))

Expand Down Expand Up @@ -123,6 +126,15 @@ def test_UnknownTransferEncoding_of_httplib(self):

def test_JSONDecodeError_of_json(self):
self.assertOnlyIn((3, 5), self.detect("from json import JSONDecodeError"))

def test_UnsupportedOperation_of_pathlib(self):
self.assertOnlyIn((3, 13), self.detect("from pathlib import UnsupportedOperation"))

def test_ShutDown_of_queue(self):
self.assertOnlyIn((3, 13), self.detect("from queue import ShutDown"))

def test_PatternError_of_re(self):
self.assertOnlyIn((3, 13), self.detect("from re import PatternError"))

def test_SGMLParseError_of_sgmllib(self):
self.assertOnlyIn((2, 1), self.detect("from sgmllib import SGMLParseError"))
Expand Down
Loading