[Python-Dev] New universal import mechanism ( Re: [Python-checkins] python/dist/src/Python import.c,2.210,2.211)

Wiktor Sadowski Wiktor Sadowski" <art@wiktorsadowski.com
Sun, 1 Dec 2002 02:16:52 +0100


This is a multi-part message in MIME format.

------=_NextPart_000_002D_01C298DF.B68FC6C0
Content-Type: text/plain;
	charset="windows-1250"
Content-Transfer-Encoding: quoted-printable

I think Python should have a more universal import mechanism , which =
could be done
by adding a new C_CUSTOM type  to the definitions for dynamic loading =
(importdl.h) ,
a new struct _customtab to import.h and a new function to Python API =
(import.c).
Then any archive,database,internet import architecture could be =
implemented=20
in C extensions without messing with Python core.

Wiktor Sadowski
www.wiktorsadowski.com


IMPLEMENTATION
(tested on win_98)

import.h
extern DL_IMPORT(int) PyImport_AppendCustomtab(int  =
(*get_name)(char*),void (*initfunc)(char*));

struct _customtab {
 int  (*get_name)(char*);
    void (*initfunc)(char*);
 struct _customtab *next;
};



importdl.h
enum filetype {
 SEARCH_ERROR,
 PY_SOURCE,
 PY_COMPILED,
 C_EXTENSION,
 PY_RESOURCE, /* Mac only */
 PKG_DIRECTORY,
 C_BUILTIN,
 PY_FROZEN,
 C_CUSTOM,
 PY_CODERESOURCE /* Mac only */
};

import.c
struct _customtab *PyImport_Customtab;


int=20
PyImport_AppendCustomtab(int  (*get_name)(char*),void =
(*initfunc)(char*))
{
  struct _customtab *pycustomtab;
  struct _customtab *newtab=3DPyMem_NEW(struct _customtab,1);
  newtab->get_name=3Dget_name;
  newtab->initfunc=3Dinitfunc;
  newtab->next=3DNULL;

  pycustomtab=3DPyImport_Customtab;
  if (pycustomtab)
  {
  while(pycustomtab->next)
     pycustomtab=3Dpycustomtab->next;=20
  pycustomtab->next=3Dnewtab;
  }
  else
     PyImport_Customtab=3Dnewtab;
  return 1;=20
 }


static struct filedescr *
find_module(char *realname, PyObject *path, char *buf, size_t buflen,
     FILE **p_fp)
.........................................................................=
..........................
static struct filedescr fd_custom =3D {"", "", C_CUSTOM};
.........................................................................=
..........................
before find_frozen !:

