diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index dced168f..942a5e28 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -28,6 +28,9 @@ jobs: - name: py312 python: "3.12" toxenv: py312 + - name: py313 + python: "3.13" + toxenv: py313 - name: black python: "3.12" toxenv: black diff --git a/docs/changelog.md b/docs/changelog.md index 0bc997b9..7b7ce033 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -2,6 +2,7 @@ ## Unreleased +- Add support for Python 3.13 (#824) - Drop support for Python 3.8 (#820) - Flag invalid regexes in arguments to functions like `re.search` (#816) diff --git a/pyanalyze/name_check_visitor.py b/pyanalyze/name_check_visitor.py index c56c5527..2ca5521e 100644 --- a/pyanalyze/name_check_visitor.py +++ b/pyanalyze/name_check_visitor.py @@ -4816,8 +4816,8 @@ def visit_TypeVar(self, node: ast.TypeVar) -> Value: else: bound = self.visit(node.bound) if sys.version_info >= (3, 13): - if node.default is not None: - default = self.visit(node.default) + if node.default_value is not None: + default = self.visit(node.default_value) tv = TypeVar(node.name) typevar = TypeVarValue( tv, diff --git a/pyanalyze/test_arg_spec.py b/pyanalyze/test_arg_spec.py index 7abf0bd1..2a2d2980 100644 --- a/pyanalyze/test_arg_spec.py +++ b/pyanalyze/test_arg_spec.py @@ -210,10 +210,19 @@ def test_get_argspec(): Composite(KnownValue(ClassWithCall)), ) == asc.get_argspec(ClassWithCall.pure_async_classmethod) + # This behaves differently in 3.9 through 3.12 than in earlier and later + # versions. The behavior change was made in + # https://github.com/python/cpython/issues/63272 + # and undone in https://github.com/python/cpython/issues/89519 + if hasattr(ClassWithCall.classmethod_before_async, "decorator"): + callable = ClassWithCall.classmethod_before_async.decorator.fn + else: + callable = ClassWithCall.classmethod_before_async.__func__.fn + assert BoundMethodSignature( Signature.make( [SigParameter("cls"), SigParameter("ac")], - callable=ClassWithCall.classmethod_before_async.decorator.fn, + callable=callable, is_asynq=True, ), Composite(KnownValue(ClassWithCall)), diff --git a/setup.py b/setup.py index a11d085c..8d56be22 100644 --- a/setup.py +++ b/setup.py @@ -25,6 +25,7 @@ "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", ], keywords="quora static analysis", packages=["pyanalyze"], diff --git a/tox.ini b/tox.ini index c1b507aa..0dc8a64a 100644 --- a/tox.ini +++ b/tox.ini @@ -19,7 +19,7 @@ commands = [testenv:ruff] deps = - ruff==0.2.2 + ruff==0.6.9 commands = ruff check pyanalyze/