Esempio n. 1
0
def test_resolver_blacklist():
    if PY2:
        blacklist = {'project2': '<3'}
        required_project = "project2;python_version>'3'"
    else:
        blacklist = {'project2': '>3'}
        required_project = "project2;python_version<'3'"

    project1 = make_sdist(name='project1',
                          version='1.0.0',
                          install_reqs=[required_project])
    project2 = make_sdist(name='project2', version='1.1.0')

    with temporary_dir() as td:
        safe_copy(project1, os.path.join(td, os.path.basename(project1)))
        safe_copy(project2, os.path.join(td, os.path.basename(project2)))
        fetchers = [Fetcher([td])]

        dists = resolve(['project1'], fetchers=fetchers)
        assert len(dists) == 2

        dists = resolve(['project1'],
                        fetchers=fetchers,
                        pkg_blacklist=blacklist)
        assert len(dists) == 1
Esempio n. 2
0
def test_cached_dependency_pinned_unpinned_resolution_multi_run():
  # This exercises the issue described here: https://github.com/pantsbuild/pex/issues/178
  project1_0_0 = make_sdist(name='project', version='1.0.0')
  project1_1_0 = make_sdist(name='project', version='1.1.0')

  with temporary_dir() as td:
    for sdist in (project1_0_0, project1_1_0):
      safe_copy(sdist, os.path.join(td, os.path.basename(sdist)))
    fetchers = [Fetcher([td])]
    with temporary_dir() as cd:
      # First run, pinning 1.0.0 in the cache
      dists = resolve(['project', 'project==1.0.0'], fetchers=fetchers, cache=cd, cache_ttl=1000)
      assert len(dists) == 1
      assert dists[0].version == '1.0.0'
      # This simulates separate invocations of pex but allows us to keep the same tmp cache dir
      Crawler.reset_cache()
      # Second, run, the unbounded 'project' req will find the 1.0.0 in the cache. But should also
      # return SourcePackages found in td
      dists = resolve(['project', 'project==1.1.0'], fetchers=fetchers, cache=cd, cache_ttl=1000)
      assert len(dists) == 1
      assert dists[0].version == '1.1.0'
      # Third run, if exact resolvable and inexact resolvable, and cache_ttl is expired, exact
      # resolvable should pull from pypi as well since inexact will and the resulting
      # resolvable_set.merge() would fail.
      Crawler.reset_cache()
      time.sleep(1)
      dists = resolve(['project', 'project==1.1.0'], fetchers=fetchers, cache=cd,
                      cache_ttl=1)
      assert len(dists) == 1
      assert dists[0].version == '1.1.0'
Esempio n. 3
0
def test_resolve_prereleases_cached():
  stable_dep = make_sdist(name='dep', version='2.0.0')
  prerelease_dep = make_sdist(name='dep', version='3.0.0rc3')

  with temporary_dir() as td:
    for sdist in (stable_dep, prerelease_dep):
      safe_copy(sdist, os.path.join(td, os.path.basename(sdist)))
    fetchers = [Fetcher([td])]

    with temporary_dir() as cd:
      def assert_resolve(dep, expected_version, **resolve_kwargs):
        dists = list(
          resolve_multi([dep], cache=cd, cache_ttl=1000, **resolve_kwargs)
        )
        assert 1 == len(dists)
        dist = dists[0]
        assert expected_version == dist.version

      Crawler.reset_cache()

      # First do a run to load it into the cache.
      assert_resolve('dep>=1,<4', '3.0.0rc3', allow_prereleases=True, fetchers=fetchers)

      # This simulates running from another pex command. The Crawler cache actually caches an empty
      # cache so this fails in the same "process".
      Crawler.reset_cache()

      # Now assert that we can get it from the cache by removing the source.
      assert_resolve('dep>=1,<4', '3.0.0rc3', allow_prereleases=True, fetchers=[])

      # It should also be able to resolve without allow_prereleases, if explicitly requested.
      Crawler.reset_cache()
      assert_resolve('dep>=1.rc1,<4', '3.0.0rc3', fetchers=[])
