Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove python_new_version feature flag and irrelevant code #10797

Merged
merged 2 commits into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 4 additions & 14 deletions python/lib/dependabot/python/requirement.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class Requirement < Dependabot::Requirement
.map { |k| Regexp.quote(k) }.join("|")
version_pattern = Python::Version::VERSION_PATTERN

PATTERN_RAW = "\\s*(#{quoted})?\\s*(#{version_pattern})\\s*".freeze
PATTERN_RAW = "\\s*(?<op>#{quoted})?\\s*(?<version>#{version_pattern})\\s*".freeze
PATTERN = /\A#{PATTERN_RAW}\z/
PARENS_PATTERN = /\A\(([^)]+)\)\z/

Expand All @@ -36,24 +36,14 @@ def self.parse(obj)
line = matches[1]
end

pattern = PATTERN

if Dependabot::Experiments.enabled?(:python_new_version)
quoted = OPS.keys.sort_by(&:length).reverse
.map { |k| Regexp.quote(k) }.join("|")
version_pattern = Python::Version::NEW_VERSION_PATTERN
pattern_raw = "\\s*(?<op>#{quoted})?\\s*(?<version>#{version_pattern})\\s*".freeze
pattern = /\A#{pattern_raw}\z/
end

unless (matches = pattern.match(line))
unless (matches = PATTERN.match(line))
msg = "Illformed requirement [#{obj.inspect}]"
raise BadRequirementError, msg
end

return DefaultRequirement if matches[1] == ">=" && matches[2] == "0"
return DefaultRequirement if matches[:op] == ">=" && matches[:version] == "0"

[matches[1] || "=", Python::Version.new(T.must(matches[2]))]
[matches[:op] || "=", Python::Version.new(T.must(matches[:version]))]
end

# Returns an array of requirements. At least one requirement from the
Expand Down
152 changes: 24 additions & 128 deletions python/lib/dependabot/python/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,11 @@ class Version < Dependabot::Version
sig { returns(T.nilable(T::Array[T.any(String, Integer)])) }
attr_reader :local

attr_reader :local_version
attr_reader :post_release_version

INFINITY = 1000
NEGATIVE_INFINITY = -INFINITY

