From ca2b69f765dd8a7f5c8e5c5346572519a8768ec4 Mon Sep 17 00:00:00 2001 From: Jeffrey Yasskin Date: Fri, 1 Feb 2008 06:22:46 +0000 Subject: Move __builtins__.trunc() to math.trunc() per http://mail.python.org/pipermail/python-dev/2008-January/076626.html and issue 1965. --- Doc/library/functions.rst | 8 -------- Doc/library/math.rst | 8 ++++++++ Lib/test/test_abstract_numbers.py | 13 +++++++------ Lib/test/test_builtin.py | 32 -------------------------------- Lib/test/test_decimal.py | 5 +++-- Lib/test/test_math.py | 31 +++++++++++++++++++++++++++++++ Lib/test/test_rational.py | 12 ++++++------ Modules/mathmodule.c | 16 ++++++++++++++++ Python/bltinmodule.c | 15 --------------- 9 files changed, 71 insertions(+), 69 deletions(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 44eb5d8..5b54622 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -1145,14 +1145,6 @@ available. They are listed here in alphabetical order. .. versionadded:: 2.2 -.. function:: trunc(x) - - Return the :class:`Real` value *x* truncated to an :class:`Integral` (usually - a long integer). Delegates to ``x.__trunc__()``. - - .. versionadded:: 2.6 - - .. function:: tuple([iterable]) Return a tuple whose items are the same and in the same order as *iterable*'s diff --git a/Doc/library/math.rst b/Doc/library/math.rst index b111dd1..47ebadb 100644 --- a/Doc/library/math.rst +++ b/Doc/library/math.rst @@ -103,6 +103,14 @@ Number-theoretic and representation functions: Return the fractional and integer parts of *x*. Both results carry the sign of *x*, and both are floats. + +.. function:: trunc(x) + + Return the :class:`Real` value *x* truncated to an :class:`Integral` (usually + a long integer). Delegates to ``x.__trunc__()``. + + .. versionadded:: 2.6 + Note that :func:`frexp` and :func:`modf` have a different call/return pattern than their C equivalents: they take a single argument and return a pair of values, rather than returning their second return value through an 'output diff --git a/Lib/test/test_abstract_numbers.py b/Lib/test/test_abstract_numbers.py index 19bfc79..0c1f28d 100644 --- a/Lib/test/test_abstract_numbers.py +++ b/Lib/test/test_abstract_numbers.py @@ -1,11 +1,12 @@ """Unit tests for numbers.py.""" +import math +import operator import unittest -from test import test_support -from numbers import Number -from numbers import Exact, Inexact from numbers import Complex, Real, Rational, Integral -import operator +from numbers import Exact, Inexact +from numbers import Number +from test import test_support class TestNumbers(unittest.TestCase): def test_int(self): @@ -49,8 +50,8 @@ class TestNumbers(unittest.TestCase): self.failUnless(issubclass(complex, Inexact)) c1, c2 = complex(3, 2), complex(4,1) - # XXX: This is not ideal, but see the comment in builtin_trunc(). - self.assertRaises(AttributeError, trunc, c1) + # XXX: This is not ideal, but see the comment in math_trunc(). + self.assertRaises(AttributeError, math.trunc, c1) self.assertRaises(TypeError, float, c1) self.assertRaises(TypeError, int, c1) diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index a1e2a12..59a9dcd 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -1766,38 +1766,6 @@ class BuiltinTest(unittest.TestCase): raise ValueError self.assertRaises(ValueError, sum, BadSeq()) - def test_trunc(self): - - self.assertEqual(trunc(1), 1) - self.assertEqual(trunc(-1), -1) - self.assertEqual(type(trunc(1)), int) - self.assertEqual(type(trunc(1.5)), int) - self.assertEqual(trunc(1.5), 1) - self.assertEqual(trunc(-1.5), -1) - self.assertEqual(trunc(1.999999), 1) - self.assertEqual(trunc(-1.999999), -1) - self.assertEqual(trunc(-0.999999), -0) - self.assertEqual(trunc(-100.999), -100) - - class TestTrunc(object): - def __trunc__(self): - return 23 - - class TestNoTrunc(object): - pass - - self.assertEqual(trunc(TestTrunc()), 23) - - self.assertRaises(TypeError, trunc) - self.assertRaises(TypeError, trunc, 1, 2) - # XXX: This is not ideal, but see the comment in builtin_trunc(). - self.assertRaises(AttributeError, trunc, TestNoTrunc()) - - t = TestNoTrunc() - t.__trunc__ = lambda *args: args - self.assertEquals((), trunc(t)) - self.assertRaises(TypeError, trunc, t, 0) - def test_tuple(self): self.assertEqual(tuple(()), ()) t0_3 = (0, 1, 2, 3) diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py index 0ea4a36..0c8852c 100644 --- a/Lib/test/test_decimal.py +++ b/Lib/test/test_decimal.py @@ -25,10 +25,11 @@ with the corresponding argument. """ from __future__ import with_statement -import unittest import glob +import math import os, sys import pickle, copy +import unittest from decimal import * from test.test_support import (TestSkipped, run_unittest, run_doctest, is_resource_enabled) @@ -1225,7 +1226,7 @@ class DecimalPythonAPItests(unittest.TestCase): # should work the same as to_integral in the ROUND_DOWN mode d = Decimal(s) r = d.to_integral(ROUND_DOWN) - self.assertEqual(Decimal(trunc(d)), r) + self.assertEqual(Decimal(math.trunc(d)), r) class ContextAPItests(unittest.TestCase): diff --git a/Lib/test/test_math.py b/Lib/test/test_math.py index 16f0f4d..e0e72f5 100644 --- a/Lib/test/test_math.py +++ b/Lib/test/test_math.py @@ -237,6 +237,37 @@ class MathTests(unittest.TestCase): self.ftest('tanh(0)', math.tanh(0), 0) self.ftest('tanh(1)+tanh(-1)', math.tanh(1)+math.tanh(-1), 0) + def test_trunc(self): + self.assertEqual(math.trunc(1), 1) + self.assertEqual(math.trunc(-1), -1) + self.assertEqual(type(math.trunc(1)), int) + self.assertEqual(type(math.trunc(1.5)), int) + self.assertEqual(math.trunc(1.5), 1) + self.assertEqual(math.trunc(-1.5), -1) + self.assertEqual(math.trunc(1.999999), 1) + self.assertEqual(math.trunc(-1.999999), -1) + self.assertEqual(math.trunc(-0.999999), -0) + self.assertEqual(math.trunc(-100.999), -100) + + class TestTrunc(object): + def __trunc__(self): + return 23 + + class TestNoTrunc(object): + pass + + self.assertEqual(math.trunc(TestTrunc()), 23) + + self.assertRaises(TypeError, math.trunc) + self.assertRaises(TypeError, math.trunc, 1, 2) + # XXX: This is not ideal, but see the comment in math_trunc(). + self.assertRaises(AttributeError, math.trunc, TestNoTrunc()) + + t = TestNoTrunc() + t.__trunc__ = lambda *args: args + self.assertEquals((), math.trunc(t)) + self.assertRaises(TypeError, math.trunc, t, 0) + def testCopysign(self): self.assertEqual(math.copysign(1, 42), 1.0) self.assertEqual(math.copysign(0., 42), 0.0) diff --git a/Lib/test/test_rational.py b/Lib/test/test_rational.py index b97922c..3c3d1f9 100644 --- a/Lib/test/test_rational.py +++ b/Lib/test/test_rational.py @@ -195,7 +195,7 @@ class RationalTest(unittest.TestCase): self.assertEqual(R.from_float(0.0).approximate(10000), R(0)) def testConversions(self): - self.assertTypedEquals(-1, trunc(R(-11, 10))) + self.assertTypedEquals(-1, math.trunc(R(-11, 10))) self.assertTypedEquals(-1, int(R(-11, 10))) self.assertEquals(False, bool(R(0, 1))) @@ -322,11 +322,11 @@ class RationalTest(unittest.TestCase): # Because 10**23 can't be represented exactly as a float: self.assertFalse(R(10**23) == float(10**23)) # The first test demonstrates why these are important. - self.assertFalse(1e23 < float(R(trunc(1e23) + 1))) - self.assertTrue(1e23 < R(trunc(1e23) + 1)) - self.assertFalse(1e23 <= R(trunc(1e23) - 1)) - self.assertTrue(1e23 > R(trunc(1e23) - 1)) - self.assertFalse(1e23 >= R(trunc(1e23) + 1)) + self.assertFalse(1e23 < float(R(math.trunc(1e23) + 1))) + self.assertTrue(1e23 < R(math.trunc(1e23) + 1)) + self.assertFalse(1e23 <= R(math.trunc(1e23) - 1)) + self.assertTrue(1e23 > R(math.trunc(1e23) - 1)) + self.assertFalse(1e23 >= R(math.trunc(1e23) + 1)) def testBigComplexComparisons(self): self.assertFalse(R(10**23) == complex(10**23)) diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index 6469bde..cdc3057 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -155,6 +155,21 @@ FUNC1(tanh, tanh, "tanh(x)\n\nReturn the hyperbolic tangent of x.") static PyObject * +math_trunc(PyObject *self, PyObject *number) +{ + /* XXX: The py3k branch gets better errors for this by using + _PyType_Lookup(), but since float's mro isn't set in py2.6, + we just use PyObject_CallMethod here. */ + return PyObject_CallMethod(number, "__trunc__", NULL); +} + +PyDoc_STRVAR(math_trunc_doc, +"trunc(x:Real) -> Integral\n" +"\n" +"Truncates x to the nearest Integral toward 0. Uses the __trunc__ magic" +"method."); + +static PyObject * math_frexp(PyObject *self, PyObject *arg) { int i; @@ -377,6 +392,7 @@ static PyMethodDef math_methods[] = { {"sqrt", math_sqrt, METH_O, math_sqrt_doc}, {"tan", math_tan, METH_O, math_tan_doc}, {"tanh", math_tanh, METH_O, math_tanh_doc}, + {"trunc", math_trunc, METH_O, math_trunc_doc}, {NULL, NULL} /* sentinel */ }; diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index cd74758..fe691fc 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -2044,20 +2044,6 @@ PyDoc_STRVAR(vars_doc, Without arguments, equivalent to locals().\n\ With an argument, equivalent to object.__dict__."); -static PyObject * -builtin_trunc(PyObject *self, PyObject *number) -{ - /* XXX: The py3k branch gets better errors for this by using - _PyType_Lookup(), but since float's mro isn't set in py2.6, - we just use PyObject_CallMethod here. */ - return PyObject_CallMethod(number, "__trunc__", NULL); -} - -PyDoc_STRVAR(trunc_doc, -"trunc(Real) -> Integral\n\ -\n\ -returns the integral closest to x between 0 and x."); - static PyObject* builtin_sum(PyObject *self, PyObject *args) @@ -2406,7 +2392,6 @@ static PyMethodDef builtin_methods[] = { {"unichr", builtin_unichr, METH_VARARGS, unichr_doc}, #endif {"vars", builtin_vars, METH_VARARGS, vars_doc}, - {"trunc", builtin_trunc, METH_O, trunc_doc}, {"zip", builtin_zip, METH_VARARGS, zip_doc}, {NULL, NULL}, }; -- cgit v0.12