Esempio n. 4
0
def test_resolve_prereleases_multiple_set():
  stable_dep = make_sdist(name='dep', version='2.0.0')
  prerelease_dep1 = make_sdist(name='dep', version='3.0.0rc3')
  prerelease_dep2 = make_sdist(name='dep', version='3.0.0rc4')
  prerelease_dep3 = make_sdist(name='dep', version='3.0.0rc5')

  with temporary_dir() as td:
    for sdist in (stable_dep, prerelease_dep1, prerelease_dep2, prerelease_dep3):
      safe_copy(sdist, os.path.join(td, os.path.basename(sdist)))
    fetchers = [Fetcher([td])]

    def assert_resolve(expected_version, **resolve_kwargs):
      dists = resolve(
        [
          'dep>=3.0.0rc1',
          'dep==3.0.0rc4',
        ],
        fetchers=fetchers, **resolve_kwargs)
      assert 1 == len(dists)
      dist = dists[0]
      assert expected_version == dist.version

    # This should resolve with explicit prerelease being set or implicitly.
    assert_resolve('3.0.0rc4', allow_prereleases=True)
    assert_resolve('3.0.0rc4')
Esempio n. 5
0
def test_diamond_local_resolve_cached():
  # This exercises the issue described here: https://github.com/pantsbuild/pex/issues/120
  project1_sdist = make_sdist(name='project1', install_reqs=['project2<1.0.0'])
  project2_sdist = make_sdist(name='project2')

  with temporary_dir() as dd:
    for sdist in (project1_sdist, project2_sdist):
      safe_copy(sdist, os.path.join(dd, os.path.basename(sdist)))
    fetchers = [Fetcher([dd])]
    with temporary_dir() as cd:
      dists = resolve(['project1', 'project2'], fetchers=fetchers, cache=cd, cache_ttl=1000)
      assert len(dists) == 2
Esempio n. 6
0
def test_diamond_local_resolve_cached():
  # This exercises the issue described here: https://github.com/pantsbuild/pex/issues/120
  project1_sdist = make_sdist(name='project1', install_reqs=['project2<1.0.0'])
  project2_sdist = make_sdist(name='project2')

  with temporary_dir() as dd:
    for sdist in (project1_sdist, project2_sdist):
      safe_copy(sdist, os.path.join(dd, os.path.basename(sdist)))
    fetchers = [Fetcher([dd])]
    with temporary_dir() as cd:
      dists = resolve(['project1', 'project2'], fetchers=fetchers, cache=cd, cache_ttl=1000)
      assert len(dists) == 2
Esempio n. 7
0
def test_resolve_extra_sdist():
  project1_sdist = make_sdist(name='project1',
                              version='1.0.0',
                              extras_require={'foo': ['project2']})
  project2_sdist = make_sdist(name='project2', version='2.0.0')
  with temporary_dir() as td:
    for sdist in (project1_sdist, project2_sdist):
      safe_copy(sdist, os.path.join(td, os.path.basename(sdist)))
    fetchers = [Fetcher([td])]

    resolved_dists = do_resolve_multi(['project1[foo]'], fetchers=fetchers)
    assert ({_parse_requirement(req) for req in ('project1[foo]', 'project2; extra=="foo"')} ==
            {_parse_requirement(resolved_dist.requirement) for resolved_dist in resolved_dists})
Esempio n. 8
0
def test_resolve_prereleases_and_no_version():
  prerelease_dep = make_sdist(name='dep', version='3.0.0rc3')

  with temporary_dir() as td:
    safe_copy(prerelease_dep, os.path.join(td, os.path.basename(prerelease_dep)))
    fetchers = [Fetcher([td])]

    def assert_resolve(deps, expected_version, **resolve_kwargs):
      dists = list(
        resolve_multi(deps, fetchers=fetchers, **resolve_kwargs)
      )
      assert 1 == len(dists)
      dist = dists[0]
      assert expected_version == dist.version

    # When allow_prereleases is specified, the requirement (from two dependencies)
    # for a specific pre-release version and no version specified, accepts the pre-release
    # version correctly.
    assert_resolve(['dep==3.0.0rc3', 'dep'], '3.0.0rc3', allow_prereleases=True)

    # Without allow_prereleases set, the pre-release version is rejected.
    # This used to be an issue when a command-line use did not pass the `--pre` option
    # correctly into the API call for resolve_multi() from build_pex() in pex.py.
    with pytest.raises(Unsatisfiable):
      assert_resolve(['dep==3.0.0rc3', 'dep'], '3.0.0rc3')
Esempio n. 9
0
def test_ambiguous_transitive_resolvable():
  # If an unbounded or larger bounded resolvable is resolved first, and a
  # transitive resolvable is resolved later in another round, Error(Ambiguous resolvable) can be
  # raised because foo pulls in foo-2.0.0 and bar->foo==1.0.0 pulls in foo-1.0.0.
  foo1_0 = make_sdist(name='foo', version='1.0.0')
  foo2_0 = make_sdist(name='foo', version='2.0.0')
  bar1_0 = make_sdist(name='bar', version='1.0.0', install_reqs=['foo==1.0.0'])
  with temporary_dir() as td:
    for sdist in (foo1_0, foo2_0, bar1_0):
      safe_copy(sdist, os.path.join(td, os.path.basename(sdist)))
    fetchers = [Fetcher([td])]
    with temporary_dir() as cd:
      dists = resolve(['foo', 'bar'], fetchers=fetchers, cache=cd,
                      cache_ttl=1000)
      assert len(dists) == 2
      assert dists[0].version == '1.0.0'
Esempio n. 10
0
def test_simple_local_resolve():
  project_sdist = make_sdist(name='project')

  with temporary_dir() as td:
    safe_copy(project_sdist, os.path.join(td, os.path.basename(project_sdist)))
    fetchers = [Fetcher([td])]
    dists = resolve(['project'], fetchers=fetchers)
    assert len(dists) == 1
Esempio n. 11
0
def test_intransitive():
    foo1_0 = make_sdist(name='foo', version='1.0.0')
    # The nonexistent req ensures that we are actually not acting transitively (as that would fail).
    bar1_0 = make_sdist(name='bar',
                        version='1.0.0',
                        install_reqs=['nonexistent==1.0.0'])
    with temporary_dir() as td:
        for sdist in (foo1_0, bar1_0):
            safe_copy(sdist, os.path.join(td, os.path.basename(sdist)))
        fetchers = [Fetcher([td])]
        with temporary_dir() as cd:
            resolved_dists = do_resolve_multi(['foo', 'bar'],
                                              fetchers=fetchers,
                                              cache=cd,
                                              cache_ttl=1000,
                                              transitive=False)
            assert len(resolved_dists) == 2
Esempio n. 12
0
def test_simple_local_resolve():
  project_sdist = make_sdist(name='project')

  with temporary_dir() as td:
    safe_copy(project_sdist, os.path.join(td, os.path.basename(project_sdist)))
    fetchers = [Fetcher([td])]
    dists = list(resolve_multi(['project'], fetchers=fetchers))
    assert len(dists) == 1
Esempio n. 13
0
def test_clp_prereleases_resolver():
  prerelease_dep = make_sdist(name='dep', version='1.2.3b1')
  with temporary_dir() as td:
    safe_copy(prerelease_dep, os.path.join(td, os.path.basename(prerelease_dep)))
    fetcher = Fetcher([td])

    # When no specific options are specified, allow_prereleases is None
    parser, resolver_options_builder = configure_clp()
    assert resolver_options_builder._allow_prereleases is None

    # When we specify `--pre`, allow_prereleases is True
    options, reqs = parser.parse_args(args=['--pre', 'dep==1.2.3b1', 'dep'])
    assert resolver_options_builder._allow_prereleases
    # We need to use our own fetcher instead of PyPI
    resolver_options_builder._fetchers.insert(0, fetcher)

    #####
    # The resolver created during processing of command line options (configure_clp)
    # is not actually passed into the API call (resolve_multi) from build_pex().
    # Instead, resolve_multi() calls resolve() where a new ResolverOptionsBuilder instance
    # is created. The only way to supply our own fetcher to that new instance is to patch it
    # here in the test so that it can fetch our test package (dep-1.2.3b1). Hence, this class
    # below and the change in the `pex.resolver` module where the patched object resides.
    #
    import pex.resolver

    class BuilderWithFetcher(ResolverOptionsBuilder):
      def __init__(self,
                   fetchers=None,
                   allow_all_external=False,
                   allow_external=None,
                   allow_unverified=None,
                   allow_prereleases=None,
                   precedence=None,
                   context=None
                   ):
        super(BuilderWithFetcher, self).__init__(fetchers=fetchers,
                                                 allow_all_external=allow_all_external,
                                                 allow_external=allow_external,
                                                 allow_unverified=allow_unverified,
                                                 allow_prereleases=allow_prereleases,
                                                 precedence=precedence,
                                                 context=context)
        self._fetchers.insert(0, fetcher)
    # end stub
    #####

    # Without a corresponding fix in pex.py, this test failed for a dependency requirement of
    # dep==1.2.3b1 from one package and just dep (any version accepted) from another package.
    # The failure was an exit from build_pex() with the message:
    #
    # Could not satisfy all requirements for dep==1.2.3b1:
    #     dep==1.2.3b1, dep
    #
    # With a correct behavior the assert line is reached and pex_builder object created.
    with mock.patch.object(pex.resolver, 'ResolverOptionsBuilder', BuilderWithFetcher):
      pex_builder = build_pex(reqs, options, resolver_options_builder)
      assert pex_builder is not None
