Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Include/cpython/floatobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,17 @@
typedef struct {
PyObject_HEAD
double ob_fval;
unsigned char ob_randomflag;
} PyFloatObject;

#define NOT_FROM_RANDOM 0
#define FROM_RANDOM 1

// Macro version of PyFloat_AsDouble() trading safety for speed.
// It doesn't check if op is a double object.
#define PyFloat_AS_DOUBLE(op) (((PyFloatObject *)(op))->ob_fval)

PyAPI_FUNC(PyObject *) _PyFloat_FromDoubleWithFlags(double x, unsigned char flags);

PyAPI_FUNC(int) PyFloat_Pack2(double x, char *p, int le);
PyAPI_FUNC(int) PyFloat_Pack4(double x, char *p, int le);
Expand Down
8 changes: 7 additions & 1 deletion Include/cpython/unicodeobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,8 @@ typedef struct {
unsigned int ascii:1;
/* Padding to ensure that PyUnicode_DATA() is always aligned to
4 bytes (see issue #19537 on m68k). */
unsigned int :25;
unsigned int ob_randomflag:1;
unsigned int :24;
} state;
} PyASCIIObject;

Expand Down Expand Up @@ -500,6 +501,11 @@ PyAPI_FUNC(PyObject*) _PyUnicode_FromASCII(
const char *buffer,
Py_ssize_t size);

PyAPI_FUNC(PyObject*) _PyUnicode_FromASCII_withRandomFlag(
const char *buffer,
Py_ssize_t size,
unsigned char flag);

/* Compute the maximum character of the substring unicode[start:end].
Return 127 for an empty string. */
PyAPI_FUNC(Py_UCS4) _PyUnicode_FindMaxChar (
Expand Down
8 changes: 8 additions & 0 deletions Lib/test/test_py2xwarn.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ def test_next(self):
w.reset()
self.assertNoWarning(iterator_marks.__next__(), w)

def test_random(self):
expected = "String repr of random.random() is longer in 3.x, change code accordingly"
import random
with check_py2x_warnings(("", Py2xWarning)) as w:
self.assertWarning(len(str(random.random())), w, expected)
w.reset()
self.assertNoWarning(len(str(0.123456)), w)

def test_truncate0(self):
expected = "Calling truncate(0) on text stream without seek(0)" + \
" may produce inconsistent results. Use seek(0) before truncate(0)"
Expand Down
9 changes: 8 additions & 1 deletion Modules/_randommodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,14 @@ _random_Random_random_impl(RandomObject *self)
/*[clinic end generated code: output=117ff99ee53d755c input=afb2a59cbbb00349]*/
{
uint32_t a=genrand_uint32(self)>>5, b=genrand_uint32(self)>>6;
return PyFloat_FromDouble((a*67108864.0+b)*(1.0/9007199254740992.0));
double x = (a * 67108864.0 + b) * (1.0 / 9007199254740992.0);
if (Py_Py2xWarningFlag){
return _PyFloat_FromDoubleWithFlags(x,FROM_RANDOM);
}
else{
return PyFloat_FromDouble(x);
}

}

/* initializes mt[N] with a seed */
Expand Down
19 changes: 17 additions & 2 deletions Objects/floatobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,20 @@ PyFloat_FromDouble(double fval)
}
_PyObject_Init((PyObject*)op, &PyFloat_Type);
op->ob_fval = fval;
op->ob_randomflag = NOT_FROM_RANDOM;
return (PyObject *) op;
}

PyObject *
_PyFloat_FromDoubleWithFlags(double x, unsigned char flag)
{
PyObject *o = PyFloat_FromDouble(x);
if (o == NULL)
return NULL;
((PyFloatObject *)o)->ob_randomflag = flag;
return o;
}

static PyObject *
float_from_string_inner(const char *s, Py_ssize_t len, void *obj)
{
Expand Down Expand Up @@ -376,14 +387,18 @@ float_repr(PyFloatObject *v)
{
PyObject *result;
char *buf;

buf = PyOS_double_to_string(PyFloat_AS_DOUBLE(v),
'r', 0,
Py_DTSF_ADD_DOT_0,
NULL);
if (!buf)
return PyErr_NoMemory();
result = _PyUnicode_FromASCII(buf, strlen(buf));
if (Py_Py2xWarningFlag){
result = _PyUnicode_FromASCII_withRandomFlag(buf, strlen(buf), v->ob_randomflag);
}
else{
result = _PyUnicode_FromASCII(buf, strlen(buf));
}
PyMem_Free(buf);
return result;
}
Expand Down
21 changes: 20 additions & 1 deletion Objects/unicodeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -1189,6 +1189,7 @@ PyUnicode_New(Py_ssize_t size, Py_UCS4 maxchar)
_PyUnicode_STATE(unicode).kind = kind;
_PyUnicode_STATE(unicode).compact = 1;
_PyUnicode_STATE(unicode).ascii = is_ascii;
_PyUnicode_STATE(unicode).ob_randomflag = NOT_FROM_RANDOM;
if (is_ascii) {
((char*)data)[size] = 0;
}
Expand Down Expand Up @@ -1935,6 +1936,16 @@ _PyUnicode_FromASCII(const char *buffer, Py_ssize_t size)
return unicode;
}

PyObject*
_PyUnicode_FromASCII_withRandomFlag(const char *buffer, Py_ssize_t size, unsigned char flag)
{
PyObject *o = _PyUnicode_FromASCII(buffer, size);
if (o == NULL)
return NULL;
((PyASCIIObject *)o)->state.ob_randomflag = flag;
return o;
}

static Py_UCS4
kind_maxchar_limit(int kind)
{
Expand Down Expand Up @@ -11605,7 +11616,15 @@ unicode_join(PyObject *self, PyObject *iterable)

static Py_ssize_t
unicode_length(PyObject *self)
{
{
if(Py_Py2xWarningFlag && PyUnicode_Check(self)){
if (((PyASCIIObject *)self)->state.ob_randomflag == 1) {
PyErr_WarnEx(
PyExc_Py2xWarning,
"String repr of random.random() is longer in 3.x, change code accordingly",
1);
}
}
return PyUnicode_GET_LENGTH(self);
}

Expand Down