Robert Ancell added the comment:
I've attached proof-of-concept showing how os.environ would ideally
work. It'll only work in Posix, etc etc.
Reading into it more there are a lot of general issues with environments
and memory allocation which is why I suspect Python doesn't use
putenv... See putenv(3) for details.
Compile with:
gcc -shared -o environmodule.so -g -Wall -I /usr/include/python2.5
environmodule.c
__________________________________
Tracker <[EMAIL PROTECTED]>
<http://bugs.python.org/issue1159>
__________________________________
#include "Python.h"
#include <stdlib.h>
static PyObject *environ_getenv(PyObject *self, PyObject *args)
{
char *name, *result;
if(!PyArg_ParseTuple(args, "s", &name))
return NULL;
result = getenv(name);
if(result == NULL)
Py_RETURN_NONE;
else
return PyString_FromString(result);
}
static PyObject *environ_putenv(PyObject *self, PyObject *args)
{
int result;
char *name, *value, *buffer;
if (!PyArg_ParseTuple(args, "ss", &name, &value))
return NULL;
buffer = malloc(sizeof(char) * (strlen(name) + 1 + strlen(value)));
sprintf(buffer, "%s=%s", name, value);
result = putenv(buffer);
return PyInt_FromLong((long)result);
}
/* Environment iterator */
typedef struct {
PyObject_HEAD
int offset;
} environ_EnvironIterObject;
static PyTypeObject environ_EnvironIterType = {
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"environ.EnvironIter", /*tp_name*/
sizeof(environ_EnvironIterObject) /*tp_basicsize*/
};
static PyObject *Environ_iternext(PyObject *object)
{
environ_EnvironIterObject *o = (environ_EnvironIterObject *)object;
char *value;
int i;
/* Must count from the start in case the environment has shrunk since the last iteration */
for(i = 0; i < o->offset && environ[i]; i++)
value = environ[i];
o->offset++;
if(value == NULL)
return NULL;
else
return PyString_FromString(value);
}
/* Environment object */
typedef struct {
PyObject_HEAD
} environ_EnvironObject;
static PyTypeObject environ_EnvironType = {
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"environ.Environ", /*tp_name*/
sizeof(environ_EnvironObject) /*tp_basicsize*/
};
static PyObject *Environ_getitem(PyObject *self, PyObject *arg)
{
char *result, *name;
name = PyString_AsString(arg);
result = getenv(name);
if(result == NULL)
Py_RETURN_NONE;
else
return PyString_FromString(result); /* FIXME: Should split into a 2-tuple */
}
static int Environ_setitem(PyObject *self, PyObject *key, PyObject *v)
{
int result;
char *name, *value, *buffer;
name = PyString_AsString(key);
value = PyString_AsString(v);
/* FIXME: free() the current value if we set it (i.e. getenv() == malloced_value + len(name) + len('=')) */
/* FIXME: We need to remember this malloc so we can free() it later */
buffer = malloc(sizeof(char) * (strlen(name) + 1 + strlen(value)));
sprintf(buffer, "%s=%s", name, value);
result = putenv(buffer);
return 0;
}
static PyMethodDef Environ_methods[] = {
{NULL}
};
static Py_ssize_t Environ_length(PyObject *mp)
{
int count;
for(count = 0; environ[count] != NULL; count++);
return count;
}
static PyMappingMethods environ_as_mapping = {
(lenfunc)Environ_length, /*mp_length*/
(binaryfunc)Environ_getitem, /*mp_subscript*/
(objobjargproc)Environ_setitem, /*mp_ass_subscript*/
};
static PyObject *Environ_iter(PyObject *object)
{
/* NOTE: If the environment is changed during iteration it will be safe but unpredictable */
return environ_EnvironIterType.tp_alloc(&environ_EnvironIterType, 0);
}
/* Module initialisation */
static PyMethodDef environ_methods[] = {
{"getenv", environ_getenv, METH_VARARGS, ""},
{"putenv", environ_putenv, METH_VARARGS, ""},
{NULL}
};
PyMODINIT_FUNC initenviron(void)
{
PyObject *m, *environ;
environ_EnvironType.tp_flags = Py_TPFLAGS_DEFAULT;
environ_EnvironType.tp_doc = "Environment object";
environ_EnvironType.tp_new = PyType_GenericNew;
environ_EnvironType.tp_iter = Environ_iter;
environ_EnvironType.tp_methods = Environ_methods;
if(PyType_Ready(&environ_EnvironType) < 0)
return;
environ_EnvironIterType.tp_flags = Py_TPFLAGS_DEFAULT;
environ_EnvironIterType.tp_doc = "Environment iterator";
environ_EnvironIterType.tp_new = PyType_GenericNew;
environ_EnvironIterType.tp_iternext = Environ_iternext;
environ_EnvironIterType.tp_as_mapping = &environ_as_mapping;
if(PyType_Ready(&environ_EnvironIterType) < 0)
return;
m = Py_InitModule3("environ",
environ_methods,
"Module to test potential os.environ replacement");
environ = environ_EnvironType.tp_alloc(&environ_EnvironType, 0);
PyModule_AddObject(m, "environ", environ);
}
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com