Skip to content

Commit

Permalink
Replace numeric cell type by float and int cell types
Browse files Browse the repository at this point in the history
  • Loading branch information
martinRenou committed May 20, 2019
1 parent 7b51e50 commit 641831e
Show file tree
Hide file tree
Showing 8 changed files with 56 additions and 49 deletions.
13 changes: 10 additions & 3 deletions examples/format.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,21 @@
"outputs": [],
"source": [
"sheet = ipysheet.sheet()\n",
"cell0 = ipysheet.cell(0, 0, 0, numeric_format='0.0', type='numeric')\n",
"cell0 = ipysheet.cell(0, 0, 0, numeric_format='.2', type='float')\n",
"cell1 = ipysheet.cell(1, 0, \"Hello\", type='text')\n",
"cell2 = ipysheet.cell(0, 1, 0.1, numeric_format='0.000', type='numeric')\n",
"cell3 = ipysheet.cell(1, 1, 15.9, numeric_format='0.00', type='numeric')\n",
"cell2 = ipysheet.cell(0, 1, 10000000000, numeric_format='e', type='int')\n",
"cell3 = ipysheet.cell(1, 1, 5.91234314, numeric_format='.4', type='float')\n",
"cell4 = ipysheet.cell(2, 2, \"02/14/2019\", date_format='MM/DD/YYYY', type='date')\n",
"\n",
"sheet"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
Expand Down
27 changes: 15 additions & 12 deletions ipysheet/easy.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
"""
__all__ = ['sheet', 'current', 'cell', 'calculation', 'row', 'column', 'cell_range', 'hold_cells', 'renderer']

import numbers
import six
from contextlib import contextmanager

Expand All @@ -23,15 +22,15 @@

_common_doc = {
'args': """
type (string): Type of cell, options are: text, numeric, checkbox, dropdown, numeric, date, widget.
type (string): Type of cell, options are: text, int, float, checkbox, dropdown, date, widget.
If type is None, the type is inferred from the type of the value being passed,
numeric (float or int type), boolean (bool type), widget (any widget object), or else text.
float, int, boolean (bool type), widget (any widget object), or else text.
When choice is given the type will be assumed to be dropdown.
The types refer (currently) to the handsontable types: https://handsontable.com/docs/6.2.2/demo-custom-renderers.html
color (string): The text color in the cell
background_color (string): The background color in the cell
read_only (bool): Whether the cell is editable or not
numeric_format (string): Numbers format
numeric_format (ipywidgets.widgets.trait_types.NumberFormat): Numbers format, default is 'd' for int cells, '.2f' for float cells
date_format (string): Dates format
time_format (string): Time format
renderer (string): Renderer name to use for the cell
Expand Down Expand Up @@ -95,7 +94,7 @@ def current():
@doc_subst(_common_doc)
def cell(row, column, value=0., type=None, color=None, background_color=None,
font_style=None, font_weight=None, style=None, label_left=None, choice=None,
read_only=False, numeric_format='0.000', date_format='YYYY/MM/DD', renderer=None, **kwargs):
read_only=False, numeric_format=None, date_format='YYYY/MM/DD', renderer=None, **kwargs):
"""Adds a new ``Cell`` widget to the current ``Sheet``
Args:
Expand All @@ -111,7 +110,8 @@ def cell(row, column, value=0., type=None, color=None, background_color=None,
>>> from ipysheet import sheet, cell
>>>
>>> s1 = sheet()
>>> cell(0, 0, 36.) # The Cell type will be 'numeric'
>>> cell(0, 0, 36) # The Cell type will be 'int'
>>> cell(0, 0, 36.3) # The Cell type will be 'float'
>>> cell(1, 0, True) # The Cell type will be 'checkbox'
>>> cell(0, 1, 'Hello World!') # The Cell type will be 'text'
>>> c = cell(1, 1, True)
Expand All @@ -121,8 +121,10 @@ def cell(row, column, value=0., type=None, color=None, background_color=None,
if type is None:
if isinstance(value, bool):
type = 'checkbox'
elif isinstance(value, numbers.Number):
type = 'numeric'
elif isinstance(value, int):
type = 'int'
elif isinstance(value, float):
type = 'float'
elif isinstance(value, widgets.Widget):
type = 'widget'
else:
Expand Down Expand Up @@ -157,7 +159,7 @@ def cell(row, column, value=0., type=None, color=None, background_color=None,
@doc_subst(_common_doc)
def row(row, value, column_start=0, column_end=None, type=None, color=None, background_color=None,
font_style=None, font_weight=None, style=None, choice=None,
read_only=False, numeric_format='0.000', date_format='YYYY/MM/DD', renderer=None, **kwargs):
read_only=False, numeric_format=None, date_format='YYYY/MM/DD', renderer=None, **kwargs):
"""Create a ``Cell`` widget, representing multiple cells in a sheet, in a horizontal row
Args:
Expand Down Expand Up @@ -187,7 +189,7 @@ def row(row, value, column_start=0, column_end=None, type=None, color=None, back
@doc_subst(_common_doc)
def column(column, value, row_start=0, row_end=None, type=None, color=None, background_color=None,
font_style=None, font_weight=None, style=None, choice=None,
read_only=False, numeric_format='0.000', date_format='YYYY/MM/DD', renderer=None, **kwargs):
read_only=False, numeric_format=None, date_format='YYYY/MM/DD', renderer=None, **kwargs):
"""Create a ``Cell`` widget, representing multiple cells in a sheet, in a vertical column
Args:
Expand Down Expand Up @@ -219,7 +221,7 @@ def cell_range(value,
row_start=0, column_start=0, row_end=None, column_end=None, transpose=False,
squeeze_row=False, squeeze_column=False, type=None, color=None, background_color=None,
font_style=None, font_weight=None, style=None, choice=None,
read_only=False, numeric_format='0.000', date_format='YYYY/MM/DD', renderer=None, **kwargs):
read_only=False, numeric_format=None, date_format='YYYY/MM/DD', renderer=None, **kwargs):
"""Create a ``Cell`` widget, representing multiple cells in a sheet
Args:
Expand Down Expand Up @@ -278,7 +280,8 @@ def cell_range(value,
# see if we an infer a type from the data, otherwise leave it None
if type is None:
type_check_map = [('checkbox', lambda x: isinstance(x, bool)),
('numeric', lambda x: isinstance(x, numbers.Number)),
('int', lambda x: isinstance(x, int)),
('float', lambda x: isinstance(x, float) or isinstance(x, int)),
('text', lambda x: isinstance(x, six.string_types)),
('widget', lambda x: isinstance(x, widgets.Widget)),
]
Expand Down
3 changes: 1 addition & 2 deletions ipysheet/numpy_loader.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from .easy import sheet, column, cell_range
from .utils import extract_data, get_cell_type, get_cell_numeric_format
from .utils import extract_data, get_cell_type


def from_array(array):
Expand Down Expand Up @@ -27,7 +27,6 @@ def from_array(array):
columns = 1 if len(array.shape) == 1 else array.shape[1]

kwargs = {
'numeric_format': get_cell_numeric_format(array.dtype),
'type': get_cell_type(array.dtype)
}

Expand Down
3 changes: 1 addition & 2 deletions ipysheet/pandas_loader.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from .sheet import Cell, Sheet
from .utils import extract_data, get_cell_numeric_format, get_cell_type
from .utils import extract_data, get_cell_type


def _format_date(date):
Expand Down Expand Up @@ -56,7 +56,6 @@ def from_dataframe(dataframe):
column_start=idx,
column_end=idx,
type=get_cell_type(arr.dtype),
numeric_format=get_cell_numeric_format(arr.dtype),
squeeze_row=False,
squeeze_column=True
))
Expand Down
3 changes: 2 additions & 1 deletion ipysheet/sheet.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import ipywidgets as widgets
from ipywidgets.widgets.widget_layout import LayoutTraitType
from ipywidgets.widgets.trait_types import NumberFormat

