def test_create__target_python_none(self) -> None: """ Test passing target_python=None. """ link_collector = LinkCollector( session=PipSession(), search_scope=SearchScope([], []), ) finder = PackageFinder.create( link_collector=link_collector, selection_prefs=SelectionPreferences(allow_yanked=True), target_python=None, use_deprecated_html5lib=False, ) # Spot-check the default TargetPython object. actual_target_python = finder._target_python assert actual_target_python._given_py_version_info is None assert actual_target_python.py_version_info == CURRENT_PY_VERSION_INFO
def test_create__format_control(self): """ Test that the format_control attribute is set correctly. """ format_control = FormatControl(set(), {':all:'}) selection_prefs = SelectionPreferences( allow_yanked=True, format_control=format_control, ) finder = PackageFinder.create( search_scope=SearchScope([], []), selection_prefs=selection_prefs, session=PipSession(), ) actual_format_control = finder.format_control assert actual_format_control is format_control # Check that the attributes weren't reset. assert actual_format_control.only_binary == {':all:'}
def test_create__target_python(self): """ Test that the _target_python attribute is set correctly. """ link_collector = LinkCollector( session=PipSession(), search_scope=SearchScope([], []), ) target_python = TargetPython(py_version_info=(3, 7, 3)) finder = PackageFinder.create( link_collector=link_collector, selection_prefs=SelectionPreferences(allow_yanked=True), target_python=target_python, ) actual_target_python = finder._target_python # The target_python attribute should be set as is. assert actual_target_python is target_python # Check that the attributes weren't reset. assert actual_target_python.py_version_info == (3, 7, 3)
def test_create__candidate_prefs( self, allow_all_prereleases, prefer_binary, ): """ Test that the _candidate_prefs attribute is set correctly. """ selection_prefs = SelectionPreferences( allow_yanked=True, allow_all_prereleases=allow_all_prereleases, prefer_binary=prefer_binary, ) finder = PackageFinder.create( search_scope=SearchScope([], []), selection_prefs=selection_prefs, session=PipSession(), ) candidate_prefs = finder._candidate_prefs assert candidate_prefs.allow_all_prereleases == allow_all_prereleases assert candidate_prefs.prefer_binary == prefer_binary
def test_iter_secure_origins__none_trusted_hosts(self): """ Test iter_secure_origins() after passing trusted_hosts=None. """ # Use PackageFinder.create() rather than make_test_finder() # to make sure we're really passing trusted_hosts=None. search_scope = SearchScope([], []) selection_prefs = SelectionPreferences(allow_yanked=True, ) finder = PackageFinder.create( search_scope=search_scope, selection_prefs=selection_prefs, trusted_hosts=None, session=object(), ) actual = list(finder.iter_secure_origins()) assert len(actual) == 6 # Spot-check that SECURE_ORIGINS is included. assert actual[0] == ('https', '*', '*')
def test_create__ignore_requires_python( self, ignore_requires_python: bool) -> None: """ Test that the _ignore_requires_python attribute is set correctly. """ link_collector = LinkCollector( session=PipSession(), search_scope=SearchScope([], []), ) selection_prefs = SelectionPreferences( allow_yanked=True, ignore_requires_python=ignore_requires_python, ) finder = PackageFinder.create( link_collector=link_collector, selection_prefs=selection_prefs, use_deprecated_html5lib=False, ) assert finder._ignore_requires_python == ignore_requires_python
def make_search_scope(options, suppress_no_index=False): """ :param suppress_no_index: Whether to ignore the --no-index option when constructing the SearchScope object. """ index_urls = [options.index_url] + options.extra_index_urls if options.no_index and not suppress_no_index: logger.debug( 'Ignoring indexes: %s', ','.join(redact_password_from_url(url) for url in index_urls), ) index_urls = [] search_scope = SearchScope( find_links=options.find_links, index_urls=index_urls, ) return search_scope
def create_package_finder(**kwargs): find_links = kwargs.pop('find_links', None) index_urls = kwargs.pop('index_urls', None) allow_all_prereleases = kwargs.pop('allow_all_prereleases', None) if find_links is not None: kwargs.setdefault( 'search_scope', SearchScope( find_links=find_links, index_urls=index_urls, )) if allow_all_prereleases is not None: kwargs.setdefault( 'selection_prefs', SelectionPreferences( allow_yanked=True, allow_all_prereleases=allow_all_prereleases, )) return PackageFinder.create(**kwargs)
def test_get_formatted_locations_basic_auth(self) -> None: """ Test that basic authentication credentials defined in URL is not included in formatted output. """ index_urls = [ "https://pypi.org/simple", "https://*****:*****@repo.domain.com", ] find_links = ["https://*****:*****@page.domain.com"] search_scope = SearchScope( find_links=find_links, index_urls=index_urls, ) result = search_scope.get_formatted_locations() assert "repo-user:****@repo.domain.com" in result assert "repo-pass" not in result assert "links-user:****@page.domain.com" in result assert "links-pass" not in result
def test_make_link_evaluator( self, allow_yanked: bool, ignore_requires_python: bool, only_binary: Set[str], expected_formats: FrozenSet[str], ) -> None: # Create a test TargetPython that we can check for. target_python = TargetPython(py_version_info=(3, 7)) format_control = FormatControl(set(), only_binary) link_collector = LinkCollector( session=PipSession(), search_scope=SearchScope([], []), ) finder = PackageFinder( link_collector=link_collector, target_python=target_python, allow_yanked=allow_yanked, format_control=format_control, ignore_requires_python=ignore_requires_python, use_deprecated_html5lib=False, ) # Pass a project_name that will be different from canonical_name. link_evaluator = finder.make_link_evaluator("Twine") assert link_evaluator.project_name == "Twine" assert link_evaluator._canonical_name == "twine" assert link_evaluator._allow_yanked == allow_yanked assert link_evaluator._ignore_requires_python == ignore_requires_python assert link_evaluator._formats == expected_formats # Test the _target_python attribute. actual_target_python = link_evaluator._target_python # The target_python attribute should be set as is. assert actual_target_python is target_python # For good measure, check that the attributes weren't reset. assert actual_target_python._given_py_version_info == (3, 7) assert actual_target_python.py_version_info == (3, 7, 0)
def test_make_candidate_evaluator( self, allow_all_prereleases, prefer_binary, ): target_python = TargetPython() target_python._valid_tags = [('py36', 'none', 'any')] candidate_prefs = CandidatePreferences( prefer_binary=prefer_binary, allow_all_prereleases=allow_all_prereleases, ) finder = PackageFinder( search_scope=SearchScope([], []), session=PipSession(), target_python=target_python, allow_yanked=True, candidate_prefs=candidate_prefs, ) evaluator = finder.make_candidate_evaluator() assert evaluator._allow_all_prereleases == allow_all_prereleases assert evaluator._prefer_binary == prefer_binary assert evaluator._supported_tags == [('py36', 'none', 'any')]
def test_create__format_control(self) -> None: """ Test that the format_control attribute is set correctly. """ link_collector = LinkCollector( session=PipSession(), search_scope=SearchScope([], []), ) format_control = FormatControl(set(), {":all:"}) selection_prefs = SelectionPreferences( allow_yanked=True, format_control=format_control, ) finder = PackageFinder.create( link_collector=link_collector, selection_prefs=selection_prefs, use_deprecated_html5lib=False, ) actual_format_control = finder.format_control assert actual_format_control is format_control # Check that the attributes weren't reset. assert actual_format_control.only_binary == {":all:"}
def test_create__candidate_evaluator( self, allow_all_prereleases, prefer_binary, ): """ Test that the candidate_evaluator attribute is set correctly. """ selection_prefs = SelectionPreferences( allow_yanked=True, allow_all_prereleases=allow_all_prereleases, prefer_binary=prefer_binary, ) target_python = TargetPython(py_version_info=(3, 7, 3)) target_python._valid_tags = ['tag1', 'tag2'] finder = PackageFinder.create( search_scope=SearchScope([], []), selection_prefs=selection_prefs, session=PipSession(), target_python=target_python, ) evaluator = finder.candidate_evaluator assert evaluator.allow_all_prereleases == allow_all_prereleases assert evaluator._prefer_binary == prefer_binary assert evaluator._supported_tags == ['tag1', 'tag2']
def test_make_candidate_evaluator( self, allow_all_prereleases: bool, prefer_binary: bool, ) -> None: target_python = TargetPython() target_python._valid_tags = [Tag("py36", "none", "any")] candidate_prefs = CandidatePreferences( prefer_binary=prefer_binary, allow_all_prereleases=allow_all_prereleases, ) link_collector = LinkCollector( session=PipSession(), search_scope=SearchScope([], []), ) finder = PackageFinder( link_collector=link_collector, target_python=target_python, allow_yanked=True, candidate_prefs=candidate_prefs, use_deprecated_html5lib=False, ) specifier = SpecifierSet() # Pass hashes to check that _hashes is set. hashes = Hashes({"sha256": [64 * "a"]}) evaluator = finder.make_candidate_evaluator( "my-project", specifier=specifier, hashes=hashes, ) assert evaluator._allow_all_prereleases == allow_all_prereleases assert evaluator._hashes == hashes assert evaluator._prefer_binary == prefer_binary assert evaluator._project_name == "my-project" assert evaluator._specifier is specifier assert evaluator._supported_tags == [Tag("py36", "none", "any")]
def test_make_candidate_evaluator( self, allow_all_prereleases, prefer_binary, ): target_python = TargetPython() target_python._valid_tags = [('py36', 'none', 'any')] candidate_prefs = CandidatePreferences( prefer_binary=prefer_binary, allow_all_prereleases=allow_all_prereleases, ) link_collector = LinkCollector( session=PipSession(), search_scope=SearchScope([], []), ) finder = PackageFinder( link_collector=link_collector, target_python=target_python, allow_yanked=True, candidate_prefs=candidate_prefs, ) specifier = SpecifierSet() # Pass hashes to check that _hashes is set. hashes = Hashes({'sha256': [64 * 'a']}) evaluator = finder.make_candidate_evaluator( 'my-project', specifier=specifier, hashes=hashes, ) assert evaluator._allow_all_prereleases == allow_all_prereleases assert evaluator._hashes == hashes assert evaluator._prefer_binary == prefer_binary assert evaluator._project_name == 'my-project' assert evaluator._specifier is specifier assert evaluator._supported_tags == [('py36', 'none', 'any')]
def handle_line( line, # type: ParsedLine finder=None, # type: Optional[PackageFinder] options=None, # type: Optional[optparse.Values] session=None, # type: Optional[PipSession] wheel_cache=None, # type: Optional[WheelCache] use_pep517=None, # type: Optional[bool] ): # type: (...) -> Optional[InstallRequirement] """Handle a single parsed requirements line; This can result in creating/yielding requirements, or updating the finder. For lines that contain requirements, the only options that have an effect are from SUPPORTED_OPTIONS_REQ, and they are scoped to the requirement. Other options from SUPPORTED_OPTIONS may be present, but are ignored. For lines that do not contain requirements, the only options that have an effect are from SUPPORTED_OPTIONS. Options from SUPPORTED_OPTIONS_REQ may be present, but are ignored. These lines may contain multiple options (although our docs imply only one is supported), and all our parsed and affect the finder. """ # preserve for the nested code path line_comes_from = '%s %s (line %s)' % ( '-c' if line.constraint else '-r', line.filename, line.lineno, ) # return a line requirement if line.args: isolated = options.isolated_mode if options else False if options: cmdoptions.check_install_build_global(options, line.opts) # get the options that apply to requirements req_options = {} for dest in SUPPORTED_OPTIONS_REQ_DEST: if dest in line.opts.__dict__ and line.opts.__dict__[dest]: req_options[dest] = line.opts.__dict__[dest] line_source = 'line {} of {}'.format(line.lineno, line.filename) return install_req_from_line( line.args, comes_from=line_comes_from, use_pep517=use_pep517, isolated=isolated, options=req_options, wheel_cache=wheel_cache, constraint=line.constraint, line_source=line_source, ) # return an editable requirement elif line.opts.editables: isolated = options.isolated_mode if options else False return install_req_from_editable(line.opts.editables[0], comes_from=line_comes_from, use_pep517=use_pep517, constraint=line.constraint, isolated=isolated, wheel_cache=wheel_cache) # percolate hash-checking option upward elif line.opts.require_hashes: options.require_hashes = line.opts.require_hashes # set finder options elif finder: find_links = finder.find_links index_urls = finder.index_urls if line.opts.index_url: index_urls = [line.opts.index_url] if line.opts.no_index is True: index_urls = [] if line.opts.extra_index_urls: index_urls.extend(line.opts.extra_index_urls) if line.opts.find_links: # FIXME: it would be nice to keep track of the source # of the find_links: support a find-links local path # relative to a requirements file. value = line.opts.find_links[0] req_dir = os.path.dirname(os.path.abspath(line.filename)) relative_to_reqs_file = os.path.join(req_dir, value) if os.path.exists(relative_to_reqs_file): value = relative_to_reqs_file find_links.append(value) search_scope = SearchScope( find_links=find_links, index_urls=index_urls, ) finder.search_scope = search_scope if line.opts.pre: finder.set_allow_all_prereleases() if session: for host in line.opts.trusted_hosts or []: source = 'line {} of {}'.format(line.lineno, line.filename) session.add_trusted_host(host, source=source) return None
def handle_option_line( opts, # type: Values filename, # type: str lineno, # type: int finder=None, # type: Optional[PackageFinder] options=None, # type: Optional[optparse.Values] session=None, # type: Optional[PipSession] ): # type: (...) -> None if options: # percolate options upward if opts.require_hashes: options.require_hashes = opts.require_hashes if opts.features_enabled: options.features_enabled.extend( f for f in opts.features_enabled if f not in options.features_enabled ) # set finder options if finder: find_links = finder.find_links index_urls = finder.index_urls if opts.index_url: index_urls = [opts.index_url] if opts.no_index is True: index_urls = [] if opts.extra_index_urls: index_urls.extend(opts.extra_index_urls) if opts.find_links: # FIXME: it would be nice to keep track of the source # of the find_links: support a find-links local path # relative to a requirements file. value = opts.find_links[0] req_dir = os.path.dirname(os.path.abspath(filename)) relative_to_reqs_file = os.path.join(req_dir, value) if os.path.exists(relative_to_reqs_file): value = relative_to_reqs_file find_links.append(value) if session: # We need to update the auth urls in session session.update_index_urls(index_urls) search_scope = SearchScope( find_links=find_links, index_urls=index_urls, ) finder.search_scope = search_scope if opts.pre: finder.set_allow_all_prereleases() if opts.prefer_binary: finder.set_prefer_binary() if session: for host in opts.trusted_hosts or []: source = f'line {lineno} of {filename}' session.add_trusted_host(host, source=source)
def process_line( line, # type: Text filename, # type: str line_number, # type: int finder=None, # type: Optional[PackageFinder] comes_from=None, # type: Optional[str] options=None, # type: Optional[optparse.Values] session=None, # type: Optional[PipSession] wheel_cache=None, # type: Optional[WheelCache] use_pep517=None, # type: Optional[bool] constraint=False, # type: bool ): # type: (...) -> Iterator[InstallRequirement] """Process a single requirements line; This can result in creating/yielding requirements, or updating the finder. For lines that contain requirements, the only options that have an effect are from SUPPORTED_OPTIONS_REQ, and they are scoped to the requirement. Other options from SUPPORTED_OPTIONS may be present, but are ignored. For lines that do not contain requirements, the only options that have an effect are from SUPPORTED_OPTIONS. Options from SUPPORTED_OPTIONS_REQ may be present, but are ignored. These lines may contain multiple options (although our docs imply only one is supported), and all our parsed and affect the finder. :param constraint: If True, parsing a constraints file. :param options: OptionParser options that we may update """ parser = build_parser(line) defaults = parser.get_default_values() defaults.index_url = None if finder: defaults.format_control = finder.format_control args_str, options_str = break_args_options(line) # Prior to 2.7.3, shlex cannot deal with unicode entries if sys.version_info < (2, 7, 3): # https://github.com/python/mypy/issues/1174 options_str = options_str.encode('utf8') # type: ignore # https://github.com/python/mypy/issues/1174 opts, _ = parser.parse_args(shlex.split(options_str), defaults) # type: ignore # preserve for the nested code path line_comes_from = '%s %s (line %s)' % ( '-c' if constraint else '-r', filename, line_number, ) # yield a line requirement if args_str: isolated = options.isolated_mode if options else False if options: cmdoptions.check_install_build_global(options, opts) # get the options that apply to requirements req_options = {} for dest in SUPPORTED_OPTIONS_REQ_DEST: if dest in opts.__dict__ and opts.__dict__[dest]: req_options[dest] = opts.__dict__[dest] line_source = 'line {} of {}'.format(line_number, filename) yield install_req_from_line( args_str, comes_from=line_comes_from, use_pep517=use_pep517, isolated=isolated, options=req_options, wheel_cache=wheel_cache, constraint=constraint, line_source=line_source, ) # yield an editable requirement elif opts.editables: isolated = options.isolated_mode if options else False yield install_req_from_editable(opts.editables[0], comes_from=line_comes_from, use_pep517=use_pep517, constraint=constraint, isolated=isolated, wheel_cache=wheel_cache) # parse a nested requirements file elif opts.requirements or opts.constraints: if opts.requirements: req_path = opts.requirements[0] nested_constraint = False else: req_path = opts.constraints[0] nested_constraint = True # original file is over http if SCHEME_RE.search(filename): # do a url join so relative paths work req_path = urllib_parse.urljoin(filename, req_path) # original file and nested file are paths elif not SCHEME_RE.search(req_path): # do a join so relative paths work req_path = os.path.join(os.path.dirname(filename), req_path) # TODO: Why not use `comes_from='-r {} (line {})'` here as well? parsed_reqs = parse_requirements(req_path, finder, comes_from, options, session, constraint=nested_constraint, wheel_cache=wheel_cache) for req in parsed_reqs: yield req # percolate hash-checking option upward elif opts.require_hashes: options.require_hashes = opts.require_hashes # set finder options elif finder: find_links = finder.find_links index_urls = finder.index_urls if opts.index_url: index_urls = [opts.index_url] if opts.no_index is True: index_urls = [] if opts.extra_index_urls: index_urls.extend(opts.extra_index_urls) if opts.find_links: # FIXME: it would be nice to keep track of the source # of the find_links: support a find-links local path # relative to a requirements file. value = opts.find_links[0] req_dir = os.path.dirname(os.path.abspath(filename)) relative_to_reqs_file = os.path.join(req_dir, value) if os.path.exists(relative_to_reqs_file): value = relative_to_reqs_file find_links.append(value) search_scope = SearchScope( find_links=find_links, index_urls=index_urls, ) finder.search_scope = search_scope if opts.pre: finder.set_allow_all_prereleases() for host in opts.trusted_hosts or []: source = 'line {} of {}'.format(line_number, filename) session.add_trusted_host(host, source=source)
value = opts.find_links[0] req_dir = os.path.dirname(os.path.abspath(filename)) relative_to_reqs_file = os.path.join(req_dir, value) if os.path.exists(relative_to_reqs_file): value = relative_to_reqs_file find_links.append(value) <<<<<<< HEAD if session: # We need to update the auth urls in session session.update_index_urls(index_urls) ======= >>>>>>> 74c061954d5e927be4caafbd793e96a50563c265 search_scope = SearchScope( find_links=find_links, index_urls=index_urls, ) finder.search_scope = search_scope if opts.pre: finder.set_allow_all_prereleases() if opts.prefer_binary: finder.set_prefer_binary() if session: for host in opts.trusted_hosts or []: source = 'line {} of {}'.format(lineno, filename) session.add_trusted_host(host, source=source)