[Python-checkins] r71806 - in python/branches/py3k: Doc/library/fractions.rst Lib/fractions.py Lib/test/test_fractions.py Misc/NEWS
mark.dickinson
python-checkins at python.org
Wed Apr 22 19:50:22 CEST 2009
Author: mark.dickinson
Date: Wed Apr 22 19:50:21 2009
New Revision: 71806
Log:
Issue #5812: Make Fraction('1e6') valid. The Fraction constructor now
accepts all strings accepted by the float and Decimal constructors,
with the exception of strings representing NaNs or infinities.
Modified:
python/branches/py3k/Doc/library/fractions.rst
python/branches/py3k/Lib/fractions.py
python/branches/py3k/Lib/test/test_fractions.py
python/branches/py3k/Misc/NEWS
Modified: python/branches/py3k/Doc/library/fractions.rst
==============================================================================
--- python/branches/py3k/Doc/library/fractions.rst (original)
+++ python/branches/py3k/Doc/library/fractions.rst Wed Apr 22 19:50:21 2009
@@ -25,21 +25,18 @@
:exc:`ZeroDivisionError`. The second version requires that
*other_fraction* is an instance of :class:`numbers.Rational` and
returns an :class:`Fraction` instance with the same value. The
- last version of the constructor expects a string
- instance in one of two possible forms. The first form is::
+ last version of the constructor expects a string instance. The
+ usual form for this string is::
[sign] numerator ['/' denominator]
where the optional ``sign`` may be either '+' or '-' and
``numerator`` and ``denominator`` (if present) are strings of
- decimal digits. The second permitted form is that of a number
- containing a decimal point::
-
- [sign] integer '.' [fraction] | [sign] '.' fraction
-
- where ``integer`` and ``fraction`` are strings of digits. In
- either form the input string may also have leading and/or trailing
- whitespace. Here are some examples::
+ decimal digits. In addition, any string that represents a finite
+ value and is accepted by the :class:`float` constructor is also
+ accepted by the :class:`Fraction` constructor. In either form the
+ input string may also have leading and/or trailing whitespace.
+ Here are some examples::
>>> from fractions import Fraction
>>> Fraction(16, -10)
@@ -57,6 +54,8 @@
Fraction(1414213, 1000000)
>>> Fraction('-.125')
Fraction(-1, 8)
+ >>> Fraction('7e-6')
+ Fraction(7, 1000000)
The :class:`Fraction` class inherits from the abstract base class
Modified: python/branches/py3k/Lib/fractions.py
==============================================================================
--- python/branches/py3k/Lib/fractions.py (original)
+++ python/branches/py3k/Lib/fractions.py Wed Apr 22 19:50:21 2009
@@ -28,13 +28,14 @@
(?P<sign>[-+]?) # an optional sign, then
(?=\d|\.\d) # lookahead for digit or .digit
(?P<num>\d*) # numerator (possibly empty)
- (?: # followed by an optional
- /(?P<denom>\d+) # / and denominator
+ (?: # followed by
+ (?:/(?P<denom>\d+))? # an optional denominator
| # or
- \.(?P<decimal>\d*) # decimal point and fractional part
- )?
+ (?:\.(?P<decimal>\d*))? # an optional fractional part
+ (?:E(?P<exp>[-+]?\d+))? # and optional exponent
+ )
\s*\Z # and optional whitespace to finish
-""", re.VERBOSE)
+""", re.VERBOSE | re.IGNORECASE)
class Fraction(numbers.Rational):
@@ -65,22 +66,28 @@
if not isinstance(numerator, int) and denominator == 1:
if isinstance(numerator, str):
# Handle construction from strings.
- input = numerator
- m = _RATIONAL_FORMAT.match(input)
+ m = _RATIONAL_FORMAT.match(numerator)
if m is None:
- raise ValueError('Invalid literal for Fraction: %r' % input)
- numerator = m.group('num')
- decimal = m.group('decimal')
- if decimal:
- # The literal is a decimal number.
- numerator = int(numerator + decimal)
- denominator = 10**len(decimal)
+ raise ValueError('Invalid literal for Fraction: %r' %
+ numerator)
+ numerator = int(m.group('num') or '0')
+ denom = m.group('denom')
+ if denom:
+ denominator = int(denom)
else:
- # The literal is an integer or fraction.
- numerator = int(numerator)
- # Default denominator to 1.
- denominator = int(m.group('denom') or 1)
-
+ denominator = 1
+ decimal = m.group('decimal')
+ if decimal:
+ scale = 10**len(decimal)
+ numerator = numerator * scale + int(decimal)
+ denominator *= scale
+ exp = m.group('exp')
+ if exp:
+ exp = int(exp)
+ if exp >= 0:
+ numerator *= 10**exp
+ else:
+ denominator *= 10**-exp
if m.group('sign') == '-':
numerator = -numerator
Modified: python/branches/py3k/Lib/test/test_fractions.py
==============================================================================
--- python/branches/py3k/Lib/test/test_fractions.py (original)
+++ python/branches/py3k/Lib/test/test_fractions.py Wed Apr 22 19:50:21 2009
@@ -78,6 +78,11 @@
self.assertEquals((-16, 5), _components(F(" -3.2 ")))
self.assertEquals((-3, 1), _components(F(" -3. ")))
self.assertEquals((3, 5), _components(F(" .6 ")))
+ self.assertEquals((1, 3125), _components(F("32.e-5")))
+ self.assertEquals((1000000, 1), _components(F("1E+06")))
+ self.assertEquals((-12300, 1), _components(F("-1.23e4")))
+ self.assertEquals((0, 1), _components(F(" .0e+0\t")))
+ self.assertEquals((0, 1), _components(F("-0.000e0")))
self.assertRaisesMessage(
ZeroDivisionError, "Fraction(3, 0)",
@@ -86,6 +91,9 @@
ValueError, "Invalid literal for Fraction: '3/'",
F, "3/")
self.assertRaisesMessage(
+ ValueError, "Invalid literal for Fraction: '/2'",
+ F, "/2")
+ self.assertRaisesMessage(
ValueError, "Invalid literal for Fraction: '3 /2'",
F, "3 /2")
self.assertRaisesMessage(
@@ -101,10 +109,6 @@
ValueError, "Invalid literal for Fraction: '3a2'",
F, "3a2")
self.assertRaisesMessage(
- # Only parse ordinary decimals, not scientific form.
- ValueError, "Invalid literal for Fraction: '3.2e4'",
- F, "3.2e4")
- self.assertRaisesMessage(
# Don't accept combinations of decimals and rationals.
ValueError, "Invalid literal for Fraction: '3/7.2'",
F, "3/7.2")
Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS (original)
+++ python/branches/py3k/Misc/NEWS Wed Apr 22 19:50:21 2009
@@ -75,6 +75,10 @@
Library
-------
+- Issue #5812: Fraction('1e6') is valid: more generally, any string
+ that's valid for float() is now valid for Fraction(), with the
+ exception of strings representing NaNs and infinities.
+
- Issue #5734: BufferedRWPair was poorly tested and had several glaring
bugs. Patch by Brian Quinlan.
More information about the Python-checkins
mailing list