dependabot-uv 0.354.0 → 0.356.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.
@@ -10,14 +10,19 @@ require "dependabot/errors"
10
10
  require "dependabot/uv/name_normaliser"
11
11
  require "dependabot/uv/requirement_parser"
12
12
  require "dependabot/uv/requirement"
13
+ require "dependabot/uv/version"
13
14
  require "dependabot/registry_client"
14
15
  require "dependabot/requirements_update_strategy"
15
16
  require "dependabot/update_checkers"
16
- require "dependabot/update_checkers/base"
17
+ require "dependabot/python/update_checker"
17
18
 
18
19
  module Dependabot
19
20
  module Uv
20
- class UpdateChecker < Dependabot::UpdateCheckers::Base
21
+ # UV UpdateChecker extends Python's UpdateChecker since both ecosystems
22
+ # share PyPI registry interaction and core version resolution logic.
23
+ # UV overrides only the resolver selection and UV-specific features
24
+ # (uv.lock support, no Pipenv/Poetry support).
25
+ class UpdateChecker < Dependabot::Python::UpdateChecker
21
26
  extend T::Sig
22
27
 
23
28
  require_relative "update_checker/pip_compile_version_resolver"
@@ -26,65 +31,6 @@ module Dependabot
26
31
  require_relative "update_checker/latest_version_finder"
27
32
  require_relative "update_checker/lock_file_resolver"
28
33
 
29
- MAIN_PYPI_INDEXES = %w(
30
- https://pypi.python.org/simple/
31
- https://pypi.org/simple/
32
- ).freeze
33
- VERSION_REGEX = /[0-9]+(?:\.[A-Za-z0-9\-_]+)*/
34
-
35
- sig { override.returns(T.nilable(Gem::Version)) }
36
- def latest_version
37
- @latest_version ||= T.let(
38
- fetch_latest_version,
39
- T.nilable(Gem::Version)
40
- )
41
- end
42
-
43
- sig { override.returns(T.nilable(Gem::Version)) }
44
- def latest_resolvable_version
45
- @latest_resolvable_version ||= T.let(
46
- if resolver_type == :requirements
47
- resolver.latest_resolvable_version
48
- elsif resolver_type == :pip_compile && resolver.resolvable?(version: latest_version)
49
- latest_version
50
- else
51
- resolver.latest_resolvable_version(
52
- requirement: unlocked_requirement_string
53
- )
54
- end,
55
- T.nilable(Gem::Version)
56
- )
57
- end
58
-
59
- sig { override.returns(T.nilable(Gem::Version)) }
60
- def latest_resolvable_version_with_no_unlock
61
- @latest_resolvable_version_with_no_unlock ||= T.let(
62
- if resolver_type == :requirements
63
- resolver.latest_resolvable_version_with_no_unlock
64
- else
65
- resolver.latest_resolvable_version(
66
- requirement: current_requirement_string
67
- )
68
- end,
69
- T.nilable(Gem::Version)
70
- )
71
- end
72
-
73
- sig { override.returns(T.nilable(Gem::Version)) }
74
- def lowest_security_fix_version
75
- latest_version_finder.lowest_security_fix_version
76
- end
77
-
78
- sig { override.returns(T.nilable(Gem::Version)) }
79
- def lowest_resolvable_security_fix_version
80
- raise "Dependency not vulnerable!" unless vulnerable?
81
-
82
- @lowest_resolvable_security_fix_version ||= T.let(
83
- fetch_lowest_resolvable_security_fix_version,
84
- T.nilable(Gem::Version)
85
- )
86
- end
87
-
88
34
  sig { override.returns(T::Array[T::Hash[Symbol, T.untyped]]) }
89
35
  def updated_requirements
90
36
  RequirementsUpdater.new(
@@ -95,34 +41,9 @@ module Dependabot
95
41
  ).updated_requirements
96
42
  end
97
43
 
98
- sig { override.returns(T::Boolean) }
99
- def requirements_unlocked_or_can_be?
100
- !requirements_update_strategy.lockfile_only?
101
- end
102
-
103
- sig { override.returns(Dependabot::RequirementsUpdateStrategy) }
104
- def requirements_update_strategy
105
- # If passed in as an option (in the base class) honour that option
106
- return @requirements_update_strategy if @requirements_update_strategy
107
-
108
- # Otherwise, check if this is a library or not
109
- library? ? RequirementsUpdateStrategy::WidenRanges : RequirementsUpdateStrategy::BumpVersions
110
- end
111
-
112
44
  private
113
45
 
