Skip to content

Commit b02fae5

Browse files
committed
Other approach
1 parent 7ba4547 commit b02fae5

File tree

5 files changed

+63
-185
lines changed

5 files changed

+63
-185
lines changed

ChangeLog

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ Release date: TBA
88

99
* ``astroid`` now requires Python 3.7.2 to run.
1010

11-
* Add ``orelse_lineno`` and ``orelse_col_offset`` attributes to ``nodes.If``,
12-
``nodes.For``, ``nodes.While``, and ``nodes.TryExcept``.
11+
* Made ``block_range`` of ``nodes.If``, ``nodes.For``, ``nodes.While``,
12+
and ``nodes.TryExcept`` respect ``else`` and ``finally``.
1313

1414
* Fix ``re`` brain on Python ``3.11``. The flags now come from ``re._compile``.
1515

astroid/mixins.py

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@
44

55
"""This module contains some mixins for the different nodes.
66
"""
7+
8+
from __future__ import annotations
9+
710
import itertools
811
import sys
9-
from typing import TYPE_CHECKING, Optional
12+
from typing import TYPE_CHECKING
1013

1114
from astroid import decorators
1215
from astroid.exceptions import AttributeInferenceError
@@ -27,23 +30,32 @@ class BlockRangeMixIn:
2730
def blockstart_tolineno(self):
2831
return self.lineno
2932

30-
def _elsed_block_range(self, lineno, orelse, last=None):
33+
def _elsed_block_range(
34+
self, lineno: int, orelse: list[nodes.NodeNG], last: int | None = None
35+
) -> tuple[int, int]:
3136
"""handle block line numbers range for try/finally, for, if and while
3237
statements
3338
"""
34-
if lineno == self.fromlineno:
39+
# If at the end of the node, return same line
40+
if lineno == self.tolineno:
3541
return lineno, lineno
3642
if orelse:
37-
if lineno >= orelse[0].fromlineno:
43+
# If the lineno is beyond the body of the node we check the orelse
44+
if lineno >= self.body[-1].tolineno + 1:
45+
# If the orelse has a scope of its own we determine the block range there
46+
if isinstance(orelse[0], BlockRangeMixIn):
47+
return orelse[0]._elsed_block_range(lineno, orelse[0].orelse)
48+
# Return last line of orelse
3849
return lineno, orelse[-1].tolineno
39-
return lineno, orelse[0].fromlineno - 1
50+
# If the lineno is within the body we take the last line of the body
51+
return lineno, self.body[-1].tolineno
4052
return lineno, last or self.tolineno
4153

4254

4355
class FilterStmtsMixin:
4456
"""Mixin for statement filtering and assignment type"""
4557

46-
def _get_filtered_stmts(self, _, node, _stmts, mystmt: Optional["nodes.Statement"]):
58+
def _get_filtered_stmts(self, _, node, _stmts, mystmt: nodes.Statement | None):
4759
"""method used in _filter_stmts to get statements and trigger break"""
4860
if self.statement(future=True) is mystmt:
4961
# original node's statement is the assignment, only keep
@@ -60,7 +72,7 @@ def assign_type(self):
6072
return self
6173

6274
def _get_filtered_stmts(
63-
self, lookup_node, node, _stmts, mystmt: Optional["nodes.Statement"]
75+
self, lookup_node, node, _stmts, mystmt: nodes.Statement | None
6476
):
6577
"""method used in filter_stmts"""
6678
if self is mystmt:

astroid/nodes/node_classes.py

