dependabot-python 0.226.0 → 0.227.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/helpers/requirements.txt +3 -3
- data/lib/dependabot/python/file_fetcher.rb +1 -7
- data/lib/dependabot/python/file_parser/pyproject_files_parser.rb +1 -13
- data/lib/dependabot/python/file_parser/subdependency_type_parser.rb +34 -0
- data/lib/dependabot/python/file_parser.rb +0 -4
- data/lib/dependabot/python/file_updater/pip_compile_file_updater.rb +0 -1
- data/lib/dependabot/python/file_updater/poetry_file_updater.rb +14 -22
- data/lib/dependabot/python/file_updater.rb +1 -5
- data/lib/dependabot/python/language_version_manager.rb +23 -41
- data/lib/dependabot/python/update_checker/pip_compile_version_resolver.rb +2 -8
- data/lib/dependabot/python/update_checker/pipenv_version_resolver.rb +0 -1
- data/lib/dependabot/python/update_checker/poetry_version_resolver.rb +20 -42
- data/lib/dependabot/python/update_checker.rb +2 -6
- metadata +8 -8
- data/lib/dependabot/python/python_versions.rb +0 -34
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: eb1b6edd3b3d295491ad39866fa4a7d480f9322bd60a6a05e2d9a8e7eb3c9462
         | 
| 4 | 
            +
              data.tar.gz: 3b6397f0af03444908c3b87cc6dfbc173b38f0e5ae54bc5528c6588ea3e4655a
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 295996b49310faa8aa04502f057963a0a3e21289a800be24780fcdc38c4533d0496e88a4b9a0b6722d526e707ee51cadb30a91916a882db4fb95aa8f8f2d9ebd
         | 
| 7 | 
            +
              data.tar.gz: 71b07d3ed46fe06aeecce18cf2dc42da67143be4953e9b45e051cad4e57f84332fda400b071139695847a1e7eaf8ee4c4fc6da50a03dfc9d00a81979e0ffc10c
         | 
    
        data/helpers/requirements.txt
    CHANGED
    
    | @@ -1,9 +1,9 @@ | |
| 1 | 
            -
            pip | 
| 2 | 
            -
            pip-tools | 
| 1 | 
            +
            pip==23.2.0
         | 
| 2 | 
            +
            pip-tools==7.2.0
         | 
| 3 3 | 
             
            hashin==0.17.0
         | 
| 4 4 | 
             
            pipenv==2022.4.8
         | 
| 5 5 | 
             
            pipfile==0.0.2
         | 
| 6 | 
            -
            poetry | 
| 6 | 
            +
            poetry==1.5.1
         | 
| 7 7 |  | 
| 8 8 | 
             
            # Some dependencies will only install if Cython is present
         | 
| 9 9 | 
             
            Cython==3.0.0
         | 
| @@ -91,7 +91,7 @@ module Dependabot | |
| 91 91 | 
             
                  end
         | 
| 92 92 |  | 
| 93 93 | 
             
                  def pyproject_files
         | 
