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