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