dependabot-uv 0.332.0 → 0.333.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.
@@ -1,7 +1,9 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "open3"
5
+ require "sorbet-runtime"
6
+
5
7
  require "dependabot/dependency"
6
8
  require "dependabot/uv/requirement_parser"
7
9
  require "dependabot/uv/file_fetcher"
@@ -18,40 +20,64 @@ module Dependabot
18
20
  class FileUpdater
19
21
  # rubocop:disable Metrics/ClassLength
20
22
  class CompileFileUpdater
23
+ extend T::Sig
24
+
21
25
  require_relative "requirement_replacer"
22
26
  require_relative "requirement_file_updater"
23
27
 
24
- UNSAFE_PACKAGES = %w(setuptools distribute pip).freeze
25
- INCOMPATIBLE_VERSIONS_REGEX = /There are incompatible versions in the resolved dependencies:.*\z/m
26
- WARNINGS = /\s*# WARNING:.*\Z/m
27
- UNSAFE_NOTE = /\s*# The following packages are considered to be unsafe.*\Z/m
28
- RESOLVER_REGEX = /(?<=--resolver=)(\w+)/
29
- NATIVE_COMPILATION_ERROR =
30
- "pip._internal.exceptions.InstallationSubprocessError: Getting requirements to build wheel exited with 1"
31
-
28
+ UNSAFE_PACKAGES = T.let(%w(setuptools distribute pip).freeze, T::Array[String])
29
+ INCOMPATIBLE_VERSIONS_REGEX = T.let(/There are incompatible versions in the resolved dependencies:.*\z/m,
30
+ Regexp)
31
+ WARNINGS = T.let(/\s*# WARNING:.*\Z/m, Regexp)
32
+ UNSAFE_NOTE = T.let(/\s*# The following packages are considered to be unsafe.*\Z/m, Regexp)
33
+ RESOLVER_REGEX = T.let(/(?<=--resolver=)(\w+)/, Regexp)
34
+ NATIVE_COMPILATION_ERROR = T.let(
35
+ "pip._internal.exceptions.InstallationSubprocessError: Getting requirements to build wheel exited with 1",
36
+ String
37
+ )
38
+
39
+ sig { returns(T::Array[Dependabot::Dependency]) }
32
40
  attr_reader :dependencies
41
+
42
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
33
43
  attr_reader :dependency_files
44
+
45
+ sig { returns(T::Array[Dependabot::Credential]) }
34
46
  attr_reader :credentials
35
47
 
48
+ sig do
49
+ params(
50
+ dependencies: T::Array[Dependabot::Dependency],
51
+ dependency_files: T::Array[Dependabot::DependencyFile],
52
+ credentials: T::Array[Dependabot::Credential],
53
+ index_urls: T.nilable(T::Array[T.nilable(String)])
54
+ ).void
55
+ end
36
56
  def initialize(dependencies:, dependency_files:, credentials:, index_urls: nil)
37
- @dependencies = dependencies
38
- @dependency_files = dependency_files
39
- @credentials = credentials
40
- @index_urls = index_urls
41
- @build_isolation = true
57
+ @dependencies = T.let(dependencies, T::Array[Dependabot::Dependency])
58
+ @dependency_files = T.let(dependency_files, T::Array[Dependabot::DependencyFile])
59
+ @credentials = T.let(credentials, T::Array[Dependabot::Credential])
60
+ @index_urls = T.let(index_urls, T.nilable(T::Array[T.nilable(String)]))
61
+ @build_isolation = T.let(true, T::Boolean)
42
62
  end
43
63
 
64
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
44
65
  def updated_dependency_files
45
- @updated_dependency_files ||= fetch_updated_dependency_files
66
+ @updated_dependency_files ||= T.let(
67
+ fetch_updated_dependency_files,
68
+ T.nilable(T::Array[Dependabot::DependencyFile])
69
+ )
46
70
  end
47
71
 
48
72
  private
49
73
 
74
+ sig { returns(T.nilable(Dependabot::Dependency)) }
50
75
  def dependency
51
76
  # For now, we'll only ever be updating a single dependency
52
77
  dependencies.first
53
78
  end
54
79
 
80
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
55
81
  def fetch_updated_dependency_files
56
82
  updated_compiled_files = compile_new_requirement_files
57
83
  updated_manifest_files = update_manifest_files
@@ -66,6 +92,7 @@ module Dependabot
66
92
  ]
67
93
  end
68
94
 
95
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
69
96
  def compile_new_requirement_files
70
97
  SharedHelpers.in_a_temporary_directory do
71
98
  write_updated_dependency_files
@@ -92,6 +119,7 @@ module Dependabot
92
119
  end
93
120
  end
94
121
 
122
+ sig { params(filename: String).void }
95
123
  def compile_file(filename)
96
124
  # Shell out to pip-compile, generate a new set of requirements.
97
125
  # This is slow, as pip-compile needs to do installs.
@@ -100,12 +128,12 @@ module Dependabot
100
128
 
101
129
  name_part = "pyenv exec uv pip compile " \
102
130
  "#{options} -P " \
103
- "#{dependency.name}"
131
+ "#{T.must(dependency).name}"
104
132
  fingerprint_name_part = "pyenv exec uv pip compile " \
105
133
  "#{options_fingerprint} -P " \
106
134
  "<dependency_name>"
107
135
 
108
- version_part = "#{dependency.version} #{filename}"
136
+ version_part = "#{T.must(dependency).version} #{filename}"
109
137
  fingerprint_version_part = "<dependency_version> <filename>"
110
138
 
111
139
  # Don't escape pyenv `dep-name==version` syntax
@@ -126,10 +154,12 @@ module Dependabot
126
154
  raise
127
155
  end
128
156
 
157
+ sig { params(error: SharedHelpers::HelperSubprocessFailed).returns(T::Boolean) }
129
158
  def compilation_error?(error)
130
159
  error.message.include?(NATIVE_COMPILATION_ERROR)
131
160
  end
132
161
 
162
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
133
163
  def update_manifest_files
134
164
  dependency_files.filter_map do |file|
135
165
  next unless file.name.end_with?(".in")
@@ -143,31 +173,44 @@ module Dependabot
143
173
  end
144
174
  end
145
175
 
176
+ # rubocop:disable Metrics/AbcSize
177
+ sig do
178
+ params(updated_files: T::Array[Dependabot::DependencyFile]).returns(T::Array[Dependabot::DependencyFile])
179
+ end
146
180
  def update_uncompiled_files(updated_files)
147
181
  updated_filenames = updated_files.map(&:name)
148
- old_reqs = dependency.previous_requirements
149
- .reject { |r| updated_filenames.include?(r[:file]) }
150
- new_reqs = dependency.requirements
151
- .reject { |r| updated_filenames.include?(r[:file]) }
182
+ all_old_reqs = T.must(dependency).previous_requirements
183
+ old_reqs = T.must(all_old_reqs).reject { |r| updated_filenames.include?(r[:file]) }
184
+ all_new_reqs = T.must(dependency).requirements
185
+ new_reqs = all_new_reqs.reject { |r| updated_filenames.include?(r[:file]) }
152
186
 
153
187
  return [] if new_reqs.none?
154
188
 
155
189
  files = dependency_files
156
190
  .reject { |file| updated_filenames.include?(file.name) }
157
191
 
158
- args = dependency.to_h
192
+ args = T.must(dependency).to_h
159
193
  args = args.keys.to_h { |k| [k.to_sym, args[k]] }
160
194
  args[:requirements] = new_reqs
161
195
  args[:previous_requirements] = old_reqs
162
196
 
163
197
  RequirementFileUpdater.new(
164
- dependencies: [Dependency.new(**args)],
198
+ dependencies: [Dependency.new(**T.unsafe(args))],
165
199
  dependency_files: files,
166
200
  credentials: credentials
167
201
  ).updated_dependency_files
168
202
  end
203
+ # rubocop:enable Metrics/AbcSize
169
204
 
170
- def run_command(cmd, env: python_env, allow_unsafe_shell_command: false, fingerprint:)
205
+ sig do
206
+ params(
207
+ cmd: String,
208
+ fingerprint: String,
209
+ env: T.nilable(T::Hash[String, String]),
210
+ allow_unsafe_shell_command: T::Boolean
211
+ ).returns(String)
212
+ end
213
+ def run_command(cmd, fingerprint:, env: python_env, allow_unsafe_shell_command: false)
171
214
  SharedHelpers.run_shell_command(
172
215
  cmd,
173
216
  env: env,
@@ -185,7 +228,8 @@ module Dependabot
185
228
  raise
186
229
  end
187
230
 
188
- def run_uv_compile_command(command, allow_unsafe_shell_command: false, fingerprint:)
231
+ sig { params(command: String, fingerprint: String, allow_unsafe_shell_command: T::Boolean).returns(String) }
232
+ def run_uv_compile_command(command, fingerprint:, allow_unsafe_shell_command: false)
189
233
  run_command(
190
234
  "pyenv local #{language_version_manager.python_major_minor}",
191
235
  fingerprint: "pyenv local <python_major_minor>"
@@ -198,12 +242,13 @@ module Dependabot
198
242
  )
199
243
  end
200
244
 
245
+ sig { returns(T::Hash[String, T.untyped]) }
201
246
  def python_env
202
247
  env = {}
203
248
 
204
249
  # Handle Apache Airflow 1.10.x installs
205
- if dependency_files.any? { |f| f.content.include?("apache-airflow") }
206
- if dependency_files.any? { |f| f.content.include?("unidecode") }
250
+ if dependency_files.any? { |f| T.must(f.content).include?("apache-airflow") }
251
+ if dependency_files.any? { |f| T.must(f.content).include?("unidecode") }
207
252
  env["AIRFLOW_GPL_UNIDECODE"] = "yes"
208
253
  else
209
254
  env["SLUGIFY_USES_TEXT_UNIDECODE"] = "yes"
@@ -213,6 +258,7 @@ module Dependabot
213
258
  env
214
259
  end
215
260
 
261
+ sig { void }
216
262
  def write_updated_dependency_files
217
263
  dependency_files.each do |file|
218
264
  path = file.name
@@ -224,50 +270,54 @@ module Dependabot
224
270
  File.write(".python-version", language_version_manager.python_major_minor)
225
271
  end
226
272
 
273
+ sig { params(file: Dependabot::DependencyFile).returns(T.nilable(String)) }
227
274
  def freeze_dependency_requirement(file)
228
275
  return file.content unless file.name.end_with?(".in")
229
276
 
230
- old_req = dependency.previous_requirements
231
- .find { |r| r[:file] == file.name }
277
+ old_req = T.must(dependency).previous_requirements
278
+ old_req = old_req&.find { |r| r[:file] == file.name }
232
279
 
233
280
  return file.content unless old_req
234
- return file.content if old_req == "==#{dependency.version}"
281
+ return file.content if old_req == "==#{T.must(dependency).version}"
235
282
 
236
283
  RequirementReplacer.new(
237
- content: file.content,
238
- dependency_name: dependency.name,
284
+ content: T.must(file.content),
285
+ dependency_name: T.must(dependency).name,
239
286
  old_requirement: old_req[:requirement],
240
- new_requirement: "==#{dependency.version}",
287
+ new_requirement: "==#{T.must(dependency).version}",
241
288
  index_urls: @index_urls
242
289
  ).updated_content
243
290
  end
244
291
 
292
+ sig { params(file: Dependabot::DependencyFile).returns(T.nilable(String)) }
245
293
  def update_dependency_requirement(file)
246
294
  return file.content unless file.name.end_with?(".in")
247
295
 
248
- old_req = dependency.previous_requirements
249
- .find { |r| r[:file] == file.name }
250
- new_req = dependency.requirements
251
- .find { |r| r[:file] == file.name }
296
+ old_req = T.must(dependency).previous_requirements
297
+ old_req = old_req&.find { |r| r[:file] == file.name }
298
+ new_req = T.must(dependency).requirements
299
+ new_req = new_req.find { |r| r[:file] == file.name }
252
300
  return file.content unless old_req&.fetch(:requirement)
253
301
  return file.content if old_req == new_req
254
302
 
255
303
  RequirementReplacer.new(
256
- content: file.content,
257
- dependency_name: dependency.name,
304
+ content: T.must(file.content),
305
+ dependency_name: T.must(dependency).name,
258
306
  old_requirement: old_req[:requirement],
259
- new_requirement: new_req[:requirement],
307
+ new_requirement: T.must(new_req)[:requirement],
260
308
  index_urls: @index_urls
261
309
  ).updated_content
262
310
  end
263
311
 
312
+ sig { params(updated_content: String, file: Dependabot::DependencyFile).returns(String) }
264
313
  def post_process_compiled_file(updated_content, file)
265
- content = replace_header_with_original(updated_content, file.content)
266
- content = remove_new_warnings(content, file.content)
267
- content = update_hashes_if_required(content, file.content)
268
- replace_absolute_file_paths(content, file.content)
314
+ content = replace_header_with_original(updated_content, T.must(file.content))
315
+ content = remove_new_warnings(content, T.must(file.content))
316
+ content = update_hashes_if_required(content, T.must(file.content))
317
+ replace_absolute_file_paths(content, T.must(file.content))
269
318
  end
270
319
 
320
+ sig { params(updated_content: String, original_content: String).returns(String) }
271
321
  def replace_header_with_original(updated_content, original_content)
272
322
  original_header_lines =
273
323
  original_content.lines.take_while { |l| l.start_with?("#") }
@@ -278,6 +328,7 @@ module Dependabot
278
328
  [*original_header_lines, *updated_content_lines].join
279
329
  end
280
330
 
331
+ sig { params(updated_content: String, original_content: String).returns(String) }
281
332
  def replace_absolute_file_paths(updated_content, original_content)
282
333
  content = updated_content
283
334
 
@@ -299,6 +350,7 @@ module Dependabot
299
350
  content
300
351
  end
301
352
 
353
+ sig { params(updated_content: String, original_content: String).returns(String) }
302
354
  def remove_new_warnings(updated_content, original_content)
303
355
  content = updated_content
304
356
 
@@ -312,6 +364,7 @@ module Dependabot
312
364
  content
313
365
  end
314
366
 
367
+ sig { params(updated_content: String, original_content: String).returns(String) }
315
368
  def update_hashes_if_required(updated_content, original_content)
316
369
  deps_to_update =
317
370
  deps_to_augment_hashes_for(updated_content, original_content)
@@ -324,7 +377,7 @@ module Dependabot
324
377
  name: mtch.named_captures.fetch("name"),
325
378
  version: mtch.named_captures.fetch("version"),
326
379
  algorithm: mtch.named_captures.fetch("algorithm")
327
- ).sort.join(hash_separator(mtch.to_s))
380
+ ).sort.join(T.must(hash_separator(mtch.to_s)))
328
381
  )
