~inkscape.dev/inkscape-devlibs64/trunk

« back to all changes in this revision

Viewing changes to python/Lib/symtable.py

  • Committer: Eduard Braun
  • Date: 2016-10-22 16:51:19 UTC
  • Revision ID: eduard.braun2@gmx.de-20161022165119-9eosgy6lp8j1kzli
Update Python to version 2.7.12

Included modules:
  coverage 4.2
  lxml 3.6.4
  numpy 1.11.2
  scour 0.35
  six 1.10.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
"""Interface to the compiler's internal symbol tables"""
2
 
 
3
 
import _symtable
4
 
from _symtable import (USE, DEF_GLOBAL, DEF_LOCAL, DEF_PARAM,
5
 
     DEF_IMPORT, DEF_BOUND, OPT_IMPORT_STAR, OPT_EXEC, OPT_BARE_EXEC,
6
 
     SCOPE_OFF, SCOPE_MASK, FREE, GLOBAL_IMPLICIT, GLOBAL_EXPLICIT, CELL, LOCAL)
7
 
 
8
 
import weakref
9
 
 
10
 
__all__ = ["symtable", "SymbolTable", "Class", "Function", "Symbol"]
11
 
 
12
 
def symtable(code, filename, compile_type):
13
 
    top = _symtable.symtable(code, filename, compile_type)
14
 
    return _newSymbolTable(top, filename)
15
 
 
16
 
class SymbolTableFactory:
17
 
    def __init__(self):
18
 
        self.__memo = weakref.WeakValueDictionary()
19
 
 
20
 
    def new(self, table, filename):
21
 
        if table.type == _symtable.TYPE_FUNCTION:
22
 
            return Function(table, filename)
23
 
        if table.type == _symtable.TYPE_CLASS:
24
 
            return Class(table, filename)
25
 
        return SymbolTable(table, filename)
26
 
 
27
 
    def __call__(self, table, filename):
28
 
        key = table, filename
29
 
        obj = self.__memo.get(key, None)
30
 
        if obj is None:
31
 
            obj = self.__memo[key] = self.new(table, filename)
32
 
        return obj
33
 
 
34
 
_newSymbolTable = SymbolTableFactory()
35
 
 
36
 
 
37
 
class SymbolTable(object):
38
 
 
39
 
    def __init__(self, raw_table, filename):
40
 
        self._table = raw_table
41
 
        self._filename = filename
42
 
        self._symbols = {}
43
 
 
44
 
    def __repr__(self):
45
 
        if self.__class__ == SymbolTable:
46
 
            kind = ""
47
 
        else:
48
 
            kind = "%s " % self.__class__.__name__
49
 
 
50
 
        if self._table.name == "global":
51
 
            return "<{0}SymbolTable for module {1}>".format(kind, self._filename)
52
 
        else:
53
 
            return "<{0}SymbolTable for {1} in {2}>".format(kind,
54
 
                                                            self._table.name,
55
 
                                                            self._filename)
56
 
 
57
 
    def get_type(self):
58
 
        if self._table.type == _symtable.TYPE_MODULE:
59
 
            return "module"
60
 
        if self._table.type == _symtable.TYPE_FUNCTION:
61
 
            return "function"
62
 
        if self._table.type == _symtable.TYPE_CLASS:
63
 
            return "class"
64
 
        assert self._table.type in (1, 2, 3), \
65
 
               "unexpected type: {0}".format(self._table.type)
66
 
 
67
 
    def get_id(self):
68
 
        return self._table.id
69
 
 
70
 
    def get_name(self):
71
 
        return self._table.name
72
 
 
73
 
    def get_lineno(self):
74
 
        return self._table.lineno
75
 
 
76
 
    def is_optimized(self):
77
 
        return bool(self._table.type == _symtable.TYPE_FUNCTION
78
 
                    and not self._table.optimized)
79
 
 
80
 
    def is_nested(self):
81
 
        return bool(self._table.nested)
82
 
 
83
 
    def has_children(self):
84
 
        return bool(self._table.children)
