CONVERSION REFERENCE

File I/O and C ABI

The active converter includes one closed, synchronous profile for bounded whole-file UTF-8 reads and exact UTF-8 writes.

Conversion performs no source-selected I/O. A generated C helper performs the admitted operation only if an external party separately compiles and runs the generated C.

Exact context form

with open(path, 'r', encoding='utf-8', newline='') as handle:
    ...

Each session is one direct, one-item with statement inside a top-level function. open is the unshadowed built-in and the handle is a fresh direct name. Mode is literal 'r' or 'w', encoding is exactly literal 'utf-8', and newline is exactly literal ''. Multiple sessions may occur sequentially when each has a closed one-operation lifecycle and request limits permit them.

Whole-file read

def load(path: str) -> str:
    with open(path, 'r', encoding='utf-8', newline='') as handle:
        return handle.read()

Alternatively, assign zero-argument read() to one fresh direct local, leave the context, and immediately return that value:

def load_named(path: str) -> str:
    with open(path, 'r', encoding='utf-8', newline='') as handle:
        content = handle.read()
    return content

Exact write

def save(path: str, text: str) -> int:
    with open(path, 'w', encoding='utf-8', newline='') as handle:
        handle.write(text)
    return 0

The operand is one already-proved direct string name or a NUL-free string literal. The Python character-count result is deliberately discarded. Generated C writes the exact UTF-8 byte count, borrows the text, closes exactly once, and reports write or close failure.

Composed and sequential sessions

def save_two(first: str, second: str, text: str) -> int:
    with open(first, 'w', encoding='utf-8', newline='') as left:
        left.write(text)
    with open(second, 'w', encoding='utf-8', newline='') as right:
        right.write(text)
    return 0

Closed file sessions compose with ordinary supported control flow before or after them. A file with statement itself remains a direct function-body statement; it is not nested under a conditional or loop.

Rejected file shapes

Generated-C status ABI

Every generated file-effect entry point receives one additional final int64_t *pycf_status parameter. It is hidden from Python, required, non-null, writable, and points to storage owned by the external C caller. The entry null-guards it, initializes it to 0 before source-controlled work, and helpers overwrite it on failure.

The registered helper identities are pycf.file.read_all_utf8_bounded@1.0.0 and pycf.file.write_utf8_exact@1.0.0. Generated symbols are pycf_file_read_all_utf8_bounded_v1 and pycf_file_write_utf8_exact_v1.

StatusMeaningOwnership outcome
0SuccessRead buffer transfers to caller; write owns no result.
1Open failureNo open handle or owned result remains.
2Allocation failureAny partial allocation is released.
3Read failureClose is still attempted exactly once.
4Configured read limit exceededNo oversized result is published.
5Embedded NUL in read contentRead allocation is released.
6Invalid RFC 3629 UTF-8 in read contentRead allocation is released.
7Close failureNo second close is emitted; no read result transfers.
8Exact write failureBorrowed inputs remain caller-owned.

External C caller contract

Pointer boundary. C cannot safely validate an invalid pointer, path bytes beyond the first terminator, or hidden write bytes after the first terminator. Status 5 and 6 validate file bytes read, not borrowed path or write arguments. Source path literals containing NUL reject with PYC3903; write literals containing NUL reject with PYC3905.