dependabot-uv 0.299.1 → 0.300.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 37479ebd370ef17d7a56b2e53b0f9e94d93608fcbafdfb98a588d23f3f61c8f7
4
- data.tar.gz: d3ff78147e58cf5fe353773c9bdf6c7f920c6ae73140de722827ce3f335ba30d
3
+ metadata.gz: 3e306a8d52bca54571baf167605279980eeb625a9dcfbad1128a13de55270936
4
+ data.tar.gz: 7bd9b6a85cf4e76675eaf401ed285acad0e6e518920e3cd344ae0074fa8a3a2a
5
5
  SHA512:
6
- metadata.gz: 413470f2e052517d9a689131997e6425bf253e13cf558a1a217b4f7322ba4cfc28e9d78436a8249e3373ef9d7531fb8b6f5480b19401fcfc61be134c334986fd
7
- data.tar.gz: a8edce98cdf17c759619019ab9406c4120c67129d884da7cc7111b2d247ba426ee865e53523b75c3ecd9c5fd93eaf9944071732f37ff59111e1955ead835d556
6
+ metadata.gz: 8a4fb9a0de4405de4e3130e78e917fc41480770e9b2053d7b368bbcfe397d202f12fde5db46edc563047322354abe87ff65a14190560f960b0c93f56e1d7a6fb
7
+ data.tar.gz: 0f5f35583b805d8a5047bbea2c69db49636759c63f7afc50f0957368d99f5ae874b742ade653f6983e8c5401b34cd0d966b092c14a0ea836993a704fde5f0e63
@@ -7,7 +7,7 @@ require "sorbet-runtime"
7
7
  require "dependabot/file_fetchers"
8
8
  require "dependabot/file_fetchers/base"
9
9
  require "dependabot/uv/language_version_manager"
10
- require "dependabot/uv/pip_compile_file_matcher"
10
+ require "dependabot/uv/requirements_file_matcher"
11
11
  require "dependabot/uv/requirement_parser"
12
12
  require "dependabot/uv/file_parser/pyproject_files_parser"
13
13
  require "dependabot/uv/file_parser/python_requirement_parser"
@@ -295,7 +295,7 @@ module Dependabot
295
295
 
296
296
  def parse_requirement_path_dependencies(req_file)
297
297
  # If this is a pip-compile lockfile, rely on whatever path dependencies we found in the main manifest
298
- return [] if pip_compile_file_matcher.lockfile_for_pip_compile_file?(req_file)
298
+ return [] if requirements_in_file_matcher.compiled_file?(req_file)
299
299
 
300
300
  uneditable_reqs =
301
301
  req_file.content
@@ -318,8 +318,8 @@ module Dependabot
318
318
  Pathname.new(path).cleanpath.to_path
319
319
  end
320
320
 
321
- def pip_compile_file_matcher
322
- @pip_compile_file_matcher ||= PipCompileFileMatcher.new(requirements_in_files)
321
+ def requirements_in_file_matcher
322
+ @requirements_in_file_matcher ||= RequiremenstFileMatcher.new(requirements_in_files)
323
323
  end
324
324
  end
325
325
  end
@@ -6,7 +6,7 @@ require "open3"
6
6
  require "dependabot/errors"
7
7
  require "dependabot/shared_helpers"
8
8
  require "dependabot/uv/file_parser"
9
- require "dependabot/uv/pip_compile_file_matcher"
9
+ require "dependabot/uv/requirements_file_matcher"
10
10
  require "dependabot/uv/requirement"
11
11
 
12
12
  module Dependabot
@@ -21,12 +21,10 @@ module Dependabot
21
21
 
22
22
  def user_specified_requirements
23
23
  [
24
- pipfile_python_requirement,
25
24
  pyproject_python_requirement,
26
25
  pip_compile_python_requirement,
27
26
  python_version_file_version,
28
- runtime_file_python_version,
29
- setup_file_requirement
27
+ runtime_file_python_version
30
28
  ].compact
31
29
  end
32
30
 
@@ -44,18 +42,6 @@ module Dependabot
44
42
 
45
43
  private
46
44
 