import traitlets
from traitlets import Unicode, CInt, List, Tuple, Instance, Union, Dict, Bool, Any
Expand Down Expand Up @@ -33,7 +34,7 @@ class Cell(widgets.Widget):
squeeze_column = Bool(True).tag(sync=True)
transpose = Bool(False).tag(sync=True)
choice = List(Unicode(), allow_none=True, default_value=None).tag(sync=True)
numeric_format = Unicode('0.000', allow_none=True).tag(sync=True)
numeric_format = NumberFormat(None, allow_none=True).tag(sync=True)
date_format = Unicode('YYYY/MM/DD', allow_none=True).tag(sync=True)
time_format = Unicode('h:mm:ss a', allow_none=True).tag(sync=True)

Expand Down
22 changes: 11 additions & 11 deletions ipysheet/test_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,10 +276,10 @@ def test_cell_values():

cell = ipysheet.cell(0, 0, value=1.2)
assert cell.value == 1.2
assert cell.type == 'numeric'
assert cell.type == 'float'
cell = ipysheet.cell(0, 0, value=1)
assert cell.value == 1
assert cell.type == 'numeric'
assert cell.type == 'int'

cell = ipysheet.Cell(value='1.2')
assert cell.value == '1.2'
Expand All @@ -291,18 +291,18 @@ def test_cell_values():

cell = ipysheet.row(0, [0, 1.2])
assert cell.value == [0, 1.2]
assert cell.type == 'numeric'
assert cell.type == 'float'

