dependabot-python 0.225.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9d804625d39f5d3fae7776c1963e2f33347a97fb4e9dae189674abb3dd5b3b99
4
- data.tar.gz: 25193d26af70d445a683c82f7a2ea4151f1bd879e2ac35cf55d053dc761ddbac
3
+ metadata.gz: eb1b6edd3b3d295491ad39866fa4a7d480f9322bd60a6a05e2d9a8e7eb3c9462
4
+ data.tar.gz: 3b6397f0af03444908c3b87cc6dfbc173b38f0e5ae54bc5528c6588ea3e4655a
5
5
  SHA512:
6
- metadata.gz: 1cbc7939f48ba24aedc80ce89dd0251ec5573197b2f5e6fe7a859b0192bed3e7009dca46287ebbd39f198d2fb5af4c453d4e84cd425b57175f532260386a9994
7
- data.tar.gz: b46f5e9c0dbe616b337bd03d3621ec4a004a7f6e8ff323fa32595af884906908249f126ad1de23467c8a5b936256a5a3c30146113ecccb404b118c1e9383de17
6
+ metadata.gz: 295996b49310faa8aa04502f057963a0a3e21289a800be24780fcdc38c4533d0496e88a4b9a0b6722d526e707ee51cadb30a91916a882db4fb95aa8f8f2d9ebd
7
+ data.tar.gz: 71b07d3ed46fe06aeecce18cf2dc42da67143be4953e9b45e051cad4e57f84332fda400b071139695847a1e7eaf8ee4c4fc6da50a03dfc9d00a81979e0ffc10c
@@ -1,10 +1,9 @@
1
- pip>=21.3.1,<23.2.0 # Range maintains py36 support TODO: Review python 3.6 support in April 2023 (eol ubuntu 18.04)
2
- pip-tools>=6.4.0,<=6.13.0 # Range maintains py36 support TODO: Review python 3.6 support in April 2023 (eol ubuntu 18.04)
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>=1.1.15,<1.6.0
7
- wheel==0.37.1
6
+ poetry==1.5.1
8
7
 
9
8
  # Some dependencies will only install if Cython is present
10
- Cython==0.29.34
9
+ Cython==3.0.0
@@ -91,7 +91,7 @@ module Dependabot
91
91
  end
92
92
 
93
93
  def pyproject_files
94
- [pyproject, pyproject_lock, poetry_lock, pdm_lock].compact
94
+ [pyproject, poetry_lock, pdm_lock].compact
95
95
  end
96
96
 
97
97
  def requirement_files
@@ -116,21 +116,27 @@ module Dependabot
116
116
  end
117
117
 
118
118
  def setup_file
119
- @setup_file ||= fetch_file_if_present("setup.py")
119
+ return @setup_file if defined?(@setup_file)
120
+
121
+ @setup_file = fetch_file_if_present("setup.py")
120
122
  end
121
123
 
122
124
  def setup_cfg_file
123
- @setup_cfg_file ||= fetch_file_if_present("setup.cfg")
125
+ return @setup_cfg_file if defined?(@setup_cfg_file)
126
+
127
+ @setup_cfg_file = fetch_file_if_present("setup.cfg")
124
128
  end
125
129
 
126
130
  def pip_conf
127
- @pip_conf ||= fetch_file_if_present("pip.conf")&.
128
- tap { |f| f.support_file = true }
131
+ return @pip_conf if defined?(@pip_conf)
132
+
133
+ @pip_conf = fetch_support_file("pip.conf")
129
134
  end
130
135
 
131
136
  def python_version_file
132
- @python_version_file ||= fetch_file_if_present(".python-version")&.
133
- tap { |f| f.support_file = true }
137
+ return @python_version_file if defined?(@python_version_file)
138
+
139
+ @python_version_file = fetch_support_file(".python-version")
134
140
 
135
141
  return @python_version_file if @python_version_file
136
142
  return if [".", "/"].include?(directory)
@@ -138,33 +144,38 @@ module Dependabot
138
144
  # Check the top-level for a .python-version file, too
139
145
  reverse_path = Pathname.new(directory[0]).relative_path_from(directory)
140
146
  @python_version_file ||=
