dependabot-python 0.230.0 → 0.231.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/dependabot/python/authed_url_builder.rb +1 -0
- data/lib/dependabot/python/file_fetcher.rb +41 -40
- data/lib/dependabot/python/file_parser/pipfile_files_parser.rb +3 -2
- data/lib/dependabot/python/file_parser/pyproject_files_parser.rb +4 -3
- data/lib/dependabot/python/file_parser/python_requirement_parser.rb +11 -10
- data/lib/dependabot/python/file_parser/setup_file_parser.rb +4 -3
- data/lib/dependabot/python/file_parser.rb +17 -16
- data/lib/dependabot/python/file_updater/pip_compile_file_updater.rb +40 -39
- data/lib/dependabot/python/file_updater/pipfile_file_updater.rb +22 -21
- data/lib/dependabot/python/file_updater/pipfile_manifest_updater.rb +11 -10
- data/lib/dependabot/python/file_updater/pipfile_preparer.rb +4 -3
- data/lib/dependabot/python/file_updater/poetry_file_updater.rb +21 -20
- data/lib/dependabot/python/file_updater/pyproject_preparer.rb +6 -5
- data/lib/dependabot/python/file_updater/requirement_file_updater.rb +1 -0
- data/lib/dependabot/python/file_updater/requirement_replacer.rb +28 -27
- data/lib/dependabot/python/file_updater/setup_file_sanitizer.rb +5 -4
- data/lib/dependabot/python/file_updater.rb +4 -3
- data/lib/dependabot/python/helpers.rb +1 -0
- data/lib/dependabot/python/language_version_manager.rb +1 -0
- data/lib/dependabot/python/metadata_finder.rb +4 -3
- data/lib/dependabot/python/name_normaliser.rb +1 -0
- data/lib/dependabot/python/native_helpers.rb +1 -0
- data/lib/dependabot/python/requirement.rb +16 -15
- data/lib/dependabot/python/requirement_parser.rb +1 -0
- data/lib/dependabot/python/update_checker/index_finder.rb +27 -26
- data/lib/dependabot/python/update_checker/latest_version_finder.rb +13 -12
- data/lib/dependabot/python/update_checker/pip_compile_version_resolver.rb +18 -17
- data/lib/dependabot/python/update_checker/pip_version_resolver.rb +5 -4
- data/lib/dependabot/python/update_checker/pipenv_version_resolver.rb +34 -33
- data/lib/dependabot/python/update_checker/poetry_version_resolver.rb +20 -19
- data/lib/dependabot/python/update_checker/requirements_updater.rb +28 -27
- data/lib/dependabot/python/update_checker.rb +7 -6
- data/lib/dependabot/python/version.rb +13 -12
- data/lib/dependabot/python.rb +3 -2
- metadata +19 -5
| @@ -1,3 +1,4 @@ | |
| 1 | 
            +
            # typed: false
         | 
| 1 2 | 
             
            # frozen_string_literal: true
         | 
| 2 3 |  | 
| 3 4 | 
             
            require "toml-rb"
         | 
| @@ -60,17 +61,17 @@ module Dependabot | |
| 60 61 | 
             
                    end
         | 
| 61 62 |  | 
| 62 63 | 
             
                    def updated_pyproject_content
         | 
| 63 | 
            -
                      dependencies | 
| 64 | 
            -
                        select { |dep| requirement_changed?(pyproject, dep) } | 
| 65 | 
            -
                        reduce(pyproject.content.dup) do |content, dep|
         | 
| 64 | 
            +
                      dependencies
         | 
| 65 | 
            +
                        .select { |dep| requirement_changed?(pyproject, dep) }
         | 
| 66 | 
            +
                        .reduce(pyproject.content.dup) do |content, dep|
         | 
| 66 67 | 
             
                          updated_requirement =
         | 
| 67 | 
            -
                            dep.requirements.find { |r| r[:file] == pyproject.name } | 
| 68 | 
            -
             | 
| 68 | 
            +
                            dep.requirements.find { |r| r[:file] == pyproject.name }
         | 
| 69 | 
            +
                               .fetch(:requirement)
         | 
| 69 70 |  | 
| 70 71 | 
             
                          old_req =
         | 
| 71 | 
            -
                            dep.previous_requirements | 
| 72 | 
            -
             | 
| 73 | 
            -
             | 
| 72 | 
            +
                            dep.previous_requirements
         | 
| 73 | 
            +
                               .find { |r| r[:file] == pyproject.name }
         | 
| 74 | 
            +
                               .fetch(:requirement)
         | 
| 74 75 |  | 
| 75 76 | 
             
                          declaration_regex = declaration_regex(dep)
         | 
| 76 77 | 
             
                          updated_content = if content.match?(declaration_regex)
         | 
| @@ -122,9 +123,9 @@ module Dependabot | |
| 122 123 | 
             
                    end
         | 
| 123 124 |  | 
| 124 125 | 
             
                    def freeze_other_dependencies(pyproject_content)
         | 
| 125 | 
            -
                      PyprojectPreparer | 
| 126 | 
            -
                        new(pyproject_content: pyproject_content, lockfile: lockfile) | 
| 127 | 
            -
                        freeze_top_level_dependencies_except(dependencies)
         | 
| 126 | 
            +
                      PyprojectPreparer
         | 
| 127 | 
            +
                        .new(pyproject_content: pyproject_content, lockfile: lockfile)
         | 