Esempio n. 14
0
def test_resolve_prereleases():
  stable_dep = make_sdist(name='dep', version='2.0.0')
  prerelease_dep = make_sdist(name='dep', version='3.0.0rc3')

  with temporary_dir() as td:
    for sdist in (stable_dep, prerelease_dep):
      safe_copy(sdist, os.path.join(td, os.path.basename(sdist)))
    fetchers = [Fetcher([td])]

    def assert_resolve(expected_version, **resolve_kwargs):
      dists = resolve(['dep>=1,<4'], fetchers=fetchers, **resolve_kwargs)
      assert 1 == len(dists)
      dist = dists[0]
      assert expected_version == dist.version

    assert_resolve('2.0.0')
    assert_resolve('2.0.0', allow_prereleases=False)
    assert_resolve('3.0.0rc3', allow_prereleases=True)
Esempio n. 15
0
def test_cached_dependency_pinned_unpinned_resolution_multi_run():
  # This exercises the issue described here: https://github.com/pantsbuild/pex/issues/178
  project1_0_0 = make_sdist(name='project', version='1.0.0')
  project1_1_0 = make_sdist(name='project', version='1.1.0')

  with temporary_dir() as td:
    for sdist in (project1_0_0, project1_1_0):
      safe_copy(sdist, os.path.join(td, os.path.basename(sdist)))
    fetchers = [Fetcher([td])]
    with temporary_dir() as cd:
      # First run, pinning 1.0.0 in the cache
      dists = list(
        resolve_multi(['project', 'project==1.0.0'],
                      fetchers=fetchers,
                      cache=cd,
                      cache_ttl=1000)
      )
      assert len(dists) == 1
      assert dists[0].version == '1.0.0'
      # This simulates separate invocations of pex but allows us to keep the same tmp cache dir
      Crawler.reset_cache()
      # Second, run, the unbounded 'project' req will find the 1.0.0 in the cache. But should also
      # return SourcePackages found in td
      dists = list(
        resolve_multi(['project', 'project==1.1.0'],
                      fetchers=fetchers,
                      cache=cd,
                      cache_ttl=1000)
      )
      assert len(dists) == 1
      assert dists[0].version == '1.1.0'
      # Third run, if exact resolvable and inexact resolvable, and cache_ttl is expired, exact
      # resolvable should pull from pypi as well since inexact will and the resulting
      # resolvable_set.merge() would fail.
      Crawler.reset_cache()
      time.sleep(1)
      dists = list(
        resolve_multi(['project', 'project==1.1.0'],
                      fetchers=fetchers,
                      cache=cd,
                      cache_ttl=1)
      )
      assert len(dists) == 1
      assert dists[0].version == '1.1.0'
Esempio n. 16
0
def test_ambiguous_transitive_resolvable():
  # If an unbounded or larger bounded resolvable is resolved first, and a
  # transitive resolvable is resolved later in another round, Error(Ambiguous resolvable) can be
  # raised because foo pulls in foo-2.0.0 and bar->foo==1.0.0 pulls in foo-1.0.0.
  foo1_0 = make_sdist(name='foo', version='1.0.0')
  foo2_0 = make_sdist(name='foo', version='2.0.0')
  bar1_0 = make_sdist(name='bar', version='1.0.0', install_reqs=['foo==1.0.0'])
  with temporary_dir() as td:
    for sdist in (foo1_0, foo2_0, bar1_0):
      safe_copy(sdist, os.path.join(td, os.path.basename(sdist)))
    fetchers = [Fetcher([td])]
    with temporary_dir() as cd:
      dists = list(
        resolve_multi(['foo', 'bar'],
                      fetchers=fetchers,
                      cache=cd,
                      cache_ttl=1000)
      )
      assert len(dists) == 2
      assert dists[0].version == '1.0.0'
Esempio n. 17
0
def test_resolve_prereleases():
  stable_dep = make_sdist(name='dep', version='2.0.0')
  prerelease_dep = make_sdist(name='dep', version='3.0.0rc3')

  with temporary_dir() as td:
    for sdist in (stable_dep, prerelease_dep):
      safe_copy(sdist, os.path.join(td, os.path.basename(sdist)))
    fetchers = [Fetcher([td])]

    def assert_resolve(expected_version, **resolve_kwargs):
      dists = list(
        resolve_multi(['dep>=1,<4'], fetchers=fetchers, **resolve_kwargs)
      )
      assert 1 == len(dists)
      dist = dists[0]
      assert expected_version == dist.version

    assert_resolve('2.0.0')
    assert_resolve('2.0.0', allow_prereleases=False)
    assert_resolve('3.0.0rc3', allow_prereleases=True)
