| Left: | ||
| Right: |
| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 An implementation of the new I/O lib as defined by PEP 3116 - "New I/O" | 2 An implementation of the new I/O lib as defined by PEP 3116 - "New I/O" |
| 3 | 3 |
| 4 Classes defined here: UnsupportedOperation, BlockingIOError. | 4 Classes defined here: UnsupportedOperation, BlockingIOError. |
| 5 Functions defined here: open(). | 5 Functions defined here: open(). |
| 6 | 6 |
| 7 Mostly written by Amaury Forgeot d'Arc | 7 Mostly written by Amaury Forgeot d'Arc |
| 8 */ | 8 */ |
| 9 | 9 |
| 10 #define PY_SSIZE_T_CLEAN | 10 #define PY_SSIZE_T_CLEAN |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 183 "Open file and return a stream. Raise IOError upon failure.\n" | 183 "Open file and return a stream. Raise IOError upon failure.\n" |
| 184 "\n" | 184 "\n" |
| 185 "file is either a text or byte string giving the name (and the path\n" | 185 "file is either a text or byte string giving the name (and the path\n" |
| 186 "if the file isn't in the current working directory) of the file to\n" | 186 "if the file isn't in the current working directory) of the file to\n" |
| 187 "be opened or an integer file descriptor of the file to be\n" | 187 "be opened or an integer file descriptor of the file to be\n" |
| 188 "wrapped. (If a file descriptor is given, it is closed when the\n" | 188 "wrapped. (If a file descriptor is given, it is closed when the\n" |
| 189 "returned I/O object is closed, unless closefd is set to False.)\n" | 189 "returned I/O object is closed, unless closefd is set to False.)\n" |
| 190 "\n" | 190 "\n" |
| 191 "mode is an optional string that specifies the mode in which the file\n" | 191 "mode is an optional string that specifies the mode in which the file\n" |
| 192 "is opened. It defaults to 'r' which means open for reading in text\n" | 192 "is opened. It defaults to 'r' which means open for reading in text\n" |
| 193 "mode. Other common values are 'w' for writing (truncating the file if\n" | 193 "mode. Other common values are 'x' for creating and writing to a new \n" |
| 194 "file, 'w' for writing (truncating the file if\n" | |
| 194 "it already exists), and 'a' for appending (which on some Unix systems,\n" | 195 "it already exists), and 'a' for appending (which on some Unix systems,\n" |
| 195 "means that all writes append to the end of the file regardless of the\n" | 196 "means that all writes append to the end of the file regardless of the\n" |
| 196 "current seek position). In text mode, if encoding is not specified the\n" | 197 "current seek position). In text mode, if encoding is not specified the\n" |
| 197 "encoding used is platform dependent. (For reading and writing raw\n" | 198 "encoding used is platform dependent. (For reading and writing raw\n" |
| 198 "bytes use binary mode and leave encoding unspecified.) The available\n" | 199 "bytes use binary mode and leave encoding unspecified.) The available\n" |
| 199 "modes are:\n" | 200 "modes are:\n" |
| 200 "\n" | 201 "\n" |
| 201 "========= ===============================================================\n" | 202 "========= ===============================================================\n" |
| 202 "Character Meaning\n" | 203 "Character Meaning\n" |
| 203 "--------- ---------------------------------------------------------------\n" | 204 "--------- ---------------------------------------------------------------\n" |
| 204 "'r' open for reading (default)\n" | 205 "'r' open for reading (default)\n" |
| 206 "'x' create a new file and open it for writing\n" | |
| 205 "'w' open for writing, truncating the file first\n" | 207 "'w' open for writing, truncating the file first\n" |
| 206 "'a' open for writing, appending to the end of the file if it exists\n" | 208 "'a' open for writing, appending to the end of the file if it exists\n" |
| 207 "'b' binary mode\n" | 209 "'b' binary mode\n" |
| 208 "'t' text mode (default)\n" | 210 "'t' text mode (default)\n" |
| 209 "'+' open a disk file for updating (reading and writing)\n" | 211 "'+' open a disk file for updating (reading and writing)\n" |
| 210 "'U' universal newline mode (for backwards compatibility; unneeded\n" | 212 "'U' universal newline mode (for backwards compatibility; unneeded\n" |
| 211 " for new code)\n" | 213 " for new code)\n" |
| 212 "========= ===============================================================\n" | 214 "========= ===============================================================\n" |
| 213 "\n" | 215 "\n" |
| 214 "The default mode is 'rt' (open for reading text). For binary random\n" | 216 "The default mode is 'rt' (open for reading text). For binary random\n" |
| 215 "access, the mode 'w+b' opens and truncates the file to 0 bytes, while\n" | 217 "access, the mode 'w+b' opens and truncates the file to 0 bytes, while\n" |
| 216 "'r+b' opens the file without truncation.\n" | 218 "'r+b' opens the file without truncation. The 'x' mode implies 'w' and\n" |
| 219 "raises an `IOError` if the file already exists.\n" | |
|
Benjamin Peterson
2012/01/08 16:16:10
OSError.
| |
| 217 "\n" | 220 "\n" |
| 218 "Python distinguishes between files opened in binary and text modes,\n" | 221 "Python distinguishes between files opened in binary and text modes,\n" |
| 219 "even when the underlying operating system doesn't. Files opened in\n" | 222 "even when the underlying operating system doesn't. Files opened in\n" |
| 220 "binary mode (appending 'b' to the mode argument) return contents as\n" | 223 "binary mode (appending 'b' to the mode argument) return contents as\n" |
| 221 "bytes objects without any decoding. In text mode (the default, or when\n" | 224 "bytes objects without any decoding. In text mode (the default, or when\n" |
| 222 "'t' is appended to the mode argument), the contents of the file are\n" | 225 "'t' is appended to the mode argument), the contents of the file are\n" |
| 223 "returned as strings, the bytes having been first decoded using a\n" | 226 "returned as strings, the bytes having been first decoded using a\n" |
| 224 "platform-dependent encoding or using the specified encoding if given.\n" | 227 "platform-dependent encoding or using the specified encoding if given.\n" |
| 225 "\n" | 228 "\n" |
| 226 "buffering is an optional integer used to set the buffering policy.\n" | 229 "buffering is an optional integer used to set the buffering policy.\n" |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 293 { | 296 { |
| 294 char *kwlist[] = {"file", "mode", "buffering", | 297 char *kwlist[] = {"file", "mode", "buffering", |
| 295 "encoding", "errors", "newline", | 298 "encoding", "errors", "newline", |
| 296 "closefd", NULL}; | 299 "closefd", NULL}; |
| 297 PyObject *file; | 300 PyObject *file; |
| 298 char *mode = "r"; | 301 char *mode = "r"; |
| 299 int buffering = -1, closefd = 1; | 302 int buffering = -1, closefd = 1; |
| 300 char *encoding = NULL, *errors = NULL, *newline = NULL; | 303 char *encoding = NULL, *errors = NULL, *newline = NULL; |
| 301 unsigned i; | 304 unsigned i; |
| 302 | 305 |
| 303 int reading = 0, writing = 0, appending = 0, updating = 0; | 306 int creating = 0, reading = 0, writing = 0, appending = 0, updating = 0; |
| 304 int text = 0, binary = 0, universal = 0; | 307 int text = 0, binary = 0, universal = 0; |
| 305 | 308 |
| 306 char rawmode[5], *m; | 309 char rawmode[5], *m; |
| 307 int line_buffering, isatty; | 310 int line_buffering, isatty; |
| 308 | 311 |
| 309 PyObject *raw, *modeobj = NULL, *buffer = NULL, *wrapper = NULL; | 312 PyObject *raw, *modeobj = NULL, *buffer = NULL, *wrapper = NULL; |
| 310 | 313 |
| 311 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|sizzzi:open", kwlist, | 314 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|sizzzi:open", kwlist, |
| 312 &file, &mode, &buffering, | 315 &file, &mode, &buffering, |
| 313 &encoding, &errors, &newline, | 316 &encoding, &errors, &newline, |
| 314 &closefd)) { | 317 &closefd)) { |
| 315 return NULL; | 318 return NULL; |
| 316 } | 319 } |
| 317 | 320 |
| 318 if (!PyUnicode_Check(file) && | 321 if (!PyUnicode_Check(file) && |
| 319 !PyBytes_Check(file) && | 322 !PyBytes_Check(file) && |
| 320 !PyNumber_Check(file)) { | 323 !PyNumber_Check(file)) { |
| 321 PyErr_Format(PyExc_TypeError, "invalid file: %R", file); | 324 PyErr_Format(PyExc_TypeError, "invalid file: %R", file); |
| 322 return NULL; | 325 return NULL; |
| 323 } | 326 } |
| 324 | 327 |
| 325 /* Decode mode */ | 328 /* Decode mode */ |
| 326 for (i = 0; i < strlen(mode); i++) { | 329 for (i = 0; i < strlen(mode); i++) { |
| 327 char c = mode[i]; | 330 char c = mode[i]; |
| 328 | 331 |
| 329 switch (c) { | 332 switch (c) { |
| 333 case 'x': | |
| 334 creating = 1; | |
| 335 break; | |
|
Charles-François Natali
2011/12/30 12:49:33
The indentation level odesn't match.
| |
| 330 case 'r': | 336 case 'r': |
| 331 reading = 1; | 337 reading = 1; |
| 332 break; | 338 break; |
| 333 case 'w': | 339 case 'w': |
| 334 writing = 1; | 340 writing = 1; |
| 335 break; | 341 break; |
| 336 case 'a': | 342 case 'a': |
| 337 appending = 1; | 343 appending = 1; |
| 338 break; | 344 break; |
| 339 case '+': | 345 case '+': |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 356 /* c must not be duplicated */ | 362 /* c must not be duplicated */ |
| 357 if (strchr(mode+i+1, c)) { | 363 if (strchr(mode+i+1, c)) { |
| 358 invalid_mode: | 364 invalid_mode: |
| 359 PyErr_Format(PyExc_ValueError, "invalid mode: '%s'", mode); | 365 PyErr_Format(PyExc_ValueError, "invalid mode: '%s'", mode); |
| 360 return NULL; | 366 return NULL; |
| 361 } | 367 } |
| 362 | 368 |
| 363 } | 369 } |
| 364 | 370 |
| 365 m = rawmode; | 371 m = rawmode; |
| 372 if (creating) *(m++) = 'x'; | |
| 366 if (reading) *(m++) = 'r'; | 373 if (reading) *(m++) = 'r'; |
| 367 if (writing) *(m++) = 'w'; | 374 if (writing) *(m++) = 'w'; |
| 368 if (appending) *(m++) = 'a'; | 375 if (appending) *(m++) = 'a'; |
| 369 if (updating) *(m++) = '+'; | 376 if (updating) *(m++) = '+'; |
| 370 *m = '\0'; | 377 *m = '\0'; |
| 371 | 378 |
| 372 /* Parameters validation */ | 379 /* Parameters validation */ |
| 373 if (universal) { | 380 if (universal) { |
| 374 if (writing || appending) { | 381 if (writing || appending) { |
| 375 PyErr_SetString(PyExc_ValueError, | 382 PyErr_SetString(PyExc_ValueError, |
| 376 "can't use U and writing mode at once"); | 383 "can't use U and writing mode at once"); |
| 377 return NULL; | 384 return NULL; |
| 378 } | 385 } |
| 379 reading = 1; | 386 reading = 1; |
| 380 } | 387 } |
| 381 | 388 |
| 382 if (text && binary) { | 389 if (text && binary) { |
| 383 PyErr_SetString(PyExc_ValueError, | 390 PyErr_SetString(PyExc_ValueError, |
| 384 "can't have text and binary mode at once"); | 391 "can't have text and binary mode at once"); |
| 385 return NULL; | 392 return NULL; |
| 386 } | 393 } |
| 387 | 394 |
| 388 if (reading + writing + appending > 1) { | 395 if (creating + reading + writing + appending > 1) { |
| 389 PyErr_SetString(PyExc_ValueError, | 396 PyErr_SetString(PyExc_ValueError, |
| 390 "must have exactly one of read/write/append mode"); | 397 "must have exactly one of create/read/write/append mode" ); |
| 391 return NULL; | 398 return NULL; |
| 392 } | 399 } |
| 393 | 400 |
| 394 if (binary && encoding != NULL) { | 401 if (binary && encoding != NULL) { |
| 395 PyErr_SetString(PyExc_ValueError, | 402 PyErr_SetString(PyExc_ValueError, |
| 396 "binary mode doesn't take an encoding argument"); | 403 "binary mode doesn't take an encoding argument"); |
| 397 return NULL; | 404 return NULL; |
| 398 } | 405 } |
| 399 | 406 |
| 400 if (binary && errors != NULL) { | 407 if (binary && errors != NULL) { |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 474 Py_DECREF(modeobj); | 481 Py_DECREF(modeobj); |
| 475 return raw; | 482 return raw; |
| 476 } | 483 } |
| 477 | 484 |
| 478 /* wraps into a buffered file */ | 485 /* wraps into a buffered file */ |
| 479 { | 486 { |
| 480 PyObject *Buffered_class; | 487 PyObject *Buffered_class; |
| 481 | 488 |
| 482 if (updating) | 489 if (updating) |
| 483 Buffered_class = (PyObject *)&PyBufferedRandom_Type; | 490 Buffered_class = (PyObject *)&PyBufferedRandom_Type; |
| 484 else if (writing || appending) | 491 else if (creating || writing || appending) |
| 485 Buffered_class = (PyObject *)&PyBufferedWriter_Type; | 492 Buffered_class = (PyObject *)&PyBufferedWriter_Type; |
| 486 else if (reading) | 493 else if (reading) |
| 487 Buffered_class = (PyObject *)&PyBufferedReader_Type; | 494 Buffered_class = (PyObject *)&PyBufferedReader_Type; |
| 488 else { | 495 else { |
| 489 PyErr_Format(PyExc_ValueError, | 496 PyErr_Format(PyExc_ValueError, |
| 490 "unknown mode: '%s'", mode); | 497 "unknown mode: '%s'", mode); |
| 491 goto error; | 498 goto error; |
| 492 } | 499 } |
| 493 | 500 |
| 494 buffer = PyObject_CallFunction(Buffered_class, "Oi", raw, buffering); | 501 buffer = PyObject_CallFunction(Buffered_class, "Oi", raw, buffering); |
| (...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 801 state->initialized = 1; | 808 state->initialized = 1; |
| 802 | 809 |
| 803 return m; | 810 return m; |
| 804 | 811 |
| 805 fail: | 812 fail: |
| 806 Py_XDECREF(state->os_module); | 813 Py_XDECREF(state->os_module); |
| 807 Py_XDECREF(state->unsupported_operation); | 814 Py_XDECREF(state->unsupported_operation); |
| 808 Py_DECREF(m); | 815 Py_DECREF(m); |
| 809 return NULL; | 816 return NULL; |
| 810 } | 817 } |
| OLD | NEW |