329
382
 
330
383
  updated_content_with_hashes = updated_content_with_hashes
@@ -333,6 +386,7 @@ module Dependabot
333
386
  updated_content_with_hashes
334
387
  end
335
388
 
389
+ sig { params(updated_content: String, original_content: String).returns(T::Array[T.untyped]) }
336
390
  def deps_to_augment_hashes_for(updated_content, original_content)
337
391
  regex = /^#{RequirementParser::INSTALL_REQ_WITH_REQUIREMENT}/o
338
392
 
@@ -362,6 +416,7 @@ module Dependabot
362
416
  [*new_deps, *changed_hashes_deps]
363
417
  end
364
418
 
419
+ sig { params(name: String, version: String, algorithm: String).returns(T::Array[String]) }
365
420
  def package_hashes_for(name:, version:, algorithm:)
366
421
  index_urls = @index_urls || [nil]
367
422
  hashes = []
@@ -391,6 +446,7 @@ module Dependabot
391
446
  hashes
392
447
  end
393
448
 
449
+ sig { params(requirement_string: String).returns(T.nilable(String)) }
394
450
  def hash_separator(requirement_string)
395
451
  hash_regex = RequirementParser::HASH
396
452
  return unless requirement_string.match?(hash_regex)
@@ -398,17 +454,18 @@ module Dependabot
398
454
  current_separator =
