/// <summary> /// Called by the __builtin__.__import__ functions (general importing) and ScriptEngine (for site.py) /// /// level indiciates whether to perform absolute or relative imports. /// -1 indicates both should be performed /// 0 indicates only absolute imports should be performed /// Positive numbers indicate the # of parent directories to search relative to the calling module /// </summary> public static object ImportModule(CodeContext/*!*/ context, object globals, string/*!*/ modName, bool bottom, int level) { if (modName.IndexOf(Path.DirectorySeparatorChar) != -1) { throw PythonOps.ImportError("Import by filename is not supported.", modName); } string package = null; object attribute; if (TryGetGlobalValue(globals, Symbols.Package, out attribute)) { package = attribute as string; if (package == null && attribute != null) { throw PythonOps.ValueError("__package__ set to non-string"); } } else { package = null; if (level > 0) { // explicit relative import, calculate and store __package__ object pathAttr, nameAttr; if (TryGetGlobalValue(globals, Symbols.Name, out nameAttr) && nameAttr is string) { if (TryGetGlobalValue(globals, Symbols.Path, out pathAttr)) { ((IAttributesCollection)globals)[Symbols.Package] = nameAttr; } else { ((IAttributesCollection)globals)[Symbols.Package] = ((string)nameAttr).rpartition(".")[0]; } } } } object newmod = null; string[] parts = modName.Split('.'); string finalName = null; if (level != 0) { // try a relative import // if importing a.b.c, import "a" first and then import b.c from a string name; // name of the module we are to import in relation to the current module Scope parentScope; List path; // path to search if (TryGetNameAndPath(context, globals, parts[0], level, package, out name, out path, out parentScope)) { finalName = name; // import relative if (!TryGetExistingOrMetaPathModule(context, name, path, out newmod)) { newmod = ImportFromPath(context, parts[0], name, path); if (newmod != null && parentScope != null) { parentScope.SetVariable(SymbolTable.StringToId(modName), newmod); } } else if (parts.Length == 1) { // if we imported before having the assembly // loaded and then loaded the assembly we want // to make the assembly available now. if (newmod is NamespaceTracker) { PythonContext.EnsureModule(context).ShowCls = true; } } } } if (level <= 0) { // try an absolute import if (newmod == null) { object parentPkg; if (package != null && !PythonContext.GetContext(context).SystemStateModules.TryGetValue(package, out parentPkg)) { Scope warnScope = new Scope(); warnScope.SetVariable(Symbols.File, package); warnScope.SetVariable(Symbols.Name, package); PythonOps.Warn( new CodeContext(warnScope, context.LanguageContext), PythonExceptions.RuntimeWarning, "Parent module '{0}' not found while handling absolute import", package); } newmod = ImportTopAbsolute(context, parts[0]); finalName = parts[0]; if (newmod == null) { return null; } } } // now import the a.b.c etc. a needs to be included here // because the process of importing could have modified // sys.modules. object next = newmod; string curName = null; for (int i = 0; i < parts.Length; i++) { curName = i == 0 ? finalName : curName + "." + parts[i]; object tmpNext; if (TryGetExistingModule(context, curName, out tmpNext)) { next = tmpNext; if (i == 0) { // need to update newmod if we pulled it out of sys.modules // just in case we're in bottom mode. newmod = next; } } else if(i != 0) { // child module isn't loaded yet, import it. next = ImportModuleFrom(context, next, parts[i]); } else { // top-level module doesn't exist in sys.modules, probably // came from some weird meta path hook. newmod = next; } } return bottom ? next : newmod; }
public static object ScopeMethodMissing(RubyContext/*!*/ context, Scope/*!*/ globalScope, BlockParam block, object self, SymbolId name, object[]/*!*/ args) { Assert.NotNull(context, globalScope); string str = SymbolTable.IdToString(name); if (str.LastCharacter() == '=') { if (args.Length != 1) { throw RubyOps.MakeWrongNumberOfArgumentsError(args.Length, 1); } // Consider this case: // There is {"Foo" -> 1} in the scope. // x.foo += 1 // Without name mangling this would result to {"Foo" -> 1, "foo" -> 2} while the expected result is {"Foo" -> 2}. str = str.Substring(0, str.Length - 1); name = SymbolTable.StringToId(str); if (!globalScope.ContainsVariable(name)) { var unmangled = SymbolTable.StringToId(RubyUtils.TryUnmangleName(str)); if (!unmangled.IsEmpty && globalScope.ContainsVariable(unmangled)) { name = unmangled; } } var value = args[0]; globalScope.SetVariable(name, value); return value; } else { if (args.Length != 0) { throw RubyOps.MakeWrongNumberOfArgumentsError(args.Length, 0); } object value; if (globalScope.TryGetVariable(name, out value)) { return value; } string unmangled = RubyUtils.TryUnmangleName(str); if (unmangled != null && globalScope.TryGetVariable(SymbolTable.StringToId(unmangled), out value)) { return value; } if (self != null && str == "scope") { return self; } } // TODO: call super throw RubyExceptions.CreateMethodMissing(context, self, SymbolTable.IdToString(name)); }