Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1""" 

2@file 

3@brief Helpers for pip 

4 

5Some links to look: 

6 

7* `installing_python_packages_programatically.py <https://gist.github.com/rwilcox/755524>`_ 

8* `Calling pip programmatically <http://blog.ducky.io/python/2013/08/22/calling-pip-programmatically/>`_ 

9""" 

10 

11 

12class PQPipError(Exception): 

13 """ 

14 Any exception raised by one of the following function. 

15 """ 

16 

17 def __init__(self, *args): 

18 """ 

19 @param args either a string 3 strings (cmd, out, err) 

20 """ 

21 if len(args) == 1: 

22 Exception.__init__(self, args[0]) # pragma: no cover 

23 else: 

24 cmd, out, err = args 

25 mes = "CMD:\n{0}\nOUT:\n{1}\n[piperror]\n{2}".format(cmd, out, err) 

26 Exception.__init__(self, mes) 

27 

28 

29class Distribution: 

30 """ 

31 Common interface for old and recent pip packages. 

32 

33 .. versionadded:: 1.5 

34 """ 

35 

36 def __init__(self, dist): 

37 self.dist = dist 

38 

39 def __getattr__(self, attr): 

40 if attr == 'key': 

41 if hasattr(self.__dict__['dist'], 'key'): 

42 return self.__dict__['dist'].key 

43 return self.__dict__['dist'].canonical_name 

44 if attr == 'dist': 

45 return self.__dict__['dist'] 

46 if attr in {'_get_metadata', 'requires', 'PKG_INFO', 'project_name', 

47 'py_version', 'platform', 'extras'}: 

48 if hasattr(self.__dict__['dist'], attr): 

49 return getattr(self.__dict__['dist'], attr) 

50 return getattr(self.__dict__['dist']._dist, attr) 

51 return getattr(self.__dict__['dist'], attr) 

52 

53 

54def get_installed_distributions(local_only=True, skip=None, 

55 include_editables=True, editables_only=False, 

56 user_only=False, use_cmd=False): 

57 """ 

58 Directs call to function *get_installed_distributions* from :epkg:`pip`. 

59 

60 Return a list of installed Distribution objects. 

61 

62 :param local_only: if True (default), only return installations 

63 local to the current virtualenv, if in a virtualenv. 

64 :param skip: argument is an iterable of lower-case project names to 

65 ignore; defaults to ``pip.compat.stdlib_pkgs`` (if *skip* is None) 

66 :param editables: if False, don't report editables. 

67 :param editables_only: if True , only report editables. 

68 :param user_only: if True , only report installations in the user 

69 site directory. 

70 :param use_cmd: if True, use a different process (updated package list) 

71 :return: list of installed Distribution objects. 

72 

73 .. versionadded:: 1.5 

74 """ 

75 if use_cmd: 

76 raise NotImplementedError("use_cmd should be False") 

77 if skip is None: 

78 try: 

79 from pip._internal.utils.compat import stdlib_pkgs 

80 skip = stdlib_pkgs 

81 except ImportError: 

82 pass 

83 try: 

84 from pip._internal.metadata import get_default_environment 

85 return list(map(Distribution, 

86 get_default_environment().iter_installed_distributions( 

87 local_only=local_only, skip=skip, 

88 include_editables=include_editables, 

89 editables_only=editables_only, 

90 user_only=user_only))) 

91 

92 except ImportError: 

93 from pip._internal.utils.misc import get_installed_distributions as getd 

94 return list(map(Distribution, getd( 

95 local_only=local_only, skip=skip, 

96 include_editables=include_editables, 

97 editables_only=editables_only, 

98 user_only=user_only, use_cmd=use_cmd))) 

99 

100 

101def get_packages_list(): 

102 """ 

103 calls ``pip list`` to retrieve the list of packages 

104 """ 

105 return get_installed_distributions(local_only=True) 

106 

107 

108def package2dict(pkg): 

109 """ 

110 Extracts information from a package. 

111 

112 @param pkg type *pip._vendor.pkg_resources.Distribution* 

113 @return dictionary 

114 """ 

115 return dict( 

116 version=pkg.version, 

117 project_name=pkg.project_name, 

118 py_version=pkg.py_version, 

119 requires=pkg.requires, 

120 platform=pkg.platform, 

121 extras=pkg.extras, 

122 location=pkg.location) 

123 

124 

125def get_package_info(name=None, start=0, end=-1): 

126 """ 

127 Calls ``pip show`` to retrieve information about packages. 

128 

129 @param name name of he packages or None to get all of them in a list 

130 @param start start at package n (in list return by @see fn get_packages_list) 

131 @param end end at package n, -1 for all 

132 @return dictionary or list of dictionaries 

133 """ 

134 from pip._internal.commands.show import search_packages_info 

135 if name is None: 

136 res = [] 

137 packs = get_packages_list() 

138 if end == -1: 

139 end = len(packs) # pragma: no cover 

140 subp = packs[start:end] 

141 if len(subp) == 0: 

142 raise PQPipError( # pragma: no cover 

143 "No package, start={0}, end={1}, len(subp)={2}, len(packs)={3}".format( 

144 start, end, len(subp), len(packs))) 

145 for cp in subp: 

146 pack = cp.project_name 

147 info = get_package_info(pack) 

148 res.append(info) 

149 if len(res) == 0 and len(subp) > 0: 

150 raise PQPipError( # pragma: no cover 

151 "Empty list, unexpected, start={0}, end={1}, len(subp)={3}".format( 

152 start, end, len(subp))) 

153 return res 

154 

155 res = list(search_packages_info([name])) 

156 if len(res) != 1: 

157 raise PQPipError( # pragma: no cover 

158 "Unexpected number of results {0} for {1}".format( 

159 len(res), name)) 

160 return res[0]