dependabot-uv 0.397.0 → 0.398.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/lockfile_document.rb +111 -0
- 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: f460c106ded2b40fb9c7e91e53baee1a2959a640e47bafaece6b43b0f112b022
|
|
4
|
+
data.tar.gz: 281ce9fee19f90b0b703145445bb05c83d2cbc81eadbd3f3fb8eef3f07d79a0b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 836cbb9770876a0f0c0f3c02d599cf0948739d7ad2ea12701f1cb78fcf1051b3f78364db63f46e4b4a12e2080d41a1797912e20803a1cbf201aa8ab857038314
|
|
7
|
+
data.tar.gz: f3144802f8314d9998824fe31164dc4d47cb092eb7a8ed0764e221d455cf60301c37a76033c5cf963e919fe43514e9e33347c4c74eca10575514332583beeb5a
|
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
|
|
@@ -0,0 +1,111 @@
|
|
|
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
|
+
sig { params(file: Dependabot::DependencyFile).returns(LockfileDocument) }
|
|
26
|
+
def self.from_file(file)
|
|
27
|
+
new(data: T.cast(TomlRB.parse(T.must(file.content)), Object), context: file.path)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
sig { params(data: Object, context: String).void }
|
|
31
|
+
def initialize(data:, context:)
|
|
32
|
+
@context = context
|
|
33
|
+
@data = T.let(object_hash(data), T::Hash[String, Object])
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
sig { returns(T::Array[String]) }
|
|
37
|
+
def workspace_members
|
|
38
|
+
manifest = @data["manifest"]
|
|
39
|
+
return [] unless manifest.is_a?(Hash)
|
|
40
|
+
|
|
41
|
+
members = T.cast(manifest["members"], Object)
|
|
42
|
+
return [] unless members.is_a?(Array)
|
|
43
|
+
|
|
44
|
+
members.filter_map { |member| string_or_nil(T.cast(member, Object)) }
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
sig { returns(T::Array[GraphPackage]) }
|
|
48
|
+
def graph_packages
|
|
49
|
+
package_entries.filter_map do |entry|
|
|
50
|
+
next unless entry.is_a?(Hash)
|
|
51
|
+
|
|
52
|
+
package = object_hash(entry)
|
|
53
|
+
source = package["source"]
|
|
54
|
+
GraphPackage.new(
|
|
55
|
+
name: string_or_nil(package["name"]),
|
|
56
|
+
version: string_or_nil(package["version"]),
|
|
57
|
+
local_source: source.is_a?(Hash) && LOCAL_SOURCE_KEYS.any? { |key| source.key?(key) },
|
|
58
|
+
dependencies: dependency_names(package["dependencies"]),
|
|
59
|
+
optional_dependencies: grouped_dependency_names(package["optional-dependencies"]),
|
|
60
|
+
dev_dependencies: grouped_dependency_names(package["dev-dependencies"])
|
|
61
|
+
)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
private
|
|
66
|
+
|
|
67
|
+
sig { returns(T::Array[Object]) }
|
|
68
|
+
def package_entries
|
|
69
|
+
packages = @data.fetch("package", [])
|
|
70
|
+
raise TypeError, "#{@context} package must be an array" unless packages.is_a?(Array)
|
|
71
|
+
|
|
72
|
+
packages.map { |entry| T.cast(entry, Object) }
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
sig { params(value: Object).returns(T::Hash[String, Object]) }
|
|
76
|
+
def object_hash(value)
|
|
77
|
+
raise TypeError, "#{@context} must be an object" unless value.is_a?(Hash)
|
|
78
|
+
|
|
79
|
+
value.to_h do |raw_key, raw_value|
|
|
80
|
+
key = T.cast(raw_key, Object)
|
|
81
|
+
raise TypeError, "#{@context} keys must be strings" unless key.is_a?(String)
|
|
82
|
+
|
|
83
|
+
[key, T.cast(raw_value, Object)]
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
sig { params(value: Object).returns(T.nilable(String)) }
|
|
88
|
+
def string_or_nil(value)
|
|
89
|
+
value if value.is_a?(String)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
sig { params(entries: Object).returns(T::Array[String]) }
|
|
93
|
+
def dependency_names(entries)
|
|
94
|
+
return [] unless entries.is_a?(Array)
|
|
95
|
+
|
|
96
|
+
entries.filter_map do |raw_entry|
|
|
97
|
+
entry = T.cast(raw_entry, Object)
|
|
98
|
+
name = entry.is_a?(Hash) ? T.cast(entry["name"], Object) : entry
|
|
99
|
+
string_or_nil(name)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
sig { params(groups: Object).returns(T::Array[String]) }
|
|
104
|
+
def grouped_dependency_names(groups)
|
|
105
|
+
return [] unless groups.is_a?(Hash)
|
|
106
|
+
|
|
107
|
+
groups.values.flat_map { |entries| dependency_names(T.cast(entries, Object)) }
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
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.398.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.398.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.398.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.398.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.398.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.398.0
|
|
305
306
|
rdoc_options: []
|
|
306
307
|
require_paths:
|
|
307
308
|
- lib
|