faqts : Computers : Programming : Languages : Python : Snippets

+ Search
Add Entry AlertManage Folder Edit Entry Add page to http://del.icio.us/
Did You Find This Entry Useful?

1 of 2 people (50%) answered Yes
Recently 0 of 1 people (0%) answered Yes

Entry

Parsing sys.version

Jul 5th, 2000 09:58
Nathan Wallace, Hans Nowak, Snippet 9, Michael P. Reilly


"""
Packages: text.parsing
"""

"""
: What's the best way to test the Python version in a script?  I'm
: thinking of a function like "require 5.004;" in Perl, something like 
: this:

: def require_python_version(what_I_want):
: 	what_I_want = float(what_I_want)
: 	actual_version = some_mangling_of(sys.version)
: 	if actual_version < what_I_want:
: 		print "You lose, buster."
: 		sys.exit(1)

: Currently, I can test for 1.5 compliance as a string match with
:>>> hasattr(sys, 'version') and sys.version[:3] >= '1.5'
: but that might not necessarily work with every version somebody might have
: out there, or with future versions.

: For reference, my sys.version says:
: 1.5.1 (#1, May 29 1998, 12:50:41)  [GCC 2.7.2.3]

: The double decimal point makes it unparseable as a number, unless you
: drop the second decimal and convert it to 1.51.  But what to do about
: beta versions, which will sort alphabetically after their non-beta
: counterparts?  Drop the second number by 1 if you see the word "beta" or
: the letter "b"?  

I had a similar problem with CVS/RCS numbers.  I created a class where
partial order comparisions can be performed.  This is the same with
(many) release numbers, including Python (so far).  You could possibly
use this as-is, but should take out the CVS/RCS specific idiosyncrasies.
Especially the distinction between a "branch" number and a "revision"
number.
"""

import string

class Revision:
  def __init__(self, number):
    if not number:
      number = '1'
    if hasattr(number, '__class__') and number.__class__ is Revision:
      self.path = number.path[:]
      self.type = number.type
      self.number = number.number
    elif type(number) in (type(()), type([])):
      self.path = map(None, number)
      self._join(number)
      self._settype()
    else:
      self.number = self._normalize(str(number))
      self._split(self.number)
      self._settype()

  def _split(self, number):
    parts = map(string.atoi, string.splitfields(number, '.'))
    self.path = parts
  def _join(self, path):
    parts = string.joinfields(map(str, path), '.')
    self.number = parts
  def _settype(self):
    if (len(self.path) % 2) == 0:
      self.type = 'r'
    else:
      self.type = 'b'
  def _normalize(self, number):
    pos = string.rfind(number, '.0.')
    if pos == -1:
      return number
    else:
      return number[:pos] + number[pos+2:] # keep one dot

  def __len__(self):
    """shows the depth"""
    return (len(self.path) + 1) / 2
  def __hash__(self):
    return hash(self.number)

  def __cmp__(self, other):
    if self.type != other.type:
      raise TypeError, "Not the same type"
    ps, po = self.path, other.path
    ls, lo = len(ps), len(po)
    minimum = min(ls, lo)
    val = cmp(ps[:minimum], po[:minimum])
    if val == 0:
      val = cmp(ls, lo)
    return val

  def up(self):
    return Revision(self.path[:-1])

  def next(self):
    p = self.path[:]
    p[-1] = p[-1] + 1
    return Revision(p)

  def previous(self):
    p = self.path[:]
    p[-1] = p[-1] - 1
    if p[-1] <= 0:
      return self.up()
    else:
      return Revision(p)

  def branch(self):
    if self.type == 'b':
      raise TypeError, "Invalid type"
    return self.up()

  def getpath(self):
    if self.type == 'r':
      list = (self,)
      rev = self.up()
    else:
      list = ()
      rev = self
    for i in range(len(self)-1):
      list = list + (rev,)
      rev = rev.up().up()
    list = list + (rev,) # root
    return tuple(list)

  def is_in(self, other):
    if len(self) > len(other):
      return 0
    else:
      return self.path == other.path[:len(self.path)]

  def __str__(self):
    return self.number
  def __repr__(self):
    if self.type == 'b':
      type='branch'
    else:
      type='revision'
    return '<%s %s>' % (type, self.number)

import sys
rv = Revision("1.5.1")
print rv