Commit Graph

750 Commits

Author SHA1 Message Date
morotti b1b4f9625c gh-117151: IO performance improvement, increase io.DEFAULT_BUFFER_SIZE to 128k (GH-118144)
Co-authored-by: rmorotti <romain.morotti@man.com>
2025-03-07 11:36:12 -08:00
Cody Maloney 886a4d74ee gh-129011: Update comments in FileIO to match current code (#129012) 2025-03-06 17:18:22 -08:00
Sergey Miryanov 3a7f17c7e2 gh-130790: Remove references about unicode's readiness from comments (#130801) 2025-03-03 19:18:09 +00:00
Bénédikt Tran 1988003625 gh-111178: fix UBSan failures in Modules/_io/*.c (GH-129083)
* fix UBSan failures for `buffered`, `rwpair`, `bytesio`, `bytesiobuf`, `iobase`, `stringio`, `nldecoder_object`, `textio`, `winconsoleio`

* arg names: use 'dummy' for NOARGS method and 'args' for others
2025-02-08 14:21:32 +01:00
Victor Stinner 14489c1bb4 gh-129354: Use PyErr_FormatUnraisable() function (#129656)
Replace PyErr_WriteUnraisable() with PyErr_FormatUnraisable().
2025-02-04 16:21:10 +01:00
Victor Stinner 732670d93b gh-119182: Use public PyUnicodeWriter in stringio.c (#129243)
Replace the private _PyUnicodeWriter API with the public
PyUnicodeWriter API.
2025-01-23 23:31:49 +00:00
Erlend E. Aasland 537296cdcd gh-111178: Generate correct signature for most self converters (#128447) 2025-01-20 12:40:18 +01:00
Peter Bierma b5d1e4552f gh-128083: Fix macro redefinition warning in clinic. (GH-127950) 2024-12-19 15:00:30 +01:00
Giovanni Siragusa 31f16e427b gh-109523: Raise a BlockingIOError if reading text from a non-blocking stream cannot immediately return bytes. (GH-122933) 2024-12-02 14:18:30 +01:00
Peter Bierma 99490913a0 gh-127341: Argument Clinic: fix compiler warnings for getters with docstrings (#127310)
Co-authored-by: Erlend E. Aasland <erlend@python.org>
2024-11-29 11:12:13 +01:00
Serhiy Storchaka 3cf83d91a5 gh-124008: Fix calculation of the number of written bytes for the Windows console (GH-124059)
Since MultiByteToWideChar()/WideCharToMultiByte() is not reversible if
the data contains invalid UTF-8 sequences, use binary search to
calculate the number of written bytes from the number of written
characters.

Also fix writing incomplete UTF-8 sequences.

Also fix handling of memory allocation failures.
2024-11-27 13:38:12 +02:00
sobolevn a2ee899682 gh-127182: Fix io.StringIO.__setstate__ crash when None is the first value (#127219)
Co-authored-by: Victor Stinner <vstinner@python.org>
2024-11-25 20:32:02 +03:00
Serhiy Storchaka 061e50f196 gh-122943: Add the varpos parameter in _PyArg_UnpackKeywords (GH-126564)
Remove _PyArg_UnpackKeywordsWithVararg.
Add comments for integer arguments of _PyArg_UnpackKeywords.
2024-11-08 14:23:50 +02:00
Cody Maloney 72dd4714f9 gh-120754: _io Ensure stat cache is cleared on fd change (#125166)
Performed an audit of `fileio.c` and `_pyio` and made sure anytime the
fd changes the stat result, if set, is also cleared/changed.

There's one case where it's not cleared, if code would clear it in
__init__, keep the memory allocated and just do another fstat with the
existing memory.
2024-11-01 22:50:49 +01:00
Victor Stinner ebcc578dff gh-115754: Use Py_GetConstant(Py_CONSTANT_EMPTY_STR) (#125583)
Replace PyUnicode_FromStringAndSize(NULL, 0)
with Py_GetConstant(Py_CONSTANT_EMPTY_STR).
2024-10-25 11:14:52 +02:00
Victor Stinner b9a8ca0a6a gh-115754: Use Py_GetConstant(Py_CONSTANT_EMPTY_STR) (#125194)
Replace PyUnicode_New(0, 0), PyUnicode_FromString("")
and PyUnicode_FromStringAndSize("", 0)
with Py_GetConstant(Py_CONSTANT_EMPTY_STR).
2024-10-09 17:15:23 +02:00
Victor Stinner 6a39e96ab8 gh-115754: Use Py_GetConstant(Py_CONSTANT_EMPTY_BYTES) (#125195)
Replace PyBytes_FromString("") and PyBytes_FromStringAndSize("", 0)
with Py_GetConstant(Py_CONSTANT_EMPTY_BYTES).
2024-10-09 17:12:11 +02:00
Cody Maloney cc9b9bebb2 gh-90102: Remove isatty call during regular open (#124922)
Co-authored-by: Victor Stinner <vstinner@python.org>
2024-10-08 08:50:42 +02:00
Victor Stinner d8f707420b gh-111178: Fix function signatures in fileio.c (#125043)
* Add "fileio_" prefix to getter functions.
* Small refactoring.
2024-10-07 15:27:36 +02:00
Victor Stinner 43cd7aa8cd gh-120754: Fix memory leak in FileIO.__init__() (#124225)
Free 'self->stat_atopen' before assigning it, since
io.FileIO.__init__() can be called multiple times manually
(especially by test_io).
2024-09-19 00:11:50 +02:00
Cody Maloney 8b6c7c7877 gh-120754: Refactor I/O modules to stash whole stat result rather than individual members (#123412)
Multiple places in the I/O stack optimize common cases by using the
information from stat. Currently individual members are extracted from
the stat and stored into the fileio struct. Refactor the code to store
the whole stat struct instead.

Parallels the changes to _io. The `stat` Python object doesn't allow
changing members, so rather than modifying estimated_size, just clear
the value.
2024-09-18 17:47:57 +02:00
Victor Stinner 3d60dfbe17 gh-121645: Add PyBytes_Join() function (#121646)
* Replace _PyBytes_Join() with PyBytes_Join().
* Keep _PyBytes_Join() as an alias to PyBytes_Join().
2024-08-30 12:57:33 +00:00
Wulian 9e108b8719 Fix typos in docs, error messages and comments (#123336)
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
2024-08-28 14:41:04 +03:00
Marc Mueller aef95eb107 gh-121489: Export private _PyBytes_Join() again (#122267) 2024-07-25 17:31:30 +02:00
Cody Maloney 06a1c3fb24 gh-120754: Update estimated_size in C truncate (#121357)
Sometimes a large file is truncated (test_largefile). While
estimated_size is used as a estimate (the read will stil get the number
of bytes in the file), that it is much larger than the actual size of
data can result in a significant over allocation and sometimes lead to
a MemoryError / running out of memory.

This brings the C implementation to match the Python _pyio
implementation.
2024-07-04 12:59:18 +00:00
Cody Maloney 2f5f19e783 gh-120754: Reduce system calls in full-file FileIO.readall() case (#120755)
This reduces the system call count of a simple program[0] that reads all
the `.rst` files in Doc by over 10% (5706 -> 4734 system calls on my
linux system, 5813 -> 4875 on my macOS)

This reduces the number of `fstat()` calls always and seek calls most
the time. Stat was always called twice, once at open (to error early on
directories), and a second time to get the size of the file to be able
to read the whole file in one read. Now the size is cached with the
first call.

The code keeps an optimization that if the user had previously read a
lot of data, the current position is subtracted from the number of bytes
to read. That is somewhat expensive so only do it on larger files,
otherwise just try and read the extra bytes and resize the PyBytes as
needeed.

I built a little test program to validate the behavior + assumptions
around relative costs and then ran it under `strace` to get a log of the
system calls. Full samples below[1].

After the changes, this is everything in one `filename.read_text()`:

```python3
openat(AT_FDCWD, "cpython/Doc/howto/clinic.rst", O_RDONLY|O_CLOEXEC) = 3`
fstat(3, {st_mode=S_IFREG|0644, st_size=343, ...}) = 0`
ioctl(3, TCGETS, 0x7ffdfac04b40)        = -1 ENOTTY (Inappropriate ioctl for device)
lseek(3, 0, SEEK_CUR)                   = 0
read(3, ":orphan:\n\n.. This page is retain"..., 344) = 343
read(3, "", 1)                          = 0
close(3)                                = 0
```

This does make some tradeoffs
1. If the file size changes between open() and readall(), this will
still get all the data but might have more read calls.
2. I experimented with avoiding the stat + cached result for small files
in general, but on my dev workstation at least that tended to reduce
performance compared to using the fstat().

[0]

```python3
from pathlib import Path

nlines = []
for filename in Path("cpython/Doc").glob("**/*.rst"):
    nlines.append(len(filename.read_text()))
```

[1]
Before small file:

```
openat(AT_FDCWD, "cpython/Doc/howto/clinic.rst", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=343, ...}) = 0
ioctl(3, TCGETS, 0x7ffe52525930)        = -1 ENOTTY (Inappropriate ioctl for device)
lseek(3, 0, SEEK_CUR)                   = 0
lseek(3, 0, SEEK_CUR)                   = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=343, ...}) = 0
read(3, ":orphan:\n\n.. This page is retain"..., 344) = 343
read(3, "", 1)                          = 0
close(3)                                = 0
```

After small file:

```
openat(AT_FDCWD, "cpython/Doc/howto/clinic.rst", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=343, ...}) = 0
ioctl(3, TCGETS, 0x7ffdfac04b40)        = -1 ENOTTY (Inappropriate ioctl for device)
lseek(3, 0, SEEK_CUR)                   = 0
read(3, ":orphan:\n\n.. This page is retain"..., 344) = 343
read(3, "", 1)                          = 0
close(3)                                = 0
```

Before large file:

```
openat(AT_FDCWD, "cpython/Doc/c-api/typeobj.rst", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=133104, ...}) = 0
ioctl(3, TCGETS, 0x7ffe52525930)        = -1 ENOTTY (Inappropriate ioctl for device)
lseek(3, 0, SEEK_CUR)                   = 0
lseek(3, 0, SEEK_CUR)                   = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=133104, ...}) = 0
read(3, ".. highlight:: c\n\n.. _type-struc"..., 133105) = 133104
read(3, "", 1)                          = 0
close(3)                                = 0
```

After large file:

```
openat(AT_FDCWD, "cpython/Doc/c-api/typeobj.rst", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=133104, ...}) = 0
ioctl(3, TCGETS, 0x7ffdfac04b40)        = -1 ENOTTY (Inappropriate ioctl for device)
lseek(3, 0, SEEK_CUR)                   = 0
lseek(3, 0, SEEK_CUR)                   = 0
read(3, ".. highlight:: c\n\n.. _type-struc"..., 133105) = 133104
read(3, "", 1)                          = 0
close(3)                                = 0
```

Co-authored-by: Shantanu <12621235+hauntsaninja@users.noreply.github.com>
Co-authored-by: Erlend E. Aasland <erlend.aasland@protonmail.com>
Co-authored-by: Victor Stinner <vstinner@python.org>
2024-07-04 09:17:00 +02:00
Steve Dower e731554337 Fixes loop variables to be the same types as their limit (GH-120958) 2024-06-24 17:11:47 +01:00
Serhiy Storchaka 02df679574 Use _PyLong_IsNegative instead of _PyLong_Sign if appropriate. (GH-120493)
It is faster and more obvious.
2024-06-24 09:49:01 +03:00
Petr Viktorin 6f1d448bc1 gh-113993: Allow interned strings to be mortal, and fix related issues (GH-120520)
* Add an InternalDocs file describing how interning should work and how to use it.

* Add internal functions to *explicitly* request what kind of interning is done:
  - `_PyUnicode_InternMortal`
  - `_PyUnicode_InternImmortal`
  - `_PyUnicode_InternStatic`

* Switch uses of `PyUnicode_InternInPlace` to those.

* Disallow using `_Py_SetImmortal` on strings directly.
  You should use `_PyUnicode_InternImmortal` instead:
  - Strings should be interned before immortalization, otherwise you're possibly
    interning a immortalizing copy.
  - `_Py_SetImmortal` doesn't handle the `SSTATE_INTERNED_MORTAL` to
    `SSTATE_INTERNED_IMMORTAL` update, and those flags can't be changed in
    backports, as they are now part of public API and version-specific ABI.

* Add private `_only_immortal` argument for `sys.getunicodeinternedsize`, used in refleak test machinery.

* Make sure the statically allocated string singletons are unique. This means these sets are now disjoint:
  - `_Py_ID`
  - `_Py_STR` (including the empty string)
  - one-character latin-1 singletons

  Now, when you intern a singleton, that exact singleton will be interned.

* Add a `_Py_LATIN1_CHR` macro, use it instead of `_Py_ID`/`_Py_STR` for one-character latin-1 singletons everywhere (including Clinic).

* Intern `_Py_STR` singletons at startup.

* For free-threaded builds, intern `_Py_LATIN1_CHR` singletons at startup.

* Beef up the tests. Cover internal details (marked with `@cpython_only`).

* Add lots of assertions

Co-Authored-By: Eric Snow <ericsnowcurrently@gmail.com>
2024-06-21 17:19:31 +02:00
Radislav Chugunov 52586f930f gh-119506: fix _io.TextIOWrapper.write() write during flush (#119507)
Co-authored-by: Inada Naoki <songofacandy@gmail.com>
2024-06-03 16:47:36 +09:00
Victor Stinner 7ca74a760a gh-119661: Add _Py_SINGLETON() include in Argumenet Clinic (#119712)
When the _Py_SINGLETON() is used, Argument Clinic now adds an
explicit "pycore_runtime.h" include to get the macro. Previously, the
macro may or may not be included indirectly by another include.
2024-05-29 11:37:04 +02:00
Brett Simmers c2627d6eea gh-116322: Add Py_mod_gil module slot (#116882)
This PR adds the ability to enable the GIL if it was disabled at
interpreter startup, and modifies the multi-phase module initialization
path to enable the GIL when loading a module, unless that module's spec
includes a slot indicating it can run safely without the GIL.

PEP 703 called the constant for the slot `Py_mod_gil_not_used`; I went
with `Py_MOD_GIL_NOT_USED` for consistency with gh-104148.

A warning will be issued up to once per interpreter for the first
GIL-using module that is loaded. If `-v` is given, a shorter message
will be printed to stderr every time a GIL-using module is loaded
(including the first one that issues a warning).
2024-05-03 11:30:55 -04:00
morotti 8fa1248685 gh-117151: optimize BufferedWriter(), do not buffer writes that are the buffer size (GH-118037)
BufferedWriter() was buffering calls that are the exact same size as the buffer. it's a very common case to read/write in blocks of the exact buffer size.

it's pointless to copy a full buffer, it's costing extra memory copy and the full buffer will have to be written in the next call anyway.

Co-authored-by: rmorotti <romain.morotti@man.com>
2024-04-23 18:51:20 +03:00
Serhiy Storchaka 35f60c3def gh-117764: Add signatures for __reduce__ and __reduce_ex__ in the _io module (GH-117773)
__reduce__() does not have parameters, __reduce_ex__() has a single
parameter.
2024-04-12 12:22:17 +03:00
NGRsoftlab 63d6f2623e gh-117068: Remove useless code in bytesio.c:resize_buffer() (GH-117069)
Co-authored-by: i.khabibulin <i.khabibulin@ngrsoftlab.ru>
2024-03-22 11:25:38 +00:00
AN Long cd2ed91780 gh-115538: Emit warning when use bool as fd in _io.WindowsConsoleIO (GH-116925) 2024-03-18 11:48:50 +00:00
6t8k 26800cf25a gh-95782: Fix io.BufferedReader.tell() etc. being able to return offsets < 0 (GH-99709)
lseek() always returns 0 for character pseudo-devices like
`/dev/urandom` (for other non-regular files, e.g. `/dev/stdin`, it
always returns -1, to which CPython reacts by raising appropriate
exceptions). They are thus technically seekable despite not having seek
semantics.

When calling read() on e.g. an instance of `io.BufferedReader` that
wraps such a file, `BufferedReader` reads ahead, filling its buffer,
creating a discrepancy between the number of bytes read and the internal
`tell()` always returning 0, which previously resulted in e.g.
`BufferedReader.tell()` or `BufferedReader.seek()` being able to return
positions < 0 even though these are supposed to be always >= 0.

Invariably keep the return value non-negative by returning
max(former_return_value, 0) instead, and add some corresponding tests.
2024-02-17 11:16:06 +00:00
Steve Dower 7861dfd26a gh-111140: Adds PyLong_AsNativeBytes and PyLong_FromNative[Unsigned]Bytes functions (GH-114886) 2024-02-12 20:13:13 +00:00
Serhiy Storchaka 846fd721d5 gh-115059: Flush the underlying write buffer in io.BufferedRandom.read1() (GH-115163) 2024-02-09 12:36:12 +02:00
Serhiy Storchaka 652fbf88c4 gh-82626: Emit a warning when bool is used as a file descriptor (GH-111275) 2024-02-05 22:51:11 +02:00
Erlend E. Aasland 09096a1647 gh-115015: Argument Clinic: fix generated code for METH_METHOD methods without params (#115016) 2024-02-05 21:49:17 +01:00
Nikita Sobolev 05e47202a3 gh-114286: Fix maybe-uninitialized warning in Modules/_io/fileio.c (GH-114287) 2024-01-19 10:25:05 +00:00
Jonathon Reinhart e454f9383c Fix an incorrect comment in iobase_is_closed (GH-102952)
This comment appears to have been mistakenly copied from what is now
called iobase_check_closed() in commit 4d9aec0220.

Also unite the iobase_check_closed() code with the relevant comment.

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
2024-01-16 18:27:17 +02:00
Victor Stinner 1d75fa43a2 gh-77046: os.pipe() sets _O_NOINHERIT flag on fds (#113817)
On Windows, set _O_NOINHERIT flag on file descriptors
created by os.pipe() and io.WindowsConsoleIO.

Add test_pipe_spawnl() to test_os.

Co-authored-by: Zackery Spytz <zspytz@gmail.com>
2024-01-10 23:02:17 +01:00
AN Long 623b338adf gh-66060: Use actual class name in _io type's __repr__ (#30824)
Use the object's actual class name in the following _io type's __repr__:
- FileIO
- TextIOWrapper
- _WindowsConsoleIO
2024-01-09 21:39:36 +01:00
Zackery Spytz 73c9326563 gh-80109: Fix io.TextIOWrapper dropping the internal buffer during write() (GH-22535)
io.TextIOWrapper was dropping the internal decoding buffer
during read() and write() calls.
2024-01-08 12:33:34 +02:00
Donghee Na 57b7e52790 gh-112205: Support docstring for @getter (#113160)
---------

Co-authored-by: Erlend E. Aasland <erlend@python.org>
2023-12-20 21:52:12 +09:00
Donghee Na 23a5711100 gh-112205: Update textio module to use @getter as possible. (gh-113095) 2023-12-14 10:26:46 +00:00
Serhiy Storchaka bb36f72efc gh-111049: Fix crash during garbage collection of the BytesIO buffer object (GH-111221) 2023-12-14 10:04:23 +00:00
Donghee Na 498a096a51 gh-112205: Support @setter annotation from AC (gh-112922)
---------

Co-authored-by: Erlend E. Aasland <erlend.aasland@protonmail.com>
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2023-12-13 14:00:34 +00:00