85
 
 
86
 
    def has_exec(self):
87
 
        """Return true if the scope uses exec"""
88
 
        return bool(self._table.optimized & (OPT_EXEC | OPT_BARE_EXEC))
89
 
 
90
 
    def has_import_star(self):
91
 
        """Return true if the scope uses import *"""
92
 
        return bool(self._table.optimized & OPT_IMPORT_STAR)
93
 
 
94
 
    def get_identifiers(self):
95
 
        return self._table.symbols.keys()
96
 
 
97
 
    def lookup(self, name):
98
 
        sym = self._symbols.get(name)
99
 
        if sym is None:
100
 
            flags = self._table.symbols[name]
101
 
            namespaces = self.__check_children(name)
102
 
            sym = self._symbols[name] = Symbol(name, flags, namespaces)
103
 
        return sym
104
 
 
105
 
    def get_symbols(self):
106
 
        return [self.lookup(ident) for ident in self.get_identifiers()]
107
 
 
108
 
    def __check_children(self, name):
109
 
        return [_newSymbolTable(st, self._filename)
110
 
                for st in self._table.children
111
 
                if st.name == name]
112
 
 
113
 
    def get_children(self):
114
 
        return [_newSymbolTable(st, self._filename)
115
 
                for st in self._table.children]
116
 
 
117
 
 
118
 
class Function(SymbolTable):
119
 
 
120
 
    # Default values for instance variables
121
 
    __params = None
122
 
    __locals = None
123
 
    __frees = None
124
 
    __globals = None
125
 
 
126
 
    def __idents_matching(self, test_func):
127
 
        return tuple([ident for ident in self.get_identifiers()
128
 
                      if test_func(self._table.symbols[ident])])
129
 
 
130
 
    def get_parameters(self):
131
 
        if self.__params is None:
132
 
            self.__params = self.__idents_matching(lambda x:x & DEF_PARAM)
133
 
        return self.__params
134
 
 
135
 
    def get_locals(self):
136
 
        if self.__locals is None:
137
 
            locs = (LOCAL, CELL)
138
 
            test = lambda x: ((x >> SCOPE_OFF) & SCOPE_MASK) in locs
139
 
            self.__locals = self.__idents_matching(test)
140
 
        return self.__locals
141
 
 
142
 
    def get_globals(self):
143
 
        if self.__globals is None:
144
 
            glob = (GLOBAL_IMPLICIT, GLOBAL_EXPLICIT)
145
 
            test = lambda x:((x >> SCOPE_OFF) & SCOPE_MASK) in glob
146
 
            self.__globals = self.__idents_matching(test)
147
 
        return self.__globals
148
 
 
149
 
    def get_frees(self):
150
 
        if self.__frees is None:
151
 
            is_free = lambda x:((x >> SCOPE_OFF) & SCOPE_MASK) == FREE
152
 
            self.__frees = self.__idents_matching(is_free)
153
 
        return self.__frees
154
 
 
155
 
 
156
 
class Class(SymbolTable):
157
 
 
158
 
    __methods = None
159
 
 
160
 
    def get_methods(self):
161
 
        if self.__methods is None:
162
 
            d = {}
163
 
            for st in self._table.children:
164
 
                d[st.name] = 1
165
 
            self.__methods = tuple(d)
166
 
        return self.__methods
167
 
 
168
 
 
169
 
class Symbol(object):
170
 
 
171
 
    def __init__(self, name, flags, namespaces=None):
172
 
        self.__name = name
173
 
        self.__flags = flags
174
 
        self.__scope = (flags >> SCOPE_OFF) & SCOPE_MASK # like PyST_GetScope()
175
 
        self.__namespaces = namespaces or ()
176
 
 
177
 
    def __repr__(self):
178
 
        return "<symbol {0!r}>".format(self.__name)
179
 
 
180
 
    def get_name(self):
181
 
        return self.__name
182
 
 
183
 
    def is_referenced(self):
184
 
        return bool(self.__flags & _symtable.USE)
