gvsig-scripting / org.gvsig.scripting / trunk / org.gvsig.scripting / org.gvsig.scripting.app / org.gvsig.scripting.app.mainplugin / src / main / resources-plugin / scripting / lib / astroid / astpeephole.py @ 745
History | View | Annotate | Download (2.88 KB)
1 |
# copyright 2003-2015 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
|
---|---|
2 |
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
|
3 |
#
|
4 |
# This file is part of astroid.
|
5 |
#
|
6 |
# astroid is free software: you can redistribute it and/or modify it
|
7 |
# under the terms of the GNU Lesser General Public License as published by the
|
8 |
# Free Software Foundation, either version 2.1 of the License, or (at your
|
9 |
# option) any later version.
|
10 |
#
|
11 |
# astroid is distributed in the hope that it will be useful, but
|
12 |
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
13 |
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
14 |
# for more details.
|
15 |
#
|
16 |
# You should have received a copy of the GNU Lesser General Public License along
|
17 |
# with astroid. If not, see <http://www.gnu.org/licenses/>.
|
18 |
"""Small AST optimizations."""
|
19 |
|
20 |
import _ast |
21 |
|
22 |
from astroid import nodes |
23 |
|
24 |
|
25 |
__all__ = ('ASTPeepholeOptimizer', )
|
26 |
|
27 |
|
28 |
try:
|
29 |
_TYPES = (_ast.Str, _ast.Bytes) |
30 |
except AttributeError: |
31 |
_TYPES = (_ast.Str, ) |
32 |
|
33 |
|
34 |
class ASTPeepholeOptimizer(object): |
35 |
"""Class for applying small optimizations to generate new AST."""
|
36 |
|
37 |
def optimize_binop(self, node): |
38 |
"""Optimize BinOps with string Const nodes on the lhs.
|
39 |
|
40 |
This fixes an infinite recursion crash, where multiple
|
41 |
strings are joined using the addition operator. With a
|
42 |
sufficient number of such strings, astroid will fail
|
43 |
with a maximum recursion limit exceeded. The
|
44 |
function will return a Const node with all the strings
|
45 |
already joined.
|
46 |
Return ``None`` if no AST node can be obtained
|
47 |
through optimization.
|
48 |
"""
|
49 |
ast_nodes = [] |
50 |
current = node |
51 |
while isinstance(current, _ast.BinOp): |
52 |
# lhs must be a BinOp with the addition operand.
|
53 |
if not isinstance(current.left, _ast.BinOp): |
54 |
return
|
55 |
if (not isinstance(current.left.op, _ast.Add) |
56 |
or not isinstance(current.op, _ast.Add)): |
57 |
return
|
58 |
|
59 |
# rhs must a str / bytes.
|
60 |
if not isinstance(current.right, _TYPES): |
61 |
return
|
62 |
|
63 |
ast_nodes.append(current.right.s) |
64 |
current = current.left |
65 |
|
66 |
if (isinstance(current, _ast.BinOp) |
67 |
and isinstance(current.left, _TYPES) |
68 |
and isinstance(current.right, _TYPES)): |
69 |
# Stop early if we are at the last BinOp in
|
70 |
# the operation
|
71 |
ast_nodes.append(current.right.s) |
72 |
ast_nodes.append(current.left.s) |
73 |
break
|
74 |
|
75 |
if not ast_nodes: |
76 |
return
|
77 |
|
78 |
# If we have inconsistent types, bail out.
|
79 |
known = type(ast_nodes[0]) |
80 |
if any(type(element) is not known |
81 |
for element in ast_nodes[1:]): |
82 |
return
|
83 |
|
84 |
value = known().join(reversed(ast_nodes))
|
85 |
newnode = nodes.Const(value) |
86 |
return newnode
|