def test_clean_multichartseries_non_number_is_prompting_error(self): context = RenderContext( None, None, TableShape(3, [ Column('A', ColumnType.TEXT()), Column('B', ColumnType.DATETIME()), ]), None, None) value = [ { 'column': 'A', 'color': '#aaaaaa' }, { 'column': 'B', 'color': '#cccccc' }, ] with self.assertRaises(PromptingError) as cm: clean_value(ParamDType.Multichartseries(), value, context) self.assertEqual(cm.exception.errors, [ PromptingError.WrongColumnType(['A'], 'text', frozenset({'number' })), PromptingError.WrongColumnType(['B'], 'datetime', frozenset({'number'})), ])
def test_clean_multicolumn_prompting_error_convert_to_text(self): # TODO make this _automatic_ instead of quick-fix? # ... but for now: prompt for a Quick Fix. context = RenderContext( None, None, TableShape( 3, [ Column("A", ColumnType.NUMBER()), Column("B", ColumnType.DATETIME()), Column("C", ColumnType.TEXT()), ], ), None, None, ) with self.assertRaises(PromptingError) as cm: schema = ParamDType.Multicolumn(column_types=frozenset({"text"})) clean_value(schema, "A,B", context) self.assertEqual( cm.exception.errors, [ PromptingError.WrongColumnType(["A"], "number", frozenset({"text"})), PromptingError.WrongColumnType(["B"], "datetime", frozenset({"text"})), ], )
def test_dict_prompting_error_concatenate_different_types(self): context = RenderContext( None, None, TableShape(3, [ Column("A", ColumnType.TEXT()), Column("B", ColumnType.DATETIME()) ]), None, None, ) schema = ParamDType.Dict({ "x": ParamDType.Column(column_types=frozenset({"number"})), "y": ParamDType.Column(column_types=frozenset({"number"})), }) with self.assertRaises(PromptingError) as cm: clean_value(schema, {"x": "A", "y": "B"}, context) self.assertEqual( cm.exception.errors, [ PromptingError.WrongColumnType(["A"], "text", frozenset({"number"})), PromptingError.WrongColumnType(["B"], "datetime", frozenset({"number"})), ], )
def test_clean_multichartseries_non_number_is_prompting_error(self): context = RenderContext( None, None, TableShape(3, [ Column("A", ColumnType.TEXT()), Column("B", ColumnType.DATETIME()) ]), None, None, ) value = [ { "column": "A", "color": "#aaaaaa" }, { "column": "B", "color": "#cccccc" }, ] with self.assertRaises(PromptingError) as cm: clean_value(ParamDType.Multichartseries(), value, context) self.assertEqual( cm.exception.errors, [ PromptingError.WrongColumnType(["A"], "text", frozenset({"number"})), PromptingError.WrongColumnType(["B"], "datetime", frozenset({"number"})), ], )
def test_clean_multichartseries_non_number_is_prompting_error(self): context = self._render_context(input_table=arrow_table({ "A": ["a"], "B": pa.array([datetime.now()], pa.timestamp("ns")) })) value = [ { "column": "A", "color": "#aaaaaa" }, { "column": "B", "color": "#cccccc" }, ] with self.assertRaises(PromptingError) as cm: clean_value(ParamDType.Multichartseries(), value, context) self.assertEqual( cm.exception.errors, [ PromptingError.WrongColumnType(["A"], "text", frozenset({"number"})), PromptingError.WrongColumnType(["B"], "datetime", frozenset({"number"})), ], )
def test_as_quick_fixes(self): err = PromptingError([ PromptingError.WrongColumnType(["A"], "text", frozenset({"number"})), PromptingError.WrongColumnType(["B", "C"], "datetime", frozenset({"number"})), ]) result = err.as_quick_fixes() self.assertEqual( result, [ QuickFix( 'Convert "A" to Numbers', "prependModule", ["converttexttonumber", { "colnames": ["A"] }], ), QuickFix( 'Convert "B", "C" to Numbers', "prependModule", ["converttexttonumber", { "colnames": ["B", "C"] }], ), ], )
def test_quick_fixes(self): err = PromptingError([ PromptingError.WrongColumnType(["A"], "text", frozenset({"number"})), PromptingError.WrongColumnType(["B", "C"], "datetime", frozenset({"number"})), ]) quick_fixes_result = err.as_quick_fixes() self.assertEqual( quick_fixes_result, [ QuickFix( "Convert Text to Numbers", "prependModule", ["converttexttonumber", { "colnames": ["A"] }], ), QuickFix( "Convert Dates & Times to Numbers", "prependModule", ["converttexttonumber", { "colnames": ["B", "C"] }], ), ], ) error_result = err.as_error_str() self.assertEqual( error_result, ("The column “A” must be converted from Text to Numbers.\n\n" "The columns “B” and “C” must be converted from Dates & Times to Numbers." ), )
def test_list_prompting_error_concatenate_different_type_to_text(self): context = RenderContext( None, None, TableShape( 3, [ Column("A", ColumnType.NUMBER()), Column("B", ColumnType.DATETIME()) ], ), None, None, ) schema = ParamDType.List(inner_dtype=ParamDType.Column( column_types=frozenset({"text"}))) with self.assertRaises(PromptingError) as cm: clean_value(schema, ["A", "B"], context) self.assertEqual( cm.exception.errors, [ PromptingError.WrongColumnType(["A", "B"], None, frozenset({"text"})) ], )
def test_quick_fixes_convert_to_text(self): err = PromptingError([ PromptingError.WrongColumnType(["A", "B"], None, frozenset({"text"})) ]) result = err.as_render_errors() self.assertEqual( result, [ RenderError( I18nMessage( "py.renderer.execute.types.PromptingError.WrongColumnType.as_error_message.shouldBeText", { "columns": 2, "0": "A", "1": "B" }, None, ), [ QuickFix( I18nMessage( "py.renderer.execute.types.PromptingError.WrongColumnType.as_quick_fixes.shouldBeText", {}, None, ), QuickFixAction.PrependStep( "converttotext", {"colnames": ["A", "B"]}), ) ], ) ], )
def _(dtype: ParamDType.Multicolumn, value: List[str], input_metadata: TableMetadata) -> str: if dtype.tab_parameter: raise RuntimeError("Unsupported: fetch multicolumn with tab_parameter") error_agg = PromptErrorAggregator() requested_colnames = set(value) valid_colnames = [] # ignore colnames not in valid_columns # iterate in table order for column in input_metadata.columns: if column.name not in requested_colnames: continue if dtype.column_types and column.type.name not in dtype.column_types: if "text" in dtype.column_types: found_type = None else: found_type = column.type.name error_agg.add( PromptingError.WrongColumnType([column.name], found_type, dtype.column_types)) else: valid_colnames.append(column.name) error_agg.raise_if_nonempty() return valid_colnames
def _(dtype: ParamDType.Multicolumn, value: List[str], input_shape: TableShape) -> str: if dtype.tab_parameter: raise RuntimeError('Unsupported: fetch multicolumn with tab_parameter') if input_shape is None: return [] error_agg = PromptErrorAggregator() requested_colnames = set(value) valid_colnames = [] # ignore colnames not in valid_columns # iterate in table order for column in input_shape.columns: if column.name not in requested_colnames: continue if dtype.column_types and column.type.name not in dtype.column_types: error_agg.add( PromptingError.WrongColumnType([column.name], column.type.name, dtype.column_types)) else: valid_colnames.append(column.name) error_agg.raise_if_nonempty() return valid_colnames
def test_as_quick_fixes(self): err = PromptingError([ PromptingError.WrongColumnType(['A'], 'text', frozenset({'number'})), PromptingError.WrongColumnType(['B', 'C'], 'datetime', frozenset({'number'})), ]) result = err.as_quick_fixes() self.assertEqual(result, [ QuickFix('Convert "A" to Numbers', 'prependModule', ['converttexttonumber', { 'colnames': ['A'] }]), QuickFix('Convert "B", "C" to Numbers', 'prependModule', ['converttexttonumber', { 'colnames': ['B', 'C'] }]), ])
def test_list_prompting_error_concatenate_different_type(self): context = RenderContext( None, None, TableShape(3, [ Column('A', ColumnType.TEXT()), Column('B', ColumnType.DATETIME()), ]), None, None) schema = ParamDType.List(inner_dtype=ParamDType.Column( column_types=frozenset({'number'}))) with self.assertRaises(PromptingError) as cm: clean_value(schema, ['A', 'B'], context) self.assertEqual(cm.exception.errors, [ PromptingError.WrongColumnType(['A'], 'text', frozenset({'number' })), PromptingError.WrongColumnType(['B'], 'datetime', frozenset({'number'})), ])
def test_clean_multicolumn_prompting_error_convert_to_text(self): # TODO make this _automatic_ instead of quick-fix? # ... but for now: prompt for a Quick Fix. input_shape = TableShape(3, [ Column('A', ColumnType.NUMBER()), Column('B', ColumnType.DATETIME()), Column('C', ColumnType.TEXT()), ]) with self.assertRaises(PromptingError) as cm: schema = ParamDType.Multicolumn(column_types=frozenset({'text'})) clean_value(schema, 'A,B', input_shape) self.assertEqual(cm.exception.errors, [ PromptingError.WrongColumnType(['A'], 'number', frozenset({'text' })), PromptingError.WrongColumnType(['B'], 'datetime', frozenset({'text'})), ])
def test_clean_column_prompting_error_convert_to_number(self): context = self._render_context(input_table=arrow_table({"A": ["1"]})) with self.assertRaises(PromptingError) as cm: clean_value( ParamDType.Column(column_types=frozenset({"number"})), "A", context ) self.assertEqual( cm.exception.errors, [PromptingError.WrongColumnType(["A"], "text", frozenset({"number"}))], )
def test_list_prompting_error_concatenate_different_type(self): context = self._render_context( input_table=arrow_table({"A": ["1"], "B": [datetime.now()]}) ) schema = ParamDType.List( inner_dtype=ParamDType.Column(column_types=frozenset({"number"})) ) with self.assertRaises(PromptingError) as cm: clean_value(schema, ["A", "B"], context) self.assertEqual( cm.exception.errors, [ PromptingError.WrongColumnType(["A"], "text", frozenset({"number"})), PromptingError.WrongColumnType( ["B"], "datetime", frozenset({"number"}) ), ], )
def test_clean_column_prompting_error_convert_to_number(self): input_shape = TableShape(3, [Column('A', ColumnType.TEXT())]) with self.assertRaises(PromptingError) as cm: clean_value(ParamDType.Column(column_types=frozenset({'number'})), 'A', input_shape) self.assertEqual(cm.exception.errors, [ PromptingError.WrongColumnType(['A'], 'text', frozenset({'number' })), ])
def test_dict_prompting_error(self): input_shape = TableShape( 3, [Column("A", ColumnType.TEXT()), Column("B", ColumnType.TEXT())] ) schema = ParamDType.Dict( { "col1": ParamDType.Column(column_types=frozenset({"number"})), "col2": ParamDType.Column(column_types=frozenset({"datetime"})), } ) with self.assertRaises(PromptingError) as cm: clean_value(schema, {"col1": "A", "col2": "B"}, input_shape) self.assertEqual( cm.exception.errors, [ PromptingError.WrongColumnType(["A"], "text", frozenset({"number"})), PromptingError.WrongColumnType(["B"], "text", frozenset({"datetime"})), ], )
def test_dict_prompting_error(self): context = self._render_context( input_table=arrow_table({"A": ["a"], "B": ["b"]}) ) schema = ParamDType.Dict( { "col1": ParamDType.Column(column_types=frozenset({"number"})), "col2": ParamDType.Column(column_types=frozenset({"timestamp"})), } ) with self.assertRaises(PromptingError) as cm: clean_value(schema, {"col1": "A", "col2": "B"}, context) self.assertEqual( cm.exception.errors, [ PromptingError.WrongColumnType(["A"], "text", frozenset({"number"})), PromptingError.WrongColumnType(["B"], "text", frozenset({"timestamp"})), ], )
def test_dict_prompting_error(self): input_shape = TableShape(3, [ Column('A', ColumnType.TEXT()), Column('B', ColumnType.TEXT()), ]) schema = ParamDType.Dict({ 'col1': ParamDType.Column(column_types=frozenset({'number'})), 'col2': ParamDType.Column(column_types=frozenset({'datetime'})), }) with self.assertRaises(PromptingError) as cm: clean_value(schema, {'col1': 'A', 'col2': 'B'}, input_shape) self.assertEqual(cm.exception.errors, [ PromptingError.WrongColumnType(['A'], 'text', frozenset({'number' })), PromptingError.WrongColumnType(['B'], 'text', frozenset({'datetime'})), ])
def test_clean_column_prompting_error_convert_to_number(self): input_shape = TableMetadata(3, [Column("A", ColumnType.Text())]) with self.assertRaises(PromptingError) as cm: clean_value(ParamDType.Column(column_types=frozenset({"number"})), "A", input_shape) self.assertEqual( cm.exception.errors, [ PromptingError.WrongColumnType(["A"], "text", frozenset({"number"})) ], )
def test_clean_column_prompting_error_convert_to_number(self): context = RenderContext( None, None, TableShape(3, [Column("A", ColumnType.TEXT())]), None, None) with self.assertRaises(PromptingError) as cm: clean_value(ParamDType.Column(column_types=frozenset({"number"})), "A", context) self.assertEqual( cm.exception.errors, [ PromptingError.WrongColumnType(["A"], "text", frozenset({"number"})) ], )
def test_clean_multicolumn_prompting_error_convert_to_text(self): # TODO make this _automatic_ instead of quick-fix? # ... but for now: prompt for a Quick Fix. context = self._render_context( input_table=arrow_table({"A": [1], "B": [datetime.now()], "C": ["x"]}) ) with self.assertRaises(PromptingError) as cm: schema = ParamDType.Multicolumn(column_types=frozenset({"text"})) clean_value(schema, ["A", "B"], context) self.assertEqual( cm.exception.errors, [PromptingError.WrongColumnType(["A", "B"], None, frozenset({"text"}))], )
def test_dict_prompting_error_concatenate_different_types(self): context = self._render_context(input_table=arrow_table({ "A": ["1"], "B": pa.array([datetime.now()], pa.timestamp("ns")) })) schema = ParamDType.Dict({ "x": ParamDType.Column(column_types=frozenset({"number"})), "y": ParamDType.Column(column_types=frozenset({"number"})), }) with self.assertRaises(PromptingError) as cm: clean_value(schema, {"x": "A", "y": "B"}, context) self.assertEqual( cm.exception.errors, [ PromptingError.WrongColumnType(["A"], "text", frozenset({"number"})), PromptingError.WrongColumnType(["B"], "datetime", frozenset({"number"})), ], )
def test_list_prompting_error_concatenate_different_type_to_text(self): context = self._render_context( input_table=arrow_table( {"A": [1], "B": pa.array([datetime.now()], pa.timestamp("ns"))} ) ) schema = ParamDType.List( inner_dtype=ParamDType.Column(column_types=frozenset({"text"})) ) with self.assertRaises(PromptingError) as cm: clean_value(schema, ["A", "B"], context) self.assertEqual( cm.exception.errors, [PromptingError.WrongColumnType(["A", "B"], None, frozenset({"text"}))], )
def test_clean_column_prompting_error_convert_to_text(self): # TODO make this _automatic_ instead of quick-fix? # Consider Regex. We probably want to pass the module a text Series # _separately_ from the input DataFrame. That way Regex can output # a new Text column but preserve its input column's data type. # # ... but for now: prompt for a Quick Fix. input_shape = TableMetadata(3, [Column("A", ColumnType.Number())]) with self.assertRaises(PromptingError) as cm: clean_value(ParamDType.Column(column_types=frozenset({"text"})), "A", input_shape) self.assertEqual( cm.exception.errors, [PromptingError.WrongColumnType(["A"], None, frozenset({"text"}))], )
def _(dtype: ParamDType.Column, value: str, input_shape: TableShape) -> str: if dtype.tab_parameter: raise RuntimeError("Unsupported: fetch column with tab_parameter") if input_shape is None: return "" valid_columns = {c.name: c for c in input_shape.columns} if value not in valid_columns: return "" # Null column column = valid_columns[value] if dtype.column_types and column.type.name not in dtype.column_types: raise PromptingError([ PromptingError.WrongColumnType([value], column.type.name, dtype.column_types) ]) return value
def test_clean_column_prompting_error_convert_to_text(self): # TODO make this _automatic_ instead of quick-fix? # Consider Regex. We probably want to pass the module a text Series # _separately_ from the input DataFrame. That way Regex can output # a new Text column but preserve its input column's data type. # # ... but for now: prompt for a Quick Fix. context = RenderContext( None, None, TableShape(3, [ Column('A', ColumnType.NUMBER()), ]), None, None) with self.assertRaises(PromptingError) as cm: clean_value(ParamDType.Column(column_types=frozenset({'text'})), 'A', context) self.assertEqual(cm.exception.errors, [ PromptingError.WrongColumnType(['A'], 'number', frozenset({'text' })), ])
def test_clean_condition_not_with_subclause_error(self): context = self._render_context(input_table=arrow_table({"A": [1]})) with self.assertRaises(PromptingError) as cm: clean_value( ParamDType.Condition(), { "operation": "text_is", "column": "A", "value": "", "isCaseSensitive": False, "isRegex": False, }, context, ) self.assertEqual( cm.exception.errors, [PromptingError.WrongColumnType(["A"], None, frozenset({"text"}))], )
def test_clean_condition_number_wrong_column_type(self): context = self._render_context(input_table=arrow_table({"A": ["a"]})) with self.assertRaises(PromptingError) as cm: clean_value( ParamDType.Condition(), { "operation": "number_is", "column": "A", "value": "1", "isCaseSensitive": False, "isRegex": False, }, context, ) self.assertEqual( cm.exception.errors, [PromptingError.WrongColumnType(["A"], "text", frozenset({"number"}))], )