| 94 | 
            -
                    [pyproject,  | 
| 94 | 
            +
                    [pyproject, poetry_lock, pdm_lock].compact
         | 
| 95 95 | 
             
                  end
         | 
| 96 96 |  | 
| 97 97 | 
             
                  def requirement_files
         | 
| @@ -166,12 +166,6 @@ module Dependabot | |
| 166 166 | 
             
                    @pyproject = fetch_file_if_present("pyproject.toml")
         | 
| 167 167 | 
             
                  end
         | 
| 168 168 |  | 
| 169 | 
            -
                  def pyproject_lock
         | 
| 170 | 
            -
                    return @pyproject_lock if defined?(@pyproject_lock)
         | 
| 171 | 
            -
             | 
| 172 | 
            -
                    @pyproject_lock = fetch_file_if_present("pyproject.lock")
         | 
| 173 | 
            -
                  end
         | 
| 174 | 
            -
             | 
| 175 169 | 
             
                  def poetry_lock
         | 
| 176 170 | 
             
                    return @poetry_lock if defined?(@poetry_lock)
         | 
| 177 171 |  | 
| @@ -194,12 +194,6 @@ module Dependabot | |
| 194 194 | 
             
                      raise Dependabot::DependencyFileNotParseable, pyproject.path
         | 
| 195 195 | 
             
                    end
         | 
| 196 196 |  | 
| 197 | 
            -
                    def parsed_pyproject_lock
         | 
| 198 | 
            -
                      @parsed_pyproject_lock ||= TomlRB.parse(pyproject_lock.content)
         | 
| 199 | 
            -
                    rescue TomlRB::ParseError, TomlRB::ValueOverwriteError
         | 
| 200 | 
            -
                      raise Dependabot::DependencyFileNotParseable, pyproject_lock.path
         | 
| 201 | 
            -
                    end
         | 
| 202 | 
            -
             | 
| 203 197 | 
             
                    def parsed_poetry_lock
         | 
| 204 198 | 
             
                      @parsed_poetry_lock ||= TomlRB.parse(poetry_lock.content)
         | 
| 205 199 | 
             
                    rescue TomlRB::ParseError, TomlRB::ValueOverwriteError
         | 
| @@ -212,7 +206,7 @@ module Dependabot | |
| 212 206 | 
             
                    end
         | 
| 213 207 |  | 
| 214 208 | 
             
                    def lockfile
         | 
| 215 | 
            -
                      poetry_lock | 
| 209 | 
            +
                      poetry_lock
         | 
| 216 210 | 
             
                    end
         | 
| 217 211 |  | 
| 218 212 | 
             
                    def parsed_pep621_dependencies
         | 
| @@ -235,12 +229,6 @@ module Dependabot | |
| 235 229 |  | 
| 236 230 | 
             
                    def parsed_lockfile
         | 
| 237 231 | 
             
                      return parsed_poetry_lock if poetry_lock
         | 
| 238 | 
            -
                      return parsed_pyproject_lock if pyproject_lock
         | 
| 239 | 
            -
                    end
         | 
| 240 | 
            -
             | 
| 241 | 
            -
                    def pyproject_lock
         | 
| 242 | 
            -
                      @pyproject_lock ||=
         | 
| 243 | 
            -
                        dependency_files.find { |f| f.name == "pyproject.lock" }
         | 
| 244 232 | 
             
                    end
         | 
| 245 233 |  | 
| 246 234 | 
             
                    def poetry_lock
         | 
| @@ -0,0 +1,34 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require "toml-rb"
         | 
| 4 | 
            +
            require "dependabot/python/file_parser"
         | 
| 5 | 
            +
            require "dependabot/python/name_normaliser"
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            module Dependabot
         | 
| 8 | 
            +
              module Python
         | 
| 9 | 
            +
                class FileParser
         | 
| 10 | 
            +
                  class PoetrySubdependencyTypeParser
         | 
| 11 | 
            +
                    def initialize(lockfile:)
         | 
| 12 | 
            +
                      @lockfile = lockfile
         | 
| 13 | 
            +
                    end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                    def subdep_type(dep)
         | 
| 16 | 
            +
                      category =
         | 
| 17 | 
            +
                        TomlRB.parse(lockfile.content).fetch("package", []).
         | 
| 18 | 
            +
                        find { |dets| normalise(dets.fetch("name")) == dep.name }.
         | 
| 19 | 
            +
                        fetch("category")
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                      category == "dev" ? "dev-dependencies" : "dependencies"
         | 
| 22 | 
            +
                    end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                    private
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                    attr_reader :lockfile
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                    def normalise(name)
         | 
| 29 | 
            +
                      NameNormaliser.normalise(name)
         | 
| 30 | 
            +
                    end
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
            end
         | 
| @@ -208,10 +208,6 @@ module Dependabot | |
| 208 208 | 
             
                    @pyproject ||= get_original_file("pyproject.toml")
         | 
| 209 209 | 
             
                  end
         | 
| 210 210 |  | 
| 211 | 
            -
                  def pyproject_lock
         | 
| 212 | 
            -
                    @pyproject_lock ||= get_original_file("pyproject.lock")
         | 
| 213 | 
            -
                  end
         | 
| 214 | 
            -
             | 
| 215 211 | 
             
                  def poetry_lock
         | 
| 216 212 | 
             
                    @poetry_lock ||= get_original_file("poetry.lock")
         | 
| 217 213 | 
             
                  end
         | 
| @@ -9,7 +9,6 @@ require "dependabot/python/file_updater" | |
| 9 9 | 
             
            require "dependabot/shared_helpers"
         | 
| 10 10 | 
             
            require "dependabot/python/language_version_manager"
         | 
| 11 11 | 
             
            require "dependabot/python/native_helpers"
         | 
| 12 | 
            -
            require "dependabot/python/python_versions"
         | 
| 13 12 | 
             
            require "dependabot/python/name_normaliser"
         | 
| 14 13 | 
             
            require "dependabot/python/authed_url_builder"
         | 
| 15 14 |  | 
| @@ -7,8 +7,8 @@ require "dependabot/shared_helpers" | |
| 7 7 | 
             
            require "dependabot/python/language_version_manager"
         | 
| 8 8 | 
             
            require "dependabot/python/version"
         | 
| 9 9 | 
             
            require "dependabot/python/requirement"
         | 
| 10 | 
            -
            require "dependabot/python/python_versions"
         | 
| 11 10 | 
             
            require "dependabot/python/file_parser/python_requirement_parser"
         | 
| 11 | 
            +
            require "dependabot/python/file_parser/subdependency_type_parser"
         | 
| 12 12 | 
             
            require "dependabot/python/file_updater"
         | 
| 13 13 | 
             
            require "dependabot/python/native_helpers"
         | 
| 14 14 | 
             
            require "dependabot/python/name_normaliser"
         | 
| @@ -157,17 +157,10 @@ module Dependabot | |
| 157 157 | 
             
                    end
         | 
| 158 158 |  | 
| 159 159 | 
             
                    def create_declaration_at_new_version!(poetry_object, dep)
         | 
| 160 | 
            -
                       | 
| 161 | 
            -
                      poetry_object[subdep_type][dependency.name] = dep.version
         | 
| 162 | 
            -
                    end
         | 
| 163 | 
            -
             | 
| 164 | 
            -
                    def subdep_type
         | 
| 165 | 
            -
                      category =
         | 
| 166 | 
            -
                        TomlRB.parse(lockfile.content).fetch("package", []).
         | 
| 167 | 
            -
                        find { |dets| normalise(dets.fetch("name")) == dependency.name }.
         | 
| 168 | 
            -
                        fetch("category")
         | 
| 160 | 
            +
                      subdep_type = subdependency_type_parser.subdep_type(dep)
         | 
| 169 161 |  | 
| 170 | 
            -
                       | 
| 162 | 
            +
                      poetry_object[subdep_type] ||= {}
         | 
| 163 | 
            +
                      poetry_object[subdep_type][dep.name] = dep.version
         | 
| 171 164 | 
             
                    end
         | 
| 172 165 |  | 
| 173 166 | 
             
                    def sanitize(pyproject_content)
         | 
| @@ -185,15 +178,11 @@ module Dependabot | |
| 185 178 | 
             
                          language_version_manager.install_required_python
         | 
| 186 179 |  | 
| 187 180 | 
             
                          # use system git instead of the pure Python dulwich
         | 
| 188 | 
            -
                           | 
| 189 | 
            -
                            run_poetry_command("pyenv exec poetry config experimental.system-git-client true")
         | 
| 190 | 
            -
                          end
         | 
| 181 | 
            +
                          run_poetry_command("pyenv exec poetry config experimental.system-git-client true")
         | 
| 191 182 |  | 
| 192 183 | 
             
                          run_poetry_update_command
         | 
| 193 184 |  | 
| 194 | 
            -
                           | 
| 195 | 
            -
             | 
| 196 | 
            -
                          File.read("pyproject.lock")
         | 
| 185 | 
            +
                          File.read("poetry.lock")
         | 
| 197 186 | 
             
                        end
         | 
| 198 187 | 
             
                      end
         | 
| 199 188 | 
             
                    end
         | 
| @@ -302,6 +291,13 @@ module Dependabot | |
| 302 291 | 
             
                        )
         | 
