[Python-Dev] __future__ and the interactive interpreter prompt

Jeremy Hylton jeremy@alum.mit.edu
Thu, 1 Mar 2001 13:16:03 -0500 (EST)


from __future__ import nested_scopes is accepted at the interactive
interpreter prompt but has no effect beyond the line on which it was
entered.  You could use it with lambdas entered following a
semicolon, I guess.

I would rather see the future statement take effect for the remained
of the interactive interpreter session.  I have included a first-cut
patch below that makes this possible, using an object called
PySessionState.  (I don't like the name, but don't have a better one;
PyCompilerFlags?)

The idea of the session state is to record information about the state
of an interactive session that may affect compilation.  The
state object is created in PyRun_InteractiveLoop() and passed all the
way through to PyNode_Compile().

Does this seem a reasonable approach?  Should I include it in the
beta?  Any name suggestions.

Jeremy


Index: Include/compile.h
===================================================================
RCS file: /cvsroot/python/python/dist/src/Include/compile.h,v
retrieving revision 2.27
diff -c -r2.27 compile.h
*** Include/compile.h	2001/02/28 01:58:08	2.27
--- Include/compile.h	2001/03/01 18:18:27
***************
*** 41,47 ****
  
  /* Public interface */
  struct _node; /* Declare the existence of this type */
! DL_IMPORT(PyCodeObject *) PyNode_Compile(struct _node *, char *);
  DL_IMPORT(PyCodeObject *) PyCode_New(
  	int, int, int, int, PyObject *, PyObject *, PyObject *, PyObject *,
  	PyObject *, PyObject *, PyObject *, PyObject *, int, PyObject *); 
--- 41,48 ----
  
  /* Public interface */
  struct _node; /* Declare the existence of this type */
! DL_IMPORT(PyCodeObject *) PyNode_Compile(struct _node *, char *,
! 					 PySessionState *);
  DL_IMPORT(PyCodeObject *) PyCode_New(
  	int, int, int, int, PyObject *, PyObject *, PyObject *, PyObject *,
  	PyObject *, PyObject *, PyObject *, PyObject *, int, PyObject *); 
Index: Include/pythonrun.h
===================================================================
RCS file: /cvsroot/python/python/dist/src/Include/pythonrun.h,v
retrieving revision 2.38
diff -c -r2.38 pythonrun.h
*** Include/pythonrun.h	2001/02/02 18:19:15	2.38
--- Include/pythonrun.h	2001/03/01 18:18:27
***************
*** 7,12 ****
--- 7,16 ----
  extern "C" {
  #endif
  
+ typedef struct {
+ 	int ss_nested_scopes;
+ } PySessionState;
+ 
  DL_IMPORT(void) Py_SetProgramName(char *);
  DL_IMPORT(char *) Py_GetProgramName(void);
  
***************
*** 25,31 ****
  DL_IMPORT(int) PyRun_SimpleString(char *);
  DL_IMPORT(int) PyRun_SimpleFile(FILE *, char *);
  DL_IMPORT(int) PyRun_SimpleFileEx(FILE *, char *, int);
! DL_IMPORT(int) PyRun_InteractiveOne(FILE *, char *);
  DL_IMPORT(int) PyRun_InteractiveLoop(FILE *, char *);
  
  DL_IMPORT(struct _node *) PyParser_SimpleParseString(char *, int);
--- 29,35 ----
  DL_IMPORT(int) PyRun_SimpleString(char *);
  DL_IMPORT(int) PyRun_SimpleFile(FILE *, char *);
  DL_IMPORT(int) PyRun_SimpleFileEx(FILE *, char *, int);
! DL_IMPORT(int) PyRun_InteractiveOne(FILE *, char *, PySessionState *);
  DL_IMPORT(int) PyRun_InteractiveLoop(FILE *, char *);
  
  DL_IMPORT(struct _node *) PyParser_SimpleParseString(char *, int);
Index: Python/compile.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/compile.c,v
retrieving revision 2.184
diff -c -r2.184 compile.c
*** Python/compile.c	2001/03/01 06:09:34	2.184
--- Python/compile.c	2001/03/01 18:18:28
***************
*** 471,477 ****
  static void com_assign(struct compiling *, node *, int, node *);
  static void com_assign_name(struct compiling *, node *, int);
  static PyCodeObject *icompile(node *, struct compiling *);
! static PyCodeObject *jcompile(node *, char *, struct compiling *);
  static PyObject *parsestrplus(node *);
  static PyObject *parsestr(char *);
  static node *get_rawdocstring(node *);
--- 471,478 ----
  static void com_assign(struct compiling *, node *, int, node *);
  static void com_assign_name(struct compiling *, node *, int);
  static PyCodeObject *icompile(node *, struct compiling *);
! static PyCodeObject *jcompile(node *, char *, struct compiling *,
! 			      PySessionState *);
  static PyObject *parsestrplus(node *);
  static PyObject *parsestr(char *);
  static node *get_rawdocstring(node *);
***************
*** 3814,3822 ****
  }
  
  PyCodeObject *
