Skip to content

Commit

Permalink
Support -c for plat spec dists in multiplat pexes.
Browse files Browse the repository at this point in the history
Fixes #537
  • Loading branch information
jsirois committed Aug 25, 2018
1 parent 927433a commit 69c6d6c
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 12 deletions.
23 changes: 14 additions & 9 deletions pex/finders.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,17 +293,22 @@ def get_script_from_distributions(name, dists):


def get_entry_point_from_console_script(script, dists):
# check all distributions for the console_script "script"
entries = frozenset(filter(None, (
dist.get_entry_map().get('console_scripts', {}).get(script) for dist in dists)))
# Check all distributions for the console_script "script". De-dup by dist key to allow for a
# duplicate console script IFF the distribution is platform-specific and this is a multi-platform
# pex.
def get_entrypoint(dist):
script_entry = dist.get_entry_map().get('console_scripts', {}).get(script)
if script_entry is not None:
# Entry points are of the form 'foo = bar', we just want the 'bar' part.
return dist.key, str(script_entry).split('=')[1].strip()

entries = frozenset(filter(None, (get_entrypoint(dist) for dist in dists)))

# if multiple matches, freak out
if len(entries) > 1:
raise RuntimeError(
'Ambiguous script specification %s matches multiple entry points:%s' % (
script, ' '.join(map(str, entries))))
'Ambiguous script specification %s matches multiple entry points:\n\t%s' % (
script, '\n\t'.join('%s from %s' % (entry_point, key) for key, entry_point in entries)))

if entries:
entry_point = next(iter(entries))
# entry points are of the form 'foo = bar', we just want the 'bar' part:
return str(entry_point).split('=')[1].strip()
_, entry_point = next(iter(entries))
return entry_point
5 changes: 3 additions & 2 deletions pex/testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -330,8 +330,9 @@ def ensure_python_distribution(version):
bootstrap_python_installer(pyenv_root)

if not os.path.exists(interpreter_location):
os.environ['PYENV_ROOT'] = pyenv_root
subprocess.check_call([pyenv, 'install', '--keep', version])
env = {'PYENV_ROOT': pyenv_root,
'CONFIGURE_OPTS': '--enable-shared'}
subprocess.check_call([pyenv, 'install', '--keep', version], env=env)
subprocess.check_call([pip, 'install', '-U', 'pip'])
subprocess.check_call([pip, 'install', SETUPTOOLS_REQUIREMENT])

Expand Down
32 changes: 31 additions & 1 deletion tests/test_finders.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
import zipimport

import pkg_resources
import pytest

from pex.finders import ChainedFinder
from pex.finders import _add_finder as add_finder
from pex.finders import _remove_finder as remove_finder
from pex.finders import find_eggs_in_zip, get_script_from_egg
from pex.finders import find_eggs_in_zip, get_entry_point_from_console_script, get_script_from_egg

try:
import mock
Expand Down Expand Up @@ -118,3 +119,32 @@ def test_get_script_from_egg():

assert location is None
assert content is None


class FakeDist(object):
def __init__(self, key, console_script_entry):
self.key = key
script = console_script_entry.split('=')[0].strip()
self._entry_map = {'console_scripts': {script: console_script_entry}}

def get_entry_map(self):
return self._entry_map


def test_get_entry_point_from_console_script():
dists = [FakeDist(key='fake', console_script_entry='bob= bob.main:run'),
FakeDist(key='fake', console_script_entry='bob =bob.main:run')]
assert 'bob.main:run' == get_entry_point_from_console_script('bob', dists)


def test_get_entry_point_from_console_script_conflict():
dists = [FakeDist(key='bob', console_script_entry='bob= bob.main:run'),
FakeDist(key='fake', console_script_entry='bob =bob.main:run')]
with pytest.raises(RuntimeError):
get_entry_point_from_console_script('bob', dists)


def test_get_entry_point_from_console_script_dne():
dists = [FakeDist(key='bob', console_script_entry='bob= bob.main:run'),
FakeDist(key='fake', console_script_entry='bob =bob.main:run')]
assert None is get_entry_point_from_console_script('jane', dists)
20 changes: 20 additions & 0 deletions tests/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -981,3 +981,23 @@ def test_invalid_entry_point_verification_3rdparty():
'-o', pex_out_path,
'--validate-entry-point'])
res.assert_failure()


@pytest.mark.skipif(IS_PYPY)
def test_multiplatform_entrypoint():
with temporary_dir() as td:
pex_out_path = os.path.join(td, 'p537.pex')
interpreter = ensure_python_interpreter('3.6.3')
res = run_pex_command(['p537==1.0.3',
'--no-build',
'--python={}'.format(interpreter),
'--python-shebang=#!{}'.format(interpreter),
'--platform=linux-x86_64',
'--platform=macosx-10.13-x86_64',
'-c', 'p537',
'-o', pex_out_path,
'--validate-entry-point'])
res.assert_success()

greeting = subprocess.check_output([pex_out_path])
assert b'Hello World!' == greeting.strip()

0 comments on commit 69c6d6c

Please sign in to comment.