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

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# 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/>.
22"""Few utility methods used by the rest of a package.
23"""
25__all__ = ["profile", "printTable", "filterTasks", "subTaskIter"]
27# -------------------------------
28# Imports of standard modules --
29# -------------------------------
30import contextlib
32# -----------------------------
33# Imports for other modules --
34# -----------------------------
35import lsst.pex.config as pexConfig
37# ----------------------------------
38# Local non-exported definitions --
39# ----------------------------------
41# ------------------------
42# Exported definitions --
43# ------------------------
46@contextlib.contextmanager
47def profile(filename, log=None):
48 """!Context manager for profiling with cProfile
50 @param filename filename to which to write profile (profiling disabled if None or empty)
51 @param log log object for logging the profile operations
53 If profiling is enabled, the context manager returns the cProfile.Profile object (otherwise
54 it returns None), which allows additional control over profiling. You can obtain this using
55 the "as" clause, e.g.:
57 with profile(filename) as prof:
58 runYourCodeHere()
60 The output cumulative profile can be printed with a command-line like:
62 python -c 'import pstats; pstats.Stats("<filename>").sort_stats("cumtime").print_stats(30)'
63 """
64 if not filename:
65 # Nothing to do
66 yield
67 return
68 from cProfile import Profile
70 prof = Profile()
71 if log is not None:
72 log.info("Enabling cProfile profiling")
73 prof.enable()
74 yield prof
75 prof.disable()
76 prof.dump_stats(filename)
77 if log is not None:
78 log.info("cProfile stats written to %s" % filename)
81def printTable(rows, header):
82 """Nice formatting of 2-column table.
84 Parameters
85 ----------
86 rows : `list` of `tuple`
87 Each item in the list is a 2-tuple containg left and righ column values
88 header: `tuple` or `None`
89 If `None` then table header are not prined, otherwise it's a 2-tuple
90 with column headings.
91 """
92 if not rows:
93 return
94 width = max(len(x[0]) for x in rows)
95 if header:
96 width = max(width, len(header[0]))
97 print(header[0].ljust(width), header[1])
98 print("".ljust(width, "-"), "".ljust(len(header[1]), "-"))
99 for col1, col2 in rows:
100 print(col1.ljust(width), col2)
103def filterTasks(pipeline, name):
104 """Finds list of tasks matching given name.
106 For matching task either task label or task name after last dot should
107 be identical to `name`. If task label is non-empty then task name is not
108 checked.
110 Parameters
111 ----------
112 pipeline : `Pipeline`
113 name : str or none
114 If empty or None then all tasks are returned
116 Returns
117 -------
118 Lsit of `TaskDef` instances.
119 """
120 if not name:
121 return list(pipeline.toExpandedPipeline())
122 tasks = []
123 for taskDef in pipeline.toExpandedPipeline():
124 if taskDef.label:
125 if taskDef.label == name:
126 tasks.append(taskDef)
127 elif taskDef.taskName.split('.')[-1] == name:
128 tasks.append(taskDef)
129 return tasks
132def subTaskIter(config):
133 """Recursively generates subtask names.
135 Parameters
136 ----------
137 config : `lsst.pex.config.Config`
138 Configuration of the task
140 Returns
141 -------
142 Iterator which returns tuples of (configFieldPath, taskName).
143 """
144 for fieldName, field in sorted(config.items()):
145 if hasattr(field, "value") and hasattr(field, "target"):
146 subConfig = field.value
147 if isinstance(subConfig, pexConfig.Config):
148 try:
149 taskName = "%s.%s" % (field.target.__module__, field.target.__name__)
150 except Exception:
151 taskName = repr(field.target)
152 yield fieldName, taskName
153 for subFieldName, taskName in subTaskIter(subConfig):
154 yield fieldName + '.' + subFieldName, taskName