Skip to content

Commit 305a289

Browse files
author
Eddy Xu
committed
add warnings message
fix some design issues.
1 parent 48d6ad4 commit 305a289

8 files changed

Lines changed: 62 additions & 146 deletions

File tree

Include/ceval.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ PyAPI_FUNC(PyObject *) PyEval_GetGlobals(void);
3030
PyAPI_FUNC(PyObject *) PyEval_GetLocals(void);
3131
PyAPI_FUNC(struct _frame *) PyEval_GetFrame(void);
3232
PyAPI_FUNC(int) PyEval_GetRestricted(void);
33+
PyAPI_FUNC(int) _Py3kWarn_NextOpcode(void);
3334

3435
/* Look at the current frame's (if any) code's co_flags, and turn on
3536
the corresponding compiler flags in cf->cf_flags. Return 1 if any

Include/warnings.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,3 @@ PyAPI_FUNC(int) PyErr_WarnExplicit_WithFix(PyObject *, const char *, const char
2626
}
2727
#endif
2828
#endif /* !Py_WARNINGS_H */
29-

Lib/test/test_py3kwarn.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ def test_sort_cmp_arg(self):
222222
self.assertWarning(sorted(lst, cmp), w, expected)
223223

224224
def test_next_method(self):
225-
expected = 'iterator.next() is not supported in 3.x'
225+
expected = 'iterator.next() is not supported in 3.x; use __next__() instead'
226226
it = iter(range(5))
227227
with check_py3k_warnings() as w:
228228
self.assertWarning(it.next(), w, expected)

Objects/dictobject.c

Lines changed: 1 addition & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
*/
99

1010
#include "Python.h"
11-
#include "frameobject.h"
1211
#include "opcode.h"
1312

1413

@@ -29,51 +28,9 @@ set_key_error(PyObject *arg)
2928
/* Define this out if you don't want conversion statistics on exit. */
3029
#undef SHOW_CONVERSION_COUNTS
3130

