Created
November 18, 2015 23:59
-
-
Save gcmurphy/8b92d55aaf32b0843785 to your computer and use it in GitHub Desktop.
Download all potential satisfying dependencies as per a requirements.txt file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import distlib | |
import distlib.index | |
import distlib.version | |
import requests | |
import pip.req | |
import pip.download | |
import os | |
import sys | |
import urlparse | |
import logging as LOG | |
LOG.basicConfig(level=LOG.INFO, format='%(asctime)s - %(levelname)s - %(message)s') | |
PACKAGE_INDEX = 'https://pypi.python.org/pypi' | |
DOWNLOAD_DIR = "downloads" | |
def package_info(pkg): | |
r = requests.get('{}/{}/json'.format(PACKAGE_INDEX, pkg)) | |
if not r.status_code == 200: | |
return r.status_code, r.request.url | |
data = r.json() | |
if not 'name' in data: | |
data['name'] = pkg | |
return data | |
def candidates(pkg_info, needed): | |
results = set() | |
name = pkg_info['name'] | |
versions = pkg_info['releases'].keys() | |
if not needed: | |
return set(versions) | |
version_str = "{} ({})".format(name, needed) | |
satisfier = distlib.version.NormalizedMatcher(version_str) | |
for version in versions: | |
try: | |
if satisfier.match(distlib.version.NormalizedVersion(version)): | |
results.add(version) | |
except distlib.version.UnsupportedVersionError: | |
LOG.warn("%s is an unsupported version format for %s", version, name) | |
LOG.info("%s of %s are candidates for %s", len(results), len(versions), name) | |
return results | |
def download_urls(pkg_info, candidates): | |
for version in candidates: | |
release = pkg_info['releases'][version] | |
for item in release: | |
if 'url' in item: | |
yield item['url'] | |
def download(url): | |
filename = os.path.join(DOWNLOAD_DIR, url.split('/')[-1]) | |
r = requests.get(url, stream=True) | |
with open(filename, 'wb') as out: | |
for chunk in r.iter_content(chunk_size=8192): | |
if chunk: | |
out.write(chunk) | |
return filename | |
def dependencies(requirements_txt): | |
session = pip.download.PipSession() | |
for requirement in pip.req.parse_requirements(requirements_txt, session=session): | |
yield(requirement.name, str(requirement.specifier)) | |
if __name__ == "__main__": | |
if not os.path.exists(DOWNLOAD_DIR): | |
os.makedirs(DOWNLOAD_DIR) | |
for arg in sys.argv[1:]: | |
LOG.info("Reading requirements from: %s", arg) | |
for pkg, spec in dependencies(arg): | |
info = package_info(pkg) | |
versions = candidates(info, spec) | |
for url in download_urls(info, versions): | |
outfile = download(url) | |
LOG.info("%s saved to %s", url, outfile) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment