1"""Abstract base classes related to import.""" 2from . import _bootstrap 3from . import _bootstrap_external 4from . import machinery 5try: 6 import _frozen_importlib 7except ImportError as exc: 8 if exc.name != '_frozen_importlib': 9 raise 10 _frozen_importlib = None 11try: 12 import _frozen_importlib_external 13except ImportError as exc: 14 _frozen_importlib_external = _bootstrap_external 15import abc 16 17 18def _register(abstract_cls, *classes): 19 for cls in classes: 20 abstract_cls.register(cls) 21 if _frozen_importlib is not None: 22 try: 23 frozen_cls = getattr(_frozen_importlib, cls.__name__) 24 except AttributeError: 25 frozen_cls = getattr(_frozen_importlib_external, cls.__name__) 26 abstract_cls.register(frozen_cls) 27 28 29class Finder(metaclass=abc.ABCMeta): 30 31 """Legacy abstract base class for import finders. 32 33 It may be subclassed for compatibility with legacy third party 34 reimplementations of the import system. Otherwise, finder 35 implementations should derive from the more specific MetaPathFinder 36 or PathEntryFinder ABCs. 37 """ 38 39 @abc.abstractmethod 40 def find_module(self, fullname, path=None): 41 """An abstract method that should find a module. 42 The fullname is a str and the optional path is a str or None. 43 Returns a Loader object or None. 44 """ 45 46 47class MetaPathFinder(Finder): 48 49 """Abstract base class for import finders on sys.meta_path.""" 50 51 # We don't define find_spec() here since that would break 52 # hasattr checks we do to support backward compatibility. 53 54 def find_module(self, fullname, path): 55 """Return a loader for the module. 56 57 If no module is found, return None. The fullname is a str and 58 the path is a list of strings or None. 59 60 This method is deprecated in favor of finder.find_spec(). If find_spec() 61 exists then backwards-compatible functionality is provided for this 62 method. 63 64 """ 65 if not hasattr(self, 'find_spec'): 66 return None 67 found = self.find_spec(fullname, path) 68 return found.loader if found is not None else None 69 70 def invalidate_caches(self): 71 """An optional method for clearing the finder's cache, if any. 72 This method is used by importlib.invalidate_caches(). 73 """ 74 75_register(MetaPathFinder, machinery.BuiltinImporter, machinery.FrozenImporter, 76 machinery.PathFinder, machinery.WindowsRegistryFinder) 77 78 79class PathEntryFinder(Finder): 80 81 """Abstract base class for path entry finders used by PathFinder.""" 82 83 # We don't define find_spec() here since that would break 84 # hasattr checks we do to support backward compatibility. 85 86 def find_loader(self, fullname): 87 """Return (loader, namespace portion) for the path entry. 88 89 The fullname is a str. The namespace portion is a sequence of 90 path entries contributing to part of a namespace package. The 91 sequence may be empty. If loader is not None, the portion will 92 be ignored. 93 94 The portion will be discarded if another path entry finder 95 locates the module as a normal module or package. 96 97 This method is deprecated in favor of finder.find_spec(). If find_spec() 98 is provided than backwards-compatible functionality is provided. 99 100 """ 101 if not hasattr(self, 'find_spec'): 102 return None, [] 103 found = self.find_spec(fullname) 104 if found is not None: 105 if not found.submodule_search_locations: 106 portions = [] 107 else: 108 portions = found.submodule_search_locations 109 return found.loader, portions 110 else: 111 return None, [] 112 113 find_module = _bootstrap_external._find_module_shim 114 115 def invalidate_caches(self): 116 """An optional method for clearing the finder's cache, if any. 117 This method is used by PathFinder.invalidate_caches(). 118 """ 119 120_register(PathEntryFinder, machinery.FileFinder) 121 122 123class Loader(metaclass=abc.ABCMeta): 124 125 """Abstract base class for import loaders.""" 126 127 def create_module(self, spec): 128 """Return a module to initialize and into which to load. 129 130 This method should raise ImportError if anything prevents it 131 from creating a new module. It may return None to indicate 132 that the spec should create the new module. 133 """ 134 # By default, defer to default semantics for the new module. 135 return None 136 137 # We don't define exec_module() here since that would break 138 # hasattr checks we do to support backward compatibility. 139 140 def load_module(self, fullname): 141 """Return the loaded module. 142 143 The module must be added to sys.modules and have import-related 144 attributes set properly. The fullname is a str. 145 146 ImportError is raised on failure. 147 148 This method is deprecated in favor of loader.exec_module(). If 149 exec_module() exists then it is used to provide a backwards-compatible 150 functionality for this method. 151 152 """ 153 if not hasattr(self, 'exec_module'): 154 raise ImportError 155 return _bootstrap._load_module_shim(self, fullname) 156 157 def module_repr(self, module): 158 """Return a module's repr. 159 160 Used by the module type when the method does not raise 161 NotImplementedError. 162 163 This method is deprecated. 164 165 """ 166 # The exception will cause ModuleType.__repr__ to ignore this method. 167 raise NotImplementedError 168 169 170class ResourceLoader(Loader): 171 172 """Abstract base class for loaders which can return data from their 173 back-end storage. 174 175 This ABC represents one of the optional protocols specified by PEP 302. 176 177 """ 178 179 @abc.abstractmethod 180 def get_data(self, path): 181 """Abstract method which when implemented should return the bytes for 182 the specified path. The path must be a str.""" 183 raise IOError 184 185 186class InspectLoader(Loader): 187 188 """Abstract base class for loaders which support inspection about the 189 modules they can load. 190 191 This ABC represents one of the optional protocols specified by PEP 302. 192 193 """ 194 195 def is_package(self, fullname): 196 """Optional method which when implemented should return whether the 197 module is a package. The fullname is a str. Returns a bool. 198 199 Raises ImportError if the module cannot be found. 200 """ 201 raise ImportError 202 203 def get_code(self, fullname): 204 """Method which returns the code object for the module. 205 206 The fullname is a str. Returns a types.CodeType if possible, else 207 returns None if a code object does not make sense 208 (e.g. built-in module). Raises ImportError if the module cannot be 209 found. 210 """ 211 source = self.get_source(fullname) 212 if source is None: 213 return None 214 return self.source_to_code(source) 215 216 @abc.abstractmethod 217 def get_source(self, fullname): 218 """Abstract method which should return the source code for the 219 module. The fullname is a str. Returns a str. 220 221 Raises ImportError if the module cannot be found. 222 """ 223 raise ImportError 224 225 @staticmethod 226 def source_to_code(data, path='<string>'): 227 """Compile 'data' into a code object. 228 229 The 'data' argument can be anything that compile() can handle. The'path' 230 argument should be where the data was retrieved (when applicable).""" 231 return compile(data, path, 'exec', dont_inherit=True) 232 233 exec_module = _bootstrap_external._LoaderBasics.exec_module 234 load_module = _bootstrap_external._LoaderBasics.load_module 235 236_register(InspectLoader, machinery.BuiltinImporter, machinery.FrozenImporter) 237 238 239class ExecutionLoader(InspectLoader): 240 241 """Abstract base class for loaders that wish to support the execution of 242 modules as scripts. 243 244 This ABC represents one of the optional protocols specified in PEP 302. 245 246 """ 247 248 @abc.abstractmethod 249 def get_filename(self, fullname): 250 """Abstract method which should return the value that __file__ is to be 251 set to. 252 253 Raises ImportError if the module cannot be found. 254 """ 255 raise ImportError 256 257 def get_code(self, fullname): 258 """Method to return the code object for fullname. 259 260 Should return None if not applicable (e.g. built-in module). 261 Raise ImportError if the module cannot be found. 262 """ 263 source = self.get_source(fullname) 264 if source is None: 265 return None 266 try: 267 path = self.get_filename(fullname) 268 except ImportError: 269 return self.source_to_code(source) 270 else: 271 return self.source_to_code(source, path) 272 273_register(ExecutionLoader, machinery.ExtensionFileLoader) 274 275 276class FileLoader(_bootstrap_external.FileLoader, ResourceLoader, ExecutionLoader): 277 278 """Abstract base class partially implementing the ResourceLoader and 279 ExecutionLoader ABCs.""" 280 281_register(FileLoader, machinery.SourceFileLoader, 282 machinery.SourcelessFileLoader) 283 284 285class SourceLoader(_bootstrap_external.SourceLoader, ResourceLoader, ExecutionLoader): 286 287 """Abstract base class for loading source code (and optionally any 288 corresponding bytecode). 289 290 To support loading from source code, the abstractmethods inherited from 291 ResourceLoader and ExecutionLoader need to be implemented. To also support 292 loading from bytecode, the optional methods specified directly by this ABC 293 is required. 294 295 Inherited abstractmethods not implemented in this ABC: 296 297 * ResourceLoader.get_data 298 * ExecutionLoader.get_filename 299 300 """ 301 302 def path_mtime(self, path): 303 """Return the (int) modification time for the path (str).""" 304 if self.path_stats.__func__ is SourceLoader.path_stats: 305 raise IOError 306 return int(self.path_stats(path)['mtime']) 307 308 def path_stats(self, path): 309 """Return a metadata dict for the source pointed to by the path (str). 310 Possible keys: 311 - 'mtime' (mandatory) is the numeric timestamp of last source 312 code modification; 313 - 'size' (optional) is the size in bytes of the source code. 314 """ 315 if self.path_mtime.__func__ is SourceLoader.path_mtime: 316 raise IOError 317 return {'mtime': self.path_mtime(path)} 318 319 def set_data(self, path, data): 320 """Write the bytes to the path (if possible). 321 322 Accepts a str path and data as bytes. 323 324 Any needed intermediary directories are to be created. If for some 325 reason the file cannot be written because of permissions, fail 326 silently. 327 """ 328 329_register(SourceLoader, machinery.SourceFileLoader) 330