| 128 | 
            +
                        .freeze_top_level_dependencies_except(dependencies)
         | 
| 128 129 | 
             
                    end
         | 
| 129 130 |  | 
| 130 131 | 
             
                    def freeze_dependencies_being_updated(pyproject_content)
         | 
| @@ -143,9 +144,9 @@ module Dependabot | |
| 143 144 | 
             
                    end
         | 
| 144 145 |  | 
| 145 146 | 
             
                    def update_python_requirement(pyproject_content)
         | 
| 146 | 
            -
                      PyprojectPreparer | 
| 147 | 
            -
                        new(pyproject_content: pyproject_content) | 
| 148 | 
            -
                        update_python_requirement(language_version_manager.python_version)
         | 
| 147 | 
            +
                      PyprojectPreparer
         | 
| 148 | 
            +
                        .new(pyproject_content: pyproject_content)
         | 
| 149 | 
            +
                        .update_python_requirement(language_version_manager.python_version)
         | 
| 149 150 | 
             
                    end
         | 
| 150 151 |  | 
| 151 152 | 
             
                    def lock_declaration_to_new_version!(poetry_object, dep)
         | 
| @@ -170,9 +171,9 @@ module Dependabot | |
| 170 171 | 
             
                    end
         | 
| 171 172 |  | 
| 172 173 | 
             
                    def sanitize(pyproject_content)
         | 
| 173 | 
            -
                      PyprojectPreparer | 
| 174 | 
            -
                        new(pyproject_content: pyproject_content) | 
| 175 | 
            -
                        sanitize
         | 
| 174 | 
            +
                      PyprojectPreparer
         | 
| 175 | 
            +
                        .new(pyproject_content: pyproject_content)
         | 
| 176 | 
            +
                        .sanitize
         | 
| 176 177 | 
             
                    end
         | 
| 177 178 |  | 
| 178 179 | 
             
                    def updated_lockfile_content_for(pyproject_content)
         | 
| @@ -221,9 +222,9 @@ module Dependabot | |
| 221 222 | 
             
                    end
         | 
| 222 223 |  | 
| 223 224 | 
             
                    def add_auth_env_vars
         | 
| 224 | 
            -
                      Python::FileUpdater::PyprojectPreparer | 
| 225 | 
            -
                        new(pyproject_content: pyproject.content) | 
| 226 | 
            -
                        add_auth_env_vars(credentials)
         | 
| 225 | 
            +
                      Python::FileUpdater::PyprojectPreparer
         | 
| 226 | 
            +
                        .new(pyproject_content: pyproject.content)
         | 
| 227 | 
            +
                        .add_auth_env_vars(credentials)
         | 
| 227 228 | 
             
                    end
         | 
| 228 229 |  | 
| 229 230 | 
             
                    def pyproject_hash_for(pyproject_content)
         | 
| @@ -1,3 +1,4 @@ | |
| 1 | 
            +
            # typed: false
         | 
| 1 2 | 
             
            # frozen_string_literal: true
         | 
| 2 3 |  | 
| 3 4 | 
             
            require "toml-rb"
         | 
| @@ -49,9 +50,9 @@ module Dependabot | |
| 49 50 |  | 
| 50 51 | 
             
                    def sanitize
         | 
| 51 52 | 
             
                      # {{ name }} syntax not allowed
         | 
| 52 | 
            -
                      pyproject_content | 
| 53 | 
            -
                        gsub(/\{\{.*?\}\}/, "something") | 
| 54 | 
            -
                        gsub('#{', "{")
         | 
| 53 | 
            +
                      pyproject_content
         | 
| 54 | 
            +
                        .gsub(/\{\{.*?\}\}/, "something")
         | 
| 55 | 
            +
                        .gsub('#{', "{")
         | 
| 55 56 | 
             
                    end
         | 
| 56 57 |  | 
| 57 58 | 
             
                    # rubocop:disable Metrics/PerceivedComplexity
         | 
| @@ -103,8 +104,8 @@ module Dependabot | |
| 103 104 | 
             
                    attr_reader :pyproject_content, :lockfile
         | 
| 104 105 |  | 
| 105 106 | 
             
                    def locked_details(dep_name)
         | 
| 106 | 
            -
                      parsed_lockfile.fetch("package") | 
| 107 | 
            -
             | 
| 107 | 
            +
                      parsed_lockfile.fetch("package")
         | 
| 108 | 
            +
                                     .find { |d| d["name"] == normalise(dep_name) }
         | 
| 108 109 | 
             
                    end
         | 
| 109 110 |  | 
| 110 111 | 
             
                    def normalise(name)
         | 
| @@ -1,3 +1,4 @@ | |
| 1 | 
            +
            # typed: false
         | 
| 1 2 | 
             
            # frozen_string_literal: true
         | 
| 2 3 |  | 
| 3 4 | 
             
            require "dependabot/dependency"
         | 
| @@ -51,8 +52,8 @@ module Dependabot | |
| 51 52 |  | 
| 52 53 | 
             
                      if add_space_after_operators?
         | 
| 53 54 | 
             
                        new_req_string =
         | 
| 54 | 
            -
                          new_req_string | 
