dependabot-python 0.367.0 → 0.368.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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5b03d84191a73f9cd803b3db1fd32bc70638a4f607c2e9424a3900f143119f5f
|
|
4
|
+
data.tar.gz: 6d04a235c38eb76a1a86eb2f60e2f34c80c82ff5f342d997ff3c8a25011e42f3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 793a849e50f2162b65f1da65521dfb7450081b84507fbb4134145ab5c72b63a916a59c68602bf41dea530d373cb0d2dd5e9a38fee9b6a5347b17848a8891054f
|
|
7
|
+
data.tar.gz: db96c2fd7be7c4b6ac473f29dc429f3c4163fb2dd38d4b1d48c19ea62727022ff6822166dd10e9c4a680eae24bc5f16f447bf9f8ec55b7909b8ae663698b29c6
|
|
@@ -55,33 +55,56 @@ module Dependabot
|
|
|
55
55
|
|
|
56
56
|
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
57
57
|
def fetch_updated_dependency_files
|
|
58
|
-
|
|
58
|
+
updated_contents = T.let({}, T::Hash[String, String])
|
|
59
|
+
|
|
60
|
+
unique_requirement_changes.each do |pair|
|
|
61
|
+
new_req = T.must(pair[0])
|
|
62
|
+
old_req = pair[1]
|
|
63
|
+
filename = new_req.fetch(:file)
|
|
64
|
+
content = updated_contents[filename] || T.must(T.must(get_original_file(filename)).content)
|
|
65
|
+
updated_contents[filename] = updated_requirement_or_setup_file_content(content, new_req, old_req)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
updated_contents.filter_map do |filename, content|
|
|
69
|
+
file = T.must(get_original_file(filename)).dup
|
|
70
|
+
next if content == T.must(file.content)
|
|
71
|
+
|
|
72
|
+
file.content = content
|
|
73
|
+
file
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Deduplicates requirements that share the same file and requirement strings.
|
|
78
|
+
# The replacer's regex matches all extras variants at once, so one call per
|
|
79
|
+
# unique (file, old_requirement, new_requirement) is sufficient.
|
|
80
|
+
sig { returns(T::Array[T::Array[T.nilable(T::Hash[Symbol, T.untyped])]]) }
|
|
81
|
+
def unique_requirement_changes
|
|
82
|
+
previous_reqs = dependency.previous_requirements || []
|
|
59
83
|
|
|
60
|
-
|
|
84
|
+
changes = dependency.requirements.filter_map do |new_req|
|
|
85
|
+
old_req = previous_reqs.find { |r| r[:file] == new_req[:file] && r[:groups] == new_req[:groups] }
|
|
61
86
|
next if new_req == old_req
|
|
62
87
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
updated_requirement_or_setup_file_content(new_req, old_req)
|
|
66
|
-
next if updated_content == file.content
|
|
88
|
+
[new_req, old_req]
|
|
89
|
+
end
|
|
67
90
|
|
|
68
|
-
|
|
69
|
-
|
|
91
|
+
changes.uniq do |pair|
|
|
92
|
+
new_req = pair[0]
|
|
93
|
+
old_req = pair[1]
|
|
94
|
+
[new_req[:file], old_req&.fetch(:requirement), new_req.fetch(:requirement)]
|
|
70
95
|
end
|
|
71
96
|
end
|
|
72
97
|
|
|
73
98
|
sig do
|
|
74
99
|
params(
|
|
100
|
+
content: String,
|
|
75
101
|
new_req: T::Hash[Symbol, T.untyped],
|
|
76
102
|
old_req: T.nilable(T::Hash[Symbol, T.untyped])
|
|
77
103
|
).returns(String)
|
|
78
104
|
end
|
|
79
|
-
def updated_requirement_or_setup_file_content(new_req, old_req)
|
|
80
|
-
original_file = get_original_file(new_req.fetch(:file))
|
|
81
|
-
raise "Could not find a dependency file for #{new_req}" unless original_file
|
|
82
|
-
|
|
105
|
+
def updated_requirement_or_setup_file_content(content, new_req, old_req)
|
|
83
106
|
RequirementReplacer.new(
|
|
84
|
-
content:
|
|
107
|
+
content: content,
|
|
85
108
|
dependency_name: dependency.name,
|
|
86
109
|
old_requirement: old_req&.fetch(:requirement),
|
|
87
110
|
new_requirement: new_req.fetch(:requirement),
|
|
@@ -53,7 +53,7 @@ module Dependabot
|
|
|
53
53
|
# ignore it, since it isn't actually a declaration
|
|
54
54
|
next mtch if Regexp.last_match&.pre_match&.match?(/--.*\z/)
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
updated_matched_declaration(mtch)
|
|
57
57
|
end
|
|
58
58
|
|
|
59
59
|
raise "Expected content to change!" if old_requirement != new_requirement && content == updated_content
|
|
@@ -98,29 +98,30 @@ module Dependabot
|
|
|
98
98
|
new_req_string
|
|
99
99
|
end
|
|
100
100
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
101
|
+
# Builds updated declaration from the actual matched text, preserving
|
|
102
|
+
# whatever extras (or lack thereof) appeared in the original match.
|
|
103
|
+
sig { params(matched_declaration: String).returns(String) }
|
|
104
|
+
def updated_matched_declaration(matched_declaration)
|
|
105
|
+
updated = if old_requirement
|
|
106
|
+
matched_declaration
|
|
107
|
+
.sub(RequirementParser::REQUIREMENTS, updated_requirement_string || "")
|
|
108
|
+
else
|
|
109
|
+
matched_declaration
|
|
110
|
+
.sub(RequirementParser::NAME_WITH_EXTRAS) { |nm| nm + (updated_requirement_string || "") }
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
return updated unless update_hashes? && matched_declaration.match?(RequirementParser::HASHES)
|
|
114
|
+
|
|
115
|
+
algorithm = T.must(matched_declaration.match(RequirementParser::HASHES))
|
|
116
|
+
.named_captures.fetch("algorithm")
|
|
117
|
+
separator = hash_separator(old_requirement)
|
|
118
|
+
updated.sub(
|
|
118
119
|
RequirementParser::HASHES,
|
|
119
120
|
package_hashes_for(
|
|
120
121
|
name: dependency_name,
|
|
121
122
|
version: new_hash_version,
|
|
122
|
-
algorithm:
|
|
123
|
-
).join(
|
|
123
|
+
algorithm: algorithm
|
|
124
|
+
).join(separator)
|
|
124
125
|
)
|
|
125
126
|
end
|
|
126
127
|
|
|
@@ -142,7 +143,14 @@ module Dependabot
|
|
|
142
143
|
def original_declaration_replacement_regex
|
|
143
144
|
original_string =
|
|
144
145
|
original_dependency_declaration_string(old_requirement)
|
|
145
|
-
|
|
146
|
+
match_data = T.must(original_string.match(RequirementParser::NAME_WITH_EXTRAS))
|
|
147
|
+
name_escaped = Regexp.escape(T.must(match_data[:name]))
|
|
148
|
+
# Everything after name+extras (the requirement/markers/hashes portion)
|
|
149
|
+
after_name_extras = T.must(original_string[T.must(match_data[0]).length..]).strip
|
|
150
|
+
after_escaped = Regexp.escape(after_name_extras)
|
|
151
|
+
# Match the dependency name with any extras (or none), followed by the requirement.
|
|
152
|
+
# This ensures a single gsub handles all extras variants of the same dependency.
|
|
153
|
+
/(?<![\-\w\.\[])#{name_escaped}\s*\\?\s*(?:\[[^\]]*\])?\s*\\?\s*#{after_escaped}(?![\-\w\.])/
|
|
146
154
|
end
|
|
147
155
|
|
|
148
156
|
sig { params(requirement: T.nilable(String)).returns(T::Boolean) }
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require "excon"
|
|
5
|
+
require "openssl"
|
|
5
6
|
require "uri"
|
|
6
7
|
|
|
7
8
|
require "dependabot/metadata_finders"
|
|
@@ -27,6 +28,7 @@ module Dependabot
|
|
|
27
28
|
def initialize(dependency:, credentials:)
|
|
28
29
|
super
|
|
29
30
|
@pypi_listing = T.let(nil, T.nilable(T::Hash[String, T.untyped]))
|
|
31
|
+
@parsed_source_urls = T.let({}, T::Hash[String, T.nilable(Dependabot::Source)])
|
|
30
32
|
end
|
|
31
33
|
|
|
32
34
|
sig { returns(T.nilable(String)) }
|
|
@@ -37,26 +39,88 @@ module Dependabot
|
|
|
37
39
|
super
|
|
38
40
|
end
|
|
39
41
|
|
|
42
|
+
sig { override.returns(T.nilable(String)) }
|
|
43
|
+
def maintainer_changes
|
|
44
|
+
return unless dependency.previous_version
|
|
45
|
+
return unless dependency.version
|
|
46
|
+
|
|
47
|
+
previous_ownership = ownership_for_version(T.must(dependency.previous_version))
|
|
48
|
+
current_ownership = ownership_for_version(T.must(dependency.version))
|
|
49
|
+
|
|
50
|
+
if previous_ownership.nil? || current_ownership.nil?
|
|
51
|
+
Dependabot.logger.info("Unable to determine ownership changes for #{dependency.name}")
|
|
52
|
+
return
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
previous_org = previous_ownership["organization"]
|
|
56
|
+
current_org = current_ownership["organization"]
|
|
57
|
+
|
|
58
|
+
if previous_org != current_org && !(previous_org.nil? && current_org)
|
|
59
|
+
return "The organization that maintains #{dependency.name} on PyPI has " \
|
|
60
|
+
"changed since your current version."
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
previous_users = ownership_users(previous_ownership)
|
|
64
|
+
current_users = ownership_users(current_ownership)
|
|
65
|
+
|
|
66
|
+
# Warn only when there were previous maintainers and none of them remain
|
|
67
|
+
return unless previous_users.any? && !previous_users.intersect?(current_users)
|
|
68
|
+
|
|
69
|
+
"None of the maintainers for your current version of #{dependency.name} are " \
|
|
70
|
+
"listed as maintainers for the new version on PyPI."
|
|
71
|
+
end
|
|
72
|
+
|
|
40
73
|
private
|
|
41
74
|
|
|
42
75
|
sig { override.returns(T.nilable(Dependabot::Source)) }
|
|
43
76
|
def look_up_source
|
|
77
|
+
source_url = exact_match_source_url_from_project_urls
|
|
78
|
+
source_url ||= labelled_source_url_from_project_urls
|
|
79
|
+
source_url ||= fallback_source_url
|
|
80
|
+
source_url ||= source_from_description
|
|
81
|
+
source_url ||= source_from_homepage
|
|
82
|
+
|
|
83
|
+
parsed_source_from_url(source_url)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
sig { returns(T.nilable(String)) }
|
|
87
|
+
def exact_match_source_url_from_project_urls
|
|
88
|
+
project_urls.values.find do |url|
|
|
89
|
+
repo = parsed_source_from_url(url)&.repo
|
|
90
|
+
repo&.downcase&.end_with?(normalised_dependency_name)
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
sig { returns(T.nilable(String)) }
|
|
95
|
+
def labelled_source_url_from_project_urls
|
|
96
|
+
source_urls = source_like_project_url_labels.filter_map do |label|
|
|
97
|
+
project_urls[label]
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
source_urls.find { |url| parsed_source_from_url(url) }
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
sig { returns(T.nilable(String)) }
|
|
104
|
+
def fallback_source_url
|
|
44
105
|
potential_source_urls = [
|
|
45
|
-
pypi_listing.dig("info", "project_urls", "Source"),
|
|
46
|
-
pypi_listing.dig("info", "project_urls", "Repository"),
|
|
47
106
|
pypi_listing.dig("info", "home_page"),
|
|
48
107
|
pypi_listing.dig("info", "download_url"),
|
|
49
108
|
pypi_listing.dig("info", "docs_url")
|
|
50
109
|
].compact
|
|
51
110
|
|
|
52
|
-
potential_source_urls +=
|
|
53
|
-
(pypi_listing.dig("info", "project_urls") || {}).values
|
|
111
|
+
potential_source_urls += project_urls.values
|
|
54
112
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
source_url ||= source_from_homepage
|
|
113
|
+
potential_source_urls.find { |url| parsed_source_from_url(url) }
|
|
114
|
+
end
|
|
58
115
|
|
|
59
|
-
|
|
116
|
+
sig { returns(T::Hash[String, String]) }
|
|
117
|
+
def project_urls
|
|
118
|
+
pypi_listing.dig("info", "project_urls") || {}
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
sig { returns(T::Array[String]) }
|
|
122
|
+
def source_like_project_url_labels
|
|
123
|
+
["Source", "Source Code", "Repository", "Code", "Homepage"]
|
|
60
124
|
end
|
|
61
125
|
|
|
62
126
|
# rubocop:disable Metrics/PerceivedComplexity
|
|
@@ -73,7 +137,7 @@ module Dependabot
|
|
|
73
137
|
# Looking for a source where the repo name exactly matches the
|
|
74
138
|
# dependency name
|
|
75
139
|
match_url = potential_source_urls.find do |url|
|
|
76
|
-
repo =
|
|
140
|
+
repo = parsed_source_from_url(url)&.repo
|
|
77
141
|
repo&.downcase&.end_with?(normalised_dependency_name)
|
|
78
142
|
end
|
|
79
143
|
|
|
@@ -83,11 +147,14 @@ module Dependabot
|
|
|
83
147
|
# mentioned when the link is followed
|
|
84
148
|
@source_from_description ||= T.let(
|
|
85
149
|
potential_source_urls.find do |url|
|
|
86
|
-
full_url =
|
|
150
|
+
full_url = parsed_source_from_url(url)&.url
|
|
87
151
|
next unless full_url
|
|
88
152
|
|
|
89
153
|
response = Dependabot::RegistryClient.get(url: full_url)
|
|
90
|
-
|
|
154
|
+
unless response.status == 200
|
|
155
|
+
Dependabot.logger.warn("Error fetching source URL #{full_url}: HTTP #{response.status}")
|
|
156
|
+
next
|
|
157
|
+
end
|
|
91
158
|
|
|
92
159
|
response.body.include?(normalised_dependency_name)
|
|
93
160
|
end,
|
|
@@ -108,7 +175,7 @@ module Dependabot
|
|
|
108
175
|
end
|
|
109
176
|
|
|
110
177
|
match_url = potential_source_urls.find do |url|
|
|
111
|
-
repo =
|
|
178
|
+
repo = parsed_source_from_url(url)&.repo
|
|
112
179
|
repo&.downcase&.end_with?(normalised_dependency_name)
|
|
113
180
|
end
|
|
114
181
|
|
|
@@ -116,7 +183,7 @@ module Dependabot
|
|
|
116
183
|
|
|
117
184
|
@source_from_homepage ||= T.let(
|
|
118
185
|
potential_source_urls.find do |url|
|
|
119
|
-
full_url =
|
|
186
|
+
full_url = parsed_source_from_url(url)&.url
|
|
120
187
|
next unless full_url
|
|
121
188
|
|
|
122
189
|
response = Dependabot::RegistryClient.get(url: full_url)
|
|
@@ -143,7 +210,8 @@ module Dependabot
|
|
|
143
210
|
begin
|
|
144
211
|
Dependabot::RegistryClient.get(url: homepage_url)
|
|
145
212
|
rescue Excon::Error::Timeout, Excon::Error::Socket,
|
|
146
|
-
Excon::Error::TooManyRedirects, ArgumentError
|
|
213
|
+
Excon::Error::TooManyRedirects, OpenSSL::SSL::SSLError, ArgumentError => e
|
|
214
|
+
Dependabot.logger.warn("Error fetching Python homepage URL #{homepage_url}: #{e.class}: #{e.message}")
|
|
147
215
|
nil
|
|
148
216
|
end,
|
|
149
217
|
T.nilable(Excon::Response)
|
|
@@ -165,9 +233,8 @@ module Dependabot
|
|
|
165
233
|
|
|
166
234
|
@pypi_listing = JSON.parse(response.body)
|
|
167
235
|
return @pypi_listing
|
|
168
|
-
rescue JSON::ParserError
|
|
169
|
-
|
|
170
|
-
rescue Excon::Error::Timeout
|
|
236
|
+
rescue JSON::ParserError, Excon::Error::Timeout, Excon::Error::Socket, OpenSSL::SSL::SSLError => e
|
|
237
|
+
Dependabot.logger.warn("Error fetching Python package listing from #{url}: #{e.class}: #{e.message}")
|
|
171
238
|
next
|
|
172
239
|
end
|
|
173
240
|
|
|
@@ -194,23 +261,88 @@ module Dependabot
|
|
|
194
261
|
|
|
195
262
|
sig { returns(T::Array[String]) }
|
|
196
263
|
def possible_listing_urls
|
|
197
|
-
|
|
264
|
+
index_credentials =
|
|
198
265
|
credentials
|
|
199
266
|
.select { |cred| cred["type"] == "python_index" }
|
|
200
|
-
.map { |c| AuthedUrlBuilder.authed_url(credential: c) }
|
|
201
267
|
|
|
202
|
-
|
|
268
|
+
credential_urls = index_credentials
|
|
269
|
+
.map { |c| AuthedUrlBuilder.authed_url(credential: c) }
|
|
270
|
+
.reject { |url| url.strip.empty? }
|
|
271
|
+
|
|
272
|
+
base_urls = if index_credentials.any?(&:replaces_base?)
|
|
273
|
+
credential_urls
|
|
274
|
+
else
|
|
275
|
+
credential_urls + [MAIN_PYPI_URL]
|
|
276
|
+
end
|
|
277
|
+
base_urls = [MAIN_PYPI_URL] if base_urls.empty?
|
|
278
|
+
|
|
279
|
+
base_urls.map do |base_url|
|
|
203
280
|
# Convert /simple/ endpoints to /pypi/ for JSON API access
|
|
204
281
|
json_base_url = base_url.sub(%r{/simple/?$}i, "/pypi")
|
|
205
282
|
json_base_url.gsub(%r{/$}, "") + "/#{normalised_dependency_name}/json"
|
|
206
283
|
end
|
|
207
284
|
end
|
|
208
285
|
|
|
286
|
+
sig { params(version: String).returns(T.nilable(T::Hash[String, T.untyped])) }
|
|
287
|
+
def ownership_for_version(version)
|
|
288
|
+
if version.include?("+")
|
|
289
|
+
Dependabot.logger.info("Version #{version} includes a local version identifier, skipping ownership check")
|
|
290
|
+
return nil
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
possible_version_listing_urls(version).each do |url|
|
|
294
|
+
response = fetch_authed_url(url)
|
|
295
|
+
unless response.status == 200
|
|
296
|
+
Dependabot.logger.warn(
|
|
297
|
+
"Error fetching Python package ownership from #{url} for version #{version}: " \
|
|
298
|
+
"HTTP #{response.status}"
|
|
299
|
+
)
|
|
300
|
+
next
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
data = JSON.parse(response.body)
|
|
304
|
+
ownership = data["ownership"]
|
|
305
|
+
Dependabot.logger.debug("Found ownership for #{dependency.name} version #{version}")
|
|
306
|
+
return ownership
|
|
307
|
+
rescue JSON::ParserError, Excon::Error::Timeout, Excon::Error::Socket,
|
|
308
|
+
Excon::Error::TooManyRedirects, OpenSSL::SSL::SSLError, ArgumentError => e
|
|
309
|
+
Dependabot.logger.warn(
|
|
310
|
+
"Error fetching Python package ownership from #{url} for version #{version}: #{e.class}: #{e.message}"
|
|
311
|
+
)
|
|
312
|
+
next
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
nil
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
sig { params(version: String).returns(T::Array[String]) }
|
|
319
|
+
def possible_version_listing_urls(version)
|
|
320
|
+
possible_listing_urls.map do |url|
|
|
321
|
+
url.sub(%r{/json$}, "/#{URI::DEFAULT_PARSER.escape(version)}/json")
|
|
322
|
+
end
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
sig { params(ownership: T::Hash[String, T.untyped]).returns(T::Array[String]) }
|
|
326
|
+
def ownership_users(ownership)
|
|
327
|
+
roles = ownership["roles"]
|
|
328
|
+
return [] unless roles.is_a?(Array)
|
|
329
|
+
|
|
330
|
+
roles.filter_map { |role| role["user"] if role.is_a?(Hash) }
|
|
331
|
+
end
|
|
332
|
+
|
|
209
333
|
# Strip [extras] from name (dependency_name[extra_dep,other_extra])
|
|
210
334
|
sig { returns(String) }
|
|
211
335
|
def normalised_dependency_name
|
|
212
336
|
NameNormaliser.normalise(dependency.name)
|
|
213
337
|
end
|
|
338
|
+
|
|
339
|
+
sig { params(url: T.nilable(String)).returns(T.nilable(Dependabot::Source)) }
|
|
340
|
+
def parsed_source_from_url(url)
|
|
341
|
+
return unless url
|
|
342
|
+
return @parsed_source_urls[url] if @parsed_source_urls.key?(url)
|
|
343
|
+
|
|
344
|
+
@parsed_source_urls[url] = Source.from_url(url)
|
|
345
|
+
end
|
|
214
346
|
end
|
|
215
347
|
end
|
|
216
348
|
end
|
|
@@ -238,7 +238,8 @@ module Dependabot
|
|
|
238
238
|
content = file.content
|
|
239
239
|
return [] if content.nil?
|
|
240
240
|
|
|
241
|
-
paths = content.scan(CHILD_REQUIREMENT_REGEX).flatten
|
|
241
|
+
paths = content.scan(CHILD_REQUIREMENT_REGEX).flatten +
|
|
242
|
+
content.scan(CONSTRAINT_REGEX).flatten
|
|
242
243
|
current_dir = File.dirname(file.name)
|
|
243
244
|
|
|
244
245
|
paths.flat_map do |path|
|
|
@@ -268,7 +269,8 @@ module Dependabot
|
|
|
268
269
|
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
269
270
|
def constraints_files
|
|
270
271
|
all_requirement_files = requirements_txt_files +
|
|
271
|
-
child_requirement_txt_files
|
|
272
|
+
child_requirement_txt_files +
|
|
273
|
+
requirements_in_files
|
|
272
274
|
|
|
273
275
|
constraints_paths = all_requirement_files.map do |req_file|
|
|
274
276
|
current_dir = File.dirname(req_file.name)
|
|
@@ -283,7 +285,10 @@ module Dependabot
|
|
|
283
285
|
end
|
|
284
286
|
end.flatten.uniq
|
|
285
287
|
|
|
286
|
-
|
|
288
|
+
already_fetched_names = child_requirement_files.map(&:name)
|
|
289
|
+
constraints_paths
|
|
290
|
+
.reject { |path| already_fetched_names.include?(path) }
|
|
291
|
+
.map { |path| fetch_file_from_host(path) }
|
|
287
292
|
end
|
|
288
293
|
|
|
289
294
|
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
|
@@ -355,7 +360,7 @@ module Dependabot
|
|
|
355
360
|
|
|
356
361
|
uneditable_reqs =
|
|
357
362
|
content
|
|
358
|
-
.scan(/(?<name>^['"]?(?:file:)?(?<path>\.[^\[#'"\n]*))/)
|
|
363
|
+
.scan(/(?<name>^['"]?(?:file:)?(?<path>\.[^\[#'"\n;]*))/)
|
|
359
364
|
.filter_map do |match_array|
|
|
360
365
|
n, p = match_array
|
|
361
366
|
{ name: n.to_s.strip, path: p.to_s.strip, file: req_file.name } unless p.to_s.include?("://")
|
|
@@ -363,7 +368,7 @@ module Dependabot
|
|
|
363
368
|
|
|
364
369
|
editable_reqs =
|
|
365
370
|
content
|
|
366
|
-
.scan(/(?<name>^-e\s+['"]?(?:file:)?(?<path>[^\[#'"\n]*))/)
|
|
371
|
+
.scan(/(?<name>^-e\s+['"]?(?:file:)?(?<path>[^\[#'"\n;]*))/)
|
|
367
372
|
.filter_map do |match_array|
|
|
368
373
|
n, p = match_array
|
|
369
374
|
unless p.to_s.include?("://") || p.to_s.include?("git@")
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dependabot-python
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.368.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dependabot
|
|
@@ -15,14 +15,14 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - '='
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 0.
|
|
18
|
+
version: 0.368.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.368.0
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: debug
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -294,7 +294,7 @@ licenses:
|
|
|
294
294
|
- MIT
|
|
295
295
|
metadata:
|
|
296
296
|
bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
|
|
297
|
-
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.
|
|
297
|
+
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.368.0
|
|
298
298
|
rdoc_options: []
|
|
299
299
|
require_paths:
|
|
300
300
|
- lib
|