# See https://peps.python.org/pep-0440/#appendix-b-parsing-version-strings-with-regular-expressions
NEW_VERSION_PATTERN = /
VERSION_PATTERN = /
v?
(?:
(?:(?<epoch>[0-9]+)!)? # epoch
Expand Down Expand Up @@ -65,62 +62,37 @@ class Version < Dependabot::Version
(?:\+(?<local>[a-z0-9]+(?:[-_\.][a-z0-9]+)*))? # local version
/ix

VERSION_PATTERN = 'v?([1-9][0-9]*!)?[0-9]+[0-9a-zA-Z]*(?>\.[0-9a-zA-Z]+)*' \
'(-[0-9A-Za-z]+(\.[0-9a-zA-Z]+)*)?' \
'(\+[0-9a-zA-Z]+(\.[0-9a-zA-Z]+)*)?'

ANCHORED_VERSION_PATTERN = /\A\s*#{VERSION_PATTERN}\s*\z/

sig { override.params(version: VersionParameter).returns(T::Boolean) }
def self.correct?(version)
return false if version.nil?

if Dependabot::Experiments.enabled?(:python_new_version)
version.to_s.match?(/\A\s*#{NEW_VERSION_PATTERN}\s*\z/o)
else
version.to_s.match?(ANCHORED_VERSION_PATTERN)
end
version.to_s.match?(ANCHORED_VERSION_PATTERN)
end

sig { override.params(version: VersionParameter).void }
def initialize(version) # rubocop:disable Metrics/AbcSize,Metrics/PerceivedComplexity
def initialize(version)
raise Dependabot::BadRequirementError, "Malformed version string - string is nil" if version.nil?

@version_string = version.to_s

raise Dependabot::BadRequirementError, "Malformed version string - string is empty" if @version_string.empty?

matches = anchored_version_pattern.match(@version_string.downcase)
matches = ANCHORED_VERSION_PATTERN.match(@version_string.downcase)

unless matches
raise Dependabot::BadRequirementError,
"Malformed version string - #{@version_string} does not match regex"
end

if Dependabot::Experiments.enabled?(:python_new_version)
@epoch = matches["epoch"].to_i
@release_segment = matches["release"]&.split(".")&.map(&:to_i) || []
@pre = parse_letter_version(matches["pre_l"], matches["pre_n"])
@post = parse_letter_version(matches["post_l"], matches["post_n1"] || matches["post_n2"])
@dev = parse_letter_version(matches["dev_l"], matches["dev_n"])
@local = parse_local_version(matches["local"])
super(matches["release"] || "")
else
version, @local_version = @version_string.split("+")
version ||= ""
version = version.gsub(/^v/, "")
if version.include?("!")
epoch, version = version.split("!")
@epoch = epoch.to_i
else
@epoch = 0
end
version = normalise_prerelease(version)
version, @post_release_version = version.split(/\.r(?=\d)/)
version ||= ""
@local_version = normalise_prerelease(@local_version) if @local_version
super
end
@epoch = matches["epoch"].to_i
@release_segment = matches["release"]&.split(".")&.map(&:to_i) || []
@pre = parse_letter_version(matches["pre_l"], matches["pre_n"])
@post = parse_letter_version(matches["post_l"], matches["post_n1"] || matches["post_n2"])
@dev = parse_letter_version(matches["dev_l"], matches["dev_n"])
@local = parse_local_version(matches["local"])
super(matches["release"] || "")
end

sig { override.params(version: VersionParameter).returns(Dependabot::Python::Version) }
Expand All @@ -140,52 +112,35 @@ def inspect # :nodoc:

sig { returns(T::Boolean) }
def prerelease?
return super unless Dependabot::Experiments.enabled?(:python_new_version)

!!(pre || dev)
end

sig { returns(T.any(Gem::Version, Dependabot::Python::Version)) }
sig { returns(Dependabot::Python::Version) }
def release
return super unless Dependabot::Experiments.enabled?(:python_new_version)

Dependabot::Python::Version.new(release_segment.join("."))
end

sig { params(other: VersionParameter).returns(Integer) }
def <=>(other) # rubocop:disable Metrics/AbcSize,Metrics/PerceivedComplexity
def <=>(other)
other = Dependabot::Python::Version.new(other.to_s) unless other.is_a?(Dependabot::Python::Version)
other = T.cast(other, Dependabot::Python::Version)

if Dependabot::Experiments.enabled?(:python_new_version)
epoch_comparison = epoch <=> other.epoch
return epoch_comparison unless epoch_comparison.zero?
epoch_comparison = epoch <=> other.epoch
return epoch_comparison unless epoch_comparison.zero?

release_comparison = release_version_comparison(other)
return release_comparison unless release_comparison.zero?
release_comparison = release_version_comparison(other)
return release_comparison unless release_comparison.zero?

pre_comparison = compare_keys(pre_cmp_key, other.pre_cmp_key)
return pre_comparison unless pre_comparison.zero?
pre_comparison = compare_keys(pre_cmp_key, other.pre_cmp_key)
return pre_comparison unless pre_comparison.zero?

post_comparison = compare_keys(post_cmp_key, other.post_cmp_key)
return post_comparison unless post_comparison.zero?
post_comparison = compare_keys(post_cmp_key, other.post_cmp_key)
return post_comparison unless post_comparison.zero?

dev_comparison = compare_keys(dev_cmp_key, other.dev_cmp_key)
return dev_comparison unless dev_comparison.zero?
dev_comparison = compare_keys(dev_cmp_key, other.dev_cmp_key)
return dev_comparison unless dev_comparison.zero?

compare_keys(local_cmp_key, other.local_cmp_key)
else
epoch_comparison = epoch_comparison(other)
return epoch_comparison unless epoch_comparison.zero?

version_comparison = super
return T.must(version_comparison) unless version_comparison&.zero?

post_version_comparison = post_version_comparison(other)
return post_version_comparison unless post_version_comparison.zero?

local_version_comparison(other)
end
compare_keys(local_cmp_key, other.local_cmp_key)
end

sig do
Expand Down Expand Up @@ -326,65 +281,6 @@ def parse_letter_version(letter = nil, number = nil)

[letter, number.to_i]
end

sig { returns(Regexp) }
def anchored_version_pattern
if Dependabot::Experiments.enabled?(:python_new_version)
/\A\s*#{NEW_VERSION_PATTERN}\s*\z/o
else
ANCHORED_VERSION_PATTERN
end
end

def epoch_comparison(other)
epoch.to_i <=> other.epoch.to_i
end

def post_version_comparison(other)
unless other.post_release_version
return post_release_version.nil? ? 0 : 1
end

return -1 if post_release_version.nil?

post_release_version.to_i <=> other.post_release_version.to_i
end

def local_version_comparison(other)
# Local version comparison works differently in Python: `1.0.beta`
# compares as greater than `1.0`. To accommodate, we make the
# strings the same length before comparing.
lhsegments = local_version.to_s.split(".").map(&:downcase)
rhsegments = other.local_version.to_s.split(".").map(&:downcase)
limit = [lhsegments.count, rhsegments.count].min

lhs = ["1", *lhsegments.first(limit)].join(".")
rhs = ["1", *rhsegments.first(limit)].join(".")

local_comparison = Gem::Version.new(lhs) <=> Gem::Version.new(rhs)

return local_comparison unless local_comparison&.zero?

lhsegments.count <=> rhsegments.count
end

def normalise_prerelease(version)
# Python has reserved words for release states, which are treated
# as equal (e.g., preview, pre and rc).
# Further, Python treats dashes as a separator between version
# parts and treats the alphabetical characters in strings as the
# start of a new version part (so 1.1a2 == 1.1.alpha.2).
version
.gsub("alpha", "a")
.gsub("beta", "b")
.gsub("preview", "c")
.gsub("pre", "c")
.gsub("post", "r")
.gsub("rev", "r")
.gsub(/([\d.\-_])rc([\d.\-_])?/, '\1c\2')
.tr("-", ".")
.gsub(/(\d)([a-z])/i, '\1.\2')
end
end
end
end
Expand Down
10 changes: 1 addition & 9 deletions python/spec/dependabot/python/version_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@
describe ".correct?" do
subject { described_class.correct?(version_string) }

before do
Dependabot::Experiments.register(:python_new_version, true)
end

context "with a valid version" do
let(:version_string) { "1.0.0" }

Expand Down Expand Up @@ -148,7 +144,7 @@
"1.0.0-rc.1",
"1",
"1.0.0+gc1",
# "1.0.0.post", TODO fails comparing to 1
"1.0.0.post", # TODO: fails comparing to 1
"1.post2",
"1.post2+gc1",
"1.post2+gc1.2",
Expand Down Expand Up @@ -239,10 +235,6 @@

let(:versions) { version_strings.map { |v| described_class.new(v) } }

before do
Dependabot::Experiments.register(:python_new_version, true)
end

it "returns list in the correct order" do
expect(versions.shuffle.sort).to eq versions
end
Expand Down
Loading