| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
10 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2,5 +2,5 @@ | |||
| 2 | 2 | using System.Runtime.CompilerServices; | |
| 3 | 3 | ||
| 4 | 4 | [assembly: InternalsVisibleTo("Python.EmbeddingTest, PublicKey=00240000048000009400000006020000002400005253413100040000110000005ffd8f49fb44ab0641b3fd8d55e749f716e6dd901032295db641eb98ee46063cbe0d4a1d121ef0bc2af95f8a7438d7a80a3531316e6b75c2dae92fb05a99f03bf7e0c03980e1c3cfb74ba690aca2f3339ef329313bcc5dccced125a4ffdc4531dcef914602cd5878dc5fbb4d4c73ddfbc133f840231343e013762884d6143189")] | |
| 5 | - [assembly: AssemblyVersion("2.0.1")] | ||
| 6 | - [assembly: AssemblyFileVersion("2.0.1")] | ||
| 5 | + [assembly: AssemblyVersion("2.0.2")] | ||
| 6 | + [assembly: AssemblyFileVersion("2.0.2")] | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -6,7 +6,7 @@ | |||
| 6 | 6 | <RootNamespace>Python.Runtime</RootNamespace> | |
| 7 | 7 | <AssemblyName>Python.Runtime</AssemblyName> | |
| 8 | 8 | <PackageId>QuantConnect.pythonnet</PackageId> | |
| 9 | - <Version>2.0.1</Version> | ||
| 9 | + <Version>2.0.2</Version> | ||
| 10 | 10 | <GenerateAssemblyInfo>false</GenerateAssemblyInfo> | |
| 11 | 11 | <PackageLicenseFile>LICENSE</PackageLicenseFile> | |
| 12 | 12 | <RepositoryUrl>https://github.com/pythonnet/pythonnet</RepositoryUrl> | |
@@ -65,5 +65,6 @@ | |||
| 65 | 65 | <PackageReference Include="System.Security.Permissions" Version="4.4.0" /> | |
| 66 | 66 | <PackageReference Include="System.Reflection.Emit" Version="4.3.0" /> | |
| 67 | 67 | <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" /> | |
| 68 | + <PackageReference Include="fasterflect" Version="3.0.0" /> | ||
| 68 | 69 | </ItemGroup> | |
| 69 | 70 | </Project> | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -70,7 +70,7 @@ internal static void Initialize() | |||
| 70 | 70 | // lets wait until all assemblies are loaded | |
| 71 | 71 | do | |
| 72 | 72 | { | |
| 73 | - if (safeCount++ > 200) | ||
| 73 | + if (safeCount++ > 400) | ||
| 74 | 74 | { | |
| 75 | 75 | throw new TimeoutException("Timeout while waiting for assemblies to load"); | |
| 76 | 76 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -31,9 +31,13 @@ internal CLRObject(object ob, IntPtr tp) | |||
| 31 | 31 | pyHandle = py; | |
| 32 | 32 | inst = ob; | |
| 33 | 33 | ||
| 34 | - // Fix the BaseException args (and __cause__ in case of Python 3) | ||
| 35 | - // slot if wrapping a CLR exception | ||
| 36 | - Exceptions.SetArgsAndCause(py); | ||
| 34 | + // for performance before calling SetArgsAndCause() lets check if we are an exception | ||
| 35 | + if (inst is Exception) | ||
| 36 | + { | ||
| 37 | + // Fix the BaseException args (and __cause__ in case of Python 3) | ||
| 38 | + // slot if wrapping a CLR exception | ||
| 39 | + Exceptions.SetArgsAndCause(py); | ||
| 40 | + } | ||
| 37 | 41 | } | |
| 38 | 42 | ||
| 39 | 43 | protected CLRObject() | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -84,7 +84,19 @@ internal static PyObject TryEncode(object obj, Type type) | |||
| 84 | 84 | if (obj == null) throw new ArgumentNullException(nameof(obj)); | |
| 85 | 85 | if (type == null) throw new ArgumentNullException(nameof(type)); | |
| 86 | 86 | ||
| 87 | - foreach (var encoder in clrToPython.GetOrAdd(type, GetEncoders)) | ||
| 87 | + if (clrToPython.Count == 0) | ||
| 88 | + { | ||
| 89 | + return null; | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | + IPyObjectEncoder[] availableEncoders; | ||
| 93 | + if (!clrToPython.TryGetValue(type, out availableEncoders)) | ||
| 94 | + { | ||
| 95 | + availableEncoders = GetEncoders(type); | ||
| 96 | + clrToPython[type] = availableEncoders; | ||
| 97 | + } | ||
| 98 | + | ||
| 99 | + foreach (var encoder in availableEncoders) | ||
| 88 | 100 | { | |
| 89 | 101 | var result = encoder.TryEncode(obj); | |
| 90 | 102 | if (result != null) return result; | |
@@ -93,8 +105,8 @@ internal static PyObject TryEncode(object obj, Type type) | |||
| 93 | 105 | return null; | |
| 94 | 106 | } | |
| 95 | 107 | ||
| 96 | - static readonly ConcurrentDictionary<Type, IPyObjectEncoder[]> | ||
| 97 | - clrToPython = new ConcurrentDictionary<Type, IPyObjectEncoder[]>(); | ||
| 108 | + static readonly Dictionary<Type, IPyObjectEncoder[]> clrToPython = new(); | ||
| 109 | + | ||
| 98 | 110 | static IPyObjectEncoder[] GetEncoders(Type type) | |
| 99 | 111 | { | |
| 100 | 112 | lock (encoders) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,97 @@ | |||
| 1 | + using System; | ||
| 2 | + using System.Collections.Generic; | ||
| 3 | + | ||
| 4 | + using Fasterflect; | ||
| 5 | + | ||
| 6 | + namespace Python.Runtime | ||
| 7 | + { | ||
| 8 | + public static class FasterflectManager | ||
| 9 | + { | ||
| 10 | + private static Dictionary<Type, bool> _isValueTypeCache = new(); | ||
| 11 | + private static Dictionary<string, MemberGetter> _memberGetterCache = new(); | ||
| 12 | + private static Dictionary<string, MemberSetter> _memberSetterCache = new(); | ||
| 13 | + | ||
| 14 | + public static bool IsValueType(Type type) | ||
| 15 | + { | ||
| 16 | + bool isValueType; | ||
| 17 | + if (_isValueTypeCache.TryGetValue(type, out isValueType)) | ||
| 18 | + { | ||
| 19 | + return isValueType; | ||
| 20 | + } | ||
| 21 | + | ||
| 22 | + isValueType = type.IsValueType; | ||
| 23 | + _isValueTypeCache[type] = isValueType; | ||
| 24 | + | ||
| 25 | + return isValueType; | ||
| 26 | + } | ||
| 27 | + | ||
| 28 | + public static MemberGetter GetPropertyGetter(Type type, string propertyName) | ||
| 29 | + { | ||
| 30 | + var cacheKey = GetCacheKey(type, propertyName); | ||
| 31 | + | ||
| 32 | + MemberGetter memberGetter; | ||
| 33 | + if (_memberGetterCache.TryGetValue(cacheKey, out memberGetter)) | ||
| 34 | + { | ||
| 35 | + return memberGetter; | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + memberGetter = type.DelegateForGetPropertyValue(propertyName); | ||
| 39 | + _memberGetterCache[cacheKey] = memberGetter; | ||
| 40 | + | ||
| 41 | + return memberGetter; | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | + public static MemberSetter GetPropertySetter(Type type, string propertyName) | ||
| 45 | + { | ||
| 46 | + var cacheKey = GetCacheKey(type, propertyName); | ||
| 47 | + | ||
| 48 | + MemberSetter memberSetter; | ||
| 49 | + if (_memberSetterCache.TryGetValue(cacheKey, out memberSetter)) | ||
| 50 | + { | ||
| 51 | + return memberSetter; | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + memberSetter = type.DelegateForSetPropertyValue(propertyName); | ||
| 55 | + _memberSetterCache[cacheKey] = memberSetter; | ||
| 56 | + | ||
| 57 | + return memberSetter; | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + public static MemberGetter GetFieldGetter(Type type, string fieldName) | ||
| 61 | + { | ||
| 62 | + var cacheKey = GetCacheKey(type, fieldName); | ||
| 63 | + | ||
| 64 | + MemberGetter memberGetter; | ||
| 65 | + if (_memberGetterCache.TryGetValue(cacheKey, out memberGetter)) | ||
| 66 | + { | ||
| 67 | + return memberGetter; | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + memberGetter = type.DelegateForGetFieldValue(fieldName); | ||
| 71 | + _memberGetterCache[cacheKey] = memberGetter; | ||
| 72 | + | ||
| 73 | + return memberGetter; | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + public static MemberSetter GetFieldSetter(Type type, string fieldName) | ||
| 77 | + { | ||
| 78 | + var cacheKey = GetCacheKey(type, fieldName); | ||
| 79 | + | ||
| 80 | + MemberSetter memberSetter; | ||
| 81 | + if (_memberSetterCache.TryGetValue(cacheKey, out memberSetter)) | ||
| 82 | + { | ||
| 83 | + return memberSetter; | ||
| 84 | + } | ||
| 85 | + | ||
| 86 | + memberSetter = type.DelegateForSetFieldValue(fieldName); | ||
| 87 | + _memberSetterCache[cacheKey] = memberSetter; | ||
| 88 | + | ||
| 89 | + return memberSetter; | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | + private static string GetCacheKey(Type type, string memberName) | ||
| 93 | + { | ||
| 94 | + return $"{type} {memberName}"; | ||
| 95 | + } | ||
| 96 | + } | ||
| 97 | + } | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,6 +1,8 @@ | |||
| 1 | 1 | using System; | |
| 2 | 2 | using System.Reflection; | |
| 3 | 3 | ||
| 4 | + using Fasterflect; | ||
| 5 | + | ||
| 4 | 6 | namespace Python.Runtime | |
| 5 | 7 | { | |
| 6 | 8 | using MaybeFieldInfo = MaybeMemberInfo<FieldInfo>; | |
@@ -12,6 +14,15 @@ internal class FieldObject : ExtensionType | |||
| 12 | 14 | { | |
| 13 | 15 | private MaybeFieldInfo info; | |
| 14 | 16 | ||
| 17 | + private MemberGetter _memberGetter; | ||
| 18 | + private Type _memberGetterType; | ||
| 19 | + | ||
| 20 | + private MemberSetter _memberSetter; | ||
| 21 | + private Type _memberSetterType; | ||
| 22 | + | ||
| 23 | + private bool _isValueType; | ||
| 24 | + private Type _isValueTypeType; | ||
| 25 | + | ||
| 15 | 26 | public FieldObject(FieldInfo info) | |
| 16 | 27 | { | |
| 17 | 28 | this.info = info; | |
@@ -49,7 +60,16 @@ public static IntPtr tp_descr_get(IntPtr ds, IntPtr ob, IntPtr tp) | |||
| 49 | 60 | } | |
| 50 | 61 | try | |
| 51 | 62 | { | |
| 52 | - result = info.GetValue(null); | ||
| 63 | + // Fasterflect does not support constant fields | ||
| 64 | + if (info.IsLiteral && !info.IsInitOnly) | ||
| 65 | + { | ||
| 66 | + result = info.GetValue(null); | ||
| 67 | + } | ||
| 68 | + else | ||
| 69 | + { | ||
| 70 | + result = self.GetMemberGetter(info.DeclaringType)(info.DeclaringType); | ||
| 71 | + } | ||
| 72 | + | ||
| 53 | 73 | return Converter.ToPython(result, info.FieldType); | |
| 54 | 74 | } | |
| 55 | 75 | catch (Exception e) | |
@@ -67,7 +87,18 @@ public static IntPtr tp_descr_get(IntPtr ds, IntPtr ob, IntPtr tp) | |||
| 67 | 87 | Exceptions.SetError(Exceptions.TypeError, "instance is not a clr object"); | |
| 68 | 88 | return IntPtr.Zero; | |
| 69 | 89 | } | |
| 70 | - result = info.GetValue(co.inst); | ||
| 90 | + | ||
| 91 | + // Fasterflect does not support constant fields | ||
| 92 | + if (info.IsLiteral && !info.IsInitOnly) | ||
| 93 | + { | ||
| 94 | + result = info.GetValue(co.inst); | ||
| 95 | + } | ||
| 96 | + else | ||
| 97 | + { | ||
| 98 | + var type = co.inst.GetType(); | ||
| 99 | + result = self.GetMemberGetter(type)(self.IsValueType(type) ? co.inst.WrapIfValueType() : co.inst); | ||
| 100 | + } | ||
| 101 | + | ||
| 71 | 102 | return Converter.ToPython(result, info.FieldType); | |
| 72 | 103 | } | |
| 73 | 104 | catch (Exception e) | |
@@ -137,11 +168,29 @@ public static IntPtr tp_descr_get(IntPtr ds, IntPtr ob, IntPtr tp) | |||
| 137 | 168 | Exceptions.SetError(Exceptions.TypeError, "instance is not a clr object"); | |
| 138 | 169 | return -1; | |
| 139 | 170 | } | |
| 140 | - info.SetValue(co.inst, newval); | ||
| 171 | + | ||
| 172 | + // Fasterflect does not support constant fields | ||
| 173 | + if (info.IsLiteral && !info.IsInitOnly) | ||
| 174 | + { | ||
| 175 | + info.SetValue(co.inst, newval); | ||
| 176 | + } | ||
| 177 | + else | ||
| 178 | + { | ||
| 179 | + var type = co.inst.GetType(); | ||
| 180 | + self.GetMemberSetter(type)(self.IsValueType(type) ? co.inst.WrapIfValueType() : co.inst, newval); | ||
| 181 | + } | ||
| 141 | 182 | } | |
| 142 | 183 | else | |
| 143 | 184 | { | |
| 144 | - info.SetValue(null, newval); | ||
| 185 | + // Fasterflect does not support constant fields | ||
| 186 | + if (info.IsLiteral && !info.IsInitOnly) | ||
| 187 | + { | ||
| 188 | + info.SetValue(null, newval); | ||
| 189 | + } | ||
| 190 | + else | ||
| 191 | + { | ||
| 192 | + self.GetMemberSetter(info.DeclaringType)(info.DeclaringType, newval); | ||
| 193 | + } | ||
| 145 | 194 | } | |
| 146 | 195 | return 0; | |
| 147 | 196 | } | |
@@ -160,5 +209,38 @@ public static IntPtr tp_repr(IntPtr ob) | |||
| 160 | 209 | var self = (FieldObject)GetManagedObject(ob); | |
| 161 | 210 | return Runtime.PyString_FromString($"<field '{self.info}'>"); | |
| 162 | 211 | } | |
| 212 | + | ||
| 213 | + private MemberGetter GetMemberGetter(Type type) | ||
| 214 | + { | ||
| 215 | + if (type != _memberGetterType) | ||
| 216 | + { | ||
| 217 | + _memberGetter = FasterflectManager.GetFieldGetter(type, info.Value.Name); | ||
| 218 | + _memberGetterType = type; | ||
| 219 | + } | ||
| 220 | + | ||
| 221 | + return _memberGetter; | ||
| 222 | + } | ||
| 223 | + | ||
| 224 | + private MemberSetter GetMemberSetter(Type type) | ||
| 225 | + { | ||
| 226 | + if (type != _memberSetterType) | ||
| 227 | + { | ||
| 228 | + _memberSetter = FasterflectManager.GetFieldSetter(type, info.Value.Name); | ||
| 229 | + _memberSetterType = type; | ||
| 230 | + } | ||
| 231 | + | ||
| 232 | + return _memberSetter; | ||
| 233 | + } | ||
| 234 | + | ||
| 235 | + private bool IsValueType(Type type) | ||
| 236 | + { | ||
| 237 | + if (type != _isValueTypeType) | ||
| 238 | + { | ||
| 239 | + _isValueType = FasterflectManager.IsValueType(type); | ||
| 240 | + _isValueTypeType = type; | ||
| 241 | + } | ||
| 242 | + | ||
| 243 | + return _isValueType; | ||
| 244 | + } | ||
| 163 | 245 | } | |
| 164 | 246 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -60,7 +60,7 @@ internal long RefCount | |||
| 60 | 60 | internal GCHandle AllocGCHandle(TrackTypes track = TrackTypes.Untrack) | |
| 61 | 61 | { | |
| 62 | 62 | gcHandle = GCHandle.Alloc(this); | |
| 63 | - if (track != TrackTypes.Untrack) | ||
| 63 | + if (track != TrackTypes.Untrack && PythonEngine.ShutdownMode == ShutdownMode.Reload) | ||
| 64 | 64 | { | |
| 65 | 65 | _managedObjs.Add(this, track); | |
| 66 | 66 | } | |
@@ -69,7 +69,11 @@ internal GCHandle AllocGCHandle(TrackTypes track = TrackTypes.Untrack) | |||
| 69 | 69 | ||
| 70 | 70 | internal void FreeGCHandle() | |
| 71 | 71 | { | |
| 72 | - _managedObjs.Remove(this); | ||
| 72 | + if (PythonEngine.ShutdownMode == ShutdownMode.Reload) | ||
| 73 | + { | ||
| 74 | + _managedObjs.Remove(this); | ||
| 75 | + } | ||
| 76 | + | ||
| 73 | 77 | if (gcHandle.IsAllocated) | |
| 74 | 78 | { | |
| 75 | 79 | gcHandle.Free(); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments