dependabot-python 0.225.0 → 0.227.0

Sign up to get free protection for your applications and to get access to all the features.
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