summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Demo/classes/README1
-rw-r--r--Doc/README.txt4
-rw-r--r--Doc/conf.py22
-rw-r--r--Doc/extending/windows.rst2
-rw-r--r--Doc/library/decimal.rst22
-rw-r--r--Doc/library/fractions.rst (renamed from Doc/library/rational.rst)38
-rw-r--r--Doc/library/numbers.rst10
-rw-r--r--Doc/library/pickletools.rst7
-rw-r--r--Doc/whatsnew/2.6.rst22
-rw-r--r--Lib/decimal.py2
-rwxr-xr-xLib/fractions.py (renamed from Lib/rational.py)113
-rw-r--r--Lib/pickletools.py31
-rw-r--r--Lib/test/test_builtin.py4
-rw-r--r--Lib/test/test_fractions.py (renamed from Lib/test/test_rational.py)56
-rw-r--r--Modules/_collectionsmodule.c2
15 files changed, 190 insertions, 146 deletions
diff --git a/Demo/classes/README b/Demo/classes/README
index 1d41f6af33..e5bc2893ec 100644
--- a/Demo/classes/README
+++ b/Demo/classes/README
@@ -4,7 +4,6 @@ Complex.py Complex numbers
Dates.py Date manipulation package by Tim Peters
Dbm.py Wrapper around built-in dbm, supporting arbitrary values
Range.py Example of a generator: re-implement built-in range()
-Rat.py Rational numbers
Rev.py Yield the reverse of a sequence
Vec.py A simple vector class
bitvec.py A bit-vector class by Jan-Hein B\"uhrman
diff --git a/Doc/README.txt b/Doc/README.txt
index a93542fed5..202a1ce305 100644
--- a/Doc/README.txt
+++ b/Doc/README.txt
@@ -14,7 +14,7 @@ those familiar with the previous docs written in LaTeX.
Building the docs
=================
-You need to install Python 2.5.1 or higher (but Python 3.0 is not supported yet);
+You need to install Python 2.4 or higher (but Python 3.0 is not supported yet);
the toolset used to build the docs are written in Python. The toolset used
to build the documentation is called *Sphinx*, it is not included in this
tree, but maintained separately in the Python Subversion repository. Also
@@ -55,7 +55,7 @@ Available make targets are:
* "latex", which builds LaTeX source files that can be run with "pdflatex"
to produce PDF documents.
-
+
* "linkcheck", which checks all external references to see whether they are
broken, redirected or malformed, and outputs this information to stdout
as well as a plain-text (.txt) file.
diff --git a/Doc/conf.py b/Doc/conf.py
index 273c76c98e..1c8dd71b49 100644
--- a/Doc/conf.py
+++ b/Doc/conf.py
@@ -38,17 +38,17 @@ today = ''
today_fmt = '%B %d, %Y'
# List of files that shouldn't be included in the build.
-unused_files = [
- 'whatsnew/2.0.rst',
- 'whatsnew/2.1.rst',
- 'whatsnew/2.2.rst',
- 'whatsnew/2.3.rst',
- 'whatsnew/2.4.rst',
- 'whatsnew/2.5.rst',
- 'whatsnew/2.6.rst',
- 'maclib/scrap.rst',
- 'library/xmllib.rst',
- 'library/xml.etree.rst',
+unused_docs = [
+ 'whatsnew/2.0',
+ 'whatsnew/2.1',
+ 'whatsnew/2.2',
+ 'whatsnew/2.3',
+ 'whatsnew/2.4',
+ 'whatsnew/2.5',
+ 'whatsnew/2.6',
+ 'maclib/scrap',
+ 'library/xmllib',
+ 'library/xml.etree',
]
# Relative filename of the reference count data file.
diff --git a/Doc/extending/windows.rst b/Doc/extending/windows.rst
index a34ba2bf99..a0782a7484 100644
--- a/Doc/extending/windows.rst
+++ b/Doc/extending/windows.rst
@@ -179,7 +179,7 @@ and add the following to the module initialization function::
MyObject_Type.ob_type = &PyType_Type;
-Refer to section 3 of the `Python FAQ <http://www.python.org/doc/FAQ.html>`_ for
+Refer to section 3 of the `Python FAQ <http://www.python.org/doc/faq>`_ for
details on why you must do this.
diff --git a/Doc/library/decimal.rst b/Doc/library/decimal.rst
index f6b96b23b8..422436f488 100644
--- a/Doc/library/decimal.rst
+++ b/Doc/library/decimal.rst
@@ -1,6 +1,6 @@
-:mod:`decimal` --- Decimal floating point arithmetic
-====================================================
+:mod:`decimal` --- Decimal fixed point and floating point arithmetic
+====================================================================
.. module:: decimal
:synopsis: Implementation of the General Decimal Arithmetic Specification.
@@ -16,6 +16,11 @@
The :mod:`decimal` module provides support for decimal floating point
arithmetic. It offers several advantages over the :class:`float` datatype:
+* Decimal "is based on a floating-point model which was designed with people
+ in mind, and necessarily has a paramount guiding principle -- computers must
+ provide an arithmetic that works in the same way as the arithmetic that
+ people learn at school." -- excerpt from the decimal arithmetic specification.
+
* Decimal numbers can be represented exactly. In contrast, numbers like
:const:`1.1` do not have an exact representation in binary floating point. End
users typically would not expect :const:`1.1` to display as
@@ -25,7 +30,7 @@ arithmetic. It offers several advantages over the :class:`float` datatype:
+ 0.1 + 0.1 - 0.3`` is exactly equal to zero. In binary floating point, the result
is :const:`5.5511151231257827e-017`. While near to zero, the differences
prevent reliable equality testing and differences can accumulate. For this
- reason, decimal would be preferred in accounting applications which have strict
+ reason, decimal is preferred in accounting applications which have strict
equality invariants.
* The decimal module incorporates a notion of significant places so that ``1.30
@@ -50,6 +55,13 @@ arithmetic. It offers several advantages over the :class:`float` datatype:
standards. While the built-in float type exposes only a modest portion of its
capabilities, the decimal module exposes all required parts of the standard.
When needed, the programmer has full control over rounding and signal handling.
+ This includes an option to enforce exact arithmetic by using exceptions
+ to block any inexact operations.
+
+* The decimal module was designed to support "without prejudice, both exact
+ unrounded decimal arithmetic (sometimes called fixed-point arithmetic)
+ and rounded floating-point arithmetic." -- excerpt from the decimal
+ arithmetic specification.
The module design is centered around three concepts: the decimal number, the
context for arithmetic, and signals.
@@ -832,7 +844,7 @@ described below. In addition, the module provides three pre-made contexts:
:const:`ROUND_HALF_EVEN`. All flags are cleared. No traps are enabled (so that
exceptions are not raised during computations).
- Because the trapped are disabled, this context is useful for applications that
+ Because the traps are disabled, this context is useful for applications that
prefer to have result value of :const:`NaN` or :const:`Infinity` instead of
raising exceptions. This allows an application to complete a run in the
presence of conditions that would otherwise halt the program.
@@ -1245,7 +1257,7 @@ quiet or signaling :const:`NaN` always returns :const:`False` (even when doing
:const:`True`. An attempt to compare two Decimals using any of the ``<``,
``<=``, ``>`` or ``>=`` operators will raise the :exc:`InvalidOperation` signal
if either operand is a :const:`NaN`, and return :const:`False` if this signal is
-trapped. Note that the General Decimal Arithmetic specification does not
+not trapped. Note that the General Decimal Arithmetic specification does not
specify the behavior of direct comparisons; these rules for comparisons
involving a :const:`NaN` were taken from the IEEE 854 standard (see Table 3 in
section 5.7). To ensure strict standards-compliance, use the :meth:`compare`
diff --git a/Doc/library/rational.rst b/Doc/library/fractions.rst
index 8ed702f5f8..5f30caf138 100644
--- a/Doc/library/rational.rst
+++ b/Doc/library/fractions.rst
@@ -1,28 +1,28 @@
-:mod:`rational` --- Rational numbers
+:mod:`fractions` --- Rational numbers
====================================
-.. module:: rational
+.. module:: fractions
:synopsis: Rational numbers.
.. moduleauthor:: Jeffrey Yasskin <jyasskin at gmail.com>
.. sectionauthor:: Jeffrey Yasskin <jyasskin at gmail.com>
.. versionadded:: 2.6
-The :mod:`rational` module defines an immutable, infinite-precision
+The :mod:`fractions` module defines an immutable, infinite-precision
Rational number class.
-.. class:: Rational(numerator=0, denominator=1)
- Rational(other_rational)
- Rational(string)
+.. class:: Fraction(numerator=0, denominator=1)
+ Fraction(other_fraction)
+ Fraction(string)
The first version requires that *numerator* and *denominator* are
instances of :class:`numbers.Integral` and returns a new
- ``Rational`` representing ``numerator/denominator``. If
+ ``Fraction`` representing ``numerator/denominator``. If
*denominator* is :const:`0`, raises a :exc:`ZeroDivisionError`. The
- second version requires that *other_rational* is an instance of
- :class:`numbers.Rational` and returns an instance of
+ second version requires that *other_fraction* is an instance of
+ :class:`numbers.Fraction` and returns an instance of
:class:`Rational` with the same value. The third version expects a
string of the form ``[-+]?[0-9]+(/[0-9]+)?``, optionally surrounded
by spaces.
@@ -31,39 +31,39 @@ Rational number class.
:class:`numbers.Rational` and is immutable and hashable.
-.. method:: Rational.from_float(flt)
+.. method:: Fraction.from_float(flt)
- This classmethod constructs a :class:`Rational` representing the
+ This classmethod constructs a :class:`Fraction` representing the
exact value of *flt*, which must be a :class:`float`. Beware that
- ``Rational.from_float(0.3)`` is not the same value as ``Rational(3,
+ ``Fraction.from_float(0.3)`` is not the same value as ``Rational(3,
10)``
-.. method:: Rational.from_decimal(dec)
+.. method:: Fraction.from_decimal(dec)
- This classmethod constructs a :class:`Rational` representing the
+ This classmethod constructs a :class:`Fraction` representing the
exact value of *dec*, which must be a
:class:`decimal.Decimal`.
-.. method:: Rational.__floor__()
+.. method:: Fraction.__floor__()
Returns the greatest :class:`int` ``<= self``. Will be accessible
through :func:`math.floor` in Py3k.
-.. method:: Rational.__ceil__()
+.. method:: Fraction.__ceil__()
Returns the least :class:`int` ``>= self``. Will be accessible
through :func:`math.ceil` in Py3k.
-.. method:: Rational.__round__()
- Rational.__round__(ndigits)
+.. method:: Fraction.__round__()
+ Fraction.__round__(ndigits)
The first version returns the nearest :class:`int` to ``self``,
rounding half to even. The second version rounds ``self`` to the
- nearest multiple of ``Rational(1, 10**ndigits)`` (logically, if
+ nearest multiple of ``Fraction(1, 10**ndigits)`` (logically, if
``ndigits`` is negative), again rounding half toward even. Will be
accessible through :func:`round` in Py3k.
diff --git a/Doc/library/numbers.rst b/Doc/library/numbers.rst
index 1d543c8b4b..d78595e76d 100644
--- a/Doc/library/numbers.rst
+++ b/Doc/library/numbers.rst
@@ -104,7 +104,7 @@ Notes for type implementors
Implementors should be careful to make equal numbers equal and hash
them to the same values. This may be subtle if there are two different
-extensions of the real numbers. For example, :class:`rational.Rational`
+extensions of the real numbers. For example, :class:`fractions.Fraction`
implements :func:`hash` as follows::
def __hash__(self):
@@ -199,11 +199,11 @@ in :class:`complex`, and both :meth:`__radd__` s land there, so ``a+b
Because most of the operations on any given type will be very similar,
it can be useful to define a helper function which generates the
forward and reverse instances of any given operator. For example,
-:class:`rational.Rational` uses::
+:class:`fractions.Fraction` uses::
def _operator_fallbacks(monomorphic_operator, fallback_operator):
def forward(a, b):
- if isinstance(b, (int, long, Rational)):
+ if isinstance(b, (int, long, Fraction)):
return monomorphic_operator(a, b)
elif isinstance(b, float):
return fallback_operator(float(a), b)
@@ -215,7 +215,7 @@ forward and reverse instances of any given operator. For example,
forward.__doc__ = monomorphic_operator.__doc__
def reverse(b, a):
- if isinstance(a, RationalAbc):
+ if isinstance(a, Rational):
# Includes ints.
return monomorphic_operator(a, b)
elif isinstance(a, numbers.Real):
@@ -231,7 +231,7 @@ forward and reverse instances of any given operator. For example,
def _add(a, b):
"""a + b"""
- return Rational(a.numerator * b.denominator +
+ return Fraction(a.numerator * b.denominator +
b.numerator * a.denominator,
a.denominator * b.denominator)
diff --git a/Doc/library/pickletools.rst b/Doc/library/pickletools.rst
index 3fc38ff237..3dc06acd41 100644
--- a/Doc/library/pickletools.rst
+++ b/Doc/library/pickletools.rst
@@ -33,3 +33,10 @@ probably won't find the :mod:`pickletools` module relevant.
the opcode's argument; *pos* is the position at which this opcode is located.
*pickle* can be a string or a file-like object.
+.. function:: optimize(picklestring)
+
+ Returns a new equivalent pickle string after eliminating unused ``PUT``
+ opcodes. The optimized pickle is shorter, takes less transmission time,
+ requires less storage space, and unpickles more efficiently.
+
+ .. versionadded:: 2.6
diff --git a/Doc/whatsnew/2.6.rst b/Doc/whatsnew/2.6.rst
index cbc8b8fdac..d37c5ac304 100644
--- a/Doc/whatsnew/2.6.rst
+++ b/Doc/whatsnew/2.6.rst
@@ -578,8 +578,8 @@ and comparisons.
:class:`Rational` numbers derive from :class:`Real`, have
:attr:`numerator` and :attr:`denominator` properties, and can be
-converted to floats. Python 2.6 adds a simple rational-number class
-in the :mod:`rational` module.
+converted to floats. Python 2.6 adds a simple rational-number class,
+:class:`Fraction`, in the :mod:`fractions` module.
:class:`Integral` numbers derive from :class:`Rational`, and
can be shifted left and right with ``<<`` and ``>>``,
@@ -598,29 +598,29 @@ one, :func:`trunc`, that's been backported to Python 2.6.
-The Rational Module
+The Fraction Module
--------------------------------------------------
To fill out the hierarchy of numeric types, a rational-number class
-has been added as the :mod:`rational` module. Rational numbers are
+has been added as the :mod:`fractions` module. Rational numbers are
represented as a fraction; rational numbers can exactly represent
numbers such as two-thirds that floating-point numbers can only
approximate.
-The :class:`Rational` constructor takes two :class:`Integral` values
+The :class:`Fraction` constructor takes two :class:`Integral` values
that will be the numerator and denominator of the resulting fraction. ::
- >>> from rational import Rational
- >>> a = Rational(2, 3)
- >>> b = Rational(2, 5)
+ >>> from fractions import Fraction
+ >>> a = Fraction(2, 3)
+ >>> b = Fraction(2, 5)
>>> float(a), float(b)
(0.66666666666666663, 0.40000000000000002)
>>> a+b
- rational.Rational(16,15)
+ Fraction(16, 15)
>>> a/b
- rational.Rational(5,3)
+ Fraction(5, 3)
-The :mod:`rational` module is based upon an implementation by Sjoerd
+The :mod:`fractions` module is based upon an implementation by Sjoerd
Mullender that was in Python's :file:`Demo/classes/` directory for a
long time. This implementation was significantly updated by Jeffrey
Yaskin.
diff --git a/Lib/decimal.py b/Lib/decimal.py
index 55faf993be..873f7c069e 100644
--- a/Lib/decimal.py
+++ b/Lib/decimal.py
@@ -802,7 +802,7 @@ class Decimal(_numbers.Real, _numbers.Inexact):
# != comparisons involving a NaN always return True
# <, >, <= and >= comparisons involving a (quiet or signaling)
# NaN signal InvalidOperation, and return False if the
- # InvalidOperation is trapped.
+ # InvalidOperation is not trapped.
#
# This behavior is designed to conform as closely as possible to
# that specified by IEEE 754.
diff --git a/Lib/rational.py b/Lib/fractions.py
index 6002964a88..25b9f020bf 100755
--- a/Lib/rational.py
+++ b/Lib/fractions.py
@@ -1,16 +1,15 @@
# Originally contributed by Sjoerd Mullender.
# Significantly modified by Jeffrey Yasskin <jyasskin at gmail.com>.
-"""Rational, infinite-precision, real numbers."""
+"""Fraction, infinite-precision, real numbers."""
import math
import numbers
import operator
import re
-__all__ = ["Rational"]
+__all__ = ["Fraction"]
-RationalAbc = numbers.Rational
def gcd(a, b):
@@ -38,15 +37,15 @@ _RATIONAL_FORMAT = re.compile(r"""
""", re.VERBOSE)
-class Rational(RationalAbc):
+class Fraction(numbers.Rational):
"""This class implements rational numbers.
- Rational(8, 6) will produce a rational number equivalent to
+ Fraction(8, 6) will produce a rational number equivalent to
4/3. Both arguments must be Integral. The numerator defaults to 0
- and the denominator defaults to 1 so that Rational(3) == 3 and
- Rational() == 0.
+ and the denominator defaults to 1 so that Fraction(3) == 3 and
+ Fraction() == 0.
- Rationals can also be constructed from strings of the form
+ Fraction can also be constructed from strings of the form
'[-+]?[0-9]+((/|.)[0-9]+)?', optionally surrounded by spaces.
"""
@@ -61,7 +60,7 @@ class Rational(RationalAbc):
numerator/denominator pair.
"""
- self = super(Rational, cls).__new__(cls)
+ self = super(Fraction, cls).__new__(cls)
if denominator == 1:
if isinstance(numerator, str):
@@ -69,7 +68,7 @@ class Rational(RationalAbc):
input = numerator
m = _RATIONAL_FORMAT.match(input)
if m is None:
- raise ValueError('Invalid literal for Rational: ' + input)
+ raise ValueError('Invalid literal for Fraction: ' + input)
numerator = m.group('num')
decimal = m.group('decimal')
if decimal:
@@ -86,7 +85,7 @@ class Rational(RationalAbc):
numerator = -numerator
elif (not isinstance(numerator, numbers.Integral) and
- isinstance(numerator, RationalAbc)):
+ isinstance(numerator, numbers.Rational)):
# Handle copies from other rationals.
other_rational = numerator
numerator = other_rational.numerator
@@ -94,11 +93,11 @@ class Rational(RationalAbc):
if (not isinstance(numerator, numbers.Integral) or
not isinstance(denominator, numbers.Integral)):
- raise TypeError("Rational(%(numerator)s, %(denominator)s):"
+ raise TypeError("Fraction(%(numerator)s, %(denominator)s):"
" Both arguments must be integral." % locals())
if denominator == 0:
- raise ZeroDivisionError('Rational(%s, 0)' % numerator)
+ raise ZeroDivisionError('Fraction(%s, 0)' % numerator)
g = gcd(numerator, denominator)
self._numerator = int(numerator // g)
@@ -109,7 +108,7 @@ class Rational(RationalAbc):
def from_float(cls, f):
"""Converts a finite float to a rational number, exactly.
- Beware that Rational.from_float(0.3) != Rational(3, 10).
+ Beware that Fraction.from_float(0.3) != Fraction(3, 10).
"""
if not isinstance(f, float):
@@ -141,7 +140,7 @@ class Rational(RationalAbc):
@classmethod
def from_continued_fraction(cls, seq):
- 'Build a Rational from a continued fraction expessed as a sequence'
+ 'Build a Fraction from a continued fraction expessed as a sequence'
n, d = 1, 0
for e in reversed(seq):
n, d = d, n
@@ -168,7 +167,7 @@ class Rational(RationalAbc):
if self.denominator <= max_denominator:
return self
cf = self.as_continued_fraction()
- result = Rational(0)
+ result = Fraction(0)
for i in range(1, len(cf)):
new = self.from_continued_fraction(cf[:i])
if new.denominator > max_denominator:
@@ -186,7 +185,7 @@ class Rational(RationalAbc):
def __repr__(self):
"""repr(self)"""
- return ('Rational(%r,%r)' % (self.numerator, self.denominator))
+ return ('Fraction(%r,%r)' % (self.numerator, self.denominator))
def __str__(self):
"""str(self)"""
@@ -206,13 +205,13 @@ class Rational(RationalAbc):
that mixed-mode operations either call an implementation whose
author knew about the types of both arguments, or convert both
to the nearest built in type and do the operation there. In
- Rational, that means that we define __add__ and __radd__ as:
+ Fraction, that means that we define __add__ and __radd__ as:
def __add__(self, other):
# Both types have numerators/denominator attributes,
# so do the operation directly
- if isinstance(other, (int, Rational)):
- return Rational(self.numerator * other.denominator +
+ if isinstance(other, (int, Fraction)):
+ return Fraction(self.numerator * other.denominator +
other.numerator * self.denominator,
self.denominator * other.denominator)
# float and complex don't have those operations, but we
@@ -227,8 +226,8 @@ class Rational(RationalAbc):
def __radd__(self, other):
# radd handles more types than add because there's
# nothing left to fall back to.
- if isinstance(other, RationalAbc):
- return Rational(self.numerator * other.denominator +
+ if isinstance(other, numbers.Rational):
+ return Fraction(self.numerator * other.denominator +
other.numerator * self.denominator,
self.denominator * other.denominator)
elif isinstance(other, Real):
@@ -239,32 +238,32 @@ class Rational(RationalAbc):
There are 5 different cases for a mixed-type addition on
- Rational. I'll refer to all of the above code that doesn't
- refer to Rational, float, or complex as "boilerplate". 'r'
- will be an instance of Rational, which is a subtype of
- RationalAbc (r : Rational <: RationalAbc), and b : B <:
+ Fraction. I'll refer to all of the above code that doesn't
+ refer to Fraction, float, or complex as "boilerplate". 'r'
+ will be an instance of Fraction, which is a subtype of
+ Rational (r : Fraction <: Rational), and b : B <:
Complex. The first three involve 'r + b':
- 1. If B <: Rational, int, float, or complex, we handle
+ 1. If B <: Fraction, int, float, or complex, we handle
that specially, and all is well.
- 2. If Rational falls back to the boilerplate code, and it
+ 2. If Fraction falls back to the boilerplate code, and it
were to return a value from __add__, we'd miss the
possibility that B defines a more intelligent __radd__,
so the boilerplate should return NotImplemented from
- __add__. In particular, we don't handle RationalAbc
+ __add__. In particular, we don't handle Rational
here, even though we could get an exact answer, in case
the other type wants to do something special.
- 3. If B <: Rational, Python tries B.__radd__ before
- Rational.__add__. This is ok, because it was
- implemented with knowledge of Rational, so it can
+ 3. If B <: Fraction, Python tries B.__radd__ before
+ Fraction.__add__. This is ok, because it was
+ implemented with knowledge of Fraction, so it can
handle those instances before delegating to Real or
Complex.
The next two situations describe 'b + r'. We assume that b
- didn't know about Rational in its implementation, and that it
+ didn't know about Fraction in its implementation, and that it
uses similar boilerplate code:
- 4. If B <: RationalAbc, then __radd_ converts both to the
+ 4. If B <: Rational, then __radd_ converts both to the
builtin rational type (hey look, that's us) and
proceeds.
5. Otherwise, __radd__ tries to find the nearest common
@@ -276,7 +275,7 @@ class Rational(RationalAbc):
"""
def forward(a, b):
- if isinstance(b, (int, Rational)):
+ if isinstance(b, (int, Fraction)):
return monomorphic_operator(a, b)
elif isinstance(b, float):
return fallback_operator(float(a), b)
@@ -288,7 +287,7 @@ class Rational(RationalAbc):
forward.__doc__ = monomorphic_operator.__doc__
def reverse(b, a):
- if isinstance(a, RationalAbc):
+ if isinstance(a, numbers.Rational):
# Includes ints.
return monomorphic_operator(a, b)
elif isinstance(a, numbers.Real):
@@ -304,7 +303,7 @@ class Rational(RationalAbc):
def _add(a, b):
"""a + b"""
- return Rational(a.numerator * b.denominator +
+ return Fraction(a.numerator * b.denominator +
b.numerator * a.denominator,
a.denominator * b.denominator)
@@ -312,7 +311,7 @@ class Rational(RationalAbc):
def _sub(a, b):
"""a - b"""
- return Rational(a.numerator * b.denominator -
+ return Fraction(a.numerator * b.denominator -
b.numerator * a.denominator,
a.denominator * b.denominator)
@@ -320,13 +319,13 @@ class Rational(RationalAbc):
def _mul(a, b):
"""a * b"""
- return Rational(a.numerator * b.numerator, a.denominator * b.denominator)
+ return Fraction(a.numerator * b.numerator, a.denominator * b.denominator)
__mul__, __rmul__ = _operator_fallbacks(_mul, operator.mul)
def _div(a, b):
"""a / b"""
- return Rational(a.numerator * b.denominator,
+ return Fraction(a.numerator * b.denominator,
a.denominator * b.numerator)
__truediv__, __rtruediv__ = _operator_fallbacks(_div, operator.truediv)
@@ -357,14 +356,14 @@ class Rational(RationalAbc):
result will be rational.
"""
- if isinstance(b, RationalAbc):
+ if isinstance(b, numbers.Rational):
if b.denominator == 1:
power = b.numerator
if power >= 0:
- return Rational(a.numerator ** power,
+ return Fraction(a.numerator ** power,
a.denominator ** power)
else:
- return Rational(a.denominator ** -power,
+ return Fraction(a.denominator ** -power,
a.numerator ** -power)
else:
# A fractional power will generally produce an
@@ -379,8 +378,8 @@ class Rational(RationalAbc):
# If a is an int, keep it that way if possible.
return a ** b.numerator
- if isinstance(a, RationalAbc):
- return Rational(a.numerator, a.denominator) ** b
+ if isinstance(a, numbers.Rational):
+ return Fraction(a.numerator, a.denominator) ** b
if b.denominator == 1:
return a ** b.numerator
@@ -388,16 +387,16 @@ class Rational(RationalAbc):
return a ** float(b)
def __pos__(a):
- """+a: Coerces a subclass instance to Rational"""
- return Rational(a.numerator, a.denominator)
+ """+a: Coerces a subclass instance to Fraction"""
+ return Fraction(a.numerator, a.denominator)
def __neg__(a):
"""-a"""
- return Rational(-a.numerator, a.denominator)
+ return Fraction(-a.numerator, a.denominator)
def __abs__(a):
"""abs(a)"""
- return Rational(abs(a.numerator), a.denominator)
+ return Fraction(abs(a.numerator), a.denominator)
def __trunc__(a):
"""trunc(a)"""
@@ -433,12 +432,12 @@ class Rational(RationalAbc):
return floor + 1
shift = 10**abs(ndigits)
# See _operator_fallbacks.forward to check that the results of
- # these operations will always be Rational and therefore have
+ # these operations will always be Fraction and therefore have
# round().
if ndigits > 0:
- return Rational(round(self * shift), shift)
+ return Fraction(round(self * shift), shift)
else:
- return Rational(round(self / shift) * shift)
+ return Fraction(round(self / shift) * shift)
def __hash__(self):
"""hash(self)
@@ -461,7 +460,7 @@ class Rational(RationalAbc):
def __eq__(a, b):
"""a == b"""
- if isinstance(b, RationalAbc):
+ if isinstance(b, numbers.Rational):
return (a.numerator == b.numerator and
a.denominator == b.denominator)
if isinstance(b, numbers.Complex) and b.imag == 0:
@@ -488,7 +487,7 @@ class Rational(RationalAbc):
if isinstance(b, float):
b = a.from_float(b)
try:
- # XXX: If b <: Real but not <: RationalAbc, this is likely
+ # XXX: If b <: Real but not <: Rational, this is likely
# to fall back to a float. If the actual values differ by
# less than MIN_FLOAT, this could falsely call them equal,
# which would make <= inconsistent with ==. Better ways of
@@ -496,7 +495,7 @@ class Rational(RationalAbc):
diff = a - b
except TypeError:
return NotImplemented
- if isinstance(diff, RationalAbc):
+ if isinstance(diff, numbers.Rational):
return op(diff.numerator, 0)
return op(diff, 0)
@@ -526,11 +525,11 @@ class Rational(RationalAbc):
return (self.__class__, (str(self),))
def __copy__(self):
- if type(self) == Rational:
+ if type(self) == Fraction:
return self # I'm immutable; therefore I am my own clone
return self.__class__(self.numerator, self.denominator)
def __deepcopy__(self, memo):
- if type(self) == Rational:
+ if type(self) == Fraction:
return self # My components are also immutable
return self.__class__(self.numerator, self.denominator)
diff --git a/Lib/pickletools.py b/Lib/pickletools.py
index 0665cd0bca..1b6967ae46 100644
--- a/Lib/pickletools.py
+++ b/Lib/pickletools.py
@@ -14,9 +14,7 @@ import codecs
import pickle
import re
-__all__ = ['dis',
- 'genops',
- ]
+__all__ = ['dis', 'genops', 'optimize']
bytes_types = pickle.bytes_types
@@ -1836,6 +1834,33 @@ def genops(pickle):
break
##############################################################################
+# A pickle optimizer.
+
+def optimize(p):
+ 'Optimize a pickle string by removing unused PUT opcodes'
+ gets = set() # set of args used by a GET opcode
+ puts = [] # (arg, startpos, stoppos) for the PUT opcodes
+ prevpos = None # set to pos if previous opcode was a PUT
+ for opcode, arg, pos in genops(p):
+ if prevpos is not None:
+ puts.append((prevarg, prevpos, pos))
+ prevpos = None
+ if 'PUT' in opcode.name:
+ prevarg, prevpos = arg, pos
+ elif 'GET' in opcode.name:
+ gets.add(arg)
+
+ # Copy the pickle string except for PUTS without a corresponding GET
+ s = []
+ i = 0
+ for arg, start, stop in puts:
+ j = stop if (arg in gets) else start
+ s.append(p[i:j])
+ i = stop
+ s.append(p[i:])
+ return ''.join(s)
+
+##############################################################################
# A symbolic pickle disassembler.
def dis(pickle, out=None, memo=None, indentlevel=4):
diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py
index b17133a1ce..f781db3d7d 100644
--- a/Lib/test/test_builtin.py
+++ b/Lib/test/test_builtin.py
@@ -5,7 +5,7 @@ from test.test_support import fcmp, TESTFN, unlink, run_unittest, \
run_with_locale
from operator import neg
-import sys, warnings, random, collections, io, rational
+import sys, warnings, random, collections, io, rational, fractions
warnings.filterwarnings("ignore", "hex../oct.. of negative int",
FutureWarning, __name__)
warnings.filterwarnings("ignore", "integer argument expected",
@@ -607,7 +607,7 @@ class BuiltinTest(unittest.TestCase):
n, d = f.as_integer_ratio()
self.assertEqual(float(n).__truediv__(d), f)
- R = rational.Rational
+ R = fractions.Fraction
self.assertEqual(R(0, 1),
R(*float(0.0).as_integer_ratio()))
self.assertEqual(R(5, 2),
diff --git a/Lib/test/test_rational.py b/Lib/test/test_fractions.py
index 92d8a14aee..00fd549d72 100644
--- a/Lib/test/test_rational.py
+++ b/Lib/test/test_fractions.py
@@ -1,15 +1,15 @@
-"""Tests for Lib/rational.py."""
+"""Tests for Lib/fractions.py."""
from decimal import Decimal
from test.test_support import run_unittest, verbose
import math
import operator
-import rational
+import fractions
import unittest
from copy import copy, deepcopy
from pickle import dumps, loads
-R = rational.Rational
-gcd = rational.gcd
+R = fractions.Fraction
+gcd = fractions.gcd
class GcdTest(unittest.TestCase):
@@ -31,7 +31,7 @@ def _components(r):
return (r.numerator, r.denominator)
-class RationalTest(unittest.TestCase):
+class FractionTest(unittest.TestCase):
def assertTypedEquals(self, expected, actual):
"""Asserts that both the types and values are the same."""
@@ -60,7 +60,7 @@ class RationalTest(unittest.TestCase):
self.assertEquals((7, 15), _components(R(7, 15)))
self.assertEquals((10**23, 1), _components(R(10**23)))
- self.assertRaisesMessage(ZeroDivisionError, "Rational(12, 0)",
+ self.assertRaisesMessage(ZeroDivisionError, "Fraction(12, 0)",
R, 12, 0)
self.assertRaises(TypeError, R, 1.5)
self.assertRaises(TypeError, R, 1.5 + 3j)
@@ -81,41 +81,41 @@ class RationalTest(unittest.TestCase):
self.assertEquals((3, 5), _components(R(" .6 ")))
self.assertRaisesMessage(
- ZeroDivisionError, "Rational(3, 0)",
+ ZeroDivisionError, "Fraction(3, 0)",
R, "3/0")
self.assertRaisesMessage(
- ValueError, "Invalid literal for Rational: 3/",
+ ValueError, "Invalid literal for Fraction: 3/",
R, "3/")
self.assertRaisesMessage(
- ValueError, "Invalid literal for Rational: 3 /2",
+ ValueError, "Invalid literal for Fraction: 3 /2",
R, "3 /2")
self.assertRaisesMessage(
# Denominators don't need a sign.
- ValueError, "Invalid literal for Rational: 3/+2",
+ ValueError, "Invalid literal for Fraction: 3/+2",
R, "3/+2")
self.assertRaisesMessage(
# Imitate float's parsing.
- ValueError, "Invalid literal for Rational: + 3/2",
+ ValueError, "Invalid literal for Fraction: + 3/2",
R, "+ 3/2")
self.assertRaisesMessage(
# Avoid treating '.' as a regex special character.
- ValueError, "Invalid literal for Rational: 3a2",
+ ValueError, "Invalid literal for Fraction: 3a2",
R, "3a2")
self.assertRaisesMessage(
# Only parse ordinary decimals, not scientific form.
- ValueError, "Invalid literal for Rational: 3.2e4",
+ ValueError, "Invalid literal for Fraction: 3.2e4",
R, "3.2e4")
self.assertRaisesMessage(
# Don't accept combinations of decimals and rationals.
- ValueError, "Invalid literal for Rational: 3/7.2",
+ ValueError, "Invalid literal for Fraction: 3/7.2",
R, "3/7.2")
self.assertRaisesMessage(
# Don't accept combinations of decimals and rationals.
- ValueError, "Invalid literal for Rational: 3.2/7",
+ ValueError, "Invalid literal for Fraction: 3.2/7",
R, "3.2/7")
self.assertRaisesMessage(
# Allow 3. and .3, but not .
- ValueError, "Invalid literal for Rational: .",
+ ValueError, "Invalid literal for Fraction: .",
R, ".")
def testImmutable(self):
@@ -136,7 +136,7 @@ class RationalTest(unittest.TestCase):
def testFromFloat(self):
self.assertRaisesMessage(
- TypeError, "Rational.from_float() only takes floats, not 3 (int)",
+ TypeError, "Fraction.from_float() only takes floats, not 3 (int)",
R.from_float, 3)
self.assertEquals((0, 1), _components(R.from_float(-0.0)))
@@ -152,19 +152,19 @@ class RationalTest(unittest.TestCase):
inf = 1e1000
nan = inf - inf
self.assertRaisesMessage(
- TypeError, "Cannot convert inf to Rational.",
+ TypeError, "Cannot convert inf to Fraction.",
R.from_float, inf)
self.assertRaisesMessage(
- TypeError, "Cannot convert -inf to Rational.",
+ TypeError, "Cannot convert -inf to Fraction.",
R.from_float, -inf)
self.assertRaisesMessage(
- TypeError, "Cannot convert nan to Rational.",
+ TypeError, "Cannot convert nan to Fraction.",
R.from_float, nan)
def testFromDecimal(self):
self.assertRaisesMessage(
TypeError,
- "Rational.from_decimal() only takes Decimals, not 3 (int)",
+ "Fraction.from_decimal() only takes Decimals, not 3 (int)",
R.from_decimal, 3)
self.assertEquals(R(0), R.from_decimal(Decimal("-0")))
self.assertEquals(R(5, 10), R.from_decimal(Decimal("0.5")))
@@ -174,16 +174,16 @@ class RationalTest(unittest.TestCase):
R.from_decimal(Decimal("0." + "9" * 30)))
self.assertRaisesMessage(
- TypeError, "Cannot convert Infinity to Rational.",
+ TypeError, "Cannot convert Infinity to Fraction.",
R.from_decimal, Decimal("inf"))
self.assertRaisesMessage(
- TypeError, "Cannot convert -Infinity to Rational.",
+ TypeError, "Cannot convert -Infinity to Fraction.",
R.from_decimal, Decimal("-inf"))
self.assertRaisesMessage(
- TypeError, "Cannot convert NaN to Rational.",
+ TypeError, "Cannot convert NaN to Fraction.",
R.from_decimal, Decimal("nan"))
self.assertRaisesMessage(
- TypeError, "Cannot convert sNaN to Rational.",
+ TypeError, "Cannot convert sNaN to Fraction.",
R.from_decimal, Decimal("snan"))
def testFromContinuedFraction(self):
@@ -316,7 +316,7 @@ class RationalTest(unittest.TestCase):
# Decimal refuses mixed comparisons.
self.assertRaisesMessage(
TypeError,
- "unsupported operand type(s) for +: 'Rational' and 'Decimal'",
+ "unsupported operand type(s) for +: 'Fraction' and 'Decimal'",
operator.add, R(3,11), Decimal('3.1415926'))
self.assertNotEquals(R(5, 2), Decimal('2.5'))
@@ -378,7 +378,7 @@ class RationalTest(unittest.TestCase):
self.assertFalse(R(5, 2) == 2)
def testStringification(self):
- self.assertEquals("Rational(7,3)", repr(R(7, 3)))
+ self.assertEquals("Fraction(7,3)", repr(R(7, 3)))
self.assertEquals("7/3", str(R(7, 3)))
self.assertEquals("7", str(R(7, 1)))
@@ -421,7 +421,7 @@ class RationalTest(unittest.TestCase):
self.assertEqual(id(r), id(deepcopy(r)))
def test_main():
- run_unittest(RationalTest, GcdTest)
+ run_unittest(FractionTest, GcdTest)
if __name__ == '__main__':
test_main()
diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c
index 87d744dbee..74b3ea28ff 100644
--- a/Modules/_collectionsmodule.c
+++ b/Modules/_collectionsmodule.c
@@ -1182,6 +1182,8 @@ defdict_reduce(defdictobject *dd)
static PyMethodDef defdict_methods[] = {
{"__missing__", (PyCFunction)defdict_missing, METH_O,
defdict_missing_doc},
+ {"copy", (PyCFunction)defdict_copy, METH_NOARGS,
+ defdict_copy_doc},
{"__copy__", (PyCFunction)defdict_copy, METH_NOARGS,
defdict_copy_doc},
{"__reduce__", (PyCFunction)defdict_reduce, METH_NOARGS,