399
455
  requirement_string
400
456
  .match(/#{hash_regex}((?<separator>\s*\\?\s*?)#{hash_regex})*/)
401
- .named_captures.fetch("separator")
457
+ &.named_captures&.fetch("separator")
402
458
 
403
459
  default_separator =
404
460
  requirement_string
405
461
  .match(RequirementParser::HASH)
406
- .pre_match.match(/(?<separator>\s*\\?\s*?)\z/)
407
- .named_captures.fetch("separator")
462
+ &.pre_match&.match(/(?<separator>\s*\\?\s*?)\z/)
463
+ &.named_captures&.fetch("separator")
408
464
 
409
465
  current_separator || default_separator
410
466
  end
411
467
 
468
+ sig { params(options: String).returns(String) }
412
469
  def compile_options_fingerprint(options)
413
470
  options.sub(
414
471
  /--output-file=\S+/, "--output-file=<output_file>"
@@ -419,6 +476,7 @@ module Dependabot
419
476
  )
420
477
  end
421
478
 
479
+ sig { params(filename: String).returns(String) }
422
480
  def compile_options(filename)
423
481
  options = @build_isolation ? ["--build-isolation"] : ["--no-build-isolation"]
424
482
  options += compile_index_options
@@ -430,23 +488,26 @@ module Dependabot
430
488
  options.join(" ")
431
489
  end
432
490
 
491
+ sig { params(requirements_file: Dependabot::DependencyFile).returns(T::Array[String]) }
433
492
  def uv_compile_options_from_compiled_file(requirements_file)
434
493
  options = ["--output-file=#{requirements_file.name}"]
435
- options << "--emit-index-url" if requirements_file.content.include?("index-url http")
436
- options << "--generate-hashes" if requirements_file.content.include?("--hash=sha")
437
- options << "--no-annotate" unless requirements_file.content.include?("# via ")
438
- options << "--pre" if requirements_file.content.include?("--pre")
439
- options << "--no-strip-extras" if requirements_file.content.include?("--no-strip-extras")
440
-
441
- if requirements_file.content.include?("--no-binary") || requirements_file.content.include?("--only-binary")
494
+ options << "--emit-index-url" if T.must(requirements_file.content).include?("index-url http")
495
+ options << "--generate-hashes" if T.must(requirements_file.content).include?("--hash=sha")
496
+ options << "--no-annotate" unless T.must(requirements_file.content).include?("# via ")
497
+ options << "--pre" if T.must(requirements_file.content).include?("--pre")
498
+ options << "--no-strip-extras" if T.must(requirements_file.content).include?("--no-strip-extras")
499
+
500
+ if T.must(requirements_file.content).include?("--no-binary") ||
501
+ T.must(requirements_file.content).include?("--only-binary")
442
502
  options << "--emit-build-options"
443
503
  end
444
504
 
445
- options << "--universal" if requirements_file.content.include?("--universal")
505
+ options << "--universal" if T.must(requirements_file.content).include?("--universal")
446
506
 
447
507
  options
448
508
  end
449
509
 
510
+ sig { returns(T::Array[String]) }
450
511
  def compile_index_options
451
512
  credentials
452
513
  .select { |cred| cred["type"] == "python_index" }
@@ -461,15 +522,17 @@ module Dependabot
461
522
  end
462
523
  end
463
524
 
525
+ sig { params(content: String).returns(T::Boolean) }
464
526
  def includes_unsafe_packages?(content)
465
527
  UNSAFE_PACKAGES.any? { |n| content.match?(/^#{Regexp.quote(n)}==/) }
466
528
  end
467
529
 
530
+ sig { returns(T::Array[String]) }
468
531
  def filenames_to_compile
469
532
  files_from_reqs =
470
- dependency.requirements
471
- .map { |r| r[:file] }
472
- .select { |fn| fn.end_with?(".in") }
533
+ T.must(dependency).requirements
534
+ .map { |r| r[:file] }
535
+ .select { |fn| fn.end_with?(".in") }
473
536
 
474
537
  files_from_compiled_files =
475
538
  compile_files.map(&:name).select do |fn|
@@ -482,10 +545,11 @@ module Dependabot
482
545
  order_filenames_for_compilation(filenames)
483
546
  end
484
547
 
548
+ sig { params(filename: String).returns(T.nilable(Dependabot::DependencyFile)) }
485
549
  def compiled_file_for_filename(filename)
486
550
  compiled_file =
487
551
  compiled_files
488
- .find { |f| f.content.match?(output_file_regex(filename)) }
552
+ .find { |f| T.must(f.content).match?(output_file_regex(filename)) }
489
553
 
490
554
  compiled_file ||=
491
555
  compiled_files
@@ -494,26 +558,30 @@ module Dependabot
494
558
  compiled_file
495
559
  end
496
560
 
561
+ sig { params(filename: T.any(String, Symbol)).returns(String) }
497
562
  def output_file_regex(filename)
498
563
  "--output-file[=\s]+.*\s#{Regexp.escape(filename)}\s*$"
499
564
  end
500
565
 
566
+ sig { params(compiled_file: T.nilable(Dependabot::DependencyFile)).returns(T::Boolean) }
501
567
  def compiled_file_includes_dependency?(compiled_file)
502
568
  return false unless compiled_file
503
569
 
504
570
  regex = RequirementParser::INSTALL_REQ_WITH_REQUIREMENT
505
571
 
506
572
  matches = []
507
- compiled_file.content.scan(regex) { matches << Regexp.last_match }
508
- matches.any? { |m| normalise(m[:name]) == dependency.name }
573
+ T.must(compiled_file.content).scan(regex) { matches << Regexp.last_match }
574
+ matches.any? { |m| normalise(m[:name]) == T.must(dependency).name }
509
575
  end
510
576
 
577
+ sig { params(name: String).returns(String) }
511
578
  def normalise(name)
512
579
  NameNormaliser.normalise(name)
513
580
  end
514
581
 
515
582
  # If the files we need to update require one another then we need to
516
583
  # update them in the right order
584
+ sig { params(filenames: T::Array[String]).returns(T::Array[String]) }
517
585
  def order_filenames_for_compilation(filenames)
518
586
  ordered_filenames = T.let([], T::Array[String])
519
587
 
@@ -521,7 +589,7 @@ module Dependabot
521
589
  ordered_filenames +=
522
590
  remaining_filenames
523
591
  .reject do |fn|
524
- unupdated_reqs = requirement_map[fn] - ordered_filenames
592
+ unupdated_reqs = (requirement_map[fn] || []) - ordered_filenames
525
593
  unupdated_reqs.intersect?(filenames)
526
594
  end
527
595
  end
@@ -529,11 +597,12 @@ module Dependabot
529
597
  ordered_filenames
530
598
  end
531
599
 
600
+ sig { returns(T::Hash[String, T::Array[String]]) }
532
601
  def requirement_map
533
602
  child_req_regex = Uv::FileFetcher::CHILD_REQUIREMENT_REGEX
534
- @requirement_map ||=
603
+ @requirement_map ||= T.let(
535
604
  compile_files.each_with_object({}) do |file, req_map|
536
- paths = file.content.scan(child_req_regex).flatten
605
+ paths = T.must(file.content).scan(child_req_regex).flatten
537
606
  current_dir = File.dirname(file.name)
538
607
 
539
608
  req_map[file.name] =
@@ -545,27 +614,37 @@ module Dependabot
545
614
 
546
615
  path
547
616
  end.uniq.compact
548
- end
617
+ end,
618
+ T.nilable(T::Hash[String, T::Array[String]])
619
+ )
549
620
  end
550
621
 
622
+ sig { returns(Dependabot::Uv::FileParser::PythonRequirementParser) }
551
623
  def python_requirement_parser
552
- @python_requirement_parser ||=
624
+ @python_requirement_parser ||= T.let(
553
625
  FileParser::PythonRequirementParser.new(
554
626
  dependency_files: dependency_files
555
- )
627
+ ),
628
+ T.nilable(FileParser::PythonRequirementParser)
629
+ )
556
630
  end
557
631
 
632
+ sig { returns(Dependabot::Uv::LanguageVersionManager) }
558
633
  def language_version_manager
559
- @language_version_manager ||=
634
+ @language_version_manager ||= T.let(
560
635
  LanguageVersionManager.new(
561
636
  python_requirement_parser: python_requirement_parser
562
- )
637
+ ),
638
+ T.nilable(LanguageVersionManager)
639
+ )
563
640
  end
564
641
 
642
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
565
643
  def compile_files
566
644
  dependency_files.select { |f| f.name.end_with?(".in") }
567
645
  end
568
646
 
647
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
569
648
  def compiled_files
570
649
  dependency_files.select { |f| f.name.end_with?(".txt") }
571
650
  end
@@ -18,6 +18,7 @@ module Dependabot
18
18
  class FileUpdater
19
19
  class LockFileUpdater
20
20
  extend T::Sig
21
+
21
22
  require_relative "pyproject_preparer"
22
23
 
23
24
  REQUIRED_FILES = %w(pyproject.toml uv.lock).freeze # At least one of these files should be present
@@ -31,7 +32,7 @@ module Dependabot
31
32
  sig { returns(T::Array[Dependabot::Credential]) }
32
33
  attr_reader :credentials
33
34
 
34
- sig { returns(T.nilable(T::Array[String])) }
35
+ sig { returns(T.nilable(T::Array[T.nilable(String)])) }
35
36
  attr_reader :index_urls
36
37
 
37
38
  sig do
@@ -39,7 +40,7 @@ module Dependabot
39
40
  dependencies: T::Array[Dependency],
40
41
  dependency_files: T::Array[DependencyFile],
41
42
  credentials: T::Array[Dependabot::Credential],
42
- index_urls: T.nilable(T::Array[String])
43
+ index_urls: T.nilable(T::Array[T.nilable(String)])
43
44
  ).void
44
45
  end
45
46
  def initialize(dependencies:, dependency_files:, credentials:, index_urls: nil)
@@ -29,7 +29,7 @@ module Dependabot
29
29
  dependencies: T::Array[Dependency],
30
30
  dependency_files: T::Array[DependencyFile],
31
31
  credentials: T::Array[Dependabot::Credential],
32
- index_urls: T.nilable(T::Array[String])
32
+ index_urls: T.nilable(T::Array[T.nilable(String)])
33
33
  ).void
34
34
  end
35
35
  def initialize(dependencies:, dependency_files:, credentials:, index_urls: nil)
@@ -47,16 +47,16 @@ module Dependabot
47
47
 
48
48
  private
49
49
 
50
- sig { returns(T.nilable(Dependency)) }
50
+ sig { returns(Dependency) }
51
51
  def dependency
52
52
  # For now, we'll only ever be updating a single dependency
53
- dependencies.first
53
+ T.must(dependencies.first)
54
54
  end
55
55
 
56
56
  sig { returns(T::Array[DependencyFile]) }
57
57
  def fetch_updated_dependency_files
58
- previous_requirements = dependency&.previous_requirements || []
59
- reqs = T.must(dependency).requirements.zip(previous_requirements)
58
+ previous_requirements = dependency.previous_requirements || []
59
+ reqs = dependency.requirements.zip(previous_requirements)
60
60
 
61
61
  reqs.filter_map do |(new_req, old_req)|
62
62
  next if new_req == old_req
@@ -77,11 +77,11 @@ module Dependabot
77
77
  raise "Could not find a dependency file for #{new_req}" unless original_file
78
78
 
79
79
  RequirementReplacer.new(
80
- content: original_file.content,
81
- dependency_name: dependency&.name,
80
+ content: T.must(original_file.content),
81
+ dependency_name: dependency.name,
82
82
  old_requirement: old_req.fetch(:requirement),
83
83
  new_requirement: new_req.fetch(:requirement),
84
- new_hash_version: dependency&.version,
84
+ new_hash_version: dependency.version,
85
85
  index_urls: @index_urls
86
86
  ).updated_content
87
87
  end