dependabot-python 0.320.0 → 0.320.1

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,6 +1,7 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
+ require "sorbet-runtime"
4
5
  require "dependabot/python/requirement_parser"
5
6
  require "dependabot/python/requirement"
6
7
  require "dependabot/python/update_checker"
@@ -11,28 +12,46 @@ module Dependabot
11
12
  module Python
12
13
  class UpdateChecker
13
14
  class RequirementsUpdater
14
- PYPROJECT_OR_SEPARATOR = /(?<=[a-zA-Z0-9*])\s*\|+/
15
- PYPROJECT_SEPARATOR = /#{PYPROJECT_OR_SEPARATOR}|,/
15
+ extend T::Sig
16
+
17
+ PYPROJECT_OR_SEPARATOR = T.let(/(?<=[a-zA-Z0-9*])\s*\|+/, Regexp)
18
+ PYPROJECT_SEPARATOR = T.let(/#{PYPROJECT_OR_SEPARATOR}|,/, Regexp)
16
19
 
17
20
  class UnfixableRequirement < StandardError; end
18
21
 
22
+ sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
19
23
  attr_reader :requirements
24
+
25
+ sig { returns(Dependabot::RequirementsUpdateStrategy) }
20
26
  attr_reader :update_strategy
27
+
28
+ sig { returns(T::Boolean) }
21
29
  attr_reader :has_lockfile
30
+
31
+ sig { returns(T.nilable(Dependabot::Python::Version)) }
22
32
  attr_reader :latest_resolvable_version
23
33
 
34
+ sig do
35
+ params(
36
+ requirements: T::Array[T::Hash[Symbol, T.untyped]],
37
+ update_strategy: Dependabot::RequirementsUpdateStrategy,
38
+ has_lockfile: T::Boolean,
39
+ latest_resolvable_version: T.nilable(String)
40
+ ).void
41
+ end
24
42
  def initialize(requirements:, update_strategy:, has_lockfile:,
25
43
  latest_resolvable_version:)
26
- @requirements = requirements
27
- @update_strategy = update_strategy
28
- @has_lockfile = has_lockfile
44
+ @requirements = T.let(requirements, T::Array[T::Hash[Symbol, T.untyped]])
45
+ @update_strategy = T.let(update_strategy, Dependabot::RequirementsUpdateStrategy)
46
+ @has_lockfile = T.let(has_lockfile, T::Boolean)
47
+ @latest_resolvable_version = T.let(nil, T.nilable(Dependabot::Python::Version))
29
48
 
30
49
  return unless latest_resolvable_version
31
50
 
32
- @latest_resolvable_version =
33
- Python::Version.new(latest_resolvable_version)
51
+ @latest_resolvable_version = Python::Version.new(latest_resolvable_version)
34
52
  end
35
53
 
54
+ sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
36
55
  def updated_requirements
37
56
  return requirements if update_strategy.lockfile_only?
38
57
 
@@ -50,6 +69,7 @@ module Dependabot
50
69
  private
51
70
 
52
71
  # rubocop:disable Metrics/PerceivedComplexity
72
+ sig { params(req: T::Hash[Symbol, T.untyped]).returns(T::Hash[Symbol, T.untyped]) }
53
73
  def updated_setup_requirement(req)
54
74
  return req unless latest_resolvable_version
55
75
  return req unless req.fetch(:requirement)
@@ -62,7 +82,7 @@ module Dependabot
62
82
  find_and_update_equality_match(req_strings)
63
83
  elsif req_strings.any? { |r| r.start_with?("~=", "==") }
64
84
  tw_req = req_strings.find { |r| r.start_with?("~=", "==") }
65
- convert_to_range(tw_req, latest_resolvable_version)
85
+ convert_to_range(tw_req, T.must(latest_resolvable_version))
66
86
  else
67
87
  update_requirements_range(req_strings)
68
88
  end
@@ -73,12 +93,14 @@ module Dependabot
73
93
  end
74
94
  # rubocop:enable Metrics/PerceivedComplexity
75
95
 
96
+ sig { params(req: T::Hash[Symbol, T.untyped]).returns(T::Hash[Symbol, T.untyped]) }
76
97
  def updated_pipfile_requirement(req)
77
98
  # For now, we just proxy to updated_requirement. In future this
78
99
  # method may treat Pipfile requirements differently.
79
100
  updated_requirement(req)
80
101
  end
81
102
 
103
+ sig { params(req: T::Hash[Symbol, T.untyped]).returns(T::Hash[Symbol, T.untyped]) }
82
104
  def updated_pyproject_requirement(req)
83
105
  return req unless latest_resolvable_version
84
106
  return req unless req.fetch(:requirement)
@@ -101,12 +123,14 @@ module Dependabot
101
123
  req.merge(requirement: :unfixable)
102
124
  end
103
125
 
126
+ sig { params(req: T::Hash[Symbol, T.untyped]).returns(T::Hash[Symbol, T.untyped]) }
104
127
  def update_pyproject_version_if_needed(req)
105
128
  return req if new_version_satisfies?(req)
106
129
 
107
130
  update_pyproject_version(req)
108
131
  end
109
132
 
133
+ sig { params(req: T::Hash[Symbol, T.untyped]).returns(T::Hash[Symbol, T.untyped]) }
110
134
  def update_pyproject_version(req)
111
135
  requirement_strings = req[:requirement].split(",").map(&:strip)
112
136
 
@@ -132,6 +156,7 @@ module Dependabot
132
156
  req.merge(requirement: new_requirement)
133
157
  end
134
158
 
159
+ sig { params(req: T::Hash[Symbol, T.untyped]).returns(T::Hash[Symbol, T.untyped]) }
135
160
  def widen_pyproject_requirement(req)
136
161
  return req if new_version_satisfies?(req)
137
162
 
@@ -145,9 +170,10 @@ module Dependabot
145
170
  req.merge(requirement: new_requirement)
146
171
  end
147
172
 
173
+ sig { params(req_string: String).returns(String) }
148
174
  def add_new_requirement_option(req_string)
149
- option_to_copy = req_string.split(PYPROJECT_OR_SEPARATOR).last
150
- .split(PYPROJECT_SEPARATOR).first.strip
175
+ option_to_copy = T.must(T.must(req_string.split(PYPROJECT_OR_SEPARATOR).last)
176
+ .split(PYPROJECT_SEPARATOR).first).strip
151
177
  operator = option_to_copy.gsub(/\d.*/, "").strip
152
178
 
153
179
  new_option =
@@ -167,6 +193,7 @@ module Dependabot
167
193
  end
168
194
 
169
195
  # rubocop:disable Metrics/PerceivedComplexity
196
+ sig { params(req_string: String).returns(String) }
170
197
  def widen_requirement_range(req_string)
171
198
  requirement_strings = req_string.split(",").map(&:strip)
172
199
 
@@ -180,7 +207,7 @@ module Dependabot
180
207
  # range to include the new version
181
208
  v_req = requirement_strings
182
209
  .find { |r| r.start_with?("~", "^") || r.include?("*") }
183
- convert_to_range(v_req, latest_resolvable_version)
210
+ convert_to_range(T.must(v_req), T.must(latest_resolvable_version))
184
211
  else
185
212
  # Otherwise we have a range, and need to update the upper bound
186
213
  update_requirements_range(requirement_strings)
@@ -188,6 +215,7 @@ module Dependabot
188
215
  end
189
216
  # rubocop:enable Metrics/PerceivedComplexity
190
217
 
218
+ sig { params(req: T::Hash[Symbol, T.untyped]).returns(T::Hash[Symbol, T.untyped]) }
191
219
  def updated_requirement(req)
192
220
  return req unless latest_resolvable_version
193
221
  return req unless req.fetch(:requirement)
@@ -204,12 +232,14 @@ module Dependabot
204
232
  end
205
233
  end
206
234
 
235
+ sig { params(req: T::Hash[Symbol, T.untyped]).returns(T::Hash[Symbol, T.untyped]) }
207
236
  def update_requirement_if_needed(req)
208
237
  return req if new_version_satisfies?(req)
209
238
 
210
239
  update_requirement(req)
211
240
  end
212
241
 
242
+ sig { params(req: T::Hash[Symbol, T.untyped]).returns(T::Hash[Symbol, T.untyped]) }
213
243
  def update_requirement(req)
214
244
  requirement_strings = req[:requirement].split(",").map(&:strip)
215
245
 
@@ -229,6 +259,7 @@ module Dependabot
229
259
  req.merge(requirement: :unfixable)
230
260
  end
231
261
 
262
+ sig { params(req: T::Hash[Symbol, T.untyped]).returns(T::Hash[Symbol, T.untyped]) }
232
263
  def widen_requirement(req)
233
264
  return req if new_version_satisfies?(req)
234
265
 
@@ -237,29 +268,32 @@ module Dependabot
237
268
  req.merge(requirement: new_requirement)
238
269
  end
239
270
 
271
+ sig { params(req: T::Hash[Symbol, T.untyped]).returns(T::Boolean) }
240
272
  def new_version_satisfies?(req)
241
273
  requirement_class
242
274
  .requirements_array(req.fetch(:requirement))
243
- .any? { |r| r.satisfied_by?(latest_resolvable_version) }
275
+ .any? { |r| r.satisfied_by?(T.must(latest_resolvable_version)) }
244
276
  end
245
277
 
278
+ sig { params(requirement_strings: T::Array[String]).returns(String) }
246
279
  def find_and_update_equality_match(requirement_strings)
247
280
  if requirement_strings.any? { |r| requirement_class.new(r).exact? }
248
281
  # True equality match
249
- requirement_strings.find { |r| requirement_class.new(r).exact? }
250
- .sub(
251
- RequirementParser::VERSION,
252
- latest_resolvable_version.to_s
253
- )
282
+ T.must(requirement_strings.find { |r| requirement_class.new(r).exact? })
283
+ .sub(
284
+ RequirementParser::VERSION,
285
+ T.must(latest_resolvable_version).to_s
286
+ )
254
287
  else
255
288
  # Prefix match
256
- requirement_strings.find { |r| r.match?(/^(=+|\d)/) }
257
- .sub(RequirementParser::VERSION) do |v|
258
- at_same_precision(latest_resolvable_version.to_s, v)
289
+ T.must(requirement_strings.find { |r| r.match?(/^(=+|\d)/) })
290
+ .sub(RequirementParser::VERSION) do |v|
291
+ at_same_precision(T.must(latest_resolvable_version).to_s, v)
259
292
  end
260
293
  end
261
294
  end
262
295
 
296
+ sig { params(new_version: String, old_version: String).returns(String) }
263
297
  def at_same_precision(new_version, old_version)
264
298
  # return new_version unless old_version.include?("*")
265
299
 
@@ -273,18 +307,19 @@ module Dependabot
273
307
  .join(".")
274
308
  end
275
309
 
276
- def update_requirements_range(requirement_strings)
310
+ sig { params(requirement_strings: T::Array[String]).returns(String) }
311
+ def update_requirements_range(requirement_strings) # rubocop:disable Metrics/AbcSize
277
312
  ruby_requirements =
278
313
  requirement_strings.map { |r| requirement_class.new(r) }
279
314
 
280
315
  updated_requirement_strings = ruby_requirements.flat_map do |r|
281
- next r.to_s if r.satisfied_by?(latest_resolvable_version)
316
+ next r.to_s if r.satisfied_by?(T.must(latest_resolvable_version))
282
317
 
283
318
  case op = r.requirements.first.first
284
319
  when "<"
285
- "<" + update_greatest_version(r.requirements.first.last, latest_resolvable_version)
320
+ "<" + update_greatest_version(r.requirements.first.last, T.must(latest_resolvable_version))
286
321
  when "<="
287
- "<=" + latest_resolvable_version.to_s
322
+ "<=" + T.must(latest_resolvable_version).to_s
288
323
  when "!=", ">", ">="
289
324
  raise UnfixableRequirement
290
325
  else
@@ -298,10 +333,11 @@ module Dependabot
298
333
  end
299
334
 
300
335
  # Updates the version in a constraint to be the given version
336
+ sig { params(req_string: String, version_to_be_permitted: String).returns(String) }
301
337
  def bump_version(req_string, version_to_be_permitted)
302
- old_version = req_string
303
- .match(/(#{RequirementParser::VERSION})/o)
304
- .captures.first
338
+ old_version = T.must(T.must(req_string
339
+ .match(/(#{RequirementParser::VERSION})/o))
340
+ .captures.first)
305
341
 
306
342
  req_string.sub(
307
343
  old_version,
@@ -309,14 +345,15 @@ module Dependabot
309
345
  )
310
346
  end
311
347
 
348
+ sig { params(req_string: String, version_to_be_permitted: Dependabot::Python::Version).returns(String) }
312
349
  def convert_to_range(req_string, version_to_be_permitted)
313
350
  # Construct an upper bound at the same precision that the original
314
351
  # requirement was at (taking into account ~ dynamics)
315
352
  index_to_update = index_to_update_for(req_string)
316
- ub_segments = version_to_be_permitted.segments
317
- ub_segments << 0 while ub_segments.count <= index_to_update
318
- ub_segments = ub_segments[0..index_to_update]
319
- ub_segments[index_to_update] += 1
353
+ ub_segments = T.let(version_to_be_permitted.segments, T::Array[T.any(String, Integer)])
354
+ ub_segments << "0" while ub_segments.count <= index_to_update
355
+ ub_segments = T.must(ub_segments[0..index_to_update])
356
+ ub_segments[index_to_update] = T.must(ub_segments[index_to_update]).to_i + 1
320
357
 
321
358
  lb_segments = lower_bound_segments_for_req(req_string)
322
359
 
@@ -328,6 +365,7 @@ module Dependabot
328
365
  ">=#{lb_segments.join('.')},<#{ub_segments.join('.')}"
329
366
  end
330
367
 
368
+ sig { params(req_string: String).returns(T::Array[Integer]) }
331
369
  def lower_bound_segments_for_req(req_string)
332
370
  requirement = requirement_class.new(req_string)
333
371
  version = requirement.requirements.first.last
@@ -339,6 +377,7 @@ module Dependabot
339
377
  lb_segments
340
378
  end
341
379
 
380
+ sig { params(req_string: String).returns(Integer) }
342
381
  def index_to_update_for(req_string)
343
382
  req = requirement_class.new(req_string.split(/[.\-]\*/).first)
344
383
  version = req.requirements.first.last.release
@@ -357,6 +396,12 @@ module Dependabot
357
396
  end
358
397
 
359
398
  # Updates the version in a "<" constraint to allow the given version
399
+ sig do
400
+ params(
401
+ version: Gem::Version,
402
+ version_to_be_permitted: T.any(String, Dependabot::Python::Version)
403
+ ).returns(String)
404
+ end
360
405
  def update_greatest_version(version, version_to_be_permitted)
361
406
  if version_to_be_permitted.is_a?(String)
362
407
  version_to_be_permitted =
@@ -365,7 +410,7 @@ module Dependabot
365
410
  version = version.release if version.prerelease?
366
411
 
367
412
  index_to_update = [
368
- version.segments.map.with_index { |n, i| n.zero? ? 0 : i }.max,
413
+ version.segments.map.with_index { |n, i| n.to_i.zero? ? 0 : i }.max,
369
414
  version_to_be_permitted.segments.count - 1
370
415
  ].min
371
416
 
@@ -373,7 +418,7 @@ module Dependabot
373
418
  if index < index_to_update
374
419
  version_to_be_permitted.segments[index]
375
420
  elsif index == index_to_update
376
- version_to_be_permitted.segments[index] + 1
421
+ version_to_be_permitted.segments[index].to_i + 1
377
422
  else
378
423
  0
379
424
  end
@@ -382,6 +427,7 @@ module Dependabot
382
427
  new_segments.join(".")
383
428
  end
384
429
 
430
+ sig { returns(T.class_of(Dependabot::Python::Requirement)) }
385
431
  def requirement_class
386
432
  Python::Requirement
387
433
  end
@@ -1,6 +1,7 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
+ require "sorbet-runtime"
4
5
  require "dependabot/version"
5
6
  require "dependabot/utils"
6
7
 
@@ -9,6 +10,8 @@ require "dependabot/utils"
9
10
  module Dependabot
10
11
  module Python
11
12
  class Version < Dependabot::Version
13
+ extend T::Sig
14
+
12
15
  sig { returns(Integer) }
13
16
  attr_reader :epoch
14
17
 
@@ -27,8 +30,8 @@ module Dependabot
27
30
  sig { returns(T.nilable(T::Array[T.any(String, Integer)])) }
28
31
  attr_reader :local
29
32
 
30
- INFINITY = 1000
31
- NEGATIVE_INFINITY = -INFINITY
33
+ INFINITY = T.let(1000, Integer)
34
+ NEGATIVE_INFINITY = T.let(-INFINITY, Integer)
32
35
 
33
36
  # See https://peps.python.org/pep-0440/#appendix-b-parsing-version-strings-with-regular-expressions
34
37
  VERSION_PATTERN = /
@@ -72,10 +75,10 @@ module Dependabot
72
75
  end
73
76
 
74
77
  sig { override.params(version: VersionParameter).void }
75
- def initialize(version)
78
+ def initialize(version) # rubocop:disable Metrics/AbcSize
76
79
  raise Dependabot::BadRequirementError, "Malformed version string - string is nil" if version.nil?
77
80
 
78
- @version_string = version.to_s
81
+ @version_string = T.let(version.to_s, String)
79
82
 
80
83
  raise Dependabot::BadRequirementError, "Malformed version string - string is empty" if @version_string.empty?
81
84
 
@@ -86,12 +89,17 @@ module Dependabot
86
89
  "Malformed version string - #{@version_string} does not match regex"
87
90
  end
88
91
 
89
- @epoch = matches["epoch"].to_i
90
- @release_segment = matches["release"]&.split(".")&.map(&:to_i) || []
91
- @pre = parse_letter_version(matches["pre_l"], matches["pre_n"])
92
- @post = parse_letter_version(matches["post_l"], matches["post_n1"] || matches["post_n2"])
93
- @dev = parse_letter_version(matches["dev_l"], matches["dev_n"])
94
- @local = parse_local_version(matches["local"])
92
+ @epoch = T.let(matches["epoch"].to_i, Integer)
93
+ @release_segment = T.let(matches["release"]&.split(".")&.map(&:to_i) || [], T::Array[Integer])
94
+ @pre = T.let(parse_letter_version(matches["pre_l"], matches["pre_n"]),
95
+ T.nilable(T::Array[T.any(String, Integer)]))
96
+ @post = T.let(
97
+ parse_letter_version(matches["post_l"], matches["post_n1"] || matches["post_n2"]),
98
+ T.nilable(T::Array[T.any(String, Integer)])
99
+ )
100
+ @dev = T.let(parse_letter_version(matches["dev_l"], matches["dev_n"]),
101
+ T.nilable(T::Array[T.any(String, Integer)]))
102
+ @local = T.let(parse_local_version(matches["local"]), T.nilable(T::Array[T.any(String, Integer)]))
95
103
  super(matches["release"] || "")
96
104
  end
97
105
 
@@ -123,7 +131,6 @@ module Dependabot
123
131
  sig { params(other: VersionParameter).returns(Integer) }
124
132
  def <=>(other)
125
133
  other = Dependabot::Python::Version.new(other.to_s) unless other.is_a?(Dependabot::Python::Version)
126
- other = T.cast(other, Dependabot::Python::Version)
127
134
 
128
135
  epoch_comparison = epoch <=> other.epoch
129
136
  return epoch_comparison unless epoch_comparison.zero?
@@ -183,13 +190,13 @@ module Dependabot
183
190
  # - Alphanumeric segments sort lexicographically
184
191
  # - Numeric segments sort numerically
185
192
  # - Shorter versions sort before longer versions when the prefixes match exactly
186
- local&.map do |token|
193
+ T.must(local).map do |token|
187
194
  if token.is_a?(Integer)
188
195
  [token, ""]
189
196
  else
190
197
  [NEGATIVE_INFINITY, token]
191
198
  end
192
- end
199
+ end.flatten
193
200
  end
194
201
  end
195
202
 
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.320.0
4
+ version: 0.320.1
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.320.0
18
+ version: 0.320.1
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.320.0
25
+ version: 0.320.1
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: debug
28
28
  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.320.0
293
+ changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.320.1
294
294
  rdoc_options: []
295
295
  require_paths:
296
296
  - lib