[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:03:08 UTC 2010


The following commit has been merged in the webkit-1.2 branch:
commit 25cd1efd1f859ff314c2ab42e8c1487fb42f1d14
Author: cjerdonek at webkit.org <cjerdonek at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Sat Feb 27 08:04:48 2010 +0000

    Rewrote autoinstall.py to support unzipping *.zip files after
    download, unzipping and extracting *.tar.gz files after download,
    and copying installed files to a destination directory.
    
    Reviewed by David Levin.
    
    https://bugs.webkit.org/show_bug.cgi?id=35163
    
    These changes will allow us to autoinstall pep8.py from the web
    and to put our third-party autoinstalled code in an explicit
    directory like webkitpy/thirdparty/autoinstalled. They should
    also speed up imports from autoinstalled *.zip packages slightly
    since *.pyc files cannot be generated when importing from
    zipped packages.
    
    * Scripts/webkitpy/__init__.py:
      - Updated the autoinstall lines to use the new autoinstall methods.
      - Added pep8.py to the list of auto-installed packages.
    
    * Scripts/webkitpy/bugzilla.py:
      - Updated mechanize import path.
    
    * Scripts/webkitpy/init/__init__.py: Copied from WebKitTools/QueueStatusServer/filters/__init__.py.
    
    * Scripts/webkitpy/init/autoinstall.py: Added.
      - Added AutoInstaller class.
      - Added sample testing usage to __main__.
    
    * Scripts/webkitpy/networktransaction.py:
      - Updated mechanize import path.
    
    * Scripts/webkitpy/networktransaction_unittest.py:
      - Updated mechanize import path.
    
    * Scripts/webkitpy/statusserver.py:
      - Updated mechanize import path.
    
    * Scripts/webkitpy/thirdparty/autoinstall.py: Removed.
      - Replaced with rewritten autoinstall in init/autoinstall.py.
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@55348 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/WebKitTools/ChangeLog b/WebKitTools/ChangeLog
index 00c5dc3..54a8eea 100644
--- a/WebKitTools/ChangeLog
+++ b/WebKitTools/ChangeLog
@@ -1,3 +1,45 @@
+2010-02-26  Chris Jerdonek  <cjerdonek at webkit.org>
+
+        Reviewed by David Levin.
+
+        Rewrote autoinstall.py to support unzipping *.zip files after
+        download, unzipping and extracting *.tar.gz files after download,
+        and copying installed files to a destination directory.
+
+        https://bugs.webkit.org/show_bug.cgi?id=35163
+
+        These changes will allow us to autoinstall pep8.py from the web
+        and to put our third-party autoinstalled code in an explicit
+        directory like webkitpy/thirdparty/autoinstalled. They should
+        also speed up imports from autoinstalled *.zip packages slightly
+        since *.pyc files cannot be generated when importing from
+        zipped packages.
+
+        * Scripts/webkitpy/__init__.py:
+          - Updated the autoinstall lines to use the new autoinstall methods.
+          - Added pep8.py to the list of auto-installed packages.
+
+        * Scripts/webkitpy/bugzilla.py:
+          - Updated mechanize import path.
+
+        * Scripts/webkitpy/init/__init__.py: Copied from WebKitTools/QueueStatusServer/filters/__init__.py.
+
+        * Scripts/webkitpy/init/autoinstall.py: Added.
+          - Added AutoInstaller class.
+          - Added sample testing usage to __main__.
+
+        * Scripts/webkitpy/networktransaction.py:
+          - Updated mechanize import path.
+
+        * Scripts/webkitpy/networktransaction_unittest.py:
+          - Updated mechanize import path.
+
+        * Scripts/webkitpy/statusserver.py:
+          - Updated mechanize import path.
+
+        * Scripts/webkitpy/thirdparty/autoinstall.py: Removed.
+          - Replaced with rewritten autoinstall in init/autoinstall.py.
+
 2010-02-26  Dirk Pranke  <dpranke at chromium.org>
 
         Reviewed by Adam Barth.
diff --git a/WebKitTools/Scripts/webkitpy/__init__.py b/WebKitTools/Scripts/webkitpy/__init__.py
index efa8c7a..c3dd7bf 100644
--- a/WebKitTools/Scripts/webkitpy/__init__.py
+++ b/WebKitTools/Scripts/webkitpy/__init__.py
@@ -1,8 +1,22 @@
 # Required for Python to search this directory for module files
 
-import thirdparty.autoinstall as autoinstall
+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)
 
 # List our third-party library dependencies here and where they can be
 # downloaded.
-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")
+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")
diff --git a/WebKitTools/Scripts/webkitpy/bugzilla.py b/WebKitTools/Scripts/webkitpy/bugzilla.py
index 00e6940..5a21728 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 mechanize import Browser
+from webkitpy.thirdparty.autoinstalled.mechanize import Browser
 
 
 def parse_bug_id(message):
diff --git a/WebKitTools/QueueStatusServer/filters/__init__.py b/WebKitTools/Scripts/webkitpy/init/__init__.py
similarity index 100%
copy from WebKitTools/QueueStatusServer/filters/__init__.py
copy to WebKitTools/Scripts/webkitpy/init/__init__.py
diff --git a/WebKitTools/Scripts/webkitpy/init/autoinstall.py b/WebKitTools/Scripts/webkitpy/init/autoinstall.py
new file mode 100644
index 0000000..1ead2cc
--- /dev/null
+++ b/WebKitTools/Scripts/webkitpy/init/autoinstall.py
@@ -0,0 +1,432 @@
+# 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 65ea27d..a4c9300 100644
--- a/WebKitTools/Scripts/webkitpy/networktransaction.py
+++ b/WebKitTools/Scripts/webkitpy/networktransaction.py
@@ -28,7 +28,7 @@
 
 import time
 
-from mechanize import HTTPError
+from webkitpy.thirdparty.autoinstalled.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 3cffe02..f7cebd8 100644
--- a/WebKitTools/Scripts/webkitpy/networktransaction_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/networktransaction_unittest.py
@@ -28,7 +28,7 @@
 
 import unittest
 
-from mechanize import HTTPError
+from webkitpy.thirdparty.autoinstalled.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 9a56702..39882ea 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 mechanize import Browser
+from webkitpy.thirdparty.autoinstalled.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
deleted file mode 100644
index 467e6b4..0000000
--- a/WebKitTools/Scripts/webkitpy/thirdparty/autoinstall.py
+++ /dev/null
@@ -1,335 +0,0 @@
-# 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