File: test_group_exceptions.py

package info (click to toggle)
astroid 4.0.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,132 kB
  • sloc: python: 38,560; makefile: 24
file content (151 lines) | stat: -rw-r--r-- 5,021 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/pylint-dev/astroid/blob/main/LICENSE
# Copyright (c) https://github.com/pylint-dev/astroid/blob/main/CONTRIBUTORS.txt
import textwrap

import pytest

from astroid import (
    Uninferable,
    bases,
    extract_node,
    nodes,
)
from astroid.const import PY311_PLUS
from astroid.context import InferenceContext


@pytest.mark.skipif(not PY311_PLUS, reason="Exception group introduced in Python 3.11")
def test_group_exceptions_exceptions() -> None:
    node = extract_node(
        textwrap.dedent(
            """
        try:
            raise ExceptionGroup('', [TypeError(), TypeError()])
        except ExceptionGroup as eg:
            eg.exceptions #@"""
        )
    )

    inferred = node.inferred()[0]
    assert isinstance(inferred, nodes.Tuple)


@pytest.mark.skipif(not PY311_PLUS, reason="Requires Python 3.11 or higher")
def test_group_exceptions() -> None:
    node = extract_node(
        textwrap.dedent(
            """
        try:
            raise ExceptionGroup("group", [ValueError(654)])
        except ExceptionGroup as eg:
            for err in eg.exceptions:
                if isinstance(err, ValueError):
                    print("Handling ValueError")
                elif isinstance(err, TypeError):
                    print("Handling TypeError")"""
        )
    )
    assert isinstance(node, nodes.Try)
    handler = node.handlers[0]
    assert node.block_range(lineno=1) == (1, 9)
    assert node.block_range(lineno=2) == (2, 2)
    assert node.block_range(lineno=5) == (5, 9)
    assert isinstance(handler, nodes.ExceptHandler)
    assert handler.type.name == "ExceptionGroup"
    children = list(handler.get_children())
    assert len(children) == 3
    exception_group, short_name, for_loop = children
    assert isinstance(exception_group, nodes.Name)
    assert exception_group.block_range(1) == (1, 4)
    assert isinstance(short_name, nodes.AssignName)
    assert isinstance(for_loop, nodes.For)


@pytest.mark.skipif(not PY311_PLUS, reason="Requires Python 3.11 or higher")
def test_star_exceptions() -> None:
    code = textwrap.dedent(
        """
    try:
        raise ExceptionGroup("group", [ValueError(654)])
    except* ValueError:
        print("Handling ValueError")
    except* TypeError:
        print("Handling TypeError")
    else:
        sys.exit(127)
    finally:
        sys.exit(0)"""
    )
    node = extract_node(code)
    assert isinstance(node, nodes.TryStar)
    assert node.as_string() == code.replace('"', "'").strip()
    assert isinstance(node.body[0], nodes.Raise)
    assert node.block_range(1) == (1, 11)
    assert node.block_range(2) == (2, 2)
    assert node.block_range(3) == (3, 3)
    assert node.block_range(4) == (4, 4)
    assert node.block_range(5) == (5, 5)
    assert node.block_range(6) == (6, 6)
    assert node.block_range(7) == (7, 7)
    assert node.block_range(8) == (8, 8)
    assert node.block_range(9) == (9, 9)
    assert node.block_range(10) == (10, 10)
    assert node.block_range(11) == (11, 11)
    assert node.handlers
    handler = node.handlers[0]
    assert isinstance(handler, nodes.ExceptHandler)
    assert handler.type.name == "ValueError"
    orelse = node.orelse[0]
    assert isinstance(orelse, nodes.Expr)
    assert orelse.value.args[0].value == 127
    final = node.finalbody[0]
    assert isinstance(final, nodes.Expr)
    assert final.value.args[0].value == 0


@pytest.mark.skipif(not PY311_PLUS, reason="Requires Python 3.11 or higher")
def test_star_exceptions_infer_name() -> None:
    trystar = extract_node(
        """
try:
    1/0
except* ValueError:
    pass"""
    )
    name = "arbitraryName"
    context = InferenceContext()
    context.lookupname = name
    stmts = bases._infer_stmts([trystar], context)
    assert list(stmts) == [Uninferable]
    assert context.lookupname == name


@pytest.mark.skipif(not PY311_PLUS, reason="Requires Python 3.11 or higher")
def test_star_exceptions_infer_exceptions() -> None:
    code = textwrap.dedent(
        """
    try:
        raise ExceptionGroup("group", [ValueError(654), TypeError(10)])
    except* ValueError as ve:
        print(e.exceptions)
    except* TypeError as te:
        print(e.exceptions)
    else:
        sys.exit(127)
    finally:
        sys.exit(0)"""
    )
    node = extract_node(code)
    assert isinstance(node, nodes.TryStar)
    inferred_ve = next(node.handlers[0].statement().name.infer())
    assert inferred_ve.name == "ExceptionGroup"
    assert isinstance(inferred_ve.getattr("exceptions")[0], nodes.List)
    assert (
        inferred_ve.getattr("exceptions")[0].elts[0].pytype() == "builtins.ValueError"
    )

    inferred_te = next(node.handlers[1].statement().name.infer())
    assert inferred_te.name == "ExceptionGroup"
    assert isinstance(inferred_te.getattr("exceptions")[0], nodes.List)
    assert inferred_te.getattr("exceptions")[0].elts[0].pytype() == "builtins.TypeError"