dependabot-python 0.334.0 → 0.335.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 +1 -1
- data/lib/dependabot/python/file_fetcher.rb +48 -39
- data/lib/dependabot/python/file_parser/pipfile_files_parser.rb +26 -16
- data/lib/dependabot/python/file_parser/pyproject_files_parser.rb +21 -11
- data/lib/dependabot/python/file_parser/python_requirement_parser.rb +4 -2
- data/lib/dependabot/python/file_parser.rb +54 -24
- data/lib/dependabot/python/file_updater/pip_compile_file_updater.rb +14 -6
- data/lib/dependabot/python/file_updater/pipfile_file_updater.rb +5 -3
- data/lib/dependabot/python/file_updater/pipfile_manifest_updater.rb +1 -0
- data/lib/dependabot/python/file_updater/pipfile_preparer.rb +8 -4
- data/lib/dependabot/python/file_updater/poetry_file_updater.rb +11 -7
- data/lib/dependabot/python/file_updater/pyproject_preparer.rb +1 -0
- data/lib/dependabot/python/file_updater/requirement_replacer.rb +18 -6
- data/lib/dependabot/python/file_updater.rb +8 -6
- data/lib/dependabot/python/language.rb +6 -3
- data/lib/dependabot/python/metadata_finder.rb +6 -3
- data/lib/dependabot/python/name_normaliser.rb +1 -1
- data/lib/dependabot/python/package/package_details_fetcher.rb +5 -5
- data/lib/dependabot/python/pipenv_runner.rb +2 -0
- data/lib/dependabot/python/requirement.rb +7 -4
- data/lib/dependabot/python/update_checker/pip_compile_version_resolver.rb +4 -2
- data/lib/dependabot/python/update_checker/pip_version_resolver.rb +9 -2
- data/lib/dependabot/python/update_checker/poetry_version_resolver.rb +54 -35
- data/lib/dependabot/python/update_checker/requirements_updater.rb +18 -8
- data/lib/dependabot/python/version.rb +8 -4
- metadata +12 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 535cedbc5cc0a4b3594a556be6563af3afa5b354b5d9a3e2d2af9af60c30c116
|
4
|
+
data.tar.gz: e2bd11041a92793ca4f0eb56b63377a6346ae105400b34658dd5b146701c41ff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 133569373fc3bddac801d7a8a8e5055f2897a69add2ab8fca7d6d1af104a669c637b3ccaba895ec5765f6369a51366e4461c6d24cdc41248449a3614bfe51512
|
7
|
+
data.tar.gz: 07c053fce5c40ae72981acd60c67add022bbe668bf3e2b0f2410aebac52b6a2115fbd31870fa1edcaf1303689808354c5551702053bd5cfbb166fe3f23bbe89f
|
data/helpers/requirements.txt
CHANGED
@@ -151,16 +151,19 @@ module Dependabot
|
|
151
151
|
|
152
152
|
sig { returns(T.nilable(Dependabot::DependencyFile)) }
|
153
153
|
def python_version_file
|
154
|
-
@python_version_file ||= T.let(
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
154
|
+
@python_version_file ||= T.let(
|
155
|
+
begin
|
156
|
+
file = fetch_support_file(".python-version")
|
157
|
+
return file if file
|
158
|
+
return if [".", "/"].include?(directory)
|
159
|
+
|
160
|
+
# Check the top-level for a .python-version file, too
|
161
|
+
reverse_path = Pathname.new(directory[0]).relative_path_from(directory)
|
162
|
+
fetch_support_file(File.join(reverse_path, ".python-version"))
|
163
|
+
&.tap { |f| f.name = ".python-version" }
|
164
|
+
end,
|
165
|
+
T.nilable(Dependabot::DependencyFile)
|
166
|
+
)
|
164
167
|
end
|
165
168
|
|
166
169
|
sig { returns(T.nilable(Dependabot::DependencyFile)) }
|
@@ -240,23 +243,26 @@ module Dependabot
|
|
240
243
|
|
241
244
|
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
242
245
|
def req_txt_and_in_files
|
243
|
-
@req_txt_and_in_files ||= T.let(
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
246
|
+
@req_txt_and_in_files ||= T.let(
|
247
|
+
begin
|
248
|
+
files = T.let([], T::Array[Dependabot::DependencyFile])
|
249
|
+
|
250
|
+
repo_contents
|
251
|
+
.select { |f| f.type == "file" }
|
252
|
+
.select { |f| f.name.end_with?(".txt", ".in") }
|
253
|
+
.reject { |f| f.size > 500_000 }
|
254
|
+
.map { |f| fetch_file_from_host(f.name) }
|
255
|
+
.select { |f| requirements_file?(f) }
|
256
|
+
.each { |f| files << f }
|
257
|
+
|
258
|
+
repo_contents
|
259
|
+
.select { |f| f.type == "dir" }
|
260
|
+
.each { |f| files.concat(req_files_for_dir(f)) }
|
261
|
+
|
262
|
+
files
|
263
|
+
end,
|
264
|
+
T.nilable(T::Array[Dependabot::DependencyFile])
|
265
|
+
)
|
260
266
|
end
|
261
267
|
|
262
268
|
sig { params(requirements_dir: T.untyped).returns(T::Array[Dependabot::DependencyFile]) }
|
@@ -285,18 +291,21 @@ module Dependabot
|
|
285
291
|
|
286
292
|
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
287
293
|
def child_requirement_files
|
288
|
-
@child_requirement_files ||= T.let(
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
294
|
+
@child_requirement_files ||= T.let(
|
295
|
+
begin
|
296
|
+
fetched_files = req_txt_and_in_files.dup
|
297
|
+
req_txt_and_in_files.flat_map do |requirement_file|
|
298
|
+
child_files = fetch_child_requirement_files(
|
299
|
+
file: requirement_file,
|
300
|
+
previously_fetched_files: fetched_files
|
301
|
+
)
|
302
|
+
|
303
|
+
fetched_files += child_files
|
304
|
+
child_files
|
305
|
+
end
|
306
|
+
end,
|
307
|
+
T.nilable(T::Array[Dependabot::DependencyFile])
|
308
|
+
)
|
300
309
|
end
|
301
310
|
|
302
311
|
sig do
|
@@ -15,16 +15,19 @@ module Dependabot
|
|
15
15
|
class PipfileFilesParser
|
16
16
|
extend T::Sig
|
17
17
|
|
18
|
-
DEPENDENCY_GROUP_KEYS = T.let(
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
18
|
+
DEPENDENCY_GROUP_KEYS = T.let(
|
19
|
+
[
|
20
|
+
{
|
21
|
+
pipfile: "packages",
|
22
|
+
lockfile: "default"
|
23
|
+
},
|
24
|
+
{
|
25
|
+
pipfile: "dev-packages",
|
26
|
+
lockfile: "develop"
|
27
|
+
}
|
28
|
+
].freeze,
|
29
|
+
T::Array[T::Hash[Symbol, String]]
|
30
|
+
)
|
28
31
|
|
29
32
|
sig { params(dependency_files: T::Array[Dependabot::DependencyFile]).void }
|
30
33
|
def initialize(dependency_files:)
|
@@ -116,8 +119,11 @@ module Dependabot
|
|
116
119
|
end
|
117
120
|
|
118
121
|
sig do
|
119
|
-
params(
|
120
|
-
|
122
|
+
params(
|
123
|
+
dep_name: String,
|
124
|
+
requirement: T.any(String, T::Hash[String, T.untyped]),
|
125
|
+
group: String
|
126
|
+
).returns(T.nilable(String))
|
121
127
|
end
|
122
128
|
def dependency_version(dep_name, requirement, group)
|
123
129
|
req = version_from_hash_or_string(requirement)
|
@@ -171,8 +177,10 @@ module Dependabot
|
|
171
177
|
|
172
178
|
sig { returns(T::Hash[String, T.untyped]) }
|
173
179
|
def parsed_pipfile_lock
|
174
|
-
@parsed_pipfile_lock ||= T.let(
|
175
|
-
|
180
|
+
@parsed_pipfile_lock ||= T.let(
|
181
|
+
JSON.parse(T.must(T.must(pipfile_lock).content)),
|
182
|
+
T.nilable(T::Hash[String, T.untyped])
|
183
|
+
)
|
176
184
|
rescue JSON::ParserError
|
177
185
|
raise Dependabot::DependencyFileNotParseable, T.must(pipfile_lock).path
|
178
186
|
end
|
@@ -184,8 +192,10 @@ module Dependabot
|
|
184
192
|
|
185
193
|
sig { returns(T.nilable(Dependabot::DependencyFile)) }
|
186
194
|
def pipfile_lock
|
187
|
-
@pipfile_lock ||= T.let(
|
188
|
-
|
195
|
+
@pipfile_lock ||= T.let(
|
196
|
+
dependency_files.find { |f| f.name == "Pipfile.lock" },
|
197
|
+
T.nilable(Dependabot::DependencyFile)
|
198
|
+
)
|
189
199
|
end
|
190
200
|
end
|
191
201
|
end
|
@@ -107,9 +107,11 @@ module Dependabot
|
|
107
107
|
end
|
108
108
|
|
109
109
|
sig do
|
110
|
-
params(
|
111
|
-
|
112
|
-
|
110
|
+
params(
|
111
|
+
type: String,
|
112
|
+
deps_hash: T::Hash[String,
|
113
|
+
T.untyped]
|
114
|
+
).returns(Dependabot::FileParsers::Base::DependencySet)
|
113
115
|
end
|
114
116
|
def parse_poetry_dependency_group(type, deps_hash)
|
115
117
|
dependencies = Dependabot::FileParsers::Base::DependencySet.new
|
@@ -218,8 +220,10 @@ module Dependabot
|
|
218
220
|
|
219
221
|
sig { returns(T::Array[T.nilable(String)]) }
|
220
222
|
def production_dependency_names
|
221
|
-
@production_dependency_names ||= T.let(
|
222
|
-
|
223
|
+
@production_dependency_names ||= T.let(
|
224
|
+
parse_production_dependency_names,
|
225
|
+
T.nilable(T::Array[T.nilable(String)])
|
226
|
+
)
|
223
227
|
end
|
224
228
|
|
225
229
|
sig { returns(T::Array[T.nilable(String)]) }
|
@@ -283,8 +287,10 @@ module Dependabot
|
|
283
287
|
|
284
288
|
sig { returns(T.nilable(Dependabot::DependencyFile)) }
|
285
289
|
def pyproject
|
286
|
-
@pyproject ||= T.let(
|
287
|
-
|
290
|
+
@pyproject ||= T.let(
|
291
|
+
dependency_files.find { |f| f.name == "pyproject.toml" },
|
292
|
+
T.nilable(Dependabot::DependencyFile)
|
293
|
+
)
|
288
294
|
end
|
289
295
|
|
290
296
|
sig { returns(T.untyped) }
|
@@ -319,14 +325,18 @@ module Dependabot
|
|
319
325
|
|
320
326
|
sig { returns(T.nilable(Dependabot::DependencyFile)) }
|
321
327
|
def poetry_lock
|
322
|
-
@poetry_lock ||= T.let(
|
323
|
-
|
328
|
+
@poetry_lock ||= T.let(
|
329
|
+
dependency_files.find { |f| f.name == "poetry.lock" },
|
330
|
+
T.nilable(Dependabot::DependencyFile)
|
331
|
+
)
|
324
332
|
end
|
325
333
|
|
326
334
|
sig { returns(T.nilable(Dependabot::DependencyFile)) }
|
327
335
|
def pdm_lock
|
328
|
-
@pdm_lock ||= T.let(
|
329
|
-
|
336
|
+
@pdm_lock ||= T.let(
|
337
|
+
dependency_files.find { |f| f.name == "pdm.lock" },
|
338
|
+
T.nilable(Dependabot::DependencyFile)
|
339
|
+
)
|
330
340
|
end
|
331
341
|
end
|
332
342
|
end
|
@@ -153,8 +153,10 @@ module Dependabot
|
|
153
153
|
|
154
154
|
sig { returns(T.nilable(PipCompileFileMatcher)) }
|
155
155
|
def pip_compile_file_matcher
|
156
|
-
@pip_compile_file_matcher = T.let(
|
157
|
-
|
156
|
+
@pip_compile_file_matcher = T.let(
|
157
|
+
PipCompileFileMatcher.new(pip_compile_files),
|
158
|
+
T.nilable(PipCompileFileMatcher)
|
159
|
+
)
|
158
160
|
end
|
159
161
|
|
160
162
|
sig { returns(T.class_of(Dependabot::Python::Requirement)) }
|
@@ -25,16 +25,19 @@ module Dependabot
|
|
25
25
|
require_relative "file_parser/setup_file_parser"
|
26
26
|
require_relative "file_parser/python_requirement_parser"
|
27
27
|
|
28
|
-
DEPENDENCY_GROUP_KEYS = T.let(
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
28
|
+
DEPENDENCY_GROUP_KEYS = T.let(
|
29
|
+
[
|
30
|
+
{
|
31
|
+
pipfile: "packages",
|
32
|
+
lockfile: "default"
|
33
|
+
},
|
34
|
+
{
|
35
|
+
pipfile: "dev-packages",
|
36
|
+
lockfile: "develop"
|
37
|
+
}
|
38
|
+
].freeze,
|
39
|
+
T::Array[T::Hash[Symbol, String]]
|
40
|
+
)
|
38
41
|
REQUIREMENT_FILE_EVALUATION_ERRORS = %w(
|
39
42
|
InstallationError RequirementsFileParseError InvalidMarker
|
40
43
|
InvalidRequirement ValueError RecursionError
|
@@ -76,14 +79,24 @@ module Dependabot
|
|
76
79
|
|
77
80
|
sig { returns(Dependabot::Python::LanguageVersionManager) }
|
78
81
|
def language_version_manager
|
79
|
-
@language_version_manager ||= T.let(
|
80
|
-
|
82
|
+
@language_version_manager ||= T.let(
|
83
|
+
LanguageVersionManager.new(
|
84
|
+
python_requirement_parser:
|
85
|
+
python_requirement_parser
|
86
|
+
),
|
87
|
+
T.nilable(LanguageVersionManager)
|
88
|
+
)
|
81
89
|
end
|
82
90
|
|
83
91
|
sig { returns(Dependabot::Python::FileParser::PythonRequirementParser) }
|
84
92
|
def python_requirement_parser
|
85
|
-
@python_requirement_parser ||= T.let(
|
86
|
-
|
93
|
+
@python_requirement_parser ||= T.let(
|
94
|
+
FileParser::PythonRequirementParser.new(
|
95
|
+
dependency_files:
|
96
|
+
dependency_files
|
97
|
+
),
|
98
|
+
T.nilable(FileParser::PythonRequirementParser)
|
99
|
+
)
|
87
100
|
end
|
88
101
|
|
89
102
|
sig { returns(Ecosystem::VersionManager) }
|
@@ -240,14 +253,24 @@ module Dependabot
|
|
240
253
|
|
241
254
|
sig { returns(DependencySet) }
|
242
255
|
def pipenv_dependencies
|
243
|
-
@pipenv_dependencies ||= T.let(
|
244
|
-
|
256
|
+
@pipenv_dependencies ||= T.let(
|
257
|
+
PipfileFilesParser.new(
|
258
|
+
dependency_files:
|
259
|
+
dependency_files
|
260
|
+
).dependency_set,
|
261
|
+
T.nilable(DependencySet)
|
262
|
+
)
|
245
263
|
end
|
246
264
|
|
247
265
|
sig { returns(DependencySet) }
|
248
266
|
def pyproject_file_dependencies
|
249
|
-
@pyproject_file_dependencies ||= T.let(
|
250
|
-
|
267
|
+
@pyproject_file_dependencies ||= T.let(
|
268
|
+
PyprojectFilesParser.new(
|
269
|
+
dependency_files:
|
270
|
+
dependency_files
|
271
|
+
).dependency_set,
|
272
|
+
T.nilable(DependencySet)
|
273
|
+
)
|
251
274
|
end
|
252
275
|
|
253
276
|
sig { returns(DependencySet) }
|
@@ -347,8 +370,10 @@ module Dependabot
|
|
347
370
|
end
|
348
371
|
|
349
372
|
sig do
|
350
|
-
params(
|
351
|
-
|
373
|
+
params(
|
374
|
+
condition: T.untyped,
|
375
|
+
python_version: T.any(String, Integer, Gem::Version)
|
376
|
+
).returns(T::Boolean)
|
352
377
|
end
|
353
378
|
def evaluate_condition(condition, python_version)
|
354
379
|
operator, version = condition.match(/([<>=!]=?)\s*"?([\d.]+)"?/)&.captures
|
@@ -371,8 +396,11 @@ module Dependabot
|
|
371
396
|
|
372
397
|
sig { returns(DependencySet) }
|
373
398
|
def setup_file_dependencies
|
374
|
-
@setup_file_dependencies ||= T.let(
|
375
|
-
|
399
|
+
@setup_file_dependencies ||= T.let(
|
400
|
+
SetupFileParser.new(dependency_files: dependency_files)
|
401
|
+
.dependency_set,
|
402
|
+
T.nilable(DependencySet)
|
403
|
+
)
|
376
404
|
end
|
377
405
|
|
378
406
|
sig { returns(T.untyped) }
|
@@ -497,8 +525,10 @@ module Dependabot
|
|
497
525
|
|
498
526
|
sig { returns(Dependabot::Python::PipCompileFileMatcher) }
|
499
527
|
def pip_compile_file_matcher
|
500
|
-
@pip_compile_file_matcher ||= T.let(
|
501
|
-
|
528
|
+
@pip_compile_file_matcher ||= T.let(
|
529
|
+
PipCompileFileMatcher.new(pip_compile_files),
|
530
|
+
T.nilable(Dependabot::Python::PipCompileFileMatcher)
|
531
|
+
)
|
502
532
|
end
|
503
533
|
end
|
504
534
|
end
|
@@ -25,8 +25,10 @@ module Dependabot
|
|
25
25
|
require_relative "setup_file_sanitizer"
|
26
26
|
|
27
27
|
UNSAFE_PACKAGES = T.let(%w(setuptools distribute pip).freeze, T::Array[String])
|
28
|
-
INCOMPATIBLE_VERSIONS_REGEX = T.let(
|
29
|
-
|
28
|
+
INCOMPATIBLE_VERSIONS_REGEX = T.let(
|
29
|
+
/not supported between instances of 'InstallationCandidate'.*\z/m,
|
30
|
+
Regexp
|
31
|
+
)
|
30
32
|
WARNINGS = T.let(/\s*# WARNING:.*\Z/m, Regexp)
|
31
33
|
UNSAFE_NOTE = T.let(/\s*# The following packages are considered to be unsafe.*\Z/m, Regexp)
|
32
34
|
RESOLVER_REGEX = T.let(/(?<=--resolver=)(\w+)/, Regexp)
|
@@ -70,8 +72,10 @@ module Dependabot
|
|
70
72
|
|
71
73
|
sig { returns(T.nilable(T::Array[Dependabot::DependencyFile])) }
|
72
74
|
def updated_dependency_files
|
73
|
-
@updated_dependency_files = T.let(
|
74
|
-
|
75
|
+
@updated_dependency_files = T.let(
|
76
|
+
fetch_updated_dependency_files,
|
77
|
+
T.nilable(T::Array[Dependabot::DependencyFile])
|
78
|
+
)
|
75
79
|
end
|
76
80
|
|
77
81
|
private
|
@@ -488,8 +492,12 @@ module Dependabot
|
|
488
492
|
T.must(requirement_string.match(/#{hash_regex}((?<separator>\s*\\?\s*?)#{hash_regex})*/)).named_captures.fetch("separator")
|
489
493
|
|
490
494
|
default_separator =
|
491
|
-
T.must(
|
492
|
-
|
495
|
+
T.must(
|
496
|
+
T.must(
|
497
|
+
requirement_string
|
498
|
+
.match(RequirementParser::HASH)
|
499
|
+
).pre_match.match(/(?<separator>\s*\\?\s*?)\z/)
|
500
|
+
).named_captures.fetch("separator")
|
493
501
|
|
494
502
|
# rubocop:enable Layout/LineLength
|
495
503
|
current_separator || default_separator
|
@@ -334,9 +334,11 @@ module Dependabot
|
|
334
334
|
pipfile_content: String
|
335
335
|
).returns(
|
336
336
|
T.nilable(
|
337
|
-
T.any(
|
338
|
-
|
339
|
-
|
337
|
+
T.any(
|
338
|
+
T::Hash[String, T.untyped],
|
339
|
+
String,
|
340
|
+
T::Array[T::Hash[String, T.untyped]]
|
341
|
+
)
|
340
342
|
)
|
341
343
|
)
|
342
344
|
end
|
@@ -70,13 +70,17 @@ module Dependabot
|
|
70
70
|
|
71
71
|
sig { returns(T::Array[T::Hash[String, String]]) }
|
72
72
|
def pipfile_sources
|
73
|
-
@pipfile_sources ||= T.let(
|
74
|
-
|
73
|
+
@pipfile_sources ||= T.let(
|
74
|
+
TomlRB.parse(pipfile_content).fetch("source", []),
|
75
|
+
T.nilable(T::Array[T::Hash[String, String]])
|
76
|
+
)
|
75
77
|
end
|
76
78
|
|
77
79
|
sig do
|
78
|
-
params(
|
79
|
-
|
80
|
+
params(
|
81
|
+
source: T::Hash[String, String],
|
82
|
+
credentials: T::Array[Dependabot::Credential]
|
83
|
+
).returns(T.nilable(T::Hash[String, String]))
|
80
84
|
end
|
81
85
|
def sub_auth_url(source, credentials)
|
82
86
|
if source["url"]&.include?("${")
|
@@ -126,8 +126,10 @@ module Dependabot
|
|
126
126
|
content.sub(T.must(declaration), new_declaration)
|
127
127
|
else
|
128
128
|
content.gsub(table_declaration_regex(dep, new_r)) do |match|
|
129
|
-
match.gsub(
|
130
|
-
|
129
|
+
match.gsub(
|
130
|
+
/(\s*version\s*=\s*["'])#{Regexp.escape(old_req)}/,
|
131
|
+
'\1' + new_req
|
132
|
+
)
|
131
133
|
end
|
132
134
|
end
|
133
135
|
end
|
@@ -284,11 +286,13 @@ module Dependabot
|
|
284
286
|
sig do
|
285
287
|
params(
|
286
288
|
pyproject_content: String
|
287
|
-
).returns(T.nilable(
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
289
|
+
).returns(T.nilable(
|
290
|
+
T.any(
|
291
|
+
T::Hash[String, T.untyped],
|
292
|
+
String,
|
293
|
+
T::Array[T::Hash[String, T.untyped]]
|
294
|
+
)
|
295
|
+
))
|
292
296
|
end
|
293
297
|
def pyproject_hash_for(pyproject_content)
|
294
298
|
SharedHelpers.in_a_temporary_directory do |dir|
|
@@ -29,8 +29,14 @@ module Dependabot
|
|
29
29
|
index_urls: T.nilable(T::Array[T.nilable(String)])
|
30
30
|
).void
|
31
31
|
end
|
32
|
-
def initialize(
|
33
|
-
|
32
|
+
def initialize(
|
33
|
+
content:,
|
34
|
+
dependency_name:,
|
35
|
+
old_requirement:,
|
36
|
+
new_requirement:,
|
37
|
+
new_hash_version: nil,
|
38
|
+
index_urls: nil
|
39
|
+
)
|
34
40
|
@content = T.let(content, String)
|
35
41
|
@dependency_name = T.let(normalise(dependency_name), String)
|
36
42
|
@old_requirement = T.let(old_requirement, T.nilable(String))
|
@@ -158,12 +164,18 @@ module Dependabot
|
|
158
164
|
return "" unless requirement_includes_hashes?(requirement)
|
159
165
|
|
160
166
|
hash_regex = RequirementParser::HASH
|
161
|
-
matches = T.must(
|
162
|
-
|
167
|
+
matches = T.must(
|
168
|
+
original_dependency_declaration_string(requirement)
|
169
|
+
.match(/#{hash_regex}((?<separator>\s*\\?\s*?)#{hash_regex})*/)
|
170
|
+
)
|
163
171
|
current_separator = matches.named_captures.fetch("separator")
|
164
172
|
|
165
|
-
hash_matches = T.must(
|
166
|
-
.
|
173
|
+
hash_matches = T.must(
|
174
|
+
T.must(
|
175
|
+
original_dependency_declaration_string(requirement)
|
176
|
+
.match(RequirementParser::HASH)
|
177
|
+
).pre_match.match(/(?<separator>\s*\\?\s*?)\z/)
|
178
|
+
)
|
167
179
|
default_separator = hash_matches
|
168
180
|
.named_captures.fetch("separator")
|
169
181
|
|
@@ -114,12 +114,14 @@ module Dependabot
|
|
114
114
|
|
115
115
|
sig { returns(T::Array[DependencyFile]) }
|
116
116
|
def updated_pip_compile_based_files
|
117
|
-
T.must(
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
117
|
+
T.must(
|
118
|
+
PipCompileFileUpdater.new(
|
119
|
+
dependencies: dependencies,
|
120
|
+
dependency_files: dependency_files,
|
121
|
+
credentials: credentials,
|
122
|
+
index_urls: pip_compile_index_urls
|
123
|
+
).updated_dependency_files
|
124
|
+
)
|
123
125
|
end
|
124
126
|
|
125
127
|
sig { returns(T::Array[DependencyFile]) }
|
@@ -23,9 +23,12 @@ module Dependabot
|
|
23
23
|
3.9.23
|
24
24
|
).freeze
|
25
25
|
|
26
|
-
PRE_INSTALLED_PYTHON_VERSIONS = T.let(
|
27
|
-
|
28
|
-
|
26
|
+
PRE_INSTALLED_PYTHON_VERSIONS = T.let(
|
27
|
+
PRE_INSTALLED_PYTHON_VERSIONS_RAW.map do |v|
|
28
|
+
Version.new(v)
|
29
|
+
end.sort,
|
30
|
+
T::Array[Dependabot::Python::Version]
|
31
|
+
)
|
29
32
|
|
30
33
|
PRE_INSTALLED_VERSIONS_MAP = T.let(
|
31
34
|
PRE_INSTALLED_PYTHON_VERSIONS.to_h do |v|
|
@@ -90,7 +90,8 @@ module Dependabot
|
|
90
90
|
next unless response.status == 200
|
91
91
|
|
92
92
|
response.body.include?(normalised_dependency_name)
|
93
|
-
end,
|
93
|
+
end,
|
94
|
+
T.nilable(String)
|
94
95
|
)
|
95
96
|
end
|
96
97
|
# rubocop:enable Metrics/PerceivedComplexity
|
@@ -122,7 +123,8 @@ module Dependabot
|
|
122
123
|
next unless response.status == 200
|
123
124
|
|
124
125
|
response.body.include?(normalised_dependency_name)
|
125
|
-
end,
|
126
|
+
end,
|
127
|
+
T.nilable(String)
|
126
128
|
)
|
127
129
|
end
|
128
130
|
# rubocop:enable Metrics/PerceivedComplexity
|
@@ -143,7 +145,8 @@ module Dependabot
|
|
143
145
|
rescue Excon::Error::Timeout, Excon::Error::Socket,
|
144
146
|
Excon::Error::TooManyRedirects, ArgumentError
|
145
147
|
nil
|
146
|
-
end,
|
148
|
+
end,
|
149
|
+
T.nilable(Excon::Response)
|
147
150
|
)
|
148
151
|
|
149
152
|
return unless @homepage_response&.status == 200
|
@@ -69,12 +69,12 @@ module Dependabot
|
|
69
69
|
.select { |index_url| validate_index(index_url) } # Ensure only valid URLs
|
70
70
|
.flat_map do |index_url|
|
71
71
|
fetch_from_registry(index_url) || [] # Ensure it always returns an array
|
72
|
-
|
73
|
-
|
72
|
+
rescue Excon::Error::Timeout, Excon::Error::Socket
|
73
|
+
raise if MAIN_PYPI_INDEXES.include?(index_url)
|
74
74
|
|
75
|
-
|
76
|
-
|
77
|
-
|
75
|
+
raise PrivateSourceTimedOut, sanitized_url(index_url)
|
76
|
+
rescue URI::InvalidURIError
|
77
|
+
raise DependencyFileNotResolvable, "Invalid URL: #{sanitized_url(index_url)}"
|
78
78
|
end
|
79
79
|
|
80
80
|
Dependabot::Package::PackageDetails.new(
|
@@ -57,8 +57,10 @@ module Dependabot
|
|
57
57
|
|
58
58
|
sig { returns(Dependabot::Dependency) }
|
59
59
|
attr_reader :dependency
|
60
|
+
|
60
61
|
sig { returns(T.nilable(Dependabot::DependencyFile)) }
|
61
62
|
attr_reader :lockfile
|
63
|
+
|
62
64
|
sig { returns(LanguageVersionManager) }
|
63
65
|
attr_reader :language_version_manager
|
64
66
|
|
@@ -15,10 +15,13 @@ module Dependabot
|
|
15
15
|
OR_SEPARATOR = T.let(/(?<=[a-zA-Z0-9)*])\s*\|+/, Regexp)
|
16
16
|
|
17
17
|
# Add equality and arbitrary-equality matchers
|
18
|
-
OPS = T.let(
|
19
|
-
|
20
|
-
|
21
|
-
|
18
|
+
OPS = T.let(
|
19
|
+
OPS.merge(
|
20
|
+
"==" => ->(v, r) { v == r },
|
21
|
+
"===" => ->(v, r) { v.to_s == r.to_s }
|
22
|
+
),
|
23
|
+
T::Hash[String, T.proc.params(arg0: T.untyped, arg1: T.untyped).returns(T.untyped)]
|
24
|
+
)
|
22
25
|
|
23
26
|
quoted = OPS.keys.sort_by(&:length).reverse
|
24
27
|
.map { |k| Regexp.quote(k) }.join("|")
|
@@ -532,7 +532,8 @@ module Dependabot
|
|
532
532
|
@python_requirement_parser ||= T.let(
|
533
533
|
FileParser::PythonRequirementParser.new(
|
534
534
|
dependency_files: dependency_files
|
535
|
-
),
|
535
|
+
),
|
536
|
+
T.nilable(FileParser::PythonRequirementParser)
|
536
537
|
)
|
537
538
|
end
|
538
539
|
|
@@ -541,7 +542,8 @@ module Dependabot
|
|
541
542
|
@language_version_manager ||= T.let(
|
542
543
|
LanguageVersionManager.new(
|
543
544
|
python_requirement_parser: python_requirement_parser
|
544
|
-
),
|
545
|
+
),
|
546
|
+
T.nilable(LanguageVersionManager)
|
545
547
|
)
|
546
548
|
end
|
547
549
|
|
@@ -24,8 +24,15 @@ module Dependabot
|
|
24
24
|
raise_on_ignored: T::Boolean
|
25
25
|
).void
|
26
26
|
end
|
27
|
-
def initialize(
|
28
|
-
|
27
|
+
def initialize(
|
28
|
+
dependency:,
|
29
|
+
dependency_files:,
|
30
|
+
credentials:,
|
31
|
+
ignored_versions:,
|
32
|
+
security_advisories:,
|
33
|
+
update_cooldown: nil,
|
34
|
+
raise_on_ignored: false
|
35
|
+
)
|
29
36
|
@dependency = T.let(dependency, Dependabot::Dependency)
|
30
37
|
@dependency_files = T.let(dependency_files, T::Array[Dependabot::DependencyFile])
|
31
38
|
@credentials = T.let(credentials, T::Array[Dependabot::Credential])
|
@@ -44,11 +44,14 @@ module Dependabot
|
|
44
44
|
|
45
45
|
INCOMPATIBLE_CONSTRAINTS = /Incompatible constraints in requirements of (?<dep>.+?) ((?<ver>.+?)):/
|
46
46
|
|
47
|
-
PACKAGE_RESOLVER_ERRORS = T.let(
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
47
|
+
PACKAGE_RESOLVER_ERRORS = T.let(
|
48
|
+
{
|
49
|
+
package_info_error: /Unable to determine package info/,
|
50
|
+
self_dep_error: /Package '(?<path>.*)' is listed as a dependency of itself./,
|
51
|
+
incompatible_constraints: /Incompatible constraints in requirements/
|
52
|
+
}.freeze,
|
53
|
+
T::Hash[T.nilable(String), Regexp]
|
54
|
+
)
|
52
55
|
|
53
56
|
sig { returns(Dependabot::Dependency) }
|
54
57
|
attr_reader :dependency
|
@@ -78,8 +81,10 @@ module Dependabot
|
|
78
81
|
@dependency_files = T.let(dependency_files, T::Array[Dependabot::DependencyFile])
|
79
82
|
@credentials = T.let(credentials, T::Array[Dependabot::Credential])
|
80
83
|
@repo_contents_path = T.let(repo_contents_path, T.nilable(String))
|
81
|
-
@error_handler = T.let(
|
82
|
-
|
84
|
+
@error_handler = T.let(
|
85
|
+
PoetryErrorHandler.new(dependencies: dependency, dependency_files: dependency_files),
|
86
|
+
Dependabot::Python::PoetryErrorHandler
|
87
|
+
)
|
83
88
|
@resolvable = T.let({}, T::Hash[Gem::Version, T::Boolean])
|
84
89
|
@latest_resolvable_version_string = T.let({}, T::Hash[T.nilable(String), T.nilable(String)])
|
85
90
|
@original_reqs_resolvable = T.let(nil, T.nilable(T::Boolean))
|
@@ -233,8 +238,10 @@ module Dependabot
|
|
233
238
|
update_pyproject: T::Boolean
|
234
239
|
).void
|
235
240
|
end
|
236
|
-
def write_temporary_dependency_files(
|
237
|
-
|
241
|
+
def write_temporary_dependency_files(
|
242
|
+
updated_req: nil,
|
243
|
+
update_pyproject: true
|
244
|
+
)
|
238
245
|
dependency_files.each do |file|
|
239
246
|
path = file.name
|
240
247
|
FileUtils.mkdir_p(Pathname.new(path).dirname)
|
@@ -409,21 +416,27 @@ module Dependabot
|
|
409
416
|
PACKAGE_NOT_FOUND = /Package (?<pkg>.*) ((?<req_ver>.*)) not found./
|
410
417
|
|
411
418
|
# client access error codes while accessing package index
|
412
|
-
CLIENT_ERROR_CODES = T.let(
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
+
CLIENT_ERROR_CODES = T.let(
|
420
|
+
{
|
421
|
+
error401: /401 Client Error/,
|
422
|
+
error403: /403 Client Error/,
|
423
|
+
error404: /404 Client Error/,
|
424
|
+
http403: /HTTP error 403/,
|
425
|
+
http404: /HTTP error 404/
|
426
|
+
}.freeze,
|
427
|
+
T::Hash[T.nilable(String), Regexp]
|
428
|
+
)
|
419
429
|
|
420
430
|
# server response error codes while accessing package index
|
421
|
-
SERVER_ERROR_CODES = T.let(
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
431
|
+
SERVER_ERROR_CODES = T.let(
|
432
|
+
{
|
433
|
+
server500: /500 Server Error/,
|
434
|
+
server502: /502 Server Error/,
|
435
|
+
server503: /503 Server Error/,
|
436
|
+
server504: /504 Server Error/
|
437
|
+
}.freeze,
|
438
|
+
T::Hash[T.nilable(String), Regexp]
|
439
|
+
)
|
427
440
|
|
428
441
|
# invalid configuration in pyproject.toml
|
429
442
|
POETRY_VIRTUAL_ENV_CONFIG = %r{pypoetry/virtualenvs(.|\n)*list index out of range}
|
@@ -431,17 +444,23 @@ module Dependabot
|
|
431
444
|
# error related to local project as dependency in pyproject.toml
|
432
445
|
ERR_LOCAL_PROJECT_PATH = /Path (?<path>.*) for (?<dep>.*) does not exist/
|
433
446
|
|
434
|
-
TIME_OUT_ERRORS = T.let(
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
447
|
+
TIME_OUT_ERRORS = T.let(
|
448
|
+
{
|
449
|
+
time_out_max_retries: /Max retries exceeded/,
|
450
|
+
time_out_read_timed_out: /Read timed out/,
|
451
|
+
time_out_inactivity: /Timed out due to inactivity/
|
452
|
+
}.freeze,
|
453
|
+
T::Hash[T.nilable(String), Regexp]
|
454
|
+
)
|
455
|
+
|
456
|
+
PACKAGE_RESOLVER_ERRORS = T.let(
|
457
|
+
{
|
458
|
+
package_info_error: /Unable to determine package info/,
|
459
|
+
self_dep_error: /Package '(?<path>.*)' is listed as a dependency of itself./,
|
460
|
+
incompatible_constraints: /Incompatible constraints in requirements/
|
461
|
+
}.freeze,
|
462
|
+
T::Hash[T.nilable(String), Regexp]
|
463
|
+
)
|
445
464
|
|
446
465
|
sig do
|
447
466
|
params(
|
@@ -502,7 +521,7 @@ module Dependabot
|
|
502
521
|
SERVER_ERROR_CODES.each do |(_error_codes, error_regex)|
|
503
522
|
next unless error.message.match?(error_regex)
|
504
523
|
|
505
|
-
index_url = URI.extract(error.message.to_s).last
|
524
|
+
index_url = URI.extract(error.message.to_s).last.then { sanitize_url(_1) }
|
506
525
|
raise InconsistentRegistryResponse, index_url
|
507
526
|
end
|
508
527
|
|
@@ -515,7 +534,7 @@ module Dependabot
|
|
515
534
|
CLIENT_ERROR_CODES.each do |(_error_codes, error_regex)|
|
516
535
|
next unless error.message.match?(error_regex)
|
517
536
|
|
518
|
-
index_url = URI.extract(error.message.to_s).last
|
537
|
+
index_url = URI.extract(error.message.to_s).last.then { sanitize_url(_1) }
|
519
538
|
raise PrivateSourceAuthenticationFailure, index_url
|
520
539
|
end
|
521
540
|
|
@@ -39,8 +39,12 @@ module Dependabot
|
|
39
39
|
latest_resolvable_version: T.nilable(String)
|
40
40
|
).void
|
41
41
|
end
|
42
|
-
def initialize(
|
43
|
-
|
42
|
+
def initialize(
|
43
|
+
requirements:,
|
44
|
+
update_strategy:,
|
45
|
+
has_lockfile:,
|
46
|
+
latest_resolvable_version:
|
47
|
+
)
|
44
48
|
@requirements = T.let(requirements, T::Array[T::Hash[Symbol, T.untyped]])
|
45
49
|
@update_strategy = T.let(update_strategy, Dependabot::RequirementsUpdateStrategy)
|
46
50
|
@has_lockfile = T.let(has_lockfile, T::Boolean)
|
@@ -172,9 +176,11 @@ module Dependabot
|
|
172
176
|
|
173
177
|
sig { params(req_string: String).returns(String) }
|
174
178
|
def add_new_requirement_option(req_string)
|
175
|
-
option_to_copy = T.must(
|
176
|
-
|
177
|
-
|
179
|
+
option_to_copy = T.must(
|
180
|
+
T.must(req_string.split(PYPROJECT_OR_SEPARATOR).last)
|
181
|
+
.split(PYPROJECT_SEPARATOR).first
|
182
|
+
).strip
|
183
|
+
operator = option_to_copy.gsub(/\d.*/, "").strip
|
178
184
|
|
179
185
|
new_option =
|
180
186
|
case operator
|
@@ -335,9 +341,13 @@ module Dependabot
|
|
335
341
|
# Updates the version in a constraint to be the given version
|
336
342
|
sig { params(req_string: String, version_to_be_permitted: String).returns(String) }
|
337
343
|
def bump_version(req_string, version_to_be_permitted)
|
338
|
-
old_version = T.must(
|
339
|
-
|
340
|
-
|
344
|
+
old_version = T.must(
|
345
|
+
T.must(
|
346
|
+
req_string
|
347
|
+
.match(/(#{RequirementParser::VERSION})/o)
|
348
|
+
)
|
349
|
+
.captures.first
|
350
|
+
)
|
341
351
|
|
342
352
|
req_string.sub(
|
343
353
|
old_version,
|
@@ -91,14 +91,18 @@ module Dependabot
|
|
91
91
|
|
92
92
|
@epoch = T.let(matches["epoch"].to_i, Integer)
|
93
93
|
@release_segment = T.let(matches["release"]&.split(".")&.map(&:to_i) || [], T::Array[Integer])
|
94
|
-
@pre = T.let(
|
95
|
-
|
94
|
+
@pre = T.let(
|
95
|
+
parse_letter_version(matches["pre_l"], matches["pre_n"]),
|
96
|
+
T.nilable(T::Array[T.any(String, Integer)])
|
97
|
+
)
|
96
98
|
@post = T.let(
|
97
99
|
parse_letter_version(matches["post_l"], matches["post_n1"] || matches["post_n2"]),
|
98
100
|
T.nilable(T::Array[T.any(String, Integer)])
|
99
101
|
)
|
100
|
-
@dev = T.let(
|
101
|
-
|
102
|
+
@dev = T.let(
|
103
|
+
parse_letter_version(matches["dev_l"], matches["dev_n"]),
|
104
|
+
T.nilable(T::Array[T.any(String, Integer)])
|
105
|
+
)
|
102
106
|
@local = T.let(parse_local_version(matches["local"]), T.nilable(T::Array[T.any(String, Integer)]))
|
103
107
|
super(matches["release"] || "")
|
104
108
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dependabot-python
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.335.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dependabot
|
@@ -15,14 +15,14 @@ dependencies:
|
|
15
15
|
requirements:
|
16
16
|
- - '='
|
17
17
|
- !ruby/object:Gem::Version
|
18
|
-
version: 0.
|
18
|
+
version: 0.335.0
|
19
19
|
type: :runtime
|
20
20
|
prerelease: false
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
22
22
|
requirements:
|
23
23
|
- - '='
|
24
24
|
- !ruby/object:Gem::Version
|
25
|
-
version: 0.
|
25
|
+
version: 0.335.0
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: debug
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
@@ -113,56 +113,56 @@ dependencies:
|
|
113
113
|
requirements:
|
114
114
|
- - "~>"
|
115
115
|
- !ruby/object:Gem::Version
|
116
|
-
version: '1.
|
116
|
+
version: '1.80'
|
117
117
|
type: :development
|
118
118
|
prerelease: false
|
119
119
|
version_requirements: !ruby/object:Gem::Requirement
|
120
120
|
requirements:
|
121
121
|
- - "~>"
|
122
122
|
- !ruby/object:Gem::Version
|
123
|
-
version: '1.
|
123
|
+
version: '1.80'
|
124
124
|
- !ruby/object:Gem::Dependency
|
125
125
|
name: rubocop-performance
|
126
126
|
requirement: !ruby/object:Gem::Requirement
|
127
127
|
requirements:
|
128
128
|
- - "~>"
|
129
129
|
- !ruby/object:Gem::Version
|
130
|
-
version: '1.
|
130
|
+
version: '1.26'
|
131
131
|
type: :development
|
132
132
|
prerelease: false
|
133
133
|
version_requirements: !ruby/object:Gem::Requirement
|
134
134
|
requirements:
|
135
135
|
- - "~>"
|
136
136
|
- !ruby/object:Gem::Version
|
137
|
-
version: '1.
|
137
|
+
version: '1.26'
|
138
138
|
- !ruby/object:Gem::Dependency
|
139
139
|
name: rubocop-rspec
|
140
140
|
requirement: !ruby/object:Gem::Requirement
|
141
141
|
requirements:
|
142
142
|
- - "~>"
|
143
143
|
- !ruby/object:Gem::Version
|
144
|
-
version: '
|
144
|
+
version: '3.7'
|
145
145
|
type: :development
|
146
146
|
prerelease: false
|
147
147
|
version_requirements: !ruby/object:Gem::Requirement
|
148
148
|
requirements:
|
149
149
|
- - "~>"
|
150
150
|
- !ruby/object:Gem::Version
|
151
|
-
version: '
|
151
|
+
version: '3.7'
|
152
152
|
- !ruby/object:Gem::Dependency
|
153
153
|
name: rubocop-sorbet
|
154
154
|
requirement: !ruby/object:Gem::Requirement
|
155
155
|
requirements:
|
156
156
|
- - "~>"
|
157
157
|
- !ruby/object:Gem::Version
|
158
|
-
version: '0.
|
158
|
+
version: '0.10'
|
159
159
|
type: :development
|
160
160
|
prerelease: false
|
161
161
|
version_requirements: !ruby/object:Gem::Requirement
|
162
162
|
requirements:
|
163
163
|
- - "~>"
|
164
164
|
- !ruby/object:Gem::Version
|
165
|
-
version: '0.
|
165
|
+
version: '0.10'
|
166
166
|
- !ruby/object:Gem::Dependency
|
167
167
|
name: simplecov
|
168
168
|
requirement: !ruby/object:Gem::Requirement
|
@@ -290,7 +290,7 @@ licenses:
|
|
290
290
|
- MIT
|
291
291
|
metadata:
|
292
292
|
bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
|
293
|
-
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.
|
293
|
+
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.335.0
|
294
294
|
rdoc_options: []
|
295
295
|
require_paths:
|
296
296
|
- lib
|