Skip to content

Commit

Permalink
1.8.12
Browse files Browse the repository at this point in the history
* #196: dataframes that have datatime indexes without a name
* jest test refactoring
* fix for CicleCI JS memory issues
* Added the ability to apply formats to all columns of same dtype
  • Loading branch information
aschonfeld committed May 15, 2020
1 parent 642e807 commit d277dc7
Show file tree
Hide file tree
Showing 95 changed files with 2,919 additions and 4,141 deletions.
4 changes: 2 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ javascript: &javascript
name: Run JS Tests & Coverage
command: |
export TZ=America/New_York
yarn run test-with-coverage --maxWorkers=50%
yarn run test-with-coverage -w 1
bash <(curl -s https://codecov.io/bash) -c -F javascript -f ./JS_coverage/lcov.info
yarn run report-duplicate-code
cp -r ./JS_coverage /tmp/circleci-test-results
Expand All @@ -66,7 +66,7 @@ python: &python
CIRCLE_ARTIFACTS: /tmp/circleci-artifacts
CIRCLE_TEST_REPORTS: /tmp/circleci-test-results
CODECOV_TOKEN: b0d35139-0a75-427a-907b-2c78a762f8f0
VERSION: 1.8.11
VERSION: 1.8.12
PANDOC_RELEASES_URL: https://github.com/jgm/pandoc/releases
steps:
- attach_workspace:
Expand Down
6 changes: 5 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
## Changelog

### 1.8.12 (2020-5-15)
* [#196](https://github.com/man-group/dtale/issues/196): dataframes that have datatime indexes without a name
* Added the ability to apply formats to all columns of same dtype

### 1.8.11 (2020-5-3)
* [#191](https://github.com/man-group/dtale/issues/191): improving outlier filter suggestions
* [#196](https://github.com/man-group/dtale/issues/191): improving outlier filter suggestions
* [#190](https://github.com/man-group/dtale/issues/190): hide "Animate" inputs when "Percentage Sum" or "Percentage Count" aggregations are used
* [#189](https://github.com/man-group/dtale/issues/189): hide "Barsort" when grouping is being applied
* [#187](https://github.com/man-group/dtale/issues/187): missing & outlier tooltip descriptions on column headers
Expand Down
2 changes: 1 addition & 1 deletion docker/dtale.env
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
VERSION=1.8.11
VERSION=1.8.12
TZ=America/New_York
4 changes: 2 additions & 2 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@
# built documents.
#
# The short X.Y version.
version = u'1.8.11'
version = u'1.8.12'
# The full version, including alpha/beta/rc tags.
release = u'1.8.11'
release = u'1.8.12'

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
Expand Down
2 changes: 1 addition & 1 deletion dtale/charts/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ def build_base_chart(raw_data, x, y, group_col=None, group_val=None, agg=None, a
msg = (
'Group ({}) contains more than {} unique values, more groups than that will make the chart unreadable. '
'You can choose specific groups to display from then "Group(s)" dropdown above. The available group(s) '
'are listed below:'
'are listed below:\n\n{}'
).format(', '.join(group_col), MAX_GROUPS, group_vals.to_string(index=False))
raise ChartBuildingError(msg, group_vals.to_string(index=False))

Expand Down
8 changes: 4 additions & 4 deletions dtale/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ def format_dict(self, lst):
return {name: f(lst[idx], nan_display=self.nan_display) for idx, name, f in self.fmts}

def format_dicts(self, lsts):
return [self.format_dict(l) for l in lsts]
return list(map(self.format_dict, lsts))

def format_lists(self, df):
return {
Expand Down Expand Up @@ -633,13 +633,13 @@ def flatten_lists(lists):
return [item for sublist in lists for item in sublist]


def divide_chunks(l, n):
def divide_chunks(lst, n):
"""
Break list input 'l' up into smaller lists of size 'n'
"""
# looping till length l
for i in range(0, len(l), n):
yield l[i:i + n]
for i in range(0, len(lst), n):
yield lst[i:i + n]


def build_query(data_id, query=None):
Expand Down
47 changes: 44 additions & 3 deletions dtale/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,13 @@ def format_data(data):
data = data.to_frame(index=False)

index = [str(i) for i in make_list(data.index.name or data.index.names) if i is not None]
data = data.reset_index().drop('index', axis=1, errors='ignore')
drop = True
if not len(index) and not data.index.equals(pd.RangeIndex(0, len(data))):
drop = False
index = ['index']
data = data.reset_index()
if drop:
data = data.drop('index', axis=1, errors='ignore')
data.columns = [str(c) for c in data.columns]
return data, index

Expand Down Expand Up @@ -726,6 +732,41 @@ def update_settings(data_id):
return jsonify_error(e)


@dtale.route('/update-formats/<data_id>')
def update_formats(data_id):
"""
:class:`flask:flask.Flask` route which updates the "formats" property for global SETTINGS associated w/ the
current port
:param data_id: integer string identifier for a D-Tale process's data
:type data_id: str
:param all: boolean flag which, if true, tells us we should apply this formatting to all columns with the same
data type as our selected column
:param col: selected column
:param format: JSON string for the formatting configuration we want applied to either the selected column of all
columns with the selected column's data type
:return: JSON
"""
try:
update_all_dtype = get_bool_arg(request, 'all')
col = get_str_arg(request, 'col')
col_format = get_json_arg(request, 'format')
curr_settings = global_state.get_settings(data_id) or {}
updated_formats = {col: col_format}
if update_all_dtype:
dtypes = global_state.get_dtypes(data_id)
col_dtype = next((c['dtype'] for c in dtypes if c['name'] == col), None)
updated_formats = {
c['name']: col_format for c in global_state.get_dtypes(data_id) if c['dtype'] == col_dtype
}
updated_formats = dict_merge(curr_settings.get('formats') or {}, updated_formats)
updated_settings = dict_merge(curr_settings, dict(formats=updated_formats))
global_state.set_settings(data_id, updated_settings)
return jsonify(dict(success=True))
except BaseException as e:
return jsonify_error(e)


def refresh_col_indexes(data_id):
"""
Helper function to sync column indexes to current state of dataframe for data_id.
Expand Down Expand Up @@ -1401,7 +1442,7 @@ def handle_top(df, top):
code.append((
"chart['ordinal'] = ordinal_data\n"
"chart = chart.sort_values('ordinal')"
).format(col=selected_col, ordinal=ordinal_col, agg=ordinal_agg))
))
hist.index.name = 'labels'
hist = hist.reset_index()
hist, top = handle_top(hist, get_int_arg(request, 'top'))
Expand Down Expand Up @@ -1429,7 +1470,7 @@ def handle_top(df, top):
elif data_type == 'histogram':
hist_data, hist_labels = np.histogram(data, bins=bins)
hist_data = [json_float(h) for h in hist_data]
hist_labels = ['{0:.1f}'.format(l) for l in hist_labels]
hist_labels = ['{0:.1f}'.format(lbl) for lbl in hist_labels]
code.append("chart = np.histogram(df[~pd.isnull(df['{col}'])][['{col}']], bins={bins})".format(
col=selected_col, bins=bins))
desc, desc_code = load_describe(data[selected_col])
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dtale",
"version": "1.8.11",
"version": "1.8.12",
"description": "Visualizer for Pandas Data Structures",
"main": "main.js",
"directories": {
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def run_tests(self):

setup(
name="dtale",
version="1.8.11",
version="1.8.12",
author="MAN Alpha Technology",
author_email="ManAlphaTech@man.com",
description="Web Client for Visualizing Pandas Objects",
Expand Down
31 changes: 12 additions & 19 deletions static/__tests__/CopyToClipboard-test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import { mount } from "enzyme";
import _ from "lodash";
import React from "react";

import * as t from "./jest-assertions";
import { expect, it } from "@jest/globals";

import { buildInnerHTML, withGlobalJquery } from "./test-utils";

describe("CopyToClipboard tests", () => {
test("CopyToClipboard no queryCommandSupported test", done => {
const render = () => {
const { CopyToClipboard } = withGlobalJquery(() => require("../CopyToClipboard"));
buildInnerHTML();

const buttonBuilder = props => (
<div id="clicker" {...props}>
Hello
Expand All @@ -19,28 +19,21 @@ describe("CopyToClipboard tests", () => {
attachTo: document.getElementById("content"),
});
result.render();
t.equal(result.html(), null, "shouldn't render anything");
done();
return result;
};

it("CopyToClipboard no queryCommandSupported test", () => {
const result = render();
expect(result.html()).toBeNull();
});

test("CopyToClipboard queryCommandSupported test", done => {
const { CopyToClipboard } = withGlobalJquery(() => require("../CopyToClipboard"));
buildInnerHTML();
it("CopyToClipboard queryCommandSupported test", () => {
Object.defineProperty(global.document, "queryCommandSupported", {
value: () => true,
});
Object.defineProperty(global.document, "execCommand", { value: _.noop });
const buttonBuilder = props => (
<div id="clicker" {...props}>
Hello
</div>
);
const result = mount(<CopyToClipboard text="test code" buttonBuilder={buttonBuilder} />, {
attachTo: document.getElementById("content"),
});
result.render();
t.ok(result.find("#clicker").length, 1, "should display button");
const result = render();
expect(result.find("#clicker").length).toBe(1);
result.find("#clicker").simulate("click");
done();
});
});
11 changes: 5 additions & 6 deletions static/__tests__/JSAnchor-test.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { mount } from "enzyme";
import React from "react";

import { expect, it } from "@jest/globals";

import { JSAnchor } from "../JSAnchor";
import * as t from "./jest-assertions";

describe("JSAnchor tests", () => {
test("JSAnchor click test", done => {
it("JSAnchor click test", () => {
const clicks = [];
const result = mount(
<JSAnchor onClick={() => clicks.push(1)}>
Expand All @@ -14,18 +15,16 @@ describe("JSAnchor tests", () => {
);
result.render();
result.find("a").simulate("click");
t.ok(clicks.length == 1, "should activate click function");
done();
expect(clicks.length).toBe(1);
});

test("JSAnchor no-click test", done => {
it("JSAnchor no-click test", () => {
const result = mount(
<JSAnchor>
<span>Hello</span>
</JSAnchor>
);
result.render();
result.find("a").simulate("click");
done();
});
});
8 changes: 4 additions & 4 deletions static/__tests__/RemovableError-test.jsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { mount } from "enzyme";
import React from "react";

import { expect, it } from "@jest/globals";

import { RemovableError } from "../RemovableError";
import * as t from "./jest-assertions";

describe("RemovableError tests", () => {
test("RemovableError Remove null onRemove", done => {
it("RemovableError Remove null onRemove", () => {
const result = mount(<RemovableError message="foo" onRemove={null} />);
result.render();
t.notOk(result.hasClass("fa-times-circle"), "the icon should not exist");
done();
expect(result.hasClass("fa-times-circle")).toBe(false);
});
});
19 changes: 7 additions & 12 deletions static/__tests__/actions/dtale-test.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as t from "../jest-assertions";
import { expect, it } from "@jest/globals";

describe("dtale tests", () => {
const { location } = window;
Expand All @@ -14,18 +14,13 @@ describe("dtale tests", () => {
window.location = location;
});

test("dtale: testing getParams", done => {
it("dtale: testing getParams", () => {
const actions = require("../../actions/dtale").default;
const urlParams = actions.getParams();
t.deepEqual(
{
col: "foo",
vals: ["a", "b", "c"],
baz: JSON.stringify({ bizz: [1, 2] }),
},
urlParams,
"should parse parameters"
);
done();
expect({
col: "foo",
vals: ["a", "b", "c"],
baz: JSON.stringify({ bizz: [1, 2] }),
}).toEqual(urlParams);
});
});
32 changes: 13 additions & 19 deletions static/__tests__/actions/url-utils-test.jsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { expect, it } from "@jest/globals";

import { buildURLParams } from "../../actions/url-utils";
import * as t from "../jest-assertions";

describe("url-utils tests", () => {
test("url-utils: testing URL_KEYS", done => {
it("url-utils: testing URL_KEYS", () => {
let params = {
filters: {},
ids: [0, 5],
Expand All @@ -11,16 +12,12 @@ describe("url-utils tests", () => {
selectedCols: ["col1", "col2"],
};
let urlParams = buildURLParams(params);
t.deepEqual(
urlParams,
{
cols: '["col1","col2"]',
query: "col == 3",
sort: '[["col1","ASC"]]',
ids: "[0,5]",
},
"should serialize parameters"
);
expect(urlParams).toEqual({
cols: '["col1","col2"]',
query: "col == 3",
sort: '[["col1","ASC"]]',
ids: "[0,5]",
});

params = {
filters: {
Expand All @@ -31,14 +28,11 @@ describe("url-utils tests", () => {
},
};
urlParams = buildURLParams(params);
t.deepEqual(
urlParams,
{ filters: '{"col1":{"value":"blah","type":"StringFilter"}}' },
"should serialize filters parameters"
);
expect(urlParams).toEqual({
filters: '{"col1":{"value":"blah","type":"StringFilter"}}',
});

urlParams = buildURLParams({}, null, ["ids"]);
t.deepEqual(urlParams, {}, "should return empty object when missing required field");
done();
expect(urlParams).toEqual({});
});
});
Loading

0 comments on commit d277dc7

Please sign in to comment.