! PyNode_Compile(node *n, char *filename)
  {
! 	return jcompile(n, filename, NULL);
  }
  
  struct symtable *
--- 3815,3823 ----
  }
  
  PyCodeObject *
! PyNode_Compile(node *n, char *filename, PySessionState *sess)
  {
! 	return jcompile(n, filename, NULL, sess);
  }
  
  struct symtable *
***************
*** 3844,3854 ****
  static PyCodeObject *
  icompile(node *n, struct compiling *base)
  {
! 	return jcompile(n, base->c_filename, base);
  }
  
  static PyCodeObject *
! jcompile(node *n, char *filename, struct compiling *base)
  {
  	struct compiling sc;
  	PyCodeObject *co;
--- 3845,3856 ----
  static PyCodeObject *
  icompile(node *n, struct compiling *base)
  {
! 	return jcompile(n, base->c_filename, base, NULL);
  }
  
  static PyCodeObject *
! jcompile(node *n, char *filename, struct compiling *base,
! 	 PySessionState *sess)
  {
  	struct compiling sc;
  	PyCodeObject *co;
***************
*** 3864,3870 ****
  	} else {
  		sc.c_private = NULL;
  		sc.c_future = PyNode_Future(n, filename);
! 		if (sc.c_future == NULL || symtable_build(&sc, n) < 0) {
  			com_free(&sc);
  			return NULL;
  		}
--- 3866,3882 ----
  	} else {
  		sc.c_private = NULL;
  		sc.c_future = PyNode_Future(n, filename);
! 		if (sc.c_future == NULL) {
! 			com_free(&sc);
! 			return NULL;
! 		}
! 		if (sess) {
! 			if (sess->ss_nested_scopes)
! 				sc.c_future->ff_nested_scopes = 1;
! 			else if (sc.c_future->ff_nested_scopes)
! 				sess->ss_nested_scopes = 1;
! 		}
! 		if (symtable_build(&sc, n) < 0) {
  			com_free(&sc);
  			return NULL;
  		}
Index: Python/import.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/import.c,v
retrieving revision 2.169
diff -c -r2.169 import.c
*** Python/import.c	2001/03/01 08:47:29	2.169
--- Python/import.c	2001/03/01 18:18:28
***************
*** 608,614 ****
  	n = PyParser_SimpleParseFile(fp, pathname, Py_file_input);
  	if (n == NULL)
  		return NULL;
! 	co = PyNode_Compile(n, pathname);
  	PyNode_Free(n);
  
  	return co;
--- 608,614 ----
  	n = PyParser_SimpleParseFile(fp, pathname, Py_file_input);
  	if (n == NULL)
  		return NULL;
! 	co = PyNode_Compile(n, pathname, NULL);
  	PyNode_Free(n);
  
  	return co;
Index: Python/pythonrun.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/pythonrun.c,v
retrieving revision 2.125
diff -c -r2.125 pythonrun.c
*** Python/pythonrun.c	2001/02/28 20:58:04	2.125
--- Python/pythonrun.c	2001/03/01 18:18:28
***************
*** 37,45 ****
  static void initmain(void);
  static void initsite(void);
  static PyObject *run_err_node(node *n, char *filename,
! 			      PyObject *globals, PyObject *locals);
  static PyObject *run_node(node *n, char *filename,
! 			  PyObject *globals, PyObject *locals);
  static PyObject *run_pyc_file(FILE *fp, char *filename,
  			      PyObject *globals, PyObject *locals);
  static void err_input(perrdetail *);
--- 37,47 ----
  static void initmain(void);
  static void initsite(void);
  static PyObject *run_err_node(node *n, char *filename,
! 			      PyObject *globals, PyObject *locals,
! 			      PySessionState *sess);
  static PyObject *run_node(node *n, char *filename,
! 			  PyObject *globals, PyObject *locals,
! 			  PySessionState *sess);
  static PyObject *run_pyc_file(FILE *fp, char *filename,
  			      PyObject *globals, PyObject *locals);
  static void err_input(perrdetail *);
***************
*** 56,62 ****
  extern void _PyCodecRegistry_Init(void);
  extern void _PyCodecRegistry_Fini(void);
  
- 
  int Py_DebugFlag; /* Needed by parser.c */
  int Py_VerboseFlag; /* Needed by import.c */
  int Py_InteractiveFlag; /* Needed by Py_FdIsInteractive() below */
--- 58,63 ----
***************
*** 472,477 ****
--- 473,481 ----
  {
  	PyObject *v;
  	int ret;
+ 	PySessionState sess;
+ 
+ 	sess.ss_nested_scopes = 0;
  	v = PySys_GetObject("ps1");
  	if (v == NULL) {
  		PySys_SetObject("ps1", v = PyString_FromString(">>> "));
***************
*** 483,489 ****
  		Py_XDECREF(v);
  	}
  	for (;;) {
! 		ret = PyRun_InteractiveOne(fp, filename);
  #ifdef Py_REF_DEBUG
  		fprintf(stderr, "[%ld refs]\n", _Py_RefTotal);
  #endif
--- 487,493 ----
  		Py_XDECREF(v);
  	}
  	for (;;) {
! 		ret = PyRun_InteractiveOne(fp, filename, &sess);
  #ifdef Py_REF_DEBUG
  		fprintf(stderr, "[%ld refs]\n", _Py_RefTotal);
  #endif
***************
*** 497,503 ****
  }
  
  int
! PyRun_InteractiveOne(FILE *fp, char *filename)
  {
  	PyObject *m, *d, *v, *w;
  	node *n;
--- 501,507 ----
  }
  
  int
! PyRun_InteractiveOne(FILE *fp, char *filename, PySessionState *sess)
  {
  	PyObject *m, *d, *v, *w;
  	node *n;
***************
*** 537,543 ****
  	if (m == NULL)
  		return -1;
  	d = PyModule_GetDict(m);
! 	v = run_node(n, filename, d, d);
  	if (v == NULL) {
  		PyErr_Print();
  		return -1;
--- 541,547 ----
  	if (m == NULL)
  		return -1;
  	d = PyModule_GetDict(m);
! 	v = run_node(n, filename, d, d, sess);
  	if (v == NULL) {
  		PyErr_Print();
  		return -1;
***************
*** 907,913 ****
  PyRun_String(char *str, int start, PyObject *globals, PyObject *locals)
  {
  	return run_err_node(PyParser_SimpleParseString(str, start),
! 			    "<string>", globals, locals);
  }
  
  PyObject *
--- 911,917 ----
  PyRun_String(char *str, int start, PyObject *globals, PyObject *locals)
  {
  	return run_err_node(PyParser_SimpleParseString(str, start),
! 			    "<string>", globals, locals, NULL);
  }
  
  PyObject *
***************
*** 924,946 ****
  	node *n = PyParser_SimpleParseFile(fp, filename, start);
  	if (closeit)
  		fclose(fp);
! 	return run_err_node(n, filename, globals, locals);
  }
  
  static PyObject *
! run_err_node(node *n, char *filename, PyObject *globals, PyObject *locals)
  {
  	if (n == NULL)
  		return  NULL;
! 	return run_node(n, filename, globals, locals);
  }
  
  static PyObject *
! run_node(node *n, char *filename, PyObject *globals, PyObject *locals)
  {
  	PyCodeObject *co;
  	PyObject *v;
! 	co = PyNode_Compile(n, filename);
  	PyNode_Free(n);
  	if (co == NULL)
  		return NULL;
--- 928,957 ----
  	node *n = PyParser_SimpleParseFile(fp, filename, start);
  	if (closeit)
  		fclose(fp);
! 	return run_err_node(n, filename, globals, locals, NULL);
  }
  
  static PyObject *
! run_err_node(node *n, char *filename, PyObject *globals, PyObject *locals,
! 	     PySessionState *sess)
  {
  	if (n == NULL)
  		return  NULL;
! 	return run_node(n, filename, globals, locals, sess);
  }
  
  static PyObject *
! run_node(node *n, char *filename, PyObject *globals, PyObject *locals,
! 	 PySessionState *sess)
  {
  	PyCodeObject *co;
  	PyObject *v;
! 	if (sess) {
! 		fprintf(stderr, "session state: %d\n",
! 			sess->ss_nested_scopes);
! 	}
! 	/* XXX pass sess->ss_nested_scopes to PyNode_Compile */
! 	co = PyNode_Compile(n, filename, sess);
  	PyNode_Free(n);
  	if (co == NULL)
  		return NULL;
***************
*** 986,992 ****
  	n = PyParser_SimpleParseString(str, start);
  	if (n == NULL)
  		return NULL;
! 	co = PyNode_Compile(n, filename);
  	PyNode_Free(n);
  	return (PyObject *)co;
  }
--- 997,1003 ----
  	n = PyParser_SimpleParseString(str, start);
  	if (n == NULL)
  		return NULL;
! 	co = PyNode_Compile(n, filename, NULL);
  	PyNode_Free(n);
  	return (PyObject *)co;
  }