diff -r 8e9131d0e597 Include/pythonrun.h --- a/Include/pythonrun.h Fri Sep 12 09:40:46 2014 +0200 +++ b/Include/pythonrun.h Sun Sep 14 23:05:39 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 8e9131d0e597 Lib/asyncio/tasks.py --- a/Lib/asyncio/tasks.py Fri Sep 12 09:40:46 2014 +0200 +++ b/Lib/asyncio/tasks.py Sun Sep 14 23:05:39 2014 +0200 @@ -3,7 +3,7 @@ __all__ = ['coroutine', 'Task', 'iscoroutinefunction', 'iscoroutine', 'FIRST_COMPLETED', 'FIRST_EXCEPTION', 'ALL_COMPLETED', - 'wait', 'wait_for', 'as_completed', 'sleep', 'async', + 'wait', 'wait_for', 'as_completed', 'sleep', 'input', 'async', 'gather', 'shield', ] @@ -12,6 +12,8 @@ import functools import inspect import linecache +import readline +import sys import traceback import weakref @@ -513,6 +515,30 @@ 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() + prompt = prompt.encode(sys.__stdout__.encoding) + def callback(): + future.set_result(None) + loop.add_reader(sys.__stdin__.fileno(), callback) + readline._input(prompt) + 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 8e9131d0e597 Lib/test/test_compile.py --- a/Lib/test/test_compile.py Fri Sep 12 09:40:46 2014 +0200 +++ b/Lib/test/test_compile.py Sun Sep 14 23:05:39 2014 +0200 @@ -474,6 +474,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 8e9131d0e597 Modules/readline.c --- a/Modules/readline.c Fri Sep 12 09:40:46 2014 +0200 +++ b/Modules/readline.c Sun Sep 14 23:05:39 2014 +0200 @@ -735,6 +735,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[] = @@ -782,6 +873,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} }; @@ -1040,28 +1134,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 8e9131d0e597 Python/bltinmodule.c --- a/Python/bltinmodule.c Fri Sep 12 09:40:46 2014 +0200 +++ b/Python/bltinmodule.c Sun Sep 14 23:05:39 2014 +0200 @@ -617,7 +617,7 @@ cf.cf_flags = supplied_flags | PyCF_SOURCE_IS_UTF8; if (supplied_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 8e9131d0e597 Python/compile.c --- a/Python/compile.c Fri Sep 12 09:40:46 2014 +0200 +++ b/Python/compile.c Sun Sep 14 23:05:39 2014 +0200 @@ -3444,7 +3444,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); @@ -3455,7 +3457,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); @@ -4184,6 +4188,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);