185
 
 
186
 
    def is_parameter(self):
187
 
        return bool(self.__flags & DEF_PARAM)
188
 
 
189
 
    def is_global(self):
190
 
        return bool(self.__scope in (GLOBAL_IMPLICIT, GLOBAL_EXPLICIT))
191
 
 
192
 
    def is_declared_global(self):
193
 
        return bool(self.__scope == GLOBAL_EXPLICIT)
194
 
 
195
 
    def is_local(self):
196
 
        return bool(self.__flags & DEF_BOUND)
197
 
 
198
 
    def is_free(self):
199
 
        return bool(self.__scope == FREE)
200
 
 
201
 
    def is_imported(self):
202
 
        return bool(self.__flags & DEF_IMPORT)
203
 
 
204
 
    def is_assigned(self):
205
 
        return bool(self.__flags & DEF_LOCAL)
206
 
 
207
 
    def is_namespace(self):
208
 
        """Returns true if name binding introduces new namespace.
209
 
 
210
 
        If the name is used as the target of a function or class
211
 
        statement, this will be true.
212
 
 
213
 
        Note that a single name can be bound to multiple objects.  If
214
 
        is_namespace() is true, the name may also be bound to other
215
 
        objects, like an int or list, that does not introduce a new
216
 
        namespace.
217
 
        """
218
 
        return bool(self.__namespaces)
219
 
 
220
 
    def get_namespaces(self):
221
 
        """Return a list of namespaces bound to this name"""
222
 
        return self.__namespaces
223
 
 
224
 
    def get_namespace(self):
225
 
        """Returns the single namespace bound to this name.
226
 
 
227
 
        Raises ValueError if the name is bound to multiple namespaces.
228
 
        """
229
 
        if len(self.__namespaces) != 1:
230
 
            raise ValueError, "name is bound to multiple namespaces"
231
 
        return self.__namespaces[0]
232
 
 
233
 
if __name__ == "__main__":
234
 
    import os, sys
235
 
    src = open(sys.argv[0]).read()
236
 
    mod = symtable(src, os.path.split(sys.argv[0])[1], "exec")
237
 
    for ident in mod.get_identifiers():
238
 
        info = mod.lookup(ident)
239
 
        print info, info.is_local(), info.is_namespace()
 
1
"""Interface to the compiler's internal symbol tables"""
 
2
 
 
3
import _symtable
 
4
from _symtable import (USE, DEF_GLOBAL, DEF_LOCAL, DEF_PARAM,
 
5
     DEF_IMPORT, DEF_BOUND, OPT_IMPORT_STAR, OPT_EXEC, OPT_BARE_EXEC,
 
6
     SCOPE_OFF, SCOPE_MASK, FREE, GLOBAL_IMPLICIT, GLOBAL_EXPLICIT, CELL, LOCAL)
 
7
 
 
8
import weakref
 
9
 
 
10
__all__ = ["symtable", "SymbolTable", "Class", "Function", "Symbol"]
 
11
 
 
12
def symtable(code, filename, compile_type):
 
13
    top = _symtable.symtable(code, filename, compile_type)
 
14
    return _newSymbolTable(top, filename)
 
15
 
 
16
class SymbolTableFactory:
 
17
    def __init__(self):
 
18
        self.__memo = weakref.WeakValueDictionary()
 
19
 
 
20
    def new(self, table, filename):
 
21
        if table.type == _symtable.TYPE_FUNCTION:
 
22
            return Function(table, filename)
 
23
        if table.type == _symtable.TYPE_CLASS:
 
24
            return Class(table, filename)
 
25
        return SymbolTable(table, filename)
 
26
 
 
27
    def __call__(self, table, filename):
 
28
        key = table, filename
 
29
        obj = self.__memo.get(key, None)
 
30
        if obj is None:
 
31
            obj = self.__memo[key] = self.new(table, filename)
 
32
        return obj
 
33
 
 
34
_newSymbolTable = SymbolTableFactory()
 
35
 
 
36
 
 
37
class SymbolTable(object):
 
