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 +4 -4
- data/lib/dependabot/uv/file_fetcher.rb +4 -4
- data/lib/dependabot/uv/file_parser/python_requirement_parser.rb +5 -44
- data/lib/dependabot/uv/file_parser.rb +41 -103
- data/lib/dependabot/uv/{pip_compile_file_matcher.rb → requirements_file_matcher.rb} +5 -5
- metadata +6 -7
- data/lib/dependabot/uv/file_parser/pipfile_files_parser.rb +0 -192
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3e306a8d52bca54571baf167605279980eeb625a9dcfbad1128a13de55270936
|
4
|
+
data.tar.gz: 7bd9b6a85cf4e76675eaf401ed285acad0e6e518920e3cd344ae0074fa8a3a2a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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/
|
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
|
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
|
322
|
-
@
|
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/
|
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
|
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
|
137
|
-
@
|
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/
|
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
|
-
#
|
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[
|
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(
|
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(
|
75
|
+
sig { returns(FileParser::PythonRequirementParser) }
|
81
76
|
def python_requirement_parser
|
82
|
-
@python_requirement_parser ||= T.let(
|
83
|
-
dependency_files), T.nilable(
|
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
|
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(
|
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
|
92
|
+
setup_python_environment if Experiments.enabled?(:enable_file_parser_python_local)
|
98
93
|
|
99
|
-
PackageManager.new(T.must(
|
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
|
105
|
-
|
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
|
-
|
101
|
+
log_if_version_malformed("uv", version)
|
112
102
|
|
113
|
-
|
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 {
|
121
|
-
def
|
122
|
-
version_info = SharedHelpers.run_shell_command("pyenv exec
|
123
|
-
Dependabot.logger.info("Package manager
|
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
|
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[
|
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 &&
|
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
|
-
|
275
|
+
Version.new(python_version) < Version.new(version)
|
299
276
|
when "<="
|
300
|
-
|
277
|
+
Version.new(python_version) <= Version.new(version)
|
301
278
|
when ">"
|
302
|
-
|
279
|
+
Version.new(python_version) > Version.new(version)
|
303
280
|
when ">="
|
304
|
-
|
281
|
+
Version.new(python_version) >= Version.new(version)
|
305
282
|
when "=="
|
306
|
-
|
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
|
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
|
-
|
315
|
+
Requirement.new(dep["requirement"].split(","))
|
345
316
|
rescue Gem::Requirement::BadRequirementError => e
|
346
|
-
raise
|
317
|
+
raise DependencyFileNotEvaluatable, e.message
|
347
318
|
end
|
348
319
|
end
|
349
320
|
|
350
|
-
sig { returns(T::
|
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(
|
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(
|
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[
|
424
|
-
def
|
425
|
-
@
|
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(
|
429
|
-
def
|
430
|
-
@
|
431
|
-
|
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
|
6
|
+
class RequiremenstFileMatcher
|
7
7
|
extend T::Sig
|
8
8
|
|
9
|
-
sig { params(requirements_in_files: T::Array[
|
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:
|
15
|
-
def
|
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[
|
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.
|
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-
|
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.
|
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.
|
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.
|
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
|