Skip to content

Commit 8aab314

Browse files
committed
GR-26530: fix ImportError no name attribute raised by __create_dynamic__
1 parent 41e23c9 commit 8aab314

File tree

5 files changed

+60
-26
lines changed

5 files changed

+60
-26
lines changed

graalpython/com.oracle.graal.python.cext/modules/_testmultiphase.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
1+
/* Copyright (c) 2020, Oracle and/or its affiliates.
2+
* Copyright (C) 1996-2020 Python Software Foundation
3+
*
4+
* Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
5+
*/
26
/* Testing module for multi-phase initialization of extension modules (PEP 489)
37
*/
48

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ImpModuleBuiltins.java

Lines changed: 50 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242

4343
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.SystemError;
4444
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__FILE__;
45-
import static com.oracle.graal.python.runtime.exception.PythonErrorType.ImportError;
4645
import static com.oracle.graal.python.runtime.exception.PythonErrorType.NotImplementedError;
4746

4847
import java.io.IOException;
@@ -75,6 +74,7 @@
7574
import com.oracle.graal.python.builtins.objects.object.PythonObjectLibrary;
7675
import com.oracle.graal.python.builtins.objects.str.PString;
7776
import com.oracle.graal.python.nodes.ErrorMessages;
77+
import com.oracle.graal.python.nodes.PConstructAndRaiseNode;
7878
import com.oracle.graal.python.nodes.SpecialMethodNames;
7979
import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode;
8080
import com.oracle.graal.python.nodes.attributes.SetAttributeNode;
@@ -203,6 +203,24 @@ public abstract static class CreateDynamic extends PythonBuiltinNode {
203203
@Child private SetItemNode setItemNode;
204204
@Child private CheckFunctionResultNode checkResultNode;
205205
@Child private LookupAndCallUnaryNode callReprNode = LookupAndCallUnaryNode.create(SpecialMethodNames.__REPR__);
206+
@Child private PConstructAndRaiseNode constructAndRaiseNode;
207+
208+
static class ImportException extends Exception {
209+
private static final long serialVersionUID = 3517291912314595890L;
210+
public final PBaseException cause;
211+
public final Object name;
212+
public final Object path;
213+
public final String formatString;
214+
public final Object[] formatArgs;
215+
216+
ImportException(PBaseException cause, Object name, Object path, String formatString, Object... formatArgs) {
217+
this.cause = cause;
218+
this.name = name;
219+
this.path = path;
220+
this.formatString = formatString;
221+
this.formatArgs = formatArgs;
222+
}
223+
}
206224

207225
@Specialization
208226
@SuppressWarnings("try")
@@ -212,13 +230,15 @@ public Object run(VirtualFrame frame, PythonObject moduleSpec, @SuppressWarnings
212230
Object state = ForeignCallContext.enter(frame, context, this);
213231
try {
214232
return run(moduleSpec, interop);
233+
} catch (ImportException ie) {
234+
throw getConstructAndRaiseNode().raiseImportError(frame, ie.cause, ie.name, ie.path, ie.formatString, ie.formatArgs);
215235
} finally {
216236
ForeignCallContext.exit(frame, context, state);
217237
}
218238
}
219239

220240
@TruffleBoundary
221-
private Object run(PythonObject moduleSpec, InteropLibrary interop) {
241+
private Object run(PythonObject moduleSpec, InteropLibrary interop) throws ImportException {
222242
String name = moduleSpec.getAttribute("name").toString();
223243
String path = moduleSpec.getAttribute("origin").toString();
224244

@@ -238,9 +258,9 @@ private Object findExtensionObject(String name, String path) {
238258
}
239259

240260
@TruffleBoundary
241-
private Object loadDynamicModuleWithSpec(String name, String path, InteropLibrary interop) {
261+
private Object loadDynamicModuleWithSpec(String name, String path, InteropLibrary interop) throws ImportException {
242262
// we always need to load the CPython C API (even for HPy modules)
243-
ensureCapiWasLoaded();
263+
ensureCapiWasLoaded(name, path);
244264
PythonContext context = getContext();
245265
Env env = context.getEnv();
246266
String basename = name.substring(name.lastIndexOf('.') + 1);
@@ -251,9 +271,9 @@ private Object loadDynamicModuleWithSpec(String name, String path, InteropLibrar
251271
sulongLibrary = (TruffleObject) callTarget.call();
252272
} catch (SecurityException | IOException e) {
253273
logJavaException(e);
254-
throw raise(ImportError, wrapJavaException(e), ErrorMessages.CANNOT_LOAD_M, path, e);
274+
throw new ImportException(wrapJavaException(e), name, path, ErrorMessages.CANNOT_LOAD_M, path, e);
255275
} catch (RuntimeException e) {
256-
throw reportImportError(e, path);
276+
throw reportImportError(e, name, path);
257277
}
258278

259279
// Now, try to detect the C extension's API by looking for the appropriate init
@@ -267,23 +287,23 @@ private Object loadDynamicModuleWithSpec(String name, String path, InteropLibrar
267287
return initCApiModule(sulongLibrary, initFuncName, name, path, interop);
268288
} catch (UnsupportedTypeException | ArityException | UnsupportedMessageException e) {
269289
logJavaException(e);
270-
throw raise(ImportError, wrapJavaException(e), ErrorMessages.CANNOT_INITIALIZE_WITH, path, basename, "");
290+
throw new ImportException(wrapJavaException(e), name, path, ErrorMessages.CANNOT_INITIALIZE_WITH, path, basename, "");
271291
} catch (RuntimeException e) {
272-
throw reportImportError(e, path);
292+
throw reportImportError(e, name, path);
273293
}
274294
}
275295

276296
@TruffleBoundary
277297
private Object initHPyModule(TruffleObject sulongLibrary, String initFuncName, String name, String path, InteropLibrary interop)
278-
throws UnsupportedMessageException, ArityException, UnsupportedTypeException {
298+
throws UnsupportedMessageException, ArityException, UnsupportedTypeException, ImportException {
279299
PythonContext context = getContext();
280-
GraalHPyContext hpyContext = ensureHPyWasLoaded(context);
300+
GraalHPyContext hpyContext = ensureHPyWasLoaded(context, name, path);
281301

282302
TruffleObject pyinitFunc;
283303
try {
284304
pyinitFunc = (TruffleObject) interop.readMember(sulongLibrary, initFuncName);
285305
} catch (UnknownIdentifierException | UnsupportedMessageException e1) {
286-
throw raise(ImportError, ErrorMessages.NO_FUNCTION_FOUND, "", initFuncName, path);
306+
throw new ImportException(null, name, path, ErrorMessages.NO_FUNCTION_FOUND, "", initFuncName, path);
287307
}
288308
Object nativeResult = interop.execute(pyinitFunc, hpyContext);
289309
getCheckResultNode().execute(initFuncName, nativeResult);
@@ -304,13 +324,13 @@ private Object initHPyModule(TruffleObject sulongLibrary, String initFuncName, S
304324

305325
@TruffleBoundary
306326
private Object initCApiModule(TruffleObject sulongLibrary, String initFuncName, String name, String path, InteropLibrary interop)
307-
throws UnsupportedMessageException, ArityException, UnsupportedTypeException {
327+
throws UnsupportedMessageException, ArityException, UnsupportedTypeException, ImportException {
308328
PythonContext context = getContext();
309329
TruffleObject pyinitFunc;
310330
try {
311331
pyinitFunc = (TruffleObject) interop.readMember(sulongLibrary, initFuncName);
312332
} catch (UnknownIdentifierException | UnsupportedMessageException e1) {
313-
throw raise(ImportError, ErrorMessages.NO_FUNCTION_FOUND, "", initFuncName, path);
333+
throw new ImportException(null, name, path, ErrorMessages.NO_FUNCTION_FOUND, "", initFuncName, path);
314334
}
315335
Object nativeResult = interop.execute(pyinitFunc);
316336
getCheckResultNode().execute(initFuncName, nativeResult);
@@ -330,11 +350,11 @@ private Object initCApiModule(TruffleObject sulongLibrary, String initFuncName,
330350
}
331351

332352
@TruffleBoundary
333-
private void ensureCapiWasLoaded() {
353+
private void ensureCapiWasLoaded(String name, String path) throws ImportException {
334354
PythonContext context = getContext();
335355
if (!context.hasCApiContext()) {
336356
if (!context.getEnv().isNativeAccessAllowed()) {
337-
throw raise(ImportError, ErrorMessages.NATIVE_ACCESS_NOT_ALLOWED);
357+
throw new ImportException(null, name, path, ErrorMessages.NATIVE_ACCESS_NOT_ALLOWED);
338358
}
339359

340360
Env env = context.getEnv();
@@ -352,7 +372,7 @@ private void ensureCapiWasLoaded() {
352372
capi = context.getEnv().parseInternal(capiSrcBuilder.build()).call();
353373
} catch (IOException | RuntimeException e) {
354374
logJavaException(e);
355-
throw raise(ImportError, wrapJavaException(e), ErrorMessages.CAPI_LOAD_ERROR, capiFile.getAbsoluteFile().getPath());
375+
throw new ImportException(wrapJavaException(e), name, path, ErrorMessages.CAPI_LOAD_ERROR, capiFile.getAbsoluteFile().getPath());
356376
}
357377
try {
358378
// call into Python to initialize python_cext module globals
@@ -369,13 +389,13 @@ private void ensureCapiWasLoaded() {
369389
callNode.executeObject(null, readNode.execute(builtinModule, IMPORT_NATIVE_MEMORYVIEW), capi);
370390
} catch (RuntimeException e) {
371391
logJavaException(e);
372-
throw raise(ImportError, wrapJavaException(e), ErrorMessages.CAPI_LOAD_ERROR, capiFile.getAbsoluteFile().getPath());
392+
throw new ImportException(wrapJavaException(e), name, path, ErrorMessages.CAPI_LOAD_ERROR, capiFile.getAbsoluteFile().getPath());
373393
}
374394
}
375395
}
376396

377397
@TruffleBoundary
378-
private GraalHPyContext ensureHPyWasLoaded(PythonContext context) {
398+
private GraalHPyContext ensureHPyWasLoaded(PythonContext context, String name, String path) throws ImportException {
379399
if (!context.hasHPyContext()) {
380400
Env env = context.getEnv();
381401
CompilerDirectives.transferToInterpreterAndInvalidate();
@@ -395,7 +415,7 @@ private GraalHPyContext ensureHPyWasLoaded(PythonContext context) {
395415
interopLibrary.invokeMember(hpyLibrary, "graal_hpy_init", new GraalHPyInitObject(context.getHPyContext()));
396416
} catch (IOException | RuntimeException | InteropException e) {
397417
logJavaException(e);
398-
throw raise(ImportError, wrapJavaException(e), ErrorMessages.HPY_LOAD_ERROR, capiFile.getAbsoluteFile().getPath());
418+
throw new ImportException(wrapJavaException(e), name, path, ErrorMessages.HPY_LOAD_ERROR, capiFile.getAbsoluteFile().getPath());
399419
}
400420
}
401421
return context.getHPyContext();
@@ -435,8 +455,16 @@ private CheckFunctionResultNode getCheckResultNode() {
435455
return checkResultNode;
436456
}
437457

458+
private PConstructAndRaiseNode getConstructAndRaiseNode() {
459+
if (constructAndRaiseNode == null) {
460+
CompilerDirectives.transferToInterpreterAndInvalidate();
461+
constructAndRaiseNode = insert(PConstructAndRaiseNode.create());
462+
}
463+
return constructAndRaiseNode;
464+
}
465+
438466
@TruffleBoundary
439-
private PException reportImportError(RuntimeException e, String path) {
467+
private PException reportImportError(RuntimeException e, String name, String path) throws ImportException {
440468
StringBuilder sb = new StringBuilder();
441469
PBaseException pythonCause = null;
442470
if (e instanceof PException) {
@@ -465,9 +493,9 @@ private PException reportImportError(RuntimeException e, String path) {
465493
}
466494
Object[] args = new Object[]{path, sb.toString()};
467495
if (pythonCause != null) {
468-
throw raise(ImportError, pythonCause, ErrorMessages.CANNOT_LOAD, args);
496+
throw new ImportException(pythonCause, name, path, ErrorMessages.CANNOT_LOAD, args);
469497
} else {
470-
throw raise(ImportError, ErrorMessages.CANNOT_LOAD, args);
498+
throw new ImportException(null, name, path, ErrorMessages.CANNOT_LOAD, args);
471499
}
472500
}
473501
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PConstructAndRaiseNode.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,8 @@ private PException raiseInternal(VirtualFrame frame, PythonBuiltinClassType type
120120
}
121121

122122
@Specialization(guards = {"format == null", "formatArgs == null"})
123-
PException constructAndRaiseNoFormatString(VirtualFrame frame, PythonBuiltinClassType type, PBaseException cause, @SuppressWarnings("unused") String format, @SuppressWarnings("unused") Object[] formatArgs,
123+
PException constructAndRaiseNoFormatString(VirtualFrame frame, PythonBuiltinClassType type, PBaseException cause, @SuppressWarnings("unused") String format,
124+
@SuppressWarnings("unused") Object[] formatArgs,
124125
Object[] arguments, PKeyword[] keywords,
125126
@Cached.Shared("callNode") @Cached CallVarargsMethodNode callNode,
126127
@CachedLanguage PythonLanguage language,
@@ -152,7 +153,7 @@ PException constructAndRaise(VirtualFrame frame, PythonBuiltinClassType type, PB
152153
Object[] args = new Object[arguments.length + 1];
153154
args[0] = formatArgs != null ? getFormattedMessage(pol, format, formatArgs) : format;
154155
System.arraycopy(arguments, 0, args, 1, arguments.length);
155-
return raiseInternal(frame, type,cause, args, keywords, callNode, language, core);
156+
return raiseInternal(frame, type, cause, args, keywords, callNode, language, core);
156157
}
157158

158159
// ImportError helpers

graalpython/lib-graalpython/zipimport.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
1+
# Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
22
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
33
#
44
# The Universal Permissive License (UPL), Version 1.0

mx.graalpython/copyrights/overrides

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ graalpython/com.oracle.graal.python.cext/modules/_cpython_struct.c,python.copyri
145145
graalpython/com.oracle.graal.python.cext/modules/_memoryview.c,python.copyright
146146
graalpython/com.oracle.graal.python.cext/modules/_mmap.c,python.copyright
147147
graalpython/com.oracle.graal.python.cext/modules/_testcapi.c,python.copyright
148+
graalpython/com.oracle.graal.python.cext/modules/_testmultiphase.c,python.copyright
148149
graalpython/com.oracle.graal.python.cext/modules/clinic/_bz2module.c.h,python.copyright
149150
graalpython/com.oracle.graal.python.cext/modules/clinic/_sre.c.h,python.copyright
150151
graalpython/com.oracle.graal.python.cext/modules/clinic/_struct.c.h,python.copyright

0 commit comments

Comments
 (0)