Commit 400adb03 authored by Christian Heimes's avatar Christian Heimes

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
........
parent a7712090
......@@ -1059,12 +1059,6 @@ available. They are listed here in alphabetical order.
operators such as ``super(C, self)[name]``.
.. function:: trunc(x)
Return the :class:`Real` value *x* truncated to an :class:`Integral` (usually
a long integer). Delegates to ``x.__trunc__()``.
.. function:: tuple([iterable])
Return a tuple whose items are the same and in the same order as *iterable*'s
......
......@@ -96,6 +96,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
......
......@@ -111,6 +111,10 @@ typedef Py_intptr_t Py_ssize_t;
/* Smallest negative value of type Py_ssize_t. */
#define PY_SSIZE_T_MIN (-PY_SSIZE_T_MAX-1)
#if SIZEOF_PID_T > SIZEOF_LONG
# error "Python doesn't support sizeof(pid_t) > sizeof(long)"
#endif
/* PY_FORMAT_SIZE_T is a platform-specific modifier for use in a printf
* format to convert an argument with the width of a size_t or Py_ssize_t.
* C99 introduced "z" for this purpose, but not all platforms support that;
......@@ -550,7 +554,7 @@ extern char * _getpty(int *, int, mode_t, int);
functions, even though they are included in libutil. */
#include <termios.h>
extern int openpty(int *, int *, char *, struct termios *, struct winsize *);
extern int forkpty(int *, char *, struct termios *, struct winsize *);
extern pid_t forkpty(int *, char *, struct termios *, struct winsize *);
#endif /* !defined(HAVE_PTY_H) && !defined(HAVE_LIBUTIL_H) */
#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) */
......
......@@ -42,7 +42,7 @@ class Rational(RationalAbc):
"""
__slots__ = ('numerator', 'denominator')
__slots__ = ('_numerator', '_denominator')
# We're immutable, so use __new__ not __init__
def __new__(cls, numerator=0, denominator=1):
......@@ -92,8 +92,8 @@ class Rational(RationalAbc):
raise ZeroDivisionError('Rational(%s, 0)' % numerator)
g = gcd(numerator, denominator)
self.numerator = int(numerator // g)
self.denominator = int(denominator // g)
self._numerator = int(numerator // g)
self._denominator = int(denominator // g)
return self
@classmethod
......@@ -167,6 +167,14 @@ class Rational(RationalAbc):
result = new
return result
@property
def numerator(a):
return a._numerator
@property
def denominator(a):
return a._denominator
def __repr__(self):
"""repr(self)"""
return ('Rational(%r,%r)' % (self.numerator, self.denominator))
......@@ -192,20 +200,20 @@ class Rational(RationalAbc):
Rational, 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)):
# Do the real operation.
return Rational(self.numerator * other.denominator +
other.numerator * self.denominator,
self.denominator * other.denominator)
# float and complex don't follow this protocol, and
# Rational knows about them, so special case them.
# float and complex don't have those operations, but we
# know about those types, so special case them.
elif isinstance(other, float):
return float(self) + other
elif isinstance(other, complex):
return complex(self) + other
else:
# Let the other type take over.
return NotImplemented
# Let the other type take over.
return NotImplemented
def __radd__(self, other):
# radd handles more types than add because there's
......@@ -218,8 +226,7 @@ class Rational(RationalAbc):
return float(other) + float(self)
elif isinstance(other, Complex):
return complex(other) + complex(self)
else:
return NotImplemented
return NotImplemented
There are 5 different cases for a mixed-type addition on
......
"""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):
......@@ -37,7 +38,8 @@ class TestNumbers(unittest.TestCase):
self.failUnless(issubclass(complex, Inexact))
c1, c2 = complex(3, 2), complex(4,1)
self.assertRaises(TypeError, trunc, c1)
# XXX: This is not ideal, but see the comment in math_trunc().
self.assertRaises(TypeError, math.trunc, c1)
self.assertRaises(TypeError, operator.mod, c1, c2)
self.assertRaises(TypeError, divmod, c1, c2)
self.assertRaises(TypeError, operator.floordiv, c1, c2)
......
......@@ -1643,37 +1643,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:
def __trunc__(self):
return 23
class TestNoTrunc:
pass
self.assertEqual(trunc(TestTrunc()), 23)
self.assertRaises(TypeError, trunc)
self.assertRaises(TypeError, trunc, 1, 2)
self.assertRaises(TypeError, trunc, TestNoTrunc())
t = TestNoTrunc()
t.__trunc__ = lambda *args: args
self.assertRaises(TypeError, trunc, t)
self.assertRaises(TypeError, trunc, t, 0)
def test_tuple(self):
self.assertEqual(tuple(()), ())
t0_3 = (0, 1, 2, 3)
......
......@@ -338,6 +338,13 @@ class ComplexTest(unittest.TestCase):
except (OSError, IOError):
pass
if float.__getformat__("double").startswith("IEEE"):
def test_plus_minus_0j(self):
# test that -0j and 0j literals are not identified
z1, z2 = 0j, -0j
self.assertEquals(atan2(z1.imag, -1.), atan2(0., -1.))
self.assertEquals(atan2(z2.imag, -1.), atan2(-0., -1.))
def test_main():
test_support.run_unittest(ComplexTest)
......
......@@ -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)
......@@ -1213,7 +1214,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):
......
......@@ -233,6 +233,38 @@ 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)
self.assertRaises(TypeError, math.trunc, TestNoTrunc())
# XXX Doesn't work because the method is looked up on
# the type only.
#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)
......
......@@ -117,6 +117,17 @@ class RationalTest(unittest.TestCase):
r.__init__(2, 15)
self.assertEquals((7, 3), _components(r))
self.assertRaises(AttributeError, setattr, r, 'numerator', 12)
self.assertRaises(AttributeError, setattr, r, 'denominator', 6)
self.assertEquals((7, 3), _components(r))
# But if you _really_ need to:
r._numerator = 4
r._denominator = 2
self.assertEquals((4, 2), _components(r))
# Which breaks some important operations:
self.assertNotEquals(R(4, 2), r)
def testFromFloat(self):
self.assertRaisesMessage(
TypeError, "Rational.from_float() only takes floats, not 3 (int)",
......@@ -193,7 +204,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(-2, math.floor(R(-11, 10)))
self.assertTypedEquals(-1, math.ceil(R(-11, 10)))
self.assertTypedEquals(-1, math.ceil(R(-10, 10)))
......@@ -337,11 +348,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))
......
......@@ -205,6 +205,39 @@ FUNC1(tan, tan,
FUNC1(tanh, tanh,
"tanh(x)\n\nReturn the hyperbolic tangent of x.")
static PyObject *
math_trunc(PyObject *self, PyObject *number)
{
static PyObject *trunc_str = NULL;
PyObject *trunc;
if (Py_TYPE(number)->tp_dict == NULL) {
if (PyType_Ready(Py_TYPE(number)) < 0)
return NULL;
}
if (trunc_str == NULL) {
trunc_str = PyUnicode_InternFromString("__trunc__");
if (trunc_str == NULL)
return NULL;
}
trunc = _PyType_Lookup(Py_TYPE(number), trunc_str);
if (trunc == NULL) {
PyErr_Format(PyExc_TypeError,
"type %.100s doesn't define __trunc__ method",
Py_TYPE(number)->tp_name);
return NULL;
}
return PyObject_CallFunctionObjArgs(trunc, number, 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)
{
......@@ -428,6 +461,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 */
};
......
......@@ -3616,11 +3616,11 @@ Return 0 to child process and PID of child to parent process.");
static PyObject *
posix_fork1(PyObject *self, PyObject *noargs)
{
int pid = fork1();
pid_t pid = fork1();
if (pid == -1)
return posix_error();
PyOS_AfterFork();
return PyLong_FromLong((long)pid);
return PyLong_FromLong(pid);
}
#endif
......@@ -3634,12 +3634,12 @@ Return 0 to child process and PID of child to parent process.");
static PyObject *
posix_fork(PyObject *self, PyObject *noargs)
{
int pid = fork();
pid_t pid = fork();
if (pid == -1)
return posix_error();
if (pid == 0)
PyOS_AfterFork();
return PyLong_FromLong((long)pid);
return PyLong_FromLong(pid);
}
#endif
......@@ -3741,14 +3741,15 @@ To both, return fd of newly opened pseudo-terminal.\n");
static PyObject *
posix_forkpty(PyObject *self, PyObject *noargs)
{
int master_fd = -1, pid;
int master_fd = -1;
pid_t pid;
pid = forkpty(&master_fd, NULL, NULL, NULL);
if (pid == -1)
return posix_error();
if (pid == 0)
PyOS_AfterFork();
return Py_BuildValue("(ii)", pid, master_fd);
return Py_BuildValue("(li)", pid, master_fd);
}
#endif
......
......@@ -1570,40 +1570,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)
{
static PyObject *trunc_str = NULL;
PyObject *trunc;
if (Py_TYPE(number)->tp_dict == NULL) {
if (PyType_Ready(Py_TYPE(number)) < 0)
return NULL;
}
if (trunc_str == NULL) {
trunc_str = PyUnicode_InternFromString("__trunc__");
if (trunc_str == NULL)
return NULL;
}
trunc = _PyType_Lookup(Py_TYPE(number), trunc_str);
if (trunc == NULL) {
PyErr_Format(PyExc_TypeError,
"type %.100s doesn't define __trunc__ method",
Py_TYPE(number)->tp_name);
return NULL;
}
return PyObject_CallFunction(trunc, "O", number);
}
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)
{
......@@ -1870,7 +1836,6 @@ static PyMethodDef builtin_methods[] = {
{"sorted", (PyCFunction)builtin_sorted, METH_VARARGS | METH_KEYWORDS, sorted_doc},
{"sum", builtin_sum, METH_VARARGS, sum_doc},
{"vars", builtin_vars, METH_VARARGS, vars_doc},
{"trunc", builtin_trunc, METH_O, trunc_doc},
{"zip", builtin_zip, METH_VARARGS, zip_doc},
{NULL, NULL},
};
......
......@@ -885,24 +885,59 @@ compiler_add_o(struct compiler *c, PyObject *dict, PyObject *o)
{
PyObject *t, *v;
Py_ssize_t arg;
unsigned char *p, *q;
Py_complex z;
double d;
int real_part_zero, imag_part_zero;
/* necessary to make sure types aren't coerced (e.g., int and long) */
/* _and_ to distinguish 0.0 from -0.0 e.g. on IEEE platforms */
if (PyFloat_Check(o)) {
double d = PyFloat_AS_DOUBLE(o);
unsigned char* p = (unsigned char*) &d;
/* all we need is to make the tuple different in either the 0.0
* or -0.0 case from all others, just to avoid the "coercion".
*/
if (*p==0 && p[sizeof(double)-1]==0)
t = PyTuple_Pack(3, o, o->ob_type, Py_None);
else
t = PyTuple_Pack(2, o, o->ob_type);
} else {
t = PyTuple_Pack(2, o, o->ob_type);
d = PyFloat_AS_DOUBLE(o);
p = (unsigned char*) &d;
/* all we need is to make the tuple different in either the 0.0
* or -0.0 case from all others, just to avoid the "coercion".
*/
if (*p==0 && p[sizeof(double)-1]==0)
t = PyTuple_Pack(3, o, o->ob_type, Py_None);
else
t = PyTuple_Pack(2, o, o->ob_type);
}
else if (PyComplex_Check(o)) {
/* complex case is even messier: we need to make complex(x,
0.) different from complex(x, -0.) and complex(0., y)
different from complex(-0., y), for any x and y. In
particular, all four complex zeros should be
distinguished.*/
z = PyComplex_AsCComplex(o);
p = (unsigned char*) &(z.real);
q = (unsigned char*) &(z.imag);
/* all that matters here is that on IEEE platforms
real_part_zero will be true if z.real == 0., and false if
z.real == -0. In fact, real_part_zero will also be true
for some other rarely occurring nonzero floats, but this
doesn't matter. Similar comments apply to
imag_part_zero. */
real_part_zero = *p==0 && p[sizeof(double)-1]==0;
imag_part_zero = *q==0 && q[sizeof(double)-1]==0;
if (real_part_zero && imag_part_zero) {
t = PyTuple_Pack(4, o, o->ob_type, Py_True, Py_True);
}
else if (real_part_zero && !imag_part_zero) {
t = PyTuple_Pack(4, o, o->ob_type, Py_True, Py_False);
}
else if (!real_part_zero && imag_part_zero) {
t = PyTuple_Pack(4, o, o->ob_type, Py_False, Py_True);
}
else {
t = PyTuple_Pack(2, o, o->ob_type);
}
}
else {
t = PyTuple_Pack(2, o, o->ob_type);
}
if (t == NULL)
return -1;
return -1;
v = PyDict_GetItem(dict, t);
if (!v) {
......
......@@ -833,6 +833,7 @@ r_object(RFILE *p)
v = NULL;
break;
}
Py_DECREF(v2);
}
retval = v;
break;
......
This diff is collapsed.
......@@ -1177,7 +1177,7 @@ AC_TYPE_PID_T
AC_TYPE_SIGNAL
AC_TYPE_SIZE_T
AC_TYPE_UID_T
AC_CHECK_TYPE(ssize_t,
AC_CHECK_TYPE(ssize_t,
AC_DEFINE(HAVE_SSIZE_T, 1, Define if your compiler provides ssize_t),,)
# Sizes of various common basic types
......@@ -1190,6 +1190,7 @@ AC_CHECK_SIZEOF(float, 4)
AC_CHECK_SIZEOF(double, 8)
AC_CHECK_SIZEOF(fpos_t, 4)
AC_CHECK_SIZEOF(size_t, 4)
AC_CHECK_SIZEOF(pid_t, 4)
AC_MSG_CHECKING(for long long support)
have_long_long=no
......
......@@ -872,6 +872,9 @@
/* The number of bytes in an off_t. */
#undef SIZEOF_OFF_T
/* The size of `pid_t', as computed by sizeof. */
#undef SIZEOF_PID_T
/* The number of bytes in a pthread_t. */
#undef SIZEOF_PTHREAD_T
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment