mitosheet 0.2.53__py2.py3-none-any.whl → 0.2.55__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. mitosheet/dataframe_display_formatters.py +33 -66
  2. mitosheet/formatter/__init__.py +10 -0
  3. mitosheet/formatter/viewer.py +148 -0
  4. mitosheet/labextension/package.json +23 -7
  5. mitosheet/labextension/static/339.967abbd46339aee7868c.js +1 -0
  6. mitosheet/labextension/static/418.0ec6f919714352f77210.js +1 -0
  7. mitosheet/labextension/static/remoteEntry.b3dffe9fd1efc1d162d4.js +1 -0
  8. mitosheet/saved_analyses/save_utils.py +1 -1
  9. mitosheet/tests/test_formatter.py +240 -0
  10. {mitosheet-0.2.53.data → mitosheet-0.2.55.data}/data/share/jupyter/labextensions/mitosheet/package.json +23 -7
  11. mitosheet-0.2.55.data/data/share/jupyter/labextensions/mitosheet/static/339.967abbd46339aee7868c.js +1 -0
  12. mitosheet-0.2.55.data/data/share/jupyter/labextensions/mitosheet/static/418.0ec6f919714352f77210.js +1 -0
  13. mitosheet-0.2.55.data/data/share/jupyter/labextensions/mitosheet/static/remoteEntry.b3dffe9fd1efc1d162d4.js +1 -0
  14. {mitosheet-0.2.53.dist-info → mitosheet-0.2.55.dist-info}/METADATA +5 -2
  15. {mitosheet-0.2.53.dist-info → mitosheet-0.2.55.dist-info}/RECORD +22 -17
  16. mitosheet/labextension/static/339.5f826c48e1170f2309de.js +0 -1
  17. mitosheet/labextension/static/remoteEntry.905183b0f55e620383e3.js +0 -1
  18. mitosheet-0.2.53.data/data/share/jupyter/labextensions/mitosheet/static/339.5f826c48e1170f2309de.js +0 -1
  19. mitosheet-0.2.53.data/data/share/jupyter/labextensions/mitosheet/static/remoteEntry.905183b0f55e620383e3.js +0 -1
  20. {mitosheet-0.2.53.data → mitosheet-0.2.55.data}/data/share/jupyter/labextensions/mitosheet/static/405.4dea6fd8e64e4dc9015a.js +0 -0
  21. {mitosheet-0.2.53.data → mitosheet-0.2.55.data}/data/share/jupyter/labextensions/mitosheet/static/509.9cd86a57778b85719494.js +0 -0
  22. {mitosheet-0.2.53.data → mitosheet-0.2.55.data}/data/share/jupyter/labextensions/mitosheet/static/style.js +0 -0
  23. {mitosheet-0.2.53.data → mitosheet-0.2.55.data}/data/share/jupyter/labextensions/mitosheet/static/third-party-licenses.json +0 -0
  24. {mitosheet-0.2.53.dist-info → mitosheet-0.2.55.dist-info}/LICENSE.txt +0 -0
  25. {mitosheet-0.2.53.dist-info → mitosheet-0.2.55.dist-info}/WHEEL +0 -0
  26. {mitosheet-0.2.53.dist-info → mitosheet-0.2.55.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,240 @@
1
+ #!/usr/bin/env python
2
+ # coding: utf-8
3
+ # Copyright (c) Saga Inc.
4
+ # Distributed under the terms of the GNU Affero General Public License v3.0 License.
5
+
6
+ """
7
+ Tests for the formatter module, specifically the format_dataframe_mimetype function.
8
+ """
9
+
10
+ import json
11
+
12
+ import pandas as pd
13
+
14
+ from mitosheet.formatter.viewer import format_dataframe_mimetype
15
+
16
+
17
+ def test_format_dataframe_mimetype_basic():
18
+ """Test basic DataFrame formatting."""
19
+ df = pd.DataFrame({"A": [1, 2, 3], "B": ["foo", "bar", "baz"]})
20
+
21
+ result = format_dataframe_mimetype(df)
22
+
23
+ assert result is not None
24
+ assert "columns" in result
25
+ assert "data" in result
26
+ assert "totalRows" in result
27
+ assert "indexLevels" in result
28
+ assert "columnLevels" in result
29
+
30
+ assert result["totalRows"] == 3
31
+ assert result["indexLevels"] == 1
32
+ assert result["columnLevels"] == 1
33
+
34
+ # Check column metadata
35
+ columns = result["columns"]
36
+ assert len(columns) == 3 # index + 2 data columns
37
+ assert columns[0]["name"] == ["index"]
38
+ assert columns[1]["name"] == ["A"]
39
+ assert columns[2]["name"] == ["B"]
40
+
41
+ # Check data
42
+ data = json.loads(result["data"])
43
+ assert len(data) == 3
44
+ assert data[0] == [0, 1, "foo"]
45
+ assert data[1] == [1, 2, "bar"]
46
+ assert data[2] == [2, 3, "baz"]
47
+
48
+
49
+ def test_format_dataframe_mimetype_with_named_index():
50
+ """Test DataFrame with named index."""
51
+ df = pd.DataFrame({"A": [1, 2, 3], "B": ["foo", "bar", "baz"]})
52
+ df.index.name = "my_index"
53
+
54
+ result = format_dataframe_mimetype(df)
55
+
56
+ assert result is not None
57
+ assert result["columns"][0]["name"] == ["my_index"]
58
+
59
+
60
+ def test_format_dataframe_mimetype_with_datetime_index():
61
+ """Test DataFrame with datetime index."""
62
+ dates = pd.date_range("2023-01-01", periods=3, freq="D")
63
+ df = pd.DataFrame({"A": [1, 2, 3], "B": ["foo", "bar", "baz"]}, index=dates)
64
+
65
+ result = format_dataframe_mimetype(df)
66
+
67
+ assert result is not None
68
+ data = json.loads(result["data"])
69
+ assert len(data) == 3
70
+ # Check that datetime is formatted correctly
71
+ assert data[0][0] == "2023-01-01T00:00:00.000"
72
+ assert data[1][0] == "2023-01-02T00:00:00.000"
73
+ assert data[2][0] == "2023-01-03T00:00:00.000"
74
+
75
+
76
+ def test_format_dataframe_mimetype_with_multiindex():
77
+ """Test DataFrame with MultiIndex."""
78
+ index = pd.MultiIndex.from_tuples(
79
+ [("A", 1), ("A", 2), ("B", 1)], names=["letter", "number"]
80
+ )
81
+
82
+ df = pd.DataFrame({"X": [10, 20, 30], "Y": [40, 50, 60]}, index=index)
83
+
84
+ result = format_dataframe_mimetype(df)
85
+
86
+ assert result is not None
87
+ assert result["indexLevels"] == 2
88
+
89
+ # Check column metadata includes both index levels
90
+ columns = result["columns"]
91
+ assert len(columns) == 4 # 2 index levels + 2 data columns
92
+ assert columns[0]["name"] == ["letter"]
93
+ assert columns[1]["name"] == ["number"]
94
+ assert columns[2]["name"] == ["X"]
95
+ assert columns[3]["name"] == ["Y"]
96
+
97
+ # Check data
98
+ data = json.loads(result["data"])
99
+ assert len(data) == 3
100
+ assert data[0] == ["A", 1, 10, 40]
101
+ assert data[1] == ["A", 2, 20, 50]
102
+ assert data[2] == ["B", 1, 30, 60]
103
+
104
+
105
+ def test_format_dataframe_mimetype_with_nan_values():
106
+ """Test DataFrame with NaN values."""
107
+ df = pd.DataFrame(
108
+ {"A": [1, None, 3], "B": ["foo", None, "baz"], "C": [1.5, float("nan"), 3.5]}
109
+ )
110
+
111
+ result = format_dataframe_mimetype(df)
112
+
113
+ assert result is not None
114
+ data = json.loads(result["data"])
115
+ assert len(data) == 3
116
+ # NaN values should be converted to empty strings
117
+ assert data[0] == [0, 1.0, "foo", 1.5]
118
+ assert data[1] == [1, None, None, None]
119
+ assert data[2] == [2, 3.0, "baz", 3.5]
120
+
121
+
122
+ def test_format_dataframe_mimetype_truncation():
123
+ """Test DataFrame truncation when exceeding display.max_rows."""
124
+ # Create a DataFrame with more rows than the default display.max_rows
125
+ df = pd.DataFrame({"A": range(100), "B": [f"val_{i}" for i in range(100)]})
126
+
127
+ # Temporarily set display.max_rows to a small value
128
+ original_max_rows = pd.get_option("display.max_rows")
129
+ pd.set_option("display.max_rows", 10)
130
+
131
+ try:
132
+ result = format_dataframe_mimetype(df)
133
+
134
+ assert result is not None
135
+ assert result["totalRows"] == 100
136
+ assert len(json.loads(result["data"])) < result["totalRows"]
137
+
138
+ finally:
139
+ # Restore original setting
140
+ pd.set_option("display.max_rows", original_max_rows)
141
+
142
+
143
+ def test_format_dataframe_mimetype_describe_output():
144
+ """Test that describe() output returns None."""
145
+ df = pd.DataFrame({"A": [1, 2, 3, 4, 5], "B": [10, 20, 30, 40, 50]})
146
+ describe_df = df.describe()
147
+
148
+ result = format_dataframe_mimetype(describe_df)
149
+
150
+ # Should return None for describe() output
151
+ assert result is None
152
+
153
+
154
+ def test_format_dataframe_mimetype_empty_dataframe():
155
+ """Test empty DataFrame."""
156
+ df = pd.DataFrame()
157
+
158
+ result = format_dataframe_mimetype(df)
159
+
160
+ assert result is not None
161
+ assert result["totalRows"] == 0
162
+ assert len(json.loads(result["data"])) == 0
163
+
164
+
165
+ def test_format_dataframe_mimetype_single_column():
166
+ """Test DataFrame with single column."""
167
+ df = pd.DataFrame({"A": [1, 2, 3]})
168
+
169
+ result = format_dataframe_mimetype(df)
170
+
171
+ assert result is not None
172
+ columns = result["columns"]
173
+ assert len(columns) == 2 # index + 1 data column
174
+ assert columns[0]["name"] == ["index"]
175
+ assert columns[1]["name"] == ["A"]
176
+
177
+ data = json.loads(result["data"])
178
+ assert len(data) == 3
179
+ assert data[0] == [0, 1]
180
+ assert data[1] == [1, 2]
181
+ assert data[2] == [2, 3]
182
+
183
+
184
+ def test_format_dataframe_mimetype_with_different_dtypes():
185
+ """Test DataFrame with different column dtypes."""
186
+ df = pd.DataFrame(
187
+ {
188
+ "int_col": [1, 2, 3],
189
+ "float_col": [1.1, 2.2, 3.3],
190
+ "str_col": ["a", "b", "c"],
191
+ "bool_col": [True, False, True],
192
+ "datetime_col": pd.date_range("2023-01-01", periods=3),
193
+ }
194
+ )
195
+
196
+ result = format_dataframe_mimetype(df)
197
+
198
+ assert result is not None
199
+ columns = result["columns"]
200
+
201
+ # Check that dtypes are preserved in metadata
202
+ dtype_names = [col["dtype"] for col in columns]
203
+ assert "int64" in dtype_names or "int32" in dtype_names
204
+ assert "float64" in dtype_names or "float32" in dtype_names
205
+ assert "object" in dtype_names # strings
206
+ assert "bool" in dtype_names
207
+ assert any("datetime64" in dtype for dtype in dtype_names)
208
+
209
+
210
+ def test_format_dataframe_mimetype_with_multiindex_columns():
211
+ """Test DataFrame with MultiIndex columns."""
212
+ # Create a DataFrame with MultiIndex columns
213
+ columns = pd.MultiIndex.from_tuples(
214
+ [("A", "one"), ("A", "two"), ("B", "one"), ("B", "two")],
215
+ names=["level_0", "level_1"],
216
+ )
217
+ df = pd.DataFrame([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]], columns=columns)
218
+
219
+ result = format_dataframe_mimetype(df)
220
+
221
+ assert result is not None
222
+ assert result["columnLevels"] == 2
223
+
224
+ # Check column metadata
225
+ columns_result = result["columns"]
226
+ assert len(columns_result) == 5 # index + 4 data columns
227
+
228
+ # Check that column names are lists representing the multi-index structure
229
+ assert columns_result[0]["name"] == ["index"] # index column
230
+ assert columns_result[1]["name"] == ["A", "one"] # first multi-index column
231
+ assert columns_result[2]["name"] == ["A", "two"]
232
+ assert columns_result[3]["name"] == ["B", "one"]
233
+ assert columns_result[4]["name"] == ["B", "two"]
234
+
235
+ # Check data
236
+ data = json.loads(result["data"])
237
+ assert len(data) == 3
238
+ assert data[0] == [0, 1, 2, 3, 4]
239
+ assert data[1] == [1, 5, 6, 7, 8]
240
+ assert data[2] == [2, 9, 10, 11, 12]
@@ -9,9 +9,11 @@
9
9
  "jupyterlab": {
10
10
  "outputDir": "mitosheet/labextension",
11
11
  "extension": "lib/plugin",
12
+ "mimeExtension": "lib/viewer/renderer",
12
13
  "_build": {
13
- "load": "static/remoteEntry.905183b0f55e620383e3.js",
14
- "extension": "./extension"
14
+ "load": "static/remoteEntry.b3dffe9fd1efc1d162d4.js",
15
+ "extension": "./extension",
16
+ "mimeExtension": "./mimeExtension"
15
17
  }
16
18
  },
