Skip to content

Commit a3c1b9e

Browse files
authored
Merge pull request #1259 from mito-ds/preconfig-conditional-format
Preconfig conditional format
2 parents 957c0d8 + a487a74 commit a3c1b9e

16 files changed

+475
-28
lines changed

mitosheet/mitosheet/code_chunks/postprocessing/set_dataframe_format_code_chunk.py

+1
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ def get_conditional_format_code_list(state: State, sheet_index: int) -> Tuple[Op
180180
"""Returns all the code to set the conditional formats"""
181181
df_name = state.df_names[sheet_index]
182182
df = state.dfs[sheet_index]
183+
183184
conditional_formats = state.df_formats[sheet_index]['conditional_formats']
184185

185186
# We get the conditional formatting results, and we filter out any columns that are

mitosheet/mitosheet/mito_backend.py

+7-3
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
from mitosheet.steps_manager import StepsManager
3030
from mitosheet.telemetry.telemetry_utils import (log, log_event_processed,
3131
telemetry_turned_on)
32-
from mitosheet.types import CodeOptions, MitoTheme, ParamMetadata
32+
from mitosheet.types import CodeOptions, ColumnDefinintion, ColumnDefinitions, ConditionalFormat, MitoTheme, ParamMetadata
3333
from mitosheet.updates.replay_analysis import REPLAY_ANALYSIS_UPDATE
3434
from mitosheet.user.create import try_create_user_json_file
3535
from mitosheet.user.db import USER_JSON_PATH, get_user_field
@@ -57,6 +57,7 @@ def __init__(
5757
user_defined_importers: Optional[List[Callable]]=None,
5858
user_defined_editors: Optional[List[Callable]]=None,
5959
code_options: Optional[CodeOptions]=None,
60+
column_definitions: Optional[List[ColumnDefinitions]]=None,
6061
theme: Optional[MitoTheme]=None,
6162
):
6263
"""
@@ -92,7 +93,7 @@ def __init__(
9293

9394
if not os.path.exists(import_folder):
9495
raise ValueError(f"Import folder {import_folder} does not exist. Please change the file path or create the folder.")
95-
96+
9697
# Set up the state container to hold private widget state
9798
self.steps_manager = StepsManager(
9899
args,
@@ -104,6 +105,7 @@ def __init__(
104105
user_defined_importers=all_custom_importers,
105106
user_defined_editors=user_defined_editors,
106107
code_options=code_options,
108+
column_definitions=column_definitions,
107109
theme=theme
108110
)
109111

@@ -314,6 +316,7 @@ def get_mito_backend(
314316
user_defined_functions: Optional[List[Callable]]=None,
315317
user_defined_importers: Optional[List[Callable]]=None,
316318
user_defined_editors: Optional[List[Callable]]=None,
319+
column_definitions: Optional[List[ColumnDefinitions]]=None,
317320
) -> MitoBackend:
318321

319322
# We pass in the dataframes directly to the widget
@@ -322,7 +325,8 @@ def get_mito_backend(
322325
analysis_to_replay=analysis_to_replay,
323326
user_defined_functions=user_defined_functions,
324327
user_defined_importers=user_defined_importers,
325-
user_defined_editors=user_defined_editors
328+
user_defined_editors=user_defined_editors,
329+
column_definitions=column_definitions
326330
)
327331

328332
return mito_backend

mitosheet/mitosheet/pro/conditional_formatting_utils.py

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ def get_conditonal_formatting_result(
5252
# are sent to the frontend
5353
json_index = json.dumps(index, cls=NpEncoder)
5454
formatted_result[column_id][json_index] = {'backgroundColor': backgroundColor, 'color': color}
55+
5556
except Exception as e:
5657
if format_uuid not in invalid_conditional_formats:
5758
invalid_conditional_formats[format_uuid] = []

mitosheet/mitosheet/step_performers/filter.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
FC_NUMBER_HIGHEST,
4242
]
4343

44+
4445
class FilterStepPerformer(StepPerformer):
4546
"""
4647
Allows you to filter a column based on some conditions and some values.
@@ -260,5 +261,5 @@ def check_filters_contain_condition_that_needs_full_df(filters: List[Union[Filte
260261
filter_group: FilterGroup = filter_or_group #type: ignore
261262
if check_filters_contain_condition_that_needs_full_df(filter_group["filters"]):
262263
return True
263-
264+
264265
return False

mitosheet/mitosheet/steps_manager.py

+11-7
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,10 @@
3535
SnowflakeImportStepPerformer
3636
from mitosheet.transpiler.transpile import transpile
3737
from mitosheet.transpiler.transpile_utils import get_default_code_options
38-
from mitosheet.types import CodeOptions, MitoTheme, ParamMetadata
38+
from mitosheet.types import CodeOptions, ColumnDefinintion, ColumnDefinitions, MitoTheme, ParamMetadata
3939
from mitosheet.updates import UPDATES
4040
from mitosheet.user.utils import is_enterprise, is_running_test
41-
from mitosheet.utils import NpEncoder, dfs_to_array_for_json, get_new_id, is_default_df_names
41+
from mitosheet.utils import NpEncoder, dfs_to_array_for_json, get_default_df_formats, get_new_id, is_default_df_names
4242
from mitosheet.step_performers.utils.user_defined_function_utils import get_user_defined_importers_for_frontend, get_user_defined_editors_for_frontend
4343
from mitosheet.step_performers.utils.user_defined_function_utils import validate_and_wrap_sheet_functions, validate_user_defined_editors
4444

@@ -187,6 +187,7 @@ def __init__(
187187
user_defined_importers: Optional[List[Callable]]=None,
188188
user_defined_editors: Optional[List[Callable]]=None,
189189
code_options: Optional[CodeOptions]=None,
190+
column_definitions: Optional[List[ColumnDefinitions]]=None,
190191
theme: Optional[MitoTheme]=None,
191192
):
192193
"""
@@ -221,11 +222,11 @@ def __init__(
221222
# saving any data that we need to transpilate it later this
222223
self.preprocess_execution_data = {}
223224
df_names = None
224-
for preprocess_step_performers in PREPROCESS_STEP_PERFORMERS:
225-
args, df_names, execution_data = preprocess_step_performers.execute(args)
225+
for preprocess_step_performer in PREPROCESS_STEP_PERFORMERS:
226+
args, df_names, execution_data = preprocess_step_performer.execute(args)
226227
self.preprocess_execution_data[
227-
preprocess_step_performers.preprocess_step_type()
228-
] = execution_data
228+
preprocess_step_performer.preprocess_step_type()
229+
] = execution_data
229230

230231
# We set the original_args_raw_strings. If we later have an args update, then these
231232
# are overwritten by the args update (and are actually correct). But since we don't
@@ -255,6 +256,8 @@ def __init__(
255256
# The version of the public interface used by this analysis
256257
self.public_interface_version = 3
257258

259+
df_formats = get_default_df_formats(column_definitions, list(args))
260+
258261
# Then we initialize the analysis with just a simple initialize step
259262
self.steps_including_skipped: List[Step] = [
260263
Step(
@@ -265,7 +268,8 @@ def __init__(
265268
df_names=df_names,
266269
user_defined_functions=self.user_defined_functions,
267270
user_defined_importers=self.user_defined_importers,
268-
user_defined_editors=self.user_defined_editors
271+
user_defined_editors=self.user_defined_editors,
272+
df_formats=df_formats
269273
),
270274
{}
271275
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import pandas as pd
2+
import streamlit as st
3+
from mitosheet.streamlit.v1 import spreadsheet
4+
5+
st.set_page_config(layout="wide")
6+
st.title('Tesla Stock Volume Analysis')
7+
8+
df = pd.DataFrame({
9+
'A': [1, 2, 3, 4, 5, 6, 7, 8, 9],
10+
'B': [1, 2, 3, 4, 5, 6, 7, 8, 9]
11+
})
12+
new_dfs, code = spreadsheet(
13+
df,
14+
column_definitions=[
15+
[
16+
{
17+
'columns': ['A', 'B'],
18+
'conditional_formats': [{
19+
'filters': [{'condition': 'greater_than_or_equal', 'value': 5}],
20+
'font_color': '#c30010',
21+
'background_color': '#ffcbd1'
22+
}]
23+
},
24+
{
25+
'columns': ['A'],
26+
'conditional_formats': [{
27+
'filters': [{'condition': 'less', 'value': 2}],
28+
'font_color': '#f30010',
29+
'background_color': '#ddcbd1'
30+
}]
31+
}
32+
],
33+
]
34+
)
35+
36+
st.write(new_dfs)
37+
st.code(code)

mitosheet/mitosheet/streamlit/v1/apps/simple.py mitosheet/mitosheet/streamlit/v1/apps/simple_dataframe_app.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
'a': [1, 2, 3],
1010
'b': [4, 5, 6]
1111
})
12-
new_dfs, code = spreadsheet(df, height='1000px')
12+
new_dfs, code = spreadsheet(df)
1313

1414
st.write(new_dfs)
1515
st.code(code)

mitosheet/mitosheet/streamlit/v1/spreadsheet.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
from mitosheet.mito_backend import MitoBackend
1515
from mitosheet.selection_utils import get_selected_element
16-
from mitosheet.types import CodeOptions, ParamMetadata, ParamType
16+
from mitosheet.types import CodeOptions, ColumnDefinitions, ConditionalFormat, ParamMetadata, ParamType
1717
from mitosheet.utils import get_new_id
1818

1919
CURRENT_MITO_ANALYSIS_VERSION = 1
@@ -269,6 +269,7 @@ def _get_mito_backend(
269269
_editors: Optional[List[Callable]]=None,
270270
_sheet_functions: Optional[List[Callable]]=None,
271271
_code_options: Optional[CodeOptions]=None,
272+
_column_definitions: Optional[List[ColumnDefinitions]]=None,
272273
import_folder: Optional[str]=None,
273274
df_names: Optional[List[str]]=None,
274275
session_id: Optional[str]=None,
@@ -280,6 +281,7 @@ def _get_mito_backend(
280281
import_folder=import_folder,
281282
user_defined_importers=_importers, user_defined_functions=_sheet_functions, user_defined_editors=_editors,
282283
code_options=_code_options,
284+
column_definitions = _column_definitions,
283285
)
284286

285287
# Make a send function that stores the responses in a list
@@ -320,6 +322,7 @@ def spreadsheet( # type: ignore
320322
df_names: Optional[List[str]]=None,
321323
import_folder: Optional[str]=None,
322324
code_options: Optional[CodeOptions]=None,
325+
column_definitions: Optional[List[ColumnDefinitions]]=None,
323326
return_type: str='default',
324327
height: Optional[str]=None,
325328
key=None
@@ -366,6 +369,7 @@ def spreadsheet( # type: ignore
366369
_importers=importers,
367370
_editors=editors,
368371
_code_options=code_options,
372+
_column_definitions=column_definitions,
369373
import_folder=import_folder,
370374
session_id=session_id,
371375
df_names=df_names,

mitosheet/mitosheet/tests/api/test_get_code_snippets.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import json
2+
3+
from pytest_httpserver import HTTPServer
24
from mitosheet.enterprise.mito_config import MITO_CONFIG_CODE_SNIPPETS_URL, MITO_CONFIG_CODE_SNIPPETS_VERSION, MITO_CONFIG_VERSION
35
from mitosheet.tests.test_mito_config import delete_all_mito_config_environment_variables
46
from mitosheet.tests.test_utils import create_mito_wrapper
57
from mitosheet.api.get_code_snippets import get_code_snippets, DEFAULT_CODE_SNIPPETS
68
import os
7-
from pytest_httpserver import HTTPServer
89

910

1011
TEST_CODE_SNIPPETS = [

mitosheet/mitosheet/tests/streamlit/test_runnable_analysis.py

+9-9
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ def function(file_name_import_csv_0, file_name_import_excel_0, file_name_export_
8585
}
8686
]
8787

88-
analysis = RunnableAnalysis('', None, fully_parameterized_function, param_metadata)
88+
analysis = RunnableAnalysis('', None, fully_parameterized_function, param_metadata)
8989
result = analysis.run()
9090
assert result is not None
9191
pd.testing.assert_frame_equal(result[0], expected_df)
@@ -154,7 +154,7 @@ def function(file_name_import_csv_0, file_name_import_excel_0, file_name_export_
154154

155155
new_export_file_0 = str(tmp_path / 'new_export.csv')
156156
new_export_file_1 = str(tmp_path / 'new_export.xlsx')
157-
analysis = RunnableAnalysis('', None, fully_parameterized_function, param_metadata)
157+
analysis = RunnableAnalysis('', None, fully_parameterized_function, param_metadata)
158158

159159
# Test that get_param_metadata works
160160
assert analysis.get_param_metadata() == param_metadata
@@ -192,7 +192,7 @@ def function_ctqm(import_dataframe_0):
192192
}
193193
]
194194

195-
analysis = RunnableAnalysis('', None, fully_parameterized_function, param_metadata)
195+
analysis = RunnableAnalysis('', None, fully_parameterized_function, param_metadata)
196196

197197
assert analysis.get_param_metadata() == param_metadata
198198
assert analysis.get_param_metadata('import') == param_metadata
@@ -273,7 +273,7 @@ def function(import_dataframe_0, file_name_import_csv_0, file_name_import_excel_
273273

274274
new_export_file_0 = str(tmp_path / 'new_export.csv')
275275
new_export_file_1 = str(tmp_path / 'new_export.xlsx')
276-
analysis = RunnableAnalysis('', None, fully_parameterized_function, param_metadata)
276+
analysis = RunnableAnalysis('', None, fully_parameterized_function, param_metadata)
277277

278278
# Test that get_param_metadata works
279279
assert analysis.get_param_metadata() == param_metadata
@@ -383,7 +383,7 @@ def function(import_dataframe_0):
383383
},
384384
]
385385

386-
analysis = RunnableAnalysis('', None, fully_parameterized_function, param_metadata)
386+
analysis = RunnableAnalysis('', None, fully_parameterized_function, param_metadata)
387387
with pytest.raises(TypeError):
388388
analysis.run()
389389

@@ -406,14 +406,14 @@ def function(import_dataframe_0):
406406
}
407407
]
408408

409-
analysis = RunnableAnalysis('', None, fully_parameterized_function, param_metadata)
409+
analysis = RunnableAnalysis('', None, fully_parameterized_function, param_metadata)
410410
with pytest.raises(TypeError):
411411
analysis.run(testing=1)
412412

413413

414414
@requires_streamlit
415415
def test_to_and_from_json():
416-
analysis = RunnableAnalysis('', None, simple_fn, simple_param_metadata)
416+
analysis = RunnableAnalysis('', None, simple_fn, simple_param_metadata)
417417
# Test that the to_json function
418418
json = analysis.to_json()
419419
assert json is not None
@@ -445,7 +445,7 @@ def function(vari\abl"e_name{}):
445445
'name': 'vari\ abl"e_name{}'
446446
},
447447
]
448-
analysis = RunnableAnalysis('', None, special_characters_fn, special_characters_metadata)
448+
analysis = RunnableAnalysis('', None, special_characters_fn, special_characters_metadata)
449449
# Test that the to_json function
450450
json = analysis.to_json()
451451
assert json is not None
@@ -467,7 +467,7 @@ def function():
467467
468468
return df1
469469
"""
470-
analysis = RunnableAnalysis('', None, fully_parameterized_code, [])
470+
analysis = RunnableAnalysis('', None, fully_parameterized_code, [])
471471
result = analysis.run()
472472
pd.testing.assert_frame_equal(result, pd.DataFrame({'A': [1, 2, 3], 'B': [2, 3, 4]}))
473473

mitosheet/mitosheet/tests/streamlit/test_streamlit.py

+30-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
'return type of analysis',
6363
[df1], {'return_type': 'analysis'},
6464
(
65-
RunnableAnalysis('', None, '', [])
65+
RunnableAnalysis('', None, '', [], 0)
6666
)
6767
)
6868
]
@@ -109,3 +109,32 @@ def test_return_type_function_invalid_code_options():
109109
spreadsheet(df1, code_options={'as_function': False, 'call_function': False, 'function_name': 'test', 'function_params': {}}, return_type='function')
110110
with pytest.raises(ValueError):
111111
spreadsheet(df1, code_options={'as_function': True, 'call_function': True, 'function_name': 'test', 'function_params': {}}, return_type='function')
112+
113+
@requires_streamlit
114+
def test_spreadsheet_with_column_definitions():
115+
f = spreadsheet(
116+
df1,
117+
column_definitions=[
118+
[
119+
{
120+
'columns': ['A'],
121+
'conditional_formats': [{
122+
'filters': [{'condition': 'greater_than_or_equal', 'value': 5}],
123+
'font_color': '#c30010',
124+
'background_color': '#ffcbd1'
125+
}]
126+
},
127+
{
128+
'columns': ['A'],
129+
'conditional_formats': [{
130+
'filters': [{'condition': 'less', 'value': 2}],
131+
'font_color': '#f30010',
132+
'background_color': '#ddcbd1'
133+
}]
134+
}
135+
]
136+
],
137+
code_options={'as_function': True, 'call_function': False, 'function_name': 'test', 'function_params': {}},
138+
return_type='function'
139+
)
140+
assert callable(f)

0 commit comments

Comments
 (0)