diff --git a/CHANGELOG.md b/CHANGELOG.md index da8f94774..387217c76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,6 +51,7 @@ One must now either use enum members (e.g. `MyEnum.Option`), or use enum constru - BREAKING: custom encoders are no longer called for instances of `System.Type` - `PythonException.Restore` no longer clears `PythonException` instance. - Replaced the old `__import__` hook hack with a PEP302-style Meta Path Loader +- BREAKING: Names of .NET types (e.g. `str(__class__)`) changed to better support generic types ### Fixed diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index 8d5600e4f..554858756 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -211,18 +211,7 @@ internal static unsafe PyType CreateType(Type impl) static PyType CreateClass(Type clrType) { - // Cleanup the type name to get rid of funny nested type names. - string name = $"clr.{clrType.FullName}"; - int i = name.LastIndexOf('+'); - if (i > -1) - { - name = name.Substring(i + 1); - } - i = name.LastIndexOf('.'); - if (i > -1) - { - name = name.Substring(i + 1); - } + string name = GetPythonTypeName(clrType); using var baseTuple = GetBaseTypeTuple(clrType); @@ -251,6 +240,65 @@ static PyType CreateClass(Type clrType) return pyType; } + static string GetPythonTypeName(Type clrType) + { + var result = new System.Text.StringBuilder(); + GetPythonTypeName(clrType, target: result); + return result.ToString(); + } + + static void GetPythonTypeName(Type clrType, System.Text.StringBuilder target) + { + if (clrType.IsGenericType) + { + string fullName = clrType.GetGenericTypeDefinition().FullName; + int argCountIndex = fullName.LastIndexOf('`'); + if (argCountIndex >= 0) + { + string nonGenericFullName = fullName.Substring(0, argCountIndex); + string nonGenericName = CleanupFullName(nonGenericFullName); + target.Append(nonGenericName); + + var arguments = clrType.GetGenericArguments(); + target.Append('['); + for (int argIndex = 0; argIndex < arguments.Length; argIndex++) + { + if (argIndex != 0) + { + target.Append(','); + } + + GetPythonTypeName(arguments[argIndex], target); + } + + target.Append(']'); + return; + } + } + + string name = CleanupFullName(clrType.FullName); + target.Append(name); + } + + static string CleanupFullName(string fullTypeName) + { + // Cleanup the type name to get rid of funny nested type names. + string name = "clr." + fullTypeName; + int i = name.LastIndexOf('+'); + if (i > -1) + { + name = name.Substring(i + 1); + } + + i = name.LastIndexOf('.'); + if (i > -1) + { + name = name.Substring(i + 1); + } + + return name; + } + static BorrowedReference InitializeBases(PyType pyType, PyTuple baseTuple) { Debug.Assert(baseTuple.Length() > 0);