1 #!/usr/bin/env python 2 3 """ 4 The micropython package for processing Python source code. The code originates 5 from the simplify package but has had various details related to that package 6 removed. 7 8 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Paul Boddie <paul@boddie.org.uk> 9 10 This program is free software; you can redistribute it and/or modify it under 11 the terms of the GNU General Public License as published by the Free Software 12 Foundation; either version 3 of the License, or (at your option) any later 13 version. 14 15 This program is distributed in the hope that it will be useful, but WITHOUT 16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 17 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 18 details. 19 20 You should have received a copy of the GNU General Public License along with 21 this program. If not, see <http://www.gnu.org/licenses/>. 22 23 -------- 24 25 To use this module, an importer should be constructed. Here, the standard path 26 for module searching is employed: 27 28 importer = Importer(sys.path) 29 30 To generate programs, the above importer should be supplied in the 31 initialisation of a program instance, and then various methods are called: 32 33 program = Program(importer) 34 image = program.get_raw_image() 35 36 Such importer and program objects are the most convenient mechanism through 37 which the functionality of the micropython package may be accessed. 38 """ 39 40 from micropython.common import * 41 from micropython.data import * 42 from micropython.program import Location 43 import micropython.ast 44 import micropython.native 45 import micropython.opt 46 import micropython.inspect 47 import micropython.table 48 import bisect 49 import os 50 #import sys 51 52 try: 53 set 54 except NameError: 55 from sets import Set as set 56 57 class Program: 58 59 "This class supports the generation of a program image." 60 61 supported_optimisations = micropython.opt.Optimiser.supported_optimisations 62 63 def __init__(self, importer, optimisations=None): 64 65 """ 66 Initialise the program representation with an 'importer' which is able 67 to locate and load Python modules. 68 69 The optional 'optimisations' cause certain techniques to be used in 70 reducing program size and improving program efficiency. 71 """ 72 73 self.importer = importer 74 self.optimisations = optimisations or set() 75 self.native = micropython.native.NativeLibrary(self) 76 77 # Remember the tables once generated. 78 79 self.objtable = None 80 self.paramtable = None 81 82 # Main program information. 83 84 self.code = None 85 self.code_location = None 86 87 def get_importer(self): 88 return self.importer 89 90 # Access to finalised program information. 91 92 def finalise(self): 93 94 "Finalise the program." 95 96 self.importer.complete_modules() 97 98 # Need the tables to finalise. 99 100 objtable = self.get_object_table() 101 self.get_parameter_table() 102 103 self.importer.vacuum(objtable) 104 105 # Now remove unneeded things from the tables. 106 107 objtable = self.get_object_table(reset=1) 108 self.get_parameter_table(reset=1) 109 110 self.importer.finalise(objtable) 111 112 def get_image(self, with_builtins=0): 113 114 """ 115 Return the program image including built-in objects if 'with_builtins' 116 is specified and set to a true value. 117 """ 118 119 if self.code is not None: 120 return self.code 121 122 # Optimise and regenerate the object table. 123 124 self.finalise() 125 self.code = [] 126 127 # Append constants to the image. 128 129 for const in self.importer.constants(): 130 self.code.append(const) 131 132 # Generate each module. 133 134 last_module = self.importer.modules_ordered[-1] 135 136 for module in self.importer.modules_ordered: 137 suppress_builtins = not with_builtins and module.name in ("__builtins__", "native") 138 139 # Position the module in the image and make a translation. 140 141 trans = micropython.ast.Translation(module, self) 142 143 # Add header details. 144 145 self.code.append(module) 146 147 # Append module attributes to the image. 148 149 attributes = module.module_attributes() 150 self.code += module.attributes_as_list() 151 152 # Append classes and functions to the image. 153 154 for obj in module.all_objects: 155 if isinstance(obj, Class): 156 157 # Add header details. 158 159 self.code.append(obj) 160 161 # Append class attributes to the image. 162 163 attributes = obj.class_attributes() 164 self.code += obj.attributes_as_list() 165 166 # Omit built-in function code where requested. 167 168 if suppress_builtins and obj.astnode.doc is None: 169 continue 170 171 # Generate the instantiator/initialiser. 172 # Append the function code to the image. 173 174 code = trans.get_instantiator_code(obj) 175 self.code += code 176 177 # Class-level code is generated separately at the module 178 # level, and the code location is set within the code 179 # generation process for the module. 180 181 elif isinstance(obj, Function): 182 183 # Add header details. 184 185 self.code.append(obj) 186 187 # Append any default values to the image. 188 # Only do this for functions which are not dynamic. 189 190 if not obj.is_dynamic(): 191 self.code += obj.default_attrs 192 193 # Omit built-in function code where requested. 194 195 if suppress_builtins and obj.astnode.doc is None: 196 pass 197 198 # Append the function code to the image. 199 200 else: 201 code = trans.get_code(obj) 202 self.code += code 203 204 # Omit built-in module code where requested. 205 206 if suppress_builtins: 207 pass 208 209 # Append the module top-level code to the image. 210 211 else: 212 code = trans.get_module_code() 213 self.code += code 214 215 # Generate the native library once we know how much of it is used. 216 217 self.code += self.native.get_native_code() 218 219 return self.code 220 221 def get_raw_image(self, architecture=None, with_builtins=0): 222 223 "Return the raw image representation of the program." 224 225 architecture = architecture or micropython.rsvp 226 227 self.get_image(with_builtins) 228 229 objtable = self.get_object_table() 230 paramtable = self.get_parameter_table() 231 232 # Position the objects. 233 234 pos = 0 235 236 for item in self.code: 237 arch_item = architecture.get_object(item) 238 239 # Get the raw version for the architecture. 240 241 if arch_item is not None: 242 pos = arch_item.set_location(pos, objtable, with_builtins) 243 else: 244 pos += 1 245 246 # Generate the raw code. 247 248 self.raw_code = [] 249 250 for item in self.code: 251 arch_item = architecture.get_object(item) 252 253 # Get the raw version for the architecture. 254 255 if arch_item is not None: 256 self.raw_code += arch_item.as_raw(objtable, paramtable, with_builtins) 257 arch_item.finalise_location(with_builtins) 258 else: 259 self.raw_code.append(item) 260 261 # Fix the module locations. 262 263 for module in self.importer.modules_ordered: 264 265 if not with_builtins and module.name in ("__builtins__", "native"): 266 continue 267 268 module.code_location = module.blocks[0].location 269 270 self.code_location = self.importer.modules["__main__"].code_location 271 return self.raw_code 272 273 def get_object_table(self, reset=0): 274 275 "Return a table with details of attributes for classes and modules." 276 277 if self.objtable is None or reset: 278 279 t = self.objtable = micropython.table.ObjectTable() 280 281 # First, get all active modules and classes. 282 283 all_objects = set() 284 285 for module in self.importer.get_modules(): 286 all_objects.add(module) 287 for obj in module.all_objects: 288 if isinstance(obj, Class): 289 all_objects.add(obj) 290 291 # Then, visit the modules and classes. 292 293 for obj in all_objects: 294 295 # Add module attributes and module identity information. 296 297 if isinstance(obj, Module): 298 full_name = obj.full_name() 299 attributes = {"#" + full_name : obj} 300 attributes.update(obj.module_attributes()) 301 t.add(full_name, attributes) 302 303 # Add class and instance attributes for all classes, together 304 # with descendant information. 305 306 elif isinstance(obj, Class): 307 308 # Prevent ambiguous classes. 309 310 full_name = obj.full_name() 311 312 #if obj.module.has_key(name) and obj.module[name].defines_ambiguous_class(): 313 # raise TableGenerationError, "Class %r in module %r is ambiguously defined." % (name, obj.module.full_name()) 314 315 # Define a table entry for the class. 316 317 attributes = {"#" + full_name : obj} 318 attributes.update(obj.all_attributes()) 319 320 # Filter out unused classes. 321 322 for name, descendant in obj.all_descendants().items(): 323 if descendant in all_objects: 324 attributes["#" + name] = descendant 325 326 t.add(full_name, attributes) 327 328 return self.objtable 329 330 def get_parameter_table(self, reset=0): 331 332 "Return a table with details of parameters for functions and methods." 333 334 # Need the object table to get at class details. 335 336 if self.paramtable is None or reset: 337 t = self.paramtable = micropython.table.ParameterTable() 338 339 # Visit each module, getting function and method details. 340 341 for module in self.importer.get_modules(): 342 for obj in module.all_objects: 343 if isinstance(obj, Function): 344 t.add(obj.full_name(), obj.parameters()) 345 346 # Classes are callable, too. 347 # Take details of the appropriate __init__ method to make an 348 # entry for an instantiation function for the class. 349 350 elif isinstance(obj, Class): 351 t.add(obj.get_instantiator().full_name(), obj.get_instantiator().parameters()) 352 353 # Filter out all parameter table entries not referenced by keyword 354 # arguments. 355 356 keyword_names = set() 357 358 for module in self.importer.get_modules(): 359 keyword_names.update(module.keyword_names) 360 361 for function_name, parameters in t.table.items(): 362 for name in parameters.keys(): 363 if name in keyword_names: 364 break 365 else: 366 del t.table[function_name] 367 368 return self.paramtable 369 370 def object_at(self, pos): 371 372 "Return the object whose code can be found at 'pos'." 373 374 i = bisect.bisect_left(self.code, Location(pos)) 375 if i > 0: 376 return self.code[i-1] 377 else: 378 return None 379 380 class Importer: 381 382 "An import machine, searching for and loading modules." 383 384 predefined_constants = { 385 "None" : None, 386 "True" : True, 387 "False" : False, 388 #"Ellipsis" : Ellipsis, 389 "NotImplemented" : NotImplemented 390 } 391 392 names_always_used = [ 393 "__call__" 394 ] 395 396 def __init__(self, path=None, verbose=0, optimisations=None): 397 398 """ 399 Initialise the importer with the given search 'path' - a list of 400 directories to search for Python modules. 401 402 The optional 'verbose' parameter causes output concerning the activities 403 of the object to be produced if set to a true value (not the default). 404 405 The optional 'optimisations' cause certain techniques to be used in 406 reducing program size and improving program efficiency. 407 """ 408 409 self.path = path or [os.getcwd()] 410 self.verbose = verbose 411 self.optimisations = optimisations or set() 412 413 self.modules = {} 414 self.modules_ordered = [] 415 self.loading = set() 416 417 # Constant records. 418 419 self.constant_values = {} 420 self.constants_used = set() 421 self.constant_references = {} 422 self.init_predefined_constants() 423 424 # Attribute usage. 425 426 self.attributes_used = set() 427 self.name_references = {} 428 self.specific_name_references = {} 429 430 # Attribute coverage calculated during collection. 431 432 self.inferred_name_references = {} 433 434 # Attribute coverage status during collection. 435 436 self.attribute_users_visited = set() 437 self.attributes_to_visit = {} 438 439 # Status information. 440 441 self.completed = 0 442 self.vacuumed = 0 443 self.finalised = 0 444 445 def get_modules(self): 446 447 "Return all modules known to the importer." 448 449 return self.modules.values() 450 451 def get_module(self, name): 452 453 "Return the module with the given 'name'." 454 455 return self.modules[name] 456 457 def complete_modules(self): 458 459 "Complete the processing of modules." 460 461 if self.completed: 462 return 463 464 processed = set() 465 modules = self.get_modules() 466 467 while len(processed) != len(modules): 468 for module in modules: 469 if module in processed: 470 continue 471 if self.verbose: 472 print >>sys.stderr, "Completing", module.full_name() 473 module.process_functions() 474 processed.add(module) 475 modules = self.get_modules() 476 477 self.completed = 1 478 479 # General maintenance. 480 481 def vacuum(self, objtable): 482 483 "Tidy up the modules." 484 485 if self.vacuumed: 486 return 487 488 # Complete the list of attribute names used in the program. 489 490 self.collect_attributes(objtable) 491 492 for name, module in self.modules.items(): 493 if module.loaded: 494 module.vacuum() 495 else: 496 del self.modules[name] 497 498 self.vacuumed = 1 499 500 def finalise(self, objtable): 501 502 "Finalise the program (which should have been vacuumed first)." 503 504 if self.finalised: 505 return 506 507 # Reset any previously compiled information. 508 509 for module in self.get_modules(): 510 module.unfinalise() 511 512 # Prepare module information again. 513 514 for module in self.get_modules(): 515 module.finalise(objtable) 516 517 self.finalised = 1 518 519 # Name accounting. 520 521 def use_name(self, name, from_name, value=None): 522 523 """ 524 Register the given 'name' as being used in the program from within an 525 object with the specified 'from_name'. If the optional 'value' is given, 526 note an assignment. 527 """ 528 529 if not self.name_references.has_key(from_name): 530 self.name_references[from_name] = set() 531 532 attrnames = ObjectSet([name]) 533 usage = (attrnames,) 534 self.name_references[from_name].add((None, None, usage)) 535 536 def use_names(self, user, name, usage, from_name): 537 538 """ 539 For the given attribute 'user' (which may be None if no specific user is 540 given), register for the given 'name' the given attribute 'usage' 541 (combinations of attribute names), noting the scope of this usage as 542 being the program object with the specified 'from_name'. 543 """ 544 545 if not self.name_references.has_key(from_name): 546 self.name_references[from_name] = set() 547 548 self.name_references[from_name].add((user, name, usage)) 549 550 def use_specific_name(self, objname, attrname, from_name): 551 552 """ 553 Register the given 'objname' (for an object) whose 'attrname' is being 554 used in the program from within an object with the specified 555 'from_name'. 556 """ 557 558 if not self.specific_name_references.has_key(from_name): 559 self.specific_name_references[from_name] = set() 560 self.specific_name_references[from_name].add((objname, attrname)) 561 562 # Name accounting products. 563 564 def uses_attribute(self, objname, name): 565 566 """ 567 Return whether the attribute of the object with the given 'objname' 568 having the given 'name' is used as an attribute in the program. 569 """ 570 571 return (objname + "." + name) in self.attributes_used 572 573 def use_attribute(self, objname, name): 574 575 """ 576 Indicate that in the object with the given 'objname', the attribute of 577 the given 'name' is used. 578 """ 579 580 self.attributes_used.add(objname + "." + name) 581 582 def use_object(self, objname): 583 584 "Indicate that the object with the given 'objname' is used." 585 586 self.attributes_used.add(objname) 587 588 def collect_attributes(self, objtable): 589 590 "Collect attribute references for the entire program." 591 592 # Include names which may not be explicitly used in programs. 593 # NOTE: Potentially declare these when inspecting. 594 595 for attrname in self.names_always_used: 596 for objname in objtable.all_possible_objects([attrname]): 597 598 # Record attributes of objects for potential visiting. 599 600 self.add_attribute_to_visit(objname, attrname) 601 602 # Visit all modules, since some may employ initialisation code which has 603 # some kind of side-effect. 604 605 for name in self.modules.keys(): 606 self._collect_attributes(name, objtable) 607 608 def add_attribute_to_visit(self, objname, attrname): 609 610 """ 611 Queue an attribute of the object with the given 'objname', having the 612 given 'attrname', to the list for potential visiting if the specified 613 object is actually referenced. 614 """ 615 616 if not self.attributes_to_visit.has_key(objname): 617 self.attributes_to_visit[objname] = set() 618 self.attributes_to_visit[objname].add(attrname) 619 620 def _collect_attributes_from(self, from_name, objname, attrname, objtable): 621 622 """ 623 Record the association between 'from_name' and the attribute of 624 'objname' with the given 'attrname'. Then collect attributes for the 625 referenced attribute using 'objtable'. 626 """ 627 628 if not self.inferred_name_references.has_key(from_name): 629 self.inferred_name_references[from_name] = set() 630 631 self.inferred_name_references[from_name].add((objname, attrname)) 632 self._collect_attributes(objname + "." + attrname, objtable) 633 634 def _collect_attributes(self, from_name, objtable): 635 636 """ 637 Given an object called 'from_name', find all names referenced from such 638 an object according to the register of names, using 'objtable' to infer 639 types. 640 """ 641 642 if from_name in self.attribute_users_visited: 643 return 644 645 self.attribute_users_visited.add(from_name) 646 647 # Get constant references. 648 649 for const in self.constant_references.get(from_name, []): 650 self.constants_used.add(const) 651 652 # The getattr function is a special case: it can potentially reference 653 # any known attribute. Since accessor attributes must be known 654 # constants, the intersection of known constants and attributes is used 655 # to build a set of objects that might be referenced by getattr. 656 657 if from_name == "__builtins__.getattr": 658 all_attributes = set(objtable.attribute_names()) 659 all_string_constants = set([const.get_value() for const in self.constants() if const.value_type_name() == "__builtins__.str"]) 660 all_attribute_constants = all_attributes.intersection(all_string_constants) 661 662 # Get the types supporting each attribute and visit the referenced 663 # objects. 664 665 all_objtypes = set() 666 667 for attrname in all_attribute_constants: 668 objtypes = objtable.any_possible_objects_plus_status([attrname]) 669 all_objtypes.update(objtypes) 670 671 # Attribute assignment does not take place, so an empty list of 672 # values is given. 673 674 self._collect_attributes_for_types(from_name, objtable, all_objtypes, 675 [{attrname : []} for attrname in all_attribute_constants]) 676 677 # Get name references and find possible objects which support such 678 # combinations of attribute names. 679 680 for user, name, usage in self.name_references.get(from_name, []): 681 682 # Using all attribute names for a particular name, attempt to get 683 # specific object types. 684 685 all_objtypes = get_object_types_for_usage(usage, objtable, name, from_name, True) 686 if not all_objtypes: 687 all_objtypes = get_object_types_for_usage(usage, objtable, name, from_name, False) 688 689 # Where the name through which the attributes are accessed is the 690 # special "self" name, restrict the possibilities to types 691 # appropriate for the method involved. 692 693 if name == "self" and user and user.unit and user.unit.is_method(): 694 cls = user.unit.parent 695 valid_objtypes = filter_using_self(all_objtypes, cls) 696 else: 697 valid_objtypes = all_objtypes 698 699 # Investigate the object types. 700 701 self._collect_attributes_for_types(from_name, objtable, valid_objtypes, usage) 702 703 # Get specific name references and visit the referenced objects. 704 705 for objname, attrname in self.specific_name_references.get(from_name, []): 706 self.use_attribute(objname, attrname) 707 self._collect_attributes_from(from_name, objname, attrname, objtable) 708 709 # Where the object has an __init__ attribute, assume that it is an 710 # initialiser which is called at some point, and collect attributes used 711 # in this initialiser. 712 713 if "__init__" in objtable.table.get(from_name, []): 714 self.use_attribute(from_name, "__init__") 715 self._collect_attributes_from(from_name, from_name, "__init__", objtable) 716 717 # Visit attributes on this object that were queued in case of the object 718 # being referenced. 719 720 attributes_to_visit = self.attributes_to_visit.get(from_name, []) 721 722 if attributes_to_visit: 723 del self.attributes_to_visit[from_name] 724 725 for attrname in attributes_to_visit: 726 self.use_attribute(from_name, attrname) 727 self._collect_attributes_from(from_name, from_name, attrname, objtable) 728 729 def _collect_attributes_for_types(self, from_name, objtable, objtypes, usage): 730 731 """ 732 For the unit known as 'from_name' and using the 'objtable' to validate 733 each attribute, identify and attempt to visit attributes found for each 734 of the suggested object types given by 'objtypes' and the 'usage' 735 provided. 736 """ 737 738 for objname, is_static in objtypes: 739 for attrnames in usage: 740 for attrname, attrvalues in attrnames.items(): 741 742 # Test for the presence of an attribute on the suggested 743 # object type. 744 745 try: 746 attr = objtable.access(objname, attrname) 747 except TableError: 748 #print >>sys.stderr, "Warning: object type %r does not support attribute %r" % (objname, attrname) 749 continue 750 751 # Get the real identity of the attribute in order to 752 # properly collect usage from it. 753 754 parent = attr.parent 755 756 # NOTE: At this point, parent should never be None. 757 758 if parent is None: 759 continue 760 761 # Instances provide the same identity as the object name. 762 763 elif isinstance(parent, Instance): 764 parentname = objname 765 766 # In general, the fully qualified name is obtained. 767 768 else: 769 parentname = parent.full_name() 770 771 # Test for assignment. 772 773 if attrvalues: 774 775 # NOTE: Here, an instance can actually represent any 776 # NOTE: kind of object. 777 778 if isinstance(parent, Instance): 779 780 # Get the parent object using the special 781 # table entry. 782 783 parent = objtable.get_object(objname) 784 785 # Permit assignment to known instance attributes 786 # only. 787 788 if not (isinstance(parent, Class) and 789 parent.instance_attributes().has_key(attrname)): 790 791 print >>sys.stderr, "Warning: potential assignment to instance attribute %s of %s not permitted" % ( 792 attrname, parent.full_name()) 793 794 # Assignment to a known attribute is permitted. 795 796 elif parent.has_key(attrname): 797 for attrvalue in attrvalues: 798 parent.set(attrname, attrvalue, 0) 799 800 # Assignment to an unknown attribute is not permitted. 801 802 else: 803 print >>sys.stderr, "Warning: potential assignment to static attribute %s of %s not permitted" % ( 804 attrname, parent.full_name()) 805 806 # Visit attributes of objects known to be used. 807 808 if parentname in self.attributes_used: 809 self.use_attribute(parentname, attrname) 810 self._collect_attributes_from(from_name, parentname, attrname, objtable) 811 812 # Record attributes of other objects for potential visiting. 813 814 else: 815 self.add_attribute_to_visit(parentname, attrname) 816 817 # Constant accounting. 818 819 def use_constant(self, const, from_name): 820 821 """ 822 Register the given 'const' as being used in the program from within an 823 object with the specified 'from_name'. 824 """ 825 826 if not self.constant_references.has_key(from_name): 827 self.constant_references[from_name] = set() 828 829 self.constant_references[from_name].add(const) 830 831 def init_predefined_constants(self): 832 833 "Ensure the predefined constants." 834 835 for name, value in self.predefined_constants.items(): 836 self.constants_used.add(self.make_constant(value)) 837 838 def get_predefined_constant(self, name): 839 840 "Return the predefined constant for the given 'name'." 841 842 return self.make_constant(self.predefined_constants[name]) 843 844 def get_constant(self, value): 845 846 "Return a constant for the given 'value'." 847 848 const = Const(value) 849 return self.constant_values[const] 850 851 def get_constant_type_name(self, value): 852 853 "Return the type name for the given constant 'value'." 854 855 return value.__class__.__name__ 856 857 def make_constant(self, value): 858 859 "Make and return a constant for the given 'value'." 860 861 # Make a constant object and return it. 862 863 const = Const(value) 864 if not self.constant_values.has_key(const): 865 self.constant_values[const] = const 866 return self.constant_values[const] 867 868 def constants(self): 869 870 "Return a list of constants." 871 872 return self.constants_used 873 874 # Import methods. 875 876 def find_in_path(self, name): 877 878 """ 879 Find the given module 'name' in the search path, returning None where no 880 such module could be found, or a 2-tuple from the 'find' method 881 otherwise. 882 """ 883 884 for d in self.path: 885 m = self.find(d, name) 886 if m: return m 887 return None 888 889 def find(self, d, name): 890 891 """ 892 In the directory 'd', find the given module 'name', where 'name' can 893 either refer to a single file module or to a package. Return None if the 894 'name' cannot be associated with either a file or a package directory, 895 or a 2-tuple from '_find_package' or '_find_module' otherwise. 896 """ 897 898 m = self._find_package(d, name) 899 if m: return m 900 m = self._find_module(d, name) 901 if m: return m 902 return None 903 904 def _find_module(self, d, name): 905 906 """ 907 In the directory 'd', find the given module 'name', returning None where 908 no suitable file exists in the directory, or a 2-tuple consisting of 909 None (indicating that no package directory is involved) and a filename 910 indicating the location of the module. 911 """ 912 913 name_py = name + os.extsep + "py" 914 filename = self._find_file(d, name_py) 915 if filename: 916 return None, filename 917 return None 918 919 def _find_package(self, d, name): 920 921 """ 922 In the directory 'd', find the given package 'name', returning None 923 where no suitable package directory exists, or a 2-tuple consisting of 924 a directory (indicating the location of the package directory itself) 925 and a filename indicating the location of the __init__.py module which 926 declares the package's top-level contents. 927 """ 928 929 filename = self._find_file(d, name) 930 if filename: 931 init_py = "__init__" + os.path.extsep + "py" 932 init_py_filename = self._find_file(filename, init_py) 933 if init_py_filename: 934 return filename, init_py_filename 935 return None 936 937 def _find_file(self, d, filename): 938 939 """ 940 Return the filename obtained when searching the directory 'd' for the 941 given 'filename', or None if no actual file exists for the filename. 942 """ 943 944 filename = os.path.join(d, filename) 945 if os.path.exists(filename): 946 return filename 947 else: 948 return None 949 950 def load(self, name, return_leaf=0): 951 952 """ 953 Load the module or package with the given 'name'. Return an object 954 referencing the loaded module or package, or None if no such module or 955 package exists. 956 """ 957 958 if return_leaf: 959 name_for_return = name 960 else: 961 name_for_return = name.split(".")[0] 962 963 if self.modules.has_key(name) and self.modules[name].loaded: 964 #print >>sys.stderr, "Cached (%s)" % name 965 return self.modules[name_for_return] 966 967 if self.verbose: 968 print >>sys.stderr, "Loading", name 969 970 # Split the name into path components, and try to find the uppermost in 971 # the search path. 972 973 path = name.split(".") 974 m = self.find_in_path(path[0]) 975 if not m: 976 if self.verbose: 977 print >>sys.stderr, "Not found (%s)" % path[0] 978 return None # NOTE: Import error. 979 d, filename = m 980 981 # Either acquire a reference to an already-imported module, or load the 982 # module from a file. 983 984 top = module = self.load_from_file(filename, path[0]) 985 986 # For hierarchical names, traverse each path component... 987 988 if len(path) > 1: 989 if not d: 990 if self.verbose: 991 print >>sys.stderr, "No package (%s)" % filename 992 return None # NOTE: Import error (package not found). 993 else: 994 self.add_submodules(d, module) 995 996 path_so_far = path[:1] 997 for p in path[1:]: 998 path_so_far.append(p) 999 1000 # Find the package or module concerned. 1001 1002 m = self.find(d, p) 1003 if not m: 1004 if self.verbose: 1005 print >>sys.stderr, "Not found (%s)" % p 1006 return None # NOTE: Import error. 1007 d, filename = m 1008 module_name = ".".join(path_so_far) 1009 1010 # Either reference an imported module or load one from a file. 1011 1012 submodule = self.load_from_file(filename, module_name) 1013 1014 if d: 1015 self.add_submodules(d, module) 1016 1017 # Store the submodule within its parent module. 1018 1019 module.set_module(p, submodule) 1020 module = submodule 1021 1022 # Stop descending if no package was found. 1023 1024 if not d: 1025 break 1026 1027 # Return either the deepest or the uppermost module. 1028 1029 if return_leaf: 1030 return module 1031 else: 1032 return top 1033 1034 def load_from_file(self, name, module_name=None): 1035 1036 """ 1037 Load the module with the given 'name' (which may be a full module path). 1038 """ 1039 1040 if module_name is None: 1041 module_name = "__main__" 1042 1043 module = self.add_module(module_name) 1044 if not module.loaded and module not in self.loading: 1045 self.loading.add(module) 1046 if self.verbose: 1047 print >>sys.stderr, "Parsing", name 1048 module.parse(name) 1049 if self.verbose: 1050 print >>sys.stderr, "Loaded", name 1051 self.loading.remove(module) 1052 module.loaded = 1 1053 1054 # Record the module. 1055 1056 self.use_object(module.full_name()) 1057 #print >>sys.stderr, "Loaded", module_name, "with namespace", module.namespace.keys() 1058 return module 1059 1060 def add_module(self, module_name): 1061 1062 """ 1063 Return the module with the given 'module_name', adding a new module 1064 object if one does not already exist. 1065 """ 1066 1067 if not self.modules.has_key(module_name): 1068 self.modules[module_name] = module = micropython.inspect.InspectedModule(module_name, self) 1069 self.modules_ordered.append(module) 1070 else: 1071 module = self.modules[module_name] 1072 return module 1073 1074 def add_submodules(self, pathname, module): 1075 1076 """ 1077 Work around insufficient __all__ declarations and examine the directory 1078 with the given 'pathname', adding submodules to the given 'module'. 1079 """ 1080 1081 for filename in os.listdir(pathname): 1082 submodule, ext = os.path.splitext(filename) 1083 if ext not in ("", ".py"): 1084 continue 1085 module.set_module(submodule, self.add_module(module.name + "." + submodule)) 1086 1087 # vim: tabstop=4 expandtab shiftwidth=4