class Dependabot::Python::Version

Constants

ANCHORED_VERSION_PATTERN
VERSION_PATTERN

Attributes

local_version[R]
post_release_version[R]

Public Class Methods

correct?(version) click to toggle source
# File lib/dependabot/python/version.rb, line 21
def self.correct?(version)
  return false if version.nil?

  version.to_s.match?(ANCHORED_VERSION_PATTERN)
end
new(version) click to toggle source
Calls superclass method
# File lib/dependabot/python/version.rb, line 27
def initialize(version)
  @version_string = version.to_s
  version, @local_version = version.split("+")
  version ||= ""
  version = version.gsub(/^v/, "")
  version = normalise_prerelease(version)
  version, @post_release_version = version.split(/\.r(?=\d)/)
  version ||= ""
  @local_version = normalise_prerelease(@local_version) if @local_version
  super
end

Public Instance Methods

<=>(other) click to toggle source
# File lib/dependabot/python/version.rb, line 47
def <=>(other)
  version_comparison = old_comp(other)
  return version_comparison unless version_comparison.zero?

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

  local_version_comparison(other)
end
local_version_comparison(other) click to toggle source
# File lib/dependabot/python/version.rb, line 70
def local_version_comparison(other)
  unless other.is_a?(Python::Version)
    return local_version.nil? ? 0 : 1
  end

  # 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
post_version_comparison(other) click to toggle source
# File lib/dependabot/python/version.rb, line 56
def post_version_comparison(other)
  unless other.is_a?(Python::Version) && other.post_release_version
    return post_release_version.nil? ? 0 : 1
  end

  return -1 if post_release_version.nil?

  # Post release versions should only ever be a single number, so we can
  # just string-comparison them.
  return 0 if post_release_version.to_i == other.post_release_version.to_i

  post_release_version.to_i > other.post_release_version.to_i ? 1 : -1
end
to_s() click to toggle source
# File lib/dependabot/python/version.rb, line 39
def to_s
  @version_string
end

Private Instance Methods

normalise_prerelease(version) click to toggle source
# File lib/dependabot/python/version.rb, line 94
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
old_comp(other) click to toggle source

TODO: Delete this once we're using a version of Rubygems that includes github.com/rubygems/rubygems/pull/2651

rubocop:disable Metrics/PerceivedComplexity rubocop:disable Style/CaseEquality rubocop:disable Style/ParallelAssignment rubocop:disable Style/RedundantReturn

# File lib/dependabot/python/version.rb, line 119
def old_comp(other)
  return unless Gem::Version === other
  return 0 if @version == other._version || canonical_segments == other.canonical_segments

  lhsegments = canonical_segments
  rhsegments = other.canonical_segments

  lhsize = lhsegments.size
  rhsize = rhsegments.size
  limit  = (lhsize > rhsize ? lhsize : rhsize) - 1

  i = 0

  while i <= limit
    lhs, rhs = lhsegments[i] || 0, rhsegments[i] || 0
    i += 1

    next      if lhs == rhs
    return -1 if String  === lhs && Numeric === rhs
    return  1 if Numeric === lhs && String  === rhs

    return lhs <=> rhs
  end

  return 0
end