Skip to content

Commit 400adb0

Browse files
committed
Merged revisions 60475-60479,60481-60488 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r60482 | raymond.hettinger | 2008-01-31 23:07:16 +0100 (Thu, 31 Jan 2008) | 1 line Minor wordsmithing on docstring ........ r60483 | mark.dickinson | 2008-01-31 23:17:37 +0100 (Thu, 31 Jan 2008) | 5 lines Issue #1678380. Fix a bug that identifies 0j and -0j when they appear in the same code unit. The fix is essentially the same as the fix for a previous bug identifying 0. and -0. ........ r60484 | christian.heimes | 2008-02-01 00:08:23 +0100 (Fri, 01 Feb 2008) | 1 line Fixed bug #1983: Return from fork() is pid_t, not int ........ r60486 | jeffrey.yasskin | 2008-02-01 07:22:46 +0100 (Fri, 01 Feb 2008) | 4 lines Move __builtins__.trunc() to math.trunc() per http://mail.python.org/pipermail/python-dev/2008-January/076626.html and issue 1965. ........ r60487 | jeffrey.yasskin | 2008-02-01 08:05:46 +0100 (Fri, 01 Feb 2008) | 3 lines Roll back r60248. It's useful to encourage users not to change Rational instances. ........ r60488 | neal.norwitz | 2008-02-01 08:22:59 +0100 (Fri, 01 Feb 2008) | 1 line Fix refleak ........
1 parent a771209 commit 400adb0

18 files changed

+597
-117
lines changed

Doc/library/functions.rst

-6
Original file line numberDiff line numberDiff line change
@@ -1059,12 +1059,6 @@ available. They are listed here in alphabetical order.
10591059
operators such as ``super(C, self)[name]``.
10601060

10611061

1062-
.. function:: trunc(x)
1063-
1064-
Return the :class:`Real` value *x* truncated to an :class:`Integral` (usually
1065-
a long integer). Delegates to ``x.__trunc__()``.
1066-
1067-
10681062
.. function:: tuple([iterable])
10691063

10701064
Return a tuple whose items are the same and in the same order as *iterable*'s

Doc/library/math.rst

+8
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,14 @@ Number-theoretic and representation functions:
9696
Return the fractional and integer parts of *x*. Both results carry the sign of
9797
*x*, and both are floats.
9898

99+
100+
.. function:: trunc(x)
101+
102+
Return the :class:`Real` value *x* truncated to an :class:`Integral` (usually
103+
a long integer). Delegates to ``x.__trunc__()``.
104+
105+
.. versionadded:: 2.6
106+
99107
Note that :func:`frexp` and :func:`modf` have a different call/return pattern
100108
than their C equivalents: they take a single argument and return a pair of
101109
values, rather than returning their second return value through an 'output

Include/pyport.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@ typedef Py_intptr_t Py_ssize_t;
111111
/* Smallest negative value of type Py_ssize_t. */
112112
#define PY_SSIZE_T_MIN (-PY_SSIZE_T_MAX-1)
113113

114+
#if SIZEOF_PID_T > SIZEOF_LONG
115+
# error "Python doesn't support sizeof(pid_t) > sizeof(long)"
116+
#endif
117+
114118
/* PY_FORMAT_SIZE_T is a platform-specific modifier for use in a printf
115119
* format to convert an argument with the width of a size_t or Py_ssize_t.
116120
* C99 introduced "z" for this purpose, but not all platforms support that;
@@ -550,7 +554,7 @@ extern char * _getpty(int *, int, mode_t, int);
550554
functions, even though they are included in libutil. */
551555
#include <termios.h>
552556
extern int openpty(int *, int *, char *, struct termios *, struct winsize *);
553-
extern int forkpty(int *, char *, struct termios *, struct winsize *);
557+
extern pid_t forkpty(int *, char *, struct termios *, struct winsize *);
554558
#endif /* !defined(HAVE_PTY_H) && !defined(HAVE_LIBUTIL_H) */
555559
#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) */
556560