Lines changed: 0 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -2661,12 +2661,6 @@ def __init__(
26612661
self.orelse: typing.List[NodeNG] = []
26622662
"""The contents of the ``else`` block of the loop."""
26632663

2664-
self.orelse_lineno: Optional[int] = None
2665-
"""The line number of the ``else`` keyword."""
2666-
2667-
self.orelse_col_offset: Optional[int] = None
2668-
"""The column offset of the ``else`` keyword."""
2669-
26702664
self.type_annotation: Optional[NodeNG] = None # can be None
26712665
"""If present, this will contain the type annotation passed by a type comment"""
26722666

@@ -2686,9 +2680,6 @@ def postinit(
26862680
body: Optional[typing.List[NodeNG]] = None,
26872681
orelse: Optional[typing.List[NodeNG]] = None,
26882682
type_annotation: Optional[NodeNG] = None,
2689-
*,
2690-
orelse_lineno: Optional[int] = None,
2691-
orelse_col_offset: Optional[int] = None,
26922683
) -> None:
26932684
"""Do some setup after initialisation.
26942685
@@ -2699,19 +2690,13 @@ def postinit(
26992690
:param body: The contents of the body of the loop.
27002691
27012692
:param orelse: The contents of the ``else`` block of the loop.
2702-
2703-
:param orelse_lineno: The line number of the ``else`` keyword.
2704-
2705-
:param orelse_lineno: The column offset of the ``else`` keyword.
27062693
"""
27072694
self.target = target
27082695
self.iter = iter
27092696
if body is not None:
27102697
self.body = body
27112698
if orelse is not None:
27122699
self.orelse = orelse
2713-
self.orelse_lineno = orelse_lineno
2714-
self.orelse_col_offset = orelse_col_offset
27152700
self.type_annotation = type_annotation
27162701

27172702
assigned_stmts: ClassVar[AssignedStmtsCall["For"]]
@@ -3048,12 +3033,6 @@ def __init__(
30483033
self.is_orelse: bool = False
30493034
"""Whether the if-statement is the orelse-block of another if statement."""
30503035

3051-
self.orelse_lineno: Optional[int] = None
3052-
"""The line number of the ``else`` or ``elif`` keyword."""
3053-
3054-
self.orelse_col_offset: Optional[int] = None
3055-
"""The column offset of the ``else`` or ``elif`` keyword."""
3056-
30573036
super().__init__(
30583037
lineno=lineno,
30593038
col_offset=col_offset,
@@ -3067,9 +3046,6 @@ def postinit(
30673046
test: Optional[NodeNG] = None,
30683047
body: Optional[typing.List[NodeNG]] = None,
30693048
orelse: Optional[typing.List[NodeNG]] = None,
3070-
*,
3071-
orelse_lineno: Optional[int] = None,
3072-
orelse_col_offset: Optional[int] = None,
30733049
) -> None:
30743050
"""Do some setup after initialisation.
30753051
@@ -3078,10 +3054,6 @@ def postinit(
30783054
:param body: The contents of the block.
30793055
30803056
:param orelse: The contents of the ``else`` block.
3081-
3082-
:param orelse_lineno: The line number of the ``else`` or ``elif`` keyword.
3083-
3084-
:param orelse_lineno: The column offset of the ``else`` or ``elif`` keyword.
30853057
"""
30863058
self.test = test
30873059
if body is not None:
@@ -3090,8 +3062,6 @@ def postinit(
30903062
self.orelse = orelse
30913063
if isinstance(self.parent, If) and self in self.parent.orelse:
30923064
self.is_orelse = True
3093-
self.orelse_lineno = orelse_lineno
3094-
self.orelse_col_offset = orelse_col_offset
30953065

30963066
@cached_property
30973067
def blockstart_tolineno(self):
@@ -3994,12 +3964,6 @@ def __init__(
39943964
self.orelse: typing.List[NodeNG] = []
39953965
"""The contents of the ``else`` block."""
39963966

3997-
self.orelse_lineno: Optional[int] = None
3998-
"""The line number of the ``else`` keyword."""
3999-
4000-
self.orelse_col_offset: Optional[int] = None
4001-
"""The column offset of the ``else`` keyword."""
4002-
40033967
super().__init__(
40043968
lineno=lineno,
40053969
col_offset=col_offset,
@@ -4013,9 +3977,6 @@ def postinit(
40133977
body: Optional[typing.List[NodeNG]] = None,
40143978
handlers: Optional[typing.List[ExceptHandler]] = None,
40153979
orelse: Optional[typing.List[NodeNG]] = None,
4016-
*,
4017-
orelse_lineno: Optional[int] = None,
4018-
orelse_col_offset: Optional[int] = None,
40193980
) -> None:
40203981
"""Do some setup after initialisation.
40213982
@@ -4024,19 +3985,13 @@ def postinit(
40243985
:param handlers: The exception handlers.
40253986
40263987
:param orelse: The contents of the ``else`` block.
4027-
4028-
:param orelse_lineno: The line number of the ``else`` keyword.
4029-
4030-
:param orelse_lineno: The column offset of the ``else`` keyword.
40313988
"""
40323989
if body is not None:
40333990
self.body = body
40343991
if handlers is not None:
40353992
self.handlers = handlers
40363993
if orelse is not None:
40373994
self.orelse = orelse
4038-
self.orelse_lineno = orelse_lineno
4039-
self.orelse_col_offset = orelse_col_offset
40403995

40413996
def _infer_name(self, frame, name):
40423997
return name
@@ -4371,12 +4326,6 @@ def __init__(
43714326
self.orelse: typing.List[NodeNG] = []
43724327
"""The contents of the ``else`` block."""
43734328

4374-
self.orelse_lineno: Optional[int] = None
4375-
"""The line number of the ``else`` keyword."""
4376-
4377-
self.orelse_col_offset: Optional[int] = None
4378-
"""The column offset of the ``else`` keyword."""
4379-
43804329
super().__init__(
43814330
lineno=lineno,
43824331
col_offset=col_offset,
@@ -4390,9 +4339,6 @@ def postinit(
43904339
test: Optional[NodeNG] = None,
43914340
body: Optional[typing.List[NodeNG]] = None,
43924341
orelse: Optional[typing.List[NodeNG]] = None,
4393-
*,
4394-
orelse_lineno: Optional[int] = None,
4395-
orelse_col_offset: Optional[int] = None,
43964342
) -> None:
43974343
"""Do some setup after initialisation.
43984344
@@ -4401,18 +4347,12 @@ def postinit(
44014347
:param body: The contents of the loop.
44024348
44034349
:param orelse: The contents of the ``else`` block.
4404-
4405-
:param orelse_lineno: The line number of the ``else`` keyword.
4406-
4407-
:param orelse_lineno: The column offset of the ``else`` keyword.
44084350
"""
44094351
self.test = test
44104352
if body is not None:
44114353
self.body = body
44124354
if orelse is not None:
44134355
self.orelse = orelse
4414-
self.orelse_lineno = orelse_lineno
4415-
self.orelse_col_offset = orelse_col_offset
44164356

44174357
@cached_property
44184358
def blockstart_tolineno(self):

astroid/rebuilder.py

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -248,26 +248,6 @@ def _reset_end_lineno(self, newnode: nodes.NodeNG) -> None:
248248
for child_node in newnode.get_children():
249249
self._reset_end_lineno(child_node)
250250

251-
def _find_orelse_keyword(
252-
self, node: Union["ast.If", "ast.Try", "ast.For", "ast.AsyncFor", "ast.While"]
253-
) -> Tuple[Optional[int], Optional[int]]:
254-
"""Get the line number and column offset of the `else` or `elif` keyword."""
255-
if not self._data or not node.orelse:
256-
return None, None
257-
258-
start = node.orelse[0].lineno
259-
260-
# pylint: disable-next=unsubscriptable-object
261-
for index, line in enumerate(self._data[start - 1 :: -1]):
262-
if line.lstrip().startswith("else"):
263-
# if start - index == 37:
264-
# breakpoint()
265-
return start - index, line.index("else")
266-
if line.lstrip().startswith("elif"):
267-
return start - index, line.index("elif")
268-
269-
return None, None
270-
271251
def visit_module(
272252
self, node: "ast.Module", modname: str, modpath: str, package: bool
273253
) -> nodes.Module:
@@ -1195,8 +1175,6 @@ def _visit_for(
11951175
# pylint: disable-next=unsubscriptable-object
11961176
col_offset = self._data[node.lineno - 1].index("async")
11971177

1198-
orelse_lineno, orelse_col_offset = self._find_orelse_keyword(node)
1199-
12001178
newnode = cls(
12011179
lineno=node.lineno,
12021180
col_offset=col_offset,
@@ -1212,8 +1190,6 @@ def _visit_for(
12121190
body=[self.visit(child, newnode) for child in node.body],
12131191
orelse=[self.visit(child, newnode) for child in node.orelse],
12141192
type_annotation=type_annotation,
1215-
orelse_lineno=orelse_lineno,
1216-
orelse_col_offset=orelse_col_offset,
12171193
)
12181194
return newnode
12191195

@@ -1406,14 +1382,10 @@ def visit_if(self, node: "ast.If", parent: NodeNG) -> nodes.If:
14061382
parent=parent,
14071383
)
14081384

1409-
orelse_lineno, orelse_col_offset = self._find_orelse_keyword(node)
1410-
14111385
newnode.postinit(
14121386
self.visit(node.test, newnode),
14131387
[self.visit(child, newnode) for child in node.body],
14141388
[self.visit(child, newnode) for child in node.orelse],
1415-
orelse_lineno=orelse_lineno,
1416-
orelse_col_offset=orelse_col_offset,
14171389
)
14181390
return newnode
14191391

@@ -1827,14 +1799,10 @@ def visit_tryexcept(self, node: "ast.Try", parent: NodeNG) -> nodes.TryExcept:
18271799
else:
18281800
newnode = nodes.TryExcept(node.lineno, node.col_offset, parent)
18291801

1830-
orelse_lineno, orelse_col_offset = self._find_orelse_keyword(node)
1831-
18321802
newnode.postinit(
18331803
[self.visit(child, newnode) for child in node.body],
18341804
[self.visit(child, newnode) for child in node.handlers],
18351805
[self.visit(child, newnode) for child in node.orelse],
1836-
orelse_lineno=orelse_lineno,
1837-
orelse_col_offset=orelse_col_offset,
18381806
)
18391807
return newnode
18401808

@@ -1903,14 +1871,10 @@ def visit_while(self, node: "ast.While", parent: NodeNG) -> nodes.While:
19031871
parent=parent,
19041872
)
19051873

1906-
orelse_lineno, orelse_col_offset = self._find_orelse_keyword(node)
1907-
19081874
newnode.postinit(
19091875
self.visit(node.test, newnode),
19101876
[self.visit(child, newnode) for child in node.body],
19111877
[self.visit(child, newnode) for child in node.orelse],
1912-
orelse_lineno=orelse_lineno,
1913-
orelse_col_offset=orelse_col_offset,
19141878
)
19151879
return newnode
19161880

0 commit comments

Comments
 (0)