Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
4 changes: 2 additions & 2 deletions Lib/contextlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ def __init__(self, gen):

def __enter__(self):
try:
return self.gen.next()
return next(self.gen)
except StopIteration:
raise RuntimeError("generator didn't yield")

def __exit__(self, type, value, traceback):
if type is None:
try:
self.gen.next()
next(self.gen)
except StopIteration:
return
else:
Expand Down
35 changes: 32 additions & 3 deletions Lib/test/test_py3kwarn.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,34 @@ def test_sort_cmp_arg(self):
w.reset()
self.assertWarning(sorted(lst, cmp), w, expected)

def test_next_method(self):
expected = 'iterator.next() is not supported in 3.x'
it = iter(range(5))
with check_py3k_warnings() as w:
self.assertWarning(it.next(), w, expected)

def test_intern(self):
expected = 'intern() is not supported in 3.x: use sys.intern() instead'
with check_py3k_warnings() as w:
self.assertWarning(intern('pygrate-next-method'), w, expected)

def test_range_materialization(self):
expected = 'range() may require list materialization in 3.x'
with check_py3k_warnings() as w:
self.assertWarning(range(5) + [5], w, expected)

def test_xrange_materialization(self):
expected = 'xrange() may require list materialization in 3.x'
with check_py3k_warnings() as w:
items = xrange(5)
self.assertWarning(None, w, expected)

def test_dict_listlike_materialization(self):
expected = 'dict.keys() may require list materialization in 3.x'
d = {'a': 1, 'b': 2}
with check_py3k_warnings() as w:
self.assertWarning(d.keys()[0], w, expected)

def test_sys_exc_clear(self):
expected = 'sys.exc_clear() not supported in 3.x; use except clauses'
with check_py3k_warnings() as w:
Expand Down Expand Up @@ -288,9 +316,10 @@ def test_bytesio_truncate(self):
from io import BytesIO
x = BytesIO(b'AAAAAA')
expected = "BytesIO.truncate() does not shift the file pointer: use seek(0) before doing truncate(0)"
self.assertWarning(x.truncate(0), w, expected)
w.reset()
self.assertNoWarning(x.truncate(-1), w)
with check_py3k_warnings() as w:
self.assertWarning(x.truncate(0), w, expected)
w.reset()
self.assertNoWarning(x.truncate(-1), w)

