28 __all__ = (
'Color',
'format')
36 """A controller that determines whether strings should be colored.
41 Text content to print to a terminal.
43 Semantic category of the ``text``. See `categories` for possible
49 Raised when the ``category`` is not a key of ``Color.categories``.
53 The usual usage is ``Color(string, category)`` which returns a string that
54 may be printed; categories are given by the keys of `Color.categories`.
56 `Color.colorize` may be used to set or retrieve whether the user wants
57 color. It always returns `False` when `sys.stdout` is not attached to a
68 """Mapping of semantic labels to color names (`dict`).
72 The default categories are:
91 """Mapping of color names to terminal color codes (`dict`).
98 color = Color.categories[category]
100 raise RuntimeError(
"Unknown category: %s" % category)
103 x = color.lower().split(
";")
104 self.color, bold = x.pop(0),
False
107 if props
in (
"bold",):
111 self.
_code =
"%s" % (30 + Color.colors[self.color])
113 raise RuntimeError(
"Unknown colour: %s" % self.color)
120 """Get or set whether the string should be colorized.
124 val : `bool` or `dict`, optional
125 The value is usually a bool, but it may be a dict which is used
126 to modify Color.categories
130 shouldColorize : `bool`
131 If `True`, the string should be colorized. A string **will not** be
132 colorized if standard output or standard error are not attached to
133 a terminal or if the ``val`` argument was `False`.
135 Only strings written to a terminal are colorized.
139 Color._colorize = val
141 if isinstance(val, dict):
144 if k
in Color.categories:
145 if val[k]
in Color.colors:
146 Color.categories[k] = val[k]
148 print(
"Unknown colour %s for category %s" % (val[k], k), file=sys.stderr)
153 print(
"Unknown colourizing category: %s" %
" ".join(unknown), file=sys.stderr)
155 return Color._colorize
if sys.stdout.isatty()
else False
163 prefix = base + self.
_code +
"m"
166 return prefix + self.
rawText + suffix
169 def _colorize(text, category):
170 text =
Color(text, category)
174 def format(config, name=None, writeSourceLine=True, prefix="", verbose=False):
175 """Format the history record for a configuration, or a specific
180 config : `lsst.pex.config.Config`
181 A configuration instance.
182 name : `str`, optional
183 The name of a configuration field to specifically format the history
184 for. Otherwise the history of all configuration fields is printed.
185 writeSourceLine : `bool`, optional
186 If `True`, prefix each printout line with the code filename and line
187 number where the configuration event occurred. Default is `True`.
188 prefix : `str`, optional
189 A prefix for to add to each printout line. This prefix occurs first,
190 even before any source line. The default is an empty string.
191 verbose : `bool`, optional
196 for i, name
in enumerate(config.history.keys()):
199 print(
format(config, name))
202 for value, stack, label
in config.history[name]:
205 if frame.function
in (
"__new__",
"__set__",
"__setattr__",
"execfile",
"wrapper")
or \
206 os.path.split(frame.filename)[1]
in (
"argparse.py",
"argumentParser.py"):
212 line.append([
"%s" % (
"%s:%d" % (frame.filename, frame.lineno)),
"FILE", ])
214 line.append([frame.content,
"TEXT", ])
216 line.append([frame.function,
"FUNCTION_NAME", ])
220 outputs.append([value, output])
225 for value, output
in outputs:
226 sourceLengths.append(
max([len(x[0][0])
for x
in output]))
227 sourceLength =
max(sourceLengths)
229 valueLength = len(prefix) +
max([len(str(value))
for value, output
in outputs])
233 fullname =
"%s.%s" % (config._name, name)
if config._name
is not None else name
234 msg.append(_colorize(re.sub(
r"^root\.",
"", fullname),
"NAME"))
235 for value, output
in outputs:
236 line = prefix + _colorize(
"%-*s" % (valueLength, value),
"VALUE") +
" "
237 for i, vt
in enumerate(output):
239 vt[0][0] =
"%-*s" % (sourceLength, vt[0][0])
241 output[i] =
" ".join([_colorize(v, t)
for v, t
in vt])
243 line += (
"\n%*s" % (valueLength + 1,
"")).join(output)
246 return "\n".join(msg)