114
- sig { override.returns(T::Boolean) }
115
- def latest_version_resolvable_with_full_unlock?
116
- # Full unlock checks aren't implemented for Python (yet)
117
- false
118
- end
119
-
120
- sig { override.returns(T::Array[Dependabot::Dependency]) }
121
- def updated_dependencies_after_full_unlock
122
- raise NotImplementedError
123
- end
124
-
125
- sig { returns(T.nilable(Gem::Version)) }
46
+ sig { override.returns(T.nilable(Gem::Version)) }
126
47
  def fetch_lowest_resolvable_security_fix_version
127
48
  fix_version = lowest_security_fix_version
128
49
  return latest_resolvable_version if fix_version.nil?
@@ -137,7 +58,7 @@ module Dependabot
137
58
  resolver.resolvable?(version: fix_version) ? fix_version : nil
138
59
  end
139
60
 
140
- sig { returns(T.untyped) }
61
+ sig { override.returns(T.untyped) }
141
62
  def resolver
142
63
  case resolver_type
143
64
  when :pip_compile then pip_compile_version_resolver
@@ -147,13 +68,12 @@ module Dependabot
147
68
  end
148
69
  end
149
70
 
150
- sig { returns(Symbol) }
71
+ sig { override.returns(Symbol) }
151
72
  def resolver_type
152
73
  reqs = requirements
153
74
 
154
75
  # If there are no requirements then this is a sub-dependency.
155
- # It must come from one of Pipenv, Poetry or pip-tools,
156
- # and can't come from the first two unless they have a lockfile.
76
+ # It must come from pip-tools or uv.lock.
157
77
  return subdependency_resolver if reqs.none?
158
78
 
159
79
  # Otherwise, this is a top-level dependency, and we can figure out
@@ -169,7 +89,7 @@ module Dependabot
169
89
  end
170
90
  end
171
91
 
172
- sig { returns(Symbol) }
92
+ sig { override.returns(Symbol) }
173
93
  def subdependency_resolver
174
94
  return :pip_compile if pip_compile_files.any?
175
95
  return :lock_file if uv_lock.any?
@@ -177,7 +97,7 @@ module Dependabot
177
97
  raise "Claimed to be a sub-dependency, but no lockfile exists!"
178
98
  end
179
99
 
180
- sig { params(reqs: T::Array[T::Hash[Symbol, T.untyped]]).returns(T::Boolean) }
100
+ sig { override.params(reqs: T::Array[T::Hash[Symbol, T.untyped]]).returns(T::Boolean) }
181
101
  def exact_requirement?(reqs)
182
102
  reqs = reqs.map { |r| r.fetch(:requirement) }
183
103
  reqs = reqs.compact
@@ -185,7 +105,7 @@ module Dependabot
185
105
  reqs.any? { |r| Uv::Requirement.new(r).exact? }
186
106
  end
187
107
 
188
- sig { returns(PipCompileVersionResolver) }
108
+ sig { override.returns(Object) }
189
109
  def pip_compile_version_resolver
190
110
  @pip_compile_version_resolver ||= T.let(
191
111
  PipCompileVersionResolver.new(
@@ -198,7 +118,7 @@ module Dependabot
198
118
  )
199
119
  end
200
120
 
201
- sig { returns(PipVersionResolver) }
121
+ sig { override.returns(PipVersionResolver) }
202
122
  def pip_version_resolver
203
123
  @pip_version_resolver ||= T.let(
204
124
  PipVersionResolver.new(
@@ -229,17 +149,7 @@ module Dependabot
229
149
  )
230
150
  end
231
151
 
232
- sig { returns(T::Hash[Symbol, T.untyped]) }
233
- def resolver_args
234
- {
235
- dependency: dependency,
236
- dependency_files: dependency_files,
237
- credentials: credentials,
238
- repo_contents_path: repo_contents_path
239
- }
240
- end
241
-
242
- sig { returns(T.nilable(String)) }
152
+ sig { override.returns(T.nilable(String)) }
243
153
  def current_requirement_string
244
154
  reqs = requirements
245
155
  return if reqs.none?
@@ -253,7 +163,7 @@ module Dependabot
253
163
  requirement&.fetch(:requirement)
254
164
  end
255
165
 
256
- sig { returns(String) }
166
+ sig { override.returns(String) }
257
167
  def unlocked_requirement_string
258
168
  lower_bound_req = updated_version_req_lower_bound
259
169
 
@@ -270,7 +180,7 @@ module Dependabot
270
180
  lower_bound_req + ",<=#{latest_version}"
271
181
  end
272
182
 
273
- sig { returns(String) }
183
+ sig { override.returns(String) }
274
184
  def updated_version_req_lower_bound
275
185
  return ">=#{dependency.version}" if dependency.version
276
186
 
@@ -285,12 +195,7 @@ module Dependabot
285
195
  ">=#{version_for_requirement || 0}"
286
196
  end
287
197
 
288
- sig { returns(T.nilable(Gem::Version)) }
289
- def fetch_latest_version
290
- latest_version_finder.latest_version
291
- end
292
-
293
- sig { returns(LatestVersionFinder) }
198
+ sig { override.returns(LatestVersionFinder) }
294
199
  def latest_version_finder
295
200
  @latest_version_finder ||= T.let(
296
201
  LatestVersionFinder.new(
@@ -306,7 +211,7 @@ module Dependabot
306
211
  )
307
212
  end
308
213
 
309
- sig { returns(T::Boolean) }
214
+ sig { override.returns(T::Boolean) }
310
215
  def library?
311
216
  return false unless updating_pyproject?
312
217
  return false unless library_details
@@ -329,16 +234,6 @@ module Dependabot
329
234
  false
330
235
  end
331
236
 
332
- sig { returns(T::Boolean) }
333
- def updating_pyproject?
334
- requirement_files.any?("pyproject.toml")
335
- end
336
-
337
- sig { returns(T::Boolean) }
338
- def updating_in_file?
339
- requirement_files.any? { |f| f.end_with?(".in") }
340
- end
341
-
342
237
  sig { returns(T::Boolean) }
343
238
  def updating_uv_lock?
344
239
  requirement_files.any?("uv.lock")
@@ -349,32 +244,7 @@ module Dependabot
349
244
  requirement_files.any? { |f| f.end_with?("requirements.txt") }
350
245
  end
351
246
 
352
- sig { returns(T::Boolean) }
353
- def updating_requirements_file?
354
- requirement_files.any? { |f| f =~ /\.txt$|\.in$/ }
355
- end
356
-
357
- sig { returns(T::Array[String]) }
358
- def requirement_files
359
- requirements.map { |r| r.fetch(:file) }
360
- end
361
-
362
- sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
363
- def requirements
364
- dependency.requirements
365
- end
366
-
367
- sig { params(name: String).returns(String) }
368
- def normalised_name(name)
369
- NameNormaliser.normalise(name)
370
- end
371
-
372
- sig { returns(T.nilable(Dependabot::DependencyFile)) }
373
- def pyproject
374
- dependency_files.find { |f| f.name == "pyproject.toml" }
375
- end
376
-
377
- sig { returns(T.nilable(T::Hash[String, T.untyped])) }
247
+ sig { override.returns(T.nilable(T::Hash[String, T.untyped])) }
378
248
  def library_details
379
249
  @library_details ||= T.let(
380
250
  standard_details || build_system_details,
@@ -382,35 +252,6 @@ module Dependabot
382
252
  )
383
253
  end
384
254
 
385
- sig { returns(T.nilable(T::Hash[String, T.untyped])) }
386
- def standard_details
387
- @standard_details ||= T.let(
388
- toml_content["project"],
389
- T.nilable(T::Hash[String, T.untyped])
390
- )
391
- end
392
-
393
- sig { returns(T.nilable(T::Hash[String, T.untyped])) }
394
- def build_system_details
395
- @build_system_details ||= T.let(
396
- toml_content["build-system"],
397
- T.nilable(T::Hash[String, T.untyped])
398
- )
399
- end
400
-
401
- sig { returns(T::Hash[String, T.untyped]) }
402
- def toml_content
403
- @toml_content ||= T.let(
404
- TomlRB.parse(T.must(pyproject).content),
405
- T.nilable(T::Hash[String, T.untyped])
406
- )
407
- end
408
-
409
- sig { returns(T::Array[Dependabot::DependencyFile]) }
410
- def pip_compile_files
411
- dependency_files.select { |f| f.name.end_with?(".in") }
412
- end
413
-
414
255
  sig { returns(T::Array[Dependabot::DependencyFile]) }
415
256
  def uv_lock
416
257
  dependency_files.select { |f| f.name == "uv.lock" }
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.354.0
4
+ version: 0.356.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dependabot
@@ -15,28 +15,28 @@ dependencies:
15
15
  requirements:
16
16
  - - '='
17
17
  - !ruby/object:Gem::Version
18
- version: 0.354.0
18
+ version: 0.356.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.354.0
25
+ version: 0.356.0
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: dependabot-python
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
30
30
  - - '='
31
31
  - !ruby/object:Gem::Version
32
- version: 0.354.0
32
+ version: 0.356.0
33
33
  type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - '='
38
38
  - !ruby/object:Gem::Version
39
- version: 0.354.0
39
+ version: 0.356.0
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: debug
42
42
  requirement: !ruby/object:Gem::Requirement
@@ -297,7 +297,7 @@ licenses:
297
297
  - MIT
298
298
  metadata:
299
299
  bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
300
- changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.354.0
300
+ changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.356.0
301
301
  rdoc_options: []
302
302
  require_paths:
303
303
  - lib