From b6ae9d3bbb32647e012f9cef0b20e4af131c6387 Mon Sep 17 00:00:00 2001 From: Jurre Stender Date: Tue, 8 Jun 2021 19:08:11 +0200 Subject: [PATCH] Drop python 2.x support and fix pipenv 2021.5.29 tests and Python 2 has been unsupported for a year and a half now, pip 21 no longer supports it and we see pretty small usage numbers at GitHub. Maintaining support for it has become increasingly harder, and this pipenv upgrade made it even more cumbersome. It's been a good ride, python 2. See ya! --- Dockerfile | 1 - python/helpers/build | 1 - .../file_updater/pip_compile_file_updater.rb | 26 -- .../file_updater/pipfile_file_updater.rb | 28 -- .../lib/dependabot/python/python_versions.rb | 7 +- .../pip_compile_version_resolver.rb | 38 --- .../update_checker/pipenv_version_resolver.rb | 71 ++--- .../pip_compile_file_updater_spec.rb | 97 ------ .../file_updater/pipfile_file_updater_spec.rb | 80 +---- .../latest_version_finder_spec.rb | 12 +- .../pip_compile_version_resolver_spec.rb | 80 ----- .../pip_version_resolver_spec.rb | 19 +- .../pipenv_version_resolver_spec.rb | 90 +----- .../poetry_version_resolver_spec.rb | 4 +- .../dependabot/python/update_checker_spec.rb | 10 +- .../fixtures/lockfiles/required_python.lock | 4 +- .../lockfiles/required_python_implicit_2.lock | 105 ------- .../pip_compile_files/legacy_python.in | 1 - .../pip_compile_files/legacy_python_2.in | 2 - .../pip_compile_files/legacy_python_3.in | 2 - .../unresolvable_if_unpinned.txt | 101 +++++++ python/spec/fixtures/pipfiles/bad_requirement | 9 - .../fixtures/pipfiles/extra_subdependency | 3 - .../fixtures/pipfiles/problematic_resolution | 3 - python/spec/fixtures/pipfiles/required_python | 4 +- .../pipfiles/required_python_blocking | 9 - .../pipfiles/required_python_implicit_2 | 10 - .../pipfiles/unresolvable_python_version | 13 - .../pypi/pypi_simple_response_django.html | 285 ++++++++++++++---- .../pip_compile_legacy_python.txt | 7 - .../pip_compile_legacy_python_2.txt | 11 - .../pip_compile_legacy_python_3.txt | 9 - .../pip_compile_unresolvable_if_unpinned.txt | 133 +++++--- 33 files changed, 477 insertions(+), 798 deletions(-) delete mode 100644 python/spec/fixtures/lockfiles/required_python_implicit_2.lock delete mode 100644 python/spec/fixtures/pip_compile_files/legacy_python.in delete mode 100644 python/spec/fixtures/pip_compile_files/legacy_python_2.in delete mode 100644 python/spec/fixtures/pip_compile_files/legacy_python_3.in create mode 100644 python/spec/fixtures/pip_compile_files/unresolvable_if_unpinned.txt delete mode 100644 python/spec/fixtures/pipfiles/bad_requirement delete mode 100644 python/spec/fixtures/pipfiles/required_python_blocking delete mode 100644 python/spec/fixtures/pipfiles/required_python_implicit_2 delete mode 100644 python/spec/fixtures/pipfiles/unresolvable_python_version delete mode 100644 python/spec/fixtures/requirements/pip_compile_legacy_python.txt delete mode 100644 python/spec/fixtures/requirements/pip_compile_legacy_python_2.txt delete mode 100644 python/spec/fixtures/requirements/pip_compile_legacy_python_3.txt diff --git a/Dockerfile b/Dockerfile index d30cfc4482..5a7452c862 100644 --- a/Dockerfile +++ b/Dockerfile @@ -84,7 +84,6 @@ RUN mkdir -p "$PYENV_ROOT" && chown dependabot:dependabot "$PYENV_ROOT" USER dependabot RUN git clone https://github.com/pyenv/pyenv.git --branch 1.2.26 --single-branch --depth=1 /usr/local/.pyenv \ && pyenv install 3.9.4 \ - && pyenv install 2.7.18 \ && pyenv global 3.9.4 \ && rm -Rf /tmp/python-build* USER root diff --git a/python/helpers/build b/python/helpers/build index d1b9273a6e..a9c1aaefaa 100755 --- a/python/helpers/build +++ b/python/helpers/build @@ -16,7 +16,6 @@ cp -r \ "$install_dir" cd "$install_dir" -PYENV_VERSION=2.7.18 pyenv exec pip install -r "requirements.txt" PYENV_VERSION=3.9.4 pyenv exec pip install -r "requirements.txt" # Workaround of https://github.com/python-poetry/poetry/issues/3010 diff --git a/python/lib/dependabot/python/file_updater/pip_compile_file_updater.rb b/python/lib/dependabot/python/file_updater/pip_compile_file_updater.rb index 65dab63530..dca9894b2c 100644 --- a/python/lib/dependabot/python/file_updater/pip_compile_file_updater.rb +++ b/python/lib/dependabot/python/file_updater/pip_compile_file_updater.rb @@ -170,24 +170,6 @@ def run_pip_compile_command(command, allow_unsafe_shell_command: false) command, allow_unsafe_shell_command: allow_unsafe_shell_command ) - rescue SharedHelpers::HelperSubprocessFailed => e - original_error ||= e - msg = e.message - - relevant_error = - if error_suggests_bad_python_version?(msg) then original_error - else e - end - - 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.18" - - @python_version = "2.7.18" - retry - ensure - @python_version = nil - FileUtils.remove_entry(".python-version", true) end def python_env @@ -205,14 +187,6 @@ def python_env env end - def error_suggests_bad_python_version?(message) - return true if message.include?("UnsupportedPythonVersion") - return true if message.include?("not find a version that satisfies") - - message.include?('Command "python setup.py egg_info" failed') || - message.include?("exit status 1: python setup.py egg_info") - end - def write_updated_dependency_files dependency_files.each do |file| path = file.name diff --git a/python/lib/dependabot/python/file_updater/pipfile_file_updater.rb b/python/lib/dependabot/python/file_updater/pipfile_file_updater.rb index b7cd2ec97e..8a940deda1 100644 --- a/python/lib/dependabot/python/file_updater/pipfile_file_updater.rb +++ b/python/lib/dependabot/python/file_updater/pipfile_file_updater.rb @@ -264,34 +264,6 @@ def run_command(command, env: {}) def run_pipenv_command(command, env: pipenv_env_variables) run_command("pyenv local #{python_version}") run_command(command, env: env) - rescue SharedHelpers::HelperSubprocessFailed => e - original_error ||= e - msg = e.message - - relevant_error = - if error_suggests_bad_python_version?(msg) then original_error - else e - end - - raise relevant_error unless error_suggests_bad_python_version?(msg) - raise relevant_error if python_version.start_with?("2") - - # Clear the existing virtualenv, so that we use the new Python version - run_command("pyenv local #{python_version}") - run_command("pyenv exec pipenv --rm") - - @python_version = "2.7.18" - retry - ensure - @python_version = nil - FileUtils.remove_entry(".python-version", true) - end - - def error_suggests_bad_python_version?(message) - return true if message.include?("UnsupportedPythonVersion") - - message.include?('Command "python setup.py egg_info" failed') || - message.include?("exit status 1: python setup.py egg_info") end def write_temporary_dependency_files(pipfile_content) diff --git a/python/lib/dependabot/python/python_versions.rb b/python/lib/dependabot/python/python_versions.rb index 4c4dcb1c4a..2b620db8f6 100644 --- a/python/lib/dependabot/python/python_versions.rb +++ b/python/lib/dependabot/python/python_versions.rb @@ -4,7 +4,7 @@ module Dependabot module Python module PythonVersions PRE_INSTALLED_PYTHON_VERSIONS = %w( - 3.9.4 2.7.18 + 3.9.4 ).freeze # Due to an OpenSSL issue we can only install the following versions in @@ -15,14 +15,13 @@ module PythonVersions 3.7.10 3.7.9 3.7.8 3.7.7 3.7.6 3.7.5 3.7.4 3.7.3 3.7.2 3.7.1 3.7.0 3.6.13 3.6.12 3.6.11 3.6.10 3.6.9 3.6.8 3.6.7 3.6.6 3.6.5 3.6.4 3.6.3 3.6.2 3.6.1 3.6.0 3.5.10 3.5.8 3.5.7 3.5.6 3.5.5 3.5.4 3.5.3 - 2.7.18 2.7.17 2.7.16 2.7.15 2.7.14 2.7.13 ).freeze # This list gets iterated through to find a valid version, so we have - # the two pre-installed versions listed first. + # the pre-installed versions listed first. SUPPORTED_VERSIONS_TO_ITERATE = [ - *PRE_INSTALLED_PYTHON_VERSIONS.select { |v| v.start_with?("3") }, + *PRE_INSTALLED_PYTHON_VERSIONS, *SUPPORTED_VERSIONS ].freeze end 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 c07bf064d1..c40b261b7d 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 @@ -235,35 +235,6 @@ def pip_compile_index_options def run_pip_compile_command(command) run_command("pyenv local #{python_version}") run_command(command) - rescue SharedHelpers::HelperSubprocessFailed => e - original_err ||= e - msg = e.message - - 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.18" - - @python_version = "2.7.18" - retry - ensure - @python_version = nil - 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) - return new_error if error_certainly_bad_python_version?(previous_error.message) - - # Otherwise, if the new error may be due to using the wrong Python - # version, return the old error (which can't be worse) - return previous_error if error_suggests_bad_python_version?(new_error.message) - - # Otherwise, default to the new error - new_error end def python_env @@ -292,15 +263,6 @@ def error_certainly_bad_python_version?(message) message.include?("SyntaxError") end - def error_suggests_bad_python_version?(message) - return true if error_certainly_bad_python_version?(message) - return true if message.include?("not find a version that satisfies") - return true if message.include?("No matching distribution found") - - message.include?('Command "python setup.py egg_info" failed') || - message.include?("exit status 1: python setup.py egg_info") - end - def write_temporary_dependency_files(updated_req: nil, update_requirement: true) dependency_files.each do |file| diff --git a/python/lib/dependabot/python/update_checker/pipenv_version_resolver.rb b/python/lib/dependabot/python/update_checker/pipenv_version_resolver.rb index f969903c2f..8d4a58e3c5 100644 --- a/python/lib/dependabot/python/update_checker/pipenv_version_resolver.rb +++ b/python/lib/dependabot/python/update_checker/pipenv_version_resolver.rb @@ -16,7 +16,6 @@ require "dependabot/python/name_normaliser" require "dependabot/python/version" -# rubocop:disable Metrics/ClassLength module Dependabot module Python class UpdateChecker @@ -35,16 +34,14 @@ class PipenvVersionResolver GIT_REFERENCE_NOT_FOUND_REGEX = %r{git checkout -q (?[^\n"]+)\n?[^\n]*/(?.*?)(\\n'\]|$)}m. freeze - UNSUPPORTED_DEPS = %w(pyobjc).freeze - UNSUPPORTED_DEP_REGEX = - /"python setup\.py egg_info".*(?:#{UNSUPPORTED_DEPS.join("|")})/. - freeze - PIPENV_INSTALLATION_ERROR = "pipenv.patched.notpip._internal."\ - "exceptions.InstallationError: "\ - "Command \"python setup.py egg_info\" "\ - "failed with error code 1 in" + PIPENV_INSTALLATION_ERROR = "pipenv.patched.notpip._internal.exceptions.InstallationError: Command errored out"\ + " with exit status 1: python setup.py egg_info" + TRACEBACK = "Traceback (most recent call last):" PIPENV_INSTALLATION_ERROR_REGEX = - %r{#{Regexp.quote(PIPENV_INSTALLATION_ERROR)}.+/(?.+)/$}.freeze + /#{Regexp.quote(TRACEBACK)}[\s\S]*^\s+import\s(?.+)[\s\S]*^#{Regexp.quote(PIPENV_INSTALLATION_ERROR)}/. + freeze + UNSUPPORTED_DEP_REGEX = /(?:pyobjc)[\s\S]*#{Regexp.quote(PIPENV_INSTALLATION_ERROR)}/.freeze + PIPENV_RANGE_WARNING = /Warning:\sPython\s[<>].* was not found/.freeze attr_reader :dependency, :dependency_files, :credentials @@ -151,9 +148,19 @@ def handle_pipenv_errors(error) raise DependencyFileNotResolvable, msg end - if error.message.include?("Could not find a version") || - error.message.include?("is not a python version") - check_original_requirements_resolvable + if error.message.match?(PIPENV_RANGE_WARNING) + msg = "Pipenv does not support specifying Python ranges "\ + "(see https://github.com/pypa/pipenv/issues/1050 for more "\ + "details)." + raise DependencyFileNotResolvable, msg + end + + check_original_requirements_resolvable if error.message.include?("Could not find a version") + + if error.message.include?("SyntaxError: invalid syntax") + raise DependencyFileNotResolvable, + "SyntaxError while installing dependencies. Is one of the dependencies not Python 3 compatible? "\ + "Pip v21 no longer supports Python 2." end if (error.message.include?('Command "python setup.py egg_info"') || @@ -221,13 +228,6 @@ def handle_pipenv_errors_resolving_original_reqs(error) raise DependencyFileNotResolvable, msg end - if error.message.include?("is not a python version") - msg = "Pipenv does not support specifying Python ranges "\ - "(see https://github.com/pypa/pipenv/issues/1050 for more "\ - "details)." - raise DependencyFileNotResolvable, msg - end - if error.message.include?("UnsupportedPythonVersion") && user_specified_python_requirement msg = clean_error_message(error.message). @@ -465,36 +465,6 @@ def run_command(command, env: {}) def run_pipenv_command(command, env: pipenv_env_variables) run_command("pyenv local #{python_version}") run_command(command, env: env) - rescue SharedHelpers::HelperSubprocessFailed => e - original_error ||= e - msg = e.message - - relevant_error = - if may_be_using_wrong_python_version?(msg) then original_error - else e - end - - raise relevant_error unless may_be_using_wrong_python_version?(msg) - raise relevant_error if python_version.start_with?("2") - - # Clear the existing virtualenv, so that we use the new Python version - run_command("pyenv local #{python_version}") - run_command("pyenv exec pipenv --rm") - - @python_version = "2.7.18" - retry - ensure - @python_version = nil - FileUtils.remove_entry(".python-version", true) - end - - def may_be_using_wrong_python_version?(error_message) - return false if user_specified_python_requirement - return true if error_message.include?("UnsupportedPythonVersion") - return true if error_message.include?("at matches #{dependency.name}") - - error_message.include?('Command "python setup.py egg_info" failed') || - error_message.include?("exit status 1: python setup.py egg_info") end def pipenv_env_variables @@ -530,4 +500,3 @@ def setup_cfg_files end end end -# rubocop:enable Metrics/ClassLength diff --git a/python/spec/dependabot/python/file_updater/pip_compile_file_updater_spec.rb b/python/spec/dependabot/python/file_updater/pip_compile_file_updater_spec.rb index 2ce0e88ab2..3baaba45a0 100644 --- a/python/spec/dependabot/python/file_updater/pip_compile_file_updater_spec.rb +++ b/python/spec/dependabot/python/file_updater/pip_compile_file_updater_spec.rb @@ -175,17 +175,6 @@ end end - context "with a met marker that forces a difference Python version" do - let(:manifest_fixture_name) { "met_marker.in" } - let(:generated_fixture_name) { "pip_compile_met_marker.txt" } - - it "updates the requirements.txt, keeping the unmet dep in it" do - expect(updated_files.count).to eq(1) - expect(updated_files.first.content).to include("attrs==18.1.0") - expect(updated_files.first.content).to include("flaky") - end - end - context "with an unsafe dependency" do let(:manifest_fixture_name) { "unsafe.in" } let(:dependency_name) { "flake8" } @@ -498,91 +487,5 @@ end end end - - context "when the upgrade requires Python 2.7" do - let(:manifest_fixture_name) { "legacy_python.in" } - let(:generated_fixture_name) { "pip_compile_legacy_python.txt" } - - let(:dependency_name) { "wsgiref" } - let(:dependency_version) { "0.1.2" } - let(:dependency_previous_version) { "0.1.1" } - let(:dependency_requirements) do - [{ - file: "requirements/test.in", - requirement: "<=0.1.2", - groups: [], - source: nil - }] - end - let(:dependency_previous_requirements) { dependency_requirements } - - it "updates the requirements.txt" do - expect(updated_files.count).to eq(1) - expect(updated_files.last.content).to include("wsgiref==0.1.2") - end - - context "for a dependency that uses markers correctly" do - let(:manifest_fixture_name) { "legacy_python_2.in" } - let(:generated_fixture_name) { "pip_compile_legacy_python_2.txt" } - - let(:dependency_name) { "astroid" } - let(:dependency_version) { "1.6.5" } - let(:dependency_previous_version) { "1.6.4" } - let(:dependency_requirements) do - [{ - file: "requirements/test.in", - requirement: "<2", - groups: [], - source: nil - }] - end - let(:dependency_previous_requirements) { dependency_requirements } - - it "updates the requirements.txt" do - expect(updated_files.count).to eq(1) - expect(updated_files.last.content).to include("astroid==1.6.5") - end - end - end - - context "when the upgrade would resolve differently on Python 3" do - let(:dependency_files) { [manifest_file, generated_file, python_file] } - let(:manifest_fixture_name) { "resolves_differently_by_python.in" } - let(:generated_fixture_name) do - "pip_compile_resolves_differently_by_python.txt" - end - let(:python_file) do - Dependabot::DependencyFile.new( - name: ".python-version", - content: "2.7.18" - ) - end - - let(:dependency_name) { "tornado" } - let(:dependency_version) { "5.1.1" } - let(:dependency_previous_version) { "5.1.0" } - let(:dependency_requirements) do - [{ - file: "requirements/test.in", - requirement: "==5.1.1", - groups: [], - source: nil - }] - end - let(:dependency_previous_requirements) do - [{ - file: "requirements/test.in", - requirement: "==5.1.0", - groups: [], - source: nil - }] - end - - it "updates the requirements.txt using Python 2.7" do - expect(updated_files.count).to eq(2) - expect(updated_files.last.content).to include("tornado==5.1.1") - expect(updated_files.last.content).to include("futures") - end - end end end diff --git a/python/spec/dependabot/python/file_updater/pipfile_file_updater_spec.rb b/python/spec/dependabot/python/file_updater/pipfile_file_updater_spec.rb index f0d2aa2ca9..8a15699a23 100644 --- a/python/spec/dependabot/python/file_updater/pipfile_file_updater_spec.rb +++ b/python/spec/dependabot/python/file_updater/pipfile_file_updater_spec.rb @@ -141,14 +141,12 @@ json_lockfile = JSON.parse(updated_lockfile.content) expect(updated_pipfile.content). - to include('python_full_version = "2.7.18"') + to include('python_full_version = "3.9.4"') expect(json_lockfile["default"]["requests"]["version"]). to eq("==2.18.4") expect(json_lockfile["develop"]["pytest"]["version"]).to eq("==3.4.0") expect(json_lockfile["_meta"]["requires"]). to eq(JSON.parse(lockfile.content)["_meta"]["requires"]) - expect(json_lockfile["develop"]["funcsigs"]["markers"]). - to eq("python_version < '3.0'") end context "that comes from a Poetry file and includes || logic" do @@ -171,7 +169,7 @@ let(:python_version_file) do Dependabot::DependencyFile.new( name: ".python-version", - content: "2.7.18\n" + content: "3.9.4\n" ) end @@ -179,80 +177,6 @@ expect(updated_files.map(&:name)).to eq(%w(Pipfile Pipfile.lock)) end end - - context "when the Python requirement is implicit" do - let(:pipfile_fixture_name) { "required_python_implicit" } - let(:dependency) do - Dependabot::Dependency.new( - name: "pytest", - version: "3.8.1", - previous_version: "3.4.1", - package_manager: "pip", - requirements: [{ - requirement: "==3.8.1", - file: "Pipfile", - source: nil, - groups: ["develop"] - }], - previous_requirements: [{ - requirement: "==3.4.0", - file: "Pipfile", - source: nil, - groups: ["develop"] - }] - ) - end - - it "updates both files correctly" do - expect(updated_files.map(&:name)).to eq(%w(Pipfile Pipfile.lock)) - end - - context "when updating a python-2 only dep" do - let(:dependency) do - Dependabot::Dependency.new( - name: "futures", - version: "3.3.0", - previous_version: "3.2.0", - package_manager: "pip", - requirements: [{ - requirement: "==3.3.0", - file: "Pipfile", - source: nil, - groups: ["default"] - }], - previous_requirements: [{ - requirement: "==3.2.0", - file: "Pipfile", - source: nil, - groups: ["default"] - }] - ) - end - - it "updates both files correctly" do - expect(updated_files.map(&:name)).to eq(%w(Pipfile Pipfile.lock)) - end - end - - context "due to a version in the lockfile" do - let(:pipfile_fixture_name) { "required_python_implicit_2" } - let(:lockfile_fixture_name) { "required_python_implicit_2.lock" } - - it "updates both files correctly" do - expect(updated_files.map(&:name)).to eq(%w(Pipfile Pipfile.lock)) - - updated_lockfile = updated_files.find do |f| - f.name == "Pipfile.lock" - end - json_lockfile = JSON.parse(updated_lockfile.content) - - expect(json_lockfile["develop"]["pytest"]["version"]). - to eq("==3.8.1") - expect(json_lockfile["default"]["futures"]["version"]). - to eq("==3.2.0") - end - end - end end context "when the Pipfile included an environment variable source" do diff --git a/python/spec/dependabot/python/update_checker/latest_version_finder_spec.rb b/python/spec/dependabot/python/update_checker/latest_version_finder_spec.rb index 9049c5f3b6..2454c01da6 100644 --- a/python/spec/dependabot/python/update_checker/latest_version_finder_spec.rb +++ b/python/spec/dependabot/python/update_checker/latest_version_finder_spec.rb @@ -141,19 +141,19 @@ let(:dependency_name) { "django" } let(:dependency_version) { "1.2.4" } - it { is_expected.to eq(Gem::Version.new("2.2.2")) } + it { is_expected.to eq(Gem::Version.new("3.2.4")) } context "and a python version specified" do subject { finder.latest_version(python_version: python_version) } context "that allows the latest version" do let(:python_version) { Dependabot::Python::Version.new("3.6.3") } - it { is_expected.to eq(Gem::Version.new("2.2.2")) } + it { is_expected.to eq(Gem::Version.new("3.2.4")) } end context "that forbids the latest version" do let(:python_version) { Dependabot::Python::Version.new("2.7.11") } - it { is_expected.to eq(Gem::Version.new("1.11.21")) } + it { is_expected.to eq(Gem::Version.new("1.11.29")) } end end end @@ -548,7 +548,7 @@ let(:dependency_name) { "django" } let(:dependency_version) { "1.2.4" } - it { is_expected.to eq(Gem::Version.new("2.2.2")) } + it { is_expected.to eq(Gem::Version.new("3.2.4")) } context "and a python version specified" do subject do @@ -557,12 +557,12 @@ context "that allows the latest version" do let(:python_version) { Dependabot::Python::Version.new("3.6.3") } - it { is_expected.to eq(Gem::Version.new("2.2.2")) } + it { is_expected.to eq(Gem::Version.new("3.2.4")) } end context "that forbids the latest version" do let(:python_version) { Dependabot::Python::Version.new("2.7.11") } - it { is_expected.to eq(Gem::Version.new("1.11.21")) } + it { is_expected.to eq(Gem::Version.new("1.11.29")) } end end end 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 e80effc033..02824a3578 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 @@ -375,86 +375,6 @@ end end - context "with a Python 2.7 library" do - let(:manifest_fixture_name) { "legacy_python.in" } - let(:generated_fixture_name) { "pip_compile_legacy_python.txt" } - - let(:dependency_name) { "wsgiref" } - let(:dependency_version) { "0.1.1" } - let(:dependency_requirements) do - [{ - file: "requirements/test.in", - requirement: "<=0.1.2", - groups: [], - source: nil - }] - end - let(:updated_requirement) { ">= 0.1.1, <= 2.0.0" } - - it { is_expected.to eq(Gem::Version.new("0.1.2")) } - - context "that uses markers correctly (so raises a different error)" do - let(:manifest_fixture_name) { "legacy_python_2.in" } - let(:generated_fixture_name) { "pip_compile_legacy_python_2.txt" } - - let(:dependency_name) { "astroid" } - let(:dependency_version) { "1.6.4" } - let(:dependency_requirements) do - [{ - file: "requirements/test.in", - requirement: "<2", - groups: [], - source: nil - }] - end - - 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] - end - let(:python_version_file) do - Dependabot::DependencyFile.new( - name: ".python-version", - content: "2.7.18\n" - ) - end - - it { is_expected.to eq(Gem::Version.new("0.1.2")) } - - context "that has a bad version in it" do - let(:python_version_file) do - Dependabot::DependencyFile.new( - name: ".python-version", - content: "rubbish\n" - ) - end - - it { is_expected.to eq(Gem::Version.new("0.1.2")) } - end - end - end - context "with native dependencies that are not pre-built" do let(:manifest_fixture_name) { "native_dependencies.in" } let(:generated_fixture_name) { "pip_compile_native_dependencies.txt" } diff --git a/python/spec/dependabot/python/update_checker/pip_version_resolver_spec.rb b/python/spec/dependabot/python/update_checker/pip_version_resolver_spec.rb index e82421e6bd..04328186d3 100644 --- a/python/spec/dependabot/python/update_checker/pip_version_resolver_spec.rb +++ b/python/spec/dependabot/python/update_checker/pip_version_resolver_spec.rb @@ -72,18 +72,18 @@ context "with no indication of the Python version" do let(:dependency_files) { [requirements_file] } - it { is_expected.to eq(Gem::Version.new("2.2.2")) } + it { is_expected.to eq(Gem::Version.new("3.2.4")) } end context "with a .python-version file" do let(:dependency_files) { [requirements_file, python_version_file] } let(:python_version_content) { "3.7.0\n" } - it { is_expected.to eq(Gem::Version.new("2.2.2")) } + it { is_expected.to eq(Gem::Version.new("3.2.4")) } context "that disallows the latest version" do - let(:python_version_content) { "2.7.13\n" } - it { is_expected.to eq(Gem::Version.new("1.11.21")) } + let(:python_version_content) { "3.5.3\n" } + it { is_expected.to eq(Gem::Version.new("2.2.24")) } end end end @@ -116,7 +116,16 @@ it { is_expected.to eq(Gem::Version.new("2.1.1")) } context "that disallows all fixed versions" do - let(:python_version_content) { "2.7.13\n" } + let(:python_version_content) { "3.5.3\n" } + let(:dependency_version) { "3.0.0" } + let(:dependency_requirements) do + [{ + file: "requirements.txt", + requirement: "==3.0.0", + groups: [], + source: nil + }] + end it { is_expected.to be_nil } end diff --git a/python/spec/dependabot/python/update_checker/pipenv_version_resolver_spec.rb b/python/spec/dependabot/python/update_checker/pipenv_version_resolver_spec.rb index d093b86a42..574f9cf414 100644 --- a/python/spec/dependabot/python/update_checker/pipenv_version_resolver_spec.rb +++ b/python/spec/dependabot/python/update_checker/pipenv_version_resolver_spec.rb @@ -114,7 +114,7 @@ expect { subject }. to raise_error(Dependabot::DependencyFileNotResolvable) do |error| expect(error.message).to start_with( - "CRITICAL:pipenv.patched.notpip._internal.index:"\ + "CRITICAL:pipenv.patched.notpip._internal.index.package_finder:"\ "Could not find a version that satisfies the requirement "\ "pytest==10.4.0" ) @@ -122,33 +122,6 @@ end end - context "when the Python version conflicts with another dependency" do - let(:pipfile_fixture_name) { "unresolvable_python_version" } - let(:dependency_files) { [pipfile] } - - let(:dependency_name) { "pytest" } - let(:dependency_version) { "3.4.0" } - let(:dependency_requirements) do - [{ - file: "Pipfile", - requirement: "==3.4.0", - groups: ["develop"], - source: nil - }] - end - - it "raises a helpful error" do - expect { subject }. - to raise_error(Dependabot::DependencyFileNotResolvable) do |error| - expect(error.message).to start_with( - "pipenv.patched.notpip._internal.exceptions."\ - "UnsupportedPythonVersion: futures requires Python '>=2.6, <3' "\ - "but the running Python is 3." - ) - end - end - end - context "with a subdependency" do let(:dependency_name) { "py" } let(:dependency_version) { "1.5.3" } @@ -274,48 +247,12 @@ end let(:updated_requirement) { ">= 3.4.0, <= 3.8.2" } - it { is_expected.to eq(Gem::Version.new("3.8.2")) } - - context "when updating a python-2 only dep" do - let(:dependency_name) { "futures" } - let(:dependency_version) { "3.2.0" } - let(:dependency_requirements) do - [{ - file: "Pipfile", - requirement: "==3.2.0", - groups: ["default"], - source: nil - }] + it "raises an error" do + expect { subject }.to raise_error(Dependabot::DependencyFileNotResolvable) do |error| + expect(error.message).to include( + "SyntaxError while installing dependencies. Is one of the dependencies not Python 3 compatible?" + ) end - let(:updated_requirement) { ">= 3.2.0, <= 3.3.0" } - - it { is_expected.to be >= Gem::Version.new("3.3.0") } - end - - context "due to a version in the lockfile" do - let(:pipfile_fixture_name) { "required_python_implicit_2" } - let(:lockfile_fixture_name) { "required_python_implicit_2.lock" } - - it { is_expected.to eq(Gem::Version.new("3.8.2")) } - end - end - - context "where updating to the latest would break Python compatibility" do - let(:pipfile_fixture_name) { "required_python_blocking" } - let(:dependency_name) { "django" } - let(:dependency_version) { "1.1.14" } - let(:dependency_requirements) do - [{ - file: "Pipfile", - requirement: "==1.1.14", - groups: ["default"], - source: nil - }] - end - let(:updated_requirement) { ">= 1.1.14, <= 2.1.4" } - - it "updates to the latest resolvable 1.x version" do - expect(subject.to_s).to start_with("1.") end end @@ -337,21 +274,6 @@ end end - context "with an unfetchable requirement" do - let(:dependency_files) { [pipfile] } - let(:pipfile_fixture_name) { "bad_requirement" } - - it "raises a helpful error" do - expect { subject }. - to raise_error(Dependabot::DependencyFileNotResolvable) do |error| - expect(error.message).to eq( - "packaging.specifiers.InvalidSpecifier: "\ - "Invalid specifier: '3.4.0'" - ) - end - end - end - context "with extra requirements" do let(:dependency_name) { "raven" } let(:dependency_version) { "5.27.1" } diff --git a/python/spec/dependabot/python/update_checker/poetry_version_resolver_spec.rb b/python/spec/dependabot/python/update_checker/poetry_version_resolver_spec.rb index 97397da4c0..0d88dbf5f1 100644 --- a/python/spec/dependabot/python/update_checker/poetry_version_resolver_spec.rb +++ b/python/spec/dependabot/python/update_checker/poetry_version_resolver_spec.rb @@ -138,8 +138,8 @@ let(:pyproject_fixture_name) { "python_2.toml" } let(:lockfile_fixture_name) { "python_2.lock" } - it "resolves version" do - is_expected.to eq(Gem::Version.new("2.18.4")) + it "raises an error" do + expect { subject }.to raise_error(Dependabot::DependencyFileNotResolvable) end end diff --git a/python/spec/dependabot/python/update_checker_spec.rb b/python/spec/dependabot/python/update_checker_spec.rb index b89bf811ed..447a44a1f8 100644 --- a/python/spec/dependabot/python/update_checker_spec.rb +++ b/python/spec/dependabot/python/update_checker_spec.rb @@ -164,21 +164,21 @@ end let(:pypi_url) { "https://pypi.org/simple/django/" } let(:dependency_name) { "django" } - let(:dependency_version) { "1.2.4" } + let(:dependency_version) { "2.2.0" } let(:dependency_requirements) do [{ file: "requirements.txt", - requirement: "==1.2.4", + requirement: "==2.2.0", groups: [], source: nil }] end - it { is_expected.to eq(Gem::Version.new("2.2.2")) } + it { is_expected.to eq(Gem::Version.new("3.2.4")) } context "that disallows the latest version" do - let(:python_version_content) { "2.7.13\n" } - it { is_expected.to eq(Gem::Version.new("1.11.21")) } + let(:python_version_content) { "3.5.3\n" } + it { is_expected.to eq(Gem::Version.new("2.2.24")) } end end end diff --git a/python/spec/fixtures/lockfiles/required_python.lock b/python/spec/fixtures/lockfiles/required_python.lock index 3ae7f1a556..633a6de243 100644 --- a/python/spec/fixtures/lockfiles/required_python.lock +++ b/python/spec/fixtures/lockfiles/required_python.lock @@ -5,8 +5,8 @@ }, "pipfile-spec": 6, "requires": { - "python_full_version": "2.7.18", - "python_version": "2.7" + "python_full_version": "3.9.4", + "python_version": "3.9" }, "sources": [ { diff --git a/python/spec/fixtures/lockfiles/required_python_implicit_2.lock b/python/spec/fixtures/lockfiles/required_python_implicit_2.lock deleted file mode 100644 index 219b70f24a..0000000000 --- a/python/spec/fixtures/lockfiles/required_python_implicit_2.lock +++ /dev/null @@ -1,105 +0,0 @@ -{ - "_meta": { - "hash": { - "sha256": "dc89996cd5f25c308d01a3825e434d133ada35b5a196f1571ead4def69b1c49d" - }, - "pipfile-spec": 6, - "requires": {}, - "sources": [ - { - "url": "https://pypi.org/simple", - "verify_ssl": true - } - ] - }, - "default": { - "certifi": { - "hashes": [ - "sha256:339dc09518b07e2fa7eda5450740925974815557727d6bd35d319c1524a04a4c", - "sha256:6d58c986d22b038c8c0df30d639f23a3e6d172a05c3583e766f4c0b785c0986a" - ], - "version": "==2018.10.15" - }, - "chardet": { - "hashes": [ - "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", - "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" - ], - "version": "==3.0.4" - }, - "futures": { - "hashes": [ - "sha256:9ec02aa7d674acb8618afb127e27fde7fc68994c0437ad759fa094a574adb265", - "sha256:ec0a6cb848cc212002b9828c3e34c675e0c9ff6741dc445cab6fdd4e1085d1f1" - ], - "version": "==3.2.0" - }, - "idna": { - "hashes": [ - "sha256:3cb5ce08046c4e3a560fc02f138d0ac63e00f8ce5901a56b32ec8b7994082aab", - "sha256:cc19709fd6d0cbfed39ea875d29ba6d4e22c0cebc510a76d6302a28385e8bb70" - ], - "version": "==2.5" - }, - "requests": { - "hashes": [ - "sha256:5e88d64aa56ac0fda54e77fb9762ebc65879e171b746d5479a33c4082519d6c6", - "sha256:cd0189f962787284bff715fddaad478eb4d9c15aa167bd64e52ea0f661e7ea5c" - ], - "version": "==2.18.0" - }, - "urllib3": { - "hashes": [ - "sha256:8ed6d5c1ff9d6ba84677310060d6a3a78ca3072ce0684cb3c645023009c114b1", - "sha256:b14486978518ca0901a76ba973d7821047409d7f726f22156b24e83fd71382a5" - ], - "version": "==1.21.1" - } - }, - "develop": { - "attrs": { - "hashes": [ - "sha256:10cbf6e27dbce8c30807caf056c8eb50917e0eaafe86347671b57254006c3e69", - "sha256:ca4be454458f9dec299268d472aaa5a11f67a4ff70093396e1ceae9c76cf4bbb" - ], - "version": "==18.2.0" - }, - "funcsigs": { - "hashes": [ - "sha256:330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca", - "sha256:a7bb0f2cf3a3fd1ab2732cb49eba4252c2af4240442415b4abce3b87022a8f50" - ], - "markers": "python_version < '3.0'", - "version": "==1.0.2" - }, - "pluggy": { - "hashes": [ - "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff", - "sha256:d345c8fe681115900d6da8d048ba67c25df42973bda370783cd58826442dcd7c", - "sha256:e160a7fcf25762bb60efc7e171d4497ff1d8d2d75a3d0df7a21b76821ecbf5c5" - ], - "version": "==0.6.0" - }, - "py": { - "hashes": [ - "sha256:bf92637198836372b520efcba9e020c330123be8ce527e535d185ed4b6f45694", - "sha256:e76826342cefe3c3d5f7e8ee4316b80d1dd8a300781612ddbc765c17ba25a6c6" - ], - "version": "==1.7.0" - }, - "pytest": { - "hashes": [ - "sha256:6074ea3b9c999bd6d0df5fa9d12dd95ccd23550df2a582f5f5b848331d2e82ca", - "sha256:95fa025cd6deb5d937e04e368a00552332b58cae23f63b76c8c540ff1733ab6d" - ], - "version": "==3.4.0" - }, - "six": { - "hashes": [ - "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", - "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb" - ], - "version": "==1.11.0" - } - } -} diff --git a/python/spec/fixtures/pip_compile_files/legacy_python.in b/python/spec/fixtures/pip_compile_files/legacy_python.in deleted file mode 100644 index 5201453d44..0000000000 --- a/python/spec/fixtures/pip_compile_files/legacy_python.in +++ /dev/null @@ -1 +0,0 @@ -wsgiref<=0.1.2 # Only works with Python < 3.2 diff --git a/python/spec/fixtures/pip_compile_files/legacy_python_2.in b/python/spec/fixtures/pip_compile_files/legacy_python_2.in deleted file mode 100644 index 553595c9c1..0000000000 --- a/python/spec/fixtures/pip_compile_files/legacy_python_2.in +++ /dev/null @@ -1,2 +0,0 @@ -astroid<2 -futures diff --git a/python/spec/fixtures/pip_compile_files/legacy_python_3.in b/python/spec/fixtures/pip_compile_files/legacy_python_3.in deleted file mode 100644 index 74ba9f7b3c..0000000000 --- a/python/spec/fixtures/pip_compile_files/legacy_python_3.in +++ /dev/null @@ -1,2 +0,0 @@ -oauth2==1.5.211 -django-adv-cache-tag==0.2.1 diff --git a/python/spec/fixtures/pip_compile_files/unresolvable_if_unpinned.txt b/python/spec/fixtures/pip_compile_files/unresolvable_if_unpinned.txt new file mode 100644 index 0000000000..d5192c6e00 --- /dev/null +++ b/python/spec/fixtures/pip_compile_files/unresolvable_if_unpinned.txt @@ -0,0 +1,101 @@ +# +# This file is autogenerated by pip-compile +# To update, run: +# +# pip-compile spec/fixtures/pip_compile_files/unresolvable_if_unpinned.in +# +aws-xray-sdk==0.95 + # via moto +boto3==1.7.84 + # via + # -r spec/fixtures/pip_compile_files/unresolvable_if_unpinned.in + # moto +boto==2.49.0 + # via moto +botocore==1.10.84 + # via + # -r spec/fixtures/pip_compile_files/unresolvable_if_unpinned.in + # boto3 + # moto + # s3transfer +certifi==2021.5.30 + # via requests +cffi==1.14.5 + # via cryptography +chardet==4.0.0 + # via requests +cookies==2.2.1 + # via moto +cryptography==3.4.7 + # via moto +docker==5.0.0 + # via moto +docutils==0.17.1 + # via botocore +ecdsa==0.17.0 + # via python-jose +future==0.18.2 + # via python-jose +idna==2.10 + # via requests +jinja2==3.0.1 + # via moto +jmespath==0.10.0 + # via + # boto3 + # botocore +jsondiff==1.1.1 + # via moto +jsonpickle==2.0.0 + # via aws-xray-sdk +markupsafe==2.0.1 + # via jinja2 +mock==4.0.3 + # via moto +moto==1.3.6 + # via -r spec/fixtures/pip_compile_files/unresolvable_if_unpinned.in +pyaml==20.4.0 + # via moto +pycparser==2.20 + # via cffi +pycryptodome==3.10.1 + # via python-jose +python-dateutil==2.8.1 + # via + # botocore + # moto +python-jose==2.0.2 + # via moto +pytz==2021.1 + # via moto +pyyaml==5.4.1 + # via pyaml +requests==2.25.1 + # via + # aws-xray-sdk + # docker + # moto + # responses +responses==0.13.3 + # via moto +s3transfer==0.1.13 + # via boto3 +six==1.16.0 + # via + # ecdsa + # moto + # python-dateutil + # python-jose + # responses +urllib3==1.26.5 + # via + # requests + # responses +websocket-client==1.0.1 + # via docker +werkzeug==2.0.1 + # via moto +wrapt==1.12.1 + # via aws-xray-sdk +xmltodict==0.12.0 + # via moto diff --git a/python/spec/fixtures/pipfiles/bad_requirement b/python/spec/fixtures/pipfiles/bad_requirement deleted file mode 100644 index 641febb314..0000000000 --- a/python/spec/fixtures/pipfiles/bad_requirement +++ /dev/null @@ -1,9 +0,0 @@ -[[source]] -url = "https://pypi.org/simple" -verify_ssl = true - -[dev-packages] -pytest = "3.4.0" - -[packages] -requests = "2.18.0" diff --git a/python/spec/fixtures/pipfiles/extra_subdependency b/python/spec/fixtures/pipfiles/extra_subdependency index 5bfc35daf4..d3b28dead3 100644 --- a/python/spec/fixtures/pipfiles/extra_subdependency +++ b/python/spec/fixtures/pipfiles/extra_subdependency @@ -3,9 +3,6 @@ url = "https://pypi.org/simple" verify_ssl = true name = "pypi" -[requires] -python_version = "2.7" - [packages] flask = "==1.0.*" raven = {extras = ["flask"], version = "==5.27.1"} diff --git a/python/spec/fixtures/pipfiles/problematic_resolution b/python/spec/fixtures/pipfiles/problematic_resolution index d494e5417e..37d6678f24 100644 --- a/python/spec/fixtures/pipfiles/problematic_resolution +++ b/python/spec/fixtures/pipfiles/problematic_resolution @@ -10,9 +10,6 @@ mockredispy = "==2.9.3" moto = "==1.3.3" pylint = "==1.9.2" -[requires] -python_version = "2.7" - [[source]] name = "pypi" url = "https://pypi.org/simple/" diff --git a/python/spec/fixtures/pipfiles/required_python b/python/spec/fixtures/pipfiles/required_python index a652b60cfc..10c96ff926 100644 --- a/python/spec/fixtures/pipfiles/required_python +++ b/python/spec/fixtures/pipfiles/required_python @@ -3,8 +3,8 @@ url = "https://pypi.org/simple" verify_ssl = true [requires] -python_full_version = "2.7.18" -python_version = "2.7" +python_full_version = "3.9.4" +python_version = "3.9" [dev-packages] pytest = "==3.4.0" diff --git a/python/spec/fixtures/pipfiles/required_python_blocking b/python/spec/fixtures/pipfiles/required_python_blocking deleted file mode 100644 index 5102458d7e..0000000000 --- a/python/spec/fixtures/pipfiles/required_python_blocking +++ /dev/null @@ -1,9 +0,0 @@ -[[source]] -url = "https://pypi.org/simple" -verify_ssl = true - -[requires] -python_version = "2.7" - -[packages] -Django = "==1.1.14" diff --git a/python/spec/fixtures/pipfiles/required_python_implicit_2 b/python/spec/fixtures/pipfiles/required_python_implicit_2 deleted file mode 100644 index a303b6779f..0000000000 --- a/python/spec/fixtures/pipfiles/required_python_implicit_2 +++ /dev/null @@ -1,10 +0,0 @@ -[[source]] -url = "https://pypi.org/simple" -verify_ssl = true - -[dev-packages] -pytest = "==3.4.0" - -[packages] -requests = "==2.18.0" -futures = "*" diff --git a/python/spec/fixtures/pipfiles/unresolvable_python_version b/python/spec/fixtures/pipfiles/unresolvable_python_version deleted file mode 100644 index 648527f8d9..0000000000 --- a/python/spec/fixtures/pipfiles/unresolvable_python_version +++ /dev/null @@ -1,13 +0,0 @@ -[[source]] -url = "https://pypi.org/simple" -verify_ssl = true -name = "pypi" - -[requires] -python_version = "3.7" - -[dev-packages] -pytest = "==3.4.0" - -[packages] -futures = "==3.2.0" diff --git a/python/spec/fixtures/pypi/pypi_simple_response_django.html b/python/spec/fixtures/pypi/pypi_simple_response_django.html index e82b84979b..a14d2e5c3a 100644 --- a/python/spec/fixtures/pypi/pypi_simple_response_django.html +++ b/python/spec/fixtures/pypi/pypi_simple_response_django.html @@ -1,6 +1,7 @@ - + + Links for Django @@ -256,68 +257,224 @@

