blob: 0bbdc7122d89bdb48d900b133676c822b1f328ae [file] [log] [blame]
Jeremy Hylton8b966dc2001-04-09 04:35:35 +00001"""Module symbol-table generator"""
2
3from compiler import ast
Neil Schemenauer92c3b212009-02-07 00:54:41 +00004from compiler.consts import SC_LOCAL, SC_GLOBAL_IMPLICIT, SC_GLOBAL_EXPLICT, \
5 SC_FREE, SC_CELL, SC_UNKNOWN
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00006from compiler.misc import mangle
Jeremy Hyltonf870c952001-04-09 13:57:32 +00007import types
Jeremy Hylton8b966dc2001-04-09 04:35:35 +00008
Jeremy Hyltonc59e2202001-08-27 22:56:16 +00009
Jeremy Hylton364f9b92001-04-12 06:40:42 +000010import sys
11
Jeremy Hyltonf870c952001-04-09 13:57:32 +000012MANGLE_LEN = 256
Jeremy Hylton8b966dc2001-04-09 04:35:35 +000013
14class Scope:
15 # XXX how much information do I need about each name?
Jeremy Hyltonf870c952001-04-09 13:57:32 +000016 def __init__(self, name, module, klass=None):
Jeremy Hylton8b966dc2001-04-09 04:35:35 +000017 self.name = name
Jeremy Hyltonf870c952001-04-09 13:57:32 +000018 self.module = module
Jeremy Hylton8b966dc2001-04-09 04:35:35 +000019 self.defs = {}
20 self.uses = {}
21 self.globals = {}
22 self.params = {}
Jeremy Hylton364f9b92001-04-12 06:40:42 +000023 self.frees = {}
24 self.cells = {}
Jeremy Hyltonf870c952001-04-09 13:57:32 +000025 self.children = []
Jeremy Hylton364f9b92001-04-12 06:40:42 +000026 # nested is true if the class could contain free variables,
27 # i.e. if it is nested within another function.
28 self.nested = None
Jeremy Hyltond4be10d2001-08-29 18:10:51 +000029 self.generator = None
Jeremy Hyltonf870c952001-04-09 13:57:32 +000030 self.klass = None
31 if klass is not None:
32 for i in range(len(klass)):
33 if klass[i] != '_':
34 self.klass = klass[i:]
35 break
Jeremy Hylton8b966dc2001-04-09 04:35:35 +000036
37 def __repr__(self):
38 return "<%s: %s>" % (self.__class__.__name__, self.name)
39
Jeremy Hyltonf870c952001-04-09 13:57:32 +000040 def mangle(self, name):
41 if self.klass is None:
42 return name
Jeremy Hyltonc59e2202001-08-27 22:56:16 +000043 return mangle(name, self.klass)
Jeremy Hyltonf870c952001-04-09 13:57:32 +000044
Jeremy Hylton8b966dc2001-04-09 04:35:35 +000045 def add_def(self, name):
Jeremy Hyltonf870c952001-04-09 13:57:32 +000046 self.defs[self.mangle(name)] = 1
Jeremy Hylton8b966dc2001-04-09 04:35:35 +000047
48 def add_use(self, name):
Jeremy Hyltonf870c952001-04-09 13:57:32 +000049 self.uses[self.mangle(name)] = 1
Jeremy Hylton8b966dc2001-04-09 04:35:35 +000050
51 def add_global(self, name):
Jeremy Hyltonf870c952001-04-09 13:57:32 +000052 name = self.mangle(name)
Georg Brandl2d2fe572008-12-15 08:58:59 +000053 if name in self.uses or name in self.defs:
Jeremy Hylton8b966dc2001-04-09 04:35:35 +000054 pass # XXX warn about global following def/use
Georg Brandl2d2fe572008-12-15 08:58:59 +000055 if name in self.params:
Jeremy Hylton8b966dc2001-04-09 04:35:35 +000056 raise SyntaxError, "%s in %s is global and parameter" % \
57 (name, self.name)
58 self.globals[name] = 1
Jeremy Hyltonf870c952001-04-09 13:57:32 +000059 self.module.add_def(name)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +000060
61 def add_param(self, name):
Jeremy Hyltonf870c952001-04-09 13:57:32 +000062 name = self.mangle(name)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +000063 self.defs[name] = 1
64 self.params[name] = 1
65
66 def get_names(self):
67 d = {}
68 d.update(self.defs)
69 d.update(self.uses)
Jeremy Hyltondbdb28e2001-04-09 20:11:59 +000070 d.update(self.globals)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +000071 return d.keys()
72
Jeremy Hyltonf870c952001-04-09 13:57:32 +000073 def add_child(self, child):
74 self.children.append(child)
75
76 def get_children(self):
77 return self.children
78
Jeremy Hylton364f9b92001-04-12 06:40:42 +000079 def DEBUG(self):
Jeremy Hylton364f9b92001-04-12 06:40:42 +000080 print >> sys.stderr, self.name, self.nested and "nested" or ""
81 print >> sys.stderr, "\tglobals: ", self.globals
82 print >> sys.stderr, "\tcells: ", self.cells
83 print >> sys.stderr, "\tdefs: ", self.defs
84 print >> sys.stderr, "\tuses: ", self.uses
85 print >> sys.stderr, "\tfrees:", self.frees
86
87 def check_name(self, name):
88 """Return scope of name.
89
90 The scope of a name could be LOCAL, GLOBAL, FREE, or CELL.
91 """
Georg Brandl2d2fe572008-12-15 08:58:59 +000092 if name in self.globals:
Neil Schemenauer92c3b212009-02-07 00:54:41 +000093 return SC_GLOBAL_EXPLICT
Georg Brandl2d2fe572008-12-15 08:58:59 +000094 if name in self.cells:
Jeremy Hylton364f9b92001-04-12 06:40:42 +000095 return SC_CELL
Georg Brandl2d2fe572008-12-15 08:58:59 +000096 if name in self.defs:
Jeremy Hylton364f9b92001-04-12 06:40:42 +000097 return SC_LOCAL
Georg Brandl2d2fe572008-12-15 08:58:59 +000098 if self.nested and (name in self.frees or 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:
Neil Schemenauer92c3b212009-02-07 00:54:41 +0000103 return SC_GLOBAL_IMPLICIT
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000104
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():
Georg Brandl2d2fe572008-12-15 08:58:59 +0000111 if name not in self.defs and name not in self.globals:
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000112 free[name] = 1
113 return free.keys()
114
115 def handle_children(self):
116 for child in self.children:
117 frees = child.get_free_vars()
118 globals = self.add_frees(frees)
119 for name in globals:
120 child.force_global(name)
121
122 def force_global(self, name):
123 """Force name to be global in scope.
124
125 Some child of the current node had a free reference to name.
126 When the child was processed, it was labelled a free
127 variable. Now that all its enclosing scope have been
128 processed, the name is known to be a global or builtin. So
129 walk back down the child chain and set the name to be global
130 rather than free.
131
132 Be careful to stop if a child does not think the name is
Tim Peterse0c446b2001-10-18 21:57:37 +0000133 free.
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000134 """
135 self.globals[name] = 1
Georg Brandl2d2fe572008-12-15 08:58:59 +0000136 if name in self.frees:
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000137 del self.frees[name]
138 for child in self.children:
139 if child.check_name(name) == SC_FREE:
140 child.force_global(name)
141
142 def add_frees(self, names):
143 """Process list of free vars from nested scope.
144
145 Returns a list of names that are either 1) declared global in the
146 parent or 2) undefined in a top-level parent. In either case,
147 the nested scope should treat them as globals.
148 """
149 child_globals = []
150 for name in names:
151 sc = self.check_name(name)
152 if self.nested:
153 if sc == SC_UNKNOWN or sc == SC_FREE \
154 or isinstance(self, ClassScope):
155 self.frees[name] = 1
Neil Schemenauer92c3b212009-02-07 00:54:41 +0000156 elif sc == SC_GLOBAL_IMPLICIT:
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000157 child_globals.append(name)
158 elif isinstance(self, FunctionScope) and sc == SC_LOCAL:
159 self.cells[name] = 1
Jeremy Hyltoncd8a1272001-08-27 21:06:35 +0000160 elif sc != SC_CELL:
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000161 child_globals.append(name)
162 else:
163 if sc == SC_LOCAL:
164 self.cells[name] = 1
Jeremy Hyltoncd8a1272001-08-27 21:06:35 +0000165 elif sc != SC_CELL:
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000166 child_globals.append(name)
167 return child_globals
168
169 def get_cell_vars(self):
170 return self.cells.keys()
171
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000172class ModuleScope(Scope):
173 __super_init = Scope.__init__
Tim Peterse0c446b2001-10-18 21:57:37 +0000174
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000175 def __init__(self):
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000176 self.__super_init("global", self)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000177
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000178class FunctionScope(Scope):
179 pass
180
Raymond Hettinger354433a2004-05-19 08:20:33 +0000181class GenExprScope(Scope):
182 __super_init = Scope.__init__
183
184 __counter = 1
185
186 def __init__(self, module, klass=None):
187 i = self.__counter
188 self.__counter += 1
189 self.__super_init("generator expression<%d>"%i, module, klass)
Neil Schemenauer4c6b0d52006-08-16 23:38:05 +0000190 self.add_param('.0')
Raymond Hettinger354433a2004-05-19 08:20:33 +0000191
192 def get_names(self):
Neal Norwitz6aaccc62006-06-11 08:35:14 +0000193 keys = Scope.get_names(self)
Raymond Hettinger354433a2004-05-19 08:20:33 +0000194 return keys
195
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000196class LambdaScope(FunctionScope):
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000197 __super_init = Scope.__init__
198
199 __counter = 1
Tim Peterse0c446b2001-10-18 21:57:37 +0000200
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000201 def __init__(self, module, klass=None):
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000202 i = self.__counter
203 self.__counter += 1
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000204 self.__super_init("lambda.%d" % i, module, klass)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000205
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000206class ClassScope(Scope):
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000207 __super_init = Scope.__init__
208
209 def __init__(self, name, module):
210 self.__super_init(name, module, name)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000211
212class SymbolVisitor:
213 def __init__(self):
214 self.scopes = {}
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000215 self.klass = None
Tim Peterse0c446b2001-10-18 21:57:37 +0000216
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000217 # node that define new scopes
218
219 def visitModule(self, node):
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000220 scope = self.module = self.scopes[node] = ModuleScope()
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000221 self.visit(node.node, scope)
222
Barry Warsaw52acb492001-12-21 20:04:22 +0000223 visitExpression = visitModule
224
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000225 def visitFunction(self, node, parent):
Anthony Baxterc2a5a632004-08-02 06:10:11 +0000226 if node.decorators:
227 self.visit(node.decorators, parent)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000228 parent.add_def(node.name)
229 for n in node.defaults:
230 self.visit(n, parent)
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000231 scope = FunctionScope(node.name, self.module, self.klass)
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000232 if parent.nested or isinstance(parent, FunctionScope):
233 scope.nested = 1
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000234 self.scopes[node] = scope
Jeremy Hyltondbdb28e2001-04-09 20:11:59 +0000235 self._do_args(scope, node.argnames)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000236 self.visit(node.code, scope)
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000237 self.handle_free_vars(scope, parent)
Tim Peterse0c446b2001-10-18 21:57:37 +0000238
Raymond Hettinger354433a2004-05-19 08:20:33 +0000239 def visitGenExpr(self, node, parent):
240 scope = GenExprScope(self.module, self.klass);
241 if parent.nested or isinstance(parent, FunctionScope) \
242 or isinstance(parent, GenExprScope):
243 scope.nested = 1
244
245 self.scopes[node] = scope
246 self.visit(node.code, scope)
247
248 self.handle_free_vars(scope, parent)
249
250 def visitGenExprInner(self, node, scope):
251 for genfor in node.quals:
252 self.visit(genfor, scope)
253
254 self.visit(node.expr, scope)
255
256 def visitGenExprFor(self, node, scope):
257 self.visit(node.assign, scope, 1)
258 self.visit(node.iter, scope)
259 for if_ in node.ifs:
260 self.visit(if_, scope)
261
262 def visitGenExprIf(self, node, scope):
263 self.visit(node.test, scope)
Tim Peters4e0e1b62004-07-07 20:54:48 +0000264
Jeremy Hyltonead21f52003-08-28 02:09:26 +0000265 def visitLambda(self, node, parent, assign=0):
266 # Lambda is an expression, so it could appear in an expression
267 # context where assign is passed. The transformer should catch
268 # any code that has a lambda on the left-hand side.
Tim Peters4e0e1b62004-07-07 20:54:48 +0000269 assert not assign
270
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000271 for n in node.defaults:
272 self.visit(n, parent)
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000273 scope = LambdaScope(self.module, self.klass)
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000274 if parent.nested or isinstance(parent, FunctionScope):
275 scope.nested = 1
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000276 self.scopes[node] = scope
Jeremy Hyltondbdb28e2001-04-09 20:11:59 +0000277 self._do_args(scope, node.argnames)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000278 self.visit(node.code, scope)
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000279 self.handle_free_vars(scope, parent)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000280
Jeremy Hyltondbdb28e2001-04-09 20:11:59 +0000281 def _do_args(self, scope, args):
282 for name in args:
283 if type(name) == types.TupleType:
284 self._do_args(scope, name)
285 else:
286 scope.add_param(name)
287
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000288 def handle_free_vars(self, scope, parent):
289 parent.add_child(scope)
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000290 scope.handle_children()
291
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000292 def visitClass(self, node, parent):
293 parent.add_def(node.name)
294 for n in node.bases:
295 self.visit(n, parent)
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000296 scope = ClassScope(node.name, self.module)
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000297 if parent.nested or isinstance(parent, FunctionScope):
298 scope.nested = 1
Jeremy Hyltonaccb62b2002-12-31 18:17:44 +0000299 if node.doc is not None:
300 scope.add_def('__doc__')
301 scope.add_def('__module__')
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000302 self.scopes[node] = scope
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000303 prev = self.klass
304 self.klass = node.name
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000305 self.visit(node.code, scope)
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000306 self.klass = prev
Jeremy Hylton364f9b92001-04-12 06:40:42 +0000307 self.handle_free_vars(scope, parent)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000308
309 # name can be a def or a use
310
311 # XXX a few calls and nodes expect a third "assign" arg that is
312 # true if the name is being used as an assignment. only
313 # expressions contained within statements may have the assign arg.
314
315 def visitName(self, node, scope, assign=0):
316 if assign:
317 scope.add_def(node.name)
318 else:
319 scope.add_use(node.name)
320
321 # operations that bind new names
322
323 def visitFor(self, node, scope):
324 self.visit(node.assign, scope, 1)
325 self.visit(node.list, scope)
326 self.visit(node.body, scope)
327 if node.else_:
328 self.visit(node.else_, scope)
329
330 def visitFrom(self, node, scope):
331 for name, asname in node.names:
332 if name == "*":
333 continue
334 scope.add_def(asname or name)
335
336 def visitImport(self, node, scope):
337 for name, asname in node.names:
338 i = name.find(".")
339 if i > -1:
340 name = name[:i]
341 scope.add_def(asname or name)
342
Jeremy Hyltond4be10d2001-08-29 18:10:51 +0000343 def visitGlobal(self, node, scope):
344 for name in node.names:
345 scope.add_global(name)
346
347 def visitAssign(self, node, scope):
348 """Propagate assignment flag down to child nodes.
349
350 The Assign node doesn't itself contains the variables being
351 assigned to. Instead, the children in node.nodes are visited
352 with the assign flag set to true. When the names occur in
353 those nodes, they are marked as defs.
354
355 Some names that occur in an assignment target are not bound by
356 the assignment, e.g. a name occurring inside a slice. The
357 visitor handles these nodes specially; they do not propagate
358 the assign flag to their children.
359 """
360 for n in node.nodes:
361 self.visit(n, scope, 1)
362 self.visit(node.expr, scope)
363
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000364 def visitAssName(self, node, scope, assign=1):
365 scope.add_def(node.name)
366
Jeremy Hyltoncd8a1272001-08-27 21:06:35 +0000367 def visitAssAttr(self, node, scope, assign=0):
368 self.visit(node.expr, scope, 0)
369
370 def visitSubscript(self, node, scope, assign=0):
371 self.visit(node.expr, scope, 0)
372 for n in node.subs:
373 self.visit(n, scope, 0)
Jeremy Hyltond4be10d2001-08-29 18:10:51 +0000374
375 def visitSlice(self, node, scope, assign=0):
Jeremy Hylton652a2242001-09-14 22:45:57 +0000376 self.visit(node.expr, scope, 0)
Jeremy Hyltond4be10d2001-08-29 18:10:51 +0000377 if node.lower:
378 self.visit(node.lower, scope, 0)
379 if node.upper:
380 self.visit(node.upper, scope, 0)
Tim Peterse0c446b2001-10-18 21:57:37 +0000381
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000382 def visitAugAssign(self, node, scope):
Jeremy Hylton5c9aad62001-04-12 07:06:25 +0000383 # If the LHS is a name, then this counts as assignment.
384 # Otherwise, it's just use.
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000385 self.visit(node.node, scope)
Jeremy Hylton5c9aad62001-04-12 07:06:25 +0000386 if isinstance(node.node, ast.Name):
387 self.visit(node.node, scope, 1) # XXX worry about this
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000388 self.visit(node.expr, scope)
389
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000390 # prune if statements if tests are false
391
392 _const_types = types.StringType, types.IntType, types.FloatType
393
394 def visitIf(self, node, scope):
395 for test, body in node.tests:
396 if isinstance(test, ast.Const):
397 if type(test.value) in self._const_types:
398 if not test.value:
399 continue
400 self.visit(test, scope)
401 self.visit(body, scope)
402 if node.else_:
403 self.visit(node.else_, scope)
404
Jeremy Hyltond4be10d2001-08-29 18:10:51 +0000405 # a yield statement signals a generator
406
407 def visitYield(self, node, scope):
Jeremy Hylton652a2242001-09-14 22:45:57 +0000408 scope.generator = 1
Jeremy Hyltond4be10d2001-08-29 18:10:51 +0000409 self.visit(node.value, scope)
410
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000411def list_eq(l1, l2):
Neal Norwitzf9232672005-11-25 03:16:34 +0000412 return sorted(l1) == sorted(l2)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000413
414if __name__ == "__main__":
415 import sys
416 from compiler import parseFile, walk
417 import symtable
418
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000419 def get_names(syms):
420 return [s for s in [s.get_name() for s in syms.get_symbols()]
Tim Peterse0c446b2001-10-18 21:57:37 +0000421 if not (s.startswith('_[') or s.startswith('.'))]
422
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000423 for file in sys.argv[1:]:
424 print file
425 f = open(file)
426 buf = f.read()
427 f.close()
428 syms = symtable.symtable(buf, file, "exec")
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000429 mod_names = get_names(syms)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000430 tree = parseFile(file)
431 s = SymbolVisitor()
432 walk(tree, s)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000433
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000434 # compare module-level symbols
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000435 names2 = s.scopes[tree].get_names()
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000436
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000437 if not list_eq(mod_names, names2):
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000438 print
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000439 print "oops", file
Neal Norwitzf9232672005-11-25 03:16:34 +0000440 print sorted(mod_names)
441 print sorted(names2)
Jeremy Hylton8b966dc2001-04-09 04:35:35 +0000442 sys.exit(-1)
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000443
444 d = {}
445 d.update(s.scopes)
446 del d[tree]
447 scopes = d.values()
448 del d
449
450 for s in syms.get_symbols():
451 if s.is_namespace():
452 l = [sc for sc in scopes
453 if sc.name == s.get_name()]
454 if len(l) > 1:
455 print "skipping", s.get_name()
456 else:
457 if not list_eq(get_names(s.get_namespace()),
458 l[0].get_names()):
459 print s.get_name()
Neal Norwitzf9232672005-11-25 03:16:34 +0000460 print sorted(get_names(s.get_namespace()))
461 print sorted(l[0].get_names())
Jeremy Hyltonf870c952001-04-09 13:57:32 +0000462 sys.exit(-1)