Skip to content

Commit f5ffcd8

Browse files
author
thomas.wouters
committed
from __future__ import with_statement addon for 'with', mostly written by Neal. git-svn-id: http://svn.python.org/projects/python/trunk@42667 6015fed2-1504-0410-9fe1-9d1591cc4771
1 parent 8fc7de1 commit f5ffcd8

File tree

16 files changed

+102
-40
lines changed

16 files changed

+102
-40
lines changed

Include/code.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ typedef struct {
4646
#endif
4747
#define CO_FUTURE_DIVISION 0x2000
4848
#define CO_FUTURE_ABSIMPORT 0x4000 /* absolute import by default */
49+
#define CO_FUTURE_WITH_STATEMENT 0x8000
50+
51+
/* This should be defined if a future statement modifies the syntax.
52+
For example, when a keyword is added.
53+
*/
54+
#define PY_PARSER_REQUIRES_FUTURE_KEYWORD
4955

5056
#define CO_MAXBLOCKS 20 /* Max static block nesting within a function */
5157

Include/compile.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ typedef struct {
2323
#define FUTURE_GENERATORS "generators"
2424
#define FUTURE_DIVISION "division"
2525
#define FUTURE_ABSIMPORT "absolute_import"
26+
#define FUTURE_WITH_STATEMENT "with_statement"
2627

2728
struct _mod; /* Declare the existence of this type */
2829
PyAPI_FUNC(PyCodeObject *) PyAST_Compile(struct _mod *, const char *,

Include/modsupport.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ PyAPI_FUNC(int) PyModule_AddIntConstant(PyObject *, const char *, long);
3939
PyAPI_FUNC(int) PyModule_AddStringConstant(PyObject *, const char *, const char *);
4040

4141

42-
#define PYTHON_API_VERSION 1012
43-
#define PYTHON_API_STRING "1012"
42+
#define PYTHON_API_VERSION 1013
43+
#define PYTHON_API_STRING "1013"
4444
/* The API version is maintained (independently from the Python version)
4545
so we can detect mismatches between the interpreter and dynamically
4646
loaded modules. These are diagnosed by an error message but
@@ -54,6 +54,8 @@ PyAPI_FUNC(int) PyModule_AddStringConstant(PyObject *, const char *, const char
5454
Please add a line or two to the top of this log for each API
5555
version change:
5656
57+
22-Feb-2006 GvR 1013 PEP 353 - long indices for sequence lengths
58+
5759
19-Aug-2002 GvR 1012 Changes to string object struct for
5860
interning changes, saving 3 bytes.
5961

Include/parsetok.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ typedef struct {
2323

2424
#define PyPARSE_DONT_IMPLY_DEDENT 0x0002
2525

26+
#define PyPARSE_WITH_IS_KEYWORD 0x0003
27+
2628
PyAPI_FUNC(node *) PyParser_ParseString(const char *, grammar *, int,
2729
perrdetail *);
2830
PyAPI_FUNC(node *) PyParser_ParseFile (FILE *, const char *, grammar *, int,

Include/pythonrun.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
extern "C" {
88
#endif
99

10-
#define PyCF_MASK (CO_FUTURE_DIVISION | CO_FUTURE_ABSIMPORT)
10+
#define PyCF_MASK (CO_FUTURE_DIVISION | CO_FUTURE_ABSIMPORT | \
11+
CO_FUTURE_WITH_STATEMENT)
1112
#define PyCF_MASK_OBSOLETE (CO_NESTED)
1213
#define PyCF_SOURCE_IS_UTF8 0x0100
1314
#define PyCF_DONT_IMPLY_DEDENT 0x0200

Lib/__future__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
"generators",
5353
"division",
5454
"absolute_import",
55+
"with_statement",
5556
]
5657

5758
__all__ = ["all_feature_names"] + all_feature_names
@@ -64,6 +65,7 @@
6465
CO_GENERATOR_ALLOWED = 0 # generators (obsolete, was 0x1000)
6566
CO_FUTURE_DIVISION = 0x2000 # division
6667
CO_FUTURE_ABSIMPORT = 0x4000 # absolute_import
68+
CO_FUTURE_WITH_STATEMENT = 0x8000 # with statement added in 2.5
6769

6870
class _Feature:
6971
def __init__(self, optionalRelease, mandatoryRelease, compiler_flag):
@@ -108,3 +110,7 @@ def __repr__(self):
108110
absolute_import = _Feature((2, 5, 0, "alpha", 1),
109111
(2, 7, 0, "alpha", 0),
110112
CO_FUTURE_ABSIMPORT)
113+
114+
with_statement = _Feature((2, 5, 0, "alpha", 2),
115+
(2, 6, 0, "alpha", 0),
116+
CO_FUTURE_WITH_STATEMENT)

Lib/compiler/future.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ def is_future(stmt):
1515

1616
class FutureParser:
1717

18-
features = ("nested_scopes", "generators", "division")
18+
features = ("nested_scopes", "generators", "division",
19+
"absolute_import", "with_statement")
1920

2021
def __init__(self):
2122
self.found = {} # set

Lib/test/test_with.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
"""Unit tests for the with statement specified in PEP 343."""
44

5+
from __future__ import with_statement
6+
57
__author__ = "Mike Bland"
68
__email__ = "mbland at acm dot org"
79

Misc/NEWS

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ Core and builtins
3232
- dict.__getitem__ now looks for a __missing__ hook before raising
3333
KeyError.
3434

35-
- PEP 343: with statement implemented.
35+
- PEP 343: with statement implemented. Needs 'from __future__ import
36+
with_statement'. Use of 'with' as a variable will generate a warning.
3637

3738
- Fix the encodings package codec search function to only search
3839
inside its own package. Fixes problem reported in patch #1433198.

Parser/parser.c

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ PyParser_New(grammar *g, int start)
7979
if (ps == NULL)
8080
return NULL;
8181
ps->p_grammar = g;
82-
#if 0 /* future keyword */
83-
ps->p_generators = 0;
82+
#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
83+
ps->p_flags = 0;
8484
#endif
8585
ps->p_tree = PyNode_New(start);
8686
if (ps->p_tree == NULL) {
@@ -147,10 +147,10 @@ classify(parser_state *ps, int type, char *str)
147147
if (l->lb_type == NAME && l->lb_str != NULL &&
148148
l->lb_str[0] == s[0] &&
149149
strcmp(l->lb_str, s) == 0) {
150-
#if 0 /* future keyword */
151-
if (!ps->p_generators &&
152-
s[0] == 'y' &&
153-
strcmp(s, "yield") == 0)
150+
#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
151+
if (!(ps->p_flags & CO_FUTURE_WITH_STATEMENT) &&
152+
s[0] == 'w' &&
153+
strcmp(s, "with") == 0)
154154
break; /* not a keyword */
155155
#endif
156156
D(printf("It's a keyword\n"));
@@ -174,24 +174,35 @@ classify(parser_state *ps, int type, char *str)
174174
return -1;
175175
}
176176

177-
#if 0 /* future keyword */
177+
#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
178178
static void
179179
future_hack(parser_state *ps)
180180
{
181181
node *n = ps->p_stack.s_top->s_parent;
182182
node *ch;
183183
int i;
184184

185-
if (strcmp(STR(CHILD(n, 0)), "from") != 0)
185+
/* from __future__ import ..., must have at least 4 children */
186+
n = CHILD(n, 0);
187+
if (NCH(n) < 4)
188+
return;
189+
ch = CHILD(n, 0);
190+
if (STR(ch) == NULL || strcmp(STR(ch), "from") != 0)
186191
return;
187192
ch = CHILD(n, 1);
188-
if (strcmp(STR(CHILD(ch, 0)), "__future__") != 0)
193+
if (NCH(ch) == 1 && STR(CHILD(ch, 0)) &&
194+
strcmp(STR(CHILD(ch, 0)), "__future__") != 0)
189195
return;
190196
for (i = 3; i < NCH(n); i += 2) {
197+
/* XXX: assume we don't have parentheses in import:
198+
from __future__ import (x, y, z)
199+
*/
191200
ch = CHILD(n, i);
201+
if (NCH(ch) == 1)
202+
ch = CHILD(ch, 0);
192203
if (NCH(ch) >= 1 && TYPE(CHILD(ch, 0)) == NAME &&
193-
strcmp(STR(CHILD(ch, 0)), "generators") == 0) {
194-
ps->p_generators = 1;
204+
strcmp(STR(CHILD(ch, 0)), "with_statement") == 0) {
205+
ps->p_flags |= CO_FUTURE_WITH_STATEMENT;
195206
break;
196207
}
197208
}
@@ -255,7 +266,7 @@ PyParser_AddToken(register parser_state *ps, register int type, char *str,
255266
"Direct pop.\n",
256267
d->d_name,
257268
ps->p_stack.s_top->s_state));
258-
#if 0 /* future keyword */
269+
#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
259270
if (d->d_name[0] == 'i' &&
260271
strcmp(d->d_name,
261272
"import_stmt") == 0)
@@ -273,7 +284,7 @@ PyParser_AddToken(register parser_state *ps, register int type, char *str,
273284
}
274285

275286
if (s->s_accept) {
276-
#if 0 /* future keyword */
287+
#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
277288
if (d->d_name[0] == 'i' &&
278289
strcmp(d->d_name, "import_stmt") == 0)
279290
future_hack(ps);

0 commit comments

Comments
 (0)