47
- def pipfile_python_requirement
48
- return unless pipfile
49
-
50
- parsed_pipfile = TomlRB.parse(pipfile.content)
51
- requirement =
52
- parsed_pipfile.dig("requires", "python_full_version") ||
53
- parsed_pipfile.dig("requires", "python_version")
54
- return unless requirement&.match?(/^\d/)
55
-
56
- requirement
57
- end
58
-
59
45
  def pyproject_python_requirement
60
46
  return unless pyproject
61
47
 
@@ -74,7 +60,7 @@ module Dependabot
74
60
 
75
61
  def pip_compile_python_requirement
76
62
  requirement_files.each do |file|
77
- next unless pip_compile_file_matcher.lockfile_for_pip_compile_file?(file)
63
+ next unless requirements_in_file_matcher.compiled_file?(file)
78
64
 
79
65
  marker = /^# This file is autogenerated by pip-compile with [pP]ython (?<version>\d+.\d+)$/m
80
66
  match = marker.match(file.content)
@@ -112,19 +98,6 @@ module Dependabot
112
98
  file_version
113
99
  end
114
100
 
115
- def setup_file_requirement
116
- return unless setup_file
117
-
118
- req = setup_file.content
119
- .match(/python_requires\s*=\s*['"](?<req>[^'"]+)['"]/)
120
- &.named_captures&.fetch("req")&.strip
121
-
122
- requirement_class.new(req)
123
- req
124
- rescue Gem::Requirement::BadRequirementError
125
- nil
126
- end
127
-
128
101
  def pyenv_versions
129
102
  @pyenv_versions ||= run_command("pyenv install --list")
130
103
  end
@@ -133,8 +106,8 @@ module Dependabot
133
106
  SharedHelpers.run_shell_command(command, env: env, stderr_to_stdout: true)
134
107
  end
135
108
 
136
- def pip_compile_file_matcher
137
- @pip_compile_file_matcher ||= PipCompileFileMatcher.new(pip_compile_files)
109
+ def requirements_in_file_matcher
110
+ @requirements_in_file_matcher ||= RequiremenstFileMatcher.new(pip_compile_files)
138
111
  end
139
112
 
140
113
  def requirement_class
@@ -148,22 +121,10 @@ module Dependabot
148
121
  false
149
122
  end
150
123
 
151
- def pipfile
152
- dependency_files.find { |f| f.name == "Pipfile" }
153
- end
154
-
155
- def pipfile_lock
156
- dependency_files.find { |f| f.name == "Pipfile.lock" }
157
- end
158
-
159
124
  def pyproject
160
125
  dependency_files.find { |f| f.name == "pyproject.toml" }
161
126
  end
162
127
 
163
- def setup_file
164
- dependency_files.find { |f| f.name == "setup.py" }
165
- end
166
-
167
128
  def python_version_file
168
129
  dependency_files.find { |f| f.name == ".python-version" }
169
130
  end
@@ -11,7 +11,7 @@ require "dependabot/errors"
11
11
  require "dependabot/uv/language"
12
12
  require "dependabot/uv/native_helpers"
13
13
  require "dependabot/uv/name_normaliser"
14
- require "dependabot/uv/pip_compile_file_matcher"
14
+ require "dependabot/uv/requirements_file_matcher"
15
15
  require "dependabot/uv/language_version_manager"
16
16
  require "dependabot/uv/package_manager"
17
17
 
@@ -19,9 +19,7 @@ module Dependabot
19
19
  module Uv
20
20
  class FileParser < Dependabot::FileParsers::Base
21
21
  extend T::Sig
22
- require_relative "file_parser/pipfile_files_parser"
23
22
  require_relative "file_parser/pyproject_files_parser"
24
- require_relative "file_parser/setup_file_parser"
25
23
  require_relative "file_parser/python_requirement_parser"
26
24
 
