mirror of
https://github.com/python/cpython.git
synced 2025-08-05 17:39:02 +00:00
[3.9] bpo-46502: Remove "How do I tell incomplete input" from FAQ (GH-30925) (GH-30934)
Since,
- Py_CompileString no longer allows to distinguish "incomplete input"
from "invalid input"
- there is no alternative solution available from the Python C API
due to how the new parser works (rewritten in 3.9)
- the only supported way is to manually import the codeop module from C
and use its API as IDLE does, and accept its own complications
it is desirable to remove this Q&A from the official FAQ..
(cherry picked from commit f0a648152f
)
Co-authored-by: Mateusz Łoskot <mateusz@loskot.net>
Co-authored-by: Mateusz Łoskot <mateusz@loskot.net>
This commit is contained in:
parent
ff11effab7
commit
dafada393f
1 changed files with 0 additions and 156 deletions
|
@ -254,7 +254,6 @@ For Red Hat, install the python-devel RPM to get the necessary files.
|
||||||
|
|
||||||
For Debian, run ``apt-get install python-dev``.
|
For Debian, run ``apt-get install python-dev``.
|
||||||
|
|
||||||
|
|
||||||
How do I tell "incomplete input" from "invalid input"?
|
How do I tell "incomplete input" from "invalid input"?
|
||||||
------------------------------------------------------
|
------------------------------------------------------
|
||||||
|
|
||||||
|
@ -273,161 +272,6 @@ you. You can also set the :c:func:`PyOS_ReadlineFunctionPointer` to point at you
|
||||||
custom input function. See ``Modules/readline.c`` and ``Parser/myreadline.c``
|
custom input function. See ``Modules/readline.c`` and ``Parser/myreadline.c``
|
||||||
for more hints.
|
for more hints.
|
||||||
|
|
||||||
However sometimes you have to run the embedded Python interpreter in the same
|
|
||||||
thread as your rest application and you can't allow the
|
|
||||||
:c:func:`PyRun_InteractiveLoop` to stop while waiting for user input. The one
|
|
||||||
solution then is to call :c:func:`PyParser_ParseString` and test for ``e.error``
|
|
||||||
equal to ``E_EOF``, which means the input is incomplete. Here's a sample code
|
|
||||||
fragment, untested, inspired by code from Alex Farber::
|
|
||||||
|
|
||||||
#define PY_SSIZE_T_CLEAN
|
|
||||||
#include <Python.h>
|
|
||||||
#include <node.h>
|
|
||||||
#include <errcode.h>
|
|
||||||
#include <grammar.h>
|
|
||||||
#include <parsetok.h>
|
|
||||||
#include <compile.h>
|
|
||||||
|
|
||||||
int testcomplete(char *code)
|
|
||||||
/* code should end in \n */
|
|
||||||
/* return -1 for error, 0 for incomplete, 1 for complete */
|
|
||||||
{
|
|
||||||
node *n;
|
|
||||||
perrdetail e;
|
|
||||||
|
|
||||||
n = PyParser_ParseString(code, &_PyParser_Grammar,
|
|
||||||
Py_file_input, &e);
|
|
||||||
if (n == NULL) {
|
|
||||||
if (e.error == E_EOF)
|
|
||||||
return 0;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyNode_Free(n);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Another solution is trying to compile the received string with
|
|
||||||
:c:func:`Py_CompileString`. If it compiles without errors, try to execute the
|
|
||||||
returned code object by calling :c:func:`PyEval_EvalCode`. Otherwise save the
|
|
||||||
input for later. If the compilation fails, find out if it's an error or just
|
|
||||||
more input is required - by extracting the message string from the exception
|
|
||||||
tuple and comparing it to the string "unexpected EOF while parsing". Here is a
|
|
||||||
complete example using the GNU readline library (you may want to ignore
|
|
||||||
**SIGINT** while calling readline())::
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <readline.h>
|
|
||||||
|
|
||||||
#define PY_SSIZE_T_CLEAN
|
|
||||||
#include <Python.h>
|
|
||||||
#include <object.h>
|
|
||||||
#include <compile.h>
|
|
||||||
#include <eval.h>
|
|
||||||
|
|
||||||
int main (int argc, char* argv[])
|
|
||||||
{
|
|
||||||
int i, j, done = 0; /* lengths of line, code */
|
|
||||||
char ps1[] = ">>> ";
|
|
||||||
char ps2[] = "... ";
|
|
||||||
char *prompt = ps1;
|
|
||||||
char *msg, *line, *code = NULL;
|
|
||||||
PyObject *src, *glb, *loc;
|
|
||||||
PyObject *exc, *val, *trb, *obj, *dum;
|
|
||||||
|
|
||||||
Py_Initialize ();
|
|
||||||
loc = PyDict_New ();
|
|
||||||
glb = PyDict_New ();
|
|
||||||
PyDict_SetItemString (glb, "__builtins__", PyEval_GetBuiltins ());
|
|
||||||
|
|
||||||
while (!done)
|
|
||||||
{
|
|
||||||
line = readline (prompt);
|
|
||||||
|
|
||||||
if (NULL == line) /* Ctrl-D pressed */
|
|
||||||
{
|
|
||||||
done = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
i = strlen (line);
|
|
||||||
|
|
||||||
if (i > 0)
|
|
||||||
add_history (line); /* save non-empty lines */
|
|
||||||
|
|
||||||
if (NULL == code) /* nothing in code yet */
|
|
||||||
j = 0;
|
|
||||||
else
|
|
||||||
j = strlen (code);
|
|
||||||
|
|
||||||
code = realloc (code, i + j + 2);
|
|
||||||
if (NULL == code) /* out of memory */
|
|
||||||
exit (1);
|
|
||||||
|
|
||||||
if (0 == j) /* code was empty, so */
|
|
||||||
code[0] = '\0'; /* keep strncat happy */
|
|
||||||
|
|
||||||
strncat (code, line, i); /* append line to code */
|
|
||||||
code[i + j] = '\n'; /* append '\n' to code */
|
|
||||||
code[i + j + 1] = '\0';
|
|
||||||
|
|
||||||
src = Py_CompileString (code, "<stdin>", Py_single_input);
|
|
||||||
|
|
||||||
if (NULL != src) /* compiled just fine - */
|
|
||||||
{
|
|
||||||
if (ps1 == prompt || /* ">>> " or */
|
|
||||||
'\n' == code[i + j - 1]) /* "... " and double '\n' */
|
|
||||||
{ /* so execute it */
|
|
||||||
dum = PyEval_EvalCode (src, glb, loc);
|
|
||||||
Py_XDECREF (dum);
|
|
||||||
Py_XDECREF (src);
|
|
||||||
free (code);
|
|
||||||
code = NULL;
|
|
||||||
if (PyErr_Occurred ())
|
|
||||||
PyErr_Print ();
|
|
||||||
prompt = ps1;
|
|
||||||
}
|
|
||||||
} /* syntax error or E_EOF? */
|
|
||||||
else if (PyErr_ExceptionMatches (PyExc_SyntaxError))
|
|
||||||
{
|
|
||||||
PyErr_Fetch (&exc, &val, &trb); /* clears exception! */
|
|
||||||
|
|
||||||
if (PyArg_ParseTuple (val, "sO", &msg, &obj) &&
|
|
||||||
!strcmp (msg, "unexpected EOF while parsing")) /* E_EOF */
|
|
||||||
{
|
|
||||||
Py_XDECREF (exc);
|
|
||||||
Py_XDECREF (val);
|
|
||||||
Py_XDECREF (trb);
|
|
||||||
prompt = ps2;
|
|
||||||
}
|
|
||||||
else /* some other syntax error */
|
|
||||||
{
|
|
||||||
PyErr_Restore (exc, val, trb);
|
|
||||||
PyErr_Print ();
|
|
||||||
free (code);
|
|
||||||
code = NULL;
|
|
||||||
prompt = ps1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else /* some non-syntax error */
|
|
||||||
{
|
|
||||||
PyErr_Print ();
|
|
||||||
free (code);
|
|
||||||
code = NULL;
|
|
||||||
prompt = ps1;
|
|
||||||
}
|
|
||||||
|
|
||||||
free (line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Py_XDECREF(glb);
|
|
||||||
Py_XDECREF(loc);
|
|
||||||
Py_Finalize();
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
How do I find undefined g++ symbols __builtin_new or __pure_virtual?
|
How do I find undefined g++ symbols __builtin_new or __pure_virtual?
|
||||||
--------------------------------------------------------------------
|
--------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue