diff options
author | Nishanth Amuluru | 2011-01-08 11:20:57 +0530 |
---|---|---|
committer | Nishanth Amuluru | 2011-01-08 11:20:57 +0530 |
commit | 65411d01d448ff0cd4abd14eee14cf60b5f8fc20 (patch) | |
tree | b4c404363c4c63a61d6e2f8bd26c5b057c1fb09d /eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/download.py | |
parent | 2e35094d43b4cc6974172e1febf76abb50f086ec (diff) | |
download | pytask-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.py | 251 |
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 |