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() + """ + )