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