diff --git a/piptools/scripts/compile.py b/piptools/scripts/compile.py index ef5d5131..59a2b99f 100755 --- a/piptools/scripts/compile.py +++ b/piptools/scripts/compile.py @@ -28,6 +28,7 @@ install_req_from_line, is_pinned_requirement, key_from_ireq, + render_requirements_json_txt, ) from ..writer import OutputWriter from . import options @@ -309,7 +310,7 @@ def cli( # Proxy with a LocalRequirementsRepository if --upgrade is not specified # (= default invocation) output_file_exists = os.path.exists(output_file.name) - if not (upgrade or json) and output_file_exists: + if not upgrade and output_file_exists: output_file_is_empty = os.path.getsize(output_file.name) == 0 if upgrade_install_reqs and output_file_is_empty: log.warning( @@ -320,11 +321,16 @@ def cli( "as any existing content is truncated." ) + if json: + # Render contents of JSON output file to a temporary requirements + # file in text format in order to make it readable by ``pip`` + tmpfile_name = render_requirements_json_txt(output_file.name) + # Use a temporary repository to ensure outdated(removed) options from # existing requirements.txt wouldn't get into the current repository. tmp_repository = PyPIRepository(pip_args, cache_dir=cache_dir) ireqs = parse_requirements( - output_file.name, + tmpfile_name if json else output_file.name, finder=tmp_repository.finder, session=tmp_repository.session, options=tmp_repository.options, diff --git a/piptools/utils.py b/piptools/utils.py index 39a51e92..2e5a016a 100644 --- a/piptools/utils.py +++ b/piptools/utils.py @@ -9,6 +9,7 @@ import re import shlex import sys +import tempfile from pathlib import Path from typing import Any, Callable, Iterable, Iterator, TypeVar, cast @@ -772,3 +773,18 @@ def is_path_relative_to(path1: Path, path2: Path) -> bool: except ValueError: return False return True + + +def render_requirements_json_txt(filename: str) -> str: + """Render a given ``requirements.json`` file to a temporary + ``requirements.txt`` file and return its name. + """ + with open(filename, encoding="utf-8") as f: + reqs = json.load(f) + tmpfile = tempfile.NamedTemporaryFile(mode="w+t", encoding="utf-8", delete=False) + for req in reqs: + tmpfile.write(req["line"]) + tmpfile.write("\n") + tmpfile.flush() + + return tmpfile.name