diff --git a/Doc/c-api/utilities.rst b/Doc/c-api/utilities.rst index 18e2733a2c5..b9eb390bda5 100644 --- a/Doc/c-api/utilities.rst +++ b/Doc/c-api/utilities.rst @@ -184,7 +184,8 @@ Importing Modules single: modules (in module sys) This is a simplified interface to :cfunc:`PyImport_ImportModuleEx` below, - leaving the *globals* and *locals* arguments set to *NULL*. When the *name* + leaving the *globals* and *locals* arguments set to *NULL* and *level* set + to 0. When the *name* argument contains a dot (when it specifies a submodule of a package), the *fromlist* argument is set to the list ``['*']`` so that the return value is the named module rather than the top-level package containing it as would otherwise @@ -196,6 +197,27 @@ Importing Modules to find out. Starting with Python 2.4, a failing import of a module no longer leaves the module in ``sys.modules``. + .. versionchanged:: 2.6 + always use absolute imports + + .. index:: single: modules (in module sys) + + +.. cfunction:: PyObject* PyImport_ImportModuleNoBlock(const char *name) + + .. index:: + single: `cfunc:PyImport_ImportModule` + + This version of `cfunc:PyImport_ImportModule` does not block. It's intended + to be used in C function which import other modules to execute a function. + The import may block if another thread holds the import lock. The function + `cfunc:PyImport_ImportModuleNoBlock` doesn't block. It first tries to fetch + the module from sys.modules and falls back to `cfunc:PyImport_ImportModule` + unless the the lock is hold. In the latter case the function raises an + ImportError. + + .. versionadded:: 2.6 + .. cfunction:: PyObject* PyImport_ImportModuleEx(char *name, PyObject *globals, PyObject *locals, PyObject *fromlist) @@ -214,6 +236,24 @@ Importing Modules Failing imports remove incomplete module objects, like with :cfunc:`PyImport_ImportModule`. + .. versionchanged:: 2.6 + The function is an alias for `cfunc:PyImport_ImportModuleLevel` with + -1 as level, meaning relative import. + + +.. cfunction:: PyObject* PyImport_ImportModuleLevel(char *name, PyObject *globals, PyObject *locals, PyObject *fromlist, int level) + + Import a module. This is best described by referring to the built-in Python + function :func:`__import__`, as the standard :func:`__import__` function calls + this function directly. + + The return value is a new reference to the imported module or top-level package, + or *NULL* with an exception set on failure. Like for :func:`__import__`, + the return value when a submodule of a package was requested is normally the + top-level package, unless a non-empty *fromlist* was given. + + ..versionadded:: 2.5 + .. cfunction:: PyObject* PyImport_Import(PyObject *name) @@ -222,6 +262,9 @@ Importing Modules current globals. This means that the import is done using whatever import hooks are installed in the current environment. + .. versionchanged:: 2.6 + always use absolute imports + .. cfunction:: PyObject* PyImport_ReloadModule(PyObject *m) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 49fd77d6a32..48efff551ac 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -915,10 +915,13 @@ available. They are listed here in alphabetical order. .. function:: round(x[, n]) Return the floating point value *x* rounded to *n* digits after the decimal - point. If *n* is omitted, it defaults to zero. The result is a floating point - number. Values are rounded to the closest multiple of 10 to the power minus - *n*; if two multiples are equally close, rounding is done away from 0 (so. for - example, ``round(0.5)`` is ``1.0`` and ``round(-0.5)`` is ``-1.0``). + point. If *n* is omitted, it defaults to zero. Values are rounded to the + closest multiple of 10 to the power minus *n*; if two multiples are equally + close, rounding is done toward the even choice (so, for example, both + ``round(0.5)`` and ``round(-0.5)`` are ``0``, and ``round(1.5)`` is + ``2``). Delegates to ``x.__round__(n)``. + + .. versionchanged:: 2.6 .. function:: set([iterable]) @@ -1064,6 +1067,14 @@ 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__()``. + + .. 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 7ea4aac9949..dc8c74a1e76 100644 --- a/Doc/library/math.rst +++ b/Doc/library/math.rst @@ -26,8 +26,17 @@ Number-theoretic and representation functions: .. function:: ceil(x) - Return the ceiling of *x* as a float, the smallest integer value greater than or - equal to *x*. + Return the ceiling of *x* as a float, the smallest integer value greater than + or equal to *x*. If *x* is not a float, delegates to ``x.__ceil__()``, which + should return an :class:`Integral` value. + + +.. function:: copysign(x, y) + + Return *x* with the sign of *y*. ``copysign`` copies the sign bit of an IEEE + 754 float, ``copysign(1, -0.0)`` returns *-1.0*. + + ..versionadded:: 2.6 .. function:: fabs(x) @@ -37,8 +46,9 @@ Number-theoretic and representation functions: .. function:: floor(x) - Return the floor of *x* as a float, the largest integer value less than or equal - to *x*. + Return the floor of *x* as a float, the largest integer value less than or + equal to *x*. If *x* is not a float, delegates to ``x.__floor__()``, which + should return an :class:`Integral` value. .. function:: fmod(x, y) @@ -64,6 +74,23 @@ Number-theoretic and representation functions: apart" the internal representation of a float in a portable way. +.. function:: isinf(x) + + Checks if the float *x* is positive or negative infinite. + + ..versionadded:: 2.6 + + +.. function:: isnan(x) + + Checks if the float *x* is a NaN (not a number). NaNs are part of the + IEEE 754 standards. Operation like but not limited to ``inf * 0``, + ``inf / inf`` or any operation involving a NaN, e.g. ``nan * 1``, return + a NaN. + + ..versionadded:: 2.6 + + .. function:: ldexp(x, i) Return ``x * (2**i)``. This is essentially the inverse of function diff --git a/Doc/library/numbers.rst b/Doc/library/numbers.rst new file mode 100644 index 00000000000..d0f9c3b83db --- /dev/null +++ b/Doc/library/numbers.rst @@ -0,0 +1,99 @@ + +:mod:`numbers` --- Numeric abstract base classes +================================================ + +.. module:: numbers + :synopsis: Numeric abstract base classes (Complex, Real, Integral, etc.). + +The :mod:`numbers` module (:pep:`3141`) defines a hierarchy of numeric abstract +base classes which progressively define more operations. These concepts also +provide a way to distinguish exact from inexact types. None of the types defined +in this module can be instantiated. + + +.. class:: Number + + The root of the numeric hierarchy. If you just want to check if an argument + *x* is a number, without caring what kind, use ``isinstance(x, Number)``. + + +Exact and inexact operations +---------------------------- + +.. class:: Exact + + Subclasses of this type have exact operations. + + As long as the result of a homogenous operation is of the same type, you can + assume that it was computed exactly, and there are no round-off errors. Laws + like commutativity and associativity hold. + + +.. class:: Inexact + + Subclasses of this type have inexact operations. + + Given X, an instance of :class:`Inexact`, it is possible that ``(X + -X) + 3 + == 3``, but ``X + (-X + 3) == 0``. The exact form this error takes will vary + by type, but it's generally unsafe to compare this type for equality. + + +The numeric tower +----------------- + +.. class:: Complex + + Subclasses of this type describe complex numbers and include the operations + that work on the builtin :class:`complex` type. These are: conversions to + :class:`complex` and :class:`bool`, :attr:`.real`, :attr:`.imag`, ``+``, + ``-``, ``*``, ``/``, :func:`abs`, :meth:`conjugate`, ``==``, and ``!=``. All + except ``-`` and ``!=`` are abstract. + +.. attribute:: Complex.real + + Abstract. Retrieves the :class:`Real` component of this number. + +.. attribute:: Complex.imag + + Abstract. Retrieves the :class:`Real` component of this number. + +.. method:: Complex.conjugate() + + Abstract. Returns the complex conjugate. For example, ``(1+3j).conjugate() == + (1-3j)``. + +.. class:: Real + + To :class:`Complex`, :class:`Real` adds the operations that work on real + numbers. + + In short, those are: a conversion to :class:`float`, :func:`trunc`, + :func:`round`, :func:`math.floor`, :func:`math.ceil`, :func:`divmod`, ``//``, + ``%``, ``<``, ``<=``, ``>``, and ``>=``. + + Real also provides defaults for :func:`complex`, :attr:`Complex.real`, + :attr:`Complex.imag`, and :meth:`Complex.conjugate`. + + +.. class:: Rational + + Subtypes both :class:`Real` and :class:`Exact`, and adds + :attr:`Rational.numerator` and :attr:`Rational.denominator` properties, which + should be in lowest terms. With these, it provides a default for + :func:`float`. + +.. attribute:: Rational.numerator + + Abstract. + +.. attribute:: Rational.denominator + + Abstract. + + +.. class:: Integral + + Subtypes :class:`Rational` and adds a conversion to :class:`long`, the + 3-argument form of :func:`pow`, and the bit-string operations: ``<<``, + ``>>``, ``&``, ``^``, ``|``, ``~``. Provides defaults for :func:`float`, + :attr:`Rational.numerator`, and :attr:`Rational.denominator`. diff --git a/Doc/library/numeric.rst b/Doc/library/numeric.rst index 0d9d59fbe16..d2b4d8b346e 100644 --- a/Doc/library/numeric.rst +++ b/Doc/library/numeric.rst @@ -6,16 +6,18 @@ Numeric and Mathematical Modules ******************************** The modules described in this chapter provide numeric and math-related functions -and data types. The :mod:`math` and :mod:`cmath` contain various mathematical -functions for floating-point and complex numbers. For users more interested in -decimal accuracy than in speed, the :mod:`decimal` module supports exact -representations of decimal numbers. +and data types. The :mod:`numbers` module defines an abstract hierarchy of +numeric types. The :mod:`math` and :mod:`cmath` modules contain various +mathematical functions for floating-point and complex numbers. For users more +interested in decimal accuracy than in speed, the :mod:`decimal` module supports +exact representations of decimal numbers. The following modules are documented in this chapter: .. toctree:: + numbers.rst math.rst cmath.rst decimal.rst diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 0ec255fb626..3c7f8e6ed03 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -152,7 +152,7 @@ Ellipsis object is accessed through the literal ``...`` or the built-in name ``Ellipsis``. Its truth value is true. -Numbers +:class:`numbers.Number` .. index:: object: numeric These are created by numeric literals and returned as results by arithmetic @@ -164,7 +164,7 @@ Numbers Python distinguishes between integers, floating point numbers, and complex numbers: - Integers + :class:`numbers.Integral` .. index:: object: integer These represent elements from the mathematical set of integers (positive and @@ -202,7 +202,7 @@ Numbers operation except left shift, if it yields a result in the plain integer domain without causing overflow, will yield the same result when using mixed operands. - Floating point numbers + :class:`numbers.Real` (:class:`float`) .. index:: object: floating point pair: floating point; number @@ -217,7 +217,7 @@ Numbers overhead of using objects in Python, so there is no reason to complicate the language with two kinds of floating point numbers. - Complex numbers + :class:`numbers.Complex` .. index:: object: complex pair: complex; number diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst index 6e160ee558f..cf95636da74 100644 --- a/Doc/reference/expressions.rst +++ b/Doc/reference/expressions.rst @@ -768,7 +768,8 @@ float result is delivered. For example, ``10**2`` returns ``100``, but ``10**-2`` returns ``0.01``. Raising ``0.0`` to a negative power results in a :exc:`ZeroDivisionError`. -Raising a negative number to a fractional power results in a :exc:`ValueError`. +Raising a negative number to a fractional power results in a :class:`complex` +number. (Since Python 2.6. In earlier versions it raised a :exc:`ValueError`.) .. _unary: diff --git a/Include/import.h b/Include/import.h index af9f3394b13..05ad7f008a0 100644 --- a/Include/import.h +++ b/Include/import.h @@ -14,13 +14,10 @@ PyAPI_FUNC(PyObject *) PyImport_ExecCodeModuleEx( PyAPI_FUNC(PyObject *) PyImport_GetModuleDict(void); PyAPI_FUNC(PyObject *) PyImport_AddModule(const char *name); PyAPI_FUNC(PyObject *) PyImport_ImportModule(const char *name); +PyAPI_FUNC(PyObject *) PyImport_ImportModuleNoBlock(const char *); PyAPI_FUNC(PyObject *) PyImport_ImportModuleLevel(char *name, PyObject *globals, PyObject *locals, PyObject *fromlist, int level); -/* For DLL compatibility */ -#undef PyImport_ImportModuleEx -PyAPI_FUNC(PyObject *) PyImport_ImportModuleEx( - char *name, PyObject *globals, PyObject *locals, PyObject *fromlist); #define PyImport_ImportModuleEx(n, g, l, f) \ PyImport_ImportModuleLevel(n, g, l, f, -1) diff --git a/Include/py_curses.h b/Include/py_curses.h index 3cb23cc90f3..c6cbdbd5469 100644 --- a/Include/py_curses.h +++ b/Include/py_curses.h @@ -90,7 +90,7 @@ static void **PyCurses_API; #define import_curses() \ { \ - PyObject *module = PyImport_ImportModule("_curses"); \ + PyObject *module = PyImport_ImportModuleNoBlock("_curses"); \ if (module != NULL) { \ PyObject *module_dict = PyModule_GetDict(module); \ PyObject *c_api_object = PyDict_GetItemString(module_dict, "_C_API"); \ diff --git a/Include/pyport.h b/Include/pyport.h index 82d305ce323..e4da8f4347a 100644 --- a/Include/pyport.h +++ b/Include/pyport.h @@ -335,12 +335,19 @@ extern "C" { /* High precision defintion of pi and e (Euler) * The values are taken from libc6's math.h. */ +#ifndef Py_MATH_PIl +#define Py_MATH_PIl 3.1415926535897932384626433832795029L +#endif #ifndef Py_MATH_PI -#define Py_MATH_PI 3.1415926535897932384626433832795029L +#define Py_MATH_PI 3.14159265358979323846 +#endif + +#ifndef Py_MATH_El +#define Py_MATH_El 2.7182818284590452353602874713526625L #endif #ifndef Py_MATH_E -#define Py_MATH_E 2.7182818284590452353602874713526625L +#define Py_MATH_E 2.7182818284590452354 #endif /* Py_IS_NAN(X) diff --git a/Lib/distutils/command/build_scripts.py b/Lib/distutils/command/build_scripts.py index 227bb9c7a1e..7b44264cc22 100644 --- a/Lib/distutils/command/build_scripts.py +++ b/Lib/distutils/command/build_scripts.py @@ -110,7 +110,8 @@ class build_scripts(Command): if f: f.close() else: - f.close() + if f: + f.close() self.copy_file(script, outfile) if os.name == 'posix': diff --git a/Lib/sre_compile.py b/Lib/sre_compile.py index f9f073614d9..f3b415d43f2 100644 --- a/Lib/sre_compile.py +++ b/Lib/sre_compile.py @@ -516,7 +516,7 @@ def compile(p, flags=0): indexgroup[i] = k return _sre.compile( - pattern, flags, code, + pattern, flags | p.pattern.flags, code, p.pattern.groups-1, groupindex, indexgroup ) diff --git a/Lib/test/test_math.py b/Lib/test/test_math.py index 2d15f3aa41b..8449794cc45 100644 --- a/Lib/test/test_math.py +++ b/Lib/test/test_math.py @@ -231,6 +231,29 @@ 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 testCopysign(self): + self.assertEqual(math.copysign(1, 42), 1.0) + self.assertEqual(math.copysign(0., 42), 0.0) + self.assertEqual(math.copysign(1., -42), -1.0) + self.assertEqual(math.copysign(3, 0.), 3.0) + self.assertEqual(math.copysign(4., -0.), -4.0) + + def testIsnan(self): + self.assert_(math.isnan(float("nan"))) + self.assert_(math.isnan(float("inf")* 0.)) + self.failIf(math.isnan(float("inf"))) + self.failIf(math.isnan(0.)) + self.failIf(math.isnan(1.)) + + def testIsinf(self): + self.assert_(math.isinf(float("inf"))) + self.assert_(math.isinf(float("-inf"))) + self.assert_(math.isinf(1E400)) + self.assert_(math.isinf(-1E400)) + self.failIf(math.isinf(float("nan"))) + self.failIf(math.isinf(0.)) + self.failIf(math.isinf(1.)) + # RED_FLAG 16-Oct-2000 Tim # While 2.0 is more consistent about exceptions than previous releases, it # still fails this part of the test on some platforms. For now, we only diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py index 88fecbf9dbd..75c016e43d3 100644 --- a/Lib/test/test_re.py +++ b/Lib/test/test_re.py @@ -632,6 +632,36 @@ class ReTests(unittest.TestCase): self.assertEqual(re.compile("bla").match(a), None) self.assertEqual(re.compile("").match(a).groups(), ()) + def test_inline_flags(self): + # Bug #1700 + upper_char = unichr(0x1ea0) # Latin Capital Letter A with Dot Bellow + lower_char = unichr(0x1ea1) # Latin Small Letter A with Dot Bellow + + p = re.compile(upper_char, re.I | re.U) + q = p.match(lower_char) + self.assertNotEqual(q, None) + + p = re.compile(lower_char, re.I | re.U) + q = p.match(upper_char) + self.assertNotEqual(q, None) + + p = re.compile('(?i)' + upper_char, re.U) + q = p.match(lower_char) + self.assertNotEqual(q, None) + + p = re.compile('(?i)' + lower_char, re.U) + q = p.match(upper_char) + self.assertNotEqual(q, None) + + p = re.compile('(?iu)' + upper_char) + q = p.match(lower_char) + self.assertNotEqual(q, None) + + p = re.compile('(?iu)' + lower_char) + q = p.match(upper_char) + self.assertNotEqual(q, None) + + def run_re_tests(): from test.re_tests import benchmarks, tests, SUCCEED, FAIL, SYNTAX_ERROR if verbose: diff --git a/Mac/Modules/MacOS.c b/Mac/Modules/MacOS.c index 7ba1dd64d4c..4b86cf0b3d2 100644 --- a/Mac/Modules/MacOS.c +++ b/Mac/Modules/MacOS.c @@ -356,7 +356,7 @@ MacOS_GetErrorString(PyObject *self, PyObject *args) PyObject *m, *rv; errors_loaded = 1; - m = PyImport_ImportModule("macresource"); + m = PyImport_ImportModuleNoBlock("macresource"); if (!m) { if (Py_VerboseFlag) PyErr_Print(); diff --git a/Modules/_ctypes/callbacks.c b/Modules/_ctypes/callbacks.c index 5e61938f7a2..050a5c154a7 100644 --- a/Modules/_ctypes/callbacks.c +++ b/Modules/_ctypes/callbacks.c @@ -367,7 +367,7 @@ long Call_GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) if (context == NULL) context = PyUnicode_FromString("_ctypes.DllGetClassObject"); - mod = PyImport_ImportModule("ctypes"); + mod = PyImport_ImportModuleNoBlock("ctypes"); if (!mod) { PyErr_WriteUnraisable(context ? context : Py_None); /* There has been a warning before about this already */ @@ -446,7 +446,7 @@ long Call_CanUnloadNow(void) if (context == NULL) context = PyUnicode_FromString("_ctypes.DllCanUnloadNow"); - mod = PyImport_ImportModule("ctypes"); + mod = PyImport_ImportModuleNoBlock("ctypes"); if (!mod) { /* OutputDebugString("Could not import ctypes"); */ /* We assume that this error can only occur when shutting diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index ea98d085ad5..638b3883195 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -2316,7 +2316,7 @@ static int update_lines_cols(void) { PyObject *o; - PyObject *m = PyImport_ImportModule("curses"); + PyObject *m = PyImport_ImportModuleNoBlock("curses"); if (!m) return 0; diff --git a/Modules/cjkcodecs/cjkcodecs.h b/Modules/cjkcodecs/cjkcodecs.h index 3ec24cb7eb7..fb6b5ce878d 100644 --- a/Modules/cjkcodecs/cjkcodecs.h +++ b/Modules/cjkcodecs/cjkcodecs.h @@ -245,7 +245,7 @@ getmultibytecodec(void) static PyObject *cofunc = NULL; if (cofunc == NULL) { - PyObject *mod = PyImport_ImportModule("_multibytecodec"); + PyObject *mod = PyImport_ImportModuleNoBlock("_multibytecodec"); if (mod == NULL) return NULL; cofunc = PyObject_GetAttrString(mod, "__create_codec"); diff --git a/Modules/datetimemodule.c b/Modules/datetimemodule.c index 1e30f7ef8f3..b91a0823045 100644 --- a/Modules/datetimemodule.c +++ b/Modules/datetimemodule.c @@ -1329,7 +1329,7 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple, goto Done; { PyObject *format; - PyObject *time = PyImport_ImportModule("time"); + PyObject *time = PyImport_ImportModuleNoBlock("time"); if (time == NULL) goto Done; format = PyUnicode_FromString(PyString_AS_STRING(newfmt)); @@ -1357,7 +1357,7 @@ static PyObject * time_time(void) { PyObject *result = NULL; - PyObject *time = PyImport_ImportModule("time"); + PyObject *time = PyImport_ImportModuleNoBlock("time"); if (time != NULL) { result = PyObject_CallMethod(time, "time", "()"); @@ -1375,7 +1375,7 @@ build_struct_time(int y, int m, int d, int hh, int mm, int ss, int dstflag) PyObject *time; PyObject *result = NULL; - time = PyImport_ImportModule("time"); + time = PyImport_ImportModuleNoBlock("time"); if (time != NULL) { result = PyObject_CallMethod(time, "struct_time", "((iiiiiiiii))", @@ -3821,7 +3821,7 @@ datetime_strptime(PyObject *cls, PyObject *args) if (!PyArg_ParseTuple(args, "uu:strptime", &string, &format)) return NULL; - if ((module = PyImport_ImportModule("time")) == NULL) + if ((module = PyImport_ImportModuleNoBlock("time")) == NULL) return NULL; obj = PyObject_CallMethod(module, "strptime", "uu", string, format); Py_DECREF(module); diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index 37fcc51906c..d449a2b9fef 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -1199,7 +1199,7 @@ initgc(void) * the import and triggers an assertion. */ if (tmod == NULL) { - tmod = PyImport_ImportModule("time"); + tmod = PyImport_ImportModuleNoBlock("time"); if (tmod == NULL) PyErr_Clear(); } diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index edf5e9b8c57..8992baed837 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -133,6 +133,14 @@ FUNC1(cos, cos, "cos(x)\n\nReturn the cosine of x (measured in radians).") FUNC1(cosh, cosh, "cosh(x)\n\nReturn the hyperbolic cosine of x.") +#if defined(MS_WINDOWS) || defined(HAVE_COPYSIGN) +#ifdef MS_WINDOWS +FUNC2(copysign, _copysign, +#else +FUNC2(copysign, copysign, +#endif + "copysign(x,y)\n\nReturn x with the sign of y."); +#endif FUNC1(exp, exp, "exp(x)\n\nReturn e raised to the power of x.") FUNC1(fabs, fabs, @@ -315,9 +323,8 @@ math_log10(PyObject *self, PyObject *arg) PyDoc_STRVAR(math_log10_doc, "log10(x) -> the base 10 logarithm of x."); -/* XXX(nnorwitz): Should we use the platform M_PI or something more accurate - like: 3.14159265358979323846264338327950288 */ -static const double degToRad = 3.141592653589793238462643383 / 180.0; +static const double degToRad = Py_MATH_PI / 180.0; +static const double radToDeg = 180.0 / Py_MATH_PI; static PyObject * math_degrees(PyObject *self, PyObject *arg) @@ -325,7 +332,7 @@ math_degrees(PyObject *self, PyObject *arg) double x = PyFloat_AsDouble(arg); if (x == -1.0 && PyErr_Occurred()) return NULL; - return PyFloat_FromDouble(x / degToRad); + return PyFloat_FromDouble(x * radToDeg); } PyDoc_STRVAR(math_degrees_doc, @@ -343,12 +350,42 @@ math_radians(PyObject *self, PyObject *arg) PyDoc_STRVAR(math_radians_doc, "radians(x) -> converts angle x from degrees to radians"); +static PyObject * +math_isnan(PyObject *self, PyObject *arg) +{ + double x = PyFloat_AsDouble(arg); + if (x == -1.0 && PyErr_Occurred()) + return NULL; + return PyBool_FromLong((long)Py_IS_NAN(x)); +} + +PyDoc_STRVAR(math_isnan_doc, +"isnan(x) -> bool\n\ +Checks if float x is not a number (NaN)"); + +static PyObject * +math_isinf(PyObject *self, PyObject *arg) +{ + double x = PyFloat_AsDouble(arg); + if (x == -1.0 && PyErr_Occurred()) + return NULL; + return PyBool_FromLong((long)Py_IS_INFINITY(x)); +} + +PyDoc_STRVAR(math_isinf_doc, +"isinf(x) -> bool\n\ +Checks if float x is infinite (positive or negative)"); + + static PyMethodDef math_methods[] = { {"acos", math_acos, METH_O, math_acos_doc}, {"asin", math_asin, METH_O, math_asin_doc}, {"atan", math_atan, METH_O, math_atan_doc}, {"atan2", math_atan2, METH_VARARGS, math_atan2_doc}, {"ceil", math_ceil, METH_O, math_ceil_doc}, +#if defined(MS_WINDOWS) || defined(HAVE_COPYSIGN) + {"copysign", math_copysign, METH_VARARGS, math_copysign_doc}, +#endif {"cos", math_cos, METH_O, math_cos_doc}, {"cosh", math_cosh, METH_O, math_cosh_doc}, {"degrees", math_degrees, METH_O, math_degrees_doc}, @@ -358,6 +395,8 @@ static PyMethodDef math_methods[] = { {"fmod", math_fmod, METH_VARARGS, math_fmod_doc}, {"frexp", math_frexp, METH_O, math_frexp_doc}, {"hypot", math_hypot, METH_VARARGS, math_hypot_doc}, + {"isinf", math_isinf, METH_O, math_isinf_doc}, + {"isnan", math_isnan, METH_O, math_isnan_doc}, {"ldexp", math_ldexp, METH_VARARGS, math_ldexp_doc}, {"log", math_log, METH_VARARGS, math_log_doc}, {"log10", math_log10, METH_O, math_log10_doc}, @@ -389,13 +428,13 @@ initmath(void) if (d == NULL) goto finally; - if (!(v = PyFloat_FromDouble(atan(1.0) * 4.0))) + if (!(v = PyFloat_FromDouble(Py_MATH_PI))) goto finally; if (PyDict_SetItemString(d, "pi", v) < 0) goto finally; Py_DECREF(v); - if (!(v = PyFloat_FromDouble(exp(1.0)))) + if (!(v = PyFloat_FromDouble(Py_MATH_E))) goto finally; if (PyDict_SetItemString(d, "e", v) < 0) goto finally; diff --git a/Modules/parsermodule.c b/Modules/parsermodule.c index 4c0020350ac..9cc1227d148 100644 --- a/Modules/parsermodule.c +++ b/Modules/parsermodule.c @@ -3093,7 +3093,7 @@ initparser(void) * If this fails, the import of this module will fail because an * exception will be raised here; should we clear the exception? */ - copyreg = PyImport_ImportModule("copy_reg"); + copyreg = PyImport_ImportModuleNoBlock("copy_reg"); if (copyreg != NULL) { PyObject *func, *pickler; diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 12bdde0d34d..f3df9b7187b 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -4217,7 +4217,7 @@ wait_helper(int pid, int status, struct rusage *ru) return posix_error(); if (struct_rusage == NULL) { - PyObject *m = PyImport_ImportModule("resource"); + PyObject *m = PyImport_ImportModuleNoBlock("resource"); if (m == NULL) return NULL; struct_rusage = PyObject_GetAttrString(m, "struct_rusage"); diff --git a/Modules/socketmodule.h b/Modules/socketmodule.h index b41a0405e1d..135b7166bf7 100644 --- a/Modules/socketmodule.h +++ b/Modules/socketmodule.h @@ -222,7 +222,7 @@ int PySocketModule_ImportModuleAndAPI(void) void *api; DPRINTF("Importing the %s C API...\n", apimodule); - mod = PyImport_ImportModule(apimodule); + mod = PyImport_ImportModuleNoBlock(apimodule); if (mod == NULL) goto onError; DPRINTF(" %s package found\n", apimodule); diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 8854d0d825a..de8c99c1f11 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -556,7 +556,7 @@ is not present, current time as returned by localtime() is used."); static PyObject * time_strptime(PyObject *self, PyObject *args) { - PyObject *strptime_module = PyImport_ImportModule("_strptime"); + PyObject *strptime_module = PyImport_ImportModuleNoBlock("_strptime"); PyObject *strptime_result; if (!strptime_module) @@ -668,7 +668,7 @@ time_tzset(PyObject *self, PyObject *unused) { PyObject* m; - m = PyImport_ImportModule("time"); + m = PyImport_ImportModuleNoBlock("time"); if (m == NULL) { return NULL; } diff --git a/Modules/zipimport.c b/Modules/zipimport.c index 08322b6a6c4..84985a8a6cd 100644 --- a/Modules/zipimport.c +++ b/Modules/zipimport.c @@ -766,7 +766,7 @@ get_decompress_func(void) let's avoid a stack overflow. */ return NULL; importing_zlib = 1; - zlib = PyImport_ImportModule("zlib"); /* import zlib */ + zlib = PyImport_ImportModuleNoBlock("zlib"); importing_zlib = 0; if (zlib != NULL) { decompress = PyObject_GetAttrString(zlib, diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 5b94b0f4112..694f3b0a261 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -2800,7 +2800,7 @@ PyObject *PyUnicode_DecodeUnicodeEscape(const char *s, if (ucnhash_CAPI == NULL) { /* load the unicode data module */ PyObject *m, *api; - m = PyImport_ImportModule("unicodedata"); + m = PyImport_ImportModuleNoBlock("unicodedata"); if (m == NULL) goto ucnhashError; api = PyObject_GetAttrString(m, "ucnhash_CAPI"); diff --git a/PC/VS8.0/pythoncore.vcproj b/PC/VS8.0/pythoncore.vcproj index 6a16cd9d22d..2a5392efbf9 100644 --- a/PC/VS8.0/pythoncore.vcproj +++ b/PC/VS8.0/pythoncore.vcproj @@ -1598,10 +1598,6 @@ RelativePath="..\..\Python\ast.c" > - - diff --git a/PCbuild/pythoncore.vcproj b/PCbuild/pythoncore.vcproj index 413e4078d0c..930ee5f6d1b 100644 --- a/PCbuild/pythoncore.vcproj +++ b/PCbuild/pythoncore.vcproj @@ -1598,10 +1598,6 @@ RelativePath="..\Python\ast.c" > - - diff --git a/Python/errors.c b/Python/errors.c index 79f711dd835..cbc6f156a1b 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -711,7 +711,7 @@ PyErr_WarnExplicit(PyObject *category, const char *message, { PyObject *mod, *dict, *func = NULL; - mod = PyImport_ImportModule("warnings"); + mod = PyImport_ImportModuleNoBlock("warnings"); if (mod != NULL) { dict = PyModule_GetDict(mod); func = PyDict_GetItemString(dict, "warn_explicit"); diff --git a/Python/import.c b/Python/import.c index a7f6a48d36a..658cc70a3b7 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1896,6 +1896,53 @@ PyImport_ImportModule(const char *name) return result; } +/* Import a module without blocking + * + * At first it tries to fetch the module from sys.modules. If the module was + * never loaded before it loads it with PyImport_ImportModule() unless another + * thread holds the import lock. In the latter case the function raises an + * ImportError instead of blocking. + * + * Returns the module object with incremented ref count. + */ +PyObject * +PyImport_ImportModuleNoBlock(const char *name) +{ + PyObject *result; + PyObject *modules; + long me; + + /* Try to get the module from sys.modules[name] */ + modules = PyImport_GetModuleDict(); + if (modules == NULL) + return NULL; + + result = PyDict_GetItemString(modules, name); + if (result != NULL) { + Py_INCREF(result); + return result; + } + else { + PyErr_Clear(); + } + + /* check the import lock + * me might be -1 but I ignore the error here, the lock function + * takes care of the problem */ + me = PyThread_get_thread_ident(); + if (import_lock_thread == -1 || import_lock_thread == me) { + /* no thread or me is holding the lock */ + return PyImport_ImportModule(name); + } + else { + PyErr_Format(PyExc_ImportError, + "Failed to import %.200s because the import lock" + "is held by another thread.", + name); + return NULL; + } +} + /* Forward declarations for helper routines */ static PyObject *get_parent(PyObject *globals, char *buf, Py_ssize_t *p_buflen, int level); @@ -1965,26 +2012,6 @@ import_module_level(char *name, PyObject *globals, PyObject *locals, return tail; } -/* For DLL compatibility */ -#undef PyImport_ImportModuleEx -PyObject * -PyImport_ImportModuleEx(char *name, PyObject *globals, PyObject *locals, - PyObject *fromlist) -{ - PyObject *result; - lock_import(); - result = import_module_level(name, globals, locals, fromlist, -1); - if (unlock_import() < 0) { - Py_XDECREF(result); - PyErr_SetString(PyExc_RuntimeError, - "not holding the import lock"); - return NULL; - } - return result; -} -#define PyImport_ImportModuleEx(n, g, l, f) \ - PyImport_ImportModuleLevel(n, g, l, f, -1); - PyObject * PyImport_ImportModuleLevel(char *name, PyObject *globals, PyObject *locals, PyObject *fromlist, int level) @@ -2572,9 +2599,10 @@ PyImport_Import(PyObject *module_name) if (import == NULL) goto err; - /* Call the __import__ function with the proper argument list */ - r = PyObject_CallFunctionObjArgs(import, module_name, globals, - globals, silly_list, NULL); + /* Call the __import__ function with the proper argument list + * Always use absolute import here. */ + r = PyObject_CallFunction(import, "OOOOi", module_name, globals, + globals, silly_list, 0, NULL); err: Py_XDECREF(globals); diff --git a/Python/mactoolboxglue.c b/Python/mactoolboxglue.c index 6688b02459e..bb1ebb1318f 100644 --- a/Python/mactoolboxglue.c +++ b/Python/mactoolboxglue.c @@ -36,7 +36,7 @@ PyMac_StrError(int err) PyObject *m; PyObject *rv; - m = PyImport_ImportModule("MacOS"); + m = PyImport_ImportModuleNoBlock("MacOS"); if (!m) { if (Py_VerboseFlag) PyErr_Print();