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 = {}