Lib/rational.py

+18-11
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class Rational(RationalAbc):
4242
4343
"""
4444

45-
__slots__ = ('numerator', 'denominator')
45+
__slots__ = ('_numerator', '_denominator')
4646

4747
# We're immutable, so use __new__ not __init__
4848
def __new__(cls, numerator=0, denominator=1):
@@ -92,8 +92,8 @@ def __new__(cls, numerator=0, denominator=1):
9292
raise ZeroDivisionError('Rational(%s, 0)' % numerator)
9393

9494
g = gcd(numerator, denominator)
95-
self.numerator = int(numerator // g)
96-
self.denominator = int(denominator // g)
95+
self._numerator = int(numerator // g)
96+
self._denominator = int(denominator // g)
9797
return self
9898

9999
@classmethod
@@ -167,6 +167,14 @@ def approximate(self, max_denominator):
167167
result = new
168168
return result
169169

170+
@property
171+
def numerator(a):
172+
return a._numerator
173+
174+
@property
175+
def denominator(a):
176+
return a._denominator
177+
170178
def __repr__(self):
171179
"""repr(self)"""
172180
return ('Rational(%r,%r)' % (self.numerator, self.denominator))
@@ -192,20 +200,20 @@ def _operator_fallbacks(monomorphic_operator, fallback_operator):
192200
Rational, that means that we define __add__ and __radd__ as:
193201
194202
def __add__(self, other):
203+
# Both types have numerators/denominator attributes,
204+
# so do the operation directly
195205
if isinstance(other, (int, Rational)):
196-
# Do the real operation.
197206
return Rational(self.numerator * other.denominator +
198207
other.numerator * self.denominator,
199208
self.denominator * other.denominator)
200-
# float and complex don't follow this protocol, and
201-
# Rational knows about them, so special case them.
209+
# float and complex don't have those operations, but we
210+
# know about those types, so special case them.
202211
elif isinstance(other, float):
203212
return float(self) + other
204213
elif isinstance(other, complex):
205214
return complex(self) + other
206-
else:
207-
# Let the other type take over.
208-
return NotImplemented
215+
# Let the other type take over.
216+
return NotImplemented
209217
210218
def __radd__(self, other):
211219
# radd handles more types than add because there's
@@ -218,8 +226,7 @@ def __radd__(self, other):
218226
return float(other) + float(self)
219227
elif isinstance(other, Complex):
220228
return complex(other) + complex(self)
221-
else:
222-
return NotImplemented
229+
return NotImplemented
223230
224231
225232
There are 5 different cases for a mixed-type addition on

Lib/test/test_abstract_numbers.py

+7-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
"""Unit tests for numbers.py."""
22

3+
import math
4+
import operator
35
import unittest
4-
from test import test_support
5-
from numbers import Number
6-
from numbers import Exact, Inexact
76
from numbers import Complex, Real, Rational, Integral
8-
import operator
7+
from numbers import Exact, Inexact
8+
from numbers import Number
9+
from test import test_support
910

1011
class TestNumbers(unittest.TestCase):
1112
def test_int(self):
@@ -37,7 +38,8 @@ def test_complex(self):
3738
self.failUnless(issubclass(complex, Inexact))
3839

3940
c1, c2 = complex(3, 2), complex(4,1)
40-
self.assertRaises(TypeError, trunc, c1)
41+
# XXX: This is not ideal, but see the comment in math_trunc().
42+
self.assertRaises(TypeError, math.trunc, c1)
4143
self.assertRaises(TypeError, operator.mod, c1, c2)
4244
self.assertRaises(TypeError, divmod, c1, c2)
4345
self.assertRaises(TypeError, operator.floordiv, c1, c2)

Lib/test/test_builtin.py

-31
Original file line numberDiff line numberDiff line change
@@ -1643,37 +1643,6 @@ def __getitem__(self, index):
16431643
raise ValueError
16441644
self.assertRaises(ValueError, sum, BadSeq())
16451645

1646-
def test_trunc(self):
1647-
1648-
self.assertEqual(trunc(1), 1)
1649-
self.assertEqual(trunc(-1), -1)
1650-
self.assertEqual(type(trunc(1)), int)
1651-
self.assertEqual(type(trunc(1.5)), int)
1652-
self.assertEqual(trunc(1.5), 1)
1653-
self.assertEqual(trunc(-1.5), -1)
1654-
self.assertEqual(trunc(1.999999), 1)
1655-
self.assertEqual(trunc(-1.999999), -1)
1656-
self.assertEqual(trunc(-0.999999), -0)
1657-
self.assertEqual(trunc(-100.999), -100)
1658-
1659-
class TestTrunc:
1660-
def __trunc__(self):
1661-
return 23
1662-
1663-
class TestNoTrunc:
1664-
pass
1665-
1666-
self.assertEqual(trunc(TestTrunc()), 23)
1667-
1668-
self.assertRaises(TypeError, trunc)
1669-
self.assertRaises(TypeError, trunc, 1, 2)
1670-
self.assertRaises(TypeError, trunc, TestNoTrunc())
1671-
1672-
t = TestNoTrunc()
1673-
t.__trunc__ = lambda *args: args
1674-
self.assertRaises(TypeError, trunc, t)
1675-
self.assertRaises(TypeError, trunc, t, 0)
1676-
16771646
def test_tuple(self):
16781647
self.assertEqual(tuple(()), ())
16791648
t0_3 = (0, 1, 2, 3)

Lib/test/test_complex.py

+7
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,13 @@ def test_file(self):
338338
except (OSError, IOError):
339339
pass
340340

341+
if float.__getformat__("double").startswith("IEEE"):
342+
def test_plus_minus_0j(self):
343+
# test that -0j and 0j literals are not identified
344+
z1, z2 = 0j, -0j
345+
self.assertEquals(atan2(z1.imag, -1.), atan2(0., -1.))
346+
self.assertEquals(atan2(z2.imag, -1.), atan2(-0., -1.))
347+
341348
def test_main():
342349
test_support.run_unittest(ComplexTest)
343350

Lib/test/test_decimal.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,11 @@
2525
"""
2626
from __future__ import with_statement
2727

