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