Skip to content

Commit a46b827

Browse files
author
Eric Arellano
committed
Fix backend python issues
1 parent 88fa18a commit a46b827

File tree

9 files changed

+38
-24
lines changed

9 files changed

+38
-24
lines changed

src/python/pants/backend/python/tasks/pytest_run.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ def _cov_setup(self, workdirs, coverage_morfs, src_to_target_base):
240240
# Note that it's important to put the tmpfile under the workdir, because pytest
241241
# uses all arguments that look like paths to compute its rootdir, and we want
242242
# it to pick the buildroot.
243-
with temporary_file(root_dir=workdirs.root_dir) as fp:
243+
with temporary_file(root_dir=workdirs.root_dir, binary_mode=False) as fp:
244244
cp.write(fp)
245245
fp.close()
246246
coverage_rc = fp.name

src/python/pants/backend/python/tasks/python_execution_task_base.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import os
88
from builtins import str
99

10+
from future.utils import binary_type, text_type
1011
from pex.interpreter import PythonInterpreter
1112
from pex.pex import PEX
1213

@@ -46,7 +47,7 @@ def extra_requirements(self):
4647
"""
4748
return ()
4849

49-
class ExtraFile(datatype(['path', 'content'])):
50+
class ExtraFile(datatype([('path', text_type), ('content', binary_type)])):
5051
"""Models an extra file to place in a PEX."""
5152

5253
@classmethod
@@ -56,7 +57,7 @@ def empty(cls, path):
5657
:param str path: The path this extra file should have when added to a PEX.
5758
:rtype: :class:`ExtraFile`
5859
"""
59-
return cls(path=path, content='')
60+
return cls(path=path, content=b'')
6061

