aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlivier Tilloy <olivier@tilloy.net>2009-03-06 15:07:59 +0100
committerOlivier Tilloy <olivier@tilloy.net>2009-03-06 15:07:59 +0100
commit4b0b859dd1d0884da54d633cf6dec8c5f4d8318f (patch)
tree1ac7ddcf64eb66e16e818634af865bebdb50a5e4
parentf2a4f351d61aca1dd24d62a3ec9893f0f3965fc0 (diff)
downloadpyexiv2-4b0b859dd1d0884da54d633cf6dec8c5f4d8318f.tar.gz
Conversion of a string to a Rational.
-rw-r--r--src/pyexiv2.py42
-rw-r--r--unittest/rational.py8
2 files changed, 30 insertions, 20 deletions
diff --git a/src/pyexiv2.py b/src/pyexiv2.py
index 0241914..4f23757 100644
--- a/src/pyexiv2.py
+++ b/src/pyexiv2.py
@@ -289,6 +289,8 @@ class Rational(object):
A class representing a rational number.
"""
+ _format_re = re.compile(r'(?P<numerator>-?\d+)/(?P<denominator>\d+)')
+
def __init__(self, numerator, denominator):
"""
Constructor.
@@ -306,6 +308,26 @@ class Rational(object):
self.numerator = long(numerator)
self.denominator = long(denominator)
+ @staticmethod
+ def from_string(string):
+ """
+ Instantiate a Rational from a string formatted as
+ C{[-]numerator/denominator}.
+
+ @param string: a string representation of a rational number
+ @type string: C{str}
+
+ @return: the rational number parsed
+ @rtype: L{Rational}
+
+ @raise ValueError: if the format of the string is invalid
+ """
+ match = Rational._format_re.match(string)
+ if match is None:
+ raise ValueError('Invalid format for a rational: %s' % string)
+ gd = match.groupdict()
+ return Rational(long(gd['numerator']), long(gd['denominator']))
+
def __eq__(self, other):
"""
Compare two rational numbers for equality.
@@ -327,26 +349,6 @@ class Rational(object):
"""
return '%d/%d' % (self.numerator, self.denominator)
-def StringToRational(string):
- """
- Try to convert a string containing a rational number to a Rational object.
-
- Try to convert a string containing a rational number to the corresponding
- Rational object.
- The conversion is done by matching a regular expression.
- If the pattern does not match, the Rational object with numerator=0 and
- denominator=1 is returned.
-
- Keyword arguments:
- string -- the string potentially containing a rational number
- """
- pattern = re.compile("(-?[0-9]+)/(-?[1-9][0-9]*)")
- match = pattern.match(string)
- if match == None:
- return Rational(0, 1)
- else:
- return Rational(*map(long, match.groups()))
-
class MetadataTag(object):
diff --git a/unittest/rational.py b/unittest/rational.py
index 8ae6d65..f475846 100644
--- a/unittest/rational.py
+++ b/unittest/rational.py
@@ -36,6 +36,14 @@ class TestRational(unittest.TestCase):
self.assertEqual(r.denominator, 1)
self.assertRaises(ZeroDivisionError, Rational, 1, 0)
+ def test_from_string(self):
+ self.assertEqual(Rational.from_string('4/3'), Rational(4, 3))
+ self.assertEqual(Rational.from_string('-4/3'), Rational(-4, 3))
+ self.assertRaises(ValueError, Rational.from_string, '+3/5')
+ self.assertRaises(ValueError, Rational.from_string, '3 / 5')
+ self.assertRaises(ValueError, Rational.from_string, '3/-5')
+ self.assertRaises(ValueError, Rational.from_string, 'invalid')
+
def test_equality(self):
r1 = Rational(2, 1)
r2 = Rational(2, 1)