Commit Graph
21 Commits
Author SHA1 Message Date
Seonghun An 33d98d122e Implement negative zero coercion format option (#8475)
Assisted-by: Codex:gpt-5
2026-08-09 14:58:07 +09:00
OkJaandClaude Opus 5 6b554d96c7 Implement fractional grouping in format specs (#8373)
Support the CPython 3.13+ format spec syntax that puts a grouping option
after the precision, so `format(1234.56789, '.6,f')` gives
'1234.567,890'. The integer and fractional parts group independently and
may use different separators (`,.6_f` -> '1,234.567_890'), so the spec
carries a separate `frac_grouping_option`.

`parse_precision` now consumes the separator that follows the precision
digits and rejects a `,`/`_` mix. A repeated separator is deliberately
left in the spec so the trailing-text check reports it, which is how
CPython arrives at a different message there. A dot followed by neither
digits nor a separator now raises "Format specifier missing precision"
rather than an unrelated error.

Fraction digits group away from the decimal point, so the last group may
be short, and any exponent or percent tail is left intact. The
separators count toward the field width, so zero padding of the integer
part reserves room for them.

'n' takes its separators from the locale and so cannot carry one. The
complex locale path rewrites 'n' to 'g' before delegating, so it has to
validate first; that also makes `format(1+2j, ',n')` fail as it does in
CPython, which it previously did not.

Reference (CPython 3.14), Python/formatter_unicode.c:
- parsing: https://github.com/python/cpython/blob/3.14/Python/formatter_unicode.c#L257-L299
- 'n' rejection: https://github.com/python/cpython/blob/3.14/Python/formatter_unicode.c#L361-L367
- number split: https://github.com/python/cpython/blob/3.14/Python/formatter_unicode.c#L488-L516
- zero-pad width: https://github.com/python/cpython/blob/3.14/Python/formatter_unicode.c#L604-L606

Remove `@unittest.expectedFailure` from tests that now pass
(2 in test_format, 1 in test_float).

Assisted-by: Claude:claude-opus-5

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-07-26 14:31:34 +09:00
Jeong, YunWon 40b2da6037 more hostenv isolation (#7886)
* Convert host_env Windows path/argv params from raw *const u16 to &WideCStr

* Migrate remaining winapi raw u16 pointer signatures to typed references

* Migrate winreg pub unsafe fn string parameters to typed references

* Add ToPyException impls for host_env error types (PyPy wrap_oserror analog)

* Add CheckLibcResult helper and apply to socket/fcntl/shm/posix_wasi

* Add Win32 BOOL/HANDLE check helpers; apply check helpers across host_env

* Apply Win32/libc check helpers to overlapped/testconsole/os.rs

* Apply Win32 check helpers to winapi.rs (partial)

* Apply Win32 check helpers across more winapi.rs functions

* Apply Win32 check helpers to nt.rs (partial)

* Add CheckWin32Sentinel helper; apply to nt.rs INVALID_HANDLE_VALUE/INVALID_FILE_ATTRIBUTES patterns

* Add OwnedHandle / HandleToOwned helper; apply to mmap create_named_mapping leak path

* Use OwnedHandle RAII in nt::pipe to eliminate manual cleanup on error path

* Use OwnedHandle in nt::chmod_follow; hoist HandleToOwned import

* Drop rustix dependency from vm crate

Remove unused IntoPyException impl for rustix::io::Errno and the
rustix entry in crates/vm/Cargo.toml. rustix is now only depended on
by host_env.

* Fix CI failures: cross-platform regressions

- winapi.rs: pass None to create_event_w; the recent Option<&WideCStr>
  migration left one call site still passing a raw null pointer.
- exceptions.rs: gate ToPyException for LockfError with
  cfg(any(unix, target_os = "wasi")), matching host_env::fcntl's own
  cfg. The previous cfg let it compile on wasm32-unknown-unknown where
  host_env::fcntl does not exist.
- io_unsupported.rs: derive Eq on FileMode alongside PartialEq to
  satisfy clippy::derive_partial_eq_without_eq.

* Fix CI failures: cfg gates and unused imports

- exceptions.rs: gate ToPyException for LockfError with
  cfg(all(unix, not(target_os = "redox"))) to match the type's own
  cfg in host_env/src/fcntl.rs (LockfError is not built on wasi).
- signal.rs: CheckLibcResult is only used in unix-gated functions;
  split import so it is not pulled in for windows.
- mmap.rs: remove CheckWin32Handle from imports; no longer used after
  switching to HandleToOwned-based RAII.
- overlapped.rs: remove INVALID_HANDLE_VALUE from connect_pipe import;
  the call now uses .check_valid().

* Fix CI failures: rustfmt and windows unused import

- signal.rs: reorder cfg-gated imports per rustfmt.
- socket.rs: gate ToPyException import to cfg(all(unix, not(target_os = "redox")));
  it is only used inside sendmsg which has the same gate, so it was unused
  on windows.

* Push remaining libc/extern callsites from vm into host_env

Add host_env wrappers and replace the corresponding vm call sites:
- host_env::errno::strerror_string for libc::strerror
- host_env::io::write_stderr_raw for libc::write(STDERR_FILENO,...)
- host_env::locale::localeconv_data reused from vm::format
- host_env::os::abort for the inline abort extern
- host_env::os::urandom wraps getrandom; getrandom moves from vm to host_env
- host_env::posix::lchmod for the macOS/BSD lchmod extern
- host_env::posix::fcopyfile for the macOS fcopyfile extern
- host_env::nt::wputenv for the Windows _wputenv extern

vm/format.rs's get_locale_info now uses host_env on both unix and windows
instead of the unix-only libc::localeconv path.

* Move time tz state and winsound FFI into host_env

- host_env::time::tz: wraps the libc tzset/timezone/daylight/tzname
  globals on non-msvc, non-wasm32 targets. vm::stdlib::time now reads
  these via the typed wrappers instead of declaring its own externs.
- host_env::winsound (windows): exposes PlaySoundW (via a typed
  PlaySoundSource enum), Beep, and MessageBeep. vm::stdlib::winsound
  drops its inline FFI block and routes through host_env.

* Migrate unsetenv to host_env::nt::wputenv; rustfmt

- vm::stdlib::os::unsetenv had a second _wputenv call site that still
  referenced the removed inline extern. Route it through
  host_env::nt::wputenv like putenv.
- rustfmt fixups in exceptions.rs (boolean chain layout) and the two
  winsound files.

* Address PR review comments

- host_env::winapi::create_process: assert that the command_line buffer
  is NUL-terminated and that the env block ends with a double-NUL,
  matching the Win32 CreateProcessW contract.
- stdlib::overlapped CreateEvent: replace WideCString::from_str_truncate
  with the fallible from_str(), so embedded NULs in the event name
  surface as ValueError instead of being silently truncated.
- vm::exceptions::ReadlinkError::NotSymbolicLink now maps to OSError
  (matches Win32 ERROR_NOT_A_REPARSE_POINT semantics) rather than
  ValueError.
- winreg::ConnectRegistry: route the non-zero return through the
  existing os_error_from_windows_code helper so the resulting exception
  carries the real winerror/message instead of a generic OSError.

* Fix CI failures and address review follow-ups

CI failures:
- rustfmt cleanup in exceptions.rs after the ReadlinkError change.
- vm/stdlib/os.rs: drop unused ToWideString import that the wputenv
  migration left behind.
- vm/stdlib/winsound.rs: replace explicit `&*buf` with `&buf` to
  satisfy clippy::explicit_auto_deref.
- Lib/test/test_format.py, Lib/test/test_types.py: drop the now-stale
  expectedFailureIfWindows decorators on the locale-format tests; the
  Windows path now reads real `localeconv` data via host_env so these
  tests pass.

Review follow-ups:
- host_env::winapi::create_process: switch the new buffer terminator
  checks from `assert!` to fallible validators returning
  `io::ErrorKind::InvalidInput`, so bad inputs stay recoverable at
  the API boundary.
- host_env::winsound::play_sound: reject `Memory(_)` together with
  `SND_ASYNC` (lifetime-unsafe) and `SND_MEMORY` without a
  `Memory(_)` source. Expand `PlaySoundError` into a variant enum.
- vm::stdlib::_winapi::CreateProcess: route the Win32 path/argv strings
  through `as_wtf8().to_wide_cstring()` like the rest of the Windows
  API surface; `expect_str()` could panic on Python strings containing
  lone surrogates.
2026-05-20 16:16:14 +09:00
Shahar Naveh fca69f5b78 Remove some tests from PLATFORM_INDEPENDENT_TESTS (#7459)
* Remove some platform dependent tests

* Mark failing tests
2026-03-18 21:55:56 +09:00
Jeong, YunWonandgithub-actions[bot] 1bd40ffd86 Implement locale-aware 'n' format specifier for int, float, complex (#7350)
* Implement locale-aware 'n' format specifier for int, float, complex

Add LocaleInfo struct and locale-aware formatting methods to FormatSpec.
The 'n' format type now reads thousands_sep, decimal_point, and grouping
from C localeconv() and applies proper locale-based number grouping.
Remove @unittest.skip from test_format.test_locale.

* Fix complex 'n' format and remove locale expectedFailure markers

Rewrite format_complex_locale to reuse format_complex_re_im, matching
formatter_unicode.c: add_parens=0 and skip_re=0 for 'n' type.
Remove @expectedFailure from test_float__format__locale and
test_int__format__locale in test_types.py.

* Auto-format: cargo fmt --all

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-06 01:09:43 +09:00
ShaharNaveh 5396b9730d Mark failing tests 2026-03-01 10:42:37 +09:00
ShaharNaveh 041da5ba93 Update test_format.py from 3.14.3 2026-03-01 10:42:37 +09:00
yt2b 23a5c82a3a Add separator validation (#5904)
* Add separator validation

* Remove @unittest.expectedFailure
2025-07-06 23:08:07 +09:00
yt2b 0a59c1cad3 Implement PyComplex's __format__ function (#5900)
* Add num-complex in rustpython-common

* Implement PyComplex's __format__ function

* Remove @unittest.expectedFailure

* Fix PyComplex's __format__ function

* Remove @unittest.expectedFailure

* Add extra tests

* Rename to ZeroPadding and AlignmentFlag
2025-07-04 22:35:28 +09:00
Daniel Chiquito 23ebbd021b Skip test_format.test_locale
I had previously `test_locale` as expected to fail, as it did indeed
fail on my system due to unimplemented functionality. As it happens, it
passes in CI because the locale settings used there (`C`, I believe)
just happen to format integers the same with "%d" as "%n".

I mistakenly un-marked it because I thought I misunderstood the problem.
2024-03-10 22:53:39 -04:00
Daniel Chiquito 9b974bda0d Re-enable test_format.test_locale
Technically speaking, my system was misconfigured, leading me to disable
the test in the first place.

`test_locale` calls `locale.setlocale(locale.LC_ALL, '')`, which reads
the value of the `LANG` environment variable and uses that to look up
and reset all the locale settings. My system has `LANG=en_US.UTF-8`,
which is apparently not what this test was expecting. If `LANG` is unset
or set to `C`, the test passes, as it does in CI.
2024-03-10 22:30:41 -04:00
Daniel Chiquito ead42beff6 Disable test_locale in test_format.py
See https://github.com/RustPython/RustPython/issues/5181
2024-03-09 18:22:57 -05:00
Christopher Gambrell d918f7e51b 'n' support for float format (#4865) 2023-04-16 00:06:20 +09:00
Andrey Maltsev 0674aa7d8f Update test_format.py from Cpython v3.11.2 2023-04-02 14:57:54 +00:00
Jim Fasarakis-Hilliard 2c2656dc7a Raise value error on large precision values for float, int __format__ (#3415) 2021-11-05 21:15:49 +02:00
Daniel Watkins 14b4f0092f cformat.rs: fix remaining test_format.test_common_format failures (#3405)
* cformat.rs: refactor fill_string to take fill_with_precision

This allows it to be used with both self.min_field_width and
self.precision, which is necessary for padding out %ds with precision.

* cformat.rs: zero-pad %d entries using precision

This matches CPython's behaviour.

* cformat.rs: don't left-adjust when filling with precision

That will always be prepending 0s to %d arguments, the LEFT_ADJUST flag
will be used by a later call to `fill_string` with the 0-filled string
as the `string` param.

* floats: handle alternate form of general formatting

* cformat.rs: convert width/precision to i32

In CPython, width can be isize but precision can only be i32.  Our
implementation currently assumes the same type for both: as CPython's
tests assert on overflows for precision, but not for width, we use that
size for both.

* test_format: run test_common_format

Except for the line which raises an OverflowError in CPython, because
overflows in Rust (and therefore RustPython) abort the process
immediately.

* test_types: don't expect test_float_to_string to fail

Its string formatting usage now works as expected.
2021-11-05 12:06:58 +02:00
Daniel Watkins c5eba15370 test_format: run test_bytes_and_bytearray_format
All the errors have now been addressed.
2021-11-01 21:34:51 -04:00
Daniel Watkins 380653b6cb cformat.rs: implement %a correctly, using builtins::ascii
The repr() of Unicode strings is the Unicode string, so the previous
code was incorrect for that case (at least).
2021-11-01 21:34:51 -04:00
Padraic Fanning 2c665ff961 Mark erroring/failing tests 2021-02-21 11:31:52 -05:00
Padraic Fanning aecc074cf2 Skip test for chewing up RAM 2021-02-21 11:31:51 -05:00
Padraic Fanning e90491cc7d Add test_format from CPython 3.8.7 2021-02-21 11:31:51 -05:00