Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions graalpython/com.oracle.graal.python.test/src/tests/test_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,12 @@ def test_stringio_overwrite(self):
s.write('ab')
self.assertEqual('heabo', s.getvalue())

def test_stringio_validates_newline_before_initial_value(self):
self.assertRaises(ValueError, _io.StringIO, b'', 'x')
self.assertRaises(ValueError, _io.StringIO, 1, 'x')
self.assertRaises(TypeError, _io.StringIO, b'')
self.assertEqual('', _io.StringIO(None).getvalue())

def test_cr_not_ignored(self):
d = _io.IncrementalNewlineDecoder(None, translate=False)
d.decode("h\rello")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
import static com.oracle.graal.python.builtins.modules.io.IONodes.T_READLINE;
import static com.oracle.graal.python.builtins.modules.io.TextIOWrapperNodes.validateNewline;
import static com.oracle.graal.python.nodes.ErrorMessages.CAN_T_DO_NONZERO_CUR_RELATIVE_SEEKS;
import static com.oracle.graal.python.nodes.ErrorMessages.INITIAL_VALUE_MUST_BE_STR_OR_NONE_NOT_P;
import static com.oracle.graal.python.nodes.ErrorMessages.INVALID_WHENCE_D_SHOULD_BE_0_1_OR_2;
import static com.oracle.graal.python.nodes.ErrorMessages.IO_CLOSED;
import static com.oracle.graal.python.nodes.ErrorMessages.IO_UNINIT;
Expand Down Expand Up @@ -116,11 +117,13 @@
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryClinicBuiltinNode;
import com.oracle.graal.python.nodes.function.builtins.PythonTernaryBuiltinNode;
import com.oracle.graal.python.nodes.function.builtins.PythonTernaryClinicBuiltinNode;
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
import com.oracle.graal.python.nodes.function.builtins.clinic.ArgumentClinicProvider;
import com.oracle.graal.python.nodes.object.BuiltinClassProfiles.IsBuiltinObjectExactProfile;
import com.oracle.graal.python.nodes.object.GetOrCreateDictNode;
import com.oracle.graal.python.nodes.util.CannotCastException;
import com.oracle.graal.python.nodes.util.CastToTruffleStringNode;
import com.oracle.graal.python.runtime.object.PFactory;
import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
Expand Down Expand Up @@ -280,17 +283,11 @@ static PStringIO doNew(Object cls, @SuppressWarnings("unused") Object arg,

@Slot(value = SlotKind.tp_init, isComplex = true)
@SlotSignature(name = "StringIO", minNumOfPositionalArgs = 1, parameterNames = {"$self", "initial_value", "newline"})
@ArgumentClinic(name = "initial_value", conversion = ArgumentClinic.ClinicConversion.TString, defaultValue = "T_EMPTY_STRING", useDefaultForNone = true)
@GenerateNodeFactory
public abstract static class InitNode extends PythonTernaryClinicBuiltinNode {

@Override
protected ArgumentClinicProvider getArgumentClinic() {
return StringIOBuiltinsClinicProviders.InitNodeClinicProviderGen.INSTANCE;
}
public abstract static class InitNode extends PythonTernaryBuiltinNode {

@Specialization
static PNone init(VirtualFrame frame, PStringIO self, TruffleString initialValue, Object newlineArg,
static PNone init(VirtualFrame frame, PStringIO self, Object initialValueArg, Object newlineArg,
@Bind Node inliningTarget,
@Cached PRaiseNode lazyRaiseNode,
@Cached IncrementalNewlineDecoderBuiltins.DecodeNode decodeNode,
Expand All @@ -303,6 +300,7 @@ static PNone init(VirtualFrame frame, PStringIO self, TruffleString initialValue
@Cached TruffleStringBuilder.ToStringNode toStringNode,
@Cached TruffleStringBuilder.AppendCodePointNode appendCodePointNode,
@Cached IONodes.ToTruffleStringNode toTruffleStringNode,
@Cached CastToTruffleStringNode castToStringNode,
@Bind PythonLanguage language,
@Cached PRaiseNode raiseNode) {
TruffleString newline;
Expand All @@ -318,6 +316,16 @@ static PNone init(VirtualFrame frame, PStringIO self, TruffleString initialValue
if (newline != null) {
validateNewline(newline, inliningTarget, lazyRaiseNode, codePointLengthNode, codePointAtIndexNode);
}
TruffleString initialValue;
if (PGuards.isPNone(initialValueArg)) {
initialValue = T_EMPTY_STRING;
} else {
try {
initialValue = castToStringNode.execute(inliningTarget, initialValueArg);
} catch (CannotCastException e) {
throw raiseNode.raise(inliningTarget, TypeError, INITIAL_VALUE_MUST_BE_STR_OR_NONE_NOT_P, initialValueArg);
}
}
self.setOK(false);
self.clearAll();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -999,6 +999,7 @@ public abstract class ErrorMessages {
public static final TruffleString INPUT_FMT_NOT_SUPPORTED_BY_DECODER = tsLiteral("Input format not supported by decoder");
public static final TruffleString INVALID_UNSUPPORTED_OPTIONS = tsLiteral("Invalid or unsupported options");
public static final TruffleString INDENT_MUST_BE_STR_OR_NONE_NOT_P = tsLiteral("indent must be str or None, not %p");
public static final TruffleString INITIAL_VALUE_MUST_BE_STR_OR_NONE_NOT_P = tsLiteral("initial_value must be str or None, not %p");
public static final TruffleString CORRUPT_INPUT_DATA = tsLiteral("Corrupt input data");
public static final TruffleString INSUFFICIENT_BUFFER_SPACE = tsLiteral("Insufficient buffer space");
public static final TruffleString INTERNAL_ERROR = tsLiteral("Internal error");
Expand Down