summaryrefslogtreecommitdiff
path: root/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/download.py
diff options
context:
space:
mode:
authorNishanth Amuluru2011-01-08 11:20:57 +0530
committerNishanth Amuluru2011-01-08 11:20:57 +0530
commit65411d01d448ff0cd4abd14eee14cf60b5f8fc20 (patch)
treeb4c404363c4c63a61d6e2f8bd26c5b057c1fb09d /eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/download.py
parent2e35094d43b4cc6974172e1febf76abb50f086ec (diff)
downloadpytask-65411d01d448ff0cd4abd14eee14cf60b5f8fc20.tar.gz
pytask-65411d01d448ff0cd4abd14eee14cf60b5f8fc20.tar.bz2
pytask-65411d01d448ff0cd4abd14eee14cf60b5f8fc20.zip
Added buildout stuff and made changes accordingly
--HG-- rename : profile/management/__init__.py => eggs/djangorecipe-0.20-py2.6.egg/EGG-INFO/dependency_links.txt rename : profile/management/__init__.py => eggs/djangorecipe-0.20-py2.6.egg/EGG-INFO/not-zip-safe rename : profile/management/__init__.py => eggs/infrae.subversion-1.4.5-py2.6.egg/EGG-INFO/dependency_links.txt rename : profile/management/__init__.py => eggs/infrae.subversion-1.4.5-py2.6.egg/EGG-INFO/not-zip-safe rename : profile/management/__init__.py => eggs/mercurial-1.7.3-py2.6-linux-x86_64.egg/EGG-INFO/dependency_links.txt rename : profile/management/__init__.py => eggs/mercurial-1.7.3-py2.6-linux-x86_64.egg/EGG-INFO/not-zip-safe rename : profile/management/__init__.py => eggs/py-1.4.0-py2.6.egg/EGG-INFO/dependency_links.txt rename : profile/management/__init__.py => eggs/py-1.4.0-py2.6.egg/EGG-INFO/not-zip-safe rename : profile/management/__init__.py => eggs/zc.buildout-1.5.2-py2.6.egg/EGG-INFO/dependency_links.txt rename : profile/management/__init__.py => eggs/zc.buildout-1.5.2-py2.6.egg/EGG-INFO/not-zip-safe rename : profile/management/__init__.py => eggs/zc.recipe.egg-1.3.2-py2.6.egg/EGG-INFO/dependency_links.txt rename : profile/management/__init__.py => eggs/zc.recipe.egg-1.3.2-py2.6.egg/EGG-INFO/not-zip-safe rename : profile/management/__init__.py => parts/django/Django.egg-info/dependency_links.txt rename : taskapp/models.py => parts/django/django/conf/app_template/models.py rename : taskapp/tests.py => parts/django/django/conf/app_template/tests.py rename : taskapp/views.py => parts/django/django/conf/app_template/views.py rename : taskapp/views.py => parts/django/django/contrib/gis/tests/geo3d/views.py rename : profile/management/__init__.py => parts/django/tests/modeltests/delete/__init__.py rename : profile/management/__init__.py => parts/django/tests/modeltests/files/__init__.py rename : profile/management/__init__.py => parts/django/tests/modeltests/invalid_models/__init__.py rename : profile/management/__init__.py => parts/django/tests/modeltests/m2m_signals/__init__.py rename : profile/management/__init__.py => parts/django/tests/modeltests/model_package/__init__.py rename : profile/management/__init__.py => parts/django/tests/regressiontests/bash_completion/__init__.py rename : profile/management/__init__.py => parts/django/tests/regressiontests/bash_completion/management/__init__.py rename : profile/management/__init__.py => parts/django/tests/regressiontests/bash_completion/management/commands/__init__.py rename : profile/management/__init__.py => parts/django/tests/regressiontests/bash_completion/models.py rename : profile/management/__init__.py => parts/django/tests/regressiontests/delete_regress/__init__.py rename : profile/management/__init__.py => parts/django/tests/regressiontests/file_storage/__init__.py rename : profile/management/__init__.py => parts/django/tests/regressiontests/max_lengths/__init__.py rename : profile/forms.py => pytask/profile/forms.py rename : profile/management/__init__.py => pytask/profile/management/__init__.py rename : profile/management/commands/seed_db.py => pytask/profile/management/commands/seed_db.py rename : profile/models.py => pytask/profile/models.py rename : profile/templatetags/user_tags.py => pytask/profile/templatetags/user_tags.py rename : taskapp/tests.py => pytask/profile/tests.py rename : profile/urls.py => pytask/profile/urls.py rename : profile/utils.py => pytask/profile/utils.py rename : profile/views.py => pytask/profile/views.py rename : static/css/base.css => pytask/static/css/base.css rename : taskapp/tests.py => pytask/taskapp/tests.py rename : taskapp/views.py => pytask/taskapp/views.py rename : templates/base.html => pytask/templates/base.html rename : templates/profile/browse_notifications.html => pytask/templates/profile/browse_notifications.html rename : templates/profile/edit.html => pytask/templates/profile/edit.html rename : templates/profile/view.html => pytask/templates/profile/view.html rename : templates/profile/view_notification.html => pytask/templates/profile/view_notification.html rename : templates/registration/activate.html => pytask/templates/registration/activate.html rename : templates/registration/activation_email.txt => pytask/templates/registration/activation_email.txt rename : templates/registration/activation_email_subject.txt => pytask/templates/registration/activation_email_subject.txt rename : templates/registration/logged_out.html => pytask/templates/registration/logged_out.html rename : templates/registration/login.html => pytask/templates/registration/login.html rename : templates/registration/logout.html => pytask/templates/registration/logout.html rename : templates/registration/password_change_done.html => pytask/templates/registration/password_change_done.html rename : templates/registration/password_change_form.html => pytask/templates/registration/password_change_form.html rename : templates/registration/password_reset_complete.html => pytask/templates/registration/password_reset_complete.html rename : templates/registration/password_reset_confirm.html => pytask/templates/registration/password_reset_confirm.html rename : templates/registration/password_reset_done.html => pytask/templates/registration/password_reset_done.html rename : templates/registration/password_reset_email.html => pytask/templates/registration/password_reset_email.html rename : templates/registration/password_reset_form.html => pytask/templates/registration/password_reset_form.html rename : templates/registration/registration_complete.html => pytask/templates/registration/registration_complete.html rename : templates/registration/registration_form.html => pytask/templates/registration/registration_form.html rename : utils.py => pytask/utils.py
Diffstat (limited to 'eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/download.py')
-rw-r--r--eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/download.py251
1 files changed, 251 insertions, 0 deletions
diff --git a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/download.py b/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/download.py
new file mode 100644
index 0000000..3d1295b
--- /dev/null
+++ b/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/download.py
@@ -0,0 +1,251 @@
+##############################################################################
+#
+# Copyright (c) 2009 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Buildout download infrastructure"""
+
+try:
+ from hashlib import md5
+except ImportError:
+ from md5 import new as md5
+from zc.buildout.easy_install import realpath
+import logging
+import os
+import os.path
+import re
+import shutil
+import tempfile
+import urllib
+import urlparse
+import zc.buildout
+
+
+class URLOpener(urllib.FancyURLopener):
+ http_error_default = urllib.URLopener.http_error_default
+
+
+class ChecksumError(zc.buildout.UserError):
+ pass
+
+
+url_opener = URLOpener()
+
+
+class Download(object):
+ """Configurable download utility.
+
+ Handles the download cache and offline mode.
+
+ Download(options=None, cache=None, namespace=None, hash_name=False)
+
+ options: mapping of buildout options (e.g. a ``buildout`` config section)
+ cache: path to the download cache (excluding namespaces)
+ namespace: namespace directory to use inside the cache
+ hash_name: whether to use a hash of the URL as cache file name
+ logger: an optional logger to receive download-related log messages
+
+ """
+
+ def __init__(self, options={}, cache=-1, namespace=None,
+ offline=-1, fallback=False, hash_name=False, logger=None):
+ self.directory = options.get('directory', '')
+ self.cache = cache
+ if cache == -1:
+ self.cache = options.get('download-cache')
+ self.namespace = namespace
+ self.offline = offline
+ if offline == -1:
+ self.offline = (options.get('offline') == 'true'
+ or options.get('install-from-cache') == 'true')
+ self.fallback = fallback
+ self.hash_name = hash_name
+ self.logger = logger or logging.getLogger('zc.buildout')
+
+ @property
+ def download_cache(self):
+ if self.cache is not None:
+ return realpath(os.path.join(self.directory, self.cache))
+
+ @property
+ def cache_dir(self):
+ if self.download_cache is not None:
+ return os.path.join(self.download_cache, self.namespace or '')
+
+ def __call__(self, url, md5sum=None, path=None):
+ """Download a file according to the utility's configuration.
+
+ url: URL to download
+ md5sum: MD5 checksum to match
+ path: where to place the downloaded file
+
+ Returns the path to the downloaded file.
+
+ """
+ if self.cache:
+ local_path, is_temp = self.download_cached(url, md5sum)
+ else:
+ local_path, is_temp = self.download(url, md5sum, path)
+
+ return locate_at(local_path, path), is_temp
+
+ def download_cached(self, url, md5sum=None):
+ """Download a file from a URL using the cache.
+
+ This method assumes that the cache has been configured. Optionally, it
+ raises a ChecksumError if a cached copy of a file has an MD5 mismatch,
+ but will not remove the copy in that case.
+
+ """
+ if not os.path.exists(self.download_cache):
+ raise zc.buildout.UserError(
+ 'The directory:\n'
+ '%r\n'
+ "to be used as a download cache doesn't exist.\n"
+ % self.download_cache)
+ cache_dir = self.cache_dir
+ if not os.path.exists(cache_dir):
+ os.mkdir(cache_dir)
+ cache_key = self.filename(url)
+ cached_path = os.path.join(cache_dir, cache_key)
+
+ self.logger.debug('Searching cache at %s' % cache_dir)
+ if os.path.isfile(cached_path):
+ is_temp = False
+ if self.fallback:
+ try:
+ _, is_temp = self.download(url, md5sum, cached_path)
+ except ChecksumError:
+ raise
+ except Exception:
+ pass
+
+ if not check_md5sum(cached_path, md5sum):
+ raise ChecksumError(
+ 'MD5 checksum mismatch for cached download '
+ 'from %r at %r' % (url, cached_path))
+ self.logger.debug('Using cache file %s' % cached_path)
+ else:
+ self.logger.debug('Cache miss; will cache %s as %s' %
+ (url, cached_path))
+ _, is_temp = self.download(url, md5sum, cached_path)
+
+ return cached_path, is_temp
+
+ def download(self, url, md5sum=None, path=None):
+ """Download a file from a URL to a given or temporary path.
+
+ An online resource is always downloaded to a temporary file and moved
+ to the specified path only after the download is complete and the
+ checksum (if given) matches. If path is None, the temporary file is
+ returned and the client code is responsible for cleaning it up.
+
+ """
+ if re.match(r"^[A-Za-z]:\\", url):
+ url = 'file:' + url
+ parsed_url = urlparse.urlparse(url, 'file')
+ url_scheme, _, url_path = parsed_url[:3]
+ if url_scheme == 'file':
+ self.logger.debug('Using local resource %s' % url)
+ if not check_md5sum(url_path, md5sum):
+ raise ChecksumError(
+ 'MD5 checksum mismatch for local resource at %r.' %
+ url_path)
+ return locate_at(url_path, path), False
+
+ if self.offline:
+ raise zc.buildout.UserError(
+ "Couldn't download %r in offline mode." % url)
+
+ self.logger.info('Downloading %s' % url)
+ urllib._urlopener = url_opener
+ handle, tmp_path = tempfile.mkstemp(prefix='buildout-')
+ try:
+ try:
+ tmp_path, headers = urllib.urlretrieve(url, tmp_path)
+ if not check_md5sum(tmp_path, md5sum):
+ raise ChecksumError(
+ 'MD5 checksum mismatch downloading %r' % url)
+ finally:
+ os.close(handle)
+ except:
+ os.remove(tmp_path)
+ raise
+
+ if path:
+ shutil.move(tmp_path, path)
+ return path, False
+ else:
+ return tmp_path, True
+
+ def filename(self, url):
+ """Determine a file name from a URL according to the configuration.
+
+ """
+ if self.hash_name:
+ return md5(url).hexdigest()
+ else:
+ if re.match(r"^[A-Za-z]:\\", url):
+ url = 'file:' + url
+ parsed = urlparse.urlparse(url, 'file')
+ url_path = parsed[2]
+
+ if parsed[0] == 'file':
+ while True:
+ url_path, name = os.path.split(url_path)
+ if name:
+ return name
+ if not url_path:
+ break
+ else:
+ for name in reversed(url_path.split('/')):
+ if name:
+ return name
+
+ url_host, url_port = parsed[-2:]
+ return '%s:%s' % (url_host, url_port)
+
+
+def check_md5sum(path, md5sum):
+ """Tell whether the MD5 checksum of the file at path matches.
+
+ No checksum being given is considered a match.
+
+ """
+ if md5sum is None:
+ return True
+
+ f = open(path, 'rb')
+ checksum = md5()
+ try:
+ chunk = f.read(2**16)
+ while chunk:
+ checksum.update(chunk)
+ chunk = f.read(2**16)
+ return checksum.hexdigest() == md5sum
+ finally:
+ f.close()
+
+
+def remove(path):
+ if os.path.exists(path):
+ os.remove(path)
+
+
+def locate_at(source, dest):
+ if dest is None or realpath(dest) == realpath(source):
+ return source
+
+ try:
+ os.link(source, dest)
+ except (AttributeError, OSError):
+ shutil.copyfile(source, dest)
+ return dest