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