Coverage for python/lsst/ctrl/mpexec/util.py: 11%

Shortcuts 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

52 statements  

1# This file is part of ctrl_mpexec. 

2# 

3# Developed for the LSST Data Management System. 

4# This product includes software developed by the LSST Project 

5# (http://www.lsst.org). 

6# See the COPYRIGHT file at the top-level directory of this distribution 

7# for details of code ownership. 

8# 

9# This program is free software: you can redistribute it and/or modify 

10# it under the terms of the GNU General Public License as published by 

11# the Free Software Foundation, either version 3 of the License, or 

12# (at your option) any later version. 

13# 

14# This program is distributed in the hope that it will be useful, 

15# but WITHOUT ANY WARRANTY; without even the implied warranty of 

16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

17# GNU General Public License for more details. 

18# 

19# You should have received a copy of the GNU General Public License 

20# along with this program. If not, see <http://www.gnu.org/licenses/>. 

21 

22"""Few utility methods used by the rest of a package. 

23""" 

24 

25__all__ = ["profile", "printTable", "filterTasks", "subTaskIter"] 

26 

27# ------------------------------- 

28# Imports of standard modules -- 

29# ------------------------------- 

30import contextlib 

31 

32# ----------------------------- 

33# Imports for other modules -- 

34# ----------------------------- 

35import lsst.pex.config as pexConfig 

36 

37# ---------------------------------- 

38# Local non-exported definitions -- 

39# ---------------------------------- 

40 

41# ------------------------ 

42# Exported definitions -- 

43# ------------------------ 

44 

45 

46@contextlib.contextmanager 

47def profile(filename, log=None): 

48 """Context manager for profiling with cProfile 

49 

50 Parameters 

51 ---------- 

52 filename : 

53 Filename to which to write profile (profiling disabled if `None` 

54 or empty). 

55 log : 

56 Log object for logging the profile operations. 

57 

58 Yields 

59 ------ 

60 profile : `cProfile.Profile` or `None` 

61 If profiling is enabled, the context manager returns the 

62 `cProfile.Profile` object (otherwise it returns `None`) 

63 

64 Notes 

65 ----- 

66 The returned profile object allows additional control 

67 over profiling. You can obtain this using the ``as`` clause, e.g.: 

68 

69 .. code-block:: py 

70 

71 with profile(filename) as prof: 

72 runYourCodeHere() 

73 

74 The output cumulative profile can be printed with a command-line like: 

75 

76 .. code-block:: bash 

77 

78 python -c 'import pstats; pstats.Stats("<filename>").\ 

79 sort_stats("cumtime").print_stats(30)' 

80 """ 

81 if not filename: 

82 # Nothing to do 

83 yield 

84 return 

85 from cProfile import Profile 

86 

87 prof = Profile() 

88 if log is not None: 

89 log.info("Enabling cProfile profiling") 

90 prof.enable() 

91 yield prof 

92 prof.disable() 

93 prof.dump_stats(filename) 

94 if log is not None: 

95 log.info("cProfile stats written to %s" % filename) 

96 

97 

98def printTable(rows, header): 

99 """Nice formatting of 2-column table. 

100 

101 Parameters 

102 ---------- 

103 rows : `list` of `tuple` 

104 Each item in the list is a 2-tuple containg left and righ column values 

105 header: `tuple` or `None` 

106 If `None` then table header are not prined, otherwise it's a 2-tuple 

107 with column headings. 

108 """ 

109 if not rows: 

110 return 

111 width = max(len(x[0]) for x in rows) 

112 if header: 

113 width = max(width, len(header[0])) 

114 print(header[0].ljust(width), header[1]) 

115 print("".ljust(width, "-"), "".ljust(len(header[1]), "-")) 

116 for col1, col2 in rows: 

117 print(col1.ljust(width), col2) 

118 

119 

120def filterTasks(pipeline, name): 

121 """Finds list of tasks matching given name. 

122 

123 For matching task either task label or task name after last dot should 

124 be identical to `name`. If task label is non-empty then task name is not 

125 checked. 

126 

127 Parameters 

128 ---------- 

129 pipeline : `Pipeline` 

130 name : str or none 

131 If empty or None then all tasks are returned 

132 

133 Returns 

134 ------- 

135 Lsit of `TaskDef` instances. 

136 """ 

137 if not name: 

138 return list(pipeline.toExpandedPipeline()) 

139 tasks = [] 

140 for taskDef in pipeline.toExpandedPipeline(): 

141 if taskDef.label: 

142 if taskDef.label == name: 

143 tasks.append(taskDef) 

144 elif taskDef.taskName.split(".")[-1] == name: 

145 tasks.append(taskDef) 

146 return tasks 

147 

148 

149def subTaskIter(config): 

150 """Recursively generates subtask names. 

151 

152 Parameters 

153 ---------- 

154 config : `lsst.pex.config.Config` 

155 Configuration of the task 

156 

157 Returns 

158 ------- 

159 Iterator which returns tuples of (configFieldPath, taskName). 

160 """ 

161 for fieldName, field in sorted(config.items()): 

162 if hasattr(field, "value") and hasattr(field, "target"): 

163 subConfig = field.value 

164 if isinstance(subConfig, pexConfig.Config): 

165 try: 

166 taskName = "%s.%s" % (field.target.__module__, field.target.__name__) 

167 except Exception: 

168 taskName = repr(field.target) 

169 yield fieldName, taskName 

170 for subFieldName, taskName in subTaskIter(subConfig): 

171 yield fieldName + "." + subFieldName, taskName