Source: astroid
Version: 3.2.2-1
Severity: normal
User: [email protected]
Usertags: python3.13
Forwarded: https://github.com/pylint-dev/astroid/issues/2349

This package failed build from source when test-built against a version of
python3-defaults that includes 3.13 as a supported version.

To reproduce this issue, build against python3-defaults (python3-all-dev etc.)
from Debian experimental.

Looks like 3.3.0 upstream should add support.

What's new in Python 3.13:
https://docs.python.org/3.13/whatsnew/3.13.html

Log snippet:

I: pybuild plugin_pyproject:144: Unpacking wheel built for python3.12 with 
"installer" module
   dh_auto_test -O--buildsystem=pybuild
I: pybuild pybuild:308: cp -r /<<PKGBUILDDIR>>/tests 
/<<PKGBUILDDIR>>/.pybuild/cpython3_3.13_astroid/build/astroid/
I: pybuild base:311: cd /<<PKGBUILDDIR>>/.pybuild/cpython3_3.13_astroid/build; 
python3.13 -m pytest tests
============================= test session starts ==============================
platform linux -- Python 3.13.0rc2, pytest-8.3.2, pluggy-1.5.0
rootdir: /<<PKGBUILDDIR>>/.pybuild/cpython3_3.13_astroid/build
configfile: pyproject.toml
plugins: typeguard-4.3.0
collected 1689 items

tests/brain/numpy/test_core_einsumfunc.py ss                             [  0%]
tests/brain/numpy/test_core_fromnumeric.py s                             [  0%]
tests/brain/numpy/test_core_function_base.py s                           [  0%]
tests/brain/numpy/test_core_multiarray.py sssss                          [  0%]
tests/brain/numpy/test_core_numeric.py sssss                             [  0%]
tests/brain/numpy/test_core_numerictypes.py sssssss..                    [  1%]
tests/brain/numpy/test_core_umath.py ssssssss                            [  1%]
tests/brain/numpy/test_ma.py ssss                                        [  2%]
tests/brain/numpy/test_ndarray.py sss                                    [  2%]
tests/brain/numpy/test_random_mtrand.py ss                               [  2%]
tests/brain/test_argparse.py .                                           [  2%]
tests/brain/test_attr.py sssss                                           [  2%]
tests/brain/test_brain.py .s.....s....ss........................F....... [  5%]
............s..........................................................x [  9%]
...............s......                                                   [ 11%]
tests/brain/test_builtin.py ..................                           [ 12%]
tests/brain/test_ctypes.py ....x........................                 [ 13%]
tests/brain/test_dataclasses.py ........................................ [ 16%]
......................................x...                               [ 18%]
tests/brain/test_dateutil.py s                                           [ 18%]
tests/brain/test_enum.py .............................                   [ 20%]
tests/brain/test_hashlib.py ...                                          [ 20%]
tests/brain/test_multiprocessing.py ...                                  [ 20%]
tests/brain/test_named_tuple.py .......................                  [ 22%]
tests/brain/test_nose.py s                                               [ 22%]
tests/brain/test_pathlib.py FF..                                         [ 22%]
tests/brain/test_pytest.py .                                             [ 22%]
tests/brain/test_qt.py sss                                               [ 22%]
tests/brain/test_regex.py ss                                             [ 22%]
tests/brain/test_signal.py ...                                           [ 22%]
tests/brain/test_six.py .......                                          [ 23%]
tests/brain/test_ssl.py .                                                [ 23%]
tests/brain/test_threading.py ....                                       [ 23%]
tests/brain/test_typing.py .                                             [ 23%]
tests/brain/test_typing_extensions.py .                                  [ 23%]
tests/brain/test_unittest.py .                                           [ 23%]
tests/test_builder.py .................................................. [ 26%]
.....x..                                                                 [ 27%]
tests/test_constraint.py ...................................             [ 29%]
tests/test_decorators.py ...                                             [ 29%]
tests/test_filter_statements.py .                                        [ 29%]
tests/test_group_exceptions.py ...                                       [ 29%]
tests/test_helpers.py ...............                                    [ 30%]
tests/test_inference.py ................................................ [ 33%]
..........................................x...........x.....x.....F..... [ 37%]
..............................................x......................... [ 42%]
........................................................................ [ 46%]
........................................x........xx..................... [ 50%]
x...x..........................................sF.....x................. [ 54%]
.......................                                                  [ 56%]
tests/test_inference_calls.py ........................                   [ 57%]
tests/test_lookup.py ................................................... [ 60%]
....                                                                     [ 60%]
tests/test_manager.py ............................................       [ 63%]
tests/test_modutils.py ................................................. [ 66%]
................s.                                                       [ 67%]
tests/test_nodes.py .................................................... [ 70%]
........................................................................ [ 74%]
................................................................         [ 78%]
tests/test_nodes_lineno.py s.......................                      [ 79%]
tests/test_nodes_position.py ...                                         [ 80%]
tests/test_object_model.py x...............x.........s.........          [ 82%]
tests/test_objects.py ......................                             [ 83%]
tests/test_protocols.py .....................                            [ 84%]
tests/test_python3.py ..........................                         [ 86%]
tests/test_raw_building.py .............                                 [ 87%]
tests/test_regrtest.py .............ss...........                        [ 88%]
tests/test_scoped_nodes.py ............................................. [ 91%]
........................................................................ [ 95%]
..................................................                       [ 98%]
tests/test_stdlib.py ..                                                  [ 98%]
tests/test_transforms.py .........                                       [ 99%]
tests/test_type_params.py .....                                          [ 99%]
tests/test_utils.py ........                                             [100%]

