LSSTApplications  10.0-2-g4f67435,11.0.rc2+1,11.0.rc2+12,11.0.rc2+3,11.0.rc2+4,11.0.rc2+5,11.0.rc2+6,11.0.rc2+7,11.0.rc2+8
LSSTDataManagementBasePackage
history.py
Go to the documentation of this file.
1 #
2 # LSST Data Management System
3 # Copyright 2008, 2009, 2010 LSST Corporation.
4 #
5 # This product includes software developed by the
6 # LSST Project (http://www.lsst.org/).
7 #
8 # This program is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation, either version 3 of the License, or
11 # (at your option) any later version.
12 #
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the LSST License Statement and
19 # the GNU General Public License along with this program. If not,
20 # see <http://www.lsstcorp.org/LegalNotices/>.
21 #
22 
23 import os
24 import re
25 import sys
26 
27 #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
28 
29 
30 class Color(object):
31  categories = dict(
32  NAME = "blue",
33  VALUE = "yellow",
34  FILE = "green",
35  TEXT = "red",
36  FUNCTION_NAME = "blue",
37  )
38 
39  colors = {
40  "black" : 0,
41  "red" : 1,
42  "green" : 2,
43  "yellow" : 3,
44  "blue" : 4,
45  "magenta": 5,
46  "cyan" : 6,
47  "white" : 7,
48  }
49 
50  _colorize = True
51 
52  def __init__(self, text, category):
53  """Return a string that should display as coloured on a conformant terminal"""
54  try:
55  color = Color.categories[category]
56  except KeyError:
57  raise RuntimeError("Unknown category: %s" % category)
58 
59  self.rawText = str(text)
60  x = color.lower().split(";")
61  self.color, bold = x.pop(0), False
62  if x:
63  props = x.pop(0)
64  if props in ("bold",):
65  bold = True
66 
67  try:
68  self._code = "%s" % (30 + Color.colors[self.color])
69  except KeyError:
70  raise RuntimeError("Unknown colour: %s" % self.color)
71 
72  if bold:
73  self._code += ";1"
74 
75  @staticmethod
76  def colorize(val=None):
77  """Should I colour strings? With an argument, set the value"""
78 
79  if val is not None:
80  Color._colorize = val
81 
82  if isinstance(val, dict):
83  unknown = []
84  for k in val.keys():
85  if Color.categories.has_key(k):
86  if Color.colors.has_key(val[k]):
87  Color.categories[k] = val[k]
88  else:
89  print >> sys.stderr, "Unknown colour %s for category %s" % (val[k], k)
90  else:
91  unknown.append(k)
92 
93  if unknown:
94  print >> sys.stderr, "Unknown colourizing category: %s" % " ".join(unknown)
95 
96  return Color._colorize
97 
98  def __str__(self):
99  if not self.colorize():
100  return self.rawText
101 
102  base = "\033["
103 
104  prefix = base + self._code + "m"
105  suffix = base + "m"
106 
107  return prefix + self.rawText + suffix
108 
109 
110 def _colorize(text, category):
111  text = Color(text, category)
112  return str(text)
113 
114 #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
115 
116 class StackFrame(object):
117  def __init__(self, stackTrace):
118  self.fileName = stackTrace[0]
119  self.lineNumber = stackTrace[1]
120  self.functionName = stackTrace[2]
121  self.text = stackTrace[3]
122 
123  self.fileName = re.sub(r'.*/python/lsst/', "", self.fileName)
124 
125 #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
126 
127 def format(config, name=None, writeSourceLine=True, prefix="", verbose=False):
128  """Format the history record for config.name"""
129 
130  if name is None:
131  for i, name in enumerate(config.history.keys()):
132  if i > 0:
133  print
134  print format(config, name)
135 
136  outputs = []
137  for value, tb, label in config.history[name]:
138  output = []
139  for frame in [StackFrame(t) for t in tb]:
140  if frame.functionName in ("__new__", "__set__", "__setattr__", "execfile", "wrapper") or \
141  os.path.split(frame.fileName)[1] in ("argparse.py", "argumentParser.py"):
142  if not verbose:
143  continue
144 
145  line = []
146  if writeSourceLine:
147  line.append(["%s" % ("%s:%d" % (frame.fileName, frame.lineNumber)), "FILE",])
148 
149  line.append([frame.text, "TEXT",])
150  if False:
151  line.append([frame.functionName, "FUNCTION_NAME",])
152 
153  output.append(line)
154 
155  outputs.append([value, output])
156  #
157  # Find the maximum widths of the value and file:lineNo fields
158  #
159  if writeSourceLine:
160  sourceLengths = []
161  for value, output in outputs:
162  sourceLengths.append(max([len(x[0][0]) for x in output]))
163  sourceLength = max(sourceLengths)
164 
165  valueLength = len(prefix) + max([len(str(value)) for value, output in outputs])
166  #
167  # actually generate the config history
168  #
169  msg = []
170  fullname = "%s.%s" %(config._name, name) if config._name is not None else name
171  msg.append(_colorize(re.sub(r"^root\.", "", fullname), "NAME"))
172  for value, output in outputs:
173  line = prefix + _colorize("%-*s" % (valueLength, value), "VALUE") + " "
174  for i, vt in enumerate(output):
175  if writeSourceLine:
176  vt[0][0] = "%-*s" % (sourceLength, vt[0][0])
177 
178  output[i] = " ".join([_colorize(v, t) for v, t in vt])
179 
180  line += ("\n%*s" % (valueLength + 1, "")).join(output)
181  msg.append(line)
182 
183  return "\n".join(msg)
184