6162
def add_to(self, builder):
6263
"""Adds this extra file to a PEX builder.

src/python/pants/backend/python/tasks/select_interpreter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def compute_fingerprint(self, python_target):
3434
return None
3535
hasher = hashlib.sha1()
3636
for element in hash_elements_for_target:
37-
hasher.update(element)
37+
hasher.update(element.encode('utf-8'))
3838
return hasher.hexdigest() if PY3 else hasher.hexdigest().decode('utf-8')
3939

4040

src/python/pants/backend/python/tasks/setup_py.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from builtins import map, object, str, zip
1414
from collections import OrderedDict, defaultdict
1515

16-
from pex.compatibility import string, to_bytes
16+
from future.utils import PY2, PY3
1717
from pex.installer import InstallerBase, Packager
1818
from pex.interpreter import PythonInterpreter
1919
from twitter.common.collections import OrderedSet
@@ -300,7 +300,7 @@ def collect_reduced_dependencies(current):
300300
class SetupPy(Task):
301301
"""Generate setup.py-based Python projects."""
302302

303-
SOURCE_ROOT = b'src'
303+
SOURCE_ROOT = 'src' if PY3 else b'src'
304304

305305
PYTHON_DISTS_PRODUCT = 'python_dists'
306306

@@ -514,18 +514,23 @@ def write_setup(self, root_target, reduced_dependencies, chroot):
514514

515515
setup_keywords = root_target.provides.setup_py_keywords.copy()
516516

517-
package_dir = {b'': self.SOURCE_ROOT}
517+
package_dir = {'' if PY3 else b'': self.SOURCE_ROOT}
518518
packages, namespace_packages, resources = self.find_packages(chroot, self.context.log)
519519

520520
if namespace_packages:
521521
setup_keywords['namespace_packages'] = list(sorted(namespace_packages))
522522

523523
if packages:
524+
normalized_package_data = (
525+
resources.items()
526+
if PY3 else
527+
((package.encode('utf-8'), [v.encode('utf-8') for v in rs])
528+
for (package, rs) in resources.items())
529+
)
524530
setup_keywords.update(
525531
package_dir=package_dir,
526532
packages=list(sorted(packages)),
527-
package_data=dict((str(package), list(map(str, rs)))
528-
for (package, rs) in resources.items()))
533+
package_data=dict(normalized_package_data))
529534

530535
setup_keywords['install_requires'] = list(self.install_requires(reduced_dependencies))
531536

@@ -546,8 +551,8 @@ def convert(input):
546551
return out
547552
elif isinstance(input, list):
548553
return [convert(element) for element in input]
549-
elif isinstance(input, string):
550-
return to_bytes(input)
554+
elif PY2 and isinstance(input, str):
555+
return input.encode('utf-8')
551556
else:
552557
return input
553558

@@ -571,7 +576,7 @@ def convert(input):
571576
chroot.write(self._setup_boilerplate().format(
572577
setup_dict=pprint.pformat(convert(setup_keywords), indent=4),
573578
setup_target=repr(root_target)
574-
), 'setup.py')
579+
).encode('utf-8'), 'setup.py')
575580

576581
# make sure that setup.py is included
577582
chroot.write('include *.py'.encode('utf8'), 'MANIFEST.in')

tests/python/pants_test/backend/python/tasks/test_pytest_run.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,7 @@ def load_coverage_data_for(self, context, covered_path, expect_coverage=True):
479479
PytestRun._add_plugin_config(cp,
480480
src_chroot_path=src_chroot_path,
481481
src_to_target_base=src_to_target_base)
482-
with temporary_file() as fp:
482+
with temporary_file(binary_mode=False) as fp:
483483
cp.write(fp)
484484
fp.close()
485485

tests/python/pants_test/backend/python/tasks/test_python_distribution_integration.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def test_pants_binary(self):
4141
# Check that the pex was built.
4242
self.assertTrue(os.path.isfile(pex))
4343
# Check that the pex runs.
44-
output = subprocess.check_output(pex)
44+
output = subprocess.check_output(pex).decode('utf-8')
4545
self._assert_native_greeting(output)
4646
# Check that we have exact one wheel output
4747
self.assertEqual(len(glob.glob(wheel_glob)), 1)
@@ -141,11 +141,11 @@ def test_pants_binary_dep_isolation_with_multiple_targets(self):
141141
self.assertTrue(os.path.isfile(pex1))
142142
self.assertTrue(os.path.isfile(pex2))
143143
# Check that the pex 1 runs.
144-
output = subprocess.check_output(pex1)
144+
output = subprocess.check_output(pex1).decode('utf-8')
145145
self._assert_native_greeting(output)
146146
# Check that the pex 2 fails due to no python_dists leaked into it.
147147
try:
148-
output = subprocess.check_output(pex2)
148+
subprocess.check_output(pex2)
149149
except subprocess.CalledProcessError as e:
150150
self.assertNotEqual(0, e.returncode)
151151

@@ -172,7 +172,7 @@ def test_pants_resolves_local_dists_for_current_platform_only(self):
172172
# Check that the pex was built.
173173
self.assertTrue(os.path.isfile(pex))
174174
# Check that the pex runs.
175-
output = subprocess.check_output(pex)
175+
output = subprocess.check_output(pex).decode('utf-8')
176176
self._assert_native_greeting(output)
177177

178178
def _get_current_platform_string(self):
@@ -229,7 +229,7 @@ def test_python_distribution_with_setup_requires(self):
229229
# Check that the pex was built.
230230
self.assertTrue(os.path.isfile(pex))
231231
# Check that the pex runs.
232-
output = subprocess.check_output(pex)
232+
output = subprocess.check_output(pex).decode('utf-8')
233233
self.assertIn('Hello, world!', output)
234234
finally:
235235
if os.path.exists(pex):

tests/python/pants_test/backend/python/tasks/test_resolve_requirements.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import os
88
from builtins import str
99

10+
from future.utils import PY3
1011
from pex.interpreter import PythonInterpreter
1112

1213
from pants.backend.python.interpreter_cache import PythonInterpreterCache
@@ -34,7 +35,12 @@ def test_resolve_simple_requirements(self):
3435
# the requirement isn't sneaking in some other way, which would render the remainder
3536
# of this test moot.)
3637
_, stderr_data = self._exercise_module(self._resolve_requirements([noreqs_tgt]), 'colors')
37-
self.assertIn('ImportError: No module named colors', stderr_data)
38+
39+
try:
40+
self.assertIn("ModuleNotFoundError: No module named 'colors'", stderr_data)
41+
except AssertionError:
42+
# < Python 3.6 uses ImportError instead of ModuleNotFoundError.
43+
self.assertIn('ImportError: No module named colors', stderr_data)
3844

3945
# Check that the module is available if specified as a requirement.
4046
stdout_data, stderr_data = self._exercise_module(self._resolve_requirements([ansicolors_tgt]),
@@ -43,7 +49,7 @@ def test_resolve_simple_requirements(self):
4349

4450
path = stdout_data.strip()
4551
# Check that the requirement resolved to what we expect.
46-
self.assertTrue(path.endswith('/.deps/ansicolors-1.0.2-py2-none-any.whl/colors.py'))
52+
self.assertTrue(path.endswith('/.deps/ansicolors-1.0.2-{}-none-any.whl/colors.py'.format('py3' if PY3 else 'py2')))
4753
# Check that the path is under the test's build root, so we know the pex was created there.
4854
self.assertTrue(path.startswith(os.path.realpath(get_buildroot())))
4955

@@ -136,9 +142,10 @@ def _resolve_requirements(self, target_roots, options=None):
136142
return context.products.get_data(ResolveRequirements.REQUIREMENTS_PEX)
137143

138144
def _exercise_module(self, pex, expected_module):
139-
with temporary_file() as f:
145+
with temporary_file(binary_mode=False) as f:
140146
f.write('import {m}; print({m}.__file__)'.format(m=expected_module))
141147
f.close()
142148
proc = pex.run(args=[f.name], blocking=False,
143149
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
144-
return proc.communicate()
150+
stdout, stderr = proc.communicate()
151+
return (stdout.decode('utf-8'), stderr.decode('utf-8'))

tests/python/pants_test/backend/python/tasks/test_setup_py.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -601,7 +601,7 @@ def test_prep_command_case(self):
601601

602602
def test_detect_namespace_packages():
603603
def has_ns(stmt):
604-
with temporary_file() as fp:
604+
with temporary_file(binary_mode=False) as fp:
605605
fp.write(stmt)
606606
fp.flush()
607607
return SetupPy.declares_namespace_package(fp.name)

tests/python/pants_test/backend/python/test_interpreter_cache.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from contextlib import contextmanager
1010

1111
import mock
12+
from future.utils import PY3
1213
from pex.package import EggPackage, Package, SourcePackage
1314
from pex.resolver import Unsatisfiable, resolve
1415

@@ -28,7 +29,7 @@ def _make_bad_requirement(requirement):
2829
2930
E.g. 'CPython==2.7.5' becomes 'CPython==99.7.5'
3031
"""
31-
return str(requirement).replace('==2.', '==99.')
32+
return str(requirement).replace('==3', '==99') if PY3 else str(requirement).replace('==2.', '==99')
3233

3334
def setUp(self):
3435
super(TestInterpreterCache, self).setUp()

0 commit comments

Comments
 (0)