Skip to content

Commit 1e07343

Browse files
committed
Merge branch 'master' into 3.6
2 parents 1fe72e5 + 30463ab commit 1e07343

13 files changed

Lines changed: 225 additions & 508 deletions

File tree

Src/IronPython/Lib/iptest/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# The .NET Foundation licenses this file to you under the Apache 2.0 License.
33
# See the LICENSE file in the project root for more information.
44

5-
from .ipunittest import IronPythonTestCase, stdout_trapper, stderr_trapper, path_modifier, retryOnFailure, run_test, skipUnlessIronPython, source_root
5+
from .ipunittest import IronPythonTestCase, stdout_trapper, stderr_trapper, path_modifier, retryOnFailure, run_test, skipUnlessIronPython, source_root, expectedFailureIf
66
from .test_env import *
77
from .type_util import *
88
from .misc_util import ip_supported_encodings

Src/IronPython/Lib/iptest/ipunittest.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,15 @@ def skipUnlessIronPython():
5353
"""Skips the test unless currently running on IronPython"""
5454
return unittest.skipUnless(is_cli, 'IronPython specific test')
5555

56+
def expectedFailureIf(condition):
57+
"""The test is marked as an expectedFailure if the condition is satisfied."""
58+
def wrapper(func):
59+
if condition:
60+
return unittest.expectedFailure(func)
61+
else:
62+
return func
63+
return wrapper
64+
5665
MAX_FAILURE_RETRY = 3
5766
def retryOnFailure(f, times=MAX_FAILURE_RETRY, *args, **kwargs):
5867
'''

Src/IronPython/Runtime/Exceptions/PythonExceptions.cs

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ public partial class _OSError {
129129
errno = WinErrorToErrno(winerror);
130130
}
131131
}
132-
cls = ErrnoToPythonType((Error)errno);
132+
cls = ErrnoToPythonType(ErrnoToErrorEnum(errno));
133133
}
134134
return Activator.CreateInstance(cls.UnderlyingSystemType, cls);
135135
}
@@ -183,25 +183,26 @@ public override void __init__(params object[] args) {
183183
}
184184

185185
private enum Error {
186+
UNSPECIFIED = -1,
186187
EPERM = 1,
187188
ENOENT = 2,
188189
ESRCH = 3,
189190
EINTR = 4,
190191
ECHILD = 10,
191-
EAGAIN = 11,
192+
EAGAIN = 11, // 35 on OSX
192193
EACCES = 13,
193194
EEXIST = 17,
194195
ENOTDIR = 20,
195196
EISDIR = 21,
196197
EPIPE = 32,
197198
// Linux
198-
ECONNABORTED = 103,
199-
ECONNRESET = 104,
200-
ESHUTDOWN = 108,
201-
ETIMEDOUT = 110,
202-
ECONNREFUSED = 111,
203-
EALREADY = 114,
204-
EINPROGRESS = 115,
199+
ECONNABORTED = 103, // 53 on OSX
200+
ECONNRESET = 104, // 54 on OSX
201+
ESHUTDOWN = 108, // 58 on OSX
202+
ETIMEDOUT = 110, // 60 on OSX
203+
ECONNREFUSED = 111, // 61 on OSX
204+
EALREADY = 114, // 37 on OSX
205+
EINPROGRESS = 115, // 36 on OSX
205206
// Windows
206207
WSAEWOULDBLOCK = 10035,
207208
WSAEINPROGRESS = 10036,
@@ -213,6 +214,14 @@ private enum Error {
213214
WSAECONNREFUSED = 10061,
214215
}
215216

217+
private static Error ErrnoToErrorEnum(int errno) {
218+
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) {
219+
if (errno == 11) return Error.UNSPECIFIED; // EAGAIN on Linux/Windows but EDEADLK on OSX, which is not being remapped
220+
if (errno >= 35) errno += 10000; // add WSABASEERR to map to Windows error range
221+
}
222+
return (Error)errno;
223+
}
224+
216225
private static PythonType ErrnoToPythonType(Error errno) {
217226
var res = errno switch
218227
{
@@ -229,10 +238,10 @@ private static PythonType ErrnoToPythonType(Error errno) {
229238
Error.EPIPE => BrokenPipeError,
230239
_ => null
231240
};
232-
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
241+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) {
233242
res ??= errno switch
234243
{
235-
// Windows
244+
// Windows or remapped OSX
236245
Error.WSAEWOULDBLOCK => BlockingIOError,
237246
Error.WSAEINPROGRESS => BlockingIOError,
238247
Error.WSAEALREADY => BlockingIOError,
@@ -243,8 +252,7 @@ private static PythonType ErrnoToPythonType(Error errno) {
243252
Error.WSAECONNREFUSED => ConnectionRefusedError,
244253
_ => null
245254
};
246-
} else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) {
247-
// TODO: verify that these are the same on OSX
255+
} else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) {
248256
res ??= errno switch
249257
{
250258
// Linux

Src/IronPython/Runtime/FormattingHelper.cs

Lines changed: 18 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,46 @@
1-
/* ****************************************************************************
2-
*
3-
* Copyright (c) Microsoft Corporation.
4-
*
5-
* This source code is subject to terms and conditions of the Apache License, Version 2.0. A
6-
* copy of the license can be found in the License.html file at the root of this distribution. If
7-
* you cannot locate the Apache License, Version 2.0, please send an email to
8-
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
9-
* by the terms of the Apache License, Version 2.0.
10-
*
11-
* You must not remove this notice, or any other, from this software.
12-
*
13-
*
14-
* ***************************************************************************/
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
3+
// See the LICENSE file in the project root for more information.
154

165
using System;
17-
using System.Collections.Generic;
186
using System.Globalization;
19-
using System.Linq;
207
using System.Text;
218
using System.Threading;
229

23-
namespace IronPython.Runtime
24-
{
25-
internal static class FormattingHelper
26-
{
27-
private static NumberFormatInfo _invariantCommaSeperatorInfo;
10+
namespace IronPython.Runtime {
11+
internal static class FormattingHelper {
12+
private static NumberFormatInfo _invariantUnderscoreSeperatorInfo;
2813

2914
/// <summary>
3015
/// Helper NumberFormatInfo for use by int/BigInteger __format__ routines
31-
/// for width specified leading zero support that contains ','s every 3 digits.
16+
/// for width specified leading zero support that contains '_'s every 3 digits.
3217
/// i.e. For use by d/g/G format specifiers. NOT for use by n format specifiers.
3318
/// </summary>
34-
public static NumberFormatInfo InvariantCommaNumberInfo {
19+
public static NumberFormatInfo InvariantUnderscoreNumberInfo {
3520
get {
36-
if (_invariantCommaSeperatorInfo == null) {
21+
if (_invariantUnderscoreSeperatorInfo == null) {
3722
Interlocked.CompareExchange(
38-
ref _invariantCommaSeperatorInfo,
39-
new NumberFormatInfo()
40-
{
41-
NumberGroupSeparator = ",",
23+
ref _invariantUnderscoreSeperatorInfo,
24+
new NumberFormatInfo() {
25+
NumberGroupSeparator = "_",
4226
NumberDecimalSeparator = ".",
43-
NumberGroupSizes = new int[] {3}
27+
NumberGroupSizes = new int[] { 3 }
4428
},
4529
null
4630
);
4731
}
48-
return _invariantCommaSeperatorInfo;
32+
return _invariantUnderscoreSeperatorInfo;
4933
}
5034
}
5135

52-
public static string/*!*/ ToCultureString<T>(T/*!*/ val, NumberFormatInfo/*!*/ nfi, StringFormatSpec spec) {
36+
public static string/*!*/ ToCultureString<T>(T/*!*/ val, NumberFormatInfo/*!*/ nfi, StringFormatSpec spec, int? overrideWidth = null) {
5337
string separator = nfi.NumberGroupSeparator;
5438
int[] separatorLocations = nfi.NumberGroupSizes;
5539
string digits = val.ToString();
5640

5741
// If we're adding leading zeros, we need to know how
5842
// many we need.
59-
int width = spec.Width ?? 0;
43+
int width = overrideWidth ?? spec.Width ?? 0;
6044
int fillerLength = Math.Max(width - digits.Length, 0);
6145
bool addLeadingZeros = (spec.Fill ?? '\0') == '0' && width > digits.Length;
6246
int beginningOfDigits = fillerLength;
@@ -127,12 +111,10 @@ public static NumberFormatInfo InvariantCommaNumberInfo {
127111
break;
128112
}
129113
}
130-
}
131-
else {
114+
} else {
132115
res.Remove(0, beginningOfMaximumWidth);
133116
}
134-
}
135-
else {
117+
} else {
136118
// If we ran out of remainingWidth just formatting
137119
// the actual digits, then remove any extra leading zeros
138120
// we added.

Src/IronPython/Runtime/NewStringFormatter.cs

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,11 @@
1-
/* ****************************************************************************
2-
*
3-
* Copyright (c) Microsoft Corporation.
4-
*
5-
* This source code is subject to terms and conditions of the Apache License, Version 2.0. A
6-
* copy of the license can be found in the License.html file at the root of this distribution. If
7-
* you cannot locate the Apache License, Version 2.0, please send an email to
8-
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
9-
* by the terms of the Apache License, Version 2.0.
10-
*
11-
* You must not remove this notice, or any other, from this software.
12-
*
13-
*
14-
* ***************************************************************************/
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
3+
// See the LICENSE file in the project root for more information.
154

165
using System;
176
using System.Collections.Generic;
187
using System.Text;
19-
using System.Diagnostics;
208

21-
using Microsoft.Scripting;
229
using Microsoft.Scripting.Runtime;
2310
using Microsoft.Scripting.Utils;
2411

Src/IronPython/Runtime/Operations/BigIntegerOps.cs

Lines changed: 22 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -742,10 +742,8 @@ public static BigInteger ToBigInteger(BigInteger self) {
742742
throw PythonOps.ValueError("Precision not allowed in integer format specifier");
743743
}
744744

745-
BigInteger val = self;
746-
if (self < 0) {
747-
val = -self;
748-
}
745+
BigInteger val = self.Abs();
746+
749747
string digits;
750748

751749
switch (spec.Type) {
@@ -758,84 +756,50 @@ public static BigInteger ToBigInteger(BigInteger self) {
758756
goto case 'd';
759757
}
760758

761-
digits = FormattingHelper.ToCultureString(val, context.LanguageContext.NumericCulture.NumberFormat, spec);
759+
if (spec.Fill == '0' && spec.Width > 1) {
760+
digits = FormattingHelper.ToCultureString(val, culture.NumberFormat, spec, (spec.Sign != null && spec.Sign != '-' || self < 0) ? spec.Width - 1 : null);
761+
}
762+
else {
763+
digits = FormattingHelper.ToCultureString(val, culture.NumberFormat, spec);
764+
}
762765
break;
763766
case null:
764767
case 'd':
765-
if (spec.ThousandsComma) {
766-
var width = spec.Width ?? 0;
768+
if (spec.ThousandsComma || spec.ThousandsUnderscore) {
769+
var numberFormat = spec.ThousandsUnderscore ? FormattingHelper.InvariantUnderscoreNumberInfo : CultureInfo.InvariantCulture.NumberFormat;
770+
767771
// If we're inserting commas, and we're padding with leading zeros.
768772
// AlignNumericText won't know where to place the commas,
769-
// so force .Net to help us out here.
770-
if (spec.Fill.HasValue && spec.Fill.Value == '0' && width > 1) {
771-
digits = val.ToString(FormattingHelper.ToCultureString(self, FormattingHelper.InvariantCommaNumberInfo, spec));
773+
// so use FormattingHelper.ToCultureString for that support.
774+
if (spec.Fill == '0' && spec.Width > 1) {
775+
digits = FormattingHelper.ToCultureString(val, numberFormat, spec, (spec.Sign != null && spec.Sign != '-' || self < 0) ? spec.Width - 1 : null);
776+
} else {
777+
digits = val.ToString("#,0", numberFormat);
772778
}
773-
else {
774-
digits = val.ToString("#,0", CultureInfo.InvariantCulture);
775-
}
776-
}
777-
else {
779+
} else {
778780
digits = val.ToString("D", CultureInfo.InvariantCulture);
779781
}
780782
break;
781783
case '%':
782-
if (spec.ThousandsComma) {
783-
digits = val.ToString("#,0.000000%", CultureInfo.InvariantCulture);
784-
} else {
785-
digits = val.ToString("0.000000%", CultureInfo.InvariantCulture);
786-
}
787-
break;
788784
case 'e':
789-
if (spec.ThousandsComma) {
790-
digits = val.ToString("#,0.000000e+00", CultureInfo.InvariantCulture);
791-
} else {
792-
digits = val.ToString("0.000000e+00", CultureInfo.InvariantCulture);
793-
}
794-
break;
795785
case 'E':
796-
if (spec.ThousandsComma) {
797-
digits = val.ToString("#,0.000000E+00", CultureInfo.InvariantCulture);
798-
} else {
799-
digits = val.ToString("0.000000E+00", CultureInfo.InvariantCulture);
800-
}
801-
break;
802786
case 'f':
803787
case 'F':
804-
if (spec.ThousandsComma) {
805-
digits = val.ToString("#,########0.000000", CultureInfo.InvariantCulture);
806-
} else {
807-
digits = val.ToString("#########0.000000", CultureInfo.InvariantCulture);
808-
}
809-
break;
810788
case 'g':
811-
if (val >= 1000000) {
812-
digits = val.ToString("0.#####e+00", CultureInfo.InvariantCulture);
813-
} else if (spec.ThousandsComma) {
814-
goto case 'd';
815-
} else {
816-
digits = val.ToString(CultureInfo.InvariantCulture);
817-
}
818-
break;
819789
case 'G':
820-
if (val >= 1000000) {
821-
digits = val.ToString("0.#####E+00", CultureInfo.InvariantCulture);
822-
} else if (spec.ThousandsComma) {
823-
goto case 'd';
824-
} else {
825-
digits = val.ToString(CultureInfo.InvariantCulture);
826-
}
790+
digits = DoubleOps.DoubleToFormatString(context, ToDouble(val), spec);
827791
break;
828792
case 'X':
829-
digits = AbsToHex(val, false);
793+
digits = AbsToHex(val, lowercase: false);
830794
break;
831795
case 'x':
832-
digits = AbsToHex(val, true);
796+
digits = AbsToHex(val, lowercase: true);
833797
break;
834798
case 'o': // octal
835-
digits = ToOctal(val, true);
799+
digits = ToOctal(val, lowercase: true);
836800
break;
837801
case 'b': // binary
838-
digits = ToBinary(val, false, true);
802+
digits = ToBinary(val, includeType: false, lowercase: true);
839803
break;
840804
case 'c': // single char
841805
int iVal;

Src/IronPython/Runtime/Operations/FloatOps.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -813,7 +813,7 @@ public static string __format__(CodeContext/*!*/ context, double self, [NotNone]
813813
/// <summary>
814814
/// Returns the digits for the format spec, no sign is included.
815815
/// </summary>
816-
private static string DoubleToFormatString(CodeContext/*!*/ context, double self, StringFormatSpec/*!*/ spec) {
816+
internal static string DoubleToFormatString(CodeContext/*!*/ context, double self, StringFormatSpec/*!*/ spec) {
817817
self = Math.Abs(self);
818818
const int DefaultPrecision = 6;
819819
int precision = spec.Precision ?? DefaultPrecision;

0 commit comments

Comments
 (0)