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