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