Skip to content

Commit

Permalink
Order of hashes are unpredictable
Browse files Browse the repository at this point in the history
Fixes #93
  • Loading branch information
peterbe committed Oct 31, 2018
1 parent fefd565 commit fb5444d
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 16 deletions.
4 changes: 4 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,10 @@ Version History

next

* Order of hashes should not affect if a package in the requirements file
should be replaced or not.
See https://github.com/peterbe/hashin/issues/93

* (Internal) All tests have been rewritten as plain pytest functions.

* In Python 3, if the package can't be found you get a more explicit exception
Expand Down
28 changes: 20 additions & 8 deletions hashin.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,10 +230,26 @@ def run_packages(


def amend_requirements_content(requirements, all_new_lines):

# I wish we had types!
assert isinstance(all_new_lines, list), type(all_new_lines)

padding = " " * 4

def is_different_lines(package, new_lines):
# This assumes that for sure the package is already mentioned in the old
# requirements. Now we just need to double-check that they really are
# different.
# The 'new_lines` is what we might intend to replace it with.
lines = set()
for line in requirements.splitlines():
if regex.search(line):
lines.add(line.strip(" \\"))
elif lines and line.startswith(padding):
lines.add(line.strip(" \\"))
elif lines:
break
return lines != set([x.strip(" \\") for x in new_lines.splitlines()])

for package, new_lines in all_new_lines:
regex = re.compile(
r"(^|\n|\n\r){0}==|(^|\n|\n\r){0}\[.*\]==".format(re.escape(package)),
Expand All @@ -245,10 +261,9 @@ def amend_requirements_content(requirements, all_new_lines):
if requirements:
requirements = requirements.strip() + "\n"
requirements += new_lines.strip() + "\n"
else:
elif is_different_lines(package, new_lines):
# need to replace the existing
lines = []
padding = " " * 4
for line in requirements.splitlines():
if regex.search(line):
lines.append(line)
Expand Down Expand Up @@ -509,11 +524,8 @@ def get_package_hashes(
else:
raise PackageError("No releases could be found for {0}".format(version))

# Sorting them helps make sure the results are more predictable
# when running more than once for the same version
hashes = sorted(
get_releases_hashes(releases=releases, algorithm=algorithm, verbose=verbose),
key=lambda x: x["hash"],
hashes = list(
get_releases_hashes(releases=releases, algorithm=algorithm, verbose=verbose)
)
return {"package": package, "version": version, "hashes": hashes}

Expand Down
65 changes: 57 additions & 8 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,55 @@ def test_amend_requirements_content_replacement():
assert result == new_lines[1]


def test_amend_requirements_content_actually_not_replacement():
requirements = (
"""
autocompeter==1.2.2
--hash=sha256:33a5d0145e82326e781ddee1ad375f92cb84f8cfafea56e9504682adff64a5ee
--hash=sha256:4d64ed1b9e0e73095f5cfa87f0e97ddb4c840049e8efeb7e63b46118ba1d623a
""".strip()
+ "\n"
)

new_lines = (
"autocompeter",
"""
autocompeter==1.2.2
--hash=sha256:4d64ed1b9e0e73095f5cfa87f0e97ddb4c840049e8efeb7e63b46118ba1d623a
--hash=sha256:33a5d0145e82326e781ddee1ad375f92cb84f8cfafea56e9504682adff64a5ee
""".strip()
+ "\n",
)

result = hashin.amend_requirements_content(requirements, [new_lines])
# It should be unchanged because the only thing that changed was the
# order of the --hash lines.
assert result == requirements


def test_amend_requirements_content_replacement_addition():
requirements = (
"""
autocompeter==1.2.2
--hash=sha256:33a5d0145e82326e781ddee1ad375f92cb84f8cfafea56e9504682adff64a5ee
""".strip()
+ "\n"
)

new_lines = (
"autocompeter",
"""
autocompeter==1.2.2
--hash=sha256:4d64ed1b9e0e73095f5cfa87f0e97ddb4c840049e8efeb7e63b46118ba1d623a
--hash=sha256:33a5d0145e82326e781ddee1ad375f92cb84f8cfafea56e9504682adff64a5ee
""".strip()
+ "\n",
)

result = hashin.amend_requirements_content(requirements, [new_lines])
assert result == new_lines[1]


def test_amend_requirements_content_replacement_single_to_multi():
"""Change from autocompeter==1.2.2 to autocompeter==1.2.3
when it was previously written as a single line and now
Expand Down Expand Up @@ -512,21 +561,21 @@ def mocked_get(url, **options):
assert output.endswith("\n")
lines = output.splitlines()
assert lines[0] == "hashin==0.10 \\"
assert lines[1] == (
assert (
" --hash=sha512:0d63bf4c115154781846ecf573049324f06b021a1"
"d4b92da4fae2bf491da2b83a13096b14d73e73cefad36855f4fa936bac4"
"b2357dabf05a2b1e7329ff1e5455 \\"
)
assert lines[2] == (
) in lines
assert (
" --hash=sha512:45d1c5d2237a3b4f78b4198709fb2ecf1f781c823"
"4ce3d94356f2100a36739433952c6c13b2843952f608949e6baa9f95055"
"a314487cd8fb3f9d76522d8edb50 \\"
)
assert lines[3] == (
) in lines
assert (
" --hash=sha512:c32e6d9fb09dc36ab9222c4606a1f43a2dcc183a8"
"c64bdd9199421ef779072c174fa044b155babb12860cf000e36bc4d3586"
"94fa22420c997b1dd75b623d4daa"
)
) in lines


def test_run_atomic_not_write_with_error_on_last_package(murlopen, tmpfile):
Expand Down Expand Up @@ -1449,10 +1498,10 @@ def mocked_get(url, **options):
"version": "0.10",
"hashes": [
{
"hash": "0d63bf4c115154781846ecf573049324f06b021a1d4b92da4fae2bf491da2b83a13096b14d73e73cefad36855f4fa936bac4b2357dabf05a2b1e7329ff1e5455"
"hash": "45d1c5d2237a3b4f78b4198709fb2ecf1f781c8234ce3d94356f2100a36739433952c6c13b2843952f608949e6baa9f95055a314487cd8fb3f9d76522d8edb50"
},
{
"hash": "45d1c5d2237a3b4f78b4198709fb2ecf1f781c8234ce3d94356f2100a36739433952c6c13b2843952f608949e6baa9f95055a314487cd8fb3f9d76522d8edb50"
"hash": "0d63bf4c115154781846ecf573049324f06b021a1d4b92da4fae2bf491da2b83a13096b14d73e73cefad36855f4fa936bac4b2357dabf05a2b1e7329ff1e5455"
},
{
"hash": "c32e6d9fb09dc36ab9222c4606a1f43a2dcc183a8c64bdd9199421ef779072c174fa044b155babb12860cf000e36bc4d358694fa22420c997b1dd75b623d4daa"
Expand Down

0 comments on commit fb5444d

Please sign in to comment.