if (is_custom(name)) {
   strcpy(buf, name);
   return &fd_custom;
  }

  if (find_frozen(name) !=3D NULL) {
   strcpy(buf, name);
   return &fd_frozen;
.........................................................................=
..........................
and again:
if (path =3D=3D NULL) {
  if (is_custom(name)) {
   strcpy(buf, name);
   return &fd_custom;
  }

LOAD_MODULE
static PyObject *
load_module(char *name, FILE *fp, char *buf, int type)
.........................................................................=
..........................
switch (type) {
.............................................
case C_CUSTOM:

  if (buf !=3D NULL && buf[0] !=3D '\0')
   name =3D buf;
 =20
   err =3D init_custom(name);
 =20
  if (err < 0)
   return NULL;
  if (err =3D=3D 0) {
   PyErr_Format(PyExc_ImportError,
         "Purported %s module %.200s not found",
         type =3D=3D C_BUILTIN ?
      "builtin" : type =3D=3D C_CUSTOM ? "custom":"frozen",
         name);
   return NULL;
  }
  modules =3D PyImport_GetModuleDict();
  m =3D PyDict_GetItemString(modules, name);
  if (m =3D=3D NULL) {
   PyErr_Format(
    PyExc_ImportError,
    "%s module %.200s not properly initialized",
    type =3D=3D C_BUILTIN ?
      "builtin" : type =3D=3D C_CUSTOM ? "custom":"frozen",
    name);
   return NULL;
  }
  Py_INCREF(m);
  break;

IS_CUSTOM

static int
is_custom(char *name)
{
  struct _customtab *p;

if (!PyImport_Customtab)
  return 0;

p=3DPyImport_Customtab;

while(p){
     if (p->get_name)
         if ((*p->get_name)(name))
      return 1;
     p=3Dp->next;=20
}
 return 0;
}

INIT_CUSTOM
static int
init_custom(char *name)
{
 struct _customtab *p =3D PyImport_Customtab;

 if (_PyImport_FindExtension(name, name) !=3D NULL)
  return 1;

 while(p) {
     if (p->get_name){
   if ((*p->get_name)(name)) {
    if (p->initfunc =3D=3D NULL) {
     PyErr_Format(PyExc_ImportError,
      "Cannot re-init internal module %.200s",
      name);
     return -1;
    }
    if (Py_VerboseFlag)
     PySys_WriteStderr("import %s # builtin\n", name);
    (*p->initfunc)(name);
    if (PyErr_Occurred())
     return -1;
    if (_PyImport_FixupExtension(name, name) =3D=3D NULL)
     return -1;
    return 1;
   }
  }
  p=3Dp->next;
 }
 return 0;
}






------=_NextPart_000_002D_01C298DF.B68FC6C0
Content-Type: text/html;
	charset="windows-1250"
Content-Transfer-Encoding: quoted-printable

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=3DContent-Type content=3D"text/html; =
charset=3Dwindows-1250">
<META content=3D"MSHTML 6.00.2600.0" name=3DGENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY bgColor=3D#ffffff>
<DIV>I think Python should have a more universal import mechanism , =
which could=20
be done</DIV>
<DIV>by adding a new C_CUSTOM type&nbsp; to the definitions for dynamic =
loading=20
(importdl.h) ,</DIV>
<DIV>a new struct _customtab to import.h and a new function =
to&nbsp;Python API=20
(import.c).</DIV>
<DIV>Then any&nbsp;archive,database,internet import&nbsp;architecture =
could be=20
implemented </DIV>
<DIV>in C extensions without messing with Python core.</DIV>
<DIV><FONT face=3DArial size=3D2></FONT>&nbsp;</DIV>
<DIV>Wiktor Sadowski</DIV>
<DIV><A =
href=3D"http://www.wiktorsadowski.com">www.wiktorsadowski.com</A></DIV>
<DIV><FONT face=3DArial size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT face=3DArial size=3D2></FONT>&nbsp;</DIV>
<DIV>IMPLEMENTATION</DIV>
<DIV>(tested on win_98)</DIV>
<DIV>
<DIV><FONT face=3DArial size=3D2></FONT>&nbsp;</DIV>
<DIV>import.h</DIV>
<DIV>extern DL_IMPORT(int) PyImport_AppendCustomtab(int&nbsp;=20
(*get_name)(char*),void (*initfunc)(char*));</DIV>
<DIV>&nbsp;</DIV>
<DIV>struct _customtab {<BR>&nbsp;int&nbsp;=20
(*get_name)(char*);<BR>&nbsp;&nbsp;&nbsp; void=20
(*initfunc)(char*);<BR>&nbsp;struct _customtab *next;<BR>};</DIV></DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;</DIV>
<DIV>importdl.h</DIV>
<DIV>enum filetype=20
{<BR>&nbsp;SEARCH_ERROR,<BR>&nbsp;PY_SOURCE,<BR>&nbsp;PY_COMPILED,<BR>&nb=
sp;C_EXTENSION,<BR>&nbsp;PY_RESOURCE,=20
/* Mac only=20
*/<BR>&nbsp;PKG_DIRECTORY,<BR>&nbsp;C_BUILTIN,<BR>&nbsp;PY_FROZEN,<BR>&nb=
sp;C_CUSTOM,<BR>&nbsp;PY_CODERESOURCE=20
/* Mac only */<BR>};</DIV>
<DIV>&nbsp;</DIV>
<DIV>import.c</DIV>
<DIV>struct _customtab *PyImport_Customtab;</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;</DIV>
<DIV>int <BR>PyImport_AppendCustomtab(int&nbsp; (*get_name)(char*),void=20
(*initfunc)(char*))<BR>{<BR>&nbsp; struct _customtab =
*pycustomtab;<BR>&nbsp;=20
struct _customtab *newtab=3DPyMem_NEW(struct _customtab,1);<BR>&nbsp;=20
newtab-&gt;get_name=3Dget_name;<BR>&nbsp; =
newtab-&gt;initfunc=3Dinitfunc;<BR>&nbsp;=20
newtab-&gt;next=3DNULL;</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp; pycustomtab=3DPyImport_Customtab;</DIV>
<DIV>&nbsp; if (pycustomtab)<BR>&nbsp; {<BR>&nbsp;=20
while(pycustomtab-&gt;next)<BR>&nbsp;&nbsp;&nbsp;&nbsp;=20
pycustomtab=3Dpycustomtab-&gt;next; <BR>&nbsp;=20
pycustomtab-&gt;next=3Dnewtab;<BR>&nbsp; }<BR>&nbsp;=20
else<BR>&nbsp;&nbsp;&nbsp;&nbsp; PyImport_Customtab=3Dnewtab;</DIV>
<DIV>&nbsp; return 1; <BR>&nbsp;}</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;</DIV>
<DIV>static struct filedescr *<BR>find_module(char *realname, PyObject =
*path,=20
char *buf, size_t buflen,<BR>&nbsp;&nbsp;&nbsp;&nbsp; FILE **p_fp)</DIV>
<DIV>....................................................................=
...............................</DIV>
<DIV>static struct filedescr fd_custom =3D {"", "", C_CUSTOM};</DIV>
<DIV>....................................................................=
...............................</DIV>
<DIV>before find_frozen !:</DIV>
<DIV>&nbsp;</DIV>
<DIV>if (is_custom(name)) {<BR>&nbsp;&nbsp;&nbsp;strcpy(buf,=20
name);<BR>&nbsp;&nbsp;&nbsp;return =
&amp;fd_custom;<BR>&nbsp;&nbsp;}</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;&nbsp;if (find_frozen(name) !=3D NULL)=20
{<BR>&nbsp;&nbsp;&nbsp;strcpy(buf, name);<BR>&nbsp;&nbsp;&nbsp;return=20
&amp;fd_frozen;</DIV>
<DIV>....................................................................=
...............................</DIV>
<DIV>and again:</DIV>
<DIV>if (path =3D=3D NULL) {</DIV>
<DIV>&nbsp; if (is_custom(name)) {<BR>&nbsp;&nbsp;&nbsp;strcpy(buf,=20
name);<BR>&nbsp;&nbsp;&nbsp;return =
&amp;fd_custom;<BR>&nbsp;&nbsp;}</DIV>
<DIV>&nbsp;</DIV>
<DIV>LOAD_MODULE</DIV>
<DIV>static PyObject *<BR>load_module(char *name, FILE *fp, char *buf, =
int=20
type)</DIV>
<DIV>....................................................................=
...............................</DIV>
<DIV>switch (type) {</DIV>
<DIV>.............................................</DIV>
<DIV>case C_CUSTOM:</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;&nbsp;if (buf !=3D NULL &amp;&amp; buf[0] !=3D=20
'\0')<BR>&nbsp;&nbsp;&nbsp;name =3D =
buf;<BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;err=20
=3D init_custom(name);<BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;if (err &lt;=20
0)<BR>&nbsp;&nbsp;&nbsp;return NULL;<BR>&nbsp;&nbsp;if (err =3D=3D 0)=20
{<BR>&nbsp;&nbsp;&nbsp;PyErr_Format(PyExc_ImportError,<BR>&nbsp;&nbsp;&nb=
sp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=20
"Purported %s module %.200s not=20
found",<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type =3D=3D =
C_BUILTIN=20
?<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"builtin" : type =3D=3D =
C_CUSTOM ?=20
"custom":"frozen",<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=20
name);<BR>&nbsp;&nbsp;&nbsp;return =
NULL;<BR>&nbsp;&nbsp;}<BR>&nbsp;&nbsp;modules=20
=3D PyImport_GetModuleDict();<BR>&nbsp;&nbsp;m =3D =
PyDict_GetItemString(modules,=20
name);<BR>&nbsp;&nbsp;if (m =3D=3D NULL)=20
{<BR>&nbsp;&nbsp;&nbsp;PyErr_Format(<BR>&nbsp;&nbsp;&nbsp;&nbsp;PyExc_Imp=
ortError,<BR>&nbsp;&nbsp;&nbsp;&nbsp;"%s=20
module %.200s not properly initialized",<BR>&nbsp;&nbsp;&nbsp;&nbsp;type =
=3D=3D=20
C_BUILTIN ?<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"builtin" : type =
=3D=3D C_CUSTOM=20
?=20
"custom":"frozen",<BR>&nbsp;&nbsp;&nbsp;&nbsp;name);<BR>&nbsp;&nbsp;&nbsp=
;return=20
NULL;<BR>&nbsp;&nbsp;}<BR>&nbsp;&nbsp;Py_INCREF(m);<BR>&nbsp;&nbsp;break;=
</DIV>
<DIV>&nbsp;</DIV>
<DIV>IS_CUSTOM</DIV>
<DIV><FONT face=3DArial size=3D2></FONT>&nbsp;</DIV>
<DIV>static int<BR>is_custom(char *name)<BR>{<BR>&nbsp; struct =
_customtab=20
*p;</DIV>
<DIV>&nbsp;</DIV>
<DIV>if (!PyImport_Customtab)<BR>&nbsp; return 0;</DIV>
<DIV>&nbsp;</DIV>
<DIV>p=3DPyImport_Customtab;</DIV>
<DIV>&nbsp;</DIV>
<DIV>while(p){<BR>&nbsp;&nbsp; &nbsp; if=20
(p-&gt;get_name)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if=20
((*p-&gt;get_name)(name))<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return=20
1;<BR>&nbsp;&nbsp;&nbsp;&nbsp; p=3Dp-&gt;next; <BR>}<BR>&nbsp;return =
0;<BR>}</DIV>
<DIV>&nbsp;</DIV>
<DIV>INIT_CUSTOM</DIV>
<DIV>static int<BR>init_custom(char *name)<BR>{<BR>&nbsp;struct =
_customtab *p =3D=20
PyImport_Customtab;</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;if (_PyImport_FindExtension(name, name) !=3D=20
NULL)<BR>&nbsp;&nbsp;return 1;</DIV>
<DIV>&nbsp;</DIV>
<DIV>&nbsp;while(p) {<BR>&nbsp;&nbsp;&nbsp; &nbsp;if=20
(p-&gt;get_name){<BR>&nbsp;&nbsp;&nbsp;if ((*p-&gt;get_name)(name))=20
{<BR>&nbsp;&nbsp;&nbsp;&nbsp;if (p-&gt;initfunc =3D=3D NULL)=20
{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PyErr_Format(PyExc_ImportError,<BR>&nb=
sp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Cannot=20
re-init internal module=20
%.200s",<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;name);<BR>&nbsp;&nbsp;&nb=
sp;&nbsp;&nbsp;return=20
-1;<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;if=20
(Py_VerboseFlag)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PySys_WriteStderr("impo=
rt %s #=20
builtin\n",=20
name);<BR>&nbsp;&nbsp;&nbsp;&nbsp;(*p-&gt;initfunc)(name);<BR>&nbsp;&nbsp=
;&nbsp;&nbsp;if=20
(PyErr_Occurred())<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return=20
-1;<BR>&nbsp;&nbsp;&nbsp;&nbsp;if (_PyImport_FixupExtension(name, name) =
=3D=3D=20
NULL)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return=20
-1;<BR>&nbsp;&nbsp;&nbsp;&nbsp;return=20
1;<BR>&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;}<BR>&nbsp;=20
p=3Dp-&gt;next;<BR>&nbsp;}<BR>&nbsp;return 0;<BR>}<BR></DIV>
<DIV><FONT face=3DArial size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT face=3DArial size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT face=3DArial size=3D2><FONT face=3DArial =
size=3D2></FONT></FONT>&nbsp;</DIV>
<DIV><FONT face=3DArial size=3D2>&nbsp;</DIV></FONT></BODY></HTML>

------=_NextPart_000_002D_01C298DF.B68FC6C0--