141
- fetch_file_if_present(File.join(reverse_path, ".python-version"))&.
142
- tap { |f| f.support_file = true }&.
147
+ fetch_support_file(File.join(reverse_path, ".python-version"))&.
143
148
  tap { |f| f.name = ".python-version" }
144
149
  end
145
150
 
146
151
  def pipfile
147
- @pipfile ||= fetch_file_if_present("Pipfile")
152
+ return @pipfile if defined?(@pipfile)
153
+
154
+ @pipfile = fetch_file_if_present("Pipfile")
148
155
  end
149
156
 
150
157
  def pipfile_lock
151
- @pipfile_lock ||= fetch_file_if_present("Pipfile.lock")
158
+ return @pipfile_lock if defined?(@pipfile_lock)
159
+
160
+ @pipfile_lock = fetch_file_if_present("Pipfile.lock")
152
161
  end
153
162
 
154
163
  def pyproject
155
- @pyproject ||= fetch_file_if_present("pyproject.toml")
156
- end
164
+ return @pyproject if defined?(@pyproject)
157
165
 
158
- def pyproject_lock
159
- @pyproject_lock ||= fetch_file_if_present("pyproject.lock")
166
+ @pyproject = fetch_file_if_present("pyproject.toml")
160
167
  end
161
168
 
162
169
  def poetry_lock
163
- @poetry_lock ||= fetch_file_if_present("poetry.lock")
170
+ return @poetry_lock if defined?(@poetry_lock)
171
+
172
+ @poetry_lock = fetch_file_if_present("poetry.lock")
164
173
  end
165
174
 
166
175
  def pdm_lock
167
- @pdm_lock ||= fetch_file_if_present("pdm.lock")
176
+ return @pdm_lock if defined?(@pdm_lock)
177
+
178
+ @pdm_lock = fetch_file_if_present("pdm.lock")
168
179
  end
169
180
 
170
181
  def requirements_txt_files
@@ -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 || pyproject_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
 
@@ -37,9 +36,6 @@ module Dependabot
37
36
  end
38
37
 
39
38
  def updated_dependency_files
40
- return @updated_dependency_files if @update_already_attempted
41
-
42
- @update_already_attempted = true
43
39
  @updated_dependency_files ||= fetch_updated_dependency_files
44
40
  end
45
41
 
@@ -30,9 +30,6 @@ module Dependabot
30
30
  end
31
31
 
32
32
  def updated_dependency_files
33
- return @updated_dependency_files if @update_already_attempted
34
-
35
- @update_already_attempted = true
36
33
  @updated_dependency_files ||= fetch_updated_dependency_files
37
34
  end
38
35
 
@@ -92,7 +89,7 @@ module Dependabot
92
89
 
93
90
  # Find any requirement files that list the same dependencies as
94
91
  # the (old) Pipfile.lock. Any such files were almost certainly
95
- # generated using `pipenv lock -r`
92
+ # generated using `pipenv requirements`
96
93
  requirements_files.select do |req_file|
97
94
  deps = []
98
95
  req_file.content.scan(regex) { deps << Regexp.last_match }
@@ -237,12 +234,12 @@ module Dependabot
237
234
 
238
235
  def generate_updated_requirements_files
239
236
  req_content = run_pipenv_command(
240
- "pyenv exec pipenv lock -r"
237
+ "pyenv exec pipenv requirements"
241
238
  )
242
239
  File.write("req.txt", req_content)
243
240
 
244
241
  dev_req_content = run_pipenv_command(
245
- "pyenv exec pipenv lock -r -d"
242
+ "pyenv exec pipenv requirements --dev"
246
243
  )
247
244
  File.write("dev-req.txt", dev_req_content)
248
245
  end
@@ -109,9 +109,7 @@ module Dependabot
109
109
  end
110
110
 
111
111
  def pipfile_sources