| 303 292 | 
             
                    end
         | 
| 304 293 |  | 
| 294 | 
            +
                    def subdependency_type_parser
         | 
| 295 | 
            +
                      @subdependency_type_parser ||=
         | 
| 296 | 
            +
                        FileParser::PoetrySubdependencyTypeParser.new(
         | 
| 297 | 
            +
                          lockfile: lockfile
         | 
| 298 | 
            +
                        )
         | 
| 299 | 
            +
                    end
         | 
| 300 | 
            +
             | 
| 305 301 | 
             
                    def language_version_manager
         | 
| 306 302 | 
             
                      @language_version_manager ||=
         | 
| 307 303 | 
             
                        LanguageVersionManager.new(
         | 
| @@ -315,17 +311,13 @@ module Dependabot | |
| 315 311 | 
             
                    end
         | 
| 316 312 |  | 
| 317 313 | 
             
                    def lockfile
         | 
| 318 | 
            -
                      @lockfile ||=  | 
| 314 | 
            +
                      @lockfile ||= poetry_lock
         | 
| 319 315 | 
             
                    end
         | 
| 320 316 |  | 
| 321 317 | 
             
                    def python_helper_path
         | 
| 322 318 | 
             
                      NativeHelpers.python_helper_path
         | 
| 323 319 | 
             
                    end
         | 
| 324 320 |  | 
| 325 | 
            -
                    def pyproject_lock
         | 
| 326 | 
            -
                      dependency_files.find { |f| f.name == "pyproject.lock" }
         | 
| 327 | 
            -
                    end
         | 
| 328 | 
            -
             | 
| 329 321 | 
             
                    def poetry_lock
         | 
| 330 322 | 
             
                      dependency_files.find { |f| f.name == "poetry.lock" }
         | 
| 331 323 | 
             
                    end
         | 
| @@ -77,7 +77,7 @@ module Dependabot | |
| 77 77 |  | 
| 78 78 | 
             
                  def subdependency_resolver
         | 
| 79 79 | 
             
                    return :pipfile if pipfile_lock
         | 
| 80 | 
            -
                    return :poetry if poetry_lock | 
| 80 | 
            +
                    return :poetry if poetry_lock
         | 
| 81 81 | 
             
                    return :pip_compile if pip_compile_files.any?
         | 
| 82 82 |  | 
| 83 83 | 
             
                    raise "Claimed to be a sub-dependency, but no lockfile exists!"
         | 
| @@ -144,10 +144,6 @@ module Dependabot | |
| 144 144 | 
             
                    @pyproject ||= get_original_file("pyproject.toml")
         | 
| 145 145 | 
             
                  end
         | 
| 146 146 |  | 
| 147 | 
            -
                  def pyproject_lock
         | 
| 148 | 
            -
                    @pyproject_lock ||= get_original_file("pyproject.lock")
         | 
| 149 | 
            -
                  end
         | 
| 150 | 
            -
             | 
| 151 147 | 
             
                  def poetry_lock
         | 
| 152 148 | 
             
                    @poetry_lock ||= get_original_file("poetry.lock")
         | 
| 153 149 | 
             
                  end
         | 
| @@ -6,6 +6,14 @@ require "dependabot/python/version" | |
| 6 6 | 
             
            module Dependabot
         | 
| 7 7 | 
             
              module Python
         | 
| 8 8 | 
             
                class LanguageVersionManager
         | 
| 9 | 
            +
                  # This list must match the versions specified at the top of `python/Dockerfile`
         | 
| 10 | 
            +
                  PRE_INSTALLED_PYTHON_VERSIONS = %w(
         | 
| 11 | 
            +
                    3.11.4
         | 
| 12 | 
            +
                    3.10.12
         | 
| 13 | 
            +
                    3.9.17
         | 
| 14 | 
            +
                    3.8.17
         | 
| 15 | 
            +
                  ).freeze
         | 
| 16 | 
            +
             | 
| 9 17 | 
             
                  def initialize(python_requirement_parser:)
         | 
| 10 18 | 
             
                    @python_requirement_parser = python_requirement_parser
         | 
| 11 19 | 
             
                  end
         | 
| @@ -14,22 +22,9 @@ module Dependabot | |
| 14 22 | 
             
                    # The leading space is important in the version check
         | 
| 15 23 | 
             
                    return if SharedHelpers.run_shell_command("pyenv versions").include?(" #{python_major_minor}.")
         | 
| 16 24 |  | 
| 17 | 
            -
                     | 
| 18 | 
            -
                       | 
| 19 | 
            -
             | 
| 20 | 
            -
                      )
         | 
| 21 | 
            -
                      return if SharedHelpers.run_shell_command("pyenv versions").
         | 
| 22 | 
            -
                                include?(" #{python_major_minor}.")
         | 
| 23 | 
            -
                    end
         | 
| 24 | 
            -
             | 
| 25 | 
            -
                    Dependabot.logger.info("Installing required Python #{python_version}.")
         | 
| 26 | 
            -
                    start = Time.now
         | 
