diff --git a/piptools/sync.py b/piptools/sync.py index 619ada06d..614fa01fc 100644 --- a/piptools/sync.py +++ b/piptools/sync.py @@ -163,9 +163,13 @@ def sync(to_install, to_uninstall, verbose=False, dry_run=False, pip_flags=None, req_lines.append(format_requirement(ireq, hashes=ireq_hashes)) # save requirement lines to a temporary file - with tempfile.NamedTemporaryFile(mode='wt') as tmp_req_file: - tmp_req_file.write('\n'.join(req_lines)) - tmp_req_file.flush() + tmp_req_file = tempfile.NamedTemporaryFile(mode='wt', delete=False) + tmp_req_file.write('\n'.join(req_lines)) + tmp_req_file.close() + try: check_call([pip, 'install', '-r', tmp_req_file.name] + pip_flags + install_flags) + finally: + os.unlink(tmp_req_file.name) + return 0 diff --git a/tests/test_sync.py b/tests/test_sync.py index 51d7efd69..32e820ba5 100644 --- a/tests/test_sync.py +++ b/tests/test_sync.py @@ -12,10 +12,16 @@ @pytest.fixture -def mocked_tmp_req_file(): +def mocked_tmp_file(): with mock.patch.object(tempfile, 'NamedTemporaryFile') as m: - m.return_value.__enter__.return_value.name = 'requirements.txt' - yield m.return_value.__enter__.return_value + yield m.return_value + + +@pytest.fixture +def mocked_tmp_req_file(mocked_tmp_file): + with mock.patch('os.unlink'): + mocked_tmp_file.name = 'requirements.txt' + yield mocked_tmp_file @pytest.mark.parametrize( @@ -227,6 +233,16 @@ def test_sync_install_temporary_requirement_file(from_line, from_editable, mocke check_call.assert_called_once_with(['pip', 'install', '-r', mocked_tmp_req_file.name, '-q']) +def test_temporary_requirement_file_deleted(from_line, from_editable, mocked_tmp_file): + with mock.patch('piptools.sync.check_call'): + to_install = {from_line('django==1.8')} + + with mock.patch('os.unlink') as unlink: + sync(to_install, set()) + + unlink.assert_called_once_with(mocked_tmp_file.name) + + def test_sync_requirement_file(from_line, from_editable, mocked_tmp_req_file): with mock.patch('piptools.sync.check_call'): to_install = {