Rip out the file object's implementation.

Fixed test_import.py while I was at it.

However, there's still a problem in import.c -- get_file() can leak a
FILE struct (not a file descriptor though).  I'm not sure how to fix
this; closing the FILE* closes the file descriptor, and that's the
wrong thing to do when there's still a Python file object keeping the
file descriptor open.  I also would rather not mess with dup(), as it
won't port to Windows.
This commit is contained in:
Guido van Rossum 2007-06-12 23:30:11 +00:00
parent 2d5c219fe0
commit da5b8f2d28
14 changed files with 106 additions and 2537 deletions

View file

@ -659,8 +659,7 @@ builtin_exec(PyObject *self, PyObject *args)
locals = globals;
if (!PyString_Check(prog) &&
!PyUnicode_Check(prog) &&
!PyCode_Check(prog) &&
!PyFile_Check(prog)) {
!PyCode_Check(prog)) {
PyErr_Format(PyExc_TypeError,
"exec() arg 1 must be a string, file, or code "
"object, not %.100s", prog->ob_type->tp_name);
@ -692,18 +691,6 @@ builtin_exec(PyObject *self, PyObject *args)
}
v = PyEval_EvalCode((PyCodeObject *) prog, globals, locals);
}
else if (PyFile_Check(prog)) {
FILE *fp = PyFile_AsFile(prog);
char *name = PyString_AsString(PyFile_Name(prog));
PyCompilerFlags cf;
cf.cf_flags = 0;
if (PyEval_MergeCompilerFlags(&cf))
v = PyRun_FileFlags(fp, name, Py_file_input, globals,
locals, &cf);
else
v = PyRun_File(fp, name, Py_file_input, globals,
locals);
}
else {
char *str = source_as_string(prog);
PyCompilerFlags cf;

View file

@ -2764,19 +2764,21 @@ static FILE *
get_file(char *pathname, PyObject *fob, char *mode)
{
FILE *fp;
if (mode[0] == 'U')
mode = "r" PY_STDIOTEXTMODE;
if (fob == NULL) {
if (mode[0] == 'U')
mode = "r" PY_STDIOTEXTMODE;
fp = fopen(pathname, mode);
if (fp == NULL)
PyErr_SetFromErrno(PyExc_IOError);
}
else {
fp = PyFile_AsFile(fob);
if (fp == NULL)
PyErr_SetString(PyExc_ValueError,
"bad/closed file object");
int fd = PyObject_AsFileDescriptor(fob);
if (fd == -1)
return NULL;
/* XXX This will leak a FILE struct. Fix this!!!!
(But it doesn't leak a file descrioptor!) */
fp = fdopen(fd, mode);
}
if (fp == NULL)
PyErr_SetFromErrno(PyExc_IOError);
return fp;
}
@ -2788,8 +2790,8 @@ imp_load_compiled(PyObject *self, PyObject *args)
PyObject *fob = NULL;
PyObject *m;
FILE *fp;
if (!PyArg_ParseTuple(args, "ss|O!:load_compiled", &name, &pathname,
&PyFile_Type, &fob))
if (!PyArg_ParseTuple(args, "ss|O:load_compiled",
&name, &pathname, &fob))
return NULL;
fp = get_file(pathname, fob, "rb");
if (fp == NULL)
@ -2810,8 +2812,8 @@ imp_load_dynamic(PyObject *self, PyObject *args)
PyObject *fob = NULL;
PyObject *m;
FILE *fp = NULL;
if (!PyArg_ParseTuple(args, "ss|O!:load_dynamic", &name, &pathname,
&PyFile_Type, &fob))
if (!PyArg_ParseTuple(args, "ss|O:load_dynamic",
&name, &pathname, &fob))
return NULL;
if (fob) {
fp = get_file(pathname, fob, "r");
@ -2832,8 +2834,8 @@ imp_load_source(PyObject *self, PyObject *args)
PyObject *fob = NULL;
PyObject *m;
FILE *fp;
if (!PyArg_ParseTuple(args, "ss|O!:load_source", &name, &pathname,
&PyFile_Type, &fob))
if (!PyArg_ParseTuple(args, "ss|O:load_source",
&name, &pathname, &fob))
return NULL;
fp = get_file(pathname, fob, "r");
if (fp == NULL)
@ -2873,12 +2875,7 @@ imp_load_module(PyObject *self, PyObject *args)
if (fob == Py_None)
fp = NULL;
else {
if (!PyFile_Check(fob)) {
PyErr_SetString(PyExc_ValueError,
"load_module arg#2 should be a file or None");
return NULL;
}
fp = get_file(pathname, fob, mode);
fp = get_file(NULL, fob, mode);
if (fp == NULL)
return NULL;
}

View file

@ -1138,81 +1138,52 @@ PyMarshal_WriteObjectToString(PyObject *x, int version)
static PyObject *
marshal_dump(PyObject *self, PyObject *args)
{
WFILE wf;
/* XXX Quick hack -- need to do this differently */
PyObject *x;
PyObject *f;
int version = Py_MARSHAL_VERSION;
PyObject *s;
PyObject *res;
if (!PyArg_ParseTuple(args, "OO|i:dump", &x, &f, &version))
return NULL;
if (!PyFile_Check(f)) {
/* XXX Quick hack -- need to do this differently */
PyObject *s = PyMarshal_WriteObjectToString(x, version);
PyObject *res = NULL;
if (s != NULL) {
res = PyObject_CallMethod(f, "write", "O", s);
Py_DECREF(s);
}
return res;
}
wf.fp = PyFile_AsFile(f);
wf.str = NULL;
wf.ptr = wf.end = NULL;
wf.error = 0;
wf.depth = 0;
wf.strings = (version > 0) ? PyDict_New() : 0;
wf.version = version;
w_object(x, &wf);
Py_XDECREF(wf.strings);
if (wf.error) {
PyErr_SetString(PyExc_ValueError,
(wf.error==1)?"unmarshallable object"
:"object too deeply nested to marshal");
s = PyMarshal_WriteObjectToString(x, version);
if (s == NULL)
return NULL;
}
Py_INCREF(Py_None);
return Py_None;
res = PyObject_CallMethod(f, "write", "O", s);
Py_DECREF(s);
return res;
}
static PyObject *
marshal_load(PyObject *self, PyObject *f)
{
/* XXX Quick hack -- need to do this differently */
PyObject *data, *result;
RFILE rf;
PyObject *result;
if (!PyFile_Check(f)) {
/* XXX Quick hack -- need to do this differently */
PyObject *data, *result;
RFILE rf;
data = PyObject_CallMethod(f, "read", "");
if (data == NULL)
return NULL;
rf.fp = NULL;
if (PyString_Check(data)) {
rf.ptr = PyString_AS_STRING(data);
rf.end = rf.ptr + PyString_GET_SIZE(data);
}
else if (PyBytes_Check(data)) {
rf.ptr = PyBytes_AS_STRING(data);
rf.end = rf.ptr + PyBytes_GET_SIZE(data);
}
else {
PyErr_Format(PyExc_TypeError,
"f.read() returned neither string "
"nor bytes but %.100s",
data->ob_type->tp_name);
Py_DECREF(data);
return NULL;
}
rf.strings = PyList_New(0);
result = read_object(&rf);
Py_DECREF(rf.strings);
Py_DECREF(data);
return result;
data = PyObject_CallMethod(f, "read", "");
if (data == NULL)
return NULL;
rf.fp = NULL;
if (PyString_Check(data)) {
rf.ptr = PyString_AS_STRING(data);
rf.end = rf.ptr + PyString_GET_SIZE(data);
}
else if (PyBytes_Check(data)) {
rf.ptr = PyBytes_AS_STRING(data);
rf.end = rf.ptr + PyBytes_GET_SIZE(data);
}
else {
PyErr_Format(PyExc_TypeError,
"f.read() returned neither string "
"nor bytes but %.100s",
data->ob_type->tp_name);
Py_DECREF(data);
return NULL;
}
rf.fp = PyFile_AsFile(f);
rf.strings = PyList_New(0);
rf.depth = 0;
result = read_object(&rf);
Py_DECREF(rf.strings);
Py_DECREF(data);
return result;
}

View file

@ -155,7 +155,6 @@ Py_InitializeEx(int install_sigs)
#if defined(HAVE_LANGINFO_H) && defined(CODESET)
char *codeset;
char *saved_locale;
PyObject *sys_stream, *sys_isatty;
#endif
extern void _Py_ReadyTypes(void);
@ -273,39 +272,6 @@ Py_InitializeEx(int install_sigs)
free(saved_locale);
if (codeset) {
sys_stream = PySys_GetObject("stdin");
sys_isatty = PyObject_CallMethod(sys_stream, "isatty", "");
if (!sys_isatty)
PyErr_Clear();
if(sys_isatty && PyObject_IsTrue(sys_isatty) &&
PyFile_Check(sys_stream)) {
if (!PyFile_SetEncoding(sys_stream, codeset))
Py_FatalError("Cannot set codeset of stdin");
}
Py_XDECREF(sys_isatty);
sys_stream = PySys_GetObject("stdout");
sys_isatty = PyObject_CallMethod(sys_stream, "isatty", "");
if (!sys_isatty)
PyErr_Clear();
if(sys_isatty && PyObject_IsTrue(sys_isatty) &&
PyFile_Check(sys_stream)) {
if (!PyFile_SetEncoding(sys_stream, codeset))
Py_FatalError("Cannot set codeset of stdout");
}
Py_XDECREF(sys_isatty);
sys_stream = PySys_GetObject("stderr");
sys_isatty = PyObject_CallMethod(sys_stream, "isatty", "");
if (!sys_isatty)
PyErr_Clear();
if(sys_isatty && PyObject_IsTrue(sys_isatty) &&
PyFile_Check(sys_stream)) {
if (!PyFile_SetEncoding(sys_stream, codeset))
Py_FatalError("Cannot set codeset of stderr");
}
Py_XDECREF(sys_isatty);
if (!Py_FileSystemDefaultEncoding)
Py_FileSystemDefaultEncoding = codeset;
else

View file

@ -55,18 +55,6 @@ PySys_GetObject(char *name)
return PyDict_GetItemString(sd, name);
}
FILE *
PySys_GetFile(char *name, FILE *def)
{
FILE *fp = NULL;
PyObject *v = PySys_GetObject(name);
if (v != NULL && PyFile_Check(v))
fp = PyFile_AsFile(v);
if (fp == NULL)
fp = def;
return fp;
}
int
PySys_SetObject(char *name, PyObject *v)
{
@ -1353,25 +1341,21 @@ mywrite(char *name, FILE *fp, const char *format, va_list va)
{
PyObject *file;
PyObject *error_type, *error_value, *error_traceback;
char buffer[1001];
int written;
PyErr_Fetch(&error_type, &error_value, &error_traceback);
file = PySys_GetObject(name);
if (file == NULL || PyFile_AsFile(file) == fp)
vfprintf(fp, format, va);
else {
char buffer[1001];
const int written = PyOS_vsnprintf(buffer, sizeof(buffer),
format, va);
if (PyFile_WriteString(buffer, file) != 0) {
written = PyOS_vsnprintf(buffer, sizeof(buffer), format, va);
if (PyFile_WriteString(buffer, file) != 0) {
PyErr_Clear();
fputs(buffer, fp);
}
if (written < 0 || (size_t)written >= sizeof(buffer)) {
const char *truncated = "... truncated";
if (PyFile_WriteString(truncated, file) != 0) {
PyErr_Clear();
fputs(buffer, fp);
}
if (written < 0 || (size_t)written >= sizeof(buffer)) {
const char *truncated = "... truncated";
if (PyFile_WriteString(truncated, file) != 0) {
PyErr_Clear();
fputs(truncated, fp);
}
fputs(truncated, fp);
}
}
PyErr_Restore(error_type, error_value, error_traceback);