mirror of
				https://github.com/python/cpython.git
				synced 2025-11-01 06:01:29 +00:00 
			
		
		
		
	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:
		
							parent
							
								
									2d5c219fe0
								
							
						
					
					
						commit
						da5b8f2d28
					
				
					 14 changed files with 106 additions and 2537 deletions
				
			
		|  | @ -1,5 +1,4 @@ | ||||||
| 
 | /* File object interface (what's left of it -- see io.py) */ | ||||||
| /* File object interface */ |  | ||||||
| 
 | 
 | ||||||
| #ifndef Py_FILEOBJECT_H | #ifndef Py_FILEOBJECT_H | ||||||
| #define Py_FILEOBJECT_H | #define Py_FILEOBJECT_H | ||||||
|  | @ -7,59 +6,20 @@ | ||||||
| extern "C" { | extern "C" { | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| typedef struct { | #define PY_STDIOTEXTMODE "b" | ||||||
| 	PyObject_HEAD |  | ||||||
| 	FILE *f_fp; |  | ||||||
| 	PyObject *f_name; |  | ||||||
| 	PyObject *f_mode; |  | ||||||
| 	int (*f_close)(FILE *); |  | ||||||
| 	int f_binary;		/* Flag which indicates whether the file is 
 |  | ||||||
| 				   open in binary (1) or text (0) mode */ |  | ||||||
| 	char* f_buf;		/* Allocated readahead buffer */ |  | ||||||
| 	char* f_bufend;		/* Points after last occupied position */ |  | ||||||
| 	char* f_bufptr;		/* Current buffer position */ |  | ||||||
| 	char *f_setbuf;		/* Buffer for setbuf(3) and setvbuf(3) */ |  | ||||||
| 	int f_univ_newline;	/* Handle any newline convention */ |  | ||||||
| 	int f_newlinetypes;	/* Types of newlines seen */ |  | ||||||
| 	int f_skipnextlf;	/* Skip next \n */ |  | ||||||
| 	PyObject *f_encoding; |  | ||||||
| 	PyObject *weakreflist; /* List of weak references */ |  | ||||||
| } PyFileObject; |  | ||||||
| 
 | 
 | ||||||
| PyAPI_DATA(PyTypeObject) PyFile_Type; | PyAPI_FUNC(PyObject *) PyFile_FromFile(FILE *, char *, char *, int (*)(FILE*)); | ||||||
| 
 |  | ||||||
| #define PyFile_Check(op) PyObject_TypeCheck(op, &PyFile_Type) |  | ||||||
| #define PyFile_CheckExact(op) ((op)->ob_type == &PyFile_Type) |  | ||||||
| 
 |  | ||||||
| PyAPI_FUNC(PyObject *) PyFile_FromString(char *, char *); |  | ||||||
| PyAPI_FUNC(void) PyFile_SetBufSize(PyObject *, int); |  | ||||||
| PyAPI_FUNC(int) PyFile_SetEncoding(PyObject *, const char *); |  | ||||||
| PyAPI_FUNC(PyObject *) PyFile_FromFile(FILE *, char *, char *, |  | ||||||
|                                              int (*)(FILE *)); |  | ||||||
| PyAPI_FUNC(FILE *) PyFile_AsFile(PyObject *); |  | ||||||
| PyAPI_FUNC(PyObject *) PyFile_Name(PyObject *); |  | ||||||
| PyAPI_FUNC(PyObject *) PyFile_GetLine(PyObject *, int); | PyAPI_FUNC(PyObject *) PyFile_GetLine(PyObject *, int); | ||||||
| PyAPI_FUNC(int) PyFile_WriteObject(PyObject *, PyObject *, int); | PyAPI_FUNC(int) PyFile_WriteObject(PyObject *, PyObject *, int); | ||||||
| PyAPI_FUNC(int) PyFile_WriteString(const char *, PyObject *); | PyAPI_FUNC(int) PyFile_WriteString(const char *, PyObject *); | ||||||
| PyAPI_FUNC(int) PyObject_AsFileDescriptor(PyObject *); | PyAPI_FUNC(int) PyObject_AsFileDescriptor(PyObject *); | ||||||
|  | PyAPI_FUNC(char *) Py_UniversalNewlineFgets(char *, int, FILE*, PyObject *); | ||||||
| 
 | 
 | ||||||
| /* The default encoding used by the platform file system APIs
 | /* The default encoding used by the platform file system APIs
 | ||||||
|    If non-NULL, this is different than the default encoding for strings |    If non-NULL, this is different than the default encoding for strings | ||||||
| */ | */ | ||||||
| PyAPI_DATA(const char *) Py_FileSystemDefaultEncoding; | PyAPI_DATA(const char *) Py_FileSystemDefaultEncoding; | ||||||
| 
 | 
 | ||||||
| /* Routines to replace fread() and fgets() which accept any of \r, \n
 |  | ||||||
|    or \r\n as line terminators. |  | ||||||
| */ |  | ||||||
| #define PY_STDIOTEXTMODE "b" |  | ||||||
| char *Py_UniversalNewlineFgets(char *, int, FILE*, PyObject *); |  | ||||||
| size_t Py_UniversalNewlineFread(char *, size_t, FILE *, PyObject *); |  | ||||||
| 
 |  | ||||||
| /* A routine to do sanity checking on the file mode string.  returns
 |  | ||||||
|    non-zero on if an exception occurred |  | ||||||
| */ |  | ||||||
| int _PyFile_SanitizeMode(char *mode); |  | ||||||
| 
 |  | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -9,7 +9,6 @@ extern "C" { | ||||||
| 
 | 
 | ||||||
| PyAPI_FUNC(PyObject *) PySys_GetObject(char *); | PyAPI_FUNC(PyObject *) PySys_GetObject(char *); | ||||||
| PyAPI_FUNC(int) PySys_SetObject(char *, PyObject *); | PyAPI_FUNC(int) PySys_SetObject(char *, PyObject *); | ||||||
| PyAPI_FUNC(FILE *) PySys_GetFile(char *, FILE *); |  | ||||||
| PyAPI_FUNC(void) PySys_SetArgv(int, char **); | PyAPI_FUNC(void) PySys_SetArgv(int, char **); | ||||||
| PyAPI_FUNC(void) PySys_SetPath(char *); | PyAPI_FUNC(void) PySys_SetPath(char *); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1287,12 +1287,13 @@ PyCursesWindow_PutWin(PyCursesWindowObject *self, PyObject *args) | ||||||
|    |    | ||||||
|   if (!PyArg_ParseTuple(args, "O;fileobj", &temp)) |   if (!PyArg_ParseTuple(args, "O;fileobj", &temp)) | ||||||
|     return NULL; |     return NULL; | ||||||
|   if (!PyFile_Check(temp)) { |   PyErr_SetString(PyExc_TypeError, "argument must be a file object"); | ||||||
|     PyErr_SetString(PyExc_TypeError, "argument must be a file object"); |   return NULL; | ||||||
|     return NULL; | 
 | ||||||
|   } | #if 0 | ||||||
|   return PyCursesCheckERR(putwin(self->win, PyFile_AsFile(temp)),  |   return PyCursesCheckERR(putwin(self->win, PyFile_AsFile(temp)),  | ||||||
| 			  "putwin"); | 			  "putwin"); | ||||||
|  | #endif | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static PyObject * | static PyObject * | ||||||
|  | @ -1748,11 +1749,10 @@ PyCurses_GetWin(PyCursesWindowObject *self, PyObject *temp) | ||||||
| 
 | 
 | ||||||
|   PyCursesInitialised |   PyCursesInitialised | ||||||
| 
 | 
 | ||||||
|   if (!PyFile_Check(temp)) { |   PyErr_SetString(PyExc_TypeError, "argument must be a file object"); | ||||||
|     PyErr_SetString(PyExc_TypeError, "argument must be a file object"); |   return NULL; | ||||||
|     return NULL; |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|  | #if 0 | ||||||
|   win = getwin(PyFile_AsFile(temp)); |   win = getwin(PyFile_AsFile(temp)); | ||||||
| 
 | 
 | ||||||
|   if (win == NULL) { |   if (win == NULL) { | ||||||
|  | @ -1761,6 +1761,7 @@ PyCurses_GetWin(PyCursesWindowObject *self, PyObject *temp) | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   return PyCursesWindow_New(win); |   return PyCursesWindow_New(win); | ||||||
|  | #endif | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static PyObject * | static PyObject * | ||||||
|  |  | ||||||
|  | @ -1075,6 +1075,7 @@ BZ2File_seek(BZ2FileObject *self, PyObject *args) | ||||||
| 		offset -= self->pos; | 		offset -= self->pos; | ||||||
| 	} else { | 	} else { | ||||||
| 		/* we cannot move back, so rewind the stream */ | 		/* we cannot move back, so rewind the stream */ | ||||||
|  | 		FILE *fp = NULL; /* XXX temporary!!! */ | ||||||
| 		BZ2_bzReadClose(&bzerror, self->fp); | 		BZ2_bzReadClose(&bzerror, self->fp); | ||||||
| 		if (bzerror != BZ_OK) { | 		if (bzerror != BZ_OK) { | ||||||
| 			Util_CatchBZ2Error(bzerror); | 			Util_CatchBZ2Error(bzerror); | ||||||
|  | @ -1086,7 +1087,7 @@ BZ2File_seek(BZ2FileObject *self, PyObject *args) | ||||||
| 		Py_DECREF(ret); | 		Py_DECREF(ret); | ||||||
| 		ret = NULL; | 		ret = NULL; | ||||||
| 		self->pos = 0; | 		self->pos = 0; | ||||||
| 		self->fp = BZ2_bzReadOpen(&bzerror, PyFile_AsFile(self->file), | 		self->fp = BZ2_bzReadOpen(&bzerror, fp, | ||||||
| 					  0, 0, NULL, 0); | 					  0, 0, NULL, 0); | ||||||
| 		if (bzerror != BZ_OK) { | 		if (bzerror != BZ_OK) { | ||||||
| 			Util_CatchBZ2Error(bzerror); | 			Util_CatchBZ2Error(bzerror); | ||||||
|  | @ -1286,6 +1287,7 @@ BZ2File_init(BZ2FileObject *self, PyObject *args, PyObject *kwargs) | ||||||
| { | { | ||||||
| 	static char *kwlist[] = {"filename", "mode", "buffering", | 	static char *kwlist[] = {"filename", "mode", "buffering", | ||||||
|                                        "compresslevel", 0}; |                                        "compresslevel", 0}; | ||||||
|  | 	FILE *fp = NULL; /* XXX temporary!!! */ | ||||||
| 	PyObject *name; | 	PyObject *name; | ||||||
| 	char *mode = "r"; | 	char *mode = "r"; | ||||||
| 	int buffering = -1; | 	int buffering = -1; | ||||||
|  | @ -1347,8 +1349,8 @@ BZ2File_init(BZ2FileObject *self, PyObject *args, PyObject *kwargs) | ||||||
| 
 | 
 | ||||||
| 	mode = (mode_char == 'r') ? "rb" : "wb"; | 	mode = (mode_char == 'r') ? "rb" : "wb"; | ||||||
| 
 | 
 | ||||||
| 	self->file = PyObject_CallFunction((PyObject*)&PyFile_Type, "(Osi)", | 	self->file = NULL; /* XXX io.open(name, mode, buffering); */ | ||||||
| 					   name, mode, buffering); | 	PyErr_SetString(PyExc_RuntimeError, "can't open bz2 files yet"); | ||||||
| 	if (self->file == NULL) | 	if (self->file == NULL) | ||||||
| 		return -1; | 		return -1; | ||||||
| 
 | 
 | ||||||
|  | @ -1365,11 +1367,11 @@ BZ2File_init(BZ2FileObject *self, PyObject *args, PyObject *kwargs) | ||||||
| 
 | 
 | ||||||
| 	if (mode_char == 'r') | 	if (mode_char == 'r') | ||||||
| 		self->fp = BZ2_bzReadOpen(&bzerror, | 		self->fp = BZ2_bzReadOpen(&bzerror, | ||||||
| 					  PyFile_AsFile(self->file), | 					  fp, | ||||||
| 					  0, 0, NULL, 0); | 					  0, 0, NULL, 0); | ||||||
| 	else | 	else | ||||||
| 		self->fp = BZ2_bzWriteOpen(&bzerror, | 		self->fp = BZ2_bzWriteOpen(&bzerror, | ||||||
| 					   PyFile_AsFile(self->file), | 					   fp, | ||||||
| 					   compresslevel, 0, 0); | 					   compresslevel, 0, 0); | ||||||
| 
 | 
 | ||||||
| 	if (bzerror != BZ_OK) { | 	if (bzerror != BZ_OK) { | ||||||
|  |  | ||||||
|  | @ -417,31 +417,6 @@ cPickle_ErrFormat(PyObject *ErrType, char *stringformat, char *format, ...) | ||||||
| 	return NULL; | 	return NULL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int |  | ||||||
| write_file(Picklerobject *self, const char *s, Py_ssize_t  n) |  | ||||||
| { |  | ||||||
| 	size_t nbyteswritten; |  | ||||||
| 
 |  | ||||||
| 	if (s == NULL) { |  | ||||||
| 		return 0; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (n > INT_MAX) { |  | ||||||
| 		/* String too large */ |  | ||||||
| 		return -1; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	Py_BEGIN_ALLOW_THREADS |  | ||||||
| 	nbyteswritten = fwrite(s, sizeof(char), n, self->fp); |  | ||||||
| 	Py_END_ALLOW_THREADS |  | ||||||
| 	if (nbyteswritten != (size_t)n) { |  | ||||||
| 		PyErr_SetFromErrno(PyExc_IOError); |  | ||||||
| 		return -1; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return (int)n; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int | static int | ||||||
| write_cStringIO(Picklerobject *self, const char *s, Py_ssize_t  n) | write_cStringIO(Picklerobject *self, const char *s, Py_ssize_t  n) | ||||||
| { | { | ||||||
|  | @ -516,92 +491,6 @@ write_other(Picklerobject *self, const char *s, Py_ssize_t  _n) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static Py_ssize_t |  | ||||||
| read_file(Unpicklerobject *self, char **s, Py_ssize_t n) |  | ||||||
| { |  | ||||||
| 	size_t nbytesread; |  | ||||||
| 
 |  | ||||||
| 	if (self->buf_size == 0) { |  | ||||||
| 		int size; |  | ||||||
| 
 |  | ||||||
| 		size = ((n < 32) ? 32 : n); |  | ||||||
| 		if (!( self->buf = (char *)malloc(size))) { |  | ||||||
| 			PyErr_NoMemory(); |  | ||||||
| 			return -1; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		self->buf_size = size; |  | ||||||
| 	} |  | ||||||
| 	else if (n > self->buf_size) { |  | ||||||
| 		char *newbuf = (char *)realloc(self->buf, n); |  | ||||||
| 		if (!newbuf)  { |  | ||||||
| 			PyErr_NoMemory(); |  | ||||||
| 			return -1; |  | ||||||
| 		} |  | ||||||
| 		self->buf = newbuf; |  | ||||||
| 		self->buf_size = n; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	Py_BEGIN_ALLOW_THREADS |  | ||||||
| 	nbytesread = fread(self->buf, sizeof(char), n, self->fp); |  | ||||||
| 	Py_END_ALLOW_THREADS |  | ||||||
| 	if (nbytesread != (size_t)n) { |  | ||||||
| 		if (feof(self->fp)) { |  | ||||||
| 			PyErr_SetNone(PyExc_EOFError); |  | ||||||
| 			return -1; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		PyErr_SetFromErrno(PyExc_IOError); |  | ||||||
| 		return -1; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	*s = self->buf; |  | ||||||
| 
 |  | ||||||
| 	return n; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| static Py_ssize_t |  | ||||||
| readline_file(Unpicklerobject *self, char **s) |  | ||||||
| { |  | ||||||
| 	int i; |  | ||||||
| 
 |  | ||||||
| 	if (self->buf_size == 0) { |  | ||||||
| 		if (!( self->buf = (char *)malloc(40))) { |  | ||||||
| 			PyErr_NoMemory(); |  | ||||||
| 			return -1; |  | ||||||
| 		} |  | ||||||
| 		self->buf_size = 40; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	i = 0; |  | ||||||
| 	while (1) { |  | ||||||
| 		int bigger; |  | ||||||
| 		char *newbuf; |  | ||||||
| 		for (; i < (self->buf_size - 1); i++) { |  | ||||||
| 			if (feof(self->fp) || |  | ||||||
| 			    (self->buf[i] = getc(self->fp)) == '\n') { |  | ||||||
| 				self->buf[i + 1] = '\0'; |  | ||||||
| 				*s = self->buf; |  | ||||||
| 				return i + 1; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		bigger = self->buf_size << 1; |  | ||||||
| 		if (bigger <= 0) {	/* overflow */ |  | ||||||
| 			PyErr_NoMemory(); |  | ||||||
| 			return -1; |  | ||||||
| 		} |  | ||||||
| 		newbuf = (char *)realloc(self->buf, bigger); |  | ||||||
| 		if (!newbuf)  { |  | ||||||
| 			PyErr_NoMemory(); |  | ||||||
| 			return -1; |  | ||||||
| 		} |  | ||||||
| 		self->buf = newbuf; |  | ||||||
| 		self->buf_size = bigger; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| static Py_ssize_t | static Py_ssize_t | ||||||
| read_cStringIO(Unpicklerobject *self, char **s, Py_ssize_t  n) | read_cStringIO(Unpicklerobject *self, char **s, Py_ssize_t  n) | ||||||
| { | { | ||||||
|  | @ -2665,16 +2554,7 @@ newPicklerobject(PyObject *file, int proto) | ||||||
| 	if (!( self->memo = PyDict_New())) | 	if (!( self->memo = PyDict_New())) | ||||||
| 		goto err; | 		goto err; | ||||||
| 
 | 
 | ||||||
| 	if (PyFile_Check(file)) { |         if (PycStringIO_OutputCheck(file)) { | ||||||
| 		self->fp = PyFile_AsFile(file); |  | ||||||
| 		if (self->fp == NULL) { |  | ||||||
| 			PyErr_SetString(PyExc_ValueError, |  | ||||||
| 					"I/O operation on closed file"); |  | ||||||
| 			goto err; |  | ||||||
| 		} |  | ||||||
| 		self->write_func = write_file; |  | ||||||
| 	} |  | ||||||
| 	else if (PycStringIO_OutputCheck(file)) { |  | ||||||
| 		self->write_func = write_cStringIO; | 		self->write_func = write_cStringIO; | ||||||
| 	} | 	} | ||||||
| 	else if (file == Py_None) { | 	else if (file == Py_None) { | ||||||
|  | @ -4988,17 +4868,7 @@ newUnpicklerobject(PyObject *f) | ||||||
| 	self->file = f; | 	self->file = f; | ||||||
| 
 | 
 | ||||||
| 	/* Set read, readline based on type of f */ | 	/* Set read, readline based on type of f */ | ||||||
| 	if (PyFile_Check(f)) { | 	if (PycStringIO_InputCheck(f)) { | ||||||
| 		self->fp = PyFile_AsFile(f); |  | ||||||
| 		if (self->fp == NULL) { |  | ||||||
| 			PyErr_SetString(PyExc_ValueError, |  | ||||||
| 					"I/O operation on closed file"); |  | ||||||
| 			goto err; |  | ||||||
| 		} |  | ||||||
| 		self->read_func = read_file; |  | ||||||
| 		self->readline_func = readline_file; |  | ||||||
| 	} |  | ||||||
| 	else if (PycStringIO_InputCheck(f)) { |  | ||||||
| 		self->fp = NULL; | 		self->fp = NULL; | ||||||
| 		self->read_func = read_cStringIO; | 		self->read_func = read_cStringIO; | ||||||
| 		self->readline_func = readline_cStringIO; | 		self->readline_func = readline_cStringIO; | ||||||
|  |  | ||||||
|  | @ -956,10 +956,7 @@ xmlparse_ParseFile(xmlparseobject *self, PyObject *f) | ||||||
|     FILE *fp; |     FILE *fp; | ||||||
|     PyObject *readmethod = NULL; |     PyObject *readmethod = NULL; | ||||||
| 
 | 
 | ||||||
|     if (PyFile_Check(f)) { |     { | ||||||
|         fp = PyFile_AsFile(f); |  | ||||||
|     } |  | ||||||
|     else { |  | ||||||
|         fp = NULL; |         fp = NULL; | ||||||
|         readmethod = PyObject_GetAttrString(f, "read"); |         readmethod = PyObject_GetAttrString(f, "read"); | ||||||
|         if (readmethod == NULL) { |         if (readmethod == NULL) { | ||||||
|  |  | ||||||
							
								
								
									
										2141
									
								
								Objects/fileobject.c
									
										
									
									
									
								
							
							
						
						
									
										2141
									
								
								Objects/fileobject.c
									
										
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -669,66 +669,6 @@ PyTokenizer_Free(struct tok_state *tok) | ||||||
| 	PyMem_FREE(tok); | 	PyMem_FREE(tok); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #if !defined(PGEN) |  | ||||||
| static int |  | ||||||
| tok_stdin_decode(struct tok_state *tok, char **inp) |  | ||||||
| { |  | ||||||
| 	PyObject *enc, *sysstdin, *decoded, *utf8; |  | ||||||
| 	const char *encoding; |  | ||||||
| 	char *converted; |  | ||||||
| 
 |  | ||||||
| 	if (PySys_GetFile((char *)"stdin", NULL) != stdin) |  | ||||||
| 		return 0; |  | ||||||
| 	sysstdin = PySys_GetObject("stdin"); |  | ||||||
| 	if (sysstdin == NULL || !PyFile_Check(sysstdin)) |  | ||||||
| 		return 0; |  | ||||||
| 
 |  | ||||||
| 	enc = ((PyFileObject *)sysstdin)->f_encoding; |  | ||||||
| 	if (enc == NULL || !PyString_Check(enc)) |  | ||||||
| 		return 0; |  | ||||||
| 	Py_INCREF(enc); |  | ||||||
| 
 |  | ||||||
| 	encoding = PyString_AsString(enc); |  | ||||||
| 	decoded = PyUnicode_Decode(*inp, strlen(*inp), encoding, NULL); |  | ||||||
| 	if (decoded == NULL) |  | ||||||
| 		goto error_clear; |  | ||||||
| 
 |  | ||||||
| 	utf8 = PyUnicode_AsEncodedString(decoded, "utf-8", NULL); |  | ||||||
| 	Py_DECREF(decoded); |  | ||||||
| 	if (utf8 == NULL) |  | ||||||
| 		goto error_clear; |  | ||||||
| 
 |  | ||||||
| 	assert(PyBytes_Check(utf8)); |  | ||||||
| 	converted = new_string(PyBytes_AS_STRING(utf8), |  | ||||||
| 			       PyBytes_GET_SIZE(utf8)); |  | ||||||
| 	Py_DECREF(utf8); |  | ||||||
| 	if (converted == NULL) |  | ||||||
| 		goto error_nomem; |  | ||||||
| 
 |  | ||||||
| 	PyMem_FREE(*inp); |  | ||||||
| 	*inp = converted; |  | ||||||
| 	if (tok->encoding != NULL) |  | ||||||
| 		PyMem_FREE(tok->encoding); |  | ||||||
| 	tok->encoding = new_string(encoding, strlen(encoding)); |  | ||||||
| 	if (tok->encoding == NULL) |  | ||||||
| 		goto error_nomem; |  | ||||||
| 
 |  | ||||||
| 	Py_DECREF(enc); |  | ||||||
| 	return 0; |  | ||||||
| 
 |  | ||||||
| error_nomem: |  | ||||||
| 	Py_DECREF(enc); |  | ||||||
| 	tok->done = E_NOMEM; |  | ||||||
| 	return -1; |  | ||||||
| 
 |  | ||||||
| error_clear: |  | ||||||
| 	/* Fallback to iso-8859-1: for backward compatibility */ |  | ||||||
| 	Py_DECREF(enc); |  | ||||||
| 	PyErr_Clear(); |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| /* Get next char, updating state; error code goes into tok->done */ | /* Get next char, updating state; error code goes into tok->done */ | ||||||
| 
 | 
 | ||||||
| static int | static int | ||||||
|  | @ -768,10 +708,6 @@ tok_nextc(register struct tok_state *tok) | ||||||
| 				PyMem_FREE(newtok); | 				PyMem_FREE(newtok); | ||||||
| 				tok->done = E_EOF; | 				tok->done = E_EOF; | ||||||
| 			} | 			} | ||||||
| #if !defined(PGEN) |  | ||||||
| 			else if (tok_stdin_decode(tok, &newtok) != 0) |  | ||||||
| 				PyMem_FREE(newtok); |  | ||||||
| #endif |  | ||||||
| 			else if (tok->start != NULL) { | 			else if (tok->start != NULL) { | ||||||
| 				size_t start = tok->start - tok->buf; | 				size_t start = tok->start - tok->buf; | ||||||
| 				size_t oldlen = tok->cur - tok->buf; | 				size_t oldlen = tok->cur - tok->buf; | ||||||
|  |  | ||||||
|  | @ -659,8 +659,7 @@ builtin_exec(PyObject *self, PyObject *args) | ||||||
| 		locals = globals; | 		locals = globals; | ||||||
| 	if (!PyString_Check(prog) && | 	if (!PyString_Check(prog) && | ||||||
| 	    !PyUnicode_Check(prog) && | 	    !PyUnicode_Check(prog) && | ||||||
| 	    !PyCode_Check(prog) && | 	    !PyCode_Check(prog)) { | ||||||
| 	    !PyFile_Check(prog)) { |  | ||||||
| 		PyErr_Format(PyExc_TypeError, | 		PyErr_Format(PyExc_TypeError, | ||||||
| 			"exec() arg 1 must be a string, file, or code " | 			"exec() arg 1 must be a string, file, or code " | ||||||
| 			"object, not %.100s", prog->ob_type->tp_name); | 			"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); | 		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 { | 	else { | ||||||
| 		char *str = source_as_string(prog); | 		char *str = source_as_string(prog); | ||||||
| 		PyCompilerFlags cf; | 		PyCompilerFlags cf; | ||||||
|  |  | ||||||
|  | @ -2764,19 +2764,21 @@ static FILE * | ||||||
| get_file(char *pathname, PyObject *fob, char *mode) | get_file(char *pathname, PyObject *fob, char *mode) | ||||||
| { | { | ||||||
| 	FILE *fp; | 	FILE *fp; | ||||||
|  | 	if (mode[0] == 'U') | ||||||
|  | 		mode = "r" PY_STDIOTEXTMODE; | ||||||
| 	if (fob == NULL) { | 	if (fob == NULL) { | ||||||
| 		if (mode[0] == 'U') |  | ||||||
| 			mode = "r" PY_STDIOTEXTMODE; |  | ||||||
| 		fp = fopen(pathname, mode); | 		fp = fopen(pathname, mode); | ||||||
| 		if (fp == NULL) |  | ||||||
| 			PyErr_SetFromErrno(PyExc_IOError); |  | ||||||
| 	} | 	} | ||||||
| 	else { | 	else { | ||||||
| 		fp = PyFile_AsFile(fob); | 		int fd = PyObject_AsFileDescriptor(fob); | ||||||
| 		if (fp == NULL) | 		if (fd == -1) | ||||||
| 			PyErr_SetString(PyExc_ValueError, | 			return NULL; | ||||||
| 					"bad/closed file object"); | 		/* 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; | 	return fp; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -2788,8 +2790,8 @@ imp_load_compiled(PyObject *self, PyObject *args) | ||||||
| 	PyObject *fob = NULL; | 	PyObject *fob = NULL; | ||||||
| 	PyObject *m; | 	PyObject *m; | ||||||
| 	FILE *fp; | 	FILE *fp; | ||||||
| 	if (!PyArg_ParseTuple(args, "ss|O!:load_compiled", &name, &pathname, | 	if (!PyArg_ParseTuple(args, "ss|O:load_compiled", | ||||||
| 			      &PyFile_Type, &fob)) | 			      &name, &pathname, &fob)) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	fp = get_file(pathname, fob, "rb"); | 	fp = get_file(pathname, fob, "rb"); | ||||||
| 	if (fp == NULL) | 	if (fp == NULL) | ||||||
|  | @ -2810,8 +2812,8 @@ imp_load_dynamic(PyObject *self, PyObject *args) | ||||||
| 	PyObject *fob = NULL; | 	PyObject *fob = NULL; | ||||||
| 	PyObject *m; | 	PyObject *m; | ||||||
| 	FILE *fp = NULL; | 	FILE *fp = NULL; | ||||||
| 	if (!PyArg_ParseTuple(args, "ss|O!:load_dynamic", &name, &pathname, | 	if (!PyArg_ParseTuple(args, "ss|O:load_dynamic", | ||||||
| 			      &PyFile_Type, &fob)) | 			      &name, &pathname, &fob)) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	if (fob) { | 	if (fob) { | ||||||
| 		fp = get_file(pathname, fob, "r"); | 		fp = get_file(pathname, fob, "r"); | ||||||
|  | @ -2832,8 +2834,8 @@ imp_load_source(PyObject *self, PyObject *args) | ||||||
| 	PyObject *fob = NULL; | 	PyObject *fob = NULL; | ||||||
| 	PyObject *m; | 	PyObject *m; | ||||||
| 	FILE *fp; | 	FILE *fp; | ||||||
| 	if (!PyArg_ParseTuple(args, "ss|O!:load_source", &name, &pathname, | 	if (!PyArg_ParseTuple(args, "ss|O:load_source", | ||||||
| 			      &PyFile_Type, &fob)) | 			      &name, &pathname, &fob)) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	fp = get_file(pathname, fob, "r"); | 	fp = get_file(pathname, fob, "r"); | ||||||
| 	if (fp == NULL) | 	if (fp == NULL) | ||||||
|  | @ -2873,12 +2875,7 @@ imp_load_module(PyObject *self, PyObject *args) | ||||||
| 	if (fob == Py_None) | 	if (fob == Py_None) | ||||||
| 		fp = NULL; | 		fp = NULL; | ||||||
| 	else { | 	else { | ||||||
| 		if (!PyFile_Check(fob)) { | 		fp = get_file(NULL, fob, mode); | ||||||
| 			PyErr_SetString(PyExc_ValueError, |  | ||||||
| 				"load_module arg#2 should be a file or None"); |  | ||||||
| 			return NULL; |  | ||||||
| 		} |  | ||||||
| 		fp = get_file(pathname, fob, mode); |  | ||||||
| 		if (fp == NULL) | 		if (fp == NULL) | ||||||
| 			return NULL; | 			return NULL; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -1138,81 +1138,52 @@ PyMarshal_WriteObjectToString(PyObject *x, int version) | ||||||
| static PyObject * | static PyObject * | ||||||
| marshal_dump(PyObject *self, PyObject *args) | marshal_dump(PyObject *self, PyObject *args) | ||||||
| { | { | ||||||
| 	WFILE wf; | 	/* XXX Quick hack -- need to do this differently */ | ||||||
| 	PyObject *x; | 	PyObject *x; | ||||||
| 	PyObject *f; | 	PyObject *f; | ||||||
| 	int version = Py_MARSHAL_VERSION; | 	int version = Py_MARSHAL_VERSION; | ||||||
|  | 	PyObject *s; | ||||||
|  | 	PyObject *res; | ||||||
| 	if (!PyArg_ParseTuple(args, "OO|i:dump", &x, &f, &version)) | 	if (!PyArg_ParseTuple(args, "OO|i:dump", &x, &f, &version)) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	if (!PyFile_Check(f)) { | 	s = PyMarshal_WriteObjectToString(x, version); | ||||||
| 		/* XXX Quick hack -- need to do this differently */ | 	if (s == NULL) | ||||||
| 		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"); |  | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	} | 	res = PyObject_CallMethod(f, "write", "O", s); | ||||||
| 	Py_INCREF(Py_None); | 	Py_DECREF(s); | ||||||
| 	return Py_None; | 	return res; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static PyObject * | static PyObject * | ||||||
| marshal_load(PyObject *self, PyObject *f) | marshal_load(PyObject *self, PyObject *f) | ||||||
| { | { | ||||||
|  | 	/* XXX Quick hack -- need to do this differently */ | ||||||
|  | 	PyObject *data, *result; | ||||||
| 	RFILE rf; | 	RFILE rf; | ||||||
| 	PyObject *result; | 	data = PyObject_CallMethod(f, "read", ""); | ||||||
| 	if (!PyFile_Check(f)) { | 	if (data == NULL) | ||||||
| 		/* XXX Quick hack -- need to do this differently */ | 		return NULL; | ||||||
| 		PyObject *data, *result; | 	rf.fp = NULL; | ||||||
| 		RFILE rf; | 	if (PyString_Check(data)) { | ||||||
| 		data = PyObject_CallMethod(f, "read", ""); | 		rf.ptr = PyString_AS_STRING(data); | ||||||
| 		if (data == NULL) | 		rf.end = rf.ptr + PyString_GET_SIZE(data); | ||||||
| 			return NULL; | 	} | ||||||
| 		rf.fp = NULL; | 	else if (PyBytes_Check(data)) { | ||||||
| 		if (PyString_Check(data)) { | 		rf.ptr = PyBytes_AS_STRING(data); | ||||||
| 			rf.ptr = PyString_AS_STRING(data); | 		rf.end = rf.ptr + PyBytes_GET_SIZE(data); | ||||||
| 			rf.end = rf.ptr + PyString_GET_SIZE(data); | 	} | ||||||
| 		} | 	else { | ||||||
| 		else if (PyBytes_Check(data)) { | 		PyErr_Format(PyExc_TypeError, | ||||||
| 			rf.ptr = PyBytes_AS_STRING(data); | 			     "f.read() returned neither string " | ||||||
| 			rf.end = rf.ptr + PyBytes_GET_SIZE(data); | 			     "nor bytes but %.100s", | ||||||
| 		} | 			     data->ob_type->tp_name); | ||||||
| 		else { | 		Py_DECREF(data); | ||||||
| 			PyErr_Format(PyExc_TypeError, | 		return NULL; | ||||||
| 				     "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; |  | ||||||
| 	} | 	} | ||||||
| 	rf.fp = PyFile_AsFile(f); |  | ||||||
| 	rf.strings = PyList_New(0); | 	rf.strings = PyList_New(0); | ||||||
| 	rf.depth = 0; |  | ||||||
| 	result = read_object(&rf); | 	result = read_object(&rf); | ||||||
| 	Py_DECREF(rf.strings); | 	Py_DECREF(rf.strings); | ||||||
|  | 	Py_DECREF(data); | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -155,7 +155,6 @@ Py_InitializeEx(int install_sigs) | ||||||
| #if defined(HAVE_LANGINFO_H) && defined(CODESET) | #if defined(HAVE_LANGINFO_H) && defined(CODESET) | ||||||
| 	char *codeset; | 	char *codeset; | ||||||
| 	char *saved_locale; | 	char *saved_locale; | ||||||
| 	PyObject *sys_stream, *sys_isatty; |  | ||||||
| #endif | #endif | ||||||
| 	extern void _Py_ReadyTypes(void); | 	extern void _Py_ReadyTypes(void); | ||||||
| 
 | 
 | ||||||
|  | @ -273,39 +272,6 @@ Py_InitializeEx(int install_sigs) | ||||||
| 	free(saved_locale); | 	free(saved_locale); | ||||||
| 
 | 
 | ||||||
| 	if (codeset) { | 	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) | 		if (!Py_FileSystemDefaultEncoding) | ||||||
| 			Py_FileSystemDefaultEncoding = codeset; | 			Py_FileSystemDefaultEncoding = codeset; | ||||||
| 		else | 		else | ||||||
|  |  | ||||||
|  | @ -55,18 +55,6 @@ PySys_GetObject(char *name) | ||||||
| 	return PyDict_GetItemString(sd, 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 | int | ||||||
| PySys_SetObject(char *name, PyObject *v) | PySys_SetObject(char *name, PyObject *v) | ||||||
| { | { | ||||||
|  | @ -1353,25 +1341,21 @@ mywrite(char *name, FILE *fp, const char *format, va_list va) | ||||||
| { | { | ||||||
| 	PyObject *file; | 	PyObject *file; | ||||||
| 	PyObject *error_type, *error_value, *error_traceback; | 	PyObject *error_type, *error_value, *error_traceback; | ||||||
|  | 	char buffer[1001]; | ||||||
|  | 	int written; | ||||||
| 
 | 
 | ||||||
| 	PyErr_Fetch(&error_type, &error_value, &error_traceback); | 	PyErr_Fetch(&error_type, &error_value, &error_traceback); | ||||||
| 	file = PySys_GetObject(name); | 	file = PySys_GetObject(name); | ||||||
| 	if (file == NULL || PyFile_AsFile(file) == fp) | 	written = PyOS_vsnprintf(buffer, sizeof(buffer), format, va); | ||||||
| 		vfprintf(fp, format, va); | 	if (PyFile_WriteString(buffer, file) != 0) { | ||||||
| 	else { | 		PyErr_Clear(); | ||||||
| 		char buffer[1001]; | 		fputs(buffer, fp); | ||||||
| 		const int written = PyOS_vsnprintf(buffer, sizeof(buffer), | 	} | ||||||
| 						   format, va); | 	if (written < 0 || (size_t)written >= sizeof(buffer)) { | ||||||
| 		if (PyFile_WriteString(buffer, file) != 0) { | 		const char *truncated = "... truncated"; | ||||||
|  | 		if (PyFile_WriteString(truncated, file) != 0) { | ||||||
| 			PyErr_Clear(); | 			PyErr_Clear(); | ||||||
| 			fputs(buffer, fp); | 			fputs(truncated, fp); | ||||||
| 		} |  | ||||||
| 		if (written < 0 || (size_t)written >= sizeof(buffer)) { |  | ||||||
| 			const char *truncated = "... truncated"; |  | ||||||
| 			if (PyFile_WriteString(truncated, file) != 0) { |  | ||||||
| 				PyErr_Clear(); |  | ||||||
| 				fputs(truncated, fp); |  | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	PyErr_Restore(error_type, error_value, error_traceback); | 	PyErr_Restore(error_type, error_value, error_traceback); | ||||||
|  |  | ||||||
|  | @ -24,8 +24,8 @@ mkdir -p OUT | ||||||
| >BAD | >BAD | ||||||
| >SKIPPED | >SKIPPED | ||||||
| 
 | 
 | ||||||
| # The -uall flag (edit this file to change). | # The -u flag (edit this file to change). | ||||||
| UALL="-uall" | UFLAG="-unetwork" | ||||||
| 
 | 
 | ||||||
| # Compute the list of tests to run. | # Compute the list of tests to run. | ||||||
| case $# in | case $# in | ||||||
|  | @ -41,7 +41,7 @@ esac | ||||||
| for T in $TESTS | for T in $TESTS | ||||||
| do | do | ||||||
|     echo -n $T |     echo -n $T | ||||||
|     if $PYTHON Lib/test/regrtest.py $UALL $T >OUT/$T.out 2>&1 |     if $PYTHON Lib/test/regrtest.py $UFLAG $T >OUT/$T.out 2>&1 | ||||||
|     then |     then | ||||||
| 	if grep -q "1 test skipped:" OUT/$T.out | 	if grep -q "1 test skipped:" OUT/$T.out | ||||||
| 	then | 	then | ||||||
|  | @ -55,6 +55,6 @@ do | ||||||
| 	echo " BAD" | 	echo " BAD" | ||||||
|         echo $T >>BAD |         echo $T >>BAD | ||||||
| 	echo "---------- Re-running test in verbose mode ----------" >>OUT/$T | 	echo "---------- Re-running test in verbose mode ----------" >>OUT/$T | ||||||
| 	$PYTHON Lib/test/regrtest.py -v $UALL $T >>OUT/$T.out 2>&1 | 	$PYTHON Lib/test/regrtest.py -v $UFLAG $T >>OUT/$T.out 2>&1 | ||||||
|     fi |     fi | ||||||
| done | done | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Guido van Rossum
						Guido van Rossum