Repository navigation
fix: give the LCB sandbox's fake stdout a binary buffer - #1465
Open
abhishekcpp007 wants to merge 1 commit into
Open
abhishekcpp007 wants to merge 1 commit into
abhishekcpp007 wants to merge 1 commit into
Conversation
`Capturing` swaps sys.stdout for a StringIO while a solution runs, and the grader reads the solution's answer back out of it. A real sys.stdout also exposes a binary `.buffer`, and a StringIO does not, so a correct solution that writes with sys.stdout.buffer.write() raises AttributeError inside the sandbox and is graded as wrong. Writing bytes straight to the buffer is an ordinary fast-output idiom in competitive programming, so the grader was scoring solutions on how they emit their answer rather than on the answer. The fake stdout now carries a `.buffer` that decodes writes into the text stream Capturing reads from, so buffered output lands in the captured result and keeps its order relative to print(). Undecodable bytes are replaced rather than raising, since a grader should not crash on a solution's output. RawIOBase rather than BytesIO is deliberate. BytesIO implements writelines in C against its own buffer, so it bypasses an overridden write and drops that output silently, which would turn a visible AttributeError into a wrong answer that is much harder to notice. Tests cover print(), sys.stdout.write, sys.stdout.writelines and both buffer write paths, plus interleaving, the returned byte count, restoration of the real stdout, and undecodable bytes. This is the output-side counterpart of huggingface#1255, which is about sys.stdin and is already being fixed in huggingface#1257. The two do not overlap.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Capturingswapssys.stdoutfor a plainStringIOwhile a candidate solution runs, and the LCB grader reads the solution's answer back out of it. The realsys.stdoutalso exposes a binary.buffer, and aStringIOdoes not, so a correct solution that writes withsys.stdout.buffer.write(...)raisesAttributeErrorinside the sandbox and is graded as wrong.Writing bytes straight to the buffer is an ordinary fast-output idiom in competitive programming, so the grader was scoring solutions on how they emit their answer rather than on the answer.
Before:
Fix
The fake stdout now carries a
.bufferthat decodes writes into the text streamCapturingreads from, so buffered output lands in the captured result and keeps its order relative toprint(). Undecodable bytes are replaced rather than raising, since a grader should not crash on a solution's output.RawIOBaserather thanBytesIOis deliberate, and it is the part worth reviewing.BytesIOimplementswritelinesin C against its own internal buffer, so it bypasses an overriddenwriteand the output is dropped with no error:That would trade a loud
AttributeErrorfor a quiet wrong answer, which is the worse outcome for a grader.RawIOBaserouteswritelinesthrough the overriddenwrite.Tests
tests/unit/tasks/test_lcb_capturing.pycoversprint(),sys.stdout.write,sys.stdout.writelines, and both buffer write paths. All of them print the same answer and all are required to capture identically. It also covers interleaving of text and binary writes, the byte countwritereturns, restoration of the realsys.stdout, and undecodable bytes.The buffer cases fail on
mainwithAttributeErrorand pass here.Relationship to #1255 and #1257
This is the output-side counterpart of #1255, which reports the same defect on
sys.stdin. That one is already being fixed in #1257, so I have deliberately leftcall_methoduntouched and the two do not overlap. #1257 changescall_method, this changesCapturing, and they add different test files.Closes #1464