17
19
  "name": "mitosheet",
@@ -21,16 +23,18 @@
21
23
  "email": "aaron@sagacollab.com"
22
24
  },
23
25
  "bugs": {
24
- "url": "https://github.com/mito-ds/monorepo/issues"
26
+ "url": "https://github.com/mito-ds/mito/issues"
25
27
  },
26
28
  "repository": {
27
- "url": "https://github.com/mito-ds/monorepo",
29
+ "url": "https://github.com/mito-ds/mito",
28
30
  "type": "git"
29
31
  },
30
- "version": "0.2.53",
32
+ "version": "0.2.55",
31
33
  "dependencies": {
32
34
  "@jupyterlab/application": "^4.0.0",
33
35
  "@jupyterlab/notebook": "^4.2.4",
36
+ "@jupyterlab/rendermime-interfaces": "^3.0.0",
37
+ "@jupyterlab/ui-components": "^4.0.0",
34
38
  "@types/fscreen": "^1.0.1",
35
39
  "@types/react-dom": "^18.3.0",
36
40
  "fscreen": "^1.1.0",
@@ -70,7 +74,10 @@
70
74
  "lint": "eslint src/ --ext .ts,.tsx --fix",
71
75
  "prepack": "jlpm run build:all",
72
76
  "build:docs:update_frontend": "python docs/make_function_docs.py update_frontend",
73
- "build:docs:generate_markdown": "python docs/make_function_docs.py generate_markdown"
77
+ "build:docs:generate_markdown": "python docs/make_function_docs.py generate_markdown",
78
+ "test": "jest",
79
+ "test:watch": "jest --watch",
80
+ "test:coverage": "jest --coverage"
74
81
  },
