Changing Widgets to work better with GUI2 (#9017)

- Rename `Column.replace` to `Column.text_replace` (consistency with Table and allow for adding `Column.replace`).
- Changed Regex insert to be `.to_regex` rather than `Regex.compile`.
https://github.com/enso-org/enso/assets/4699705/3694e876-5b46-49f9-8e8c-352fa0684777

- Adjusted `Table.rename_columns` to insert a `Pair.new` for each rename.
![image](https://github.com/enso-org/enso/assets/4699705/8240f302-498c-46d6-9b77-b1a0f5bb585e)

- Added a `<Regular Expression>` option to the `rename_columns`.
https://github.com/enso-org/enso/assets/4699705/d3c695ad-93f2-419d-b1c1-1f607ca825bd

- Added constant values to `Table.fill_nothing` and made it value type dependent on `Column.fill_nothing`.
https://github.com/enso-org/enso/assets/4699705/26e2e975-e972-46f0-ae1a-6b09dcd39fe6
![image](https://github.com/enso-org/enso/assets/4699705/51393d09-c06b-4eb1-9471-1856430fbfdc)
![image](https://github.com/enso-org/enso/assets/4699705/064fa42b-6187-4816-b3f0-0b7f0f00f6a9)

- Removed `use_regex` option from `Sort_Column.By_Name` (in favour of Regex type).

- Improved widgets for `order_by`. Drop down now on the column name and allow using the Index method with specified numeric range.
![image](https://github.com/enso-org/enso/assets/4699705/549b9c4c-5753-4518-801c-ecd06db5c2e7)
This commit is contained in:
James Dunkerley 2024-02-12 15:12:19 +00:00 committed by GitHub
parent ecc434e788
commit f257952680
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 124 additions and 125 deletions

View File

@ -10,10 +10,10 @@ import project.Data.Text.Text
import project.Data.Vector.No_Wrap
import project.Data.Vector.Vector
import project.Error.Error
import project.Errors.Empty_Error.Empty_Error
import project.Errors.Common.Incomparable_Values
import project.Errors.Common.Index_Out_Of_Bounds
import project.Errors.Common.Not_Found
import project.Errors.Empty_Error.Empty_Error
import project.Errors.Problem_Behavior.Problem_Behavior
import project.Errors.Unimplemented.Unimplemented
import project.Internal.Array_Like_Helpers

View File

@ -6,9 +6,9 @@ import project.Data.Pair.Pair
import project.Data.Text.Text
import project.Data.Vector.Vector
import project.Error.Error
import project.Errors.Empty_Error.Empty_Error
import project.Errors.Common.Index_Out_Of_Bounds
import project.Errors.Common.Not_Found
import project.Errors.Empty_Error.Empty_Error
import project.Function.Function
import project.Meta
import project.Nothing.Nothing

View File

@ -6,8 +6,8 @@ import project.Data.Pair.Pair
import project.Data.Text.Text
import project.Data.Vector.Vector
import project.Error.Error
import project.Errors.Empty_Error.Empty_Error
import project.Errors.Common.Index_Out_Of_Bounds
import project.Errors.Empty_Error.Empty_Error
import project.Errors.Illegal_Argument.Illegal_Argument
import project.Errors.Illegal_State.Illegal_State
import project.Function.Function

View File

@ -8,8 +8,8 @@ import project.Data.Ordering.Ordering
import project.Data.Vector.No_Wrap
import project.Data.Vector.Vector
import project.Error.Error
import project.Errors.Empty_Error.Empty_Error
import project.Errors.Common.Incomparable_Values
import project.Errors.Empty_Error.Empty_Error
import project.Errors.Illegal_Argument.Illegal_Argument
import project.Meta
import project.Nothing.Nothing

View File

@ -10,8 +10,8 @@ import project.Data.Time.Date_Period.Date_Period
import project.Data.Time.Period.Period
import project.Data.Vector.Vector
import project.Error.Error
import project.Errors.Empty_Error.Empty_Error
import project.Errors.Common.Index_Out_Of_Bounds
import project.Errors.Empty_Error.Empty_Error
import project.Errors.Illegal_Argument.Illegal_Argument
import project.Function.Function
import project.Nothing.Nothing

View File

@ -9,12 +9,12 @@ import project.Data.Range.Range
import project.Data.Sort_Direction.Sort_Direction
import project.Data.Text.Text
import project.Error.Error
import project.Errors.Empty_Error.Empty_Error
import project.Errors.Common.Incomparable_Values
import project.Errors.Common.Index_Out_Of_Bounds
import project.Errors.Common.No_Such_Method
import project.Errors.Common.Not_Found
import project.Errors.Common.Type_Error
import project.Errors.Empty_Error.Empty_Error
import project.Errors.Illegal_Argument.Illegal_Argument
import project.Errors.Problem_Behavior.Problem_Behavior
import project.Errors.Wrapped_Error.Wrapped_Error

View File

@ -11,7 +11,7 @@ from project.Metadata import make_single_choice
Creates a Regex / Text Widget for search and replace.
make_regex_text_widget : Widget
make_regex_text_widget =
make_single_choice [["Text", '""'], ["Regular Expression", '(Regex.compile "^$")']]
make_single_choice [["Text", '""'], ["Regular Expression", '"^$".to_regex']]
## PRIVATE
Creates a Single_Choice Widget for delimiters.

View File

@ -1107,7 +1107,7 @@ type Column
import Standard.Examples
example_fill_nothing = Examples.decimal_column.fill_nothing 20.5
@default (Widget_Helpers.make_fill_default_value_selector include_custom_text=False)
@default (self-> Widget_Helpers.make_fill_default_value_selector add_number=(self.value_type.is_numeric || self.value_type==Value_Type.Mixed) add_boolean=(self.value_type.is_boolean || self.value_type==Value_Type.Mixed) add_text=(self.value_type.is_text || self.value_type==Value_Type.Mixed))
fill_nothing : Column | Previous_Value | Any -> Column
fill_nothing self default =
if Previous_Value == default then Error.throw (Unsupported_Database_Operation.Error "The Previous_Value argument is currently not supported in the database backend.") else
@ -1136,7 +1136,7 @@ type Column
import Standard.Examples
example_fill_empty = Examples.text_column_1.fill_empty "hello"
@default (Widget_Helpers.make_fill_default_value_selector include_custom_text=True)
@default (Widget_Helpers.make_fill_default_value_selector add_text=True)
fill_empty : Column | Previous_Value | Any -> Column
fill_empty self default =
if Previous_Value == default then Error.throw (Unsupported_Database_Operation.Error "The Previous_Value argument is currently not supported in the database backend.") else
@ -1423,20 +1423,20 @@ type Column
> Example
Replace dashes with underscores.
column.replace "-" "_"
column.text_replace "-" "_"
> Example
Remove leading and trailing spaces from cells.
column.replace "^\s*(.*?)\s*$".to_regex "$1"
column.text_replace "^\s*(.*?)\s*$".to_regex "$1"
> Example
Replace texts in quotes with parentheses.
column.replace '"(.*?)"'.to_regex '($1)'
column.text_replace '"(.*?)"'.to_regex '($1)'
@term make_regex_text_widget
replace : Text | Regex | Column -> Text | Column -> Case_Sensitivity -> Boolean -> Column ! Unsupported_Database_Operation
replace self term="" new_text="" case_sensitivity=Case_Sensitivity.Default only_first=False =
text_replace : Text | Regex | Column -> Text | Column -> Case_Sensitivity -> Boolean -> Column ! Unsupported_Database_Operation
text_replace self term="" new_text="" case_sensitivity=Case_Sensitivity.Default only_first=False =
Value_Type.expect_text self <| case_sensitivity.disallow_non_default_locale <|
input_type = Meta.type_of term
params = Replace_Params.Value input_type case_sensitivity only_first

View File

@ -1082,7 +1082,7 @@ type Table
> Example
Sort the table by columns whose names start with letter `a`.
table.order_by [(Sort_Column.Select_By_Name "a.*" use_regex=True case_sensitivity=Case_Sensitivity.Insensitive)]
table.order_by [(Sort_Column.Select_By_Name "a.*".to_regex case_sensitivity=Case_Sensitivity.Insensitive)]
@columns Widget_Helpers.make_order_by_selector
order_by : Vector (Text | Sort_Column) | Text -> Text_Ordering -> Boolean -> Problem_Behavior -> Table ! Incomparable_Values | No_Input_Columns_Selected | Missing_Input_Columns
order_by self (columns = ([(Sort_Column.Name (self.columns.at 0 . name))])) text_ordering=Text_Ordering.Default error_on_missing_columns=True on_problems=Problem_Behavior.Report_Warning =
@ -2626,7 +2626,7 @@ type Table
fill_nothing = table.fill_nothing ["col0", "col1"] 20.5
@columns Widget_Helpers.make_column_name_vector_selector
@default (self -> Widget_Helpers.make_fill_default_value_selector column_source=self include_custom_text=False)
@default (self -> Widget_Helpers.make_fill_default_value_selector column_source=self add_text=True add_number=True add_boolean=True)
fill_nothing : Vector (Integer | Text | Regex) | Text | Integer | Regex -> Column | Column_Ref | Previous_Value | Any -> Table
fill_nothing self (columns : Vector | Text | Integer | Regex) default =
resolved_default = (self:Table_Ref).resolve default
@ -2654,7 +2654,7 @@ type Table
fill_empty = table.fill_empty ["col0", "col1"] "hello"
@columns Widget_Helpers.make_column_name_vector_selector
@default (self -> Widget_Helpers.make_fill_default_value_selector column_source=self include_custom_text=True)
@default (self -> Widget_Helpers.make_fill_default_value_selector column_source=self add_text=True)
fill_empty : Vector (Integer | Text | Regex) | Text | Integer | Regex -> Column | Column_Ref | Previous_Value | Any -> Table
fill_empty self (columns : Vector | Text | Integer | Regex) default =
resolved_default = (self:Table_Ref).resolve default
@ -2682,26 +2682,26 @@ type Table
> Example
Replace dashes with underscores.
table.text_replace ["col0", "col1"] "-" "_"
table.text_replace ["Input"] "-" "_"
> Example
Remove leading and trailing spaces from cells.
table.text_replace ["col.*".to_regex] "^\s*(.*?)\s*$".to_regex "$1"
table.text_replace ["Input"] "^\s*(.*?)\s*$".to_regex "$1"
> Example
Replace texts in quotes with parentheses.
column.replace ["col0"] '"(.*?)"'.to_regex '($1)'
table.text_replace ["Input"] '"(.*?)"'.to_regex '($1)'
@columns Widget_Helpers.make_column_name_vector_selector
@term Widget_Helpers.make_column_ref_or_text_value_selector
@new_text Widget_Helpers.make_column_ref_or_text_value_selector
@term (Widget_Helpers.make_column_ref_by_name_selector add_regex=True add_text=True)
@new_text (Widget_Helpers.make_column_ref_by_name_selector add_text=True)
text_replace : Vector (Integer | Text | Regex) | Text | Integer | Regex -> Text | Column | Column_Ref | Regex -> Text | Column | Column_Ref -> Case_Sensitivity -> Boolean -> Column
text_replace self columns (term : Text | Column | Column_Ref | Regex = "") (new_text : Text | Column | Column_Ref = "") case_sensitivity=Case_Sensitivity.Sensitive only_first=False =
table_ref = Table_Ref.from self
resolved_term = table_ref.resolve term
resolved_new_text = table_ref.resolve new_text
transformer col = col.replace resolved_term resolved_new_text case_sensitivity only_first
transformer col = col.text_replace resolved_term resolved_new_text case_sensitivity only_first
Table_Helpers.replace_columns_with_transformed_columns self columns transformer
## PRIVATE

View File

@ -1155,7 +1155,7 @@ type Column
import Standard.Examples
example_fill_nothing = Examples.decimal_column.fill_nothing 20.5
@default (Widget_Helpers.make_fill_default_value_selector include_custom_text=False)
@default (self-> Widget_Helpers.make_fill_default_value_selector add_number=(self.value_type.is_numeric || self.value_type==Value_Type.Mixed) add_boolean=(self.value_type.is_boolean || self.value_type==Value_Type.Mixed) add_text=(self.value_type.is_text || self.value_type==Value_Type.Mixed))
fill_nothing : Column | Previous_Value | Any -> Column
fill_nothing self default =
if Previous_Value == default then fill_previous self Nothing else
@ -1192,7 +1192,7 @@ type Column
import Standard.Examples
example_fill_empty = Examples.text_column_1.fill_empty "hello"
@default (Widget_Helpers.make_fill_default_value_selector include_custom_text=True)
@default (Widget_Helpers.make_fill_default_value_selector add_text=True)
fill_empty : Column | Previous_Value | Any -> Column
fill_empty self default =
Value_Type.expect_text self <|
@ -1428,20 +1428,20 @@ type Column
> Example
Replace dashes with underscores.
column.replace "-" "_"
column.text_replace "-" "_"
> Example
Remove leading and trailing spaces from cells.
column.replace "^\s*(.*?)\s*$".to_regex "$1"
column.text_replace "^\s*(.*?)\s*$".to_regex "$1"
> Example
Replace texts in quotes with parentheses.
column.replace '"(.*?)"'.to_regex '($1)'
column.text_replace '"(.*?)"'.to_regex '($1)'
@term make_regex_text_widget
replace : Text | Regex | Column -> Text | Column -> Case_Sensitivity -> Boolean -> Column
replace self term="" new_text="" case_sensitivity=Case_Sensitivity.Sensitive only_first=False =
text_replace : Text | Regex | Column -> Text | Column -> Case_Sensitivity -> Boolean -> Column
text_replace self term="" new_text="" case_sensitivity=Case_Sensitivity.Sensitive only_first=False =
Value_Type.expect_text self <|
term_fn = wrap_text_or_regex_argument_as_value_provider term
new_text_fn = wrap_text_argument_as_value_provider new_text

View File

@ -8,7 +8,7 @@ type Sort_Column
Name name:Text direction:Sort_Direction=Sort_Direction.Ascending
## A column to sort by, selected by its index.
Index index:Integer direction:Sort_Direction=Sort_Direction.Ascending
Index index:Integer=0 direction:Sort_Direction=Sort_Direction.Ascending
## A selector allowing to match columns by their name.
@ -17,4 +17,4 @@ type Sort_Column
matched columns will be placed in the ORDER BY clause at the position of
this selector. Their relative order between each other will be the same
as in the table.
Select_By_Name name:Text direction:Sort_Direction=Sort_Direction.Ascending case_sensitivity:Case_Sensitivity=Case_Sensitivity.Insensitive use_regex:Boolean=False
Select_By_Name name:Text|Regex direction:Sort_Direction=Sort_Direction.Ascending case_sensitivity:Case_Sensitivity=Case_Sensitivity.Insensitive

View File

@ -786,7 +786,7 @@ type Table
> Example
Sort the table by columns whose names start with letter `a`.
table.order_by [(Sort_Column.Select_By_Name "a.*" use_regex=True case_sensitivity=Case_Sensitivity.Insensitive)]
table.order_by [(Sort_Column.Select_By_Name "a.*".to_regex case_sensitivity=Case_Sensitivity.Insensitive)]
@columns Widget_Helpers.make_order_by_selector
order_by : Vector (Text | Sort_Column) | Text -> Text_Ordering -> Boolean -> Problem_Behavior -> Table ! Incomparable_Values | No_Input_Columns_Selected | Missing_Input_Columns
order_by self (columns = [self.columns.first.name]) text_ordering=Text_Ordering.Default error_on_missing_columns=True on_problems=Problem_Behavior.Report_Warning =
@ -2707,7 +2707,7 @@ type Table
fill_nothing = table.fill_nothing ["col0", "col1"] 20.5
@columns Widget_Helpers.make_column_name_vector_selector
@default (self -> Widget_Helpers.make_fill_default_value_selector column_source=self include_custom_text=False)
@default (self -> Widget_Helpers.make_fill_default_value_selector column_source=self add_text=True add_number=True add_boolean=True)
fill_nothing : Vector (Integer | Text | Regex) | Text | Integer | Regex -> Column | Column_Ref | Previous_Value | Any -> Table
fill_nothing self (columns : Vector | Text | Integer | Regex) default =
resolved_default = (self:Table_Ref).resolve default
@ -2735,7 +2735,7 @@ type Table
fill_empty = table.fill_empty ["col0", "col1"] "hello"
@columns Widget_Helpers.make_column_name_vector_selector
@default (self -> Widget_Helpers.make_fill_default_value_selector column_source=self include_custom_text=True)
@default (self -> Widget_Helpers.make_fill_default_value_selector column_source=self add_text=True)
fill_empty : Vector (Integer | Text | Regex) | Text | Integer | Regex -> Column | Column_Ref | Previous_Value | Any -> Table
fill_empty self (columns : Vector | Text | Integer | Regex) default =
resolved_default = (self:Table_Ref).resolve default
@ -2763,26 +2763,26 @@ type Table
> Example
Replace dashes with underscores.
table.text_replace "-" "_"
table.text_replace ["Input"] "-" "_"
> Example
Remove leading and trailing spaces from cells.
column.replace "^\s*(.*?)\s*$".to_regex "$1"
table.text_replace ["Input"] "^\s*(.*?)\s*$".to_regex "$1"
> Example
Replace texts in quotes with parentheses.
column.replace '"(.*?)"'.to_regex '($1)'
table.text_replace ["Input"] '"(.*?)"'.to_regex '($1)'
@columns Widget_Helpers.make_column_name_vector_selector
@term Widget_Helpers.make_column_ref_or_text_value_selector
@new_text Widget_Helpers.make_column_ref_or_text_value_selector
@term (Widget_Helpers.make_column_ref_by_name_selector add_regex=True add_text=True)
@new_text (Widget_Helpers.make_column_ref_by_name_selector add_text=True)
text_replace : Vector (Integer | Text | Regex) | Text | Integer | Regex -> Text | Column | Column_Ref | Regex -> Text | Column | Column_Ref -> Case_Sensitivity -> Boolean -> Column
text_replace self columns (term : Text | Column | Column_Ref | Regex = "") (new_text : Text | Column | Column_Ref = "") case_sensitivity=Case_Sensitivity.Sensitive only_first=False =
table_ref = Table_Ref.from self
resolved_term = table_ref.resolve term
resolved_new_text = table_ref.resolve new_text
transformer col = col.replace resolved_term resolved_new_text case_sensitivity only_first
transformer col = col.text_replace resolved_term resolved_new_text case_sensitivity only_first
Table_Helpers.replace_columns_with_transformed_columns self columns transformer
## PRIVATE

View File

@ -430,14 +430,13 @@ resolve_order_by internal_columns column_selectors problem_builder =
name : Text -> resolve_selector (Sort_Column.Name name)
ix : Integer -> resolve_selector (Sort_Column.Index ix)
Sort_Column.Name name direction ->
resolve_selector (Sort_Column.Select_By_Name name direction Case_Sensitivity.Sensitive use_regex=False)
resolve_selector (Sort_Column.Select_By_Name name direction Case_Sensitivity.Sensitive)
Sort_Column.Index ix _ ->
if is_index_valid internal_columns.length ix then [Column_Transform_Element.Value (internal_columns.at ix) selector] else
problem_builder.report_oob_indices [ix]
[]
Sort_Column.Select_By_Name name _ case_sensitivity use_regex ->
regex_or_text = if use_regex then name.to_regex else name
matches = match_columns regex_or_text case_sensitivity internal_columns
Sort_Column.Select_By_Name name _ case_sensitivity ->
matches = match_columns name case_sensitivity internal_columns
if matches.is_empty then problem_builder.report_missing_input_columns [name]
matches.map c-> Column_Transform_Element.Value c selector
selectors_vec = case column_selectors of

View File

@ -2,11 +2,12 @@ from Standard.Base import all
import Standard.Base.Metadata.Display
import Standard.Base.Metadata.Widget
from Standard.Base.Metadata.Choice import Option
from Standard.Base.Metadata.Widget import Single_Choice, Vector_Editor
from Standard.Base.Metadata.Widget import Single_Choice, Vector_Editor, Numeric_Input
from Standard.Base.System.File_Format import format_types
import project.Data.Aggregate_Column.Aggregate_Column
import project.Data.Join_Condition.Join_Condition
import project.Data.Sort_Column.Sort_Column
import project.Data.Table.Table
import project.Data.Type.Value_Type.Auto
import project.Data.Type.Value_Type.Value_Type
@ -82,52 +83,47 @@ make_column_name_vector_selector table display=Display.Always =
## PRIVATE
Make a column reference by name selector.
make_column_ref_by_name_selector : Table -> Display -> Widget
make_column_ref_by_name_selector table display=Display.Always =
col_names_options = table.column_names.map (name -> Option name "(Column_Ref.Name "+name.pretty+")")
expression_option = Option "<Expression>" "(Column_Ref.Expression '["+table.column_names.first+"]')"
Single_Choice values=(col_names_options+[expression_option]) display=display
## PRIVATE
Same as `make_column_ref_by_name_selector` but also highlights an option for
custom text.
make_column_ref_or_text_value_selector : Table -> Display -> Widget
make_column_ref_or_text_value_selector table display=Display.Always =
col_names_options = table.column_names.map (name -> Option name "(Column_Ref.Name "+name.pretty+")")
custom_text_option = Option "'custom text'" "''"
expression_option = Option "<Expression>" "(Column_Ref.Expression '["+table.column_names.first+"]')"
Single_Choice values=(col_names_options+[custom_text_option, expression_option]) display=display
make_column_ref_by_name_selector : Table -> Display -> Boolean -> Boolean -> Boolean -> Boolean -> Widget
make_column_ref_by_name_selector table display:Display=Display.Always add_text:Boolean=False add_regex:Boolean=False add_number:Boolean=False add_boolean:Boolean=False =
text = if add_text then [Option "<Text Value>" "''"] else []
regex = if add_regex then [Option "<Regular Expression>" "('').to_regex"] else []
number = if add_number then [Option "<Number Value>" "0"] else []
boolean = if add_boolean then [Option "<True/False>" "True"] else []
expression = if table.is_nothing then [] else [Option "<Expression>" "(Column_Ref.Expression '["+table.column_names.first+"]')"]
col_names = if table.is_nothing then [] else table.column_names.map (name -> Option name "(Column_Ref.Name "+name.pretty+")")
values = text + regex + number + boolean + expression + col_names
Single_Choice values=values display=display
## PRIVATE
If `column_source` is Nothing, `Column_Ref` options will not be added.
make_fill_default_value_selector : Table | Nothing -> Boolean -> Display -> Widget
make_fill_default_value_selector column_source=Nothing include_custom_text=False display=Display.Always =
col_names_options = if column_source.is_nothing then [] else
column_source.column_names.map (name -> Option name "(Column_Ref.Name "+name.pretty+")")
custom_text_option = if include_custom_text then [Option "'custom text'" "''"] else []
previous_value_option = [Option 'Previous Value' 'Previous_Value']
default_column = if column_source.is_nothing then '""' else column_source.name.pretty
expression_option = Option "<Expression>" '(Column_Ref.Expression \''+default_column+'\')'
Single_Choice values=(previous_value_option+col_names_options+custom_text_option+expression_option) display=display
make_fill_default_value_selector : Table | Nothing -> Display -> Boolean -> Boolean -> Boolean -> Widget
make_fill_default_value_selector column_source=Nothing display=Display.Always add_text:Boolean=False add_number:Boolean=False add_boolean:Boolean=False =
column_ref = make_column_ref_by_name_selector column_source display add_text add_regex=False add_number=add_number add_boolean=add_boolean
previous_value = [Option 'Previous Value' 'Previous_Value']
Single_Choice values=(previous_value+column_ref.values) display=display
## PRIVATE
Make a filter condition selector.
make_filter_condition_selector : Table -> Display -> Widget
make_filter_condition_selector table display=Display.Always =
col_names = make_column_ref_by_name_selector table
with_all_types = make_column_ref_by_name_selector table add_text=True add_number=True add_boolean=True
with_number_text = make_column_ref_by_name_selector table add_text=True add_number=True
with_text = make_column_ref_by_name_selector table add_text=True
builder = Vector.new_builder
fqn = Meta.get_qualified_type_name Filter_Condition
builder.append (Option "Equals" fqn+".Equal" [["to", col_names]])
builder.append (Option "Not Equals" fqn+".Not_Equal" [["to", col_names]])
builder.append (Option "Less Than" fqn+".Less" [["than", col_names]])
builder.append (Option "Less Than Or Equal" fqn+".Equal_Or_Less" [["than", col_names]])
builder.append (Option "Greater Than" fqn+".Greater" [["than", col_names]])
builder.append (Option "Greater Than Or Equal" fqn+".Equal_Or_Greater" [["than", col_names]])
builder.append (Option "Between" fqn+".Between" [["lower", col_names], ["upper", col_names]])
builder.append (Option "Equals Ignore Case" fqn+".Equal_Ignore_Case" [["to", col_names]])
builder.append (Option "Starts With" fqn+".Starts_With" [["prefix", col_names]])
builder.append (Option "Ends With" fqn+".Ends_With" [["suffix", col_names]])
builder.append (Option "Contains" fqn+".Contains" [["substring", col_names]])
builder.append (Option "Equals" fqn+".Equal" [["to", with_all_types]])
builder.append (Option "Not Equals" fqn+".Not_Equal" [["to", with_all_types]])
builder.append (Option "Less Than" fqn+".Less" [["than", with_number_text]])
builder.append (Option "Less Than Or Equal" fqn+".Equal_Or_Less" [["than", with_number_text]])
builder.append (Option "Greater Than" fqn+".Greater" [["than", with_number_text]])
builder.append (Option "Greater Than Or Equal" fqn+".Equal_Or_Greater" [["than", with_number_text]])
builder.append (Option "Between" fqn+".Between" [["lower", col_names], ["upper", with_number_text]])
builder.append (Option "Equals Ignore Case" fqn+".Equal_Ignore_Case" [["to", with_text]])
builder.append (Option "Starts With" fqn+".Starts_With" [["prefix", with_text]])
builder.append (Option "Ends With" fqn+".Ends_With" [["suffix", with_text]])
builder.append (Option "Contains" fqn+".Contains" [["substring", with_text]])
builder.append (Option "Is Nothing" fqn+".Is_Nothing")
builder.append (Option "Is Not Nothing" fqn+".Not_Nothing")
builder.append (Option "Is Finite" fqn+".Is_Finite")
@ -137,7 +133,7 @@ make_filter_condition_selector table display=Display.Always =
builder.append (Option "Is False" fqn+".Is_False")
builder.append (Option "Is Empty" fqn+".Is_Empty")
builder.append (Option "Is Not Empty" fqn+".Not_Empty")
builder.append (Option "Like" fqn+".Like" [["pattern", col_names]])
builder.append (Option "Like" fqn+".Like" [["pattern", with_text]])
builder.append (Option "Is In" fqn+".Is_In")
Single_Choice builder.to_vector display=display
@ -160,20 +156,23 @@ make_join_condition_selector table display=Display.Always =
Make a column name selector.
make_order_by_selector : Table -> Display -> Widget
make_order_by_selector table display=Display.Always =
col_names = table.column_names
names = col_names.fold [] c-> n-> c + [Option n "(Sort_Column.Name "+n.pretty+")"]
item_editor = Single_Choice display=display values=names
Vector_Editor item_editor=item_editor item_default=names.first.value display=display
fqn = Meta.get_qualified_type_name Sort_Column
name = Option "Name" fqn+".Name" [["name", make_column_name_selector table display=Display.Always]]
index = Option "Index" fqn+".Index" [["index", Numeric_Input display=Display.Always minimum=0 maximum=table.column_count-1]]
item_editor = Single_Choice display=Display.Always values=[name, index]
Vector_Editor item_editor=item_editor item_default="(Sort_Column.Name "+table.column_names.first.pretty+")" display=display
## PRIVATE
Make a column rename name selector.
make_rename_name_vector_selector : Table -> Display -> Widget
make_rename_name_vector_selector table display=Display.Always =
col_names = table.column_names
names = col_names.map n-> Option n "["+n.pretty+", "+n.pretty+"]"
item_editor = Single_Choice display=Display.Always values=names
default_item = "["+col_names.first.pretty+", "+col_names.first.pretty+"]"
Vector_Editor item_editor=item_editor item_default=default_item display=display
names = [Option "<Regular Expression>" "'^.*$'.to_regex"] + (col_names.map n-> Option n n.pretty)
fqn = Meta.get_qualified_type_name Pair
name = Option "Name" fqn+".Value" [["first", Single_Choice values=names display=Display.Always]]
item_editor = Single_Choice display=Display.Always values=[name]
Vector_Editor item_editor=item_editor item_default="(Pair.Value "+col_names.first.pretty+" 'New Name')" display=display
## PRIVATE
Selector for type argument on `Column.parse`.

View File

@ -1,15 +1,16 @@
import project.Bench.Bench
import project.Bench.Phase_Conf
import project.Faker.Faker
import project.Problems
import project.Suite.Suite
import project.Test.Test
import project.Problems
from project.Extensions import all
export project.Bench.Bench
export project.Bench.Phase_Conf
export project.Faker.Faker
export project.Problems
export project.Suite.Suite
export project.Test.Test
export project.Problems
from project.Extensions export all

View File

@ -1364,10 +1364,10 @@ add_specs suite_builder setup =
supported_replace_params . should_be_a Set
are_params_supported = supported_replace_params.contains params
case are_params_supported of
True -> column.replace term new_text case_sensitivity only_first . to_vector . should_equal expected
False -> column.replace term new_text case_sensitivity only_first . should_fail_with Unsupported_Database_Operation
True -> column.text_replace term new_text case_sensitivity only_first . to_vector . should_equal expected
False -> column.text_replace term new_text case_sensitivity only_first . should_fail_with Unsupported_Database_Operation
False ->
result = column.replace term new_text case_sensitivity only_first
result = column.text_replace term new_text case_sensitivity only_first
result.value_type . should_equal Value_Type.Char
result . to_vector . should_equal expected
@ -1470,7 +1470,7 @@ add_specs suite_builder setup =
group_builder.specify "should not allow Case_Sensitivity.Insensitive with a non-default locale" <|
col = table_builder [["A", ["Alpha", "Bravo", "Charlie", "Delta", "Echo", "Foxtrot"]]] . at 'A'
locale = Locale.new "en" "GB" "UTF-8"
col.replace 'asdf' 'zxcv' case_sensitivity=(Case_Sensitivity.Insensitive locale) . should_fail_with Illegal_Argument
col.text_replace 'asdf' 'zxcv' case_sensitivity=(Case_Sensitivity.Insensitive locale) . should_fail_with Illegal_Argument
group_builder.specify "column name" <|
table = table_builder [["x", ['hello Hello', 'hello hello', 'HELLO HELLO', 'a[bcd] A[bCd] a[bcd]', 'abac ad Ab aCAd']], ["patterns", ['hello', 'hello', 'hello', 'a[bcd]', 'a[bcd]']], ["replacements", ['bye', 'bye', 'bye', 'hey', 'hey']]]
@ -1480,11 +1480,11 @@ add_specs suite_builder setup =
supported_replace_params = setup.test_selection.supported_replace_params
if supported_replace_params.contains (Replace_Params.Value Text Case_Sensitivity.Default False) then
col.replace 'hello' 'bye' . name . should_equal 'replace([x], \'hello\', \'bye\')'
col.text_replace 'hello' 'bye' . name . should_equal 'replace([x], \'hello\', \'bye\')'
if supported_replace_params.contains (Replace_Params.Value Regex Case_Sensitivity.Default False) then
col.replace 'a[bcd]'.to_regex 'hey' . name . should_equal 'replace([x], \'a[bcd]\', \'hey\')'
col.text_replace 'a[bcd]'.to_regex 'hey' . name . should_equal 'replace([x], \'a[bcd]\', \'hey\')'
if supported_replace_params.contains (Replace_Params.Value Column Case_Sensitivity.Default False) then
col.replace patterns replacements . name . should_equal 'replace([x], [patterns], [replacements])'
col.text_replace patterns replacements . name . should_equal 'replace([x], [patterns], [replacements])'
suite_builder.group prefix+"Column Operations - Text Replace (in-memory only)" group_builder->
@ -1498,18 +1498,18 @@ add_specs suite_builder setup =
setup.table_builder cols connection=data.connection
group_builder.specify "should allow simple replacing" <|
data.a.replace "a" "#" . to_vector . should_equal ["Alph#", "Br#vo", "Ch#rlie", "Delt#", "Echo", "Foxtrot"]
data.a.replace "o" "#" . to_vector . should_equal ["Alpha", "Brav#", "Charlie", "Delta", "Ech#", "F#xtr#t"]
data.a.replace data.b "#" . to_vector . should_equal ["#lpha", "Bravo", "Ch#rlie", "Delta", "Ech#", "Foxtrot"]
data.a.replace "o" "#" only_first=True . to_vector . should_equal ["Alpha", "Brav#", "Charlie", "Delta", "Ech#", "F#xtrot"]
data.a.replace "a" "#" Case_Sensitivity.Insensitive . to_vector . should_equal ["#lph#", "Br#vo", "Ch#rlie", "Delt#", "Echo", "Foxtrot"]
data.a.replace data.b "#" Case_Sensitivity.Insensitive . to_vector . should_equal ["#lph#", "Brav#", "Ch#rlie", "D#lta", "Ech#", "F#xtr#t"]
data.a.replace data.b "#" Case_Sensitivity.Insensitive only_first=True . to_vector . should_equal ["#lpha", "Brav#", "Ch#rlie", "D#lta", "Ech#", "F#xtrot"]
data.a.text_replace "a" "#" . to_vector . should_equal ["Alph#", "Br#vo", "Ch#rlie", "Delt#", "Echo", "Foxtrot"]
data.a.text_replace "o" "#" . to_vector . should_equal ["Alpha", "Brav#", "Charlie", "Delta", "Ech#", "F#xtr#t"]
data.a.text_replace data.b "#" . to_vector . should_equal ["#lpha", "Bravo", "Ch#rlie", "Delta", "Ech#", "Foxtrot"]
data.a.text_replace "o" "#" only_first=True . to_vector . should_equal ["Alpha", "Brav#", "Charlie", "Delta", "Ech#", "F#xtrot"]
data.a.text_replace "a" "#" Case_Sensitivity.Insensitive . to_vector . should_equal ["#lph#", "Br#vo", "Ch#rlie", "Delt#", "Echo", "Foxtrot"]
data.a.text_replace data.b "#" Case_Sensitivity.Insensitive . to_vector . should_equal ["#lph#", "Brav#", "Ch#rlie", "D#lta", "Ech#", "F#xtr#t"]
data.a.text_replace data.b "#" Case_Sensitivity.Insensitive only_first=True . to_vector . should_equal ["#lpha", "Brav#", "Ch#rlie", "D#lta", "Ech#", "F#xtrot"]
group_builder.specify "should allow regex based replacing" <|
data.a.replace "[aeiou]".to_regex "#" . to_vector . should_equal ["Alph#", "Br#v#", "Ch#rl##", "D#lt#", "Ech#", "F#xtr#t"]
data.a.replace "[aeiou]".to_regex "#" . to_vector . should_equal ["Alph#", "Br#v#", "Ch#rl##", "D#lt#", "Ech#", "F#xtr#t"]
data.a.replace "([aeiou])(.*?)[aeiou]".to_regex "$1$2$1" . to_vector . should_equal ["Alpha", "Brava", "Charlae", "Delte", "Echo", "Foxtrot"]
data.a.text_replace "[aeiou]".to_regex "#" . to_vector . should_equal ["Alph#", "Br#v#", "Ch#rl##", "D#lt#", "Ech#", "F#xtr#t"]
data.a.text_replace "[aeiou]".to_regex "#" . to_vector . should_equal ["Alph#", "Br#v#", "Ch#rl##", "D#lt#", "Ech#", "F#xtr#t"]
data.a.text_replace "([aeiou])(.*?)[aeiou]".to_regex "$1$2$1" . to_vector . should_equal ["Alpha", "Brava", "Charlae", "Delte", "Echo", "Foxtrot"]
group_builder.specify "should handle unicode" <|
table = table_builder [["x", ["śćxx", "ąąasdfąą", "affib"]], ["patterns", ["ć", "ąą", "ffi"]], ["replacements", ["abc", "def", "ghi"]]]
@ -1517,7 +1517,7 @@ add_specs suite_builder setup =
patterns = table.at "patterns"
replacements = table.at "replacements"
col.replace patterns replacements . to_vector . should_equal ["śabcxx", "defasdfdef", "aghib"]
col.text_replace patterns replacements . to_vector . should_equal ["śabcxx", "defasdfdef", "aghib"]
group_builder.specify "should take pattern and replacement string columns" <|
t = table_builder [["x", ["hello", "what", "yes"]], ["patterns", ["ell", "wh", "es"]], ["replacements", ["xyz", "qwer", "asdf"]]]
@ -1525,23 +1525,23 @@ add_specs suite_builder setup =
patterns = t.at "patterns"
replacements = t.at "replacements"
col.replace patterns replacements . to_vector . should_equal ["hxyzo", "qwerat", "yasdf"]
col.text_replace patterns replacements . to_vector . should_equal ["hxyzo", "qwerat", "yasdf"]
group_builder.specify "should only allow replace on Text columns" <|
data.c.replace "a" "#" . should_fail_with Invalid_Value_Type
data.a.replace 1 "#" . should_fail_with Invalid_Value_Type
data.a.replace data.c "#" . should_fail_with Invalid_Value_Type
data.a.replace "a" 1 . should_fail_with Invalid_Value_Type
data.a.replace "a" data.c . should_fail_with Invalid_Value_Type
data.c.text_replace "a" "#" . should_fail_with Invalid_Value_Type
data.a.text_replace 1 "#" . should_fail_with Invalid_Value_Type
data.a.text_replace data.c "#" . should_fail_with Invalid_Value_Type
data.a.text_replace "a" 1 . should_fail_with Invalid_Value_Type
data.a.text_replace "a" data.c . should_fail_with Invalid_Value_Type
group_builder.specify "should not replace if Empty term" <|
data.a.replace '' "#" . to_vector . should_equal ["Alpha", "Bravo", "Charlie", "Delta", "Echo", "Foxtrot"]
data.a.replace data.d "#" . to_vector . should_equal ["Alpha", "Bravo", "Charlie", "Delta", "Echo", "Foxtrot"]
data.a.text_replace '' "#" . to_vector . should_equal ["Alpha", "Bravo", "Charlie", "Delta", "Echo", "Foxtrot"]
data.a.text_replace data.d "#" . to_vector . should_equal ["Alpha", "Bravo", "Charlie", "Delta", "Echo", "Foxtrot"]
group_builder.specify "should infer correct return type" <|
c = table_builder [["texts", ["foo", "bar"]]] . at "texts"
c1 = c.replace "a" "---"
c1 = c.text_replace "a" "---"
c1.to_vector . should_equal ["foo", "b---r"]
vt1 = c1.value_type
Test.with_clue "c1.value_type="+vt1.to_display_text+": " <|
@ -1551,7 +1551,7 @@ add_specs suite_builder setup =
group_builder.specify "should infer correct return type (2)" pending=(if setup.test_selection.fixed_length_text_columns.not then "Fixed-length Char columns are not supported by this backend.") <|
c = table_builder [["texts", ["foo", "bar"]]] . at "texts"
c2 = c.cast (Value_Type.Char size=2 variable_length=False)
c3 = c2.replace "a" "---"
c3 = c2.text_replace "a" "---"
c3.to_vector . should_equal ["fo", "b---"]
vt3 = c3.value_type

View File

@ -70,7 +70,7 @@ add_specs suite_builder setup =
t2.at "gamma" . to_vector . should_equal [3, 1, 4, 2]
t2.at "alpha" . to_vector . should_equal [1, 3, 0, 2]
t3 = data.table.order_by [Sort_Column.Select_By_Name "a.*" use_regex=True case_sensitivity=Case_Sensitivity.Insensitive]
t3 = data.table.order_by [Sort_Column.Select_By_Name "a.*".to_regex case_sensitivity=Case_Sensitivity.Insensitive]
t3.at "alpha" . to_vector . should_equal [0, 1, 2, 3]
group_builder.specify "should work with single column name" <|
@ -96,11 +96,11 @@ add_specs suite_builder setup =
t4.at "gamma" . to_vector . should_equal [1, 2, 3, 4]
group_builder.specify "should allow the selector to mix regex and case insensitive matching" <|
t4 = data.table.order_by [Sort_Column.Select_By_Name "A.*" use_regex=True case_sensitivity=Case_Sensitivity.Insensitive]
t4 = data.table.order_by [Sort_Column.Select_By_Name "A.*".to_regex case_sensitivity=Case_Sensitivity.Insensitive]
t4.at "alpha" . to_vector . should_equal [0, 1, 2, 3]
group_builder.specify "should correctly handle regexes matching multiple names" <|
t1 = data.table.order_by [Sort_Column.Select_By_Name ".*ta" Sort_Direction.Descending use_regex=True]
t1 = data.table.order_by [Sort_Column.Select_By_Name ".*ta".to_regex Sort_Direction.Descending]
t1.at "beta" . to_vector . should_equal ["b", "b", "a", "a"]
t1.at "delta" . to_vector . should_equal ["a1", "a03", "a2", "a10"]
t1.at "gamma" . to_vector . should_equal [2, 4, 3, 1]
@ -142,7 +142,7 @@ add_specs suite_builder setup =
t1.at "gamma" . to_vector . should_equal [4, 3, 2, 1]
group_builder.specify "should correctly handle edge-cases: duplicate matches due to regexes" <|
selector = [Sort_Column.Select_By_Name "a.*" use_regex=True, Sort_Column.Select_By_Name "alpha" Sort_Direction.Descending]
selector = [Sort_Column.Select_By_Name "a.*".to_regex, Sort_Column.Select_By_Name "alpha" Sort_Direction.Descending]
t1 = data.table.order_by selector
Problems.assume_no_problems t1
t1.at "alpha" . to_vector . should_equal [0, 1, 2, 3]
@ -154,7 +154,7 @@ add_specs suite_builder setup =
t1.at "beta" . to_vector . should_equal ["b", "a", "b", "a"]
t1.at "gamma" . to_vector . should_equal [4, 3, 2, 1]
t2 = data.table.order_by [Sort_Column.Select_By_Name "a.*a" use_regex=True, Sort_Column.Index 1]
t2 = data.table.order_by [Sort_Column.Select_By_Name "a.*a".to_regex, Sort_Column.Index 1]
t2.at "alpha" . to_vector . should_equal [0, 1, 2, 3]
t2.at "beta" . to_vector . should_equal ["b", "a", "b", "a"]
t2.at "gamma" . to_vector . should_equal [4, 3, 2, 1]