Coverage for src/pymyinstall/installhelper/module_dependencies.py: 97%

30 statements  

« prev     ^ index     » next       coverage.py v7.1.0, created at 2023-07-19 01:47 +0200

1""" 

2@file 

3@brief Guess missing dependencies 

4""" 

5from .pip_helper import get_installed_distributions 

6 

7 

8def get_default_ignore_modules(): 

9 """ 

10 A couple of modules have some dependencies on not supported modules 

11 or modules integrated to the standard distributiion such 

12 `enum34 <https://pypi.python.org/pypi/enum34>`_. 

13 This function returns this list. 

14 Skips errors such as ``Module 'cachecontrol' misses 'msgpack_python'``. 

15 """ 

16 return [ 

17 "argparse", # standard distribution (>= 3.5) 

18 "backports.weakref", # standard distribution (>= 3.4) 

19 "distribute", # standard distribution 

20 "enum", # standard distribution (>= 3.4) 

21 "enum34", # standard distribution (>= 3.4) 

22 "enum_compat", # standard distribution (>= 3.4) 

23 "enum-compat", # standard distribution (>= 3.4) 

24 "fasttsne", # deprecated module 

25 "futures", # standard distribution (>= 3.5) 

26 "holoviews", # needed by geoviews but still marked as missing 

27 "hypertemp", # temporary solution, should disappear 

28 "keyrings.alt", # weird this one on Windows 

29 # "guidata", 

30 # "monotonic", 

31 "msgpack_python", # Called msgpack now. 

32 "msgpack-python", # Called msgpack now. 

33 "onnx", # working on it 

34 "ordereddict", # standard distribution (>= 3.4) 

35 "path", # subfolder of existing module 

36 "path.py", # weird 

37 "pathlib", # standard distribution (>= 3.5) 

38 "pip", # almost standard distribution, should be rare 

39 "pipdeptree", # weird 

40 # manny names for this one (PTable, not maintained anymore) 

41 "prettytable", 

42 "pycryptodome", # many names for this one 

43 "pydocstyle", # does not seem to be maintained 

44 "pyopengl", # weird this one 

45 "pypiwin32", # manny names for this one 

46 "pythonnet", # weird 

47 "pywin32", # manny names for this one 

48 "pywin32_ctypes", # manny names for this one 

49 "rope", # for spyder 

50 "setuptools", # standard distribution 

51 ] 

52 

53 

54def _main_pipdeptree(local_only=False): 

55 """ 

56 The function relies on module 

57 `pipdeptree.main <https://pypi.python.org/pypi/pipdeptree>`_. 

58 """ 

59 default_skip = ['setuptools', 'pip', 'python', 'distribute', 'hypertemp'] 

60 skip = default_skip + ['pipdeptree'] 

61 pkgs = get_installed_distributions(local_only=local_only, skip=skip) 

62 req_map = dict((p.key, (p, p.requires())) for p in pkgs) 

63 return req_map 

64 

65 

66def missing_dependencies(specific=None, ignore_module=get_default_ignore_modules()): 

67 """ 

68 Returns the list of missing dependencies for the installed modules. 

69 

70 @param specific look dependencies only for a specific module 

71 @param ignore_module list of modules not to consider as a missing dependency 

72 even if they are installed 

73 @return list of missing dependencies as dictionary (module, missing dependencies) 

74 

75 .. versionchanged:: 1.5 

76 Parameters *ignore_module*. 

77 """ 

78 skip = set(ignore_module) 

79 tree = _main_pipdeptree() 

80 stack = {} 

81 for k, v in tree.items(): 

82 if specific is not None and specific != k: 

83 continue 

84 for mod in v[1]: 

85 dep = mod.key 

86 if dep in skip: 

87 continue 

88 if dep not in tree: 

89 if "-" in dep: 

90 dep = dep.replace("-", "_") 

91 elif "_" in dep: 

92 dep = dep.replace("_", "_") 

93 if dep not in tree: 

94 if k not in stack: 

95 stack[k] = [] 

96 stack[k].append(dep) 

97 return stack