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