custom_descriptions.py
5.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# Copyright (C) 2018 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Custom descriptions and summaries for the builtin types.
The docstrings for objects of primitive types reflect the type of the object,
rather than the object itself. For example, the docstring for any dict is this:
> print({'key': 'value'}.__doc__)
dict() -> new empty dictionary
dict(mapping) -> new dictionary initialized from a mapping object's
(key, value) pairs
dict(iterable) -> new dictionary initialized as if via:
d = {}
for k, v in iterable:
d[k] = v
dict(**kwargs) -> new dictionary initialized with the name=value pairs
in the keyword argument list. For example: dict(one=1, two=2)
As you can see, this docstring is more pertinant to the function `dict` and
would be suitable as the result of `dict.__doc__`, but is wholely unsuitable
as a description for the dict `{'key': 'value'}`.
This modules aims to resolve that problem, providing custom summaries and
descriptions for primitive typed values.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from fire import formatting
import six
TWO_DOUBLE_QUOTES = '""'
STRING_DESC_PREFIX = 'The string '
def NeedsCustomDescription(component):
"""Whether the component should use a custom description and summary.
Components of primitive type, such as ints, floats, dicts, lists, and others
have messy builtin docstrings. These are inappropriate for display as
descriptions and summaries in a CLI. This function determines whether the
provided component has one of these docstrings.
Note that an object such as `int` has the same docstring as an int like `3`.
The docstring is OK for `int`, but is inappropriate as a docstring for `3`.
Args:
component: The component of interest.
Returns:
Whether the component should use a custom description and summary.
"""
type_ = type(component)
if (type_ in six.string_types
or type_ in six.integer_types
or type_ is six.text_type
or type_ is six.binary_type
or type_ in (float, complex, bool)
or type_ in (dict, tuple, list, set, frozenset)
):
return True
return False
def GetStringTypeSummary(obj, available_space, line_length):
"""Returns a custom summary for string type objects.
This function constructs a summary for string type objects by double quoting
the string value. The double quoted string value will be potentially truncated
with ellipsis depending on whether it has enough space available to show the
full string value.
Args:
obj: The object to generate summary for.
available_space: Number of character spaces available.
line_length: The full width of the terminal, default is 80.
Returns:
A summary for the input object.
"""
if len(obj) + len(TWO_DOUBLE_QUOTES) <= available_space:
content = obj
else:
additional_len_needed = len(TWO_DOUBLE_QUOTES) + len(formatting.ELLIPSIS)
if available_space < additional_len_needed:
available_space = line_length
content = formatting.EllipsisTruncate(
obj, available_space - len(TWO_DOUBLE_QUOTES), line_length)
return formatting.DoubleQuote(content)
def GetStringTypeDescription(obj, available_space, line_length):
"""Returns the predefined description for string obj.
This function constructs a description for string type objects in the format
of 'The string "<string_value>"'. <string_value> could be potentially
truncated depending on whether it has enough space available to show the full
string value.
Args:
obj: The object to generate description for.
available_space: Number of character spaces available.
line_length: The full width of the terminal, default if 80.
Returns:
A description for input object.
"""
additional_len_needed = len(STRING_DESC_PREFIX) + len(
TWO_DOUBLE_QUOTES) + len(formatting.ELLIPSIS)
if available_space < additional_len_needed:
available_space = line_length
return STRING_DESC_PREFIX + formatting.DoubleQuote(
formatting.EllipsisTruncate(
obj, available_space - len(STRING_DESC_PREFIX) -
len(TWO_DOUBLE_QUOTES), line_length))
CUSTOM_DESC_SUM_FN_DICT = {
'str': (GetStringTypeSummary, GetStringTypeDescription),
'unicode': (GetStringTypeSummary, GetStringTypeDescription),
}
def GetSummary(obj, available_space, line_length):
obj_type_name = type(obj).__name__
if obj_type_name in CUSTOM_DESC_SUM_FN_DICT.keys():
return CUSTOM_DESC_SUM_FN_DICT.get(obj_type_name)[0](obj, available_space,
line_length)
return None
def GetDescription(obj, available_space, line_length):
obj_type_name = type(obj).__name__
if obj_type_name in CUSTOM_DESC_SUM_FN_DICT.keys():
return CUSTOM_DESC_SUM_FN_DICT.get(obj_type_name)[1](obj, available_space,
line_length)
return None