Ejemplo n.º 1
0
        /// <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;
        }
Ejemplo n.º 2
0
        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));
        }