=================================== FAILURES ===================================
_______________ TypingBrain.test_typing_annotated_subscriptable ________________

self = <tests.brain.test_brain.TypingBrain 
testMethod=test_typing_annotated_subscriptable>

    @test_utils.require_version(minver="3.9")
    def test_typing_annotated_subscriptable(self):
        """Test typing.Annotated is subscriptable with __class_getitem__"""
        node = builder.extract_node(
            """
        import typing
        typing.Annotated[str, "data"]
        """
        )
        inferred = next(node.infer())
        assert isinstance(inferred, nodes.ClassDef)
>       assert isinstance(inferred.getattr("__class_getitem__")[0], 
> nodes.FunctionDef)

tests/brain/test_brain.py:659: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <ClassDef.Annotated l.10 at 0xffffb01be5d0>, name = '__class_getitem__'
context = None, class_context = True

    def getattr(
        self,
        name: str,
        context: InferenceContext | None = None,
        class_context: bool = True,
    ) -> list[InferenceResult]:
        """Get an attribute from this class, using Python's attribute semantic.
    
        This method doesn't look in the :attr:`instance_attrs` dictionary
        since it is done by an :class:`Instance` proxy at inference time.
        It may return an :class:`Uninferable` object if
        the attribute has not been
        found, but a ``__getattr__`` or ``__getattribute__`` method is defined.
        If ``class_context`` is given, then it is considered that the
        attribute is accessed from a class context,
        e.g. ClassDef.attribute, otherwise it might have been accessed
        from an instance as well. If ``class_context`` is used in that
        case, then a lookup in the implicit metaclass and the explicit
        metaclass will be done.
    
        :param name: The attribute to look for.
    
        :param class_context: Whether the attribute can be accessed statically.
    
        :returns: The attribute.
    
        :raises AttributeInferenceError: If the attribute cannot be inferred.
        """
        if not name:
            raise AttributeInferenceError(target=self, attribute=name, 
context=context)
    
        # don't modify the list in self.locals!
        values: list[InferenceResult] = list(self.locals.get(name, []))
        for classnode in self.ancestors(recurs=True, context=context):
            values += classnode.locals.get(name, [])
    
        if name in self.special_attributes and class_context and not values:
            result = [self.special_attributes.lookup(name)]
            if name == "__bases__":
                # Need special treatment, since they are mutable
                # and we need to return all the values.
                result += values
            return result
    
        if class_context:
            values += self._metaclass_lookup_attribute(name, context)
    
        # Remove AnnAssigns without value, which are not attributes in the 
purest sense.
        for value in values.copy():
            if isinstance(value, node_classes.AssignName):
                stmt = value.statement()
                if isinstance(stmt, node_classes.AnnAssign) and stmt.value is 
None:
                    values.pop(values.index(value))
    
        if not values:
>           raise AttributeInferenceError(target=self, attribute=name, 
> context=context)
E           astroid.exceptions.AttributeInferenceError: '__class_getitem__' not 
found on <ClassDef.Annotated l.10 at 0xffffb01be5d0>.

astroid/nodes/scoped_nodes/scoped_nodes.py:2441: AttributeInferenceError
____________________________ test_inference_parents ____________________________

    def test_inference_parents() -> None:
        """Test inference of ``pathlib.Path.parents``."""
        name_node = astroid.extract_node(
            """
        from pathlib import Path
    
        current_path = Path().resolve()
        path_parents = current_path.parents
        path_parents
        """
        )
        inferred = name_node.inferred()
        assert len(inferred) == 1
        assert isinstance(inferred[0], bases.Instance)
>       assert inferred[0].qname() == "pathlib._PathParents"
E       AssertionError: assert 'builtins.tuple' == 'pathlib._PathParents'
E         
E         - pathlib._PathParents
E         + builtins.tuple

tests/brain/test_pathlib.py:26: AssertionError
____________________ test_inference_parents_subscript_index ____________________

