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