diff options
Diffstat (limited to 'venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/operations/freeze.py')
| -rw-r--r-- | venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/operations/freeze.py | 252 |
1 files changed, 252 insertions, 0 deletions
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/operations/freeze.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/operations/freeze.py new file mode 100644 index 0000000..000102d --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_internal/operations/freeze.py | |||
| @@ -0,0 +1,252 @@ | |||
| 1 | from __future__ import absolute_import | ||
| 2 | |||
| 3 | import collections | ||
| 4 | import logging | ||
| 5 | import os | ||
| 6 | import re | ||
| 7 | import warnings | ||
| 8 | |||
| 9 | from pip._vendor import pkg_resources, six | ||
| 10 | from pip._vendor.packaging.utils import canonicalize_name | ||
| 11 | from pip._vendor.pkg_resources import RequirementParseError | ||
| 12 | |||
| 13 | from pip._internal.exceptions import InstallationError | ||
| 14 | from pip._internal.req import InstallRequirement | ||
| 15 | from pip._internal.req.req_file import COMMENT_RE | ||
| 16 | from pip._internal.utils.deprecation import RemovedInPip11Warning | ||
| 17 | from pip._internal.utils.misc import ( | ||
| 18 | dist_is_editable, get_installed_distributions, | ||
| 19 | ) | ||
| 20 | |||
| 21 | logger = logging.getLogger(__name__) | ||
| 22 | |||
| 23 | |||
| 24 | def freeze( | ||
| 25 | requirement=None, | ||
| 26 | find_links=None, local_only=None, user_only=None, skip_regex=None, | ||
| 27 | isolated=False, | ||
| 28 | wheel_cache=None, | ||
| 29 | exclude_editable=False, | ||
| 30 | skip=()): | ||
| 31 | find_links = find_links or [] | ||
| 32 | skip_match = None | ||
| 33 | |||
| 34 | if skip_regex: | ||
| 35 | skip_match = re.compile(skip_regex).search | ||
| 36 | |||
| 37 | dependency_links = [] | ||
| 38 | |||
| 39 | for dist in pkg_resources.working_set: | ||
| 40 | if dist.has_metadata('dependency_links.txt'): | ||
| 41 | dependency_links.extend( | ||
| 42 | dist.get_metadata_lines('dependency_links.txt') | ||
| 43 | ) | ||
| 44 | for link in find_links: | ||
| 45 | if '#egg=' in link: | ||
| 46 | dependency_links.append(link) | ||
| 47 | for link in find_links: | ||
| 48 | yield '-f %s' % link | ||
| 49 | installations = {} | ||
| 50 | for dist in get_installed_distributions(local_only=local_only, | ||
| 51 | skip=(), | ||
| 52 | user_only=user_only): | ||
| 53 | try: | ||
| 54 | req = FrozenRequirement.from_dist( | ||
| 55 | dist, | ||
| 56 | dependency_links | ||
| 57 | ) | ||
| 58 | except RequirementParseError: | ||
| 59 | logger.warning( | ||
| 60 | "Could not parse requirement: %s", | ||
| 61 | dist.project_name | ||
| 62 | ) | ||
| 63 | continue | ||
| 64 | if exclude_editable and req.editable: | ||
| 65 | continue | ||
| 66 | installations[req.name] = req | ||
| 67 | |||
| 68 | if requirement: | ||
| 69 | # the options that don't get turned into an InstallRequirement | ||
| 70 | # should only be emitted once, even if the same option is in multiple | ||
| 71 | # requirements files, so we need to keep track of what has been emitted | ||
| 72 | # so that we don't emit it again if it's seen again | ||
| 73 | emitted_options = set() | ||
| 74 | # keep track of which files a requirement is in so that we can | ||
| 75 | # give an accurate warning if a requirement appears multiple times. | ||
| 76 | req_files = collections.defaultdict(list) | ||
| 77 | for req_file_path in requirement: | ||
| 78 | with open(req_file_path) as req_file: | ||
| 79 | for line in req_file: | ||
| 80 | if (not line.strip() or | ||
| 81 | line.strip().startswith('#') or | ||
| 82 | (skip_match and skip_match(line)) or | ||
| 83 | line.startswith(( | ||
| 84 | '-r', '--requirement', | ||
| 85 | '-Z', '--always-unzip', | ||
| 86 | '-f', '--find-links', | ||
| 87 | '-i', '--index-url', | ||
| 88 | '--pre', | ||
| 89 | '--trusted-host', | ||
| 90 | '--process-dependency-links', | ||
| 91 | '--extra-index-url'))): | ||
| 92 | line = line.rstrip() | ||
| 93 | if line not in emitted_options: | ||
| 94 | emitted_options.add(line) | ||
| 95 | yield line | ||
| 96 | continue | ||
| 97 | |||
| 98 | if line.startswith('-e') or line.startswith('--editable'): | ||
| 99 | if line.startswith('-e'): | ||
| 100 | line = line[2:].strip() | ||
| 101 | else: | ||
| 102 | line = line[len('--editable'):].strip().lstrip('=') | ||
| 103 | line_req = InstallRequirement.from_editable( | ||
| 104 | line, | ||
| 105 | isolated=isolated, | ||
| 106 | wheel_cache=wheel_cache, | ||
| 107 | ) | ||
| 108 | else: | ||
| 109 | line_req = InstallRequirement.from_line( | ||
| 110 | COMMENT_RE.sub('', line).strip(), | ||
| 111 | isolated=isolated, | ||
| 112 | wheel_cache=wheel_cache, | ||
| 113 | ) | ||
| 114 | |||
| 115 | if not line_req.name: | ||
| 116 | logger.info( | ||
| 117 | "Skipping line in requirement file [%s] because " | ||
| 118 | "it's not clear what it would install: %s", | ||
| 119 | req_file_path, line.strip(), | ||
| 120 | ) | ||
| 121 | logger.info( | ||
| 122 | " (add #egg=PackageName to the URL to avoid" | ||
| 123 | " this warning)" | ||
| 124 | ) | ||
| 125 | elif line_req.name not in installations: | ||
| 126 | # either it's not installed, or it is installed | ||
| 127 | # but has been processed already | ||
| 128 | if not req_files[line_req.name]: | ||
| 129 | logger.warning( | ||
| 130 | "Requirement file [%s] contains %s, but that " | ||
| 131 | "package is not installed", | ||
| 132 | req_file_path, | ||
| 133 | COMMENT_RE.sub('', line).strip(), | ||
| 134 | ) | ||
| 135 | else: | ||
| 136 | req_files[line_req.name].append(req_file_path) | ||
| 137 | else: | ||
| 138 | yield str(installations[line_req.name]).rstrip() | ||
| 139 | del installations[line_req.name] | ||
| 140 | req_files[line_req.name].append(req_file_path) | ||
| 141 | |||
| 142 | # Warn about requirements that were included multiple times (in a | ||
| 143 | # single requirements file or in different requirements files). | ||
| 144 | for name, files in six.iteritems(req_files): | ||
| 145 | if len(files) > 1: | ||
| 146 | logger.warning("Requirement %s included multiple times [%s]", | ||
| 147 | name, ', '.join(sorted(set(files)))) | ||
| 148 | |||
| 149 | yield( | ||
| 150 | '## The following requirements were added by ' | ||
| 151 | 'pip freeze:' | ||
| 152 | ) | ||
| 153 | for installation in sorted( | ||
| 154 | installations.values(), key=lambda x: x.name.lower()): | ||
| 155 | if canonicalize_name(installation.name) not in skip: | ||
| 156 | yield str(installation).rstrip() | ||
| 157 | |||
| 158 | |||
| 159 | class FrozenRequirement(object): | ||
| 160 | def __init__(self, name, req, editable, comments=()): | ||
| 161 | self.name = name | ||
| 162 | self.req = req | ||
| 163 | self.editable = editable | ||
| 164 | self.comments = comments | ||
| 165 | |||
| 166 | _rev_re = re.compile(r'-r(\d+)$') | ||
| 167 | _date_re = re.compile(r'-(20\d\d\d\d\d\d)$') | ||
| 168 | |||
| 169 | @classmethod | ||
| 170 | def from_dist(cls, dist, dependency_links): | ||
| 171 | location = os.path.normcase(os.path.abspath(dist.location)) | ||
| 172 | comments = [] | ||
| 173 | from pip._internal.vcs import vcs, get_src_requirement | ||
| 174 | if dist_is_editable(dist) and vcs.get_backend_name(location): | ||
| 175 | editable = True | ||
| 176 | try: | ||
| 177 | req = get_src_requirement(dist, location) | ||
| 178 | except InstallationError as exc: | ||
| 179 | logger.warning( | ||
| 180 | "Error when trying to get requirement for VCS system %s, " | ||
| 181 | "falling back to uneditable format", exc | ||
| 182 | ) | ||
| 183 | req = None | ||
| 184 | if req is None: | ||
| 185 | logger.warning( | ||
| 186 | 'Could not determine repository location of %s', location | ||
| 187 | ) | ||
| 188 | comments.append( | ||
| 189 | '## !! Could not determine repository location' | ||
| 190 | ) | ||
| 191 | req = dist.as_requirement() | ||
| 192 | editable = False | ||
| 193 | else: | ||
| 194 | editable = False | ||
| 195 | req = dist.as_requirement() | ||
| 196 | specs = req.specs | ||
| 197 | assert len(specs) == 1 and specs[0][0] in ["==", "==="], \ | ||
| 198 | 'Expected 1 spec with == or ===; specs = %r; dist = %r' % \ | ||
| 199 | (specs, dist) | ||
| 200 | version = specs[0][1] | ||
| 201 | ver_match = cls._rev_re.search(version) | ||
| 202 | date_match = cls._date_re.search(version) | ||
| 203 | if ver_match or date_match: | ||
| 204 | svn_backend = vcs.get_backend('svn') | ||
| 205 | if svn_backend: | ||
| 206 | svn_location = svn_backend().get_location( | ||
| 207 | dist, | ||
| 208 | dependency_links, | ||
| 209 | ) | ||
| 210 | if not svn_location: | ||
| 211 | logger.warning( | ||
| 212 | 'Warning: cannot find svn location for %s', req, | ||
| 213 | ) | ||
| 214 | comments.append( | ||
| 215 | '## FIXME: could not find svn URL in dependency_links ' | ||
| 216 | 'for this package:' | ||
| 217 | ) | ||
| 218 | else: | ||
| 219 | warnings.warn( | ||
| 220 | "SVN editable detection based on dependency links " | ||
| 221 | "will be dropped in the future.", | ||
| 222 | RemovedInPip11Warning, | ||
| 223 | ) | ||
| 224 | comments.append( | ||
| 225 | '# Installing as editable to satisfy requirement %s:' % | ||
| 226 | req | ||
| 227 | ) | ||
| 228 | if ver_match: | ||
| 229 | rev = ver_match.group(1) | ||
| 230 | else: | ||
| 231 | rev = '{%s}' % date_match.group(1) | ||
| 232 | editable = True | ||
| 233 | req = '%s@%s#egg=%s' % ( | ||
| 234 | svn_location, | ||
| 235 | rev, | ||
| 236 | cls.egg_name(dist) | ||
| 237 | ) | ||
| 238 | return cls(dist.project_name, req, editable, comments) | ||
| 239 | |||
| 240 | @staticmethod | ||
| 241 | def egg_name(dist): | ||
| 242 | name = dist.egg_name() | ||
| 243 | match = re.search(r'-py\d\.\d$', name) | ||
| 244 | if match: | ||
| 245 | name = name[:match.start()] | ||
| 246 | return name | ||
| 247 | |||
| 248 | def __str__(self): | ||
| 249 | req = self.req | ||
| 250 | if self.editable: | ||
| 251 | req = '-e %s' % req | ||
| 252 | return '\n'.join(list(self.comments) + [str(req)]) + '\n' | ||
