[Python-Dev] Relative Package Imports

M.-A. Lemburg mal@lemburg.com
Fri, 10 Sep 1999 21:06:28 +0200


This is a multi-part message in MIME format.

--------------60F2EF1167E1920659766E3D
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Hi everybody,

I've spent the last two hours trying to get relative package
imports to work because I need them for my extension packages
which will soon all move under a new top-level package name
to overcome the conflicts with PIL and Zope.

Here are the results...

Demo Package Structure: (see the attached demopkg.zip)

[a]
       [b]
              bc.py
       ab.py

With the attached patch you can do the following:

# Pretty useless...
import a.b.__.ab

# From inside bc.py:
from __ import ab

# At top-level (also useless, but shows how this situation is handled):
import __.sys
# __ is bound to None since we are at top-level; sys is still
# being loaded though.

Of course, common usage will be of the form:
form __.__ import submodule_at_higher_level

Please tell me what you think and give it a try. It's a first
try and may have some design errors. Especially the way
head and tail are treated in Python/import.c:import_module_ex
may cause trouble -- I need help here.

Note: The patch is against the CVS version. If you run Python
in verbose mode, the patch will produce some verbose output
of what it's doing.

Enjoy,
-- 
Marc-Andre Lemburg
______________________________________________________________________
Y2000:                                                   113 days left
Business:                                      http://www.lemburg.com/
Python Pages:                           http://www.lemburg.com/python/

--------------60F2EF1167E1920659766E3D
Content-Type: text/plain; charset=us-ascii; name="parentimport.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="parentimport.patch"

--- /home/lemburg/orig/Python/Python/import.c	Fri Apr  9 19:00:51 1999
+++ Python/import.c	Fri Sep 10 20:51:02 1999
@@ -1572,10 +1572,14 @@ load_next(mod, altmod, p_name, buf, p_bu
 	char *dot = strchr(name, '.');
 	int len;
 	char *p;
 	PyObject *result;
 
+	if (Py_VerboseFlag)
+		printf("# load_next: (1) name='%s', buf='%.*s'\n",
+		       name,*p_buflen,buf);
+
 	if (dot == NULL) {
 		*p_name = NULL;
 		len = strlen(name);
 	}
 	else {
@@ -1586,10 +1590,39 @@ load_next(mod, altmod, p_name, buf, p_bu
 		PyErr_SetString(PyExc_ValueError,
 				"Empty module name");
 		return NULL;
 	}
 
+	/* Handle "__" indicator telling the import mechanism to
+	   continue the search one level higher in the package
+	   hierarchy */
+	if (strncmp(name,"__",len) == 0) {
+		PyObject *modules = PyImport_GetModuleDict();
+
+		/* Strip the final dotted name from buf */
+		dot = strrchr(buf, '.');
+		if (dot == NULL)
+			*p_buflen = 0;
+		else
+			*p_buflen = dot - buf;
+		buf[*p_buflen] = '\0';
+
+		/* Fetch the parent module or revert to a top-level search */
+		if (*p_buflen > 0) {
+			mod = PyDict_GetItemString(modules,buf);
+			if (mod == NULL) {
+				PyErr_SetString(PyExc_SystemError,
+						"Parent module missing");
+				return NULL;
+			}
+		}
+		else
+			mod = Py_None;
+		Py_INCREF(mod);
+		return mod;
+	}
+
 	p = buf + *p_buflen;
 	if (p != buf)
 		*p++ = '.';
 	if (p+len-buf >= MAXPATHLEN) {
 		PyErr_SetString(PyExc_ValueError,
@@ -1597,10 +1630,14 @@ load_next(mod, altmod, p_name, buf, p_bu
 		return NULL;
 	}
 	strncpy(p, name, len);
 	p[len] = '\0';
 	*p_buflen = p+len-buf;
+	
+	if (Py_VerboseFlag)
+		printf("# load_next: (2) modname='%s', fullname=buf='%s'\n",
+		       p,buf);
 
 	result = import_submodule(mod, p, buf);
 	if (result == Py_None && altmod != mod) {
 		Py_DECREF(result);
 		/* Here, altmod must be None and mod must not be None */

--------------60F2EF1167E1920659766E3D
Content-Type: application/x-zip-compressed; name="demopkg.zip"
Content-Transfer-Encoding: base64
Content-Disposition: inline; filename="demopkg.zip"

UEsDBAoAAgAAAASgKiejNvGqNwAAADcAAAANABUAYS9fX2luaXRfXy5weVVUCQADJ0fZN01H
2TdVeAQA9AFkAApwcmludCAnSW5pdCBtb2R1bGUgJXMsIHBhdGg9JXMnICUgKF9fbmFtZV9f
LF9fcGF0aF9fKQpQSwMECgACAAAALaAqJ+7ynLElAAAAJQAAAAcAFQBhL2FiLnB5VVQJAAN2
R9k3hEfZN1V4BAD0AWQACnByaW50ICdJbml0IG1vZHVsZSAlcycgJSAoX19uYW1lX18pClBL
AwQKAAIAAAAHoConozbxqjcAAAA3AAAADwAVAGEvYi9fX2luaXRfXy5weVVUCQADLkfZN09H
2TdVeAQA9AFkAApwcmludCAnSW5pdCBtb2R1bGUgJXMsIHBhdGg9JXMnICUgKF9fbmFtZV9f
LF9fcGF0aF9fKQpQSwMEFAACAAgAFqYqJzw5S0GaAAAAAgEAAAkAFQBhL2IvYmMucHlVVAkA
A4tS2TeTUtk3VXgEAPQBZABljkEKgzAQRfc5xYcitpscoOABuumqpcsQddSAyUgSld6+amMR
uprFf2/+F4M3LiK/ORNhuR57QhZyZDgr5bQlpS5CJOjh38a1MHZgH8HNLigldYmigF6vlDIX
idmSn/8ihI7HvobjGZ2eCLqqKARETk82+Ysn94Q7e6t7jEG3hHnzS7qKxrNdoH3OoecZ1pl/
OWZCS/HYsUgfUEsBAhYDCgACAAAABKAqJ6M28ao3AAAANwAAAA0ADQAAAAAAAQAAAKSBAAAA
AGEvX19pbml0X18ucHlVVAUAAydH2TdVeAAAUEsBAhYDCgACAAAALaAqJ+7ynLElAAAAJQAA
AAcADQAAAAAAAQAAAKSBdwAAAGEvYWIucHlVVAUAA3ZH2TdVeAAAUEsBAhYDCgACAAAAB6Aq
J6M28ao3AAAANwAAAA8ADQAAAAAAAQAAAKSB1gAAAGEvYi9fX2luaXRfXy5weVVUBQADLkfZ
N1V4AABQSwECFgMUAAIACAAWpionPDlLQZoAAAACAQAACQANAAAAAAABAAAApIFPAQAAYS9i
L2JjLnB5VVQFAAOLUtk3VXgAAFBLBQYAAAAABAAEABgBAAAlAgAAAAA=
--------------60F2EF1167E1920659766E3D--