def fetch_dist(self, dist, fetch_dir, force=False, check_md5=False, dry_run=False): """ Get a distribution, i.e. copy or download the distribution into fetch_dir. force: force download or copy check_md5: when determining if a file needs to be downloaded or copied, check it's MD5. This is, of course, slower but more reliable then just checking the file-size (which always done first). Note: * This option has option has nothing to do with checking the MD5 of a download. The md5 is always checked when files are downloaded (regardless of this option). * If force=True, this option is has no effect, because the file is forcefully downloaded, ignoring any existing file (as well as the MD5). """ md5 = self.index[dist].get('md5', None) size = self.index[dist].get('size', None) fn = dist_naming.filename_dist(dist) dst = join(fetch_dir, fn) # if force is not used, see if (i) the file exists (ii) its size is # the expected (iii) optionally, make sure the md5 is the expected. if (not force and isfile(dst) and getsize(dst) == size and (not check_md5 or md5_file(dst) == md5)): if self.verbose: print "Not forcing refetch, %r already exists" % dst return pprint_fn_action(fn, ['copying', 'downloading'][dist.startswith('http://')]) if dry_run: return if self.verbose: print "Copying: %r" % dist print " to: %r" % dst fo = open(dst + '.part', 'wb') write_data_from_url(fo, dist, md5, size) fo.close() rm_rf(dst) os.rename(dst + '.part', dst)
def fetch_dist(self, dist, fetch_dir, force=False, check_md5=False, dry_run=False): """ Get a distribution, i.e. copy or download the distribution into fetch_dir. force: force download or copy check_md5: when determining if a file needs to be downloaded or copied, check it's MD5. This is, of course, slower but more reliable then just checking the file-size (which is always done first). Note: * This option has nothing to do with checking the MD5 of the download. The md5 is always checked when files are downloaded (regardless of this option). * If force=True, this option is has no effect, because the file is forcefully downloaded, ignoring any existing file (as well as the MD5). """ md5 = self.index[dist].get('md5') size = self.index[dist].get('size') fn = dist_naming.filename_dist(dist) dst = join(fetch_dir, fn) # if force is not used, see if (i) the file exists (ii) its size is # the expected (iii) optionally, make sure the md5 is the expected. if (not force and isfile(dst) and getsize(dst) == size and (not check_md5 or md5_file(dst) == md5)): if self.verbose: print "Not forcing refetch, %r already exists" % dst return self.file_action_callback(fn, ('copying', 'downloading') [dist.startswith(('http://', 'https://'))]) if dry_run: return if self.verbose: print "Copying: %r" % dist print " to: %r" % dst fo = open(dst + '.part', 'wb') write_data_from_url(fo, dist, md5, size, progress_callback=self.download_progress_callback) fo.close() rm_rf(dst) os.rename(dst + '.part', dst)
def determine_install_order(self, dists): """ given the distributions 'dists' (which are already complete, i.e. the for each distribution all dependencies are also included in the 'dists'), return a list of the same distribution in the correct install order """ dists = list(dists) assert self.are_complete(dists) # make sure each project name is listed only once assert len(dists) == len(set(self.cname_dist(d) for d in dists)) # the distributions corresponding to the requirements must be sorted # because the output of this function is otherwise not deterministic dists.sort(key=self.cname_dist) # maps dist -> set of required (project) names rns = {} for dist in dists: rns[dist] = set(r.name for r in self.reqs_dist(dist)) # as long as we have things missing, simply look for things which # can be added, i.e. all the requirements have been added already result = [] names_inst = set() while len(result) < len(dists): n = len(result) for dist in dists: if dist in result: continue # see if all required packages were added already if all(bool(name in names_inst) for name in rns[dist]): result.append(dist) names_inst.add(self.index[dist]['cname']) assert len(names_inst) == len(result) if len(result) == n: # nothing was added raise Exception("Loop in dependency graph\n%r" % [dist_naming.filename_dist(d) for d in dists]) return result
def dist_as_req(dist, strictness=3): """ Return the distribution in terms of the a requirement object. That is: What requirement gives me the distribution? """ return filename_as_req(filename_dist(dist), strictness)