def test_file_open(self):
expected = ("The builtin 'file()'/'open()' function is not supported in 3.x, "
Expand Down
59 changes: 59 additions & 0 deletions Objects/dictobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
*/

#include "Python.h"
#include "frameobject.h"
#include "opcode.h"


/* Set a key error with the specified argument, wrapping it in a
Expand All @@ -27,6 +29,57 @@ set_key_error(PyObject *arg)
/* Define this out if you don't want conversion statistics on exit. */
#undef SHOW_CONVERSION_COUNTS

static int
py3kwarn_next_opcode(void)
{
PyFrameObject *frame;
char *code;
Py_ssize_t n;
int offset;
int op;
int steps;

frame = PyEval_GetFrame();
if (frame == NULL || frame->f_code == NULL)
return -1;
if (PyString_AsStringAndSize(frame->f_code->co_code, &code, &n) < 0) {
PyErr_Clear();
return -1;
}

offset = frame->f_lasti;
if (offset < 0 || offset >= n)
return -1;

op = (unsigned char)code[offset];
offset += 1;
if (HAS_ARG(op))
offset += 2;

for (steps = 0; steps < 8 && offset >= 0 && offset < n; steps++) {
op = (unsigned char)code[offset];
if (op == BINARY_ADD || op == INPLACE_ADD || op == GET_ITER ||
op == BINARY_SUBSCR || op == STORE_SUBSCR)
return op;
if (op == RETURN_VALUE || op == STORE_NAME || op == STORE_FAST ||
op == STORE_GLOBAL || op == STORE_ATTR || op == POP_TOP)
return -1;
offset += 1;
if (HAS_ARG(op))
offset += 2;
}
return -1;
}

#define WARN_DICT_LISTLIKE(MSG) \
do { \
int nextop = py3kwarn_next_opcode(); \
if ((nextop == BINARY_SUBSCR || nextop == STORE_SUBSCR || \
nextop == BINARY_ADD || nextop == INPLACE_ADD) && \
PyErr_WarnPy3k((MSG), 1) < 0) \
return NULL; \
} while (0)

/* See large comment block below. This must be >= 1. */
#define PERTURB_SHIFT 5

Expand Down Expand Up @@ -1301,6 +1354,8 @@ dict_keys(register PyDictObject *mp)
PyDictEntry *ep;
Py_ssize_t mask, n;

WARN_DICT_LISTLIKE("dict.keys() may require list materialization in 3.x");

again:
n = mp->ma_used;
v = PyList_New(n);
Expand Down Expand Up @@ -1335,6 +1390,8 @@ dict_values(register PyDictObject *mp)
PyDictEntry *ep;
Py_ssize_t mask, n;

WARN_DICT_LISTLIKE("dict.values() may require list materialization in 3.x");

again:
n = mp->ma_used;
v = PyList_New(n);
Expand Down Expand Up @@ -1370,6 +1427,8 @@ dict_items(register PyDictObject *mp)
PyObject *item, *key, *value;
PyDictEntry *ep;

WARN_DICT_LISTLIKE("dict.items() may require list materialization in 3.x");

/* Preallocate the list of tuples, to avoid allocations during
* the loop over the items, which could trigger GC, which
* could resize the dict. :-(
Expand Down
57 changes: 55 additions & 2 deletions Objects/rangeobject.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/* Range object implementation */

#include "Python.h"
#include "frameobject.h"
#include "opcode.h"

typedef struct {
PyObject_HEAD
Expand All @@ -9,6 +11,48 @@ typedef struct {
long len;
} rangeobject;

static int
py3kwarn_next_opcode(void)
{
PyFrameObject *frame;
char *code;
Py_ssize_t n;
int offset;
int op;
int steps;

frame = PyEval_GetFrame();
if (frame == NULL || frame->f_code == NULL)
return -1;
if (PyString_AsStringAndSize(frame->f_code->co_code, &code, &n) < 0) {
PyErr_Clear();
return -1;
}

offset = frame->f_lasti;
if (offset < 0 || offset >= n)
return -1;

op = (unsigned char)code[offset];
offset += 1;
if (HAS_ARG(op))
offset += 2;

for (steps = 0; steps < 8 && offset >= 0 && offset < n; steps++) {
op = (unsigned char)code[offset];
if (op == BINARY_ADD || op == INPLACE_ADD || op == GET_ITER ||
op == BINARY_SUBSCR || op == STORE_SUBSCR)
return op;
if (op == RETURN_VALUE || op == STORE_NAME || op == STORE_FAST ||
op == STORE_GLOBAL || op == STORE_ATTR || op == POP_TOP)
return -1;
offset += 1;
if (HAS_ARG(op))
offset += 2;
}
return -1;
}

/* Return number of items in range (lo, hi, step). step != 0
* required. The result always fits in an unsigned long.
*/
Expand Down Expand Up @@ -67,9 +111,18 @@ range_new(PyTypeObject *type, PyObject *args, PyObject *kw)
rangeobject *obj;
long ilow = 0, ihigh = 0, istep = 1;
unsigned long n;
int nextop;

if (PyErr_WarnPy3k_WithFix("xrange() is not supported in 3.x", "use range() instead", 1) < 0)
return NULL;
nextop = py3kwarn_next_opcode();
if (nextop == GET_ITER) {
if (PyErr_WarnPy3k_WithFix("xrange() is not supported in 3.x",
"use range() instead", 1) < 0)
return NULL;
}
else {
if (PyErr_WarnPy3k("xrange() may require list materialization in 3.x", 1) < 0)
return NULL;
}

if (!_PyArg_NoKeywords("xrange()", kw))
return NULL;
Expand Down
4 changes: 4 additions & 0 deletions Objects/typeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -4857,6 +4857,10 @@ wrap_next(PyObject *self, PyObject *args, void *wrapped)

if (!check_num_args(args, 0))
return NULL;
if (Py_TYPE(self)->tp_iter != NULL) {
if (PyErr_WarnPy3k("iterator.next() is not supported in 3.x", 1) < 0)
return NULL;
}
res = (*func)(self);
if (res == NULL && !PyErr_Occurred())
PyErr_SetNone(PyExc_StopIteration);
Expand Down
53 changes: 53 additions & 0 deletions Python/bltinmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

#include "Python.h"
#include "Python-ast.h"
#include "frameobject.h"

#include "node.h"
#include "code.h"
#include "eval.h"
#include "opcode.h"

#include <ctype.h>
#include <float.h> /* for DBL_MANT_DIG and friends */
Expand All @@ -32,6 +34,48 @@ static PyObject *filterunicode(PyObject *, PyObject *);
#endif
static PyObject *filtertuple (PyObject *, PyObject *);

static int
py3kwarn_next_opcode(void)
{
PyFrameObject *frame;
char *code;
Py_ssize_t n;
int offset;
int op;
int steps;

frame = PyEval_GetFrame();
if (frame == NULL || frame->f_code == NULL)
return -1;
if (PyString_AsStringAndSize(frame->f_code->co_code, &code, &n) < 0) {
PyErr_Clear();
return -1;
}

offset = frame->f_lasti;
if (offset < 0 || offset >= n)
return -1;

op = (unsigned char)code[offset];
offset += 1;
if (HAS_ARG(op))
offset += 2;

for (steps = 0; steps < 8 && offset >= 0 && offset < n; steps++) {
op = (unsigned char)code[offset];
if (op == BINARY_ADD || op == INPLACE_ADD || op == GET_ITER ||
op == BINARY_SUBSCR || op == STORE_SUBSCR)
return op;
if (op == RETURN_VALUE || op == STORE_NAME || op == STORE_FAST ||
op == STORE_GLOBAL || op == STORE_ATTR || op == POP_TOP)
return -1;
offset += 1;
if (HAS_ARG(op))
offset += 2;
}
return -1;
}

static PyObject *
builtin___import__(PyObject *self, PyObject *args, PyObject *kwds)
{
Expand Down Expand Up @@ -1282,6 +1326,9 @@ builtin_intern(PyObject *self, PyObject *args)
"can't intern subclass of string");
return NULL;
}
if (PyErr_WarnPy3k("intern() is not supported in 3.x: use sys.intern() instead",
1) < 0)
return NULL;
Py_INCREF(s);
PyString_InternInPlace(&s);
return s;
Expand Down Expand Up @@ -1970,9 +2017,15 @@ builtin_range(PyObject *self, PyObject *args)
long ilow = 0, ihigh = 0, istep = 1;
long bign;
Py_ssize_t i, n;
int nextop;

PyObject *v;

nextop = py3kwarn_next_opcode();
if ((nextop == BINARY_ADD || nextop == INPLACE_ADD) &&
PyErr_WarnPy3k("range() may require list materialization in 3.x", 1) < 0)
return NULL;

if (PyTuple_Size(args) <= 1) {
if (!PyArg_ParseTuple(args,
"l;range() requires 1-3 int arguments",
Expand Down