From ab51159649240c76700592935ed3b71f2b0408be Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Wed, 15 Mar 2017 22:58:45 +0000 Subject: [PATCH] Cleaned up unicode handling --- holoviews/core/dimension.py | 10 ++++----- holoviews/core/util.py | 15 ++++++++----- holoviews/plotting/mpl/chart.py | 5 ++--- holoviews/plotting/mpl/tabular.py | 31 ++++++-------------------- holoviews/plotting/plot.py | 20 ++++++++--------- holoviews/plotting/plotly/chart.py | 3 +-- holoviews/plotting/util.py | 5 ++--- holoviews/plotting/widgets/__init__.py | 6 ++--- 8 files changed, 39 insertions(+), 56 deletions(-) diff --git a/holoviews/core/dimension.py b/holoviews/core/dimension.py index 66c9b3f593..b0055c13e1 100644 --- a/holoviews/core/dimension.py +++ b/holoviews/core/dimension.py @@ -14,7 +14,7 @@ from ..core.util import (basestring, sanitize_identifier, group_sanitizer, label_sanitizer, max_range, find_range, dimension_sanitizer, OrderedDict, - safe_unicode, unicode, dt64_to_dt, unique_array) + bytes_to_unicode, unicode, dt64_to_dt, unique_array) from .options import Store, StoreOptions from .pprint import PrettyPrinter @@ -173,7 +173,7 @@ def pprint_label(self): "The pretty-printed label string for the Dimension" unit = ('' if self.unit is None else type(self.unit)(self.unit_format).format(unit=self.unit)) - return safe_unicode(self.label) + safe_unicode(unit) + return bytes_to_unicode(self.label) + bytes_to_unicode(unit) def pprint_value(self, value): @@ -195,7 +195,7 @@ def pprint_value(self, value): return formatter.format(value) else: return formatter % value - return value + return unicode(bytes_to_unicode(value)) def __repr__(self): @@ -208,9 +208,9 @@ def pprint_value_string(self, value): title_format variable, including the unit string (if set). Numeric types are printed to the stated rounding level. """ - unit = '' if self.unit is None else ' ' + safe_unicode(self.unit) + unit = '' if self.unit is None else ' ' + bytes_to_unicode(self.unit) value = self.pprint_value(value) - return title_format.format(name=safe_unicode(self.label), val=value, unit=unit) + return title_format.format(name=bytes_to_unicode(self.label), val=value, unit=unit) def __hash__(self): diff --git a/holoviews/core/util.py b/holoviews/core/util.py index 54de8cd17e..4e3c5eb0e7 100644 --- a/holoviews/core/util.py +++ b/holoviews/core/util.py @@ -130,10 +130,13 @@ def process_ellipses(obj, key, vdim_selection=False): return head + ((slice(None),) * padlen) + tail -def safe_unicode(value): - if sys.version_info.major == 3 or not isinstance(value, str): return value - else: return unicode(value.decode('utf-8')) - +def bytes_to_unicode(value): + """ + Safely casts bytestring to unicode + """ + if isinstance(value, bytes): + return unicode(value.decode('utf-8')) + return value def capitalize_unicode_name(s): @@ -297,7 +300,7 @@ def remove_diacritics(self_or_cls, identifier): for c in identifier: replacement = unicodedata.normalize('NFKD', c).encode('ASCII', 'ignore') if replacement != '': - chars += safe_unicode(replacement) + chars += bytes_to_unicode(replacement) else: chars += c return chars @@ -328,7 +331,7 @@ def __call__(self, name, escape=True, version=None): return self.aliases[name] elif name in self._lookup_table: return self._lookup_table[name] - name = safe_unicode(name) + name = bytes_to_unicode(name) version = self.version if version is None else version if not self.allowable(name): raise AttributeError("String %r is in the disallowed list of attribute names: %r" % self.disallowed) diff --git a/holoviews/plotting/mpl/chart.py b/holoviews/plotting/mpl/chart.py index cc8c76fd52..38190e45a4 100644 --- a/holoviews/plotting/mpl/chart.py +++ b/holoviews/plotting/mpl/chart.py @@ -16,7 +16,7 @@ import param from ...core import OrderedDict, Dimension -from ...core.util import (match_spec, unique_iterator, safe_unicode, +from ...core.util import (match_spec, unique_iterator, bytes_to_unicode, basestring, max_range, unicode) from ...element import Points, Raster, Polygons, HeatMap from ...operation import interpolate_curve @@ -1045,8 +1045,7 @@ def get_data(self, element, ranges, style): groups = groups.data.items() if element.kdims else [(element.label, element)] for key, group in groups: if element.kdims: - label = ','.join([unicode(safe_unicode(d.pprint_value(v))) - for d, v in zip(element.kdims, key)]) + label = ','.join([d.pprint_value(v) for d, v in zip(element.kdims, key)]) else: label = key data.append(group[group.vdims[0]]) diff --git a/holoviews/plotting/mpl/tabular.py b/holoviews/plotting/mpl/tabular.py index dbd21242e4..794ad1a737 100644 --- a/holoviews/plotting/mpl/tabular.py +++ b/holoviews/plotting/mpl/tabular.py @@ -6,7 +6,7 @@ import param from .element import ElementPlot -from ...core.util import safe_unicode +from ...core.util import bytes_to_unicode class TablePlot(ElementPlot): @@ -70,8 +70,9 @@ def _format_table(self): else: if summarize and row > half_rows: adjusted_row = (frame.rows - self.max_rows + row) - value = frame.pprint_cell(adjusted_row, col) - cell_text = self.pprint_value(value) + cell_text = frame.pprint_cell(adjusted_row, col) + if len(cell_text) > self.max_value_len: + cell_text = cell_text[:(self.max_value_len-3)]+'...' if len(cell_text) + 2 > cell_widths[col]: cell_widths[col] = len(cell_text) + 2 return cell_widths @@ -86,30 +87,12 @@ def _cell_value(self, element, row, col): else: if summarize and row > half_rows: row = (element.rows - self.max_rows + row) - value = element.pprint_cell(row, col) - cell_text = self.pprint_value(value) + cell_text = element.pprint_cell(row, col) + if len(cell_text) > self.max_value_len: + cell_text = cell_text[:(self.max_value_len-3)]+'...' return cell_text - def pprint_value(self, value): - """ - Generate the pretty printed representation of a value for - inclusion in a table cell. - """ - if isinstance(value, float): - formatter = '{:.%df}' % self.float_precision - formatted = formatter.format(value) - elif isinstance(value, (str, unicode)): - formatted = safe_unicode(value) - else: - formatted = str(value) - - if len(formatted) > self.max_value_len: - return formatted[:(self.max_value_len-3)]+'...' - else: - return formatted - - def initialize_plot(self, ranges=None): element = self.hmap.last axis = self.handles['axis'] diff --git a/holoviews/plotting/plot.py b/holoviews/plotting/plot.py index f6014b7da2..9b2f43337c 100644 --- a/holoviews/plotting/plot.py +++ b/holoviews/plotting/plot.py @@ -280,7 +280,7 @@ def _frame_title(self, key, group_size=2, separator='\n'): zip(dimensions, key)] groups = [', '.join(dimension_labels[i*group_size:(i+1)*group_size]) for i in range(len(dimension_labels))] - return util.safe_unicode(separator.join(g for g in groups if g)) + return util.bytes_to_unicode(separator.join(g for g in groups if g)) def _fontsize(self, key, label='fontsize', common=True): @@ -746,9 +746,9 @@ def _format_title(self, key, separator='\n'): if self.layout_dimensions: title = dim_title else: - title_format = util.safe_unicode(self.title_format) - title = title_format.format(label=util.safe_unicode(label), - group=util.safe_unicode(group), + title_format = util.bytes_to_unicode(self.title_format) + title = title_format.format(label=util.bytes_to_unicode(label), + group=util.bytes_to_unicode(group), type=type_name, dimensions=dim_title) return title.strip(' \n') @@ -1021,12 +1021,12 @@ def _format_title(self, key, separator='\n'): dim_title = self._frame_title(key, 3, separator) layout = self.layout type_name = type(self.layout).__name__ - group = util.safe_unicode(layout.group if layout.group != type_name else '') - label = util.safe_unicode(layout.label) - title = util.safe_unicode(self.title_format).format(label=label, - group=group, - type=type_name, - dimensions=dim_title) + group = util.bytes_to_unicode(layout.group if layout.group != type_name else '') + label = util.bytes_to_unicode(layout.label) + title = util.bytes_to_unicode(self.title_format).format(label=label, + group=group, + type=type_name, + dimensions=dim_title) return title.strip(' \n') diff --git a/holoviews/plotting/plotly/chart.py b/holoviews/plotting/plotly/chart.py index b6817d989d..f1c49999c5 100644 --- a/holoviews/plotting/plotly/chart.py +++ b/holoviews/plotting/plotly/chart.py @@ -210,8 +210,7 @@ def generate_plot(self, key, ranges): plots = [] for key, group in groups: if element.kdims: - label = ','.join([util.unicode(util.safe_unicode(d.pprint_value(v))) - for d, v in zip(element.kdims, key)]) + label = ','.join([d.pprint_value(v) for d, v in zip(element.kdims, key)]) else: label = key data = {axis: group.dimension_values(group.vdims[0])} diff --git a/holoviews/plotting/util.py b/holoviews/plotting/util.py index 83f7dafb33..69537dbe6f 100644 --- a/holoviews/plotting/util.py +++ b/holoviews/plotting/util.py @@ -7,7 +7,7 @@ Overlay, GridSpace, NdLayout, Store, Dataset) from ..core.spaces import get_nested_streams, Callable from ..core.util import (match_spec, is_number, wrap_tuple, basestring, - get_overlay_spec, unique_iterator, safe_unicode) + get_overlay_spec, unique_iterator) def displayable(obj): @@ -289,8 +289,7 @@ def dim_axis_label(dimensions, separator=', '): Returns an axis label for one or more dimensions. """ if not isinstance(dimensions, list): dimensions = [dimensions] - return separator.join([safe_unicode(d.pprint_label) - for d in dimensions]) + return separator.join([d.pprint_label for d in dimensions]) def attach_streams(plot, obj): diff --git a/holoviews/plotting/widgets/__init__.py b/holoviews/plotting/widgets/__init__.py index 4fd31de352..2e9801a045 100644 --- a/holoviews/plotting/widgets/__init__.py +++ b/holoviews/plotting/widgets/__init__.py @@ -7,7 +7,7 @@ from ...core import OrderedDict, NdMapping from ...core.options import Store -from ...core.util import (dimension_sanitizer, safe_unicode, +from ...core.util import (dimension_sanitizer, bytes_to_unicode, unique_array, unicode, isnumeric, wrap_tuple_streams, drop_streams) from ...core.traversal import hierarchical @@ -23,7 +23,7 @@ def escape_vals(vals, escape_numerics=True): escaped = [] for v in vals: if not isnumeric(v): - v = "'"+unicode(safe_unicode(v))+"'" + v = "'"+unicode(bytes_to_unicode(v))+"'" elif isinstance(v, np.datetime64): v = "'"+str(v)+"'" else: @@ -316,7 +316,7 @@ def get_widgets(self): if idx < self.mock_obj.ndims-1: next_vals = hierarchy[idx] - next_dim = safe_unicode(self.mock_obj.kdims[idx+1]) + next_dim = bytes_to_unicode(self.mock_obj.kdims[idx+1]) else: next_vals = {}