* fix: segfault when moving `scoped_ostream_redirect`
The default move constructor left the stream (`std::cout`) pointing at
the moved-from `pythonbuf`, whose internal buffer and streambuf pointers
were nulled by the move. Any subsequent write through the stream
dereferenced null, causing a segfault.
Replace `= default` with an explicit move constructor that re-points
the stream to the new buffer and disarms the moved-from destructor.
* fix: mark move constructor noexcept to satisfy clang-tidy
* fix: use bool flag instead of nullptr sentinel for moved-from state
Using `old == nullptr` as the moved-from sentinel was incorrect because
nullptr is a valid original rdbuf() value (e.g. `std::ostream os(nullptr)`).
Replace with an explicit `active` flag so the destructor correctly
restores nullptr buffers.
Add tests for the nullptr-rdbuf edge case.
* fix: remove noexcept and propagate active flag from source
- Remove noexcept: pythonbuf inherits from std::streambuf whose move
is not guaranteed nothrow on all implementations. Suppress clang-tidy
with NOLINTNEXTLINE instead.
- Initialize active from other.active so that moving an already
moved-from object does not incorrectly re-activate the redirect.
- Only rebind the stream and disarm the source when active.
* test: add unflushed ostream redirect regression
Cover the buffered-before-move case for `scoped_ostream_redirect`, which still crashes despite the current move fix. This gives the PR a direct reproducer for the remaining bug path.
Made-with: Cursor
* fix: disarm moved-from pythonbuf after redirect move
The redirect guard now survives moves, but buffered output could still remain in the moved-from `pythonbuf` and be flushed during destruction through moved-out Python handles. Rebuild the destination put area from the transferred storage and clear the source put area so unflushed bytes follow the active redirect instead of crashing in the moved-from destructor.
Made-with: Cursor
---------
Co-authored-by: Ralf W. Grosse-Kunstleve <rgrossekunst@nvidia.com>
* Apply ruff/flake8-implicit-str-concat rule ISC003
ISC003 Explicitly concatenated string should be implicitly concatenated
* Enforce ruff/flake8-implicit-str-concat rules (ISC)
* Apply ruff/Perflint rule PERF102
PERF102 When using only the values of a dict use the `values()` method
* Apply ruff/Perflint rule PERF401
PERF401 Use a list comprehension to create a transformed list
* Enforce ruff/Perflint rules (PERF)
* Revert "s/windows-2022/windows-latest/ in .github/workflows/{ci,pip}.yml (#5826)"
This reverts commit 852a4b5010.
* Add module-level skip for Windows build >= 26100 in test_iostream.py
* Changes suggested by at-henryiii
* Initial support for GraalPy
* Mark tests that currently fail on GraalPy with xfail
* Add graalpy to CI
* Limit test deps on graalpy to available binary wheels
* Skip cmake test installed_function on GraalPy
CMake won't find libpython on GraalPy, it either fails or silently picks
CPython's libpython.
* Factor out setting function docstrings into a macro
* Try to narrow down skipped tests
* `#error BYE_BYE_GOLDEN_SNAKE`
* Removing everything related to 2.7 from ci.yml
* Commenting-out Centos7
* Removing `PYTHON: 27` from .appveyor.yml
* "PY2" removal, mainly from tests. C++ code is not touched.
* Systematic removal of `u` prefix from `u"..."` and `u'...'` literals. Collateral cleanup of a couple minor other things.
* Cleaning up around case-insensitive hits for `[^a-z]py.*2` in tests/.
* Removing obsolete Python 2 mention in compiling.rst
* Proper `#error` for Python 2.
* Using PY_VERSION_HEX to guard `#error "PYTHON 2 IS NO LONGER SUPPORTED.`
* chore: bump pre-commit
* style: run pre-commit for pyupgrade 3+
* tests: use sys.version_info, not PY
* chore: more Python 2 removal
* Uncommenting Centos7 block (PR #3691 showed that it is working again).
* Update pre-commit hooks
* Fix pre-commit hook
* refactor: remove Python 2 from CMake
* refactor: remove Python 2 from setup code
* refactor: simplify, better static typing
* feat: fail with nice messages
* refactor: drop Python 2 C++ code
* docs: cleanup for Python 3
* revert: intree
revert: intree
* docs: minor touchup to py2 statement
Co-authored-by: Henry Schreiner <henryschreineriii@gmail.com>
Co-authored-by: Aaron Gokaslan <skylion.aaron@gmail.com>
* Apply isort
* Tweak isort config
* Add env.py as a known_first_party
* Add one missing known first party
* Make config compat with older isort versions
* Add another comment
* Revert pyproject setting
* Crash when printing Unicode to redirected cout
Add failing tests
* Fix Unicode crashes redirected cout
* pythonbuf::utf8_remainder check end iterator
* Remove trailing whitespace and formatting iostream
* Avoid buffer overflow if ostream redirect races
This doesn't solve the actual race, but at least it now has a much lower
probability of reading past the end of the buffer even when data races
do occur.