Skip to content

Commit 2cd61c5

Browse files
authored
Fix various formatting bugs in errors (#1998)
* Fix various formatting bugs in errors * Obsolete PythonOps.IOError/WindowsError usage * Add internal non-formatting PythonOps.*Error methods * Add test * Fix failing tests * Fix failing tests
1 parent d966863 commit 2cd61c5

21 files changed

Lines changed: 177 additions & 227 deletions

File tree

.editorconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ dotnet_naming_style.pascal_case_style.capitalization = pascal_case
4040
dotnet_style_require_accessibility_modifiers = for_non_interface_members:error
4141
csharp_preferred_modifier_order = public, private, protected, internal, static, extern, new, virtual, abstract, sealed, override, readonly, unsafe, volatile, async:error
4242

43+
# CA2241: Provide correct arguments to formatting methods
44+
dotnet_code_quality.CA2241.try_determine_additional_string_formatting_methods_automatically = true
45+
4346
# IPY01: Parameter which is marked not nullable does not have the NotNullAttribute
4447
dotnet_diagnostic.IPY01.severity = warning
4548

eng/scripts/generate_exceptions.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -265,9 +265,9 @@ def get_clr_name(e):
265265
return e.replace('Error', '') + 'Exception'
266266

267267
FACTORY = """
268-
public static Exception %(name)s(string format, params object?[] args) {
269-
return new %(clrname)s(string.Format(format, args));
270-
}"""
268+
internal static Exception %(name)s(string message) => new %(clrname)s(message);
269+
public static Exception %(name)s(string format, params object?[] args) => new %(clrname)s(string.Format(format, args));
270+
""".rstrip()
271271

272272
def factory_gen(cw):
273273
for e in pythonExcs:

src/core/IronPython.Modules/_ctypes/_ctypes.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ public static PythonTuple buffer_info(CData data) {
317317

318318
public static void _check_HRESULT(int hresult) {
319319
if (hresult < 0) {
320-
throw PythonOps.WindowsError("ctypes function returned failed HRESULT: {0:x}", (uint)hresult);
320+
throw PythonOps.OSError("ctypes function returned failed HRESULT: {0:x}", (uint)hresult);
321321
}
322322
}
323323

@@ -584,12 +584,12 @@ private static void GetFieldInfo(INativeType type, object o, out string fieldNam
584584

585585
fieldName = pt[0] as string;
586586
if (fieldName == null) {
587-
throw PythonOps.TypeError("first item in _fields_ tuple must be a string, got", PythonOps.GetPythonTypeName(pt[0]));
587+
throw PythonOps.TypeError("first item in _fields_ tuple must be a string, got {0}", PythonOps.GetPythonTypeName(pt[0]));
588588
}
589589

590590
cdata = pt[1] as INativeType;
591591
if (cdata == null) {
592-
throw PythonOps.TypeError("second item in _fields_ tuple must be a C type, got {0}", PythonOps.GetPythonTypeName(pt[0]));
592+
throw PythonOps.TypeError("second item in _fields_ tuple must be a C type, got {0}", PythonOps.GetPythonTypeName(pt[1]));
593593
} else if (cdata == type) {
594594
throw StructureCannotContainSelf();
595595
}

src/core/IronPython.Modules/_datetime.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1571,7 +1571,7 @@ public override object fromutc([NotNone] datetime dt) {
15711571
private bool IsUtc => ReferenceEquals(this, utc);
15721572

15731573
public override string tzname(object? dt) {
1574-
if (dt is not null && dt is not datetime) throw PythonOps.TypeError($"tzname(dt) argument must be a datetime instance or None, not {0}", PythonOps.GetPythonTypeName(dt));
1574+
if (dt is not null && dt is not datetime) throw PythonOps.TypeError("tzname(dt) argument must be a datetime instance or None, not {0}", PythonOps.GetPythonTypeName(dt));
15751575
if (_name is not null) return _name;
15761576

15771577
if (IsUtc) return "UTC";

src/core/IronPython.Modules/msvcrt.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public static void SetErrorMode(int mode) {
4949
to the operating system. On failure, this raises IOError.")]
5050
public static void heapmin() {
5151
if (_heapmin() != 0) {
52-
throw PythonOps.IOError(new Win32Exception());
52+
throw PythonOps.OSError(0, "Error");
5353
}
5454
}
5555

@@ -178,7 +178,7 @@ public static void putwch(char @char) {
178178
it will be the next character read by getch() or getche().")]
179179
public static void ungetch(char @char) {
180180
if (_ungetch(@char) == EOF) {
181-
throw PythonOps.IOError(new Win32Exception());
181+
throw PythonOps.OSError(0, "Error");
182182
}
183183
}
184184

@@ -187,7 +187,7 @@ public static void ungetch(char @char) {
187187
Wide char variant of ungetch(), accepting a Unicode value.")]
188188
public static void ungetwch(char @char) {
189189
if (_ungetwch(@char) == WEOF) {
190-
throw PythonOps.IOError(new Win32Exception());
190+
throw PythonOps.OSError(0, "Error");
191191
}
192192
}
193193

src/core/IronPython.Modules/nt.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2233,7 +2233,7 @@ private static FileAccess FileAccessFromFlags(int flags) {
22332233
if (!TryGetExecutableCommand(command, out baseCommand, out args)) {
22342234
if (!TryGetShellCommand(command, out baseCommand, out args)) {
22352235
if (throwException) {
2236-
throw PythonOps.WindowsError("The system can not find command '{0}'", command);
2236+
throw PythonOps.OSError("The system can not find command '{0}'", command);
22372237
} else {
22382238
return null;
22392239
}

src/core/IronPython.Modules/zipimport.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ public Bytes get_data(CodeContext/*!*/ context, string path) {
292292

293293
path = path.Replace(_archive, string.Empty).TrimStart(Path.DirectorySeparatorChar);
294294
if (!__files.ContainsKey(path)) {
295-
throw PythonOps.IOError(path);
295+
throw PythonOps.OSError(path);
296296
}
297297

298298
var data = GetData(context, _archive, __files[path] as PythonTuple);
@@ -394,7 +394,7 @@ private byte[] GetData(CodeContext context, string archive, PythonTuple toc_entr
394394
try {
395395
fp = new BinaryReader(new FileStream(archive, FileMode.Open, FileAccess.Read));
396396
} catch {
397-
throw PythonOps.IOError("zipimport: can not open file {0}", archive);
397+
throw PythonOps.OSError("zipimport: can not open file {0}", archive);
398398
}
399399

400400
// Check to make sure the local file header is correct
@@ -412,7 +412,7 @@ private byte[] GetData(CodeContext context, string archive, PythonTuple toc_entr
412412
try {
413413
raw_data = fp.ReadBytes(compress == 0 ? data_size : data_size + 1);
414414
} catch {
415-
throw PythonOps.IOError("zipimport: can't read data");
415+
throw PythonOps.OSError("zipimport: can't read data");
416416
}
417417

418418
if (compress != 0) {

src/core/IronPython/Modules/_ast.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ internal static PythonAst ConvertToPythonAst(CodeContext codeContext, AST source
6666
stmt = _ast.stmt.RevertStmts(interactive.body);
6767
printExpression = true;
6868
} else
69-
throw PythonOps.TypeError("unsupported type of AST: {0}", (source.GetType()));
69+
throw PythonOps.TypeError("unsupported type of AST: {0}", source.GetType());
7070

7171
return new PythonAst(stmt, false, ModuleOptions.ExecOrEvalCode, printExpression, compilerContext, Array.Empty<int>());
7272
}

src/core/IronPython/Modules/_io.cs

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -435,11 +435,11 @@ internal Exception UnsupportedOperationWithMessage(CodeContext/*!*/ context, str
435435
=> PythonExceptions.CreateThrowable((PythonType)context.LanguageContext.GetModuleState(_unsupportedOperationKey), msg);
436436

437437
internal Exception AttributeError(string attrName) {
438-
throw PythonOps.AttributeError("'{0}' object has no attribute '{1}'", PythonOps.GetPythonTypeName(this), attrName);
438+
return PythonOps.AttributeError("'{0}' object has no attribute '{1}'", PythonOps.GetPythonTypeName(this), attrName);
439439
}
440440

441441
internal Exception InvalidPosition(BigInteger pos) {
442-
return PythonOps.IOError("Raw stream returned invalid position {0}", pos);
442+
return PythonOps.OSError("Raw stream returned invalid position {0}", pos);
443443
}
444444

445445
#endregion
@@ -550,7 +550,7 @@ public virtual BigInteger readinto(CodeContext/*!*/ context, object buf) {
550550
return data.Count;
551551
}
552552

553-
throw PythonOps.TypeError("must be read-write buffer, not " + PythonOps.GetPythonTypeName(buf));
553+
throw PythonOps.TypeError("must be read-write buffer, not {0}", PythonOps.GetPythonTypeName(buf));
554554
}
555555

556556
public override BigInteger write(CodeContext/*!*/ context, object buf) {
@@ -648,11 +648,11 @@ public void __init__(
648648

649649
if (_rawIO != null) {
650650
if (!_rawIO.readable(context)) {
651-
throw PythonOps.IOError("\"raw\" argument must be readable.");
651+
throw PythonOps.OSError("\"raw\" argument must be readable.");
652652
}
653653
} else {
654654
if (PythonOps.Not(PythonOps.Invoke(context, _raw, "readable"))) {
655-
throw PythonOps.IOError("\"raw\" argument must be readable.");
655+
throw PythonOps.OSError("\"raw\" argument must be readable.");
656656
}
657657
}
658658
if (buffer_size <= 0) {
@@ -1125,11 +1125,11 @@ public void __init__(
11251125
this.raw = raw;
11261126
if (_rawIO != null) {
11271127
if (!_rawIO.writable(context)) {
1128-
throw PythonOps.IOError("\"raw\" argument must be writable.");
1128+
throw PythonOps.OSError("\"raw\" argument must be writable.");
11291129
}
11301130
} else {
11311131
if (PythonOps.Not(PythonOps.Invoke(context, _raw, "writable"))) {
1132-
throw PythonOps.IOError("\"raw\" argument must be writable.");
1132+
throw PythonOps.OSError("\"raw\" argument must be writable.");
11331133
}
11341134
}
11351135
if (buffer_size <= 0) {
@@ -1332,7 +1332,7 @@ private void FlushNoLock(CodeContext/*!*/ context) {
13321332

13331333
int written = GetInt(writtenObj, "write() should return integer");
13341334
if (written > _writeBuf.Count || written < 0) {
1335-
throw PythonOps.IOError("write() returned incorrect number of bytes");
1335+
throw PythonOps.OSError("write() returned incorrect number of bytes");
13361336
}
13371337
_writeBuf.RemoveRange(0, written);
13381338
count += written;
@@ -1450,9 +1450,9 @@ public void __init__(
14501450
if (buffer_size <= 0) {
14511451
throw PythonOps.ValueError("invalid buffer size (must be positive)");
14521452
} else if (!raw.readable(context)) {
1453-
throw PythonOps.IOError("\"raw\" argument must be readable.");
1453+
throw PythonOps.OSError("\"raw\" argument must be readable.");
14541454
} else if (!raw.writable(context)) {
1455-
throw PythonOps.IOError("\"raw\" argument must be writable.");
1455+
throw PythonOps.OSError("\"raw\" argument must be writable.");
14561456
}
14571457

14581458
_bufSize = buffer_size;
@@ -1744,7 +1744,7 @@ private void FlushNoLock(CodeContext/*!*/ context) {
17441744
var bytes = Bytes.Make(_writeBuf.ToArray());
17451745
int written = (int)_inner.write(context, bytes);
17461746
if (written > _writeBuf.Count || written < 0) {
1747-
throw PythonOps.IOError("write() returned incorrect number of bytes");
1747+
throw PythonOps.OSError("write() returned incorrect number of bytes");
17481748
}
17491749
_writeBuf.RemoveRange(0, written);
17501750
count += written;
@@ -1792,7 +1792,7 @@ public override BigInteger seek(CodeContext/*!*/ context, BigInteger pos, [Optio
17921792
pos = _inner.seek(context, pos, whence);
17931793
ResetReadBuf();
17941794
if (pos < 0) {
1795-
throw PythonOps.IOError("seek() returned invalid position");
1795+
throw PythonOps.OSError("seek() returned invalid position");
17961796
}
17971797
GC.KeepAlive(this);
17981798
return pos;
@@ -1863,10 +1863,10 @@ public void __init__(
18631863
this.writer = writer;
18641864

18651865
if (!_reader.readable(context)) {
1866-
throw PythonOps.IOError("\"reader\" object must be readable.");
1866+
throw PythonOps.OSError("\"reader\" object must be readable.");
18671867
}
18681868
if (!_writer.writable(context)) {
1869-
throw PythonOps.IOError("\"writer\" object must be writable.");
1869+
throw PythonOps.OSError("\"writer\" object must be writable.");
18701870
}
18711871
}
18721872

@@ -2027,7 +2027,7 @@ public void __init__(
20272027
case "\r\n":
20282028
break;
20292029
default:
2030-
throw PythonOps.ValueError(string.Format("illegal newline value: " + newline));
2030+
throw PythonOps.ValueError("illegal newline value: {0}", newline);
20312031
}
20322032

20332033
encoding ??= context.LanguageContext.PythonOptions.Utf8Mode ? "UTF-8" : PythonLocale.PreferredEncoding;
@@ -2193,10 +2193,10 @@ public override BigInteger write(CodeContext/*!*/ context, object s) {
21932193

21942194
public override BigInteger tell(CodeContext/*!*/ context) {
21952195
if (!_seekable) {
2196-
throw PythonOps.IOError("underlying stream is not seekable");
2196+
throw PythonOps.OSError("underlying stream is not seekable");
21972197
}
21982198
if (!_telling) {
2199-
throw PythonOps.IOError("telling position disabled by next() call");
2199+
throw PythonOps.OSError("telling position disabled by next() call");
22002200
}
22012201

22022202
flush(context);
@@ -2285,7 +2285,7 @@ public override BigInteger tell(CodeContext/*!*/ context) {
22852285
}
22862286

22872287
if (charsDecoded < skip) {
2288-
throw PythonOps.IOError("can't reconstruct logical file position");
2288+
throw PythonOps.OSError("can't reconstruct logical file position");
22892289
}
22902290
break;
22912291
}
@@ -2347,21 +2347,21 @@ public override BigInteger seek(CodeContext/*!*/ context, BigInteger cookie, [Op
23472347
throw PythonOps.ValueError("tell on closed file");
23482348
}
23492349
if (!_seekable) {
2350-
throw PythonOps.IOError("underlying stream is not seekable");
2350+
throw PythonOps.OSError("underlying stream is not seekable");
23512351
}
23522352

23532353
IncrementalNewlineDecoder typedDecoder;
23542354
if (whenceInt == 1) {
23552355
// seek relative to the current position
23562356
if (cookie != 0) {
2357-
throw PythonOps.IOError("can't do nonzero cur-relative seeks");
2357+
throw PythonOps.OSError("can't do nonzero cur-relative seeks");
23582358
}
23592359
whenceInt = 0;
23602360
cookie = tell(context);
23612361
} else if (whenceInt == 2) {
23622362
// seek relative to the end of the stream
23632363
if (cookie != 0) {
2364-
throw PythonOps.IOError("can't do nonzero end-relative seeks");
2364+
throw PythonOps.OSError("can't do nonzero end-relative seeks");
23652365
}
23662366
flush(context);
23672367
BigInteger pos = _bufferTyped != null ?
@@ -2452,7 +2452,7 @@ public override BigInteger seek(CodeContext/*!*/ context, BigInteger cookie, [Op
24522452

24532453
// skip appropriate number of decoded chars
24542454
if (_decodedChars.Length < skip) {
2455-
throw PythonOps.IOError("can't restore logical file position");
2455+
throw PythonOps.OSError("can't restore logical file position");
24562456
}
24572457
_decodedCharsUsed = skip;
24582458
}
@@ -3218,7 +3218,7 @@ private static bool TryGetInt(object? i, out int value) {
32183218
return Bytes.Make(s.MakeByteArray());
32193219
}
32203220

3221-
throw PythonOps.TypeError("'" + name + "' should have returned bytes");
3221+
throw PythonOps.TypeError($"'{name}' should have returned bytes");
32223222
}
32233223

32243224
#nullable restore

src/core/IronPython/Modules/_io/StringIO.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ public void __setstate__(CodeContext context, [NotNone] PythonTuple tuple) {
309309
null => null,
310310
string s => s,
311311
Extensible<string> es => es.Value,
312-
_ => throw PythonOps.TypeError($"newline must be str or None, not {0}", PythonOps.GetPythonTypeName(tuple[1])),
312+
_ => throw PythonOps.TypeError($"newline must be str or None, not {PythonOps.GetPythonTypeName(tuple[1])}"),
313313
};
314314
CheckNewline(context, newline);
315315

0 commit comments

Comments
 (0)