dependabot-uv 0.327.0 → 0.330.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/dependabot/uv/file_fetcher.rb +127 -40
- data/lib/dependabot/uv/file_parser.rb +11 -12
- data/lib/dependabot/uv/requirements_file_matcher.rb +6 -4
- data/lib/dependabot/uv.rb +13 -0
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 439dcd622fb16fb120a560e350814994af41808a9b451be75eefa37c1558512b
|
|
4
|
+
data.tar.gz: 1a614a6c05a9081496efb729181b7ffb399c64eac080584895d00b26d7cfcb56
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3b0676d7407422abeefa96a1443481154794861a42d8359200cf09bcadbd32f86cb0049af2bd0de48c2fa7ac27d9bed2957be3657b7787d18fc28254e716c481
|
|
7
|
+
data.tar.gz: 2e7d837110017ea0c0dd71abcf58e6afa2ee6c068a9f7078a3db1fa3c5b6b426059fa4a73e6270754a3730a6412840f37f55ce1be3452deebeffa38b47c4a2e5
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# typed:
|
|
1
|
+
# typed: strict
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require "toml-rb"
|
|
@@ -6,6 +6,7 @@ require "sorbet-runtime"
|
|
|
6
6
|
|
|
7
7
|
require "dependabot/file_fetchers"
|
|
8
8
|
require "dependabot/file_fetchers/base"
|
|
9
|
+
require "dependabot/uv"
|
|
9
10
|
require "dependabot/uv/language_version_manager"
|
|
10
11
|
require "dependabot/uv/requirements_file_matcher"
|
|
11
12
|
require "dependabot/uv/requirement_parser"
|
|
@@ -22,14 +23,20 @@ module Dependabot
|
|
|
22
23
|
CHILD_REQUIREMENT_REGEX = /^-r\s?(?<path>.*\.(?:txt|in))/
|
|
23
24
|
CONSTRAINT_REGEX = /^-c\s?(?<path>.*\.(?:txt|in))/
|
|
24
25
|
DEPENDENCY_TYPES = %w(packages dev-packages).freeze
|
|
25
|
-
REQUIREMENT_FILE_PATTERNS = {
|
|
26
|
+
REQUIREMENT_FILE_PATTERNS = T.let({
|
|
26
27
|
extensions: [".txt", ".in"],
|
|
27
28
|
filenames: ["uv.lock"]
|
|
28
|
-
}.freeze
|
|
29
|
+
}.freeze, T::Hash[Symbol, T::Array[String]])
|
|
30
|
+
|
|
29
31
|
MAX_FILE_SIZE = 500_000
|
|
30
32
|
|
|
33
|
+
sig { override.params(filenames: T::Array[String]).returns(T::Boolean) }
|
|
31
34
|
def self.required_files_in?(filenames)
|
|
32
|
-
return true if filenames.any?
|
|
35
|
+
return true if filenames.any? do |name|
|
|
36
|
+
T.must(REQUIREMENT_FILE_PATTERNS[:extensions]).any? do |ext|
|
|
37
|
+
name.end_with?(ext)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
33
40
|
|
|
34
41
|
# If there is a directory of requirements return true
|
|
35
42
|
return true if filenames.include?("requirements")
|
|
@@ -38,10 +45,12 @@ module Dependabot
|
|
|
38
45
|
filenames.include?("pyproject.toml")
|
|
39
46
|
end
|
|
40
47
|
|
|
48
|
+
sig { override.returns(String) }
|
|
41
49
|
def self.required_files_message
|
|
42
50
|
"Repo must contain a requirements.txt, uv.lock, requirements.in, or pyproject.toml" \
|
|
43
51
|
end
|
|
44
52
|
|
|
53
|
+
sig { override.returns(T.nilable(T::Hash[Symbol, T.untyped])) }
|
|
45
54
|
def ecosystem_versions
|
|
46
55
|
# Hmm... it's weird that this calls file parser methods, but here we are in the file fetcher... for all
|
|
47
56
|
# ecosystems our goal is to extract the user specified versions, so we'll need to do file parsing... so should
|
|
@@ -83,16 +92,19 @@ module Dependabot
|
|
|
83
92
|
|
|
84
93
|
private
|
|
85
94
|
|
|
95
|
+
sig { params(fetched_files: T::Array[Dependabot::DependencyFile]).returns(T::Array[Dependabot::DependencyFile]) }
|
|
86
96
|
def uniq_files(fetched_files)
|
|
87
97
|
uniq_files = fetched_files.reject(&:support_file?).uniq
|
|
88
98
|
uniq_files += fetched_files
|
|
89
99
|
.reject { |f| uniq_files.map(&:name).include?(f.name) }
|
|
90
100
|
end
|
|
91
101
|
|
|
102
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
92
103
|
def pyproject_files
|
|
93
104
|
[pyproject].compact
|
|
94
105
|
end
|
|
95
106
|
|
|
107
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
96
108
|
def requirement_files
|
|
97
109
|
[
|
|
98
110
|
*requirements_txt_files,
|
|
@@ -101,10 +113,11 @@ module Dependabot
|
|
|
101
113
|
]
|
|
102
114
|
end
|
|
103
115
|
|
|
116
|
+
sig { returns(T.nilable(Dependabot::DependencyFile)) }
|
|
104
117
|
def python_version_file
|
|
105
118
|
return @python_version_file if defined?(@python_version_file)
|
|
106
119
|
|
|
107
|
-
@python_version_file = fetch_support_file(".python-version")
|
|
120
|
+
@python_version_file = T.let(fetch_support_file(".python-version"), T.nilable(Dependabot::DependencyFile))
|
|
108
121
|
|
|
109
122
|
return @python_version_file if @python_version_file
|
|
110
123
|
return if [".", "/"].include?(directory)
|
|
@@ -116,66 +129,77 @@ module Dependabot
|
|
|
116
129
|
&.tap { |f| f.name = ".python-version" }
|
|
117
130
|
end
|
|
118
131
|
|
|
132
|
+
sig { returns(T.nilable(Dependabot::DependencyFile)) }
|
|
119
133
|
def pyproject
|
|
120
134
|
return @pyproject if defined?(@pyproject)
|
|
121
135
|
|
|
122
|
-
@pyproject = fetch_file_if_present("pyproject.toml")
|
|
136
|
+
@pyproject = T.let(fetch_file_if_present("pyproject.toml"), T.nilable(Dependabot::DependencyFile))
|
|
123
137
|
end
|
|
124
138
|
|
|
139
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
125
140
|
def requirements_txt_files
|
|
126
141
|
req_txt_and_in_files.select { |f| f.name.end_with?(".txt") }
|
|
127
142
|
end
|
|
128
143
|
|
|
144
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
129
145
|
def requirements_in_files
|
|
130
146
|
req_txt_and_in_files.select { |f| f.name.end_with?(".in") } +
|
|
131
147
|
child_requirement_in_files
|
|
132
148
|
end
|
|
133
149
|
|
|
150
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
134
151
|
def uv_lock_files
|
|
135
152
|
req_txt_and_in_files.select { |f| f.name.end_with?("uv.lock") } +
|
|
136
153
|
child_uv_lock_files
|
|
137
154
|
end
|
|
138
155
|
|
|
156
|
+
sig { returns(TomlContent) }
|
|
139
157
|
def parsed_pyproject
|
|
140
158
|
raise "No pyproject.toml" unless pyproject
|
|
141
159
|
|
|
142
|
-
@parsed_pyproject ||= TomlRB.parse(pyproject.content)
|
|
160
|
+
@parsed_pyproject ||= T.let(TomlRB.parse(T.must(pyproject).content), T.nilable(TomlContent))
|
|
143
161
|
rescue TomlRB::ParseError, TomlRB::ValueOverwriteError
|
|
144
|
-
raise Dependabot::DependencyFileNotParseable, pyproject.path
|
|
162
|
+
raise Dependabot::DependencyFileNotParseable, T.must(pyproject).path
|
|
145
163
|
end
|
|
146
164
|
|
|
165
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
147
166
|
def req_txt_and_in_files
|
|
148
167
|
return @req_txt_and_in_files if @req_txt_and_in_files
|
|
149
168
|
|
|
150
|
-
@req_txt_and_in_files = []
|
|
151
|
-
@req_txt_and_in_files
|
|
169
|
+
@req_txt_and_in_files = T.let([], T.nilable(T::Array[Dependabot::DependencyFile]))
|
|
170
|
+
@req_txt_and_in_files = T.must(@req_txt_and_in_files) + fetch_requirement_files_from_path
|
|
152
171
|
@req_txt_and_in_files += fetch_requirement_files_from_dirs
|
|
153
172
|
|
|
154
173
|
@req_txt_and_in_files
|
|
155
174
|
end
|
|
156
175
|
|
|
176
|
+
sig { params(requirements_dir: OpenStruct).returns(T::Array[Dependabot::DependencyFile]) }
|
|
157
177
|
def req_files_for_dir(requirements_dir)
|
|
158
178
|
dir = directory.gsub(%r{(^/|/$)}, "")
|
|
159
179
|
relative_reqs_dir =
|
|
160
|
-
requirements_dir.path.gsub(%r{^/?#{Regexp.escape(dir)}/?}, "")
|
|
180
|
+
T.unsafe(requirements_dir).path.gsub(%r{^/?#{Regexp.escape(dir)}/?}, "")
|
|
161
181
|
|
|
162
182
|
fetch_requirement_files_from_path(relative_reqs_dir)
|
|
163
183
|
end
|
|
164
184
|
|
|
185
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
165
186
|
def child_requirement_txt_files
|
|
166
187
|
child_requirement_files.select { |f| f.name.end_with?(".txt") }
|
|
167
188
|
end
|
|
168
189
|
|
|
190
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
169
191
|
def child_requirement_in_files
|
|
170
192
|
child_requirement_files.select { |f| f.name.end_with?(".in") }
|
|
171
193
|
end
|
|
172
194
|
|
|
195
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
173
196
|
def child_uv_lock_files
|
|
174
197
|
child_requirement_files.select { |f| f.name.end_with?("uv.lock") }
|
|
175
198
|
end
|
|
176
199
|
|
|
200
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
177
201
|
def child_requirement_files
|
|
178
|
-
@child_requirement_files ||=
|
|
202
|
+
@child_requirement_files ||= T.let(
|
|
179
203
|
begin
|
|
180
204
|
fetched_files = req_txt_and_in_files.dup
|
|
181
205
|
req_txt_and_in_files.flat_map do |requirement_file|
|
|
@@ -187,11 +211,21 @@ module Dependabot
|
|
|
187
211
|
fetched_files += child_files
|
|
188
212
|
child_files
|
|
189
213
|
end
|
|
190
|
-
end
|
|
214
|
+
end, T.nilable(T::Array[Dependabot::DependencyFile])
|
|
215
|
+
)
|
|
191
216
|
end
|
|
192
217
|
|
|
218
|
+
sig do
|
|
219
|
+
params(
|
|
220
|
+
file: Dependabot::DependencyFile,
|
|
221
|
+
previously_fetched_files: T::Array[Dependabot::DependencyFile]
|
|
222
|
+
).returns(T::Array[Dependabot::DependencyFile])
|
|
223
|
+
end
|
|
193
224
|
def fetch_child_requirement_files(file:, previously_fetched_files:)
|
|
194
|
-
|
|
225
|
+
content = file.content
|
|
226
|
+
return [] if content.nil?
|
|
227
|
+
|
|
228
|
+
paths = content.scan(CHILD_REQUIREMENT_REGEX).flatten
|
|
195
229
|
current_dir = File.dirname(file.name)
|
|
196
230
|
|
|
197
231
|
paths.flat_map do |path|
|
|
@@ -210,13 +244,17 @@ module Dependabot
|
|
|
210
244
|
end.compact
|
|
211
245
|
end
|
|
212
246
|
|
|
247
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
213
248
|
def constraints_files
|
|
214
249
|
all_requirement_files = requirements_txt_files +
|
|
215
250
|
child_requirement_txt_files
|
|
216
251
|
|
|
217
252
|
constraints_paths = all_requirement_files.map do |req_file|
|
|
218
253
|
current_dir = File.dirname(req_file.name)
|
|
219
|
-
|
|
254
|
+
content = req_file.content
|
|
255
|
+
next [] if content.nil?
|
|
256
|
+
|
|
257
|
+
paths = content.scan(CONSTRAINT_REGEX).flatten
|
|
220
258
|
|
|
221
259
|
paths.map do |path|
|
|
222
260
|
path = File.join(current_dir, path) unless current_dir == "."
|
|
@@ -227,12 +265,15 @@ module Dependabot
|
|
|
227
265
|
constraints_paths.map { |path| fetch_file_from_host(path) }
|
|
228
266
|
end
|
|
229
267
|
|
|
268
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
230
269
|
def project_files
|
|
231
270
|
project_files = T.let([], T::Array[Dependabot::DependencyFile])
|
|
232
271
|
unfetchable_deps = []
|
|
233
272
|
|
|
234
273
|
path_dependencies.each do |dep|
|
|
235
274
|
path = dep[:path]
|
|
275
|
+
next if path.nil?
|
|
276
|
+
|
|
236
277
|
project_files += fetch_project_file(path)
|
|
237
278
|
rescue Dependabot::DependencyFileNotFound
|
|
238
279
|
unfetchable_deps << "\"#{dep[:name]}\" at #{cleanpath(File.join(directory, dep[:file]))}"
|
|
@@ -243,6 +284,7 @@ module Dependabot
|
|
|
243
284
|
project_files
|
|
244
285
|
end
|
|
245
286
|
|
|
287
|
+
sig { params(path: String).returns(T::Array[Dependabot::DependencyFile]) }
|
|
246
288
|
def fetch_project_file(path)
|
|
247
289
|
project_files = []
|
|
248
290
|
|
|
@@ -258,15 +300,17 @@ module Dependabot
|
|
|
258
300
|
project_files
|
|
259
301
|
end
|
|
260
302
|
|
|
303
|
+
sig { params(path: String).returns(T::Boolean) }
|
|
261
304
|
def sdist_or_wheel?(path)
|
|
262
305
|
path.end_with?(".tar.gz", ".whl", ".zip")
|
|
263
306
|
end
|
|
264
307
|
|
|
308
|
+
sig { params(file: Dependabot::DependencyFile).returns(T::Boolean) }
|
|
265
309
|
def requirements_file?(file)
|
|
266
|
-
return false unless file.content
|
|
310
|
+
return false unless file.content&.valid_encoding?
|
|
267
311
|
return true if file.name.match?(/requirements/x)
|
|
268
312
|
|
|
269
|
-
file.content.lines.all? do |line|
|
|
313
|
+
T.must(file.content).lines.all? do |line|
|
|
270
314
|
next true if line.strip.empty?
|
|
271
315
|
next true if line.strip.start_with?("#", "-r ", "-c ", "-e ", "--")
|
|
272
316
|
|
|
@@ -274,6 +318,7 @@ module Dependabot
|
|
|
274
318
|
end
|
|
275
319
|
end
|
|
276
320
|
|
|
321
|
+
sig { returns(T::Array[PathDependency]) }
|
|
277
322
|
def path_dependencies
|
|
278
323
|
[
|
|
279
324
|
*requirement_txt_path_dependencies,
|
|
@@ -282,47 +327,74 @@ module Dependabot
|
|
|
282
327
|
]
|
|
283
328
|
end
|
|
284
329
|
|
|
330
|
+
sig { returns(T::Array[PathDependency]) }
|
|
285
331
|
def requirement_txt_path_dependencies
|
|
286
332
|
(requirements_txt_files + child_requirement_txt_files)
|
|
287
333
|
.map { |req_file| parse_requirement_path_dependencies(req_file) }
|
|
288
334
|
.flatten.uniq { |dep| dep[:path] }
|
|
289
335
|
end
|
|
290
336
|
|
|
337
|
+
sig { returns(T::Array[PathDependency]) }
|
|
291
338
|
def requirement_in_path_dependencies
|
|
292
339
|
requirements_in_files
|
|
293
340
|
.map { |req_file| parse_requirement_path_dependencies(req_file) }
|
|
294
341
|
.flatten.uniq { |dep| dep[:path] }
|
|
295
342
|
end
|
|
296
343
|
|
|
344
|
+
sig { params(req_file: Dependabot::DependencyFile).returns(T::Array[PathDependency]) }
|
|
297
345
|
def parse_requirement_path_dependencies(req_file)
|
|
298
346
|
# If this is a pip-compile lockfile, rely on whatever path dependencies we found in the main manifest
|
|
299
347
|
return [] if requirements_in_file_matcher.compiled_file?(req_file)
|
|
300
348
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
.filter_map do |n, p|
|
|
305
|
-
{ name: n.strip, path: p.strip, file: req_file.name } unless p.include?("://")
|
|
306
|
-
end
|
|
307
|
-
|
|
308
|
-
editable_reqs =
|
|
309
|
-
req_file.content
|
|
310
|
-
.scan(/(?<name>^(?:-e)\s+['"]?(?:file:)?(?<path>.*?)(?=\[|#|'|"|$))/)
|
|
311
|
-
.filter_map do |n, p|
|
|
312
|
-
{ name: n.strip, path: p.strip, file: req_file.name } unless p.include?("://") || p.include?("git@")
|
|
313
|
-
end
|
|
349
|
+
content = T.must(req_file.content)
|
|
350
|
+
uneditable_reqs = parse_uneditable_requirements(content, req_file.name)
|
|
351
|
+
editable_reqs = parse_editable_requirements(content, req_file.name)
|
|
314
352
|
|
|
315
353
|
uneditable_reqs + editable_reqs
|
|
316
354
|
end
|
|
317
355
|
|
|
356
|
+
sig { params(content: String, file_name: String).returns(T::Array[PathDependency]) }
|
|
357
|
+
def parse_uneditable_requirements(content, file_name)
|
|
358
|
+
content
|
|
359
|
+
.scan(/(?<name>^['"]?(?:file:)?(?<path>\..*?)(?=\[|#|'|"|$))/)
|
|
360
|
+
.filter_map { |match_data| process_requirement_match(T.cast(match_data, T::Array[String]), file_name, false) }
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
sig { params(content: String, file_name: String).returns(T::Array[PathDependency]) }
|
|
364
|
+
def parse_editable_requirements(content, file_name)
|
|
365
|
+
content
|
|
366
|
+
.scan(/(?<name>^(?:-e)\s+['"]?(?:file:)?(?<path>.*?)(?=\[|#|'|"|$))/)
|
|
367
|
+
.filter_map { |match_data| process_requirement_match(T.cast(match_data, T::Array[String]), file_name, true) }
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
sig do
|
|
371
|
+
params(
|
|
372
|
+
match_data: T::Array[String],
|
|
373
|
+
file_name: String,
|
|
374
|
+
editable: T::Boolean
|
|
375
|
+
).returns(T.nilable(PathDependency))
|
|
376
|
+
end
|
|
377
|
+
def process_requirement_match(match_data, file_name, editable)
|
|
378
|
+
name, path = match_data
|
|
379
|
+
return nil if name.nil? || path.nil?
|
|
380
|
+
return nil if path.include?("://")
|
|
381
|
+
return nil if editable && path.include?("git@")
|
|
382
|
+
|
|
383
|
+
{ name: name.strip, path: path.strip, file: file_name }
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
sig { params(path: String).returns(String) }
|
|
318
387
|
def cleanpath(path)
|
|
319
388
|
Pathname.new(path).cleanpath.to_path
|
|
320
389
|
end
|
|
321
390
|
|
|
391
|
+
sig { returns(Dependabot::Uv::RequiremenstFileMatcher) }
|
|
322
392
|
def requirements_in_file_matcher
|
|
323
|
-
@requirements_in_file_matcher ||= RequiremenstFileMatcher.new(requirements_in_files)
|
|
393
|
+
@requirements_in_file_matcher ||= T.let(RequiremenstFileMatcher.new(requirements_in_files),
|
|
394
|
+
T.nilable(Dependabot::Uv::RequiremenstFileMatcher))
|
|
324
395
|
end
|
|
325
396
|
|
|
397
|
+
sig { returns(T::Array[PathDependency]) }
|
|
326
398
|
def uv_sources_path_dependencies
|
|
327
399
|
return [] unless pyproject
|
|
328
400
|
|
|
@@ -334,37 +406,52 @@ module Dependabot
|
|
|
334
406
|
{
|
|
335
407
|
name: name,
|
|
336
408
|
path: source_config["path"],
|
|
337
|
-
file: pyproject.name
|
|
409
|
+
file: T.must(pyproject).name
|
|
338
410
|
}
|
|
339
411
|
end
|
|
340
412
|
end
|
|
341
413
|
end
|
|
342
414
|
|
|
415
|
+
sig { params(path: T.nilable(T.any(Pathname, String))).returns(T::Array[Dependabot::DependencyFile]) }
|
|
343
416
|
def fetch_requirement_files_from_path(path = nil)
|
|
344
417
|
contents = path ? repo_contents(dir: path) : repo_contents
|
|
345
418
|
filter_requirement_files(contents, base_path: path)
|
|
346
419
|
end
|
|
347
420
|
|
|
421
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
348
422
|
def fetch_requirement_files_from_dirs
|
|
349
423
|
repo_contents
|
|
350
|
-
.select { |f| f.type == "dir" }
|
|
424
|
+
.select { |f| T.unsafe(f).type == "dir" }
|
|
351
425
|
.flat_map { |dir| req_files_for_dir(dir) }
|
|
352
426
|
end
|
|
353
427
|
|
|
428
|
+
sig do
|
|
429
|
+
params(
|
|
430
|
+
contents: T::Array[OpenStruct],
|
|
431
|
+
base_path: T.nilable(T.any(Pathname, String))
|
|
432
|
+
).returns(T::Array[Dependabot::DependencyFile])
|
|
433
|
+
end
|
|
354
434
|
def filter_requirement_files(contents, base_path: nil)
|
|
355
435
|
contents
|
|
356
|
-
.select { |f| f.type == "file" }
|
|
357
|
-
.select { |f| file_matches_requirement_pattern?(f.name) }
|
|
358
|
-
.reject { |f| f.size > MAX_FILE_SIZE }
|
|
359
|
-
.map { |f| fetch_file_with_path(f.name, base_path) }
|
|
360
|
-
.select { |f| REQUIREMENT_FILE_PATTERNS[:filenames].include?(f.name) || requirements_file?(f) }
|
|
436
|
+
.select { |f| T.unsafe(f).type == "file" }
|
|
437
|
+
.select { |f| file_matches_requirement_pattern?(T.unsafe(f).name) }
|
|
438
|
+
.reject { |f| T.unsafe(f).size > MAX_FILE_SIZE }
|
|
439
|
+
.map { |f| fetch_file_with_path(T.unsafe(f).name, base_path) }
|
|
440
|
+
.select { |f| T.must(REQUIREMENT_FILE_PATTERNS[:filenames]).include?(f.name) || requirements_file?(f) }
|
|
361
441
|
end
|
|
362
442
|
|
|
443
|
+
sig { params(filename: String).returns(T::Boolean) }
|
|
363
444
|
def file_matches_requirement_pattern?(filename)
|
|
364
|
-
REQUIREMENT_FILE_PATTERNS[:extensions].any? { |ext| filename.end_with?(ext) } ||
|
|
365
|
-
REQUIREMENT_FILE_PATTERNS[:filenames].any?(filename)
|
|
445
|
+
T.must(REQUIREMENT_FILE_PATTERNS[:extensions]).any? { |ext| filename.end_with?(ext) } ||
|
|
446
|
+
T.must(REQUIREMENT_FILE_PATTERNS[:filenames]).any?(filename)
|
|
366
447
|
end
|
|
367
448
|
|
|
449
|
+
sig do
|
|
450
|
+
params(
|
|
451
|
+
filename: T.any(Pathname, String),
|
|
452
|
+
base_path: T.nilable(T.any(Pathname, String))
|
|
453
|
+
).returns(Dependabot::DependencyFile)
|
|
454
|
+
end
|
|
368
455
|
def fetch_file_with_path(filename, base_path)
|
|
369
456
|
path = base_path ? File.join(base_path, filename) : filename
|
|
370
457
|
fetch_file_from_host(path)
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require "dependabot/dependency"
|
|
5
|
+
require "dependabot/dependency_file"
|
|
5
6
|
require "dependabot/file_parsers"
|
|
6
7
|
require "dependabot/file_parsers/base"
|
|
7
8
|
require "dependabot/file_parsers/base/dependency_set"
|
|
@@ -20,6 +21,7 @@ module Dependabot
|
|
|
20
21
|
module Uv
|
|
21
22
|
class FileParser < Dependabot::FileParsers::Base
|
|
22
23
|
extend T::Sig
|
|
24
|
+
|
|
23
25
|
require_relative "file_parser/pyproject_files_parser"
|
|
24
26
|
require_relative "file_parser/python_requirement_parser"
|
|
25
27
|
|
|
@@ -128,14 +130,11 @@ module Dependabot
|
|
|
128
130
|
nil
|
|
129
131
|
end
|
|
130
132
|
|
|
131
|
-
sig { params(package_manager: String, version: String).
|
|
133
|
+
sig { params(package_manager: String, version: String).void }
|
|
132
134
|
def log_if_version_malformed(package_manager, version)
|
|
133
|
-
if version.match?(/^\d+(?:\.\d+)*$/)
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
Dependabot.logger.warn("Detected #{package_manager} with malformed version #{version}")
|
|
137
|
-
false
|
|
138
|
-
end
|
|
135
|
+
return if version.match?(/^\d+(?:\.\d+)*$/)
|
|
136
|
+
|
|
137
|
+
Dependabot.logger.warn("Detected #{package_manager} with malformed version #{version}")
|
|
139
138
|
end
|
|
140
139
|
|
|
141
140
|
sig { returns(String) }
|
|
@@ -273,12 +272,12 @@ module Dependabot
|
|
|
273
272
|
def marker_satisfied?(marker, python_version)
|
|
274
273
|
conditions = marker.split(/\s+(and|or)\s+/)
|
|
275
274
|
|
|
276
|
-
result = T.let(evaluate_condition(conditions.shift, python_version), T::Boolean)
|
|
275
|
+
result = T.let(evaluate_condition?(conditions.shift, python_version), T::Boolean)
|
|
277
276
|
|
|
278
277
|
until conditions.empty?
|
|
279
278
|
operator = conditions.shift
|
|
280
279
|
next_condition = conditions.shift
|
|
281
|
-
next_result = evaluate_condition(next_condition, python_version)
|
|
280
|
+
next_result = evaluate_condition?(next_condition, python_version)
|
|
282
281
|
|
|
283
282
|
result = if operator == "and"
|
|
284
283
|
result && next_result
|
|
@@ -294,7 +293,7 @@ module Dependabot
|
|
|
294
293
|
params(condition: T.untyped,
|
|
295
294
|
python_version: T.any(String, Integer, Gem::Version)).returns(T::Boolean)
|
|
296
295
|
end
|
|
297
|
-
def evaluate_condition(condition, python_version)
|
|
296
|
+
def evaluate_condition?(condition, python_version)
|
|
298
297
|
operator, version = condition.match(/([<>=!]=?)\s*"?([\d.]+)"?/)&.captures
|
|
299
298
|
|
|
300
299
|
case operator
|
|
@@ -385,9 +384,9 @@ module Dependabot
|
|
|
385
384
|
@pyproject ||= T.let(get_original_file("pyproject.toml"), T.nilable(DependencyFile))
|
|
386
385
|
end
|
|
387
386
|
|
|
388
|
-
sig { returns(T::Array[
|
|
387
|
+
sig { returns(T::Array[DependencyFile]) }
|
|
389
388
|
def requirements_in_files
|
|
390
|
-
|
|
389
|
+
dependency_files.select { |f| f.name.end_with?(".in") }
|
|
391
390
|
end
|
|
392
391
|
|
|
393
392
|
sig { returns(RequiremenstFileMatcher) }
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
# typed:
|
|
1
|
+
# typed: strong
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
+
require "dependabot/dependency_file"
|
|
5
|
+
|
|
4
6
|
module Dependabot
|
|
5
7
|
module Uv
|
|
6
8
|
class RequiremenstFileMatcher
|
|
7
9
|
extend T::Sig
|
|
8
10
|
|
|
9
|
-
sig { params(requirements_in_files: T::Array[
|
|
11
|
+
sig { params(requirements_in_files: T::Array[DependencyFile]).void }
|
|
10
12
|
def initialize(requirements_in_files)
|
|
11
13
|
@requirements_in_files = requirements_in_files
|
|
12
14
|
end
|
|
@@ -21,12 +23,12 @@ module Dependabot
|
|
|
21
23
|
return true if file.content&.match?(output_file_regex(name))
|
|
22
24
|
|
|
23
25
|
basename = name.gsub(/\.txt$/, "")
|
|
24
|
-
requirements_in_files.any? { |f| f.
|
|
26
|
+
requirements_in_files.any? { |f| f.name == basename + ".in" }
|
|
25
27
|
end
|
|
26
28
|
|
|
27
29
|
private
|
|
28
30
|
|
|
29
|
-
sig { returns(T::Array[
|
|
31
|
+
sig { returns(T::Array[DependencyFile]) }
|
|
30
32
|
attr_reader :requirements_in_files
|
|
31
33
|
|
|
32
34
|
sig { params(filename: T.any(String, Symbol)).returns(String) }
|
data/lib/dependabot/uv.rb
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
# typed: strict
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
+
require "sorbet-runtime"
|
|
5
|
+
|
|
6
|
+
# Type definitions for repository file structures
|
|
7
|
+
module Dependabot
|
|
8
|
+
module Uv
|
|
9
|
+
extend T::Sig
|
|
10
|
+
|
|
11
|
+
PathDependency = T.type_alias { { name: String, path: String, file: String } }
|
|
12
|
+
|
|
13
|
+
TomlContent = T.type_alias { T::Hash[String, T.untyped] }
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
4
17
|
# These all need to be required so the various classes can be registered in a
|
|
5
18
|
# lookup table of package manager names to concrete classes.
|
|
6
19
|
require "dependabot/uv/file_fetcher"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dependabot-uv
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.330.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.330.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.330.0
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: debug
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -284,7 +284,7 @@ licenses:
|
|
|
284
284
|
- MIT
|
|
285
285
|
metadata:
|
|
286
286
|
bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
|
|
287
|
-
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.
|
|
287
|
+
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.330.0
|
|
288
288
|
rdoc_options: []
|
|
289
289
|
require_paths:
|
|
290
290
|
- lib
|