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 * 41 import micropython.ast 42 import micropython.data 43 import micropython.opt 44 import micropython.inspect 45 import micropython.table 46 import os 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 supported_optimisations = micropython.opt.Optimiser.supported_optimisations 58 59 def __init__(self, importer, optimisations=None): 60 61 """ 62 Initialise the program representation with an 'importer' which is able 63 to locate and load Python modules. 64 65 The optional 'optimisations' cause certain techniques to be used in 66 reducing program size and improving program efficiency. 67 """ 68 69 self.importer = importer 70 self.optimisations = optimisations or set() 71 72 # Remember the tables once generated. 73 74 self.objtable = None 75 self.paramtable = None 76 77 # Main program information. 78 79 self.code = None 80 self.code_location = None 81 82 def get_importer(self): 83 return self.importer 84 85 # Access to finalised program information. 86 87 def finalise(self): 88 89 "Finalise the program." 90 91 # Need the tables to finalise. 92 93 objtable = self.get_object_table() 94 self.get_parameter_table() 95 96 self.importer.vacuum(objtable) 97 98 # Now remove unneeded things from the tables. 99 100 objtable = self.get_object_table(reset=1) 101 self.get_parameter_table(reset=1) 102 103 self.importer.finalise(objtable) 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 in ("__builtins__", "native") 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 in ("__builtins__", "native"): 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.constants_used = set() 380 self.constant_references = {} 381 self.init_predefined_constants() 382 383 # Attribute usage. 384 385 self.attributes_used = set() 386 self.name_references = {} 387 self.specific_name_references = {} 388 389 # Attribute coverage calculated during collection. 390 391 self.inferred_name_references = {} 392 393 # Attribute coverage status during collection. 394 395 self.attribute_users_visited = set() 396 self.attributes_to_visit = {} 397 398 # Status information. 399 400 self.vacuumed = 0 401 self.finalised = 0 402 403 def get_modules(self): 404 405 "Return all modules known to the importer." 406 407 return self.modules.values() 408 409 def get_module(self, name): 410 411 "Return the module with the given 'name'." 412 413 return self.modules[name] 414 415 # General maintenance. 416 417 def vacuum(self, objtable): 418 419 "Tidy up the modules." 420 421 if self.vacuumed: 422 return 423 424 # Complete the list of attribute names used in the program. 425 426 self.collect_attributes(objtable) 427 428 for name, module in self.modules.items(): 429 if module.loaded: 430 module.vacuum() 431 else: 432 del self.modules[name] 433 434 self.vacuumed = 1 435 436 def finalise(self, objtable): 437 438 "Finalise the program (which should have been vacuumed first)." 439 440 if self.finalised: 441 return 442 443 # Reset any previously compiled information. 444 445 for module in self.get_modules(): 446 module.unfinalise() 447 448 # Prepare module information again. 449 450 for module in self.get_modules(): 451 module.finalise(objtable) 452 453 self.finalised = 1 454 455 # Name accounting. 456 457 def use_name(self, name, from_name, value=None): 458 459 """ 460 Register the given 'name' as being used in the program from within an 461 object with the specified 'from_name'. If the optional 'value' is given, 462 note an assignment. 463 """ 464 465 if not self.name_references.has_key(from_name): 466 self.name_references[from_name] = set() 467 468 attrnames = ObjectSet([name]) 469 usage = (attrnames,) 470 self.name_references[from_name].add((None, None, usage)) 471 472 def use_names(self, user, name, usage, from_name): 473 474 """ 475 For the given attribute 'user' (which may be None if no specific user is 476 given), register for the given 'name' the given attribute 'usage' 477 (combinations of attribute names), noting the scope of this usage as 478 being the program object with the specified 'from_name'. 479 """ 480 481 if not self.name_references.has_key(from_name): 482 self.name_references[from_name] = set() 483 484 self.name_references[from_name].add((user, name, usage)) 485 486 def use_specific_name(self, objname, attrname, from_name): 487 488 """ 489 Register the given 'objname' (for an object) whose 'attrname' is being 490 used in the program from within an object with the specified 491 'from_name'. 492 """ 493 494 if not self.specific_name_references.has_key(from_name): 495 self.specific_name_references[from_name] = set() 496 self.specific_name_references[from_name].add((objname, attrname)) 497 498 # Name accounting products. 499 500 def uses_attribute(self, objname, name): 501 502 """ 503 Return whether the attribute of the object with the given 'objname' 504 having the given 'name' is used as an attribute in the program. 505 """ 506 507 return (objname + "." + name) in self.attributes_used 508 509 def use_attribute(self, objname, name): 510 511 """ 512 Indicate that in the object with the given 'objname', the attribute of 513 the given 'name' is used. 514 """ 515 516 self.attributes_used.add(objname + "." + name) 517 518 def use_object(self, objname): 519 520 "Indicate that the object with the given 'objname' is used." 521 522 self.attributes_used.add(objname) 523 524 def collect_attributes(self, objtable): 525 526 "Collect attribute references for the entire program." 527 528 # Include names which may not be explicitly used in programs. 529 # NOTE: Potentially declare these when inspecting. 530 531 for attrname in self.names_always_used: 532 for objname in objtable.all_possible_objects([attrname]): 533 534 # Record attributes of objects for potential visiting. 535 536 self.add_attribute_to_visit(objname, attrname) 537 538 # Visit all modules, since some may employ initialisation code which has 539 # some kind of side-effect. 540 541 for name in self.modules.keys(): 542 self._collect_attributes(name, objtable) 543 544 def add_attribute_to_visit(self, objname, attrname): 545 546 """ 547 Queue an attribute of the object with the given 'objname', having the 548 given 'attrname', to the list for potential visiting if the specified 549 object is actually referenced. 550 """ 551 552 if not self.attributes_to_visit.has_key(objname): 553 self.attributes_to_visit[objname] = set() 554 self.attributes_to_visit[objname].add(attrname) 555 556 def _collect_attributes_from(self, from_name, objname, attrname, objtable): 557 558 """ 559 Record the association between 'from_name' and the attribute of 560 'objname' with the given 'attrname'. Then collect attributes for the 561 referenced attribute using 'objtable'. 562 """ 563 564 if not self.inferred_name_references.has_key(from_name): 565 self.inferred_name_references[from_name] = set() 566 567 self.inferred_name_references[from_name].add((objname, attrname)) 568 self._collect_attributes(objname + "." + attrname, objtable) 569 570 def _collect_attributes(self, from_name, objtable): 571 572 """ 573 Given an object called 'from_name', find all names referenced from such 574 an object according to the register of names, using 'objtable' to infer 575 types. 576 """ 577 578 if from_name in self.attribute_users_visited: 579 return 580 581 self.attribute_users_visited.add(from_name) 582 583 # Get constant references. 584 585 for const in self.constant_references.get(from_name, []): 586 self.constants_used.add(const) 587 588 # The getattr function is a special case: it can potentially reference 589 # any known attribute. Since accessor attributes must be known 590 # constants, the intersection of known constants and attributes is used 591 # to build a set of objects that might be referenced by getattr. 592 593 if from_name == "__builtins__.getattr": 594 all_attributes = set(objtable.attribute_names()) 595 all_string_constants = set([const.get_value() for const in self.constants() if const.value_type_name() == "__builtins__.str"]) 596 all_attribute_constants = all_attributes.intersection(all_string_constants) 597 598 # Get the types supporting each attribute and visit the referenced 599 # objects. 600 601 all_objtypes = set() 602 603 for attrname in all_attribute_constants: 604 objtypes = objtable.any_possible_objects_plus_status([attrname]) 605 all_objtypes.update(objtypes) 606 607 # Attribute assignment does not take place, so an empty list of 608 # values is given. 609 610 self._collect_attributes_for_types(from_name, objtable, all_objtypes, 611 [{attrname : []} for attrname in all_attribute_constants]) 612 613 # Get name references and find possible objects which support such 614 # combinations of attribute names. 615 616 for user, name, usage in self.name_references.get(from_name, []): 617 618 # Using all attribute names for a particular name, attempt to get 619 # specific object types. 620 621 all_objtypes = get_object_types_for_usage(usage, objtable, name, from_name) 622 623 # Investigate the object types. 624 625 self._collect_attributes_for_types(from_name, objtable, all_objtypes, usage) 626 627 # Get specific name references and visit the referenced objects. 628 629 for objname, attrname in self.specific_name_references.get(from_name, []): 630 self.use_attribute(objname, attrname) 631 self._collect_attributes_from(from_name, objname, attrname, objtable) 632 633 # Where the object has an __init__ attribute, assume that it is an 634 # initialiser which is called at some point, and collect attributes used 635 # in this initialiser. 636 637 if "__init__" in objtable.table.get(from_name, []): 638 self.use_attribute(from_name, "__init__") 639 self._collect_attributes_from(from_name, from_name, "__init__", objtable) 640 641 # Visit attributes on this object that were queued in case of the object 642 # being referenced. 643 644 attributes_to_visit = self.attributes_to_visit.get(from_name, []) 645 646 if attributes_to_visit: 647 del self.attributes_to_visit[from_name] 648 649 for attrname in attributes_to_visit: 650 self.use_attribute(from_name, attrname) 651 self._collect_attributes_from(from_name, from_name, attrname, objtable) 652 653 def _collect_attributes_for_types(self, from_name, objtable, objtypes, usage): 654 655 """ 656 For the unit known as 'from_name' and using the 'objtable' to validate 657 each attribute, identify and attempt to visit attributes found for each 658 of the suggested object types given by 'objtypes' and the 'usage' 659 provided. 660 """ 661 662 for objname, is_static in objtypes: 663 for attrnames in usage: 664 for attrname, attrvalues in attrnames.items(): 665 666 # Test for the presence of an attribute on the suggested 667 # object type. 668 669 try: 670 attr = objtable.access(objname, attrname) 671 except TableError: 672 #print "Warning: object type %r does not support attribute %r" % (objname, attrname) 673 continue 674 675 # Get the real identity of the attribute in order to 676 # properly collect usage from it. 677 678 parent = attr.parent 679 if parent is None: 680 continue 681 elif isinstance(parent, micropython.data.Instance): 682 parentname = objname 683 else: 684 parentname = parent.full_name() 685 686 # Test for assignment. 687 688 if attrvalues: 689 690 # Instance-related accesses may involve any type 691 # supporting the attribute. 692 # NOTE: Here, an instance actually represents any kind 693 # NOTE: of object. 694 695 if isinstance(parent, micropython.data.Instance): 696 for attrvalue in attrvalues: 697 for name in objtable.any_possible_objects([attrname]): 698 parent = objtable.access(name, name) 699 if not parent.instance_attributes().has_key(attrname): 700 parent.set(attrname, attrvalue, 0) 701 else: 702 for attrvalue in attrvalues: 703 parent.set(attrname, attrvalue, 0) 704 705 # Visit attributes of objects known to be used. 706 707 if parentname in self.attributes_used: 708 self.use_attribute(parentname, attrname) 709 self._collect_attributes_from(from_name, parentname, attrname, objtable) 710 711 # Record attributes of other objects for potential visiting. 712 713 else: 714 self.add_attribute_to_visit(parentname, attrname) 715 716 # Constant accounting. 717 718 def use_constant(self, const, from_name): 719 720 """ 721 Register the given 'const' as being used in the program from within an 722 object with the specified 'from_name'. 723 """ 724 725 if not self.constant_references.has_key(from_name): 726 self.constant_references[from_name] = set() 727 728 self.constant_references[from_name].add(const) 729 730 def init_predefined_constants(self): 731 732 "Ensure the predefined constants." 733 734 for name, value in self.predefined_constants.items(): 735 self.constants_used.add(self.make_constant(value)) 736 737 def get_predefined_constant(self, name): 738 739 "Return the predefined constant for the given 'name'." 740 741 return self.make_constant(self.predefined_constants[name]) 742 743 def get_constant(self, value): 744 745 "Return a constant for the given 'value'." 746 747 const = micropython.data.Const(value) 748 return self.constant_values[const] 749 750 def get_constant_type_name(self, value): 751 752 "Return the type name for the given constant 'value'." 753 754 return value.__class__.__name__ 755 756 def make_constant(self, value): 757 758 "Make and return a constant for the given 'value'." 759 760 # Make a constant object and return it. 761 762 const = micropython.data.Const(value) 763 if not self.constant_values.has_key(const): 764 self.constant_values[const] = const 765 return self.constant_values[const] 766 767 def constants(self): 768 769 "Return a list of constants." 770 771 return self.constants_used 772 773 # Import methods. 774 775 def find_in_path(self, name): 776 777 """ 778 Find the given module 'name' in the search path, returning None where no 779 such module could be found, or a 2-tuple from the 'find' method 780 otherwise. 781 """ 782 783 for d in self.path: 784 m = self.find(d, name) 785 if m: return m 786 return None 787 788 def find(self, d, name): 789 790 """ 791 In the directory 'd', find the given module 'name', where 'name' can 792 either refer to a single file module or to a package. Return None if the 793 'name' cannot be associated with either a file or a package directory, 794 or a 2-tuple from '_find_package' or '_find_module' otherwise. 795 """ 796 797 m = self._find_package(d, name) 798 if m: return m 799 m = self._find_module(d, name) 800 if m: return m 801 return None 802 803 def _find_module(self, d, name): 804 805 """ 806 In the directory 'd', find the given module 'name', returning None where 807 no suitable file exists in the directory, or a 2-tuple consisting of 808 None (indicating that no package directory is involved) and a filename 809 indicating the location of the module. 810 """ 811 812 name_py = name + os.extsep + "py" 813 filename = self._find_file(d, name_py) 814 if filename: 815 return None, filename 816 return None 817 818 def _find_package(self, d, name): 819 820 """ 821 In the directory 'd', find the given package 'name', returning None 822 where no suitable package directory exists, or a 2-tuple consisting of 823 a directory (indicating the location of the package directory itself) 824 and a filename indicating the location of the __init__.py module which 825 declares the package's top-level contents. 826 """ 827 828 filename = self._find_file(d, name) 829 if filename: 830 init_py = "__init__" + os.path.extsep + "py" 831 init_py_filename = self._find_file(filename, init_py) 832 if init_py_filename: 833 return filename, init_py_filename 834 return None 835 836 def _find_file(self, d, filename): 837 838 """ 839 Return the filename obtained when searching the directory 'd' for the 840 given 'filename', or None if no actual file exists for the filename. 841 """ 842 843 filename = os.path.join(d, filename) 844 if os.path.exists(filename): 845 return filename 846 else: 847 return None 848 849 def load(self, name, return_leaf=0): 850 851 """ 852 Load the module or package with the given 'name'. Return an object 853 referencing the loaded module or package, or None if no such module or 854 package exists. 855 """ 856 857 if return_leaf: 858 name_for_return = name 859 else: 860 name_for_return = name.split(".")[0] 861 862 if self.modules.has_key(name) and self.modules[name].loaded: 863 #print "Cached (%s)" % name 864 return self.modules[name_for_return] 865 866 if self.verbose: 867 print "Loading", name 868 869 # Split the name into path components, and try to find the uppermost in 870 # the search path. 871 872 path = name.split(".") 873 m = self.find_in_path(path[0]) 874 if not m: 875 if self.verbose: 876 print "Not found (%s)" % path[0] 877 return None # NOTE: Import error. 878 d, filename = m 879 880 # Either acquire a reference to an already-imported module, or load the 881 # module from a file. 882 883 top = module = self.load_from_file(filename, path[0]) 884 885 # For hierarchical names, traverse each path component... 886 887 if len(path) > 1: 888 if not d: 889 if self.verbose: 890 print "No package (%s)" % filename 891 return None # NOTE: Import error (package not found). 892 else: 893 self.add_submodules(d, module) 894 895 path_so_far = path[:1] 896 for p in path[1:]: 897 path_so_far.append(p) 898 899 # Find the package or module concerned. 900 901 m = self.find(d, p) 902 if not m: 903 if self.verbose: 904 print "Not found (%s)" % p 905 return None # NOTE: Import error. 906 d, filename = m 907 module_name = ".".join(path_so_far) 908 909 # Either reference an imported module or load one from a file. 910 911 submodule = self.load_from_file(filename, module_name) 912 913 if d: 914 self.add_submodules(d, module) 915 916 # Store the submodule within its parent module. 917 918 module.set_module(p, submodule) 919 module = submodule 920 921 # Return either the deepest or the uppermost module. 922 923 if return_leaf: 924 return module 925 else: 926 return top 927 928 def load_from_file(self, name, module_name=None): 929 930 """ 931 Load the module with the given 'name' (which may be a full module path). 932 """ 933 934 if module_name is None: 935 module_name = "__main__" 936 937 module = self.add_module(module_name) 938 if not module.loaded and module not in self.loading: 939 self.loading.add(module) 940 #print "Parsing", name 941 module.parse(name) 942 #print "Done", name 943 self.loading.remove(module) 944 module.loaded = 1 945 946 # Record the module. 947 948 self.use_object(module.full_name()) 949 #print "Loaded", module_name, "with namespace", module.namespace.keys() 950 return module 951 952 def add_module(self, module_name): 953 954 """ 955 Return the module with the given 'module_name', adding a new module 956 object if one does not already exist. 957 """ 958 959 if not self.modules.has_key(module_name): 960 self.modules[module_name] = module = micropython.inspect.InspectedModule(module_name, self) 961 self.modules_ordered.append(module) 962 else: 963 module = self.modules[module_name] 964 return module 965 966 def add_submodules(self, pathname, module): 967 968 """ 969 Work around insufficient __all__ declarations and examine the directory 970 with the given 'pathname', adding submodules to the given 'module'. 971 """ 972 973 for filename in os.listdir(pathname): 974 submodule, ext = os.path.splitext(filename) 975 if ext not in ("", ".py"): 976 continue 977 module.set_module(submodule, self.add_module(module.name + "." + submodule)) 978 979 # vim: tabstop=4 expandtab shiftwidth=4