dependabot-uv 0.397.0 → 0.399.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/helpers/requirements.txt +3 -3
- data/lib/dependabot/uv/dependency_grapher.rb +34 -101
- data/lib/dependabot/uv/file_parser.rb +4 -9
- data/lib/dependabot/uv/file_updater/compile_file_updater.rb +10 -0
- data/lib/dependabot/uv/lockfile_document.rb +167 -0
- data/lib/dependabot/uv/update_checker/lock_file_resolver.rb +6 -13
- metadata +7 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7bbb68bb0a2bc28ad6791a412231ba074cbfaa658252e6e1c3cceac992a05469
|
|
4
|
+
data.tar.gz: cea56c236a2c71bcf1c0fb6fc5a342631acb720925122241a2ee3405c68b32df
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 333c7cba768d01f88b1e075c3f639e4ab799802c63ac7bd6fa8cd5fae6564b27145a5e1c2881f7d3a8b550564baecb85f636bf2e6de14ecf1bd948655c0e30e4
|
|
7
|
+
data.tar.gz: 0a1647d7b40b5297f3320c37ff7e61922f6bbe627fdf76fd2b55ad2215545600852c833cd7f31b2067a6f8d54b961609c4a2567216457e145696ec5504f00cb6
|
data/helpers/requirements.txt
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
pip==26.2.1
|
|
2
2
|
pip-tools==7.6.1
|
|
3
|
-
flake8==7.
|
|
3
|
+
flake8==7.4.1
|
|
4
4
|
hashin==1.0.5
|
|
5
5
|
pipenv==2024.4.1
|
|
6
6
|
plette==2.2.1
|
|
7
|
-
poetry==2.
|
|
7
|
+
poetry==2.5.1
|
|
8
8
|
# TODO: Replace 3p package `tomli` with 3.11's new stdlib `tomllib` once we drop support for Python 3.10.
|
|
9
9
|
tomli==2.4.1
|
|
10
|
-
uv==0.12.
|
|
10
|
+
uv==0.12.18
|
|
11
11
|
|
|
12
12
|
# Some dependencies will only install if Cython is present
|
|
13
13
|
Cython==3.3.0
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# typed:
|
|
1
|
+
# typed: strong
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require "sorbet-runtime"
|
|
@@ -7,7 +7,7 @@ require "dependabot/dependency"
|
|
|
7
7
|
require "dependabot/dependency_graphers"
|
|
8
8
|
require "dependabot/dependency_graphers/base"
|
|
9
9
|
require "dependabot/uv/file_parser"
|
|
10
|
-
require "
|
|
10
|
+
require "dependabot/uv/lockfile_document"
|
|
11
11
|
|
|
12
12
|
module Dependabot
|
|
13
13
|
module Uv
|
|
@@ -42,19 +42,17 @@ module Dependabot
|
|
|
42
42
|
sig { returns(T::Hash[String, T::Array[String]]) }
|
|
43
43
|
def package_relationships
|
|
44
44
|
@package_relationships ||= T.let(
|
|
45
|
-
package_relationships_from_lockfile(T.must(
|
|
45
|
+
package_relationships_from_lockfile(T.must(uv_lock)),
|
|
46
46
|
T.nilable(T::Hash[String, T::Array[String]])
|
|
47
47
|
)
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
sig { void }
|
|
51
51
|
def prepare_from_lockfile!
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
packages = T.cast(parsed.fetch("package", []), T::Array[T.untyped])
|
|
55
|
-
manifest = parsed.fetch("manifest", {})
|
|
52
|
+
document = LockfileDocument.from_file(T.must(uv_lock))
|
|
53
|
+
packages = document.graph_packages
|
|
56
54
|
|
|
57
|
-
root_names = root_package_names(packages,
|
|
55
|
+
root_names = root_package_names(packages, document.workspace_members.to_set)
|
|
58
56
|
direct_runtime, direct_dev = direct_dependency_names(packages, root_names)
|
|
59
57
|
|
|
60
58
|
@dependencies = packages.filter_map do |pkg|
|
|
@@ -73,14 +71,15 @@ module Dependabot
|
|
|
73
71
|
@prepared = true
|
|
74
72
|
end
|
|
75
73
|
|
|
76
|
-
sig { params(
|
|
77
|
-
def package_relationships_from_lockfile(
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
74
|
+
sig { params(lockfile: Dependabot::DependencyFile).returns(T::Hash[String, T::Array[String]]) }
|
|
75
|
+
def package_relationships_from_lockfile(lockfile)
|
|
76
|
+
relationships = T.let({}, T::Hash[String, T::Array[String]])
|
|
77
|
+
LockfileDocument.from_file(lockfile).graph_packages.each_with_object(relationships) do |package, rels|
|
|
78
|
+
name = package.name
|
|
79
|
+
next unless name
|
|
81
80
|
|
|
82
|
-
|
|
83
|
-
rels[parent].concat(lockfile_child_names(
|
|
81
|
+
parent = normalised_dependency_name(name)
|
|
82
|
+
(rels[parent] ||= []).concat(lockfile_child_names(package))
|
|
84
83
|
end
|
|
85
84
|
rescue StandardError => e
|
|
86
85
|
errored_fetching_subdependencies!
|
|
@@ -89,48 +88,15 @@ module Dependabot
|
|
|
89
88
|
{}
|
|
90
89
|
end
|
|
91
90
|
|
|
92
|
-
sig { params(lockfile_content: String).returns(T::Array[T.untyped]) }
|
|
93
|
-
def lockfile_packages(lockfile_content)
|
|
94
|
-
parsed = TomlRB.parse(lockfile_content)
|
|
95
|
-
T.cast(parsed.fetch("package", []), T::Array[T.untyped])
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
sig { params(package_data: T.untyped).returns(T.nilable(String)) }
|
|
99
|
-
def lockfile_parent_name(package_data)
|
|
100
|
-
return unless package_data.is_a?(Hash)
|
|
101
|
-
|
|
102
|
-
package_name = package_data["name"]
|
|
103
|
-
return unless package_name.is_a?(String)
|
|
104
|
-
|
|
105
|
-
normalised_dependency_name(package_name)
|
|
106
|
-
end
|
|
107
|
-
|
|
108
91
|
# Mirrors uv's `create_dependencies` (crates/uv-resolver/src/lock/export/cyclonedx_json.rs),
|
|
109
92
|
# which chains a package's `dependencies`, `optional-dependencies`, and
|
|
110
93
|
# `dev-dependencies` when building the SBOM dependency graph.
|
|
111
|
-
sig { params(
|
|
112
|
-
def lockfile_child_names(
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
names = T.let([], T::Array[String])
|
|
116
|
-
collect_dep_names(package_data["dependencies"], names)
|
|
117
|
-
collect_dep_names_from_groups(package_data["optional-dependencies"], names)
|
|
118
|
-
collect_dep_names_from_groups(package_data["dev-dependencies"], names)
|
|
94
|
+
sig { params(package: LockfileDocument::GraphPackage).returns(T::Array[String]) }
|
|
95
|
+
def lockfile_child_names(package)
|
|
96
|
+
names = package.dependencies + package.optional_dependencies + package.dev_dependencies
|
|
119
97
|
names.map { |name| normalised_dependency_name(name) }.uniq
|
|
120
98
|
end
|
|
121
99
|
|
|
122
|
-
sig { params(dependency_data: T.untyped).returns(T.nilable(String)) }
|
|
123
|
-
def lockfile_dependency_name(dependency_data)
|
|
124
|
-
if dependency_data.is_a?(Hash)
|
|
125
|
-
name = dependency_data["name"]
|
|
126
|
-
return name if name.is_a?(String)
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
return dependency_data if dependency_data.is_a?(String)
|
|
130
|
-
|
|
131
|
-
nil
|
|
132
|
-
end
|
|
133
|
-
|
|
134
100
|
# Identifies the workspace member packages whose `dependencies`,
|
|
135
101
|
# `optional-dependencies`, and `dev-dependencies` arrays describe the
|
|
136
102
|
# project's direct deps.
|
|
@@ -144,32 +110,17 @@ module Dependabot
|
|
|
144
110
|
# Fallback for single-member workspaces (which omit `[manifest] members`):
|
|
145
111
|
# match packages whose `source` is a local variant — `virtual`, `editable`,
|
|
146
112
|
# or `directory` — per the `SourceWire` enum in the same file.
|
|
147
|
-
sig
|
|
148
|
-
|
|
149
|
-
|
|
113
|
+
sig do
|
|
114
|
+
params(packages: T::Array[LockfileDocument::GraphPackage], declared: T::Set[String]).returns(T::Set[String])
|
|
115
|
+
end
|
|
116
|
+
def root_package_names(packages, declared)
|
|
150
117
|
return declared unless declared.empty?
|
|
151
118
|
|
|
152
119
|
packages.each_with_object(Set.new) do |pkg, set|
|
|
153
|
-
next unless pkg.
|
|
154
|
-
|
|
155
|
-
source = pkg["source"]
|
|
156
|
-
next unless source.is_a?(Hash)
|
|
157
|
-
next unless source.key?("virtual") || source.key?("editable") || source.key?("directory")
|
|
120
|
+
next unless pkg.local_source
|
|
158
121
|
|
|
159
|
-
name = pkg
|
|
160
|
-
set << name if name
|
|
161
|
-
end
|
|
162
|
-
end
|
|
163
|
-
|
|
164
|
-
sig { params(manifest: T.untyped).returns(T::Set[String]) }
|
|
165
|
-
def declared_workspace_members(manifest)
|
|
166
|
-
return Set.new unless manifest.is_a?(Hash)
|
|
167
|
-
|
|
168
|
-
members = manifest["members"]
|
|
169
|
-
return Set.new unless members.is_a?(Array)
|
|
170
|
-
|
|
171
|
-
members.each_with_object(Set.new) do |name, set|
|
|
172
|
-
set << name if name.is_a?(String)
|
|
122
|
+
name = pkg.name
|
|
123
|
+
set << name if name
|
|
173
124
|
end
|
|
174
125
|
end
|
|
175
126
|
|
|
@@ -180,7 +131,7 @@ module Dependabot
|
|
|
180
131
|
# semantics because the dependency graph reports what *could* be installed, not what was
|
|
181
132
|
# selected for a particular sync.
|
|
182
133
|
sig do
|
|
183
|
-
params(packages: T::Array[
|
|
134
|
+
params(packages: T::Array[LockfileDocument::GraphPackage], root_names: T::Set[String])
|
|
184
135
|
.returns([T::Set[String], T::Set[String]])
|
|
185
136
|
end
|
|
186
137
|
def direct_dependency_names(packages, root_names)
|
|
@@ -188,47 +139,29 @@ module Dependabot
|
|
|
188
139
|
dev = T.let(Set.new, T::Set[String])
|
|
189
140
|
|
|
190
141
|
packages.each do |pkg|
|
|
191
|
-
|
|
142
|
+
name = pkg.name
|
|
143
|
+
next unless name && root_names.include?(name)
|
|
192
144
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
145
|
+
runtime.merge(pkg.dependencies)
|
|
146
|
+
runtime.merge(pkg.optional_dependencies)
|
|
147
|
+
dev.merge(pkg.dev_dependencies)
|
|
196
148
|
end
|
|
197
149
|
|
|
198
150
|
[runtime, dev]
|
|
199
151
|
end
|
|
200
152
|
|
|
201
|
-
sig { params(entries: T.untyped, collection: T.any(T::Set[String], T::Array[String])).void }
|
|
202
|
-
def collect_dep_names(entries, collection)
|
|
203
|
-
return unless entries.is_a?(Array)
|
|
204
|
-
|
|
205
|
-
entries.each do |entry|
|
|
206
|
-
name = lockfile_dependency_name(entry)
|
|
207
|
-
collection << name if name.is_a?(String)
|
|
208
|
-
end
|
|
209
|
-
end
|
|
210
|
-
|
|
211
|
-
sig { params(groups: T.untyped, collection: T.any(T::Set[String], T::Array[String])).void }
|
|
212
|
-
def collect_dep_names_from_groups(groups, collection)
|
|
213
|
-
return unless groups.is_a?(Hash)
|
|
214
|
-
|
|
215
|
-
groups.each_value { |entries| collect_dep_names(entries, collection) }
|
|
216
|
-
end
|
|
217
|
-
|
|
218
153
|
sig do
|
|
219
154
|
params(
|
|
220
|
-
pkg:
|
|
155
|
+
pkg: LockfileDocument::GraphPackage,
|
|
221
156
|
root_names: T::Set[String],
|
|
222
157
|
direct_runtime: T::Set[String],
|
|
223
158
|
direct_dev: T::Set[String]
|
|
224
159
|
).returns(T.nilable(Dependabot::Dependency))
|
|
225
160
|
end
|
|
226
161
|
def build_dependency(pkg, root_names, direct_runtime, direct_dev)
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
name
|
|
230
|
-
version = pkg["version"]
|
|
231
|
-
return unless name.is_a?(String) && version.is_a?(String)
|
|
162
|
+
name = pkg.name
|
|
163
|
+
version = pkg.version
|
|
164
|
+
return unless name && version
|
|
232
165
|
|
|
233
166
|
# Root project packages get requirements: [] (indirect, runtime) to
|
|
234
167
|
# match the prior FileParser-derived behaviour where uv.lock packages
|
|
@@ -16,8 +16,8 @@ require "dependabot/uv/name_normaliser"
|
|
|
16
16
|
require "dependabot/uv/requirements_file_matcher"
|
|
17
17
|
require "dependabot/uv/language_version_manager"
|
|
18
18
|
require "dependabot/uv/package_manager"
|
|
19
|
+
require "dependabot/uv/lockfile_document"
|
|
19
20
|
require "dependabot/python/file_parser/pep_dependency"
|
|
20
|
-
require "toml-rb"
|
|
21
21
|
|
|
22
22
|
module Dependabot
|
|
23
23
|
module Uv
|
|
@@ -199,15 +199,10 @@ module Dependabot
|
|
|
199
199
|
dependency_set = DependencySet.new
|
|
200
200
|
|
|
201
201
|
uv_lock_files.each do |file|
|
|
202
|
-
|
|
203
|
-
packages = lockfile_content.fetch("package", [])
|
|
204
|
-
|
|
205
|
-
packages.each do |package_data|
|
|
206
|
-
next unless package_data.is_a?(Hash) && package_data["name"] && package_data["version"]
|
|
207
|
-
|
|
202
|
+
LockfileDocument.from_file(file).each_dependency do |package|
|
|
208
203
|
dependency_set << Dependency.new(
|
|
209
|
-
name: normalised_name(
|
|
210
|
-
version:
|
|
204
|
+
name: normalised_name(package.name),
|
|
205
|
+
version: package.version,
|
|
211
206
|
requirements: [], # Lock files don't contain requirements
|
|
212
207
|
package_manager: "uv"
|
|
213
208
|
)
|
|
@@ -322,9 +322,19 @@ module Dependabot
|
|
|
322
322
|
content = replace_header_with_original(updated_content, T.must(file.content))
|
|
323
323
|
content = remove_new_warnings(content, T.must(file.content))
|
|
324
324
|
content = update_hashes_if_required(content, T.must(file.content))
|
|
325
|
+
content = scrub_index_url_credentials(content)
|
|
325
326
|
replace_absolute_file_paths(content, T.must(file.content))
|
|
326
327
|
end
|
|
327
328
|
|
|
329
|
+
# Index URLs are passed to `uv pip compile` with credentials embedded so
|
|
330
|
+
# the private index can be fetched, and uv emits those URLs verbatim
|
|
331
|
+
# into the compiled file when `--emit-index-url` is active. Strip any
|
|
332
|
+
# userinfo so tokens are never written into the regenerated file.
|
|
333
|
+
sig { params(content: String).returns(String) }
|
|
334
|
+
def scrub_index_url_credentials(content)
|
|
335
|
+
content.gsub(%r{^(--(?:extra-)?index-url[= ]https?://)[^/\s]+@}, "\\1")
|
|
336
|
+
end
|
|
337
|
+
|
|
328
338
|
sig { params(updated_content: String, original_content: String).returns(String) }
|
|
329
339
|
def replace_header_with_original(updated_content, original_content)
|
|
330
340
|
original_header_lines =
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# typed: strong
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "sorbet-runtime"
|
|
5
|
+
require "toml-rb"
|
|
6
|
+
|
|
7
|
+
require "dependabot/dependency_file"
|
|
8
|
+
|
|
9
|
+
module Dependabot
|
|
10
|
+
module Uv
|
|
11
|
+
class LockfileDocument
|
|
12
|
+
extend T::Sig
|
|
13
|
+
|
|
14
|
+
LOCAL_SOURCE_KEYS = %w(virtual editable directory).freeze
|
|
15
|
+
|
|
16
|
+
class GraphPackage < T::ImmutableStruct
|
|
17
|
+
const :name, T.nilable(String)
|
|
18
|
+
const :version, T.nilable(String)
|
|
19
|
+
const :local_source, T::Boolean
|
|
20
|
+
const :dependencies, T::Array[String]
|
|
21
|
+
const :optional_dependencies, T::Array[String]
|
|
22
|
+
const :dev_dependencies, T::Array[String]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
class LockedPackage < T::ImmutableStruct
|
|
26
|
+
const :name, String
|
|
27
|
+
const :version, String
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
sig { params(file: Dependabot::DependencyFile).returns(LockfileDocument) }
|
|
31
|
+
def self.from_file(file)
|
|
32
|
+
new(data: T.cast(TomlRB.parse(T.must(file.content)), Object), context: file.path)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
sig { params(data: Object, context: String).void }
|
|
36
|
+
def initialize(data:, context:)
|
|
37
|
+
@context = context
|
|
38
|
+
@data = T.let(object_hash(data), T::Hash[String, Object])
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
sig { returns(T::Array[String]) }
|
|
42
|
+
def workspace_members
|
|
43
|
+
manifest = @data["manifest"]
|
|
44
|
+
return [] unless manifest.is_a?(Hash)
|
|
45
|
+
|
|
46
|
+
members = T.cast(manifest["members"], Object)
|
|
47
|
+
return [] unless members.is_a?(Array)
|
|
48
|
+
|
|
49
|
+
members.filter_map { |member| string_or_nil(T.cast(member, Object)) }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
sig { returns(T::Array[GraphPackage]) }
|
|
53
|
+
def graph_packages
|
|
54
|
+
package_entries.filter_map do |entry|
|
|
55
|
+
next unless entry.is_a?(Hash)
|
|
56
|
+
|
|
57
|
+
package = object_hash(entry)
|
|
58
|
+
source = package["source"]
|
|
59
|
+
GraphPackage.new(
|
|
60
|
+
name: string_or_nil(package["name"]),
|
|
61
|
+
version: string_or_nil(package["version"]),
|
|
62
|
+
local_source: source.is_a?(Hash) && LOCAL_SOURCE_KEYS.any? { |key| source.key?(key) },
|
|
63
|
+
dependencies: dependency_names(package["dependencies"]),
|
|
64
|
+
optional_dependencies: grouped_dependency_names(package["optional-dependencies"]),
|
|
65
|
+
dev_dependencies: grouped_dependency_names(package["dev-dependencies"])
|
|
66
|
+
)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
sig { params(block: T.proc.params(package: LockedPackage).void).void }
|
|
71
|
+
def each_dependency(&block)
|
|
72
|
+
# The file parser historically skips the pairs yielded by an object-shaped package section.
|
|
73
|
+
return if @data["package"].is_a?(Hash)
|
|
74
|
+
|
|
75
|
+
package_entries.each_with_index do |entry, index|
|
|
76
|
+
next unless entry.is_a?(Hash)
|
|
77
|
+
|
|
78
|
+
package = object_hash(entry)
|
|
79
|
+
name = package["name"]
|
|
80
|
+
version = package["version"]
|
|
81
|
+
next unless name && version
|
|
82
|
+
|
|
83
|
+
yield(LockedPackage.new(
|
|
84
|
+
name: string(name, "package[#{index}].name"),
|
|
85
|
+
version: string(version, "package[#{index}].version")
|
|
86
|
+
))
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
sig { returns(T::Array[LockedPackage]) }
|
|
91
|
+
def resolution_packages
|
|
92
|
+
return [] if @data["package"].nil?
|
|
93
|
+
|
|
94
|
+
package_entries.each_with_index.filter_map do |entry, index|
|
|
95
|
+
# String#[] cannot produce a valid version from the "version" lookup.
|
|
96
|
+
next if entry.is_a?(String)
|
|
97
|
+
|
|
98
|
+
package = object_hash(entry)
|
|
99
|
+
name = optional_string(package["name"], "package[#{index}].name")
|
|
100
|
+
version = optional_string(package["version"], "package[#{index}].version")
|
|
101
|
+
next unless name && version
|
|
102
|
+
|
|
103
|
+
LockedPackage.new(name: name, version: version)
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
private
|
|
108
|
+
|
|
109
|
+
sig { returns(T::Array[Object]) }
|
|
110
|
+
def package_entries
|
|
111
|
+
packages = @data.fetch("package", [])
|
|
112
|
+
raise TypeError, "#{@context} package must be an array" unless packages.is_a?(Array)
|
|
113
|
+
|
|
114
|
+
packages.map { |entry| T.cast(entry, Object) }
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
sig { params(value: Object).returns(T::Hash[String, Object]) }
|
|
118
|
+
def object_hash(value)
|
|
119
|
+
raise TypeError, "#{@context} must be an object" unless value.is_a?(Hash)
|
|
120
|
+
|
|
121
|
+
value.to_h do |raw_key, raw_value|
|
|
122
|
+
key = T.cast(raw_key, Object)
|
|
123
|
+
raise TypeError, "#{@context} keys must be strings" unless key.is_a?(String)
|
|
124
|
+
|
|
125
|
+
[key, T.cast(raw_value, Object)]
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
sig { params(value: Object).returns(T.nilable(String)) }
|
|
130
|
+
def string_or_nil(value)
|
|
131
|
+
value if value.is_a?(String)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
sig { params(value: Object, field: String).returns(T.nilable(String)) }
|
|
135
|
+
def optional_string(value, field)
|
|
136
|
+
return if value.nil?
|
|
137
|
+
|
|
138
|
+
string(value, field)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
sig { params(value: Object, field: String).returns(String) }
|
|
142
|
+
def string(value, field)
|
|
143
|
+
return value if value.is_a?(String)
|
|
144
|
+
|
|
145
|
+
raise TypeError, "#{@context} #{field} must be a string"
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
sig { params(entries: Object).returns(T::Array[String]) }
|
|
149
|
+
def dependency_names(entries)
|
|
150
|
+
return [] unless entries.is_a?(Array)
|
|
151
|
+
|
|
152
|
+
entries.filter_map do |raw_entry|
|
|
153
|
+
entry = T.cast(raw_entry, Object)
|
|
154
|
+
name = entry.is_a?(Hash) ? T.cast(entry["name"], Object) : entry
|
|
155
|
+
string_or_nil(name)
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
sig { params(groups: Object).returns(T::Array[String]) }
|
|
160
|
+
def grouped_dependency_names(groups)
|
|
161
|
+
return [] unless groups.is_a?(Hash)
|
|
162
|
+
|
|
163
|
+
groups.values.flat_map { |entries| dependency_names(T.cast(entries, Object)) }
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require "sorbet-runtime"
|
|
5
|
-
require "
|
|
5
|
+
require "dependabot/uv/lockfile_document"
|
|
6
6
|
|
|
7
7
|
require "dependabot/errors"
|
|
8
8
|
require "dependabot/package/release_cooldown_options"
|
|
@@ -278,20 +278,13 @@ module Dependabot
|
|
|
278
278
|
.returns(T::Array[Dependabot::Uv::Version])
|
|
279
279
|
end
|
|
280
280
|
def locked_versions(lockfile)
|
|
281
|
-
parsed = T.cast(TomlRB.parse(T.must(lockfile.content)), T::Hash[String, Object])
|
|
282
|
-
packages = T.cast(parsed["package"], T.nilable(T::Array[T::Hash[String, Object]])) || []
|
|
283
281
|
dependency_name = NameNormaliser.normalise(dependency.name)
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
package_version = T.cast(package["version"], T.nilable(String))
|
|
288
|
-
next unless package_name && NameNormaliser.normalise(package_name) == dependency_name
|
|
289
|
-
next unless Uv::Version.correct?(package_version)
|
|
290
|
-
|
|
291
|
-
versions << Uv::Version.new(package_version)
|
|
292
|
-
end
|
|
282
|
+
LockfileDocument.from_file(lockfile).resolution_packages.filter_map do |package|
|
|
283
|
+
next unless NameNormaliser.normalise(package.name) == dependency_name
|
|
284
|
+
next unless Uv::Version.correct?(package.version)
|
|
293
285
|
|
|
294
|
-
|
|
286
|
+
Uv::Version.new(package.version)
|
|
287
|
+
end
|
|
295
288
|
end
|
|
296
289
|
|
|
297
290
|
sig { returns(T.nilable(Dependabot::DependencyFile)) }
|
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.
|
|
4
|
+
version: 0.399.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.
|
|
18
|
+
version: 0.399.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.
|
|
25
|
+
version: 0.399.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.
|
|
32
|
+
version: 0.399.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.
|
|
39
|
+
version: 0.399.0
|
|
40
40
|
- !ruby/object:Gem::Dependency
|
|
41
41
|
name: debug
|
|
42
42
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -280,6 +280,7 @@ files:
|
|
|
280
280
|
- lib/dependabot/uv/file_updater/version_config_parser.rb
|
|
281
281
|
- lib/dependabot/uv/language.rb
|
|
282
282
|
- lib/dependabot/uv/language_version_manager.rb
|
|
283
|
+
- lib/dependabot/uv/lockfile_document.rb
|
|
283
284
|
- lib/dependabot/uv/metadata_finder.rb
|
|
284
285
|
- lib/dependabot/uv/name_normaliser.rb
|
|
285
286
|
- lib/dependabot/uv/native_helpers.rb
|
|
@@ -301,7 +302,7 @@ licenses:
|
|
|
301
302
|
- MIT
|
|
302
303
|
metadata:
|
|
303
304
|
bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
|
|
304
|
-
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.
|
|
305
|
+
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.399.0
|
|
305
306
|
rdoc_options: []
|
|
306
307
|
require_paths:
|
|
307
308
|
- lib
|