home *** CD-ROM | disk | FTP | other *** search
Wrap
# Source Generated with Decompyle++ # File: in.pyc (Python 2.6) import sys import os.path as os import re import urlparse import urllib2 import shutil import random import socket import cStringIO from pkg_resources import * from distutils import log from distutils.errors import DistutilsError try: from hashlib import md5 except ImportError: from md5 import md5 from fnmatch import translate EGG_FRAGMENT = re.compile('^egg=([-A-Za-z0-9_.]+)$') HREF = re.compile('href\\s*=\\s*[\'"]?([^\'"> ]+)', re.I) PYPI_MD5 = re.compile('<a href="([^"#]+)">([^<]+)</a>\n\\s+\\(<a (?:title="MD5 hash"\n\\s+)href="[^?]+\\?:action=show_md5&digest=([0-9a-f]{32})">md5</a>\\)') URL_SCHEME = re.compile('([-+.a-z0-9]{2,}):', re.I).match EXTENSIONS = '.tar.gz .tar.bz2 .tar .zip .tgz'.split() __all__ = [ 'PackageIndex', 'distros_for_url', 'parse_bdist_wininst', 'interpret_distro_name'] def parse_bdist_wininst(name): lower = name.lower() (base, py_ver) = (None, None) if lower.endswith('.exe'): if lower.endswith('.win32.exe'): base = name[:-10] elif lower.startswith('.win32-py', -16): py_ver = name[-7:-4] base = name[:-16] return (base, py_ver) def egg_info_for_url(url): (scheme, server, path, parameters, query, fragment) = urlparse.urlparse(url) base = urllib2.unquote(path.split('/')[-1]) if '#' in base: (base, fragment) = base.split('#', 1) return (base, fragment) def distros_for_url(url, metadata = None): (base, fragment) = egg_info_for_url(url) for dist in distros_for_location(url, base, metadata): yield dist if fragment: match = EGG_FRAGMENT.match(fragment) if match: for dist in interpret_distro_name(url, match.group(1), metadata, precedence = CHECKOUT_DIST): yield dist def distros_for_location(location, basename, metadata = None): if basename.endswith('.egg.zip'): basename = basename[:-4] if basename.endswith('.egg') and '-' in basename: return [ Distribution.from_location(location, basename, metadata)] for ext in EXTENSIONS: if basename.endswith(ext): basename = basename[:-len(ext)] return interpret_distro_name(location, basename, metadata) return [] def distros_for_filename(filename, metadata = None): return distros_for_location(normalize_path(filename), os.path.basename(filename), metadata) def interpret_distro_name(location, basename, metadata, py_version = None, precedence = SOURCE_DIST, platform = None): parts = basename.split('-') if not py_version: for i, p in enumerate(parts[2:]): if len(p) == 5 and p.startswith('py2.'): return None for p in range(1, len(parts) + 1): yield Distribution(location, metadata, '-'.join(parts[:p]), '-'.join(parts[p:]), py_version = py_version, precedence = precedence, platform = platform) REL = re.compile('<([^>]*\\srel\\s*=\\s*[\'"]?([^\'">]+)[^>]*)>', re.I) def find_external_links(url, page): for match in REL.finditer(page): (tag, rel) = match.groups() rels = map(str.strip, rel.lower().split(',')) if 'homepage' in rels or 'download' in rels: for match in HREF.finditer(tag): yield urlparse.urljoin(url, htmldecode(match.group(1))) for tag in ('<th>Home Page', '<th>Download URL'): pos = page.find(tag) if pos != -1: match = HREF.search(page, pos) if match: yield urlparse.urljoin(url, htmldecode(match.group(1))) match user_agent = 'Python-urllib/%s setuptools/%s' % (urllib2.__version__, require('setuptools')[0].version) class PackageIndex(Environment): def __init__(self, index_url = 'http://pypi.python.org/simple', hosts = ('*',), *args, **kw): Environment.__init__(self, *args, **kw) self.index_url = index_url + '/'[:not index_url.endswith('/')] self.scanned_urls = { } self.fetched_urls = { } self.package_pages = { } self.allows = re.compile('|'.join(map(translate, hosts))).match self.to_scan = [] def process_url(self, url, retrieve = False): if url in self.scanned_urls and not retrieve: return None self.scanned_urls[url] = True if not URL_SCHEME(url): self.process_filename(url) return None dists = list(distros_for_url(url)) if dists and not retrieve or url in self.fetched_urls: map(self.add, dists) return None if not self.url_ok(url): self.fetched_urls[url] = True return None self.info('Reading %s', url) f = self.open_url(url, 'Download error: %s -- Some packages may not be found!') if f is None: return None if 'html' not in f.headers.get('content-type', '').lower(): f.close() return None base = f.url page = f.read() f.close() for match in HREF.finditer(page): link = urlparse.urljoin(base, htmldecode(match.group(1))) self.process_url(link) def process_filename(self, fn, nested = False): if not os.path.exists(fn): self.warn('Not found: %s', fn) return None if os.path.isdir(fn) and not nested: path = os.path.realpath(fn) for item in os.listdir(path): self.process_filename(os.path.join(path, item), True) dists = distros_for_filename(fn) if dists: self.debug('Found: %s', fn) map(self.add, dists) def url_ok(self, url, fatal = False): s = URL_SCHEME(url) if s or s.group(1).lower() == 'file' or self.allows(urlparse.urlparse(url)[1]): return True msg = '\nLink to % s ***BLOCKED*** by --allow-hosts\n' if fatal: raise DistutilsError(msg % url) fatal self.warn(msg, url) def scan_egg_links(self, search_path): for item in search_path: if os.path.isdir(item): for entry in os.listdir(item): if entry.endswith('.egg-link'): self.scan_egg_link(item, entry) continue def scan_egg_link(self, path, entry): lines = filter(None, map(str.strip, file(os.path.join(path, entry)))) if len(lines) == 2: for dist in find_distributions(os.path.join(path, lines[0])): dist.location = os.path.join(path, *lines) dist.precedence = SOURCE_DIST self.add(dist) def process_index(self, url, page): def scan(link): if link.startswith(self.index_url): parts = map(urllib2.unquote, link[len(self.index_url):].split('/')) if len(parts) == 2 and '#' not in parts[1]: pkg = safe_name(parts[0]) ver = safe_version(parts[1]) self.package_pages.setdefault(pkg.lower(), { })[link] = True return (to_filename(pkg), to_filename(ver)) return (None, None) for match in HREF.finditer(page): scan(urlparse.urljoin(url, htmldecode(match.group(1)))) (pkg, ver) = scan(url) if pkg: for new_url in find_external_links(url, page): (base, frag) = egg_info_for_url(new_url) if base.endswith('.py') and not frag: if ver: new_url += '#egg=%s-%s' % (pkg, ver) else: self.need_version_info(url) self.scan_url(new_url) return PYPI_MD5.sub((lambda m: '<a href="%s#md5=%s">%s</a>' % m.group(1, 3, 2)), page) return '' def need_version_info(self, url): self.scan_all('Page at %s links to .py file(s) without version info; an index scan is required.', url) def scan_all(self, msg = None, *args): if self.index_url not in self.fetched_urls: if msg: self.warn(msg, *args) self.info('Scanning index of all packages (this may take a while)') self.scan_url(self.index_url) def find_packages(self, requirement): self.scan_url(self.index_url + requirement.unsafe_name + '/') if not self.package_pages.get(requirement.key): self.scan_url(self.index_url + requirement.project_name + '/') if not self.package_pages.get(requirement.key): self.not_found_in_index(requirement) for url in list(self.package_pages.get(requirement.key, ())): self.scan_url(url) def obtain(self, requirement, installer = None): self.prescan() self.find_packages(requirement) for dist in self[requirement.key]: if dist in requirement: return dist self.debug('%s does not match %s', requirement, dist) return super(PackageIndex, self).obtain(requirement, installer) def check_md5(self, cs, info, filename, tfp): if re.match('md5=[0-9a-f]{32}$', info): self.debug('Validating md5 checksum for %s', filename) if cs.hexdigest() != info[4:]: tfp.close() os.unlink(filename) raise DistutilsError('MD5 validation failed for ' + os.path.basename(filename) + '; possible download problem?') cs.hexdigest() != info[4:] def add_find_links(self, urls): for url in urls: if self.to_scan is None and not URL_SCHEME(url) and url.startswith('file:') or list(distros_for_url(url)): self.scan_url(url) continue self.to_scan.append(url) def prescan(self): if self.to_scan: map(self.scan_url, self.to_scan) self.to_scan = None def not_found_in_index(self, requirement): if self[requirement.key]: meth = self.info msg = "Couldn't retrieve index page for %r" else: meth = self.warn msg = "Couldn't find index page for %r (maybe misspelled?)" meth(msg, requirement.unsafe_name) self.scan_all() def download(self, spec, tmpdir): if not isinstance(spec, Requirement): scheme = URL_SCHEME(spec) if scheme: found = self._download_url(scheme.group(1), spec, tmpdir) (base, fragment) = egg_info_for_url(spec) if base.endswith('.py'): found = self.gen_setup(found, fragment, tmpdir) return found if os.path.exists(spec): return spec try: spec = Requirement.parse(spec) except ValueError: os.path.exists(spec) os.path.exists(spec) scheme raise DistutilsError('Not a URL, existing file, or requirement spec: %r' % (spec,)) except: os.path.exists(spec)<EXCEPTION MATCH>ValueError os.path.exists(spec) return getattr(self.fetch_distribution(spec, tmpdir), 'location', None) def fetch_distribution(self, requirement, tmpdir, force_scan = False, source = False, develop_ok = False): self.info('Searching for %s', requirement) skipped = { } def find(req): for dist in self[req.key]: if dist.precedence == DEVELOP_DIST and not develop_ok: if dist not in skipped: self.warn('Skipping development or system egg: %s', dist) skipped[dist] = 1 continue continue if dist in req: if dist.precedence <= SOURCE_DIST or not source: self.info('Best match: %s', dist) return dist.clone(location = self.download(dist.location, tmpdir)) if force_scan: self.prescan() self.find_packages(requirement) dist = find(requirement) if dist is None and self.to_scan is not None: self.prescan() dist = find(requirement) if dist is None and not force_scan: self.find_packages(requirement) dist = find(requirement) if dist is None: if not source or 'a source distribution of ': pass self.warn('No local packages or download links found for %s%s', '', requirement) return dist def fetch(self, requirement, tmpdir, force_scan = False, source = False): dist = self.fetch_distribution(requirement, tmpdir, force_scan, source) if dist is not None: return dist.location def gen_setup(self, filename, fragment, tmpdir): match = EGG_FRAGMENT.match(fragment) if not match or _[1]: pass dists = [] if len(dists) == 1: basename = os.path.basename(filename) file = open(os.path.join(tmpdir, 'setup.py'), 'w') file.write('from setuptools import setup\nsetup(name=%r, version=%r, py_modules=[%r])\n' % (dists[0].project_name, dists[0].version, os.path.splitext(basename)[0])) file.close() return filename if match: raise DistutilsError("Can't unambiguously interpret project/version identifier %r; any dashes in the name or version should be escaped using underscores. %r" % (fragment, dists)) match raise DistutilsError("Can't process plain .py files without an '#egg=name-version' suffix to enable automatic setup script generation.") dl_blocksize = 8192 def _download_to(self, url, filename): self.info('Downloading %s', url) (fp, tfp, info) = (None, None, None) try: if '#' in url: (url, info) = url.split('#', 1) fp = self.open_url(url) if isinstance(fp, urllib2.HTTPError): raise DistutilsError("Can't download %s: %s %s" % (url, fp.code, fp.msg)) isinstance(fp, urllib2.HTTPError) cs = md5() headers = fp.info() blocknum = 0 bs = self.dl_blocksize size = -1 if 'content-length' in headers: size = int(headers['Content-Length']) self.reporthook(url, filename, blocknum, bs, size) tfp = open(filename, 'wb') while True: block = fp.read(bs) if block: cs.update(block) tfp.write(block) blocknum += 1 self.reporthook(url, filename, blocknum, bs, size) continue break if info: self.check_md5(cs, info, filename, tfp) return headers finally: if fp: fp.close() if tfp: tfp.close() def reporthook(self, url, filename, blocknum, blksize, size): pass def open_url(self, url, warning = None): if url.startswith('file:'): return local_open(url) try: return open_with_auth(url) except urllib2.HTTPError: url.startswith('file:') v = url.startswith('file:') return v except urllib2.URLError: v = None if warning: self.warn(warning, v.reason) else: raise DistutilsError('Download error for %s: %s' % (url, v.reason)) warning else: return None def _download_url(self, scheme, url, tmpdir): name = filter(None, urlparse.urlparse(url)[2].split('/')) if name: name = name[-1] while '..' in name: name = name.replace('..', '.').replace('\\', '_') else: name = '__downloaded__' if name.endswith('.egg.zip'): name = name[:-4] filename = os.path.join(tmpdir, name) if scheme == 'svn' or scheme.startswith('svn+'): return self._download_svn(url, filename) if scheme == 'file': return urllib2.url2pathname(urlparse.urlparse(url)[2]) self.url_ok(url, True) return self._attempt_download(url, filename) def scan_url(self, url): self.process_url(url, True) def _attempt_download(self, url, filename): headers = self._download_to(url, filename) if 'html' in headers.get('content-type', '').lower(): return self._download_html(url, headers, filename) return filename def _download_html(self, url, headers, filename): file = open(filename) for line in file: if line.strip(): if re.search('<title>([^- ]+ - )?Revision \\d+:', line): file.close() os.unlink(filename) return self._download_svn(url, filename) break continue re.search('<title>([^- ]+ - )?Revision \\d+:', line) file.close() os.unlink(filename) raise DistutilsError('Unexpected HTML page found at ' + url) def _download_svn(self, url, filename): url = url.split('#', 1)[0] self.info('Doing subversion checkout from %s to %s', url, filename) os.system('svn checkout -q %s %s' % (url, filename)) return filename def debug(self, msg, *args): log.debug(msg, *args) def info(self, msg, *args): log.info(msg, *args) def warn(self, msg, *args): log.warn(msg, *args) entity_sub = re.compile('&(#(\\d+|x[\\da-fA-F]+)|[\\w.:-]+);?').sub def uchr(c): if not isinstance(c, int): return c if c > 255: return unichr(c) return chr(c) def decode_entity(match): what = match.group(1) if what.startswith('#x'): what = int(what[2:], 16) elif what.startswith('#'): what = int(what[1:]) else: name2codepoint = name2codepoint import htmlentitydefs what = name2codepoint.get(what, match.group(0)) return uchr(what) def htmldecode(text): return entity_sub(decode_entity, text) def open_with_auth(url): (scheme, netloc, path, params, query, frag) = urlparse.urlparse(url) if scheme in ('http', 'https'): (auth, host) = urllib2.splituser(netloc) else: auth = None if auth: auth = 'Basic ' + urllib2.unquote(auth).encode('base64').strip() new_url = urlparse.urlunparse((scheme, host, path, params, query, frag)) request = urllib2.Request(new_url) request.add_header('Authorization', auth) else: request = urllib2.Request(url) request.add_header('User-Agent', user_agent) fp = urllib2.urlopen(request) if auth: (s2, h2, path2, param2, query2, frag2) = urlparse.urlparse(fp.url) if s2 == scheme and h2 == host: fp.url = urlparse.urlunparse((s2, netloc, path2, param2, query2, frag2)) return fp def fix_sf_url(url): return url def local_open(url): (scheme, server, path, param, query, frag) = urlparse.urlparse(url) filename = urllib2.url2pathname(path) if os.path.isfile(filename): return urllib2.urlopen(url) return urllib2.HTTPError(url, status, message, { 'content-type': 'text/html' }, cStringIO.StringIO(body))