]> git.proxmox.com Git - mirror_edk2.git/blame - AppPkg/Applications/Python/Python-2.7.10/Lib/runpy.py
EmbeddedPkg: Extend NvVarStoreFormattedLib LIBRARY_CLASS
[mirror_edk2.git] / AppPkg / Applications / Python / Python-2.7.10 / Lib / runpy.py
CommitLineData
3257aa99
DM
1"""runpy.py - locating and running Python code using the module namespace\r
2\r
3Provides support for locating and running Python scripts using the Python\r
4module namespace instead of the native filesystem.\r
5\r
6This allows Python code to play nicely with non-filesystem based PEP 302\r
7importers when locating support scripts as well as when importing modules.\r
8"""\r
9# Written by Nick Coghlan <ncoghlan at gmail.com>\r
10# to implement PEP 338 (Executing Modules as Scripts)\r
11\r
12import sys\r
13import imp\r
14from pkgutil import read_code\r
15try:\r
16 from imp import get_loader\r
17except ImportError:\r
18 from pkgutil import get_loader\r
19\r
20__all__ = [\r
21 "run_module", "run_path",\r
22]\r
23\r
24class _TempModule(object):\r
25 """Temporarily replace a module in sys.modules with an empty namespace"""\r
26 def __init__(self, mod_name):\r
27 self.mod_name = mod_name\r
28 self.module = imp.new_module(mod_name)\r
29 self._saved_module = []\r
30\r
31 def __enter__(self):\r
32 mod_name = self.mod_name\r
33 try:\r
34 self._saved_module.append(sys.modules[mod_name])\r
35 except KeyError:\r
36 pass\r
37 sys.modules[mod_name] = self.module\r
38 return self\r
39\r
40 def __exit__(self, *args):\r
41 if self._saved_module:\r
42 sys.modules[self.mod_name] = self._saved_module[0]\r
43 else:\r
44 del sys.modules[self.mod_name]\r
45 self._saved_module = []\r
46\r
47class _ModifiedArgv0(object):\r
48 def __init__(self, value):\r
49 self.value = value\r
50 self._saved_value = self._sentinel = object()\r
51\r
52 def __enter__(self):\r
53 if self._saved_value is not self._sentinel:\r
54 raise RuntimeError("Already preserving saved value")\r
55 self._saved_value = sys.argv[0]\r
56 sys.argv[0] = self.value\r
57\r
58 def __exit__(self, *args):\r
59 self.value = self._sentinel\r
60 sys.argv[0] = self._saved_value\r
61\r
62def _run_code(code, run_globals, init_globals=None,\r
63 mod_name=None, mod_fname=None,\r
64 mod_loader=None, pkg_name=None):\r
65 """Helper to run code in nominated namespace"""\r
66 if init_globals is not None:\r
67 run_globals.update(init_globals)\r
68 run_globals.update(__name__ = mod_name,\r
69 __file__ = mod_fname,\r
70 __loader__ = mod_loader,\r
71 __package__ = pkg_name)\r
72 exec code in run_globals\r
73 return run_globals\r
74\r
75def _run_module_code(code, init_globals=None,\r
76 mod_name=None, mod_fname=None,\r
77 mod_loader=None, pkg_name=None):\r
78 """Helper to run code in new namespace with sys modified"""\r
79 with _TempModule(mod_name) as temp_module, _ModifiedArgv0(mod_fname):\r
80 mod_globals = temp_module.module.__dict__\r
81 _run_code(code, mod_globals, init_globals,\r
82 mod_name, mod_fname, mod_loader, pkg_name)\r
83 # Copy the globals of the temporary module, as they\r
84 # may be cleared when the temporary module goes away\r
85 return mod_globals.copy()\r
86\r
87\r
88# This helper is needed due to a missing component in the PEP 302\r
89# loader protocol (specifically, "get_filename" is non-standard)\r
90# Since we can't introduce new features in maintenance releases,\r
91# support was added to zipimporter under the name '_get_filename'\r
92def _get_filename(loader, mod_name):\r
93 for attr in ("get_filename", "_get_filename"):\r
94 meth = getattr(loader, attr, None)\r
95 if meth is not None:\r
96 return meth(mod_name)\r
97 return None\r
98\r
99# Helper to get the loader, code and filename for a module\r
100def _get_module_details(mod_name):\r
101 loader = get_loader(mod_name)\r
102 if loader is None:\r
103 raise ImportError("No module named %s" % mod_name)\r
104 if loader.is_package(mod_name):\r
105 if mod_name == "__main__" or mod_name.endswith(".__main__"):\r
106 raise ImportError("Cannot use package as __main__ module")\r
107 try:\r
108 pkg_main_name = mod_name + ".__main__"\r
109 return _get_module_details(pkg_main_name)\r
110 except ImportError, e:\r
111 raise ImportError(("%s; %r is a package and cannot " +\r
112 "be directly executed") %(e, mod_name))\r
113 code = loader.get_code(mod_name)\r
114 if code is None:\r
115 raise ImportError("No code object available for %s" % mod_name)\r
116 filename = _get_filename(loader, mod_name)\r
117 return mod_name, loader, code, filename\r
118\r
119\r
120def _get_main_module_details():\r
121 # Helper that gives a nicer error message when attempting to\r
122 # execute a zipfile or directory by invoking __main__.py\r
123 main_name = "__main__"\r
124 try:\r
125 return _get_module_details(main_name)\r
126 except ImportError as exc:\r
127 if main_name in str(exc):\r
128 raise ImportError("can't find %r module in %r" %\r
129 (main_name, sys.path[0]))\r
130 raise\r
131\r
132# This function is the actual implementation of the -m switch and direct\r
133# execution of zipfiles and directories and is deliberately kept private.\r
134# This avoids a repeat of the situation where run_module() no longer met the\r
135# needs of mainmodule.c, but couldn't be changed because it was public\r
136def _run_module_as_main(mod_name, alter_argv=True):\r
137 """Runs the designated module in the __main__ namespace\r
138\r
139 Note that the executed module will have full access to the\r
140 __main__ namespace. If this is not desirable, the run_module()\r
141 function should be used to run the module code in a fresh namespace.\r
142\r
143 At the very least, these variables in __main__ will be overwritten:\r
144 __name__\r
145 __file__\r
146 __loader__\r
147 __package__\r
148 """\r
149 try:\r
150 if alter_argv or mod_name != "__main__": # i.e. -m switch\r
151 mod_name, loader, code, fname = _get_module_details(mod_name)\r
152 else: # i.e. directory or zipfile execution\r
153 mod_name, loader, code, fname = _get_main_module_details()\r
154 except ImportError as exc:\r
155 msg = "%s: %s" % (sys.executable, str(exc))\r
156 sys.exit(msg)\r
157 pkg_name = mod_name.rpartition('.')[0]\r
158 main_globals = sys.modules["__main__"].__dict__\r
159 if alter_argv:\r
160 sys.argv[0] = fname\r
161 return _run_code(code, main_globals, None,\r
162 "__main__", fname, loader, pkg_name)\r
163\r
164def run_module(mod_name, init_globals=None,\r
165 run_name=None, alter_sys=False):\r
166 """Execute a module's code without importing it\r
167\r
168 Returns the resulting top level namespace dictionary\r
169 """\r
170 mod_name, loader, code, fname = _get_module_details(mod_name)\r
171 if run_name is None:\r
172 run_name = mod_name\r
173 pkg_name = mod_name.rpartition('.')[0]\r
174 if alter_sys:\r
175 return _run_module_code(code, init_globals, run_name,\r
176 fname, loader, pkg_name)\r
177 else:\r
178 # Leave the sys module alone\r
179 return _run_code(code, {}, init_globals, run_name,\r
180 fname, loader, pkg_name)\r
181\r
182\r
183# XXX (ncoghlan): Perhaps expose the C API function\r
184# as imp.get_importer instead of reimplementing it in Python?\r
185def _get_importer(path_name):\r
186 """Python version of PyImport_GetImporter C API function"""\r
187 cache = sys.path_importer_cache\r
188 try:\r
189 importer = cache[path_name]\r
190 except KeyError:\r
191 # Not yet cached. Flag as using the\r
192 # standard machinery until we finish\r
193 # checking the hooks\r
194 cache[path_name] = None\r
195 for hook in sys.path_hooks:\r
196 try:\r
197 importer = hook(path_name)\r
198 break\r
199 except ImportError:\r
200 pass\r
201 else:\r
202 # The following check looks a bit odd. The trick is that\r
203 # NullImporter raises ImportError if the supplied path is a\r
204 # *valid* directory entry (and hence able to be handled\r
205 # by the standard import machinery)\r
206 try:\r
207 importer = imp.NullImporter(path_name)\r
208 except ImportError:\r
209 return None\r
210 cache[path_name] = importer\r
211 return importer\r
212\r
213def _get_code_from_file(fname):\r
214 # Check for a compiled file first\r
215 with open(fname, "rb") as f:\r
216 code = read_code(f)\r
217 if code is None:\r
218 # That didn't work, so try it as normal source code\r
219 with open(fname, "rU") as f:\r
220 code = compile(f.read(), fname, 'exec')\r
221 return code\r
222\r
223def run_path(path_name, init_globals=None, run_name=None):\r
224 """Execute code located at the specified filesystem location\r
225\r
226 Returns the resulting top level namespace dictionary\r
227\r
228 The file path may refer directly to a Python script (i.e.\r
229 one that could be directly executed with execfile) or else\r
230 it may refer to a zipfile or directory containing a top\r
231 level __main__.py script.\r
232 """\r
233 if run_name is None:\r
234 run_name = "<run_path>"\r
235 importer = _get_importer(path_name)\r
236 if isinstance(importer, imp.NullImporter):\r
237 # Not a valid sys.path entry, so run the code directly\r
238 # execfile() doesn't help as we want to allow compiled files\r
239 code = _get_code_from_file(path_name)\r
240 return _run_module_code(code, init_globals, run_name, path_name)\r
241 else:\r
242 # Importer is defined for path, so add it to\r
243 # the start of sys.path\r
244 sys.path.insert(0, path_name)\r
245 try:\r
246 # Here's where things are a little different from the run_module\r
247 # case. There, we only had to replace the module in sys while the\r
248 # code was running and doing so was somewhat optional. Here, we\r
249 # have no choice and we have to remove it even while we read the\r
250 # code. If we don't do this, a __loader__ attribute in the\r
251 # existing __main__ module may prevent location of the new module.\r
252 main_name = "__main__"\r
253 saved_main = sys.modules[main_name]\r
254 del sys.modules[main_name]\r
255 try:\r
256 mod_name, loader, code, fname = _get_main_module_details()\r
257 finally:\r
258 sys.modules[main_name] = saved_main\r
259 pkg_name = ""\r
260 with _TempModule(run_name) as temp_module, \\r
261 _ModifiedArgv0(path_name):\r
262 mod_globals = temp_module.module.__dict__\r
263 return _run_code(code, mod_globals, init_globals,\r
264 run_name, fname, loader, pkg_name).copy()\r
265 finally:\r
266 try:\r
267 sys.path.remove(path_name)\r
268 except ValueError:\r
269 pass\r
270\r
271\r
272if __name__ == "__main__":\r
273 # Run the module specified as the next command line argument\r
274 if len(sys.argv) < 2:\r
275 print >> sys.stderr, "No module specified for execution"\r
276 else:\r
277 del sys.argv[0] # Make the requested module sys.argv[0]\r
278 _run_module_as_main(sys.argv[0])\r