112
- @pipfile_sources ||=
113
- TomlRB.parse(pipfile_content).fetch("source", []).
114
- map { |h| h.dup.merge("url" => h["url"].gsub(%r{/*$}, "") + "/") }
112
+ @pipfile_sources ||= TomlRB.parse(pipfile_content).fetch("source", [])
115
113
  end
116
114
 
117
115
  def sub_auth_url(source, credentials)
@@ -132,9 +130,12 @@ module Dependabot
132
130
 
133
131
  def config_variable_sources(credentials)
134
132
  @config_variable_sources ||=
135
- credentials.
136
- select { |cred| cred["type"] == "python_index" }.
137
- map { |c| { "url" => AuthedUrlBuilder.authed_url(credential: c) } }
133
+ credentials.select { |cred| cred["type"] == "python_index" }.map.with_index do |c, i|
134
+ {
135
+ "name" => "dependabot-inserted-index-#{i}",
136
+ "url" => AuthedUrlBuilder.authed_url(credential: c)
137
+ }
138
+ end
138
139
  end
139
140
  end
140
141
  end
@@ -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"
@@ -28,9 +28,6 @@ module Dependabot
28
28
  end
29
29
 
30
30
  def updated_dependency_files
31
- return @updated_dependency_files if @update_already_attempted
32
-
33
- @update_already_attempted = true
34
31
  @updated_dependency_files ||= fetch_updated_dependency_files
35
32
  end
36
33
 
@@ -160,17 +157,10 @@ module Dependabot
160
157
  end
161
158
 
162
159
  def create_declaration_at_new_version!(poetry_object, dep)
163
- poetry_object[subdep_type] ||= {}
164
- poetry_object[subdep_type][dependency.name] = dep.version
165
- end
160
+ subdep_type = subdependency_type_parser.subdep_type(dep)
166
161
 
167
- def subdep_type
168
- category =
169
- TomlRB.parse(lockfile.content).fetch("package", []).
170
- find { |dets| normalise(dets.fetch("name")) == dependency.name }.
171
- fetch("category")
172
-
173
- category == "dev" ? "dev-dependencies" : "dependencies"
162
+ poetry_object[subdep_type] ||= {}
163
+ poetry_object[subdep_type][dep.name] = dep.version
174
164
  end
175
165
 
176
166
  def sanitize(pyproject_content)
@@ -188,15 +178,11 @@ module Dependabot
188
178
  language_version_manager.install_required_python
189
179
 
190
180
  # use system git instead of the pure Python dulwich
191
- unless language_version_manager.python_version&.start_with?("3.6")
192
- run_poetry_command("pyenv exec poetry config experimental.system-git-client true")
193
- end
181
+ run_poetry_command("pyenv exec poetry config experimental.system-git-client true")
194
182
 
195
183
  run_poetry_update_command
196
184
 
197
- return File.read("poetry.lock") if File.exist?("poetry.lock")
198
-
199
- File.read("pyproject.lock")
185
+ File.read("poetry.lock")
200
186
  end
201
187
  end
202
188
  end
@@ -305,6 +291,13 @@ module Dependabot
305
291
  )
306
292
  end
307
293
 
294
+ def subdependency_type_parser
295
+ @subdependency_type_parser ||=
296
+ FileParser::PoetrySubdependencyTypeParser.new(
297
+ lockfile: lockfile
298
+ )
299
+ end
300
+
308
301
  def language_version_manager
309
302
  @language_version_manager ||=
310
303
  LanguageVersionManager.new(
@@ -318,17 +311,13 @@ module Dependabot
318
311
  end
319
312
 
320
313
  def lockfile
321
- @lockfile ||= pyproject_lock || poetry_lock
314
+ @lockfile ||= poetry_lock
322
315
  end
323
316
 
324
317
  def python_helper_path
325
318
  NativeHelpers.python_helper_path
326
319
  end
327
320
 
328
- def pyproject_lock
329
- dependency_files.find { |f| f.name == "pyproject.lock" }
330
- end
331
-
332
321
  def poetry_lock
333
322
  dependency_files.find { |f| f.name == "poetry.lock" }
334
323
  end
@@ -20,9 +20,6 @@ module Dependabot
20
20
  end
21
21
 
22
22
  def updated_dependency_files
23
- return @updated_dependency_files if @update_already_attempted
24
-
25
- @update_already_attempted = true
26
23
  @updated_dependency_files ||= fetch_updated_dependency_files
27
24
  end
28
25
 
@@ -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 || pyproject_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,27 +22,13 @@ 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
- if File.exist?("/usr/local/.pyenv/#{python_major_minor}.tar.gz")
18
- SharedHelpers.run_shell_command(
19
- "tar xzf /usr/local/.pyenv/#{python_major_minor}.tar.gz -C /usr/local/.pyenv/"
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
36
- @python ||= Python::Version.new(python_version)
37
- "#{@python.segments[0]}.#{@python.segments[1]}"
31
+ @python_major_minor ||= Python::Version.new(python_version).segments[0..1].join(".")
38
32
  end
39
33
 
40
34
  def python_version
@@ -59,32 +53,19 @@ module Dependabot
59
53
  def python_version_from_supported_versions
60
54
  requirement_string = python_requirement_string
61
55
 
62
- # Ideally, the requirement is satisfied by a Python version we support
63
- requirement =
64
- Python::Requirement.requirements_array(requirement_string).first
65
- version =
66
- PythonVersions::SUPPORTED_VERSIONS_TO_ITERATE.
67
- find { |v| requirement.satisfied_by?(Python::Version.new(v)) }
68
- 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/)
69
59
 
70
- # If not, and we're dealing with a simple version string
71
- # and changing the patch version would fix things, we do that
72
- # as the patch version is unlikely to affect resolution
73
- if requirement_string.start_with?(/\d/)
74
- requirement =
75
- Python::Requirement.new(requirement_string.gsub(/\.\d+$/, ".*"))
76
- version =
77
- PythonVersions::SUPPORTED_VERSIONS_TO_ITERATE.
78
- find { |v| requirement.satisfied_by?(Python::Version.new(v)) }
79
- return version if version
80
- 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
81
64
 
82
- # Otherwise we have to raise, giving details of the Python versions
83
- # that Dependabot supports
84
- msg = "Dependabot detected the following Python requirement " \
85
- "for your project: '#{requirement_string}'.\n\nCurrently, the " \
86
- "following Python versions are supported in Dependabot: " \
87
- "#{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(', ')}."
88
69
  raise DependencyFileNotResolvable, msg
89
70
  end
90
71
 
@@ -101,7 +82,7 @@ module Dependabot
101
82
  end
102
83
 
103
84
  def python_version_matching(requirements)
104
- PythonVersions::SUPPORTED_VERSIONS_TO_ITERATE.find do |version_string|
85
+ PRE_INSTALLED_PYTHON_VERSIONS.find do |version_string|
105
86
  version = Python::Version.new(version_string)
106
87
  requirements.all? do |req|
107
88
  next req.any? { |r| r.satisfied_by?(version) } if req.is_a?(Array)
@@ -27,7 +27,6 @@ module Dependabot
27
27
  potential_source_urls = [
28
28
  pypi_listing.dig("info", "project_urls", "Source"),
29
29
  pypi_listing.dig("info", "home_page"),
30
- pypi_listing.dig("info", "bugtrack_url"),
31
30
  pypi_listing.dig("info", "download_url"),
32
31
  pypi_listing.dig("info", "docs_url")
33
32
  ].compact
@@ -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}"
@@ -301,17 +296,6 @@ module Dependabot
301
296
  env
302
297
  end
303
298
 
304
- def error_certainly_bad_python_version?(message)
305
- return true if message.include?("UnsupportedPythonVersion")
306
-
307
- unless message.include?('"python setup.py egg_info" failed') ||
308
- message.include?("exit status 1: python setup.py egg_info")
309
- return false
310
- end
311
-
312
- message.include?("SyntaxError")
313
- end
314
-
315
299
  def write_temporary_dependency_files(updated_req: nil,
316
300
  update_requirement: true)
317
301
  dependency_files.each do |file|
@@ -513,7 +497,6 @@ module Dependabot
513
497
  dependency_files.select { |f| f.name.end_with?("setup.cfg") }
514
498
  end
515
499
  end
516
- # rubocop:enable Metrics/ClassLength
517
500
  end
518
501
  end
519
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
- (?:'git'.*pypoetry-git-(?<name>.+?).{8}',
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 # TODO: remove the first clause and | when py3.6 support is EoL
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 # TODO: remove the first clause and | when py3.6 support is EoL
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?("SolverProblemError") || # TODO: Remove once py3.6 is EoL
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
- unless language_version_manager.python_version&.start_with?("3.6")
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?("PackageNotFound") ||
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?("PackageNotFound") ||
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 || pyproject_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 || pyproject_lock).nil?
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 || pyproject_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.225.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-07-31 00:00:00.000000000 Z
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.225.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.225.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.17.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.17.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.225.0
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