cell = ipysheet.row(0, [0, 1])
assert cell.value == [0, 1]
assert cell.type == 'numeric'
assert cell.type == 'int'

cell = ipysheet.row(0, ['a', 'b'])
assert cell.value == ['a', 'b']
assert cell.type == 'text'

cell = ipysheet.row(0, [True, 0])
assert cell.type == 'numeric'
assert cell.type == 'int'

cell = ipysheet.row(0, [True, 'bla'])
assert cell.type is None
Expand Down Expand Up @@ -442,21 +442,21 @@ def test_from_dataframe():
sheet = ipysheet.from_dataframe(df)
assert len(sheet.cells) == 7
assert sheet.cells[0].value == [1., 1., 1., 1.]
assert sheet.cells[0].type == 'numeric'
assert sheet.cells[0].type == 'float'
assert sheet.cells[1].value == [None, '2013/01/02', None, '2013/01/02']
assert sheet.cells[1].type == 'date'
assert sheet.cells[2].value == [1., 1., 1., 1.]
assert sheet.cells[2].type == 'numeric'
assert sheet.cells[2].numeric_format == '0.000'
assert sheet.cells[2].type == 'float'
assert sheet.cells[2].numeric_format is None
assert sheet.cells[3].value == [False, True, False, False]
assert sheet.cells[3].type == 'checkbox'
assert sheet.cells[4].value == ['test', 'train', 'test', 'train']
assert sheet.cells[4].type == 'text'
assert sheet.cells[5].value == ['foo', 'foo', 'foo', 'foo']
assert sheet.cells[5].type == 'text'
assert sheet.cells[6].value == [0, 3, 9, 18]
assert sheet.cells[6].type == 'numeric'
assert sheet.cells[6].numeric_format == '0[.]0'
assert sheet.cells[6].type == 'int'
assert sheet.cells[6].numeric_format is None


def test_from_to_dataframe():
Expand Down Expand Up @@ -503,7 +503,7 @@ def test_from_array():
arr = np.random.randn(6, 10)
sheet = ipysheet.from_array(arr)
assert len(sheet.cells) == 1
assert sheet.cells[0].type == 'numeric'
assert sheet.cells[0].type == 'float'
assert sheet.cells[0].value is arr
assert sheet.rows == 6
assert sheet.columns == 10
Expand Down
16 changes: 4 additions & 12 deletions ipysheet/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,24 +50,16 @@ def extract_data(sheet):


def get_cell_type(dt):
# TODO Differentiate integer and float? Using custom renderers and
# validators for integers?
# Add support for void type from NumPy?
# See https://handsontable.com/docs/6.2.2/tutorial-cell-types.html
return {
'b': 'checkbox',
'i': 'numeric',
'u': 'numeric',
'f': 'numeric',
'm': 'numeric',
'i': 'int',
'u': 'int',
'f': 'float',
'm': 'float',
'M': 'date',
'S': 'text',
'U': 'text'
}.get(dt.kind, 'text')


def get_cell_numeric_format(dt):
return {
'i': '0[.]0',
'f': '0.000',
}.get(dt.kind)
18 changes: 12 additions & 6 deletions js/src/sheet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ let CellRangeModel = widgets.WidgetModel.extend({
squeeze_row: true,
squeeze_column: true,
transpose: false,
numeric_format: '0.000',
numeric_format: null,
date_format: 'YYYY/MM/DD',
time_format: 'h:mm:ss a'
});
Expand Down Expand Up @@ -275,9 +275,9 @@ let put_values2d = function(grid, values) {


// Register `int` and `float` cell types
class NumberEditor extends Handsontable.editors.TextEditor {
class IntEditor extends Handsontable.editors.TextEditor {
getValue() {
return Number.parseFloat(this.TEXTAREA.value);
return parseInt(this.TEXTAREA.value);
}
};

Expand All @@ -291,23 +291,29 @@ function int_validator(query, callback) {
}

(Handsontable.cellTypes as any).registerCellType('int', {
editor: NumberEditor,
editor: IntEditor,
renderer: int_renderer,
validator: int_validator,
allowInvalid: false
});

class FloatEditor extends Handsontable.editors.TextEditor {
getValue() {
return parseFloat(this.TEXTAREA.value);
}
};

function float_renderer(hotInstance, td, row, column, prop, value, cellProperties) {
const numeric_format = cellProperties.numericFormat || '.2f';
td.innerHTML = d3.format(numeric_format)(value);
}

function float_validator(query, callback) {
callback(Number.isInteger(query));
callback(typeof query == 'number');
}

(Handsontable.cellTypes as any).registerCellType('float', {
editor: NumberEditor,
editor: FloatEditor,
renderer: float_renderer,
validator: float_validator,
allowInvalid: false
Expand Down

0 comments on commit 641831e

Please sign in to comment.