27
25
  DEPENDENCY_GROUP_KEYS = T.let([
@@ -40,15 +38,12 @@ module Dependabot
40
38
  ).freeze
41
39
 
42
40
  # we use this placeholder version in case we are not able to detect any
43
- # PIP version from shell, we are ensuring that the actual update is not blocked
41
+ # uv version from shell, we are ensuring that the actual update is not blocked
44
42
  # in any way if any metric collection exception start happening
45
43
  UNDETECTED_PACKAGE_MANAGER_VERSION = "0.0"
46
44
 
47
- sig { override.returns(T::Array[Dependabot::Dependency]) }
45
+ sig { override.returns(T::Array[Dependency]) }
48
46
  def parse
49
- # TODO: setup.py from external dependencies is evaluated. Provide guards before removing this.
50
- raise Dependabot::UnexpectedExternalCode if @reject_external_code
51
-
52
47
  dependency_set = DependencySet.new
53
48
 
54
49
  dependency_set += pyproject_file_dependencies if pyproject
@@ -71,56 +66,49 @@ module Dependabot
71
66
 
72
67
  private
73
68
 
74
- sig { returns(Dependabot::Uv::LanguageVersionManager) }
69
+ sig { returns(LanguageVersionManager) }
75
70
  def language_version_manager
76
71
  @language_version_manager ||= T.let(LanguageVersionManager.new(python_requirement_parser:
77
72
  python_requirement_parser), T.nilable(LanguageVersionManager))
78
73
  end
79
74
 
80
- sig { returns(Dependabot::Uv::FileParser::PythonRequirementParser) }
75
+ sig { returns(FileParser::PythonRequirementParser) }
81
76
  def python_requirement_parser
82
- @python_requirement_parser ||= T.let(FileParser::PythonRequirementParser.new(dependency_files:
83
- dependency_files), T.nilable(FileParser::PythonRequirementParser))
77
+ @python_requirement_parser ||= T.let(PythonRequirementParser.new(dependency_files:
78
+ dependency_files), T.nilable(PythonRequirementParser))
84
79
  end
85
80
 
86
81
  sig { returns(Ecosystem::VersionManager) }
87
82
  def package_manager
88
- if Dependabot::Experiments.enabled?(:enable_file_parser_python_local)
83
+ if Experiments.enabled?(:enable_file_parser_python_local)
89
84
  Dependabot.logger.info("Detected package manager : #{detected_package_manager.name}")
90
85
  end
91
86
 
92
- @package_manager ||= T.let(detected_package_manager, T.nilable(Dependabot::Ecosystem::VersionManager))
87
+ @package_manager ||= T.let(detected_package_manager, T.nilable(Ecosystem::VersionManager))
93
88
  end
94
89
 
95
90
  sig { returns(Ecosystem::VersionManager) }
96
91
  def detected_package_manager
97
- setup_python_environment if Dependabot::Experiments.enabled?(:enable_file_parser_python_local)
92
+ setup_python_environment if Experiments.enabled?(:enable_file_parser_python_local)
98
93
 
99
- PackageManager.new(T.must(detect_pipcompile_version))
94
+ PackageManager.new(T.must(detect_uv_version))
100
95
  end
101
96
 
102
- # Detects the version of pip-compile. If the version cannot be detected, it returns nil
103
97
  sig { returns(T.nilable(String)) }
104
- def detect_pipcompile_version
105
- if pipcompile_in_file
106
- package_manager = PackageManager::NAME
107
-
108
- version = package_manager_version(package_manager)
109
- .to_s.split("version ").last&.split(")")&.first
98
+ def detect_uv_version
99
+ version = uv_version.to_s.split("version ").last&.split(")")&.first
110
100
 
111
- log_if_version_malformed(package_manager, version)
101
+ log_if_version_malformed("uv", version)
112
102
 
113
- # makes sure we have correct version format returned
114
- version if version&.match?(/^\d+(?:\.\d+)*$/)
115
- end
103
+ version if version&.match?(/^\d+(?:\.\d+)*$/)
116
104
  rescue StandardError
117
105
  nil
118
106
  end
119
107
 
120
- sig { params(package_manager: String).returns(T.any(String, T.untyped)) }
121
- def package_manager_version(package_manager)
122
- version_info = SharedHelpers.run_shell_command("pyenv exec #{package_manager} --version")
123
- Dependabot.logger.info("Package manager #{package_manager}, Info : #{version_info}")
108
+ sig { returns(T.any(String, T.untyped)) }
109
+ def uv_version
110
+ version_info = SharedHelpers.run_shell_command("pyenv exec uv --version")
111
+ Dependabot.logger.info("Package manager uv, Info : #{version_info}")
124
112
 
125
113
  version_info.match(/\d+(?:\.\d+)*/)&.to_s
126
114
  rescue StandardError => e
@@ -128,7 +116,6 @@ module Dependabot
128
116
  nil
129
117
  end
130
118
 
131
- # setup python local setup on file parser stage
132
119
  sig { returns(T.nilable(String)) }
133
120
  def setup_python_environment
134
121
  language_version_manager.install_required_python
@@ -141,7 +128,6 @@ module Dependabot
141
128
 
142
129
  sig { params(package_manager: String, version: String).returns(T::Boolean) }
143
130
  def log_if_version_malformed(package_manager, version)
144
- # logs warning if malformed version is found
145
131
  if version.match?(/^\d+(?:\.\d+)*$/)
146
132
  true
147
133
  else
@@ -152,7 +138,7 @@ module Dependabot
152
138
 
153
139
  sig { returns(String) }
154
140
  def python_raw_version
155
- if Dependabot::Experiments.enabled?(:enable_file_parser_python_local)
141
+ if Experiments.enabled?(:enable_file_parser_python_local)
156
142
  Dependabot.logger.info("Detected python version: #{language_version_manager.python_version}")
157
143
  Dependabot.logger.info("Detected python major minor version: #{language_version_manager.python_major_minor}")
158
144
  end
@@ -173,17 +159,11 @@ module Dependabot
173
159
  )
174
160
  end
175
161
 
176
- sig { returns(T::Array[Dependabot::DependencyFile]) }
162
+ sig { returns(T::Array[DependencyFile]) }
177
163
  def requirement_files
178
164
  dependency_files.select { |f| f.name.end_with?(".txt", ".in") }
179
165
  end
180
166
 
181
- sig { returns(DependencySet) }
182
- def pipenv_dependencies
183
- @pipenv_dependencies ||= T.let(PipfileFilesParser.new(dependency_files:
184
- dependency_files).dependency_set, T.nilable(DependencySet))
185
- end
186
-
187
167
  sig { returns(DependencySet) }
188
168
  def pyproject_file_dependencies
189
169
  @pyproject_file_dependencies ||= T.let(PyprojectFilesParser.new(dependency_files:
@@ -194,8 +174,6 @@ module Dependabot
194
174
  def requirement_dependencies
195
175
  dependencies = DependencySet.new
196
176
  parsed_requirement_files.each do |dep|
197
- # If a requirement has a `<`, `<=` or '==' marker then updating it is
198
- # probably blocked. Ignore it.
199
177
  next if blocking_marker?(dep)
200
178
 
201
179
  name = dep["name"]
@@ -204,7 +182,7 @@ module Dependabot
204
182
  original_file = get_original_file(file)
205
183
 
206
184
  requirements =
207
- if original_file && pip_compile_file_matcher.lockfile_for_pip_compile_file?(original_file) then []
185
+ if original_file && requirements_in_file_matcher.compiled_file?(original_file) then []
208
186
  else
209
187
  [{
210
188
  requirement: dep["requirement"],
@@ -214,7 +192,7 @@ module Dependabot
214
192
  }]
215
193
  end
216
194
 
217
- # PyYAML < 6.0 will cause `pip-compile` to fail due to incompatibility with Cython 3. Workaround it.
195
+ # PyYAML < 6.0 will cause `pip-compile` to fail due to incompatibility with Cython 3. Workaround it. PR #8189
218
196
  SharedHelpers.run_shell_command("pyenv exec pip install cython<3.0") if old_pyyaml?(name, version)
219
197
 
220
198
  dependencies <<
@@ -268,7 +246,6 @@ module Dependabot
268
246
  def marker_satisfied?(marker, python_version)
269
247
  conditions = marker.split(/\s+(and|or)\s+/)
270
248
 
271
- # Explicitly define the type of result as T::Boolean
272
249
  result = T.let(evaluate_condition(conditions.shift, python_version), T::Boolean)
273
250
 
274
251
  until conditions.empty?
@@ -295,26 +272,20 @@ module Dependabot
295
272
 
296
273
  case operator
297
274
  when "<"
298
- Dependabot::Uv::Version.new(python_version) < Dependabot::Uv::Version.new(version)
275
+ Version.new(python_version) < Version.new(version)
299
276
  when "<="
300
- Dependabot::Uv::Version.new(python_version) <= Dependabot::Uv::Version.new(version)
277
+ Version.new(python_version) <= Version.new(version)
301
278
  when ">"
302
- Dependabot::Uv::Version.new(python_version) > Dependabot::Uv::Version.new(version)
279
+ Version.new(python_version) > Version.new(version)
303
280
  when ">="
304
- Dependabot::Uv::Version.new(python_version) >= Dependabot::Uv::Version.new(version)
281
+ Version.new(python_version) >= Version.new(version)
305
282
  when "=="
306
- Dependabot::Uv::Version.new(python_version) == Dependabot::Uv::Version.new(version)
283
+ Version.new(python_version) == Version.new(version)
307
284
  else
308
285
  false
309
286
  end
310
287
  end
311
288
 
312
- sig { returns(DependencySet) }
313
- def setup_file_dependencies
314
- @setup_file_dependencies ||= T.let(SetupFileParser.new(dependency_files: dependency_files)
315
- .dependency_set, T.nilable(DependencySet))
316
- end
317
-
318
289
  sig { returns(T.untyped) }
319
290
  def parsed_requirement_files
320
291
  SharedHelpers.in_a_temporary_directory do
@@ -333,7 +304,7 @@ module Dependabot
333
304
  evaluation_errors = REQUIREMENT_FILE_EVALUATION_ERRORS
334
305
  raise unless e.message.start_with?(*evaluation_errors)
335
306
 
336
- raise Dependabot::DependencyFileNotEvaluatable, e.message
307
+ raise DependencyFileNotEvaluatable, e.message
337
308
  end
338
309
 
339
310
  sig { params(requirements: T.untyped).returns(T.untyped) }
@@ -341,18 +312,13 @@ module Dependabot
341
312
  requirements.each do |dep|
342
313
  next unless dep["requirement"]
343
314
 
344
- Uv::Requirement.new(dep["requirement"].split(","))
315
+ Requirement.new(dep["requirement"].split(","))
345
316
  rescue Gem::Requirement::BadRequirementError => e
346
- raise Dependabot::DependencyFileNotEvaluatable, e.message
317
+ raise DependencyFileNotEvaluatable, e.message
347
318
  end
348
319
  end
349
320
 
350
- sig { returns(T::Boolean) }
351
- def pipcompile_in_file
352
- requirement_files.any? { |f| f.name.end_with?(PackageManager::MANIFEST_FILENAME) }
353
- end
354
-
355
- sig { returns(T::Array[Dependabot::DependencyFile]) }
321
+ sig { returns(T::Array[DependencyFile]) }
356
322
  def write_temporary_dependency_files
357
323
  dependency_files
358
324
  .reject { |f| f.name == ".python-version" }
@@ -382,53 +348,25 @@ module Dependabot
382
348
  def check_required_files
383
349
  filenames = dependency_files.map(&:name)
384
350
  return if filenames.any? { |name| name.end_with?(".txt", ".in") }
385
- return if pipfile
386
351
  return if pyproject
387
- return if setup_file
388
- return if setup_cfg_file
389
352
 
390
353
  raise "Missing required files!"
391
354
  end
392
355
 
393
- sig { returns(T.nilable(Dependabot::DependencyFile)) }
394
- def pipfile
395
- @pipfile ||= T.let(get_original_file("Pipfile"), T.nilable(Dependabot::DependencyFile))
396
- end
397
-
398
- sig { returns(T.nilable(Dependabot::DependencyFile)) }
399
- def pipfile_lock
400
- @pipfile_lock ||= T.let(get_original_file("Pipfile.lock"), T.nilable(Dependabot::DependencyFile))
401
- end
402
-
403
- sig { returns(T.nilable(Dependabot::DependencyFile)) }
356
+ sig { returns(T.nilable(DependencyFile)) }
404
357
  def pyproject
405
- @pyproject ||= T.let(get_original_file("pyproject.toml"), T.nilable(Dependabot::DependencyFile))
406
- end
407
-
408
- sig { returns(T.nilable(Dependabot::DependencyFile)) }
409
- def poetry_lock
410
- @poetry_lock ||= T.let(get_original_file("poetry.lock"), T.nilable(Dependabot::DependencyFile))
411
- end
412
-
413
- sig { returns(T.nilable(Dependabot::DependencyFile)) }
414
- def setup_file
415
- @setup_file ||= T.let(get_original_file("setup.py"), T.nilable(Dependabot::DependencyFile))
416
- end
417
-
418
- sig { returns(T.nilable(Dependabot::DependencyFile)) }
419
- def setup_cfg_file
420
- @setup_cfg_file ||= T.let(get_original_file("setup.cfg"), T.nilable(Dependabot::DependencyFile))
358
+ @pyproject ||= T.let(get_original_file("pyproject.toml"), T.nilable(DependencyFile))
421
359
  end
422
360
 
423
- sig { returns(T::Array[Dependabot::Uv::Requirement]) }
424
- def pip_compile_files
425
- @pip_compile_files ||= T.let(dependency_files.select { |f| f.name.end_with?(".in") }, T.untyped)
361
+ sig { returns(T::Array[Requirement]) }
362
+ def requirements_in_files
363
+ @requirements_in_files ||= T.let(dependency_files.select { |f| f.name.end_with?(".in") }, T.untyped)
426
364
  end
427
365
 
428
- sig { returns(Dependabot::Uv::PipCompileFileMatcher) }
429
- def pip_compile_file_matcher
430
- @pip_compile_file_matcher ||= T.let(PipCompileFileMatcher.new(pip_compile_files),
431
- T.nilable(Dependabot::Uv::PipCompileFileMatcher))
366
+ sig { returns(RequiremenstFileMatcher) }
367
+ def requirements_in_file_matcher
368
+ @requirements_in_file_matcher ||= T.let(RequiremenstFileMatcher.new(requirements_in_files),
369
+ T.nilable(RequiremenstFileMatcher))
432
370
  end
433
371
  end
434
372
  end
@@ -3,16 +3,16 @@
3
3
 
4
4
  module Dependabot
5
5
  module Uv
6
- class PipCompileFileMatcher
6
+ class RequiremenstFileMatcher
7
7
  extend T::Sig
8
8
 
9
- sig { params(requirements_in_files: T::Array[Dependabot::Uv::Requirement]).void }
9
+ sig { params(requirements_in_files: T::Array[Requirement]).void }
10
10
  def initialize(requirements_in_files)
11
11
  @requirements_in_files = requirements_in_files
12
12
  end
13
13
 
14
- sig { params(file: Dependabot::DependencyFile).returns(T::Boolean) }
15
- def lockfile_for_pip_compile_file?(file)
14
+ sig { params(file: DependencyFile).returns(T::Boolean) }
15
+ def compiled_file?(file)
16
16
  return false unless requirements_in_files.any?
17
17
 
18
18
  name = file.name
@@ -26,7 +26,7 @@ module Dependabot
26
26
 
27
27
  private
28
28
 
29
- sig { returns(T::Array[Dependabot::Uv::Requirement]) }
29
+ sig { returns(T::Array[Requirement]) }
30
30
  attr_reader :requirements_in_files
31
31
 
32
32
  sig { params(filename: T.any(String, Symbol)).returns(String) }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dependabot-uv
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.299.1
4
+ version: 0.300.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dependabot
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-02-28 00:00:00.000000000 Z
11
+ date: 2025-03-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dependabot-common
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 0.299.1
19
+ version: 0.300.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 0.299.1
26
+ version: 0.300.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: debug
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -252,7 +252,6 @@ files:
252
252
  - lib/dependabot/uv/authed_url_builder.rb
253
253
  - lib/dependabot/uv/file_fetcher.rb
254
254
  - lib/dependabot/uv/file_parser.rb
255
- - lib/dependabot/uv/file_parser/pipfile_files_parser.rb
256
255
  - lib/dependabot/uv/file_parser/pyproject_files_parser.rb
257
256
  - lib/dependabot/uv/file_parser/python_requirement_parser.rb
258
257
  - lib/dependabot/uv/file_parser/setup_file_parser.rb
@@ -267,10 +266,10 @@ files:
267
266
  - lib/dependabot/uv/name_normaliser.rb
268
267
  - lib/dependabot/uv/native_helpers.rb
269
268
  - lib/dependabot/uv/package_manager.rb
270
- - lib/dependabot/uv/pip_compile_file_matcher.rb
271
269
  - lib/dependabot/uv/pipenv_runner.rb
272
270
  - lib/dependabot/uv/requirement.rb
273
271
  - lib/dependabot/uv/requirement_parser.rb
272
+ - lib/dependabot/uv/requirements_file_matcher.rb
274
273
  - lib/dependabot/uv/update_checker.rb
275
274
  - lib/dependabot/uv/update_checker/index_finder.rb
276
275
  - lib/dependabot/uv/update_checker/latest_version_finder.rb
@@ -283,7 +282,7 @@ licenses:
283
282
  - MIT
284
283
  metadata:
285
284
  bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
286
- changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.299.1
285
+ changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.300.0
287
286
  post_install_message:
288
287
  rdoc_options: []
289
288
  require_paths:
@@ -1,192 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- require "toml-rb"
5
-
6
- require "dependabot/dependency"
7
- require "dependabot/file_parsers/base/dependency_set"
8
- require "dependabot/uv/file_parser"
9
- require "dependabot/errors"
10
- require "dependabot/uv/name_normaliser"
11
-
12
- module Dependabot
13
- module Uv
14
- class FileParser
15
- class PipfileFilesParser
16
- extend T::Sig
17
- DEPENDENCY_GROUP_KEYS = T.let([
18
- {
19
- pipfile: "packages",
20
- lockfile: "default"
21
- },
22
- {
23
- pipfile: "dev-packages",
24
- lockfile: "develop"
25
- }
26
- ].freeze, T::Array[T::Hash[Symbol, String]])
27
-
28
- sig { params(dependency_files: T::Array[Dependabot::DependencyFile]).void }
29
- def initialize(dependency_files:)
30
- @dependency_files = dependency_files
31
- end
32
-
33
- sig { returns(Dependabot::FileParsers::Base::DependencySet) }
34
- def dependency_set
35
- dependency_set = Dependabot::FileParsers::Base::DependencySet.new
36
-
37
- dependency_set += pipfile_dependencies
38
- dependency_set += pipfile_lock_dependencies
39
-
40
- dependency_set
41
- end
42
-
43
- private
44
-
45
- sig { returns(T::Array[Dependabot::DependencyFile]) }
46
- attr_reader :dependency_files
47
-
48
- sig { returns(Dependabot::FileParsers::Base::DependencySet) }
49
- def pipfile_dependencies
50
- dependencies = Dependabot::FileParsers::Base::DependencySet.new
51
-
52
- DEPENDENCY_GROUP_KEYS.each do |keys|
53
- next unless parsed_pipfile[T.must(keys[:pipfile])]
54
-
55
- parsed_pipfile[T.must(keys[:pipfile])].map do |dep_name, req|
56
- group = keys[:lockfile]
57
- next unless specifies_version?(req)
58
- next if git_or_path_requirement?(req)
59
- next if pipfile_lock && !dependency_version(dep_name, req, T.must(group))
60
-
61
- # Empty requirements are not allowed in Dependabot::Dependency and
62
- # equivalent to "*" (latest available version)
63
- req = "*" if req == ""
64
-
65
- dependencies <<
66
- Dependency.new(
67
- name: normalised_name(dep_name),
68
- version: dependency_version(dep_name, req, T.must(group)),
69
- requirements: [{
70
- requirement: req.is_a?(String) ? req : req["version"],
71
- file: T.must(pipfile).name,
72
- source: nil,
73
- groups: [group]
74
- }],
75
- package_manager: "uv",
76
- metadata: { original_name: dep_name }
77
- )
78
- end
79
- end
80
-
81
- dependencies
82
- end
83
-
84
- # Create a DependencySet where each element has no requirement. Any
85
- # requirements will be added when combining the DependencySet with
86
- # other DependencySets.
87
- sig { returns(Dependabot::FileParsers::Base::DependencySet) }
88
- def pipfile_lock_dependencies
89
- dependencies = Dependabot::FileParsers::Base::DependencySet.new
90
- return dependencies unless pipfile_lock
91
-
92
- DEPENDENCY_GROUP_KEYS.map { |h| h.fetch(:lockfile) }.each do |key|
93
- next unless parsed_pipfile_lock[key]
94
-
95
- parsed_pipfile_lock[key].each do |dep_name, details|
96
- version = case details
97
- when String then details
98
- when Hash then details["version"]
99
- end
100
- next unless version
101
- next if git_or_path_requirement?(details)
102
-
103
- dependencies <<
104
- Dependency.new(
105
- name: dep_name,
106
- version: version&.gsub(/^===?/, ""),
107
- requirements: [],
108
- package_manager: "uv",
109
- subdependency_metadata: [{ production: key != "develop" }]
110
- )
111
- end
112
- end
113
-
114
- dependencies
115
- end
116
-
117
- sig do
118
- params(dep_name: String, requirement: T.any(String, T::Hash[String, T.untyped]),
119
- group: String).returns(T.nilable(String))
120
- end
121
- def dependency_version(dep_name, requirement, group)
122
- req = version_from_hash_or_string(requirement)
123
-
124
- if pipfile_lock
125
- details = parsed_pipfile_lock
126
- .dig(group, normalised_name(dep_name))
127
-
128
- version = version_from_hash_or_string(details)
129
- version&.gsub(/^===?/, "")
130
- elsif T.must(req).start_with?("==") && !T.must(req).include?("*")
131
- T.must(req).strip.gsub(/^===?/, "")
132
- end
133
- end
134
-
135
- sig do
136
- params(obj: T.any(String, NilClass, T::Array[String], T::Hash[String, T.untyped])).returns(T.nilable(String))
137
- end
138
- def version_from_hash_or_string(obj)
139
- case obj
140
- when String then obj.strip
141
- when Hash then obj["version"]
142
- end
143
- end
144
-
145
- sig { params(req: T.any(String, T::Hash[String, T.untyped])).returns(T.any(T::Boolean, NilClass, String)) }
146
- def specifies_version?(req)
147
- return true if req.is_a?(String)
148
-
149
- req["version"]
150
- end
151
-
152
- sig { params(req: T.any(String, T::Hash[String, T.untyped])).returns(T::Boolean) }
153
- def git_or_path_requirement?(req)
154
- return false unless req.is_a?(Hash)
155
-
156
- %w(git path).any? { |k| req.key?(k) }
157
- end
158
-
159
- sig { params(name: String, extras: T::Array[String]).returns(String) }
160
- def normalised_name(name, extras = [])
161
- NameNormaliser.normalise_including_extras(name, extras)
162
- end
163
-
164
- sig { returns(T::Hash[String, T.untyped]) }
165
- def parsed_pipfile
166
- @parsed_pipfile ||= T.let(TomlRB.parse(T.must(pipfile).content), T.nilable(T::Hash[String, T.untyped]))
167
- rescue TomlRB::ParseError, TomlRB::ValueOverwriteError
168
- raise Dependabot::DependencyFileNotParseable, T.must(pipfile).path
169
- end
170
-
171
- sig { returns(T::Hash[String, T.untyped]) }
172
- def parsed_pipfile_lock
173
- @parsed_pipfile_lock ||= T.let(JSON.parse(T.must(T.must(pipfile_lock).content)),
174
- T.nilable(T::Hash[String, T.untyped]))
175
- rescue JSON::ParserError
176
- raise Dependabot::DependencyFileNotParseable, T.must(pipfile_lock).path
177
- end
178
-
179
- sig { returns(T.nilable(Dependabot::DependencyFile)) }
180
- def pipfile
181
- @pipfile ||= T.let(dependency_files.find { |f| f.name == "Pipfile" }, T.nilable(Dependabot::DependencyFile))
182
- end
183
-
184
- sig { returns(T.nilable(Dependabot::DependencyFile)) }
185
- def pipfile_lock
186
- @pipfile_lock ||= T.let(dependency_files.find { |f| f.name == "Pipfile.lock" },
187
- T.nilable(Dependabot::DependencyFile))
188
- end
189
- end
190
- end
191
- end
192
- end