diff -r 5eb95d41ee43 Include/pythonrun.h --- a/Include/pythonrun.h Mon Sep 15 02:10:01 2014 -0700 +++ b/Include/pythonrun.h Mon Sep 15 11:56:50 2014 +0200 @@ -15,6 +15,7 @@ #define PyCF_DONT_IMPLY_DEDENT 0x0200 #define PyCF_ONLY_AST 0x0400 #define PyCF_IGNORE_COOKIE 0x0800 +#define PyCF_GENERATOR 0x1000 #ifndef Py_LIMITED_API typedef struct { diff -r 5eb95d41ee43 Lib/asyncio/tasks.py --- a/Lib/asyncio/tasks.py Mon Sep 15 02:10:01 2014 -0700 +++ b/Lib/asyncio/tasks.py Mon Sep 15 11:56:50 2014 +0200 @@ -2,7 +2,7 @@ __all__ = ['Task', 'FIRST_COMPLETED', 'FIRST_EXCEPTION', 'ALL_COMPLETED', - 'wait', 'wait_for', 'as_completed', 'sleep', 'async', + 'wait', 'wait_for', 'as_completed', 'sleep', 'input', 'async', 'gather', 'shield', ] @@ -10,6 +10,7 @@ import functools import inspect import linecache +import readline import sys import traceback import weakref @@ -490,6 +491,27 @@ h.cancel() +@coroutine +def input(prompt="", *, loop=None): + """This is a coroutine replacement for builtin.input + + It will read from __stdin__ using the readline library. It does + not work for other input streams. """ + if loop is None: + loop = events.get_event_loop() + readline._input(prompt.encode(sys.__stdout__.encoding)) + loop.add_reader(sys.__stdin__.fileno(), lambda: future.set_result(None)) + try: + while True: + future = futures.Future(loop=loop) + yield from future + ret = readline._input() + if ret is not None: + return ret.decode(sys.__stdin__.encoding) + finally: + loop.remove_reader(0) + + def async(coro_or_future, *, loop=None): """Wrap a coroutine in a future. diff -r 5eb95d41ee43 Lib/test/test_compile.py --- a/Lib/test/test_compile.py Mon Sep 15 02:10:01 2014 -0700 +++ b/Lib/test/test_compile.py Mon Sep 15 11:56:50 2014 +0200 @@ -492,6 +492,18 @@ self.assertInvalidSingle('f()\nxy # blah\nblah()') self.assertInvalidSingle('x = 5 # comment\nx = 6\n') + + def test_yield(self): + self.assertInvalidSingle('yield 7') + c = compile("yield 7", "", "single", flags=0x1000) + l = list(eval(c)) + self.assertEqual(l, [7]) + + c = compile("None", "", "single", flags=0x1000) + l = list(eval(c)) + self.assertEqual(l, []) + + @support.cpython_only def test_compiler_recursion_limit(self): # Expected limit is sys.getrecursionlimit() * the scaling factor diff -r 5eb95d41ee43 Modules/readline.c --- a/Modules/readline.c Mon Sep 15 02:10:01 2014 -0700 +++ b/Modules/readline.c Mon Sep 15 11:56:50 2014 +0200 @@ -734,6 +734,97 @@ contents of the line buffer."); +#if defined(HAVE_RL_CALLBACK) + +static char *completed_input_string = NULL; +static char *not_done_reading = ""; + +static void +rlhandler(char *text) +{ + completed_input_string = text; + rl_callback_handler_remove(); +} + +static PyObject * +input_one_char(PyObject *self, PyObject *args) +{ + size_t n; + const char *prompt = NULL; + char *saved_locale; + PyObject *result; + + if (!PyArg_ParseTuple(args, "|y", &prompt)) + return NULL; + +#ifdef SAVE_LOCALE + saved_locale = strdup(setlocale(LC_CTYPE, NULL)); + if (!saved_locale) + Py_FatalError("not enough memory to save locale"); + setlocale(LC_CTYPE, ""); +#endif + + if (prompt) { + if (stdin != rl_instream || stdout != rl_outstream) { + rl_instream = stdin; + rl_outstream = stdout; +#ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER + rl_prep_terminal (1); +#endif + } + + if (completed_input_string != not_done_reading) { + completed_input_string = not_done_reading; + rl_callback_handler_install (prompt, rlhandler); + } + RESTORE_LOCALE(saved_locale) + Py_RETURN_NONE; + } + + rl_callback_read_char(); + if (completed_input_string == not_done_reading) { + RESTORE_LOCALE(saved_locale) + Py_RETURN_NONE; + } + + /* We got an EOF, raise error. */ + if (!completed_input_string) { + PyErr_SetNone(PyExc_EOFError); + RESTORE_LOCALE(saved_locale) + return NULL; + } + + /* we have a valid line */ + n = strlen(completed_input_string); + if (n > 0) { + const char *line; + int length = _py_get_history_length(); + if (length > 0) +#ifdef __APPLE__ + if (using_libedit_emulation) { + /* handle older 0-based or newer 1-based indexing */ + line = (const char *)history_get(length + libedit_history_start - 1)->line; + } else +#endif /* __APPLE__ */ + line = (const char *)history_get(length)->line; + else + line = ""; + if (strcmp(completed_input_string, line)) + add_history(completed_input_string); + } + + result = PyBytes_FromString(completed_input_string); + free(completed_input_string); + RESTORE_LOCALE(saved_locale) + return result; +} + +PyDoc_STRVAR(doc__input, +"_input(bytes) -> bytes\n\ +Internal helper function for asyncio.input. For details see there."); + +#endif + /* Table of functions exported by the module */ static struct PyMethodDef readline_methods[] = @@ -781,6 +872,9 @@ #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER {"clear_history", py_clear_history, METH_NOARGS, doc_clear_history}, #endif +#if defined(HAVE_RL_CALLBACK) + {"_input", input_one_char, METH_VARARGS, doc__input}, +#endif {0, 0} }; @@ -1054,28 +1148,19 @@ #if defined(HAVE_RL_CALLBACK) && defined(HAVE_SELECT) -static char *completed_input_string; -static void -rlhandler(char *text) -{ - completed_input_string = text; - rl_callback_handler_remove(); -} - extern PyThreadState* _PyOS_ReadlineTState; static char * readline_until_enter_or_signal(const char *prompt, int *signal) { - char * not_done_reading = ""; fd_set selectset; *signal = 0; #ifdef HAVE_RL_CATCH_SIGNAL rl_catch_signals = 0; #endif - - rl_callback_handler_install (prompt, rlhandler); + if (completed_input_string != not_done_reading) + rl_callback_handler_install (prompt, rlhandler); FD_ZERO(&selectset); completed_input_string = not_done_reading; diff -r 5eb95d41ee43 Python/bltinmodule.c --- a/Python/bltinmodule.c Mon Sep 15 02:10:01 2014 -0700 +++ b/Python/bltinmodule.c Mon Sep 15 11:56:50 2014 +0200 @@ -837,7 +837,7 @@ cf.cf_flags = flags | PyCF_SOURCE_IS_UTF8; if (flags & - ~(PyCF_MASK | PyCF_MASK_OBSOLETE | PyCF_DONT_IMPLY_DEDENT | PyCF_ONLY_AST)) + ~(PyCF_MASK | PyCF_MASK_OBSOLETE | PyCF_DONT_IMPLY_DEDENT | PyCF_ONLY_AST | PyCF_GENERATOR)) { PyErr_SetString(PyExc_ValueError, "compile(): unrecognised flags"); diff -r 5eb95d41ee43 Python/compile.c --- a/Python/compile.c Mon Sep 15 02:10:01 2014 -0700 +++ b/Python/compile.c Mon Sep 15 11:56:50 2014 +0200 @@ -3457,7 +3457,9 @@ case DictComp_kind: return compiler_dictcomp(c, e); case Yield_kind: - if (c->u->u_ste->ste_type != FunctionBlock) + if (c->u->u_ste->ste_type != FunctionBlock && + (!(c->c_flags->cf_flags & PyCF_GENERATOR) || + c->u->u_ste->ste_type != ModuleBlock)) return compiler_error(c, "'yield' outside function"); if (e->v.Yield.value) { VISIT(c, expr, e->v.Yield.value); @@ -3468,7 +3470,9 @@ ADDOP(c, YIELD_VALUE); break; case YieldFrom_kind: - if (c->u->u_ste->ste_type != FunctionBlock) + if (c->u->u_ste->ste_type != FunctionBlock && + (!(c->c_flags->cf_flags & PyCF_GENERATOR) || + c->u->u_ste->ste_type != ModuleBlock)) return compiler_error(c, "'yield' outside function"); VISIT(c, expr, e->v.YieldFrom.value); ADDOP(c, GET_ITER); @@ -4201,6 +4205,9 @@ flags |= CO_VARKEYWORDS; } + if (ste->ste_type == ModuleBlock && c->c_flags->cf_flags & PyCF_GENERATOR) + flags |= CO_GENERATOR; + /* (Only) inherit compilerflags in PyCF_MASK */ flags |= (c->c_flags->cf_flags & PyCF_MASK);