| 27 | 
            -
                    SharedHelpers.run_shell_command("pyenv install -s #{python_version}")
         | 
| 28 | 
            -
                    SharedHelpers.run_shell_command("pyenv exec pip install --upgrade pip")
         | 
| 29 | 
            -
                    SharedHelpers.run_shell_command("pyenv exec pip install -r" \
         | 
| 30 | 
            -
                                                    "#{NativeHelpers.python_requirements_path}")
         | 
| 31 | 
            -
                    time_taken = Time.now - start
         | 
| 32 | 
            -
                    Dependabot.logger.info("Installing Python #{python_version} took #{time_taken}s.")
         | 
| 25 | 
            +
                    SharedHelpers.run_shell_command(
         | 
| 26 | 
            +
                      "tar xzf /usr/local/.pyenv/#{python_major_minor}.tar.gz -C /usr/local/.pyenv/"
         | 
| 27 | 
            +
                    )
         | 
| 33 28 | 
             
                  end
         | 
| 34 29 |  | 
| 35 30 | 
             
                  def python_major_minor
         | 
| @@ -58,32 +53,19 @@ module Dependabot | |
| 58 53 | 
             
                  def python_version_from_supported_versions
         | 
| 59 54 | 
             
                    requirement_string = python_requirement_string
         | 
| 60 55 |  | 
| 61 | 
            -
                    #  | 
| 62 | 
            -
                     | 
| 63 | 
            -
             | 
| 64 | 
            -
                    version =
         | 
| 65 | 
            -
                      PythonVersions::SUPPORTED_VERSIONS_TO_ITERATE.
         | 
| 66 | 
            -
                      find { |v| requirement.satisfied_by?(Python::Version.new(v)) }
         | 
| 67 | 
            -
                    return version if version
         | 
| 56 | 
            +
                    # If the requirement string isn't already a range (eg ">3.10"), coerce it to "major.minor.*".
         | 
| 57 | 
            +
                    # The patch version is ignored because a non-matching patch version is unlikely to affect resolution.
         | 
| 58 | 
            +
                    requirement_string = requirement_string.gsub(/\.\d+$/, ".*") if requirement_string.start_with?(/\d/)
         | 
| 68 59 |  | 
| 69 | 
            -
                    #  | 
| 70 | 
            -
                     | 
| 71 | 
            -
                     | 
| 72 | 
            -
                    if  | 
| 73 | 
            -
                      requirement =
         | 
| 74 | 
            -
                        Python::Requirement.new(requirement_string.gsub(/\.\d+$/, ".*"))
         | 
| 75 | 
            -
                      version =
         | 
| 76 | 
            -
                        PythonVersions::SUPPORTED_VERSIONS_TO_ITERATE.
         | 
| 77 | 
            -
                        find { |v| requirement.satisfied_by?(Python::Version.new(v)) }
         | 
| 78 | 
            -
                      return version if version
         | 
| 79 | 
            -
                    end
         | 
| 60 | 
            +
                    # Try to match one of our pre-installed Python versions
         | 
| 61 | 
            +
                    requirement = Python::Requirement.requirements_array(requirement_string).first
         | 
| 62 | 
            +
                    version = PRE_INSTALLED_PYTHON_VERSIONS.find { |v| requirement.satisfied_by?(Python::Version.new(v)) }
         | 
| 63 | 
            +
                    return version if version
         | 
| 80 64 |  | 
| 81 | 
            -
                    # Otherwise we have to raise | 
| 82 | 
            -
                     | 
| 83 | 
            -
             | 
| 84 | 
            -
                          " | 
| 85 | 
            -
                          "following Python versions are supported in Dependabot: " \
         | 
| 86 | 
            -
                          "#{PythonVersions::SUPPORTED_VERSIONS.join(', ')}."
         | 
| 65 | 
            +
                    # Otherwise we have to raise
         | 
| 66 | 
            +
                    msg = "Dependabot detected the following Python requirement for your project: '#{python_requirement_string}'." \
         | 
| 67 | 
            +
                          "\n\nCurrently, the following Python versions are supported in Dependabot: " \
         | 
| 68 | 
            +
                          "#{PRE_INSTALLED_PYTHON_VERSIONS.map { |x| x.gsub(/\.\d+$/, '.*') }.join(', ')}."
         | 
| 87 69 | 
             
                    raise DependencyFileNotResolvable, msg
         | 
| 88 70 | 
             
                  end
         | 
| 89 71 |  | 
| @@ -100,7 +82,7 @@ module Dependabot | |
| 100 82 | 
             
                  end
         | 
| 101 83 |  | 
| 102 84 | 
             
                  def python_version_matching(requirements)
         | 
| 103 | 
            -
                     | 
| 85 | 
            +
                    PRE_INSTALLED_PYTHON_VERSIONS.find do |version_string|
         | 
| 104 86 | 
             
                      version = Python::Version.new(version_string)
         | 
| 105 87 | 
             
                      requirements.all? do |req|
         | 
| 106 88 | 
             
                        next req.any? { |r| r.satisfied_by?(version) } if req.is_a?(Array)
         | 
| @@ -13,7 +13,6 @@ require "dependabot/python/version" | |
| 13 13 | 
             
            require "dependabot/shared_helpers"
         | 
| 14 14 | 
             
            require "dependabot/python/language_version_manager"
         | 
| 15 15 | 
             
            require "dependabot/python/native_helpers"
         | 
| 16 | 
            -
            require "dependabot/python/python_versions"
         | 
| 17 16 | 
             
            require "dependabot/python/name_normaliser"
         | 
| 18 17 | 
             
            require "dependabot/python/authed_url_builder"
         | 
| 19 18 |  | 
| @@ -23,7 +22,6 @@ module Dependabot | |
| 23 22 | 
             
                  # This class does version resolution for pip-compile. Its approach is:
         | 
