Branch* load_module(const char* module_name, Term* loadCall) { Branch* existing = find_loaded_module(module_name); if (existing != NULL) return existing; Value filename; bool found = find_module_file(module_name, &filename); if (!found) return NULL; Term* import = load_module_from_file(module_name, as_cstring(&filename))->owningTerm; // If a loadCall is provided, possibly move the new import to be before the loadCall. if (loadCall != NULL) { Term* callersModule = find_parent_term_in_branch(loadCall, import->owningBranch); if (callersModule != NULL && (import->index > callersModule->index)) move_before(import, callersModule); } // If the module has static errors, print them now. print_static_errors_formatted(nested_contents(import)); return nested_contents(import); }
/* * name will be the fully-qualified package name in question, but * we are the loader for a given directory (eg. package) so we should * only get this if we are already the correct path for a given module * We cache by fully-qualified name though, since that's what we need * everywhere else. */ PyObject* PyResMgrImportLoader::find_module( const std::string& name ) { // TRACE_MSG( "PyResMgrImportLoader(%s)::find_module: %s\n", path_.c_str(), // name.c_str() ); std::string moduleName = name; std::string::size_type dotPos = name.rfind( "." ); if ( dotPos != std::string::npos ) { moduleName = name.substr( dotPos + 1 ); } moduleCache::const_iterator moduleIt = modules_.find( name ); // If we haven't already cached this module, do so now if ( moduleIt == modules_.end() ) { modules_[ name ] = find_module_file( moduleName, pDirectory_ ); } // Do we have a matching module? if ( modules_[ name ].first == NOT_FOUND ) { Py_Return; } if ( modules_[ name ].first == C_EXTENSION ) { //ERROR_MSG( "PyResMgrImportLoader(%s)::find_module: Can't load module %s " // "as a C extension\n", path_.c_str(), name.c_str() ); Py_Return; } Py_INCREF( this ); return this; }
/** * This static routine identifies a Python module for the given name in * the supplied DataSection, returning the relevant DataSectionPtr and * the type of the module. * * @param name The name of the python module to find * * @param pDirectory The DataSection to locate the module within * * @return A pair of < pythonModuleType, DataSectionPtr > for the requested * module file, or < NOT_FOUND, NULL > if one could not be found. */ PyResMgrImportLoader::moduleCacheEntry PyResMgrImportLoader::find_module_file( const std::string& name, DataSectionPtr pDirectory ) { moduleCacheEntry result; result.first = NOT_FOUND; DataSectionPtr package = pDirectory->findChild( name ); if ( package ) { // packageInit is basically a wasted load here. It'll be needed // soon enough. moduleCacheEntry packgeInit = find_module_file( "__init__", package ); switch( packgeInit.first ) { case PY_SOURCE: case PY_OBJECT: case C_EXTENSION: return std::make_pair( PKG_DIRECTORY, package ); break; case NOT_FOUND: case PKG_DIRECTORY: break; } } suffixLookupMap::const_iterator suffixIt; for ( suffixIt = s_suffixes_.begin(); suffixIt != s_suffixes_.end(); suffixIt++ ) { DataSectionPtr pCandidate = pDirectory->openSection( name + "." + suffixIt->first ); if ( !pCandidate ) continue; // This shouldn't happen... MF_ASSERT( suffixIt->second != PKG_DIRECTORY ); // We have a match, check if it's a better match than any known match if ( suffixIt->second > result.first ) { result.first = suffixIt->second; result.second = pCandidate; } } return result; }
/* * This routine needs to emulate load_package in import.c in * python, but from a DataSectionPtr */ PyObject* PyResMgrImportLoader::load_package( const std::string& name, DataSectionPtr package ) { // We don't erase ourselves from the modules_ list, since whatever // we call to process our __init__ script will do it for us. std::string moduleName = name; std::string::size_type dotPos = name.rfind( "." ); if ( dotPos != std::string::npos ) { moduleName = name.substr( dotPos + 1 ); } PyObject *module = PyImport_AddModule( name.c_str() ); if ( module == NULL ) { // Propagate the PyErr up return NULL; } PyObject *moduleDict = PyModule_GetDict( module ); PyObject *file = PyString_FromString( ( path_ + "/" + moduleName).c_str() ); if ( file == NULL ) { return NULL; } PyObject *path = Py_BuildValue( "[O]", file ); if ( path == NULL ) { Py_DECREF( file ); return NULL; } int err = PyDict_SetItemString( moduleDict, "__file__", file ); Py_DECREF( file ); if ( err != 0 ) { Py_DECREF( path ); return NULL; } err = PyDict_SetItemString( moduleDict, "__path__", path ); Py_DECREF( path ); if ( err != 0 ) { return NULL; } err = PyDict_SetItemString( moduleDict, "__loader__", this ); if ( err != 0 ) { return NULL; } // This call was tested in find_module_file earlier. moduleCacheEntry packageInit = find_module_file( "__init__", package ); // TRACE_MSG( "PyResMgrImportLoader(%s)::load_package: processing %s\n", // path_.c_str(), name.c_str() ); switch( packageInit.first ) { case PY_OBJECT: return load_compiled_module( name, packageInit.second->asBinary() ); case PY_SOURCE: return load_source_module( name, packageInit.second->asBinary(), package ); case NOT_FOUND: case PKG_DIRECTORY: case C_EXTENSION: break; } Py_Return; }