Statistics
| Revision:

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