Links for Django

Django-1.11.20.tar.gz
Django-1.11.21-py2.py3-none-any.whl
Django-1.11.21.tar.gz
- Django-2.0a1-py3-none-any.whl
- Django-2.0b1-py3-none-any.whl
- Django-2.0rc1-py3-none-any.whl
- Django-2.0-py3-none-any.whl
- Django-2.0.tar.gz
- Django-2.0.1-py3-none-any.whl
- Django-2.0.1.tar.gz
- Django-2.0.2-py3-none-any.whl
- Django-2.0.2.tar.gz
- Django-2.0.3-py3-none-any.whl
- Django-2.0.3.tar.gz
- Django-2.0.4-py3-none-any.whl
- Django-2.0.4.tar.gz
- Django-2.0.5-py3-none-any.whl
- Django-2.0.5.tar.gz
- Django-2.0.6-py3-none-any.whl
- Django-2.0.6.tar.gz
- Django-2.0.7-py3-none-any.whl
- Django-2.0.7.tar.gz
- Django-2.0.8-py3-none-any.whl
- Django-2.0.8.tar.gz
- Django-2.0.9-py3-none-any.whl
- Django-2.0.9.tar.gz
- Django-2.0.10-py3-none-any.whl
- Django-2.0.10.tar.gz
- Django-2.0.12-py3-none-any.whl
- Django-2.0.12.tar.gz
- Django-2.0.13-py3-none-any.whl
- Django-2.0.13.tar.gz
- Django-2.1a1-py3-none-any.whl
- Django-2.1b1-py3-none-any.whl
- Django-2.1rc1-py3-none-any.whl
- Django-2.1-py3-none-any.whl
- Django-2.1.tar.gz
- Django-2.1.1-py3-none-any.whl
- Django-2.1.1.tar.gz
- Django-2.1.2-py3-none-any.whl
- Django-2.1.2.tar.gz
- Django-2.1.3-py3-none-any.whl
- Django-2.1.3.tar.gz
- Django-2.1.4-py3-none-any.whl
- Django-2.1.4.tar.gz
- Django-2.1.5-py3-none-any.whl
- Django-2.1.5.tar.gz
- Django-2.1.7-py3-none-any.whl
- Django-2.1.7.tar.gz
- Django-2.1.8-py3-none-any.whl
- Django-2.1.8.tar.gz
- Django-2.1.9-py3-none-any.whl
- Django-2.1.9.tar.gz
- Django-2.2a1-py3-none-any.whl
- Django-2.2a1.tar.gz
- Django-2.2b1-py3-none-any.whl
- Django-2.2b1.tar.gz
- Django-2.2rc1-py3-none-any.whl
- Django-2.2rc1.tar.gz
- Django-2.2-py3-none-any.whl
- Django-2.2.tar.gz
- Django-2.2.1-py3-none-any.whl
- Django-2.2.1.tar.gz
- Django-2.2.2-py3-none-any.whl
- Django-2.2.2.tar.gz
+ Django-1.11.22-py2.py3-none-any.whl
+ Django-1.11.22.tar.gz
+ Django-1.11.23-py2.py3-none-any.whl
+ Django-1.11.23.tar.gz
+ Django-1.11.24-py2.py3-none-any.whl
+ Django-1.11.24.tar.gz
+ Django-1.11.25-py2.py3-none-any.whl
+ Django-1.11.25.tar.gz
+ Django-1.11.26-py2.py3-none-any.whl
+ Django-1.11.26.tar.gz
+ Django-1.11.27-py2.py3-none-any.whl
+ Django-1.11.27.tar.gz
+ Django-1.11.28-py2.py3-none-any.whl
+ Django-1.11.28.tar.gz
+ Django-1.11.29-py2.py3-none-any.whl
+ Django-1.11.29.tar.gz
+ Django-2.0a1-py3-none-any.whl
+ Django-2.0b1-py3-none-any.whl
+ Django-2.0rc1-py3-none-any.whl
+ Django-2.0-py3-none-any.whl
+ Django-2.0.tar.gz
+ Django-2.0.1-py3-none-any.whl
+ Django-2.0.1.tar.gz
+ Django-2.0.2-py3-none-any.whl
+ Django-2.0.2.tar.gz
+ Django-2.0.3-py3-none-any.whl
+ Django-2.0.3.tar.gz
+ Django-2.0.4-py3-none-any.whl
+ Django-2.0.4.tar.gz
+ Django-2.0.5-py3-none-any.whl
+ Django-2.0.5.tar.gz
+ Django-2.0.6-py3-none-any.whl
+ Django-2.0.6.tar.gz
+ Django-2.0.7-py3-none-any.whl
+ Django-2.0.7.tar.gz
+ Django-2.0.8-py3-none-any.whl
+ Django-2.0.8.tar.gz
+ Django-2.0.9-py3-none-any.whl
+ Django-2.0.9.tar.gz
+ Django-2.0.10-py3-none-any.whl
+ Django-2.0.10.tar.gz
+ Django-2.0.12-py3-none-any.whl
+ Django-2.0.12.tar.gz
+ Django-2.0.13-py3-none-any.whl
+ Django-2.0.13.tar.gz
+ Django-2.1a1-py3-none-any.whl
+ Django-2.1b1-py3-none-any.whl
+ Django-2.1rc1-py3-none-any.whl
+ Django-2.1-py3-none-any.whl
+ Django-2.1.tar.gz
+ Django-2.1.1-py3-none-any.whl
+ Django-2.1.1.tar.gz
+ Django-2.1.2-py3-none-any.whl
+ Django-2.1.2.tar.gz
+ Django-2.1.3-py3-none-any.whl
+ Django-2.1.3.tar.gz
+ Django-2.1.4-py3-none-any.whl
+ Django-2.1.4.tar.gz
+ Django-2.1.5-py3-none-any.whl
+ Django-2.1.5.tar.gz
+ Django-2.1.7-py3-none-any.whl
+ Django-2.1.7.tar.gz
+ Django-2.1.8-py3-none-any.whl
+ Django-2.1.8.tar.gz
+ Django-2.1.9-py3-none-any.whl
+ Django-2.1.9.tar.gz
+ Django-2.1.10-py3-none-any.whl
+ Django-2.1.10.tar.gz
+ Django-2.1.11-py3-none-any.whl
+ Django-2.1.11.tar.gz
+ Django-2.1.12-py3-none-any.whl
+ Django-2.1.12.tar.gz
+ Django-2.1.13-py3-none-any.whl
+ Django-2.1.13.tar.gz
+ Django-2.1.14-py3-none-any.whl
+ Django-2.1.14.tar.gz
+ Django-2.1.15-py3-none-any.whl
+ Django-2.1.15.tar.gz
+ Django-2.2a1-py3-none-any.whl
+ Django-2.2a1.tar.gz
+ Django-2.2b1-py3-none-any.whl
+ Django-2.2b1.tar.gz
+ Django-2.2rc1-py3-none-any.whl
+ Django-2.2rc1.tar.gz
+ Django-2.2-py3-none-any.whl
+ Django-2.2.tar.gz
+ Django-2.2.1-py3-none-any.whl
+ Django-2.2.1.tar.gz
+ Django-2.2.2-py3-none-any.whl
+ Django-2.2.2.tar.gz
+ Django-2.2.3-py3-none-any.whl
+ Django-2.2.3.tar.gz
+ Django-2.2.4-py3-none-any.whl
+ Django-2.2.4.tar.gz
+ Django-2.2.5-py3-none-any.whl
+ Django-2.2.5.tar.gz
+ Django-2.2.6-py3-none-any.whl
+ Django-2.2.6.tar.gz
+ Django-2.2.7-py3-none-any.whl
+ Django-2.2.7.tar.gz
+ Django-2.2.8-py3-none-any.whl
+ Django-2.2.8.tar.gz
+ Django-2.2.9-py3-none-any.whl
+ Django-2.2.9.tar.gz
+ Django-2.2.10-py3-none-any.whl
+ Django-2.2.10.tar.gz
+ Django-2.2.11-py3-none-any.whl
+ Django-2.2.11.tar.gz
+ Django-2.2.12-py3-none-any.whl
+ Django-2.2.12.tar.gz
+ Django-2.2.13-py3-none-any.whl
+ Django-2.2.13.tar.gz
+ Django-2.2.14-py3-none-any.whl
+ Django-2.2.14.tar.gz
+ Django-2.2.15-py3-none-any.whl
+ Django-2.2.15.tar.gz
+ Django-2.2.16-py3-none-any.whl
+ Django-2.2.16.tar.gz
+ Django-2.2.17-py3-none-any.whl
+ Django-2.2.17.tar.gz
+ Django-2.2.18-py3-none-any.whl
+ Django-2.2.18.tar.gz
+ Django-2.2.19-py3-none-any.whl
+ Django-2.2.19.tar.gz
+ Django-2.2.20-py3-none-any.whl
+ Django-2.2.20.tar.gz
+ Django-2.2.21-py3-none-any.whl
+ Django-2.2.21.tar.gz
+ Django-2.2.22-py3-none-any.whl
+ Django-2.2.22.tar.gz
+ Django-2.2.23-py3-none-any.whl
+ Django-2.2.23.tar.gz
+ Django-2.2.24-py3-none-any.whl
+ Django-2.2.24.tar.gz
+ Django-3.0a1-py3-none-any.whl
+ Django-3.0a1.tar.gz
+ Django-3.0b1-py3-none-any.whl
+ Django-3.0b1.tar.gz
+ Django-3.0rc1-py3-none-any.whl
+ Django-3.0rc1.tar.gz
+ Django-3.0-py3-none-any.whl
+ Django-3.0.tar.gz
+ Django-3.0.1-py3-none-any.whl
+ Django-3.0.1.tar.gz
+ Django-3.0.2-py3-none-any.whl
+ Django-3.0.2.tar.gz
+ Django-3.0.3-py3-none-any.whl
+ Django-3.0.3.tar.gz
+ Django-3.0.4-py3-none-any.whl
+ Django-3.0.4.tar.gz
+ Django-3.0.5-py3-none-any.whl
+ Django-3.0.5.tar.gz
+ Django-3.0.6-py3-none-any.whl
+ Django-3.0.6.tar.gz
+ Django-3.0.7-py3-none-any.whl
+ Django-3.0.7.tar.gz
+ Django-3.0.8-py3-none-any.whl
+ Django-3.0.8.tar.gz
+ Django-3.0.9-py3-none-any.whl
+ Django-3.0.9.tar.gz
+ Django-3.0.10-py3-none-any.whl
+ Django-3.0.10.tar.gz
+ Django-3.0.11-py3-none-any.whl
+ Django-3.0.11.tar.gz
+ Django-3.0.12-py3-none-any.whl
+ Django-3.0.12.tar.gz
+ Django-3.0.13-py3-none-any.whl
+ Django-3.0.13.tar.gz
+ Django-3.0.14-py3-none-any.whl
+ Django-3.0.14.tar.gz
+ Django-3.1a1-py3-none-any.whl
+ Django-3.1a1.tar.gz
+ Django-3.1b1-py3-none-any.whl
+ Django-3.1b1.tar.gz
+ Django-3.1rc1-py3-none-any.whl
+ Django-3.1rc1.tar.gz
+ Django-3.1-py3-none-any.whl
+ Django-3.1.tar.gz
+ Django-3.1.1-py3-none-any.whl
+ Django-3.1.1.tar.gz
+ Django-3.1.2-py3-none-any.whl
+ Django-3.1.2.tar.gz
+ Django-3.1.3-py3-none-any.whl
+ Django-3.1.3.tar.gz
+ Django-3.1.4-py3-none-any.whl
+ Django-3.1.4.tar.gz
+ Django-3.1.5-py3-none-any.whl
+ Django-3.1.5.tar.gz
+ Django-3.1.6-py3-none-any.whl
+ Django-3.1.6.tar.gz
+ Django-3.1.7-py3-none-any.whl
+ Django-3.1.7.tar.gz
+ Django-3.1.8-py3-none-any.whl
+ Django-3.1.8.tar.gz
+ Django-3.1.9-py3-none-any.whl
+ Django-3.1.9.tar.gz
+ Django-3.1.10-py3-none-any.whl
+ Django-3.1.10.tar.gz
+ Django-3.1.11-py3-none-any.whl
+ Django-3.1.11.tar.gz
+ Django-3.1.12-py3-none-any.whl
+ Django-3.1.12.tar.gz
+ Django-3.2a1-py3-none-any.whl
+ Django-3.2a1.tar.gz
+ Django-3.2b1-py3-none-any.whl
+ Django-3.2b1.tar.gz
+ Django-3.2rc1-py3-none-any.whl
+ Django-3.2rc1.tar.gz
+ Django-3.2-py3-none-any.whl
+ Django-3.2.tar.gz
+ Django-3.2.1-py3-none-any.whl
+ Django-3.2.1.tar.gz
+ Django-3.2.2-py3-none-any.whl
+ Django-3.2.2.tar.gz
+ Django-3.2.3-py3-none-any.whl
+ Django-3.2.3.tar.gz
+ Django-3.2.4-py3-none-any.whl
+ Django-3.2.4.tar.gz
- + diff --git a/python/spec/fixtures/requirements/pip_compile_legacy_python.txt b/python/spec/fixtures/requirements/pip_compile_legacy_python.txt deleted file mode 100644 index ad95c350b5..0000000000 --- a/python/spec/fixtures/requirements/pip_compile_legacy_python.txt +++ /dev/null @@ -1,7 +0,0 @@ -# -# This file is autogenerated by pip-compile -# To update, run: -# -# pip-compile --output-file requirements.txt requirements.in -# -wsgiref==0.1.1 diff --git a/python/spec/fixtures/requirements/pip_compile_legacy_python_2.txt b/python/spec/fixtures/requirements/pip_compile_legacy_python_2.txt deleted file mode 100644 index c01442bea1..0000000000 --- a/python/spec/fixtures/requirements/pip_compile_legacy_python_2.txt +++ /dev/null @@ -1,11 +0,0 @@ -# -# This file is autogenerated by pip-compile -# To update, run: -# -# pip-compile --output-file req.txt req.in -# -astroid==1.6.4 -futures==3.2.0 -lazy-object-proxy==1.3.1 # via astroid -six==1.11.0 # via astroid -wrapt==1.10.11 # via astroid diff --git a/python/spec/fixtures/requirements/pip_compile_legacy_python_3.txt b/python/spec/fixtures/requirements/pip_compile_legacy_python_3.txt deleted file mode 100644 index 3bf473fd7f..0000000000 --- a/python/spec/fixtures/requirements/pip_compile_legacy_python_3.txt +++ /dev/null @@ -1,9 +0,0 @@ -# -# 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 diff --git a/python/spec/fixtures/requirements/pip_compile_unresolvable_if_unpinned.txt b/python/spec/fixtures/requirements/pip_compile_unresolvable_if_unpinned.txt index 15963dcf54..d5192c6e00 100644 --- a/python/spec/fixtures/requirements/pip_compile_unresolvable_if_unpinned.txt +++ b/python/spec/fixtures/requirements/pip_compile_unresolvable_if_unpinned.txt @@ -2,47 +2,100 @@ # This file is autogenerated by pip-compile # To update, run: # -# pip-compile --output-file requirements.txt requirements.in +# pip-compile spec/fixtures/pip_compile_files/unresolvable_if_unpinned.in # ---no-binary psycopg2 - -asn1crypto==0.24.0 # via cryptography -aws-xray-sdk==0.95 # via moto +aws-xray-sdk==0.95 + # via moto boto3==1.7.84 -boto==2.49.0 # via moto + # via + # -r spec/fixtures/pip_compile_files/unresolvable_if_unpinned.in + # moto +boto==2.49.0 + # via moto botocore==1.10.84 -certifi==2018.8.24 # via requests -cffi==1.11.5 # via cryptography -chardet==3.0.4 # via requests -cookies==2.2.1 # via moto, responses -cryptography==2.3.1 # via moto -docker-pycreds==0.3.0 # via docker -docker==3.5.0 # via moto -docutils==0.14 # via botocore -ecdsa==0.13 # via python-jose -future==0.16.0 # via python-jose -idna==2.7 # via cryptography, requests -jinja2==2.10 # via moto -jmespath==0.9.3 # via boto3, botocore -jsondiff==1.1.1 # via moto -jsonpickle==1.0 # via aws-xray-sdk -markupsafe==1.0 # via jinja2 -mock==2.0.0 # via moto + # via + # -r spec/fixtures/pip_compile_files/unresolvable_if_unpinned.in + # boto3 + # moto + # s3transfer +certifi==2021.5.30 + # via requests +cffi==1.14.5 + # via cryptography +chardet==4.0.0 + # via requests +cookies==2.2.1 + # via moto +cryptography==3.4.7 + # via moto +docker==5.0.0 + # via moto +docutils==0.17.1 + # via botocore +ecdsa==0.17.0 + # via python-jose +future==0.18.2 + # via python-jose +idna==2.10 + # via requests +jinja2==3.0.1 + # via moto +jmespath==0.10.0 + # via + # boto3 + # botocore +jsondiff==1.1.1 + # via moto +jsonpickle==2.0.0 + # via aws-xray-sdk +markupsafe==2.0.1 + # via jinja2 +mock==4.0.3 + # via moto moto==1.3.6 -pbr==4.3.0 # via mock -pyaml==17.12.1 # via moto -pycparser==2.19 # via cffi -pycryptodome==3.6.6 # via python-jose -python-dateutil==2.7.3 # via botocore, moto -python-jose==2.0.2 # via moto -pytz==2018.5 # via moto -pyyaml==3.13 # via pyaml -requests==2.20.0 # via aws-xray-sdk, docker, moto, responses -responses==0.9.0 # via moto -s3transfer==0.1.13 # via boto3 -six==1.11.0 # via cryptography, docker, docker-pycreds, mock, moto, python-dateutil, python-jose, responses, websocket-client -urllib3==1.23 # via requests -websocket-client==0.53.0 # via docker -werkzeug==0.14.1 # via moto -wrapt==1.10.11 # via aws-xray-sdk -xmltodict==0.11.0 # via moto + # via -r spec/fixtures/pip_compile_files/unresolvable_if_unpinned.in +pyaml==20.4.0 + # via moto +pycparser==2.20 + # via cffi +pycryptodome==3.10.1 + # via python-jose +python-dateutil==2.8.1 + # via + # botocore + # moto +python-jose==2.0.2 + # via moto +pytz==2021.1 + # via moto +pyyaml==5.4.1 + # via pyaml +requests==2.25.1 + # via + # aws-xray-sdk + # docker + # moto + # responses +responses==0.13.3 + # via moto +s3transfer==0.1.13 + # via boto3 +six==1.16.0 + # via + # ecdsa + # moto + # python-dateutil + # python-jose + # responses +urllib3==1.26.5 + # via + # requests + # responses +websocket-client==1.0.1 + # via docker +werkzeug==2.0.1 + # via moto +wrapt==1.12.1 + # via aws-xray-sdk +xmltodict==0.12.0 + # via moto