001: // Copyright (c) Corporation for National Research Initiatives
002: package org.python.core;
003:
004: import java.io.ByteArrayOutputStream;
005: import java.io.File;
006: import java.io.FileInputStream;
007: import java.io.FileOutputStream;
008: import java.io.IOException;
009: import java.io.InputStream;
010: import java.util.ArrayList;
011: import java.util.Iterator;
012: import java.util.List;
013:
014: /**
015: * Utility functions for "import" support.
016: */
017: public class imp {
018: private static final String IMPORT_LOG = "import";
019:
020: private static final String UNKNOWN_SOURCEFILE = "<unknown>";
021:
022: public static final int APIVersion = 12;
023:
024: private static Object syspathJavaLoaderLock = new Object();
025:
026: private static ClassLoader syspathJavaLoader = null;
027:
028: public static ClassLoader getSyspathJavaLoader() {
029: synchronized (syspathJavaLoaderLock) {
030: if (syspathJavaLoader == null) {
031: syspathJavaLoader = new SyspathJavaLoader();
032: }
033: }
034: return syspathJavaLoader;
035: }
036:
037: private imp() {
038: ;
039: }
040:
041: /**
042: * If the given name is found in sys.modules, the entry from there is
043: * returned. Otherwise a new PyModule is created for the name and added to
044: * sys.modules
045: */
046: public static PyModule addModule(String name) {
047: name = name.intern();
048: PyObject modules = Py.getSystemState().modules;
049: PyModule module = (PyModule) modules.__finditem__(name);
050: if (module != null) {
051: return module;
052: }
053: module = new PyModule(name, null);
054: modules.__setitem__(name, module);
055: return module;
056: }
057:
058: private static byte[] readBytes(InputStream fp) {
059: try {
060: return FileUtil.readBytes(fp);
061: } catch (IOException ioe) {
062: throw Py.IOError(ioe);
063: } finally {
064: try {
065: fp.close();
066: } catch (IOException e) {
067: throw Py.IOError(e);
068: }
069: }
070: }
071:
072: private static InputStream makeStream(File file) {
073: try {
074: return new FileInputStream(file);
075: } catch (IOException ioe) {
076: throw Py.IOError(ioe);
077: }
078: }
079:
080: static PyObject createFromPyClass(String name, InputStream fp,
081: boolean testing, String fileName) {
082: byte[] data = readBytes(fp);
083: int n = data.length;
084:
085: int api = (data[n - 4] << 24) + (data[n - 3] << 16)
086: + (data[n - 2] << 8) + data[n - 1];
087: if (api != APIVersion) {
088: if (testing) {
089: return null;
090: } else {
091: throw Py.ImportError("invalid api version(" + api
092: + " != " + APIVersion + ") in: " + name);
093: }
094: }
095: PyCode code;
096: try {
097: code = BytecodeLoader
098: .makeCode(name + "$py", data, fileName);
099: } catch (Throwable t) {
100: if (testing) {
101: return null;
102: } else {
103: throw Py.JavaError(t);
104: }
105: }
106:
107: Py.writeComment(IMPORT_LOG, "'" + name + "' as " + fileName);
108:
109: return createFromCode(name, code, fileName);
110: }
111:
112: public static byte[] compileSource(String name, File file,
113: String sourceFilename, String compiledFilename) {
114: if (sourceFilename == null) {
115: sourceFilename = file.toString();
116: }
117: return compileSource(name, makeStream(file), sourceFilename);
118: }
119:
120: private static String makeCompiledFilename(String filename) {
121: return filename.substring(0, filename.length() - 3)
122: + "$py.class";
123: }
124:
125: /**
126: * Stores the bytes in compiledSource in compiledFilename.
127: *
128: * If compiledFilename is null it's set to the results of
129: * makeCompiledFilename(sourcefileName)
130: *
131: * If sourceFilename is null or set to UNKNOWN_SOURCEFILE null is returned
132: *
133: * @return the compiledFilename eventually used or null if a
134: * compiledFilename couldn't be determined of if an error was thrown
135: * while writing to the cache file.
136: */
137: public static String cacheCompiledSource(String sourceFilename,
138: String compiledFilename, byte[] compiledSource) {
139: if (compiledFilename == null) {
140: if (sourceFilename == null
141: || sourceFilename.equals(UNKNOWN_SOURCEFILE)) {
142: return null;
143: }
144: compiledFilename = makeCompiledFilename(sourceFilename);
145: }
146: FileOutputStream fop = null;
147: try {
148: fop = new FileOutputStream(compiledFilename);
149: fop.write(compiledSource);
150: fop.close();
151: return compiledFilename;
152: } catch (IOException exc) {
153: // If we can't write the cache file, just log and continue
154: Py.writeDebug(IMPORT_LOG,
155: "Unable to write to source cache file '"
156: + compiledFilename + "' due to " + exc);
157: return null;
158: } finally {
159: if (fop != null) {
160: try {
161: fop.close();
162: } catch (IOException e) {
163: Py.writeDebug(IMPORT_LOG,
164: "Unable to close source cache file '"
165: + compiledFilename + "' due to "
166: + e);
167: }
168: }
169: }
170: }
171:
172: static byte[] compileSource(String name, InputStream fp,
173: String filename) {
174: ByteArrayOutputStream ofp = new ByteArrayOutputStream();
175: try {
176: if (filename == null) {
177: filename = UNKNOWN_SOURCEFILE;
178: }
179: org.python.parser.ast.modType node;
180: try {
181: node = parser.parse(fp, "exec", filename, Py
182: .getCompilerFlags());
183: } finally {
184: fp.close();
185: }
186: org.python.compiler.Module.compile(node, ofp, name + "$py",
187: filename, true, false, true, Py.getCompilerFlags());
188: return ofp.toByteArray();
189: } catch (Throwable t) {
190: throw parser.fixParseError(null, t, filename);
191: }
192: }
193:
194: public static PyObject createFromSource(String name,
195: InputStream fp, String filename) {
196: return createFromSource(name, fp, filename, null);
197: }
198:
199: static PyObject createFromSource(String name, InputStream fp,
200: String filename, String outFilename) {
201: byte[] bytes = compileSource(name, fp, filename);
202: outFilename = cacheCompiledSource(filename, outFilename, bytes);
203:
204: Py.writeComment(IMPORT_LOG, "'" + name + "' as " + filename);
205:
206: PyCode code = BytecodeLoader.makeCode(name + "$py", bytes,
207: filename);
208: return createFromCode(name, code, filename);
209: }
210:
211: /**
212: * Returns a module with the given name whose contents are the results of
213: * running c. __file__ is set to whatever is in c.
214: */
215: static PyObject createFromCode(String name, PyCode c) {
216: return createFromCode(name, c, null);
217: }
218:
219: /*
220: * Returns a module with the given name whose contents are the results of
221: * running c. Sets __file__ on the module to be moduleLocation unless
222: * moduleLocation is null. If c comes from a local .py file or compiled
223: * $py.class class moduleLocation should be the result of running new
224: * File(moduleLocation).getAbsoultePath(). If c comes from a remote file or
225: * is a jar moduleLocation should be the full uri for c.
226: */
227: static PyObject createFromCode(String name, PyCode c,
228: String moduleLocation) {
229: PyModule module = addModule(name);
230:
231: PyTableCode code = null;
232: if (c instanceof PyTableCode) {
233: code = (PyTableCode) c;
234: }
235: try {
236: PyFrame f = new PyFrame(code, module.__dict__,
237: module.__dict__, null);
238: code.call(f);
239: } catch (RuntimeException t) {
240: Py.getSystemState().modules.__delitem__(name.intern());
241: throw t;
242: }
243: if (moduleLocation != null) {
244: module
245: .__setattr__("__file__", new PyString(
246: moduleLocation));
247: } else {
248: Py.writeDebug(IMPORT_LOG,
249: "No fileName known to set __file__ for " + name
250: + ".");
251: }
252: return module;
253: }
254:
255: static PyObject createFromClass(String name, Class c) {
256: // Two choices. c implements PyRunnable or c is Java package
257: if (PyRunnable.class.isAssignableFrom(c)) {
258: try {
259: return createFromCode(name, ((PyRunnable) c
260: .newInstance()).getMain());
261: } catch (InstantiationException e) {
262: throw Py.JavaError(e);
263: } catch (IllegalAccessException e) {
264: throw Py.JavaError(e);
265: }
266: }
267: return PyJavaClass.lookup(c); // xxx?
268: }
269:
270: static PyObject getPathImporter(PyObject cache, PyList hooks,
271: PyObject p) {
272:
273: // attempt to get an importer for the path
274: // use null as default value since Py.None is
275: // a valid value in the cache for the default
276: // importer
277: PyObject importer = cache.__finditem__(p);
278: if (importer != null) {
279: return importer;
280: }
281:
282: // nothing in the cache, so check all hooks
283: PyObject iter = hooks.__iter__();
284: for (PyObject hook; (hook = iter.__iternext__()) != null;) {
285: try {
286: importer = hook.__call__(p);
287: break;
288: } catch (PyException e) {
289: if (!Py.matchException(e, Py.ImportError)) {
290: throw e;
291: }
292: }
293: }
294:
295: importer = (importer == null ? Py.None : importer);
296: cache.__setitem__(p, importer);
297:
298: return importer;
299: }
300:
301: static PyObject replacePathItem(PyObject path) {
302: if (path instanceof SyspathArchive) {
303: // already an archive
304: return null;
305: }
306:
307: try {
308: // this has the side affect of adding the jar to the PackageManager
309: // during the initialization of the SyspathArchive
310: return new SyspathArchive(path.toString());
311: } catch (Exception e) {
312: return null;
313: }
314: }
315:
316: static PyObject find_module(String name, String moduleName,
317: PyList path) {
318:
319: PyObject loader = Py.None;
320: PySystemState sys = Py.getSystemState();
321: PyObject metaPath = sys.meta_path;
322:
323: /*
324: * Needed to convert all entries on the path to SyspathArchives if
325: * necessary.
326: */
327: PyList ppath = path == null ? sys.path : path;
328: for (int i = 0; i < ppath.__len__(); i++) {
329: PyObject p = ppath.__getitem__(i);
330: PyObject q = replacePathItem(p);
331: if (q == null) {
332: continue;
333: }
334: ppath.__setitem__(i, q);
335: }
336:
337: PyObject iter = metaPath.__iter__();
338: for (PyObject importer; (importer = iter.__iternext__()) != null;) {
339: PyObject findModule = importer.__getattr__("find_module");
340: loader = findModule.__call__(new PyObject[] {
341: new PyString(moduleName),
342: path == null ? Py.None : path });
343: if (loader != Py.None) {
344: return loadFromLoader(loader, moduleName);
345: }
346: }
347:
348: PyObject ret = loadBuiltin(moduleName);
349: if (ret != null) {
350: return ret;
351: }
352:
353: path = path == null ? sys.path : path;
354: for (int i = 0; i < path.__len__(); i++) {
355: PyObject p = path.__getitem__(i);
356: // System.err.println("find_module (" + name + ", " + moduleName +
357: // ") Path: " + path);
358: PyObject importer = getPathImporter(
359: sys.path_importer_cache, sys.path_hooks, p);
360: if (importer != Py.None) {
361: PyObject findModule = importer
362: .__getattr__("find_module");
363: loader = findModule
364: .__call__(new PyObject[] { new PyString(
365: moduleName) });
366: if (loader != Py.None) {
367: return loadFromLoader(loader, moduleName);
368: }
369: }
370: ret = loadFromSource(name, moduleName, p);
371: if (ret != null) {
372: return ret;
373: }
374: }
375:
376: return ret;
377: }
378:
379: private static PyObject loadBuiltin(String name) {
380: if (name == "sys") {
381: Py.writeComment(IMPORT_LOG, "'" + name + "' as sys in "
382: + "builtin modules");
383: return Py.java2py(Py.getSystemState());
384: }
385: String mod = PySystemState.getBuiltin(name);
386: if (mod != null) {
387: Class c = Py.findClassEx(mod, "builtin modules");
388: if (c != null) {
389: Py.writeComment(IMPORT_LOG, "'" + name + "' as " + mod
390: + " in builtin modules");
391: try {
392: if (PyObject.class.isAssignableFrom(c)) { // xxx ok?
393: return PyType.fromClass(c);
394: }
395: return createFromClass(name, c);
396: } catch (NoClassDefFoundError e) {
397: throw Py.ImportError("Cannot import " + name
398: + ", missing class " + c.getName());
399: }
400: }
401: }
402: return null;
403: }
404:
405: static PyObject loadFromLoader(PyObject importer, String name) {
406: PyObject load_module = importer.__getattr__("load_module");
407: return load_module
408: .__call__(new PyObject[] { new PyString(name) });
409: }
410:
411: public static PyObject loadFromCompiled(String name,
412: InputStream stream, String filename) {
413: return createFromPyClass(name, stream, false, filename);
414: }
415:
416: /**
417: * If <code>directoryName</code> is empty, return a correct directory name for a path.
418: * If <code>directoryName</code> is not an empty string, this method returns <code>directoryName</code> unchanged.
419: */
420: public static String defaultEmptyPathDirectory(String directoryName) {
421: // The empty string translates into the current working
422: // directory, which is usually provided on the system property
423: // "user.dir". Don't rely on File's constructor to provide
424: // this correctly.
425: if (directoryName.length() == 0) {
426: directoryName = System.getProperty("user.dir");
427: }
428: return directoryName;
429: }
430:
431: static PyObject loadFromSource(String name, String modName,
432: PyObject entry) {
433: // System.err.println("load-from-source: "+name+" "+modName+" "+entry);
434:
435: int nlen = name.length();
436: String sourceName = "__init__.py";
437: String compiledName = "__init__$py.class";
438: String directoryName = defaultEmptyPathDirectory(entry
439: .toString());
440:
441: // First check for packages
442: File dir = new File(directoryName, name);
443: File sourceFile = new File(dir, sourceName);
444: File compiledFile = new File(dir, compiledName);
445:
446: boolean pkg = (dir.isDirectory() && caseok(dir, name, nlen) && (sourceFile
447: .isFile() || compiledFile.isFile()));
448: if (!pkg) {
449: Py.writeDebug(IMPORT_LOG, "trying source " + dir.getPath());
450: sourceName = name + ".py";
451: compiledName = name + "$py.class";
452: sourceFile = new File(directoryName, sourceName);
453: compiledFile = new File(directoryName, compiledName);
454: } else {
455: PyModule m = addModule(modName);
456: PyObject filename = new PyString(dir.getPath());
457: m.__dict__.__setitem__("__path__", new PyList(
458: new PyObject[] { filename }));
459: m.__dict__.__setitem__("__file__", filename);
460: }
461:
462: if (sourceFile.isFile()
463: && caseok(sourceFile, sourceName, sourceName.length())) {
464: if (compiledFile.isFile()
465: && caseok(compiledFile, compiledName, compiledName
466: .length())) {
467: Py.writeDebug(IMPORT_LOG, "trying precompiled "
468: + compiledFile.getPath());
469: long pyTime = sourceFile.lastModified();
470: long classTime = compiledFile.lastModified();
471: if (classTime >= pyTime) {
472: PyObject ret = createFromPyClass(modName,
473: makeStream(compiledFile), true, sourceFile
474: .getAbsolutePath());
475: if (ret != null) {
476: return ret;
477: }
478: }
479: }
480: return createFromSource(modName, makeStream(sourceFile),
481: sourceFile.getAbsolutePath());
482: }
483: // If no source, try loading precompiled
484: Py.writeDebug(IMPORT_LOG, "trying precompiled with no source"
485: + compiledFile.getPath());
486: if (compiledFile.isFile()
487: && caseok(compiledFile, compiledName, compiledName
488: .length())) {
489: return createFromPyClass(modName, makeStream(compiledFile),
490: true, compiledFile.getAbsolutePath());
491: }
492: return null;
493: }
494:
495: public static boolean caseok(File file, String filename, int namelen) {
496: if (Options.caseok) {
497: return true;
498: }
499: try {
500: File canFile = new File(file.getCanonicalPath());
501: return filename.regionMatches(0, canFile.getName(), 0,
502: namelen);
503: } catch (IOException exc) {
504: return false;
505: }
506: }
507:
508: /**
509: * Load the module by name. Upon loading the module it will be added to
510: * sys.modules.
511: *
512: * @param name the name of the module to load
513: * @return the loaded module
514: */
515: public static PyObject load(String name) {
516: return import_first(name, new StringBuffer());
517: }
518:
519: /**
520: * Find the parent module name for a module. If __name__ does not exist in
521: * the module then the parent is null. If __name__ does exist then the
522: * __path__ is checked for the parent module. For example, the __name__
523: * 'a.b.c' would return 'a.b'.
524: *
525: * @param dict the __dict__ of a loaded module
526: * @return the parent name for a module
527: */
528: private static String getParent(PyObject dict) {
529: PyObject tmp = dict.__finditem__("__name__");
530: if (tmp == null) {
531: return null;
532: }
533: String name = tmp.toString();
534:
535: tmp = dict.__finditem__("__path__");
536: if (tmp != null && tmp instanceof PyList) {
537: return name.intern();
538: } else {
539: int dot = name.lastIndexOf('.');
540: if (dot == -1) {
541: return null;
542: }
543: return name.substring(0, dot).intern();
544: }
545: }
546:
547: /**
548: *
549: * @param mod a previously loaded module
550: * @param parentNameBuffer
551: * @param name the name of the module to load
552: * @return null or None
553: */
554: private static PyObject import_next(PyObject mod,
555: StringBuffer parentNameBuffer, String name,
556: String outerFullName, PyObject fromlist) {
557: if (parentNameBuffer.length() > 0) {
558: parentNameBuffer.append('.');
559: }
560: parentNameBuffer.append(name);
561:
562: String fullName = parentNameBuffer.toString().intern();
563:
564: PyObject modules = Py.getSystemState().modules;
565: PyObject ret = modules.__finditem__(fullName);
566: if (ret != null) {
567: return ret;
568: }
569: if (mod == null) {
570: ret = find_module(fullName.intern(), name, null);
571: } else {
572: ret = mod.impAttr(name.intern());
573: }
574: if (ret == null || ret == Py.None) {
575: if (JavaImportHelper.tryAddPackage(outerFullName, fromlist)) {
576: ret = modules.__finditem__(fullName);
577: }
578: return ret;
579: }
580: if (modules.__finditem__(fullName) == null) {
581: modules.__setitem__(fullName, ret);
582: } else {
583: ret = modules.__finditem__(fullName);
584: }
585: return ret;
586: }
587:
588: // never returns null or None
589: private static PyObject import_first(String name,
590: StringBuffer parentNameBuffer) {
591: PyObject ret = import_next(null, parentNameBuffer, name, null,
592: null);
593: if (ret == null || ret == Py.None) {
594: throw Py.ImportError("no module named " + name);
595: }
596: return ret;
597: }
598:
599: private static PyObject import_first(String name,
600: StringBuffer parentNameBuffer, String fullName,
601: PyObject fromlist) {
602: PyObject ret = import_next(null, parentNameBuffer, name,
603: fullName, fromlist);
604: if (ret == null || ret == Py.None) {
605: if (JavaImportHelper.tryAddPackage(fullName, fromlist)) {
606: ret = import_next(null, parentNameBuffer, name,
607: fullName, fromlist);
608: }
609: }
610: if (ret == null || ret == Py.None) {
611: throw Py.ImportError("no module named " + name);
612: }
613: return ret;
614: }
615:
616: // Hierarchy-recursively search for dotted name in mod;
617: // never returns null or None
618: // ??pending: check if result is really a module/jpkg/jclass?
619: private static PyObject import_logic(PyObject mod,
620: StringBuffer parentNameBuffer, String dottedName,
621: String fullName, PyObject fromlist) {
622: int dot = 0;
623: int last_dot = 0;
624:
625: do {
626: String name;
627: dot = dottedName.indexOf('.', last_dot);
628: if (dot == -1) {
629: name = dottedName.substring(last_dot);
630: } else {
631: name = dottedName.substring(last_dot, dot);
632: }
633: mod = import_next(mod, parentNameBuffer, name, fullName,
634: fromlist);
635: if (mod == null || mod == Py.None) {
636: throw Py.ImportError("no module named " + name);
637: }
638: last_dot = dot + 1;
639: } while (dot != -1);
640:
641: return mod;
642: }
643:
644: /**
645: * Most similar to import.c:import_module_ex.
646: *
647: * @param name
648: * @param top
649: * @param modDict
650: * @return a module
651: */
652: private static PyObject import_name(String name, boolean top,
653: PyObject modDict, PyObject fromlist) {
654: // System.err.println("import_name " + name);
655: if (name.length() == 0) {
656: throw Py.ValueError("Empty module name");
657: }
658: PyObject modules = Py.getSystemState().modules;
659: PyObject pkgMod = null;
660: String pkgName = null;
661: if (modDict != null && !(modDict instanceof PyNone)) {
662: pkgName = getParent(modDict);
663: pkgMod = modules.__finditem__(pkgName);
664: // System.err.println("GetParent: " + pkgName + " => " + pkgMod);
665: if (pkgMod != null && !(pkgMod instanceof PyModule)) {
666: pkgMod = null;
667: }
668: }
669: int dot = name.indexOf('.');
670: String firstName;
671: if (dot == -1) {
672: firstName = name;
673: } else {
674: firstName = name.substring(0, dot);
675: }
676: StringBuffer parentNameBuffer = new StringBuffer(
677: pkgMod != null ? pkgName : "");
678: PyObject topMod = import_next(pkgMod, parentNameBuffer,
679: firstName, name, fromlist);
680: if (topMod == Py.None || topMod == null) {
681: // Add None to sys.modules for submodule or subpackage names that aren't found, but
682: // leave top-level entries out. This allows them to be tried again if another
683: // import attempt is made after they've been added to sys.path.
684: if (topMod == null && pkgMod != null) {
685: modules.__setitem__(parentNameBuffer.toString()
686: .intern(), Py.None);
687: }
688: parentNameBuffer = new StringBuffer("");
689: // could throw ImportError
690: topMod = import_first(firstName, parentNameBuffer, name,
691: fromlist);
692: }
693: PyObject mod = topMod;
694: if (dot != -1) {
695: // could throw ImportError
696: mod = import_logic(topMod, parentNameBuffer, name
697: .substring(dot + 1), name, fromlist);
698: }
699: if (top) {
700: return topMod;
701: }
702: return mod;
703: }
704:
705: /**
706: * Import a module by name.
707: *
708: * @param name the name of the package to import
709: * @param top if true, return the top module in the name, otherwise the last
710: * @return an imported module (Java or Python)
711: */
712: public static PyObject importName(String name, boolean top) {
713: return import_name(name, top, null, null);
714: }
715:
716: /**
717: * Import a module by name. This is the default call for
718: * __builtin__.__import__.
719: *
720: * @param name the name of the package to import
721: * @param top if true, return the top module in the name, otherwise the last
722: * @param modDict the __dict__ of an already imported module
723: * @return an imported module (Java or Python)
724: */
725: public synchronized static PyObject importName(String name,
726: boolean top, PyObject modDict, PyObject fromlist) {
727: return import_name(name, top, modDict, fromlist);
728: }
729:
730: /**
731: * Called from jython generated code when a statement like "import spam" is
732: * executed.
733: */
734: public static PyObject importOne(String mod, PyFrame frame) {
735: // System.out.println("importOne(" + mod + ")");
736: PyObject module = __builtin__.__import__(mod, frame.f_globals,
737: frame.getf_locals(), Py.EmptyTuple);
738: /*
739: * int dot = mod.indexOf('.'); if (dot != -1) { mod = mod.substring(0,
740: * dot).intern(); }
741: */
742: // System.err.println("mod: "+mod+", "+dot);
743: return module;
744: }
745:
746: /**
747: * Called from jython generated code when a statement like "import spam as
748: * foo" is executed.
749: */
750: public static PyObject importOneAs(String mod, PyFrame frame) {
751: // System.out.println("importOne(" + mod + ")");
752: PyObject module = __builtin__.__import__(mod, frame.f_globals,
753: frame.getf_locals(), getStarArg());
754: // frame.setlocal(asname, module);
755: return module;
756: }
757:
758: /**
759: * Called from jython generated code when a stamenet like "from spam.eggs
760: * import foo, bar" is executed.
761: */
762: public static PyObject[] importFrom(String mod, String[] names,
763: PyFrame frame) {
764: return importFromAs(mod, names, null, frame);
765: }
766:
767: /**
768: * Called from jython generated code when a statement like "from spam.eggs
769: * import foo as spam" is executed.
770: */
771: public static PyObject[] importFromAs(String mod, String[] names,
772: String[] asnames, PyFrame frame) {
773: // StringBuffer sb = new StringBuffer();
774: // for(int i=0; i<names.length; i++)
775: // sb.append(names[i] + " ");
776: // System.out.println("importFrom(" + mod + ", [" + sb + "]");
777:
778: PyObject[] pynames = new PyObject[names.length];
779: for (int i = 0; i < names.length; i++)
780: pynames[i] = Py.newString(names[i]);
781:
782: PyObject module = __builtin__.__import__(mod, frame.f_globals,
783: frame.getf_locals(), new PyTuple(pynames));
784: PyObject[] submods = new PyObject[names.length];
785: List wrongNames = new ArrayList(1);
786: for (int i = 0; i < names.length; i++) {
787: PyObject submod = module.__findattr__(names[i]);
788: if (submod == null) {
789: if (module instanceof PyJavaPackage) {
790: if (JavaImportHelper.tryAddPackage(mod + "."
791: + names[i], null)) {
792: submod = module.__findattr__(names[i]);
793: }
794: }
795: }
796: if (submod == null) {
797: wrongNames.add(names[i]);
798: } else {
799: submods[i] = submod;
800: }
801: }
802: int size = wrongNames.size();
803: if (size > 0) {
804: StringBuffer buf = new StringBuffer(20);
805: buf.append("cannot import name");
806: if (size > 1) {
807: buf.append("s");
808: }
809: Iterator wrongNamesIterator = wrongNames.iterator();
810: buf.append(" ");
811: buf.append(wrongNamesIterator.next());
812: while (wrongNamesIterator.hasNext()) {
813: buf.append(", ");
814: buf.append(wrongNamesIterator.next());
815: }
816: throw Py.ImportError(buf.toString());
817: }
818: return submods;
819: }
820:
821: private static PyTuple all = null;
822:
823: private synchronized static PyTuple getStarArg() {
824: if (all == null) {
825: all = new PyTuple(new PyString[] { Py.newString('*') });
826: }
827: return all;
828: }
829:
830: /**
831: * Called from jython generated code when a statement like "from spam.eggs
832: * import *" is executed.
833: */
834: public static void importAll(String mod, PyFrame frame) {
835: // System.out.println("importAll(" + mod + ")");
836: PyObject module = __builtin__.__import__(mod, frame.f_globals,
837: frame.getf_locals(), getStarArg());
838: PyObject names;
839: boolean filter = true;
840: if (module instanceof PyJavaPackage) {
841: names = ((PyJavaPackage) module).fillDir();
842: } else {
843: PyObject __all__ = module.__findattr__("__all__");
844: if (__all__ != null) {
845: names = __all__;
846: filter = false;
847: } else {
848: names = module.__dir__();
849: }
850: }
851:
852: loadNames(names, module, frame.getf_locals(), filter);
853: }
854:
855: /**
856: * From a module, load the attributes found in <code>names</code> into
857: * locals.
858: *
859: * @param filter if true, if the name starts with an underscore '_' do not
860: * add it to locals
861: * @param locals the namespace into which names will be loaded
862: * @param names the names to load from the module
863: * @param module the fully imported module
864: */
865: private static void loadNames(PyObject names, PyObject module,
866: PyObject locals, boolean filter) {
867: PyObject iter = names.__iter__();
868: for (PyObject name; (name = iter.__iternext__()) != null;) {
869: String sname = ((PyString) name).internedString();
870: if (filter && sname.startsWith("_")) {
871: continue;
872: } else {
873: try {
874: locals
875: .__setitem__(sname, module
876: .__getattr__(sname));
877: } catch (Exception exc) {
878: continue;
879: }
880: }
881: }
882: }
883:
884: /* Reloading */
885: static PyObject reload(PyJavaClass c) {
886: // This is a dummy placeholder for the feature that allow
887: // reloading of java classes. But this feature does not yet
888: // work.
889: return c;
890: }
891:
892: static PyObject reload(PyModule m) {
893: String name = m.__getattr__("__name__").toString().intern();
894:
895: PyObject modules = Py.getSystemState().modules;
896: PyModule nm = (PyModule) modules.__finditem__(name);
897:
898: if (nm == null
899: || !nm.__getattr__("__name__").toString().equals(name)) {
900: throw Py.ImportError("reload(): module " + name
901: + " not in sys.modules");
902: }
903:
904: PyList path = Py.getSystemState().path;
905: String modName = name;
906: int dot = name.lastIndexOf('.');
907: if (dot != -1) {
908: String iname = name.substring(0, dot).intern();
909: PyObject pkg = modules.__finditem__(iname);
910: if (pkg == null) {
911: throw Py
912: .ImportError("reload(): parent not in sys.modules");
913: }
914: path = (PyList) pkg.__getattr__("__path__");
915: name = name.substring(dot + 1, name.length()).intern();
916: }
917:
918: // This should be better "protected"
919: // ((PyStringMap)nm.__dict__).clear();
920:
921: nm.__setattr__("__name__", new PyString(modName));
922: PyObject ret = find_module(name, modName, path);
923: modules.__setitem__(modName, ret);
924: return ret;
925: }
926: }
|