diff -r 26491ee91e33 -r e4cb9c53db3e thirdparty/google_appengine/google/appengine/dist/py_zipimport.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thirdparty/google_appengine/google/appengine/dist/py_zipimport.py Fri Apr 24 14:16:00 2009 +0000 @@ -0,0 +1,288 @@ +#!/usr/bin/env python +# +# Copyright 2007 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +"""Pure Python zipfile importer. + +This approximates the standard zipimport module, which isn't supported +by Google App Engine. See PEP 302 for more information about the API +for import hooks. + +Usage: + import py_zipimport + +As a side effect of importing, the module overrides sys.path_hooks, +and also creates an alias 'zipimport' for itself. When your app is +running in Google App Engine production, you don't even need to import +it, since this is already done for you. In the Google App Engine SDK +this module is not used; instead, the standard zipimport module is +used. +""" + + +__all__ = ['ZipImportError', 'zipimporter'] + + +import os +import sys +import types +import UserDict +import zipfile + + +_SEARCH_ORDER = [ + + ('.py', False), + ('/__init__.py', True), +] + + +_zipfile_cache = {} + + +class ZipImportError(ImportError): + """Exception raised by zipimporter objects.""" + + +class zipimporter: + """A PEP-302-style importer that can import from a zipfile. + + Just insert or append this class (not an instance) to sys.path_hooks + and you're in business. Instances satisfy both the 'importer' and + 'loader' APIs specified in PEP 302. + """ + + def __init__(self, path_entry): + """Constructor. + + Args: + path_entry: The entry in sys.path. This should be the name of an + existing zipfile possibly with a path separator and a prefix + path within the archive appended, e.g. /x/django.zip or + /x/django.zip/foo/bar. + + Raises: + ZipImportError if the path_entry does not represent a valid + zipfile with optional prefix. + """ + archive = path_entry + prefix = '' + while not os.path.lexists(archive): + head, tail = os.path.split(archive) + if head == archive: + msg = 'Nothing found for %r' % path_entry + raise ZipImportError(msg) + archive = head + prefix = os.path.join(tail, prefix) + if not os.path.isfile(archive): + msg = 'Non-file %r found for %r' % (archive, path_entry) + raise ZipImportError(msg) + self.archive = archive + self.prefix = os.path.join(prefix, '') + self.zipfile = _zipfile_cache.get(archive) + if self.zipfile is None: + try: + self.zipfile = zipfile.ZipFile(self.archive) + except (EnvironmentError, zipfile.BadZipfile), err: + msg = 'Can\'t open zipfile %s: %s: %s' % (self.archive, + err.__class__.__name__, err) + import logging + logging.warn(msg) + raise ZipImportError(msg) + else: + _zipfile_cache[archive] = self.zipfile + import logging + logging.info('zipimporter(%r, %r)', archive, prefix) + + def __repr__(self): + """Return a string representation matching zipimport.c.""" + name = self.archive + if self.prefix: + name = os.path.join(name, self.prefix) + return '' % name + + def _get_info(self, fullmodname): + """Internal helper for find_module() and load_module(). + + Args: + fullmodname: The dot-separated full module name, e.g. 'django.core.mail'. + + Returns: + A tuple (submodname, is_package, relpath) where: + submodname: The final component of the module name, e.g. 'mail'. + is_package: A bool indicating whether this is a package. + relpath: The path to the module's source code within to the zipfile. + + Raises: + ImportError if the module is not found in the archive. + """ + parts = fullmodname.split('.') + submodname = parts[-1] + for suffix, is_package in _SEARCH_ORDER: + relpath = os.path.join(self.prefix, + submodname + suffix.replace('/', os.sep)) + try: + self.zipfile.getinfo(relpath.replace(os.sep, '/')) + except KeyError: + pass + else: + return submodname, is_package, relpath + msg = ('Can\'t find module %s in zipfile %s with prefix %r' % + (fullmodname, self.archive, self.prefix)) + raise ZipImportError(msg) + + def _get_source(self, fullmodname): + """Internal helper for load_module(). + + Args: + fullmodname: The dot-separated full module name, e.g. 'django.core.mail'. + + Returns: + A tuple (submodname, is_package, fullpath, source) where: + submodname: The final component of the module name, e.g. 'mail'. + is_package: A bool indicating whether this is a package. + fullpath: The path to the module's source code including the + zipfile's filename. + source: The module's source code. + + Raises: + ImportError if the module is not found in the archive. + """ + submodname, is_package, relpath = self._get_info(fullmodname) + fullpath = '%s%s%s' % (self.archive, os.sep, relpath) + source = self.zipfile.read(relpath.replace(os.sep, '/')) + source = source.replace('\r\n', '\n') + source = source.replace('\r', '\n') + return submodname, is_package, fullpath, source + + def find_module(self, fullmodname, path=None): + """PEP-302-compliant find_module() method. + + Args: + fullmodname: The dot-separated full module name, e.g. 'django.core.mail'. + path: Optional and ignored; present for API compatibility only. + + Returns: + None if the module isn't found in the archive; self if it is found. + """ + try: + submodname, is_package, relpath = self._get_info(fullmodname) + except ImportError: + return None + else: + return self + + def load_module(self, fullmodname): + """PEP-302-compliant load_module() method. + + Args: + fullmodname: The dot-separated full module name, e.g. 'django.core.mail'. + + Returns: + The module object constructed from the source code. + + Raises: + SyntaxError if the module's source code is syntactically incorrect. + ImportError if there was a problem accessing the source code. + Whatever else can be raised by executing the module's source code. + """ + submodname, is_package, fullpath, source = self._get_source(fullmodname) + code = compile(source, fullpath, 'exec') + mod = sys.modules.get(fullmodname) + try: + if mod is None: + mod = sys.modules[fullmodname] = types.ModuleType(fullmodname) + mod.__loader__ = self + mod.__file__ = fullpath + mod.__name__ = fullmodname + if is_package: + mod.__path__ = [os.path.dirname(mod.__file__)] + exec code in mod.__dict__ + except: + if fullmodname in sys.modules: + del sys.modules[fullmodname] + raise + return mod + + + def get_data(self, fullpath): + """Return (binary) content of a data file in the zipfile.""" + required_prefix = os.path.join(self.archive, '') + if not fullpath.startswith(required_prefix): + raise IOError('Path %r doesn\'t start with zipfile name %r' % + (fullpath, required_prefix)) + relpath = fullpath[len(required_prefix):] + try: + return self.zipfile.read(relpath) + except KeyError: + raise IOError('Path %r not found in zipfile %r' % + (relpath, self.archive)) + + def is_package(self, fullmodname): + """Return whether a module is a package.""" + submodname, is_package, relpath = self._get_info(fullmodname) + return is_package + + def get_code(self, fullmodname): + """Return bytecode for a module.""" + submodname, is_package, fullpath, source = self._get_source(fullmodname) + return compile(source, fullpath, 'exec') + + def get_source(self, fullmodname): + """Return source code for a module.""" + submodname, is_package, fullpath, source = self._get_source(fullmodname) + return source + + +class ZipFileCache(UserDict.DictMixin): + """Helper class to export archive data in _zip_directory_cache. + + Just take the info from _zipfile_cache and convert it as required. + """ + + def __init__(self, archive): + _zipfile_cache[archive] + + self._archive = archive + + def keys(self): + return _zipfile_cache[self._archive].namelist() + + def __getitem__(self, filename): + info = _zipfile_cache[self._archive].getinfo(filename) + dt = info.date_time + dostime = dt[3] << 11 | dt[4] << 5 | (dt[5] // 2) + dosdate = (dt[0] - 1980) << 9 | dt[1] << 5 | dt[2] + return (os.path.join(self._archive, info.filename), info.compress_type, + info.compress_size, info.file_size, info.header_offset, dostime, + dosdate, info.CRC) + + +class ZipDirectoryCache(UserDict.DictMixin): + """Helper class to export _zip_directory_cache.""" + + def keys(self): + return _zipfile_cache.keys() + + def __getitem__(self, archive): + return ZipFileCache(archive) + + +_zip_directory_cache = ZipDirectoryCache() + + +sys.modules['zipimport'] = sys.modules[__name__] +sys.path_hooks[:] = [zipimporter]