/src/Python-3.8.3/Objects/fileobject.c
Line  | Count  | Source  | 
1  |  | /* File object implementation (what's left of it -- see io.py) */  | 
2  |  |  | 
3  |  | #define PY_SSIZE_T_CLEAN  | 
4  |  | #include "Python.h"  | 
5  |  | #include "pycore_pystate.h"  | 
6  |  |  | 
7  |  | #if defined(HAVE_GETC_UNLOCKED) && !defined(_Py_MEMORY_SANITIZER)  | 
8  |  | /* clang MemorySanitizer doesn't yet understand getc_unlocked. */  | 
9  |  | #define GETC(f) getc_unlocked(f)  | 
10  |  | #define FLOCKFILE(f) flockfile(f)  | 
11  |  | #define FUNLOCKFILE(f) funlockfile(f)  | 
12  |  | #else  | 
13  | 0  | #define GETC(f) getc(f)  | 
14  |  | #define FLOCKFILE(f)  | 
15  |  | #define FUNLOCKFILE(f)  | 
16  |  | #endif  | 
17  |  |  | 
18  |  | /* Newline flags */  | 
19  |  | #define NEWLINE_UNKNOWN 0       /* No newline seen, yet */  | 
20  | 0  | #define NEWLINE_CR 1            /* \r newline seen */  | 
21  | 0  | #define NEWLINE_LF 2            /* \n newline seen */  | 
22  | 0  | #define NEWLINE_CRLF 4          /* \r\n newline seen */  | 
23  |  |  | 
24  |  | #ifdef __cplusplus  | 
25  |  | extern "C" { | 
26  |  | #endif  | 
27  |  |  | 
28  |  | /* External C interface */  | 
29  |  |  | 
30  |  | PyObject *  | 
31  |  | PyFile_FromFd(int fd, const char *name, const char *mode, int buffering, const char *encoding,  | 
32  |  |               const char *errors, const char *newline, int closefd)  | 
33  | 0  | { | 
34  | 0  |     PyObject *io, *stream;  | 
35  | 0  |     _Py_IDENTIFIER(open);  | 
36  |  |  | 
37  |  |     /* import _io in case we are being used to open io.py */  | 
38  | 0  |     io = PyImport_ImportModule("_io"); | 
39  | 0  |     if (io == NULL)  | 
40  | 0  |         return NULL;  | 
41  | 0  |     stream = _PyObject_CallMethodId(io, &PyId_open, "isisssi", fd, mode,  | 
42  | 0  |                                  buffering, encoding, errors,  | 
43  | 0  |                                  newline, closefd);  | 
44  | 0  |     Py_DECREF(io);  | 
45  | 0  |     if (stream == NULL)  | 
46  | 0  |         return NULL;  | 
47  |  |     /* ignore name attribute because the name attribute of _BufferedIOMixin  | 
48  |  |        and TextIOWrapper is read only */  | 
49  | 0  |     return stream;  | 
50  | 0  | }  | 
51  |  |  | 
52  |  | PyObject *  | 
53  |  | PyFile_GetLine(PyObject *f, int n)  | 
54  | 0  | { | 
55  | 0  |     _Py_IDENTIFIER(readline);  | 
56  | 0  |     PyObject *result;  | 
57  |  | 
  | 
58  | 0  |     if (f == NULL) { | 
59  | 0  |         PyErr_BadInternalCall();  | 
60  | 0  |         return NULL;  | 
61  | 0  |     }  | 
62  |  |  | 
63  | 0  |     if (n <= 0) { | 
64  | 0  |         result = _PyObject_CallMethodIdObjArgs(f, &PyId_readline, NULL);  | 
65  | 0  |     }  | 
66  | 0  |     else { | 
67  | 0  |         result = _PyObject_CallMethodId(f, &PyId_readline, "i", n);  | 
68  | 0  |     }  | 
69  | 0  |     if (result != NULL && !PyBytes_Check(result) &&  | 
70  | 0  |         !PyUnicode_Check(result)) { | 
71  | 0  |         Py_DECREF(result);  | 
72  | 0  |         result = NULL;  | 
73  | 0  |         PyErr_SetString(PyExc_TypeError,  | 
74  | 0  |                    "object.readline() returned non-string");  | 
75  | 0  |     }  | 
76  |  | 
  | 
77  | 0  |     if (n < 0 && result != NULL && PyBytes_Check(result)) { | 
78  | 0  |         char *s = PyBytes_AS_STRING(result);  | 
79  | 0  |         Py_ssize_t len = PyBytes_GET_SIZE(result);  | 
80  | 0  |         if (len == 0) { | 
81  | 0  |             Py_DECREF(result);  | 
82  | 0  |             result = NULL;  | 
83  | 0  |             PyErr_SetString(PyExc_EOFError,  | 
84  | 0  |                             "EOF when reading a line");  | 
85  | 0  |         }  | 
86  | 0  |         else if (s[len-1] == '\n') { | 
87  | 0  |             if (result->ob_refcnt == 1)  | 
88  | 0  |                 _PyBytes_Resize(&result, len-1);  | 
89  | 0  |             else { | 
90  | 0  |                 PyObject *v;  | 
91  | 0  |                 v = PyBytes_FromStringAndSize(s, len-1);  | 
92  | 0  |                 Py_DECREF(result);  | 
93  | 0  |                 result = v;  | 
94  | 0  |             }  | 
95  | 0  |         }  | 
96  | 0  |     }  | 
97  | 0  |     if (n < 0 && result != NULL && PyUnicode_Check(result)) { | 
98  | 0  |         Py_ssize_t len = PyUnicode_GET_LENGTH(result);  | 
99  | 0  |         if (len == 0) { | 
100  | 0  |             Py_DECREF(result);  | 
101  | 0  |             result = NULL;  | 
102  | 0  |             PyErr_SetString(PyExc_EOFError,  | 
103  | 0  |                             "EOF when reading a line");  | 
104  | 0  |         }  | 
105  | 0  |         else if (PyUnicode_READ_CHAR(result, len-1) == '\n') { | 
106  | 0  |             PyObject *v;  | 
107  | 0  |             v = PyUnicode_Substring(result, 0, len-1);  | 
108  | 0  |             Py_DECREF(result);  | 
109  | 0  |             result = v;  | 
110  | 0  |         }  | 
111  | 0  |     }  | 
112  | 0  |     return result;  | 
113  | 0  | }  | 
114  |  |  | 
115  |  | /* Interfaces to write objects/strings to file-like objects */  | 
116  |  |  | 
117  |  | int  | 
118  |  | PyFile_WriteObject(PyObject *v, PyObject *f, int flags)  | 
119  | 112  | { | 
120  | 112  |     PyObject *writer, *value, *result;  | 
121  | 112  |     _Py_IDENTIFIER(write);  | 
122  |  |  | 
123  | 112  |     if (f == NULL) { | 
124  | 0  |         PyErr_SetString(PyExc_TypeError, "writeobject with NULL file");  | 
125  | 0  |         return -1;  | 
126  | 0  |     }  | 
127  | 112  |     writer = _PyObject_GetAttrId(f, &PyId_write);  | 
128  | 112  |     if (writer == NULL)  | 
129  | 0  |         return -1;  | 
130  | 112  |     if (flags & Py_PRINT_RAW) { | 
131  | 112  |         value = PyObject_Str(v);  | 
132  | 112  |     }  | 
133  | 0  |     else  | 
134  | 0  |         value = PyObject_Repr(v);  | 
135  | 112  |     if (value == NULL) { | 
136  | 0  |         Py_DECREF(writer);  | 
137  | 0  |         return -1;  | 
138  | 0  |     }  | 
139  | 112  |     result = PyObject_CallFunctionObjArgs(writer, value, NULL);  | 
140  | 112  |     Py_DECREF(value);  | 
141  | 112  |     Py_DECREF(writer);  | 
142  | 112  |     if (result == NULL)  | 
143  | 0  |         return -1;  | 
144  | 112  |     Py_DECREF(result);  | 
145  | 112  |     return 0;  | 
146  | 112  | }  | 
147  |  |  | 
148  |  | int  | 
149  |  | PyFile_WriteString(const char *s, PyObject *f)  | 
150  | 0  | { | 
151  | 0  |     if (f == NULL) { | 
152  |  |         /* Should be caused by a pre-existing error */  | 
153  | 0  |         if (!PyErr_Occurred())  | 
154  | 0  |             PyErr_SetString(PyExc_SystemError,  | 
155  | 0  |                             "null file for PyFile_WriteString");  | 
156  | 0  |         return -1;  | 
157  | 0  |     }  | 
158  | 0  |     else if (!PyErr_Occurred()) { | 
159  | 0  |         PyObject *v = PyUnicode_FromString(s);  | 
160  | 0  |         int err;  | 
161  | 0  |         if (v == NULL)  | 
162  | 0  |             return -1;  | 
163  | 0  |         err = PyFile_WriteObject(v, f, Py_PRINT_RAW);  | 
164  | 0  |         Py_DECREF(v);  | 
165  | 0  |         return err;  | 
166  | 0  |     }  | 
167  | 0  |     else  | 
168  | 0  |         return -1;  | 
169  | 0  | }  | 
170  |  |  | 
171  |  | /* Try to get a file-descriptor from a Python object.  If the object  | 
172  |  |    is an integer, its value is returned.  If not, the  | 
173  |  |    object's fileno() method is called if it exists; the method must return  | 
174  |  |    an integer, which is returned as the file descriptor value.  | 
175  |  |    -1 is returned on failure.  | 
176  |  | */  | 
177  |  |  | 
178  |  | int  | 
179  |  | PyObject_AsFileDescriptor(PyObject *o)  | 
180  | 0  | { | 
181  | 0  |     int fd;  | 
182  | 0  |     PyObject *meth;  | 
183  | 0  |     _Py_IDENTIFIER(fileno);  | 
184  |  | 
  | 
185  | 0  |     if (PyLong_Check(o)) { | 
186  | 0  |         fd = _PyLong_AsInt(o);  | 
187  | 0  |     }  | 
188  | 0  |     else if (_PyObject_LookupAttrId(o, &PyId_fileno, &meth) < 0) { | 
189  | 0  |         return -1;  | 
190  | 0  |     }  | 
191  | 0  |     else if (meth != NULL) { | 
192  | 0  |         PyObject *fno = _PyObject_CallNoArg(meth);  | 
193  | 0  |         Py_DECREF(meth);  | 
194  | 0  |         if (fno == NULL)  | 
195  | 0  |             return -1;  | 
196  |  |  | 
197  | 0  |         if (PyLong_Check(fno)) { | 
198  | 0  |             fd = _PyLong_AsInt(fno);  | 
199  | 0  |             Py_DECREF(fno);  | 
200  | 0  |         }  | 
201  | 0  |         else { | 
202  | 0  |             PyErr_SetString(PyExc_TypeError,  | 
203  | 0  |                             "fileno() returned a non-integer");  | 
204  | 0  |             Py_DECREF(fno);  | 
205  | 0  |             return -1;  | 
206  | 0  |         }  | 
207  | 0  |     }  | 
208  | 0  |     else { | 
209  | 0  |         PyErr_SetString(PyExc_TypeError,  | 
210  | 0  |                         "argument must be an int, or have a fileno() method.");  | 
211  | 0  |         return -1;  | 
212  | 0  |     }  | 
213  |  |  | 
214  | 0  |     if (fd == -1 && PyErr_Occurred())  | 
215  | 0  |         return -1;  | 
216  | 0  |     if (fd < 0) { | 
217  | 0  |         PyErr_Format(PyExc_ValueError,  | 
218  | 0  |                      "file descriptor cannot be a negative integer (%i)",  | 
219  | 0  |                      fd);  | 
220  | 0  |         return -1;  | 
221  | 0  |     }  | 
222  | 0  |     return fd;  | 
223  | 0  | }  | 
224  |  |  | 
225  |  | /*  | 
226  |  | ** Py_UniversalNewlineFgets is an fgets variation that understands  | 
227  |  | ** all of \r, \n and \r\n conventions.  | 
228  |  | ** The stream should be opened in binary mode.  | 
229  |  | ** If fobj is NULL the routine always does newline conversion, and  | 
230  |  | ** it may peek one char ahead to gobble the second char in \r\n.  | 
231  |  | ** If fobj is non-NULL it must be a PyFileObject. In this case there  | 
232  |  | ** is no readahead but in stead a flag is used to skip a following  | 
233  |  | ** \n on the next read. Also, if the file is open in binary mode  | 
234  |  | ** the whole conversion is skipped. Finally, the routine keeps track of  | 
235  |  | ** the different types of newlines seen.  | 
236  |  | ** Note that we need no error handling: fgets() treats error and eof  | 
237  |  | ** identically.  | 
238  |  | */  | 
239  |  | char *  | 
240  |  | Py_UniversalNewlineFgets(char *buf, int n, FILE *stream, PyObject *fobj)  | 
241  | 0  | { | 
242  | 0  |     char *p = buf;  | 
243  | 0  |     int c;  | 
244  | 0  |     int newlinetypes = 0;  | 
245  | 0  |     int skipnextlf = 0;  | 
246  |  | 
  | 
247  | 0  |     if (fobj) { | 
248  | 0  |         errno = ENXIO;          /* What can you do... */  | 
249  | 0  |         return NULL;  | 
250  | 0  |     }  | 
251  | 0  |     FLOCKFILE(stream);  | 
252  | 0  |     c = 'x'; /* Shut up gcc warning */  | 
253  | 0  |     while (--n > 0 && (c = GETC(stream)) != EOF ) { | 
254  | 0  |         if (skipnextlf ) { | 
255  | 0  |             skipnextlf = 0;  | 
256  | 0  |             if (c == '\n') { | 
257  |  |                 /* Seeing a \n here with skipnextlf true  | 
258  |  |                 ** means we saw a \r before.  | 
259  |  |                 */  | 
260  | 0  |                 newlinetypes |= NEWLINE_CRLF;  | 
261  | 0  |                 c = GETC(stream);  | 
262  | 0  |                 if (c == EOF) break;  | 
263  | 0  |             } else { | 
264  |  |                 /*  | 
265  |  |                 ** Note that c == EOF also brings us here,  | 
266  |  |                 ** so we're okay if the last char in the file  | 
267  |  |                 ** is a CR.  | 
268  |  |                 */  | 
269  | 0  |                 newlinetypes |= NEWLINE_CR;  | 
270  | 0  |             }  | 
271  | 0  |         }  | 
272  | 0  |         if (c == '\r') { | 
273  |  |             /* A \r is translated into a \n, and we skip  | 
274  |  |             ** an adjacent \n, if any. We don't set the  | 
275  |  |             ** newlinetypes flag until we've seen the next char.  | 
276  |  |             */  | 
277  | 0  |             skipnextlf = 1;  | 
278  | 0  |             c = '\n';  | 
279  | 0  |         } else if ( c == '\n') { | 
280  | 0  |             newlinetypes |= NEWLINE_LF;  | 
281  | 0  |         }  | 
282  | 0  |         *p++ = c;  | 
283  | 0  |         if (c == '\n') break;  | 
284  | 0  |     }  | 
285  |  |     /* if ( c == EOF && skipnextlf )  | 
286  |  |         newlinetypes |= NEWLINE_CR; */  | 
287  | 0  |     FUNLOCKFILE(stream);  | 
288  | 0  |     *p = '\0';  | 
289  | 0  |     if ( skipnextlf ) { | 
290  |  |         /* If we have no file object we cannot save the  | 
291  |  |         ** skipnextlf flag. We have to readahead, which  | 
292  |  |         ** will cause a pause if we're reading from an  | 
293  |  |         ** interactive stream, but that is very unlikely  | 
294  |  |         ** unless we're doing something silly like  | 
295  |  |         ** exec(open("/dev/tty").read()). | 
296  |  |         */  | 
297  | 0  |         c = GETC(stream);  | 
298  | 0  |         if ( c != '\n' )  | 
299  | 0  |             ungetc(c, stream);  | 
300  | 0  |     }  | 
301  | 0  |     if (p == buf)  | 
302  | 0  |         return NULL;  | 
303  | 0  |     return buf;  | 
304  | 0  | }  | 
305  |  |  | 
306  |  | /* **************************** std printer ****************************  | 
307  |  |  * The stdprinter is used during the boot strapping phase as a preliminary  | 
308  |  |  * file like object for sys.stderr.  | 
309  |  |  */  | 
310  |  |  | 
311  |  | typedef struct { | 
312  |  |     PyObject_HEAD  | 
313  |  |     int fd;  | 
314  |  | } PyStdPrinter_Object;  | 
315  |  |  | 
316  |  | static PyObject *  | 
317  |  | stdprinter_new(PyTypeObject *type, PyObject *args, PyObject *kews)  | 
318  | 0  | { | 
319  | 0  |     PyStdPrinter_Object *self;  | 
320  |  | 
  | 
321  | 0  |     assert(type != NULL && type->tp_alloc != NULL);  | 
322  |  | 
  | 
323  | 0  |     self = (PyStdPrinter_Object *) type->tp_alloc(type, 0);  | 
324  | 0  |     if (self != NULL) { | 
325  | 0  |         self->fd = -1;  | 
326  | 0  |     }  | 
327  |  | 
  | 
328  | 0  |     return (PyObject *) self;  | 
329  | 0  | }  | 
330  |  |  | 
331  |  | static int  | 
332  |  | stdprinter_init(PyObject *self, PyObject *args, PyObject *kwds)  | 
333  | 0  | { | 
334  | 0  |     PyErr_SetString(PyExc_TypeError,  | 
335  | 0  |                     "cannot create 'stderrprinter' instances");  | 
336  | 0  |     return -1;  | 
337  | 0  | }  | 
338  |  |  | 
339  |  | PyObject *  | 
340  |  | PyFile_NewStdPrinter(int fd)  | 
341  | 14  | { | 
342  | 14  |     PyStdPrinter_Object *self;  | 
343  |  |  | 
344  | 14  |     if (fd != fileno(stdout) && fd != fileno(stderr)) { | 
345  |  |         /* not enough infrastructure for PyErr_BadInternalCall() */  | 
346  | 0  |         return NULL;  | 
347  | 0  |     }  | 
348  |  |  | 
349  | 14  |     self = PyObject_New(PyStdPrinter_Object,  | 
350  | 14  |                         &PyStdPrinter_Type);  | 
351  | 14  |     if (self != NULL) { | 
352  | 14  |         self->fd = fd;  | 
353  | 14  |     }  | 
354  | 14  |     return (PyObject*)self;  | 
355  | 14  | }  | 
356  |  |  | 
357  |  | static PyObject *  | 
358  |  | stdprinter_write(PyStdPrinter_Object *self, PyObject *args)  | 
359  | 0  | { | 
360  | 0  |     PyObject *unicode;  | 
361  | 0  |     PyObject *bytes = NULL;  | 
362  | 0  |     const char *str;  | 
363  | 0  |     Py_ssize_t n;  | 
364  | 0  |     int err;  | 
365  |  |  | 
366  |  |     /* The function can clear the current exception */  | 
367  | 0  |     assert(!PyErr_Occurred());  | 
368  |  | 
  | 
369  | 0  |     if (self->fd < 0) { | 
370  |  |         /* fd might be invalid on Windows  | 
371  |  |          * I can't raise an exception here. It may lead to an  | 
372  |  |          * unlimited recursion in the case stderr is invalid.  | 
373  |  |          */  | 
374  | 0  |         Py_RETURN_NONE;  | 
375  | 0  |     }  | 
376  |  |  | 
377  | 0  |     if (!PyArg_ParseTuple(args, "U", &unicode)) { | 
378  | 0  |         return NULL;  | 
379  | 0  |     }  | 
380  |  |  | 
381  |  |     /* Encode Unicode to UTF-8/surrogateescape */  | 
382  | 0  |     str = PyUnicode_AsUTF8AndSize(unicode, &n);  | 
383  | 0  |     if (str == NULL) { | 
384  | 0  |         PyErr_Clear();  | 
385  | 0  |         bytes = _PyUnicode_AsUTF8String(unicode, "backslashreplace");  | 
386  | 0  |         if (bytes == NULL)  | 
387  | 0  |             return NULL;  | 
388  | 0  |         str = PyBytes_AS_STRING(bytes);  | 
389  | 0  |         n = PyBytes_GET_SIZE(bytes);  | 
390  | 0  |     }  | 
391  |  |  | 
392  | 0  |     n = _Py_write(self->fd, str, n);  | 
393  |  |     /* save errno, it can be modified indirectly by Py_XDECREF() */  | 
394  | 0  |     err = errno;  | 
395  |  | 
  | 
396  | 0  |     Py_XDECREF(bytes);  | 
397  |  | 
  | 
398  | 0  |     if (n == -1) { | 
399  | 0  |         if (err == EAGAIN) { | 
400  | 0  |             PyErr_Clear();  | 
401  | 0  |             Py_RETURN_NONE;  | 
402  | 0  |         }  | 
403  | 0  |         return NULL;  | 
404  | 0  |     }  | 
405  |  |  | 
406  | 0  |     return PyLong_FromSsize_t(n);  | 
407  | 0  | }  | 
408  |  |  | 
409  |  | static PyObject *  | 
410  |  | stdprinter_fileno(PyStdPrinter_Object *self, PyObject *Py_UNUSED(ignored))  | 
411  | 0  | { | 
412  | 0  |     return PyLong_FromLong((long) self->fd);  | 
413  | 0  | }  | 
414  |  |  | 
415  |  | static PyObject *  | 
416  |  | stdprinter_repr(PyStdPrinter_Object *self)  | 
417  | 0  | { | 
418  | 0  |     return PyUnicode_FromFormat("<stdprinter(fd=%d) object at %p>", | 
419  | 0  |                                 self->fd, self);  | 
420  | 0  | }  | 
421  |  |  | 
422  |  | static PyObject *  | 
423  |  | stdprinter_noop(PyStdPrinter_Object *self, PyObject *Py_UNUSED(ignored))  | 
424  | 0  | { | 
425  | 0  |     Py_RETURN_NONE;  | 
426  | 0  | }  | 
427  |  |  | 
428  |  | static PyObject *  | 
429  |  | stdprinter_isatty(PyStdPrinter_Object *self, PyObject *Py_UNUSED(ignored))  | 
430  | 0  | { | 
431  | 0  |     long res;  | 
432  | 0  |     if (self->fd < 0) { | 
433  | 0  |         Py_RETURN_FALSE;  | 
434  | 0  |     }  | 
435  |  |  | 
436  | 0  |     Py_BEGIN_ALLOW_THREADS  | 
437  | 0  |     res = isatty(self->fd);  | 
438  | 0  |     Py_END_ALLOW_THREADS  | 
439  |  | 
  | 
440  | 0  |     return PyBool_FromLong(res);  | 
441  | 0  | }  | 
442  |  |  | 
443  |  | static PyMethodDef stdprinter_methods[] = { | 
444  |  |     {"close",           (PyCFunction)stdprinter_noop, METH_NOARGS, ""}, | 
445  |  |     {"flush",           (PyCFunction)stdprinter_noop, METH_NOARGS, ""}, | 
446  |  |     {"fileno",          (PyCFunction)stdprinter_fileno, METH_NOARGS, ""}, | 
447  |  |     {"isatty",          (PyCFunction)stdprinter_isatty, METH_NOARGS, ""}, | 
448  |  |     {"write",           (PyCFunction)stdprinter_write, METH_VARARGS, ""}, | 
449  |  |     {NULL,              NULL}  /*sentinel */ | 
450  |  | };  | 
451  |  |  | 
452  |  | static PyObject *  | 
453  |  | get_closed(PyStdPrinter_Object *self, void *closure)  | 
454  | 0  | { | 
455  | 0  |     Py_RETURN_FALSE;  | 
456  | 0  | }  | 
457  |  |  | 
458  |  | static PyObject *  | 
459  |  | get_mode(PyStdPrinter_Object *self, void *closure)  | 
460  | 0  | { | 
461  | 0  |     return PyUnicode_FromString("w"); | 
462  | 0  | }  | 
463  |  |  | 
464  |  | static PyObject *  | 
465  |  | get_encoding(PyStdPrinter_Object *self, void *closure)  | 
466  | 0  | { | 
467  | 0  |     Py_RETURN_NONE;  | 
468  | 0  | }  | 
469  |  |  | 
470  |  | static PyGetSetDef stdprinter_getsetlist[] = { | 
471  |  |     {"closed", (getter)get_closed, NULL, "True if the file is closed"}, | 
472  |  |     {"encoding", (getter)get_encoding, NULL, "Encoding of the file"}, | 
473  |  |     {"mode", (getter)get_mode, NULL, "String giving the file mode"}, | 
474  |  |     {0}, | 
475  |  | };  | 
476  |  |  | 
477  |  | PyTypeObject PyStdPrinter_Type = { | 
478  |  |     PyVarObject_HEAD_INIT(&PyType_Type, 0)  | 
479  |  |     "stderrprinter",                            /* tp_name */  | 
480  |  |     sizeof(PyStdPrinter_Object),                /* tp_basicsize */  | 
481  |  |     0,                                          /* tp_itemsize */  | 
482  |  |     /* methods */  | 
483  |  |     0,                                          /* tp_dealloc */  | 
484  |  |     0,                                          /* tp_vectorcall_offset */  | 
485  |  |     0,                                          /* tp_getattr */  | 
486  |  |     0,                                          /* tp_setattr */  | 
487  |  |     0,                                          /* tp_as_async */  | 
488  |  |     (reprfunc)stdprinter_repr,                  /* tp_repr */  | 
489  |  |     0,                                          /* tp_as_number */  | 
490  |  |     0,                                          /* tp_as_sequence */  | 
491  |  |     0,                                          /* tp_as_mapping */  | 
492  |  |     0,                                          /* tp_hash */  | 
493  |  |     0,                                          /* tp_call */  | 
494  |  |     0,                                          /* tp_str */  | 
495  |  |     PyObject_GenericGetAttr,                    /* tp_getattro */  | 
496  |  |     0,                                          /* tp_setattro */  | 
497  |  |     0,                                          /* tp_as_buffer */  | 
498  |  |     Py_TPFLAGS_DEFAULT,                         /* tp_flags */  | 
499  |  |     0,                                          /* tp_doc */  | 
500  |  |     0,                                          /* tp_traverse */  | 
501  |  |     0,                                          /* tp_clear */  | 
502  |  |     0,                                          /* tp_richcompare */  | 
503  |  |     0,                                          /* tp_weaklistoffset */  | 
504  |  |     0,                                          /* tp_iter */  | 
505  |  |     0,                                          /* tp_iternext */  | 
506  |  |     stdprinter_methods,                         /* tp_methods */  | 
507  |  |     0,                                          /* tp_members */  | 
508  |  |     stdprinter_getsetlist,                      /* tp_getset */  | 
509  |  |     0,                                          /* tp_base */  | 
510  |  |     0,                                          /* tp_dict */  | 
511  |  |     0,                                          /* tp_descr_get */  | 
512  |  |     0,                                          /* tp_descr_set */  | 
513  |  |     0,                                          /* tp_dictoffset */  | 
514  |  |     stdprinter_init,                            /* tp_init */  | 
515  |  |     PyType_GenericAlloc,                        /* tp_alloc */  | 
516  |  |     stdprinter_new,                             /* tp_new */  | 
517  |  |     PyObject_Del,                               /* tp_free */  | 
518  |  | };  | 
519  |  |  | 
520  |  |  | 
521  |  | /* ************************** open_code hook ***************************  | 
522  |  |  * The open_code hook allows embedders to override the method used to  | 
523  |  |  * open files that are going to be used by the runtime to execute code  | 
524  |  |  */  | 
525  |  |  | 
526  |  | int  | 
527  | 0  | PyFile_SetOpenCodeHook(Py_OpenCodeHookFunction hook, void *userData) { | 
528  | 0  |     if (Py_IsInitialized() &&  | 
529  | 0  |         PySys_Audit("setopencodehook", NULL) < 0) { | 
530  | 0  |         return -1;  | 
531  | 0  |     }  | 
532  |  |  | 
533  | 0  |     if (_PyRuntime.open_code_hook) { | 
534  | 0  |         if (Py_IsInitialized()) { | 
535  | 0  |             PyErr_SetString(PyExc_SystemError,  | 
536  | 0  |                 "failed to change existing open_code hook");  | 
537  | 0  |         }  | 
538  | 0  |         return -1;  | 
539  | 0  |     }  | 
540  |  |  | 
541  | 0  |     _PyRuntime.open_code_hook = hook;  | 
542  | 0  |     _PyRuntime.open_code_userdata = userData;  | 
543  | 0  |     return 0;  | 
544  | 0  | }  | 
545  |  |  | 
546  |  | PyObject *  | 
547  |  | PyFile_OpenCodeObject(PyObject *path)  | 
548  | 235  | { | 
549  | 235  |     PyObject *iomod, *f = NULL;  | 
550  | 235  |     _Py_IDENTIFIER(open);  | 
551  |  |  | 
552  | 235  |     if (!PyUnicode_Check(path)) { | 
553  | 0  |         PyErr_Format(PyExc_TypeError, "'path' must be 'str', not '%.200s'",  | 
554  | 0  |                      Py_TYPE(path)->tp_name);  | 
555  | 0  |         return NULL;  | 
556  | 0  |     }  | 
557  |  |  | 
558  | 235  |     Py_OpenCodeHookFunction hook = _PyRuntime.open_code_hook;  | 
559  | 235  |     if (hook) { | 
560  | 0  |         f = hook(path, _PyRuntime.open_code_userdata);  | 
561  | 235  |     } else { | 
562  | 235  |         iomod = PyImport_ImportModule("_io"); | 
563  | 235  |         if (iomod) { | 
564  | 235  |             f = _PyObject_CallMethodId(iomod, &PyId_open, "Os",  | 
565  | 235  |                                        path, "rb");  | 
566  | 235  |             Py_DECREF(iomod);  | 
567  | 235  |         }  | 
568  | 235  |     }  | 
569  |  |  | 
570  | 235  |     return f;  | 
571  | 235  | }  | 
572  |  |  | 
573  |  | PyObject *  | 
574  |  | PyFile_OpenCode(const char *utf8path)  | 
575  | 0  | { | 
576  | 0  |     PyObject *pathobj = PyUnicode_FromString(utf8path);  | 
577  | 0  |     PyObject *f;  | 
578  | 0  |     if (!pathobj) { | 
579  | 0  |         return NULL;  | 
580  | 0  |     }  | 
581  | 0  |     f = PyFile_OpenCodeObject(pathobj);  | 
582  | 0  |     Py_DECREF(pathobj);  | 
583  | 0  |     return f;  | 
584  | 0  | }  | 
585  |  |  | 
586  |  |  | 
587  |  | #ifdef __cplusplus  | 
588  |  | }  | 
589  |  | #endif  |