Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python 3 fixes - fix base folder #6252

Merged
merged 9 commits into from
Jul 28, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/python/pants/base/hash_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import json
from builtins import object

from pants.util.strutil import ensure_binary


def hash_all(strs, digest=None):
"""Returns a hash of the concatenation of all the strings in strs.
Expand All @@ -16,6 +18,7 @@ def hash_all(strs, digest=None):
"""
digest = digest or hashlib.sha1()
for s in strs:
s = ensure_binary(s)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hasher requires byte strings. Most of the changes made below are converting to bytes.

digest.update(s)
return digest.hexdigest()

Expand Down
7 changes: 6 additions & 1 deletion src/python/pants/base/payload.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
from builtins import object
from hashlib import sha1

from pants.util.strutil import ensure_binary


class PayloadFieldAlreadyDefinedError(Exception): pass

Expand Down Expand Up @@ -119,7 +121,10 @@ def _compute_fingerprint(self, field_keys):
fp = field.fingerprint()
if fp is not None:
empty_hash = False
hasher.update(sha1(key).hexdigest())
fp = ensure_binary(fp)
key = ensure_binary(key)
key_sha1 = sha1(key).hexdigest().encode('utf-8')
hasher.update(key_sha1)
hasher.update(fp)
if empty_hash:
return None
Expand Down
2 changes: 2 additions & 0 deletions src/python/pants/base/payload_field.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@
from pants.base.deprecated import deprecated
from pants.base.hash_utils import stable_json_hash
from pants.util.meta import AbstractClass
from pants.util.strutil import ensure_binary


def combine_hashes(hashes):
"""A simple helper function to combine other hashes. Sorts the hashes before rolling them in."""
hasher = sha1()
for h in sorted(hashes):
h = ensure_binary(h)
hasher.update(h)
return hasher.hexdigest()

Expand Down
6 changes: 3 additions & 3 deletions src/python/pants/base/project_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ def walk(self, relpath, topdown=True):
matched_dirs = self.ignore.match_files([os.path.join(root, "{}/".format(d)) for d in dirs])
matched_files = self.ignore.match_files([os.path.join(root, f) for f in files])
for matched_dir in matched_dirs:
dirs.remove(fast_relpath(matched_dir, root).rstrip(b'/'))
dirs.remove(fast_relpath(matched_dir, root).rstrip('/'))

for matched_file in matched_files:
files.remove(fast_relpath(matched_file, root))
Expand Down Expand Up @@ -180,15 +180,15 @@ def _filter_ignored(self, entries, selector=None):
return [entry for path, entry in prefixed_entries if path not in ignored_paths]

def _relpath_no_dot(self, relpath):
return relpath.lstrip(b'./') if relpath != b'.' else b''
return relpath.lstrip('./') if relpath != '.' else ''

def _raise_access_ignored(self, relpath):
"""Raises exception when accessing ignored path."""
raise self.AccessIgnoredPathError('The path {} is ignored in {}'.format(relpath, self))

def _append_trailing_slash(self, relpath):
"""Add a trailing slash if not already has one."""
return relpath if relpath.endswith(b'/') or len(relpath) == 0 else relpath + b'/'
return relpath if relpath.endswith('/') or len(relpath) == 0 else relpath + '/'

def _append_slash_if_dir_path(self, relpath):
"""For a dir path return a path that has a trailing slash."""
Expand Down
16 changes: 15 additions & 1 deletion src/python/pants/base/revision.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,18 @@ def components(self):
def _is_valid_operand(self, other):
return hasattr(other, '_components')

def _fill_value_if_missing(self, ours, theirs):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Python 2 allows comparing ints and strs, but Py3 doesn't. So, the old fillvalue of 0 for missing values would not work. Instead, it should be 0 if dealing with ints and '' if dealing with strs.

__lt__ was changed to have a fillvalue of None, which is then used in this helper function to determine if it should be a str or int value.

if theirs is None:
return ours, type(ours)() # gets type's zero-value, e.g. 0 or ""
elif ours is None:
return type(theirs)(), theirs
return ours, theirs

def _stringify_if_different_types(self, ours, theirs):
if any(isinstance(v, str) for v in (ours, theirs)):
return str(ours), str(theirs)
return ours, theirs

def __repr__(self):
return '{}({})'.format(self.__class__.__name__, ', '.join(map(repr, self._components)))

Expand All @@ -106,8 +118,10 @@ def __lt__(self, other):
if not self._is_valid_operand(other):
return AttributeError # TODO(python3port): typically this should return NotImplemented.
# Returning AttributeError for now to avoid changing prior API.
for ours, theirs in zip_longest(self._components, other._components, fillvalue=0):
for ours, theirs in zip_longest(self._components, other._components, fillvalue=None):
if ours != theirs:
ours, theirs = self._fill_value_if_missing(ours, theirs)
ours, theirs = self._stringify_if_different_types(ours, theirs)
return ours < theirs
return False

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def _test_bundle_existences(self, args, bundles, config=None):
stdout=subprocess.PIPE,
cwd=path)
java_retcode = java_run.wait()
java_out = java_run.stdout.read()
java_out = java_run.stdout.read().decode('utf-8')
self.assertEquals(java_retcode, 0)
self.assertTrue(expected in java_out, "Expected '{output}' from {jar}, not '{stdout}'."
.format(output=expected, jar=jar, stdout=java_out))
Expand Down
6 changes: 3 additions & 3 deletions tests/python/pants_test/base/test_hash_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ class TestHashUtils(unittest.TestCase):

def test_hash_all(self):
expected_hash = hashlib.md5()
expected_hash.update('jakejones')
expected_hash.update(b'jakejones')
self.assertEqual(expected_hash.hexdigest(), hash_all(['jake', 'jones'], digest=hashlib.md5()))

def test_hash_file(self):
expected_hash = hashlib.md5()
expected_hash.update('jake jones')
expected_hash.update(b'jake jones')

with temporary_file() as fd:
fd.write('jake jones')
fd.write(b'jake jones')
fd.close()

self.assertEqual(expected_hash.hexdigest(), hash_file(fd.name, digest=hashlib.md5()))
Expand Down
4 changes: 3 additions & 1 deletion tests/python/pants_test/base/test_payload_field.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
PythonRequirementsField)
from pants.java.jar.exclude import Exclude
from pants.java.jar.jar_dependency import JarDependency
from pants.util.strutil import ensure_binary
from pants_test.test_base import TestBase


Expand Down Expand Up @@ -72,7 +73,7 @@ def test_primitive_field(self):
)
self.assertEqual(
PrimitiveField('foo').fingerprint(),
PrimitiveField(b'foo').fingerprint(),
PrimitiveField('foo').fingerprint(),
)
self.assertNotEqual(
PrimitiveField('foo').fingerprint(),
Expand Down Expand Up @@ -105,6 +106,7 @@ def __init__(self, test_value):

def fingerprint(self):
hasher = sha1()
self.test_value = ensure_binary(self.test_value)
hasher.update(self.test_value)
return hasher.hexdigest()

Expand Down