37
37
import java .util .concurrent .locks .ReentrantLock ;
38
38
import java .util .function .Supplier ;
39
39
40
+ import org .graalvm .nativeimage .ImageInfo ;
40
41
import org .graalvm .options .OptionValues ;
41
42
42
43
import com .oracle .graal .python .PythonLanguage ;
45
46
import com .oracle .graal .python .builtins .objects .cext .PythonNativeClass ;
46
47
import com .oracle .graal .python .builtins .objects .common .HashingStorage ;
47
48
import com .oracle .graal .python .builtins .objects .dict .PDict ;
49
+ import com .oracle .graal .python .builtins .objects .list .PList ;
48
50
import com .oracle .graal .python .builtins .objects .module .PythonModule ;
51
+ import com .oracle .graal .python .builtins .objects .str .PString ;
52
+ import com .oracle .graal .python .nodes .SpecialAttributeNames ;
49
53
import com .oracle .graal .python .runtime .AsyncHandler .AsyncAction ;
50
54
import com .oracle .graal .python .runtime .exception .PException ;
51
55
import com .oracle .truffle .api .Assumption ;
@@ -234,17 +238,50 @@ public boolean isInitialized() {
234
238
235
239
public void initialize () {
236
240
core .initialize (this );
237
- setupRuntimeInformation ();
241
+ setupRuntimeInformation (false );
238
242
core .postInitialize ();
239
243
}
240
244
241
245
public void patch (Env newEnv ) {
242
246
setEnv (newEnv );
243
- setupRuntimeInformation ();
247
+ setupRuntimeInformation (true );
244
248
core .postInitialize ();
245
249
}
246
250
247
- private void setupRuntimeInformation () {
251
+ /**
252
+ * During pre-initialization, we're also loading code from the Python standard library. Since
253
+ * some of those modules may be packages, they will have their __path__ attribute set to the
254
+ * absolute path of the package on the build system. We use this function to patch the paths
255
+ * during build time and after starting up from a pre-initialized context so they point to the
256
+ * run-time package paths.
257
+ */
258
+ private void patchPackagePaths (String from , String to ) {
259
+ for (Object v : sysModules .getDictStorage ().values ()) {
260
+ if (v instanceof PythonModule ) {
261
+ Object path = ((PythonModule ) v ).getAttribute (SpecialAttributeNames .__PATH__ );
262
+ if (path instanceof PList ) {
263
+ Object [] paths = ((PList ) path ).getSequenceStorage ().getCopyOfInternalArray ();
264
+ for (int i = 0 ; i < paths .length ; i ++) {
265
+ Object pathElement = paths [i ];
266
+ String strPath ;
267
+ if (pathElement instanceof PString ) {
268
+ strPath = ((PString ) pathElement ).getValue ();
269
+ } else if (pathElement instanceof String ) {
270
+ strPath = (String ) pathElement ;
271
+ } else {
272
+ continue ;
273
+ }
274
+ if (strPath .startsWith (from )) {
275
+ paths [i ] = strPath .replace (from , to );
276
+ }
277
+ }
278
+ ((PythonModule ) v ).setAttribute (SpecialAttributeNames .__PATH__ , core .factory ().createList (paths ));
279
+ }
280
+ }
281
+ }
282
+ }
283
+
284
+ private void setupRuntimeInformation (boolean isPatching ) {
248
285
PythonModule sysModule = core .lookupBuiltinModule ("sys" );
249
286
sysModules = (PDict ) sysModule .getAttribute ("modules" );
250
287
@@ -256,6 +293,18 @@ private void setupRuntimeInformation() {
256
293
257
294
sysModules .setItem (__MAIN__ , mainModule );
258
295
296
+ final String stdLibPlaceholder = "!stdLibHome!" ;
297
+ final String stdLibHome = PythonCore .getStdlibHome (getEnv ());
298
+ if (ImageInfo .inImageBuildtimeCode ()) {
299
+ // Patch any pre-loaded packages' paths if we're running
300
+ // pre-initialization
301
+ patchPackagePaths (stdLibHome , stdLibPlaceholder );
302
+ } else if (isPatching && ImageInfo .inImageRuntimeCode ()) {
303
+ // Patch any pre-loaded packages' paths to the new stdlib home if
304
+ // we're patching a pre-initialized context
305
+ patchPackagePaths (stdLibPlaceholder , stdLibHome );
306
+ }
307
+
259
308
currentException = null ;
260
309
isInitialized = true ;
261
310
}
0 commit comments