Skip to content
Merged
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
30 changes: 18 additions & 12 deletions Src/IronPython.Modules/winreg.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@

#if FEATURE_REGISTRY

using Microsoft.Win32;
using Microsoft.Win32.SafeHandles;
using System;
using System.Buffers.Binary;
using System.Collections.Concurrent;
using System.ComponentModel;
using System.Diagnostics;
Expand All @@ -22,6 +21,9 @@
using IronPython.Runtime.Exceptions;
using IronPython.Runtime.Types;

using Microsoft.Win32;
using Microsoft.Win32.SafeHandles;

[assembly: PythonModule("winreg", typeof(IronPython.Modules.PythonWinReg), PlatformsAttribute.PlatformFamily.Windows)]
namespace IronPython.Modules {
[SupportedOSPlatform("windows")]
Expand Down Expand Up @@ -70,6 +72,7 @@ public static class PythonWinReg {
public const int REG_FULL_RESOURCE_DESCRIPTOR = 0X9;
public const int REG_RESOURCE_REQUIREMENTS_LIST = 0XA;
public const int REG_QWORD = 0xB;
public const int REG_QWORD_LITTLE_ENDIAN = 0XB;

public const int REG_NOTIFY_CHANGE_NAME = 0X1;
public const int REG_NOTIFY_CHANGE_ATTRIBUTES = 0X2;
Expand Down Expand Up @@ -346,19 +349,22 @@ private static void QueryValueExImpl(SafeRegistryHandle handle, string valueName
break;
case REG_EXPAND_SZ:
case REG_SZ:
if (length >= 2 && data[length - 1] == 0 && data[length - 2] == 0) {
value = ExtractString(data, 0, (int)length - 2);
} else {
value = ExtractString(data, 0, (int)length);
}
var span = MemoryMarshal.Cast<byte, char>(data.AsSpan());
var len = span.IndexOf((char)0);
if (len != -1) span = span.Slice(0, len);
value = span.ToString();
break;
case REG_DWORD:
if (BitConverter.IsLittleEndian) {
value = (uint)((data[3] << 24) | (data[2] << 16) | (data[1] << 8) | data[0]);
} else {
value = (uint)((data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]);
}
var dval = BitConverter.ToUInt32(data, 0);
if (!BitConverter.IsLittleEndian) dval = BinaryPrimitives.ReverseEndianness(dval);
value = dval > int.MaxValue ? (BigInteger)dval : unchecked((int)dval);
break;
case REG_QWORD:
var qval = BitConverter.ToUInt64(data, 0);
if (!BitConverter.IsLittleEndian) qval = BinaryPrimitives.ReverseEndianness(qval);
value = (BigInteger)qval;
break;

default:
value = null;
break;
Expand Down
2 changes: 1 addition & 1 deletion Src/IronPython/Modules/Builtin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public static object __import__(CodeContext/*!*/ context, [NotNone] string name,

object ret = Importer.ImportModule(context, globals, name, from != null && from.Count > 0, level);
if (ret == null) {
var err = PythonOps.ImportError("No module named '{0}'", name);
var err = PythonOps.ModuleNotFoundError("No module named {0}", PythonOps.Repr(context, name));
((PythonExceptions._ImportError)err.GetPythonException()!).name = name;
return LightExceptions.Throw(err);
}
Expand Down
60 changes: 59 additions & 1 deletion Src/IronPython/Modules/unicodedata.cs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,61 @@ public UCD(string version) {
public string unidata_version { get; private set; }

public string lookup(string name) {
return char.ConvertFromUtf32(nameLookup[name]);
if (TryLookup(name, out int code))
return char.ConvertFromUtf32(code);
throw PythonOps.KeyError("undefined character name");
}

private static bool IsUnifiedIdeograph(int code) {
return (0x3400 <= code && code <= 0x4DB5) || // CJK Ideograph Extension A
(0x4E00 <= code && code <= 0x9FEF) || // CJK Ideograph
(0x20000 <= code && code <= 0x2A6D6) || // CJK Ideograph Extension B
(0x2A700 <= code && code <= 0x2B734) || // CJK Ideograph Extension C - 5.2
(0x2B740 <= code && code <= 0x2B81D) || // CJK Ideograph Extension D - 6.0
(0x2B820 <= code && code <= 0x2CEA1) || // CJK Ideograph Extension E - 8.0
(0x2CEB0 <= code && code <= 0x2EBEF) || // CJK Ideograph Extension F - 10.0
(0x30000 <= code && code <= 0x3134A); // CJK Ideograph Extension G - 13.0
}

private bool TryLookup(string name, out int code) {
code = 0;

if (name.StartsWith("CJK UNIFIED IDEOGRAPH-", StringComparison.Ordinal)) {
var val = name.AsSpan(22);
if (val.Length != 4 && val.Length != 5) return false;
foreach (var c in val) {
code *= 16;
switch (c) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
code += c - '0';
break;
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
code += c - 'A' + 10;
break;
default:
code = 0;
return false;
}
}
return IsUnifiedIdeograph(code);

}

return nameLookup.TryGetValue(name, out code);
}

#nullable enable
Expand All @@ -166,6 +220,10 @@ public string name([NotNone] string unichr)
=> TryGetName(GetRune(unichr), out var name) ? name : @default;

internal bool TryGetName(int rune, [NotNullWhen(true)] out string? name) {
if (IsUnifiedIdeograph(rune)) {
name = $"CJK UNIFIED IDEOGRAPH-{rune:X}";
return true;
}
if (TryGetInfo(rune, out CharInfo info, excludeRanges: true)) {
name = info.Name;
return true;
Expand Down
2 changes: 1 addition & 1 deletion Src/IronPython/Runtime/Operations/StringOps.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1217,7 +1217,7 @@ private static void AppendValueForTranslate(this StringBuilder ret, object? mapp
return;
case int mappedInt:
if (mappedInt > 0xFFFF) {
throw PythonOps.TypeError("character mapping must be in range(0x10000)");
throw PythonOps.ValueError("character mapping must be in range(0x10000)");
}
ret.Append((char)mappedInt);
break;
Expand Down
5 changes: 1 addition & 4 deletions Src/IronPythonTest/Cases/CPythonCasesManifest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -1181,7 +1181,7 @@ Ignore=true # blocking
Ignore=true # https://github.com/IronLanguages/ironpython3/issues/1135

[CPython.test_call]
Ignore=true # test_kwargs_order
Ignore=true # test_kwargs_order - https://github.com/IronLanguages/ironpython3/issues/1460

[CPython.test_code_module]
Ignore=true # test_context_tb
Expand Down Expand Up @@ -1261,8 +1261,5 @@ Ignore=true # test_free_after_iterating
[CPython.test_uuid]
Ignore=true # LookupError: unknown encoding: oem - https://github.com/IronLanguages/ironpython3/issues/1451

[CPython.test_winreg]
Ignore=true # 3 failures

[CPython.test_zipapp]
Ignore=true # NotImplementedError: The method or operation is not implemented.
6 changes: 0 additions & 6 deletions Src/IronPythonTest/Cases/IronPythonCasesManifest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -180,12 +180,6 @@ Ignore=true
[IronPython.modules.system_related.test_signal]
Ignore=true # test_doc

[IronPython.test_builtin_stdlib]
Ignore=true # multiple failures

[IronPython.test_codeccallbacks_stdlib]
Ignore=true # multiple failures

[IronPython.test_imp]
Ignore=true # 1 failure

Expand Down
18 changes: 9 additions & 9 deletions Tests/test_builtin_stdlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,18 +79,18 @@ def load_tests(loader, standard_tests, pattern):
suite.addTest(unittest.expectedFailure(test.test_builtin.PtyTests('test_input_tty_non_ascii_unicode_errors')))
if not is_netcoreapp:
suite.addTest(test.test_builtin.ShutdownTest('test_cleanup'))
suite.addTest(test.test_builtin.TestSorted('test_bad_arguments'))
suite.addTest(unittest.expectedFailure(test.test_builtin.TestSorted('test_bad_arguments'))) # AssertionError: TypeError not raised
suite.addTest(test.test_builtin.TestSorted('test_baddecorator'))
suite.addTest(test.test_builtin.TestSorted('test_basic'))
suite.addTest(test.test_builtin.TestSorted('test_inputtypes'))
suite.addTest(test.test_builtin.TestType('test_bad_args'))
suite.addTest(test.test_builtin.TestType('test_bad_slots'))
suite.addTest(test.test_builtin.TestType('test_namespace_order'))
suite.addTest(test.test_builtin.TestType('test_new_type'))
suite.addTest(test.test_builtin.TestType('test_type_doc'))
suite.addTest(test.test_builtin.TestType('test_type_name'))
suite.addTest(test.test_builtin.TestType('test_type_nokwargs'))
suite.addTest(test.test_builtin.TestType('test_type_qualname'))
suite.addTest(unittest.expectedFailure(test.test_builtin.TestType('test_bad_args'))) # AssertionError: TypeError not raised
suite.addTest(unittest.expectedFailure(test.test_builtin.TestType('test_bad_slots'))) # AssertionError: TypeError not raised
suite.addTest(unittest.expectedFailure(test.test_builtin.TestType('test_namespace_order'))) # https://github.com/IronLanguages/ironpython3/issues/1468
suite.addTest(unittest.expectedFailure(test.test_builtin.TestType('test_new_type'))) # AssertionError: <class 'test.test_builtin.B'> is not <class 'int'>
suite.addTest(unittest.expectedFailure(test.test_builtin.TestType('test_type_doc'))) # AssertionError: UnicodeEncodeError not raised
suite.addTest(unittest.expectedFailure(test.test_builtin.TestType('test_type_name'))) # AssertionError: ValueError not raised
suite.addTest(unittest.expectedFailure(test.test_builtin.TestType('test_type_nokwargs'))) # AssertionError: TypeError not raised
suite.addTest(unittest.expectedFailure(test.test_builtin.TestType('test_type_qualname'))) # https://github.com/IronLanguages/ironpython3/issues/30
suite.addTest(doctest.DocTestSuite(builtins))
return suite

Expand Down
8 changes: 4 additions & 4 deletions Tests/test_codeccallbacks_stdlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,22 @@
def load_tests(loader, standard_tests, pattern):
if sys.implementation.name == 'ironpython':
suite = unittest.TestSuite()
suite.addTest(unittest.expectedFailure(test.test_codeccallbacks.CodecCallbackTest('test_backslashescape'))) # UTF-16 vs. UTF-32
suite.addTest(test.test_codeccallbacks.CodecCallbackTest('test_backslashescape'))
suite.addTest(unittest.expectedFailure(test.test_codeccallbacks.CodecCallbackTest('test_badandgoodbackslashreplaceexceptions'))) # UTF-16 vs. UTF-32
suite.addTest(test.test_codeccallbacks.CodecCallbackTest('test_badandgoodignoreexceptions'))
suite.addTest(test.test_codeccallbacks.CodecCallbackTest('test_badandgoodnamereplaceexceptions'))
suite.addTest(unittest.expectedFailure(test.test_codeccallbacks.CodecCallbackTest('test_badandgoodnamereplaceexceptions'))) # https://github.com/IronLanguages/ironpython3/issues/252
suite.addTest(unittest.expectedFailure(test.test_codeccallbacks.CodecCallbackTest('test_badandgoodreplaceexceptions'))) # UTF-16 vs. UTF-32
suite.addTest(test.test_codeccallbacks.CodecCallbackTest('test_badandgoodstrictexceptions'))
suite.addTest(test.test_codeccallbacks.CodecCallbackTest('test_badandgoodsurrogateescapeexceptions'))
suite.addTest(test.test_codeccallbacks.CodecCallbackTest('test_badandgoodsurrogatepassexceptions'))
suite.addTest(unittest.expectedFailure(test.test_codeccallbacks.CodecCallbackTest('test_badandgoodsurrogatepassexceptions'))) # AssertionError: UnicodeEncodeError not raised by surrogatepass_errors
suite.addTest(unittest.expectedFailure(test.test_codeccallbacks.CodecCallbackTest('test_badandgoodxmlcharrefreplaceexceptions'))) # UTF-16 vs. UTF-32
suite.addTest(unittest.expectedFailure(test.test_codeccallbacks.CodecCallbackTest('test_badhandlerresults'))) # TypeError not raised by decode
suite.addTest(test.test_codeccallbacks.CodecCallbackTest('test_badlookupcall'))
suite.addTest(test.test_codeccallbacks.CodecCallbackTest('test_badregistercall'))
suite.addTest(test.test_codeccallbacks.CodecCallbackTest('test_bug828737'))
suite.addTest(unittest.expectedFailure(test.test_codeccallbacks.CodecCallbackTest('test_callbacks'))) # Moving cursor not implemented
suite.addTest(test.test_codeccallbacks.CodecCallbackTest('test_charmapencode'))
suite.addTest(test.test_codeccallbacks.CodecCallbackTest('test_crashing_decode_handler'))
suite.addTest(unittest.expectedFailure(test.test_codeccallbacks.CodecCallbackTest('test_crashing_decode_handler'))) # NotImplementedError: Moving a decoding cursor not implemented yet
suite.addTest(unittest.expectedFailure(test.test_codeccallbacks.CodecCallbackTest('test_decodehelper'))) # Moving cursor not implemented
suite.addTest(test.test_codeccallbacks.CodecCallbackTest('test_decodeunicodeinternal'))
suite.addTest(unittest.expectedFailure(test.test_codeccallbacks.CodecCallbackTest('test_decoding_callbacks'))) # Moving cursor not implemented
Expand Down
7 changes: 1 addition & 6 deletions Tests/test_regressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -1103,12 +1103,7 @@ def test_ipy2_gh357(self):

import unicodedata

if is_cli:
with self.assertRaises(ValueError):
unicodedata.name(u'\u4e2d')
else:
self.assertEqual(unicodedata.name(u'\u4e2d'), 'CJK UNIFIED IDEOGRAPH-4E2D')

self.assertEqual(unicodedata.name(u'\u4e2d'), 'CJK UNIFIED IDEOGRAPH-4E2D')
self.assertRaises(ValueError, unicodedata.decimal, u'\u4e2d')
self.assertEqual(unicodedata.decimal(u'\u4e2d', 0), 0)
self.assertRaises(ValueError, unicodedata.digit, u'\u4e2d')
Expand Down
2 changes: 1 addition & 1 deletion Tests/test_str.py
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,7 @@ def __getitem__(self, idx):
for t in (dict, indexable):
self.assertEqual(u"abcd".translate(t({})), u"abcd")
self.assertEqual(u"abcd".translate(t({ord('a') : ord('A'), ord('b') : None, ord('d') : u"XY"})) , "AcXY")
self.assertRaisesMessage(TypeError, "character mapping must be in range(0x10000)", lambda: 'a'.translate(t({ord('a') : 65536})))
self.assertRaisesMessage(ValueError, "character mapping must be in range(0x10000)", lambda: 'a'.translate(t({ord('a') : sys.maxunicode + 1})))
self.assertRaisesMessage(TypeError, "character mapping must return integer, None or str", lambda: 'a'.translate(t({ord('a') : 2.0})))

class ThrowingIndexable:
Expand Down
2 changes: 1 addition & 1 deletion Tests/test_unicode_stdlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ def load_tests(loader, standard_tests, pattern):
suite.addTest(test.test_unicode.UnicodeTest('test_literals'))
suite.addTest(test.test_unicode.UnicodeTest('test_ljust'))
suite.addTest(unittest.expectedFailure(test.test_unicode.UnicodeTest('test_lower')))
suite.addTest(unittest.expectedFailure(test.test_unicode.UnicodeTest('test_maketrans_translate')))
suite.addTest(test.test_unicode.UnicodeTest('test_maketrans_translate'))
suite.addTest(unittest.expectedFailure(test.test_unicode.UnicodeTest('test_mul')))
suite.addTest(test.test_unicode.UnicodeTest('test_none_arguments'))
suite.addTest(unittest.expectedFailure(test.test_unicode.UnicodeTest('test_partition')))
Expand Down