summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/library/os.rst4
-rw-r--r--Doc/library/subprocess.rst88
-rw-r--r--Doc/whatsnew/2.7.rst6
-rw-r--r--Grammar/Grammar3
-rw-r--r--Lib/multiprocessing/queues.py2
-rw-r--r--Lib/os.py6
-rwxr-xr-xLib/symbol.py2
-rw-r--r--Lib/test/test_generators.py2
-rw-r--r--Lib/test/test_genexps.py2
-rw-r--r--Lib/test/test_syntax.py6
-rw-r--r--Makefile.pre.in2
-rw-r--r--Objects/dictobject.c2
-rw-r--r--Parser/asdl.py22
-rwxr-xr-xParser/asdl_c.py20
-rw-r--r--Python/ast.c24
15 files changed, 118 insertions, 73 deletions
diff --git a/Doc/library/os.rst b/Doc/library/os.rst
index 9bb2fc6..90e59ef 100644
--- a/Doc/library/os.rst
+++ b/Doc/library/os.rst
@@ -1470,8 +1470,8 @@ written in Python, such as a mail server's external command delivery program.
(Note that the :mod:`subprocess` module provides more powerful facilities for
spawning new processes and retrieving their results; using that module is
- preferable to using these functions. Check specially the *Replacing Older
- Functions with the subprocess Module* section in that documentation page.)
+ preferable to using these functions. Check especially the
+ :ref:`subprocess-replacements` section.)
If *mode* is :const:`P_NOWAIT`, this function returns the process id of the new
process; if *mode* is :const:`P_WAIT`, returns the process's exit code if it
diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst
index 3318d43..d0e655d 100644
--- a/Doc/library/subprocess.rst
+++ b/Doc/library/subprocess.rst
@@ -412,8 +412,8 @@ Replacing shell pipeline
output = p2.communicate()[0]
-Replacing os.system()
-^^^^^^^^^^^^^^^^^^^^^
+Replacing :func:`os.system`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
::
@@ -440,8 +440,8 @@ A more realistic example would look like this::
print("Execution failed:", e, file=sys.stderr)
-Replacing the os.spawn family
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Replacing the :func:`os.spawn <os.spawnl>` family
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
P_NOWAIT example::
@@ -468,17 +468,85 @@ Environment example::
Popen(["/bin/mycmd", "myarg"], env={"PATH": "/usr/bin"})
-Replacing os.popen
-^^^^^^^^^^^^^^^^^^
+
+Replacing :func:`os.popen`, :func:`os.popen2`, :func:`os.popen3`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
::
- pipe = os.popen(cmd, 'r', bufsize)
+ (child_stdin, child_stdout) = os.popen2(cmd, mode, bufsize)
==>
- pipe = Popen(cmd, shell=True, bufsize=bufsize, stdout=PIPE).stdout
+ p = Popen(cmd, shell=True, bufsize=bufsize,
+ stdin=PIPE, stdout=PIPE, close_fds=True)
+ (child_stdin, child_stdout) = (p.stdin, p.stdout)
::
- pipe = os.popen(cmd, 'w', bufsize)
+ (child_stdin,
+ child_stdout,
+ child_stderr) = os.popen3(cmd, mode, bufsize)
+ ==>
+ p = Popen(cmd, shell=True, bufsize=bufsize,
+ stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)
+ (child_stdin,
+ child_stdout,
+ child_stderr) = (p.stdin, p.stdout, p.stderr)
+
+::
+
+ (child_stdin, child_stdout_and_stderr) = os.popen4(cmd, mode, bufsize)
+ ==>
+ p = Popen(cmd, shell=True, bufsize=bufsize,
+ stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True)
+ (child_stdin, child_stdout_and_stderr) = (p.stdin, p.stdout)
+
+Return code handling translates as follows::
+
+ pipe = os.popen(cmd, 'w')
+ ...
+ rc = pipe.close()
+ if rc != None and rc % 256:
+ print "There were some errors"
==>
- pipe = Popen(cmd, shell=True, bufsize=bufsize, stdin=PIPE).stdin
+ process = Popen(cmd, 'w', stdin=PIPE)
+ ...
+ process.stdin.close()
+ if process.wait() != 0:
+ print "There were some errors"
+
+
+Replacing functions from the :mod:`popen2` module
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. note::
+
+ If the cmd argument to popen2 functions is a string, the command is executed
+ through /bin/sh. If it is a list, the command is directly executed.
+
+::
+
+ (child_stdout, child_stdin) = popen2.popen2("somestring", bufsize, mode)
+ ==>
+ p = Popen(["somestring"], shell=True, bufsize=bufsize,
+ stdin=PIPE, stdout=PIPE, close_fds=True)
+ (child_stdout, child_stdin) = (p.stdout, p.stdin)
+
+::
+
+ (child_stdout, child_stdin) = popen2.popen2(["mycmd", "myarg"], bufsize, mode)
+ ==>
+ p = Popen(["mycmd", "myarg"], bufsize=bufsize,
+ stdin=PIPE, stdout=PIPE, close_fds=True)
+ (child_stdout, child_stdin) = (p.stdout, p.stdin)
+
+:class:`popen2.Popen3` and :class:`popen2.Popen4` basically work as
+:class:`subprocess.Popen`, except that:
+
+* :class:`Popen` raises an exception if the execution fails.
+
+* the *capturestderr* argument is replaced with the *stderr* argument.
+
+* ``stdin=PIPE`` and ``stdout=PIPE`` must be specified.
+
+* popen2 closes all file descriptors by default, but you have to specify
+ ``close_fds=True`` with :class:`Popen`.
diff --git a/Doc/whatsnew/2.7.rst b/Doc/whatsnew/2.7.rst
index 9182c453..f5f7d19 100644
--- a/Doc/whatsnew/2.7.rst
+++ b/Doc/whatsnew/2.7.rst
@@ -663,7 +663,11 @@ Porting to Python 2.7
This section lists previously described changes and other bugfixes
that may require changes to your code:
-To be written.
+* Because of an optimization for the :keyword:`with` statement, the special
+ methods :meth:`__enter__` and :meth:`__exit__` must belong to the object's
+ type, and cannot be directly attached to the object's instance. This
+ affects new-style classes (derived from :class:`object`) and C extension
+ types. (:issue:`6101`.)
.. ======================================================================
diff --git a/Grammar/Grammar b/Grammar/Grammar
index 1b196e5..1f226b8 100644
--- a/Grammar/Grammar
+++ b/Grammar/Grammar
@@ -116,8 +116,9 @@ classdef: 'class' NAME ['(' [arglist] ')'] ':' suite
arglist: (argument ',')* (argument [',']
|'*' test (',' argument)* [',' '**' test]
|'**' test)
+# The reason that keywords are test nodes instead of NAME is that using NAME
+# results in an ambiguity. ast.c makes sure it's a NAME.
argument: test [comp_for] | test '=' test # Really [keyword '='] test
-
comp_iter: comp_for | comp_if
comp_for: 'for' exprlist 'in' or_test [comp_iter]
comp_if: 'if' test_nocond [comp_iter]
diff --git a/Lib/multiprocessing/queues.py b/Lib/multiprocessing/queues.py
index a3393d4..bbaf6d5 100644
--- a/Lib/multiprocessing/queues.py
+++ b/Lib/multiprocessing/queues.py
@@ -109,7 +109,7 @@ class Queue(object):
self._rlock.release()
def qsize(self):
- # Raises NotImplementError on Mac OSX because of broken sem_getvalue()
+ # Raises NotImplementedError on Mac OSX because of broken sem_getvalue()
return self._maxsize - self._sem._semlock._get_value()
def empty(self):
diff --git a/Lib/os.py b/Lib/os.py
index 65f88ba..5dce0c1 100644
--- a/Lib/os.py
+++ b/Lib/os.py
@@ -437,11 +437,7 @@ def getenv(key, default=None):
__all__.append("getenv")
def _exists(name):
- try:
- eval(name)
- return True
- except NameError:
- return False
+ return name in globals()
# Supply spawn*() (probably only for Unix)
if _exists("fork") and not _exists("spawnv") and _exists("execv"):
diff --git a/Lib/symbol.py b/Lib/symbol.py
index 1b773d0..4b4c219 100755
--- a/Lib/symbol.py
+++ b/Lib/symbol.py
@@ -52,7 +52,7 @@ while_stmt = 294
for_stmt = 295
try_stmt = 296
with_stmt = 297
-with_var = 298
+with_item = 298
except_clause = 299
suite = 300
test = 301
diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py
index 9b4e342..84028e8 100644
--- a/Lib/test/test_generators.py
+++ b/Lib/test/test_generators.py
@@ -1584,7 +1584,7 @@ SyntaxError: can't assign to yield expression
>>> def f(): (yield bar) += y
Traceback (most recent call last):
...
-SyntaxError: augmented assignment to yield expression not possible
+SyntaxError: can't assign to yield expression
Now check some throw() conditions:
diff --git a/Lib/test/test_genexps.py b/Lib/test/test_genexps.py
index 61e9fe5..1f46af1 100644
--- a/Lib/test/test_genexps.py
+++ b/Lib/test/test_genexps.py
@@ -142,7 +142,7 @@ Verify that syntax error's are raised for genexps used as lvalues
>>> (y for y in (1,2)) += 10
Traceback (most recent call last):
...
- SyntaxError: augmented assignment to generator expression not possible
+ SyntaxError: can't assign to generator expression
########### Tests borrowed from or inspired by test_generators.py ############
diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py
index c82787e..c55171a 100644
--- a/Lib/test/test_syntax.py
+++ b/Lib/test/test_syntax.py
@@ -222,17 +222,17 @@ Traceback (most recent call last):
SyntaxError: keyword can't be an expression
-From ast_for_expr_stmt():
+More set_context():
>>> (x for x in x) += 1
Traceback (most recent call last):
-SyntaxError: augmented assignment to generator expression not possible
+SyntaxError: can't assign to generator expression
>>> None += 1
Traceback (most recent call last):
SyntaxError: assignment to keyword
>>> f() += 1
Traceback (most recent call last):
-SyntaxError: illegal expression for augmented assignment
+SyntaxError: can't assign to function call
Test continue in finally in weird combinations.
diff --git a/Makefile.pre.in b/Makefile.pre.in
index 2f5cccc..41fc51e 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -562,7 +562,7 @@ $(AST_H): $(AST_ASDL) $(ASDLGEN_FILES)
$(AST_C): $(AST_ASDL) $(ASDLGEN_FILES)
$(ASDLGEN) -c $(AST_C_DIR) $(AST_ASDL)
-Python/compile.o Python/symtable.o: $(GRAMMAR_H) $(AST_H)
+Python/compile.o Python/symtable.o Python/ast.o: $(GRAMMAR_H) $(AST_H)
Python/getplatform.o: $(srcdir)/Python/getplatform.c
$(CC) -c $(PY_CFLAGS) -DPLATFORM='"$(MACHDEP)"' -o $@ $(srcdir)/Python/getplatform.c
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index f21cea2..ce6760f 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -717,7 +717,7 @@ PyDict_GetItem(PyObject *op, PyObject *key)
/* We can arrive here with a NULL tstate during initialization:
try running "python -Wi" for an example related to string
interning. Let's just hope that no exception occurs then... */
- tstate = _PyThreadState_Current;
+ tstate = PyThreadState_GET();
if (tstate != NULL && tstate->curexc_type != NULL) {
/* preserve the existing exception */
PyObject *err_type, *err_value, *err_tb;
diff --git a/Parser/asdl.py b/Parser/asdl.py
index ce9d0d3..28a7138 100644
--- a/Parser/asdl.py
+++ b/Parser/asdl.py
@@ -20,7 +20,7 @@ def output(string):
sys.stdout.write(string + "\n")
-class Token:
+class Token(object):
# spark seems to dispatch in the parser based on a token's
# type attribute
def __init__(self, type, lineno):
@@ -221,20 +221,20 @@ class ASDLParser(spark.GenericParser, object):
def p_field_2(self, info):
" field ::= Id * Id "
type, _, name = info
- return Field(type, name, seq=1)
+ return Field(type, name, seq=True)
def p_field_3(self, info):
" field ::= Id ? Id "
type, _, name = info
- return Field(type, name, opt=1)
+ return Field(type, name, opt=True)
def p_field_4(self, type_):
" field ::= Id * "
- return Field(type_[0], seq=1)
+ return Field(type_[0], seq=True)
def p_field_5(self, type_):
" field ::= Id ? "
- return Field(type[0], opt=1)
+ return Field(type[0], opt=True)
builtin_types = ("identifier", "string", "int", "bool", "object")
@@ -242,7 +242,7 @@ builtin_types = ("identifier", "string", "int", "bool", "object")
# not sure if any of the methods are useful yet, but I'm adding them
# piecemeal as they seem helpful
-class AST:
+class AST(object):
pass # a marker class
class Module(AST):
@@ -274,7 +274,7 @@ class Constructor(AST):
return "Constructor(%s, %s)" % (self.name, self.fields)
class Field(AST):
- def __init__(self, type, name=None, seq=0, opt=0):
+ def __init__(self, type, name=None, seq=False, opt=False):
self.type = type
self.name = name
self.seq = seq
@@ -282,9 +282,9 @@ class Field(AST):
def __repr__(self):
if self.seq:
- extra = ", seq=1"
+ extra = ", seq=True"
elif self.opt:
- extra = ", opt=1"
+ extra = ", opt=True"
else:
extra = ""
if self.name is None:
@@ -312,7 +312,7 @@ class Product(AST):
class VisitorBase(object):
- def __init__(self, skip=0):
+ def __init__(self, skip=False):
self.cache = {}
self.skip = skip
@@ -347,7 +347,7 @@ class VisitorBase(object):
class Check(VisitorBase):
def __init__(self):
- super(Check, self).__init__(skip=1)
+ super(Check, self).__init__(skip=True)
self.cons = {}
self.errors = 0
self.types = {}
diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py
index af0b349..8ccb3ea 100755
--- a/Parser/asdl_c.py
+++ b/Parser/asdl_c.py
@@ -86,7 +86,7 @@ class EmitVisitor(asdl.VisitorBase):
self.file = file
super(EmitVisitor, self).__init__()
- def emit(self, s, depth, reflow=1):
+ def emit(self, s, depth, reflow=True):
# XXX reflow long lines?
if reflow:
lines = reflow_lines(s, depth)
@@ -255,7 +255,7 @@ class PrototypeVisitor(EmitVisitor):
ctype = get_c_type(type)
self.emit_function(cons.name, ctype, args, attrs)
- def emit_function(self, name, ctype, args, attrs, union=1):
+ def emit_function(self, name, ctype, args, attrs, union=True):
args = args + attrs
if args:
argstr = ", ".join(["%s %s" % (atype, aname)
@@ -267,19 +267,19 @@ class PrototypeVisitor(EmitVisitor):
for i in range(1, len(args)+1):
margs += ", a%d" % i
self.emit("#define %s(%s) _Py_%s(%s)" % (name, margs, name, margs), 0,
- reflow = 0)
- self.emit("%s _Py_%s(%s);" % (ctype, name, argstr), 0)
+ reflow=False)
+ self.emit("%s _Py_%s(%s);" % (ctype, name, argstr), False)
def visitProduct(self, prod, name):
self.emit_function(name, get_c_type(name),
- self.get_args(prod.fields), [], union=0)
+ self.get_args(prod.fields), [], union=False)
class FunctionVisitor(PrototypeVisitor):
"""Visitor to generate constructor functions for AST."""
- def emit_function(self, name, ctype, args, attrs, union=1):
- def emit(s, depth=0, reflow=1):
+ def emit_function(self, name, ctype, args, attrs, union=True):
+ def emit(s, depth=0, reflow=True):
self.emit(s, depth, reflow)
argstr = ", ".join(["%s %s" % (atype, aname)
for atype, aname, opt in args + attrs])
@@ -297,7 +297,7 @@ class FunctionVisitor(PrototypeVisitor):
emit("PyErr_SetString(PyExc_ValueError,", 2)
msg = "field %s is required for %s" % (argname, name)
emit(' "%s");' % msg,
- 2, reflow=0)
+ 2, reflow=False)
emit('return NULL;', 2)
emit('}', 1)
@@ -313,7 +313,7 @@ class FunctionVisitor(PrototypeVisitor):
emit("")
def emit_body_union(self, name, args, attrs):
- def emit(s, depth=0, reflow=1):
+ def emit(s, depth=0, reflow=True):
self.emit(s, depth, reflow)
emit("p->kind = %s_kind;" % name, 1)
for argtype, argname, opt in args:
@@ -322,7 +322,7 @@ class FunctionVisitor(PrototypeVisitor):
emit("p->%s = %s;" % (argname, argname), 1)
def emit_body_struct(self, name, args, attrs):
- def emit(s, depth=0, reflow=1):
+ def emit(s, depth=0, reflow=True):
self.emit(s, depth, reflow)
for argtype, argname, opt in args:
emit("p->%s = %s;" % (argname, argname), 1)
diff --git a/Python/ast.c b/Python/ast.c
index ff412b3..83572ee 100644
--- a/Python/ast.c
+++ b/Python/ast.c
@@ -2103,29 +2103,6 @@ ast_for_expr_stmt(struct compiling *c, const node *n)
expr1 = ast_for_testlist(c, ch);
if (!expr1)
return NULL;
- /* TODO(nas): Remove duplicated error checks (set_context does it) */
- switch (expr1->kind) {
- case GeneratorExp_kind:
- ast_error(ch, "augmented assignment to generator "
- "expression not possible");
- return NULL;
- case Yield_kind:
- ast_error(ch, "augmented assignment to yield "
- "expression not possible");
- return NULL;
- case Name_kind: {
- if (forbidden_name(expr1, ch))
- return NULL;
- break;
- }
- case Attribute_kind:
- case Subscript_kind:
- break;
- default:
- ast_error(ch, "illegal expression for augmented "
- "assignment");
- return NULL;
- }
if(!set_context(c, expr1, Store, ch))
return NULL;
@@ -3086,7 +3063,6 @@ ast_for_stmt(struct compiling *c, const node *n)
n = CHILD(n, 0);
}
if (TYPE(n) == small_stmt) {
- REQ(n, small_stmt);
n = CHILD(n, 0);
/* small_stmt: expr_stmt | del_stmt | pass_stmt | flow_stmt
| import_stmt | global_stmt | nonlocal_stmt | assert_stmt