Commit Graph
406 Commits
Author SHA1 Message Date
Jeong, YunWon cfee8a7ffa Fix -m argv[0] and file SyntaxError display (#8684)
* Fix -m argv[0] and file SyntaxError display

Set sys.argv[0] to -m for module execution. Convert an escalated
invalid-escape SyntaxWarning into a SyntaxError that spans just
the `\X` pair. Report null bytes in source files with filename,
lineno, and the truncated line.

Enable the four corresponding test_cmd_line_script cases.

Assisted-by: Grok:4.6

* Pass SyntaxError text when escalating escape warnings

Keep the warning and SyntaxError messages as separate strings at
the invalid-escape site. CompileWarningError carries an optional
replacement instead of rewriting the warning text later.

Assisted-by: Grok:4.6

* Remove expectedFailure from bytes invalid-escape test

The invalid-escape SyntaxError path now satisfies
test_eval_bytes_invalid_escape.

Assisted-by: Grok:4.6
2026-09-11 09:54:59 +09:00
cui fliter 521b75ec4a cli: avoid panic when -X int_max_str_digits has no value (#8677)
Signed-off-by: cuishuang <imcusg@gmail.com>
2026-09-10 22:38:19 +09:00
Jeong, YunWon eee9ad6420 Align contextvars, CLI startup, and stat validation with CPython (#8657)
* Align contextvars, CLI startup, and stat validation with CPython

Validate Context and ContextVar arguments and mapping keys, hash names through the Python protocol, and preserve string contents without invoking __str__. Set the main module loader for command and stdin execution, report missing scripts with exit status 2, and reject file descriptors combined with follow_symlinks=False.

Enable the nine corresponding stdlib regression tests.

Assisted-by: Codex:gpt-6

* Move set_main_builtin_importer off the compiler feature

Define the method in vm_new.rs so builds without rustpython-compiler,
such as example_projects/barebone, can compile. Also set BuiltinImporter
on an existing __main__ when its loader is missing or None.

Assisted-by: Grok:4.6
2026-09-06 23:54:30 +09:00
Jeong, YunWon e3bf84d1e7 Fix resource index conversion and REPL warning (#8654)
Accept __index__ values when converting resource limits and only report PyREPL fallback reasons for terminal-backed interactive sessions.

Assisted-by: Codex:gpt-5
2026-09-05 19:49:56 +09:00
Jeong, YunWon 25b5dfe5ca Fix /dev/fd, rlimit, spawn scheduler, and context cache (#8651)
* Fix /dev/fd, rlimit, spawn scheduler, and context cache

Honor PYTHONEXECUTABLE when computing sys.executable.
Rewind the file offset after a pyc magic probe.
Stop masking rlimit values with RLIM_INFINITY.
Print the pyrepl-unavailable warning before the rustyline shell.
Parse posix_spawn scheduler and apply it where the host supports it.
Update ContextVar cache fields under one lock.
Remove expectedFailure and skip markers for tests that now pass.

Assisted-by: Grok:4.6

* address review: check rlim_t overflow on convert

Replace the u64-to-rlim_t as-cast in py2rlim_limit with
a checked try_from, matching py2rlim.

Assisted-by: Grok:4.6
2026-09-05 17:57:29 +09:00
Jeong, YunWon 699913d8cd Align codec, call, exception, and Unix module behavior with CPython (#8647)
* Collect consecutive charmap encoding failures

Pass one contiguous run of unmappable characters to the codec error handler, and use the full run when a text replacement is itself unmappable.

Assisted-by: Codex:gpt-5

* Leave conversions out of standalone format specs

A conversion belongs to a replacement field rather than the format specification consumed by format(), so stop accepting and storing it in FormatSpec.

Assisted-by: Codex:gpt-5

* Decode empty byte strings without looking up a codec

Match PyUnicode_FromEncodedObject by returning the shared empty string before resolving the requested encoding for empty bytes and bytearray inputs.

Assisted-by: Codex:gpt-5

* Validate call shape before converting builtin arguments

Reject unknown keywords and excess arguments before conversions can raise a different error. Align Python-function positional-only handling, use declared list arguments in heapq, keep delegated codecs positional-only, and preserve CPython parameter names and validation order.

Assisted-by: Codex:gpt-5

* Align attribute and exception initialization errors

Give __dict__ and type __qualname__ their CPython diagnostics, preserve OSError filename fields correctly, accept seven-item SyntaxError details, and report Unicode error constructor arity before converting values.

Assisted-by: Codex:gpt-5

* Expose missing Unix and Darwin module APIs

Add the platform constants exported by fcntl, mmap, select, socket, syslog, termios, stat, errno, time, and _sre. Implement posix.killpg and resource.getpagesize, and expose resource.error as OSError.

Assisted-by: Codex:gpt-5

* Honor the configured Python CPU count

Parse -X cpu_count and PYTHON_CPU_COUNT, expose the stored value through sys._get_cpu_count_config, and let os.cpu_count prefer it over the host count. Also publish getsizeof with its CPython parameter name.

Assisted-by: Codex:gpt-5

* Fix CPU count and WASI CI coverage

Remove the obsolete expected-failure marker now that CPU count overrides pass, and avoid exporting FASYNC where WASI libc has no O_ASYNC constant.

Assisted-by: Codex:gpt-5

* self review
2026-09-05 11:34:43 +09:00
Jeong, YunWonandIvan Mironov de6053099a ssl: take the OID table and the OpenSSL cipher-string parser from #8007 (#8646)
* ssl: read the OID table out of OpenSSL's object database

`txt2obj` and `nid2obj` have to answer with OpenSSL's own numbers, and the
table behind them was 39 entries transcribed by hand, so every object
outside that set was reported unknown.

Read OpenSSL's own files instead: `obj_mac.num` carries each object's NID
and `objects.txt` carries its OID, short name and description, and the
identifier `objects.pl` derives per object -- the `!Cname` override, else
the description, else the short name, each qualified by the enclosing
`!module` with `-` spelled `_` -- joins the two.  `OidEntry`, `OidTable`
and the `find_by_*` functions keep their shape, so `ssl.rs` only changes
where an object has no OID to report.

Three details the object database settles that a curated table did not
have to:

- an object written with one name carries it as both, so
  `nid2obj(48)` is `('emailAddress', 'emailAddress', ...)`;
- an object need not have an OID at all -- `DES-EDE3` and 139 other
  algorithm names have a NID and nothing to encode -- so the fourth
  field of the tuple is None for those, as it is on OpenSSL;
- one arc does not encode, since DER packs the first two into a byte,
  so the bare roots `iso` and `itu-t` are OID-less too, while two arcs
  such as X500's `2.5` are a real object.

Checked against `_ssl.nid2obj` on CPython built with OpenSSL, over every
NID it answers: 1387 of its 1390 present, with no disagreement on any of
them, up from 39.  The three absent are OpenSSL's unnamed placeholder
slots, which it reports as ('NULL', 'NULL', None).

The data files come from openssl/openssl `crypto/objects/`, via the
rustls integration rewrite in #8007.

Co-authored-by: Ivan Mironov <mironov.ivan@gmail.com>
Assisted-by: Claude

* ssl: parse OpenSSL cipher strings in set_ciphers

Replaces the pattern matcher `set_ciphers` used with the grammar
`man openssl-ciphers` documents, in a new `ssl/cipher.rs` taken from
#8007: `!`, `-`, `+`, `@STRENGTH`, `@SECLEVEL=n`, `+`-joined
conjunctions, the DEFAULT/ALL/COMPLEMENTOF* groups, protocol versions,
SUITEB*, and the aXXX/kXXX/eXXX prefixes.

`set_ciphers` raises "No cipher can be selected." for a string that
names nothing the provider offers, which is the one failure
SSL_CTX_set_cipher_list reports, and keeps the TLS 1.3 suites selected
in provider order because that setter does not reach them. A SUITEB*
string pins its own key exchange groups, which `prepare_kx_groups`
now reads.

Against CPython's OpenSSL over 78 cipher strings, the selections agree
except under `@SECLEVEL=n`, which OpenSSL applies at handshake time and
this applies to the selection.

`CryptoExt` gains `default_cipher_suites` so that `DEFAULT` and `ALL`
are distinguishable.

Co-authored-by: Ivan Mironov <mironov.ivan@gmail.com>
Assisted-by: Claude

* ssl: finish cipher reporting and provider handling

Use the provider-ordered cipher metadata table as the single source for parsing, reporting, OpenSSL names and descriptions. This makes get_ciphers reflect the context selection and validates curves and Suite B against the active provider.

Keep set_ciphers from changing TLS 1.3 suites, preserve the provider's order, fix empty conjunctions, and keep FIPS initialization within the provider's filtered cipher and key-exchange defaults.

Co-authored-by: Ivan Mironov <mironov.ivan@gmail.com>

Assisted-by: Claude

Assisted-by: CodeRabbit

Assisted-by: OpenAI Codex: GPT-5

* ssl: preserve OpenSSL OID lookup rules

Keep object-name lookup case-sensitive and canonicalize numeric OID arcs before consulting the generated OpenSSL object table.

Assisted-by: OpenAI Codex: GPT-5

* ssl: preserve cleartext after MemoryBIO shutdown

Read at most one TLS record while waiting for close_notify in BIO mode, leaving any post-TLS cleartext queued for the BIO owner.

Co-authored-by: Ivan Mironov <mironov.ivan@gmail.com>

Assisted-by: OpenAI Codex: GPT-5

* ssl: reject empty cipher conjunction operands

Keep empty operands visible to the parser so malformed OpenSSL cipher strings such as AES+ and ALL++AES are rejected instead of normalized.

Assisted-by: CodeRabbit

Assisted-by: OpenAI Codex: GPT-5

* ssl: make Suite B cipher ids unambiguous

Spell out the u16 conversion so Windows-only iterator implementations cannot make collection type inference ambiguous.

Assisted-by: OpenAI Codex: GPT-5

* ssl: move native certificate loading behind host_env

Keep platform trust-store loading and filesystem predicates on the host boundary while exposing backend-neutral certificate bytes to the rustls integration.

Assisted-by: OpenAI Codex: GPT-5

* ssl: invalidate server config after cipher changes

Rebuild cached server configuration after set_ciphers updates the selected suites or Suite B key-exchange groups.

Assisted-by: CodeRabbit

Assisted-by: OpenAI Codex: GPT-5

* ssl: load default certificate sources independently

Honor SSL_CERT_FILE and SSL_CERT_DIR independently. Keep directory certificates as lazy capath candidates, and fall back to native roots only when no environment certificate file was loaded.

Co-authored-by: Ivan Mironov <mironov.ivan@gmail.com>

Assisted-by: OpenAI Codex: GPT-5

---------

Co-authored-by: Ivan Mironov <mironov.ivan@gmail.com>
2026-09-04 22:49:06 +09:00
Jeong, YunWon 7c6c78f955 Implement CPython 3.14 subinterpreter APIs (#8605)
* Add _interpreters and _interpchannels modules

Apply the patch baseline for the low-level subinterpreter modules:

- crates/vm/src/stdlib/_interpreters.rs: create/destroy/list_all/get_main/
  get_current/is_running/exec/call/run_string/run_func/set___main___attrs/
  is_shareable/whence and the Interpreter*Error exceptions
- crates/vm/src/stdlib/_interpchannels.rs: channel create/destroy/send/recv/
  list_all/list_interpreters/release/close and the Channel*Error exceptions
- crates/vm/src/vm/crossinterp.rs: cross-interpreter data protocol
- crates/vm/src/vm/{interpreter,mod,runtime,vm_new}.rs: interpreter registry
  and lifecycle plumbing the modules need
- Lib/concurrent/interpreters/: high-level PEP 734 package

Assisted-by: Claude:claude-opus-5

* Correct _interpreters and _interpchannels against CPython 3.14

Argument matching:
- Add `function::ArgSpec`, a `PyArg_ParseTupleAndKeywords` equivalent that
  applies the `|`, `$` and `:` markers of a format string to a `kwlist`, and
  route every module function of both modules through it. This enforces
  keyword-only parameters, rejects unexpected keywords, accepts keyword forms
  that were previously positional-only (`whence(id=)`, `get_config(id=)`,
  `set___main___attrs(id=, updates=)`, `capture_exception(exc=)`,
  `_register_end_types(send=, recv=)`), and reproduces the arity messages.
- `O!` slots (`shared`, `updates`, `call`'s `args`/`kwargs`) now reject None,
  and `_PyArg_BadArgument` renders None as "None" rather than "NoneType".
- `new_config` takes at most one positional `str`; `list_all` of
  `_interpchannels` is argument-less.
- Convert arguments in `kwlist` order, so an argument's own error is raised
  ahead of the checks that follow it.

_interpreters:
- Add the `CrossInterpreterBufferView` type and build the received memoryview
  on it, keeping the sending interpreter's exporter out of the destination.
- Build `excinfo.errdisplay` from `traceback.TracebackException`.

Feature flags:
- `os.fork` checks finalization before `allow_fork`, matching `os_fork_impl`.
- `_thread.start_new_thread` and `start_joinable_thread` reject an interpreter
  without `allow_threads`.

Lib/concurrent/interpreters/_crossinterp.py: restore the stripped docstrings
and comments.

Assisted-by: Claude:claude-opus-5

* Correct the stateless checks and error shapes of _interpreters against CPython 3.14

verify_stateless_function follows _PyFunction_VerifyStateless: it rejects
non-dict builtins, a non-empty __defaults__, __kwdefaults__ or __closure__,
and code whose LOAD_GLOBAL names are held by the function's globals or
absent from its builtins.

code_returns_only_none follows _PyCode_ReturnsOnlyNone: generator,
coroutine and async-generator code is rejected up front, the instruction
walk skips inline caches and maps specialized and instrumented opcodes
back, and the LOAD_CONST preceding each RETURN_VALUE is compared against
the index of None in co_consts.

ExcInfo::capture keeps an empty exception message instead of dropping it,
and builds `formatted` as `module.qualname: msg`, leaving out the builtins
and __main__ modules.

_interpreters.call packs the callable through _PyFunction_GetXIData before
pickle and re-raises the stateless-check failure when both fail. A func,
args or kwargs that cannot be rebuilt in the target, and a result without
cross-interpreter data, now raise NotShareableError with the snapshot as
the cause rather than being returned as excinfo.

_interpreters.capture_exception() without an argument returns None.

pickle_loads and _PyFunction_GetXIData attach the underlying failure as
__cause__.

channel_send converts the object to cross-interpreter data after the
channel's `closing` check.

ChannelID rich comparison returns the result of comparing its id with the
other number instead of coercing that result to bool.

PyMemoryView_FromObjectAndFlags raises "memoryview: a bytes-like object is
required, not 'X'" for an object that is not a buffer.

Assisted-by: Claude:claude-opus-5

* Correct cross-interpreter data conversion and channel argument parsing

Bound shareable ints by isize, raising OverflowError("try sending as
bytes") outside that range and keeping it as the NotShareableError cause.

Report an unshareable object by its repr, and attach a failing conversion
as __cause__ of the NotShareableError raised for the object it was called
for, so each level of a nested tuple appears in the chain.

Guard each tuple item conversion with with_recursion("while sharing a
tuple").

Gate the memoryview getdata function on `_interpreters` having been
imported, and route channel_send_buffer through a memoryview so it uses
that function and the resolved fallback.

Create the cross-interpreter exception types from the module_exec of
either module that raises them, instead of only `_interpreters`.

parse_cid raises OverflowError("int too big to convert"); int_arg
reproduces the `i` converter's three overflow messages and is also used
while parsing channel_send arguments.

Add BASETYPE to _queue.Empty, and gate nt.execv/nt.execve on allow_exec.

Assisted-by: Claude:claude-opus-5

* Correct interpreter ID parsing and the channel_send defaults lookup

_PyInterpreterState_ObjectToID accepts any object with __index__, raises
OverflowError("int too big to convert") outside the int64 range, and
reports a negative ID with the repr of the original object.

channelsmod_send reads the channel's default unboundop and fallback only
when one of the two arguments is negative, so an explicit pair is
validated before the channel is looked up.

Assisted-by: Claude:claude-opus-5

* Add the _interpqueues module and concurrent.interpreters._queues

_interpqueues holds a process-wide queue table and exposes create,
destroy, list_all, put, get, bind, release, get_maxsize,
get_queue_defaults, is_full, get_count and _register_heap_types, raising
QueueError and QueueNotFoundError.  QueueEmpty and QueueFull, which
subclass queue.Empty and queue.Full, are registered per interpreter by
concurrent.interpreters._queues.

Cross-interpreter data carries a queue as a refcounted queue ID that
binds when the data is captured and releases when it is dropped, and
is_shareable reports a registered Queue as shareable.

Queue and channel items owned by an interpreter are now cleared from
Interpreter::finalize, after module finalization, rather than from
destroy_owned_interpreter, so values sent by an atexit callback also
become unbound.

is_shareable gates memoryview on the same registration flag as the
getdata lookup.

Assisted-by: Claude:claude-opus-5

* Add the high-level concurrent.interpreters API

Interpreter, ExecutionFailed and the queue aliases, copied verbatim from
CPython 3.14.

Assisted-by: Claude:claude-opus-5

* Destroy leftover subinterpreters when the main interpreter finalizes

Interpreter::finalize now runs finalize_subinterpreters between the atexit
handlers and the finalizing flag: when the main interpreter still owns
subinterpreters it emits the RuntimeWarning "remaining subinterpreters;
close them with Interpreter.close()" and then finalizes each of them.

runtime::owned_interpreter_ids lists the runtime-owned interpreters.

Assisted-by: Claude:claude-opus-5

* Absolutize the script path in run_file

_Py_abspath and _PyPathConfig_ComputeSysPath0 arrive as abs_path and
script_sys_path0. run_file hands the absolutized path to get_importer
and to the runner, so __file__ and co_filename no longer stay relative,
and inserts the symlink-resolved script directory as sys.path[0]
instead of the argument's parent.

test_cmd_line_script.test_script_abspath no longer expects a failure.

Assisted-by: Claude:claude-opus-5

* Name types in error messages the way tp_name does

The object, number, sequence and mapping protocols, the
unsupported-operand helpers, and the type-specific messages fed from
them now read PyType::slot_name() where they read PyType::name(),
so a type declared with a module keeps it.

Message texts corrected along the way:
- PySequence_Size, PyMapping_Size, PySequence_GetItem and
  PySequence_SetItem/DelItem split their merged wording in two, and
  PyObject_SetItem/DelItem say "object".
- PyObject_GenericSetAttr reports a read-only attribute and the
  missing __dict__.
- check_class drops the type name it appended.
- __int__ and __index__ drop the class prefix; __float__ keeps it.
- float(), complex(), round(), next(), str subscripting and list
  subscripting take their own wording.
- str.join and bytes.join number the item they turn down and name what
  they wanted, and report a non-iterable as "can only join an
  iterable".

test_class.testObjectAttributeAccessErrorMessages,
string_tests.test_subscript and the test_descrtut doctest no longer
expect a failure.

Assisted-by: Claude:claude-opus-5

* Gate script_code's source compilation on the compiler feature

crossinterp::script_code called vm.compile unconditionally, which only
exists with the rustpython-compiler feature. Builds without it, such as
example_projects/barebone, now raise a TypeError instead of failing to
compile.

Assisted-by: Claude:claude-opus-5

* Skip test_pyinit_function_raises_exception

The test imports _testsinglephase in its body without a decorator
guarding it, and now that _interpreters exists requires_subinterpreters
no longer skips it.

Assisted-by: Claude:claude-opus-5
2026-08-30 13:45:54 +09:00
Jeong, YunWon a7981dccc7 Align compiler futures, annotations, and symtable with CPython (#8550)
* Align compiler futures and annotations with CPython

Handle Barry parsing consistently across AST, type-comment, REPL, and WASM paths. Preserve deferred annotation source and scope metadata, and make _symtable conversion cached and linear-time.

Assisted-by: Codex:gpt-5.4

* Fix f-string debug ranges and update Barry/annotate test expectations

Compute the debug f-string source range from the raw leading and
trailing text instead of the comment-stripped text, so a comment inside
a multi-line replacement field no longer shifts the emitted LOAD_CONST
location.

Restrict the obsolete-operator location shift to `<>` by also requiring
a `>` at the reported offset; without it any `ExpectedExpression` that
followed a `<` (`2 <;`) was reported one column to the left.

Add `CodeFlags::FUTURE_MASK` and use it in builtins, the shell, and the
WASM VM instead of repeating the eight-flag union, and collapse the
duplicated Barry diagnostic sequences into `BarrySource::diagnostic`.

Update the `__annotate__` disassembly snapshot to LOAD_FAST_BORROW and
replace the RustPython-only `barry_as_FLUFL` co_flags assertion in
extra_tests with the CPython-matching one.

Assisted-by: Claude Code:claude-opus-5

* Restore the annotated function in __annotate__ qualnames

Signature annotation scopes are compiled in the scope enclosing the
annotated function, so the function name has to be folded back into the
qualname: `f.__annotate__`, `C.m.__annotate__`,
`outer.<locals>.inner.__annotate__`. test_type_annotations
test_annotate_qualname covers this.

test_pyrepl test_future_barry_as_flufl now passes, so drop its
expectedFailure marker.

Assisted-by: Claude Code:claude-opus-5

* Pass safepoints in the attached-thread interpreter tests

`main_and_subinterpreter_run_sections_overlap` parked its workers on a
condvar while attached, and `busy_main_interpreter_does_not_block_subinterpreter`
looped over protocol calls that never reach a safepoint. An attached
thread that never reaches a safepoint cannot be suspended, so a
concurrent process-wide stop-the-world (from the gc test running in
parallel) never completes and the already-stopped sibling interpreter
stays stopped; the second worker then waits in `wait_while_suspended`
until the 30s deadline.

Both loops now call `vm.check_signals()` each iteration, and the condvar
wait uses `wait_timeout` so the lock is released between safepoints.

Reproduced on Linux (4 CPUs): the two tests with `--test-threads=2`
failed 2/40 before and 0/40 after; the full `rustpython-vm` lib binary
failed 1/30 before and 0/30 after.

Assisted-by: Claude Code:claude-opus-5

* Report the obsolete `<>` operator from one place

`<>` was located twice: `BarrySource` recorded the token ranges it
rewrote to `!=`, and `cpython_parse_diagnostic_override` separately
peeked at the bytes around an `ExpectedExpression` location. Both
produced "invalid syntax" spanning the whole operator.

`prepare_barry_as_flufl_source` now records the operator ranges in the
non-Barry case too -- by plain text search, since nothing is rewritten
there -- so `BarrySource::invalid_legacy_operator` covers both, and the
byte-peeking helper is gone. It also defers to an unclosed bracket
earlier in the source, which the diagnostic chain it used to sit in did
for it.

A `<>` that starts a statement now spans both characters: the parser
stops at the `<` rather than one character in, which the byte peek did
not handle.

Assisted-by: Claude Code:claude-opus-5

* Drop a py object's payload before its class

`PyInner` declares `typ` before `payload`, so `drop_in_place` dropped the
class first and `PyAtomicRef::drop` left it null. A `PyWeak` payload is
still linked into the weakref list of the object it points at until its
own `Drop` unlinks it under the stripe lock, which happens after that.
`WeakRefList::add` walks the same list looking for a proxy to reuse and
reads `node.class()` off every node it passes, so it could dereference
the null class of a node on its way out.

`PyInner::dealloc` now runs the two destructors in the other order at all
three of its exit paths, with a compile-time check that no other field
has one.

Reproduced by the new test in about 0.1s, as the panic CI hit in the
c-api `weakrefobject::tests::new_proxy` run:

  panicked at crates/vm/src/object/ext.rs:312:
  unsafe precondition(s) violated: hint::unreachable_unchecked must
  never be reached

Assisted-by: Claude Code:claude-opus-5
2026-08-20 12:47:36 +09:00
Leesoo Ahn 729fdab88e interpreter: canonicalize when initializing search paths dynamically (#8299)
Dual-Root Mismatch in RustPython:
Unlike CPython, RustPython manages the standard library
in two separate locations in the workspace:
 - Workspace 'Lib/': Contains the test suite ('Lib/test/...') and
   standard library files.
 - crates/pylib/Lib/: A helper directory used for packaging.
   'crates/pylib/Lib' is a symlink pointing to the real workspace '../../Lib/'.

Runtime Directory Discrepancy:
 - 'sys.path' contains 'crates/pylib/Lib' (the path to the symlink).
 - Thus, when 'test.support' is imported, its '__file__' is resolved relative
   to the symlink: '/opt/RustPython/crates/pylib/Lib/test/support/__init__.py'.
 - Consequently, 'STDLIB_DIR' resolves to the symlink root:
   '/opt/RustPython/crates/pylib/Lib'.
 - However, since 'test_program.py' is executed directly from the workspace,
   its 'pkg_dir' is: '/opt/RustPython/Lib/test/test_unittest/testmock'.
 - When 'os.path.relpath(pkg_dir, top_dir)' is called:
   ---
   os.path.relpath(
       "/opt/RustPython/Lib/test/test_unittest/testmock",
       "/opt/RustPython/crates/pylib/Lib"
   )
   # Result: "../../../Lib/test/test_unittest/testmock"
   ---
   Because the relative path starts with '..', the assertion fails.

Assisted-by: Gemini
2026-07-19 13:32:46 +09:00
Bas SchoenmaeckersandJeong YunWon b1cfa575c4 Fix clippy warning (#8249)
* Fix clippy warning

* Fix clippy warnings surfaced by newer clippy

- exceptions.rs: {b:#02x} -> {b:#04x} (unused_format_specs); output
  unchanged for decode-error bytes (always >= 0x80)
- binascii.rs: [b'\r', b'\n'] -> b"\r\n" (byte_str_slice)
- host_env, _io.rs, ssl.rs, pyexpat.rs: expect std_instead_of_core where
  the suggested core::io items (ErrorKind, Cursor) are unstable (core_io);
  use expect so the suppression is flagged for removal once core::io
  stabilizes. build_posix_spawn_attrs co-gates the expect with the cfg
  block so it is not left unfulfilled on platforms compiling it out.

Assisted-by: Claude

* Fix more

---------

Co-authored-by: Jeong YunWon <jeong@youknowone.org>
2026-07-12 12:35:00 +00:00
Jeong, YunWon a1ba6a662c Align compiler and AST behavior with CPython (#8138)
* Align compiler and AST behavior with CPython

Update the compiler pipeline, AST module support, and related VM compile/eval paths toward CPython 3.14 behavior.

Use upstream Ruff parser crates directly and keep RustPython-specific syntax preflight handling in the compile path.

Refresh opcode metadata, snapshots, and targeted tests for the aligned bytecode and AST behavior.

* fix

* Fix PR 8138 CI failures

* Fix match mapping wildcard scan complexity

* fixes

* Use Ruff runtime AST fields

* Minimize residual patch diff

* refactor error handling

* Remove _ast conversion context wrappers

* Clean up _ast conversion glue and compiler warning escalation

Rename the Node conversion parameter `ctx` to `vm` throughout the _ast
module.

Remove the unused compile_program, compile_program_single,
compile_block_expression, and compile_expression forwarders; compile_top
stays as the entry point.

Stash an escalated compiler SyntaxWarning so a non-SyntaxWarning category
propagates unchanged instead of being rewritten to SyntaxError, matching
PyErr_ExceptionMatches(SyntaxWarning) in compiler_warn. Drop the now-unused
CompileWarningError::into_codegen_error.

Replace the PositionalArguments two-variant enum with a struct holding a
shared range and a PositionalArgumentsKind enum.

Assisted-by: Claude

* Represent compiler flags as a CompilerFlags bitflags

Replace the loose PY_CF_*/CO_* i32 constants in compile_mode with a
CompilerFlags bitflags covering the PyCF_* flags and __future__
CO_FUTURE_* bits. The Python-visible ast.PyCF_* attribute values are
derived from it via bits(); parser input modes stay plain consts.

builtins::compile and the compile_string flag handling test flags
through CompilerFlags::contains instead of raw bit math.

Assisted-by: Claude

* Fix PR 8138 test regressions

* Fix PR 8138 CI failures

* Avoid shell interpolation in Linux deps action

* Fix review findings in compiler/AST changes

- frame.rs: compute the MATCH_CLASS class name lazily so a successful
  match no longer takes the type name lock or allocates; the
  __match_args__-not-a-tuple branch reuses it instead of recomputing.
- _ast/constant.rs: add the missing leading space to the with_recursion
  label ("maximum recursion depth exceeded during compilation").
- sys.set_int_max_str_digits: restore the "maxdigits must be 0 or larger
  than {n}" error text.
- codegen: set CO_MAXBLOCKS to 20 in both ir.rs and compile.rs.
- _ast/exception.rs: extract the duplicated excepthandler node guard
  into ensure_excepthandler_node.
- codegen: correct the validate_keywords doc comment.
- Drop redundant "CPython" qualifiers from comments added in this branch.

Assisted-by: Claude
2026-06-26 18:22:08 +09:00
Rory Yorke e65b1fc488 Dedent -c command-line parameter value (#8056) 2026-06-16 15:58:12 +09:00
Shahar Naveh 7da696661b Reduce number of string clones when compiling python source code (#8103) 2026-06-15 11:20:48 +09:00
Shahar Naveh e6b1fd038b Code nitpicks (#8058)
* Code nitpicks

* fix error message

* Use `vm.new_.*_error` methods
2026-06-11 11:40:11 +09:00
Joshua MegnauthandJeong, YunWon f347ae4fbb Support custom rustls providers (#7657)
* Modularize rustls as work towards providers

`rustls`'s architecture is very clean and trait-driven. There are many
providers for `rustls` including the built-in `aws-lc-rs` and `ring` as
well as backends for `boringssl`, `graviola`, `openssl`, `mbedtls`, etc.

This commit removes the hard dependency on `aws-lc-rs` and adds support
for `ring`. It works towards #7059 as well.

* Clean up rustls features

* Remove ring as an explicit feature
* ssl-rustls is the default and implies aws-lc

* Support custom rustls crypto providers

The new feature, `ssl-rustls-no-provider`, enables custom rustls
providers. By default, `aws-lc-rs` is enabled which matches the old
behavior and keeps backward compatibility.

I wrote a new type that abstracts what we need from crypto providers.
CryptoExt encapsulates the ticketer as well as cipher suites and KX
groups. I wrote fallbacks to help select a reasonable default if a
provider is missing features (they all seem to support the same things
though).

I also wrote an example to show how to actually use custom providers.

* Fix duplicate VERIFY_X509 constants and unused imports in ssl module

Remove duplicate VERIFY_X509_STRICT/VERIFY_X509_PARTIAL_CHAIN definitions
from compat.rs (already defined in _ssl module with #[pyattr]).
Remove unused imports: ClientConnection, ServerConnection.

* no-provider as default

* Fix CI failures: openssl build, wasm target, cargo-shear

- Update openssl.rs to use renamed sock_wait/SockWaitKind and add vm parameter
- Add skip_ssl for wasm32-wasip2 target (aws-lc-sys cannot build for wasm)
- Remove unused workspace dependency aws-lc-rs
- Fix foreign-types-shared version to match openssl's dependency (0.1)
- Restore Cargo.lock from upstream/main

---------

Co-authored-by: Jeong, YunWon <jeong@youknowone.org>
2026-05-28 11:07:09 +09:00
Joshua Megnauth d1eec5d168 Const eval all of version.rs (#7923)
`version.rs` essentially consists of constants that can be baked in at
compile time. I moved most of `version.rs` to `build.rs`. The constants
are passed via rustc's environment then stored in the binary.
2026-05-19 21:02:56 +09:00
Bas Schoenmaeckers 4ec52c2e94 Add basic capi error support (#7787)
* Add basic capi error support

* Add missing symbols to make tests compile again

* Add `pyerrors` to dictionary

* Return exception in `Py_GetConstantBorrowed`

* Remove `allow(dead_code)`

* Fix windows

* Load stdlib when calling `Py_InitializeEx`

* Debug tests

* Revert "Load stdlib when calling `Py_InitializeEx`"

This reverts commit bccd38e981.

* Disable tests on windows for now

* Truncate `PyType_GetFlags` to be always 32 bits

* Add test for exception type checking

* Remove subclass type flags

* Use latest pyo3 to make test work on windows

* Revert "Use latest pyo3 to make test work on windows"

This reverts commit b2c2f6913f.

* `set_main_interpreter` -> `init_main_interpreter`
2026-05-13 23:19:58 +09:00
Bas SchoenmaeckersandJeong, YunWon f122e3e12a Add minimal capi lifecycle support (#7648)
* Add minimal capi lifecycle support

* Force enable `threading` on `stdlib`

---------

Co-authored-by: Jeong, YunWon <jeong@youknowone.org>
2026-05-06 02:02:26 +09:00
Noa 6bb84f3e80 Use cfg_select in a bunch more places (#7740) 2026-05-04 20:26:16 +00:00
Shahar Naveh 9c729bc80c Use cfg_select! (#7636) 2026-04-21 17:35:26 +00:00
f51f27c949 Create rustpython-host-env (#7582)
* Create rustpython-host-env crate; move host abstractions out of common

Move os, crt_fd, fileutils, windows, macros modules from
rustpython-common into the new rustpython-host-env crate.
This isolates host OS API wrappers behind a crate boundary
with zero Python runtime dependency.

- Add crates/host_env to workspace
- Drop nix, windows-sys, widestring deps from common
- Wire vm and stdlib to depend on rustpython-host-env
- Migrate all imports from common::{os,crt_fd,fileutils,windows}
  to rustpython_host_env::

* refactor: extract host helpers

Agent-Logs-Url: https://github.com/RustPython/RustPython/sessions/48d1e64d-37ce-409f-b511-8e61a349665c

Co-authored-by: youknowone <69878+youknowone@users.noreply.github.com>

* lint: enforce direct host API boundaries

Agent-Logs-Url: https://github.com/RustPython/RustPython/sessions/97225fb7-7b3d-4197-a77c-eb44aead5b13

Co-authored-by: youknowone <69878+youknowone@users.noreply.github.com>

* refactor: extract remaining host env helpers

Agent-Logs-Url: https://github.com/RustPython/RustPython/sessions/d96f57e1-b196-4460-9983-97d5ff118835

Co-authored-by: youknowone <69878+youknowone@users.noreply.github.com>

* fix: clean extracted host env follow-up

Agent-Logs-Url: https://github.com/RustPython/RustPython/sessions/d96f57e1-b196-4460-9983-97d5ff118835

Co-authored-by: youknowone <69878+youknowone@users.noreply.github.com>

* fix: document env mutation safety

Agent-Logs-Url: https://github.com/RustPython/RustPython/sessions/d96f57e1-b196-4460-9983-97d5ff118835

Co-authored-by: youknowone <69878+youknowone@users.noreply.github.com>

* refactor: split host fs helpers from fileutils

Agent-Logs-Url: https://github.com/RustPython/RustPython/sessions/c57424c5-0e1d-490a-82b3-2d2f6c8cf2cd

Co-authored-by: youknowone <69878+youknowone@users.noreply.github.com>

* fix: resolve latest host env ci regressions

Agent-Logs-Url: https://github.com/RustPython/RustPython/sessions/899eb717-ebc6-4a4a-870c-2a15c5f33e02

Co-authored-by: youknowone <69878+youknowone@users.noreply.github.com>

* fix: resolve remaining windows clippy host fs calls

Agent-Logs-Url: https://github.com/RustPython/RustPython/sessions/12f32740-8173-4b10-a1d6-00b29e90a8ec

Co-authored-by: youknowone <69878+youknowone@users.noreply.github.com>

* host_env

---------

Co-authored-by: Jeong, YunWon <jeong@youknowone.org>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: youknowone <69878+youknowone@users.noreply.github.com>
2026-04-21 00:13:25 +09:00
psycheandEtherealPsyche f5e1f62d47 Expose rustpython_pylib in rustpython (#7498)
Co-authored-by: EtherealPsyche <EtherealPsyche@users.noreply.github.com>
2026-03-24 17:51:01 +09:00
Jeong, YunWon 7311b87c7b Remove PyStr::as_str, use as_wtf8/PyUtf8Str instead (#7218)
- Remove as_str() from PyStr/Py<PyStr> (was panicking on surrogates)
- Add Wtf8Concat trait and concat! macro for WTF-8 formatting
- Add impl From<&str> for &Wtf8 conversion
- Add AsPyStr/DictKey impls for PyUtf8Str types
- Migrate all call sites to as_wtf8(), to_str(), or PyUtf8Str
- Fix exception message APIs to accept Wtf8Buf
- Deduplicate inner-scope imports across modules
2026-02-27 04:20:11 +09:00
Jeong, YunWon ab2876f33c Add missing _winapi functions (#7185)
* Add missing _winapi functions and fix WinHandle int conversion

Add 13 functions: ReadFile, SetNamedPipeHandleState, CreateFileMapping,
OpenFileMapping, MapViewOfFile, UnmapViewOfFile, VirtualQuerySize,
CopyFile2, ResetEvent, CreateMutex, OpenEventW, LoadLibrary,
_mimetypes_read_windows_registry.

Add constants: INVALID_HANDLE_VALUE, FILE_MAP_READ/WRITE/COPY/EXECUTE.

Change WinHandle integer type from usize to isize so negative values
like INVALID_HANDLE_VALUE (-1) can be passed from Python.

* Align _winapi module with CPython

- Rename winapi.rs to _winapi.rs with #[path] attribute
- Rename CreateMutex to CreateMutexW
- Add missing constants: ERROR_ACCESS_DENIED, ERROR_PRIVILEGE_NOT_HELD,
  PROCESS_ALL_ACCESS, 10 STARTF_ constants, LOCALE_NAME_SYSTEM_DEFAULT,
  LOCALE_NAME_USER_DEFAULT, COPY_FILE_DIRECTORY
- Fix OpenMutexW return type and ReleaseMutex param type to use WinHandle

* Fix ReadFile/WriteFile overlapped keyword argument

Use FromArgs structs so overlapped parameter can be passed as
a keyword argument (overlapped=True), matching the CPython API.

* Remove extra constants and LoadLibrary not in CPython _winapi

Remove 19 constants (WAIT_ABANDONED, CREATE_ALWAYS, CREATE_NEW,
OPEN_ALWAYS, TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, 8 FILE_FLAG_*,
3 FILE_SHARE_*, NMPWAIT_NOWAIT, NMPWAIT_USE_DEFAULT_WAIT) and
LoadLibrary function that are not present in CPython's _winapi module.

* Fix utf8_mode default to 0 and add PYTHONUTF8 env var support

Default utf8_mode was incorrectly set to 1, causing text-mode
subprocess to always decode as UTF-8 instead of locale encoding.
Changed default to 0 to match CPython 3.13 behavior on Windows.
Added PYTHONUTF8 environment variable handling with -X utf8 override.

* Fix CopyFile2 to raise proper OSError subclass

Use std::io::Error::from_raw_os_error instead of vm.new_os_error so
that winerror attribute is set and errno-to-exception mapping works
(e.g. ERROR_ACCESS_DENIED → PermissionError).

* Fix syntax_non_utf8 test to not depend on locale encoding

Use explicit encoding='latin-1' so the test works regardless of
the system locale (e.g. C/POSIX locale uses ASCII by default).
2026-02-22 19:54:27 +09:00
Jeong, YunWonandgithub-actions[bot] b877f76141 initial sandbox (#7035)
* Add host_env feature for sandbox isolation

Introduce a `host_env` feature flag that gates all host environment
access (filesystem, network, signals, processes). When disabled,
the VM operates in sandbox mode:

- _io module always available; FileIO gated by host_env
- SandboxStdio provides lightweight stdin/stdout/stderr via Rust std::io
- BytesIO/StringIO/BufferedIO/TextIOWrapper work without host_env
- open() returns UnsupportedOperation in sandbox
- stdlib modules (os, socket, signal, etc.) gated by host_env
- CI checks both host_env ON and OFF builds

* Auto-format: ruff check --select I --fix

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-08 13:58:30 +00:00
Jeong, YunWon 69c280fdaa Merge pull request #6997 from youknowone/test_io
Better codecs and fix lots of test_io and other expectedFailures
2026-02-06 09:04:47 +09:00
Jeong, YunWon 3e6cb83fc5 Fix test_io expectedFailures
Assisted-by: Codex:gpt-6
2026-02-06 00:15:18 +09:00
Jeong, YunWon 654a3eab8c Implement more warnings 2026-02-05 23:50:08 +09:00
Jeong, YunWon 5e732c5e2a Fix wasip2 build (#6935) 2026-02-02 01:26:17 +09:00
Elmir 44c3179ae0 Docs: add reference to rustpython_derive close to example (#6882)
Include a link for native module macros documentation, after an
example where they are used.
2026-01-28 10:25:48 +09:00
Jeong YunWon 20376451eb Implement Py_mod_create slot support in multi-phase init 2026-01-22 11:21:42 +09:00
Jeong YunWon bc02b2318c module_exec 2026-01-21 22:39:40 +09:00
Jeong YunWon fee1a4b097 multiphase 2026-01-21 22:39:39 +09:00
Jeong, YunWon b76906a8bf Add sys._stdlib_dir (#6798) 2026-01-20 03:38:40 +09:00
Jeong, YunWon e8dd5826e6 init warnings before site (#6771) 2026-01-18 19:16:02 +09:00
Jeong, YunWon 96e08a425e Initialize warnings module during interpreter startup to process (#6766) 2026-01-18 13:15:40 +09:00
Jeong, YunWonandCPython Devleopers ca76cb7bb0 thread_inherit_context, upgrade threading & contextvar (#6727)
* thread_inherit_context

* Update contextvar, threading from CPython 3.14.2

* partially patch test_sys to 3.14.2

---------

Co-authored-by: CPython Devleopers <>
2026-01-18 08:53:41 +09:00
Lee Dogeon 0cd6eb7b13 Write profile even if failed (#6685) 2026-01-10 15:26:49 +09:00
Jeong, YunWon e1b22f19e6 vm.run_pyc_bytes (#6645)
* rustpython_vm::import::check_pyc_magic_number_bytes

* vm.new_scope_with_main

* PyCode::from_pyc

* vm.run_pyc_bytes

* add boundary check
2026-01-04 22:58:16 +09:00
Jeong, YunWon bdd036ea6b pythonrun (#6643) 2026-01-04 20:52:35 +09:00
Jeong, YunWon e10dc94992 Fix stdio_encoding, stdio_errors (#6617)
* stdio_errors, stdio_encodings

* add ascii

* unmark tests
2026-01-01 14:48:27 +09:00
Jeong, YunWonandMohamed Gharbi 1e706d911e Interpreter (#6614)
* Refine documentation in interpreter.rs

Improve InterpreterConfig with convenience methods (with_debug, add_path, add_paths), better documentation with working examples, refactored stdlib setup into focused functions, and comprehensive unit tests while maintaining 100% backward compatibility.

* Improve error message for non-Unicode paths

* Use consistent make_module naming in all doc examples

* cut useful changes

---------

Co-authored-by: Mohamed Gharbi <galaxysea777@gmail.com>
2025-12-31 22:14:28 +09:00
Jeong, YunWon e79a1a1a66 Fix traceback (#6569)
* Fix traceback

* Update traceback from CPython 3.13.11

* unmark test_traceback

* fix code

* fix debug range

* fix tests
2025-12-30 16:58:53 +09:00
Terry Tianlin Luan 1464d5ca43 Adding + Fixing Clippy rules to better align with #[no_std] (#6570)
* * Added alloc_instead_of_core, std_instead_of_alloc, and std_instead_of_core clippy rules
* Manually changed part of the code to use core/alloc

* use clippy --fix to fix issues in stdlib

* * Used clippy --fix to fix issues in vm
* Imported Range in vm/src/anystr.rs

* * Used clippy --fix to fix issues in common
2025-12-30 13:10:14 +09:00
Jeong, YunWon 57b4b4ae45 fix sys path (#6537) 2025-12-26 21:43:00 +09:00
Jeong, YunWon 8b3bf558fc Introduce PyConfig to implement Paths correctly (#6461)
* getpath

* introduce PyConfig

* landmark in getpath
2025-12-21 08:25:17 +09:00
Jeong, YunWon 4bec0ad1c6 Fix test_runpy (#6409) 2025-12-12 15:26:00 +09:00
Jeong, YunWon 2ff1fba6ed Faulthandler (#6406) 2025-12-12 09:23:59 +09:00
Jeong, YunWon 04d55fa5c6 Faulthandler (#6400) 2025-12-12 00:08:55 +09:00