diff --git a/plotly/graph_objs/graph_objs.py b/plotly/graph_objs/graph_objs.py index 7d77e6958cd..7618a8a609a 100644 --- a/plotly/graph_objs/graph_objs.py +++ b/plotly/graph_objs/graph_objs.py @@ -808,6 +808,7 @@ def to_string(self, level=0, indent=4, eol='\n', pretty=True, max_chars=80): obj_key = NAME_TO_KEY[self.__class__.__name__] for key in INFO[obj_key]: # this sets the order of the keys! nice. if key in self: + index += 1 string += "{eol}{indent}{key}=".format( eol=eol, indent=' ' * indent * (level+1), @@ -819,16 +820,40 @@ def to_string(self, level=0, indent=4, eol='\n', pretty=True, max_chars=80): pretty=pretty, max_chars=max_chars) except AttributeError: - val = repr(self[key]) - val_chars = max_chars - (indent*(level+1)) - (len(key)+1) - if pretty and (len(val) > val_chars): - string += val[:val_chars - 5] + '...' + val[-1] - else: - string += val - if index < len(self) - 1: + if pretty: # curtail representation if too many chars + max_len = (max_chars - + indent*(level + 1) - + len(key + "=") - + len(eol)) + if index < len(self): + max_len -= len(',') # remember the comma! + if isinstance(self[key], list): + s = "[]" + for iii, entry in enumerate(self[key], 1): + if iii < len(self[key]): + s_sub = graph_objs_tools.curtail_val_repr( + entry, + max_chars=max_len - len(s), + add_delim=True + ) + else: + s_sub = graph_objs_tools.curtail_val_repr( + entry, + max_chars=max_len - len(s), + add_delim=False + ) + s = s[:-1] + s_sub + s[-1] + if len(s) == max_len: + break + string += s + else: + string += graph_objs_tools.curtail_val_repr( + self[key], max_len) + else: # they want it all! + string += repr(self[key]) + if index < len(self): string += "," - index += 1 - if index == len(self): + if index == len(self): # TODO: extraneous... break string += "{eol}{indent})".format(eol=eol, indent=' ' * indent * level) return string @@ -1341,16 +1366,41 @@ def to_string(self, level=0, indent=4, eol='\n', pretty=True, max_chars=80): pretty=pretty, max_chars=max_chars) except AttributeError: - val = repr(self[key]) - val_chars = max_chars - (indent*(level+1)) - (len(key)+1) - if pretty and (len(val) > val_chars): - string += val[:val_chars - 5] + '...' + val[-1] - else: - string += val + if pretty: # curtail representation if too many chars + max_len = (max_chars - + indent*(level + 1) - + len(key + "=") - + len(eol)) + if index < len(self): + max_len -= len(',') # remember the comma! + if isinstance(self[key], list): + s = "[]" + for iii, entry in enumerate(self[key], 1): + if iii < len(self[key]): + s_sub = graph_objs_tools.curtail_val_repr( + entry, + max_chars=max_len - len(s), + add_delim=True + ) + else: + s_sub = graph_objs_tools.curtail_val_repr( + entry, + max_chars=max_len - len(s), + add_delim=False + ) + s = s[:-1] + s_sub + s[-1] + if len(s) == max_len: + break + string += s + else: + string += graph_objs_tools.curtail_val_repr( + self[key], max_len) + else: # they want it all! + string += repr(self[key]) if index < len(self) - 1: string += "," index += 1 - if index == len(self): + if index == len(self): # TODO: extraneous... break left_over_keys = [key for key in self if key not in INFO[obj_key]] left_over_keys.sort() diff --git a/plotly/graph_objs/graph_objs_tools.py b/plotly/graph_objs/graph_objs_tools.py index 4b4dbbd5c31..02444e12b3a 100644 --- a/plotly/graph_objs/graph_objs_tools.py +++ b/plotly/graph_objs/graph_objs_tools.py @@ -1,3 +1,5 @@ +import six + def update_keys(keys): """Change keys we used to support to their new equivalent.""" updated_keys = list() @@ -12,3 +14,32 @@ def update_keys(keys): scl="colorscale", reversescl="reversescale" ) + + +def curtail_val_repr(val, max_chars, add_delim=False): + delim = ", " + end = ".." + if isinstance(val, six.string_types): + if max_chars <= len("'" + end + "'"): + return ' ' * max_chars + elif add_delim and max_chars <= len("'" + end + "'") + len(delim): + return "'" + end + "'" + ' ' * (max_chars - len("'" + end + "'")) + else: + if max_chars <= len(end): + return ' ' * max_chars + elif add_delim and max_chars <= len(end) + len(delim): + return end + ' ' * (max_chars - len(end)) + if add_delim: + max_chars -= len(delim) + r = repr(val) + if len(r) > max_chars: + if isinstance(val, six.string_types): + # TODO: can we assume this ends in "'" + r = r[:max_chars - len(end + "'")] + end + "'" + elif isinstance(val, list) and max_chars >= len("[{end}]".format(end)): + r = r[:max_chars - len(end + ']')] + end + ']' + else: + r = r[:max_chars - len(end)] + end + if add_delim: + r += delim + return r