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

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

I think Python should have a more universal import mechanism , = which could=20 be done
by adding a new C_CUSTOM type  to the definitions for dynamic = loading=20 (importdl.h) ,
a new struct _customtab to import.h and a new function = to Python API=20 (import.c).
Then any archive,database,internet import architecture = could be=20 implemented
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 =20 (*get_name)(char*),void (*initfunc)(char*));
 
struct _customtab {
 int =20 (*get_name)(char*);
    void=20 (*initfunc)(char*);
 struct _customtab *next;
};
 
 
 
importdl.h
enum filetype=20 {
 SEARCH_ERROR,
 PY_SOURCE,
 PY_COMPILED,
&nb= sp;C_EXTENSION,
 PY_RESOURCE,=20 /* Mac only=20 */
 PKG_DIRECTORY,
 C_BUILTIN,
 PY_FROZEN,
&nb= sp;C_CUSTOM,
 PY_CODERESOURCE=20 /* Mac only */
};
 
import.c
struct _customtab *PyImport_Customtab;
 
 
int
PyImport_AppendCustomtab(int  (*get_name)(char*),void=20 (*initfunc)(char*))
{
  struct _customtab = *pycustomtab;
 =20 struct _customtab *newtab=3DPyMem_NEW(struct _customtab,1);
 =20 newtab->get_name=3Dget_name;
  = newtab->initfunc=3Dinitfunc;
 =20 newtab->next=3DNULL;
 
  pycustomtab=3DPyImport_Customtab;
  if (pycustomtab)
  {
 =20 while(pycustomtab->next)
    =20 pycustomtab=3Dpycustomtab->next;
 =20 pycustomtab->next=3Dnewtab;
  }
 =20 else
     PyImport_Customtab=3Dnewtab;
  return 1;
 }
 
 
static struct filedescr *
find_module(char *realname, PyObject = *path,=20 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,=20 name);
   return = &fd_custom;
  }
 
  if (find_frozen(name) !=3D NULL)=20 {
   strcpy(buf, name);
   return=20 &fd_frozen;
....................................................................= ...............................
and again:
if (path =3D=3D NULL) {
  if (is_custom(name)) {
   strcpy(buf,=20 name);
   return = &fd_custom;
  }
 
LOAD_MODULE
static PyObject *
load_module(char *name, FILE *fp, char *buf, = int=20 type)
....................................................................= ...............................
switch (type) {
.............................................
case C_CUSTOM:
 
  if (buf !=3D NULL && buf[0] !=3D=20 '\0')
   name =3D = buf;
  
   err=20 =3D init_custom(name);
  
  if (err <=20 0)
   return NULL;
  if (err =3D=3D 0)=20 {
   PyErr_Format(PyExc_ImportError,
  &nb= sp;     =20 "Purported %s module %.200s not=20 found",
         type =3D=3D = C_BUILTIN=20 ?
      "builtin" : type =3D=3D = C_CUSTOM ?=20 "custom":"frozen",
        =20 name);
   return = NULL;
  }
  modules=20 =3D PyImport_GetModuleDict();
  m =3D = PyDict_GetItemString(modules,=20 name);
  if (m =3D=3D NULL)=20 {
   PyErr_Format(
    PyExc_Imp= ortError,
    "%s=20 module %.200s not properly initialized",
    type = =3D=3D=20 C_BUILTIN ?
      "builtin" : type = =3D=3D C_CUSTOM=20 ?=20 "custom":"frozen",
    name);
   = ;return=20 NULL;
  }
  Py_INCREF(m);
  break;=
 
IS_CUSTOM
 
static int
is_custom(char *name)
{
  struct = _customtab=20 *p;
 
if (!PyImport_Customtab)
  return 0;
 
p=3DPyImport_Customtab;
 
while(p){
     if=20 (p->get_name)
         if=20 ((*p->get_name)(name))
      return=20 1;
     p=3Dp->next;
}
 return = 0;
}
 
INIT_CUSTOM
static int
init_custom(char *name)
{
 struct = _customtab *p =3D=20 PyImport_Customtab;
 
 if (_PyImport_FindExtension(name, name) !=3D=20 NULL)
  return 1;
 
 while(p) {
     if=20 (p->get_name){
   if ((*p->get_name)(name))=20 {
    if (p->initfunc =3D=3D NULL)=20 {
     PyErr_Format(PyExc_ImportError,
&nb= sp;     "Cannot=20 re-init internal module=20 %.200s",
      name);
  &nb= sp;  return=20 -1;
    }
    if=20 (Py_VerboseFlag)
     PySys_WriteStderr("impo= rt %s #=20 builtin\n",=20 name);
    (*p->initfunc)(name);
  = ;  if=20 (PyErr_Occurred())
     return=20 -1;
    if (_PyImport_FixupExtension(name, name) = =3D=3D=20 NULL)
     return=20 -1;
    return=20 1;
   }
  }
 =20 p=3Dp->next;
 }
 return 0;
}
 
 
 
 

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