[Python-checkins] python/dist/src/Python newcompile.c, 1.1.2.120, 1.1.2.121 symtable.c, 2.10.8.37, 2.10.8.38

jhylton@users.sourceforge.net jhylton at users.sourceforge.net
Fri Oct 14 22:06:17 CEST 2005


Update of /cvsroot/python/python/dist/src/Python
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5863/Python

Modified Files:
      Tag: ast-branch
	newcompile.c symtable.c 
Log Message:
Fix two dotted import problems uncovered by zope test suite

The symbol table did not handle dots in import names.  If you imported
"a.b.c", it would put "a.b.c" in the symbol table instead of "a".

The compiler did not generate the correct code for "import a.b.c as
d".  It bound a to d instead of c to d.

Add very simple tests cases to test_import to cover these failures.



Index: newcompile.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/Attic/newcompile.c,v
retrieving revision 1.1.2.120
retrieving revision 1.1.2.121
diff -u -d -r1.1.2.120 -r1.1.2.121
--- newcompile.c	14 Oct 2005 07:22:20 -0000	1.1.2.120
+++ newcompile.c	14 Oct 2005 20:06:13 -0000	1.1.2.121
@@ -54,9 +54,6 @@
      #: line numbers are off a bit (may just need to add calls to set lineno)
         In some cases, the line numbers for generated code aren't strictly
         increasing.  This breaks the lnotab.
-     #: Modules/parsermodule.c:496: warning: implicit declaration 
-                                    of function `PyParser_SimpleParseString'
-     #: compile.h::b_return is only set, never used
 
     ISSUES:
 
@@ -2507,37 +2504,67 @@
 }
 
 static int
+compiler_import_as(struct compiler *c, identifier name, identifier asname)
+{
+	/* The IMPORT_NAME opcode was already generated.  This function
+	   merely needs to bind the result to a name.
+
+	   If there is a dot in name, we need to split it and emit a 
+	   LOAD_ATTR for each name.
+	*/
+	const char *src = PyString_AS_STRING(name);
+	const char *dot = strchr(src, '.');
+	if (dot) {
+		/* Consume the base module name to get the first attribute */
+		src = dot + 1;
+		while (dot) {
+			/* NB src is only defined when dot != NULL */
+			dot = strchr(src, '.');
+			PyObject *attr = PyString_FromStringAndSize(src, 
+					    dot ? dot - src : strlen(src));
+			ADDOP_O(c, LOAD_ATTR, attr, names);
+			src = dot + 1;
+		}
+	}
+	return compiler_nameop(c, asname, Store);
+}
+
+static int
 compiler_import(struct compiler *c, stmt_ty s)
 {
+	/* The Import node stores a module name like a.b.c as a single
+	   string.  This is convenient for all cases except
+	     import a.b.c as d
+	   where we need to parse that string to extract the individual
+	   module names.  
+	   XXX Perhaps change the representation to make this case simpler?
+	 */
 	int i, n = asdl_seq_LEN(s->v.Import.names);
 	for (i = 0; i < n; i++) {
 		alias_ty alias = asdl_seq_GET(s->v.Import.names, i);
-		identifier store_name;
+		int r;
+
 		ADDOP_O(c, LOAD_CONST, Py_None, consts);
 		ADDOP_NAME(c, IMPORT_NAME, alias->name, names);
 
-                /* XXX: handling of store_name should be cleaned up */
 		if (alias->asname) {
-			store_name = alias->asname;
-                        Py_INCREF(store_name);
+			return compiler_import_as(c, 
+						  alias->name, alias->asname);
                 }
                 else {
-                    const char *base = PyString_AS_STRING(alias->name);
-                    char *dot = strchr(base, '.');
-                    if (dot)
-                        store_name = PyString_FromStringAndSize(base,
-                                                                dot - base);
-                    else {
-                        store_name = alias->name;
-                        Py_INCREF(store_name);
-                    }
-                }
-
-		if (!compiler_nameop(c, store_name, Store)) {
-                    Py_DECREF(store_name);
-                    return 0;
-                }
-                Py_DECREF(store_name);
+			identifier tmp = alias->name;
+			const char *base = PyString_AS_STRING(alias->name);
+			char *dot = strchr(base, '.');
+			if (dot)
+				tmp = PyString_FromStringAndSize(base, 
+								 dot - base);
+			r = compiler_nameop(c, tmp, Store);
+			if (dot) {
+				Py_DECREF(tmp);
+			}
+			if (!r)
+				return r;
+		}
 	}
 	return 1;
 }
@@ -2913,6 +2940,14 @@
 		break;
 	}
 
+	fprintf(stderr, 
+		"block=%s name=%s opt=%d scope=%d optype=%d\n", 
+		PyString_AS_STRING(c->u->u_ste->ste_name),
+		PyString_AS_STRING(name), 
+		c->u->u_ste->ste_unoptimized, scope, optype);
+	/* XXX Leave assert here, but handle __doc__ and the like better */
+	assert(scope || PyString_AS_STRING(name)[0] == '_');
+
 	switch (optype) {
 	case OP_DEREF:
 		switch (ctx) {
@@ -3301,7 +3336,7 @@
 
 	name = PyString_FromString("<generator expression>");
 	if (!name)
-    return 0;
+	  return 0;
 
 	if (!compiler_enter_scope(c, name, (void *)e, e->lineno))
 		return 0;

Index: symtable.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/symtable.c,v
retrieving revision 2.10.8.37
retrieving revision 2.10.8.38
diff -u -d -r2.10.8.37 -r2.10.8.38
--- symtable.c	11 Oct 2005 19:18:11 -0000	2.10.8.37
+++ symtable.c	14 Oct 2005 20:06:13 -0000	2.10.8.38
@@ -1195,9 +1195,25 @@
 static int 
 symtable_visit_alias(struct symtable *st, alias_ty a)
 {
+	/* Compute store_name, the name actually bound by the import
+	   operation.  It is diferent than a->name when a->name is a
+	   dotted package name (e.g. spam.eggs) 
+	*/
+	PyObject *store_name;
 	PyObject *name = (a->asname == NULL) ? a->name : a->asname;
-	if (strcmp(PyString_AS_STRING(name), "*"))
-	    return symtable_add_def(st, name, DEF_IMPORT);
+	const char *base = PyString_AS_STRING(name);
+	char *dot = strchr(base, '.');
+	if (dot)
+		store_name = PyString_FromStringAndSize(base, dot - base);
+	else {
+		store_name = name;
+		Py_INCREF(store_name);
+	}
+	if (strcmp(PyString_AS_STRING(name), "*")) {
+		int r = symtable_add_def(st, store_name, DEF_IMPORT); 
+		Py_DECREF(store_name);
+		return r;
+	}
 	else {
             if (st->st_cur->ste_type != ModuleBlock) {
                 if (!symtable_warn(st,



More information about the Python-checkins mailing list