75
82
  "keywords": [
76
83
  "jupyter",
@@ -82,7 +89,12 @@
82
89
  ],
83
90
  "devDependencies": {
84
91
  "@jupyterlab/builder": "^4.0.0",
92
+ "@testing-library/dom": "^10.4.1",
93
+ "@testing-library/jest-dom": "^6.9.1",
94
+ "@testing-library/react": "^16.3.0",
95
+ "@testing-library/user-event": "^14.6.1",
85
96
  "@types/expect.js": "^0.3.29",
97
+ "@types/jest": "^30.0.0",
86
98
  "@types/node": "^18.19.43",
87
99
  "@types/react": "^18.3.3",
88
100
  "@typescript-eslint/eslint-plugin": "^4.8.1",
@@ -96,15 +108,19 @@
96
108
  "expect.js": "^0.3.1",
97
109
  "file-loader": "^6.2.0",
98
110
  "fs-extra": "^10.0.0",
111
+ "identity-obj-proxy": "^3.0.0",
112
+ "jest": "^30.2.0",
113
+ "jest-environment-jsdom": "^30.2.0",
99
114
  "mkdirp": "^1.0.4",
100
115
  "mocha": "^9.1.2",
101
116
  "npm-run-all": "^4.1.5",
102
117
  "prettier": "^2.1.1",
103
118
  "rimraf": "^3.0.2",
119
+ "ts-jest": "^29.4.6",
104
120
  "typescript": "^5.5.4"
105
121
  },
106
122
  "main": "lib/index.js",
107
- "homepage": "https://trymito.io",
123
+ "homepage": "https://github.com/mito-ds/mito",
108
124
  "types": "./lib/index.d.ts",
109
125
  "description": "The Mito Spreadsheet",
110
126
  "resolutions": {