| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 7149d5e commit d9e15a7
5 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -60,6 +60,7 @@ | |||
| 60 | 60 | - Sean Freitag ([@cowboygneox](https://github.com/cowboygneox)) | |
| 61 | 61 | - Serge Weinstock ([@sweinst](https://github.com/sweinst)) | |
| 62 | 62 | - Simon Mourier ([@smourier](https://github.com/smourier)) | |
| 63 | + - Tom Minka ([@tminka](https://github.com/tminka)) | ||
| 63 | 64 | - Viktoria Kovescses ([@vkovec](https://github.com/vkovec)) | |
| 64 | 65 | - Ville M. Vainio ([@vivainio](https://github.com/vivainio)) | |
| 65 | 66 | - Virgil Dupras ([@hsoft](https://github.com/hsoft)) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -42,6 +42,7 @@ details about the cause of the failure | |||
| 42 | 42 | - Made it possible to use `__len__` also on `ICollection<>` interface objects | |
| 43 | 43 | - Made it possible to call `ToString`, `GetHashCode`, and `GetType` on inteface objects | |
| 44 | 44 | - Fixed objects returned by enumerating `PyObject` being disposed too soon | |
| 45 | + - Incorrectly using a non-generic type with type parameters now produces a helpful Python error instead of throwing NullReferenceException | ||
| 45 | 46 | ||
| 46 | 47 | ### Removed | |
| 47 | 48 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -54,7 +54,7 @@ public virtual IntPtr type_subscript(IntPtr idx) | |||
| 54 | 54 | return c.pyHandle; | |
| 55 | 55 | } | |
| 56 | 56 | ||
| 57 | - return Exceptions.RaiseTypeError("no type matches params"); | ||
| 57 | + return Exceptions.RaiseTypeError($"{type.Namespace}.{type.Name} does not accept {types.Length} generic parameters"); | ||
| 58 | 58 | } | |
| 59 | 59 | ||
| 60 | 60 | /// <summary> | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -9,14 +9,13 @@ namespace Python.Runtime | |||
| 9 | 9 | /// This class is responsible for efficiently maintaining the bits | |
| 10 | 10 | /// of information we need to support aliases with 'nice names'. | |
| 11 | 11 | /// </summary> | |
| 12 | - internal class GenericUtil | ||
| 12 | + internal static class GenericUtil | ||
| 13 | 13 | { | |
| 14 | + /// <summary> | ||
| 15 | + /// Maps namespace -> generic base name -> list of generic type names | ||
| 16 | + /// </summary> | ||
| 14 | 17 | private static Dictionary<string, Dictionary<string, List<string>>> mapping; | |
| 15 | 18 | ||
| 16 | - private GenericUtil() | ||
| 17 | - { | ||
| 18 | - } | ||
| 19 | - | ||
| 20 | 19 | public static void Reset() | |
| 21 | 20 | { | |
| 22 | 21 | mapping = new Dictionary<string, Dictionary<string, List<string>>>(); | |
@@ -25,29 +24,23 @@ public static void Reset() | |||
| 25 | 24 | /// <summary> | |
| 26 | 25 | /// Register a generic type that appears in a given namespace. | |
| 27 | 26 | /// </summary> | |
| 27 | + /// <param name="t">A generic type definition (<c>t.IsGenericTypeDefinition</c> must be true)</param> | ||
| 28 | 28 | internal static void Register(Type t) | |
| 29 | 29 | { | |
| 30 | 30 | if (null == t.Namespace || null == t.Name) | |
| 31 | 31 | { | |
| 32 | 32 | return; | |
| 33 | 33 | } | |
| 34 | 34 | ||
| 35 | - Dictionary<string, List<string>> nsmap = null; | ||
| 36 | - mapping.TryGetValue(t.Namespace, out nsmap); | ||
| 37 | - if (nsmap == null) | ||
| 35 | + Dictionary<string, List<string>> nsmap; | ||
| 36 | + if (!mapping.TryGetValue(t.Namespace, out nsmap)) | ||
| 38 | 37 | { | |
| 39 | 38 | nsmap = new Dictionary<string, List<string>>(); | |
| 40 | 39 | mapping[t.Namespace] = nsmap; | |
| 41 | 40 | } | |
| 42 | - string basename = t.Name; | ||
| 43 | - int tick = basename.IndexOf("`"); | ||
| 44 | - if (tick > -1) | ||
| 45 | - { | ||
| 46 | - basename = basename.Substring(0, tick); | ||
| 47 | - } | ||
| 48 | - List<string> gnames = null; | ||
| 49 | - nsmap.TryGetValue(basename, out gnames); | ||
| 50 | - if (gnames == null) | ||
| 41 | + string basename = GetBasename(t.Name); | ||
| 42 | + List<string> gnames; | ||
| 43 | + if (!nsmap.TryGetValue(basename, out gnames)) | ||
| 51 | 44 | { | |
| 52 | 45 | gnames = new List<string>(); | |
| 53 | 46 | nsmap[basename] = gnames; | |
@@ -60,9 +53,8 @@ internal static void Register(Type t) | |||
| 60 | 53 | /// </summary> | |
| 61 | 54 | public static List<string> GetGenericBaseNames(string ns) | |
| 62 | 55 | { | |
| 63 | - Dictionary<string, List<string>> nsmap = null; | ||
| 64 | - mapping.TryGetValue(ns, out nsmap); | ||
| 65 | - if (nsmap == null) | ||
| 56 | + Dictionary<string, List<string>> nsmap; | ||
| 57 | + if (!mapping.TryGetValue(ns, out nsmap)) | ||
| 66 | 58 | { | |
| 67 | 59 | return null; | |
| 68 | 60 | } | |
@@ -75,84 +67,73 @@ public static List<string> GetGenericBaseNames(string ns) | |||
| 75 | 67 | } | |
| 76 | 68 | ||
| 77 | 69 | /// <summary> | |
| 78 | - /// xxx | ||
| 70 | + /// Finds a generic type with the given number of generic parameters and the same name and namespace as <paramref name="t"/>. | ||
| 79 | 71 | /// </summary> | |
| 80 | 72 | public static Type GenericForType(Type t, int paramCount) | |
| 81 | 73 | { | |
| 82 | 74 | return GenericByName(t.Namespace, t.Name, paramCount); | |
| 83 | 75 | } | |
| 84 | 76 | ||
| 85 | - public static Type GenericByName(string ns, string name, int paramCount) | ||
| 86 | - { | ||
| 87 | - foreach (Type t in GenericsByName(ns, name)) | ||
| 88 | - { | ||
| 89 | - if (t.GetGenericArguments().Length == paramCount) | ||
| 90 | - { | ||
| 91 | - return t; | ||
| 92 | - } | ||
| 93 | - } | ||
| 94 | - return null; | ||
| 95 | - } | ||
| 96 | - | ||
| 97 | - public static List<Type> GenericsForType(Type t) | ||
| 98 | - { | ||
| 99 | - return GenericsByName(t.Namespace, t.Name); | ||
| 100 | - } | ||
| 101 | - | ||
| 102 | - public static List<Type> GenericsByName(string ns, string basename) | ||
| 77 | + /// <summary> | ||
| 78 | + /// Finds a generic type in the given namespace with the given name and number of generic parameters. | ||
| 79 | + /// </summary> | ||
| 80 | + public static Type GenericByName(string ns, string basename, int paramCount) | ||
| 103 | 81 | { | |
| 104 | - Dictionary<string, List<string>> nsmap = null; | ||
| 105 | - mapping.TryGetValue(ns, out nsmap); | ||
| 106 | - if (nsmap == null) | ||
| 82 | + Dictionary<string, List<string>> nsmap; | ||
| 83 | + if (!mapping.TryGetValue(ns, out nsmap)) | ||
| 107 | 84 | { | |
| 108 | 85 | return null; | |
| 109 | 86 | } | |
| 110 | 87 | ||
| 111 | - int tick = basename.IndexOf("`"); | ||
| 112 | - if (tick > -1) | ||
| 113 | - { | ||
| 114 | - basename = basename.Substring(0, tick); | ||
| 115 | - } | ||
| 116 | - | ||
| 117 | - List<string> names = null; | ||
| 118 | - nsmap.TryGetValue(basename, out names); | ||
| 119 | - if (names == null) | ||
| 88 | + List<string> names; | ||
| 89 | + if (!nsmap.TryGetValue(GetBasename(basename), out names)) | ||
| 120 | 90 | { | |
| 121 | 91 | return null; | |
| 122 | 92 | } | |
| 123 | 93 | ||
| 124 | - var result = new List<Type>(); | ||
| 125 | 94 | foreach (string name in names) | |
| 126 | 95 | { | |
| 127 | 96 | string qname = ns + "." + name; | |
| 128 | 97 | Type o = AssemblyManager.LookupTypes(qname).FirstOrDefault(); | |
| 129 | - if (o != null) | ||
| 98 | + if (o != null && o.GetGenericArguments().Length == paramCount) | ||
| 130 | 99 | { | |
| 131 | - result.Add(o); | ||
| 100 | + return o; | ||
| 132 | 101 | } | |
| 133 | 102 | } | |
| 134 | 103 | ||
| 135 | - return result; | ||
| 104 | + return null; | ||
| 136 | 105 | } | |
| 137 | 106 | ||
| 138 | 107 | /// <summary> | |
| 139 | 108 | /// xxx | |
| 140 | 109 | /// </summary> | |
| 141 | 110 | public static string GenericNameForBaseName(string ns, string name) | |
| 142 | 111 | { | |
| 143 | - Dictionary<string, List<string>> nsmap = null; | ||
| 144 | - mapping.TryGetValue(ns, out nsmap); | ||
| 145 | - if (nsmap == null) | ||
| 112 | + Dictionary<string, List<string>> nsmap; | ||
| 113 | + if (!mapping.TryGetValue(ns, out nsmap)) | ||
| 146 | 114 | { | |
| 147 | 115 | return null; | |
| 148 | 116 | } | |
| 149 | - List<string> gnames = null; | ||
| 117 | + List<string> gnames; | ||
| 150 | 118 | nsmap.TryGetValue(name, out gnames); | |
| 151 | 119 | if (gnames?.Count > 0) | |
| 152 | 120 | { | |
| 153 | 121 | return gnames[0]; | |
| 154 | 122 | } | |
| 155 | 123 | return null; | |
| 156 | 124 | } | |
| 125 | + | ||
| 126 | + private static string GetBasename(string name) | ||
| 127 | + { | ||
| 128 | + int tick = name.IndexOf("`"); | ||
| 129 | + if (tick > -1) | ||
| 130 | + { | ||
| 131 | + return name.Substring(0, tick); | ||
| 132 | + } | ||
| 133 | + else | ||
| 134 | + { | ||
| 135 | + return name; | ||
| 136 | + } | ||
| 137 | + } | ||
| 157 | 138 | } | |
| 158 | 139 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -745,3 +745,8 @@ def test_nested_generic_class(): | |||
| 745 | 745 | """Check nested generic classes.""" | |
| 746 | 746 | # TODO NotImplemented | |
| 747 | 747 | pass | |
| 748 | + | ||
| 749 | + def test_missing_generic_type(): | ||
| 750 | + from System.Collections import IList | ||
| 751 | + with pytest.raises(TypeError): | ||
| 752 | + IList[bool] | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments