]>
git.proxmox.com Git - mirror_edk2.git/blob - AppPkg/Applications/Python/Python-2.7.10/Lib/modulefinder.py
1 """Find modules used by a script, using introspection."""
2 # This module should be kept compatible with Python 2.2, see PEP 291.
4 from __future__
import generators
13 if hasattr(sys
.__stdout
__, "newlines"):
14 READ_MODE
= "U" # universal line endings
16 # remain compatible with Python < 2.3
19 LOAD_CONST
= chr(dis
.opname
.index('LOAD_CONST'))
20 IMPORT_NAME
= chr(dis
.opname
.index('IMPORT_NAME'))
21 STORE_NAME
= chr(dis
.opname
.index('STORE_NAME'))
22 STORE_GLOBAL
= chr(dis
.opname
.index('STORE_GLOBAL'))
23 STORE_OPS
= [STORE_NAME
, STORE_GLOBAL
]
24 HAVE_ARGUMENT
= chr(dis
.HAVE_ARGUMENT
)
26 # Modulefinder does a good job at simulating Python's, but it can not
27 # handle __path__ modifications packages make at runtime. Therefore there
28 # is a mechanism whereby you can register extra paths in this map for a
29 # package, and it will be honored.
31 # Note this is a mapping is lists of paths.
35 def AddPackagePath(packagename
, path
):
36 paths
= packagePathMap
.get(packagename
, [])
38 packagePathMap
[packagename
] = paths
40 replacePackageMap
= {}
42 # This ReplacePackage mechanism allows modulefinder to work around the
43 # way the _xmlplus package injects itself under the name "xml" into
44 # sys.modules at runtime by calling ReplacePackage("_xmlplus", "xml")
45 # before running ModuleFinder.
47 def ReplacePackage(oldname
, newname
):
48 replacePackageMap
[oldname
] = newname
53 def __init__(self
, name
, file=None, path
=None):
58 # The set of global names that are assigned to in the module.
59 # This includes those names imported through starimports of
62 # The set of starimports this module did that could not be
63 # resolved, ie. a starimport from a non-Python module.
67 s
= "Module(%r" % (self
.__name
__,)
68 if self
.__file
__ is not None:
69 s
= s
+ ", %r" % (self
.__file
__,)
70 if self
.__path
__ is not None:
71 s
= s
+ ", %r" % (self
.__path
__,)
77 def __init__(self
, path
=None, debug
=0, excludes
=[], replace_paths
=[]):
85 self
.excludes
= excludes
86 self
.replace_paths
= replace_paths
87 self
.processed_paths
= [] # Used in debugging only
89 def msg(self
, level
, str, *args
):
90 if level
<= self
.debug
:
91 for i
in range(self
.indent
):
98 def msgin(self
, *args
):
100 if level
<= self
.debug
:
101 self
.indent
= self
.indent
+ 1
104 def msgout(self
, *args
):
106 if level
<= self
.debug
:
107 self
.indent
= self
.indent
- 1
110 def run_script(self
, pathname
):
111 self
.msg(2, "run_script", pathname
)
112 with
open(pathname
, READ_MODE
) as fp
:
113 stuff
= ("", "r", imp
.PY_SOURCE
)
114 self
.load_module('__main__', fp
, pathname
, stuff
)
116 def load_file(self
, pathname
):
117 dir, name
= os
.path
.split(pathname
)
118 name
, ext
= os
.path
.splitext(name
)
119 with
open(pathname
, READ_MODE
) as fp
:
120 stuff
= (ext
, "r", imp
.PY_SOURCE
)
121 self
.load_module(name
, fp
, pathname
, stuff
)
123 def import_hook(self
, name
, caller
=None, fromlist
=None, level
=-1):
124 self
.msg(3, "import_hook", name
, caller
, fromlist
, level
)
125 parent
= self
.determine_parent(caller
, level
=level
)
126 q
, tail
= self
.find_head_package(parent
, name
)
127 m
= self
.load_tail(q
, tail
)
131 self
.ensure_fromlist(m
, fromlist
)
134 def determine_parent(self
, caller
, level
=-1):
135 self
.msgin(4, "determine_parent", caller
, level
)
136 if not caller
or level
== 0:
137 self
.msgout(4, "determine_parent -> None")
139 pname
= caller
.__name
__
140 if level
>= 1: # relative import
144 parent
= self
.modules
[pname
]
145 assert parent
is caller
146 self
.msgout(4, "determine_parent ->", parent
)
148 if pname
.count(".") < level
:
149 raise ImportError, "relative importpath too deep"
150 pname
= ".".join(pname
.split(".")[:-level
])
151 parent
= self
.modules
[pname
]
152 self
.msgout(4, "determine_parent ->", parent
)
155 parent
= self
.modules
[pname
]
156 assert caller
is parent
157 self
.msgout(4, "determine_parent ->", parent
)
162 parent
= self
.modules
[pname
]
163 assert parent
.__name
__ == pname
164 self
.msgout(4, "determine_parent ->", parent
)
166 self
.msgout(4, "determine_parent -> None")
169 def find_head_package(self
, parent
, name
):
170 self
.msgin(4, "find_head_package", parent
, name
)
179 qname
= "%s.%s" % (parent
.__name
__, head
)
182 q
= self
.import_module(head
, qname
, parent
)
184 self
.msgout(4, "find_head_package ->", (q
, tail
))
189 q
= self
.import_module(head
, qname
, parent
)
191 self
.msgout(4, "find_head_package ->", (q
, tail
))
193 self
.msgout(4, "raise ImportError: No module named", qname
)
194 raise ImportError, "No module named " + qname
196 def load_tail(self
, q
, tail
):
197 self
.msgin(4, "load_tail", q
, tail
)
201 if i
< 0: i
= len(tail
)
202 head
, tail
= tail
[:i
], tail
[i
+1:]
203 mname
= "%s.%s" % (m
.__name
__, head
)
204 m
= self
.import_module(head
, mname
, m
)
206 self
.msgout(4, "raise ImportError: No module named", mname
)
207 raise ImportError, "No module named " + mname
208 self
.msgout(4, "load_tail ->", m
)
211 def ensure_fromlist(self
, m
, fromlist
, recursive
=0):
212 self
.msg(4, "ensure_fromlist", m
, fromlist
, recursive
)
216 all
= self
.find_all_submodules(m
)
218 self
.ensure_fromlist(m
, all
, 1)
219 elif not hasattr(m
, sub
):
220 subname
= "%s.%s" % (m
.__name
__, sub
)
221 submod
= self
.import_module(sub
, subname
, m
)
223 raise ImportError, "No module named " + subname
225 def find_all_submodules(self
, m
):
229 # 'suffixes' used to be a list hardcoded to [".py", ".pyc", ".pyo"].
230 # But we must also collect Python extension modules - although
231 # we cannot separate normal dlls from Python extensions.
233 for triple
in imp
.get_suffixes():
234 suffixes
.append(triple
[0])
235 for dir in m
.__path
__:
237 names
= os
.listdir(dir)
239 self
.msg(2, "can't list directory", dir)
243 for suff
in suffixes
:
245 if name
[-n
:] == suff
:
248 if mod
and mod
!= "__init__":
250 return modules
.keys()
252 def import_module(self
, partname
, fqname
, parent
):
253 self
.msgin(3, "import_module", partname
, fqname
, parent
)
255 m
= self
.modules
[fqname
]
259 self
.msgout(3, "import_module ->", m
)
261 if fqname
in self
.badmodules
:
262 self
.msgout(3, "import_module -> None")
264 if parent
and parent
.__path
__ is None:
265 self
.msgout(3, "import_module -> None")
268 fp
, pathname
, stuff
= self
.find_module(partname
,
269 parent
and parent
.__path
__, parent
)
271 self
.msgout(3, "import_module ->", None)
274 m
= self
.load_module(fqname
, fp
, pathname
, stuff
)
278 setattr(parent
, partname
, m
)
279 self
.msgout(3, "import_module ->", m
)
282 def load_module(self
, fqname
, fp
, pathname
, file_info
):
283 suffix
, mode
, type = file_info
284 self
.msgin(2, "load_module", fqname
, fp
and "fp", pathname
)
285 if type == imp
.PKG_DIRECTORY
:
286 m
= self
.load_package(fqname
, pathname
)
287 self
.msgout(2, "load_module ->", m
)
289 if type == imp
.PY_SOURCE
:
290 co
= compile(fp
.read()+'\n', pathname
, 'exec')
291 elif type == imp
.PY_COMPILED
:
292 if fp
.read(4) != imp
.get_magic():
293 self
.msgout(2, "raise ImportError: Bad magic number", pathname
)
294 raise ImportError, "Bad magic number in %s" % pathname
296 co
= marshal
.load(fp
)
299 m
= self
.add_module(fqname
)
300 m
.__file
__ = pathname
302 if self
.replace_paths
:
303 co
= self
.replace_paths_in_code(co
)
305 self
.scan_code(co
, m
)
306 self
.msgout(2, "load_module ->", m
)
309 def _add_badmodule(self
, name
, caller
):
310 if name
not in self
.badmodules
:
311 self
.badmodules
[name
] = {}
313 self
.badmodules
[name
][caller
.__name
__] = 1
315 self
.badmodules
[name
]["-"] = 1
317 def _safe_import_hook(self
, name
, caller
, fromlist
, level
=-1):
318 # wrapper for self.import_hook() that won't raise ImportError
319 if name
in self
.badmodules
:
320 self
._add
_badmodule
(name
, caller
)
323 self
.import_hook(name
, caller
, level
=level
)
324 except ImportError, msg
:
325 self
.msg(2, "ImportError:", str(msg
))
326 self
._add
_badmodule
(name
, caller
)
330 if sub
in self
.badmodules
:
331 self
._add
_badmodule
(sub
, caller
)
334 self
.import_hook(name
, caller
, [sub
], level
=level
)
335 except ImportError, msg
:
336 self
.msg(2, "ImportError:", str(msg
))
337 fullname
= name
+ "." + sub
338 self
._add
_badmodule
(fullname
, caller
)
340 def scan_opcodes(self
, co
,
341 unpack
= struct
.unpack
):
342 # Scan the code, and yield 'interesting' opcode combinations
343 # Version for Python 2.4 and older
346 consts
= co
.co_consts
350 oparg
, = unpack('<H', code
[1:3])
351 yield "store", (names
[oparg
],)
354 if c
== LOAD_CONST
and code
[3] == IMPORT_NAME
:
355 oparg_1
, oparg_2
= unpack('<xHxH', code
[:6])
356 yield "import", (consts
[oparg_1
], names
[oparg_2
])
359 if c
>= HAVE_ARGUMENT
:
364 def scan_opcodes_25(self
, co
,
365 unpack
= struct
.unpack
):
366 # Scan the code, and yield 'interesting' opcode combinations
367 # Python 2.5 version (has absolute and relative imports)
370 consts
= co
.co_consts
371 LOAD_LOAD_AND_IMPORT
= LOAD_CONST
+ LOAD_CONST
+ IMPORT_NAME
375 oparg
, = unpack('<H', code
[1:3])
376 yield "store", (names
[oparg
],)
379 if code
[:9:3] == LOAD_LOAD_AND_IMPORT
:
380 oparg_1
, oparg_2
, oparg_3
= unpack('<xHxHxH', code
[:9])
381 level
= consts
[oparg_1
]
382 if level
== -1: # normal import
383 yield "import", (consts
[oparg_2
], names
[oparg_3
])
384 elif level
== 0: # absolute import
385 yield "absolute_import", (consts
[oparg_2
], names
[oparg_3
])
386 else: # relative import
387 yield "relative_import", (level
, consts
[oparg_2
], names
[oparg_3
])
390 if c
>= HAVE_ARGUMENT
:
395 def scan_code(self
, co
, m
):
397 if sys
.version_info
>= (2, 5):
398 scanner
= self
.scan_opcodes_25
400 scanner
= self
.scan_opcodes
401 for what
, args
in scanner(co
):
404 m
.globalnames
[name
] = 1
405 elif what
in ("import", "absolute_import"):
406 fromlist
, name
= args
408 if fromlist
is not None:
411 fromlist
= [f
for f
in fromlist
if f
!= "*"]
412 if what
== "absolute_import": level
= 0
414 self
._safe
_import
_hook
(name
, m
, fromlist
, level
=level
)
416 # We've encountered an "import *". If it is a Python module,
417 # the code has already been parsed and we can suck out the
421 # At this point we don't know whether 'name' is a
422 # submodule of 'm' or a global module. Let's just try
423 # the full name first.
424 mm
= self
.modules
.get(m
.__name
__ + "." + name
)
426 mm
= self
.modules
.get(name
)
428 m
.globalnames
.update(mm
.globalnames
)
429 m
.starimports
.update(mm
.starimports
)
430 if mm
.__code
__ is None:
431 m
.starimports
[name
] = 1
433 m
.starimports
[name
] = 1
434 elif what
== "relative_import":
435 level
, fromlist
, name
= args
437 self
._safe
_import
_hook
(name
, m
, fromlist
, level
=level
)
439 parent
= self
.determine_parent(m
, level
=level
)
440 self
._safe
_import
_hook
(parent
.__name
__, None, fromlist
, level
=0)
442 # We don't expect anything else from the generator.
443 raise RuntimeError(what
)
445 for c
in co
.co_consts
:
446 if isinstance(c
, type(co
)):
449 def load_package(self
, fqname
, pathname
):
450 self
.msgin(2, "load_package", fqname
, pathname
)
451 newname
= replacePackageMap
.get(fqname
)
454 m
= self
.add_module(fqname
)
455 m
.__file
__ = pathname
456 m
.__path
__ = [pathname
]
458 # As per comment at top of file, simulate runtime __path__ additions.
459 m
.__path
__ = m
.__path
__ + packagePathMap
.get(fqname
, [])
461 fp
, buf
, stuff
= self
.find_module("__init__", m
.__path
__)
462 self
.load_module(fqname
, fp
, buf
, stuff
)
463 self
.msgout(2, "load_package ->", m
)
468 def add_module(self
, fqname
):
469 if fqname
in self
.modules
:
470 return self
.modules
[fqname
]
471 self
.modules
[fqname
] = m
= Module(fqname
)
474 def find_module(self
, name
, path
, parent
=None):
475 if parent
is not None:
476 # assert path is not None
477 fullname
= parent
.__name
__+'.'+name
480 if fullname
in self
.excludes
:
481 self
.msgout(3, "find_module -> Excluded", fullname
)
482 raise ImportError, name
485 if name
in sys
.builtin_module_names
:
486 return (None, None, ("", "", imp
.C_BUILTIN
))
489 return imp
.find_module(name
, path
)
492 """Print a report to stdout, listing the found modules with their
493 paths, as well as modules that are missing, or seem to be missing.
496 print " %-25s %s" % ("Name", "File")
497 print " %-25s %s" % ("----", "----")
498 # Print modules found
499 keys
= self
.modules
.keys()
502 m
= self
.modules
[key
]
507 print "%-25s" % key
, m
.__file
__ or ""
509 # Print missing modules
510 missing
, maybe
= self
.any_missing_maybe()
513 print "Missing modules:"
515 mods
= self
.badmodules
[name
].keys()
517 print "?", name
, "imported from", ', '.join(mods
)
518 # Print modules that may be missing, but then again, maybe not...
521 print "Submodules that appear to be missing, but could also be",
522 print "global names in the parent package:"
524 mods
= self
.badmodules
[name
].keys()
526 print "?", name
, "imported from", ', '.join(mods
)
528 def any_missing(self
):
529 """Return a list of modules that appear to be missing. Use
530 any_missing_maybe() if you want to know which modules are
531 certain to be missing, and which *may* be missing.
533 missing
, maybe
= self
.any_missing_maybe()
534 return missing
+ maybe
536 def any_missing_maybe(self
):
537 """Return two lists, one with modules that are certainly missing
538 and one with modules that *may* be missing. The latter names could
539 either be submodules *or* just global names in the package.
541 The reason it can't always be determined is that it's impossible to
542 tell which names are imported when "from module import *" is done
543 with an extension module, short of actually importing it.
547 for name
in self
.badmodules
:
548 if name
in self
.excludes
:
556 pkg
= self
.modules
.get(pkgname
)
558 if pkgname
in self
.badmodules
[name
]:
559 # The package tried to import this module itself and
560 # failed. It's definitely missing.
562 elif subname
in pkg
.globalnames
:
563 # It's a global in the package: definitely not missing.
565 elif pkg
.starimports
:
566 # It could be missing, but the package did an "import *"
567 # from a non-Python module, so we simply can't be sure.
570 # It's not a global in the package, the package didn't
571 # do funny star imports, it's very likely to be missing.
572 # The symbol could be inserted into the package from the
573 # outside, but since that's not good style we simply list
580 return missing
, maybe
582 def replace_paths_in_code(self
, co
):
583 new_filename
= original_filename
= os
.path
.normpath(co
.co_filename
)
584 for f
, r
in self
.replace_paths
:
585 if original_filename
.startswith(f
):
586 new_filename
= r
+ original_filename
[len(f
):]
589 if self
.debug
and original_filename
not in self
.processed_paths
:
590 if new_filename
!= original_filename
:
591 self
.msgout(2, "co_filename %r changed to %r" \
592 % (original_filename
,new_filename
,))
594 self
.msgout(2, "co_filename %r remains unchanged" \
595 % (original_filename
,))
596 self
.processed_paths
.append(original_filename
)
598 consts
= list(co
.co_consts
)
599 for i
in range(len(consts
)):
600 if isinstance(consts
[i
], type(co
)):
601 consts
[i
] = self
.replace_paths_in_code(consts
[i
])
603 return types
.CodeType(co
.co_argcount
, co
.co_nlocals
, co
.co_stacksize
,
604 co
.co_flags
, co
.co_code
, tuple(consts
), co
.co_names
,
605 co
.co_varnames
, new_filename
, co
.co_name
,
606 co
.co_firstlineno
, co
.co_lnotab
,
607 co
.co_freevars
, co
.co_cellvars
)
614 opts
, args
= getopt
.getopt(sys
.argv
[1:], "dmp:qx:")
615 except getopt
.error
, msg
:
630 addpath
= addpath
+ a
.split(os
.pathsep
)
636 # Provide default arguments
642 # Set the path based on sys.path and the script directory
644 path
[0] = os
.path
.dirname(script
)
645 path
= addpath
+ path
649 print " ", repr(item
)
651 # Create the module finder and turn its crank
652 mf
= ModuleFinder(path
, debug
, exclude
)
659 mf
.import_hook(arg
[:-2], None, ["*"])
664 mf
.run_script(script
)
666 return mf
# for -i debugging
669 if __name__
== '__main__':
672 except KeyboardInterrupt:
673 print "\n[interrupt]"