• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14# ==============================================================================
15"""Configurations for TensorFlow Debugger (TFDBG) command-line interfaces."""
16from __future__ import absolute_import
17from __future__ import division
18from __future__ import print_function
19
20import collections
21import json
22import os
23
24from tensorflow.python.debug.cli import debugger_cli_common
25from tensorflow.python.platform import gfile
26
27RL = debugger_cli_common.RichLine
28
29
30class CLIConfig(object):
31  """Client-facing configurations for TFDBG command-line interfaces."""
32
33  _CONFIG_FILE_NAME = ".tfdbg_config"
34
35  _DEFAULT_CONFIG = [
36      ("graph_recursion_depth", 20),
37      ("mouse_mode", True),
38  ]
39
40  def __init__(self, config_file_path=None):
41    self._config_file_path = (config_file_path or
42                              self._default_config_file_path())
43    self._config = collections.OrderedDict(self._DEFAULT_CONFIG)
44    if gfile.Exists(self._config_file_path):
45      config = self._load_from_file()
46      for key, value in config.items():
47        self._config[key] = value
48    self._save_to_file()
49
50    self._set_callbacks = {}
51
52  def get(self, property_name):
53    if property_name not in self._config:
54      raise KeyError("%s is not a valid property name." % property_name)
55    return self._config[property_name]
56
57  def set(self, property_name, property_val):
58    """Set the value of a property.
59
60    Supports limitd property value types: `bool`, `int` and `str`.
61
62    Args:
63      property_name: Name of the property.
64      property_val: Value of the property. If the property has `bool` type and
65        this argument has `str` type, the `str` value will be parsed as a `bool`
66
67    Raises:
68      ValueError: if a `str` property_value fails to be parsed as a `bool`.
69      KeyError: if `property_name` is an invalid property name.
70    """
71    if property_name not in self._config:
72      raise KeyError("%s is not a valid property name." % property_name)
73
74    orig_val = self._config[property_name]
75    if isinstance(orig_val, bool):
76      if isinstance(property_val, str):
77        if property_val.lower() in ("1", "true", "t", "yes", "y", "on"):
78          property_val = True
79        elif property_val.lower() in ("0", "false", "f", "no", "n", "off"):
80          property_val = False
81        else:
82          raise ValueError(
83              "Invalid string value for bool type: %s" % property_val)
84      else:
85        property_val = bool(property_val)
86    elif isinstance(orig_val, int):
87      property_val = int(property_val)
88    elif isinstance(orig_val, str):
89      property_val = str(property_val)
90    else:
91      raise TypeError("Unsupported property type: %s" % type(orig_val))
92    self._config[property_name] = property_val
93    self._save_to_file()
94
95    # Invoke set-callback.
96    if property_name in self._set_callbacks:
97      self._set_callbacks[property_name](self._config)
98
99  def set_callback(self, property_name, callback):
100    """Set a set-callback for given property.
101
102    Args:
103      property_name: Name of the property.
104      callback: The callback as a `callable` of signature:
105          def cbk(config):
106        where config is the config after it is set to the new value.
107        The callback is invoked each time the set() method is called with the
108        matching property_name.
109
110    Raises:
111      KeyError: If property_name does not exist.
112      TypeError: If `callback` is not callable.
113    """
114    if property_name not in self._config:
115      raise KeyError("%s is not a valid property name." % property_name)
116    if not callable(callback):
117      raise TypeError("The callback object provided is not callable.")
118    self._set_callbacks[property_name] = callback
119
120  def _default_config_file_path(self):
121    return os.path.join(os.path.expanduser("~"), self._CONFIG_FILE_NAME)
122
123  def _save_to_file(self):
124    try:
125      with gfile.Open(self._config_file_path, "w") as config_file:
126        json.dump(self._config, config_file)
127    except IOError:
128      pass
129
130  def summarize(self, highlight=None):
131    """Get a text summary of the config.
132
133    Args:
134      highlight: A property name to highlight in the output.
135
136    Returns:
137      A `RichTextLines` output.
138    """
139    lines = [RL("Command-line configuration:", "bold"), RL("")]
140    for name, val in self._config.items():
141      highlight_attr = "bold" if name == highlight else None
142      line = RL("  ")
143      line += RL(name, ["underline", highlight_attr])
144      line += RL(": ")
145      line += RL(str(val), font_attr=highlight_attr)
146      lines.append(line)
147    return debugger_cli_common.rich_text_lines_from_rich_line_list(lines)
148
149  def _load_from_file(self):
150    try:
151      with gfile.Open(self._config_file_path, "r") as config_file:
152        config_dict = json.load(config_file)
153        config = collections.OrderedDict()
154        for key in sorted(config_dict.keys()):
155          config[key] = config_dict[key]
156        return config
157    except (IOError, ValueError):
158      # The reading of the config file may fail due to IO issues or file
159      # corruption. We do not want tfdbg to error out just because of that.
160      return dict()
161