38
 
 
39
    def __init__(self, raw_table, filename):
 
40
        self._table = raw_table
 
41
        self._filename = filename
 
42
        self._symbols = {}
 
43
 
 
44
    def __repr__(self):
 
45
        if self.__class__ == SymbolTable:
 
46
            kind = ""
 
47
        else:
 
48
            kind = "%s " % self.__class__.__name__
 
49
 
 
50
        if self._table.name == "global":
 
51
            return "<{0}SymbolTable for module {1}>".format(kind, self._filename)
 
52
        else:
 
53
            return "<{0}SymbolTable for {1} in {2}>".format(kind,
 
54
                                                            self._table.name,
 
55
                                                            self._filename)
 
56
 
 
57
    def get_type(self):
 
58
        if self._table.type == _symtable.TYPE_MODULE:
 
59
            return "module"
 
60
        if self._table.type == _symtable.TYPE_FUNCTION:
 
61
            return "function"
 
62
        if self._table.type == _symtable.TYPE_CLASS:
 
63
            return "class"
 
64
        assert self._table.type in (1, 2, 3), \
 
65
               "unexpected type: {0}".format(self._table.type)
 
66
 
 
67
    def get_id(self):
 
68
        return self._table.id
 
69
 
 
70
    def get_name(self):
 
71
        return self._table.name
 
72
 
 
73
    def get_lineno(self):
 
74
        return self._table.lineno
 
75
 
 
76
    def is_optimized(self):
 
77
        return bool(self._table.type == _symtable.TYPE_FUNCTION
 
78
                    and not self._table.optimized)
 
79
 
 
80
    def is_nested(self):
 
81
        return bool(self._table.nested)
 
82
 
 
83
    def has_children(self):
 
84
        return bool(self._table.children)
 
85
 
 
86
    def has_exec(self):
 
87
        """Return true if the scope uses exec"""
 
88
        return bool(self._table.optimized & (OPT_EXEC | OPT_BARE_EXEC))
 
89
 
 
90
    def has_import_star(self):
 
91
        """Return true if the scope uses import *"""
 
92
        return bool(self._table.optimized & OPT_IMPORT_STAR)
 
93
 
 
94
    def get_identifiers(self):
 
95
        return self._table.symbols.keys()
 
96
 
 
97
    def lookup(self, name):
 
98
        sym = self._symbols.get(name)
 
99
        if sym is None:
 
100
            flags = self._table.symbols[name]
 
101
            namespaces = self.__check_children(name)
 
102
            sym = self._symbols[name] = Symbol(name, flags, namespaces)
 
103
        return sym
 
104
 
 
105
    def get_symbols(self):
 
106
        return [self.lookup(ident) for ident in self.get_identifiers()]
 
107
 
 
108
    def __check_children(self, name):
 
109
        return [_newSymbolTable(st, self._filename)
 
110
                for st in self._table.children
 
111
                if st.name == name]
 
112
 
 
113
    def get_children(self):
 
114
        return [_newSymbolTable(st, self._filename)
 
115
                for st in self._table.children]
 
116
 
 
117
 
 
118
class Function(SymbolTable):
 
119
 
 
120
    # Default values for instance variables
 
121
    __params = None
 
122
    __locals = None
 
123
    __frees = None
 
124
    __globals = None
 
125
 
 
126
    def __idents_matching(self, test_func):
 
127
        return tuple([ident for ident in self.get_identifiers()
 
128
                      if test_func(self._table.symbols[ident])])
 
129
 
 
130
    def get_parameters(self):
 
131
        if self.__params is None:
 
132
            self.__params = self.__idents_matching(lambda x:x & DEF_PARAM)
 
133
        return self.__params
 
134
 
 
135
    def get_locals(self):
 
136
        if self.__locals is None:
 
137
            locs = (LOCAL, CELL)
 
138
            test = lambda x: ((x >> SCOPE_OFF) & SCOPE_MASK) in locs
 
139
            self.__locals = self.__idents_matching(test)
 
