|
3 | 3 | package py
|
4 | 4 |
|
5 | 5 | import (
|
| 6 | + "io/ioutil" |
| 7 | + "os" |
| 8 | + "path" |
| 9 | + "path/filepath" |
6 | 10 | "strings"
|
7 | 11 | )
|
8 | 12 |
|
| 13 | +var ( |
| 14 | + // This will become sys.path one day ;-) |
| 15 | + modulePath = []string{"", "/usr/lib/python3.3", "/usr/local/lib/python3.3/dist-packages", "/usr/lib/python3/dist-packages"} |
| 16 | +) |
| 17 | + |
9 | 18 | // The workings of __import__
|
10 |
| -func ImportModuleLevelObject(nameObj, given_globals, locals, given_fromlist Object, level int) Object { |
| 19 | +// |
| 20 | +// __import__(name, globals=None, locals=None, fromlist=(), level=0) |
| 21 | +// |
| 22 | +// This function is invoked by the import statement. It can be |
| 23 | +// replaced (by importing the builtins module and assigning to |
| 24 | +// builtins.__import__) in order to change semantics of the import |
| 25 | +// statement, but doing so is strongly discouraged as it is usually |
| 26 | +// simpler to use import hooks (see PEP 302) to attain the same goals |
| 27 | +// and does not cause issues with code which assumes the default |
| 28 | +// import implementation is in use. Direct use of __import__() is also |
| 29 | +// discouraged in favor of importlib.import_module(). |
| 30 | +// |
| 31 | +// The function imports the module name, potentially using the given |
| 32 | +// globals and locals to determine how to interpret the name in a |
| 33 | +// package context. The fromlist gives the names of objects or |
| 34 | +// submodules that should be imported from the module given by |
| 35 | +// name. The standard implementation does not use its locals argument |
| 36 | +// at all, and uses its globals only to determine the package context |
| 37 | +// of the import statement. |
| 38 | +// |
| 39 | +// level specifies whether to use absolute or relative imports. 0 (the |
| 40 | +// default) means only perform absolute imports. Positive values for |
| 41 | +// level indicate the number of parent directories to search relative |
| 42 | +// to the directory of the module calling __import__() (see PEP 328 |
| 43 | +// for the details). |
| 44 | +// |
| 45 | +// When the name variable is of the form package.module, normally, the |
| 46 | +// top-level package (the name up till the first dot) is returned, not |
| 47 | +// the module named by name. However, when a non-empty fromlist |
| 48 | +// argument is given, the module named by name is returned. |
| 49 | +// |
| 50 | +// For example, the statement import spam results in bytecode |
| 51 | +// resembling the following code: |
| 52 | +// |
| 53 | +// spam = __import__('spam', globals(), locals(), [], 0) |
| 54 | +// The statement import spam.ham results in this call: |
| 55 | +// |
| 56 | +// spam = __import__('spam.ham', globals(), locals(), [], 0) |
| 57 | +// |
| 58 | +// Note how __import__() returns the toplevel module here because this |
| 59 | +// is the object that is bound to a name by the import statement. |
| 60 | +// |
| 61 | +// On the other hand, the statement from spam.ham import eggs, sausage |
| 62 | +// as saus results in |
| 63 | +// |
| 64 | +// _temp = __import__('spam.ham', globals(), locals(), ['eggs', 'sausage'], 0) |
| 65 | +// eggs = _temp.eggs |
| 66 | +// saus = _temp.sausage |
| 67 | +// |
| 68 | +// Here, the spam.ham module is returned from __import__(). From this |
| 69 | +// object, the names to import are retrieved and assigned to their |
| 70 | +// respective names. |
| 71 | +// |
| 72 | +// If you simply want to import a module (potentially within a |
| 73 | +// package) by name, use importlib.import_module(). |
| 74 | +// |
| 75 | +// Changed in version 3.3: Negative values for level are no longer |
| 76 | +// supported (which also changes the default value to 0). |
| 77 | +func ImportModuleLevelObject(name string, globals, locals StringDict, fromlist Tuple, level int) Object { |
| 78 | + // Module already loaded - return that |
| 79 | + if module, ok := modules[name]; ok { |
| 80 | + return module |
| 81 | + } |
| 82 | + |
| 83 | + if level != 0 { |
| 84 | + panic("Relative import not supported yet") |
| 85 | + } |
| 86 | + |
| 87 | + parts := strings.Split(name, ".") |
| 88 | + pathParts := path.Join(parts...) |
| 89 | + |
| 90 | + for _, mpath := range modulePath { |
| 91 | + if mpath == "" { |
| 92 | + mpathObj, ok := globals["__file__"] |
| 93 | + if !ok { |
| 94 | + panic(ExceptionNewf(SystemError, "Couldn't find __file__ in globals")) |
| 95 | + } |
| 96 | + mpath = string(mpathObj.(String)) |
| 97 | + } |
| 98 | + fullPath := path.Join(mpath, pathParts) |
| 99 | + // FIXME Read pyc/pyo too |
| 100 | + fullPath, err := filepath.Abs(fullPath + ".py") |
| 101 | + if err != nil { |
| 102 | + continue |
| 103 | + } |
| 104 | + // Check if file exists |
| 105 | + if _, err := os.Stat(fullPath); err == nil { |
| 106 | + str, err := ioutil.ReadFile(fullPath) |
| 107 | + if err != nil { |
| 108 | + panic(ExceptionNewf(OSError, "Couldn't read %q: %v", fullPath, err)) |
| 109 | + } |
| 110 | + codeObj := Compile(string(str), fullPath, "exec", 0, true) |
| 111 | + code, ok := codeObj.(*Code) |
| 112 | + if !ok { |
| 113 | + panic(ExceptionNewf(ImportError, "Compile didn't return code object")) |
| 114 | + } |
| 115 | + module := NewModule(name, "", nil, nil) |
| 116 | + _, err = Run(module.Globals, module.Globals, code, nil) |
| 117 | + if err != nil { |
| 118 | + panic(err) |
| 119 | + } |
| 120 | + return module |
| 121 | + } |
| 122 | + } |
| 123 | + panic(ExceptionNewf(ImportError, "No module named '%s'", name)) |
| 124 | + |
| 125 | + // Convert to absolute path if relative |
| 126 | + // Use __file__ from globals to work out what we are relative to |
| 127 | + |
| 128 | + // '' in path seems to mean use the current __file__ |
| 129 | + |
| 130 | + // Find a valid path which we need to check for the correct __init__.py in subdirectories etc |
| 131 | + |
| 132 | + // Look for .py and .pyc files |
| 133 | + |
| 134 | + // Make absolute module path too if we can for sys.modules |
| 135 | + |
| 136 | + //How do we uniquely identify modules? |
| 137 | + |
| 138 | + // SystemError: Parent module '' not loaded, cannot perform relative import |
| 139 | + |
| 140 | +} |
| 141 | + |
| 142 | +// Straight port of the python code |
| 143 | +// |
| 144 | +// This calls functins from _bootstrap.py which is a frozen module |
| 145 | +// |
| 146 | +// Too much functionality for the moment |
| 147 | +func XImportModuleLevelObject(nameObj, given_globals, locals, given_fromlist Object, level int) Object { |
11 | 148 | var abs_name string
|
12 | 149 | var builtins_import Object
|
13 | 150 | var final_mod Object
|
|
0 commit comments