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