blob: 3585efc3013aa25d1d2425b6dbe77d20528b6ce6 [file] [log] [blame]
Jeremy Hylton8b966dc2001-04-09 04:35:35 +00001"""Module symbol-table generator"""
2
3from compiler import ast
Jeremy Hylton364f9b92001-04-12 06:40:42 +00004from compiler.consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL, SC_UNKNOWN
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00005from compiler.misc import mangle
Jeremy Hyltonf870c952001-04-09 13:57:32 +00006import types
Jeremy Hylton8b966dc2001-04-09 04:35:35 +00007
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00008
Jeremy Hylton364f9b92001-04-12 06:40:42 +00009import sys
10
Jeremy Hyltonf870c952001-04-09 13:57:32 +000011MANGLE_LEN = 256
Jeremy Hylton8b966dc2001-04-09 04:35:35 +000012
13class Scope:
14 # XXX how much information do I need about each name?
Jeremy Hyltonf870c952001-04-09 13:57:32 +000015 def __init__(self, name, module, klass=None):
Jeremy Hylton8b966dc2001-04-09 04:35:35 +000016 self.name = name
Jeremy Hyltonf870c952001-04-09 13:57:32 +000017 self.module = module
Jeremy Hylton8b966dc2001-04-09 04:35:35 +000018 self.defs = {}
19 self.uses = {}
20 self.globals = {}
21 self.params = {}
Jeremy Hylton364f9b92001-04-12 06:40:42 +000022 self.frees = {}
23 self.cells = {}
Jeremy Hyltonf870c952001-04-09 13:57:32 +000024 self.children = []
Jeremy Hylton364f9b92001-04-12 06:40:42 +000025 # nested is true if the class could contain free variables,
26 # i.e. if it is nested within another function.
27 self.nested = None
Jeremy Hyltond4be10d2001-08-29 18:10:51 +000028 self.generator = None
Jeremy Hyltonf870c952001-04-09 13:57:32 +000029 self.klass = None
30 if klass is not None:
31 for i in range(len(klass)):
32 if klass[i] != '_':
33 self.klass = klass[i:]
34 break
Jeremy Hylton8b966dc2001-04-09 04:35:35 +000035
36 def __repr__(self):
37 return "<%s: %s>" % (self.__class__.__name__, self.name)
38
Jeremy Hyltonf870c952001-04-09 13:57:32 +000039 def mangle(self, name):
40 if self.klass is None:
41 return name
Jeremy Hyltonc59e2202001-08-27 22:56:16 +000042 return mangle(name, self.klass)
Jeremy Hyltonf870c952001-04-09 13:57:32 +000043
Jeremy Hylton8b966dc2001-04-09 04:35:35 +000044 def add_def(self, name):
Jeremy Hyltonf870c952001-04-09 13:57:32 +000045 self.defs[self.mangle(name)] = 1
Jeremy Hylton8b966dc2001-04-09 04:35:35 +000046
47 def add_use(self, name):
Jeremy Hyltonf870c952001-04-09 13:57:32 +000048 self.uses[self.mangle(name)] = 1
Jeremy Hylton8b966dc2001-04-09 04:35:35 +000049
50 def add_global(self, name):
Jeremy Hyltonf870c952001-04-09 13:57:32 +000051 name = self.mangle(name)
Guido van Rossum49061f72006-08-19 15:28:37 +000052 if name in self.uses or name in self.defs:
Jeremy Hylton8b966dc2001-04-09 04:35:35 +000053 pass # XXX warn about global following def/use
Guido van Rossum49061f72006-08-19 15:28:37 +000054 if name in self.params:
Jeremy Hylton8b966dc2001-04-09 04:35:35 +000055 raise SyntaxError, "%s in %s is global and parameter" % \
56 (name, self.name)
57 self.globals[name] = 1
Jeremy Hyltonf870c952001-04-09 13:57:32 +000058 self.module.add_def(name)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +000059
60 def add_param(self, name):
Jeremy Hyltonf870c952001-04-09 13:57:32 +000061 name = self.mangle(name)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +000062 self.defs[name] = 1
63 self.params[name] = 1
64
65 def get_names(self):
66 d = {}
67 d.update(self.defs)
68 d.update(self.uses)
Jeremy Hyltondbdb28e2001-04-09 20:11:59 +000069 d.update(self.globals)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +000070 return d.keys()
71
Jeremy Hyltonf870c952001-04-09 13:57:32 +000072 def add_child(self, child):
73 self.children.append(child)
74
75 def get_children(self):
76 return self.children
77
Jeremy Hylton364f9b92001-04-12 06:40:42 +000078 def DEBUG(self):
Jeremy Hylton364f9b92001-04-12 06:40:42 +000079 print >> sys.stderr, self.name, self.nested and "nested" or ""
80 print >> sys.stderr, "\tglobals: ", self.globals
81 print >> sys.stderr, "\tcells: ", self.cells
82 print >> sys.stderr, "\tdefs: ", self.defs
83 print >> sys.stderr, "\tuses: ", self.uses
84 print >> sys.stderr, "\tfrees:", self.frees
85
86 def check_name(self, name):
87 """Return scope of name.
88
89 The scope of a name could be LOCAL, GLOBAL, FREE, or CELL.
90 """
Guido van Rossum49061f72006-08-19 15:28:37 +000091 if name in self.globals:
Jeremy Hylton364f9b92001-04-12 06:40:42 +000092 return SC_GLOBAL
Guido van Rossum49061f72006-08-19 15:28:37 +000093 if name in self.cells:
Jeremy Hylton364f9b92001-04-12 06:40:42 +000094 return SC_CELL
Guido van Rossum49061f72006-08-19 15:28:37 +000095 if name in self.defs:
Jeremy Hylton364f9b92001-04-12 06:40:42 +000096 return SC_LOCAL
Guido van Rossum49061f72006-08-19 15:28:37 +000097 if self.nested and (name in self.frees or
98 name in self.uses):
Jeremy Hylton364f9b92001-04-12 06:40:42 +000099 return SC_FREE
100 if self.nested:
101 return SC_UNKNOWN
102 else:
103 return SC_GLOBAL
104
105 def get_free_vars(self):
106 if not self.nested:
107 return ()
108 free = {}
109 free.update(self.frees)
110 for name in self.uses.keys():
Guido van Rossum49061f72006-08-19 15:28:37 +0000111 if not (name in self.defs or
112 name in self.globals):
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000113 free[name] = 1
114 return free.keys()
115
116 def handle_children(self):
117 for child in self.children:
118 frees = child.get_free_vars()
119 globals = self.add_frees(frees)
120 for name in globals:
121 child.force_global(name)
122
123 def force_global(self, name):
124 """Force name to be global in scope.
125
126 Some child of the current node had a free reference to name.
127 When the child was processed, it was labelled a free
128 variable. Now that all its enclosing scope have been
129 processed, the name is known to be a global or builtin. So
130 walk back down the child chain and set the name to be global
131 rather than free.
132
133 Be careful to stop if a child does not think the name is
Tim Peterse0c446b2001-10-18 21:57:37 +0000134 free.
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000135 """
136 self.globals[name] = 1
Guido van Rossum49061f72006-08-19 15:28:37 +0000137 if name in self.frees:
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000138 del self.frees[name]
139 for child in self.children:
140 if child.check_name(name) == SC_FREE:
141 child.force_global(name)
142
143 def add_frees(self, names):
144 """Process list of free vars from nested scope.
145
146 Returns a list of names that are either 1) declared global in the
147 parent or 2) undefined in a top-level parent. In either case,
148 the nested scope should treat them as globals.
149 """
150 child_globals = []
151 for name in names:
152 sc = self.check_name(name)
153 if self.nested:
154 if sc == SC_UNKNOWN or sc == SC_FREE \
155 or isinstance(self, ClassScope):
156 self.frees[name] = 1
157 elif sc == SC_GLOBAL:
158 child_globals.append(name)
159 elif isinstance(self, FunctionScope) and sc == SC_LOCAL:
160 self.cells[name] = 1
Jeremy Hyltoncd8a1272001-08-27 21:06:35 +0000161 elif sc != SC_CELL:
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000162 child_globals.append(name)
163 else:
164 if sc == SC_LOCAL:
165 self.cells[name] = 1
Jeremy Hyltoncd8a1272001-08-27 21:06:35 +0000166 elif sc != SC_CELL:
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000167 child_globals.append(name)
168 return child_globals
169
170 def get_cell_vars(self):
171 return self.cells.keys()
172
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000173class ModuleScope(Scope):
174 __super_init = Scope.__init__
Tim Peterse0c446b2001-10-18 21:57:37 +0000175
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000176 def __init__(self):
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000177 self.__super_init("global", self)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000178
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000179class FunctionScope(Scope):
180 pass
181
Raymond Hettinger354433a2004-05-19 08:20:33 +0000182class GenExprScope(Scope):
183 __super_init = Scope.__init__
184
185 __counter = 1
186
187 def __init__(self, module, klass=None):
188 i = self.__counter
189 self.__counter += 1
190 self.__super_init("generator expression<%d>"%i, module, klass)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000191 self.add_param('.0')
Raymond Hettinger354433a2004-05-19 08:20:33 +0000192
193 def get_names(self):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000194 keys = Scope.get_names(self)
Raymond Hettinger354433a2004-05-19 08:20:33 +0000195 return keys
196
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000197class LambdaScope(FunctionScope):
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000198 __super_init = Scope.__init__
199
200 __counter = 1
Tim Peterse0c446b2001-10-18 21:57:37 +0000201
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000202 def __init__(self, module, klass=None):
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000203 i = self.__counter
204 self.__counter += 1
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000205 self.__super_init("lambda.%d" % i, module, klass)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000206
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000207class ClassScope(Scope):
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000208 __super_init = Scope.__init__
209
210 def __init__(self, name, module):
211 self.__super_init(name, module, name)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000212
213class SymbolVisitor:
214 def __init__(self):
215 self.scopes = {}
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000216 self.klass = None
Tim Peterse0c446b2001-10-18 21:57:37 +0000217
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000218 # node that define new scopes
219
220 def visitModule(self, node):
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000221 scope = self.module = self.scopes[node] = ModuleScope()
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000222 self.visit(node.node, scope)
223
Barry Warsaw52acb492001-12-21 20:04:22 +0000224 visitExpression = visitModule
225
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000226 def visitFunction(self, node, parent):
Anthony Baxterc2a5a632004-08-02 06:10:11 +0000227 if node.decorators:
228 self.visit(node.decorators, parent)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000229 parent.add_def(node.name)
230 for n in node.defaults:
231 self.visit(n, parent)
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000232 scope = FunctionScope(node.name, self.module, self.klass)
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000233 if parent.nested or isinstance(parent, FunctionScope):
234 scope.nested = 1
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000235 self.scopes[node] = scope
Neal Norwitzc1505362006-12-28 06:47:50 +0000236
237 args = node.arguments
238 for kwonly in node.kwonlyargs:
239 args.append(kwonly.arg)
240 self._do_arguments(scope, args)
241
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000242 self.visit(node.code, scope)
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000243 self.handle_free_vars(scope, parent)
Tim Peterse0c446b2001-10-18 21:57:37 +0000244
Raymond Hettinger354433a2004-05-19 08:20:33 +0000245 def visitGenExpr(self, node, parent):
246 scope = GenExprScope(self.module, self.klass);
247 if parent.nested or isinstance(parent, FunctionScope) \
248 or isinstance(parent, GenExprScope):
249 scope.nested = 1
250
251 self.scopes[node] = scope
252 self.visit(node.code, scope)
253
254 self.handle_free_vars(scope, parent)
255
256 def visitGenExprInner(self, node, scope):
257 for genfor in node.quals:
258 self.visit(genfor, scope)
259
260 self.visit(node.expr, scope)
261
262 def visitGenExprFor(self, node, scope):
263 self.visit(node.assign, scope, 1)
264 self.visit(node.iter, scope)
265 for if_ in node.ifs:
266 self.visit(if_, scope)
267
268 def visitGenExprIf(self, node, scope):
269 self.visit(node.test, scope)
Tim Peters4e0e1b62004-07-07 20:54:48 +0000270
Jeremy Hyltonead21f52003-08-28 02:09:26 +0000271 def visitLambda(self, node, parent, assign=0):
272 # Lambda is an expression, so it could appear in an expression
273 # context where assign is passed. The transformer should catch
274 # any code that has a lambda on the left-hand side.
Tim Peters4e0e1b62004-07-07 20:54:48 +0000275 assert not assign
276
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000277 for n in node.defaults:
278 self.visit(n, parent)
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000279 scope = LambdaScope(self.module, self.klass)
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000280 if parent.nested or isinstance(parent, FunctionScope):
281 scope.nested = 1
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000282 self.scopes[node] = scope
Neal Norwitzc1505362006-12-28 06:47:50 +0000283 self._do_arguments(scope, node.arguments)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000284 self.visit(node.code, scope)
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000285 self.handle_free_vars(scope, parent)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000286
Neal Norwitzc1505362006-12-28 06:47:50 +0000287 def _do_arguments(self, scope, arguments):
288 for node in arguments:
289 if isinstance(node, ast.SimpleArg):
290 scope.add_param(node.name)
291 if node.annotation:
292 self.visit(node.annotation, scope)
Jeremy Hyltondbdb28e2001-04-09 20:11:59 +0000293 else:
Neal Norwitzc1505362006-12-28 06:47:50 +0000294 self._do_arguments(scope, node.args)
Jeremy Hyltondbdb28e2001-04-09 20:11:59 +0000295
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000296 def handle_free_vars(self, scope, parent):
297 parent.add_child(scope)
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000298 scope.handle_children()
299
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000300 def visitClass(self, node, parent):
301 parent.add_def(node.name)
302 for n in node.bases:
303 self.visit(n, parent)
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000304 scope = ClassScope(node.name, self.module)
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000305 if parent.nested or isinstance(parent, FunctionScope):
306 scope.nested = 1
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +0000307 if node.doc is not None:
308 scope.add_def('__doc__')
309 scope.add_def('__module__')
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000310 self.scopes[node] = scope
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000311 prev = self.klass
312 self.klass = node.name
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000313 self.visit(node.code, scope)
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000314 self.klass = prev
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000315 self.handle_free_vars(scope, parent)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000316
317 # name can be a def or a use
318
319 # XXX a few calls and nodes expect a third "assign" arg that is
320 # true if the name is being used as an assignment. only
321 # expressions contained within statements may have the assign arg.
322
323 def visitName(self, node, scope, assign=0):
324 if assign:
325 scope.add_def(node.name)
326 else:
327 scope.add_use(node.name)
328
329 # operations that bind new names
330
331 def visitFor(self, node, scope):
332 self.visit(node.assign, scope, 1)
333 self.visit(node.list, scope)
334 self.visit(node.body, scope)
335 if node.else_:
336 self.visit(node.else_, scope)
337
338 def visitFrom(self, node, scope):
339 for name, asname in node.names:
340 if name == "*":
341 continue
342 scope.add_def(asname or name)
343
344 def visitImport(self, node, scope):
345 for name, asname in node.names:
346 i = name.find(".")
347 if i > -1:
348 name = name[:i]
349 scope.add_def(asname or name)
350
Jeremy Hyltond4be10d2001-08-29 18:10:51 +0000351 def visitGlobal(self, node, scope):
352 for name in node.names:
353 scope.add_global(name)
354
355 def visitAssign(self, node, scope):
356 """Propagate assignment flag down to child nodes.
357
358 The Assign node doesn't itself contains the variables being
359 assigned to. Instead, the children in node.nodes are visited
360 with the assign flag set to true. When the names occur in
361 those nodes, they are marked as defs.
362
363 Some names that occur in an assignment target are not bound by
364 the assignment, e.g. a name occurring inside a slice. The
365 visitor handles these nodes specially; they do not propagate
366 the assign flag to their children.
367 """
368 for n in node.nodes:
369 self.visit(n, scope, 1)
370 self.visit(node.expr, scope)
371
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000372 def visitAssName(self, node, scope, assign=1):
373 scope.add_def(node.name)
374
Jeremy Hyltoncd8a1272001-08-27 21:06:35 +0000375 def visitAssAttr(self, node, scope, assign=0):
376 self.visit(node.expr, scope, 0)
377
378 def visitSubscript(self, node, scope, assign=0):
379 self.visit(node.expr, scope, 0)
380 for n in node.subs:
381 self.visit(n, scope, 0)
Jeremy Hyltond4be10d2001-08-29 18:10:51 +0000382
383 def visitSlice(self, node, scope, assign=0):
Jeremy Hylton652a2242001-09-14 22:45:57 +0000384 self.visit(node.expr, scope, 0)
Jeremy Hyltond4be10d2001-08-29 18:10:51 +0000385 if node.lower:
386 self.visit(node.lower, scope, 0)
387 if node.upper:
388 self.visit(node.upper, scope, 0)
Tim Peterse0c446b2001-10-18 21:57:37 +0000389
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000390 def visitAugAssign(self, node, scope):
Jeremy Hylton5c9aad62001-04-12 07:06:25 +0000391 # If the LHS is a name, then this counts as assignment.
392 # Otherwise, it's just use.
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000393 self.visit(node.node, scope)
Jeremy Hylton5c9aad62001-04-12 07:06:25 +0000394 if isinstance(node.node, ast.Name):
395 self.visit(node.node, scope, 1) # XXX worry about this
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000396 self.visit(node.expr, scope)
397
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000398 # prune if statements if tests are false
399
400 _const_types = types.StringType, types.IntType, types.FloatType
401
402 def visitIf(self, node, scope):
403 for test, body in node.tests:
404 if isinstance(test, ast.Const):
405 if type(test.value) in self._const_types:
406 if not test.value:
407 continue
408 self.visit(test, scope)
409 self.visit(body, scope)
410 if node.else_:
411 self.visit(node.else_, scope)
412
Jeremy Hyltond4be10d2001-08-29 18:10:51 +0000413 # a yield statement signals a generator
414
415 def visitYield(self, node, scope):
Jeremy Hylton652a2242001-09-14 22:45:57 +0000416 scope.generator = 1
Jeremy Hyltond4be10d2001-08-29 18:10:51 +0000417 self.visit(node.value, scope)
418
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000419def list_eq(l1, l2):
Neal Norwitzf9232672005-11-25 03:16:34 +0000420 return sorted(l1) == sorted(l2)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000421
422if __name__ == "__main__":
423 import sys
424 from compiler import parseFile, walk
425 import symtable
426
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000427 def get_names(syms):
428 return [s for s in [s.get_name() for s in syms.get_symbols()]
Tim Peterse0c446b2001-10-18 21:57:37 +0000429 if not (s.startswith('_[') or s.startswith('.'))]
430
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000431 for file in sys.argv[1:]:
432 print file
433 f = open(file)
434 buf = f.read()
435 f.close()
436 syms = symtable.symtable(buf, file, "exec")
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000437 mod_names = get_names(syms)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000438 tree = parseFile(file)
439 s = SymbolVisitor()
440 walk(tree, s)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000441
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000442 # compare module-level symbols
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000443 names2 = s.scopes[tree].get_names()
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000444
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000445 if not list_eq(mod_names, names2):
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000446 print
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000447 print "oops", file
Neal Norwitzf9232672005-11-25 03:16:34 +0000448 print sorted(mod_names)
449 print sorted(names2)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000450 sys.exit(-1)
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000451
452 d = {}
453 d.update(s.scopes)
454 del d[tree]
455 scopes = d.values()
456 del d
457
458 for s in syms.get_symbols():
459 if s.is_namespace():
460 l = [sc for sc in scopes
461 if sc.name == s.get_name()]
462 if len(l) > 1:
463 print "skipping", s.get_name()
464 else:
465 if not list_eq(get_names(s.get_namespace()),
466 l[0].get_names()):
467 print s.get_name()
Neal Norwitzf9232672005-11-25 03:16:34 +0000468 print sorted(get_names(s.get_namespace()))
469 print sorted(l[0].get_names())
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000470 sys.exit(-1)