]> git.proxmox.com Git - mirror_edk2.git/blame - AppPkg/Applications/Python/Python-2.7.10/Lib/modulefinder.py
AppPkg/Applications/Python/Python-2.7.10: Initial Checkin part 4/5.
[mirror_edk2.git] / AppPkg / Applications / Python / Python-2.7.10 / Lib / modulefinder.py
CommitLineData
3257aa99
DM
1"""Find modules used by a script, using introspection."""\r
2# This module should be kept compatible with Python 2.2, see PEP 291.\r
3\r
4from __future__ import generators\r
5import dis\r
6import imp\r
7import marshal\r
8import os\r
9import sys\r
10import types\r
11import struct\r
12\r
13if hasattr(sys.__stdout__, "newlines"):\r
14 READ_MODE = "U" # universal line endings\r
15else:\r
16 # remain compatible with Python < 2.3\r
17 READ_MODE = "r"\r
18\r
19LOAD_CONST = chr(dis.opname.index('LOAD_CONST'))\r
20IMPORT_NAME = chr(dis.opname.index('IMPORT_NAME'))\r
21STORE_NAME = chr(dis.opname.index('STORE_NAME'))\r
22STORE_GLOBAL = chr(dis.opname.index('STORE_GLOBAL'))\r
23STORE_OPS = [STORE_NAME, STORE_GLOBAL]\r
24HAVE_ARGUMENT = chr(dis.HAVE_ARGUMENT)\r
25\r
26# Modulefinder does a good job at simulating Python's, but it can not\r
27# handle __path__ modifications packages make at runtime. Therefore there\r
28# is a mechanism whereby you can register extra paths in this map for a\r
29# package, and it will be honored.\r
30\r
31# Note this is a mapping is lists of paths.\r
32packagePathMap = {}\r
33\r
34# A Public interface\r
35def AddPackagePath(packagename, path):\r
36 paths = packagePathMap.get(packagename, [])\r
37 paths.append(path)\r
38 packagePathMap[packagename] = paths\r
39\r
40replacePackageMap = {}\r
41\r
42# This ReplacePackage mechanism allows modulefinder to work around the\r
43# way the _xmlplus package injects itself under the name "xml" into\r
44# sys.modules at runtime by calling ReplacePackage("_xmlplus", "xml")\r
45# before running ModuleFinder.\r
46\r
47def ReplacePackage(oldname, newname):\r
48 replacePackageMap[oldname] = newname\r
49\r
50\r
51class Module:\r
52\r
53 def __init__(self, name, file=None, path=None):\r
54 self.__name__ = name\r
55 self.__file__ = file\r
56 self.__path__ = path\r
57 self.__code__ = None\r
58 # The set of global names that are assigned to in the module.\r
59 # This includes those names imported through starimports of\r
60 # Python modules.\r
61 self.globalnames = {}\r
62 # The set of starimports this module did that could not be\r
63 # resolved, ie. a starimport from a non-Python module.\r
64 self.starimports = {}\r
65\r
66 def __repr__(self):\r
67 s = "Module(%r" % (self.__name__,)\r
68 if self.__file__ is not None:\r
69 s = s + ", %r" % (self.__file__,)\r
70 if self.__path__ is not None:\r
71 s = s + ", %r" % (self.__path__,)\r
72 s = s + ")"\r
73 return s\r
74\r
75class ModuleFinder:\r
76\r
77 def __init__(self, path=None, debug=0, excludes=[], replace_paths=[]):\r
78 if path is None:\r
79 path = sys.path\r
80 self.path = path\r
81 self.modules = {}\r
82 self.badmodules = {}\r
83 self.debug = debug\r
84 self.indent = 0\r
85 self.excludes = excludes\r
86 self.replace_paths = replace_paths\r
87 self.processed_paths = [] # Used in debugging only\r
88\r
89 def msg(self, level, str, *args):\r
90 if level <= self.debug:\r
91 for i in range(self.indent):\r
92 print " ",\r
93 print str,\r
94 for arg in args:\r
95 print repr(arg),\r
96 print\r
97\r
98 def msgin(self, *args):\r
99 level = args[0]\r
100 if level <= self.debug:\r
101 self.indent = self.indent + 1\r
102 self.msg(*args)\r
103\r
104 def msgout(self, *args):\r
105 level = args[0]\r
106 if level <= self.debug:\r
107 self.indent = self.indent - 1\r
108 self.msg(*args)\r
109\r
110 def run_script(self, pathname):\r
111 self.msg(2, "run_script", pathname)\r
112 with open(pathname, READ_MODE) as fp:\r
113 stuff = ("", "r", imp.PY_SOURCE)\r
114 self.load_module('__main__', fp, pathname, stuff)\r
115\r
116 def load_file(self, pathname):\r
117 dir, name = os.path.split(pathname)\r
118 name, ext = os.path.splitext(name)\r
119 with open(pathname, READ_MODE) as fp:\r
120 stuff = (ext, "r", imp.PY_SOURCE)\r
121 self.load_module(name, fp, pathname, stuff)\r
122\r
123 def import_hook(self, name, caller=None, fromlist=None, level=-1):\r
124 self.msg(3, "import_hook", name, caller, fromlist, level)\r
125 parent = self.determine_parent(caller, level=level)\r
126 q, tail = self.find_head_package(parent, name)\r
127 m = self.load_tail(q, tail)\r
128 if not fromlist:\r
129 return q\r
130 if m.__path__:\r
131 self.ensure_fromlist(m, fromlist)\r
132 return None\r
133\r
134 def determine_parent(self, caller, level=-1):\r
135 self.msgin(4, "determine_parent", caller, level)\r
136 if not caller or level == 0:\r
137 self.msgout(4, "determine_parent -> None")\r
138 return None\r
139 pname = caller.__name__\r
140 if level >= 1: # relative import\r
141 if caller.__path__:\r
142 level -= 1\r
143 if level == 0:\r
144 parent = self.modules[pname]\r
145 assert parent is caller\r
146 self.msgout(4, "determine_parent ->", parent)\r
147 return parent\r
148 if pname.count(".") < level:\r
149 raise ImportError, "relative importpath too deep"\r
150 pname = ".".join(pname.split(".")[:-level])\r
151 parent = self.modules[pname]\r
152 self.msgout(4, "determine_parent ->", parent)\r
153 return parent\r
154 if caller.__path__:\r
155 parent = self.modules[pname]\r
156 assert caller is parent\r
157 self.msgout(4, "determine_parent ->", parent)\r
158 return parent\r
159 if '.' in pname:\r
160 i = pname.rfind('.')\r
161 pname = pname[:i]\r
162 parent = self.modules[pname]\r
163 assert parent.__name__ == pname\r
164 self.msgout(4, "determine_parent ->", parent)\r
165 return parent\r
166 self.msgout(4, "determine_parent -> None")\r
167 return None\r
168\r
169 def find_head_package(self, parent, name):\r
170 self.msgin(4, "find_head_package", parent, name)\r
171 if '.' in name:\r
172 i = name.find('.')\r
173 head = name[:i]\r
174 tail = name[i+1:]\r
175 else:\r
176 head = name\r
177 tail = ""\r
178 if parent:\r
179 qname = "%s.%s" % (parent.__name__, head)\r
180 else:\r
181 qname = head\r
182 q = self.import_module(head, qname, parent)\r
183 if q:\r
184 self.msgout(4, "find_head_package ->", (q, tail))\r
185 return q, tail\r
186 if parent:\r
187 qname = head\r
188 parent = None\r
189 q = self.import_module(head, qname, parent)\r
190 if q:\r
191 self.msgout(4, "find_head_package ->", (q, tail))\r
192 return q, tail\r
193 self.msgout(4, "raise ImportError: No module named", qname)\r
194 raise ImportError, "No module named " + qname\r
195\r
196 def load_tail(self, q, tail):\r
197 self.msgin(4, "load_tail", q, tail)\r
198 m = q\r
199 while tail:\r
200 i = tail.find('.')\r
201 if i < 0: i = len(tail)\r
202 head, tail = tail[:i], tail[i+1:]\r
203 mname = "%s.%s" % (m.__name__, head)\r
204 m = self.import_module(head, mname, m)\r
205 if not m:\r
206 self.msgout(4, "raise ImportError: No module named", mname)\r
207 raise ImportError, "No module named " + mname\r
208 self.msgout(4, "load_tail ->", m)\r
209 return m\r
210\r
211 def ensure_fromlist(self, m, fromlist, recursive=0):\r
212 self.msg(4, "ensure_fromlist", m, fromlist, recursive)\r
213 for sub in fromlist:\r
214 if sub == "*":\r
215 if not recursive:\r
216 all = self.find_all_submodules(m)\r
217 if all:\r
218 self.ensure_fromlist(m, all, 1)\r
219 elif not hasattr(m, sub):\r
220 subname = "%s.%s" % (m.__name__, sub)\r
221 submod = self.import_module(sub, subname, m)\r
222 if not submod:\r
223 raise ImportError, "No module named " + subname\r
224\r
225 def find_all_submodules(self, m):\r
226 if not m.__path__:\r
227 return\r
228 modules = {}\r
229 # 'suffixes' used to be a list hardcoded to [".py", ".pyc", ".pyo"].\r
230 # But we must also collect Python extension modules - although\r
231 # we cannot separate normal dlls from Python extensions.\r
232 suffixes = []\r
233 for triple in imp.get_suffixes():\r
234 suffixes.append(triple[0])\r
235 for dir in m.__path__:\r
236 try:\r
237 names = os.listdir(dir)\r
238 except os.error:\r
239 self.msg(2, "can't list directory", dir)\r
240 continue\r
241 for name in names:\r
242 mod = None\r
243 for suff in suffixes:\r
244 n = len(suff)\r
245 if name[-n:] == suff:\r
246 mod = name[:-n]\r
247 break\r
248 if mod and mod != "__init__":\r
249 modules[mod] = mod\r
250 return modules.keys()\r
251\r
252 def import_module(self, partname, fqname, parent):\r
253 self.msgin(3, "import_module", partname, fqname, parent)\r
254 try:\r
255 m = self.modules[fqname]\r
256 except KeyError:\r
257 pass\r
258 else:\r
259 self.msgout(3, "import_module ->", m)\r
260 return m\r
261 if fqname in self.badmodules:\r
262 self.msgout(3, "import_module -> None")\r
263 return None\r
264 if parent and parent.__path__ is None:\r
265 self.msgout(3, "import_module -> None")\r
266 return None\r
267 try:\r
268 fp, pathname, stuff = self.find_module(partname,\r
269 parent and parent.__path__, parent)\r
270 except ImportError:\r
271 self.msgout(3, "import_module ->", None)\r
272 return None\r
273 try:\r
274 m = self.load_module(fqname, fp, pathname, stuff)\r
275 finally:\r
276 if fp: fp.close()\r
277 if parent:\r
278 setattr(parent, partname, m)\r
279 self.msgout(3, "import_module ->", m)\r
280 return m\r
281\r
282 def load_module(self, fqname, fp, pathname, file_info):\r
283 suffix, mode, type = file_info\r
284 self.msgin(2, "load_module", fqname, fp and "fp", pathname)\r
285 if type == imp.PKG_DIRECTORY:\r
286 m = self.load_package(fqname, pathname)\r
287 self.msgout(2, "load_module ->", m)\r
288 return m\r
289 if type == imp.PY_SOURCE:\r
290 co = compile(fp.read()+'\n', pathname, 'exec')\r
291 elif type == imp.PY_COMPILED:\r
292 if fp.read(4) != imp.get_magic():\r
293 self.msgout(2, "raise ImportError: Bad magic number", pathname)\r
294 raise ImportError, "Bad magic number in %s" % pathname\r
295 fp.read(4)\r
296 co = marshal.load(fp)\r
297 else:\r
298 co = None\r
299 m = self.add_module(fqname)\r
300 m.__file__ = pathname\r
301 if co:\r
302 if self.replace_paths:\r
303 co = self.replace_paths_in_code(co)\r
304 m.__code__ = co\r
305 self.scan_code(co, m)\r
306 self.msgout(2, "load_module ->", m)\r
307 return m\r
308\r
309 def _add_badmodule(self, name, caller):\r
310 if name not in self.badmodules:\r
311 self.badmodules[name] = {}\r
312 if caller:\r
313 self.badmodules[name][caller.__name__] = 1\r
314 else:\r
315 self.badmodules[name]["-"] = 1\r
316\r
317 def _safe_import_hook(self, name, caller, fromlist, level=-1):\r
318 # wrapper for self.import_hook() that won't raise ImportError\r
319 if name in self.badmodules:\r
320 self._add_badmodule(name, caller)\r
321 return\r
322 try:\r
323 self.import_hook(name, caller, level=level)\r
324 except ImportError, msg:\r
325 self.msg(2, "ImportError:", str(msg))\r
326 self._add_badmodule(name, caller)\r
327 else:\r
328 if fromlist:\r
329 for sub in fromlist:\r
330 if sub in self.badmodules:\r
331 self._add_badmodule(sub, caller)\r
332 continue\r
333 try:\r
334 self.import_hook(name, caller, [sub], level=level)\r
335 except ImportError, msg:\r
336 self.msg(2, "ImportError:", str(msg))\r
337 fullname = name + "." + sub\r
338 self._add_badmodule(fullname, caller)\r
339\r
340 def scan_opcodes(self, co,\r
341 unpack = struct.unpack):\r
342 # Scan the code, and yield 'interesting' opcode combinations\r
343 # Version for Python 2.4 and older\r
344 code = co.co_code\r
345 names = co.co_names\r
346 consts = co.co_consts\r
347 while code:\r
348 c = code[0]\r
349 if c in STORE_OPS:\r
350 oparg, = unpack('<H', code[1:3])\r
351 yield "store", (names[oparg],)\r
352 code = code[3:]\r
353 continue\r
354 if c == LOAD_CONST and code[3] == IMPORT_NAME:\r
355 oparg_1, oparg_2 = unpack('<xHxH', code[:6])\r
356 yield "import", (consts[oparg_1], names[oparg_2])\r
357 code = code[6:]\r
358 continue\r
359 if c >= HAVE_ARGUMENT:\r
360 code = code[3:]\r
361 else:\r
362 code = code[1:]\r
363\r
364 def scan_opcodes_25(self, co,\r
365 unpack = struct.unpack):\r
366 # Scan the code, and yield 'interesting' opcode combinations\r
367 # Python 2.5 version (has absolute and relative imports)\r
368 code = co.co_code\r
369 names = co.co_names\r
370 consts = co.co_consts\r
371 LOAD_LOAD_AND_IMPORT = LOAD_CONST + LOAD_CONST + IMPORT_NAME\r
372 while code:\r
373 c = code[0]\r
374 if c in STORE_OPS:\r
375 oparg, = unpack('<H', code[1:3])\r
376 yield "store", (names[oparg],)\r
377 code = code[3:]\r
378 continue\r
379 if code[:9:3] == LOAD_LOAD_AND_IMPORT:\r
380 oparg_1, oparg_2, oparg_3 = unpack('<xHxHxH', code[:9])\r
381 level = consts[oparg_1]\r
382 if level == -1: # normal import\r
383 yield "import", (consts[oparg_2], names[oparg_3])\r
384 elif level == 0: # absolute import\r
385 yield "absolute_import", (consts[oparg_2], names[oparg_3])\r
386 else: # relative import\r
387 yield "relative_import", (level, consts[oparg_2], names[oparg_3])\r
388 code = code[9:]\r
389 continue\r
390 if c >= HAVE_ARGUMENT:\r
391 code = code[3:]\r
392 else:\r
393 code = code[1:]\r
394\r
395 def scan_code(self, co, m):\r
396 code = co.co_code\r
397 if sys.version_info >= (2, 5):\r
398 scanner = self.scan_opcodes_25\r
399 else:\r
400 scanner = self.scan_opcodes\r
401 for what, args in scanner(co):\r
402 if what == "store":\r
403 name, = args\r
404 m.globalnames[name] = 1\r
405 elif what in ("import", "absolute_import"):\r
406 fromlist, name = args\r
407 have_star = 0\r
408 if fromlist is not None:\r
409 if "*" in fromlist:\r
410 have_star = 1\r
411 fromlist = [f for f in fromlist if f != "*"]\r
412 if what == "absolute_import": level = 0\r
413 else: level = -1\r
414 self._safe_import_hook(name, m, fromlist, level=level)\r
415 if have_star:\r
416 # We've encountered an "import *". If it is a Python module,\r
417 # the code has already been parsed and we can suck out the\r
418 # global names.\r
419 mm = None\r
420 if m.__path__:\r
421 # At this point we don't know whether 'name' is a\r
422 # submodule of 'm' or a global module. Let's just try\r
423 # the full name first.\r
424 mm = self.modules.get(m.__name__ + "." + name)\r
425 if mm is None:\r
426 mm = self.modules.get(name)\r
427 if mm is not None:\r
428 m.globalnames.update(mm.globalnames)\r
429 m.starimports.update(mm.starimports)\r
430 if mm.__code__ is None:\r
431 m.starimports[name] = 1\r
432 else:\r
433 m.starimports[name] = 1\r
434 elif what == "relative_import":\r
435 level, fromlist, name = args\r
436 if name:\r
437 self._safe_import_hook(name, m, fromlist, level=level)\r
438 else:\r
439 parent = self.determine_parent(m, level=level)\r
440 self._safe_import_hook(parent.__name__, None, fromlist, level=0)\r
441 else:\r
442 # We don't expect anything else from the generator.\r
443 raise RuntimeError(what)\r
444\r
445 for c in co.co_consts:\r
446 if isinstance(c, type(co)):\r
447 self.scan_code(c, m)\r
448\r
449 def load_package(self, fqname, pathname):\r
450 self.msgin(2, "load_package", fqname, pathname)\r
451 newname = replacePackageMap.get(fqname)\r
452 if newname:\r
453 fqname = newname\r
454 m = self.add_module(fqname)\r
455 m.__file__ = pathname\r
456 m.__path__ = [pathname]\r
457\r
458 # As per comment at top of file, simulate runtime __path__ additions.\r
459 m.__path__ = m.__path__ + packagePathMap.get(fqname, [])\r
460\r
461 fp, buf, stuff = self.find_module("__init__", m.__path__)\r
462 self.load_module(fqname, fp, buf, stuff)\r
463 self.msgout(2, "load_package ->", m)\r
464 if fp:\r
465 fp.close()\r
466 return m\r
467\r
468 def add_module(self, fqname):\r
469 if fqname in self.modules:\r
470 return self.modules[fqname]\r
471 self.modules[fqname] = m = Module(fqname)\r
472 return m\r
473\r
474 def find_module(self, name, path, parent=None):\r
475 if parent is not None:\r
476 # assert path is not None\r
477 fullname = parent.__name__+'.'+name\r
478 else:\r
479 fullname = name\r
480 if fullname in self.excludes:\r
481 self.msgout(3, "find_module -> Excluded", fullname)\r
482 raise ImportError, name\r
483\r
484 if path is None:\r
485 if name in sys.builtin_module_names:\r
486 return (None, None, ("", "", imp.C_BUILTIN))\r
487\r
488 path = self.path\r
489 return imp.find_module(name, path)\r
490\r
491 def report(self):\r
492 """Print a report to stdout, listing the found modules with their\r
493 paths, as well as modules that are missing, or seem to be missing.\r
494 """\r
495 print\r
496 print " %-25s %s" % ("Name", "File")\r
497 print " %-25s %s" % ("----", "----")\r
498 # Print modules found\r
499 keys = self.modules.keys()\r
500 keys.sort()\r
501 for key in keys:\r
502 m = self.modules[key]\r
503 if m.__path__:\r
504 print "P",\r
505 else:\r
506 print "m",\r
507 print "%-25s" % key, m.__file__ or ""\r
508\r
509 # Print missing modules\r
510 missing, maybe = self.any_missing_maybe()\r
511 if missing:\r
512 print\r
513 print "Missing modules:"\r
514 for name in missing:\r
515 mods = self.badmodules[name].keys()\r
516 mods.sort()\r
517 print "?", name, "imported from", ', '.join(mods)\r
518 # Print modules that may be missing, but then again, maybe not...\r
519 if maybe:\r
520 print\r
521 print "Submodules that appear to be missing, but could also be",\r
522 print "global names in the parent package:"\r
523 for name in maybe:\r
524 mods = self.badmodules[name].keys()\r
525 mods.sort()\r
526 print "?", name, "imported from", ', '.join(mods)\r
527\r
528 def any_missing(self):\r
529 """Return a list of modules that appear to be missing. Use\r
530 any_missing_maybe() if you want to know which modules are\r
531 certain to be missing, and which *may* be missing.\r
532 """\r
533 missing, maybe = self.any_missing_maybe()\r
534 return missing + maybe\r
535\r
536 def any_missing_maybe(self):\r
537 """Return two lists, one with modules that are certainly missing\r
538 and one with modules that *may* be missing. The latter names could\r
539 either be submodules *or* just global names in the package.\r
540\r
541 The reason it can't always be determined is that it's impossible to\r
542 tell which names are imported when "from module import *" is done\r
543 with an extension module, short of actually importing it.\r
544 """\r
545 missing = []\r
546 maybe = []\r
547 for name in self.badmodules:\r
548 if name in self.excludes:\r
549 continue\r
550 i = name.rfind(".")\r
551 if i < 0:\r
552 missing.append(name)\r
553 continue\r
554 subname = name[i+1:]\r
555 pkgname = name[:i]\r
556 pkg = self.modules.get(pkgname)\r
557 if pkg is not None:\r
558 if pkgname in self.badmodules[name]:\r
559 # The package tried to import this module itself and\r
560 # failed. It's definitely missing.\r
561 missing.append(name)\r
562 elif subname in pkg.globalnames:\r
563 # It's a global in the package: definitely not missing.\r
564 pass\r
565 elif pkg.starimports:\r
566 # It could be missing, but the package did an "import *"\r
567 # from a non-Python module, so we simply can't be sure.\r
568 maybe.append(name)\r
569 else:\r
570 # It's not a global in the package, the package didn't\r
571 # do funny star imports, it's very likely to be missing.\r
572 # The symbol could be inserted into the package from the\r
573 # outside, but since that's not good style we simply list\r
574 # it missing.\r
575 missing.append(name)\r
576 else:\r
577 missing.append(name)\r
578 missing.sort()\r
579 maybe.sort()\r
580 return missing, maybe\r
581\r
582 def replace_paths_in_code(self, co):\r
583 new_filename = original_filename = os.path.normpath(co.co_filename)\r
584 for f, r in self.replace_paths:\r
585 if original_filename.startswith(f):\r
586 new_filename = r + original_filename[len(f):]\r
587 break\r
588\r
589 if self.debug and original_filename not in self.processed_paths:\r
590 if new_filename != original_filename:\r
591 self.msgout(2, "co_filename %r changed to %r" \\r
592 % (original_filename,new_filename,))\r
593 else:\r
594 self.msgout(2, "co_filename %r remains unchanged" \\r
595 % (original_filename,))\r
596 self.processed_paths.append(original_filename)\r
597\r
598 consts = list(co.co_consts)\r
599 for i in range(len(consts)):\r
600 if isinstance(consts[i], type(co)):\r
601 consts[i] = self.replace_paths_in_code(consts[i])\r
602\r
603 return types.CodeType(co.co_argcount, co.co_nlocals, co.co_stacksize,\r
604 co.co_flags, co.co_code, tuple(consts), co.co_names,\r
605 co.co_varnames, new_filename, co.co_name,\r
606 co.co_firstlineno, co.co_lnotab,\r
607 co.co_freevars, co.co_cellvars)\r
608\r
609\r
610def test():\r
611 # Parse command line\r
612 import getopt\r
613 try:\r
614 opts, args = getopt.getopt(sys.argv[1:], "dmp:qx:")\r
615 except getopt.error, msg:\r
616 print msg\r
617 return\r
618\r
619 # Process options\r
620 debug = 1\r
621 domods = 0\r
622 addpath = []\r
623 exclude = []\r
624 for o, a in opts:\r
625 if o == '-d':\r
626 debug = debug + 1\r
627 if o == '-m':\r
628 domods = 1\r
629 if o == '-p':\r
630 addpath = addpath + a.split(os.pathsep)\r
631 if o == '-q':\r
632 debug = 0\r
633 if o == '-x':\r
634 exclude.append(a)\r
635\r
636 # Provide default arguments\r
637 if not args:\r
638 script = "hello.py"\r
639 else:\r
640 script = args[0]\r
641\r
642 # Set the path based on sys.path and the script directory\r
643 path = sys.path[:]\r
644 path[0] = os.path.dirname(script)\r
645 path = addpath + path\r
646 if debug > 1:\r
647 print "path:"\r
648 for item in path:\r
649 print " ", repr(item)\r
650\r
651 # Create the module finder and turn its crank\r
652 mf = ModuleFinder(path, debug, exclude)\r
653 for arg in args[1:]:\r
654 if arg == '-m':\r
655 domods = 1\r
656 continue\r
657 if domods:\r
658 if arg[-2:] == '.*':\r
659 mf.import_hook(arg[:-2], None, ["*"])\r
660 else:\r
661 mf.import_hook(arg)\r
662 else:\r
663 mf.load_file(arg)\r
664 mf.run_script(script)\r
665 mf.report()\r
666 return mf # for -i debugging\r
667\r
668\r
669if __name__ == '__main__':\r
670 try:\r
671 mf = test()\r
672 except KeyboardInterrupt:\r
673 print "\n[interrupt]"\r