commit:     20db5ba2a46661b821c63c7a2f9c65f46bc16ffe
Author:     Michał Górny <mgorny <AT> gentoo <DOT> org>
AuthorDate: Mon Jul  8 19:04:22 2024 +0000
Commit:     Michał Górny <mgorny <AT> gentoo <DOT> org>
CommitDate: Mon Jul  8 19:22:28 2024 +0000
URL:        https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=20db5ba2

dev-python/astroid: Enable py3.13

Signed-off-by: Michał Górny <mgorny <AT> gentoo.org>

 dev-python/astroid/astroid-3.2.2-r1.ebuild         |  86 ++++++++++
 dev-python/astroid/files/astroid-3.2.2-py313.patch | 177 +++++++++++++++++++++
 2 files changed, 263 insertions(+)

diff --git a/dev-python/astroid/astroid-3.2.2-r1.ebuild 
b/dev-python/astroid/astroid-3.2.2-r1.ebuild
new file mode 100644
index 000000000000..a3d9b680035d
--- /dev/null
+++ b/dev-python/astroid/astroid-3.2.2-r1.ebuild
@@ -0,0 +1,86 @@
+# Copyright 1999-2024 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=8
+
+DISTUTILS_USE_PEP517=setuptools
+PYTHON_COMPAT=( pypy3 python3_{10..13} )
+
+inherit distutils-r1
+
+DESCRIPTION="Abstract Syntax Tree for logilab packages"
+HOMEPAGE="
+       https://github.com/pylint-dev/astroid/
+       https://pypi.org/project/astroid/
+"
+SRC_URI="
+       https://github.com/pylint-dev/astroid/archive/v${PV}.tar.gz
+               -> ${P}.gh.tar.gz
+"
+
+LICENSE="LGPL-2.1+"
+SLOT="0"
+KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~loong ~m68k ~mips ~ppc ~ppc64 
~riscv ~s390 ~sparc ~x86"
+
+# Version specified in pyproject.toml
+RDEPEND="
+       $(python_gen_cond_dep '
+               >=dev-python/typing-extensions-4.0.0[${PYTHON_USEDEP}]
+       ' 3.10)
+"
+# dev-python/regex isn't available for pypy
+BDEPEND="
+       dev-python/setuptools-scm[${PYTHON_USEDEP}]
+       test? (
+               dev-python/attrs[${PYTHON_USEDEP}]
+               >=dev-python/numpy-1.17.0[${PYTHON_USEDEP}]
+               dev-python/python-dateutil[${PYTHON_USEDEP}]
+               $(python_gen_cond_dep '
+                       dev-python/regex[${PYTHON_USEDEP}]
+               ' 'python*')
+       )
+"
+
+distutils_enable_tests pytest
+
+export SETUPTOOLS_SCM_PRETEND_VERSION=${PV}
+
+PATCHES=(
+       # https://github.com/pylint-dev/astroid/pull/2424 (rebased)
+       "${FILESDIR}/${P}-py313.patch"
+)
+
+python_test() {
+       local EPYTEST_DESELECT=(
+               # no clue why they're broken
+               
tests/test_modutils.py::GetModulePartTest::test_known_values_get_builtin_module_part
+               tests/test_regrtest.py::NonRegressionTests::test_numpy_distutils
+               # pydantic-2?
+               tests/brain/test_dataclasses.py::test_pydantic_field
+               # requires urllib3 with bundled six (skipped with urllib3>=2)
+               
tests/test_modutils.py::test_file_info_from_modpath__SixMetaPathImporter
+               # hangs
+               tests/test_nodes.py::AsStringTest::test_recursion_error_trapped
+               # TODO
+               
tests/test_builder.py::BuilderTest::test_data_build_error_filename
+               # numpy-2 (https://github.com/pylint-dev/astroid/issues/2442)
+               
tests/brain/numpy/test_core_einsumfunc.py::test_numpy_function_calls_inferred_as_ndarray
+               
tests/brain/numpy/test_core_fromnumeric.py::BrainNumpyCoreFromNumericTest::test_numpy_function_calls_inferred_as_ndarray
+               
tests/brain/numpy/test_core_multiarray.py::BrainNumpyCoreMultiarrayTest::test_numpy_function_calls_inferred_as_ndarray
+               
tests/brain/numpy/test_core_numerictypes.py::NumpyBrainCoreNumericTypesTest::test_datetime_astype_return
+               
tests/brain/numpy/test_core_numerictypes.py::NumpyBrainCoreNumericTypesTest::test_generic_types_are_subscriptables
+               
tests/brain/numpy/test_core_umath.py::NumpyBrainCoreUmathTest::test_numpy_core_umath_functions_return_type
+               
tests/brain/numpy/test_core_umath.py::NumpyBrainCoreUmathTest::test_numpy_core_umath_functions_return_type_tuple
+       )
+
+       case ${EPYTHON} in
+               pypy3)
+                       EPYTEST_DESELECT+=(
+                               
tests/test_transforms.py::TestTransforms::test_transform_aborted_if_recursion_limited
+                       )
+                       ;;
+       esac
+
+       local -x PYTEST_DISABLE_PLUGIN_AUTOLOAD=1
+       epytest
+}

diff --git a/dev-python/astroid/files/astroid-3.2.2-py313.patch 
b/dev-python/astroid/files/astroid-3.2.2-py313.patch
new file mode 100644
index 000000000000..f8addfe9ef7c
--- /dev/null
+++ b/dev-python/astroid/files/astroid-3.2.2-py313.patch
@@ -0,0 +1,177 @@
+diff --git a/astroid/brain/brain_dataclasses.py 
b/astroid/brain/brain_dataclasses.py
+index 88a4385f..743dfe96 100644
+--- a/astroid/brain/brain_dataclasses.py
++++ b/astroid/brain/brain_dataclasses.py
+@@ -19,7 +19,7 @@ from typing import Literal, Tuple, Union
+ 
+ from astroid import bases, context, nodes
+ from astroid.builder import parse
+-from astroid.const import PY39_PLUS, PY310_PLUS
++from astroid.const import PY39_PLUS, PY310_PLUS, PY313_PLUS
+ from astroid.exceptions import AstroidSyntaxError, InferenceError, 
UseInferenceDefault
+ from astroid.inference_tip import inference_tip
+ from astroid.manager import AstroidManager
+@@ -503,6 +503,15 @@ def _looks_like_dataclass_field_call(
+     return inferred.name == FIELD_NAME and inferred.root().name in 
DATACLASS_MODULES
+ 
+ 
++def _looks_like_dataclasses(node: nodes.Module) -> bool:
++    return node.qname() == "dataclasses"
++
++
++def _resolve_private_replace_to_public(node: nodes.Module) -> None:
++    if "_replace" in node.locals:
++        node.locals["replace"] = node.locals["_replace"]
++
++
+ def _get_field_default(field_call: nodes.Call) -> _FieldDefaultReturn:
+     """Return a the default value of a field call, and the corresponding 
keyword
+     argument name.
+@@ -618,6 +627,13 @@ def _infer_instance_from_annotation(
+ 
+ 
+ def register(manager: AstroidManager) -> None:
++    if PY313_PLUS:
++        manager.register_transform(
++            nodes.Module,
++            _resolve_private_replace_to_public,
++            _looks_like_dataclasses,
++        )
++
+     manager.register_transform(
+         nodes.ClassDef, dataclass_transform, is_decorated_with_dataclass
+     )
+diff --git a/astroid/brain/brain_pathlib.py b/astroid/brain/brain_pathlib.py
+index 116cd2ee..d0f53132 100644
+--- a/astroid/brain/brain_pathlib.py
++++ b/astroid/brain/brain_pathlib.py
+@@ -8,6 +8,7 @@ from collections.abc import Iterator
+ 
+ from astroid import bases, context, inference_tip, nodes
+ from astroid.builder import _extract_single_node
++from astroid.const import PY313_PLUS
+ from astroid.exceptions import InferenceError, UseInferenceDefault
+ from astroid.manager import AstroidManager
+ 
+@@ -27,10 +28,11 @@ def _looks_like_parents_subscript(node: nodes.Subscript) 
-> bool:
+         value = next(node.value.infer())
+     except (InferenceError, StopIteration):
+         return False
++    parents = "builtins.tuple" if PY313_PLUS else "pathlib._PathParents"
+     return (
+         isinstance(value, bases.Instance)
+         and isinstance(value._proxied, nodes.ClassDef)
+-        and value.qname() == "pathlib._PathParents"
++        and value.qname() == parents
+     )
+ 
+ 
+diff --git a/astroid/brain/brain_typing.py b/astroid/brain/brain_typing.py
+index 9965abc2..7a7c7183 100644
+--- a/astroid/brain/brain_typing.py
++++ b/astroid/brain/brain_typing.py
+@@ -15,7 +15,7 @@ from typing import Final
+ from astroid import context, extract_node, inference_tip
+ from astroid.brain.helpers import register_module_extender
+ from astroid.builder import AstroidBuilder, _extract_single_node
+-from astroid.const import PY39_PLUS, PY312_PLUS
++from astroid.const import PY39_PLUS, PY312_PLUS, PY313_PLUS
+ from astroid.exceptions import (
+     AstroidSyntaxError,
+     AttributeInferenceError,
+@@ -168,6 +168,15 @@ def infer_typing_attr(
+         # If typing subscript belongs to an alias handle it separately.
+         raise UseInferenceDefault
+ 
++    if (
++        PY313_PLUS
++        and isinstance(value, FunctionDef)
++        and value.qname() == "typing.Annotated"
++    ):
++        # typing.Annotated is a FunctionDef on 3.13+
++        node._explicit_inference = lambda node, context: iter([value])
++        return iter([value])
++
+     if isinstance(value, ClassDef) and value.qname() in {
+         "typing.Generic",
+         "typing.Annotated",
+diff --git a/tests/brain/test_brain.py b/tests/brain/test_brain.py
+index b8bc84e3..78b6f8b3 100644
+--- a/tests/brain/test_brain.py
++++ b/tests/brain/test_brain.py
+@@ -647,7 +647,7 @@ class TypingBrain(unittest.TestCase):
+ 
+     @test_utils.require_version(minver="3.9")
+     def test_typing_annotated_subscriptable(self):
+-        """Test typing.Annotated is subscriptable with __class_getitem__"""
++        """typing.Annotated is subscriptable with __class_getitem__ below 
3.13."""
+         node = builder.extract_node(
+             """
+         import typing
+@@ -655,8 +655,13 @@ class TypingBrain(unittest.TestCase):
+         """
+         )
+         inferred = next(node.infer())
+-        assert isinstance(inferred, nodes.ClassDef)
+-        assert isinstance(inferred.getattr("__class_getitem__")[0], 
nodes.FunctionDef)
++        if PY313_PLUS:
++            assert isinstance(inferred, nodes.FunctionDef)
++        else:
++            assert isinstance(inferred, nodes.ClassDef)
++            assert isinstance(
++                inferred.getattr("__class_getitem__")[0], nodes.FunctionDef
++            )
+ 
+     def test_typing_generic_slots(self):
+         """Test slots for Generic subclass."""
+diff --git a/tests/brain/test_pathlib.py b/tests/brain/test_pathlib.py
+index d935d964..5aea8d37 100644
+--- a/tests/brain/test_pathlib.py
++++ b/tests/brain/test_pathlib.py
+@@ -5,7 +5,7 @@
+ 
+ import astroid
+ from astroid import bases
+-from astroid.const import PY310_PLUS
++from astroid.const import PY310_PLUS, PY313_PLUS
+ from astroid.util import Uninferable
+ 
+ 
+@@ -23,7 +23,10 @@ def test_inference_parents() -> None:
+     inferred = name_node.inferred()
+     assert len(inferred) == 1
+     assert isinstance(inferred[0], bases.Instance)
+-    assert inferred[0].qname() == "pathlib._PathParents"
++    if PY313_PLUS:
++        assert inferred[0].qname() == "builtins.tuple"
++    else:
++        assert inferred[0].qname() == "pathlib._PathParents"
+ 
+ 
+ def test_inference_parents_subscript_index() -> None:
+@@ -40,7 +43,10 @@ def test_inference_parents_subscript_index() -> None:
+     inferred = path.inferred()
+     assert len(inferred) == 1
+     assert isinstance(inferred[0], bases.Instance)
+-    assert inferred[0].qname() == "pathlib.Path"
++    if PY313_PLUS:
++        assert inferred[0].qname() == "pathlib._local.Path"
++    else:
++        assert inferred[0].qname() == "pathlib.Path"
+ 
+ 
+ def test_inference_parents_subscript_slice() -> None:
+diff --git a/tests/test_inference.py b/tests/test_inference.py
+index ec8fc71b..95f00821 100644
+--- a/tests/test_inference.py
++++ b/tests/test_inference.py
+@@ -4458,8 +4458,7 @@ class InferenceTest(resources.SysPathSetup, 
unittest.TestCase):
+         # and reraise it as a TypeError in Class.getitem
+         node = extract_node(
+             """
+-        def test():
+-            yield
++        def test(): ...
+         test()
+         """
+         )

Reply via email to