[pypy-commit] pypy refactor-PyFloat_FromString: refactor possible recursion in PyFloat_FromString
mattip
pypy.commits at gmail.com
Thu Nov 16 10:21:27 EST 2017
Author: Matti Picus <matti.picus at gmail.com>
Branch: refactor-PyFloat_FromString
Changeset: r93055:57019e77c377
Date: 2017-11-16 17:19 +0200
http://bitbucket.org/pypy/pypy/changeset/57019e77c377/
Log: refactor possible recursion in PyFloat_FromString
diff --git a/pypy/module/cpyext/floatobject.py b/pypy/module/cpyext/floatobject.py
--- a/pypy/module/cpyext/floatobject.py
+++ b/pypy/module/cpyext/floatobject.py
@@ -1,12 +1,12 @@
from rpython.rtyper.lltypesystem import rffi, lltype
+from rpython.rlib import rarithmetic
from pypy.module.cpyext.api import (PyObjectFields, bootstrap_function,
cpython_struct,
CANNOT_FAIL, cpython_api, PyObject, build_type_checkers, CONST_STRING)
from pypy.module.cpyext.pyobject import (
make_typedescr, track_reference, from_ref)
-from pypy.interpreter.error import OperationError
from rpython.rlib.rstruct import runpack
-from pypy.objspace.std.floatobject import W_FloatObject
+from pypy.objspace.std.floatobject import W_FloatObject, basestring_to_float
PyFloatObjectStruct = lltype.ForwardReference()
PyFloatObject = lltype.Ptr(PyFloatObjectStruct)
@@ -66,7 +66,10 @@
"""Create a PyFloatObject object based on the string value in str, or
NULL on failure. The pend argument is ignored. It remains only for
backward compatibility."""
- return space.call_function(space.w_float, w_obj)
+ # avoid space.call_function(space.w_float, w_obj) since PyFloat_FromString
+ # could be type.tp_as_number.nb_float which would recurse
+ value = basestring_to_float(space, w_obj)
+ return space.newfloat(value)
@cpython_api([CONST_STRING, rffi.INT_real], rffi.DOUBLE, error=-1.0)
def _PyFloat_Unpack4(space, ptr, le):
diff --git a/pypy/objspace/std/floatobject.py b/pypy/objspace/std/floatobject.py
--- a/pypy/objspace/std/floatobject.py
+++ b/pypy/objspace/std/floatobject.py
@@ -135,6 +135,28 @@
return space.w_NotImplemented
return func_with_new_name(_compare, 'descr_' + opname)
+def basestring_to_float(space, w_value):
+ def _string_to_float(space, w_source, string):
+ try:
+ return rfloat.string_to_float(string)
+ except ParseStringError as e:
+ raise wrap_parsestringerror(space, e, w_source)
+
+ if space.isinstance_w(w_value, space.w_unicode):
+ from unicodeobject import unicode_to_decimal_w
+ value = _string_to_float(space, w_value,
+ unicode_to_decimal_w(space, w_value))
+ else:
+ try:
+ value = space.charbuf_w(w_value)
+ except OperationError as e:
+ if e.match(space, space.w_TypeError):
+ raise oefmt(
+ space.w_TypeError,
+ "float() argument must be a string or a number")
+ raise
+ value = _string_to_float(space, w_value, value)
+ return value
class W_FloatObject(W_Root):
"""This is a implementation of the app-level 'float' type.
@@ -193,32 +215,14 @@
@staticmethod
@unwrap_spec(w_x=WrappedDefault(0.0))
def descr__new__(space, w_floattype, w_x):
- def _string_to_float(space, w_source, string):
- try:
- return rfloat.string_to_float(string)
- except ParseStringError as e:
- raise wrap_parsestringerror(space, e, w_source)
-
w_value = w_x # 'x' is the keyword argument name in CPython
if space.lookup(w_value, "__float__") is not None:
w_obj = space.float(w_value)
if space.is_w(w_floattype, space.w_float):
return w_obj
value = space.float_w(w_obj)
- elif space.isinstance_w(w_value, space.w_unicode):
- from unicodeobject import unicode_to_decimal_w
- value = _string_to_float(space, w_value,
- unicode_to_decimal_w(space, w_value))
else:
- try:
- value = space.charbuf_w(w_value)
- except OperationError as e:
- if e.match(space, space.w_TypeError):
- raise oefmt(
- space.w_TypeError,
- "float() argument must be a string or a number")
- raise
- value = _string_to_float(space, w_value, value)
+ value = basestring_to_float(space, w_value)
w_obj = space.allocate_instance(W_FloatObject, w_floattype)
W_FloatObject.__init__(w_obj, value)
return w_obj
More information about the pypy-commit
mailing list