From 302e7902c89f4bb2f31a0333d05bde26c4f3a0c2 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Tue, 20 Mar 2012 23:17:04 -0400 Subject: use identifier api --- Python/ceval.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Python/ceval.c b/Python/ceval.c index 5498056..4182378 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1837,10 +1837,11 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) if (PyGen_CheckExact(x)) { retval = _PyGen_Send((PyGenObject *)x, u); } else { + _Py_IDENTIFIER(send); if (u == Py_None) retval = PyIter_Next(x); else - retval = PyObject_CallMethod(x, "send", "O", u); + retval = _PyObject_CallMethodId(x, &PyId_send, "O", u); } Py_DECREF(u); if (!retval) { -- cgit v0.12 From 9fc9bf465af96bf753217b0c370e4452882ecd86 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Tue, 20 Mar 2012 23:26:41 -0400 Subject: some more identifier goodness --- Objects/abstract.c | 35 ++++++++--------------------------- 1 file changed, 8 insertions(+), 27 deletions(-) diff --git a/Objects/abstract.c b/Objects/abstract.c index 39dffac..b8df950 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -1325,16 +1325,10 @@ PyObject * PyNumber_Long(PyObject *o) { PyNumberMethods *m; - static PyObject *trunc_name = NULL; PyObject *trunc_func; const char *buffer; Py_ssize_t buffer_len; - - if (trunc_name == NULL) { - trunc_name = PyUnicode_InternFromString("__trunc__"); - if (trunc_name == NULL) - return NULL; - } + _Py_IDENTIFIER(__trunc__); if (o == NULL) return null_error(); @@ -1356,7 +1350,7 @@ PyNumber_Long(PyObject *o) } if (PyLong_Check(o)) /* An int subclass without nb_int */ return _PyLong_Copy((PyLongObject *)o); - trunc_func = PyObject_GetAttr(o, trunc_name); + trunc_func = _PyObject_GetAttrId(o, &PyId___trunc__); if (trunc_func) { PyObject *truncated = PyEval_CallObject(trunc_func, NULL); PyObject *int_instance; @@ -2411,10 +2405,8 @@ PyObject_CallFunctionObjArgs(PyObject *callable, ...) /* isinstance(), issubclass() */ -/* abstract_get_bases() has logically 4 return states, with a sort of 0th - * state that will almost never happen. +/* abstract_get_bases() has logically 4 return states: * - * 0. creating the __bases__ static string could get a MemoryError * 1. getattr(cls, '__bases__') could raise an AttributeError * 2. getattr(cls, '__bases__') could raise some other exception * 3. getattr(cls, '__bases__') could return a tuple @@ -2440,16 +2432,11 @@ PyObject_CallFunctionObjArgs(PyObject *callable, ...) static PyObject * abstract_get_bases(PyObject *cls) { - static PyObject *__bases__ = NULL; + _Py_IDENTIFIER(__bases__); PyObject *bases; - if (__bases__ == NULL) { - __bases__ = PyUnicode_InternFromString("__bases__"); - if (__bases__ == NULL) - return NULL; - } Py_ALLOW_RECURSION - bases = PyObject_GetAttr(cls, __bases__); + bases = _PyObject_GetAttrId(cls, &PyId___bases__); Py_END_ALLOW_RECURSION if (bases == NULL) { if (PyErr_ExceptionMatches(PyExc_AttributeError)) @@ -2519,19 +2506,13 @@ static int recursive_isinstance(PyObject *inst, PyObject *cls) { PyObject *icls; - static PyObject *__class__ = NULL; int retval = 0; - - if (__class__ == NULL) { - __class__ = PyUnicode_InternFromString("__class__"); - if (__class__ == NULL) - return -1; - } + _Py_IDENTIFIER(__class__); if (PyType_Check(cls)) { retval = PyObject_TypeCheck(inst, (PyTypeObject *)cls); if (retval == 0) { - PyObject *c = PyObject_GetAttr(inst, __class__); + PyObject *c = _PyObject_GetAttrId(inst, &PyId___class__); if (c == NULL) { if (PyErr_ExceptionMatches(PyExc_AttributeError)) PyErr_Clear(); @@ -2552,7 +2533,7 @@ recursive_isinstance(PyObject *inst, PyObject *cls) if (!check_class(cls, "isinstance() arg 2 must be a type or tuple of types")) return -1; - icls = PyObject_GetAttr(inst, __class__); + icls = _PyObject_GetAttrId(inst, &PyId___class__); if (icls == NULL) { if (PyErr_ExceptionMatches(PyExc_AttributeError)) PyErr_Clear(); -- cgit v0.12 From 1b1a8e7cb514d95546af9dcfd42b83cea27182fa Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Tue, 20 Mar 2012 23:48:11 -0400 Subject: correctly lookup __trunc__ in int() constructor --- Lib/test/test_descr.py | 1 + Objects/abstract.c | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 5759eff..3051e57 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -1770,6 +1770,7 @@ order (MRO) for bases """ ("__format__", format, format_impl, set(), {}), ("__floor__", math.floor, zero, set(), {}), ("__trunc__", math.trunc, zero, set(), {}), + ("__trunc__", int, zero, set(), {}), ("__ceil__", math.ceil, zero, set(), {}), ("__dir__", dir, empty_seq, set(), {}), ] diff --git a/Objects/abstract.c b/Objects/abstract.c index b8df950..924ccd1 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -1350,7 +1350,7 @@ PyNumber_Long(PyObject *o) } if (PyLong_Check(o)) /* An int subclass without nb_int */ return _PyLong_Copy((PyLongObject *)o); - trunc_func = _PyObject_GetAttrId(o, &PyId___trunc__); + trunc_func = _PyObject_LookupSpecial(o, &PyId___trunc__); if (trunc_func) { PyObject *truncated = PyEval_CallObject(trunc_func, NULL); PyObject *int_instance; @@ -1362,7 +1362,8 @@ PyNumber_Long(PyObject *o) "__trunc__ returned non-Integral (type %.200s)"); return int_instance; } - PyErr_Clear(); /* It's not an error if o.__trunc__ doesn't exist. */ + if (PyErr_Occurred()) + return NULL; if (PyBytes_Check(o)) /* need to do extra error checking that PyLong_FromString() -- cgit v0.12 From d614e707caafc87bd644c1da51ea817c3df54d7b Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Wed, 21 Mar 2012 14:38:11 -0400 Subject: rewrite this function, which was still accounting for classic classes --- Objects/abstract.c | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/Objects/abstract.c b/Objects/abstract.c index 924ccd1..345b96a 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -1271,34 +1271,22 @@ PyNumber_AsSsize_t(PyObject *item, PyObject *err) PyObject * _PyNumber_ConvertIntegralToInt(PyObject *integral, const char* error_format) { - static PyObject *int_name = NULL; - if (int_name == NULL) { - int_name = PyUnicode_InternFromString("__int__"); - if (int_name == NULL) - return NULL; - } - - if (integral && !PyLong_Check(integral)) { - /* Don't go through tp_as_number->nb_int to avoid - hitting the classic class fallback to __trunc__. */ - PyObject *int_func = PyObject_GetAttr(integral, int_name); - if (int_func == NULL) { - PyErr_Clear(); /* Raise a different error. */ - goto non_integral_error; - } + PyNumberMethods *nb; + if (PyLong_Check(integral)) + return integral; + nb = Py_TYPE(integral)->tp_as_number; + if (nb->nb_int) { + PyObject *as_int = nb->nb_int(integral); Py_DECREF(integral); - integral = PyEval_CallObject(int_func, NULL); - Py_DECREF(int_func); - if (integral && !PyLong_Check(integral)) { - goto non_integral_error; - } + if (!as_int) + return NULL; + if (PyLong_Check(as_int)) + return as_int; + Py_DECREF(as_int); } - return integral; - -non_integral_error: PyErr_Format(PyExc_TypeError, error_format, Py_TYPE(integral)->tp_name); Py_DECREF(integral); - return NULL; + return NULL; } -- cgit v0.12 From b7f1da5a3c699fe95d7364f29c71f101e65257fa Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Wed, 21 Mar 2012 14:44:43 -0400 Subject: make _PyNumber_ConvertIntegralToInt static, since it's only used in abstract.c --- Include/abstract.h | 15 --------------- Objects/abstract.c | 14 ++++++++++---- 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/Include/abstract.h b/Include/abstract.h index 3a99c4e..4a27bfb 100644 --- a/Include/abstract.h +++ b/Include/abstract.h @@ -773,21 +773,6 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/ PyAPI_FUNC(Py_ssize_t) PyNumber_AsSsize_t(PyObject *o, PyObject *exc); /* - Returns the Integral instance converted to an int. The - instance is expected to be int or long or have an __int__ - method. Steals integral's reference. error_format will be - used to create the TypeError if integral isn't actually an - Integral instance. error_format should be a format string - that can accept a char* naming integral's type. - */ - -#ifndef Py_LIMITED_API - PyAPI_FUNC(PyObject *) _PyNumber_ConvertIntegralToInt( - PyObject *integral, - const char* error_format); -#endif - - /* Returns the object converted to Py_ssize_t by going through PyNumber_Index first. If an overflow error occurs while converting the int-or-long to Py_ssize_t, then the second argument diff --git a/Objects/abstract.c b/Objects/abstract.c index 345b96a..e60601b 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -1268,8 +1268,15 @@ PyNumber_AsSsize_t(PyObject *item, PyObject *err) } -PyObject * -_PyNumber_ConvertIntegralToInt(PyObject *integral, const char* error_format) +/* + Returns the Integral instance converted to an int. The instance is expected + to be an int or have an __int__ method. Steals integral's + reference. error_format will be used to create the TypeError if integral + isn't actually an Integral instance. error_format should be a format string + that can accept a char* naming integral's type. +*/ +static PyObject * +convert_integral_to_int(PyObject *integral, const char *error_format) { PyNumberMethods *nb; if (PyLong_Check(integral)) @@ -1345,8 +1352,7 @@ PyNumber_Long(PyObject *o) Py_DECREF(trunc_func); /* __trunc__ is specified to return an Integral type, but long() needs to return a long. */ - int_instance = _PyNumber_ConvertIntegralToInt( - truncated, + int_instance = convert_integral_to_int(truncated, "__trunc__ returned non-Integral (type %.200s)"); return int_instance; } -- cgit v0.12 From 520e8508a005252fbe0742458bc894475bbb195a Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Wed, 21 Mar 2012 14:51:14 -0400 Subject: long() -> int() --- Objects/abstract.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Objects/abstract.c b/Objects/abstract.c index e60601b..4737d54 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -1351,7 +1351,7 @@ PyNumber_Long(PyObject *o) PyObject *int_instance; Py_DECREF(trunc_func); /* __trunc__ is specified to return an Integral type, - but long() needs to return a long. */ + but int() needs to return a int. */ int_instance = convert_integral_to_int(truncated, "__trunc__ returned non-Integral (type %.200s)"); return int_instance; @@ -1361,7 +1361,7 @@ PyNumber_Long(PyObject *o) if (PyBytes_Check(o)) /* need to do extra error checking that PyLong_FromString() - * doesn't do. In particular long('9.5') must raise an + * doesn't do. In particular int('9.5') must raise an * exception, not truncate the float. */ return long_from_string(PyBytes_AS_STRING(o), -- cgit v0.12 From e112153727def076478a84733f30a8f44f4c8844 Mon Sep 17 00:00:00 2001 From: R David Murray Date: Wed, 21 Mar 2012 14:53:42 -0400 Subject: #12757: Make doctest skipping in -OO mode work with unittest/regrtest -v --- Lib/doctest.py | 10 +++++++--- Misc/NEWS | 3 +++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Lib/doctest.py b/Lib/doctest.py index 234733e..cc3b425 100644 --- a/Lib/doctest.py +++ b/Lib/doctest.py @@ -2266,7 +2266,8 @@ class DocTestCase(unittest.TestCase): return "Doctest: " + self._dt_test.name class SkipDocTestCase(DocTestCase): - def __init__(self): + def __init__(self, module): + self.module = module DocTestCase.__init__(self, None) def setUp(self): @@ -2276,7 +2277,10 @@ class SkipDocTestCase(DocTestCase): pass def shortDescription(self): - return "Skipping tests from %s" % module.__name__ + return "Skipping tests from %s" % self.module.__name__ + + __str__ = shortDescription + def DocTestSuite(module=None, globs=None, extraglobs=None, test_finder=None, **options): @@ -2324,7 +2328,7 @@ def DocTestSuite(module=None, globs=None, extraglobs=None, test_finder=None, if not tests and sys.flags.optimize >=2: # Skip doctests when running with -O2 suite = unittest.TestSuite() - suite.addTest(SkipDocTestCase()) + suite.addTest(SkipDocTestCase(module)) return suite elif not tests: # Why do we want to do this? Because it reveals a bug that might diff --git a/Misc/NEWS b/Misc/NEWS index dcf4e23..606898f 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -28,6 +28,9 @@ Core and Builtins Library ------- +- Issue #12757: Fix the skipping of doctests when python is run with -OO so + that it works in unittest's verbose mode as well as non-verbose mode. + - Issue #3573: IDLE hangs when passing invalid command line args (directory(ies) instead of file(s)) (Patch by Guilherme Polo) -- cgit v0.12