dependabot-uv 0.299.1 → 0.301.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 +55 -25
- data/lib/dependabot/uv/file_parser/python_requirement_parser.rb +5 -44
- data/lib/dependabot/uv/file_parser.rb +77 -101
- data/lib/dependabot/uv/file_updater/lock_file_updater.rb +392 -0
- data/lib/dependabot/uv/file_updater/pyproject_preparer.rb +97 -77
- data/lib/dependabot/uv/file_updater.rb +14 -1
- data/lib/dependabot/uv/{pip_compile_file_matcher.rb → requirements_file_matcher.rb} +5 -5
- data/lib/dependabot/uv/update_checker/lock_file_resolver.rb +48 -0
- data/lib/dependabot/uv/update_checker.rb +12 -1
- metadata +8 -7
- data/lib/dependabot/uv/file_parser/pipfile_files_parser.rb +0 -192
@@ -0,0 +1,48 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "dependabot/uv/version"
|
5
|
+
require "dependabot/uv/requirement"
|
6
|
+
require "dependabot/uv/update_checker"
|
7
|
+
|
8
|
+
module Dependabot
|
9
|
+
module Uv
|
10
|
+
class UpdateChecker
|
11
|
+
class LockFileResolver
|
12
|
+
def initialize(dependency:, dependency_files:, credentials:, repo_contents_path: nil)
|
13
|
+
@dependency = dependency
|
14
|
+
@dependency_files = dependency_files
|
15
|
+
@credentials = credentials
|
16
|
+
@repo_contents_path = repo_contents_path
|
17
|
+
end
|
18
|
+
|
19
|
+
def latest_resolvable_version(requirement:)
|
20
|
+
return nil unless requirement
|
21
|
+
|
22
|
+
req = Uv::Requirement.new(requirement)
|
23
|
+
|
24
|
+
# Get the version from the dependency if available
|
25
|
+
version_from_dependency = dependency.version && Uv::Version.new(dependency.version)
|
26
|
+
return version_from_dependency if version_from_dependency && req.satisfied_by?(version_from_dependency)
|
27
|
+
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
|
31
|
+
def resolvable?(*)
|
32
|
+
true
|
33
|
+
end
|
34
|
+
|
35
|
+
def lowest_resolvable_security_fix_version
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
attr_reader :dependency
|
42
|
+
attr_reader :dependency_files
|
43
|
+
attr_reader :credentials
|
44
|
+
attr_reader :repo_contents_path
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -21,6 +21,7 @@ module Dependabot
|
|
21
21
|
require_relative "update_checker/pip_version_resolver"
|
22
22
|
require_relative "update_checker/requirements_updater"
|
23
23
|
require_relative "update_checker/latest_version_finder"
|
24
|
+
require_relative "update_checker/lock_file_resolver"
|
24
25
|
|
25
26
|
MAIN_PYPI_INDEXES = %w(
|
26
27
|
https://pypi.python.org/simple/
|
@@ -118,6 +119,7 @@ module Dependabot
|
|
118
119
|
case resolver_type
|
119
120
|
when :pip_compile then pip_compile_version_resolver
|
120
121
|
when :requirements then pip_version_resolver
|
122
|
+
when :lock_file then lock_file_resolver
|
121
123
|
else raise "Unexpected resolver type #{resolver_type}"
|
122
124
|
end
|
123
125
|
end
|
@@ -134,6 +136,7 @@ module Dependabot
|
|
134
136
|
# which resolver to use based on the filename of its requirements
|
135
137
|
return :requirements if updating_pyproject?
|
136
138
|
return :pip_compile if updating_in_file?
|
139
|
+
return :lock_file if updating_uv_lock?
|
137
140
|
|
138
141
|
if dependency.version && !exact_requirement?(reqs)
|
139
142
|
subdependency_resolver
|
@@ -171,6 +174,10 @@ module Dependabot
|
|
171
174
|
)
|
172
175
|
end
|
173
176
|
|
177
|
+
def lock_file_resolver
|
178
|
+
@lock_file_resolver ||= LockFileResolver.new(**resolver_args)
|
179
|
+
end
|
180
|
+
|
174
181
|
def resolver_args
|
175
182
|
{
|
176
183
|
dependency: dependency,
|
@@ -187,7 +194,7 @@ module Dependabot
|
|
187
194
|
requirement = reqs.find do |r|
|
188
195
|
file = r[:file]
|
189
196
|
|
190
|
-
file == "
|
197
|
+
file == "uv.lock" || file == "pyproject.toml" || file.end_with?(".in") || file.end_with?(".txt")
|
191
198
|
end
|
192
199
|
|
193
200
|
requirement&.fetch(:requirement)
|
@@ -267,6 +274,10 @@ module Dependabot
|
|
267
274
|
requirement_files.any? { |f| f.end_with?(".in") }
|
268
275
|
end
|
269
276
|
|
277
|
+
def updating_uv_lock?
|
278
|
+
requirement_files.any?("uv.lock")
|
279
|
+
end
|
280
|
+
|
270
281
|
def requirements_text_file?
|
271
282
|
requirement_files.any? { |f| f.end_with?("requirements.txt") }
|
272
283
|
end
|
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.301.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-13 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.301.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.301.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: debug
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -252,12 +252,12 @@ 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
|
259
258
|
- lib/dependabot/uv/file_updater.rb
|
260
259
|
- lib/dependabot/uv/file_updater/compile_file_updater.rb
|
260
|
+
- lib/dependabot/uv/file_updater/lock_file_updater.rb
|
261
261
|
- lib/dependabot/uv/file_updater/pyproject_preparer.rb
|
262
262
|
- lib/dependabot/uv/file_updater/requirement_file_updater.rb
|
263
263
|
- lib/dependabot/uv/file_updater/requirement_replacer.rb
|
@@ -267,13 +267,14 @@ files:
|
|
267
267
|
- lib/dependabot/uv/name_normaliser.rb
|
268
268
|
- lib/dependabot/uv/native_helpers.rb
|
269
269
|
- lib/dependabot/uv/package_manager.rb
|
270
|
-
- lib/dependabot/uv/pip_compile_file_matcher.rb
|
271
270
|
- lib/dependabot/uv/pipenv_runner.rb
|
272
271
|
- lib/dependabot/uv/requirement.rb
|
273
272
|
- lib/dependabot/uv/requirement_parser.rb
|
273
|
+
- lib/dependabot/uv/requirements_file_matcher.rb
|
274
274
|
- lib/dependabot/uv/update_checker.rb
|
275
275
|
- lib/dependabot/uv/update_checker/index_finder.rb
|
276
276
|
- lib/dependabot/uv/update_checker/latest_version_finder.rb
|
277
|
+
- lib/dependabot/uv/update_checker/lock_file_resolver.rb
|
277
278
|
- lib/dependabot/uv/update_checker/pip_compile_version_resolver.rb
|
278
279
|
- lib/dependabot/uv/update_checker/pip_version_resolver.rb
|
279
280
|
- lib/dependabot/uv/update_checker/requirements_updater.rb
|
@@ -283,7 +284,7 @@ licenses:
|
|
283
284
|
- MIT
|
284
285
|
metadata:
|
285
286
|
bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
|
286
|
-
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.
|
287
|
+
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.301.0
|
287
288
|
post_install_message:
|
288
289
|
rdoc_options: []
|
289
290
|
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
|