| 55 | 
            -
                          gsub(/(#{RequirementParser::COMPARISON})\s*(?=\d)/o, '\1 ')
         | 
| 55 | 
            +
                          new_req_string
         | 
| 56 | 
            +
                          .gsub(/(#{RequirementParser::COMPARISON})\s*(?=\d)/o, '\1 ')
         | 
| 56 57 | 
             
                      end
         | 
| 57 58 |  | 
| 58 59 | 
             
                      new_req_string
         | 
| @@ -62,11 +63,11 @@ module Dependabot | |
| 62 63 | 
             
                      old_req = old_requirement
         | 
| 63 64 | 
             
                      updated_string =
         | 
| 64 65 | 
             
                        if old_req
         | 
| 65 | 
            -
                          original_dependency_declaration_string(old_req) | 
| 66 | 
            -
                            sub(RequirementParser::REQUIREMENTS, updated_requirement_string)
         | 
| 66 | 
            +
                          original_dependency_declaration_string(old_req)
         | 
| 67 | 
            +
                            .sub(RequirementParser::REQUIREMENTS, updated_requirement_string)
         | 
| 67 68 | 
             
                        else
         | 
| 68 | 
            -
                          original_dependency_declaration_string(old_req) | 
| 69 | 
            -
                            sub(RequirementParser::NAME_WITH_EXTRAS) do |nm|
         | 
| 69 | 
            +
                          original_dependency_declaration_string(old_req)
         | 
| 70 | 
            +
                            .sub(RequirementParser::NAME_WITH_EXTRAS) do |nm|
         | 
| 70 71 | 
             
                              nm + updated_requirement_string
         | 
| 71 72 | 
             
                            end
         | 
| 72 73 | 
             
                        end
         | 
| @@ -84,15 +85,15 @@ module Dependabot | |
| 84 85 | 
             
                    end
         | 
| 85 86 |  | 
| 86 87 | 
             
                    def add_space_after_commas?
         | 
| 87 | 
            -
                      original_dependency_declaration_string(old_requirement) | 
| 88 | 
            -
                        match(RequirementParser::REQUIREMENTS) | 
| 89 | 
            -
                        to_s.include?(", ")
         | 
| 88 | 
            +
                      original_dependency_declaration_string(old_requirement)
         | 
| 89 | 
            +
                        .match(RequirementParser::REQUIREMENTS)
         | 
| 90 | 
            +
                        .to_s.include?(", ")
         | 
| 90 91 | 
             
                    end
         | 
| 91 92 |  | 
| 92 93 | 
             
                    def add_space_after_operators?
         | 
| 93 | 
            -
                      original_dependency_declaration_string(old_requirement) | 
| 94 | 
            -
                        match(RequirementParser::REQUIREMENTS) | 
| 95 | 
            -
                        to_s.match?(/#{RequirementParser::COMPARISON}\s+\d/o)
         | 
| 94 | 
            +
                      original_dependency_declaration_string(old_requirement)
         | 
| 95 | 
            +
                        .match(RequirementParser::REQUIREMENTS)
         | 
| 96 | 
            +
                        .to_s.match?(/#{RequirementParser::COMPARISON}\s+\d/o)
         | 
| 96 97 | 
             
                    end
         | 
| 97 98 |  | 
| 98 99 | 
             
                    def original_declaration_replacement_regex
         | 
| @@ -102,16 +103,16 @@ module Dependabot | |
| 102 103 | 
             
                    end
         | 
| 103 104 |  | 
| 104 105 | 
             
                    def requirement_includes_hashes?(requirement)
         | 
| 105 | 
            -
                      original_dependency_declaration_string(requirement) | 
| 106 | 
            -
                        match?(RequirementParser::HASHES)
         | 
| 106 | 
            +
                      original_dependency_declaration_string(requirement)
         | 
| 107 | 
            +
                        .match?(RequirementParser::HASHES)
         | 
| 107 108 | 
             
                    end
         | 
| 108 109 |  | 
| 109 110 | 
             
                    def hash_algorithm(requirement)
         | 
| 110 111 | 
             
                      return unless requirement_includes_hashes?(requirement)
         | 
| 111 112 |  | 
| 112 | 
            -
                      original_dependency_declaration_string(requirement) | 
| 113 | 
            -
                        match(RequirementParser::HASHES) | 
| 114 | 
            -
                        named_captures.fetch("algorithm")
         | 
| 113 | 
            +
                      original_dependency_declaration_string(requirement)
         | 
| 114 | 
            +
                        .match(RequirementParser::HASHES)
         | 
| 115 | 
            +
                        .named_captures.fetch("algorithm")
         | 
| 115 116 | 
             
                    end
         | 
| 116 117 |  | 
| 117 118 | 
             
                    def hash_separator(requirement)
         | 
| @@ -119,15 +120,15 @@ module Dependabot | |
| 119 120 |  | 
| 120 121 | 
             
                      hash_regex = RequirementParser::HASH
         | 
| 121 122 | 
             
                      current_separator =
         | 
| 122 | 
            -
                        original_dependency_declaration_string(requirement) | 
| 123 | 
            -
                        match(/#{hash_regex}((?<separator>\s*\\?\s*?)#{hash_regex})*/) | 
| 124 | 
            -
                        named_captures.fetch("separator")
         | 
| 123 | 
            +
                        original_dependency_declaration_string(requirement)
         | 
| 124 | 
            +
                        .match(/#{hash_regex}((?<separator>\s*\\?\s*?)#{hash_regex})*/)
         | 
| 125 | 
            +
                        .named_captures.fetch("separator")
         | 
| 125 126 |  | 
| 126 127 | 
             
                      default_separator =
         | 
| 127 | 
            -
                        original_dependency_declaration_string(requirement) | 
| 128 | 
            -
                        match(RequirementParser::HASH) | 
| 129 | 
            -
                        pre_match.match(/(?<separator>\s*\\?\s*?)\z/) | 
| 130 | 
            -
                        named_captures.fetch("separator")
         | 
| 128 | 
            +
                        original_dependency_declaration_string(requirement)
         | 
| 129 | 
            +
                        .match(RequirementParser::HASH)
         | 
| 130 | 
            +
                        .pre_match.match(/(?<separator>\s*\\?\s*?)\z/)
         | 
| 131 | 
            +
                        .named_captures.fetch("separator")
         | 
| 131 132 |  | 
| 132 133 | 
             
                      current_separator || default_separator
         | 
| 133 134 | 
             
                    end
         | 
| @@ -151,9 +152,9 @@ module Dependabot | |
| 151 152 | 
             
                        else
         | 
| 152 153 | 
             
                          regex = RequirementParser::INSTALL_REQ_WITH_REQUIREMENT
         | 
| 153 154 | 
             
                          content.scan(regex) { matches << Regexp.last_match }
         | 
| 154 | 
            -
                          matches | 
| 155 | 
            -
                            select { |m| normalise(m[:name]) == dependency_name } | 
| 156 | 
            -
                            find { |m| requirements_match(m[:requirements], old_req) }
         | 
| 155 | 
            +
                          matches
         | 
| 156 | 
            +
                            .select { |m| normalise(m[:name]) == dependency_name }
         | 
| 157 | 
            +
                            .find { |m| requirements_match(m[:requirements], old_req) }
         | 
| 157 158 | 
             
                        end
         | 
| 158 159 |  | 
| 159 160 | 
             
                      raise "Declaration not found for #{dependency_name}!" unless dec
         | 
| @@ -1,3 +1,4 @@ | |
| 1 | 
            +
            # typed: false
         | 
| 1 2 | 
             
            # frozen_string_literal: true
         | 
| 2 3 |  | 
| 3 4 | 
             
            require "dependabot/python/file_updater"
         | 
| @@ -39,8 +40,8 @@ module Dependabot | |
| 39 40 | 
             
                    def install_requires_array
         | 
| 40 41 | 
             
                      @install_requires_array ||=
         | 
| 41 42 | 
             
                        parsed_setup_file.dependencies.filter_map do |dep|
         | 
| 42 | 
            -
                          next unless dep.requirements.first[:groups] | 
| 43 | 
            -
             | 
| 43 | 
            +
                          next unless dep.requirements.first[:groups]
         | 
| 44 | 
            +
                                         .include?("install_requires")
         | 
| 44 45 |  | 
| 45 46 | 
             
                          dep.name + dep.requirements.first[:requirement].to_s
         | 
| 46 47 | 
             
                        end
         | 
| @@ -49,8 +50,8 @@ module Dependabot | |
| 49 50 | 
             
                    def setup_requires_array
         | 
| 50 51 | 
             
                      @setup_requires_array ||=
         | 
| 51 52 | 
             
                        parsed_setup_file.dependencies.filter_map do |dep|
         | 
| 52 | 
            -
                          next unless dep.requirements.first[:groups] | 
| 53 | 
            -
             | 
| 53 | 
            +
                          next unless dep.requirements.first[:groups]
         | 
| 54 | 
            +
                                         .include?("setup_requires")
         | 
| 54 55 |  | 
| 55 56 | 
             
                          dep.name + dep.requirements.first[:requirement].to_s
         | 
| 56 57 | 
             
                        end
         | 
| @@ -1,3 +1,4 @@ | |
| 1 | 
            +
            # typed: false
         | 
| 1 2 | 
             
            # frozen_string_literal: true
         | 
| 2 3 |  | 
| 3 4 | 
             
            require "toml-rb"
         | 
| @@ -49,9 +50,9 @@ module Dependabot | |
| 49 50 | 
             
                  # rubocop:disable Metrics/PerceivedComplexity
         | 
| 50 51 | 
             
                  def resolver_type
         | 
| 51 52 | 
             
                    reqs = dependencies.flat_map(&:requirements)
         | 
| 52 | 
            -
                    changed_reqs = reqs.zip(dependencies.flat_map(&:previous_requirements)) | 
| 53 | 
            -
             | 
| 54 | 
            -
             | 
| 53 | 
            +
                    changed_reqs = reqs.zip(dependencies.flat_map(&:previous_requirements))
         | 
| 54 | 
            +
                                       .reject { |(new_req, old_req)| new_req == old_req }
         | 
| 55 | 
            +
                                       .map(&:first)
         | 
| 55 56 | 
             
                    changed_req_files = changed_reqs.map { |r| r.fetch(:file) }
         | 
| 56 57 |  | 
| 57 58 | 
             
                    # If there are no requirements then this is a sub-dependency. It
         | 
| @@ -1,3 +1,4 @@ | |
| 1 | 
            +
            # typed: false
         | 
| 1 2 | 
             
            # frozen_string_literal: true
         | 
| 2 3 |  | 
| 3 4 | 
             
            require "excon"
         | 
| @@ -156,9 +157,9 @@ module Dependabot | |
| 156 157 |  | 
| 157 158 | 
             
                  def possible_listing_urls
         | 
| 158 159 | 
             
                    credential_urls =
         | 
| 159 | 
            -
                      credentials | 
| 160 | 
            -
                      select { |cred| cred["type"] == "python_index" } | 
| 161 | 
            -
                      map { |c| AuthedUrlBuilder.authed_url(credential: c) }
         | 
| 160 | 
            +
                      credentials
         | 
| 161 | 
            +
                      .select { |cred| cred["type"] == "python_index" }
         | 
| 162 | 
            +
                      .map { |c| AuthedUrlBuilder.authed_url(credential: c) }
         | 
| 162 163 |  | 
| 163 164 | 
             
                    (credential_urls + [MAIN_PYPI_URL]).map do |base_url|
         | 
| 164 165 | 
             
                      base_url.gsub(%r{/$}, "") + "/#{normalised_dependency_name}/json"
         | 
| @@ -1,3 +1,4 @@ | |
| 1 | 
            +
            # typed: false
         | 
| 1 2 | 
             
            # frozen_string_literal: true
         | 
| 2 3 |  | 
| 3 4 | 
             
            require "dependabot/utils"
         | 
| @@ -14,8 +15,8 @@ module Dependabot | |
| 14 15 | 
             
                    "===" => ->(v, r) { v.to_s == r.to_s }
         | 
| 15 16 | 
             
                  )
         | 
| 16 17 |  | 
| 17 | 
            -
                  quoted = OPS.keys.sort_by(&:length).reverse | 
| 18 | 
            -
             | 
| 18 | 
            +
                  quoted = OPS.keys.sort_by(&:length).reverse
         | 
| 19 | 
            +
                              .map { |k| Regexp.quote(k) }.join("|")
         | 
| 19 20 | 
             
                  version_pattern = Python::Version::VERSION_PATTERN
         | 
| 20 21 |  | 
| 21 22 | 
             
                  PATTERN_RAW = "\\s*(#{quoted})?\\s*(#{version_pattern})\\s*".freeze
         | 
| @@ -133,23 +134,23 @@ module Dependabot | |
| 133 134 | 
             
                  def convert_wildcard(req_string)
         | 
| 134 135 | 
             
                    # NOTE: This isn't perfect. It replaces the "!= 1.0.*" case with
         | 
| 135 136 | 
             
                    # "!= 1.0.0". There's no way to model this correctly in Ruby :'(
         | 
| 136 | 
            -
                    quoted_ops = OPS.keys.sort_by(&:length).reverse | 
| 137 | 
            -
             | 
| 138 | 
            -
                    op = req_string.match(/\A\s*(#{quoted_ops})?/) | 
| 139 | 
            -
             | 
| 137 | 
            +
                    quoted_ops = OPS.keys.sort_by(&:length).reverse
         | 
| 138 | 
            +
                                    .map { |k| Regexp.quote(k) }.join("|")
         | 
| 139 | 
            +
                    op = req_string.match(/\A\s*(#{quoted_ops})?/)
         | 
| 140 | 
            +
                                   .captures.first.to_s&.strip
         | 
| 140 141 | 
             
                    exact_op = ["", "=", "==", "==="].include?(op)
         | 
| 141 142 |  | 
| 142 | 
            -
                    req_string.strip | 
| 143 | 
            -
             | 
| 144 | 
            -
             | 
| 145 | 
            -
             | 
| 146 | 
            -
             | 
| 147 | 
            -
             | 
| 148 | 
            -
             | 
| 143 | 
            +
                    req_string.strip
         | 
| 144 | 
            +
                              .split(".")
         | 
| 145 | 
            +
                              .first(req_string.split(".").index { |s| s.include?("*") } + 1)
         | 
| 146 | 
            +
                              .join(".")
         | 
| 147 | 
            +
                              .gsub(/\*(?!$)/, "0")
         | 
| 148 | 
            +
                              .gsub(/\*$/, "0.a")
         | 
| 149 | 
            +
                              .tap { |s| exact_op ? s.gsub!(/^(?<!!)=*/, "~>") : s }
         | 
| 149 150 | 
             
                  end
         | 
| 150 151 | 
             
                end
         | 
| 151 152 | 
             
              end
         | 
| 152 153 | 
             
            end
         | 
| 153 154 |  | 
| 154 | 
            -
            Dependabot::Utils | 
| 155 | 
            -
              register_requirement_class("pip", Dependabot::Python::Requirement)
         | 
| 155 | 
            +
            Dependabot::Utils
         | 
| 156 | 
            +
              .register_requirement_class("pip", Dependabot::Python::Requirement)
         | 
| @@ -1,3 +1,4 @@ | |
| 1 | 
            +
            # typed: false
         | 
| 1 2 | 
             
            # frozen_string_literal: true
         | 
| 2 3 |  | 
| 3 4 | 
             
            require "dependabot/python/update_checker"
         | 
| @@ -60,14 +61,14 @@ module Dependabot | |
| 60 61 | 
             
                      requirements_files.each do |file|
         | 
| 61 62 | 
             
                        if file.content.match?(/^--index-url\s+['"]?([^\s'"]+)['"]?/)
         | 
| 62 63 | 
             
                          urls[:main] =
         | 
| 63 | 
            -
                            file.content.match(/^--index-url\s+['"]?([^\s'"]+)['"]?/) | 
| 64 | 
            -
             | 
| 64 | 
            +
                            file.content.match(/^--index-url\s+['"]?([^\s'"]+)['"]?/)
         | 
| 65 | 
            +
                                .captures.first&.strip
         | 
| 65 66 | 
             
                        end
         | 
| 66 67 | 
             
                        urls[:extra] +=
         | 
| 67 | 
            -
                          file.content | 
| 68 | 
            -
             | 
| 69 | 
            -
             | 
| 70 | 
            -
             | 
| 68 | 
            +
                          file.content
         | 
| 69 | 
            +
                              .scan(/^--extra-index-url\s+['"]?([^\s'"]+)['"]?/)
         | 
| 70 | 
            +
                              .flatten
         | 
| 71 | 
            +
                              .map(&:strip)
         | 
| 71 72 | 
             
                      end
         | 
| 72 73 |  | 
| 73 74 | 
             
                      urls
         | 
| @@ -81,8 +82,8 @@ module Dependabot | |
| 81 82 | 
             
                      content = pip_conf.content
         | 
| 82 83 |  | 
| 83 84 | 
             
                      if content.match?(/^index-url\s*=/x)
         | 
| 84 | 
            -
                        urls[:main] = content.match(/^index-url\s*=\s*(.+)/) | 
| 85 | 
            -
             | 
| 85 | 
            +
                        urls[:main] = content.match(/^index-url\s*=\s*(.+)/)
         | 
| 86 | 
            +
                                             .captures.first
         | 
| 86 87 | 
             
                      end
         | 
| 87 88 | 
             
                      urls[:extra] += content.scan(/^extra-index-url\s*=(.+)/).flatten
         | 
| 88 89 |  | 
| @@ -137,17 +138,17 @@ module Dependabot | |
| 137 138 | 
             
                    def config_variable_index_urls
         | 
| 138 139 | 
             
                      urls = { main: nil, extra: [] }
         | 
| 139 140 |  | 
| 140 | 
            -
                      index_url_creds = credentials | 
| 141 | 
            -
                                        select { |cred| cred["type"] == "python_index" }
         | 
| 141 | 
            +
                      index_url_creds = credentials
         | 
| 142 | 
            +
                                        .select { |cred| cred["type"] == "python_index" }
         | 
| 142 143 |  | 
| 143 144 | 
             
                      if (main_cred = index_url_creds.find { |cred| cred["replaces-base"] })
         | 
| 144 145 | 
             
                        urls[:main] = AuthedUrlBuilder.authed_url(credential: main_cred)
         | 
| 145 146 | 
             
                      end
         | 
| 146 147 |  | 
| 147 148 | 
             
                      urls[:extra] =
         | 
| 148 | 
            -
                        index_url_creds | 
| 149 | 
            -
                        reject { |cred| cred["replaces-base"] } | 
| 150 | 
            -
                        map { |cred| AuthedUrlBuilder.authed_url(credential: cred) }
         | 
| 149 | 
            +
                        index_url_creds
         | 
| 150 | 
            +
                        .reject { |cred| cred["replaces-base"] }
         | 
| 151 | 
            +
                        .map { |cred| AuthedUrlBuilder.authed_url(credential: cred) }
         | 
| 151 152 |  | 
| 152 153 | 
             
                      urls
         | 
| 153 154 | 
             
                    end
         | 
| @@ -161,16 +162,16 @@ module Dependabot | |
| 161 162 | 
             
                        [
         | 
| 162 163 | 
             
                          config_variable_index_urls[:main],
         | 
| 163 164 | 
             
                          *config_variable_index_urls[:extra]
         | 
| 164 | 
            -
                        ] | 
| 165 | 
            -
                        compact | 
| 166 | 
            -
                        map { |u| u.strip.gsub(%r{/*$}, "") + "/" }
         | 
| 167 | 
            -
             | 
| 168 | 
            -
                      regexp = url | 
| 169 | 
            -
                               sub(%r{(?<=://).+@}, "") | 
| 170 | 
            -
                               sub(%r{https?://}, "") | 
| 171 | 
            -
                               split(ENVIRONMENT_VARIABLE_REGEX) | 
| 172 | 
            -
                               map { |part| Regexp.quote(part) } | 
| 173 | 
            -
                               join(".+")
         | 
| 165 | 
            +
                        ]
         | 
| 166 | 
            +
                        .compact
         | 
| 167 | 
            +
                        .map { |u| u.strip.gsub(%r{/*$}, "") + "/" }
         | 
| 168 | 
            +
             | 
| 169 | 
            +
                      regexp = url
         | 
| 170 | 
            +
                               .sub(%r{(?<=://).+@}, "")
         | 
| 171 | 
            +
                               .sub(%r{https?://}, "")
         | 
| 172 | 
            +
                               .split(ENVIRONMENT_VARIABLE_REGEX)
         | 
| 173 | 
            +
                               .map { |part| Regexp.quote(part) }
         | 
| 174 | 
            +
                               .join(".+")
         | 
| 174 175 | 
             
                      authed_url = config_variable_urls.find { |u| u.match?(regexp) }
         | 
| 175 176 | 
             
                      return authed_url if authed_url
         | 
| 176 177 |  | 
| @@ -189,9 +190,9 @@ module Dependabot | |
| 189 190 | 
             
                    end
         | 
| 190 191 |  | 
| 191 192 | 
             
                    def credential_for(url)
         | 
| 192 | 
            -
                      credentials | 
| 193 | 
            -
                        select { |c| c["type"] == "python_index" } | 
| 194 | 
            -
                        find do |c|
         | 
| 193 | 
            +
                      credentials
         | 
| 194 | 
            +
                        .select { |c| c["type"] == "python_index" }
         | 
| 195 | 
            +
                        .find do |c|
         | 
| 195 196 | 
             
                          cred_url = c.fetch("index-url").gsub(%r{/*$}, "") + "/"
         | 
| 196 197 | 
             
                          cred_url.include?(url)
         | 
| 197 198 | 
             
                        end
         | 
| @@ -1,3 +1,4 @@ | |
| 1 | 
            +
            # typed: false
         | 
| 1 2 | 
             
            # frozen_string_literal: true
         | 
| 2 3 |  | 
| 3 4 | 
             
            require "cgi"
         | 
| @@ -102,8 +103,8 @@ module Dependabot | |
| 102 103 | 
             
                    end
         | 
| 103 104 |  | 
| 104 105 | 
             
                    def filter_ignored_versions(versions_array)
         | 
| 105 | 
            -
                      filtered = versions_array | 
| 106 | 
            -
                                 reject { |v| ignore_requirements.any? { |r| r.satisfied_by?(v) } }
         | 
| 106 | 
            +
                      filtered = versions_array
         | 
| 107 | 
            +
                                 .reject { |v| ignore_requirements.any? { |r| r.satisfied_by?(v) } }
         | 
| 107 108 | 
             
                      if @raise_on_ignored && filter_lower_versions(filtered).empty? && filter_lower_versions(versions_array).any?
         | 
| 108 109 | 
             
                        raise Dependabot::AllVersionsIgnored
         | 
| 109 110 | 
             
                      end
         | 
| @@ -122,8 +123,8 @@ module Dependabot | |
| 122 123 | 
             
                        requirement_class.requirements_array(r.fetch(:requirement))
         | 
| 123 124 | 
             
                      end
         | 
| 124 125 |  | 
| 125 | 
            -
                      versions_array | 
| 126 | 
            -
                        select { |v| reqs.all? { |r| r.any? { |o| o.satisfied_by?(v) } } }
         | 
| 126 | 
            +
                      versions_array
         | 
| 127 | 
            +
                        .select { |v| reqs.all? { |r| r.any? { |o| o.satisfied_by?(v) } } }
         | 
| 127 128 | 
             
                    end
         | 
| 128 129 |  | 
| 129 130 | 
             
                    def wants_prerelease?
         | 
| @@ -189,17 +190,17 @@ module Dependabot | |
| 189 190 | 
             
                    # rubocop:enable Metrics/PerceivedComplexity
         | 
| 190 191 |  | 
| 191 192 | 
             
                    def get_version_from_filename(filename)
         | 
| 192 | 
            -
                      filename | 
| 193 | 
            -
                        gsub(/#{name_regex}-/i, "") | 
| 194 | 
            -
                        split(/-|\.tar\.|\.zip|\.whl/) | 
| 195 | 
            -
                        first
         | 
| 193 | 
            +
                      filename
         | 
| 194 | 
            +
                        .gsub(/#{name_regex}-/i, "")
         | 
| 195 | 
            +
                        .split(/-|\.tar\.|\.zip|\.whl/)
         | 
| 196 | 
            +
                        .first
         | 
| 196 197 | 
             
                    end
         | 
| 197 198 |  | 
| 198 199 | 
             
                    def build_python_requirement_from_link(link)
         | 
| 199 | 
            -
                      req_string = Nokogiri::XML(link) | 
| 200 | 
            -
             | 
| 201 | 
            -
                                   attribute("data-requires-python") | 
| 202 | 
            -
                                   content
         | 
| 200 | 
            +
                      req_string = Nokogiri::XML(link)
         | 
| 201 | 
            +
                                           .at_css("a")
         | 
| 202 | 
            +
                                   &.attribute("data-requires-python")
         | 
| 203 | 
            +
                                   &.content
         | 
| 203 204 |  | 
| 204 205 | 
             
                      return unless req_string
         | 
| 205 206 |  | 
| @@ -1,3 +1,4 @@ | |
| 1 | 
            +
            # typed: false
         | 
| 1 2 | 
             
            # frozen_string_literal: true
         | 
| 2 3 |  | 
| 3 4 | 
             
            require "open3"
         | 
| @@ -166,8 +167,8 @@ module Dependabot | |
| 166 167 | 
             
                      end
         | 
| 167 168 |  | 
| 168 169 | 
             
                      if error.message.match?(GIT_DEPENDENCY_UNREACHABLE_REGEX)
         | 
| 169 | 
            -
                        url = error.message.match(GIT_DEPENDENCY_UNREACHABLE_REGEX) | 
| 170 | 
            -
             | 
| 170 | 
            +
                        url = error.message.match(GIT_DEPENDENCY_UNREACHABLE_REGEX)
         | 
| 171 | 
            +
                                   .named_captures.fetch("url")
         | 
| 171 172 | 
             
                        raise GitDependenciesNotReachable, url
         | 
| 172 173 | 
             
                      end
         | 
| 173 174 |  | 
| @@ -259,9 +260,9 @@ module Dependabot | |
| 259 260 | 
             
                    end
         | 
| 260 261 |  | 
| 261 262 | 
             
                    def pip_compile_index_options
         | 
| 262 | 
            -
                      credentials | 
| 263 | 
            -
                        select { |cred| cred["type"] == "python_index" } | 
| 264 | 
            -
                        map do |cred|
         | 
| 263 | 
            +
                      credentials
         | 
| 264 | 
            +
                        .select { |cred| cred["type"] == "python_index" }
         | 
| 265 | 
            +
                        .map do |cred|
         | 
| 265 266 | 
             
                          authed_url = AuthedUrlBuilder.authed_url(credential: cred)
         | 
| 266 267 |  | 
| 267 268 | 
             
                          if cred["replaces-base"]
         | 
| @@ -337,9 +338,9 @@ module Dependabot | |
| 337 338 | 
             
                      return @sanitized_setup_file_content[file.name] if @sanitized_setup_file_content[file.name]
         | 
| 338 339 |  | 
| 339 340 | 
             
                      @sanitized_setup_file_content[file.name] =
         | 
| 340 | 
            -
                        Python::FileUpdater::SetupFileSanitizer | 
| 341 | 
            -
                        new(setup_file: file, setup_cfg: setup_cfg(file)) | 
| 342 | 
            -
                        sanitized_content
         | 
| 341 | 
            +
                        Python::FileUpdater::SetupFileSanitizer
         | 
| 342 | 
            +
                        .new(setup_file: file, setup_cfg: setup_cfg(file))
         | 
| 343 | 
            +
                        .sanitized_content
         | 
| 343 344 | 
             
                    end
         | 
| 344 345 |  | 
| 345 346 | 
             
                    def setup_cfg(file)
         | 
| @@ -373,9 +374,9 @@ module Dependabot | |
| 373 374 |  | 
| 374 375 | 
             
                    def filenames_to_compile
         | 
| 375 376 | 
             
                      files_from_reqs =
         | 
| 376 | 
            -
                        dependency.requirements | 
| 377 | 
            -
             | 
| 378 | 
            -
             | 
| 377 | 
            +
                        dependency.requirements
         | 
| 378 | 
            +
                                  .map { |r| r[:file] }
         | 
| 379 | 
            +
                                  .select { |fn| fn.end_with?(".in") }
         | 
| 379 380 |  | 
| 380 381 | 
             
                      files_from_compiled_files =
         | 
| 381 382 | 
             
                        pip_compile_files.map(&:name).select do |fn|
         | 
| @@ -390,12 +391,12 @@ module Dependabot | |
| 390 391 |  | 
| 391 392 | 
             
                    def compiled_file_for_filename(filename)
         | 
| 392 393 | 
             
                      compiled_file =
         | 
| 393 | 
            -
                        compiled_files | 
| 394 | 
            -
                        find { |f| f.content.match?(output_file_regex(filename)) }
         | 
| 394 | 
            +
                        compiled_files
         | 
| 395 | 
            +
                        .find { |f| f.content.match?(output_file_regex(filename)) }
         | 
| 395 396 |  | 
| 396 397 | 
             
                      compiled_file ||=
         | 
| 397 | 
            -
                        compiled_files | 
| 398 | 
            -
                        find { |f| f.name == filename.gsub(/\.in$/, ".txt") }
         | 
| 398 | 
            +
                        compiled_files
         | 
| 399 | 
            +
                        .find { |f| f.name == filename.gsub(/\.in$/, ".txt") }
         | 
| 399 400 |  | 
| 400 401 | 
             
                      compiled_file
         | 
| 401 402 | 
             
                    end
         | 
| @@ -421,8 +422,8 @@ module Dependabot | |
| 421 422 |  | 
| 422 423 | 
             
                      while (remaining_filenames = filenames - ordered_filenames).any?
         | 
| 423 424 | 
             
                        ordered_filenames +=
         | 
| 424 | 
            -
                          remaining_filenames | 
| 425 | 
            -
                          reject do |fn|
         | 
| 425 | 
            +
                          remaining_filenames
         | 
| 426 | 
            +
                          .reject do |fn|
         | 
| 426 427 | 
             
                            unupdated_reqs = requirement_map[fn] - ordered_filenames
         | 
| 427 428 | 
             
                            unupdated_reqs.intersect?(filenames)
         | 
| 428 429 | 
             
                          end
         | 
| @@ -1,3 +1,4 @@ | |
| 1 | 
            +
            # typed: false
         | 
| 1 2 | 
             
            # frozen_string_literal: true
         | 
| 2 3 |  | 
| 3 4 | 
             
            require "dependabot/python/language_version_manager"
         | 
| @@ -25,13 +26,13 @@ module Dependabot | |
| 25 26 | 
             
                    end
         | 
| 26 27 |  | 
| 27 28 | 
             
                    def latest_resolvable_version_with_no_unlock
         | 
| 28 | 
            -
                      latest_version_finder | 
| 29 | 
            -
                        latest_version_with_no_unlock(python_version: language_version_manager.python_version)
         | 
| 29 | 
            +
                      latest_version_finder
         | 
| 30 | 
            +
                        .latest_version_with_no_unlock(python_version: language_version_manager.python_version)
         | 
| 30 31 | 
             
                    end
         | 
| 31 32 |  | 
| 32 33 | 
             
                    def lowest_resolvable_security_fix_version
         | 
| 33 | 
            -
                      latest_version_finder | 
| 34 | 
            -
                        lowest_security_fix_version(python_version: language_version_manager.python_version)
         | 
| 34 | 
            +
                      latest_version_finder
         | 
| 35 | 
            +
                        .lowest_security_fix_version(python_version: language_version_manager.python_version)
         | 
| 35 36 | 
             
                    end
         | 
| 36 37 |  | 
| 37 38 | 
             
                    private
         |