1
1
using System ;
2
+ using System . Collections . Generic ;
2
3
using System . Runtime . InteropServices ;
3
4
4
5
namespace Python . Runtime
@@ -222,22 +223,12 @@ public static IntPtr __import__(IntPtr self, IntPtr args, IntPtr kw)
222
223
// Check these BEFORE the built-in import runs; may as well
223
224
// do the Incref()ed return here, since we've already found
224
225
// the module.
225
- if ( mod_name == "clr" )
226
+ if ( mod_name == "clr" || mod_name == "CLR" )
226
227
{
227
- IntPtr clr_module = GetCLRModule ( fromList ) ;
228
- if ( clr_module != IntPtr . Zero )
228
+ if ( mod_name == "CLR" )
229
229
{
230
- IntPtr sys_modules = Runtime . PyImport_GetModuleDict ( ) ;
231
- if ( sys_modules != IntPtr . Zero )
232
- {
233
- Runtime . PyDict_SetItemString ( sys_modules , "clr" , clr_module ) ;
234
- }
230
+ Exceptions . deprecation ( "The CLR module is deprecated. Please use 'clr'." ) ;
235
231
}
236
- return clr_module ;
237
- }
238
- if ( mod_name == "CLR" )
239
- {
240
- Exceptions . deprecation ( "The CLR module is deprecated. Please use 'clr'." ) ;
241
232
IntPtr clr_module = GetCLRModule ( fromList ) ;
242
233
if ( clr_module != IntPtr . Zero )
243
234
{
@@ -249,53 +240,45 @@ public static IntPtr __import__(IntPtr self, IntPtr args, IntPtr kw)
249
240
}
250
241
return clr_module ;
251
242
}
243
+
252
244
string realname = mod_name ;
253
245
string clr_prefix = null ;
254
- if ( mod_name . StartsWith ( "CLR." ) )
255
- {
256
- clr_prefix = "CLR." ; // prepend when adding the module to sys.modules
257
- realname = mod_name . Substring ( 4 ) ;
258
- string msg = $ "Importing from the CLR.* namespace is deprecated. Please import '{ realname } ' directly.";
259
- Exceptions . deprecation ( msg ) ;
260
- }
261
- else
246
+
247
+ // 2010-08-15: Always seemed smart to let python try first...
248
+ // This shaves off a few tenths of a second on test_module.py
249
+ // and works around a quirk where 'sys' is found by the
250
+ // LoadImplicit() deprecation logic.
251
+ // Turns out that the AssemblyManager.ResolveHandler() checks to see if any
252
+ // Assembly's FullName.ToLower().StartsWith(name.ToLower()), which makes very
253
+ // little sense to me.
254
+ IntPtr res = Runtime . PyObject_Call ( py_import , args , kw ) ;
255
+ if ( res != IntPtr . Zero )
262
256
{
263
- // 2010-08-15: Always seemed smart to let python try first...
264
- // This shaves off a few tenths of a second on test_module.py
265
- // and works around a quirk where 'sys' is found by the
266
- // LoadImplicit() deprecation logic.
267
- // Turns out that the AssemblyManager.ResolveHandler() checks to see if any
268
- // Assembly's FullName.ToLower().StartsWith(name.ToLower()), which makes very
269
- // little sense to me.
270
- IntPtr res = Runtime . PyObject_Call ( py_import , args , kw ) ;
271
- if ( res != IntPtr . Zero )
272
- {
273
- // There was no error.
274
- if ( fromlist && IsLoadAll ( fromList ) )
275
- {
276
- var mod = ManagedType . GetManagedObject ( res ) as ModuleObject ;
277
- mod ? . LoadNames ( ) ;
278
- }
279
- return res ;
280
- }
281
- // There was an error
282
- if ( ! Exceptions . ExceptionMatches ( Exceptions . ImportError ) )
257
+ // There was no error.
258
+ if ( fromlist && IsLoadAll ( fromList ) )
283
259
{
284
- // and it was NOT an ImportError; bail out here.
285
- return IntPtr . Zero ;
260
+ var mod = ManagedType . GetManagedObject ( res ) as ModuleObject ;
261
+ mod ? . LoadNames ( ) ;
286
262
}
263
+ return res ;
264
+ }
265
+ // There was an error
266
+ if ( ! Exceptions . ExceptionMatches ( Exceptions . ImportError ) )
267
+ {
268
+ // and it was NOT an ImportError; bail out here.
269
+ return IntPtr . Zero ;
270
+ }
287
271
288
- if ( mod_name == string . Empty )
289
- {
290
- // Most likely a missing relative import.
291
- // For example site-packages\bs4\builder\__init__.py uses it to check if a package exists:
292
- // from . import _html5lib
293
- // We don't support them anyway
294
- return IntPtr . Zero ;
295
- }
296
- // Otherwise, just clear the it.
297
- Exceptions . Clear ( ) ;
272
+ if ( mod_name == string . Empty )
273
+ {
274
+ // Most likely a missing relative import.
275
+ // For example site-packages\bs4\builder\__init__.py uses it to check if a package exists:
276
+ // from . import _html5lib
277
+ // We don't support them anyway
278
+ return IntPtr . Zero ;
298
279
}
280
+ // Otherwise, just clear the it.
281
+ Exceptions . Clear ( ) ;
299
282
300
283
string [ ] names = realname . Split ( '.' ) ;
301
284
@@ -312,11 +295,22 @@ public static IntPtr __import__(IntPtr self, IntPtr args, IntPtr kw)
312
295
AssemblyManager . UpdatePath ( ) ;
313
296
if ( ! AssemblyManager . IsValidNamespace ( realname ) )
314
297
{
315
- if ( ! AssemblyManager . LoadImplicit ( realname ) )
298
+ var loadExceptions = new List < Exception > ( ) ;
299
+ if ( ! AssemblyManager . LoadImplicit ( realname , assemblyLoadErrorHandler : loadExceptions . Add ) )
316
300
{
317
301
// May be called when a module being imported imports a module.
318
302
// In particular, I've seen decimal import copy import org.python.core
319
- return Runtime . PyObject_Call ( py_import , args , kw ) ;
303
+ IntPtr importResult = Runtime . PyObject_Call ( py_import , args , kw ) ;
304
+ // TODO: use ModuleNotFoundError in Python 3.6+
305
+ if ( importResult == IntPtr . Zero && loadExceptions . Count > 0
306
+ && Exceptions . ExceptionMatches ( Exceptions . ImportError ) )
307
+ {
308
+ loadExceptions . Add ( new PythonException ( ) ) ;
309
+ var importError = new PyObject ( new BorrowedReference ( Exceptions . ImportError ) ) ;
310
+ importError . SetAttr ( "__cause__" , new AggregateException ( loadExceptions ) . ToPython ( ) ) ;
311
+ Runtime . PyErr_SetObject ( new BorrowedReference ( Exceptions . ImportError ) , importError . Reference ) ;
312
+ }
313
+ return importResult ;
320
314
}
321
315
}
322
316
0 commit comments