diff --git a/python/lib/dependabot/python/update_checker/pip_compile_version_resolver.rb b/python/lib/dependabot/python/update_checker/pip_compile_version_resolver.rb index fcb9d12e4b..9e15ef2780 100644 --- a/python/lib/dependabot/python/update_checker/pip_compile_version_resolver.rb +++ b/python/lib/dependabot/python/update_checker/pip_compile_version_resolver.rb @@ -172,14 +172,10 @@ def run_pip_compile_command(command) run_command("pyenv local #{python_version}") run_command(command) rescue SharedHelpers::HelperSubprocessFailed => e - original_error ||= e + original_err ||= e msg = e.message - relevant_error = - if error_suggests_bad_python_version?(msg) then original_error - else e - end - + relevant_error = choose_relevant_error(original_err, e) raise relevant_error unless error_suggests_bad_python_version?(msg) raise relevant_error if user_specified_python_version raise relevant_error if python_version == "2.7.16" @@ -191,6 +187,25 @@ def run_pip_compile_command(command) FileUtils.remove_entry(".python-version", true) end + def choose_relevant_error(previous_error, new_error) + return previous_error if previous_error == new_error + + # If the previous error was definitely due to using the wrong Python + # version, return the new error (which can't be worse) + if error_certainly_bad_python_version?(previous_error.message) + return new_error + end + + # Otherwise, if the new error may be due to using the wrong Python + # version, return the old error (which can't be worse) + if error_suggests_bad_python_version?(new_error.message) + return previous_error + end + + # Otherwise, default to the new error + new_error + end + def python_env env = {} @@ -206,6 +221,14 @@ def python_env env end + def error_certainly_bad_python_version?(message) + unless message.include?('Command "python setup.py egg_info" failed') + return false + end + + message.include?("SyntaxError") + end + def error_suggests_bad_python_version?(message) return true if message.include?("not find a version that satisfies") return true if message.include?("No matching distribution found") diff --git a/python/spec/dependabot/python/update_checker/pip_compile_version_resolver_spec.rb b/python/spec/dependabot/python/update_checker/pip_compile_version_resolver_spec.rb index 055ae4c7f1..5092b999df 100644 --- a/python/spec/dependabot/python/update_checker/pip_compile_version_resolver_spec.rb +++ b/python/spec/dependabot/python/update_checker/pip_compile_version_resolver_spec.rb @@ -342,6 +342,24 @@ it { is_expected.to eq(Gem::Version.new("1.6.6")) } end + context "that has swapped syntax in the latest setup.py" do + let(:manifest_fixture_name) { "legacy_python_3.in" } + let(:generated_fixture_name) { "pip_compile_legacy_python_3.txt" } + + let(:dependency_name) { "django-adv-cache-tag" } + let(:dependency_version) { "0.2.1" } + let(:dependency_requirements) do + [{ + file: "requirements/test.in", + requirement: "==0.2.1", + groups: [], + source: nil + }] + end + + it { is_expected.to be_nil } + end + context "that has a .python-version file" do let(:dependency_files) do [manifest_file, generated_file, python_version_file] diff --git a/python/spec/fixtures/pip_compile_files/legacy_python_3.in b/python/spec/fixtures/pip_compile_files/legacy_python_3.in new file mode 100644 index 0000000000..74ba9f7b3c --- /dev/null +++ b/python/spec/fixtures/pip_compile_files/legacy_python_3.in @@ -0,0 +1,2 @@ +oauth2==1.5.211 +django-adv-cache-tag==0.2.1 diff --git a/python/spec/fixtures/requirements/pip_compile_legacy_python_3.txt b/python/spec/fixtures/requirements/pip_compile_legacy_python_3.txt new file mode 100644 index 0000000000..3bf473fd7f --- /dev/null +++ b/python/spec/fixtures/requirements/pip_compile_legacy_python_3.txt @@ -0,0 +1,9 @@ +# +# This file is autogenerated by pip-compile +# To update, run: +# +# pip-compile requirements.in +# +django-adv-cache-tag==0.2.1 +httplib2==0.12.3 # via oauth2 +oauth2==1.5.211