1 #!/usr/bin/env python 2 3 """ 4 Inspect source files, obtaining details of classes and attributes. 5 6 Copyright (C) 2007, 2008, 2009, 2010 Paul Boddie <paul@boddie.org.uk> 7 8 This program is free software; you can redistribute it and/or modify it under 9 the terms of the GNU General Public License as published by the Free Software 10 Foundation; either version 3 of the License, or (at your option) any later 11 version. 12 13 This program is distributed in the hope that it will be useful, but WITHOUT 14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 16 details. 17 18 You should have received a copy of the GNU General Public License along with 19 this program. If not, see <http://www.gnu.org/licenses/>. 20 21 -------- 22 23 The results of inspecting a module are as follows: 24 25 Constants 26 --------- 27 28 All constants identified within the code shall be registered. 29 30 Classes 31 ------- 32 33 All global classes shall be registered; local classes (within functions) or 34 nested classes (within classes) are not currently registered. 35 36 Base classes must be detected and constant. 37 38 All classes without bases are made to inherit from __builtins__.object in order 39 to support some standard methods. 40 41 Functions 42 --------- 43 44 All functions and lambda definitions shall be registered. 45 46 Namespaces 47 ---------- 48 49 Modules define their own "global" namespace, within which classes, functions 50 and lambda definitions establish a hierarchy of namespaces. 51 52 Only local, global and built-in namespaces are recognised; closures are not 53 supported. 54 55 Assignments 56 ----------- 57 58 Name assignment and attribute assignment involving modules and classes cause 59 names to be associated with values within namespaces. 60 61 Any assignments within loops are considered to cause the targets of such 62 assignments to provide non-constant values. 63 64 Assignments to names are only really considered to cause the targets of such 65 assignments to provide constant values if the targets reside in the module 66 namespace or in class namespaces, subject to the above conditions. 67 68 Assignments to names within functions are not generally considered to cause the 69 targets of such assignments to provide constant values since functions can be 70 invoked many times with different inputs. This affects particularly the 71 definition of functions or lambdas within functions. However, there may be 72 benefits in considering a local to be constant within a single invocation. 73 """ 74 75 from micropython.common import * 76 from micropython.data import * 77 import compiler.ast 78 79 # Program visitors. 80 81 class InspectedModule(ASTVisitor, Module): 82 83 """ 84 An inspected module, providing core details via the Module superclass, but 85 capable of being used as an AST visitor. 86 """ 87 88 def __init__(self, name, importer): 89 90 """ 91 Initialise this visitor with a module 'name' and an 'importer' which is 92 used to provide access to other modules when required. 93 """ 94 95 ASTVisitor.__init__(self) 96 Module.__init__(self, name) 97 self.visitor = self 98 99 # Import machinery links. 100 101 self.importer = importer 102 self.optimisations = importer.optimisations 103 self.builtins = self.importer.modules.get("__builtins__") 104 self.loaded = 0 105 106 # Current expression state. 107 108 self.expr = None 109 110 # Namespace state. 111 112 self.in_init = 0 # Find instance attributes in __init__ methods. 113 self.in_method = 0 # Find instance attributes in all methods. 114 self.in_function = 0 # Note function presence, affecting definitions. 115 self.in_loop = 0 # Note loop "membership", affecting assignments. 116 self.namespaces = [] 117 self.module = None 118 self.functions = [] 119 120 def parse(self, filename): 121 122 "Parse the file having the given 'filename'." 123 124 module = compiler.parseFile(filename) 125 self.process(module) 126 127 def process(self, module): 128 129 "Process the given 'module'." 130 131 self.astnode = self.module = module 132 133 # Add __name__ to the namespace by adding an explicit assignment to the 134 # module. 135 136 module.node.nodes.insert(0, compiler.ast.Assign( 137 [compiler.ast.AssName("__name__", 0)], 138 compiler.ast.Const(self.full_name()) 139 )) 140 141 # First, visit module-level code, recording global names. 142 143 processed = self.dispatch(module) 144 145 # Then, for each function, detect and record globals declared in those 146 # functions. 147 148 for node, namespaces in self.functions: 149 self.process_globals(node) 150 151 self.finalise_namespace(self) 152 153 # Then, visit each function, recording other names. 154 155 for node, namespaces in self.functions: 156 self._visitFunctionBody(node, namespaces) 157 self.finalise_namespace(namespaces[-1]) 158 159 # Add references to other modules declared using the __all__ global. 160 161 if self.has_key("__all__"): 162 all = self["__all__"] 163 if isinstance(all, compiler.ast.List): 164 for n in all.nodes: 165 self.store(n.value, self.importer.add_module(self.name + "." + n.value)) 166 167 return processed 168 169 def process_globals(self, node): 170 171 """ 172 Within the given 'node', process global declarations, adjusting the 173 module namespace. 174 """ 175 176 for n in node.getChildNodes(): 177 if isinstance(n, compiler.ast.Global): 178 for name in n.names: 179 if not self.has_key(name): 180 self[name] = None 181 else: 182 self.process_globals(n) 183 184 def finalise_namespace(self, namespace): 185 186 "Finalise the given 'namespace'." 187 188 for names in namespace.get_all_attribute_usage(): 189 self.importer.use_names(names, namespace.full_name()) 190 191 def vacuum(self): 192 193 """ 194 Vacuum the module namespace, removing unreferenced objects and unused 195 names. 196 """ 197 198 if self.should_optimise_unused_objects(): 199 self.vacuum_object(self) 200 201 all_objects = list(self.all_objects) 202 203 for obj in all_objects: 204 if isinstance(obj, Class): 205 self.vacuum_object(obj) 206 207 def vacuum_object(self, obj, delete_all=0): 208 209 "Vacuum the given object 'obj'." 210 211 for name, attr in obj.items(): 212 213 # Only consider deleting entire unused objects or things accessible 214 # via names which are never used. 215 216 if delete_all or not self.importer.uses_attribute(obj, name): 217 del obj[name] 218 219 # Delete any unambiguous attribute value. Such values can only 220 # have been defined within the object and therefore are not 221 # redefined by other code regions. 222 223 if attr.assignments == 1: 224 value = attr.get_value() 225 226 if value is not obj and value in self.all_objects: 227 self.all_objects.remove(value) 228 229 # Delete class contents. 230 231 if isinstance(value, Class): 232 self.vacuum_object(value, 1) 233 234 def unfinalise(self): 235 236 "Reset finalised information for the module." 237 238 for obj in self.all_objects: 239 obj.unfinalise_attributes() 240 241 def finalise(self): 242 243 "Finalise the module." 244 245 for obj in self.all_objects: 246 obj.finalise_attributes() 247 248 def add_object(self, obj, any_scope=0): 249 250 """ 251 Record 'obj' if non-local or if the optional 'any_scope' is set to a 252 true value. 253 """ 254 255 if any_scope or not (self.namespaces and isinstance(self.namespaces[-1], Function)): 256 self.all_objects.add(obj) 257 258 # Optimisation tests. 259 260 def should_optimise_unused_objects(self): 261 return "unused_objects" in self.optimisations 262 263 # Namespace methods. 264 265 def in_class(self, namespaces=None): 266 namespaces = namespaces or self.namespaces 267 return len(namespaces) > 1 and isinstance(namespaces[-2], Class) 268 269 def store(self, name, obj): 270 271 "Record attribute or local 'name', storing 'obj'." 272 273 # Store in the module. 274 275 if not self.namespaces: 276 if self.used_in_scope(name, "builtins"): 277 raise InspectError("Name %r already used as a built-in." % name) 278 else: 279 self.set(name, obj, not self.in_loop) 280 281 # Or store locally. 282 283 elif self.namespaces[-1].used_in_scope(name, "global"): 284 raise InspectError("Name %r already used as global." % name) 285 elif self.namespaces[-1].used_in_scope(name, "builtins"): 286 raise InspectError("Name %r already used as a built-in." % name) 287 else: 288 self.namespaces[-1].set(name, obj, not self.in_loop) 289 290 def store_lambda(self, obj): 291 292 "Store a lambda function 'obj'." 293 294 self.add_object(obj) 295 296 def store_module_attr(self, name, module): 297 298 """ 299 Record module attribute 'name' in the given 'module' using the current 300 expression. 301 """ 302 303 module.set(name, self.expr, 0) 304 305 def store_class_attr(self, name): 306 307 """ 308 Record class attribute 'name' in the current class using the current 309 expression. 310 """ 311 312 if self.in_method and self.namespaces[-2].has_key(name): 313 self.namespaces[-2].set(name, self.expr, 0) 314 return 1 315 316 return 0 317 318 def store_instance_attr(self, name): 319 320 "Record instance attribute 'name' in the current class." 321 322 if self.in_method: 323 324 # Current namespace is the function. 325 # Previous namespace is the class. 326 327 self.namespaces[-2].add_instance_attribute(name) 328 329 def get_namespace(self): 330 331 "Return the parent (or most recent) namespace currently exposed." 332 333 return (self.namespaces[-1:] or [self])[0] 334 335 def use_name(self, name, node=None): 336 337 """ 338 Use the given 'name' within the current namespace/unit, either in 339 conjunction with a particular object (if 'node' is specified and not 340 None) or unconditionally. 341 """ 342 343 if node is not None and isinstance(node, compiler.ast.Name): 344 self.use_attribute(node.name, name) 345 346 # For general name usage, declare usage of the given name from this 347 # particular unit. 348 349 else: 350 unit = self.get_namespace() 351 self.importer.use_name(name, unit.full_name()) 352 353 # Attribute usage methods. 354 # These are convenience methods which refer to the specific namespace's 355 # implementation of these operations. 356 357 def new_branchpoint(self): 358 self.get_namespace()._new_branchpoint() 359 360 def new_branch(self, loop_node=None): 361 self.get_namespace()._new_branch(loop_node) 362 363 def abandon_branch(self): 364 self.get_namespace()._abandon_branch() 365 366 def shelve_branch(self): 367 self.get_namespace()._shelve_branch() 368 369 def merge_branches(self): 370 self.get_namespace()._merge_branches() 371 372 def define_attribute_user(self, node): 373 374 """ 375 Define 'node' as the user of attributes, indicating the point where the 376 user is defined. 377 """ 378 379 self.get_namespace()._define_attribute_user(node) 380 381 def use_attribute(self, name, attrname): 382 383 "Note usage on the attribute user 'name' of the attribute 'attrname'." 384 385 return self.get_namespace()._use_attribute(name, attrname) 386 387 def use_specific_attribute(self, objname, attrname): 388 389 """ 390 Note attribute usage specifically on 'objname' - an object which is 391 known at inspection time - or in the current unit if 'objname' is None, 392 nominating a specific attribute 'attrname'. 393 394 This bypasses attribute user mechanisms. 395 """ 396 397 from_name = self.get_namespace().full_name() 398 objname = objname or from_name 399 self.importer.use_specific_name(objname, attrname, from_name) 400 401 # Visitor methods. 402 403 def default(self, node, *args): 404 raise InspectError("Node class %r is not supported." % node.__class__) 405 406 def NOP(self, node): 407 for n in node.getChildNodes(): 408 self.dispatch(n) 409 return None 410 411 def NOP_ABANDON(self, node): 412 self.NOP(node) 413 self.abandon_branch() 414 415 def OP(self, node): 416 for n in node.getChildNodes(): 417 self.dispatch(n) 418 return Instance() 419 420 # Generic support for classes of operations. 421 422 def _visitUnary(self, node): 423 424 "Accounting method for the unary operator 'node'." 425 426 method = unary_methods[node.__class__.__name__] 427 self.use_name(method, node) 428 return self.OP(node) 429 430 def _visitBinary(self, node): 431 432 "Accounting method for the binary operator 'node'." 433 434 left_method, right_method = binary_methods[node.__class__.__name__] 435 self.use_name(left_method, node) 436 self.use_name(right_method, node) 437 return self.OP(node) 438 439 def _visitFunction(self, node, name): 440 441 """ 442 Return a function object for the function defined by 'node' with the 443 given 'name'. If a lambda expression is being visited, 'name' should be 444 None. 445 """ 446 447 # Define the function object. 448 449 function = Function( 450 name, 451 self.get_namespace(), 452 node.argnames, 453 node.defaults, 454 (node.flags & 4 != 0), 455 (node.flags & 8 != 0), 456 self.in_loop or self.in_function, 457 self, 458 node 459 ) 460 461 self.add_object(function, any_scope=1) 462 463 # Make a back reference from the node for code generation. 464 465 node.unit = function 466 467 # Process the defaults. 468 469 for n in node.defaults: 470 self.expr = self.dispatch(n) 471 function.store_default(self.expr) 472 473 self.functions.append((node, self.namespaces + [function])) 474 475 # Store the function. 476 477 if name is not None: 478 self.store(name, function) 479 else: 480 self.store_lambda(function) 481 482 # Test the defaults and assess whether an dynamic object will result. 483 484 function.make_dynamic() 485 return function 486 487 def _visitFunctionBody(self, node, namespaces): 488 489 "Enter the function." 490 491 # Current namespace is the function. 492 # Previous namespace is the class. 493 494 if self.in_class(namespaces): 495 if namespaces[-1].name == "__init__": 496 self.in_init = 1 497 self.in_method = 1 498 499 in_function = self.in_function 500 in_loop = self.in_loop 501 self.in_function = 1 502 self.in_loop = 0 503 504 self.namespaces = namespaces 505 self.dispatch(node.code) 506 507 self.in_loop = in_loop 508 self.in_function = in_function 509 self.in_init = 0 510 self.in_method = 0 511 512 # Specific handler methods. 513 514 visitAdd = _visitBinary 515 516 visitAnd = OP 517 518 visitAssert = NOP 519 520 def visitAssign(self, node): 521 self.expr = self.dispatch(node.expr) 522 for n in node.nodes: 523 self.dispatch(n) 524 return None 525 526 def visitAssAttr(self, node): 527 expr = self.dispatch(node.expr) 528 529 # Record the attribute on the presumed target. 530 531 if isinstance(expr, Attr): 532 if expr.name == "self": 533 if not self.store_class_attr(node.attrname): 534 self.store_instance_attr(node.attrname) 535 elif isinstance(expr.get_value(), Module): 536 self.store_module_attr(node.attrname, expr.get_value()) 537 print "Warning: attribute %r of module %r set outside the module." % (node.attrname, expr.get_value().name) 538 539 # Note usage of the attribute where a local is involved. 540 541 if expr.parent is self.get_namespace(): 542 node._attrusers = self.use_attribute(expr.name, node.attrname) 543 node._username = expr.name 544 545 return None 546 547 def visitAssList(self, node): 548 549 # Declare names which will be used by generated code. 550 551 self.use_name("__getitem__", node) 552 553 # Process the assignment. 554 555 for i, n in enumerate(node.nodes): 556 self.dispatch(n) 557 self.importer.make_constant(i) # for __getitem__(i) at run-time 558 return None 559 560 def visitAssName(self, node): 561 if hasattr(node, "flags") and node.flags == "OP_DELETE": 562 print "Warning: deletion of attribute %r in %r is not supported." % (node.name, self.full_name()) 563 #raise InspectError("Deletion of attribute %r is not supported." % node.name) 564 565 self.store(node.name, self.expr) 566 self.define_attribute_user(node) 567 568 # Ensure the presence of the given name in this namespace. 569 570 self.use_specific_attribute(None, node.name) 571 return None 572 573 visitAssTuple = visitAssList 574 575 def visitAugAssign(self, node): 576 577 # Accounting. 578 579 aug_method, (left_method, right_method) = augassign_methods[node.op] 580 self.use_name(aug_method, node) 581 self.use_name(left_method, node) 582 self.use_name(right_method, node) 583 584 # Process the assignment. 585 586 self.expr = self.dispatch(node.expr) 587 588 # NOTE: Similar to micropython.ast handler code. 589 # NOTE: Slices and subscripts not supported. 590 591 if isinstance(node.node, compiler.ast.Name): 592 self.visitAssName(node.node) 593 elif isinstance(node.node, compiler.ast.Getattr): 594 self.visitAssAttr(node.node) 595 else: 596 raise InspectError("AugAssign(Slice or Subscript)") 597 598 return None 599 600 visitBackquote = OP 601 602 visitBitand = _visitBinary 603 604 visitBitor = _visitBinary 605 606 visitBitxor = _visitBinary 607 608 visitBreak = NOP_ABANDON 609 610 visitCallFunc = OP 611 612 def visitClass(self, node): 613 614 """ 615 Register the class at the given 'node' subject to the restrictions 616 mentioned in the module docstring. 617 """ 618 619 if self.namespaces: 620 print "Class %r in %r is not global: ignored." % (node.name, self.namespaces[-1].full_name()) 621 return None 622 else: 623 if self.in_loop: 624 print "Warning: class %r in %r defined in a loop." % (node.name, self.full_name()) 625 626 cls = Class(node.name, self.get_namespace(), self, node) 627 628 # Visit the base class expressions, attempting to find concrete 629 # definitions of classes. 630 631 for base in node.bases: 632 expr = self.dispatch(base) 633 if isinstance(expr, Attr): 634 if expr.assignments != 1: 635 raise InspectError("Base class %r for %r is not constant." % (base, cls.full_name())) 636 else: 637 cls.add_base(expr.get_value()) 638 else: # if expr is None: 639 raise InspectError("Base class %r for %r is not found: it may be hidden in some way." % (base, cls.full_name())) 640 641 # NOTE: Potentially dubious measure to permit __init__ availability. 642 # If no bases exist, adopt the 'object' class. 643 644 if not node.bases and not (self.name == "__builtins__" and node.name == "object") : 645 expr = self.dispatch(compiler.ast.Name("object")) 646 cls.add_base(expr.get_value()) 647 648 # Make a back reference from the node for code generation. 649 650 node.unit = cls 651 652 # Make an entry for the class. 653 654 self.store(node.name, cls) 655 self.add_object(cls) 656 657 # Process the class body. 658 659 self.namespaces.append(cls) 660 self.dispatch(node.code) 661 self.finalise_namespace(cls) 662 self.namespaces.pop() 663 664 return cls 665 666 def visitCompare(self, node): 667 668 # Accounting. 669 # NOTE: Replicates some code in micropython.ast.visitCompare. 670 671 this_node = node 672 673 for op in node.ops: 674 op_name, next_node = op 675 676 # Get the applicable methods. 677 678 methods = comparison_methods[op_name] 679 680 # Define name/attribute usage. 681 682 if methods is not None: 683 self.use_name(methods[0], this_node) 684 self.use_name(methods[1], next_node) 685 elif op_name.endswith("in"): 686 self.use_name("__contains__", next_node) 687 688 this_node = next_node 689 690 return self.OP(node) 691 692 def visitConst(self, node): 693 694 # Register the constant, if necessary, returning the resulting object. 695 696 self.use_name(self.importer.get_constant_type_name(node.value), node) 697 return self.importer.make_constant(node.value) 698 699 visitContinue = NOP_ABANDON 700 701 visitDecorators = NOP 702 703 visitDict = OP 704 705 visitDiscard = NOP 706 707 visitDiv = _visitBinary 708 709 visitEllipsis = NOP 710 711 visitExec = NOP 712 713 visitExpression = OP 714 715 visitFloorDiv = _visitBinary 716 717 def visitFor(self, node): 718 self.new_branchpoint() 719 720 # Declare names which will be used by generated code. 721 722 self.use_name("__iter__", node.list) 723 self.use_name("next") 724 725 in_loop = self.in_loop 726 self.in_loop = 1 727 self.dispatch(node.assign) 728 self.dispatch(node.list) 729 730 # Enter the loop. 731 # Propagate attribute usage to branches. 732 733 self.new_branch() 734 self.dispatch(node.body) 735 self.shelve_branch() 736 self.in_loop = in_loop 737 738 # Maintain a branch for the else clause or the current retained usage 739 # where execution avoids the conditional clauses. 740 741 self.new_branch() 742 if node.else_ is not None: 743 self.dispatch(node.else_) 744 self.shelve_branch() 745 746 self.merge_branches() 747 return None 748 749 def visitFrom(self, node): 750 module = self.importer.load(node.modname, 1) 751 752 #if module is None: 753 # print "Warning:", node.modname, "not imported." 754 755 for name, alias in node.names: 756 if name != "*": 757 if module is not None and module.has_key(name): 758 attr = module[name] 759 self.store(alias or name, attr) 760 if isinstance(attr.get_value(), Module) and not attr.get_value().loaded: 761 self.importer.load(attr.get_value().name) 762 763 # Support the import of names from missing modules. 764 765 else: 766 self.store(alias or name, UnresolvedName(name, node.modname, self)) 767 else: 768 if module is not None: 769 for n in module.keys(): 770 attr = module[n] 771 self.store(n, attr) 772 if isinstance(attr.get_value(), Module) and not attr.get_value().loaded: 773 self.importer.load(attr.get_value().name) 774 775 return None 776 777 def visitFunction(self, node): 778 return self._visitFunction(node, node.name) 779 780 visitGenExpr = OP 781 782 visitGenExprFor = NOP 783 784 visitGenExprIf = NOP 785 786 visitGenExprInner = NOP 787 788 def visitGetattr(self, node): 789 expr = self.dispatch(node.expr) 790 attrname = node.attrname 791 792 # Attempt to identify the nature of the attribute. 793 794 if isinstance(expr, Attr): 795 value = expr.get_value() 796 797 # Get the attribute and record its usage. 798 799 if isinstance(value, (Class, Module)): 800 attr = value.get(attrname) 801 self.use_specific_attribute(value.full_name(), attrname) 802 803 elif isinstance(value, UnresolvedName): 804 attr = UnresolvedName(attrname, value.full_name(), self) 805 806 else: 807 attr = None 808 809 # Note usage of the attribute where a local is involved. 810 811 if expr.parent is self.get_namespace(): 812 node._attrusers = self.use_attribute(expr.name, attrname) 813 node._username = expr.name 814 else: 815 self.use_name(attrname, node.expr) 816 817 elif self.builtins is not None: 818 attr = self.builtins.get(attrname) 819 self.use_specific_attribute(self.builtins.full_name(), attrname) 820 821 else: 822 attr = UnresolvedName(attrname, value.full_name(), self) 823 824 return attr 825 826 def visitGlobal(self, node): 827 if self.namespaces: 828 for name in node.names: 829 ns = self.namespaces[-1] 830 if not ns.make_global(name): 831 raise InspectError("Name %r is global and local in %r" % (name, ns.full_name())) 832 833 # The name is recorded in an earlier process. 834 835 def visitIf(self, node): 836 self.new_branchpoint() 837 838 # Propagate attribute usage to branches. 839 840 for test, body in node.tests: 841 self.dispatch(test) 842 843 self.new_branch() 844 self.dispatch(body) 845 self.shelve_branch() 846 847 # Maintain a branch for the else clause or the current retained usage 848 # where execution avoids the conditional clauses. 849 850 self.new_branch() 851 if node.else_ is not None: 852 self.dispatch(node.else_) 853 self.shelve_branch() 854 855 self.merge_branches() 856 return None 857 858 visitIfExp = NOP 859 860 def visitImport(self, node): 861 for name, alias in node.names: 862 if alias is not None: 863 module = self.importer.load(name, 1) or UnresolvedName(None, name, self) 864 self.store(alias, module) 865 else: 866 module = self.importer.load(name) or UnresolvedName(None, name.split(".")[0], self) 867 self.store(name.split(".")[0], module) 868 869 return None 870 871 visitInvert = _visitUnary 872 873 def visitKeyword(self, node): 874 self.dispatch(node.expr) 875 self.importer.make_constant(node.name) 876 self.keyword_names.add(node.name) 877 return None 878 879 def visitLambda(self, node): 880 self.use_name(None) # lambda functions have no names but are assumed to be invoked 881 return self._visitFunction(node, None) 882 883 visitLeftShift = _visitBinary 884 885 visitList = OP 886 887 visitListComp = OP 888 889 visitListCompFor = NOP 890 891 visitListCompIf = NOP 892 893 visitMod = _visitBinary 894 895 def visitModule(self, node): 896 897 # Make a back reference from the node for code generation. 898 899 node.unit = self 900 return self.dispatch(node.node) 901 902 visitMul = _visitBinary 903 904 def visitName(self, node): 905 name = node.name 906 907 # Constants. 908 909 if self.importer.predefined_constants.has_key(name): 910 attr = self.importer.get_predefined_constant(name) 911 912 # Locals. 913 914 elif self.namespaces and self.namespaces[-1].has_key(name): 915 attr = self.namespaces[-1][name] 916 917 # Note usage of the local (potentially a class attribute). 918 919 self.use_specific_attribute(None, name) 920 921 # Globals. 922 923 elif self.has_key(name): 924 attr = self[name] 925 926 # Note usage of the module attribute. 927 928 self.use_specific_attribute(self.full_name(), name) 929 930 # Note global usage in any local namespace. 931 932 if self.namespaces: 933 if not self.namespaces[-1].note_scope(name, "global"): 934 raise InspectError("Name %r cannot be used as global." % name) 935 936 # Builtins. 937 938 elif self.builtins is not None and self.builtins.has_key(name): 939 attr = self.builtins[name] 940 self.use_specific_attribute(self.builtins.full_name(), name) 941 942 # Note builtins usage in any local namespace. 943 944 if self.namespaces: 945 if not self.namespaces[-1].note_scope(name, "builtins"): 946 raise InspectError("Name %r cannot be used as a built-in." % name) 947 else: 948 if not self.note_scope(name, "builtins"): 949 raise InspectError("Name %r cannot be used as a built-in." % name) 950 951 # Unknown. 952 953 else: 954 attr = None 955 self.use_name(name) 956 957 return attr 958 959 visitNot = OP 960 961 visitOr = OP 962 963 visitPass = NOP 964 965 visitPower = _visitBinary 966 967 visitPrint = NOP 968 969 visitPrintnl = NOP 970 971 visitRaise = NOP_ABANDON 972 973 visitReturn = NOP_ABANDON 974 975 visitRightShift = _visitBinary 976 977 visitSlice = OP 978 979 visitSliceobj = OP 980 981 def visitStmt(self, node): 982 for n in node.nodes: 983 self.dispatch(n) 984 return None 985 986 visitSub = _visitBinary 987 988 def visitSubscript(self, node): 989 self.use_name("__getitem__", node) 990 self.OP(node) 991 992 def visitTryExcept(self, node): 993 self.dispatch(node.body) 994 995 self.new_branchpoint() 996 997 for name, var, n in node.handlers: 998 self.new_branch() 999 1000 # Establish the local for the handler. 1001 1002 if var is not None: 1003 self.dispatch(var) 1004 if n is not None: 1005 self.dispatch(n) 1006 1007 self.shelve_branch() 1008 1009 if node.else_ is not None: 1010 self.new_branch() 1011 self.dispatch(node.else_) 1012 self.shelve_branch() 1013 1014 self.merge_branches() 1015 return None 1016 1017 visitTryFinally = NOP 1018 1019 visitTuple = OP 1020 1021 visitUnaryAdd = _visitUnary 1022 1023 visitUnarySub = _visitUnary 1024 1025 def visitWhile(self, node): 1026 self.new_branchpoint() 1027 1028 # Propagate attribute usage to branches. 1029 1030 in_loop = self.in_loop 1031 self.in_loop = 1 1032 self.dispatch(node.test) 1033 self.new_branch(node) 1034 self.dispatch(node.body) 1035 self.shelve_branch() 1036 self.in_loop = in_loop 1037 1038 # Maintain a branch for the else clause or the current retained usage 1039 # where execution avoids the conditional clauses. 1040 # NOTE: Consider merging here before the else clause. 1041 1042 self.new_branch() 1043 if node.else_ is not None: 1044 self.dispatch(node.else_) 1045 self.shelve_branch() 1046 1047 self.merge_branches() 1048 return None 1049 1050 visitWith = NOP 1051 1052 visitYield = NOP 1053 1054 # vim: tabstop=4 expandtab shiftwidth=4