28-
import unittest
2928
import glob
29+
import math
3030
import os, sys
3131
import pickle, copy
32+
import unittest
3233
from decimal import *
3334
from test.test_support import (TestSkipped, run_unittest, run_doctest,
3435
is_resource_enabled)
@@ -1213,7 +1214,7 @@ def test_trunc(self):
12131214
# should work the same as to_integral in the ROUND_DOWN mode
12141215
d = Decimal(s)
12151216
r = d.to_integral(ROUND_DOWN)
1216-
self.assertEqual(Decimal(trunc(d)), r)
1217+
self.assertEqual(Decimal(math.trunc(d)), r)
12171218

12181219
class ContextAPItests(unittest.TestCase):
12191220

Lib/test/test_math.py

+32
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,38 @@ def testTanh(self):
233233
self.ftest('tanh(0)', math.tanh(0), 0)
234234
self.ftest('tanh(1)+tanh(-1)', math.tanh(1)+math.tanh(-1), 0)
235235

236+
def test_trunc(self):
237+
self.assertEqual(math.trunc(1), 1)
238+
self.assertEqual(math.trunc(-1), -1)
239+
self.assertEqual(type(math.trunc(1)), int)
240+
self.assertEqual(type(math.trunc(1.5)), int)
241+
self.assertEqual(math.trunc(1.5), 1)
242+
self.assertEqual(math.trunc(-1.5), -1)
243+
self.assertEqual(math.trunc(1.999999), 1)
244+
self.assertEqual(math.trunc(-1.999999), -1)
245+
self.assertEqual(math.trunc(-0.999999), -0)
246+
self.assertEqual(math.trunc(-100.999), -100)
247+
248+
class TestTrunc(object):
249+
def __trunc__(self):
250+
return 23
251+
252+
class TestNoTrunc(object):
253+
pass
254+
255+
self.assertEqual(math.trunc(TestTrunc()), 23)
256+
257+
self.assertRaises(TypeError, math.trunc)
258+
self.assertRaises(TypeError, math.trunc, 1, 2)
259+
self.assertRaises(TypeError, math.trunc, TestNoTrunc())
260+
261+
# XXX Doesn't work because the method is looked up on
262+
# the type only.
263+
#t = TestNoTrunc()
264+
#t.__trunc__ = lambda *args: args
265+
#self.assertEquals((), math.trunc(t))
266+
#self.assertRaises(TypeError, math.trunc, t, 0)
267+
236268
def testCopysign(self):
237269
self.assertEqual(math.copysign(1, 42), 1.0)
238270
self.assertEqual(math.copysign(0., 42), 0.0)

