// Copyright (c) Corporation for National Research Initiatives
package org.python.core;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.locks.ReentrantLock;
import org.python.compiler.Module;
import org.python.core.util.FileUtil;
import org.python.core.util.PlatformUtil;
/**
* Utility functions for "import" support.
*/
public class imp {
private static final String IMPORT_LOG = "import";
private static final String UNKNOWN_SOURCEFILE = "<unknown>";
private static final int APIVersion = 32;
public static final int NO_MTIME = -1;
// This should change to 0 for Python 2.7 and 3.0 see PEP 328
public static final int DEFAULT_LEVEL = -1;
/** A non-empty fromlist for __import__'ing sub-modules. */
private static final PyObject nonEmptyFromlist = new PyTuple(Py.newString("__doc__"));
/** Synchronizes import operations */
public static final ReentrantLock importLock = new ReentrantLock();
private static Object syspathJavaLoaderLock = new Object();
private static ClassLoader syspathJavaLoader = null;
public static ClassLoader getSyspathJavaLoader() {
synchronized (syspathJavaLoaderLock) {
if (syspathJavaLoader == null) {
syspathJavaLoader = new SyspathJavaLoader(getParentClassLoader());
}
}
return syspathJavaLoader;
}
/**
* Selects the parent class loader for Jython, to be used for
* dynamically loaded classes and resources. Chooses between the
* current and context classloader based on the following
* criteria:
*
* <ul>
* <li>If both are the same classloader, return that classloader.
* <li>If either is null, then the non-null one is selected.
* <li>If both are not null, and a parent/child relationship can
* be determined, then the child is selected.
* <li>If both are not null and not on a parent/child
* relationship, then the current class loader is returned (since
* it is likely for the context class loader to <b>not</b> see the
* Jython classes)
* </ul>
*
* @return the parent class loader for Jython or null if both the
* current and context classloaders are null.
*/
public static ClassLoader getParentClassLoader() {
ClassLoader current = imp.class.getClassLoader();
ClassLoader context = Thread.currentThread().getContextClassLoader();
if (context == current) {
return current;
}
if (context == null) {
return current;
}
if (current == null) {
return context;
}
if (isParentClassLoader(context, current)) {
return current;
}
if (isParentClassLoader(current, context)) {
return context;
}
return current;
}
private static boolean isParentClassLoader(
ClassLoader suspectedParent, ClassLoader child) {
try {
ClassLoader parent = child.getParent();
if (suspectedParent == parent) {
return true;
}
if (parent == null || parent == child) {
// We reached the boot class loader
return false;
}
return isParentClassLoader(suspectedParent, parent);
} catch (SecurityException e) {
return false;
}
}
private imp() {
}
/**
* If the given name is found in sys.modules, the entry from there is
* returned. Otherwise a new PyModule is created for the name and added to
* sys.modules
*/
public static PyModule addModule(String name) {
name = name.intern();
PyObject modules = Py.getSystemState().modules;
PyModule module = (PyModule) modules.__finditem__(name);
if (module != null) {
return module;
}
module = new PyModule(name, null);
modules.__setitem__(name, module);
return module;
}
/**
* Remove name form sys.modules if it's there.
*
* @param name the module name
*/
private static void removeModule(String name) {
name = name.intern();
PyObject modules = Py.getSystemState().modules;
if (modules.__finditem__(name) != null) {
try {
modules.__delitem__(name);
} catch (PyException pye) {
// another thread may have deleted it
if (!pye.match(Py.KeyError)) {
throw pye;
}
}
}
}
private static byte[] readBytes(InputStream fp) {
try {
return FileUtil.readBytes(fp);
} catch(IOException ioe) {
throw Py.IOError(ioe);
} finally {
try {
fp.close();
} catch(IOException e) {
throw Py.IOError(e);
}
}
}
private static InputStream makeStream(File file) {
try {
return new FileInputStream(file);
} catch (IOException ioe) {
throw Py.IOError(ioe);
}
}
static PyObject createFromPyClass(String name, InputStream fp, boolean testing,
String sourceName, String compiledName) {
return createFromPyClass(name, fp, testing, sourceName, compiledName, NO_MTIME);
}
static PyObject createFromPyClass(String name, InputStream fp, boolean testing,
String sourceName, String compiledName, long mtime) {
byte[] data = null;
try {
data = readCode(name, fp, testing, mtime);
} catch (IOException ioe) {
if (!testing) {
throw Py.ImportError(ioe.getMessage() + "[name=" + name + ", source=" + sourceName
+ ", compiled=" + compiledName + "]");
}
}
if (testing && data == null) {
return null;
}
PyCode code;
try {
code = BytecodeLoader.makeCode(name + "$py", data, sourceName);
} catch (Throwable t) {
if (testing) {
return null;
} else {
throw Py.JavaError(t);
}
}
Py.writeComment(IMPORT_LOG, String.format("import %s # precompiled from %s", name,
compiledName));
return createFromCode(name, code, compiledName);
}
public static byte[] readCode(String name, InputStream fp, boolean testing) throws IOException {
return readCode(name, fp, testing, NO_MTIME);
}
public static byte[] readCode(String name, InputStream fp, boolean testing, long mtime) throws IOException {
byte[] data = readBytes(fp);
int api;
AnnotationReader ar = new AnnotationReader(data);
api = ar.getVersion();
if (api != APIVersion) {
if (testing) {
return null;
} else {
throw Py.ImportError("invalid api version(" + api + " != "
+ APIVersion + ") in: " + name);
}
}
if (testing && mtime != NO_MTIME) {
long time = ar.getMTime();
if (mtime != time) {
return null;
}
}
return data;
}
public static byte[] compileSource(String name, File file) {
return compileSource(name, file, null);
}
public static byte[] compileSource(String name, File file, String sourceFilename) {
return compileSource(name, file, sourceFilename, null);
}
public static byte[] compileSource(String name, File file, String sourceFilename,
String compiledFilename) {
if (sourceFilename == null) {
sourceFilename = file.toString();
}
long mtime = file.lastModified();
return compileSource(name, makeStream(file), sourceFilename, mtime);
}
public static String makeCompiledFilename(String filename) {
return filename.substring(0, filename.length() - 3) + "$py.class";
}
/**
* Stores the bytes in compiledSource in compiledFilename.
*
* If compiledFilename is null, it's set to the results of
* makeCompiledFilename(sourcefileName).
*
* If sourceFilename is null or set to UNKNOWN_SOURCEFILE, then
* null is returned.
*
* @return the compiledFilename eventually used; or null if a
* compiledFilename couldn't be determined or if an error
* was thrown while writing to the cache file.
*/
public static String cacheCompiledSource(String sourceFilename,
String compiledFilename,
byte[] compiledSource) {
if(compiledFilename == null){
if(sourceFilename == null || sourceFilename.equals(UNKNOWN_SOURCEFILE)){
return null;
}
compiledFilename = makeCompiledFilename(sourceFilename);
}
FileOutputStream fop = null;
try {
SecurityManager man = System.getSecurityManager();
if (man != null) {
man.checkWrite(compiledFilename);
}
fop = new FileOutputStream(compiledFilename);
fop.write(compiledSource);
fop.close();
return compiledFilename;
} catch(IOException exc) {
// If we can't write the cache file, just log and continue
Py.writeDebug(IMPORT_LOG, "Unable to write to source cache file '"
+ compiledFilename + "' due to " + exc);
return null;
} catch(SecurityException exc) {
// If we can't write the cache file, just log and continue
Py.writeDebug(IMPORT_LOG, "Unable to write to source cache file '"
+ compiledFilename + "' due to " + exc);
return null;
} finally {
if(fop != null) {
try {
fop.close();
} catch(IOException e) {
Py.writeDebug(IMPORT_LOG,
"Unable to close source cache file '"
+ compiledFilename + "' due to " + e);
}
}
}
}
public static byte[] compileSource(String name, InputStream fp, String filename) {
return compileSource(name, fp, filename, NO_MTIME);
}
public static byte[] compileSource(String name, InputStream fp, String filename, long mtime) {
ByteArrayOutputStream ofp = new ByteArrayOutputStream();
try {
if(filename == null) {
filename = UNKNOWN_SOURCEFILE;
}
org.python.antlr.base.mod node;
try {
node = ParserFacade.parse(fp, CompileMode.exec, filename, new CompilerFlags());
} finally {
fp.close();
}
Module.compile(node, ofp, name + "$py", filename, true, false, null, mtime);
return ofp.toByteArray();
} catch(Throwable t) {
throw ParserFacade.fixParseError(null, t, filename);
}
}
public static PyObject createFromSource(String name, InputStream fp, String filename) {
return createFromSource(name, fp, filename, null, NO_MTIME);
}
public static PyObject createFromSource(String name, InputStream fp,
String filename, String outFilename) {
return createFromSource(name, fp, filename, outFilename, NO_MTIME);
}
public static PyObject createFromSource(String name, InputStream fp,
String filename, String outFilename, long mtime) {
byte[] bytes = compileSource(name, fp, filename, mtime);
outFilename = cacheCompiledSource(filename, outFilename, bytes);
Py.writeComment(IMPORT_LOG, "'" + name + "' as " + filename);
PyCode code = BytecodeLoader.makeCode(name + "$py", bytes, filename);
return createFromCode(name, code, filename);
}
/**
* Returns a module with the given name whose contents are the results of
* running c. __file__ is set to whatever is in c.
*/
public static PyObject createFromCode(String name, PyCode c){
return createFromCode(name, c, null);
}
/**
* Returns a module with the given name whose contents are the results of
* running c. Sets __file__ on the module to be moduleLocation unless
* moduleLocation is null. If c comes from a local .py file or compiled
* $py.class class moduleLocation should be the result of running new
* File(moduleLocation).getAbsoultePath(). If c comes from a remote file or
* is a jar moduleLocation should be the full uri for c.
*/
public static PyObject createFromCode(String name, PyCode c, String moduleLocation) {
PyModule module = addModule(name);
PyTableCode code = null;
if (c instanceof PyTableCode) {
code = (PyTableCode) c;
}
if (moduleLocation != null) {
module.__setattr__("__file__", new PyString(moduleLocation));
} else if (module.__findattr__("__file__") == null) {
// Should probably never happen (but maybe with an odd custom builtins, or
// Java Integration)
Py.writeDebug(IMPORT_LOG, String.format("Warning: %s __file__ is unknown", name));
}
try {
PyFrame f = new PyFrame(code, module.__dict__, module.__dict__, null);
code.call(Py.getThreadState(), f);
} catch (RuntimeException t) {
removeModule(name);
throw t;
}
return module;
}
static PyObject createFromClass(String name, Class<?> c) {
// Two choices. c implements PyRunnable or c is Java package
if (PyRunnable.class.isAssignableFrom(c)) {
try {
return createFromCode(name, ((PyRunnable)c.newInstance()).getMain());
} catch (InstantiationException e) {
throw Py.JavaError(e);
} catch (IllegalAccessException e) {
throw Py.JavaError(e);
}
}
return PyType.fromClass(c, false); // xxx?
}
static PyObject getPathImporter(PyObject cache, PyList hooks, PyObject p) {
// attempt to get an importer for the path
// use null as default value since Py.None is
// a valid value in the cache for the default
// importer
PyObject importer = cache.__finditem__(p);
if (importer != null) {
return importer;
}
// nothing in the cache, so check all hooks
PyObject iter = hooks.__iter__();
for (PyObject hook; (hook = iter.__iternext__()) != null;) {
try {
importer = hook.__call__(p);
break;
} catch (PyException e) {
if (!e.match(Py.ImportError)) {
throw e;
}
}
}
importer = (importer == null ? Py.None : importer);
cache.__setitem__(p, importer);
return importer;
}
static PyObject find_module(String name, String moduleName, PyList path) {
PyObject loader = Py.None;
PySystemState sys = Py.getSystemState();
PyObject metaPath = sys.meta_path;
for (PyObject importer : metaPath.asIterable()) {
PyObject findModule = importer.__getattr__("find_module");
loader = findModule.__call__(new PyObject[] {
new PyString(moduleName), path == null ? Py.None : path });
if (loader != Py.None) {
return loadFromLoader(loader, moduleName);
}
}
PyObject ret = loadBuiltin(moduleName);
if (ret != null) {
return ret;
}
path = path == null ? sys.path : path;
for (int i = 0; i < path.__len__(); i++) {
PyObject p = path.__getitem__(i);
PyObject importer = getPathImporter(sys.path_importer_cache,
sys.path_hooks, p);
if (importer != Py.None) {
PyObject findModule = importer.__getattr__("find_module");
loader = findModule.__call__(new PyObject[] { new PyString(
moduleName) });
if (loader != Py.None) {
return loadFromLoader(loader, moduleName);
}
}
if (!(p instanceof PyUnicode)) {
p = p.__str__();
}
ret = loadFromSource(sys, name, moduleName, p.toString());
if (ret != null) {
return ret;
}
}
return ret;
}
private static PyObject loadBuiltin(String name) {
if (name == "sys") {
Py.writeComment(IMPORT_LOG, "'" + name + "' as sys in builtin modules");
return Py.java2py(Py.getSystemState());
}
if (name == "__builtin__") {
Py.writeComment(IMPORT_LOG, "'" + name + "' as __builtin__ in builtin modules");
return new PyModule("__builtin__", PySystemState.builtins);
}
String mod = PySystemState.getBuiltin(name);
if (mod != null) {
Class c = Py.findClassEx(mod, "builtin modules");
if (c != null) {
Py.writeComment(IMPORT_LOG, "'" + name + "' as " + mod
+ " in builtin modules");
try {
if (PyObject.class.isAssignableFrom(c)) { // xxx ok?
return PyType.fromClass(c);
}
return createFromClass(name, c);
} catch (NoClassDefFoundError e) {
throw Py.ImportError("Cannot import " + name
+ ", missing class " + c.getName());
}
}
}
return null;
}
static PyObject loadFromLoader(PyObject importer, String name) {
PyObject load_module = importer.__getattr__("load_module");
return load_module.__call__(new PyObject[] { new PyString(name) });
}
public static PyObject loadFromCompiled(String name, InputStream stream, String sourceName,
String compiledName) {
return createFromPyClass(name, stream, false, sourceName, compiledName);
}
static PyObject loadFromSource(PySystemState sys, String name, String modName, String entry) {
String dirName = sys.getPath(entry);
String sourceName = "__init__.py";
String compiledName = "__init__$py.class";
// display names are for identification purposes (e.g. __file__): when entry is
// null it forces java.io.File to be a relative path (e.g. foo/bar.py instead of
// /tmp/foo/bar.py)
String displayDirName = entry.equals("") ? null : entry.toString();
String displaySourceName = new File(new File(displayDirName, name), sourceName).getPath();
String displayCompiledName = new File(new File(displayDirName, name),
compiledName).getPath();
// First check for packages
File dir = new File(dirName, name);
File sourceFile = new File(dir, sourceName);
File compiledFile = new File(dir, compiledName);
boolean pkg = false;
try {
pkg = dir.isDirectory() && caseok(dir, name)
&& (sourceFile.isFile() || compiledFile.isFile());
} catch (SecurityException e) {
// ok
}
if (!pkg) {
Py.writeDebug(IMPORT_LOG, "trying source " + dir.getPath());
sourceName = name + ".py";
compiledName = name + "$py.class";
displaySourceName = new File(displayDirName, sourceName).getPath();
displayCompiledName = new File(displayDirName, compiledName).getPath();
sourceFile = new File(dirName, sourceName);
compiledFile = new File(dirName, compiledName);
} else {
PyModule m = addModule(modName);
PyObject filename = new PyString(new File(displayDirName, name).getPath());
m.__dict__.__setitem__("__path__", new PyList(new PyObject[] {filename}));
}
try {
if (sourceFile.isFile() && caseok(sourceFile, sourceName)) {
long pyTime = sourceFile.lastModified();
if (compiledFile.isFile() && caseok(compiledFile, compiledName)) {
Py.writeDebug(IMPORT_LOG, "trying precompiled " + compiledFile.getPath());
long classTime = compiledFile.lastModified();
if (classTime >= pyTime) {
PyObject ret = createFromPyClass(modName, makeStream(compiledFile), true,
displaySourceName, displayCompiledName, pyTime);
if (ret != null) {
return ret;
}
}
return createFromSource(modName, makeStream(sourceFile), displaySourceName,
compiledFile.getPath(), pyTime);
}
return createFromSource(modName, makeStream(sourceFile), displaySourceName,
compiledFile.getPath(), pyTime);
}
// If no source, try loading precompiled
Py.writeDebug(IMPORT_LOG, "trying precompiled with no source " + compiledFile.getPath());
if (compiledFile.isFile() && caseok(compiledFile, compiledName)) {
return createFromPyClass(modName, makeStream(compiledFile), true, displaySourceName,
displayCompiledName);
}
} catch (SecurityException e) {
// ok
}
return null;
}
public static boolean caseok(File file, String filename) {
if (Options.caseok || !PlatformUtil.isCaseInsensitive()) {
return true;
}
try {
File canFile = new File(file.getCanonicalPath());
boolean match = filename.regionMatches(0, canFile.getName(), 0, filename.length());
if (!match) {
//possibly a symlink. Get parent and look for exact match in listdir()
//This is what CPython does in the case of Mac OS X and Cygwin.
//XXX: This will be a performance hit, maybe jdk7 nio2 can give us a better
// method?
File parent = file.getParentFile();
String[] children = parent.list();
for (String c: children) {
if (c.equals(filename)) {
return true;
}
}
}
return match;
} catch (IOException exc) {
return false;
}
}
/**
* Load the module by name. Upon loading the module it will be added to
* sys.modules.
*
* @param name the name of the module to load
* @return the loaded module
*/
public static PyObject load(String name) {
return import_first(name, new StringBuilder());
}
/**
* Find the parent package name for a module.
*
* If __name__ does not exist in the module or if level is <code>0</code>,
* then the parent is <code>null</code>. If __name__ does exist and is not a
* package name, the containing package is located. If no such package
* exists and level is <code>-1</code>, the parent is <code>null</code>. If
* level is <code>-1</code>, the parent is the current name. Otherwise,
* <code>level-1</code> doted parts are stripped from the current name. For
* example, the __name__ <code>"a.b.c"</code> and level <code>2</code> would
* return <code>"a.b"</code>, if <code>c</code> is a package and would
* return <code>"a"</code>, if <code>c</code> is not a package.
*
* @param dict
* the __dict__ of a loaded module
* @param level
* used for relative and absolute imports. -1 means try both, 0
* means absolute only, positive ints represent the level to look
* upward for a relative path (1 means current package, 2 means
* one level up). See PEP 328 at
* http://www.python.org/dev/peps/pep-0328/
*
* @return the parent name for a module
*/
private static String getParent(PyObject dict, int level) {
if (dict == null || level == 0) {
// try an absolute import
return null;
}
PyObject tmp = dict.__finditem__("__name__");
if (tmp == null) {
return null;
}
String name = tmp.toString();
// locate the current package
tmp = dict.__finditem__("__path__");
if (! (tmp instanceof PyList)) {
// __name__ is not a package name, try one level upwards.
int dot = name.lastIndexOf('.');
if (dot == -1) {
if (level <= -1) {
// there is no package, perform an absolute search
return null;
}
throw Py.ValueError("Attempted relative import in non-package");
}
// name should be the package name.
name = name.substring(0, dot);
}
// walk upwards if required (level >= 2)
while (level-- > 1) {
int dot = name.lastIndexOf('.');
if (dot == -1) {
throw Py.ValueError("Attempted relative import beyond toplevel package");
}
name = name.substring(0, dot);
}
return name.intern();
}
/**
*
* @param mod a previously loaded module
* @param parentNameBuffer
* @param name the name of the module to load
* @return null or None
*/
private static PyObject import_next(PyObject mod,
StringBuilder parentNameBuffer, String name, String outerFullName, PyObject fromlist) {
if (parentNameBuffer.length() > 0 && name != null && name.length() > 0) {
parentNameBuffer.append('.');
}
parentNameBuffer.append(name);
String fullName = parentNameBuffer.toString().intern();
PyObject modules = Py.getSystemState().modules;
PyObject ret = modules.__finditem__(fullName);
if (ret != null) {
return ret;
}
if (mod == null) {
ret = find_module(fullName.intern(), name, null);
} else {
ret = mod.impAttr(name.intern());
}
if (ret == null || ret == Py.None) {
if (JavaImportHelper.tryAddPackage(outerFullName, fromlist)) {
ret = modules.__finditem__(fullName);
}
return ret;
}
if (modules.__finditem__(fullName) == null) {
modules.__setitem__(fullName, ret);
} else {
ret = modules.__finditem__(fullName);
}
return ret;
}
// never returns null or None
private static PyObject import_first(String name,
StringBuilder parentNameBuffer) {
PyObject ret = import_next(null, parentNameBuffer, name, null, null);
if (ret == null || ret == Py.None) {
throw Py.ImportError("No module named " + name);
}
return ret;
}
private static PyObject import_first(String name, StringBuilder parentNameBuffer, String fullName, PyObject fromlist) {
PyObject ret = import_next(null, parentNameBuffer, name, fullName, fromlist);
if (ret == null || ret == Py.None) {
if (JavaImportHelper.tryAddPackage(fullName, fromlist)) {
ret = import_next(null, parentNameBuffer, name, fullName, fromlist);
}
}
if (ret == null || ret == Py.None) {
throw Py.ImportError("No module named " + name);
}
return ret;
}
// Hierarchy-recursively search for dotted name in mod;
// never returns null or None
// ??pending: check if result is really a module/jpkg/jclass?
private static PyObject import_logic(PyObject mod,
StringBuilder parentNameBuffer, String dottedName, String fullName, PyObject fromlist) {
int dot = 0;
int last_dot = 0;
do {
String name;
dot = dottedName.indexOf('.', last_dot);
if (dot == -1) {
name = dottedName.substring(last_dot);
} else {
name = dottedName.substring(last_dot, dot);
}
PyJavaPackage jpkg = null;
if (mod instanceof PyJavaPackage) {
jpkg = (PyJavaPackage)mod;
}
mod = import_next(mod, parentNameBuffer, name, fullName, fromlist);
if (jpkg != null && (mod == null || mod == Py.None)) {
// try again -- under certain circumstances a PyJavaPackage may
// have been added as a side effect of the last import_next
// attempt. see Lib/test_classpathimport.py#test_bug1126
mod = import_next(jpkg, parentNameBuffer, name, fullName, fromlist);
}
if (mod == null || mod == Py.None) {
throw Py.ImportError("No module named " + name);
}
last_dot = dot + 1;
} while (dot != -1);
return mod;
}
/**
* Most similar to import.c:import_module_ex.
*
* @param name
* @param top
* @param modDict
* @return a module
*/
private static PyObject import_name(String name, boolean top,
PyObject modDict, PyObject fromlist, int level) {
if (name.length() == 0 && level <= 0) {
throw Py.ValueError("Empty module name");
}
PyObject modules = Py.getSystemState().modules;
PyObject pkgMod = null;
String pkgName = null;
if (modDict != null && !(modDict instanceof PyNone)) {
pkgName = getParent(modDict, level);
pkgMod = modules.__finditem__(pkgName);
if (pkgMod != null && !(pkgMod instanceof PyModule)) {
pkgMod = null;
}
}
int dot = name.indexOf('.');
String firstName;
if (dot == -1) {
firstName = name;
} else {
firstName = name.substring(0, dot);
}
StringBuilder parentNameBuffer = new StringBuilder(pkgMod != null ? pkgName : "");
PyObject topMod = import_next(pkgMod, parentNameBuffer, firstName, name, fromlist);
if (topMod == Py.None || topMod == null) {
// Add None to sys.modules for submodule or subpackage names that aren't found, but
// leave top-level entries out. This allows them to be tried again if another
// import attempt is made after they've been added to sys.path.
if (topMod == null && pkgMod != null) {
modules.__setitem__(parentNameBuffer.toString().intern(), Py.None);
}
parentNameBuffer = new StringBuilder("");
// could throw ImportError
topMod = import_first(firstName, parentNameBuffer, name, fromlist);
}
PyObject mod = topMod;
if (dot != -1) {
// could throw ImportError
mod = import_logic(topMod, parentNameBuffer, name
.substring(dot + 1), name, fromlist);
}
if (top) {
return topMod;
}
if (fromlist != null && fromlist != Py.None) {
StringBuilder modNameBuffer = new StringBuilder(name);
for (PyObject submodName : fromlist.asIterable()) {
if (mod.__findattr__(submodName.toString()) != null
|| submodName.toString().equals("*")) {
continue;
}
String fullName = modNameBuffer.toString() + "." + submodName.toString();
import_next(mod, modNameBuffer, submodName.toString(), fullName, null);
}
}
return mod;
}
/**
* Import a module by name.
*
* @param name the name of the package to import
* @param top if true, return the top module in the name, otherwise the last
* @return an imported module (Java or Python)
*/
public static PyObject importName(String name, boolean top) {
return import_name(name, top, null, null, DEFAULT_LEVEL);
}
/**
* Import a module by name. This is the default call for
* __builtin__.__import__.
*
* @param name the name of the package to import
* @param top if true, return the top module in the name, otherwise the last
* @param modDict the __dict__ of an already imported module
* @return an imported module (Java or Python)
*/
public static PyObject importName(String name, boolean top,
PyObject modDict, PyObject fromlist, int level) {
importLock.lock();
try {
return import_name(name, top, modDict, fromlist, level);
} finally {
importLock.unlock();
}
}
/**
* Called from jython generated code when a statement like "import spam" is
* executed.
*/
@Deprecated
public static PyObject importOne(String mod, PyFrame frame) {
return importOne(mod, frame, imp.DEFAULT_LEVEL);
}
/**
* Called from jython generated code when a statement like "import spam" is
* executed.
*/
public static PyObject importOne(String mod, PyFrame frame, int level) {
PyObject module = __builtin__.__import__(mod, frame.f_globals, frame
.getLocals(), Py.None, level);
return module;
}
/**
* Called from jython generated code when a statement like "import spam as
* foo" is executed.
*/
@Deprecated
public static PyObject importOneAs(String mod, PyFrame frame) {
return importOneAs(mod, frame, imp.DEFAULT_LEVEL);
}
/**
* Called from jython generated code when a statement like "import spam as
* foo" is executed.
*/
public static PyObject importOneAs(String mod, PyFrame frame, int level) {
PyObject module = __builtin__.__import__(mod, frame.f_globals, frame
.getLocals(), Py.None, level);
int dot = mod.indexOf('.');
while (dot != -1) {
int dot2 = mod.indexOf('.', dot + 1);
String name;
if (dot2 == -1) {
name = mod.substring(dot + 1);
} else {
name = mod.substring(dot + 1, dot2);
}
module = module.__getattr__(name);
dot = dot2;
}
return module;
}
/**
* replaced by importFrom with level param. Kept for backwards compatibility.
* @deprecated use importFrom with level param.
*/
@Deprecated
public static PyObject[] importFrom(String mod, String[] names,
PyFrame frame) {
return importFromAs(mod, names, null, frame, DEFAULT_LEVEL);
}
/**
* Called from jython generated code when a statement like "from spam.eggs
* import foo, bar" is executed.
*/
public static PyObject[] importFrom(String mod, String[] names,
PyFrame frame, int level) {
return importFromAs(mod, names, null, frame, level);
}
/**
* replaced by importFromAs with level param. Kept for backwards compatibility.
* @deprecated use importFromAs with level param.
*/
@Deprecated
public static PyObject[] importFromAs(String mod, String[] names,
PyFrame frame) {
return importFromAs(mod, names, null, frame, DEFAULT_LEVEL);
}
/**
* Called from jython generated code when a statement like "from spam.eggs
* import foo as spam" is executed.
*/
public static PyObject[] importFromAs(String mod, String[] names,
String[] asnames, PyFrame frame, int level) {
PyObject[] pyNames = new PyObject[names.length];
for (int i = 0; i < names.length; i++) {
pyNames[i] = Py.newString(names[i]);
}
PyObject module = __builtin__.__import__(mod, frame.f_globals, frame.getLocals(),
new PyTuple(pyNames), level);
PyObject[] submods = new PyObject[names.length];
for (int i = 0; i < names.length; i++) {
PyObject submod = module.__findattr__(names[i]);
if (submod == null) {
throw Py.ImportError("cannot import name " + names[i]);
}
submods[i] = submod;
}
return submods;
}
private final static PyTuple all = new PyTuple(Py.newString('*'));
/**
* Called from jython generated code when a statement like "from spam.eggs
* import *" is executed.
*/
public static void importAll(String mod, PyFrame frame, int level) {
PyObject module = __builtin__.__import__(mod, frame.f_globals, frame
.getLocals(), all, level);
importAll(module, frame);
}
@Deprecated
public static void importAll(String mod, PyFrame frame) {
importAll(mod, frame, DEFAULT_LEVEL);
}
public static void importAll(PyObject module, PyFrame frame) {
PyObject names;
boolean filter = true;
if (module instanceof PyJavaPackage) {
names = ((PyJavaPackage) module).fillDir();
} else {
PyObject __all__ = module.__findattr__("__all__");
if (__all__ != null) {
names = __all__;
filter = false;
} else {
names = module.__dir__();
}
}
loadNames(names, module, frame.getLocals(), filter);
}
/**
* From a module, load the attributes found in <code>names</code> into
* locals.
*
* @param filter if true, if the name starts with an underscore '_' do not
* add it to locals
* @param locals the namespace into which names will be loaded
* @param names the names to load from the module
* @param module the fully imported module
*/
private static void loadNames(PyObject names, PyObject module,
PyObject locals, boolean filter) {
for (PyObject name : names.asIterable()) {
String sname = ((PyString) name).internedString();
if (filter && sname.startsWith("_")) {
continue;
} else {
try {
PyObject value = module.__findattr__(sname);
if (value == null) {
PyObject nameObj = module.__findattr__("__name__");
if (nameObj != null) {
String submodName = nameObj.__str__().toString() + '.' + sname;
value = __builtin__.__import__(submodName, null, null,
nonEmptyFromlist);
}
}
locals.__setitem__(sname, value);
} catch (Exception exc) {
continue;
}
}
}
}
static PyObject reload(PyModule m) {
String name = m.__getattr__("__name__").toString().intern();
PyObject modules = Py.getSystemState().modules;
PyModule nm = (PyModule) modules.__finditem__(name);
if (nm == null || !nm.__getattr__("__name__").toString().equals(name)) {
throw Py.ImportError("reload(): module " + name
+ " not in sys.modules");
}
PyList path = Py.getSystemState().path;
String modName = name;
int dot = name.lastIndexOf('.');
if (dot != -1) {
String iname = name.substring(0, dot).intern();
PyObject pkg = modules.__finditem__(iname);
if (pkg == null) {
throw Py.ImportError("reload(): parent not in sys.modules");
}
path = (PyList) pkg.__getattr__("__path__");
name = name.substring(dot + 1, name.length()).intern();
}
nm.__setattr__("__name__", new PyString(modName));
PyObject ret = find_module(name, modName, path);
modules.__setitem__(modName, ret);
return ret;
}
public static int getAPIVersion() {
return APIVersion;
}
}