Esempio n. 18
0
def test_resolver_blacklist():
  if PY2:
    blacklist = {'project2': '<3'}
    required_project = "project2;python_version>'3'"
  else:
    blacklist = {'project2': '>3'}
    required_project = "project2;python_version<'3'"

  project1 = make_sdist(name='project1', version='1.0.0', install_reqs=[required_project])
  project2 = make_sdist(name='project2', version='1.1.0')

  with temporary_dir() as td:
    safe_copy(project1, os.path.join(td, os.path.basename(project1)))
    safe_copy(project2, os.path.join(td, os.path.basename(project2)))
    fetchers = [Fetcher([td])]

    dists = resolve(['project1'], fetchers=fetchers)
    assert len(dists) == 2

    dists = resolve(['project1'], fetchers=fetchers, pkg_blacklist=blacklist)
    assert len(dists) == 1
Esempio n. 19
0
def test_resolve_prereleases_multiple_set():
  stable_dep = make_sdist(name='dep', version='2.0.0')
  prerelease_dep1 = make_sdist(name='dep', version='3.0.0rc3')
  prerelease_dep2 = make_sdist(name='dep', version='3.0.0rc4')
  prerelease_dep3 = make_sdist(name='dep', version='3.0.0rc5')

  with temporary_dir() as td:
    for sdist in (stable_dep, prerelease_dep1, prerelease_dep2, prerelease_dep3):
      safe_copy(sdist, os.path.join(td, os.path.basename(sdist)))
    fetchers = [Fetcher([td])]

    def assert_resolve(expected_version, **resolve_kwargs):
      dists = list(
        resolve_multi(['dep>=3.0.0rc1', 'dep==3.0.0rc4'],
                      fetchers=fetchers,
                      **resolve_kwargs)
      )
      assert 1 == len(dists)
      dist = dists[0]
      assert expected_version == dist.version

    # This should resolve with explicit prerelease being set or implicitly.
    assert_resolve('3.0.0rc4', allow_prereleases=True)
    assert_resolve('3.0.0rc4')
Esempio n. 20
0
def test_clp_prereleases_resolver():
    prerelease_dep = make_sdist(name='dep', version='1.2.3b1')
    with temporary_dir() as td:
        safe_copy(prerelease_dep,
                  os.path.join(td, os.path.basename(prerelease_dep)))
        fetcher = Fetcher([td])

        # When no specific options are specified, allow_prereleases is None
        parser, resolver_options_builder = configure_clp()
        assert resolver_options_builder._allow_prereleases is None

        # When we specify `--pre`, allow_prereleases is True
        options, reqs = parser.parse_args(
            args=['--pre', 'dep==1.2.3b1', 'dep'])
        assert resolver_options_builder._allow_prereleases
        # We need to use our own fetcher instead of PyPI
        resolver_options_builder._fetchers.insert(0, fetcher)

        #####
        # The resolver created during processing of command line options (configure_clp)
        # is not actually passed into the API call (resolve_multi) from build_pex().
        # Instead, resolve_multi() calls resolve() where a new ResolverOptionsBuilder instance
        # is created. The only way to supply our own fetcher to that new instance is to patch it
        # here in the test so that it can fetch our test package (dep-1.2.3b1). Hence, this class
        # below and the change in the `pex.resolver` module where the patched object resides.
        #
        import pex.resolver

        class BuilderWithFetcher(ResolverOptionsBuilder):
            def __init__(self,
                         fetchers=None,
                         allow_all_external=False,
                         allow_external=None,
                         allow_unverified=None,
                         allow_prereleases=None,
                         use_manylinux=None,
                         precedence=None,
                         context=None):
                super(BuilderWithFetcher,
                      self).__init__(fetchers=fetchers,
                                     allow_all_external=allow_all_external,
                                     allow_external=allow_external,
                                     allow_unverified=allow_unverified,
                                     allow_prereleases=allow_prereleases,
                                     use_manylinux=None,
                                     precedence=precedence,
                                     context=context)
                self._fetchers.insert(0, fetcher)

        # end stub
        #####

        # Without a corresponding fix in pex.py, this test failed for a dependency requirement of
        # dep==1.2.3b1 from one package and just dep (any version accepted) from another package.
        # The failure was an exit from build_pex() with the message:
        #
        # Could not satisfy all requirements for dep==1.2.3b1:
        #     dep==1.2.3b1, dep
        #
        # With a correct behavior the assert line is reached and pex_builder object created.
        with mock.patch.object(pex.resolver, 'ResolverOptionsBuilder',
                               BuilderWithFetcher):
            pex_builder = build_pex(reqs, options, resolver_options_builder)
            assert pex_builder is not None