| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -26,6 +26,7 @@ | |||
| 26 | 26 | - Dmitriy Se ([@dmitriyse](https://github.com/dmitriyse)) | |
| 27 | 27 | - He-chien Tsai ([@t3476](https://github.com/t3476)) | |
| 28 | 28 | - Ivan Cronyn ([@cronan](https://github.com/cronan)) | |
| 29 | + - Jan Krivanek ([@jakrivan](https://github.com/jakrivan)) | ||
| 29 | 30 | - Jeff Reback ([@jreback](https://github.com/jreback)) | |
| 30 | 31 | - Joe Frayne ([@jfrayne](https://github.com/jfrayne)) | |
| 31 | 32 | - John Burnett ([@johnburnett](https://github.com/johnburnett)) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -20,6 +20,7 @@ This document follows the conventions laid out in [Keep a CHANGELOG][]. | |||
| 20 | 20 | - Implemented GetDynamicMemberNames() for PyObject to allow dynamic object members to be visible in the debugger ([#443][i443])([#690][p690]) | |
| 21 | 21 | - Incorporated reference-style links to issues and pull requests in the CHANGELOG ([#608][i608]) | |
| 22 | 22 | - Added PyObject finalizer support, Python objects referred by C# can be auto collect now ([#692][p692]). | |
| 23 | + - Added detailed comments about aproaches and dangers to handle multi-app-domains ([#625][p625]) | ||
| 23 | 24 | ||
| 24 | 25 | ### Changed | |
| 25 | 26 | - PythonException included C# call stack | |
@@ -685,4 +686,5 @@ This document follows the conventions laid out in [Keep a CHANGELOG][]. | |||
| 685 | 686 | [p225]: https://github.com/pythonnet/pythonnet/pull/225 | |
| 686 | 687 | [p78]: https://github.com/pythonnet/pythonnet/pull/78 | |
| 687 | 688 | [p163]: https://github.com/pythonnet/pythonnet/pull/163 | |
| 689 | + [p625]: https://github.com/pythonnet/pythonnet/pull/625 | ||
| 688 | 690 | [i131]: https://github.com/pythonnet/pythonnet/issues/131 | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -17,7 +17,15 @@ internal class AssemblyManager | |||
| 17 | 17 | { | |
| 18 | 18 | // modified from event handlers below, potentially triggered from different .NET threads | |
| 19 | 19 | // therefore this should be a ConcurrentDictionary | |
| 20 | + // | ||
| 21 | + // WARNING: Dangerous if cross-app domain usage is ever supported | ||
| 22 | + // Reusing the dictionary with assemblies accross multiple initializations is problematic. | ||
| 23 | + // Loading happens from CurrentDomain (see line 53). And if the first call is from AppDomain that is later unloaded, | ||
| 24 | + // than it can end up referring to assemblies that are already unloaded (default behavior after unload appDomain - | ||
| 25 | + // unless LoaderOptimization.MultiDomain is used); | ||
| 26 | + // So for multidomain support it is better to have the dict. recreated for each app-domain initialization | ||
| 20 | 27 | private static ConcurrentDictionary<string, ConcurrentDictionary<Assembly, string>> namespaces; | |
| 28 | + | ||
| 21 | 29 | //private static Dictionary<string, Dictionary<string, string>> generics; | |
| 22 | 30 | private static AssemblyLoadEventHandler lhandler; | |
| 23 | 31 | private static ResolveEventHandler rhandler; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -237,6 +237,11 @@ public static IntPtr __import__(IntPtr self, IntPtr args, IntPtr kw) | |||
| 237 | 237 | if (res != IntPtr.Zero) | |
| 238 | 238 | { | |
| 239 | 239 | // There was no error. | |
| 240 | + if (fromlist && IsLoadAll(fromList)) | ||
| 241 | + { | ||
| 242 | + var mod = ManagedType.GetManagedObject(res) as ModuleObject; | ||
| 243 | + mod?.LoadNames(); | ||
| 244 | + } | ||
| 240 | 245 | return res; | |
| 241 | 246 | } | |
| 242 | 247 | // There was an error | |
@@ -290,6 +295,11 @@ public static IntPtr __import__(IntPtr self, IntPtr args, IntPtr kw) | |||
| 290 | 295 | { | |
| 291 | 296 | if (fromlist) | |
| 292 | 297 | { | |
| 298 | + if (IsLoadAll(fromList)) | ||
| 299 | + { | ||
| 300 | + var mod = ManagedType.GetManagedObject(module) as ModuleObject; | ||
| 301 | + mod?.LoadNames(); | ||
| 302 | + } | ||
| 293 | 303 | Runtime.XIncref(module); | |
| 294 | 304 | return module; | |
| 295 | 305 | } | |
@@ -345,20 +355,33 @@ public static IntPtr __import__(IntPtr self, IntPtr args, IntPtr kw) | |||
| 345 | 355 | } | |
| 346 | 356 | } | |
| 347 | 357 | ||
| 348 | - ModuleObject mod = fromlist ? tail : head; | ||
| 349 | - | ||
| 350 | - if (fromlist && Runtime.PySequence_Size(fromList) == 1) | ||
| 351 | 358 | { | |
| 352 | - IntPtr fp = Runtime.PySequence_GetItem(fromList, 0); | ||
| 353 | - if (!CLRModule.preload && Runtime.GetManagedString(fp) == "*") | ||
| 359 | + var mod = fromlist ? tail : head; | ||
| 360 | + | ||
| 361 | + if (fromlist && IsLoadAll(fromList)) | ||
| 354 | 362 | { | |
| 355 | 363 | mod.LoadNames(); | |
| 356 | 364 | } | |
| 357 | - Runtime.XDecref(fp); | ||
| 365 | + | ||
| 366 | + Runtime.XIncref(mod.pyHandle); | ||
| 367 | + return mod.pyHandle; | ||
| 358 | 368 | } | |
| 369 | + } | ||
| 359 | 370 | ||
| 360 | - Runtime.XIncref(mod.pyHandle); | ||
| 361 | - return mod.pyHandle; | ||
| 371 | + private static bool IsLoadAll(IntPtr fromList) | ||
| 372 | + { | ||
| 373 | + if (CLRModule.preload) | ||
| 374 | + { | ||
| 375 | + return false; | ||
| 376 | + } | ||
| 377 | + if (Runtime.PySequence_Size(fromList) != 1) | ||
| 378 | + { | ||
| 379 | + return false; | ||
| 380 | + } | ||
| 381 | + IntPtr fp = Runtime.PySequence_GetItem(fromList, 0); | ||
| 382 | + bool res = Runtime.GetManagedString(fp) == "*"; | ||
| 383 | + Runtime.XDecref(fp); | ||
| 384 | + return res; | ||
| 362 | 385 | } | |
| 363 | 386 | } | |
| 364 | 387 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -190,10 +190,17 @@ public void LoadNames() | |||
| 190 | 190 | foreach (string name in AssemblyManager.GetNames(_namespace)) | |
| 191 | 191 | { | |
| 192 | 192 | cache.TryGetValue(name, out m); | |
| 193 | - if (m == null) | ||
| 193 | + if (m != null) | ||
| 194 | 194 | { | |
| 195 | - ManagedType attr = GetAttribute(name, true); | ||
| 195 | + continue; | ||
| 196 | 196 | } | |
| 197 | + IntPtr attr = Runtime.PyDict_GetItemString(dict, name); | ||
| 198 | + // If __dict__ has already set a custom property, skip it. | ||
| 199 | + if (attr != IntPtr.Zero) | ||
| 200 | + { | ||
| 201 | + continue; | ||
| 202 | + } | ||
| 203 | + GetAttribute(name, true); | ||
| 197 | 204 | } | |
| 198 | 205 | } | |
| 199 | 206 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,13 @@ | |||
| 1 | + # -*- coding: utf-8 -*- | ||
| 2 | + | ||
| 3 | + import sys | ||
| 4 | + try: | ||
| 5 | + del sys.modules["System.IO"] | ||
| 6 | + except KeyError: | ||
| 7 | + pass | ||
| 8 | + | ||
| 9 | + assert "FileStream" not in globals() | ||
| 10 | + import System.IO | ||
| 11 | + from System.IO import * | ||
| 12 | + | ||
| 13 | + assert "FileStream" in globals() | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -3,11 +3,20 @@ | |||
| 3 | 3 | """Test the import statement.""" | |
| 4 | 4 | ||
| 5 | 5 | import pytest | |
| 6 | - | ||
| 6 | + import sys | ||
| 7 | 7 | ||
| 8 | 8 | def test_relative_missing_import(): | |
| 9 | 9 | """Test that a relative missing import doesn't crash. | |
| 10 | 10 | Some modules use this to check if a package is installed. | |
| 11 | 11 | Relative import in the site-packages folder""" | |
| 12 | 12 | with pytest.raises(ImportError): | |
| 13 | 13 | from . import _missing_import | |
| 14 | + | ||
| 15 | + | ||
| 16 | + def test_import_all_on_second_time(): | ||
| 17 | + """Test import all attributes after a normal import without '*'. | ||
| 18 | + Due to import * only allowed at module level, the test body splited | ||
| 19 | + to a module file.""" | ||
| 20 | + from . import importtest | ||
| 21 | + del sys.modules[importtest.__name__] | ||
| 22 | + | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments