Merge pull request #18903 from Homebrew/livecheck/pypi-handle-regex
Pypi: Restore regex support
This commit is contained in:
commit
ad356d3658
@ -58,8 +58,10 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Parses JSON text and identifies versions using a `strategy` block.
|
# Parses JSON text and identifies versions using a `strategy` block.
|
||||||
# If a regex is provided, it will be passed as the second argument to
|
# If the block has two parameters, the parsed JSON data will be used as
|
||||||
# the `strategy` block (after the parsed JSON data).
|
# the first argument and the regex (if any) will be the second.
|
||||||
|
# Otherwise, only the parsed JSON data will be passed to the block.
|
||||||
|
#
|
||||||
# @param content [String] the JSON text to parse and check
|
# @param content [String] the JSON text to parse and check
|
||||||
# @param regex [Regexp, nil] a regex used for matching versions in the
|
# @param regex [Regexp, nil] a regex used for matching versions in the
|
||||||
# content
|
# content
|
||||||
@ -77,10 +79,8 @@ module Homebrew
|
|||||||
json = parse_json(content)
|
json = parse_json(content)
|
||||||
return [] if json.blank?
|
return [] if json.blank?
|
||||||
|
|
||||||
block_return_value = if regex.present?
|
block_return_value = if block.arity == 2
|
||||||
yield(json, regex)
|
yield(json, regex)
|
||||||
elsif block.arity == 2
|
|
||||||
raise "Two arguments found in `strategy` block but no regex provided."
|
|
||||||
else
|
else
|
||||||
yield(json)
|
yield(json)
|
||||||
end
|
end
|
||||||
|
@ -20,10 +20,14 @@ module Homebrew
|
|||||||
|
|
||||||
# The default `strategy` block used to extract version information when
|
# The default `strategy` block used to extract version information when
|
||||||
# a `strategy` block isn't provided.
|
# a `strategy` block isn't provided.
|
||||||
DEFAULT_BLOCK = T.let(proc do |json|
|
DEFAULT_BLOCK = T.let(proc do |json, regex|
|
||||||
json.dig("info", "version").presence
|
version = json.dig("info", "version")
|
||||||
|
next if version.blank?
|
||||||
|
|
||||||
|
regex ? version[regex, 1] : version
|
||||||
end.freeze, T.proc.params(
|
end.freeze, T.proc.params(
|
||||||
arg0: T::Hash[String, T.untyped],
|
json: T::Hash[String, T.untyped],
|
||||||
|
regex: T.nilable(Regexp),
|
||||||
).returns(T.nilable(String)))
|
).returns(T.nilable(String)))
|
||||||
|
|
||||||
# The `Regexp` used to extract the package name and suffix (e.g. file
|
# The `Regexp` used to extract the package name and suffix (e.g. file
|
||||||
|
@ -107,11 +107,6 @@ RSpec.describe Homebrew::Livecheck::Strategy::Json do
|
|||||||
expect(json.versions_from_content(content_simple, regex) { next }).to eq([])
|
expect(json.versions_from_content(content_simple, regex) { next }).to eq([])
|
||||||
end
|
end
|
||||||
|
|
||||||
it "errors if a block uses two arguments but a regex is not given" do
|
|
||||||
expect { json.versions_from_content(content_simple) { |json, regex| json["version"][regex, 1] } }
|
|
||||||
.to raise_error("Two arguments found in `strategy` block but no regex provided.")
|
|
||||||
end
|
|
||||||
|
|
||||||
it "errors on an invalid return type from a block" do
|
it "errors on an invalid return type from a block" do
|
||||||
expect { json.versions_from_content(content_simple, regex) { 123 } }
|
expect { json.versions_from_content(content_simple, regex) { 123 } }
|
||||||
.to raise_error(TypeError, Homebrew::Livecheck::Strategy::INVALID_BLOCK_RETURN_VALUE_MSG)
|
.to raise_error(TypeError, Homebrew::Livecheck::Strategy::INVALID_BLOCK_RETURN_VALUE_MSG)
|
||||||
|
@ -8,7 +8,7 @@ RSpec.describe Homebrew::Livecheck::Strategy::Pypi do
|
|||||||
let(:pypi_url) { "https://files.pythonhosted.org/packages/ab/cd/efg/example-package-1.2.3.tar.gz" }
|
let(:pypi_url) { "https://files.pythonhosted.org/packages/ab/cd/efg/example-package-1.2.3.tar.gz" }
|
||||||
let(:non_pypi_url) { "https://brew.sh/test" }
|
let(:non_pypi_url) { "https://brew.sh/test" }
|
||||||
|
|
||||||
let(:regex) { /^v?(\d+(?:\.\d+)+)$/i }
|
let(:regex) { /^v?(\d+(?:\.\d+)+)/i }
|
||||||
|
|
||||||
let(:generated) do
|
let(:generated) do
|
||||||
{
|
{
|
||||||
@ -17,25 +17,26 @@ RSpec.describe Homebrew::Livecheck::Strategy::Pypi do
|
|||||||
end
|
end
|
||||||
|
|
||||||
# This is a limited subset of a PyPI JSON API response object, for the sake
|
# This is a limited subset of a PyPI JSON API response object, for the sake
|
||||||
# of testing.
|
# of testing. Typical versions use a `1.2.3` format but this adds a suffix,
|
||||||
|
# so we can test regex matching.
|
||||||
let(:content) do
|
let(:content) do
|
||||||
<<~JSON
|
<<~JSON
|
||||||
{
|
{
|
||||||
"info": {
|
"info": {
|
||||||
"version": "1.2.3"
|
"version": "1.2.3-456"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
JSON
|
JSON
|
||||||
end
|
end
|
||||||
|
|
||||||
let(:matches) { ["1.2.3"] }
|
let(:matches) { ["1.2.3-456"] }
|
||||||
|
|
||||||
let(:find_versions_return_hash) do
|
let(:find_versions_return_hash) do
|
||||||
{
|
{
|
||||||
matches: {
|
matches: {
|
||||||
"1.2.3" => Version.new("1.2.3"),
|
"1.2.3-456" => Version.new("1.2.3-456"),
|
||||||
},
|
},
|
||||||
regex: nil,
|
regex:,
|
||||||
url: generated[:url],
|
url: generated[:url],
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
@ -76,10 +77,17 @@ RSpec.describe Homebrew::Livecheck::Strategy::Pypi do
|
|||||||
{
|
{
|
||||||
cached:,
|
cached:,
|
||||||
cached_default: cached.merge({ matches: {} }),
|
cached_default: cached.merge({ matches: {} }),
|
||||||
|
cached_regex: cached.merge({
|
||||||
|
matches: { "1.2.3" => Version.new("1.2.3") },
|
||||||
|
regex:,
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
it "finds versions in provided content" do
|
it "finds versions in provided content" do
|
||||||
|
expect(pypi.find_versions(url: pypi_url, regex:, provided_content: content))
|
||||||
|
.to eq(match_data[:cached_regex])
|
||||||
|
|
||||||
expect(pypi.find_versions(url: pypi_url, provided_content: content))
|
expect(pypi.find_versions(url: pypi_url, provided_content: content))
|
||||||
.to eq(match_data[:cached])
|
.to eq(match_data[:cached])
|
||||||
end
|
end
|
||||||
@ -92,7 +100,7 @@ RSpec.describe Homebrew::Livecheck::Strategy::Pypi do
|
|||||||
next if match.blank?
|
next if match.blank?
|
||||||
|
|
||||||
match[1]
|
match[1]
|
||||||
end).to eq(match_data[:cached].merge({ regex: }))
|
end).to eq(match_data[:cached_regex])
|
||||||
|
|
||||||
expect(pypi.find_versions(url: pypi_url, provided_content: content) do |json|
|
expect(pypi.find_versions(url: pypi_url, provided_content: content) do |json|
|
||||||
json.dig("info", "version").presence
|
json.dig("info", "version").presence
|
||||||
@ -100,10 +108,14 @@ RSpec.describe Homebrew::Livecheck::Strategy::Pypi do
|
|||||||
end
|
end
|
||||||
|
|
||||||
it "returns default match_data when block doesn't return version information" do
|
it "returns default match_data when block doesn't return version information" do
|
||||||
|
no_match_regex = /will_not_match/i
|
||||||
|
|
||||||
expect(pypi.find_versions(url: pypi_url, provided_content: '{"info":{"version":""}}'))
|
expect(pypi.find_versions(url: pypi_url, provided_content: '{"info":{"version":""}}'))
|
||||||
.to eq(match_data[:cached_default])
|
.to eq(match_data[:cached_default])
|
||||||
expect(pypi.find_versions(url: pypi_url, provided_content: '{"other":true}'))
|
expect(pypi.find_versions(url: pypi_url, provided_content: '{"other":true}'))
|
||||||
.to eq(match_data[:cached_default])
|
.to eq(match_data[:cached_default])
|
||||||
|
expect(pypi.find_versions(url: pypi_url, regex: no_match_regex, provided_content: content))
|
||||||
|
.to eq(match_data[:cached_default].merge({ regex: no_match_regex }))
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns default match_data when url is blank" do
|
it "returns default match_data when url is blank" do
|
||||||
|
Loading…
x
Reference in New Issue
Block a user