1 #!/usr/bin/env python 2 3 """ 4 Import logic. 5 6 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 7 2014, 2015, 2016 Paul Boddie <paul@boddie.org.uk> 8 9 This program is free software; you can redistribute it and/or modify it under 10 the terms of the GNU General Public License as published by the Free Software 11 Foundation; either version 3 of the License, or (at your option) any later 12 version. 13 14 This program is distributed in the hope that it will be useful, but WITHOUT 15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 17 details. 18 19 You should have received a copy of the GNU General Public License along with 20 this program. If not, see <http://www.gnu.org/licenses/>. 21 """ 22 23 from errors import ProgramError 24 from os.path import exists, extsep, getmtime, join 25 from os import listdir, makedirs, remove 26 from common import init_item, readfile, writefile 27 from modules import CachedModule 28 from referencing import Reference 29 import inspector 30 import sys 31 32 class Importer: 33 34 "An import machine, searching for and loading modules." 35 36 def __init__(self, path, cache=None, verbose=False): 37 38 """ 39 Initialise the importer with the given search 'path' - a list of 40 directories to search for Python modules. 41 42 The optional 'cache' should be the name of a directory used to store 43 cached module information. 44 45 The optional 'verbose' parameter causes output concerning the activities 46 of the object to be produced if set to a true value (not the default). 47 """ 48 49 self.path = path 50 self.cache = cache 51 self.verbose = verbose 52 53 # Module importing queue, required modules, removed modules and active 54 # modules in the final program. 55 56 self.to_import = set() 57 self.required = set(["__main__"]) 58 self.removed = {} 59 self.modules = {} 60 61 # Module relationships and invalidated cached modules. 62 63 self.accessing_modules = {} 64 self.invalidated = set() 65 66 # Object relationships and dependencies. 67 68 self.depends = {} 69 self.module_depends = {} 70 71 # Basic program information. 72 73 self.objects = {} 74 self.classes = {} 75 self.function_parameters = {} 76 self.function_defaults = {} 77 self.function_locals = {} 78 self.function_targets = {} 79 self.function_arguments = {} 80 81 # Unresolved names. 82 83 self.missing = set() 84 85 # Derived information. 86 87 self.subclasses = {} 88 89 # Attributes of different object types. 90 91 self.all_class_attrs = {} 92 self.all_instance_attrs = {} 93 self.all_instance_attr_constants = {} 94 self.all_combined_attrs = {} 95 self.all_module_attrs = {} 96 self.all_shadowed_attrs = {} 97 98 # References to external names and aliases within program units. 99 100 self.all_name_references = {} 101 self.all_initialised_names = {} 102 self.all_aliased_names = {} 103 104 # General attribute accesses. 105 106 self.all_attr_accesses = {} 107 self.all_const_accesses = {} 108 self.all_attr_access_modifiers = {} 109 110 # Constant literals and values. 111 112 self.all_constants = {} 113 self.all_constant_values = {} 114 115 self.make_cache() 116 117 def make_cache(self): 118 if self.cache and not exists(self.cache): 119 makedirs(self.cache) 120 121 def check_cache(self, details): 122 123 """ 124 Check whether the cache applies for the given 'details', invalidating it 125 if it does not. 126 """ 127 128 recorded_details = self.get_cache_details() 129 130 if recorded_details != details: 131 self.remove_cache() 132 133 writefile(self.get_cache_details_filename(), details) 134 135 def get_cache_details_filename(self): 136 137 "Return the filename for the cache details." 138 139 return join(self.cache, "$details") 140 141 def get_cache_details(self): 142 143 "Return details of the cache." 144 145 details_filename = self.get_cache_details_filename() 146 147 if not exists(details_filename): 148 return None 149 else: 150 return readfile(details_filename) 151 152 def remove_cache(self): 153 154 "Remove the contents of the cache." 155 156 for filename in listdir(self.cache): 157 remove(join(self.cache, filename)) 158 159 def to_cache(self): 160 161 "Write modules to the cache." 162 163 if self.cache: 164 for module_name, module in self.modules.items(): 165 module.to_cache(join(self.cache, module_name)) 166 167 # Object retrieval and storage. 168 169 def get_object(self, name): 170 171 """ 172 Return a reference for the given 'name' or None if no such object 173 exists. 174 """ 175 176 return self.objects.get(name) 177 178 def set_object(self, name, value=None): 179 180 "Set the object with the given 'name' and the given 'value'." 181 182 if isinstance(value, Reference): 183 ref = value.alias(name) 184 else: 185 ref = Reference(value, name) 186 187 self.objects[name] = ref 188 189 # Identification of both stored object names and name references. 190 191 def identify(self, name): 192 193 "Identify 'name' using stored object and external name records." 194 195 return self.objects.get(name) or self.all_name_references.get(name) 196 197 # Indirect object retrieval. 198 199 def get_attributes(self, ref, attrname): 200 201 """ 202 Return attributes provided by 'ref' for 'attrname'. Class attributes 203 may be provided by instances. 204 """ 205 206 kind = ref.get_kind() 207 if kind == "<class>": 208 ref = self.get_class_attribute(ref.get_origin(), attrname) 209 return ref and set([ref]) or set() 210 elif kind == "<instance>": 211 return self.get_combined_attributes(ref.get_origin(), attrname) 212 elif kind == "<module>": 213 ref = self.get_module_attribute(ref.get_origin(), attrname) 214 return ref and set([ref]) or set() 215 else: 216 return set() 217 218 def get_class_attribute(self, object_type, attrname): 219 220 "Return from 'object_type' the details of class attribute 'attrname'." 221 222 attrs = self.all_class_attrs.get(object_type) 223 attr = attrs and attrs.get(attrname) 224 return attr and self.get_object(attr) 225 226 def get_instance_attributes(self, object_type, attrname): 227 228 """ 229 Return from 'object_type' the details of instance attribute 'attrname'. 230 """ 231 232 consts = self.all_instance_attr_constants.get(object_type) 233 attrs = set() 234 for attr in self.all_instance_attrs[object_type].get(attrname, []): 235 attrs.add(consts and consts.get(attrname) or Reference("<var>", attr)) 236 return attrs 237 238 def get_combined_attributes(self, object_type, attrname): 239 240 """ 241 Return from 'object_type' the details of class or instance attribute 242 'attrname'. 243 """ 244 245 ref = self.get_class_attribute(object_type, attrname) 246 refs = ref and set([ref]) or set() 247 refs.update(self.get_instance_attributes(object_type, attrname)) 248 return refs 249 250 def get_module_attribute(self, object_type, attrname): 251 252 "Return from 'object_type' the details of module attribute 'attrname'." 253 254 if attrname in self.all_module_attrs[object_type]: 255 return self.get_object("%s.%s" % (object_type, attrname)) 256 else: 257 return None 258 259 # Convenience methods for deducing which kind of object provided an 260 # attribute. 261 262 def get_attribute_provider(self, ref, attrname): 263 264 """ 265 Return the kind of provider of the attribute accessed via 'ref' using 266 'attrname'. 267 """ 268 269 kind = ref.get_kind() 270 271 if kind in ["<class>", "<module>"]: 272 return kind 273 else: 274 return self.get_instance_attribute_provider(ref.get_origin(), attrname) 275 276 def get_instance_attribute_provider(self, object_type, attrname): 277 278 """ 279 Return the kind of provider of the attribute accessed via an instance of 280 'object_type' using 'attrname'. 281 """ 282 283 if self.get_class_attribute(object_type, attrname): 284 return "<class>" 285 else: 286 return "<instance>" 287 288 # Module management. 289 290 def queue_module(self, name, accessor, required=False): 291 292 """ 293 Queue the module with the given 'name' for import from the given 294 'accessor' module. If 'required' is true (it is false by default), the 295 module will be required in the final program. 296 """ 297 298 if not self.modules.has_key(name): 299 self.to_import.add(name) 300 301 if required: 302 self.required.add(name) 303 304 init_item(self.accessing_modules, name, set) 305 self.accessing_modules[name].add(accessor.name) 306 307 def get_modules(self): 308 309 "Return all modules known to the importer." 310 311 return self.modules.values() 312 313 def get_module(self, name): 314 315 "Return the module with the given 'name'." 316 317 if not self.modules.has_key(name): 318 return None 319 320 return self.modules[name] 321 322 # Program operations. 323 324 def initialise(self, filename, reset=False): 325 326 """ 327 Initialise a program whose main module is 'filename', resetting the 328 cache if 'reset' is true. Return the main module. 329 """ 330 331 if reset: 332 self.remove_cache() 333 self.check_cache(filename) 334 335 # Load the program itself. 336 337 m = self.load_from_file(filename) 338 339 # Load any queued modules. 340 341 while self.to_import: 342 for name in list(self.to_import): # avoid mutation issue 343 self.load(name) 344 345 # Resolve dependencies between modules. 346 347 self.resolve() 348 349 # Record the type of all classes. 350 351 self.type_ref = self.get_object("__builtins__.type") 352 353 # Resolve dependencies within the program. 354 355 for module in self.modules.values(): 356 module.complete() 357 358 # Remove unneeded modules. 359 360 all_modules = self.modules.items() 361 362 for name, module in all_modules: 363 if name not in self.required: 364 module.unpropagate() 365 del self.modules[name] 366 self.removed[name] = module 367 368 # Collect redundant objects. 369 370 for module in self.removed.values(): 371 module.collect() 372 373 # Assert module objects where aliases have been removed. 374 375 for name in self.required: 376 if not self.objects.has_key(name): 377 self.objects[name] = Reference("<module>", name) 378 379 return m 380 381 def finalise(self): 382 383 """ 384 Finalise the inspected program, returning whether the program could be 385 finalised. 386 """ 387 388 self.finalise_classes() 389 self.add_init_dependencies() 390 self.to_cache() 391 392 if self.missing: 393 return False 394 395 self.set_class_types() 396 self.define_instantiators() 397 self.collect_constants() 398 399 return True 400 401 # Supporting operations. 402 403 def resolve(self): 404 405 "Resolve dependencies between modules." 406 407 self.waiting = {} 408 409 for module in self.modules.values(): 410 411 # Resolve all deferred references in each module. 412 413 original_deferred = [] 414 415 for ref in module.deferred: 416 417 # Retain original references for caching. 418 419 original_deferred.append(ref.copy()) 420 421 # Update references throughout the program. 422 423 found = self.find_dependency(ref) 424 if not found: 425 self.missing.add((module.name, ref.get_origin())) 426 427 # Record the resolved names and identify required modules. 428 429 else: 430 # Find the providing module of this reference. 431 # Where definitive details of the origin cannot be found, 432 # identify the provider using the deferred reference. 433 # NOTE: This may need to test for static origins. 434 435 provider = self.get_module_provider(found.unresolved() and ref or found) 436 ref.mutate(found) 437 438 # Record any external dependency. 439 440 if provider and provider != module.name: 441 442 # Record the provider dependency. 443 444 module.required.add(provider) 445 self.accessing_modules[provider].add(module.name) 446 447 # Postpone any inclusion of the provider until this 448 # module becomes required. 449 450 if module.name not in self.required: 451 init_item(self.waiting, module.name, set) 452 self.waiting[module.name].add(provider) 453 if self.verbose: 454 print >>sys.stderr, "Noting", provider, "for", ref, "from", module.name 455 456 # Make this module required in the accessing module. 457 458 elif provider not in self.required: 459 self.required.add(provider) 460 if self.verbose: 461 print >>sys.stderr, "Requiring", provider, "for", ref, "from", module.name 462 463 # Record a module ordering dependency. 464 465 if not found.static(): 466 self.add_module_dependency(module.name, provider) 467 468 # Restore the original references so that they may be read back in 469 # and produce the same results. 470 471 module.deferred = original_deferred 472 473 # Check modules again to see if they are now required and should now 474 # cause the inclusion of other modules providing objects to the program. 475 476 for module_name in self.waiting.keys(): 477 self.require_providers(module_name) 478 479 self.add_special_dependencies() 480 self.add_module_dependencies() 481 482 def require_providers(self, module_name): 483 484 """ 485 Test if 'module_name' is itself required and, if so, require modules 486 containing objects provided to the module. 487 """ 488 489 if module_name in self.required and self.waiting.has_key(module_name): 490 for provider in self.waiting[module_name]: 491 if provider not in self.required: 492 self.required.add(provider) 493 if self.verbose: 494 print >>sys.stderr, "Requiring", provider 495 self.require_providers(provider) 496 497 def add_special_dependencies(self): 498 499 "Add dependencies due to the use of special names in namespaces." 500 501 for module in self.modules.values(): 502 for ref, paths in module.special.values(): 503 for path in paths: 504 self.add_dependency(path, ref.get_origin()) 505 506 def add_init_dependencies(self): 507 508 "Add dependencies related to object initialisation." 509 510 for name in self.classes.keys(): 511 if self.is_dynamic_class(name): 512 513 # Make subclasses depend on any class with non-static 514 # attributes, plus its module for the initialisation. 515 516 for subclass in self.subclasses[name]: 517 ref = Reference("<class>", subclass) 518 self.add_dependency(subclass, name) 519 self.add_dependency(subclass, self.get_module_provider(ref)) 520 521 # Also make the class dependent on its module for 522 # initialisation. 523 524 ref = Reference("<class>", name) 525 self.add_dependency(name, self.get_module_provider(ref)) 526 527 for name in self.function_defaults.keys(): 528 if self.is_dynamic_callable(name): 529 530 # Make functions with defaults requiring initialisation depend 531 # on the parent scope. 532 533 ref = Reference("<function>", name) 534 self.add_dependency(name, ref.parent()) 535 536 def add_module_dependencies(self): 537 538 "Record module-based dependencies." 539 540 for module_name, providers in self.module_depends.items(): 541 if self.modules.has_key(module_name): 542 for provider in providers: 543 if self.modules.has_key(provider): 544 self.add_dependency(module_name, provider) 545 546 def add_dependency(self, path, origin): 547 548 "Add dependency details for 'path' involving 'origin'." 549 550 if origin and not origin.startswith("%s." % path): 551 init_item(self.depends, path, set) 552 self.depends[path].add(origin) 553 554 def add_module_dependency(self, module_name, provider): 555 556 "Add dependency details for 'module_name' involving 'provider'." 557 558 if provider: 559 init_item(self.module_depends, module_name, set) 560 self.module_depends[module_name].add(provider) 561 562 def condense_dependencies(self): 563 564 """ 565 Condense the dependencies by removing all functions that do not need 566 initialisation. 567 """ 568 569 d = {} 570 for path, depends in self.depends.items(): 571 d[path] = {} 572 d[path] = self.condense_dependency_entry(depends, d) 573 574 self.depends = {} 575 576 for path, depends in d.items(): 577 if depends: 578 self.depends[path] = depends 579 580 def condense_dependency_entry(self, depends, d): 581 l = set() 582 for depend in depends: 583 if self.modules.has_key(depend) or self.classes.has_key(depend) or \ 584 self.is_dynamic_callable(depend): 585 586 l.add(depend) 587 else: 588 deps = d.get(depend) 589 if deps: 590 l.update(self.condense_dependency_entry(deps, d)) 591 return l 592 593 # NOTE: Consolidate this information in a common location. 594 595 special_attributes = ("__args__", "__file__", "__fn__", "__fname__", "__mname__", "__name__") 596 597 def is_dynamic_class(self, name): 598 599 """ 600 Return whether 'name' refers to a class with members that must be 601 initialised dynamically. 602 """ 603 604 attrs = self.all_class_attrs.get(name) 605 606 if not attrs: 607 return False 608 609 for attrname, attr in attrs.items(): 610 if attrname in self.special_attributes: 611 continue 612 if not attr or not self.get_object(attr).static(): 613 return True 614 615 return False 616 617 def is_dynamic_callable(self, name): 618 619 """ 620 Return whether 'name' refers to a callable employing defaults that may 621 need initialising before the callable can be used. 622 """ 623 624 # Find any defaults for the function or method. 625 626 defaults = self.function_defaults.get(name) 627 if not defaults: 628 return False 629 630 # Identify non-constant defaults. 631 632 for name, ref in defaults: 633 if not ref.static() and not ref.is_constant_alias(): 634 return True 635 636 return False 637 638 def order_objects(self): 639 640 "Produce an object initialisation ordering." 641 642 self.condense_dependencies() 643 644 # Record the number of modules using or depending on each module. 645 646 usage = {} 647 648 # Record path-based dependencies. 649 650 for path in self.depends.keys(): 651 usage[path] = set() 652 653 for path, depends in self.depends.items(): 654 for origin in depends: 655 init_item(usage, origin, set) 656 usage[origin].add(path) 657 658 # Produce an ordering by obtaining exposed modules (required by modules 659 # already processed) and putting them at the start of the list. 660 661 ordered = [] 662 663 while usage: 664 have_next = False 665 666 for path, n in usage.items(): 667 if not n: 668 ordered.insert(0, path) 669 depends = self.depends.get(path) 670 671 # Reduce usage of the referenced objects. 672 673 if depends: 674 for origin in depends: 675 usage[origin].remove(path) 676 677 del usage[path] 678 have_next = True 679 680 if not have_next: 681 raise ProgramError("Modules with unresolvable dependencies exist: %s" % ", ".join(usage.keys())) 682 683 ordered.remove("__main__") 684 ordered.append("__main__") 685 return ordered 686 687 def order_modules(self): 688 689 "Produce a module initialisation ordering." 690 691 ordered = self.order_objects() 692 filtered = [] 693 694 for module_name in self.modules.keys(): 695 if module_name not in ordered: 696 filtered.append(module_name) 697 698 for path in ordered: 699 if self.modules.has_key(path): 700 filtered.append(path) 701 702 return filtered 703 704 def find_dependency(self, ref): 705 706 "Find the ultimate dependency for 'ref'." 707 708 found = set() 709 while ref and ref.has_kind("<depends>") and not ref in found: 710 found.add(ref) 711 ref = self.identify(ref.get_origin()) 712 return ref 713 714 def get_module_provider(self, ref): 715 716 "Identify the provider of the given 'ref'." 717 718 for ancestor in ref.ancestors(): 719 if self.modules.has_key(ancestor): 720 return ancestor 721 return None 722 723 def finalise_classes(self): 724 725 "Finalise the class relationships and attributes." 726 727 self.derive_inherited_attrs() 728 self.derive_subclasses() 729 self.derive_shadowed_attrs() 730 731 def derive_inherited_attrs(self): 732 733 "Derive inherited attributes for classes throughout the program." 734 735 for name in self.classes.keys(): 736 self.propagate_attrs_for_class(name) 737 738 def propagate_attrs_for_class(self, name, visited=None): 739 740 "Propagate inherited attributes for class 'name'." 741 742 # Visit classes only once. 743 744 if self.all_combined_attrs.has_key(name): 745 return 746 747 visited = visited or [] 748 749 if name in visited: 750 raise ProgramError, "Class %s may not inherit from itself: %s -> %s." % (name, " -> ".join(visited), name) 751 752 visited.append(name) 753 754 class_attrs = {} 755 instance_attrs = {} 756 757 # Aggregate the attributes from base classes, recording the origins of 758 # applicable attributes. 759 760 for base in self.classes[name][::-1]: 761 762 # Get the identity of the class from the reference. 763 764 base = base.get_origin() 765 766 # Define the base class completely before continuing with this 767 # class. 768 769 self.propagate_attrs_for_class(base, visited) 770 class_attrs.update(self.all_class_attrs[base]) 771 772 # Instance attribute origins are combined if different. 773 774 for key, values in self.all_instance_attrs[base].items(): 775 init_item(instance_attrs, key, set) 776 instance_attrs[key].update(values) 777 778 # Class attributes override those defined earlier in the hierarchy. 779 780 class_attrs.update(self.all_class_attrs.get(name, {})) 781 782 # Instance attributes are merely added if not already defined. 783 784 for key in self.all_instance_attrs.get(name, []): 785 if not instance_attrs.has_key(key): 786 instance_attrs[key] = set(["%s.%s" % (name, key)]) 787 788 self.all_class_attrs[name] = class_attrs 789 self.all_instance_attrs[name] = instance_attrs 790 self.all_combined_attrs[name] = set(class_attrs.keys()).union(instance_attrs.keys()) 791 792 def derive_subclasses(self): 793 794 "Derive subclass details for classes." 795 796 for name, bases in self.classes.items(): 797 for base in bases: 798 799 # Get the identity of the class from the reference. 800 801 base = base.get_origin() 802 self.subclasses[base].add(name) 803 804 def derive_shadowed_attrs(self): 805 806 "Derive shadowed attributes for classes." 807 808 for name, attrs in self.all_instance_attrs.items(): 809 attrs = set(attrs.keys()).intersection(self.all_class_attrs[name].keys()) 810 if attrs: 811 self.all_shadowed_attrs[name] = attrs 812 813 def set_class_types(self): 814 815 "Set the type of each class." 816 817 for attrs in self.all_class_attrs.values(): 818 attrs["__class__"] = self.type_ref.get_origin() 819 820 def define_instantiators(self): 821 822 """ 823 Consolidate parameter and default details, incorporating initialiser 824 details to define instantiator signatures. 825 """ 826 827 for cls, attrs in self.all_class_attrs.items(): 828 initialiser = attrs["__init__"] 829 self.function_parameters[cls] = self.function_parameters[initialiser] 830 self.function_defaults[cls] = self.function_defaults[initialiser] 831 832 def collect_constants(self): 833 834 "Get constants from all active modules." 835 836 for module in self.modules.values(): 837 self.all_constants.update(module.constants) 838 839 # Import methods. 840 841 def find_in_path(self, name): 842 843 """ 844 Find the given module 'name' in the search path, returning None where no 845 such module could be found, or a 2-tuple from the 'find' method 846 otherwise. 847 """ 848 849 for d in self.path: 850 m = self.find(d, name) 851 if m: return m 852 return None 853 854 def find(self, d, name): 855 856 """ 857 In the directory 'd', find the given module 'name', where 'name' can 858 either refer to a single file module or to a package. Return None if the 859 'name' cannot be associated with either a file or a package directory, 860 or a 2-tuple from '_find_package' or '_find_module' otherwise. 861 """ 862 863 m = self._find_package(d, name) 864 if m: return m 865 m = self._find_module(d, name) 866 if m: return m 867 return None 868 869 def _find_module(self, d, name): 870 871 """ 872 In the directory 'd', find the given module 'name', returning None where 873 no suitable file exists in the directory, or a 2-tuple consisting of 874 None (indicating that no package directory is involved) and a filename 875 indicating the location of the module. 876 """ 877 878 name_py = name + extsep + "py" 879 filename = self._find_file(d, name_py) 880 if filename: 881 return None, filename 882 return None 883 884 def _find_package(self, d, name): 885 886 """ 887 In the directory 'd', find the given package 'name', returning None 888 where no suitable package directory exists, or a 2-tuple consisting of 889 a directory (indicating the location of the package directory itself) 890 and a filename indicating the location of the __init__.py module which 891 declares the package's top-level contents. 892 """ 893 894 filename = self._find_file(d, name) 895 if filename: 896 init_py = "__init__" + extsep + "py" 897 init_py_filename = self._find_file(filename, init_py) 898 if init_py_filename: 899 return filename, init_py_filename 900 return None 901 902 def _find_file(self, d, filename): 903 904 """ 905 Return the filename obtained when searching the directory 'd' for the 906 given 'filename', or None if no actual file exists for the filename. 907 """ 908 909 filename = join(d, filename) 910 if exists(filename): 911 return filename 912 else: 913 return None 914 915 def load(self, name): 916 917 """ 918 Load the module or package with the given 'name'. Return an object 919 referencing the loaded module or package, or None if no such module or 920 package exists. 921 """ 922 923 # Loaded modules are returned immediately. 924 # Modules may be known but not yet loading (having been registered as 925 # submodules), loading, loaded, or completely unknown. 926 927 module = self.get_module(name) 928 929 if module: 930 return self.modules[name] 931 932 # Otherwise, modules are loaded. 933 934 # Split the name into path components, and try to find the uppermost in 935 # the search path. 936 937 path = name.split(".") 938 path_so_far = [] 939 module = None 940 941 for p in path: 942 943 # Get the module's filesystem details. 944 945 if not path_so_far: 946 m = self.find_in_path(p) 947 elif d: 948 m = self.find(d, p) 949 else: 950 m = None 951 952 path_so_far.append(p) 953 module_name = ".".join(path_so_far) 954 955 # Return None if the module could not be located. 956 957 if not m: 958 if self.verbose: 959 print >>sys.stderr, "Not found (%s)" % name 960 return None 961 962 # Get the directory and module filename. 963 964 d, filename = m 965 966 # Get the module itself. 967 968 return self.load_from_file(filename, module_name) 969 970 def load_from_file(self, filename, module_name=None): 971 972 "Load the module from the given 'filename'." 973 974 if module_name is None: 975 module_name = "__main__" 976 977 module = self.modules.get(module_name) 978 979 if not module: 980 981 # Try to load from cache. 982 983 module = self.load_from_cache(filename, module_name) 984 if module: 985 return module 986 987 # If no cache entry exists, load from file. 988 989 module = inspector.InspectedModule(module_name, self) 990 self.add_module(module_name, module) 991 self.update_cache_validity(module) 992 993 self._load(module, module_name, lambda m: m.parse, filename) 994 995 return module 996 997 def update_cache_validity(self, module): 998 999 "Make 'module' valid in the cache, but invalidate accessing modules." 1000 1001 accessing = self.accessing_modules.get(module.name) 1002 if accessing: 1003 self.invalidated.update(accessing) 1004 if module.name in self.invalidated: 1005 self.invalidated.remove(module.name) 1006 1007 def source_is_new(self, filename, module_name): 1008 1009 "Return whether 'filename' is newer than the cached 'module_name'." 1010 1011 if self.cache: 1012 cache_filename = join(self.cache, module_name) 1013 return not exists(cache_filename) or \ 1014 getmtime(filename) > getmtime(cache_filename) or \ 1015 module_name in self.invalidated 1016 else: 1017 return True 1018 1019 def load_from_cache(self, filename, module_name): 1020 1021 "Return a module residing in the cache." 1022 1023 module = self.modules.get(module_name) 1024 1025 if not module and not self.source_is_new(filename, module_name): 1026 module = CachedModule(module_name, self) 1027 self.add_module(module_name, module) 1028 1029 filename = join(self.cache, module_name) 1030 self._load(module, module_name, lambda m: m.from_cache, filename) 1031 1032 return module 1033 1034 def _load(self, module, module_name, fn, filename): 1035 1036 """ 1037 Load 'module' for the given 'module_name', and with 'fn' performing an 1038 invocation on the module with the given 'filename'. 1039 """ 1040 1041 # Load the module. 1042 1043 if self.verbose: 1044 print >>sys.stderr, module_name in self.required and "Required" or "Loading", module_name, "from", filename 1045 fn(module)(filename) 1046 1047 # Add the module object if not already defined. 1048 1049 if not self.objects.has_key(module_name): 1050 self.objects[module_name] = Reference("<module>", module_name) 1051 1052 def add_module(self, module_name, module): 1053 1054 """ 1055 Return the module with the given 'module_name', adding a new module 1056 object if one does not already exist. 1057 """ 1058 1059 self.modules[module_name] = module 1060 if module_name in self.to_import: 1061 self.to_import.remove(module_name) 1062 1063 # vim: tabstop=4 expandtab shiftwidth=4