Skip to content

Commit

Permalink
Support indented requirements (#114)
Browse files Browse the repository at this point in the history
* Support indented requirements (fixes #112)

* Refactor amend_requirements_content()

Remove duplicate code from is_different_lines().

* Indent only non-empty lines

* Refactor and make linter happy

Rename new_lines to new_text where it is not list

* Add test for indented spec
  • Loading branch information
techtonik authored and peterbe committed Sep 5, 2019
1 parent 10a7048 commit b42eeb1
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 22 deletions.
46 changes: 24 additions & 22 deletions hashin.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,43 +387,45 @@ def amend_requirements_content(requirements, 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
def is_different_lines(old_lines, new_lines, indent):
# This assumes that the package is already mentioned in the old
# requirements. Now we just need to double-check that its lines 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, old_name, new_lines in all_new_lines:
old = set([l.strip(" \\") for l in old_lines])
new = set([indent + x.strip(" \\") for x in new_lines])
return old != new

for package, old_name, new_text in all_new_lines:
regex = re.compile(
r"^{0}(\[.*\])?==".format(re.escape(old_name)), re.IGNORECASE | re.MULTILINE
r"^(?P<indent>[ \t]*){0}(\[.*\])?==".format(re.escape(old_name)),
re.IGNORECASE | re.MULTILINE,
)
# if the package wasn't already there, add it to the bottom
if not regex.search(requirements):
match = regex.search(requirements)
if not match:
# easy peasy
if requirements:
requirements = requirements.strip() + "\n"
requirements += new_lines.strip() + "\n"
elif is_different_lines(package, new_lines):
# need to replace the existing
requirements += new_text.strip() + "\n"
else:
indent = match.group("indent")
lines = []
for line in requirements.splitlines():
if regex.search(line):
lines.append(line)
elif lines and line.startswith(padding):
elif lines and line.startswith(indent + padding):
lines.append(line)
elif lines:
break
combined = "\n".join(lines + [""])
requirements = requirements.replace(combined, new_lines)
if is_different_lines(lines, new_text.splitlines(), indent):
# need to replace the existing
combined = "\n".join(lines + [""])
# indent non-empty lines
indented = re.sub(
r"^(.+)$", r"{0}\1".format(indent), new_text, flags=re.MULTILINE
)
requirements = requirements.replace(combined, indented)

return requirements

Expand Down
40 changes: 40 additions & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,46 @@ def test_amend_requirements_content_new_similar_name():
assert new_lines[2] in result


def test_amend_requirements_content_indented():
"""This test came from https://github.com/peterbe/hashin/issues/112"""
requirements = (
"""
boto3==1.9.85 \\
--hash=sha256:acfd27967cf1ba7f9d83ad6fc2011764541e4c295fe0d896ea7b495cc2f03336 \\
--hash=sha256:96296871863e0245b04931df7dd5c583e53cadbe1d54197829b34b03b0d048a8
botocore==1.12.85 \\
--hash=sha256:af727d4af0cf1ddbf84eaf1cc9d0160ff066eac7f9e6a2fe6a75ccbed4452c98 \\
--hash=sha256:c381fd05b777f41a608ea0846a8d8ecc32077a83e456d05e824cce8d6b213e32
""".strip()
+ "\n"
)
expect = (
"""
boto3==1.9.85 \\
--hash=sha256:acfd27967cf1ba7f9d83ad6fc2011764541e4c295fe0d896ea7b495cc2f03336 \\
--hash=sha256:96296871863e0245b04931df7dd5c583e53cadbe1d54197829b34b03b0d048a8
botocore==1.12.221 \\
--hash=sha256:6d49deff062d2ae0f03fc26b56df8b1bb9e8b136657bcd8d84c986a4068fb784 \\
--hash=sha256:bbee3fdcbe56ca53e2c32c6c12d174fa9b4ffe27b633183c29bd5aec9e200bae
""".strip()
+ "\n"
)
new_lines = (
"botocore",
"botocore",
"""
botocore==1.12.221 \\
--hash=sha256:6d49deff062d2ae0f03fc26b56df8b1bb9e8b136657bcd8d84c986a4068fb784 \\
--hash=sha256:bbee3fdcbe56ca53e2c32c6c12d174fa9b4ffe27b633183c29bd5aec9e200bae
""".strip()
+ "\n",
)
result = hashin.amend_requirements_content(requirements, [new_lines])
assert result == expect


def test_run(murlopen, tmpfile, capsys):
def mocked_get(url, **options):
if url == "https://pypi.org/pypi/hashin/json":
Expand Down

0 comments on commit b42eeb1

Please sign in to comment.