Lib/test/test_rational.py

+17-6
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,17 @@ def testImmutable(self):
117117
r.__init__(2, 15)
118118
self.assertEquals((7, 3), _components(r))
119119

120+
self.assertRaises(AttributeError, setattr, r, 'numerator', 12)
121+
self.assertRaises(AttributeError, setattr, r, 'denominator', 6)
122+
self.assertEquals((7, 3), _components(r))
123+
124+
# But if you _really_ need to:
125+
r._numerator = 4
126+
r._denominator = 2
127+
self.assertEquals((4, 2), _components(r))
128+
# Which breaks some important operations:
129+
self.assertNotEquals(R(4, 2), r)
130+
120131
def testFromFloat(self):
121132
self.assertRaisesMessage(
122133
TypeError, "Rational.from_float() only takes floats, not 3 (int)",
@@ -193,7 +204,7 @@ def testApproximateFrom(self):
193204
self.assertEqual(R.from_float(0.0).approximate(10000), R(0))
194205

195206
def testConversions(self):
196-
self.assertTypedEquals(-1, trunc(R(-11, 10)))
207+
self.assertTypedEquals(-1, math.trunc(R(-11, 10)))
197208
self.assertTypedEquals(-2, math.floor(R(-11, 10)))
198209
self.assertTypedEquals(-1, math.ceil(R(-11, 10)))
199210
self.assertTypedEquals(-1, math.ceil(R(-10, 10)))
@@ -337,11 +348,11 @@ def testBigFloatComparisons(self):
337348
# Because 10**23 can't be represented exactly as a float:
338349
self.assertFalse(R(10**23) == float(10**23))
339350
# The first test demonstrates why these are important.
340-
self.assertFalse(1e23 < float(R(trunc(1e23) + 1)))
341-
self.assertTrue(1e23 < R(trunc(1e23) + 1))
342-
self.assertFalse(1e23 <= R(trunc(1e23) - 1))
343-
self.assertTrue(1e23 > R(trunc(1e23) - 1))
344-
self.assertFalse(1e23 >= R(trunc(1e23) + 1))
351+
self.assertFalse(1e23 < float(R(math.trunc(1e23) + 1)))
352+
self.assertTrue(1e23 < R(math.trunc(1e23) + 1))
353+
self.assertFalse(1e23 <= R(math.trunc(1e23) - 1))
354+
self.assertTrue(1e23 > R(math.trunc(1e23) - 1))
355+
self.assertFalse(1e23 >= R(math.trunc(1e23) + 1))
345356

346357
def testBigComplexComparisons(self):
347358
self.assertFalse(R(10**23) == complex(10**23))

Modules/mathmodule.c

+34
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,39 @@ FUNC1(tan, tan,
205205
FUNC1(tanh, tanh,
206206
"tanh(x)\n\nReturn the hyperbolic tangent of x.")
207207

208+
static PyObject *
209+
math_trunc(PyObject *self, PyObject *number)
210+
{
211+
static PyObject *trunc_str = NULL;
212+
PyObject *trunc;
213+
214+
if (Py_TYPE(number)->tp_dict == NULL) {
215+
if (PyType_Ready(Py_TYPE(number)) < 0)
216+
return NULL;
217+
}
218+
219+
if (trunc_str == NULL) {
220+
trunc_str = PyUnicode_InternFromString("__trunc__");
221+
if (trunc_str == NULL)
222+
return NULL;
223+
}
224+
225+
trunc = _PyType_Lookup(Py_TYPE(number), trunc_str);
226+
if (trunc == NULL) {
227+
PyErr_Format(PyExc_TypeError,
228+
"type %.100s doesn't define __trunc__ method",
229+
Py_TYPE(number)->tp_name);
230+
return NULL;
231+
}
232+
return PyObject_CallFunctionObjArgs(trunc, number, NULL);
233+
}
234+
235+
PyDoc_STRVAR(math_trunc_doc,
236+
"trunc(x:Real) -> Integral\n"
237+
"\n"
238+
"Truncates x to the nearest Integral toward 0. Uses the __trunc__ magic"
239+
"method.");
240+
208241
static PyObject *
209242
math_frexp(PyObject *self, PyObject *arg)
210243
{
@@ -428,6 +461,7 @@ static PyMethodDef math_methods[] = {
428461
{"sqrt", math_sqrt, METH_O, math_sqrt_doc},
429462
{"tan", math_tan, METH_O, math_tan_doc},
430463
{"tanh", math_tanh, METH_O, math_tanh_doc},
464+
{"trunc", math_trunc, METH_O, math_trunc_doc},
431465
{NULL, NULL} /* sentinel */
432466
};
433467

Modules/posixmodule.c

+7-6
Original file line numberDiff line numberDiff line change
@@ -3616,11 +3616,11 @@ Return 0 to child process and PID of child to parent process.");
36163616
static PyObject *
36173617
posix_fork1(PyObject *self, PyObject *noargs)
36183618
{
3619-
int pid = fork1();
3619+
pid_t pid = fork1();
36203620
if (pid == -1)
36213621
return posix_error();
36223622
PyOS_AfterFork();
3623-
return PyLong_FromLong((long)pid);
3623+
return PyLong_FromLong(pid);
36243624
}
36253625
#endif
36263626

@@ -3634,12 +3634,12 @@ Return 0 to child process and PID of child to parent process.");
36343634
static PyObject *
36353635
posix_fork(PyObject *self, PyObject *noargs)
36363636
{
3637-
int pid = fork();
3637+
pid_t pid = fork();
36383638
if (pid == -1)
36393639
return posix_error();
36403640
if (pid == 0)
36413641
PyOS_AfterFork();
3642-
return PyLong_FromLong((long)pid);
3642+
return PyLong_FromLong(pid);
36433643
}
36443644
#endif
36453645

@@ -3741,14 +3741,15 @@ To both, return fd of newly opened pseudo-terminal.\n");
37413741
static PyObject *
37423742
posix_forkpty(PyObject *self, PyObject *noargs)
37433743
{
3744-
int master_fd = -1, pid;
3744+
int master_fd = -1;
3745+
pid_t pid;
37453746

37463747
pid = forkpty(&master_fd, NULL, NULL, NULL);
37473748
if (pid == -1)
37483749
return posix_error();
37493750
if (pid == 0)
37503751
PyOS_AfterFork();
3751-
return Py_BuildValue("(ii)", pid, master_fd);
3752+
return Py_BuildValue("(li)", pid, master_fd);
37523753
}
37533754
#endif
37543755

0 commit comments

Comments
 (0)