[SCM] WebKit Debian packaging branch, webkit-1.2, updated. upstream/1.1.90-6072-g9a69373
cjerdonek at webkit.org
cjerdonek at webkit.org
Thu Apr 8 02:04:32 UTC 2010
The following commit has been merged in the webkit-1.2 branch:
commit 55420d6c8c24cf0cbf9598cde8e20784a3ba2921
Author: cjerdonek at webkit.org <cjerdonek at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date: Mon Mar 1 10:07:59 2010 +0000
Unreviewed.
Rolling out: http://trac.webkit.org/changeset/55348
https://bugs.webkit.org/show_bug.cgi?id=35163
Rolling out since the changes to autoinstall do not work
with Python 2.4. In particular, ZipFile.extractall() was
added in Python 2.6.
* Scripts/webkitpy/__init__.py:
* Scripts/webkitpy/bugzilla.py:
* Scripts/webkitpy/init/__init__.py: Removed.
* Scripts/webkitpy/init/autoinstall.py: Removed.
* Scripts/webkitpy/networktransaction.py:
* Scripts/webkitpy/networktransaction_unittest.py:
* Scripts/webkitpy/statusserver.py:
* Scripts/webkitpy/thirdparty/autoinstall.py: Added.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@55363 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/WebKitTools/ChangeLog b/WebKitTools/ChangeLog
index bb57850..0863f02 100644
--- a/WebKitTools/ChangeLog
+++ b/WebKitTools/ChangeLog
@@ -1,4 +1,25 @@
-2010-03-01 cjerdonek at webkit.org <cjerdonek at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
+2010-03-01 Chris Jerdonek <cjerdonek at webkit.org>
+
+ Unreviewed.
+
+ Rolling out: http://trac.webkit.org/changeset/55348
+
+ https://bugs.webkit.org/show_bug.cgi?id=35163
+
+ Rolling out since the changes to autoinstall do not work
+ with Python 2.4. In particular, ZipFile.extractall() was
+ added in Python 2.6.
+
+ * Scripts/webkitpy/__init__.py:
+ * Scripts/webkitpy/bugzilla.py:
+ * Scripts/webkitpy/init/__init__.py: Removed.
+ * Scripts/webkitpy/init/autoinstall.py: Removed.
+ * Scripts/webkitpy/networktransaction.py:
+ * Scripts/webkitpy/networktransaction_unittest.py:
+ * Scripts/webkitpy/statusserver.py:
+ * Scripts/webkitpy/thirdparty/autoinstall.py: Added.
+
+2010-03-01 Chris Jerdonek <cjerdonek at webkit.org>
Unreviewed.
diff --git a/WebKitTools/Scripts/webkitpy/__init__.py b/WebKitTools/Scripts/webkitpy/__init__.py
index c3dd7bf..efa8c7a 100644
--- a/WebKitTools/Scripts/webkitpy/__init__.py
+++ b/WebKitTools/Scripts/webkitpy/__init__.py
@@ -1,22 +1,8 @@
# Required for Python to search this directory for module files
-import os
-
-from init.autoinstall import AutoInstaller
-
-# We put auto-installed third-party modules here:
-#
-# webkitpy/thirdparty/autoinstalled
-webkitpy_directory = os.path.dirname(__file__)
-target_directory = os.path.join(webkitpy_directory, "thirdparty",
- "autoinstalled")
-installer = AutoInstaller(target_dir=target_directory)
+import thirdparty.autoinstall as autoinstall
# List our third-party library dependencies here and where they can be
# downloaded.
-installer.install(url="http://pypi.python.org/packages/source/m/mechanize/mechanize-0.1.11.zip",
- url_subpath="mechanize")
-installer.install(url="http://pypi.python.org/packages/source/C/ClientForm/ClientForm-0.2.10.zip",
- url_subpath="ClientForm.py")
-installer.install(url="http://pypi.python.org/packages/source/p/pep8/pep8-0.5.0.tar.gz#md5=512a818af9979290cd619cce8e9c2e2b",
- url_subpath="pep8-0.5.0/pep8.py")
+autoinstall.bind("ClientForm", "http://pypi.python.org/packages/source/C/ClientForm/ClientForm-0.2.10.zip", "ClientForm-0.2.10")
+autoinstall.bind("mechanize", "http://pypi.python.org/packages/source/m/mechanize/mechanize-0.1.11.zip", "mechanize-0.1.11")
diff --git a/WebKitTools/Scripts/webkitpy/bugzilla.py b/WebKitTools/Scripts/webkitpy/bugzilla.py
index 5a21728..00e6940 100644
--- a/WebKitTools/Scripts/webkitpy/bugzilla.py
+++ b/WebKitTools/Scripts/webkitpy/bugzilla.py
@@ -45,7 +45,7 @@ from webkitpy.user import User
# so this import should always succeed.
from webkitpy.thirdparty.BeautifulSoup import BeautifulSoup, SoupStrainer
-from webkitpy.thirdparty.autoinstalled.mechanize import Browser
+from mechanize import Browser
def parse_bug_id(message):
diff --git a/WebKitTools/Scripts/webkitpy/init/__init__.py b/WebKitTools/Scripts/webkitpy/init/__init__.py
deleted file mode 100644
index ef65bee..0000000
--- a/WebKitTools/Scripts/webkitpy/init/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-# Required for Python to search this directory for module files
diff --git a/WebKitTools/Scripts/webkitpy/init/autoinstall.py b/WebKitTools/Scripts/webkitpy/init/autoinstall.py
deleted file mode 100644
index 1ead2cc..0000000
--- a/WebKitTools/Scripts/webkitpy/init/autoinstall.py
+++ /dev/null
@@ -1,432 +0,0 @@
-# Copyright (c) 2009, Daniel Krech All rights reserved.
-# Copyright (C) 2010 Chris Jerdonek (cjerdonek at webkit.org)
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-#
-# * Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# * Neither the name of the Daniel Krech nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Support for automatically downloading Python packages from an URL."""
-
-import logging
-import new
-import os
-import shutil
-import sys
-import tarfile
-import tempfile
-import urllib
-import urlparse
-import zipfile
-import zipimport
-
-_log = logging.getLogger("webkitpy.init.autoinstall")
-
-
-class AutoInstaller(object):
-
- """Supports automatically installing Python packages from an URL.
-
- Supports uncompressed files, .tar.gz, and .zip formats.
-
- Basic usage:
-
- installer = AutoInstaller()
-
- installer.install(url="http://pypi.python.org/packages/source/p/pep8/pep8-0.5.0.tar.gz#md5=512a818af9979290cd619cce8e9c2e2b",
- url_subpath="pep8-0.5.0/pep8.py")
- installer.install(url="http://pypi.python.org/packages/source/m/mechanize/mechanize-0.1.11.zip",
- url_subpath="mechanize")
-
- """
-
- def __init__(self, append_to_search_path=False, make_package=True,
- target_dir=None, temp_dir=None):
- """Create an AutoInstaller instance, and set up the target directory.
-
- Args:
- append_to_search_path: A boolean value of whether to append the
- target directory to the sys.path search path.
- make_package: A boolean value of whether to make the target
- directory a package. This adds an __init__.py file
- to the target directory -- allowing packages and
- modules within the target directory to be imported
- explicitly using dotted module names.
- target_dir: The directory path to which packages should be installed.
- Defaults to a subdirectory of the folder containing
- this module called "autoinstalled".
- temp_dir: The directory path to use for any temporary files
- generated while downloading, unzipping, and extracting
- packages to install. Defaults to a standard temporary
- location generated by the tempfile module. This
- parameter should normally be used only for development
- testing.
-
- """
- if target_dir is None:
- this_dir = os.path.dirname(__file__)
- target_dir = os.path.join(this_dir, "autoinstalled")
-
- # Ensure that the target directory exists.
- self._set_up_target_dir(target_dir, append_to_search_path, make_package)
-
- self._target_dir = target_dir
- self._temp_dir = temp_dir
-
- def _log_transfer(self, message, source, target):
- """Log a debug message that involves a source and target."""
- _log.debug("%s\n"
- ' From: "%s"\n'
- ' To: "%s"' % (message, source, target))
-
- def _write_file(self, path, text):
- """Create a file at the given path with given text.
-
- This method overwrites any existing file.
-
- """
- _log.debug('Writing file: "%s"' % path)
- file = open(path, "w")
- try:
- file.write(text)
- finally:
- file.close()
-
- def _set_up_target_dir(self, target_dir, append_to_search_path,
- make_package):
- """Set up a target directory.
-
- Args:
- target_dir: The path to the target directory to set up.
- append_to_search_path: A boolean value of whether to append the
- target directory to the sys.path search path.
- make_package: A boolean value of whether to make the target
- directory a package. This adds an __init__.py file
- to the target directory -- allowing packages and
- modules within the target directory to be imported
- explicitly using dotted module names.
-
- """
- if not os.path.exists(target_dir):
- os.makedirs(target_dir)
- _log.info('Created autoinstall package directory at: "%s".'
- % target_dir)
-
- if append_to_search_path:
- sys.path.append(target_dir)
-
- if make_package:
- init_path = os.path.join(target_dir, "__init__.py")
- if not os.path.exists(init_path):
- text = ("# This file is required for Python to search this "
- "directory for modules.\n\n")
- self._write_file(init_path, text)
-
- def _create_scratch_directory_inner(self, prefix):
- """Create a scratch directory without exception handling.
-
- Creates a scratch directory inside the AutoInstaller temp
- directory self._temp_dir, or inside a platform-dependent temp
- directory if self._temp_dir is None. Returns the path to the
- created scratch directory.
-
- Raises:
- OSError: [Errno 2] if the containing temp directory self._temp_dir
- is not None and does not exist.
-
- """
- # The tempfile.mkdtemp() method function requires that the
- # directory corresponding to the "dir" parameter already exist
- # if it is not None.
- scratch_dir = tempfile.mkdtemp(prefix=prefix, dir=self._temp_dir)
- return scratch_dir
-
- def _create_scratch_directory(self, target_name):
- """Create a temporary scratch directory, and return its path.
-
- The scratch directory is generated inside the temp directory
- of this AutoInstaller instance. This method also creates the
- temp directory if it does not already exist.
-
- """
- prefix = target_name + "_"
- try:
- scratch_dir = self._create_scratch_directory_inner(prefix)
- except OSError:
- temp_dir = self._temp_dir
- # Handle case of containing temp directory not existing--
- # OSError: [Errno 2] No such file or directory:...
- if temp_dir is None or os.path.exists(temp_dir):
- raise
- # Else try again after creating the temp directory.
- os.makedirs(temp_dir)
- _log.info('Created autoinstall temp directory at: "%s".' % temp_dir)
- scratch_dir = self._create_scratch_directory_inner(prefix)
-
- return scratch_dir
-
- def _version_path(self, target_name):
- """Return the path to the file containing the version downloaded."""
- filename = ".%s.version" % target_name
- path = os.path.join(self._target_dir, filename)
- return path
-
- def _is_downloaded(self, target_name, url):
- """Return whether a package version has been downloaded."""
- version_path = self._version_path(target_name)
-
- if not os.path.exists(version_path):
- # Then no package version has been downloaded.
- _log.debug('Version file not found: "%s"' % version_path)
- return False
-
- file = open(version_path, "r")
- try:
- version = file.read()
- finally:
- file.close()
- _log.debug('Read version "%s" from "%s".' % (version, version_path))
-
- return version.strip() == url.strip()
-
- def _write_version_downloaded(self, target_name, url):
- """Record the version downloaded to a file."""
- version_path = self._version_path(target_name)
- _log.debug('Writing version "%s" to file: "%s".'
- % (url, version_path))
-
- self._write_file(version_path, url)
-
- def _extract_targz(self, path, scratch_dir):
- # tarfile.extractall() extracts to a path without the
- # trailing ".tar.gz".
- target_basename = os.path.basename(path[:-len(".tar.gz")])
- target_path = os.path.join(scratch_dir, target_basename)
-
- self._log_transfer("Starting gunzip/extract...", path, target_path)
-
- tar_file = tarfile.open(path)
- try:
- members = tar_file.getmembers()
- _log.debug("Members of %s are: %s" % (path, members))
- tar_file.extractall(target_path)
- finally:
- tar_file.close()
-
- return target_path
-
- def _unzip(self, path, scratch_dir):
- # zipfile.extractall() extracts to a path without the
- # trailing ".zip".
- target_basename = os.path.basename(path[:-len(".zip")])
- target_path = os.path.join(scratch_dir, target_basename)
-
- self._log_transfer("Starting unzip...", path, target_path)
-
- zip_file = zipfile.ZipFile(path, "r")
- try:
- zip_file.extractall(scratch_dir)
- finally:
- zip_file.close()
-
- return target_path
-
- def _prepare_package(self, path, scratch_dir):
- """Prepare a package for use, if necessary, and return the new path.
-
- For example, this method unzips zipped files and extracts
- tar files.
-
- Args:
- path: The path to the downloaded URL contents.
- scratch_dir: The scratch directory. Note that the scratch
- directory contains the file designated by the
- path parameter.
-
- """
- # FIXME: Add other natural extensions.
- if path.endswith(".zip"):
- new_path = self._unzip(path, scratch_dir)
- elif path.endswith(".tar.gz"):
- new_path = self._extract_targz(path, scratch_dir)
- else:
- # No preparation is needed.
- new_path = path
-
- return new_path
-
- def _download_to_stream(self, url, stream):
- """Download an URL to a stream, and return the number of bytes."""
- netstream = urllib.urlopen(url)
- code = 200
- if hasattr(netstream, "getcode"):
- code = netstream.getcode()
- if not 200 <= code < 300:
- raise ValueError("HTTP Error code %s" % code)
-
- BUFSIZE = 2**13 # 8KB
- bytes = 0
- while True:
- data = netstream.read(BUFSIZE)
- if not data:
- break
- stream.write(data)
- bytes += len(data)
- netstream.close()
- return bytes
-
- def _download(self, url, scratch_dir):
- """Download URL contents, and return the download path."""
- self._log_transfer("Starting download...", url, scratch_dir)
-
- url_path = urlparse.urlsplit(url)[2]
- url_path = os.path.normpath(url_path) # Removes trailing slash.
- target_filename = os.path.basename(url_path)
- target_path = os.path.join(scratch_dir, target_filename)
-
- stream = file(target_path, "wb")
- bytes = self._download_to_stream(url, stream)
- stream.close()
-
- message = "Downloaded %s bytes..." % bytes
- self._log_transfer(message, url, target_path)
-
- return target_path
-
- def _install(self, scratch_dir, target_name, target_path, url,
- url_subpath):
- """Install a python package from an URL.
-
- This internal method overwrites the target path if the target
- path already exists.
-
- """
- path = self._download(url, scratch_dir)
- path = self._prepare_package(path, scratch_dir)
-
- if url_subpath is None:
- source_path = path
- else:
- source_path = os.path.join(path, url_subpath)
-
- if os.path.exists(target_path):
- _log.debug('Refreshing install: deleting "%s".' % target_path)
- if os.path.isdir(target_path):
- shutil.rmtree(target_path)
- else:
- os.remove(target_path)
-
- self._log_transfer("Moving into place...", source_path, target_path)
-
- # The shutil.move() command creates intermediate directories if they
- # do not exist, but we do not rely on this behavior since we
- # need to create the __init__.py file anyway.
- shutil.move(source_path, target_path)
-
- self._write_version_downloaded(target_name, url)
-
- def install(self, url, should_refresh=False, target_name=None,
- url_subpath=None):
- """Install a python package from an URL.
-
- Args:
- url: The URL from which to download the package.
-
- Optional Args:
- should_refresh: A boolean value of whether the package should be
- downloaded again if the package is already present.
- target_name: The name of the folder or file in the autoinstaller
- target directory at which the package should be
- installed. Defaults to the base name of the
- URL sub-path. This parameter must be provided if
- the URL sub-path is not specified.
- url_subpath: The relative path of the URL directory that should
- be installed. Defaults to the full directory, or
- the entire URL contents.
-
- """
- if target_name is None:
- if not url_subpath:
- raise ValueError('The "target_name" parameter must be '
- 'provided if the "url_subpath" parameter '
- "is not provided.")
- # Remove any trailing slashes.
- url_subpath = os.path.normpath(url_subpath)
- target_name = os.path.basename(url_subpath)
-
- target_path = os.path.join(self._target_dir, target_name)
- if not should_refresh and self._is_downloaded(target_name, url):
- _log.debug('URL already downloaded: skipping "%s".'
- % target_path)
- return
-
- self._log_transfer("Starting %s install..." % target_name,
- url, target_path)
-
- # The scratch directory is where we will download and prepare
- # files specific to this install until they are ready to move
- # into place.
- scratch_dir = self._create_scratch_directory(target_name)
-
- try:
- self._install(target_name=target_name,
- target_path=target_path,
- scratch_dir=scratch_dir,
- url=url,
- url_subpath=url_subpath)
- finally:
- _log.debug('Cleaning up: deleting "%s".' % scratch_dir)
- shutil.rmtree(scratch_dir)
- _log.info('Auto-installed package "%s" at: "%s".'
- % (target_name, target_path))
-
-
-if __name__=="__main__":
-
- # Configure the autoinstall logger to log DEBUG messages for
- # development testing purposes.
- console = logging.StreamHandler()
- formatter = logging.Formatter('%(name)s: [%(levelname)s] %(message)s')
- console.setFormatter(formatter)
- _log.addHandler(console)
- _log.setLevel(logging.DEBUG)
-
- # Use a more visible temp directory for debug purposes.
- this_dir = os.path.dirname(__file__)
- target_dir = os.path.join(this_dir, "autoinstalled")
- temp_dir = os.path.join(target_dir, "Temp")
-
- installer = AutoInstaller(target_dir=target_dir,
- temp_dir=temp_dir)
-
- installer.install(should_refresh=False,
- target_name="pep8.py",
- url="http://pypi.python.org/packages/source/p/pep8/pep8-0.5.0.tar.gz#md5=512a818af9979290cd619cce8e9c2e2b",
- url_subpath="pep8-0.5.0/pep8.py")
- installer.install(should_refresh=False,
- target_name="mechanize",
- url="http://pypi.python.org/packages/source/m/mechanize/mechanize-0.1.11.zip",
- url_subpath="mechanize")
-
diff --git a/WebKitTools/Scripts/webkitpy/networktransaction.py b/WebKitTools/Scripts/webkitpy/networktransaction.py
index a4c9300..65ea27d 100644
--- a/WebKitTools/Scripts/webkitpy/networktransaction.py
+++ b/WebKitTools/Scripts/webkitpy/networktransaction.py
@@ -28,7 +28,7 @@
import time
-from webkitpy.thirdparty.autoinstalled.mechanize import HTTPError
+from mechanize import HTTPError
from webkitpy.webkit_logging import log
diff --git a/WebKitTools/Scripts/webkitpy/networktransaction_unittest.py b/WebKitTools/Scripts/webkitpy/networktransaction_unittest.py
index f7cebd8..3cffe02 100644
--- a/WebKitTools/Scripts/webkitpy/networktransaction_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/networktransaction_unittest.py
@@ -28,7 +28,7 @@
import unittest
-from webkitpy.thirdparty.autoinstalled.mechanize import HTTPError
+from mechanize import HTTPError
from webkitpy.networktransaction import NetworkTransaction, NetworkTimeout
class NetworkTransactionTest(unittest.TestCase):
diff --git a/WebKitTools/Scripts/webkitpy/statusserver.py b/WebKitTools/Scripts/webkitpy/statusserver.py
index 39882ea..9a56702 100644
--- a/WebKitTools/Scripts/webkitpy/statusserver.py
+++ b/WebKitTools/Scripts/webkitpy/statusserver.py
@@ -28,7 +28,7 @@
from webkitpy.networktransaction import NetworkTransaction
from webkitpy.webkit_logging import log
-from webkitpy.thirdparty.autoinstalled.mechanize import Browser
+from mechanize import Browser
# WebKit includes a built copy of BeautifulSoup in Scripts/webkitpy/thirdparty
# so this import should always succeed.
diff --git a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstall.py b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstall.py
new file mode 100644
index 0000000..467e6b4
--- /dev/null
+++ b/WebKitTools/Scripts/webkitpy/thirdparty/autoinstall.py
@@ -0,0 +1,335 @@
+# Copyright (c) 2009, Daniel Krech All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# * Neither the name of the Daniel Krech nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""\
+package loader for auto installing Python packages.
+
+A package loader in the spirit of Zero Install that can be used to
+inject dependencies into the import process.
+
+
+To install::
+
+ easy_install -U autoinstall
+
+ or
+
+ download, unpack, python setup.py install
+
+ or
+
+ try the bootstrap loader. See below.
+
+
+To use::
+
+ # You can bind any package name to a URL pointing to something
+ # that can be imported using the zipimporter.
+
+ autoinstall.bind("pymarc", "http://pypi.python.org/packages/2.5/p/pymarc/pymarc-2.1-py2.5.egg")
+
+ import pymarc
+
+ print pymarc.__version__, pymarc.__file__
+
+
+Changelog::
+
+- added support for non top level packages.
+- cache files now use filename part from URL.
+- applied patch from Eric Seidel <eseidel at google.com> to add support
+for loading modules where the module is not at the root of the .zip
+file.
+
+
+TODO::
+
+- a description of the intended use case
+- address other issues pointed out in:
+
+ http://mail.python.org/pipermail/python-dev/2008-March/077926.html
+
+Scribbles::
+
+pull vs. push
+user vs. system
+web vs. filesystem
+auto vs. manual
+
+manage development sandboxes
+
+optional interfaces...
+
+ def get_data(pathname) -> string with file data.
+
+ Return the data associated with 'pathname'. Raise IOError if
+ the file wasn't found.");
+
+ def is_package,
+ "is_package(fullname) -> bool.
+
+ Return True if the module specified by fullname is a package.
+ Raise ZipImportError is the module couldn't be found.");
+
+ def get_code,
+ "get_code(fullname) -> code object.
+
+ Return the code object for the specified module. Raise ZipImportError
+ is the module couldn't be found.");
+
+ def get_source,
+ "get_source(fullname) -> source string.
+
+ Return the source code for the specified module. Raise ZipImportError
+ is the module couldn't be found, return None if the archive does
+ contain the module, but has no source for it.");
+
+
+Autoinstall can also be bootstraped with the nascent package loader
+bootstrap module. For example::
+
+ # or via the bootstrap
+ # loader.
+
+ try:
+ _version = "0.2"
+ import autoinstall
+ if autoinstall.__version__ != _version:
+ raise ImportError("A different version than expected found.")
+ except ImportError, e:
+ # http://svn.python.org/projects/sandbox/trunk/bootstrap/bootstrap.py
+ import bootstrap
+ pypi = "http://pypi.python.org"
+ dir = "packages/source/a/autoinstall"
+ url = "%s/%s/autoinstall-%s.tar.gz" % (pypi, dir, _version)
+ bootstrap.main((url,))
+ import autoinstall
+
+References::
+
+ http://0install.net/
+ http://www.python.org/dev/peps/pep-0302/
+ http://svn.python.org/projects/sandbox/trunk/import_in_py
+ http://0install.net/injector-find.html
+ http://roscidus.com/desktop/node/903
+
+"""
+
+# To allow use of the "with" keyword for Python 2.5 users.
+from __future__ import with_statement
+
+__version__ = "0.2"
+__docformat__ = "restructuredtext en"
+
+import os
+import new
+import sys
+import urllib
+import logging
+import tempfile
+import zipimport
+
+_logger = logging.getLogger(__name__)
+
+
+_importer = None
+
+def _getImporter():
+ global _importer
+ if _importer is None:
+ _importer = Importer()
+ sys.meta_path.append(_importer)
+ return _importer
+
+def bind(package_name, url, zip_subpath=None):
+ """bind a top level package name to a URL.
+
+ The package name should be a package name and the url should be a
+ url to something that can be imported using the zipimporter.
+
+ Optional zip_subpath parameter allows searching for modules
+ below the root level of the zip file.
+ """
+ _getImporter().bind(package_name, url, zip_subpath)
+
+
+class Cache(object):
+
+ def __init__(self, directory=None):
+ if directory is None:
+ # Default to putting the cache directory in the same directory
+ # as this file.
+ containing_directory = os.path.dirname(__file__)
+ directory = os.path.join(containing_directory, "autoinstall.cache.d");
+
+ self.directory = directory
+ try:
+ if not os.path.exists(self.directory):
+ self._create_cache_directory()
+ except Exception, err:
+ _logger.exception(err)
+ self.cache_directry = tempfile.mkdtemp()
+ _logger.info("Using cache directory '%s'." % self.directory)
+
+ def _create_cache_directory(self):
+ _logger.debug("Creating cache directory '%s'." % self.directory)
+ os.mkdir(self.directory)
+ readme_path = os.path.join(self.directory, "README")
+ with open(readme_path, "w") as f:
+ f.write("This directory was auto-generated by '%s'.\n"
+ "It is safe to delete.\n" % __file__)
+
+ def get(self, url):
+ _logger.info("Getting '%s' from cache." % url)
+ filename = url.rsplit("/")[-1]
+
+ # so that source url is significant in determining cache hits
+ d = os.path.join(self.directory, "%s" % hash(url))
+ if not os.path.exists(d):
+ os.mkdir(d)
+
+ filename = os.path.join(d, filename)
+
+ if os.path.exists(filename):
+ _logger.debug("... already cached in file '%s'." % filename)
+ else:
+ _logger.debug("... not in cache. Caching in '%s'." % filename)
+ stream = file(filename, "wb")
+ self.download(url, stream)
+ stream.close()
+ return filename
+
+ def download(self, url, stream):
+ _logger.info("Downloading: %s" % url)
+ try:
+ netstream = urllib.urlopen(url)
+ code = 200
+ if hasattr(netstream, "getcode"):
+ code = netstream.getcode()
+ if not 200 <= code < 300:
+ raise ValueError("HTTP Error code %s" % code)
+ except Exception, err:
+ _logger.exception(err)
+
+ BUFSIZE = 2**13 # 8KB
+ size = 0
+ while True:
+ data = netstream.read(BUFSIZE)
+ if not data:
+ break
+ stream.write(data)
+ size += len(data)
+ netstream.close()
+ _logger.info("Downloaded %d bytes." % size)
+
+
+class Importer(object):
+
+ def __init__(self):
+ self.packages = {}
+ self.__cache = None
+
+ def __get_store(self):
+ return self.__store
+ store = property(__get_store)
+
+ def _get_cache(self):
+ if self.__cache is None:
+ self.__cache = Cache()
+ return self.__cache
+ def _set_cache(self, cache):
+ self.__cache = cache
+ cache = property(_get_cache, _set_cache)
+
+ def find_module(self, fullname, path=None):
+ """-> self or None.
+
+ Search for a module specified by 'fullname'. 'fullname' must be
+ the fully qualified (dotted) module name. It returns the
+ zipimporter instance itself if the module was found, or None if
+ it wasn't. The optional 'path' argument is ignored -- it's
+ there for compatibility with the importer protocol.");
+ """
+ _logger.debug("find_module(%s, path=%s)" % (fullname, path))
+
+ if fullname in self.packages:
+ (url, zip_subpath) = self.packages[fullname]
+ filename = self.cache.get(url)
+ zip_path = "%s/%s" % (filename, zip_subpath) if zip_subpath else filename
+ _logger.debug("fullname: %s url: %s path: %s zip_path: %s" % (fullname, url, path, zip_path))
+ try:
+ loader = zipimport.zipimporter(zip_path)
+ _logger.debug("returning: %s" % loader)
+ except Exception, e:
+ _logger.exception(e)
+ return None
+ return loader
+ return None
+
+ def bind(self, package_name, url, zip_subpath):
+ _logger.info("binding: %s -> %s subpath: %s" % (package_name, url, zip_subpath))
+ self.packages[package_name] = (url, zip_subpath)
+
+
+if __name__=="__main__":
+ import logging
+ #logging.basicConfig()
+ logger = logging.getLogger()
+
+ console = logging.StreamHandler()
+ console.setLevel(logging.DEBUG)
+ # set a format which is simpler for console use
+ formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
+ # tell the handler to use this format
+ console.setFormatter(formatter)
+ # add the handler to the root logger
+ logger.addHandler(console)
+ logger.setLevel(logging.INFO)
+
+ bind("pymarc", "http://pypi.python.org/packages/2.5/p/pymarc/pymarc-2.1-py2.5.egg")
+
+ import pymarc
+
+ print pymarc.__version__, pymarc.__file__
+
+ assert pymarc.__version__=="2.1"
+
+ d = _getImporter().cache.directory
+ assert d in pymarc.__file__, "'%s' not found in pymarc.__file__ (%s)" % (d, pymarc.__file__)
+
+ # Can now also bind to non top level packages. The packages
+ # leading up to the package being bound will need to be defined
+ # however.
+ #
+ # bind("rdf.plugins.stores.memory",
+ # "http://pypi.python.org/packages/2.5/r/rdf.plugins.stores.memeory/rdf.plugins.stores.memory-0.9a-py2.5.egg")
+ #
+ # from rdf.plugins.stores.memory import Memory
+
+
--
WebKit Debian packaging
More information about the Pkg-webkit-commits
mailing list