| 24 23 | 
             
                  # - Unlock the dependency we're checking in the requirements.in file
         | 
| 25 24 | 
             
                  # - Run `pip-compile` and see what the result is
         | 
| 26 | 
            -
                  # rubocop:disable Metrics/ClassLength
         | 
| 27 25 | 
             
                  class PipCompileVersionResolver
         | 
| 28 26 | 
             
                    GIT_DEPENDENCY_UNREACHABLE_REGEX = /git clone --filter=blob:none --quiet (?<url>[^\s]+).* /
         | 
| 29 27 | 
             
                    GIT_REFERENCE_NOT_FOUND_REGEX = /Did not find branch or tag '(?<tag>[^\n"]+)'/m
         | 
| @@ -236,10 +234,6 @@ module Dependabot | |
| 236 234 | 
             
                      )
         | 
| 237 235 | 
             
                    end
         | 
| 238 236 |  | 
| 239 | 
            -
                    def new_resolver_supported?
         | 
| 240 | 
            -
                      language_version_manager.python_version >= Python::Version.new("3.7")
         | 
| 241 | 
            -
                    end
         | 
| 242 | 
            -
             | 
| 243 237 | 
             
                    def pip_compile_options_fingerprint(options)
         | 
| 244 238 | 
             
                      options.sub(
         | 
| 245 239 | 
             
                        /--output-file=\S+/, "--output-file=<output_file>"
         | 
| @@ -253,8 +247,9 @@ module Dependabot | |
| 253 247 | 
             
                    def pip_compile_options(filename)
         | 
| 254 248 | 
             
                      options = @build_isolation ? ["--build-isolation"] : ["--no-build-isolation"]
         | 
| 255 249 | 
             
                      options += pip_compile_index_options
         | 
| 250 | 
            +
                      # TODO: Stop explicitly specifying `allow-unsafe` once it becomes the default:
         | 
| 251 | 
            +
                      # https://github.com/jazzband/pip-tools/issues/989#issuecomment-1661254701
         | 
| 256 252 | 
             
                      options += ["--allow-unsafe"]
         | 
| 257 | 
            -
                      options += ["--resolver backtracking"] if new_resolver_supported?
         | 
| 258 253 |  | 
| 259 254 | 
             
                      if (requirements_file = compiled_file_for_filename(filename))
         | 
| 260 255 | 
             
                        options << "--output-file=#{requirements_file.name}"
         | 
| @@ -502,7 +497,6 @@ module Dependabot | |
| 502 497 | 
             
                      dependency_files.select { |f| f.name.end_with?("setup.cfg") }
         | 
| 503 498 | 
             
                    end
         | 
| 504 499 | 
             
                  end
         | 
| 505 | 
            -
                  # rubocop:enable Metrics/ClassLength
         | 
| 506 500 | 
             
                end
         | 
| 507 501 | 
             
              end
         | 
| 508 502 | 
             
            end
         | 
| @@ -11,7 +11,6 @@ require "dependabot/python/file_parser/python_requirement_parser" | |
| 11 11 | 
             
            require "dependabot/python/file_updater/pipfile_preparer"
         | 
| 12 12 | 
             
            require "dependabot/python/file_updater/setup_file_sanitizer"
         | 
| 13 13 | 
             
            require "dependabot/python/update_checker"
         | 
| 14 | 
            -
            require "dependabot/python/python_versions"
         | 
| 15 14 | 
             
            require "dependabot/python/native_helpers"
         | 
| 16 15 | 
             
            require "dependabot/python/name_normaliser"
         | 
| 17 16 | 
             
            require "dependabot/python/version"
         | 
| @@ -9,12 +9,12 @@ require "dependabot/errors" | |
| 9 9 | 
             
            require "dependabot/shared_helpers"
         | 
| 10 10 | 
             
            require "dependabot/python/file_parser"
         | 
| 11 11 | 
             
            require "dependabot/python/file_parser/python_requirement_parser"
         | 
| 12 | 
            +
            require "dependabot/python/file_parser/subdependency_type_parser"
         | 
| 12 13 | 
             
            require "dependabot/python/file_updater/pyproject_preparer"
         | 
| 13 14 | 
             
            require "dependabot/python/update_checker"
         | 
| 14 15 | 
             
            require "dependabot/python/version"
         | 
| 15 16 | 
             
            require "dependabot/python/requirement"
         | 
| 16 17 | 
             
            require "dependabot/python/native_helpers"
         | 
| 17 | 
            -
            require "dependabot/python/python_versions"
         | 
| 18 18 | 
             
            require "dependabot/python/authed_url_builder"
         | 
| 19 19 | 
             
            require "dependabot/python/name_normaliser"
         | 
| 20 20 |  | 
| @@ -24,30 +24,19 @@ module Dependabot | |
| 24 24 | 
             
                  # This class does version resolution for pyproject.toml files.
         | 
| 25 25 | 
             
                  class PoetryVersionResolver
         | 
| 26 26 | 
             
                    GIT_REFERENCE_NOT_FOUND_REGEX = /
         | 
| 27 | 
            -
                      ( | 
| 28 | 
            -
                      'checkout',
         | 
| 29 | 
            -
                      '(?<tag>.+?)'
         | 
| 30 | 
            -
                      |
         | 
| 31 | 
            -
                      Failed to checkout
         | 
| 27 | 
            +
                      (Failed to checkout
         | 
| 32 28 | 
             
                      (?<tag>.+?)
         | 
| 33 29 | 
             
                      (?<url>.+?).git at '(?<tag>.+?)'
         | 
| 34 30 | 
             
                      |
         | 
| 35 31 | 
             
                      ...Failedtoclone
         | 
| 36 32 | 
             
                      (?<url>.+?).gitat'(?<tag>.+?)',
         | 
| 37 33 | 
             
                      verifyrefexistsonremote)
         | 
| 38 | 
            -
                    /x | 
| 34 | 
            +
                    /x
         | 
| 39 35 | 
             
                    GIT_DEPENDENCY_UNREACHABLE_REGEX = /
         | 
| 40 | 
            -
                      (?:'\['git',
         | 
| 41 | 
            -
                      \s+'clone',
         | 
| 42 | 
            -
                      \s+'--recurse-submodules',
         | 
| 43 | 
            -
                      \s+'(--)?',
         | 
| 44 | 
            -
                      \s+'(?<url>.+?)'.*
         | 
| 45 | 
            -
                      \s+exit\s+status\s+128
         | 
| 46 | 
            -
                      |
         | 
| 47 36 | 
             
                      \s+Failed\sto\sclone
         | 
| 48 37 | 
             
                      \s+(?<url>.+?),
         | 
| 49 | 
            -
                      \s+check\syour\sgit\sconfiguration | 
| 50 | 
            -
                    /mx | 
| 38 | 
            +
                      \s+check\syour\sgit\sconfiguration
         | 
| 39 | 
            +
                    /mx
         | 
| 51 40 |  | 
| 52 41 | 
             
                    attr_reader :dependency, :dependency_files, :credentials
         | 
| 53 42 |  | 
| @@ -74,8 +63,7 @@ module Dependabot | |
| 74 63 | 
             
                                               false
         | 
| 75 64 | 
             
                                             end
         | 
| 76 65 | 
             
                    rescue SharedHelpers::HelperSubprocessFailed => e
         | 
| 77 | 
            -
                      raise unless e.message.include?(" | 
| 78 | 
            -
                                   e.message.include?("version solving failed.")
         | 
| 66 | 
            +
                      raise unless e.message.include?("version solving failed.")
         | 
| 79 67 |  | 
| 80 68 | 
             
                      @resolvable[version] = false
         | 
| 81 69 | 
             
                    end
         | 
| @@ -95,18 +83,12 @@ module Dependabot | |
| 95 83 | 
             
                            language_version_manager.install_required_python
         | 
| 96 84 |  | 
| 97 85 | 
             
                            # use system git instead of the pure Python dulwich
         | 
| 98 | 
            -
                             | 
| 99 | 
            -
                              run_poetry_command("pyenv exec poetry config experimental.system-git-client true")
         | 
| 100 | 
            -
                            end
         | 
| 86 | 
            +
                            run_poetry_command("pyenv exec poetry config experimental.system-git-client true")
         | 
| 101 87 |  | 
| 102 88 | 
             
                            # Shell out to Poetry, which handles everything for us.
         | 
| 103 89 | 
             
                            run_poetry_update_command
         | 
| 104 90 |  | 
| 105 | 
            -
                            updated_lockfile =
         | 
| 106 | 
            -
                              if File.exist?("poetry.lock") then File.read("poetry.lock")
         | 
| 107 | 
            -
                              else
         | 
| 108 | 
            -
                                File.read("pyproject.lock")
         | 
| 109 | 
            -
                              end
         | 
| 91 | 
            +
                            updated_lockfile = File.read("poetry.lock")
         | 
| 110 92 | 
             
                            updated_lockfile = TomlRB.parse(updated_lockfile)
         | 
| 111 93 |  | 
| 112 94 | 
             
                            fetch_version_from_parsed_lockfile(updated_lockfile)
         | 
| @@ -147,7 +129,7 @@ module Dependabot | |
| 147 129 | 
             
                      end
         | 
| 148 130 |  | 
| 149 131 | 
             
                      raise unless error.message.include?("SolverProblemError") ||
         | 
| 150 | 
            -
                                   error.message.include?(" | 
| 132 | 
            +
                                   error.message.include?("not found") ||
         | 
| 151 133 | 
             
                                   error.message.include?("version solving failed.")
         | 
| 152 134 |  | 
| 153 135 | 
             
                      check_original_requirements_resolvable
         | 
| @@ -182,7 +164,7 @@ module Dependabot | |
| 182 164 | 
             
                          @original_reqs_resolvable = true
         | 
| 183 165 | 
             
                        rescue SharedHelpers::HelperSubprocessFailed => e
         | 
| 184 166 | 
             
                          raise unless e.message.include?("SolverProblemError") ||
         | 
| 185 | 
            -
                                       e.message.include?(" | 
| 167 | 
            +
                                       e.message.include?("not found") ||
         | 
| 186 168 | 
             
                                       e.message.include?("version solving failed.")
         | 
| 187 169 |  | 
| 188 170 | 
             
                          msg = clean_error_message(e.message)
         | 
| @@ -278,6 +260,8 @@ module Dependabot | |
| 278 260 |  | 
| 279 261 | 
             
                      # If this is a sub-dependency, add the new requirement
         | 
| 280 262 | 
             
                      unless dependency.requirements.find { |r| r[:file] == pyproject.name }
         | 
| 263 | 
            +
                        subdep_type = subdependency_type_parser.subdep_type(dependency)
         | 
| 264 | 
            +
             | 
| 281 265 | 
             
                        poetry_object[subdep_type] ||= {}
         | 
| 282 266 | 
             
                        poetry_object[subdep_type][dependency.name] = updated_requirement
         | 
| 283 267 | 
             
                      end
         | 
| @@ -297,15 +281,6 @@ module Dependabot | |
| 297 281 | 
             
                      end
         | 
| 298 282 | 
             
                    end
         | 
| 299 283 |  | 
| 300 | 
            -
                    def subdep_type
         | 
| 301 | 
            -
                      category =
         | 
| 302 | 
            -
                        TomlRB.parse(lockfile.content).fetch("package", []).
         | 
| 303 | 
            -
                        find { |dets| normalise(dets.fetch("name")) == dependency.name }.
         | 
| 304 | 
            -
                        fetch("category")
         | 
| 305 | 
            -
             | 
| 306 | 
            -
                      category == "dev" ? "dev-dependencies" : "dependencies"
         | 
| 307 | 
            -
                    end
         | 
| 308 | 
            -
             | 
| 309 284 | 
             
                    def python_requirement_parser
         | 
| 310 285 | 
             
                      @python_requirement_parser ||=
         | 
| 311 286 | 
             
                        FileParser::PythonRequirementParser.new(
         | 
| @@ -313,6 +288,13 @@ module Dependabot | |
| 313 288 | 
             
                        )
         | 
| 314 289 | 
             
                    end
         | 
| 315 290 |  | 
| 291 | 
            +
                    def subdependency_type_parser
         | 
| 292 | 
            +
                      @subdependency_type_parser ||=
         | 
| 293 | 
            +
                        FileParser::PoetrySubdependencyTypeParser.new(
         | 
| 294 | 
            +
                          lockfile: lockfile
         | 
| 295 | 
            +
                        )
         | 
| 296 | 
            +
                    end
         | 
| 297 | 
            +
             | 
| 316 298 | 
             
                    def language_version_manager
         | 
| 317 299 | 
             
                      @language_version_manager ||=
         | 
| 318 300 | 
             
                        LanguageVersionManager.new(
         | 
| @@ -324,16 +306,12 @@ module Dependabot | |
| 324 306 | 
             
                      dependency_files.find { |f| f.name == "pyproject.toml" }
         | 
| 325 307 | 
             
                    end
         | 
| 326 308 |  | 
| 327 | 
            -
                    def pyproject_lock
         | 
| 328 | 
            -
                      dependency_files.find { |f| f.name == "pyproject.lock" }
         | 
| 329 | 
            -
                    end
         | 
| 330 | 
            -
             | 
| 331 309 | 
             
                    def poetry_lock
         | 
| 332 310 | 
             
                      dependency_files.find { |f| f.name == "poetry.lock" }
         | 
| 333 311 | 
             
                    end
         | 
| 334 312 |  | 
| 335 313 | 
             
                    def lockfile
         | 
| 336 | 
            -
                      poetry_lock | 
| 314 | 
            +
                      poetry_lock
         | 
| 337 315 | 
             
                    end
         | 
| 338 316 |  | 
| 339 317 | 
             
                    def run_poetry_command(command, fingerprint: nil)
         | 
| @@ -74,7 +74,7 @@ module Dependabot | |
| 74 74 | 
             
                      requirements: requirements,
         | 
| 75 75 | 
             
                      latest_resolvable_version: preferred_resolvable_version&.to_s,
         | 
| 76 76 | 
             
                      update_strategy: requirements_update_strategy,
         | 
| 77 | 
            -
                      has_lockfile: !(pipfile_lock || poetry_lock | 
| 77 | 
            +
                      has_lockfile: !(pipfile_lock || poetry_lock).nil?
         | 
| 78 78 | 
             
                    ).updated_requirements
         | 
| 79 79 | 
             
                  end
         | 
| 80 80 |  | 
| @@ -143,7 +143,7 @@ module Dependabot | |
| 143 143 |  | 
| 144 144 | 
             
                  def subdependency_resolver
         | 
| 145 145 | 
             
                    return :pipenv if pipfile_lock
         | 
| 146 | 
            -
                    return :poetry if poetry_lock | 
| 146 | 
            +
                    return :poetry if poetry_lock
         | 
| 147 147 | 
             
                    return :pip_compile if pip_compile_files.any?
         | 
| 148 148 |  | 
| 149 149 | 
             
                    raise "Claimed to be a sub-dependency, but no lockfile exists!"
         | 
| @@ -315,10 +315,6 @@ module Dependabot | |
| 315 315 | 
             
                    dependency_files.find { |f| f.name == "pyproject.toml" }
         | 
| 316 316 | 
             
                  end
         | 
| 317 317 |  | 
| 318 | 
            -
                  def pyproject_lock
         | 
| 319 | 
            -
                    dependency_files.find { |f| f.name == "pyproject.lock" }
         | 
| 320 | 
            -
                  end
         | 
| 321 | 
            -
             | 
| 322 318 | 
             
                  def poetry_lock
         | 
| 323 319 | 
             
                    dependency_files.find { |f| f.name == "poetry.lock" }
         | 
| 324 320 | 
             
                  end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: dependabot-python
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.227.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Dependabot
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2023-08- | 
| 11 | 
            +
            date: 2023-08-18 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: dependabot-common
         | 
| @@ -16,14 +16,14 @@ dependencies: | |
| 16 16 | 
             
                requirements:
         | 
| 17 17 | 
             
                - - '='
         | 
| 18 18 | 
             
                  - !ruby/object:Gem::Version
         | 
| 19 | 
            -
                    version: 0. | 
| 19 | 
            +
                    version: 0.227.0
         | 
| 20 20 | 
             
              type: :runtime
         | 
| 21 21 | 
             
              prerelease: false
         | 
| 22 22 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 23 23 | 
             
                requirements:
         | 
| 24 24 | 
             
                - - '='
         | 
| 25 25 | 
             
                  - !ruby/object:Gem::Version
         | 
| 26 | 
            -
                    version: 0. | 
| 26 | 
            +
                    version: 0.227.0
         | 
| 27 27 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 28 28 | 
             
              name: debug
         | 
| 29 29 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -128,14 +128,14 @@ dependencies: | |
| 128 128 | 
             
                requirements:
         | 
| 129 129 | 
             
                - - "~>"
         | 
| 130 130 | 
             
                  - !ruby/object:Gem::Version
         | 
| 131 | 
            -
                    version: 1. | 
| 131 | 
            +
                    version: 1.19.0
         | 
| 132 132 | 
             
              type: :development
         | 
| 133 133 | 
             
              prerelease: false
         | 
| 134 134 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 135 135 | 
             
                requirements:
         | 
| 136 136 | 
             
                - - "~>"
         | 
| 137 137 | 
             
                  - !ruby/object:Gem::Version
         | 
| 138 | 
            -
                    version: 1. | 
| 138 | 
            +
                    version: 1.19.0
         | 
| 139 139 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 140 140 | 
             
              name: stackprof
         | 
| 141 141 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -200,6 +200,7 @@ files: | |
| 200 200 | 
             
            - lib/dependabot/python/file_parser/pyproject_files_parser.rb
         | 
| 201 201 | 
             
            - lib/dependabot/python/file_parser/python_requirement_parser.rb
         | 
| 202 202 | 
             
            - lib/dependabot/python/file_parser/setup_file_parser.rb
         | 
| 203 | 
            +
            - lib/dependabot/python/file_parser/subdependency_type_parser.rb
         | 
| 203 204 | 
             
            - lib/dependabot/python/file_updater.rb
         | 
| 204 205 | 
             
            - lib/dependabot/python/file_updater/pip_compile_file_updater.rb
         | 
| 205 206 | 
             
            - lib/dependabot/python/file_updater/pipfile_file_updater.rb
         | 
| @@ -214,7 +215,6 @@ files: | |
| 214 215 | 
             
            - lib/dependabot/python/metadata_finder.rb
         | 
| 215 216 | 
             
            - lib/dependabot/python/name_normaliser.rb
         | 
| 216 217 | 
             
            - lib/dependabot/python/native_helpers.rb
         | 
| 217 | 
            -
            - lib/dependabot/python/python_versions.rb
         | 
| 218 218 | 
             
            - lib/dependabot/python/requirement.rb
         | 
| 219 219 | 
             
            - lib/dependabot/python/requirement_parser.rb
         | 
| 220 220 | 
             
            - lib/dependabot/python/update_checker.rb
         | 
| @@ -231,7 +231,7 @@ licenses: | |
| 231 231 | 
             
            - Nonstandard
         | 
| 232 232 | 
             
            metadata:
         | 
| 233 233 | 
             
              bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
         | 
| 234 | 
            -
              changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0. | 
| 234 | 
            +
              changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.227.0
         | 
| 235 235 | 
             
            post_install_message: 
         | 
| 236 236 | 
             
            rdoc_options: []
         | 
| 237 237 | 
             
            require_paths:
         | 
| @@ -1,34 +0,0 @@ | |
| 1 | 
            -
            # frozen_string_literal: true
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            module Dependabot
         | 
| 4 | 
            -
              module Python
         | 
| 5 | 
            -
                module PythonVersions
         | 
| 6 | 
            -
                  PRE_INSTALLED_PYTHON_VERSIONS = %w(
         | 
| 7 | 
            -
                    3.11.4
         | 
| 8 | 
            -
                  ).freeze
         | 
| 9 | 
            -
             | 
| 10 | 
            -
                  # Due to an OpenSSL issue we can only install the following versions in
         | 
| 11 | 
            -
                  # the Dependabot container.
         | 
| 12 | 
            -
                  # NOTE: When adding one version, always doublecheck for additional releases: https://www.python.org/downloads/
         | 
| 13 | 
            -
                  #
         | 
| 14 | 
            -
                  # WARNING: 3.9.3 is purposefully omitted as it was recalled: https://www.python.org/downloads/release/python-393/
         | 
| 15 | 
            -
                  SUPPORTED_VERSIONS = %w(
         | 
| 16 | 
            -
                    3.11.4 3.11.3 3.11.2 3.11.1 3.11.0
         | 
| 17 | 
            -
                    3.10.12 3.10.11 3.10.10 3.10.9 3.10.8 3.10.7 3.10.6 3.10.5 3.10.4 3.10.3 3.10.2 3.10.1 3.10.0
         | 
| 18 | 
            -
                    3.9.17 3.9.16 3.9.15 3.9.14 3.9.13 3.9.12 3.9.11 3.9.10 3.9.9 3.9.8 3.9.7 3.9.6 3.9.5 3.9.4 3.9.2 3.9.1 3.9.0
         | 
| 19 | 
            -
                    3.8.17 3.8.15 3.8.14 3.8.13 3.8.12 3.8.11 3.8.10 3.8.9 3.8.8 3.8.7 3.8.6 3.8.5 3.8.4 3.8.3 3.8.2 3.8.1 3.8.0
         | 
| 20 | 
            -
                    3.7.17 3.7.15 3.7.14 3.7.13 3.7.12 3.7.11 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
         | 
| 21 | 
            -
                    3.6.15 3.6.14 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
         | 
| 22 | 
            -
                    3.5.10 3.5.8 3.5.7 3.5.6 3.5.5 3.5.4 3.5.3
         | 
| 23 | 
            -
                  ).freeze
         | 
| 24 | 
            -
             | 
| 25 | 
            -
                  # This list gets iterated through to find a valid version, so we have
         | 
| 26 | 
            -
                  # the pre-installed versions listed first.
         | 
| 27 | 
            -
                  SUPPORTED_VERSIONS_TO_ITERATE =
         | 
| 28 | 
            -
                    [
         | 
| 29 | 
            -
                      *PRE_INSTALLED_PYTHON_VERSIONS,
         | 
| 30 | 
            -
                      *SUPPORTED_VERSIONS
         | 
| 31 | 
            -
                    ].freeze
         | 
| 32 | 
            -
                end
         | 
| 33 | 
            -
              end
         | 
| 34 | 
            -
            end
         |