/src/cpython/Modules/_io/_iomodule.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | An implementation of the new I/O lib as defined by PEP 3116 - "New I/O" |
3 | | |
4 | | Classes defined here: UnsupportedOperation, BlockingIOError. |
5 | | Functions defined here: open(). |
6 | | |
7 | | Mostly written by Amaury Forgeot d'Arc |
8 | | */ |
9 | | |
10 | | #include "Python.h" |
11 | | #include "pycore_abstract.h" // _PyNumber_Index() |
12 | | #include "pycore_interp.h" // _PyInterpreterState_GetConfig() |
13 | | #include "pycore_long.h" // _PyLong_IsNegative() |
14 | | #include "pycore_pyerrors.h" // _PyErr_ChainExceptions1() |
15 | | #include "pycore_pystate.h" // _PyInterpreterState_GET() |
16 | | |
17 | | #include "_iomodule.h" |
18 | | |
19 | | #ifdef HAVE_SYS_TYPES_H |
20 | | #include <sys/types.h> |
21 | | #endif /* HAVE_SYS_TYPES_H */ |
22 | | |
23 | | #ifdef HAVE_SYS_STAT_H |
24 | | #include <sys/stat.h> |
25 | | #endif /* HAVE_SYS_STAT_H */ |
26 | | |
27 | | #ifdef MS_WINDOWS |
28 | | #include <windows.h> |
29 | | #endif |
30 | | |
31 | | PyDoc_STRVAR(module_doc, |
32 | | "The io module provides the Python interfaces to stream handling. The\n" |
33 | | "builtin open function is defined in this module.\n" |
34 | | "\n" |
35 | | "At the top of the I/O hierarchy is the abstract base class IOBase. It\n" |
36 | | "defines the basic interface to a stream. Note, however, that there is no\n" |
37 | | "separation between reading and writing to streams; implementations are\n" |
38 | | "allowed to raise an OSError if they do not support a given operation.\n" |
39 | | "\n" |
40 | | "Extending IOBase is RawIOBase which deals simply with the reading and\n" |
41 | | "writing of raw bytes to a stream. FileIO subclasses RawIOBase to provide\n" |
42 | | "an interface to OS files.\n" |
43 | | "\n" |
44 | | "BufferedIOBase deals with buffering on a raw byte stream (RawIOBase). Its\n" |
45 | | "subclasses, BufferedWriter, BufferedReader, and BufferedRWPair buffer\n" |
46 | | "streams that are readable, writable, and both respectively.\n" |
47 | | "BufferedRandom provides a buffered interface to random access\n" |
48 | | "streams. BytesIO is a simple stream of in-memory bytes.\n" |
49 | | "\n" |
50 | | "Another IOBase subclass, TextIOBase, deals with the encoding and decoding\n" |
51 | | "of streams into text. TextIOWrapper, which extends it, is a buffered text\n" |
52 | | "interface to a buffered raw stream (`BufferedIOBase`). Finally, StringIO\n" |
53 | | "is an in-memory stream for text.\n" |
54 | | "\n" |
55 | | "Argument names are not part of the specification, and only the arguments\n" |
56 | | "of open() are intended to be used as keyword arguments.\n" |
57 | | "\n" |
58 | | "data:\n" |
59 | | "\n" |
60 | | "DEFAULT_BUFFER_SIZE\n" |
61 | | "\n" |
62 | | " An int containing the default buffer size used by the module's buffered\n" |
63 | | " I/O classes.\n" |
64 | | ); |
65 | | |
66 | | |
67 | | /* |
68 | | * The main open() function |
69 | | */ |
70 | | /*[clinic input] |
71 | | module _io |
72 | | |
73 | | _io.open |
74 | | file: object |
75 | | mode: str = "r" |
76 | | buffering: int = -1 |
77 | | encoding: str(accept={str, NoneType}) = None |
78 | | errors: str(accept={str, NoneType}) = None |
79 | | newline: str(accept={str, NoneType}) = None |
80 | | closefd: bool = True |
81 | | opener: object = None |
82 | | |
83 | | Open file and return a stream. Raise OSError upon failure. |
84 | | |
85 | | file is either a text or byte string giving the name (and the path |
86 | | if the file isn't in the current working directory) of the file to |
87 | | be opened or an integer file descriptor of the file to be |
88 | | wrapped. (If a file descriptor is given, it is closed when the |
89 | | returned I/O object is closed, unless closefd is set to False.) |
90 | | |
91 | | mode is an optional string that specifies the mode in which the file |
92 | | is opened. It defaults to 'r' which means open for reading in text |
93 | | mode. Other common values are 'w' for writing (truncating the file if |
94 | | it already exists), 'x' for creating and writing to a new file, and |
95 | | 'a' for appending (which on some Unix systems, means that all writes |
96 | | append to the end of the file regardless of the current seek position). |
97 | | In text mode, if encoding is not specified the encoding used is platform |
98 | | dependent: locale.getencoding() is called to get the current locale encoding. |
99 | | (For reading and writing raw bytes use binary mode and leave encoding |
100 | | unspecified.) The available modes are: |
101 | | |
102 | | ========= =============================================================== |
103 | | Character Meaning |
104 | | --------- --------------------------------------------------------------- |
105 | | 'r' open for reading (default) |
106 | | 'w' open for writing, truncating the file first |
107 | | 'x' create a new file and open it for writing |
108 | | 'a' open for writing, appending to the end of the file if it exists |
109 | | 'b' binary mode |
110 | | 't' text mode (default) |
111 | | '+' open a disk file for updating (reading and writing) |
112 | | ========= =============================================================== |
113 | | |
114 | | The default mode is 'rt' (open for reading text). For binary random |
115 | | access, the mode 'w+b' opens and truncates the file to 0 bytes, while |
116 | | 'r+b' opens the file without truncation. The 'x' mode implies 'w' and |
117 | | raises an `FileExistsError` if the file already exists. |
118 | | |
119 | | Python distinguishes between files opened in binary and text modes, |
120 | | even when the underlying operating system doesn't. Files opened in |
121 | | binary mode (appending 'b' to the mode argument) return contents as |
122 | | bytes objects without any decoding. In text mode (the default, or when |
123 | | 't' is appended to the mode argument), the contents of the file are |
124 | | returned as strings, the bytes having been first decoded using a |
125 | | platform-dependent encoding or using the specified encoding if given. |
126 | | |
127 | | buffering is an optional integer used to set the buffering policy. |
128 | | Pass 0 to switch buffering off (only allowed in binary mode), 1 to select |
129 | | line buffering (only usable in text mode), and an integer > 1 to indicate |
130 | | the size of a fixed-size chunk buffer. When no buffering argument is |
131 | | given, the default buffering policy works as follows: |
132 | | |
133 | | * Binary files are buffered in fixed-size chunks; the size of the buffer |
134 | | is max(min(blocksize, 8 MiB), DEFAULT_BUFFER_SIZE) |
135 | | when the device block size is available. |
136 | | On most systems, the buffer will typically be 128 kilobytes long. |
137 | | |
138 | | * "Interactive" text files (files for which isatty() returns True) |
139 | | use line buffering. Other text files use the policy described above |
140 | | for binary files. |
141 | | |
142 | | encoding is the name of the encoding used to decode or encode the |
143 | | file. This should only be used in text mode. The default encoding is |
144 | | platform dependent, but any encoding supported by Python can be |
145 | | passed. See the codecs module for the list of supported encodings. |
146 | | |
147 | | errors is an optional string that specifies how encoding errors are to |
148 | | be handled---this argument should not be used in binary mode. Pass |
149 | | 'strict' to raise a ValueError exception if there is an encoding error |
150 | | (the default of None has the same effect), or pass 'ignore' to ignore |
151 | | errors. (Note that ignoring encoding errors can lead to data loss.) |
152 | | See the documentation for codecs.register or run 'help(codecs.Codec)' |
153 | | for a list of the permitted encoding error strings. |
154 | | |
155 | | newline controls how universal newlines works (it only applies to text |
156 | | mode). It can be None, '', '\n', '\r', and '\r\n'. It works as |
157 | | follows: |
158 | | |
159 | | * On input, if newline is None, universal newlines mode is |
160 | | enabled. Lines in the input can end in '\n', '\r', or '\r\n', and |
161 | | these are translated into '\n' before being returned to the |
162 | | caller. If it is '', universal newline mode is enabled, but line |
163 | | endings are returned to the caller untranslated. If it has any of |
164 | | the other legal values, input lines are only terminated by the given |
165 | | string, and the line ending is returned to the caller untranslated. |
166 | | |
167 | | * On output, if newline is None, any '\n' characters written are |
168 | | translated to the system default line separator, os.linesep. If |
169 | | newline is '' or '\n', no translation takes place. If newline is any |
170 | | of the other legal values, any '\n' characters written are translated |
171 | | to the given string. |
172 | | |
173 | | If closefd is False, the underlying file descriptor will be kept open |
174 | | when the file is closed. This does not work when a file name is given |
175 | | and must be True in that case. |
176 | | |
177 | | A custom opener can be used by passing a callable as *opener*. The |
178 | | underlying file descriptor for the file object is then obtained by |
179 | | calling *opener* with (*file*, *flags*). *opener* must return an open |
180 | | file descriptor (passing os.open as *opener* results in functionality |
181 | | similar to passing None). |
182 | | |
183 | | open() returns a file object whose type depends on the mode, and |
184 | | through which the standard file operations such as reading and writing |
185 | | are performed. When open() is used to open a file in a text mode ('w', |
186 | | 'r', 'wt', 'rt', etc.), it returns a TextIOWrapper. When used to open |
187 | | a file in a binary mode, the returned class varies: in read binary |
188 | | mode, it returns a BufferedReader; in write binary and append binary |
189 | | modes, it returns a BufferedWriter, and in read/write mode, it returns |
190 | | a BufferedRandom. |
191 | | |
192 | | It is also possible to use a string or bytearray as a file for both |
193 | | reading and writing. For strings StringIO can be used like a file |
194 | | opened in a text mode, and for bytes a BytesIO can be used like a file |
195 | | opened in a binary mode. |
196 | | [clinic start generated code]*/ |
197 | | |
198 | | static PyObject * |
199 | | _io_open_impl(PyObject *module, PyObject *file, const char *mode, |
200 | | int buffering, const char *encoding, const char *errors, |
201 | | const char *newline, int closefd, PyObject *opener) |
202 | | /*[clinic end generated code: output=aefafc4ce2b46dc0 input=28027fdaabb8d744]*/ |
203 | 992 | { |
204 | 992 | size_t i; |
205 | | |
206 | 992 | int creating = 0, reading = 0, writing = 0, appending = 0, updating = 0; |
207 | 992 | int text = 0, binary = 0; |
208 | | |
209 | 992 | char rawmode[6], *m; |
210 | 992 | int line_buffering, is_number, isatty = 0; |
211 | | |
212 | 992 | PyObject *raw, *modeobj = NULL, *buffer, *wrapper, *result = NULL, *path_or_fd = NULL; |
213 | | |
214 | 992 | is_number = PyNumber_Check(file); |
215 | | |
216 | 992 | if (is_number) { |
217 | 48 | path_or_fd = Py_NewRef(file); |
218 | 944 | } else { |
219 | 944 | path_or_fd = PyOS_FSPath(file); |
220 | 944 | if (path_or_fd == NULL) { |
221 | 0 | return NULL; |
222 | 0 | } |
223 | 944 | } |
224 | | |
225 | 992 | if (!is_number && |
226 | 992 | !PyUnicode_Check(path_or_fd) && |
227 | 992 | !PyBytes_Check(path_or_fd)) { |
228 | 0 | PyErr_Format(PyExc_TypeError, "invalid file: %R", file); |
229 | 0 | goto error; |
230 | 0 | } |
231 | | |
232 | | /* Decode mode */ |
233 | 2.97k | for (i = 0; i < strlen(mode); i++) { |
234 | 1.98k | char c = mode[i]; |
235 | | |
236 | 1.98k | switch (c) { |
237 | 0 | case 'x': |
238 | 0 | creating = 1; |
239 | 0 | break; |
240 | 960 | case 'r': |
241 | 960 | reading = 1; |
242 | 960 | break; |
243 | 32 | case 'w': |
244 | 32 | writing = 1; |
245 | 32 | break; |
246 | 0 | case 'a': |
247 | 0 | appending = 1; |
248 | 0 | break; |
249 | 0 | case '+': |
250 | 0 | updating = 1; |
251 | 0 | break; |
252 | 0 | case 't': |
253 | 0 | text = 1; |
254 | 0 | break; |
255 | 992 | case 'b': |
256 | 992 | binary = 1; |
257 | 992 | break; |
258 | 0 | default: |
259 | 0 | goto invalid_mode; |
260 | 1.98k | } |
261 | | |
262 | | /* c must not be duplicated */ |
263 | 1.98k | if (strchr(mode+i+1, c)) { |
264 | 0 | invalid_mode: |
265 | 0 | PyErr_Format(PyExc_ValueError, "invalid mode: '%s'", mode); |
266 | 0 | goto error; |
267 | 0 | } |
268 | | |
269 | 1.98k | } |
270 | | |
271 | 992 | m = rawmode; |
272 | 992 | if (creating) *(m++) = 'x'; |
273 | 992 | if (reading) *(m++) = 'r'; |
274 | 992 | if (writing) *(m++) = 'w'; |
275 | 992 | if (appending) *(m++) = 'a'; |
276 | 992 | if (updating) *(m++) = '+'; |
277 | 992 | *m = '\0'; |
278 | | |
279 | | /* Parameters validation */ |
280 | 992 | if (text && binary) { |
281 | 0 | PyErr_SetString(PyExc_ValueError, |
282 | 0 | "can't have text and binary mode at once"); |
283 | 0 | goto error; |
284 | 0 | } |
285 | | |
286 | 992 | if (creating + reading + writing + appending > 1) { |
287 | 0 | PyErr_SetString(PyExc_ValueError, |
288 | 0 | "must have exactly one of create/read/write/append mode"); |
289 | 0 | goto error; |
290 | 0 | } |
291 | | |
292 | 992 | if (binary && encoding != NULL) { |
293 | 0 | PyErr_SetString(PyExc_ValueError, |
294 | 0 | "binary mode doesn't take an encoding argument"); |
295 | 0 | goto error; |
296 | 0 | } |
297 | | |
298 | 992 | if (binary && errors != NULL) { |
299 | 0 | PyErr_SetString(PyExc_ValueError, |
300 | 0 | "binary mode doesn't take an errors argument"); |
301 | 0 | goto error; |
302 | 0 | } |
303 | | |
304 | 992 | if (binary && newline != NULL) { |
305 | 0 | PyErr_SetString(PyExc_ValueError, |
306 | 0 | "binary mode doesn't take a newline argument"); |
307 | 0 | goto error; |
308 | 0 | } |
309 | | |
310 | 992 | if (binary && buffering == 1) { |
311 | 0 | if (PyErr_WarnEx(PyExc_RuntimeWarning, |
312 | 0 | "line buffering (buffering=1) isn't supported in " |
313 | 0 | "binary mode, the default buffer size will be used", |
314 | 0 | 1) < 0) { |
315 | 0 | goto error; |
316 | 0 | } |
317 | 0 | } |
318 | | |
319 | | /* Create the Raw file stream */ |
320 | 992 | _PyIO_State *state = get_io_state(module); |
321 | 992 | { |
322 | 992 | PyObject *RawIO_class = (PyObject *)state->PyFileIO_Type; |
323 | | #ifdef HAVE_WINDOWS_CONSOLE_IO |
324 | | const PyConfig *config = _Py_GetConfig(); |
325 | | if (!config->legacy_windows_stdio && _PyIO_get_console_type(path_or_fd) != '\0') { |
326 | | RawIO_class = (PyObject *)state->PyWindowsConsoleIO_Type; |
327 | | encoding = "utf-8"; |
328 | | } |
329 | | #endif |
330 | 992 | raw = PyObject_CallFunction(RawIO_class, "OsOO", |
331 | 992 | path_or_fd, rawmode, |
332 | 992 | closefd ? Py_True : Py_False, |
333 | 992 | opener); |
334 | 992 | } |
335 | | |
336 | 992 | if (raw == NULL) |
337 | 0 | goto error; |
338 | 992 | result = raw; |
339 | | |
340 | 992 | Py_SETREF(path_or_fd, NULL); |
341 | | |
342 | 992 | modeobj = PyUnicode_FromString(mode); |
343 | 992 | if (modeobj == NULL) |
344 | 0 | goto error; |
345 | | |
346 | | /* buffering */ |
347 | 992 | if (buffering < 0) { |
348 | 992 | PyObject *res = PyObject_CallMethodNoArgs(raw, &_Py_ID(_isatty_open_only)); |
349 | 992 | if (res == NULL) |
350 | 0 | goto error; |
351 | 992 | isatty = PyObject_IsTrue(res); |
352 | 992 | Py_DECREF(res); |
353 | 992 | if (isatty < 0) |
354 | 0 | goto error; |
355 | 992 | } |
356 | | |
357 | 992 | if (buffering == 1 || isatty) { |
358 | 0 | buffering = -1; |
359 | 0 | line_buffering = 1; |
360 | 0 | } |
361 | 992 | else |
362 | 992 | line_buffering = 0; |
363 | | |
364 | 992 | if (buffering < 0) { |
365 | 992 | PyObject *blksize_obj; |
366 | 992 | blksize_obj = PyObject_GetAttr(raw, &_Py_ID(_blksize)); |
367 | 992 | if (blksize_obj == NULL) |
368 | 0 | goto error; |
369 | 992 | buffering = PyLong_AsLong(blksize_obj); |
370 | 992 | Py_DECREF(blksize_obj); |
371 | 992 | if (buffering == -1 && PyErr_Occurred()) |
372 | 0 | goto error; |
373 | 992 | buffering = Py_MAX(Py_MIN(buffering, 8192 * 1024), DEFAULT_BUFFER_SIZE); |
374 | 992 | } |
375 | 992 | if (buffering < 0) { |
376 | 0 | PyErr_SetString(PyExc_ValueError, |
377 | 0 | "invalid buffering size"); |
378 | 0 | goto error; |
379 | 0 | } |
380 | | |
381 | | /* if not buffering, returns the raw file object */ |
382 | 992 | if (buffering == 0) { |
383 | 0 | if (!binary) { |
384 | 0 | PyErr_SetString(PyExc_ValueError, |
385 | 0 | "can't have unbuffered text I/O"); |
386 | 0 | goto error; |
387 | 0 | } |
388 | | |
389 | 0 | Py_DECREF(modeobj); |
390 | 0 | return result; |
391 | 0 | } |
392 | | |
393 | | /* wraps into a buffered file */ |
394 | 992 | { |
395 | 992 | PyObject *Buffered_class; |
396 | | |
397 | 992 | if (updating) { |
398 | 0 | Buffered_class = (PyObject *)state->PyBufferedRandom_Type; |
399 | 0 | } |
400 | 992 | else if (creating || writing || appending) { |
401 | 32 | Buffered_class = (PyObject *)state->PyBufferedWriter_Type; |
402 | 32 | } |
403 | 960 | else if (reading) { |
404 | 960 | Buffered_class = (PyObject *)state->PyBufferedReader_Type; |
405 | 960 | } |
406 | 0 | else { |
407 | 0 | PyErr_Format(PyExc_ValueError, |
408 | 0 | "unknown mode: '%s'", mode); |
409 | 0 | goto error; |
410 | 0 | } |
411 | | |
412 | 992 | buffer = PyObject_CallFunction(Buffered_class, "Oi", raw, buffering); |
413 | 992 | } |
414 | 992 | if (buffer == NULL) |
415 | 0 | goto error; |
416 | 992 | result = buffer; |
417 | 992 | Py_DECREF(raw); |
418 | | |
419 | | |
420 | | /* if binary, returns the buffered file */ |
421 | 992 | if (binary) { |
422 | 992 | Py_DECREF(modeobj); |
423 | 992 | return result; |
424 | 992 | } |
425 | | |
426 | | /* wraps into a TextIOWrapper */ |
427 | 0 | wrapper = PyObject_CallFunction((PyObject *)state->PyTextIOWrapper_Type, |
428 | 0 | "OsssO", |
429 | 0 | buffer, |
430 | 0 | encoding, errors, newline, |
431 | 0 | line_buffering ? Py_True : Py_False); |
432 | 0 | if (wrapper == NULL) |
433 | 0 | goto error; |
434 | 0 | result = wrapper; |
435 | 0 | Py_DECREF(buffer); |
436 | |
|
437 | 0 | if (PyObject_SetAttr(wrapper, &_Py_ID(mode), modeobj) < 0) |
438 | 0 | goto error; |
439 | 0 | Py_DECREF(modeobj); |
440 | 0 | return result; |
441 | | |
442 | 0 | error: |
443 | 0 | if (result != NULL) { |
444 | 0 | PyObject *exc = PyErr_GetRaisedException(); |
445 | 0 | PyObject *close_result = PyObject_CallMethodNoArgs(result, &_Py_ID(close)); |
446 | 0 | _PyErr_ChainExceptions1(exc); |
447 | 0 | Py_XDECREF(close_result); |
448 | 0 | Py_DECREF(result); |
449 | 0 | } |
450 | 0 | Py_XDECREF(path_or_fd); |
451 | 0 | Py_XDECREF(modeobj); |
452 | 0 | return NULL; |
453 | 0 | } |
454 | | |
455 | | |
456 | | /*[clinic input] |
457 | | _io.text_encoding |
458 | | encoding: object |
459 | | stacklevel: int = 2 |
460 | | / |
461 | | |
462 | | A helper function to choose the text encoding. |
463 | | |
464 | | When encoding is not None, this function returns it. |
465 | | Otherwise, this function returns the default text encoding |
466 | | (i.e. "locale" or "utf-8" depends on UTF-8 mode). |
467 | | |
468 | | This function emits an EncodingWarning if encoding is None and |
469 | | sys.flags.warn_default_encoding is true. |
470 | | |
471 | | This can be used in APIs with an encoding=None parameter. |
472 | | However, please consider using encoding="utf-8" for new APIs. |
473 | | [clinic start generated code]*/ |
474 | | |
475 | | static PyObject * |
476 | | _io_text_encoding_impl(PyObject *module, PyObject *encoding, int stacklevel) |
477 | | /*[clinic end generated code: output=91b2cfea6934cc0c input=4999aa8b3d90f3d4]*/ |
478 | 0 | { |
479 | 0 | if (encoding == NULL || encoding == Py_None) { |
480 | 0 | PyInterpreterState *interp = _PyInterpreterState_GET(); |
481 | 0 | if (_PyInterpreterState_GetConfig(interp)->warn_default_encoding) { |
482 | 0 | if (PyErr_WarnEx(PyExc_EncodingWarning, |
483 | 0 | "'encoding' argument not specified", stacklevel)) { |
484 | 0 | return NULL; |
485 | 0 | } |
486 | 0 | } |
487 | 0 | const PyPreConfig *preconfig = &_PyRuntime.preconfig; |
488 | 0 | if (preconfig->utf8_mode) { |
489 | 0 | _Py_DECLARE_STR(utf_8, "utf-8"); |
490 | 0 | encoding = &_Py_STR(utf_8); |
491 | 0 | } |
492 | 0 | else { |
493 | 0 | encoding = &_Py_ID(locale); |
494 | 0 | } |
495 | 0 | } |
496 | 0 | return Py_NewRef(encoding); |
497 | 0 | } |
498 | | |
499 | | |
500 | | /*[clinic input] |
501 | | _io.open_code |
502 | | |
503 | | path : unicode |
504 | | |
505 | | Opens the provided file with the intent to import the contents. |
506 | | |
507 | | This may perform extra validation beyond open(), but is otherwise interchangeable |
508 | | with calling open(path, 'rb'). |
509 | | |
510 | | [clinic start generated code]*/ |
511 | | |
512 | | static PyObject * |
513 | | _io_open_code_impl(PyObject *module, PyObject *path) |
514 | | /*[clinic end generated code: output=2fe4ecbd6f3d6844 input=f5c18e23f4b2ed9f]*/ |
515 | 944 | { |
516 | 944 | return PyFile_OpenCodeObject(path); |
517 | 944 | } |
518 | | |
519 | | /* |
520 | | * Private helpers for the io module. |
521 | | */ |
522 | | |
523 | | Py_off_t |
524 | | PyNumber_AsOff_t(PyObject *item, PyObject *err) |
525 | 1.04k | { |
526 | 1.04k | Py_off_t result; |
527 | 1.04k | PyObject *runerr; |
528 | 1.04k | PyObject *value = _PyNumber_Index(item); |
529 | 1.04k | if (value == NULL) |
530 | 0 | return -1; |
531 | | |
532 | | /* We're done if PyLong_AsSsize_t() returns without error. */ |
533 | 1.04k | result = PyLong_AsOff_t(value); |
534 | 1.04k | if (result != -1 || !(runerr = PyErr_Occurred())) |
535 | 1.04k | goto finish; |
536 | | |
537 | | /* Error handling code -- only manage OverflowError differently */ |
538 | 0 | if (!PyErr_GivenExceptionMatches(runerr, PyExc_OverflowError)) |
539 | 0 | goto finish; |
540 | | |
541 | 0 | PyErr_Clear(); |
542 | | /* If no error-handling desired then the default clipping |
543 | | is sufficient. |
544 | | */ |
545 | 0 | if (!err) { |
546 | 0 | assert(PyLong_Check(value)); |
547 | 0 | if (_PyLong_IsNegative((PyLongObject *)value)) |
548 | 0 | result = PY_OFF_T_MIN; |
549 | 0 | else |
550 | 0 | result = PY_OFF_T_MAX; |
551 | 0 | } |
552 | 0 | else { |
553 | | /* Otherwise replace the error with caller's error object. */ |
554 | 0 | PyErr_Format(err, |
555 | 0 | "cannot fit '%.200s' into an offset-sized integer", |
556 | 0 | Py_TYPE(item)->tp_name); |
557 | 0 | } |
558 | |
|
559 | 1.04k | finish: |
560 | 1.04k | Py_DECREF(value); |
561 | 1.04k | return result; |
562 | 0 | } |
563 | | |
564 | | static int |
565 | 5.58k | iomodule_traverse(PyObject *mod, visitproc visit, void *arg) { |
566 | 5.58k | _PyIO_State *state = get_io_state(mod); |
567 | 5.58k | Py_VISIT(state->unsupported_operation); |
568 | | |
569 | 5.58k | Py_VISIT(state->PyIOBase_Type); |
570 | 5.58k | Py_VISIT(state->PyIncrementalNewlineDecoder_Type); |
571 | 5.58k | Py_VISIT(state->PyRawIOBase_Type); |
572 | 5.58k | Py_VISIT(state->PyBufferedIOBase_Type); |
573 | 5.58k | Py_VISIT(state->PyBufferedRWPair_Type); |
574 | 5.58k | Py_VISIT(state->PyBufferedRandom_Type); |
575 | 5.58k | Py_VISIT(state->PyBufferedReader_Type); |
576 | 5.58k | Py_VISIT(state->PyBufferedWriter_Type); |
577 | 5.58k | Py_VISIT(state->PyBytesIOBuffer_Type); |
578 | 5.58k | Py_VISIT(state->PyBytesIO_Type); |
579 | 5.58k | Py_VISIT(state->PyFileIO_Type); |
580 | 5.58k | Py_VISIT(state->PyStringIO_Type); |
581 | 5.58k | Py_VISIT(state->PyTextIOBase_Type); |
582 | 5.58k | Py_VISIT(state->PyTextIOWrapper_Type); |
583 | | #ifdef HAVE_WINDOWS_CONSOLE_IO |
584 | | Py_VISIT(state->PyWindowsConsoleIO_Type); |
585 | | #endif |
586 | 5.58k | return 0; |
587 | 5.58k | } |
588 | | |
589 | | |
590 | | static int |
591 | 0 | iomodule_clear(PyObject *mod) { |
592 | 0 | _PyIO_State *state = get_io_state(mod); |
593 | 0 | Py_CLEAR(state->unsupported_operation); |
594 | |
|
595 | 0 | Py_CLEAR(state->PyIOBase_Type); |
596 | 0 | Py_CLEAR(state->PyIncrementalNewlineDecoder_Type); |
597 | 0 | Py_CLEAR(state->PyRawIOBase_Type); |
598 | 0 | Py_CLEAR(state->PyBufferedIOBase_Type); |
599 | 0 | Py_CLEAR(state->PyBufferedRWPair_Type); |
600 | 0 | Py_CLEAR(state->PyBufferedRandom_Type); |
601 | 0 | Py_CLEAR(state->PyBufferedReader_Type); |
602 | 0 | Py_CLEAR(state->PyBufferedWriter_Type); |
603 | 0 | Py_CLEAR(state->PyBytesIOBuffer_Type); |
604 | 0 | Py_CLEAR(state->PyBytesIO_Type); |
605 | 0 | Py_CLEAR(state->PyFileIO_Type); |
606 | 0 | Py_CLEAR(state->PyStringIO_Type); |
607 | 0 | Py_CLEAR(state->PyTextIOBase_Type); |
608 | 0 | Py_CLEAR(state->PyTextIOWrapper_Type); |
609 | | #ifdef HAVE_WINDOWS_CONSOLE_IO |
610 | | Py_CLEAR(state->PyWindowsConsoleIO_Type); |
611 | | #endif |
612 | 0 | return 0; |
613 | 0 | } |
614 | | |
615 | | static void |
616 | | iomodule_free(void *mod) |
617 | 0 | { |
618 | 0 | (void)iomodule_clear((PyObject *)mod); |
619 | 0 | } |
620 | | |
621 | | |
622 | | /* |
623 | | * Module definition |
624 | | */ |
625 | | |
626 | | #define clinic_state() (get_io_state(module)) |
627 | | #include "clinic/_iomodule.c.h" |
628 | | #undef clinic_state |
629 | | |
630 | | static PyMethodDef module_methods[] = { |
631 | | _IO_OPEN_METHODDEF |
632 | | _IO_TEXT_ENCODING_METHODDEF |
633 | | _IO_OPEN_CODE_METHODDEF |
634 | | {NULL, NULL} |
635 | | }; |
636 | | |
637 | 224 | #define ADD_TYPE(module, type, spec, base) \ |
638 | 224 | do { \ |
639 | 224 | type = (PyTypeObject *)PyType_FromModuleAndSpec(module, spec, \ |
640 | 224 | (PyObject *)base); \ |
641 | 224 | if (type == NULL) { \ |
642 | 0 | return -1; \ |
643 | 0 | } \ |
644 | 224 | if (PyModule_AddType(module, type) < 0) { \ |
645 | 0 | return -1; \ |
646 | 0 | } \ |
647 | 224 | } while (0) |
648 | | |
649 | | static int |
650 | | iomodule_exec(PyObject *m) |
651 | 16 | { |
652 | 16 | _PyIO_State *state = get_io_state(m); |
653 | | |
654 | | /* DEFAULT_BUFFER_SIZE */ |
655 | 16 | if (PyModule_AddIntMacro(m, DEFAULT_BUFFER_SIZE) < 0) |
656 | 0 | return -1; |
657 | | |
658 | | /* UnsupportedOperation inherits from ValueError and OSError */ |
659 | 16 | state->unsupported_operation = PyObject_CallFunction( |
660 | 16 | (PyObject *)&PyType_Type, "s(OO){}", |
661 | 16 | "UnsupportedOperation", PyExc_OSError, PyExc_ValueError); |
662 | 16 | if (state->unsupported_operation == NULL) |
663 | 0 | return -1; |
664 | 16 | if (PyObject_SetAttrString(state->unsupported_operation, |
665 | 16 | "__module__", &_Py_ID(io)) < 0) |
666 | 0 | { |
667 | 0 | return -1; |
668 | 0 | } |
669 | 16 | if (PyModule_AddObjectRef(m, "UnsupportedOperation", |
670 | 16 | state->unsupported_operation) < 0) |
671 | 0 | { |
672 | 0 | return -1; |
673 | 0 | } |
674 | | |
675 | | /* BlockingIOError, for compatibility */ |
676 | 16 | if (PyModule_AddObjectRef(m, "BlockingIOError", |
677 | 16 | (PyObject *) PyExc_BlockingIOError) < 0) { |
678 | 0 | return -1; |
679 | 0 | } |
680 | | |
681 | | // Base classes |
682 | 16 | ADD_TYPE(m, state->PyIncrementalNewlineDecoder_Type, &nldecoder_spec, NULL); |
683 | 16 | ADD_TYPE(m, state->PyBytesIOBuffer_Type, &bytesiobuf_spec, NULL); |
684 | 16 | ADD_TYPE(m, state->PyIOBase_Type, &iobase_spec, NULL); |
685 | | |
686 | | // PyIOBase_Type subclasses |
687 | 16 | ADD_TYPE(m, state->PyTextIOBase_Type, &textiobase_spec, |
688 | 16 | state->PyIOBase_Type); |
689 | 16 | ADD_TYPE(m, state->PyBufferedIOBase_Type, &bufferediobase_spec, |
690 | 16 | state->PyIOBase_Type); |
691 | 16 | ADD_TYPE(m, state->PyRawIOBase_Type, &rawiobase_spec, |
692 | 16 | state->PyIOBase_Type); |
693 | | |
694 | | // PyBufferedIOBase_Type(PyIOBase_Type) subclasses |
695 | 16 | ADD_TYPE(m, state->PyBytesIO_Type, &bytesio_spec, state->PyBufferedIOBase_Type); |
696 | 16 | ADD_TYPE(m, state->PyBufferedWriter_Type, &bufferedwriter_spec, |
697 | 16 | state->PyBufferedIOBase_Type); |
698 | 16 | ADD_TYPE(m, state->PyBufferedReader_Type, &bufferedreader_spec, |
699 | 16 | state->PyBufferedIOBase_Type); |
700 | 16 | ADD_TYPE(m, state->PyBufferedRWPair_Type, &bufferedrwpair_spec, |
701 | 16 | state->PyBufferedIOBase_Type); |
702 | 16 | ADD_TYPE(m, state->PyBufferedRandom_Type, &bufferedrandom_spec, |
703 | 16 | state->PyBufferedIOBase_Type); |
704 | | |
705 | | // PyRawIOBase_Type(PyIOBase_Type) subclasses |
706 | 16 | ADD_TYPE(m, state->PyFileIO_Type, &fileio_spec, state->PyRawIOBase_Type); |
707 | | |
708 | | #ifdef HAVE_WINDOWS_CONSOLE_IO |
709 | | ADD_TYPE(m, state->PyWindowsConsoleIO_Type, &winconsoleio_spec, |
710 | | state->PyRawIOBase_Type); |
711 | | #endif |
712 | | |
713 | | // PyTextIOBase_Type(PyIOBase_Type) subclasses |
714 | 16 | ADD_TYPE(m, state->PyStringIO_Type, &stringio_spec, state->PyTextIOBase_Type); |
715 | 16 | ADD_TYPE(m, state->PyTextIOWrapper_Type, &textiowrapper_spec, |
716 | 16 | state->PyTextIOBase_Type); |
717 | | |
718 | 16 | #undef ADD_TYPE |
719 | 16 | return 0; |
720 | 16 | } |
721 | | |
722 | | static struct PyModuleDef_Slot iomodule_slots[] = { |
723 | | {Py_mod_exec, iomodule_exec}, |
724 | | {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, |
725 | | {Py_mod_gil, Py_MOD_GIL_NOT_USED}, |
726 | | {0, NULL}, |
727 | | }; |
728 | | |
729 | | struct PyModuleDef _PyIO_Module = { |
730 | | .m_base = PyModuleDef_HEAD_INIT, |
731 | | .m_name = "io", |
732 | | .m_doc = module_doc, |
733 | | .m_size = sizeof(_PyIO_State), |
734 | | .m_methods = module_methods, |
735 | | .m_traverse = iomodule_traverse, |
736 | | .m_clear = iomodule_clear, |
737 | | .m_free = iomodule_free, |
738 | | .m_slots = iomodule_slots, |
739 | | }; |
740 | | |
741 | | PyMODINIT_FUNC |
742 | | PyInit__io(void) |
743 | 16 | { |
744 | 16 | return PyModuleDef_Init(&_PyIO_Module); |
745 | 16 | } |