instance = <Tuple.tuple l.349 at 0xffffae6d1bd0>, elts = []
index = <Const.int l.5 at 0xffffae573380>
context = <astroid.context.InferenceContext object at 0xffffafc94100>

    def _container_getitem(instance, elts, index, context: InferenceContext | 
None = None):
        """Get a slice or an item, using the given *index*, for the given 
sequence."""
        try:
            if isinstance(index, Slice):
                index_slice = _infer_slice(index, context=context)
                new_cls = instance.__class__()
                new_cls.elts = elts[index_slice]
                new_cls.parent = instance.parent
                return new_cls
            if isinstance(index, Const):
>               return elts[index.value]
E               IndexError: list index out of range

astroid/nodes/node_classes.py:252: IndexError

The above exception was the direct cause of the following exception:

self = <Subscript l.5 at 0xffffae6d19f0>
context = <astroid.context.InferenceContext object at 0xffffafc94100>
kwargs = {}
helpers = <module 'astroid.helpers' from 
'/<<PKGBUILDDIR>>/.pybuild/cpython3_3.13_astroid/build/astroid/helpers.py'>
found_one = False, value = <Tuple.tuple l.349 at 0xffffae6d1bd0>
index = <Const.int l.5 at 0xffffae573380>
index_value = <Const.int l.5 at 0xffffae573380>

    def _infer_subscript(
        self, context: InferenceContext | None = None, **kwargs: Any
    ) -> Generator[InferenceResult, None, InferenceErrorInfo | None]:
        """Inference for subscripts.
    
        We're understanding if the index is a Const
        or a slice, passing the result of inference
        to the value's `getitem` method, which should
        handle each supported index type accordingly.
        """
        from astroid import helpers  # pylint: disable=import-outside-toplevel
    
        found_one = False
        for value in self.value.infer(context):
            if isinstance(value, util.UninferableBase):
                yield util.Uninferable
                return None
            for index in self.slice.infer(context):
                if isinstance(index, util.UninferableBase):
                    yield util.Uninferable
                    return None
    
                # Try to deduce the index value.
                index_value = self._SUBSCRIPT_SENTINEL
                if value.__class__ == Instance:
                    index_value = index
                elif index.__class__ == Instance:
                    instance_as_index = helpers.class_instance_as_index(index)
                    if instance_as_index:
                        index_value = instance_as_index
                else:
                    index_value = index
    
                if index_value is self._SUBSCRIPT_SENTINEL:
                    raise InferenceError(node=self, context=context)
    
                try:
>                   assigned = value.getitem(index_value, context)

astroid/nodes/node_classes.py:3743: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
astroid/nodes/node_classes.py:4062: in getitem
    return _container_getitem(self, self.elts, index, context=context)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

instance = <Tuple.tuple l.349 at 0xffffae6d1bd0>, elts = []
index = <Const.int l.5 at 0xffffae573380>
context = <astroid.context.InferenceContext object at 0xffffafc94100>

    def _container_getitem(instance, elts, index, context: InferenceContext | 
None = None):
        """Get a slice or an item, using the given *index*, for the given 
sequence."""
        try:
            if isinstance(index, Slice):
                index_slice = _infer_slice(index, context=context)
                new_cls = instance.__class__()
                new_cls.elts = elts[index_slice]
                new_cls.parent = instance.parent
                return new_cls
            if isinstance(index, Const):
                return elts[index.value]
        except ValueError as exc:
            raise AstroidValueError(
                message="Slice {index!r} cannot index container",
                node=instance,
                index=index,
                context=context,
            ) from exc
        except IndexError as exc:
>           raise AstroidIndexError(
                message="Index {index!s} out of range",
                node=instance,
                index=index,
                context=context,
            ) from exc
E           astroid.exceptions.AstroidIndexError: Index Const.int(value=2,
E                     kind=None) out of range

astroid/nodes/node_classes.py:261: AstroidIndexError

The above exception was the direct cause of the following exception:

    def test_inference_parents_subscript_index() -> None:
        """Test inference of ``pathlib.Path.parents``, accessed by index."""
        path = astroid.extract_node(
            """
        from pathlib import Path
    
        current_path = Path().resolve()
        current_path.parents[2]  #@
        """
        )
    
>       inferred = path.inferred()

tests/brain/test_pathlib.py:40: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
astroid/nodes/node_ng.py:586: in inferred
    return list(self.infer())
astroid/nodes/node_ng.py:170: in infer
    for i, result in enumerate(self._infer(context=context, **kwargs)):
astroid/decorators.py:90: in inner
    yield next(generator)
astroid/decorators.py:49: in wrapped
    for res in _func(node, context, **kwargs):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <Subscript l.5 at 0xffffae6d19f0>
