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