140
        return self.__locals
 
141
 
 
142
    def get_globals(self):
 
143
        if self.__globals is None:
 
144
            glob = (GLOBAL_IMPLICIT, GLOBAL_EXPLICIT)
 
145
            test = lambda x:((x >> SCOPE_OFF) & SCOPE_MASK) in glob
 
146
            self.__globals = self.__idents_matching(test)
 
147
        return self.__globals
 
148
 
 
149
    def get_frees(self):
 
150
        if self.__frees is None:
 
151
            is_free = lambda x:((x >> SCOPE_OFF) & SCOPE_MASK) == FREE
 
152
            self.__frees = self.__idents_matching(is_free)
 
153
        return self.__frees
 
154
 
 
155
 
 
156
class Class(SymbolTable):
 
157
 
 
158
    __methods = None
 
159
 
 
160
    def get_methods(self):
 
161
        if self.__methods is None:
 
162
            d = {}
 
163
            for st in self._table.children:
 
164
                d[st.name] = 1
 
165
            self.__methods = tuple(d)
 
166
        return self.__methods
 
167
 
 
168
 
 
169
class Symbol(object):
 
170
 
 
171
    def __init__(self, name, flags, namespaces=None):
 
172
        self.__name = name
 
173
        self.__flags = flags
 
174
        self.__scope = (flags >> SCOPE_OFF) & SCOPE_MASK # like PyST_GetScope()
 
175
        self.__namespaces = namespaces or ()
 
176
 
 
177
    def __repr__(self):
 
178
        return "<symbol {0!r}>".format(self.__name)
 
179
 
 
180
    def get_name(self):
 
181
        return self.__name
 
182
 
 
183
    def is_referenced(self):
 
184
        return bool(self.__flags & _symtable.USE)
 
185
 
 
186
    def is_parameter(self):
 
187
        return bool(self.__flags & DEF_PARAM)
 
188
 
 
189
    def is_global(self):
 
190
        return bool(self.__scope in (GLOBAL_IMPLICIT, GLOBAL_EXPLICIT))
 
191
 
 
192
    def is_declared_global(self):
 
193
        return bool(self.__scope == GLOBAL_EXPLICIT)
 
194
 
 
195
    def is_local(self):
 
196
        return bool(self.__flags & DEF_BOUND)
 
197
 
 
198
    def is_free(self):
 
199
        return bool(self.__scope == FREE)
 
200
 
 
201
    def is_imported(self):
 
202
        return bool(self.__flags & DEF_IMPORT)
 
203
 
 
204
    def is_assigned(self):
 
205
        return bool(self.__flags & DEF_LOCAL)
 
206
 
 
207
    def is_namespace(self):
 
208
        """Returns true if name binding introduces new namespace.
 
209
 
 
210
        If the name is used as the target of a function or class
 
211
        statement, this will be true.
 
212
 
 
213
        Note that a single name can be bound to multiple objects.  If
 
214
        is_namespace() is true, the name may also be bound to other
 
215
        objects, like an int or list, that does not introduce a new
 
216
        namespace.
 
217
        """
 
218
        return bool(self.__namespaces)
 
219
 
 
220
    def get_namespaces(self):
 
221
        """Return a list of namespaces bound to this name"""
 
222
        return self.__namespaces
 
223
 
 
224
    def get_namespace(self):
 
225
        """Returns the single namespace bound to this name.
 
226
 
 
227
        Raises ValueError if the name is bound to multiple namespaces.
 
228
        """
 
229
        if len(self.__namespaces) != 1:
 
230
            raise ValueError, "name is bound to multiple namespaces"
 
231
        return self.__namespaces[0]
 
232
 
 
233
if __name__ == "__main__":
 
234
    import os, sys
 
235
    src = open(sys.argv[0]).read()
 
236
    mod = symtable(src, os.path.split(sys.argv[0])[1], "exec")
 
237
    for ident in mod.get_identifiers():
 
238
        info = mod.lookup(ident)
 
239
        print info, info.is_local(), info.is_namespace()