32-
static int
33-
py3kwarn_next_opcode(void)
34-
{
35-
PyFrameObject *frame;
36-
char *code;
37-
Py_ssize_t n;
38-
int offset;
39-
int op;
40-
int steps;
41-
42-
frame = PyEval_GetFrame();
43-
if (frame == NULL || frame->f_code == NULL)
44-
return -1;
45-
if (PyString_AsStringAndSize(frame->f_code->co_code, &code, &n) < 0) {
46-
PyErr_Clear();
47-
return -1;
48-
}
49-
50-
offset = frame->f_lasti;
51-
if (offset < 0 || offset >= n)
52-
return -1;
53-
54-
op = (unsigned char)code[offset];
55-
offset += 1;
56-
if (HAS_ARG(op))
57-
offset += 2;
58-
59-
for (steps = 0; steps < 8 && offset >= 0 && offset < n; steps++) {
60-
op = (unsigned char)code[offset];
61-
if (op == BINARY_ADD || op == INPLACE_ADD || op == GET_ITER ||
62-
op == BINARY_SUBSCR || op == STORE_SUBSCR)
63-
return op;
64-
if (op == RETURN_VALUE || op == STORE_NAME || op == STORE_FAST ||
65-
op == STORE_GLOBAL || op == STORE_ATTR || op == POP_TOP)
66-
return -1;
67-
offset += 1;
68-
if (HAS_ARG(op))
69-
offset += 2;
70-
}
71-
return -1;
72-
}
73-
7431
#define WARN_DICT_LISTLIKE(MSG) \
7532
do { \
76-
int nextop = py3kwarn_next_opcode(); \
33+
int nextop = _Py3kWarn_NextOpcode(); \
7734
if ((nextop == BINARY_SUBSCR || nextop == STORE_SUBSCR || \
7835
nextop == BINARY_ADD || nextop == INPLACE_ADD) && \
7936
PyErr_WarnPy3k((MSG), 1) < 0) \

Objects/rangeobject.c

Lines changed: 7 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
/* Range object implementation */
22

33
#include "Python.h"
4-
#include "frameobject.h"
54
#include "opcode.h"
65

76
typedef struct {
@@ -11,48 +10,6 @@ typedef struct {
1110
long len;
1211
} rangeobject;
1312

14-
static int
15-
py3kwarn_next_opcode(void)
16-
{
17-
PyFrameObject *frame;
18-
char *code;
19-
Py_ssize_t n;
20-
int offset;
21-
int op;
22-
int steps;
23-
24-
frame = PyEval_GetFrame();
25-
if (frame == NULL || frame->f_code == NULL)
26-
return -1;
27-
if (PyString_AsStringAndSize(frame->f_code->co_code, &code, &n) < 0) {
28-
PyErr_Clear();
29-
return -1;
30-
}
31-
32-
offset = frame->f_lasti;
33-
if (offset < 0 || offset >= n)
34-
return -1;
35-
36-
op = (unsigned char)code[offset];
37-
offset += 1;
38-
if (HAS_ARG(op))
39-
offset += 2;
40-
41-
for (steps = 0; steps < 8 && offset >= 0 && offset < n; steps++) {
42-
op = (unsigned char)code[offset];
43-
if (op == BINARY_ADD || op == INPLACE_ADD || op == GET_ITER ||
44-
op == BINARY_SUBSCR || op == STORE_SUBSCR)
45-
return op;
46-
if (op == RETURN_VALUE || op == STORE_NAME || op == STORE_FAST ||
47-
op == STORE_GLOBAL || op == STORE_ATTR || op == POP_TOP)
48-
return -1;
49-
offset += 1;
50-
if (HAS_ARG(op))
51-
offset += 2;
52-
}
53-
return -1;
54-
}
55-
5613
/* Return number of items in range (lo, hi, step). step != 0
5714
* required. The result always fits in an unsigned long.
5815
*/
@@ -113,16 +70,14 @@ range_new(PyTypeObject *type, PyObject *args, PyObject *kw)
11370
unsigned long n;
11471
int nextop;
11572

116-
nextop = py3kwarn_next_opcode();
117-
if (nextop == GET_ITER) {
118-
if (PyErr_WarnPy3k_WithFix("xrange() is not supported in 3.x",
73+
nextop = _Py3kWarn_NextOpcode();
74+
if (nextop == GET_ITER &&
75+
PyErr_WarnPy3k_WithFix("xrange() is not supported in 3.x",
11976
"use range() instead", 1) < 0)
120-
return NULL;
121-
}
122-
else {
123-
if (PyErr_WarnPy3k("xrange() may require list materialization in 3.x", 1) < 0)
124-
return NULL;
125-
}
77+
return NULL;
78+
if (nextop != GET_ITER &&
79+
PyErr_WarnPy3k("xrange() may require list materialization in 3.x", 1) < 0)
80+
return NULL;
12681

12782
if (!_PyArg_NoKeywords("xrange()", kw))
12883
return NULL;

Objects/typeobject.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4857,10 +4857,10 @@ wrap_next(PyObject *self, PyObject *args, void *wrapped)
48574857

48584858
if (!check_num_args(args, 0))
48594859
return NULL;
4860-
if (Py_TYPE(self)->tp_iter != NULL) {
4861-
if (PyErr_WarnPy3k("iterator.next() is not supported in 3.x", 1) < 0)
4862-
return NULL;
4863-
}
4860+
if (Py_TYPE(self)->tp_iter != NULL &&
4861+
PyErr_WarnPy3k("iterator.next() is not supported in 3.x; "
4862+
"use __next__() instead", 1) < 0)
4863+
return NULL;
48644864
res = (*func)(self);
48654865
if (res == NULL && !PyErr_Occurred())
48664866
PyErr_SetNone(PyExc_StopIteration);

Python/bltinmodule.c

Lines changed: 1 addition & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
#include "Python.h"
44
#include "Python-ast.h"
5-
#include "frameobject.h"
65

76
#include "node.h"
87
#include "code.h"
@@ -34,48 +33,6 @@ static PyObject *filterunicode(PyObject *, PyObject *);
3433
#endif
3534
static PyObject *filtertuple (PyObject *, PyObject *);
3635

37-
static int
38-
py3kwarn_next_opcode(void)
39-
{
40-
PyFrameObject *frame;
41-
char *code;
42-
Py_ssize_t n;
43-
int offset;
44-
int op;
45-
int steps;
46-
47-
frame = PyEval_GetFrame();
48-
if (frame == NULL || frame->f_code == NULL)
49-
return -1;
50-
if (PyString_AsStringAndSize(frame->f_code->co_code, &code, &n) < 0) {
51-
PyErr_Clear();
52-
return -1;
53-
}
54-
55-
offset = frame->f_lasti;
56-
if (offset < 0 || offset >= n)
57-
return -1;
58-
59-
op = (unsigned char)code[offset];
60-
offset += 1;
61-
if (HAS_ARG(op))
62-
offset += 2;
63-
64-
for (steps = 0; steps < 8 && offset >= 0 && offset < n; steps++) {
65-
op = (unsigned char)code[offset];
66-
if (op == BINARY_ADD || op == INPLACE_ADD || op == GET_ITER ||
67-
op == BINARY_SUBSCR || op == STORE_SUBSCR)
68-
return op;
69-
if (op == RETURN_VALUE || op == STORE_NAME || op == STORE_FAST ||
70-
op == STORE_GLOBAL || op == STORE_ATTR || op == POP_TOP)
71-
return -1;
72-
offset += 1;
73-
if (HAS_ARG(op))
74-
offset += 2;
75-
}
76-
return -1;
77-
}
78-
7936
static PyObject *
8037
builtin___import__(PyObject *self, PyObject *args, PyObject *kwds)
8138
{
@@ -2021,7 +1978,7 @@ builtin_range(PyObject *self, PyObject *args)
20211978

20221979
PyObject *v;
20231980

2024-
nextop = py3kwarn_next_opcode();
1981+
nextop = _Py3kWarn_NextOpcode();
20251982
if ((nextop == BINARY_ADD || nextop == INPLACE_ADD) &&
20261983
PyErr_WarnPy3k("range() may require list materialization in 3.x", 1) < 0)
20271984
return NULL;

Python/ceval.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,53 @@
1919

2020
#include <ctype.h>
2121

22+
int
23+
_Py3kWarn_NextOpcode(void)
24+
{
25+
PyFrameObject *frame;
26+
char *code;
27+
Py_ssize_t n;
28+
int offset;
29+
int op;
30+
int steps;
31+
32+
frame = PyEval_GetFrame();
33+
if (frame == NULL || frame->f_code == NULL)
34+
return -1;
35+
if (PyString_AsStringAndSize(frame->f_code->co_code, &code, &n) < 0) {
36+
PyErr_Clear();
37+
return -1;
38+
}
39+
40+
offset = frame->f_lasti;
41+
if (offset < 0 || offset >= n)
42+
return -1;
43+
44+
op = (unsigned char)code[offset];
45+
offset += 1;
46+
if (HAS_ARG(op))
47+
offset += 2;
48+
49+
/* These warnings only care about the immediate consumer of the
50+
just-evaluated call result. Looking ahead a handful of opcodes is
51+
enough to skip trivial stack setup before we either find a relevant
52+
consumer or hit a stop opcode showing the value has already been
53+
stored, returned, or discarded. */
54+
for (steps = 0; steps < 8 && offset >= 0 && offset < n; steps++) {
55+
op = (unsigned char)code[offset];
56+
if (op == BINARY_ADD || op == INPLACE_ADD || op == GET_ITER ||
57+
op == BINARY_SUBSCR || op == STORE_SUBSCR)
58+
return op;
59+
if (op == RETURN_VALUE || op == STORE_NAME || op == STORE_FAST ||
60+
op == STORE_GLOBAL || op == STORE_ATTR || op == POP_TOP)
61+
return -1;
62+
offset += 1;
63+
if (HAS_ARG(op))
64+
offset += 2;
65+
}
66+
return -1;
67+
}
68+
2269
#ifndef WITH_TSC
2370

2471
#define READ_TIMESTAMP(var)

0 commit comments

Comments
 (0)