2018-05-08 12:22:19 +00:00
|
|
|
|
2018-05-12 13:10:19 +00:00
|
|
|
from __future__ import absolute_import
|
2018-05-13 00:47:11 +00:00
|
|
|
import collections
|
2018-05-08 12:22:19 +00:00
|
|
|
import imp
|
|
|
|
import os
|
|
|
|
import sys
|
|
|
|
|
2018-05-12 13:10:19 +00:00
|
|
|
import mitogen.master
|
|
|
|
import ansible.module_utils
|
2018-05-08 12:22:19 +00:00
|
|
|
|
|
|
|
|
2018-05-12 13:10:19 +00:00
|
|
|
PREFIX = 'ansible.module_utils.'
|
2018-05-08 12:22:19 +00:00
|
|
|
|
|
|
|
|
2018-05-13 00:47:11 +00:00
|
|
|
Module = collections.namedtuple('Module', 'name path kind parent')
|
2018-05-08 12:22:19 +00:00
|
|
|
|
2018-05-12 13:10:19 +00:00
|
|
|
|
2018-05-13 00:47:11 +00:00
|
|
|
def get_fullname(module):
|
|
|
|
bits = [str(module.name)]
|
|
|
|
while module.parent:
|
|
|
|
bits.append(str(module.parent.name))
|
|
|
|
module = module.parent
|
|
|
|
return '.'.join(reversed(bits))
|
2018-05-12 13:10:19 +00:00
|
|
|
|
2018-05-08 12:22:19 +00:00
|
|
|
|
2018-05-13 00:47:11 +00:00
|
|
|
def get_code(module):
|
|
|
|
fp = open(module.path)
|
|
|
|
try:
|
|
|
|
return compile(fp.read(), str(module.name), 'exec')
|
|
|
|
finally:
|
|
|
|
fp.close()
|
|
|
|
|
|
|
|
|
|
|
|
def is_pkg(module):
|
|
|
|
return module.kind == imp.PKG_DIRECTORY
|
2018-05-08 12:22:19 +00:00
|
|
|
|
|
|
|
|
|
|
|
def find(name, path=(), parent=None):
|
|
|
|
"""
|
|
|
|
(Name, search path) -> Module instance or None.
|
|
|
|
"""
|
2018-05-12 13:10:19 +00:00
|
|
|
head, _, tail = name.partition('.')
|
2018-05-08 12:22:19 +00:00
|
|
|
try:
|
2018-05-12 13:10:19 +00:00
|
|
|
tup = imp.find_module(head, list(path))
|
2018-05-08 12:22:19 +00:00
|
|
|
except ImportError:
|
|
|
|
return parent
|
|
|
|
|
|
|
|
fp, path, (suffix, mode, kind) = tup
|
|
|
|
if fp:
|
|
|
|
fp.close()
|
|
|
|
|
2018-05-12 13:10:19 +00:00
|
|
|
if kind == imp.PKG_DIRECTORY:
|
|
|
|
path = os.path.join(path, '__init__.py')
|
|
|
|
module = Module(head, path, kind, parent)
|
|
|
|
if tail:
|
|
|
|
return find_relative(module, tail, path)
|
2018-05-08 12:22:19 +00:00
|
|
|
return module
|
|
|
|
|
|
|
|
|
|
|
|
def find_relative(parent, name, path=()):
|
2018-05-12 13:10:19 +00:00
|
|
|
path = [os.path.dirname(parent.path)] + list(path)
|
2018-05-08 12:22:19 +00:00
|
|
|
return find(name, path, parent=parent)
|
|
|
|
|
|
|
|
|
2018-05-12 13:10:19 +00:00
|
|
|
def scan_fromlist(code):
|
|
|
|
for level, modname_s, fromlist in mitogen.master.scan_code_imports(code):
|
|
|
|
for name in fromlist:
|
|
|
|
yield level, '%s.%s' % (modname_s, name)
|
|
|
|
if not fromlist:
|
|
|
|
yield level, modname_s
|
2018-05-08 12:22:19 +00:00
|
|
|
|
|
|
|
|
2018-05-12 13:10:19 +00:00
|
|
|
def scan(module_name, module_path, search_path):
|
2018-05-13 00:47:11 +00:00
|
|
|
module = Module(
|
|
|
|
name=module_name,
|
|
|
|
path=module_path,
|
|
|
|
kind=imp.PY_SOURCE,
|
|
|
|
parent=None,
|
|
|
|
)
|
2018-05-12 13:10:19 +00:00
|
|
|
stack = [module]
|
|
|
|
seen = set()
|
2018-05-08 12:22:19 +00:00
|
|
|
|
2018-05-12 13:10:19 +00:00
|
|
|
while stack:
|
|
|
|
module = stack.pop(0)
|
2018-05-13 00:47:11 +00:00
|
|
|
for level, fromname in scan_fromlist(get_code(module)):
|
2018-05-12 13:10:19 +00:00
|
|
|
if not fromname.startswith(PREFIX):
|
|
|
|
continue
|
2018-05-08 12:22:19 +00:00
|
|
|
|
2018-05-12 13:10:19 +00:00
|
|
|
imported = find(fromname[len(PREFIX):], search_path)
|
|
|
|
if imported is None or imported in seen:
|
|
|
|
continue
|
2018-05-08 12:22:19 +00:00
|
|
|
|
2018-05-13 00:47:11 +00:00
|
|
|
if imported in seen:
|
|
|
|
continue
|
|
|
|
|
2018-05-12 13:10:19 +00:00
|
|
|
seen.add(imported)
|
2018-05-13 00:47:11 +00:00
|
|
|
stack.append(imported)
|
2018-05-12 13:10:19 +00:00
|
|
|
parent = imported.parent
|
|
|
|
while parent:
|
2018-05-13 00:47:11 +00:00
|
|
|
module = Module(
|
|
|
|
name=get_fullname(parent),
|
|
|
|
path=parent.path,
|
|
|
|
kind=parent.kind,
|
|
|
|
parent=None,
|
|
|
|
)
|
2018-05-12 13:10:19 +00:00
|
|
|
if module not in seen:
|
|
|
|
seen.add(module)
|
|
|
|
stack.append(module)
|
|
|
|
parent = parent.parent
|
|
|
|
|
|
|
|
return sorted(
|
2018-05-13 00:47:11 +00:00
|
|
|
(PREFIX + get_fullname(module), module.path, is_pkg(module))
|
2018-05-12 13:10:19 +00:00
|
|
|
for module in seen
|
|
|
|
)
|