Skip to content

Commit

Permalink
Merge 9c9e249 into 50a7cd8
Browse files Browse the repository at this point in the history
  • Loading branch information
cdce8p committed Nov 14, 2022
2 parents 50a7cd8 + 9c9e249 commit 3f67de2
Show file tree
Hide file tree
Showing 12 changed files with 123 additions and 214 deletions.
4 changes: 1 addition & 3 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ on:
pull_request: ~

env:
CACHE_VERSION: 1
CACHE_VERSION: 2
KEY_PREFIX: venv
DEFAULT_PYTHON: "3.10"
PRE_COMMIT_CACHE: ~/.cache/pre-commit
Expand Down Expand Up @@ -49,7 +49,6 @@ jobs:
. venv/bin/activate
python -m pip install -U pip setuptools wheel
pip install -U -r requirements_test.txt -r requirements_test_brain.txt
pip install -e .
- name: Generate pre-commit restore key
id: generate-pre-commit-key
run: >-
Expand All @@ -70,7 +69,6 @@ jobs:
- name: Run pre-commit checks
run: |
. venv/bin/activate
pip install -e .
pre-commit run pylint --all-files
tests-linux:
Expand Down
8 changes: 8 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@
astroid's ChangeLog
===================

What's New in astroid 3.0.0?
=============================
Release date: TBA

* Add new ``nodes.Try`` to better match Python AST. Replaces the ``TryExcept``
and ``TryFinally`` nodes which have been removed.


What's New in astroid 2.13.0?
=============================
Release date: TBA
Expand Down
3 changes: 1 addition & 2 deletions astroid/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,7 @@
Slice,
Starred,
Subscript,
TryExcept,
TryFinally,
Try,
Tuple,
UnaryOp,
Unknown,
Expand Down
2 changes: 1 addition & 1 deletion astroid/inference.py
Original file line number Diff line number Diff line change
Expand Up @@ -1210,7 +1210,7 @@ def infer_functiondef(
isinstance(val, objects.Property) for val in parent_frame.locals[self.name]
)
# We also don't want to pass parent if the definition is within a Try node
if isinstance(self.parent, (nodes.TryExcept, nodes.TryFinally, nodes.If)):
if isinstance(self.parent, (nodes.Try, nodes.If)):
property_already_in_parent_locals = True

