Skip to content

Commit

Permalink
Add test & behavior: Compile an empty txt when the infile is empty an…
Browse files Browse the repository at this point in the history
…d --no-header is supplied (Fixes #900)

Add !is_empty (yielded) tracking to the writer's _iter_lines method, and yield a blank line (empty string) if (and only if) otherwise nothing at all would be yielded.
  • Loading branch information
AndydeCleyre committed Oct 1, 2019
1 parent 25a4e99 commit d53d3ff
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 14 deletions.
38 changes: 24 additions & 14 deletions piptools/writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,14 @@ def _iter_lines(
warn_uninstallable = False
has_hashes = hashes and any(hash for hash in hashes.values())

yielded = False

for line in self.write_header():
yield line
yielded = True
for line in self.write_flags():
yield line
yielded = True

unsafe_requirements = (
{r for r in results if r.name in UNSAFE_PACKAGES}
Expand All @@ -158,24 +162,26 @@ def _iter_lines(
)
packages = {r for r in results if r.name not in UNSAFE_PACKAGES}

packages = sorted(packages, key=self._sort_key)

for ireq in packages:
if has_hashes and not hashes.get(ireq):
yield MESSAGE_UNHASHED_PACKAGE
warn_uninstallable = True
line = self._format_requirement(
ireq,
reverse_dependencies,
primary_packages,
markers.get(key_from_ireq(ireq)),
hashes=hashes,
)
yield line
if packages:
packages = sorted(packages, key=self._sort_key)
for ireq in packages:
if has_hashes and not hashes.get(ireq):
yield MESSAGE_UNHASHED_PACKAGE
warn_uninstallable = True
line = self._format_requirement(
ireq,
reverse_dependencies,
primary_packages,
markers.get(key_from_ireq(ireq)),
hashes=hashes,
)
yield line
yielded = True

if unsafe_requirements:
unsafe_requirements = sorted(unsafe_requirements, key=self._sort_key)
yield ""
yielded = True
if has_hashes and not self.allow_unsafe:
yield MESSAGE_UNSAFE_PACKAGES_UNPINNED
warn_uninstallable = True
Expand All @@ -195,6 +201,10 @@ def _iter_lines(
else:
yield req

# Yield even when there's no real content, so that blank files are written
if not yielded:
yield ""

if warn_uninstallable:
log.warning(MESSAGE_UNINSTALLABLE)

Expand Down
26 changes: 26 additions & 0 deletions tests/test_cli_compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -801,3 +801,29 @@ def test_dry_run_doesnt_touch_output_file(
# The output file must not be touched
after_compile_mtime = os.stat("requirements.txt").st_mtime
assert after_compile_mtime == before_compile_mtime


@pytest.mark.parametrize(
"empty_input_pkg, prior_output_pkg",
[
("", ""),
("", "small-fake-a==0.1\n"),
("# Nothing to see here", ""),
("# Nothing to see here", "small-fake-a==0.1\n"),
],
)
def test_empty_input_file_no_header(runner, empty_input_pkg, prior_output_pkg):
"""
Tests pip-compile creates an empty requirements.txt file,
given --no-header and empty requirements.in
"""
with open("requirements.in", "w") as req_in:
req_in.write(empty_input_pkg) # empty input file

with open("requirements.txt", "w") as req_txt:
req_txt.write(prior_output_pkg)

runner.invoke(cli, ["--no-header", "requirements.in"])

with open("requirements.txt", "r") as req_txt:
assert req_txt.read().strip() == ""

0 comments on commit d53d3ff

Please sign in to comment.