def from_line(cls, name, comes_from=None, prereleases=None): """Creates an InstallRequirement from a name, which might be a requirement, directory containing 'setup.py', filename, or URL. """ url = None name = name.strip() req = None path = os.path.normpath(os.path.abspath(name)) link = None if is_url(name): link = Link(name) elif (os.path.isdir(path) and (os.path.sep in name or name.startswith('.'))): if not is_installable_dir(path): raise InstallationError( "Directory %r is not installable. File 'setup.py' not " "found." % name ) link = Link(path_to_url(name)) elif is_archive_file(path): if not os.path.isfile(path): logger.warn( 'Requirement %r looks like a filename, but the file does ' 'not exist', name ) link = Link(path_to_url(name)) # If the line has an egg= definition, but isn't editable, pull the # requirement out. Otherwise, assume the name is the req for the non # URL/path/archive case. if link and req is None: url = link.url_without_fragment # when fragment is None, this will become an 'unnamed' requirement req = link.egg_fragment # Handle relative file URLs if link.scheme == 'file' and re.search(r'\.\./', url): url = path_to_url(os.path.normpath(os.path.abspath(link.path))) # fail early for invalid or unsupported wheels if link.ext == wheel_ext: wheel = Wheel(link.filename) # can raise InvalidWheelFilename if not wheel.supported(): raise UnsupportedWheel( "%s is not a supported wheel on this platform." % wheel.filename ) else: req = name return cls(req, comes_from, url=url, prereleases=prereleases)
def prep(self, tmpdir, data): self.build_dir = tmpdir.join('build') self.download_dir = tmpdir.join('download') os.mkdir(self.build_dir) os.mkdir(self.download_dir) self.dist_file = "simple-1.0.tar.gz" self.dist_file2 = "simple-2.0.tar.gz" self.dist_path = data.packages.join(self.dist_file) self.dist_path2 = data.packages.join(self.dist_file2) self.dist_url = Link(path_to_url(self.dist_path)) self.dist_url2 = Link(path_to_url(self.dist_path2))
def cached_wheel(cache_dir, link, format_control, package_name): if not cache_dir: return link if not link: return link if link.is_wheel: return link if not package_name: return link canonical_name = pkg_resources.safe_name(package_name).lower() formats = pip.index.fmt_ctl_formats(format_control, canonical_name) if "binary" not in formats: return link root = _cache_for_link(cache_dir, link) try: wheel_names = os.listdir(root) except OSError as e: if e.errno == errno.ENOENT: return link raise candidates = [] for wheel_name in wheel_names: try: wheel = Wheel(wheel_name) except InvalidWheelFilename: continue if not wheel.supported(): # Built for a different python/arch/etc continue candidates.append((wheel.support_index_min(), wheel_name)) if not candidates: return link candidates.sort() path = os.path.join(root, candidates[0][1]) return pip.index.Link(path_to_url(path), trusted=True)
def test_unpack_http_url_with_urllib_response_without_content_type(data): """ It should download and unpack files even if no Content-Type header exists """ _real_session = PipSession() def _fake_session_get(*args, **kwargs): resp = _real_session.get(*args, **kwargs) del resp.headers["Content-Type"] return resp session = Mock() session.get = _fake_session_get uri = path_to_url(data.packages.join("simple-1.0.tar.gz")) link = Link(uri) temp_dir = mkdtemp() try: unpack_http_url( link, temp_dir, download_dir=None, session=session, ) assert set(os.listdir(temp_dir)) == set([ 'PKG-INFO', 'setup.cfg', 'setup.py', 'simple', 'simple.egg-info' ]) finally: rmtree(temp_dir)
def get_url(self, location): url = self.run_command( ['showconfig', 'paths.default'], show_stdout=False, cwd=location).strip() if self._is_local_repository(url): url = path_to_url(url) return url.strip()
def test_create_bundle(script, tmpdir, data): """ Test making a bundle. We'll grab one package from the filesystem (the FSPkg dummy package), one from vcs (initools) and one from an index (pip itself). """ fspkg = path_to_url(data.packages / 'FSPkg') script.pip('install', '-e', fspkg) pkg_lines = textwrap.dedent( '''\ -e %s -e %s#egg=initools-dev pip''' % (fspkg, local_checkout('svn+http://svn.colorstudy.com/INITools/trunk', tmpdir.join("cache")))) script.scratch_path.join("bundle-req.txt").write(pkg_lines) # Create a bundle in env.scratch_path/ test.pybundle result = script.pip('bundle', '-r', script.scratch_path / 'bundle-req.txt', script.scratch_path / 'test.pybundle') bundle = result.files_after.get(join('scratch', 'test.pybundle'), None) assert bundle is not None files = zipfile.ZipFile(bundle.full).namelist() assert 'src/FSPkg/' in files assert 'src/initools/' in files assert 'build/pip/' in files
def test_unpack_file_url_thats_a_dir(self, tmpdir, data): self.prep(tmpdir, data) dist_path = data.packages.join("FSPkg") dist_url = Link(path_to_url(dist_path)) unpack_file_url(dist_url, self.build_dir, download_dir=self.download_dir) assert os.path.isdir(os.path.join(self.build_dir, 'fspkg'))
def test_cleanup_after_create_bundle(script, tmpdir, data): """ Test clean up after making a bundle. Make sure (build|src)-bundle/ dirs are removed but not src/. """ # Install an editable to create a src/ dir. args = ['install'] args.extend(['-e', '%s#egg=pip-test-package' % local_checkout('git+http://github.com/pypa/pip-test-package.git', tmpdir.join("cache"))]) script.pip(*args) build = script.venv_path/"build" src = script.venv_path/"src" assert not exists(build), "build/ dir still exists: %s" % build assert exists(src), "expected src/ dir doesn't exist: %s" % src # Make the bundle. fspkg = path_to_url(data.packages/'FSPkg') pkg_lines = textwrap.dedent('''\ -e %s -e %s#egg=initools-dev pip''' % (fspkg, local_checkout('svn+http://svn.colorstudy.com/INITools/trunk', tmpdir.join("cache")))) script.scratch_path.join("bundle-req.txt").write(pkg_lines) script.pip('bundle', '--no-use-wheel', '-r', 'bundle-req.txt', 'test.pybundle') build_bundle = script.scratch_path/"build-bundle" src_bundle = script.scratch_path/"src-bundle" assert not exists(build_bundle), "build-bundle/ dir still exists: %s" % build_bundle assert not exists(src_bundle), "src-bundle/ dir still exists: %s" % src_bundle script.assert_no_temp() # Make sure previously created src/ from editable still exists assert exists(src), "expected src dir doesn't exist: %s" % src
def test_local_dir_package_is_not_archived(tmpdir, small_fake_package_dir): """ Prequ will not create an archive for a local dir requirement. """ cache_dir = str(tmpdir.mkdir('cache_dir')) pkg_dir = os.path.join(cache_dir, 'pkgs') os.mkdir(pkg_dir) fake_package_url = path_to_url(small_fake_package_dir) with mock.patch('prequ.repositories.pypi.CACHE_DIR', new=cache_dir): runner = CliRunner() with runner.isolated_filesystem(): with open('requirements.in', 'w') as req_in: req_in.write(fake_package_url) run_result = runner.invoke(cli, ['-n', '--no-header']) assert run_result.exit_code == 0 assert run_result.output == ( fake_package_url + '\n' + 'six==1.10.0 # via small-fake-with-deps\n' 'Dry-run, so nothing updated.\n') assert os.listdir(pkg_dir) == [], "Package directory should be empty"
def test_cleanup_after_create_bundle(script, tmpdir, data): """ Test clean up after making a bundle. Make sure (build|src)-bundle/ dirs are removed but not src/. """ # Install an editable to create a src/ dir. args = ['install'] args.extend(['-e', '%s#egg=pip-test-package' % local_checkout('git+http://github.com/pypa/pip-test-package.git', tmpdir.join("cache"))]) script.pip(*args) build = script.venv_path/"build" src = script.venv_path/"src" assert not exists(build), "build/ dir still exists: %s" % build assert exists(src), "expected src/ dir doesn't exist: %s" % src # Make the bundle. fspkg = path_to_url(data.packages/'FSPkg') pkg_lines = textwrap.dedent('''\ -e %s -e %s#egg=initools-dev pip''' % (fspkg, local_checkout('svn+http://svn.colorstudy.com/INITools/trunk', tmpdir.join("cache")))) script.scratch_path.join("bundle-req.txt").write(pkg_lines) script.pip('bundle', '-r', 'bundle-req.txt', 'test.pybundle') build_bundle = script.scratch_path/"build-bundle" src_bundle = script.scratch_path/"src-bundle" assert not exists(build_bundle), "build-bundle/ dir still exists: %s" % build_bundle assert not exists(src_bundle), "src-bundle/ dir still exists: %s" % src_bundle script.assert_no_temp() # Make sure previously created src/ from editable still exists assert exists(src), "expected src dir doesn't exist: %s" % src
def test_format_requirement_non_relative_editable(from_editable, small_fake_package_dir, tmpdir): tmp_package_dir = os.path.join(str(tmpdir), 'small_fake_package') shutil.copytree(small_fake_package_dir, tmp_package_dir) ireq = from_editable(tmp_package_dir) assert format_requirement(ireq) == '-e ' + path_to_url(tmp_package_dir)
def cached_wheel(self, link, package_name): not_cached = (not self._cache_dir or not link or link.is_wheel or not link.is_artifact or not package_name) if not_cached: return link canonical_name = canonicalize_name(package_name) formats = pip.index.fmt_ctl_formats(self._format_control, canonical_name) if "binary" not in formats: return link root = self.get_cache_path_for_link(link) try: wheel_names = os.listdir(root) except OSError as err: if err.errno in {errno.ENOENT, errno.ENOTDIR}: return link raise candidates = [] for wheel_name in wheel_names: try: wheel = Wheel(wheel_name) except InvalidWheelFilename: continue if not wheel.supported(): # Built for a different python/arch/etc continue candidates.append((wheel.support_index_min(), wheel_name)) if not candidates: return link candidates.sort() path = os.path.join(root, candidates[0][1]) return pip.index.Link(path_to_url(path))
def test_locally_available_editable_package_is_not_archived_in_cache_dir( tmpdir): """ Prequ will not create an archive for a locally available editable requirement """ cache_dir = tmpdir.mkdir('cache_dir') os.mkdir(os.path.join(str(cache_dir), 'pkgs')) fake_package_dir = os.path.join( os.path.split(__file__)[0], 'test_data', 'small_fake_package') fake_package_dir = path_to_url(fake_package_dir) with mock.patch('prequ.repositories.pypi.CACHE_DIR', new=str(cache_dir)): runner = CliRunner() with runner.isolated_filesystem(): with open('requirements.in', 'w') as req_in: req_in.write('-e ' + fake_package_dir) # require editable fake package out = runner.invoke(cli, ['-n']) assert out.exit_code == 0 assert fake_package_dir in out.output assert 'six==1.10.0' in out.output # we should not find any archived file in {cache_dir}/pkgs assert not os.listdir(os.path.join(str(cache_dir), 'pkgs'))
def get_url(self, location): url = call_subprocess( [self.cmd, 'showconfig', 'paths.default'], show_stdout=False, cwd=location).strip() if self._is_local_repository(url): url = path_to_url(url) return url.strip()
def __init__(self, url, comes_from=None): # url can be a UNC windows share if url.startswith('\\\\'): url = path_to_url(url) self.url = url self.comes_from = comes_from
def test_sync_with_editable(from_editable, small_fake_package_dir): with mock.patch('prequ.sync.check_call') as check_call: to_install = {from_editable(small_fake_package_dir)} sync(to_install, set()) check_call.assert_called_once_with([ 'pip', 'install', '-q', '-e', path_to_url(small_fake_package_dir) ])
def __init__(self, url, comes_from=None, internal=None, trusted=None): # url can be a UNC windows share if url != Inf and url.startswith('\\\\'): url = path_to_url(url) self.url = url self.comes_from = comes_from self.internal = internal self.trusted = trusted
def test_sync_with_editable_uses_abspath(from_editable, small_fake_package_dir): ireq = from_editable(small_fake_package_dir) rel_path = os.path.relpath(url_to_path(ireq.link.url)) ireq.link.url = 'file:{}'.format(rel_path.replace(os.path.sep, '/')) with mock.patch('prequ.sync.check_call') as check_call: sync({ireq}, set()) check_call.assert_called_once_with([ 'pip', 'install', '-q', '-e', path_to_url(os.path.abspath(small_fake_package_dir)) ])
def get_url(self, location): urls = self.run_command(['info'], show_stdout=False, cwd=location) for line in urls.splitlines(): line = line.strip() for x in ('checkout of branch: ', 'parent branch: '): if line.startswith(x): repo = line.split(x)[1] if self._is_local_repository(repo): return path_to_url(repo) return repo return None
def __init__(self, url, comes_from=None, internal=None, trusted=None, _deprecated_regex=False): # url can be a UNC windows share if url != Inf and url.startswith("\\\\"): url = path_to_url(url) self.url = url self.comes_from = comes_from self.internal = internal self.trusted = trusted self._deprecated_regex = _deprecated_regex
def get_url(self, location): urls = self.run_command(["info"], show_stdout=False, cwd=location) for line in urls.splitlines(): line = line.strip() for x in ("checkout of branch: ", "parent branch: "): if line.startswith(x): repo = line.split(x)[1] if self._is_local_repository(repo): return path_to_url(repo) return repo return None
def get_url(self, location): urls = call_subprocess( [self.cmd, 'info'], show_stdout=False, cwd=location) for line in urls.splitlines(): line = line.strip() for x in ('checkout of branch: ', 'parent branch: '): if line.startswith(x): repo = line.split(x)[1] if self._is_local_repository(repo): return path_to_url(repo) return repo return None
def test_hash_mismatch(self, data): """A hash mismatch should raise an error.""" file_url = path_to_url((data.packages / 'simple-1.0.tar.gz').abspath) reqset = self.basic_reqset(require_hashes=True) reqset.add_requirement( list(process_line('%s --hash=sha256:badbad' % file_url, 'file', 1))[0]) finder = PackageFinder([data.find_links], [], session=PipSession()) assert_raises_regexp( HashErrors, r'THESE PACKAGES DO NOT MATCH THE HASHES.*\n' r' file:///.*/data/packages/simple-1\.0\.tar\.gz .*:\n' r' Expected sha256 badbad\n' r' Got 393043e672415891885c9a2a0929b1af95fb866d' r'6ca016b42d2e6ce53619b653$', reqset.prepare_files, finder)
def test_editable_package(small_fake_package_dir): """Prequ can compile an editable """ small_fake_package_url = path_to_url(small_fake_package_dir) runner = CliRunner() with runner.isolated_filesystem(): with open('requirements.in', 'w') as req_in: req_in.write('-e ' + small_fake_package_url) out = runner.invoke(cli, ['-n']) check_successful_exit(out) assert small_fake_package_url in out.output assert '-e ' + small_fake_package_url in out.output assert 'six==1.10.0' in out.output
def test_hash_mismatch(self, data): """A hash mismatch should raise an error.""" file_url = path_to_url((data.packages / "simple-1.0.tar.gz").abspath) reqset = self.basic_reqset(require_hashes=True) reqset.add_requirement(list(process_line("%s --hash=sha256:badbad" % file_url, "file", 1))[0]) finder = PackageFinder([data.find_links], [], session=PipSession()) assert_raises_regexp( HashErrors, r"THESE PACKAGES DO NOT MATCH THE HASHES.*\n" r" file:///.*/data/packages/simple-1\.0\.tar\.gz .*:\n" r" Expected sha256 badbad\n" r" Got 393043e672415891885c9a2a0929b1af95fb866d" r"6ca016b42d2e6ce53619b653$", reqset.prepare_files, finder, )
def test_hash_mismatch(self, data): """A hash mismatch should raise an error.""" file_url = path_to_url( (data.packages / 'simple-1.0.tar.gz').abspath) reqset = RequirementSet(require_hashes=True) reqset.add_requirement( list(process_line('%s --hash=sha256:badbad' % file_url, 'file', 1))[0]) finder = PackageFinder([data.find_links], [], session=PipSession()) resolver = self._basic_resolver(finder) assert_raises_regexp( HashErrors, r'THESE PACKAGES DO NOT MATCH THE HASHES.*\n' r' file:///.*/data/packages/simple-1\.0\.tar\.gz .*:\n' r' Expected sha256 badbad\n' r' Got 393043e672415891885c9a2a0929b1af95fb866d' r'6ca016b42d2e6ce53619b653$', resolver.resolve, reqset)
def _format_link(link, root_dir): """ Format link as URL or path. :type link: pip.index.Link :type root_dir: str|None :rtype: str """ if link.scheme != 'file': return link.url path = url_to_path(link.url) if root_dir is not None and is_subdirectory(root_dir, path): relpath = os.path.relpath(path, start=root_dir) if relpath == '.': return '.' return './' + relpath.replace(os.path.sep, '/') # Make sure it's absolute return path_to_url(path)
def test_diff_with_editable(fake_dist, from_editable, from_line, small_fake_package_dir): installed = [ fake_dist('small-fake-with-deps==0.0.1'), fake_dist('six==1.10.0'), ] reqs = [ from_editable(small_fake_package_dir), from_line('six==1.10.0'), ] to_install, to_uninstall = diff(reqs, installed) assert to_uninstall == set(), "No packages should be uninstalled" # The editable should be upgraded, since the installed version # (0.0.1) was different than the version specified in setup.py of # the editable package (0.1) assert len(to_install) == 1 package = list(to_install)[0] assert package.editable assert str(package.link) == path_to_url(small_fake_package_dir)
def __init__(self, url, comes_from=None, requires_python=None): """ Object representing a parsed link from https://pypi.python.org/simple/* url: url of the resource pointed to (href of the link) comes_from: instance of HTMLPage where the link was found, or string. requires_python: String containing the `Requires-Python` metadata field, specified in PEP 345. This may be specified by a data-requires-python attribute in the HTML link tag, as described in PEP 503. """ # url can be a UNC windows share if url.startswith('\\\\'): url = path_to_url(url) self.url = url self.comes_from = comes_from self.requires_python = requires_python if requires_python else None
def test_generate_hashes_with_editable(): small_fake_package_dir = os.path.join( os.path.split(__file__)[0], 'test_data', 'small_fake_package') small_fake_package_url = path_to_url(small_fake_package_dir) runner = CliRunner() with runner.isolated_filesystem(): with open('requirements.in', 'w') as fp: fp.write('-e {}\n'.format(small_fake_package_url)) fp.write('pytz==2017.2\n') out = runner.invoke(cli, ['--generate-hashes']) expected = ( '# This file is autogenerated by Prequ. To update, run:\n' '#\n' '# prequ update\n' '#\n' '-e {}\n' 'pytz==2017.2 \\\n' ' --hash=sha256:d1d6729c85acea5423671382868627129432fba9a89ecbb248d8d1c7a9f01c67 \\\n' ' --hash=sha256:f5c056e8f62d45ba8215e5cb8f50dfccb198b4b9fbea8500674f3443e4689589\n' ).format(small_fake_package_url) assert out.exit_code == 0 assert expected in out.output
def cached_wheel(cache_dir, link, format_control, package_name): if not cache_dir: return link if not link: return link if link.is_wheel: return link if not link.is_artifact: return link if not package_name: return link canonical_name = canonicalize_name(package_name) # noinspection PyUnresolvedReferences formats = pip.index.fmt_ctl_formats(format_control, canonical_name) if "binary" not in formats: return link root = _cache_for_link(cache_dir, link) try: wheel_names = os.listdir(root) except OSError as e: if e.errno in (errno.ENOENT, errno.ENOTDIR): return link raise candidates = [] for wheel_name in wheel_names: try: wheel = Wheel(wheel_name) except InvalidWheelFilename: continue if not wheel.supported(): # Built for a different python/arch/etc continue candidates.append((wheel.support_index_min(), wheel_name)) if not candidates: return link candidates.sort() path = os.path.join(root, candidates[0][1]) return pip.index.Link(path_to_url(path))
def test_create_bundle(script, tmpdir, data): """ Test making a bundle. We'll grab one package from the filesystem (the FSPkg dummy package), one from vcs (initools) and one from an index (pip itself). """ fspkg = path_to_url(data.packages/'FSPkg') script.pip('install', '-e', fspkg) pkg_lines = textwrap.dedent('''\ -e %s -e %s#egg=initools-dev pip''' % (fspkg, local_checkout('svn+http://svn.colorstudy.com/INITools/trunk', tmpdir.join("cache")))) script.scratch_path.join("bundle-req.txt").write(pkg_lines) # Create a bundle in env.scratch_path/ test.pybundle result = script.pip('bundle', '-r', script.scratch_path/ 'bundle-req.txt', script.scratch_path/ 'test.pybundle') bundle = result.files_after.get(join('scratch', 'test.pybundle'), None) assert bundle is not None files = zipfile.ZipFile(bundle.full).namelist() assert 'src/FSPkg/' in files assert 'src/initools/' in files assert 'build/pip/' in files
def test_url_to_path_path_to_url_symmetry_win(): path = r'C:\tmp\file' assert url_to_path(path_to_url(path)) == path unc_path = r'\\unc\share\path' assert url_to_path(path_to_url(unc_path)) == unc_path
def from_line(cls, name, comes_from=None, isolated=False, options=None, wheel_cache=None, constraint=False): """Creates an InstallRequirement from a name, which might be a requirement, directory containing 'setup.py', filename, or URL. """ from pip.index import Link if is_url(name): marker_sep = '; ' else: marker_sep = ';' if marker_sep in name: name, markers = name.split(marker_sep, 1) markers = markers.strip() if not markers: markers = None else: markers = None name = name.strip() req = None path = os.path.normpath(os.path.abspath(name)) link = None extras = None if is_url(name): link = Link(name) else: p, extras = _strip_extras(path) if (os.path.isdir(p) and (os.path.sep in name or name.startswith('.'))): if not is_installable_dir(p): raise InstallationError( "Directory %r is not installable. File 'setup.py' " "not found." % name) link = Link(path_to_url(p)) elif is_archive_file(p): if not os.path.isfile(p): logger.warning( 'Requirement %r looks like a filename, but the ' 'file does not exist', name) link = Link(path_to_url(p)) # it's a local file, dir, or url if link: # Handle relative file URLs if link.scheme == 'file' and re.search(r'\.\./', link.url): link = Link( path_to_url(os.path.normpath(os.path.abspath(link.path)))) # wheel file if link.is_wheel: wheel = Wheel(link.filename) # can raise InvalidWheelFilename if not wheel.supported(): raise UnsupportedWheel( "%s is not a supported wheel on this platform." % wheel.filename) req = "%s==%s" % (wheel.name, wheel.version) else: # set the req to the egg fragment. when it's not there, this # will become an 'unnamed' requirement req = link.egg_fragment # a requirement specifier else: req = name options = options if options else {} res = cls(req, comes_from, link=link, markers=markers, isolated=isolated, options=options, wheel_cache=wheel_cache, constraint=constraint) if extras: res.extras = pkg_resources.Requirement.parse('__placeholder__' + extras).extras return res
def parse_editable(editable_req, default_vcs=None): """Parses an editable requirement into: - a requirement name - an URL - extras - editable options Accepted requirements: svn+http://blahblah@rev#egg=Foobar[baz]&subdirectory=version_subdir .[some_extra] """ from pip.index import Link url = editable_req extras = None # If a file path is specified with extras, strip off the extras. m = re.match(r'^(.+)(\[[^\]]+\])$', url) if m: url_no_extras = m.group(1) extras = m.group(2) else: url_no_extras = url if os.path.isdir(url_no_extras): if not os.path.exists(os.path.join(url_no_extras, 'setup.py')): raise InstallationError( "Directory %r is not installable. File 'setup.py' not found." % url_no_extras) # Treating it as code that has already been checked out url_no_extras = path_to_url(url_no_extras) if url_no_extras.lower().startswith('file:'): package_name = Link(url_no_extras).egg_fragment if extras: return ( package_name, url_no_extras, pkg_resources.Requirement.parse('__placeholder__' + extras).extras, {}, ) else: return package_name, url_no_extras, None, {} for version_control in vcs: if url.lower().startswith('%s:' % version_control): url = '%s+%s' % (version_control, url) break if '+' not in url: if default_vcs: url = default_vcs + '+' + url else: raise InstallationError( '%s should either be a path to a local project or a VCS url ' 'beginning with svn+, git+, hg+, or bzr+' % editable_req) vc_type = url.split('+', 1)[0].lower() if not vcs.get_backend(vc_type): error_message = 'For --editable=%s only ' % editable_req + \ ', '.join([backend.name + '+URL' for backend in vcs.backends]) + \ ' is currently supported' raise InstallationError(error_message) try: options = _build_editable_options(editable_req) except Exception as exc: raise InstallationError('--editable=%s error in editable options:%s' % (editable_req, exc)) if not options or 'egg' not in options: req = _build_req_from_url(editable_req) if not req: raise InstallationError( '--editable=%s is not the right format; it must have ' '#egg=Package' % editable_req) else: req = options['egg'] package = _strip_postfix(req) return package, url, None, options
def build(self, autobuilding=False): """Build wheels. :param unpack: If True, replace the sdist we built from the with the newly built wheel, in preparation for installation. :return: True if all the wheels built correctly. """ assert self._wheel_dir or (autobuilding and self._cache_root) # unpack sdists and constructs req set self.requirement_set.prepare_files(self.finder) reqset = self.requirement_set.requirements.values() buildset = [] for req in reqset: if req.constraint: continue if req.is_wheel: if not autobuilding: logger.info('Skipping %s, due to already being wheel.', req.name) elif req.editable: if not autobuilding: logger.info( 'Skipping bdist_wheel for %s, due to being editable', req.name) elif autobuilding and req.link and not req.link.is_artifact: pass elif autobuilding and not req.source_dir: pass else: if autobuilding: link = req.link base, ext = link.splitext() if pip.index.egg_info_matches(base, None, link) is None: # Doesn't look like a package - don't autobuild a wheel # because we'll have no way to lookup the result sanely continue if "binary" not in pip.index.fmt_ctl_formats( self.finder.format_control, pkg_resources.safe_name(req.name).lower()): logger.info( "Skipping bdist_wheel for %s, due to binaries " "being disabled for it.", req.name) continue buildset.append(req) if not buildset: return True # Build the wheels. logger.info( 'Building wheels for collected packages: %s', ', '.join([req.name for req in buildset]), ) with indent_log(): build_success, build_failure = [], [] for req in buildset: if autobuilding: output_dir = _cache_for_link(self._cache_root, req.link) ensure_dir(output_dir) else: output_dir = self._wheel_dir wheel_file = self._build_one(req, output_dir) if wheel_file: build_success.append(req) if autobuilding: # XXX: This is mildly duplicative with prepare_files, # but not close enough to pull out to a single common # method. # The code below assumes temporary source dirs - # prevent it doing bad things. if req.source_dir and not os.path.exists( os.path.join(req.source_dir, PIP_DELETE_MARKER_FILENAME)): raise AssertionError( "bad source dir - missing marker") # Delete the source we built the wheel from req.remove_temporary_source() # set the build directory again - name is known from # the work prepare_files did. req.source_dir = req.build_location( self.requirement_set.build_dir) # Update the link for this. req.link = pip.index.Link(path_to_url(wheel_file), trusted=True) assert req.link.is_wheel # extract the wheel into the dir unpack_url(req.link, req.source_dir, None, False, session=self.requirement_set.session) else: build_failure.append(req) # notify success/failure if build_success: logger.info( 'Successfully built %s', ' '.join([req.name for req in build_success]), ) if build_failure: logger.info( 'Failed to build %s', ' '.join([req.name for req in build_failure]), ) # Return True if all builds were successful return len(build_failure) == 0
def test_path_to_url_unix(): assert path_to_url('/tmp/file') == 'file:///tmp/file' path = os.path.join(os.getcwd(), 'file') assert path_to_url('file') == 'file://' + pathname2url(path)
def sort_path(path): url = path_to_url(path) if mimetypes.guess_type(url, strict=False)[0] == 'text/html': urls.append(url) else: files.append(url)
def test_path_to_url_win(): assert path_to_url('c:/tmp/file') == 'file:///C:/tmp/file' assert path_to_url('c:\\tmp\\file') == 'file:///C:/tmp/file' assert path_to_url(r'\\unc\as\path') == 'file://unc/as/path' path = os.path.join(os.getcwd(), 'file') assert path_to_url('file') == 'file:' + urllib_request.pathname2url(path)
def from_line( cls, name, comes_from=None, isolated=False, options=None, wheel_cache=None, constraint=False): """Creates an InstallRequirement from a name, which might be a requirement, directory containing 'setup.py', filename, or URL. """ from pip.index import Link if is_url(name): marker_sep = '; ' else: marker_sep = ';' if marker_sep in name: name, markers = name.split(marker_sep, 1) markers = markers.strip() if not markers: markers = None else: markers = Marker(markers) else: markers = None name = name.strip() req = None path = os.path.normpath(os.path.abspath(name)) link = None extras = None if is_url(name): link = Link(name) else: p, extras = _strip_extras(path) if (os.path.isdir(p) and (os.path.sep in name or name.startswith('.'))): if not is_installable_dir(p): raise InstallationError( "Directory %r is not installable. File 'setup.py' " "not found." % name ) link = Link(path_to_url(p)) elif is_archive_file(p): if not os.path.isfile(p): logger.warning( 'Requirement %r looks like a filename, but the ' 'file does not exist', name ) link = Link(path_to_url(p)) # it's a local file, dir, or url if link: # Handle relative file URLs if link.scheme == 'file' and re.search(r'\.\./', link.url): link = Link( path_to_url(os.path.normpath(os.path.abspath(link.path)))) # wheel file if link.is_wheel: wheel = Wheel(link.filename) # can raise InvalidWheelFilename req = "%s==%s" % (wheel.name, wheel.version) else: # set the req to the egg fragment. when it's not there, this # will become an 'unnamed' requirement req = link.egg_fragment # a requirement specifier else: req = name if extras: extras = Requirement("placeholder" + extras.lower()).extras else: extras = () if req is not None: try: req = Requirement(req) except InvalidRequirement: if os.path.sep in req: add_msg = "It looks like a path." add_msg += deduce_helpful_msg(req) elif '=' in req and not any(op in req for op in operators): add_msg = "= is not a valid operator. Did you mean == ?" else: add_msg = traceback.format_exc() raise InstallationError( "Invalid requirement: '%s'\n%s" % (req, add_msg)) return cls( req, comes_from, link=link, markers=markers, isolated=isolated, options=options if options else {}, wheel_cache=wheel_cache, constraint=constraint, extras=extras, )
def parse_editable(editable_req, default_vcs=None): """Parses an editable requirement into: - a requirement name - an URL - extras - editable options Accepted requirements: svn+http://blahblah@rev#egg=Foobar[baz]&subdirectory=version_subdir .[some_extra] """ from pip.index import Link url = editable_req extras = None # If a file path is specified with extras, strip off the extras. m = re.match(r'^(.+)(\[[^\]]+\])$', url) if m: url_no_extras = m.group(1) extras = m.group(2) else: url_no_extras = url if os.path.isdir(url_no_extras): if not os.path.exists(os.path.join(url_no_extras, 'setup.py')): raise InstallationError( "Directory %r is not installable. File 'setup.py' not found." % url_no_extras ) # Treating it as code that has already been checked out url_no_extras = path_to_url(url_no_extras) if url_no_extras.lower().startswith('file:'): package_name = Link(url_no_extras).egg_fragment if extras: return ( package_name, url_no_extras, Requirement("placeholder" + extras.lower()).extras, ) else: return package_name, url_no_extras, None for version_control in vcs: if url.lower().startswith('%s:' % version_control): url = '%s+%s' % (version_control, url) break if '+' not in url: if default_vcs: warnings.warn( "--default-vcs has been deprecated and will be removed in " "the future.", RemovedInPip10Warning, ) url = default_vcs + '+' + url else: raise InstallationError( '%s should either be a path to a local project or a VCS url ' 'beginning with svn+, git+, hg+, or bzr+' % editable_req ) vc_type = url.split('+', 1)[0].lower() if not vcs.get_backend(vc_type): error_message = 'For --editable=%s only ' % editable_req + \ ', '.join([backend.name + '+URL' for backend in vcs.backends]) + \ ' is currently supported' raise InstallationError(error_message) package_name = Link(url).egg_fragment if not package_name: raise InstallationError( "Could not detect requirement name, please specify one with #egg=" ) if not package_name: raise InstallationError( '--editable=%s is not the right format; it must have ' '#egg=Package' % editable_req ) return _strip_postfix(package_name), url, None
def build(self, autobuilding=False): """Build wheels. :param unpack: If True, replace the sdist we built from the with the newly built wheel, in preparation for installation. :return: True if all the wheels built correctly. """ assert self._wheel_dir or (autobuilding and self._cache_root) # unpack sdists and constructs req set self.requirement_set.prepare_files(self.finder) reqset = self.requirement_set.requirements.values() buildset = [] for req in reqset: if req.constraint: continue if req.is_wheel: if not autobuilding: logger.info( 'Skipping %s, due to already being wheel.', req.name) elif req.editable: if not autobuilding: logger.info( 'Skipping bdist_wheel for %s, due to being editable', req.name) elif autobuilding and req.link and not req.link.is_artifact: pass elif autobuilding and not req.source_dir: pass else: if autobuilding: link = req.link base, ext = link.splitext() if pip.index.egg_info_matches(base, None, link) is None: # Doesn't look like a package - don't autobuild a wheel # because we'll have no way to lookup the result sanely continue if "binary" not in pip.index.fmt_ctl_formats( self.finder.format_control, canonicalize_name(req.name)): logger.info( "Skipping bdist_wheel for %s, due to binaries " "being disabled for it.", req.name) continue buildset.append(req) if not buildset: return True # Build the wheels. logger.info( 'Building wheels for collected packages: %s', ', '.join([req.name for req in buildset]), ) with indent_log(): build_success, build_failure = [], [] for req in buildset: if autobuilding: output_dir = _cache_for_link(self._cache_root, req.link) try: ensure_dir(output_dir) except OSError as e: logger.warn("Building wheel for %s failed: %s", req.name, e) build_failure.append(req) continue else: output_dir = self._wheel_dir wheel_file = self._build_one(req, output_dir) if wheel_file: build_success.append(req) if autobuilding: # XXX: This is mildly duplicative with prepare_files, # but not close enough to pull out to a single common # method. # The code below assumes temporary source dirs - # prevent it doing bad things. if req.source_dir and not os.path.exists(os.path.join( req.source_dir, PIP_DELETE_MARKER_FILENAME)): raise AssertionError( "bad source dir - missing marker") # Delete the source we built the wheel from req.remove_temporary_source() # set the build directory again - name is known from # the work prepare_files did. req.source_dir = req.build_location( self.requirement_set.build_dir) # Update the link for this. req.link = pip.index.Link( path_to_url(wheel_file)) assert req.link.is_wheel # extract the wheel into the dir unpack_url( req.link, req.source_dir, None, False, session=self.requirement_set.session) else: build_failure.append(req) # notify success/failure if build_success: logger.info( 'Successfully built %s', ' '.join([req.name for req in build_success]), ) if build_failure: logger.info( 'Failed to build %s', ' '.join([req.name for req in build_failure]), ) # Return True if all builds were successful return len(build_failure) == 0
def parse_editable(editable_req, default_vcs=None): """Parses an editable requirement into: - a requirement name - an URL - extras - editable options Accepted requirements: svn+http://blahblah@rev#egg=Foobar[baz]&subdirectory=version_subdir .[some_extra] """ url = editable_req extras = None # If a file path is specified with extras, strip off the extras. m = re.match(r'^(.+)(\[[^\]]+\])$', url) if m: url_no_extras = m.group(1) extras = m.group(2) else: url_no_extras = url if os.path.isdir(url_no_extras): if not os.path.exists(os.path.join(url_no_extras, 'setup.py')): raise InstallationError( "Directory %r is not installable. File 'setup.py' not found." % url_no_extras ) # Treating it as code that has already been checked out url_no_extras = path_to_url(url_no_extras) if url_no_extras.lower().startswith('file:'): if extras: return ( None, url_no_extras, pkg_resources.Requirement.parse( '__placeholder__' + extras ).extras, {}, ) else: return None, url_no_extras, None, {} for version_control in vcs: if url.lower().startswith('%s:' % version_control): url = '%s+%s' % (version_control, url) break if '+' not in url: if default_vcs: url = default_vcs + '+' + url else: raise InstallationError( '%s should either be a path to a local project or a VCS url ' 'beginning with svn+, git+, hg+, or bzr+' % editable_req ) vc_type = url.split('+', 1)[0].lower() if not vcs.get_backend(vc_type): error_message = 'For --editable=%s only ' % editable_req + \ ', '.join([backend.name + '+URL' for backend in vcs.backends]) + \ ' is currently supported' raise InstallationError(error_message) try: options = _build_editable_options(editable_req) except Exception as exc: raise InstallationError( '--editable=%s error in editable options:%s' % (editable_req, exc) ) if not options or 'egg' not in options: req = _build_req_from_url(editable_req) if not req: raise InstallationError( '--editable=%s is not the right format; it must have ' '#egg=Package' % editable_req ) else: req = options['egg'] package = _strip_postfix(req) return package, url, None, options
def from_line(cls, name, comes_from=None, isolated=False): """Creates an InstallRequirement from a name, which might be a requirement, directory containing 'setup.py', filename, or URL. """ from pip.index import Link url = None if is_url(name): marker_sep = '; ' else: marker_sep = ';' if marker_sep in name: name, markers = name.split(marker_sep, 1) markers = markers.strip() if not markers: markers = None else: markers = None name = name.strip() req = None path = os.path.normpath(os.path.abspath(name)) link = None if is_url(name): link = Link(name) elif (os.path.isdir(path) and (os.path.sep in name or name.startswith('.'))): if not is_installable_dir(path): raise InstallationError( "Directory %r is not installable. File 'setup.py' not " "found." % name ) link = Link(path_to_url(name)) elif is_archive_file(path): if not os.path.isfile(path): logger.warning( 'Requirement %r looks like a filename, but the file does ' 'not exist', name ) link = Link(path_to_url(name)) # it's a local file, dir, or url if link: url = link.url # Handle relative file URLs if link.scheme == 'file' and re.search(r'\.\./', url): url = path_to_url(os.path.normpath(os.path.abspath(link.path))) # wheel file if link.ext == wheel_ext: wheel = Wheel(link.filename) # can raise InvalidWheelFilename if not wheel.supported(): raise UnsupportedWheel( "%s is not a supported wheel on this platform." % wheel.filename ) req = "%s==%s" % (wheel.name, wheel.version) else: # set the req to the egg fragment. when it's not there, this # will become an 'unnamed' requirement req = link.egg_fragment # a requirement specifier else: req = name return cls(req, comes_from, url=url, markers=markers, isolated=isolated)
# method. # The code below assumes temporary source dirs - # prevent it doing bad things. if req.source_dir and not os.path.exists(os.path.join( req.source_dir, PIP_DELETE_MARKER_FILENAME)): raise AssertionError( "bad source dir - missing marker") # Delete the source we built the wheel from req.remove_temporary_source() # set the build directory again - name is known from # the work prepare_files did. req.source_dir = req.build_location( self.requirement_set.build_dir) # Update the link for this. req.link = pip.index.Link( path_to_url(wheel_file)) assert req.link.is_wheel # extract the wheel into the dir unpack_url( req.link, req.source_dir, None, False, session=self.requirement_set.session) else: build_failure.append(req) # notify success/failure if build_success: logger.info( 'Successfully built %s', ' '.join([req.name for req in build_success]), ) if build_failure:
def get_url(self, location): <<<<<<< HEAD urls = self.run_command(['info'], show_stdout=False, cwd=location) ======= urls = call_subprocess( [self.cmd, 'info'], show_stdout=False, cwd=location) >>>>>>> bde4533e29dfedadf6bcf9d451baa615bc828a59 for line in urls.splitlines(): line = line.strip() for x in ('checkout of branch: ', 'parent branch: '): if line.startswith(x): repo = line.split(x)[1] if self._is_local_repository(repo): return path_to_url(repo) return repo return None def get_revision(self, location): <<<<<<< HEAD revision = self.run_command( ['revno'], show_stdout=False, cwd=location) return revision.splitlines()[-1] def get_tag_revs(self, location): tags = self.run_command( ['tags'], show_stdout=False, cwd=location) ======= revision = call_subprocess( [self.cmd, 'revno'], show_stdout=False, cwd=location)
def from_line(cls, name, comes_from=None, isolated=False, options=None, wheel_cache=None, constraint=False): """Creates an InstallRequirement from a name, which might be a requirement, directory containing 'setup.py', filename, or URL. """ from pip.index import Link if is_url(name): marker_sep = '; ' else: marker_sep = ';' if marker_sep in name: name, markers = name.split(marker_sep, 1) markers = markers.strip() if not markers: markers = None else: markers = Marker(markers) else: markers = None name = name.strip() req = None path = os.path.normpath(os.path.abspath(name)) link = None extras = None if is_url(name): link = Link(name) else: p, extras = _strip_extras(path) if (os.path.isdir(p) and (os.path.sep in name or name.startswith('.'))): if not is_installable_dir(p): raise InstallationError( "Directory %r is not installable. File 'setup.py' " "not found." % name) link = Link(path_to_url(p)) elif is_archive_file(p): if not os.path.isfile(p): logger.warning( 'Requirement %r looks like a filename, but the ' 'file does not exist', name) link = Link(path_to_url(p)) # it's a local file, dir, or url if link: # Handle relative file URLs if link.scheme == 'file' and re.search(r'\.\./', link.url): link = Link( path_to_url(os.path.normpath(os.path.abspath(link.path)))) # wheel file if link.is_wheel: wheel = Wheel(link.filename) # can raise InvalidWheelFilename req = "%s==%s" % (wheel.name, wheel.version) else: # set the req to the egg fragment. when it's not there, this # will become an 'unnamed' requirement req = link.egg_fragment # a requirement specifier else: req = name if extras: extras = Requirement("placeholder" + extras.lower()).extras else: extras = () if req is not None: try: req = Requirement(req) except InvalidRequirement: if os.path.sep in req: add_msg = "It looks like a path." add_msg += deduce_helpful_msg(req) elif '=' in req and not any(op in req for op in operators): add_msg = "= is not a valid operator. Did you mean == ?" else: add_msg = traceback.format_exc() raise InstallationError("Invalid requirement: '%s'\n%s" % (req, add_msg)) return cls( req, comes_from, link=link, markers=markers, isolated=isolated, options=options if options else {}, wheel_cache=wheel_cache, constraint=constraint, extras=extras, )
def from_line( cls, name, comes_from=None, isolated=False, options=None, wheel_cache=None, constraint=False): """Creates an InstallRequirement from a name, which might be a requirement, directory containing 'setup.py', filename, or URL. """ from pip.index import Link if is_url(name): marker_sep = '; ' else: marker_sep = ';' if marker_sep in name: name, markers = name.split(marker_sep, 1) markers = markers.strip() if not markers: markers = None else: markers = None name = name.strip() req = None path = os.path.normpath(os.path.abspath(name)) link = None extras = None if is_url(name): link = Link(name) else: p, extras = _strip_extras(path) if (os.path.isdir(p) and (os.path.sep in name or name.startswith('.'))): if not is_installable_dir(p): raise InstallationError( "Directory %r is not installable. File 'setup.py' " "not found." % name ) link = Link(path_to_url(p)) elif is_archive_file(p): if not os.path.isfile(p): logger.warning( 'Requirement %r looks like a filename, but the ' 'file does not exist', name ) link = Link(path_to_url(p)) # it's a local file, dir, or url if link: # Normalize URLs link.normalize() # wheel file if link.is_wheel: wheel = Wheel(link.filename) # can raise InvalidWheelFilename req = "%s==%s" % (wheel.name, wheel.version) else: # set the req to the egg fragment. when it's not there, this # will become an 'unnamed' requirement req = link.egg_fragment # a requirement specifier else: req = name options = options if options else {} res = cls(req, comes_from, link=link, markers=markers, isolated=isolated, options=options, wheel_cache=wheel_cache, constraint=constraint) if extras: res.extras = Requirement('placeholder' + extras).extras return res
def test_path_to_url_win(): assert path_to_url('c:/tmp/file') == 'file:///c:/tmp/file' assert path_to_url('c:\\tmp\\file') == 'file:///c:/tmp/file' path = os.path.join(os.getcwd(), 'file') assert path_to_url('file') == 'file:' + pathname2url(path)