prop_func = objects.Property(
Expand Down
3 changes: 1 addition & 2 deletions astroid/node_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,7 @@
Slice,
Starred,
Subscript,
TryExcept,
TryFinally,
Try,
Tuple,
UnaryOp,
Unknown,
Expand Down
9 changes: 3 additions & 6 deletions astroid/nodes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,7 @@
Slice,
Starred,
Subscript,
TryExcept,
TryFinally,
Try,
Tuple,
UnaryOp,
Unknown,
Expand Down Expand Up @@ -194,8 +193,7 @@
Slice,
Starred,
Subscript,
TryExcept,
TryFinally,
Try,
Tuple,
UnaryOp,
Unknown,
Expand Down Expand Up @@ -288,8 +286,7 @@
"Starred",
"Statement",
"Subscript",
"TryExcept",
"TryFinally",
"Try",
"Tuple",
"UnaryOp",
"Unknown",
Expand Down
13 changes: 5 additions & 8 deletions astroid/nodes/as_string.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from astroid import nodes
from astroid.nodes import Const
from astroid.nodes.node_classes import (
Match,
Expand Down Expand Up @@ -477,21 +478,17 @@ def visit_subscript(self, node):
idxstr = idxstr[1:-1]
return f"{self._precedence_parens(node, node.value)}[{idxstr}]"

def visit_tryexcept(self, node):
"""return an astroid.TryExcept node as string"""
def visit_try(self, node: nodes.Try) -> str:
"""return an astroid.Try node as string"""
trys = [f"try:\n{self._stmt_list(node.body)}"]
for handler in node.handlers:
trys.append(handler.accept(self))
if node.orelse:
trys.append(f"else:\n{self._stmt_list(node.orelse)}")
if node.finalbody:
trys.append(f"finally:\n{self._stmt_list(node.finalbody)}")
return "\n".join(trys)

def visit_tryfinally(self, node):
"""return an astroid.TryFinally node as string"""
return "try:\n{}\nfinally:\n{}".format(
self._stmt_list(node.body), self._stmt_list(node.finalbody)
)

def visit_tuple(self, node):
"""return an astroid.Tuple node as string"""
if len(node.elts) == 1:
Expand Down
167 changes: 43 additions & 124 deletions astroid/nodes/node_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,15 +133,15 @@ def are_exclusive(stmt1, stmt2, exceptions: list[str] | None = None) -> bool:
previous = stmt2
for node in stmt2.node_ancestors():
if node in stmt1_parents:
# if the common parent is a If or TryExcept statement, look if
# if the common parent is a If or Try statement, look if
# nodes are in exclusive branches
if isinstance(node, If) and exceptions is None:
if (
node.locate_child(previous)[1]
is not node.locate_child(children[node])[1]
):
return True
elif isinstance(node, TryExcept):
elif isinstance(node, Try):
c2attr, c2node = node.locate_child(previous)
c1attr, c1node = node.locate_child(children[node])
if c1node is not c2node:
Expand Down Expand Up @@ -4003,31 +4003,33 @@ def get_children(self):
yield self.slice


class TryExcept(_base_nodes.MultiLineWithElseBlockNode, _base_nodes.Statement):
"""Class representing an :class:`ast.TryExcept` node.
class Try(_base_nodes.MultiLineWithElseBlockNode, _base_nodes.Statement):
"""Class representing a :class:`ast.Try` node.
>>> import astroid
>>> node = astroid.extract_node('''
try:
do_something()
except Exception as error:
print("Error!")
finally:
print("Cleanup!")
''')
>>> node
<TryExcept l.2 at 0x7f23b2e9d908>
<Try l.2 at 0x7f23b2e41d68>
"""

_astroid_fields = ("body", "handlers", "orelse")
_multi_line_block_fields = ("body", "handlers", "orelse")
_astroid_fields = ("body", "handlers", "orelse", "finalbody")
_multi_line_block_fields = ("body", "handlers", "orelse", "finalbody")

def __init__(
self,
*,
lineno: int | None = None,
col_offset: int | None = None,
parent: NodeNG | None = None,
*,
end_lineno: int | None = None,
end_col_offset: int | None = None,
parent: NodeNG | None = None,
) -> None:
"""
:param lineno: The line that this node appears on in the source code.
Expand All @@ -4051,6 +4053,9 @@ def __init__(
self.orelse: list[NodeNG] = []
"""The contents of the ``else`` block."""

self.finalbody: list[NodeNG] = []
"""The contents of the ``finally`` block."""

super().__init__(
lineno=lineno,
col_offset=col_offset,
Expand All @@ -4061,9 +4066,11 @@ def __init__(

def postinit(
self,
*,
body: list[NodeNG] | None = None,
handlers: list[ExceptHandler] | None = None,
orelse: list[NodeNG] | None = None,
finalbody: list[NodeNG] | None = None,
) -> None:
"""Do some setup after initialisation.
Expand All @@ -4072,137 +4079,49 @@ def postinit(
:param handlers: The exception handlers.
:param orelse: The contents of the ``else`` block.
:param finalbody: The contents of the ``finally`` block.
"""
if body is not None:
if body:
self.body = body
if handlers is not None:
if handlers:
self.handlers = handlers
if orelse is not None:
if orelse:
self.orelse = orelse
if finalbody:
self.finalbody = finalbody

def _infer_name(self, frame, name):
return name

def block_range(self, lineno):
"""Get a range from the given line number to where this node ends.
:param lineno: The line number to start the range at.
:type lineno: int
:returns: The range of line numbers that this node belongs to,
starting at the given line number.
:rtype: tuple(int, int)
"""
last = None
def block_range(self, lineno: int) -> tuple[int, int]:
"""Get a range from a given line number to where this node ends."""
if lineno == self.fromlineno:
return lineno, lineno
if self.body and self.body[0].fromlineno <= lineno <= self.body[-1].tolineno:
# Inside try body - return from lineno till end of try body
return lineno, self.body[-1].tolineno
for exhandler in self.handlers:
if exhandler.type and lineno == exhandler.type.fromlineno:
return lineno, lineno
if exhandler.body[0].fromlineno <= lineno <= exhandler.body[-1].tolineno:
return lineno, exhandler.body[-1].tolineno
if last is None:
last = exhandler.body[0].fromlineno - 1
return self._elsed_block_range(lineno, self.orelse, last)

def get_children(self):
yield from self.body

yield from self.handlers or ()
yield from self.orelse or ()


class TryFinally(_base_nodes.MultiLineWithElseBlockNode, _base_nodes.Statement):
"""Class representing an :class:`ast.TryFinally` node.
>>> import astroid
>>> node = astroid.extract_node('''
try:
do_something()
except Exception as error:
print("Error!")
finally:
print("Cleanup!")
''')
>>> node
<TryFinally l.2 at 0x7f23b2e41d68>
"""

_astroid_fields = ("body", "finalbody")
_multi_line_block_fields = ("body", "finalbody")

def __init__(
self,
lineno: int | None = None,
col_offset: int | None = None,
parent: NodeNG | None = None,
*,
end_lineno: int | None = None,
end_col_offset: int | None = None,
) -> None:
"""
:param lineno: The line that this node appears on in the source code.
:param col_offset: The column that this node appears on in the
source code.
:param parent: The parent node in the syntax tree.
:param end_lineno: The last line this node appears on in the source code.
:param end_col_offset: The end column this node appears on in the
source code. Note: This is after the last symbol.
"""
self.body: list[NodeNG | TryExcept] = []
"""The try-except that the finally is attached to."""

self.finalbody: list[NodeNG] = []
"""The contents of the ``finally`` block."""

super().__init__(
lineno=lineno,
col_offset=col_offset,
end_lineno=end_lineno,
end_col_offset=end_col_offset,
parent=parent,
)

def postinit(
self,
body: list[NodeNG | TryExcept] | None = None,
finalbody: list[NodeNG] | None = None,
) -> None:
"""Do some setup after initialisation.
:param body: The try-except that the finally is attached to.
:param finalbody: The contents of the ``finally`` block.
"""
if body is not None:
self.body = body
if finalbody is not None:
self.finalbody = finalbody

def block_range(self, lineno):
"""Get a range from the given line number to where this node ends.
:param lineno: The line number to start the range at.
:type lineno: int
:returns: The range of line numbers that this node belongs to,
starting at the given line number.
:rtype: tuple(int, int)
"""
child = self.body[0]
# py2.5 try: except: finally:
if (
isinstance(child, TryExcept)
and child.fromlineno == self.fromlineno
and child.tolineno >= lineno > self.fromlineno
):
return child.block_range(lineno)
return self._elsed_block_range(lineno, self.finalbody)
if self.orelse:
if self.orelse[0].fromlineno - 1 == lineno:
return lineno, lineno
if self.orelse[0].fromlineno <= lineno <= self.orelse[-1].tolineno:
return lineno, self.orelse[-1].tolineno
if self.finalbody:
if self.finalbody[0].fromlineno - 1 == lineno:
return lineno, lineno
if self.finalbody[0].fromlineno <= lineno <= self.finalbody[-1].tolineno:
return lineno, self.finalbody[-1].tolineno
return lineno, self.tolineno

def get_children(self):
yield from self.body
yield from self.handlers
yield from self.orelse
yield from self.finalbody


Expand Down
2 changes: 1 addition & 1 deletion astroid/nodes/node_ng.py
Original file line number Diff line number Diff line change
Expand Up @@ -587,7 +587,7 @@ def _get_yield_nodes_skip_lambdas(self):
yield from ()

def _infer_name(self, frame, name):
# overridden for ImportFrom, Import, Global, TryExcept and Arguments
# overridden for ImportFrom, Import, Global, Try and Arguments
pass

def _infer(
Expand Down
Loading

0 comments on commit 3f67de2

Please sign in to comment.