context = <astroid.context.InferenceContext object at 0xffffafc94100>
kwargs = {}
helpers = <module 'astroid.helpers' from 
'/<<PKGBUILDDIR>>/.pybuild/cpython3_3.13_astroid/build/astroid/helpers.py'>
found_one = False, value = <Tuple.tuple l.349 at 0xffffae6d1bd0>
index = <Const.int l.5 at 0xffffae573380>
index_value = <Const.int l.5 at 0xffffae573380>

    def _infer_subscript(
        self, context: InferenceContext | None = None, **kwargs: Any
    ) -> Generator[InferenceResult, None, InferenceErrorInfo | None]:
        """Inference for subscripts.
    
        We're understanding if the index is a Const
        or a slice, passing the result of inference
        to the value's `getitem` method, which should
        handle each supported index type accordingly.
        """
        from astroid import helpers  # pylint: disable=import-outside-toplevel
    
        found_one = False
        for value in self.value.infer(context):
            if isinstance(value, util.UninferableBase):
                yield util.Uninferable
                return None
            for index in self.slice.infer(context):
                if isinstance(index, util.UninferableBase):
                    yield util.Uninferable
                    return None
    
                # Try to deduce the index value.
                index_value = self._SUBSCRIPT_SENTINEL
                if value.__class__ == Instance:
                    index_value = index
                elif index.__class__ == Instance:
                    instance_as_index = helpers.class_instance_as_index(index)
                    if instance_as_index:
                        index_value = instance_as_index
                else:
                    index_value = index
    
                if index_value is self._SUBSCRIPT_SENTINEL:
                    raise InferenceError(node=self, context=context)
    
                try:
                    assigned = value.getitem(index_value, context)
                except (
                    AstroidTypeError,
                    AstroidIndexError,
                    AstroidValueError,
                    AttributeInferenceError,
                    AttributeError,
                ) as exc:
>                   raise InferenceError(node=self, context=context) from exc
E                   astroid.exceptions.InferenceError: Inference failed for 
<Subscript l.5 at 0xffffae6d19f0>.

astroid/nodes/node_classes.py:3751: InferenceError
____________ InferenceTest.test_getitem_of_class_raised_type_error _____________

self = <tests.test_inference.InferenceTest 
testMethod=test_getitem_of_class_raised_type_error>

    def test_getitem_of_class_raised_type_error(self) -> None:
        # Test that we wrap an AttributeInferenceError
        # and reraise it as a TypeError in Class.getitem
        node = extract_node(
            """
        def test():
            yield
        test()
        """
        )
        inferred = next(node.infer())
>       with self.assertRaises(AstroidTypeError):
E       AssertionError: AstroidTypeError not raised

tests/test_inference.py:4467: AssertionError
___________ test_dataclasses_subscript_inference_recursion_error_39 ____________

    @pytest.mark.skipif(
        not PY39_PLUS,
        reason="Exact inference with dataclasses (replace function) in 
python3.9",
    )
    def test_dataclasses_subscript_inference_recursion_error_39():
        code = """
        from dataclasses import dataclass, replace
    
        @dataclass
        class ProxyConfig:
            auth: str = "/auth"
    
    
        a = ProxyConfig("")
        test_dict = {"proxy" : {"auth" : "", "bla" : "f"}}
    
        foo = test_dict['proxy']
        replace(a, **test_dict['proxy']) # This fails
        """
        node = extract_node(code)
        infer_val = util.safe_infer(node)
>       assert isinstance(infer_val, Instance)
E       assert False
E        +  where False = isinstance(Uninferable, Instance)

tests/test_inference.py:6790: AssertionError
=========================== short test summary info ============================
FAILED 
tests/brain/test_brain.py::TypingBrain::test_typing_annotated_subscriptable
FAILED tests/brain/test_pathlib.py::test_inference_parents - AssertionError: ...
FAILED tests/brain/test_pathlib.py::test_inference_parents_subscript_index - ...
FAILED 
tests/test_inference.py::InferenceTest::test_getitem_of_class_raised_type_error
FAILED 
tests/test_inference.py::test_dataclasses_subscript_inference_recursion_error_39
=========== 5 failed, 1606 passed, 62 skipped, 16 xfailed in 55.32s ============
E: pybuild pybuild:389: test: plugin pyproject failed with: exit code=1: cd 
/<<PKGBUILDDIR>>/.pybuild/cpython3_3.13_astroid/build; python3.13 -m pytest 
tests

If required, the full build log is available here (for the next 30 days):
https://debusine.debian.net/artifact/715688/

This bug has been filed at "normal" severity, as we haven't started the
transition to add 3.13 as a supported version, yet. This will be raised to RC
as soon as that happens, hopefully well before trixie.

Thanks,

Stefano

Reply via email to