1.1 --- a/classhook.py Thu Dec 09 20:50:19 2004 +0100
1.2 +++ b/classhook.py Thu Dec 09 20:51:18 2004 +0100
1.3 @@ -105,6 +105,31 @@
1.4
1.5 "A class providing support for searching directories for supported files."
1.6
1.7 + def find_module(self, name, path=None):
1.8 +
1.9 + """
1.10 + Find the module with the given 'name', using the given 'path' to locate
1.11 + it. Note that ModuleLoader.find_module is almost sufficient, but does
1.12 + not provide enough support for "package unions" where the root of a
1.13 + package hierarchy may appear in several places.
1.14 +
1.15 + Return a list of locations (each being the "stuff" data structure used
1.16 + by load_module); this replaces the single "stuff" value or None returned
1.17 + by ModuleLoader.find_module.
1.18 + """
1.19 +
1.20 + if path is None:
1.21 + path = [None] + self.default_path()
1.22 +
1.23 + found_locations = []
1.24 +
1.25 + for dir in path:
1.26 + stuff = self.find_module_in_dir(name, dir)
1.27 + if stuff:
1.28 + found_locations.append(stuff)
1.29 +
1.30 + return found_locations
1.31 +
1.32 def find_module_in_dir(self, name, dir, allow_packages=1):
1.33
1.34 """
1.35 @@ -196,107 +221,121 @@
1.36 def load_module(self, name, stuff):
1.37
1.38 """
1.39 - Load the module with the given 'name', whose 'stuff' which describes the
1.40 - location of the module is a tuple of the form (file, filename, (suffix,
1.41 - mode, data type)). Return a module object or raise an ImportError if a
1.42 - problem occurred in the import operation.
1.43 + Load the module with the given 'name', with a list of 'stuff' items,
1.44 + each of which describes the location of the module and is a tuple of the
1.45 + form (file, filename, (suffix, mode, data type)).
1.46 +
1.47 + Return a module object or raise an ImportError if a problem occurred in
1.48 + the import operation.
1.49 +
1.50 + Note that the 'stuff' parameter is a list and not a single item as in
1.51 + ModuleLoader.load_module. This should still work, however, since the
1.52 + find_module method produces such a list.
1.53 """
1.54
1.55 - # Just go into the directory and find the class files.
1.56 -
1.57 - archive, filename, info = stuff
1.58 - suffix, mode, datatype = info
1.59 - if datatype not in (JAVA_PACKAGE, JAVA_ARCHIVE):
1.60 - return ihooks.ModuleLoader.load_module(self, name, stuff)
1.61 -
1.62 - #print "Loading", archive, filename, info
1.63 -
1.64 # Set up the module.
1.65 + # A union of all locations is placed in the module's path.
1.66
1.67 module = self.hooks.add_module(name)
1.68 - module.__path__ = [filename]
1.69 + module.__path__ = [item_filename for (item_archive, item_filename, item_info) in stuff]
1.70
1.71 - # Prepare a dictionary of globals.
1.72 + # Just go into each package and find the class files.
1.73
1.74 - global_names = module.__dict__
1.75 - global_names["__builtins__"] = __builtins__
1.76 + for stuff_item in stuff:
1.77
1.78 - # Process each class file, producing a genuine Python class.
1.79 + # Extract the details, delegating loading responsibility to the
1.80 + # default loader where appropriate.
1.81 + # NOTE: Should we not be using some saved loader remembered upon
1.82 + # NOTE: installation?
1.83
1.84 - class_files = []
1.85 - classes = []
1.86 + archive, filename, info = stuff_item
1.87 + suffix, mode, datatype = info
1.88 + if datatype not in (JAVA_PACKAGE, JAVA_ARCHIVE):
1.89 + return ihooks.ModuleLoader.load_module(self, name, stuff_item)
1.90
1.91 - # Get the real filename.
1.92 + #print "Loading", archive, filename, info
1.93
1.94 - filename = self._get_path_in_archive(filename)
1.95 - #print "Real filename", filename
1.96 + # Prepare a dictionary of globals.
1.97
1.98 - # Load the class files.
1.99 + global_names = module.__dict__
1.100 + global_names["__builtins__"] = __builtins__
1.101 +
1.102 + # Process each class file, producing a genuine Python class.
1.103
1.104 - class_files = {}
1.105 - for class_filename in self.hooks.matching(filename, os.extsep + "class", archive):
1.106 - #print "Loading class", class_filename
1.107 - s = self.hooks.read(class_filename, archive)
1.108 - class_file = classfile.ClassFile(s)
1.109 - class_files[str(class_file.this_class.get_name())] = class_file
1.110 + class_files = []
1.111 + classes = []
1.112 +
1.113 + # Get the real filename.
1.114
1.115 - # Get an index of the class files.
1.116 + filename = self._get_path_in_archive(filename)
1.117 + #print "Real filename", filename
1.118
1.119 - class_file_index = class_files.keys()
1.120 + # Load the class files.
1.121
1.122 - # NOTE: Unnecessary sorting for test purposes.
1.123 -
1.124 - class_file_index.sort()
1.125 + class_files = {}
1.126 + for class_filename in self.hooks.matching(filename, os.extsep + "class", archive):
1.127 + #print "Loading class", class_filename
1.128 + s = self.hooks.read(class_filename, archive)
1.129 + class_file = classfile.ClassFile(s)
1.130 + class_files[str(class_file.this_class.get_name())] = class_file
1.131
1.132 - # Now go through the classes arranging them in a safe loading order.
1.133 + # Get an index of the class files.
1.134 +
1.135 + class_file_index = class_files.keys()
1.136
1.137 - position = 0
1.138 - while position < len(class_file_index):
1.139 - class_name = class_file_index[position]
1.140 - super_class_name = str(class_files[class_name].super_class.get_name())
1.141 + # NOTE: Unnecessary sorting for test purposes.
1.142 +
1.143 + class_file_index.sort()
1.144
1.145 - # Discover whether the superclass appears later.
1.146 + # Now go through the classes arranging them in a safe loading order.
1.147
1.148 - try:
1.149 - super_class_position = class_file_index.index(super_class_name)
1.150 - if super_class_position > position:
1.151 + position = 0
1.152 + while position < len(class_file_index):
1.153 + class_name = class_file_index[position]
1.154 + super_class_name = str(class_files[class_name].super_class.get_name())
1.155
1.156 - # If the superclass appears later, swap this class and the
1.157 - # superclass, then process the superclass.
1.158 + # Discover whether the superclass appears later.
1.159
1.160 - class_file_index[position] = super_class_name
1.161 - class_file_index[super_class_position] = class_name
1.162 - continue
1.163 + try:
1.164 + super_class_position = class_file_index.index(super_class_name)
1.165 + if super_class_position > position:
1.166 +
1.167 + # If the superclass appears later, swap this class and the
1.168 + # superclass, then process the superclass.
1.169
1.170 - except ValueError:
1.171 - pass
1.172 + class_file_index[position] = super_class_name
1.173 + class_file_index[super_class_position] = class_name
1.174 + continue
1.175
1.176 - position += 1
1.177 + except ValueError:
1.178 + pass
1.179
1.180 - class_files = [class_files[class_name] for class_name in class_file_index]
1.181 + position += 1
1.182
1.183 - for class_file in class_files:
1.184 - translator = bytecode.ClassTranslator(class_file)
1.185 - cls, external_names = translator.process(global_names)
1.186 - module.__dict__[cls.__name__] = cls
1.187 - classes.append((cls, class_file))
1.188 + class_files = [class_files[class_name] for class_name in class_file_index]
1.189
1.190 - # Import the local names.
1.191 + for class_file in class_files:
1.192 + translator = bytecode.ClassTranslator(class_file)
1.193 + cls, external_names = translator.process(global_names)
1.194 + module.__dict__[cls.__name__] = cls
1.195 + classes.append((cls, class_file))
1.196 +
1.197 + # Import the local names.
1.198
1.199 - for external_name in external_names:
1.200 - external_name_parts = external_name.split(".")
1.201 - if len(external_name_parts) > 1:
1.202 - external_module_name = ".".join(external_name_parts[:-1])
1.203 - print "* Importing", external_module_name
1.204 - obj = __import__(external_module_name, global_names, {}, [])
1.205 - global_names[external_name_parts[0]] = obj
1.206 + for external_name in external_names:
1.207 + external_name_parts = external_name.split(".")
1.208 + if len(external_name_parts) > 1:
1.209 + external_module_name = ".".join(external_name_parts[:-1])
1.210 + print "* Importing", external_module_name
1.211 + obj = __import__(external_module_name, global_names, {}, [])
1.212 + global_names[external_name_parts[0]] = obj
1.213
1.214 - # Finally, call __clinit__ methods for all relevant classes.
1.215 + # Finally, call __clinit__ methods for all relevant classes.
1.216
1.217 - for cls, class_file in classes:
1.218 - print "**", cls, class_file
1.219 - if hasattr(cls, "__clinit__"):
1.220 - eval(cls.__clinit__.func_code, global_names)
1.221 + for cls, class_file in classes:
1.222 + print "**", cls, class_file
1.223 + if hasattr(cls, "__clinit__"):
1.224 + eval(cls.__clinit__.func_code, global_names)
1.225
1.226 return module
1.227