Allow Filter_Condition to be inverted. (#8861)

- Various linting fixes (doc comments and type annotations etc.).
- Add an action to determine if a `Filter_Condition` is keep or remove.

https://github.com/enso-org/enso/assets/4699705/69ba2bd3-8893-4237-acc4-eb01f534a209

- Remove `Not_In`, `Not_Contains` and `Not_Like` from `Filter_Condition`.

- Ability to use an `Expression` as a `Column_Ref`.

https://github.com/enso-org/enso/assets/4699705/16a2e030-f8f9-4f59-beca-2646f56fcb90
This commit is contained in:
James Dunkerley 2024-02-07 14:36:14 +00:00 committed by GitHub
parent 83fffd9c05
commit 0c39f8ec04
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
54 changed files with 531 additions and 467 deletions

View File

@ -612,6 +612,7 @@
- [Added `File_By_Line` type allowing processing a file line by line. New faster - [Added `File_By_Line` type allowing processing a file line by line. New faster
JSON parser based off Jackson.][8719] JSON parser based off Jackson.][8719]
- [Implemented `Table.replace` for the in-memory backend.][8935] - [Implemented `Table.replace` for the in-memory backend.][8935]
- [Allow removing rows using a Filter_Condition.][8861]
[debug-shortcuts]: [debug-shortcuts]:
https://github.com/enso-org/enso/blob/develop/app/gui/docs/product/shortcuts.md#debug https://github.com/enso-org/enso/blob/develop/app/gui/docs/product/shortcuts.md#debug
@ -880,6 +881,7 @@
[8849]: https://github.com/enso-org/enso/pull/8849 [8849]: https://github.com/enso-org/enso/pull/8849
[8865]: https://github.com/enso-org/enso/pull/8865 [8865]: https://github.com/enso-org/enso/pull/8865
[8935]: https://github.com/enso-org/enso/pull/8935 [8935]: https://github.com/enso-org/enso/pull/8935
[8861]: https://github.com/enso-org/enso/pull/8861
#### Enso Compiler #### Enso Compiler

View File

@ -1,9 +1,9 @@
from Standard.Base import all from Standard.Base import all
from Standard.Base.Metadata import make_single_choice, Widget
from Standard.Base.Data.Enso_Cloud.Enso_Secret import as_hideable_value from Standard.Base.Data.Enso_Cloud.Enso_Secret import as_hideable_value
from Standard.Base.Metadata import make_single_choice, Widget
polyglot java import org.enso.aws.ProfileReader
polyglot java import org.enso.aws.AwsCredential polyglot java import org.enso.aws.AwsCredential
polyglot java import org.enso.aws.ProfileReader
type AWS_Credential type AWS_Credential
## Access using IAM via an AWS profile. ## Access using IAM via an AWS profile.

View File

@ -146,7 +146,7 @@ read_text path (encoding=Encoding.utf_8) (on_problems=Problem_Behavior.Report_Wa
example_list_files = example_list_files =
Data.list_directory Examples.data_dir name_filter="**.md" recursive=True Data.list_directory Examples.data_dir name_filter="**.md" recursive=True
list_directory : File -> Text | Nothing -> Boolean -> Vector File list_directory : File -> Text | Nothing -> Boolean -> Vector File
list_directory directory:File name_filter:Text|Nothing=Nothing recursive:Boolean=False = list_directory directory:File (name_filter:(Text | Nothing)=Nothing) recursive:Boolean=False =
directory . list name_filter=name_filter recursive=recursive directory . list name_filter=name_filter recursive=recursive
## ALIAS download, http get ## ALIAS download, http get

View File

@ -1,5 +1,5 @@
import project.Data.Text.Text
import project.Data.Text.Encoding.Encoding import project.Data.Text.Encoding.Encoding
import project.Data.Text.Text
import project.Errors.Encoding_Error.Encoding_Error import project.Errors.Encoding_Error.Encoding_Error
from project.Data.Text.Extensions import all from project.Data.Text.Extensions import all

View File

@ -255,7 +255,7 @@ type Enso_File
## UNSTABLE ## UNSTABLE
Resolves a file or directory within this directory. Resolves a file or directory within this directory.
/ : Text -> Enso_File / : Text -> Enso_File ! Not_Found
/ self (name : Text) -> Enso_File ! Not_Found = / self (name : Text) -> Enso_File ! Not_Found =
if self.is_directory.not then Error.throw (Illegal_Argument.Error "/ can only be used for directories") else if self.is_directory.not then Error.throw (Illegal_Argument.Error "/ can only be used for directories") else
if name.contains "/" then Error.throw (Illegal_Argument.Error "Resolving sub-paths (/) is not implemented. Temporary workaround: use the `/` operator multiple times.") else if name.contains "/" then Error.throw (Illegal_Argument.Error "Resolving sub-paths (/) is not implemented. Temporary workaround: use the `/` operator multiple times.") else

View File

@ -1,6 +1,6 @@
import project.Data.Base_64.Base_64 import project.Data.Base_64.Base_64
import project.Data.Enso_Cloud.Enso_File.Enso_File
import project.Data.Enso_Cloud.Enso_File.Enso_Asset_Type import project.Data.Enso_Cloud.Enso_File.Enso_Asset_Type
import project.Data.Enso_Cloud.Enso_File.Enso_File
import project.Data.Enso_Cloud.Utils import project.Data.Enso_Cloud.Utils
import project.Data.Json.JS_Object import project.Data.Json.JS_Object
import project.Data.Text.Text import project.Data.Text.Text
@ -15,8 +15,8 @@ import project.Network.HTTP.Request_Body.Request_Body
import project.Nothing.Nothing import project.Nothing.Nothing
import project.Runtime.Context import project.Runtime.Context
from project.Data.Boolean import Boolean, False, True from project.Data.Boolean import Boolean, False, True
from project.Data.Text.Extensions import all
from project.Data.Enso_Cloud.Enso_File import list_assets from project.Data.Enso_Cloud.Enso_File import list_assets
from project.Data.Text.Extensions import all
polyglot java import org.enso.base.enso_cloud.EnsoSecretHelper polyglot java import org.enso.base.enso_cloud.EnsoSecretHelper
polyglot java import org.enso.base.enso_cloud.HideableValue polyglot java import org.enso.base.enso_cloud.HideableValue
@ -165,7 +165,7 @@ Derived_Secret_Value.from (that : Text) = Derived_Secret_Value.Plain_Text that
Derived_Secret_Value.from (that : Enso_Secret) = Derived_Secret_Value.Secret_Value that Derived_Secret_Value.from (that : Enso_Secret) = Derived_Secret_Value.Secret_Value that
## PRIVATE ## PRIVATE
as_hideable_value : Text | Enso_Secret | Nothing -> HideableValue as_hideable_value : Text | Enso_Secret | Derived_Secret_Value -> HideableValue
as_hideable_value (value : Text | Enso_Secret | Derived_Secret_Value) = case value of as_hideable_value (value : Text | Enso_Secret | Derived_Secret_Value) = case value of
text : Text -> HideableValue.PlainValue.new text text : Text -> HideableValue.PlainValue.new text
secret : Enso_Secret -> HideableValue.SecretValue.new secret.id secret : Enso_Secret -> HideableValue.SecretValue.new secret.id

View File

@ -1,6 +1,7 @@
private private
import project.Data.Enso_Cloud.Enso_Secret.Enso_Secret
import project.Data.Enso_Cloud.Enso_Secret.Derived_Secret_Value import project.Data.Enso_Cloud.Enso_Secret.Derived_Secret_Value
import project.Data.Enso_Cloud.Enso_Secret.Enso_Secret
import project.Data.Enso_Cloud.Errors.Not_Logged_In import project.Data.Enso_Cloud.Errors.Not_Logged_In
import project.Data.Pair.Pair import project.Data.Pair.Pair
import project.Data.Text.Text import project.Data.Text.Text

View File

@ -21,25 +21,25 @@ polyglot java import org.enso.base.Regex_Utils
type Filter_Condition type Filter_Condition
## Is less than a value (or another column, in case of Table operations)? ## Is less than a value (or another column, in case of Table operations)?
Less than:Any Less than:Any action:Filter_Action=Filter_Action.Keep
## Is less than or equal to a value (or another column, in case of Table operations)? ## Is less than or equal to a value (or another column, in case of Table operations)?
Equal_Or_Less than:Any Equal_Or_Less than:Any action:Filter_Action=Filter_Action.Keep
## Is equal to a value (or another column, in case of Table operations)? ## Is equal to a value (or another column, in case of Table operations)?
Equal to:Any Equal to:Any action:Filter_Action=Filter_Action.Keep
## Is greater than or equal to a value (or another column, in case of Table operations)? ## Is greater than or equal to a value (or another column, in case of Table operations)?
Equal_Or_Greater than:Any Equal_Or_Greater than:Any action:Filter_Action=Filter_Action.Keep
## Is greater than a value (or another column, in case of Table operations)? ## Is greater than a value (or another column, in case of Table operations)?
Greater than:Any Greater than:Any action:Filter_Action=Filter_Action.Keep
## Is not equal to a value (or another column, in case of Table operations)? ## Is not equal to a value (or another column, in case of Table operations)?
Not_Equal to:Any Not_Equal to:Any action:Filter_Action=Filter_Action.Keep
## Is between (inclusive) two values (or columns, in case of Table operations)? ## Is between (inclusive) two values (or columns, in case of Table operations)?
Between lower:Any upper:Any Between lower:Any upper:Any action:Filter_Action=Filter_Action.Keep
## Is equal to another value, ignoring case (Text only)? ## Is equal to another value, ignoring case (Text only)?
@ -54,7 +54,7 @@ type Filter_Condition
This ensures that different ways of expressing the same character in This ensures that different ways of expressing the same character in
the underlying binary representation are considered equal. the underlying binary representation are considered equal.
@locale Locale.default_widget @locale Locale.default_widget
Equal_Ignore_Case (to : Text | Any) (locale:Locale=Locale.default) Equal_Ignore_Case (to : Text | Any) (locale:Locale=Locale.default) action:Filter_Action=Filter_Action.Keep
## Does the value start with a prefix (Text only)? ## Does the value start with a prefix (Text only)?
@ -62,7 +62,7 @@ type Filter_Condition
It accepts a Text value to check if the value contains it. In case of It accepts a Text value to check if the value contains it. In case of
Table operations, it can accept another column - then the corresponding Table operations, it can accept another column - then the corresponding
values from the source column and the provided column are checked. values from the source column and the provided column are checked.
Starts_With (prefix : Text | Any) (case_sensitivity:Case_Sensitivity=Case_Sensitivity.Default) Starts_With (prefix : Text | Any) (case_sensitivity:Case_Sensitivity=Case_Sensitivity.Default) action:Filter_Action=Filter_Action.Keep
## Does the value end with a suffix (Text only)? ## Does the value end with a suffix (Text only)?
@ -70,7 +70,7 @@ type Filter_Condition
It accepts a Text value to check if the value contains it. In case of It accepts a Text value to check if the value contains it. In case of
Table operations, it can accept another column - then the corresponding Table operations, it can accept another column - then the corresponding
values from the source column and the provided column are checked. values from the source column and the provided column are checked.
Ends_With (suffix : Text | Any) (case_sensitivity:Case_Sensitivity=Case_Sensitivity.Default) Ends_With (suffix : Text | Any) (case_sensitivity:Case_Sensitivity=Case_Sensitivity.Default) action:Filter_Action=Filter_Action.Keep
## Does the value contain the substring (Text only)? ## Does the value contain the substring (Text only)?
@ -78,44 +78,36 @@ type Filter_Condition
It accepts a Text value to check if the value contains it. In case of It accepts a Text value to check if the value contains it. In case of
Table operations, it can accept another column - then the corresponding Table operations, it can accept another column - then the corresponding
values from the source column and the provided column are checked. values from the source column and the provided column are checked.
Contains (substring : Text | Any) (case_sensitivity:Case_Sensitivity=Case_Sensitivity.Default) Contains (substring : Text | Any) (case_sensitivity:Case_Sensitivity=Case_Sensitivity.Default) action:Filter_Action=Filter_Action.Keep
## Is the substring not present in the value (Text only)?
? Table Operations
It accepts a Text value to check if the value contains it. In case of
Table operations, it can accept another column - then the corresponding
values from the source column and the provided column are checked.
Not_Contains (substring : Text | Any) (case_sensitivity:Case_Sensitivity=Case_Sensitivity.Default)
## Is equal to Nothing? ## Is equal to Nothing?
Is_Nothing Is_Nothing action:Filter_Action=Filter_Action.Keep
## Is not equal to Nothing? ## Is not equal to Nothing?
Not_Nothing Not_Nothing action:Filter_Action=Filter_Action.Keep
## Is the value a NaN (Number only)? ## Is the value a NaN (Number only)?
Is_Nan Is_Nan action:Filter_Action=Filter_Action.Keep
## Is the value infinite (Number only)? ## Is the value infinite (Number only)?
Is_Infinite Is_Infinite action:Filter_Action=Filter_Action.Keep
## Is the value finite (Number only)? ## Is the value finite (Number only)?
Finite numbers are ones that are not infinite nor NaN. Finite numbers are ones that are not infinite nor NaN.
Is_Finite Is_Finite action:Filter_Action=Filter_Action.Keep
## Is the value equal to True (Boolean only)? ## Is the value equal to True (Boolean only)?
Is_True Is_True action:Filter_Action=Filter_Action.Keep
## Is the value equal to False (Boolean only)? ## Is the value equal to False (Boolean only)?
Is_False Is_False action:Filter_Action=Filter_Action.Keep
## Is equal to "" or Nothing (Text only)? ## Is equal to "" or Nothing (Text only)?
Is_Empty Is_Empty action:Filter_Action=Filter_Action.Keep
## Is not equal to "" and Nothing (Text only)? ## Is not equal to "" and Nothing (Text only)?
Not_Empty Not_Empty action:Filter_Action=Filter_Action.Keep
## Does the value match the SQL pattern (Text only)? ## Does the value match the SQL pattern (Text only)?
@ -134,26 +126,7 @@ type Filter_Condition
Due to this limitation, Unicode normalization has been disabled for Due to this limitation, Unicode normalization has been disabled for
this function, so beware that some equivalent graphemes like 'ś' and this function, so beware that some equivalent graphemes like 'ś' and
's\u0301' will not be matched. 's\u0301' will not be matched.
Like (pattern : Text | Any) Like (pattern : Text | Any) action:Filter_Action=Filter_Action.Keep
## Does the value not match the SQL pattern (Text only)?
The pattern is interpreted according to the standard SQL convention:
- the `%` character matches any sequence of characters,
- the `_` character matches any single character,
- any other character is matched literally.
? Table Operations
It accepts a Text value to check if the value contains it. In case of
Table operations, it can accept another column - then the corresponding
values from the source column and the provided column are checked.
! Known Limitations.
The Truffle regex engine does not transparently handle normalization.
Due to this limitation, Unicode normalization has been disabled for
this function, so beware that some equivalent graphemes like 'ś' and
's\u0301' will not be matched.
Not_Like pattern:Text|Any
## Is the value contained in `values`? ## Is the value contained in `values`?
@ -167,21 +140,7 @@ type Filter_Condition
Using Columns can be particularly useful for Database operations, as Using Columns can be particularly useful for Database operations, as
uploading a temporary table and using its column for an `Is_In` check uploading a temporary table and using its column for an `Is_In` check
will likely be faster than using the vector directly. will likely be faster than using the vector directly.
Is_In values:Vector|Any Is_In values:Vector|Any action:Filter_Action=Filter_Action.Keep
## Is the value not contained in `values`?
? Table Operations
It accepts a `Vector` of values. In case of Table operations, it can
also accept another column - then it acts as if `column.to_vector` was
passed - i.e. every element of the original table's column is checked
if it is contained in the provided column. The columns can have
different lengths.
Using Columns can be particularly useful for Database operations, as
uploading a temporary table and using its column for an `Not_In` check
will likely be faster than using the vector directly.
Not_In values:(Vector | Any)
## Converts a `Filter_Condition` condition into a predicate taking an ## Converts a `Filter_Condition` condition into a predicate taking an
element and returning a value indicating whether the element should be element and returning a value indicating whether the element should be
@ -190,57 +149,45 @@ type Filter_Condition
The predicate can handle `Nothing` values in all cases. However, the The predicate can handle `Nothing` values in all cases. However, the
predicate will raise an error if the value is not of the expected type. predicate will raise an error if the value is not of the expected type.
to_predicate : (Any -> Boolean) to_predicate : (Any -> Boolean)
to_predicate self = case self of to_predicate self =
base = case self of
# == does not need special handling for Nothing # == does not need special handling for Nothing
Equal value -> ==value Equal value _ -> ==value
Not_Equal value -> !=value Not_Equal value _ -> !=value
Less value -> handle_nothing (<value) Less value _ -> handle_nothing (<value)
Equal_Or_Less value -> handle_nothing (<=value) Equal_Or_Less value _ -> handle_nothing (<=value)
Equal_Or_Greater value -> handle_nothing (>=value) Equal_Or_Greater value _ -> handle_nothing (>=value)
Greater value -> handle_nothing (>value) Greater value _ -> handle_nothing (>value)
Between lower upper -> handle_nothing <| elem-> Between lower upper _ -> handle_nothing <| elem->
(lower <= elem) && (elem <= upper) (lower <= elem) && (elem <= upper)
Equal_Ignore_Case value locale -> Equal_Ignore_Case value locale _ ->
handle_nothing <| txt-> (txt : Text).equals_ignore_case value locale handle_nothing <| txt-> (txt : Text).equals_ignore_case value locale
Starts_With prefix case_sensitivity -> Starts_With prefix case_sensitivity _ ->
handle_nothing <| txt-> (txt : Text).starts_with prefix case_sensitivity handle_nothing <| txt-> (txt : Text).starts_with prefix case_sensitivity
Ends_With suffix case_sensitivity -> Ends_With suffix case_sensitivity _ ->
handle_nothing <| txt-> (txt : Text).ends_with suffix case_sensitivity handle_nothing <| txt-> (txt : Text).ends_with suffix case_sensitivity
Contains substring case_sensitivity -> Contains substring case_sensitivity _ ->
handle_nothing <| txt-> (txt : Text).contains substring case_sensitivity handle_nothing <| txt-> (txt : Text).contains substring case_sensitivity
Not_Contains substring case_sensitivity -> Is_Nothing _ -> elem -> case elem of
handle_nothing <| txt-> (txt : Text).contains substring case_sensitivity . not
Is_Nothing -> elem -> case elem of
Nothing -> True Nothing -> True
_ -> False _ -> False
Not_Nothing -> elem -> case elem of Not_Nothing _ -> elem -> case elem of
Nothing -> False Nothing -> False
_ -> True _ -> True
Is_Nan -> handle_nothing x-> (x:Number).is_nan Is_Nan _ -> handle_nothing x-> (x:Number).is_nan
Is_Infinite -> handle_nothing x-> (x:Number).is_infinite Is_Infinite _ -> handle_nothing x-> (x:Number).is_infinite
Is_Finite -> handle_nothing x-> (x:Number).is_finite Is_Finite _ -> handle_nothing x-> (x:Number).is_finite
Is_True -> ==True Is_True _ -> handle_nothing b-> (b:Boolean)==True
Is_False -> ==False Is_False _ -> handle_nothing b-> (b:Boolean)==False
Is_Empty -> elem -> case elem of Is_Empty _ -> elem-> elem.is_nothing || (elem : Text)==""
Nothing -> True Not_Empty _ -> handle_nothing elem-> (elem : Text)!=""
"" -> True Like sql_pattern _ ->
_ -> False
Not_Empty -> elem -> case elem of
Nothing -> False
"" -> False
_ -> True
Like sql_pattern ->
regex = sql_like_to_regex sql_pattern regex = sql_like_to_regex sql_pattern
handle_nothing <| regex.matches handle_nothing <| regex.matches
Not_Like sql_pattern -> Is_In values _ ->
regex = sql_like_to_regex sql_pattern
handle_nothing <| elem-> regex.matches elem . not
Is_In values ->
set = Set.from_vector values set = Set.from_vector values
set.contains set.contains
Not_In values -> if self.action == Filter_Action.Keep then base else v -> (base v).not
set = Set.from_vector values
elem-> set.contains elem . not
## PRIVATE ## PRIVATE
Convert to a display representation of this Filter_Condition. Convert to a display representation of this Filter_Condition.
@ -250,34 +197,31 @@ type Filter_Condition
if case_sensitivity == Case_Sensitivity.Default then "" else " Case " + case_sensitivity.to_display_text if case_sensitivity == Case_Sensitivity.Default then "" else " Case " + case_sensitivity.to_display_text
condition = case self of condition = case self of
Less value -> "<" + value.to_display_text Less value _ -> "<" + value.to_display_text
Equal_Or_Less value -> "<=" + value.to_display_text Equal_Or_Less value _ -> "<=" + value.to_display_text
Equal value -> "==" + value.to_display_text Equal value _ -> "==" + value.to_display_text
Equal_Or_Greater value -> ">=" + value.to_display_text Equal_Or_Greater value _ -> ">=" + value.to_display_text
Greater value -> ">" + value.to_display_text Greater value _ -> ">" + value.to_display_text
Not_Equal value -> "!=" + value.to_display_text Not_Equal value _ -> "!=" + value.to_display_text
Between lower upper -> "Between " + lower.to_display_text + " And " + upper.to_display_text Between lower upper _ -> "Between " + lower.to_display_text + " And " + upper.to_display_text
Equal_Ignore_Case value locale -> Equal_Ignore_Case value locale _ ->
suffix = if locale == Locale.default then "" else " (within locale " + locale.to_display_text + ")" suffix = if locale == Locale.default then "" else " (within locale " + locale.to_display_text + ")"
"Equal Ignore Case " + value.to_display_text + suffix "Equal Ignore Case " + value.to_display_text + suffix
Starts_With prefix case_sensitivity -> "Starts With " + prefix.to_display_text + (render_case case_sensitivity) Starts_With prefix case_sensitivity _ -> "Starts With " + prefix.to_display_text + (render_case case_sensitivity)
Ends_With suffix case_sensitivity -> "Ends With " + suffix.to_display_text + (render_case case_sensitivity) Ends_With suffix case_sensitivity _ -> "Ends With " + suffix.to_display_text + (render_case case_sensitivity)
Contains substring case_sensitivity -> "Contains " + substring.to_display_text + (render_case case_sensitivity) Contains substring case_sensitivity _ -> "Contains " + substring.to_display_text + (render_case case_sensitivity)
Not_Contains substring case_sensitivity -> "not Contains " + substring.to_display_text + (render_case case_sensitivity) Is_Nothing _ -> "is Nothing"
Is_Nothing -> "is Nothing" Not_Nothing _ -> "is not Nothing"
Not_Nothing -> "is not Nothing" Is_Nan _ -> "is NaN"
Is_Nan -> "is NaN" Is_Infinite _ -> "is Infinite"
Is_Infinite -> "is Infinite" Is_Finite _ -> "is Finite"
Is_Finite -> "is Finite" Is_True _ -> "is True"
Is_True -> "is True" Is_False _ -> "is False"
Is_False -> "is False" Is_Empty _ -> "is Empty"
Is_Empty -> "is Empty" Not_Empty _ -> "is not Empty"
Not_Empty -> "is not Empty" Like sql_pattern _ -> "Like " + sql_pattern.to_display_text
Like sql_pattern -> "Like " + sql_pattern.to_display_text Is_In values _ -> "is in " + values.to_display_text
Not_Like sql_pattern -> "not Like " + sql_pattern.to_display_text "Filter Condition: " + condition + (if self.action == Filter_Action.Keep then "" else " (Remove)")
Is_In values -> "is in " + values.to_display_text
Not_In values -> "is not in " + values.to_display_text
"Filter Condition: " + condition
## PRIVATE ## PRIVATE
Creates a Single_Choice Widget for delimiters. Creates a Single_Choice Widget for delimiters.
@ -309,11 +253,8 @@ type Filter_Condition
options_builder.append "Starts_With" options_builder.append "Starts_With"
options_builder.append "Ends_With" options_builder.append "Ends_With"
options_builder.append "Contains" options_builder.append "Contains"
options_builder.append "Not_Contains"
options_builder.append "Like" options_builder.append "Like"
options_builder.append "Not_Like"
options_builder.append "Is_In" options_builder.append "Is_In"
options_builder.append "Not_In"
options = options_builder.to_vector.map constructor_name-> options = options_builder.to_vector.map constructor_name->
name = constructor_name.replace "_" " " name = constructor_name.replace "_" " "
@ -321,6 +262,13 @@ type Filter_Condition
[name, code] [name, code]
make_single_choice options make_single_choice options
## Specifies the action of a Filter_Condition.
type Filter_Action
## Items matching the filter are kept.
Keep
## Items matching the filter are removed.
Remove
## PRIVATE ## PRIVATE
sql_like_to_regex sql_pattern = sql_like_to_regex sql_pattern =

View File

@ -22,14 +22,19 @@ from project.Metadata.Widget import Single_Choice
polyglot java import com.fasterxml.jackson.core.JsonProcessingException polyglot java import com.fasterxml.jackson.core.JsonProcessingException
polyglot java import com.fasterxml.jackson.databind.JsonNode polyglot java import com.fasterxml.jackson.databind.JsonNode
polyglot java import com.fasterxml.jackson.databind.ObjectMapper
polyglot java import com.fasterxml.jackson.databind.node.ArrayNode polyglot java import com.fasterxml.jackson.databind.node.ArrayNode
polyglot java import com.fasterxml.jackson.databind.node.JsonNodeType polyglot java import com.fasterxml.jackson.databind.node.JsonNodeType
polyglot java import com.fasterxml.jackson.databind.node.ObjectNode polyglot java import com.fasterxml.jackson.databind.node.ObjectNode
polyglot java import com.fasterxml.jackson.databind.ObjectMapper
## PRIVATE ## PRIVATE
Jackson-based JSON Parser Jackson-based JSON Parser
type Java_Json type Java_Json
## ALIAS from text
GROUP Conversions
Parse a Text value into a `Jackson_Object` or an Enso primitive value
(like `Text`, `Number`, `Boolean`, `Nothing`), or a `Vector` of values.
parse : Text -> Nothing | Boolean | Number | Text | Vector | Jackson_Object parse : Text -> Nothing | Boolean | Number | Text | Vector | Jackson_Object
parse text:Text = parse text:Text =
error_handler js_exception = error_handler js_exception =
@ -60,6 +65,8 @@ read_json_array node =
## PRIVATE ## PRIVATE
type Jackson_Object type Jackson_Object
## PRIVATE
Creates a new `Jackson_Object` from an `ObjectNode`.
new : ObjectNode -> Jackson_Object new : ObjectNode -> Jackson_Object
new object_node = new object_node =
make_field_names object = make_field_names object =

View File

@ -279,7 +279,7 @@ type JS_Object
obj.set_value "foo" "asdf" obj.set_value "foo" "asdf"
# => {"foo":"asdf","baz":"quux"} # => {"foo":"asdf","baz":"quux"}
set_value : Text -> Any -> JS_Object set_value : Text -> Any -> JS_Object
set_value self:JS_Object key:Text value = JS_Object.Value (set_value self.js_object key value.to_js_object) set_value self key:Text value = JS_Object.Value (set_value self.js_object key value.to_js_object)
## PRIVATE ## PRIVATE
type JS_Object_Comparator type JS_Object_Comparator

View File

@ -1,4 +1,5 @@
import project.Any.Any import project.Any.Any
import project.Data.Filter_Condition.Filter_Action
import project.Data.Filter_Condition.Filter_Condition import project.Data.Filter_Condition.Filter_Condition
import project.Data.Text.Case.Case import project.Data.Text.Case.Case
import project.Data.Text.Text import project.Data.Text.Text
@ -438,7 +439,7 @@ type Locale
predefined_locale_fields = predefined_locale_fields =
locale_meta = Meta.meta Locale locale_meta = Meta.meta Locale
remove_us = locale_meta.methods + ["Value", "new", "default", "from_language_tag", "from_java", "predefined_locale_fields", "default_widget", "widget_options"] remove_us = locale_meta.methods + ["Value", "new", "default", "from_language_tag", "from_java", "predefined_locale_fields", "default_widget", "widget_options"]
Meta.Type.Value (Meta.type_of locale_meta.value) . methods . filter (Filter_Condition.Not_In remove_us) . sort Meta.Type.Value (Meta.type_of locale_meta.value) . methods . filter (Filter_Condition.Is_In remove_us Filter_Action.Remove) . sort
## PRIVATE ## PRIVATE
widget_options : Vector Option widget_options : Vector Option

View File

@ -8,11 +8,10 @@ import project.Errors.Common.Incomparable_Values
import project.Errors.Common.Unsupported_Argument_Types import project.Errors.Common.Unsupported_Argument_Types
import project.Errors.Illegal_Argument.Illegal_Argument import project.Errors.Illegal_Argument.Illegal_Argument
import project.Function.Function import project.Function.Function
import project.Internal.Rounding_Helpers
import project.Nothing.Nothing import project.Nothing.Nothing
import project.Panic.Panic import project.Panic.Panic
from project.Data.Boolean import Boolean, False, True from project.Data.Boolean import Boolean, False, True
import project.Internal.Rounding_Helpers
from project.Internal.Number_Builtins import all from project.Internal.Number_Builtins import all
polyglot java import java.lang.Double polyglot java import java.lang.Double

View File

@ -184,9 +184,8 @@ type Range
(0.up_to 7).filter (Filter_Condition.Greater than=3) (0.up_to 7).filter (Filter_Condition.Greater than=3)
@filter range_default_filter_condition_widget @filter range_default_filter_condition_widget
filter : (Filter_Condition | (Integer -> Boolean)) -> Vector Integer filter : (Filter_Condition | (Integer -> Boolean)) -> Vector Integer
filter self filter = case filter of filter self filter =
_ : Filter_Condition -> self.filter filter.to_predicate predicate = unify_condition_or_predicate filter
predicate : Function ->
builder = self.fold Vector.new_builder builder-> elem-> builder = self.fold Vector.new_builder builder-> elem->
if predicate elem then builder.append elem else builder if predicate elem then builder.append elem else builder
builder.to_vector builder.to_vector

View File

@ -308,7 +308,7 @@ type Date_Time
from Standard.Base import Date_Time from Standard.Base import Date_Time
example_from_unix_epoch = Date_Time.from_unix_epoch_milliseconds 1601587200000 example_from_unix_epoch = Date_Time.from_unix_epoch_milliseconds 1601587200000
from_unix_epoch_milliseconds : Integer -> Time_Zone -> Date_Time from_unix_epoch_milliseconds : Integer -> Date_Time
from_unix_epoch_milliseconds milliseconds:Integer = from_unix_epoch_milliseconds milliseconds:Integer =
unix_epoch_start + Duration.new milliseconds=milliseconds unix_epoch_start + Duration.new milliseconds=milliseconds

View File

@ -5,8 +5,8 @@ import project.Meta
import project.Nothing.Nothing import project.Nothing.Nothing
import project.Panic.Panic import project.Panic.Panic
import project.System.File.File import project.System.File.File
import project.System.File_Format_Metadata.File_Format_Metadata
import project.System.File_Format.File_Format import project.System.File_Format.File_Format
import project.System.File_Format_Metadata.File_Format_Metadata
polyglot java import java.io.FileNotFoundException polyglot java import java.io.FileNotFoundException
polyglot java import java.io.IOException polyglot java import java.io.IOException

View File

@ -5,6 +5,7 @@ import project.Data.Boolean
import project.Data.Enso_Cloud.Enso_File.Enso_File import project.Data.Enso_Cloud.Enso_File.Enso_File
import project.Data.Enso_Cloud.Enso_Secret.Enso_Secret import project.Data.Enso_Cloud.Enso_Secret.Enso_Secret
import project.Data.Enso_Cloud.Enso_User.Enso_User import project.Data.Enso_Cloud.Enso_User.Enso_User
import project.Data.Filter_Condition.Filter_Action
import project.Data.Filter_Condition.Filter_Condition import project.Data.Filter_Condition.Filter_Condition
import project.Data.Index_Sub_Range.Index_Sub_Range import project.Data.Index_Sub_Range.Index_Sub_Range
import project.Data.Interval.Bound import project.Data.Interval.Bound
@ -102,6 +103,7 @@ export project.Data.Array.Array
export project.Data.Enso_Cloud.Enso_File.Enso_File export project.Data.Enso_Cloud.Enso_File.Enso_File
export project.Data.Enso_Cloud.Enso_Secret.Enso_Secret export project.Data.Enso_Cloud.Enso_Secret.Enso_Secret
export project.Data.Enso_Cloud.Enso_User.Enso_User export project.Data.Enso_Cloud.Enso_User.Enso_User
export project.Data.Filter_Condition.Filter_Action
export project.Data.Filter_Condition.Filter_Condition export project.Data.Filter_Condition.Filter_Condition
export project.Data.Index_Sub_Range.Index_Sub_Range export project.Data.Index_Sub_Range.Index_Sub_Range
export project.Data.Interval.Bound export project.Data.Interval.Bound

View File

@ -1,13 +1,13 @@
import project.Data.Enso_Cloud.Enso_Secret.Enso_Secret
import project.Data.Enso_Cloud.Enso_Secret.Derived_Secret_Value import project.Data.Enso_Cloud.Enso_Secret.Derived_Secret_Value
import project.Data.Enso_Cloud.Enso_Secret.Enso_Secret
import project.Data.Enso_Cloud.Utils as Cloud_Utils import project.Data.Enso_Cloud.Utils as Cloud_Utils
import project.Data.Numbers.Integer import project.Data.Numbers.Integer
import project.Data.Text.Encoding.Encoding import project.Data.Text.Encoding.Encoding
import project.Data.Text.Text import project.Data.Text.Text
import project.Nothing.Nothing import project.Nothing.Nothing
from project.Data.Boolean import Boolean, False, True from project.Data.Boolean import Boolean, False, True
from project.Data.Ordering import all
from project.Data.Enso_Cloud.Enso_Secret import as_hideable_value from project.Data.Enso_Cloud.Enso_Secret import as_hideable_value
from project.Data.Ordering import all
from project.Data.Text.Extensions import all from project.Data.Text.Extensions import all
polyglot java import org.graalvm.collections.Pair as Java_Pair polyglot java import org.graalvm.collections.Pair as Java_Pair
@ -22,7 +22,7 @@ type Header
- value: The header value. - value: The header value.
Value name:Text value:(Text|Enso_Secret|Derived_Secret_Value) Value name:Text value:(Text|Enso_Secret|Derived_Secret_Value)
## ALIAS Build a Header ## ALIAS build a header
Create a new Header. Create a new Header.
@ -36,7 +36,7 @@ type Header
import Standard.Base.Network.HTTP.Header.Header import Standard.Base.Network.HTTP.Header.Header
example_new = Header.new "My_Header" "my header's value" example_new = Header.new "My_Header" "my header's value"
new : Text -> Text | Enso_Secret -> Header new : Text -> Text | Enso_Secret | Derived_Secret_Value -> Header
new name:Text value:(Text | Enso_Secret | Derived_Secret_Value) = Header.Value name value new name:Text value:(Text | Enso_Secret | Derived_Secret_Value) = Header.Value name value
## Create an "Accept" header. ## Create an "Accept" header.
@ -64,7 +64,7 @@ type Header
accept_all : Header accept_all : Header
accept_all = Header.accept "*/*" accept_all = Header.accept "*/*"
## ALIAS Build an Auth Header ## ALIAS build an auth header
Create an "Authorization" header. Create an "Authorization" header.
@ -102,7 +102,7 @@ type Header
Arguments: Arguments:
- token: The token. - token: The token.
authorization_bearer : Text -> Header authorization_bearer : Text | Enso_Secret | Derived_Secret_Value -> Header
authorization_bearer (token : Text | Enso_Secret | Derived_Secret_Value) = authorization_bearer (token : Text | Enso_Secret | Derived_Secret_Value) =
value = ((Derived_Secret_Value.from "Bearer ") + (Derived_Secret_Value.from token)) value = ((Derived_Secret_Value.from "Bearer ") + (Derived_Secret_Value.from token))
Header.authorization value.simplify Header.authorization value.simplify

View File

@ -49,7 +49,7 @@ type Response_Body
- stream: The body of the response as an InputStream. - stream: The body of the response as an InputStream.
- metadata: File format metadata associated with the response. - metadata: File format metadata associated with the response.
- uri: The URI of the response. - uri: The URI of the response.
new : InputStream -> Text -> URI -> Response_Body new : InputStream -> File_Format_Metadata -> URI -> Response_Body
new stream (metadata : File_Format_Metadata) (uri : URI) = new stream (metadata : File_Format_Metadata) (uri : URI) =
input_stream = Input_Stream.new stream (HTTP_Error.handle_java_exceptions uri) input_stream = Input_Stream.new stream (HTTP_Error.handle_java_exceptions uri)
Response_Body.Raw_Stream input_stream metadata uri Response_Body.Raw_Stream input_stream metadata uri

View File

@ -155,7 +155,7 @@ type Random
import Standard.Base.Random.Random import Standard.Base.Random.Random
d = Random.date (Date.new 2023 03 01) (Date.new 2023 10 15) d = Random.date (Date.new 2023 03 01) (Date.new 2023 10 15)
date : Date -> Date -> Boolean -> Date date : Date -> Date -> Date
date min:Date max:Date = Random_Generator.global_random_generator.date min max date min:Date max:Date = Random_Generator.global_random_generator.date min max
## GROUP Random ## GROUP Random
@ -297,7 +297,7 @@ type Random_Generator
Vector.from_polyglot_array array Vector.from_polyglot_array array
## PRIVATE ## PRIVATE
date : Date -> Date -> Boolean -> Date date : Date -> Date -> Date
date self start_date:Date end_date:Date = date self start_date:Date end_date:Date =
date_range = start_date.up_to end_date include_end=True date_range = start_date.up_to end_date include_end=True
date_range.at (self.integer 0 (date_range.length - 1)) date_range.at (self.integer 0 (date_range.length - 1))

View File

@ -14,11 +14,11 @@ from project.Data.Range.Extensions import all
from project.Data.Text.Extensions import all from project.Data.Text.Extensions import all
from project.Logging import all from project.Logging import all
polyglot java import java.io.File as Java_File
polyglot java import java.nio.charset.Charset
polyglot java import org.enso.base.Array_Utils polyglot java import org.enso.base.Array_Utils
polyglot java import org.enso.base.arrays.LongArrayList polyglot java import org.enso.base.arrays.LongArrayList
polyglot java import org.enso.base.FileLineReader polyglot java import org.enso.base.FileLineReader
polyglot java import java.io.File as Java_File
polyglot java import java.nio.charset.Charset
type File_By_Line type File_By_Line
## Creates a new File_By_Line object. ## Creates a new File_By_Line object.
@ -27,7 +27,7 @@ type File_By_Line
- file: The file to read. - file: The file to read.
- encoding: The encoding to use when reading the file (defaults to UTF 8). - encoding: The encoding to use when reading the file (defaults to UTF 8).
- offset: The position within the file to read from (defaults to first byte). - offset: The position within the file to read from (defaults to first byte).
new : File->Encoding->File_By_Line new : File -> Encoding -> Integer -> File_By_Line
new file:File encoding:Encoding=Encoding.utf_8 offset:Integer=0 = new file:File encoding:Encoding=Encoding.utf_8 offset:Integer=0 =
create_row_map = create_row_map =
row_map = LongArrayList.new row_map = LongArrayList.new

View File

@ -180,7 +180,7 @@ type Connection
True -> result True -> result
False -> False ->
hidden_tables = self.hidden_table_registry.list_hidden_tables hidden_tables = self.hidden_table_registry.list_hidden_tables
result.filter "Name" (Filter_Condition.Not_In hidden_tables) result.filter "Name" (Filter_Condition.Is_In hidden_tables Filter_Action.Remove)
## PRIVATE ## PRIVATE
Checks if the table with the given name exists in the database. Checks if the table with the given name exists in the database.

View File

@ -147,7 +147,7 @@ type Column
import Standard.Examples import Standard.Examples
example_at = Examples.integer_column.get 0 -1 example_at = Examples.integer_column.get 0 -1
get : Integer -> (Any | Nothing) get : Integer -> Any -> Any | Nothing
get self (index : Integer) (~default=Nothing) = get self (index : Integer) (~default=Nothing) =
self.read index+1 . get index default self.read index+1 . get index default

View File

@ -32,9 +32,9 @@ from project.Internal.Column_Format import all
from project.Internal.Java_Exports import make_date_builder_adapter, make_string_builder from project.Internal.Java_Exports import make_date_builder_adapter, make_string_builder
polyglot java import org.enso.base.Time_Utils polyglot java import org.enso.base.Time_Utils
polyglot java import org.enso.table.data.mask.OrderMask
polyglot java import org.enso.table.data.column.operation.cast.CastProblemAggregator polyglot java import org.enso.table.data.column.operation.cast.CastProblemAggregator
polyglot java import org.enso.table.data.column.storage.Storage as Java_Storage polyglot java import org.enso.table.data.column.storage.Storage as Java_Storage
polyglot java import org.enso.table.data.mask.OrderMask
polyglot java import org.enso.table.data.table.Column as Java_Column polyglot java import org.enso.table.data.table.Column as Java_Column
polyglot java import org.enso.table.error.ValueTypeMismatchException polyglot java import org.enso.table.error.ValueTypeMismatchException
polyglot java import org.enso.table.operations.OrderBuilder polyglot java import org.enso.table.operations.OrderBuilder
@ -1063,7 +1063,11 @@ type Column
internal_is_empty : Column internal_is_empty : Column
internal_is_empty self = internal_is_empty self =
new_name = naming_helper.concat [naming_helper.to_expression_text self, "is empty"] new_name = naming_helper.concat [naming_helper.to_expression_text self, "is empty"]
run_vectorized_unary_op self Java_Storage.Maps.IS_EMPTY new_name fallback_fn=Filter_Condition.Is_Empty.to_predicate expected_result_type=Value_Type.Boolean skip_nulls=False fallback x = case x of
_ : Text -> x == ""
Nothing -> True
_ -> False
run_vectorized_unary_op self Java_Storage.Maps.IS_EMPTY new_name fallback_fn=fallback expected_result_type=Value_Type.Boolean skip_nulls=False
## GROUP Standard.Base.Logical ## GROUP Standard.Base.Logical
Returns a column of booleans, with `True` items at the positions where Returns a column of booleans, with `True` items at the positions where
@ -2072,7 +2076,7 @@ type Column
import Standard.Examples import Standard.Examples
example_at = Examples.integer_column.get 0 -1 example_at = Examples.integer_column.get 0 -1
get : Integer -> (Any | Nothing) get : Integer -> Any -> Any | Nothing
get self (index : Integer) (~default=Nothing) = get self (index : Integer) (~default=Nothing) =
valid_index = (index >= 0) && (index < self.length) valid_index = (index >= 0) && (index < self.length)
if valid_index.not then default else if valid_index.not then default else

View File

@ -7,3 +7,6 @@ type Column_Ref
## Reference to a column by index in a table. ## Reference to a column by index in a table.
Index index:Integer Index index:Integer
## Representation of an expression derived in a table.
Expression expression:Text

View File

@ -1,6 +1,6 @@
from Standard.Base import all from Standard.Base import all
import Standard.Base.Errors.Illegal_Argument.Illegal_Argument
import Standard.Base.Data.Java_Json.Jackson_Object import Standard.Base.Data.Java_Json.Jackson_Object
import Standard.Base.Errors.Illegal_Argument.Illegal_Argument
## PRIVATE ## PRIVATE
A special type describing how to convert an object into a set of table A special type describing how to convert an object into a set of table

View File

@ -141,7 +141,7 @@ type Delimited_Format
## Creates a clone of this with a changed line ending style. ## Creates a clone of this with a changed line ending style.
with_line_endings : Line_Ending_Style | Infer -> Delimited_Format with_line_endings : Line_Ending_Style | Infer -> Delimited_Format
with_line_endings self (line_endings : Line_Ending_Style | Infer)=Infer = with_line_endings self (line_endings : Line_Ending_Style | Infer = Infer) =
self.clone line_endings=line_endings self.clone line_endings=line_endings
## Creates a clone of this with comment parsing enabled. ## Creates a clone of this with comment parsing enabled.

View File

@ -7,7 +7,7 @@ import project.Data.Column_Ref.Column_Ref
import project.Data.Expression.Expression_Error import project.Data.Expression.Expression_Error
import project.Data.Set_Mode.Set_Mode import project.Data.Set_Mode.Set_Mode
import project.Data.Table.Table import project.Data.Table.Table
from project.Errors import Existing_Column, Missing_Column, No_Such_Column from project.Errors import Existing_Column, Invalid_Value_Type, Missing_Column, No_Such_Column
## PRIVATE ## PRIVATE
A helper type allowing to resolve column references in a context of an underlying table. A helper type allowing to resolve column references in a context of an underlying table.
@ -23,12 +23,24 @@ type Table_Ref
at : Text | Integer -> Any ! No_Such_Column | Index_Out_Of_Bounds at : Text | Integer -> Any ! No_Such_Column | Index_Out_Of_Bounds
at self selector=0 = self.underlying.at selector at self selector=0 = self.underlying.at selector
## PRIVATE
Given an expression, create a derived column where each value is the
result of evaluating the expression for the row.
Arguments:
- expression: The expression to evaluate.
- on_problems: Specifies how to handle non-fatal problems, attaching a
warning by default.
evaluate_expression : Text -> Problem_Behavior -> Any ! No_Such_Column | Invalid_Value_Type | Expression_Error
evaluate_expression self expression on_problems=Report_Warning = self.underlying.evaluate_expression expression on_problems=on_problems
## PRIVATE ## PRIVATE
Resolve a Column_Ref to a Column, keeping any other values as-is. Resolve a Column_Ref to a Column, keeping any other values as-is.
resolve : Any -> Any ! No_Such_Column | Index_Out_Of_Bounds resolve : Any -> Any ! No_Such_Column | Index_Out_Of_Bounds
resolve self value = case value of resolve self value = case value of
Column_Ref.Name name -> self.at name Column_Ref.Name name -> self.at name
Column_Ref.Index index -> self.at index Column_Ref.Index index -> self.at index
Column_Ref.Expression expression -> self.evaluate_expression expression
_ -> value _ -> value
## PRIVATE ## PRIVATE
@ -38,28 +50,26 @@ type Table_Ref
resolve_as_column self value = case value of resolve_as_column self value = case value of
Column_Ref.Name name -> self.at name Column_Ref.Name name -> self.at name
Column_Ref.Index index -> self.at index Column_Ref.Index index -> self.at index
Column_Ref.Expression expression -> self.evaluate_expression expression
_ -> self.underlying.make_constant_column value _ -> self.underlying.make_constant_column value
## PRIVATE ## PRIVATE
Transforms a condition, changing any Column_Ref instances into Column instances resolved in this table. Transforms a condition, changing any Column_Ref instances into Column instances resolved in this table.
resolve_condition : Filter_Condition -> Filter_Condition resolve_condition : Filter_Condition -> Filter_Condition
resolve_condition self condition = case condition of resolve_condition self condition = case condition of
Filter_Condition.Equal value -> Filter_Condition.Equal (self.resolve value) Filter_Condition.Equal value action -> Filter_Condition.Equal (self.resolve value) action
Filter_Condition.Not_Equal value -> Filter_Condition.Not_Equal (self.resolve value) Filter_Condition.Not_Equal value action -> Filter_Condition.Not_Equal (self.resolve value) action
Filter_Condition.Less value -> Filter_Condition.Less (self.resolve value) Filter_Condition.Less value action -> Filter_Condition.Less (self.resolve value) action
Filter_Condition.Equal_Or_Less value -> Filter_Condition.Equal_Or_Less (self.resolve value) Filter_Condition.Equal_Or_Less value action -> Filter_Condition.Equal_Or_Less (self.resolve value) action
Filter_Condition.Greater value -> Filter_Condition.Greater (self.resolve value) Filter_Condition.Greater value action -> Filter_Condition.Greater (self.resolve value) action
Filter_Condition.Equal_Or_Greater value -> Filter_Condition.Equal_Or_Greater (self.resolve value) Filter_Condition.Equal_Or_Greater value action -> Filter_Condition.Equal_Or_Greater (self.resolve value) action
Filter_Condition.Between lower upper -> Filter_Condition.Between (self.resolve lower) (self.resolve upper) Filter_Condition.Between lower upper action -> Filter_Condition.Between (self.resolve lower) (self.resolve upper) action
Filter_Condition.Equal_Ignore_Case value locale -> Filter_Condition.Equal_Ignore_Case (self.resolve value) locale Filter_Condition.Equal_Ignore_Case value locale action -> Filter_Condition.Equal_Ignore_Case (self.resolve value) locale action
Filter_Condition.Starts_With prefix case_sensitivity -> Filter_Condition.Starts_With (self.resolve prefix) case_sensitivity Filter_Condition.Starts_With prefix case_sensitivity action -> Filter_Condition.Starts_With (self.resolve prefix) case_sensitivity action
Filter_Condition.Ends_With prefix case_sensitivity -> Filter_Condition.Ends_With (self.resolve prefix) case_sensitivity Filter_Condition.Ends_With prefix case_sensitivity action -> Filter_Condition.Ends_With (self.resolve prefix) case_sensitivity action
Filter_Condition.Contains prefix case_sensitivity -> Filter_Condition.Contains (self.resolve prefix) case_sensitivity Filter_Condition.Contains prefix case_sensitivity action -> Filter_Condition.Contains (self.resolve prefix) case_sensitivity action
Filter_Condition.Not_Contains prefix case_sensitivity -> Filter_Condition.Not_Contains (self.resolve prefix) case_sensitivity Filter_Condition.Like pattern action -> Filter_Condition.Like (self.resolve pattern) action
Filter_Condition.Like pattern -> Filter_Condition.Like (self.resolve pattern) Filter_Condition.Is_In values action -> Filter_Condition.Is_In (check_is_in_values "Is_In" values) action
Filter_Condition.Not_Like pattern -> Filter_Condition.Not_Like (self.resolve pattern)
Filter_Condition.Is_In values -> Filter_Condition.Is_In (check_is_in_values "Is_In" values)
Filter_Condition.Not_In values -> Filter_Condition.Not_In (check_is_in_values "Not_In" values)
_ -> condition _ -> condition
## PRIVATE ## PRIVATE

View File

@ -13,67 +13,60 @@ from project.Errors import Nothing_Value_In_Filter_Condition
It also performs validation and will throw errors if unexpected column types It also performs validation and will throw errors if unexpected column types
are encountered. are encountered.
make_filter_column source_column filter_condition on_problems = case filter_condition of make_filter_column source_column filter_condition on_problems =
base_column = case filter_condition of
# Equality # Equality
Equal value -> Equal value _ ->
warn_on_nothing_in_comparison filter_condition value <| warn_on_nothing_in_comparison filter_condition value <|
Warning.with_suspended source_column source_column-> Warning.with_suspended source_column source_column->
Warning.with_suspended value value-> Warning.with_suspended value value->
on_problems.escalate_warnings <| on_problems.escalate_warnings <|
source_column == value source_column == value
Not_Equal value -> Not_Equal value _ ->
warn_on_nothing_in_comparison filter_condition value <| warn_on_nothing_in_comparison filter_condition value <|
Warning.with_suspended source_column source_column-> Warning.with_suspended source_column source_column->
Warning.with_suspended value value-> Warning.with_suspended value value->
on_problems.escalate_warnings <| on_problems.escalate_warnings <|
source_column != value source_column != value
# Nothing # Nothing
Is_Nothing -> source_column.is_nothing Is_Nothing _ -> source_column.is_nothing
Not_Nothing -> source_column.is_nothing.not Not_Nothing _ -> source_column.is_nothing.not
# Boolean # Boolean
Is_True -> Is_True _ -> Value_Type.expect_boolean source_column <| source_column
Value_Type.expect_boolean source_column <| source_column Is_False _ -> Value_Type.expect_boolean source_column <| source_column.not
Is_False -> source_column.not
# Comparisons # Comparisons
Less value -> Less value _ ->
warn_on_nothing_in_comparison filter_condition value <| warn_on_nothing_in_comparison filter_condition value <|
source_column < value source_column < value
Equal_Or_Less value -> Equal_Or_Less value _ ->
warn_on_nothing_in_comparison filter_condition value <| warn_on_nothing_in_comparison filter_condition value <|
source_column <= value source_column <= value
Equal_Or_Greater value -> Equal_Or_Greater value _ ->
warn_on_nothing_in_comparison filter_condition value <| warn_on_nothing_in_comparison filter_condition value <|
source_column >= value source_column >= value
Greater value -> Greater value _ ->
warn_on_nothing_in_comparison filter_condition value <| warn_on_nothing_in_comparison filter_condition value <|
source_column > value source_column > value
Between lower upper -> Between lower upper _ ->
warn_on_nothing_in_comparison filter_condition lower <| warn_on_nothing_in_comparison filter_condition lower <|
warn_on_nothing_in_comparison filter_condition upper <| warn_on_nothing_in_comparison filter_condition upper <|
source_column.between lower upper source_column.between lower upper
# Text # Text
Equal_Ignore_Case value locale -> Equal_Ignore_Case value locale _ ->
source_column.equals_ignore_case value locale source_column.equals_ignore_case value locale
Starts_With prefix case_sensitivity -> Starts_With prefix case_sensitivity _ ->
source_column.starts_with prefix case_sensitivity source_column.starts_with prefix case_sensitivity
Ends_With suffix case_sensitivity -> Ends_With suffix case_sensitivity _ ->
source_column.ends_with suffix case_sensitivity source_column.ends_with suffix case_sensitivity
Contains substring case_sensitivity -> Contains substring case_sensitivity _ ->
source_column.contains substring case_sensitivity source_column.contains substring case_sensitivity
Not_Contains substring case_sensitivity -> Is_Empty _ -> source_column.is_empty
source_column.contains substring case_sensitivity . not Not_Empty _ -> source_column.is_empty.not
Is_Empty -> Like pattern _ -> source_column.like pattern
source_column.is_empty
Not_Empty ->
source_column.is_empty.not
Like pattern ->
source_column.like pattern
Not_Like pattern ->
source_column.like pattern . not
# Numeric # Numeric
Is_Nan -> source_column.is_nan Is_Nan _ -> source_column.is_nan
Is_Infinite -> source_column.is_infinite Is_Infinite _ -> source_column.is_infinite
Is_Finite -> Is_Finite _ ->
is_infinite_column = source_column.is_infinite is_infinite_column = source_column.is_infinite
is_nan_column = source_column.is_nan is_nan_column = source_column.is_nan
## We check is_nan_column for error, since some Database backends may ## We check is_nan_column for error, since some Database backends may
@ -81,12 +74,12 @@ make_filter_column source_column filter_condition on_problems = case filter_cond
if is_nan_column.is_error then is_infinite_column.not else if is_nan_column.is_error then is_infinite_column.not else
(is_infinite_column || is_nan_column).not (is_infinite_column || is_nan_column).not
# Vector # Vector
Is_In values -> Is_In values _ ->
warn_on_nothing_in_comparison_vector filter_condition values <| warn_on_nothing_in_comparison_vector filter_condition values <|
source_column.is_in values source_column.is_in values
Not_In values -> if filter_condition.action == Filter_Action.Keep then base_column else
warn_on_nothing_in_comparison_vector filter_condition values <| ## We need to fill in the Nothing values and then negate the result.
source_column.is_in values . not (base_column.fill_nothing False).not
## Attach a warning if the provided value is `Nothing`. ## Attach a warning if the provided value is `Nothing`.
warn_on_nothing_in_comparison : Filter_Condition -> Any -> Any -> Any warn_on_nothing_in_comparison : Filter_Condition -> Any -> Any -> Any

View File

@ -85,7 +85,8 @@ make_column_name_vector_selector table display=Display.Always =
make_column_ref_by_name_selector : Table -> Display -> Widget make_column_ref_by_name_selector : Table -> Display -> Widget
make_column_ref_by_name_selector table display=Display.Always = 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+")") col_names_options = table.column_names.map (name -> Option name "(Column_Ref.Name "+name.pretty+")")
Single_Choice values=col_names_options display=display expression_option = Option "<Expression>" "(Column_Ref.Expression '["+table.column_names.first+"]')"
Single_Choice values=(col_names_options+[expression_option]) display=display
## PRIVATE ## PRIVATE
Same as `make_column_ref_by_name_selector` but also highlights an option for Same as `make_column_ref_by_name_selector` but also highlights an option for
@ -94,7 +95,8 @@ make_column_ref_or_text_value_selector : Table -> Display -> Widget
make_column_ref_or_text_value_selector table display=Display.Always = 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+")") col_names_options = table.column_names.map (name -> Option name "(Column_Ref.Name "+name.pretty+")")
custom_text_option = Option "'custom text'" "''" custom_text_option = Option "'custom text'" "''"
Single_Choice values=(col_names_options+[custom_text_option]) display=display expression_option = Option "<Expression>" "(Column_Ref.Expression '["+table.column_names.first+"]')"
Single_Choice values=(col_names_options+[custom_text_option, expression_option]) display=display
## PRIVATE ## PRIVATE
If `column_source` is Nothing, `Column_Ref` options will not be added. If `column_source` is Nothing, `Column_Ref` options will not be added.
@ -104,7 +106,9 @@ make_fill_default_value_selector column_source=Nothing include_custom_text=False
column_source.column_names.map (name -> Option name "(Column_Ref.Name "+name.pretty+")") 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 [] custom_text_option = if include_custom_text then [Option "'custom text'" "''"] else []
previous_value_option = [Option 'Previous Value' 'Previous_Value'] previous_value_option = [Option 'Previous Value' 'Previous_Value']
Single_Choice values=(previous_value_option+col_names_options+custom_text_option) display=display 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
## PRIVATE ## PRIVATE
Make a filter condition selector. Make a filter condition selector.
@ -124,7 +128,6 @@ make_filter_condition_selector table display=Display.Always =
builder.append (Option "Starts With" fqn+".Starts_With" [["prefix", 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 "Ends With" fqn+".Ends_With" [["suffix", col_names]])
builder.append (Option "Contains" fqn+".Contains" [["substring", col_names]]) builder.append (Option "Contains" fqn+".Contains" [["substring", col_names]])
builder.append (Option "Not Contains" fqn+".Not_Contains" [["substring", col_names]])
builder.append (Option "Is Nothing" fqn+".Is_Nothing") builder.append (Option "Is Nothing" fqn+".Is_Nothing")
builder.append (Option "Is Not Nothing" fqn+".Not_Nothing") builder.append (Option "Is Not Nothing" fqn+".Not_Nothing")
builder.append (Option "Is Finite" fqn+".Is_Finite") builder.append (Option "Is Finite" fqn+".Is_Finite")
@ -135,9 +138,7 @@ make_filter_condition_selector table display=Display.Always =
builder.append (Option "Is Empty" fqn+".Is_Empty") builder.append (Option "Is Empty" fqn+".Is_Empty")
builder.append (Option "Is Not Empty" fqn+".Not_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", col_names]])
builder.append (Option "Not Like" fqn+".Not_Like" [["pattern", col_names]])
builder.append (Option "Is In" fqn+".Is_In") builder.append (Option "Is In" fqn+".Is_In")
builder.append (Option "Not In" fqn+".Not_In")
Single_Choice builder.to_vector display=display Single_Choice builder.to_vector display=display
## PRIVATE ## PRIVATE

View File

@ -5,13 +5,13 @@ from Standard.Base.Runtime import State
import project.Clue.Clue import project.Clue.Clue
import project.Group.Group import project.Group.Group
import project.Spec_Result.Spec_Result
import project.Spec.Spec import project.Spec.Spec
import project.Spec_Result.Spec_Result
import project.Suite.Suite import project.Suite.Suite
import project.Suite_Config.Suite_Config import project.Suite_Config.Suite_Config
import project.Test_Result.Test_Result
import project.Test_Reporter
import project.Test.Test import project.Test.Test
import project.Test_Reporter
import project.Test_Result.Test_Result
run_group_with_filter : Group -> (Regex|Text|Nothing) -> Vector Test_Result run_group_with_filter : Group -> (Regex|Text|Nothing) -> Vector Test_Result
run_group_with_filter (group : Group) (spec_filter : (Regex|Text|Nothing)) = run_group_with_filter (group : Group) (spec_filter : (Regex|Text|Nothing)) =
@ -28,7 +28,7 @@ run_group (group : Group) =
run_specs_from_group group.specs group run_specs_from_group group.specs group
run_specs_from_group : Vector Spec -> Text -> Vector Test_Result run_specs_from_group : Vector Spec -> Group -> Vector Test_Result
run_specs_from_group (specs : Vector Spec) (group : Group) = run_specs_from_group (specs : Vector Spec) (group : Group) =
case specs.is_empty of case specs.is_empty of
True -> [] True -> []

View File

@ -1,9 +1,10 @@
import project.Problems
import project.Suite.Suite import project.Suite.Suite
import project.Test.Test import project.Test.Test
import project.Problems
from project.Extensions import all from project.Extensions import all
export project.Problems
export project.Suite.Suite export project.Suite.Suite
export project.Test.Test export project.Test.Test
export project.Problems
from project.Extensions export all from project.Extensions export all

View File

@ -28,7 +28,7 @@ type Suite_Builder
`specify` method on group builder. See its docs. `specify` method on group builder. See its docs.
- pending: Contains a reason for why the test group should be ignored. If Nothing, the test - pending: Contains a reason for why the test group should be ignored. If Nothing, the test
is not ignored. is not ignored.
group : Text -> (Group_Builder -> Any) -> Nothing group : Text -> (Group_Builder -> Any) -> (Text | Nothing) -> Nothing
group self (name:Text) (fn : (Group_Builder -> Any)) (pending : (Text | Nothing) = Nothing) = group self (name:Text) (fn : (Group_Builder -> Any)) (pending : (Text | Nothing) = Nothing) =
group_builder = Group_Builder.Impl group_builder = Group_Builder.Impl
case pending of case pending of
@ -62,7 +62,7 @@ type Suite
- group_filter: Filter for group names. - group_filter: Filter for group names.
- spec_filter: Filter for spec names. - spec_filter: Filter for spec names.
- should_exit: If true, executes `System.exit` at the end. - should_exit: If true, executes `System.exit` at the end.
run_with_filter : (Regex | Text | Nothing) -> (Regex | Text | Nothing) -> Nothing run_with_filter : (Regex | Text | Nothing) -> (Regex | Text | Nothing) -> Boolean -> Nothing
run_with_filter self group_filter=Nothing spec_filter=Nothing should_exit=True = run_with_filter self group_filter=Nothing spec_filter=Nothing should_exit=True =
config = Suite_Config.from_environment config = Suite_Config.from_environment
@ -99,9 +99,11 @@ type Suite
False -> False ->
failed_tests == 0 failed_tests == 0
## Gets the names of all the groups in this suite.
group_names self = group_names self =
self.groups.map (_.name) self.groups.map (_.name)
## Print the structure of the suite to the console.
print_all self = print_all self =
IO.println "Test Suite:" IO.println "Test Suite:"
self.groups.each group-> self.groups.each group->

View File

@ -1,14 +1,14 @@
from Standard.Base import all from Standard.Base import all
from Standard.Base.Errors.Common import Uninitialized_State from Standard.Base.Errors.Common import Uninitialized_State
from Standard.Base.Runtime import State from Standard.Base.Runtime import State
import project.Test_Result.Test_Result
import project.Clue.Clue import project.Clue.Clue
import project.Group.Group import project.Group.Group
import project.Suite.Suite
import project.Suite.Suite_Builder
import project.Spec.Spec import project.Spec.Spec
import project.Spec_Result.Spec_Result import project.Spec_Result.Spec_Result
import project.Suite.Suite
import project.Suite.Suite_Builder
import project.Test_Result.Test_Result
## Contains only static methods ## Contains only static methods
type Test type Test
@ -65,6 +65,7 @@ type Test
Test.expect_panic_with Examples.My_Error <| Test.expect_panic_with Examples.My_Error <|
IO.println 'hello' IO.println 'hello'
Examples.throw_panic Examples.throw_panic
IO.println 'this is not reached' IO.println 'this is not reached'
expect_panic : Any -> Any -> Test_Result expect_panic : Any -> Any -> Test_Result
expect_panic matcher ~action = Test.expect_panic_with action matcher expect_panic matcher ~action = Test.expect_panic_with action matcher

View File

@ -1,11 +1,11 @@
private private
from Standard.Base import all from Standard.Base import all
from Standard.Base.Runtime import assert
import Standard.Base.Runtime.Context import Standard.Base.Runtime.Context
from Standard.Base.Runtime import assert
import project.Suite_Config.Suite_Config
import project.Spec_Result.Spec_Result import project.Spec_Result.Spec_Result
import project.Suite_Config.Suite_Config
import project.Test.Test import project.Test.Test
import project.Test_Result.Test_Result import project.Test_Result.Test_Result

View File

@ -5,17 +5,23 @@ import project.Spec_Result.Spec_Result
## A wrapper for `Spec_Result` that contains also name of the group and name of the spec. ## A wrapper for `Spec_Result` that contains also name of the group and name of the spec.
type Test_Result type Test_Result
## PRIVATE
Impl (group_name : Text) (spec_name : Text) (spec_result : Spec_Result) (time_taken : Duration) Impl (group_name : Text) (spec_name : Text) (spec_result : Spec_Result) (time_taken : Duration)
## PRIVATE
Render as Test_Result as Text.
to_text self = to_text self =
"'" + self.group_name + "' '" + self.spec_name + "': " + self.spec_result.to_text "'" + self.group_name + "' '" + self.spec_name + "': " + self.spec_result.to_text
## Was the test pending?
is_pending self = is_pending self =
self.spec_result.is_pending self.spec_result.is_pending
## Was the test successful?
is_success self = is_success self =
self.spec_result.is_success self.spec_result.is_success
## Was the test a failure?
is_fail self = is_fail self =
self.spec_result.is_fail self.spec_result.is_fail

View File

@ -124,7 +124,7 @@ public final class BoolStorage extends Storage<Boolean> {
*/ */
private Storage<?> fillMissingBoolean(boolean arg) { private Storage<?> fillMissingBoolean(boolean arg) {
final var newValues = (BitSet) values.clone(); final var newValues = (BitSet) values.clone();
if (arg) { if (arg != negated) {
newValues.or(isMissing); newValues.or(isMissing);
} else { } else {
newValues.andNot(isMissing); newValues.andNot(isMissing);

View File

@ -77,9 +77,9 @@ add_specs suite_builder =
Json.parse '{"start": 15, "end": 20, "step": 3}' . into Range . should_equal (Range.Between 15 20 3) Json.parse '{"start": 15, "end": 20, "step": 3}' . into Range . should_equal (Range.Between 15 20 3)
group_builder.specify "should be able to deserialize using into for multiple constructors" <| group_builder.specify "should be able to deserialize using into for multiple constructors" <|
Json.parse '{"than": 2}' . into Filter_Condition . should_fail_with Illegal_Argument Json.parse '{"than": 2}' . into Statistic . should_fail_with Illegal_Argument
Json.parse '{"constructor": "Less", "than": 2}' . into Filter_Condition . should_equal (Filter_Condition.Less 2) Json.parse '{"constructor": "Skew", "population": true}' . into Statistic . should_equal (Statistic.Skew True)
Json.parse '{"constructor": "NotARealOne", "than": 2}' . into Filter_Condition . should_fail_with Illegal_Argument Json.parse '{"constructor": "NotARealOne", "population": true}' . into Statistic . should_fail_with Illegal_Argument
group_builder.specify "should be able to convert a JS_Object into a Map using into" <| group_builder.specify "should be able to convert a JS_Object into a Map using into" <|
Json.parse '{"a": 15, "b": 20, "c": "X", "d": null}' . into Map . should_equal (Map.from_vector [["a", 15], ["b", 20], ["c", "X"], ["d", Nothing]]) Json.parse '{"a": 15, "b": 20, "c": "X", "d": null}' . into Map . should_equal (Map.from_vector [["a", 15], ["b", 20], ["c", "X"], ["d", Nothing]])

View File

@ -36,6 +36,7 @@ add_specs suite_builder = suite_builder.group "List" group_builder->
l.any (Filter_Condition.Greater 1) . should_be_true l.any (Filter_Condition.Greater 1) . should_be_true
l.any (Filter_Condition.Less 0) . should_be_false l.any (Filter_Condition.Less 0) . should_be_false
l.any (Filter_Condition.Equal_Or_Greater 1 Filter_Action.Remove) . should_be_false
Test.expect_panic_with (l.any "invalid arg") Type_Error Test.expect_panic_with (l.any "invalid arg") Type_Error
@ -47,6 +48,7 @@ add_specs suite_builder = suite_builder.group "List" group_builder->
l.all (Filter_Condition.Greater 0) . should_be_true l.all (Filter_Condition.Greater 0) . should_be_true
l.all (Filter_Condition.Less 3) . should_be_false l.all (Filter_Condition.Less 3) . should_be_false
l.any (Filter_Condition.Less 0 Filter_Action.Remove) . should_be_true
Test.expect_panic_with (l.all "invalid arg") Type_Error Test.expect_panic_with (l.all "invalid arg") Type_Error
@ -70,6 +72,7 @@ add_specs suite_builder = suite_builder.group "List" group_builder->
empty.find (==1) if_missing=Nothing . should_equal Nothing empty.find (==1) if_missing=Nothing . should_equal Nothing
l.find (Filter_Condition.Greater 1) . should_equal 2 l.find (Filter_Condition.Greater 1) . should_equal 2
l.find (Filter_Condition.Less 2 Filter_Action.Remove) . should_equal 2
Test.expect_panic_with (l.find "invalid arg") Type_Error Test.expect_panic_with (l.find "invalid arg") Type_Error
@ -90,6 +93,7 @@ add_specs suite_builder = suite_builder.group "List" group_builder->
l.index_of 2 start=-4 . should_fail_with Index_Out_Of_Bounds l.index_of 2 start=-4 . should_fail_with Index_Out_Of_Bounds
l.index_of (Filter_Condition.Greater 1) . should_equal 1 l.index_of (Filter_Condition.Greater 1) . should_equal 1
l.index_of (Filter_Condition.Less 3 Filter_Action.Remove) . should_equal 2
l.index_of "invalid arg" . should_equal Nothing l.index_of "invalid arg" . should_equal Nothing
group_builder.specify "should allow finding the last index of an element in the list with `.last_index_of`" <| group_builder.specify "should allow finding the last index of an element in the list with `.last_index_of`" <|
@ -110,6 +114,7 @@ add_specs suite_builder = suite_builder.group "List" group_builder->
ll.last_index_of (Filter_Condition.Greater 1) . should_equal 5 ll.last_index_of (Filter_Condition.Greater 1) . should_equal 5
ll.last_index_of (Filter_Condition.Less 3) . should_equal 4 ll.last_index_of (Filter_Condition.Less 3) . should_equal 4
ll.last_index_of (Filter_Condition.Greater 2 Filter_Action.Remove) . should_equal 4
ll.last_index_of "invalid arg" . should_equal Nothing ll.last_index_of "invalid arg" . should_equal Nothing
group_builder.specify "should allow checking if the list is empty with `.is_empty`" <| group_builder.specify "should allow checking if the list is empty with `.is_empty`" <|
@ -129,6 +134,7 @@ add_specs suite_builder = suite_builder.group "List" group_builder->
group_builder.specify "should filter elements by Filter_Condition" <| group_builder.specify "should filter elements by Filter_Condition" <|
list = [1, 2, 3, 4, 5].to_list list = [1, 2, 3, 4, 5].to_list
list.filter (Filter_Condition.Greater than=3) . should_equal [4, 5].to_list list.filter (Filter_Condition.Greater than=3) . should_equal [4, 5].to_list
list.filter (Filter_Condition.Greater than=3 action=Filter_Action.Remove) . should_equal [1, 2, 3].to_list
list.filter (Filter_Condition.Less than=3.5) . should_equal [1, 2, 3].to_list list.filter (Filter_Condition.Less than=3.5) . should_equal [1, 2, 3].to_list
list.filter (Filter_Condition.Equal to=3) . should_equal (List.Cons 3 List.Nil) list.filter (Filter_Condition.Equal to=3) . should_equal (List.Cons 3 List.Nil)
list.filter (Filter_Condition.Not_Equal to=3) . should_equal [1, 2, 4, 5].to_list list.filter (Filter_Condition.Not_Equal to=3) . should_equal [1, 2, 4, 5].to_list
@ -136,14 +142,23 @@ add_specs suite_builder = suite_builder.group "List" group_builder->
list.filter (Filter_Condition.Equal_Or_Less than=(-1)) . should_equal List.Nil list.filter (Filter_Condition.Equal_Or_Less than=(-1)) . should_equal List.Nil
list.filter (Filter_Condition.Between 2 4) . should_equal [2, 3, 4].to_list list.filter (Filter_Condition.Between 2 4) . should_equal [2, 3, 4].to_list
list.filter (Filter_Condition.Is_In [7, 3, 2]) . should_equal [2, 3].to_list list.filter (Filter_Condition.Is_In [7, 3, 2]) . should_equal [2, 3].to_list
list.filter (Filter_Condition.Not_In [7, 3, 2]) . should_equal [1, 4, 5].to_list
Test.expect_panic Type_Error (list.filter (Filter_Condition.Starts_With "a"))
list.filter Filter_Condition.Is_True . should_equal List.Nil
list.filter Filter_Condition.Is_False . should_equal List.Nil
list.filter Filter_Condition.Is_Nothing . should_equal List.Nil list.filter Filter_Condition.Is_Nothing . should_equal List.Nil
list.filter Filter_Condition.Not_Nothing . should_equal list list.filter Filter_Condition.Not_Nothing . should_equal list
## Boolean based filters should fail with type error
Test.expect_panic Type_Error (list.filter Filter_Condition.Is_True)
Test.expect_panic Type_Error (list.filter Filter_Condition.Is_False)
## Text based filters should fail with type error
Test.expect_panic Type_Error (list.filter (Filter_Condition.Starts_With "a"))
Test.expect_panic Type_Error (list.filter (Filter_Condition.Ends_With "a"))
Test.expect_panic Type_Error (list.filter (Filter_Condition.Contains "a"))
Test.expect_panic Type_Error (list.filter (Filter_Condition.Equal_Ignore_Case "a"))
Test.expect_panic Type_Error (list.filter (Filter_Condition.Like "a%"))
Test.expect_panic Type_Error (list.filter Filter_Condition.Is_Empty)
Test.expect_panic Type_Error (list.filter Filter_Condition.Not_Empty)
txt = ["aaa", "bbb", "abab", "cccc", "baaa", "ś"].to_list txt = ["aaa", "bbb", "abab", "cccc", "baaa", "ś"].to_list
txt.filter (Filter_Condition.Contains "a") . should_equal ["aaa", "abab", "baaa"].to_list txt.filter (Filter_Condition.Contains "a") . should_equal ["aaa", "abab", "baaa"].to_list
txt.filter (Filter_Condition.Contains 'A' Case_Sensitivity.Sensitive) . should_equal [].to_list txt.filter (Filter_Condition.Contains 'A' Case_Sensitivity.Sensitive) . should_equal [].to_list
@ -151,12 +166,6 @@ add_specs suite_builder = suite_builder.group "List" group_builder->
txt.filter (Filter_Condition.Contains 's\u0301') . should_equal ["ś"].to_list txt.filter (Filter_Condition.Contains 's\u0301') . should_equal ["ś"].to_list
txt.filter (Filter_Condition.Contains 'S\u0301' Case_Sensitivity.Sensitive) . should_equal [].to_list txt.filter (Filter_Condition.Contains 'S\u0301' Case_Sensitivity.Sensitive) . should_equal [].to_list
txt.filter (Filter_Condition.Contains 'S\u0301' Case_Sensitivity.Insensitive) . should_equal ["ś"].to_list txt.filter (Filter_Condition.Contains 'S\u0301' Case_Sensitivity.Insensitive) . should_equal ["ś"].to_list
txt.filter (Filter_Condition.Not_Contains "a") . should_equal ["bbb", "cccc", "ś"].to_list
txt.filter (Filter_Condition.Not_Contains "A" Case_Sensitivity.Sensitive) . should_equal ["aaa", "bbb", "abab", "cccc", "baaa", "ś"].to_list
txt.filter (Filter_Condition.Not_Contains "A" Case_Sensitivity.Insensitive) . should_equal ["bbb", "cccc", "ś"].to_list
txt.filter (Filter_Condition.Not_Contains 's\u0301') . should_equal ["aaa", "bbb", "abab", "cccc", "baaa"].to_list
txt.filter (Filter_Condition.Not_Contains 'S\u0301' Case_Sensitivity.Sensitive) . should_equal ["aaa", "bbb", "abab", "cccc", "baaa", "ś"].to_list
txt.filter (Filter_Condition.Not_Contains 'S\u0301' Case_Sensitivity.Insensitive) . should_equal ["aaa", "bbb", "abab", "cccc", "baaa"].to_list
txt.filter (Filter_Condition.Starts_With "a") . should_equal ["aaa", "abab"].to_list txt.filter (Filter_Condition.Starts_With "a") . should_equal ["aaa", "abab"].to_list
txt.filter (Filter_Condition.Starts_With "A" Case_Sensitivity.Sensitive) . should_equal [].to_list txt.filter (Filter_Condition.Starts_With "A" Case_Sensitivity.Sensitive) . should_equal [].to_list
txt.filter (Filter_Condition.Starts_With "A" Case_Sensitivity.Insensitive) . should_equal ["aaa", "abab"].to_list txt.filter (Filter_Condition.Starts_With "A" Case_Sensitivity.Insensitive) . should_equal ["aaa", "abab"].to_list
@ -173,7 +182,6 @@ add_specs suite_builder = suite_builder.group "List" group_builder->
["abab", "aaabaaaa", "ba"].to_list.filter (Filter_Condition.Like "ba") . should_equal (List.Cons "ba" List.Nil) ["abab", "aaabaaaa", "ba"].to_list.filter (Filter_Condition.Like "ba") . should_equal (List.Cons "ba" List.Nil)
["abab", "aaabaaaa"].to_list.filter (Filter_Condition.Like "_ba_") . should_equal ["abab"].to_list ["abab", "aaabaaaa"].to_list.filter (Filter_Condition.Like "_ba_") . should_equal ["abab"].to_list
["abab", "aaabaaaa"].to_list.filter (Filter_Condition.Like "%ba__%") . should_equal ["aaabaaaa"].to_list ["abab", "aaabaaaa"].to_list.filter (Filter_Condition.Like "%ba__%") . should_equal ["aaabaaaa"].to_list
["abab", "aaabaaaa"].to_list.filter (Filter_Condition.Not_Like "%ba%") . should_equal List.Nil
mixed = [1, Nothing, "b"].to_list mixed = [1, Nothing, "b"].to_list
mixed.filter Filter_Condition.Is_Nothing . should_equal (List.Cons Nothing List.Nil) mixed.filter Filter_Condition.Is_Nothing . should_equal (List.Cons Nothing List.Nil)
@ -192,6 +200,10 @@ add_specs suite_builder = suite_builder.group "List" group_builder->
r2.first . should_equal (List.Cons 2 (List.Cons 3 List.Nil)) r2.first . should_equal (List.Cons 2 (List.Cons 3 List.Nil))
r2.second . should_equal (List.Cons 1 List.Nil) r2.second . should_equal (List.Cons 1 List.Nil)
r2r = l.partition (Filter_Condition.Greater than=1 action=Filter_Action.Remove)
r2r.second . should_equal (List.Cons 2 (List.Cons 3 List.Nil))
r2r.first . should_equal (List.Cons 1 List.Nil)
r3 = l.partition (Filter_Condition.Equal_Or_Greater than=10) r3 = l.partition (Filter_Condition.Equal_Or_Greater than=10)
r3.first . should_equal List.Nil r3.first . should_equal List.Nil
r3.second . should_equal l r3.second . should_equal l

View File

@ -152,30 +152,48 @@ add_specs suite_builder = suite_builder.group "Range" group_builder->
group_builder.specify "should filter elements by Filter_Condition" <| group_builder.specify "should filter elements by Filter_Condition" <|
range = 1.up_to 6 range = 1.up_to 6
range.filter (Filter_Condition.Greater than=3) . should_equal [4, 5] range.filter (Filter_Condition.Greater 3) . should_equal [4, 5]
range.filter (Filter_Condition.Less than=3.5) . should_equal [1, 2, 3] range.filter (Filter_Condition.Greater 3 Filter_Action.Remove) . should_equal [1, 2, 3]
range.filter (Filter_Condition.Equal to=3) . should_equal [3] range.filter (Filter_Condition.Less 3.5) . should_equal [1, 2, 3]
range.filter (Filter_Condition.Not_Equal to=3) . should_equal [1, 2, 4, 5] range.filter (Filter_Condition.Less 3.5 Filter_Action.Remove) . should_equal [4, 5]
range.filter (Filter_Condition.Equal_Or_Greater than=3) . should_equal [3, 4, 5] range.filter (Filter_Condition.Equal 3) . should_equal [3]
range.filter (Filter_Condition.Equal_Or_Less than=(-1)) . should_equal [] range.filter (Filter_Condition.Equal 3 Filter_Action.Remove) . should_equal [1, 2, 4, 5]
range.filter (Filter_Condition.Not_Equal 3) . should_equal [1, 2, 4, 5]
range.filter (Filter_Condition.Not_Equal 3 Filter_Action.Remove) . should_equal [3]
range.filter (Filter_Condition.Equal_Or_Greater 3) . should_equal [3, 4, 5]
range.filter (Filter_Condition.Equal_Or_Greater 3 Filter_Action.Remove) . should_equal [1, 2]
range.filter (Filter_Condition.Equal_Or_Less (-1)) . should_equal []
range.filter (Filter_Condition.Equal_Or_Less (-1) Filter_Action.Remove) . should_equal [1, 2, 3, 4, 5]
range.filter (Filter_Condition.Between 2 4) . should_equal [2, 3, 4] range.filter (Filter_Condition.Between 2 4) . should_equal [2, 3, 4]
range.filter (Filter_Condition.Between 2.1 4.5) . should_equal [3, 4] range.filter (Filter_Condition.Between 2.1 4.5) . should_equal [3, 4]
range.filter (Filter_Condition.Between 2 4 Filter_Action.Remove) . should_equal [1, 5]
range.filter (Filter_Condition.Is_In [7, 3, 2]) . should_equal [2, 3] range.filter (Filter_Condition.Is_In [7, 3, 2]) . should_equal [2, 3]
range.filter (Filter_Condition.Not_In [7, 3, 2]) . should_equal [1, 4, 5] range.filter (Filter_Condition.Is_In [7, 3, 2] Filter_Action.Remove) . should_equal [1, 4, 5]
Test.expect_panic Type_Error (range.filter (Filter_Condition.Starts_With "a"))
Test.expect_panic Type_Error (range.filter (Filter_Condition.Equal_Ignore_Case "a"))
range.filter (Filter_Condition.Like "a%") . should_fail_with Type_Error
range.filter (Filter_Condition.Not_Like "a_") . should_fail_with Type_Error
range.filter Filter_Condition.Is_Nan . should_equal [] range.filter Filter_Condition.Is_Nan . should_equal []
range.filter (Filter_Condition.Is_Nan Filter_Action.Remove) . should_equal [1, 2, 3, 4, 5]
range.filter Filter_Condition.Is_Infinite . should_equal [] range.filter Filter_Condition.Is_Infinite . should_equal []
range.filter (Filter_Condition.Is_Infinite Filter_Action.Remove) . should_equal [1, 2, 3, 4, 5]
range.filter Filter_Condition.Is_Finite . should_equal [1, 2, 3, 4, 5] range.filter Filter_Condition.Is_Finite . should_equal [1, 2, 3, 4, 5]
range.filter Filter_Condition.Is_True . should_equal [] range.filter (Filter_Condition.Is_Finite Filter_Action.Remove) . should_equal []
range.filter Filter_Condition.Is_False . should_equal []
range.filter Filter_Condition.Is_Nothing . should_equal [] range.filter Filter_Condition.Is_Nothing . should_equal []
range.filter (Filter_Condition.Is_Nothing Filter_Action.Remove) . should_equal [1, 2, 3, 4, 5]
range.filter Filter_Condition.Not_Nothing . should_equal [1, 2, 3, 4, 5] range.filter Filter_Condition.Not_Nothing . should_equal [1, 2, 3, 4, 5]
range.filter Filter_Condition.Is_Empty . should_equal [] range.filter (Filter_Condition.Not_Nothing Filter_Action.Remove) . should_equal []
range.filter Filter_Condition.Not_Empty . should_equal [1, 2, 3, 4, 5]
## Text based filters should fail with type error
Test.expect_panic Type_Error (range.filter (Filter_Condition.Starts_With "a"))
Test.expect_panic Type_Error (range.filter (Filter_Condition.Ends_With "a"))
Test.expect_panic Type_Error (range.filter (Filter_Condition.Contains "a"))
Test.expect_panic Type_Error (range.filter (Filter_Condition.Equal_Ignore_Case "a"))
Test.expect_panic Type_Error (range.filter (Filter_Condition.Like "a%"))
Test.expect_panic Type_Error (range.filter Filter_Condition.Is_Empty)
Test.expect_panic Type_Error (range.filter Filter_Condition.Not_Empty)
## Boolean based filters should fail with type error
Test.expect_panic Type_Error (range.filter Filter_Condition.Is_True)
Test.expect_panic Type_Error (range.filter Filter_Condition.Is_False)
group_builder.specify "should allow to partition its elements" <| group_builder.specify "should allow to partition its elements" <|
elements = 0.up_to 10 elements = 0.up_to 10
@ -183,14 +201,19 @@ add_specs suite_builder = suite_builder.group "Range" group_builder->
r1.first . should_equal [0, 2, 4, 6, 8] r1.first . should_equal [0, 2, 4, 6, 8]
r1.second . should_equal [1, 3, 5, 7, 9] r1.second . should_equal [1, 3, 5, 7, 9]
r2 = elements.partition (Filter_Condition.Greater than=3) r2 = elements.partition (Filter_Condition.Greater 3)
r2.first . should_equal [4, 5, 6, 7, 8, 9] r2.first . should_equal [4, 5, 6, 7, 8, 9]
r2.second . should_equal [0, 1, 2, 3] r2.second . should_equal [0, 1, 2, 3]
r2r = elements.partition (Filter_Condition.Greater 3 Filter_Action.Remove)
r2r.first . should_equal [0, 1, 2, 3]
r2r.second . should_equal [4, 5, 6, 7, 8, 9]
group_builder.specify "should allow iteration" <| group_builder.specify "should allow iteration" <|
vec_mut = Vector.new_builder vec_mut = Vector.new_builder
1.up_to 6 . each (i -> vec_mut.append i) 1.up_to 6 . each (i -> vec_mut.append i)
vec_mut.to_vector . should_equal [1, 2, 3, 4, 5] vec_mut.to_vector . should_equal [1, 2, 3, 4, 5]
group_builder.specify "should allow iteration, with error propagation and early exit" <| group_builder.specify "should allow iteration, with error propagation and early exit" <|
vec_mut = Vector.new_builder vec_mut = Vector.new_builder
result = 1.up_to 6 . each_propagate i-> result = 1.up_to 6 . each_propagate i->
@ -198,6 +221,7 @@ add_specs suite_builder = suite_builder.group "Range" group_builder->
vec_mut.append i vec_mut.append i
result . should_fail_with Illegal_Argument result . should_fail_with Illegal_Argument
vec_mut.to_vector . should_equal [1, 2] vec_mut.to_vector . should_equal [1, 2]
group_builder.specify "should allow iteration with index" <| group_builder.specify "should allow iteration with index" <|
vec_mut = Vector.new_builder vec_mut = Vector.new_builder
5.up_to 8 . each_with_index ix-> elem-> 5.up_to 8 . each_with_index ix-> elem->
@ -208,36 +232,46 @@ add_specs suite_builder = suite_builder.group "Range" group_builder->
5.up_to 10 . with_step 2 . each_with_index ix-> elem-> 5.up_to 10 . with_step 2 . each_with_index ix-> elem->
vec_mut_2.append (Pair.new ix elem) vec_mut_2.append (Pair.new ix elem)
vec_mut_2.to_vector . should_equal [Pair.new 0 5, Pair.new 1 7, Pair.new 2 9] vec_mut_2.to_vector . should_equal [Pair.new 0 5, Pair.new 1 7, Pair.new 2 9]
group_builder.specify "should be able to be folded" <| group_builder.specify "should be able to be folded" <|
1.up_to 6 . fold 0 (+) . should_equal 15 1.up_to 6 . fold 0 (+) . should_equal 15
1.up_to 1 . fold 123 (+) . should_equal 123 1.up_to 1 . fold 123 (+) . should_equal 123
group_builder.specify "should be able to perform a running fold" <| group_builder.specify "should be able to perform a running fold" <|
1.up_to 6 . running_fold 0 (+) . should_equal [1, 3, 6, 10, 15] 1.up_to 6 . running_fold 0 (+) . should_equal [1, 3, 6, 10, 15]
1.up_to 1 . running_fold 123 (+) . should_equal [] 1.up_to 1 . running_fold 123 (+) . should_equal []
group_builder.specify "should be able to be reduced" <| group_builder.specify "should be able to be reduced" <|
1.up_to 6 . reduce (+) . should_equal 15 1.up_to 6 . reduce (+) . should_equal 15
1.up_to 6 . with_step 2 . reduce (+) . should_equal 9 1.up_to 6 . with_step 2 . reduce (+) . should_equal 9
1.up_to 1 . reduce (+) . should_fail_with Empty_Error 1.up_to 1 . reduce (+) . should_fail_with Empty_Error
1.up_to 1 . reduce (+) 0 . should_equal 0 1.up_to 1 . reduce (+) 0 . should_equal 0
group_builder.specify "should check all" <| group_builder.specify "should check all" <|
1.up_to 10 . all (> 0) . should_be_true 1.up_to 10 . all (> 0) . should_be_true
1.up_to 10 . all (< 0) . should_be_false 1.up_to 10 . all (< 0) . should_be_false
1.up_to 10 . all (Filter_Condition.Greater 10) . should_be_false 1.up_to 10 . all (Filter_Condition.Greater 10) . should_be_false
1.up_to 10 . all (Filter_Condition.Greater 10 Filter_Action.Remove) . should_be_true
Test.expect_panic_with (1.up_to 10 . all "invalid arg") Type_Error Test.expect_panic_with (1.up_to 10 . all "invalid arg") Type_Error
group_builder.specify "should check any" <| group_builder.specify "should check any" <|
1.up_to 10 . any (> 5) . should_be_true 1.up_to 10 . any (> 5) . should_be_true
1.up_to 10 . any (> 10) . should_be_false 1.up_to 10 . any (> 10) . should_be_false
1.up_to 10 . any (Filter_Condition.Greater 5) . should_be_true 1.up_to 10 . any (Filter_Condition.Greater 5) . should_be_true
1.up_to 10 . any (Filter_Condition.Equal_Or_Greater 1 Filter_Action.Remove) . should_be_false
Test.expect_panic_with (1.up_to 10 . any "invalid arg") Type_Error Test.expect_panic_with (1.up_to 10 . any "invalid arg") Type_Error
group_builder.specify "should find elements" <| group_builder.specify "should find elements" <|
1.up_to 10 . find (> 5) . should_equal 6 1.up_to 10 . find (> 5) . should_equal 6
1.up_to 10 . find (Filter_Condition.Greater than=5) . should_equal 6 1.up_to 10 . find (Filter_Condition.Greater 5) . should_equal 6
1.up_to 10 . find (Filter_Condition.Equal_Or_Less 3 Filter_Action.Remove) . should_equal 4
1.up_to 10 . find (> 10) . should_be_a Nothing 1.up_to 10 . find (> 10) . should_be_a Nothing
1.up_to 10 . find (v-> v%4 == 0) start=6 . should_equal 8 1.up_to 10 . find (v-> v%4 == 0) start=6 . should_equal 8
1.up_to 10 . find (< 5) start=6 . should_be_a Nothing 1.up_to 10 . find (< 5) start=6 . should_be_a Nothing
1.up_to 10 . find (< 5) start=10 . should_fail_with Index_Out_Of_Bounds 1.up_to 10 . find (< 5) start=10 . should_fail_with Index_Out_Of_Bounds
1.up_to 10 . find (< 5) start=10 . catch . should_equal (Index_Out_Of_Bounds.Error 10 10) 1.up_to 10 . find (< 5) start=10 . catch . should_equal (Index_Out_Of_Bounds.Error 10 10)
Test.expect_panic_with (1.up_to 10 . find "invalid arg") Type_Error Test.expect_panic_with (1.up_to 10 . find "invalid arg") Type_Error
group_builder.specify "should find index of elements" <| group_builder.specify "should find index of elements" <|
1.up_to 10 . index_of (> 5) . should_equal 5 1.up_to 10 . index_of (> 5) . should_equal 5
1.up_to 10 . index_of 7 . should_equal 6 1.up_to 10 . index_of 7 . should_equal 6
@ -253,9 +287,11 @@ add_specs suite_builder = suite_builder.group "Range" group_builder->
1.up_to 10 . index_of (< 5) start=10 . catch . should_equal (Index_Out_Of_Bounds.Error 10 10) 1.up_to 10 . index_of (< 5) start=10 . catch . should_equal (Index_Out_Of_Bounds.Error 10 10)
1.up_to 10 . index_of (< 5) start=-1 . should_equal Nothing 1.up_to 10 . index_of (< 5) start=-1 . should_equal Nothing
1.up_to 10 . index_of (< 5) start=-9 . should_equal 0 1.up_to 10 . index_of (< 5) start=-9 . should_equal 0
1.up_to 10 . index_of (Filter_Condition.Greater than=5) . should_equal 5 1.up_to 10 . index_of (Filter_Condition.Greater 5) . should_equal 5
1.up_to 10 . index_of (Filter_Condition.Less 5 Filter_Action.Remove) . should_equal 4
1.up_to 10 . index_of "invalid arg" . should_fail_with Illegal_Argument 1.up_to 10 . index_of "invalid arg" . should_fail_with Illegal_Argument
1.up_to 10 . index_of 2.5 . should_fail_with Illegal_Argument 1.up_to 10 . index_of 2.5 . should_fail_with Illegal_Argument
group_builder.specify "should find last index of elements" <| group_builder.specify "should find last index of elements" <|
1.up_to 10 . last_index_of (> 5) . should_equal 8 1.up_to 10 . last_index_of (> 5) . should_equal 8
1.up_to 10 . last_index_of 7 . should_equal 6 1.up_to 10 . last_index_of 7 . should_equal 6
@ -271,11 +307,14 @@ add_specs suite_builder = suite_builder.group "Range" group_builder->
1.up_to 10 . last_index_of (< 5) start=9 . should_fail_with Index_Out_Of_Bounds 1.up_to 10 . last_index_of (< 5) start=9 . should_fail_with Index_Out_Of_Bounds
1.up_to 10 . last_index_of (< 5) start=10 . catch . should_equal (Index_Out_Of_Bounds.Error 10 9) 1.up_to 10 . last_index_of (< 5) start=10 . catch . should_equal (Index_Out_Of_Bounds.Error 10 9)
1.up_to 10 . last_index_of (< 5) start=-10 . should_fail_with Index_Out_Of_Bounds 1.up_to 10 . last_index_of (< 5) start=-10 . should_fail_with Index_Out_Of_Bounds
1.up_to 10 . last_index_of (Filter_Condition.Greater than=5) . should_equal 8 1.up_to 10 . last_index_of (Filter_Condition.Greater 5) . should_equal 8
1.up_to 10 . last_index_of (Filter_Condition.Greater 5 Filter_Action.Remove) . should_equal 4
1.up_to 10 . last_index_of "invalid arg" . should_fail_with Illegal_Argument 1.up_to 10 . last_index_of "invalid arg" . should_fail_with Illegal_Argument
1.up_to 10 . last_index_of 2.5 . should_fail_with Illegal_Argument 1.up_to 10 . last_index_of 2.5 . should_fail_with Illegal_Argument
group_builder.specify "should allow conversion to vector" <| group_builder.specify "should allow conversion to vector" <|
1.up_to 6 . to_vector . should_equal [1, 2, 3, 4, 5] 1.up_to 6 . to_vector . should_equal [1, 2, 3, 4, 5]
group_builder.specify "should allow reversing" <| group_builder.specify "should allow reversing" <|
1.up_to 6 . reverse . should_equal (5.down_to 0) 1.up_to 6 . reverse . should_equal (5.down_to 0)
5.down_to 0 . reverse . should_equal (1.up_to 6) 5.down_to 0 . reverse . should_equal (1.up_to 6)
@ -297,7 +336,6 @@ add_specs suite_builder = suite_builder.group "Range" group_builder->
5.down_to 0 . contains 2.5 . should_fail_with Illegal_Argument 5.down_to 0 . contains 2.5 . should_fail_with Illegal_Argument
5.down_to 0 . contains 3.0 . should_fail_with Illegal_Argument 5.down_to 0 . contains 3.0 . should_fail_with Illegal_Argument
verify_contains range expected unexpected = verify_contains range expected unexpected =
expected.each x-> expected.each x->
if range.contains x . not then if range.contains x . not then
@ -305,10 +343,12 @@ add_specs suite_builder = suite_builder.group "Range" group_builder->
unexpected.each x-> unexpected.each x->
if range.contains x then if range.contains x then
Test.fail "Range "+range.to_text+" unexpectedly contained "+x.to_text+"." Test.fail "Range "+range.to_text+" unexpectedly contained "+x.to_text+"."
build_with_each range = build_with_each range =
builder = Vector.new_builder builder = Vector.new_builder
range.each builder.append range.each builder.append
builder.to_vector builder.to_vector
group_builder.specify "should behave correctly if it is empty" <| group_builder.specify "should behave correctly if it is empty" <|
check_empty_range r = check_empty_range r =
r.is_empty . should_be_true r.is_empty . should_be_true

View File

@ -164,6 +164,7 @@ type_spec suite_builder name alter = suite_builder.group name group_builder->
vec.any (ix -> ix < 0) . should_be_false vec.any (ix -> ix < 0) . should_be_false
vec.any (Filter_Condition.Greater 0) . should_be_true vec.any (Filter_Condition.Greater 0) . should_be_true
vec.any (Filter_Condition.Greater 0 Filter_Action.Remove) . should_be_false
vec.any (Filter_Condition.Less 3) . should_be_true vec.any (Filter_Condition.Less 3) . should_be_true
vec.any (Filter_Condition.Less 0) . should_be_false vec.any (Filter_Condition.Less 0) . should_be_false
@ -175,6 +176,7 @@ type_spec suite_builder name alter = suite_builder.group name group_builder->
vec.all (ix -> ix < 5) . should_be_false vec.all (ix -> ix < 5) . should_be_false
vec.all (Filter_Condition.Greater 0) . should_be_true vec.all (Filter_Condition.Greater 0) . should_be_true
vec.all (Filter_Condition.Greater 0 Filter_Action.Remove) . should_be_false
vec.all (Filter_Condition.Less 3) . should_be_false vec.all (Filter_Condition.Less 3) . should_be_false
Test.expect_panic_with matcher=Type_Error (vec.all "invalid argument") Test.expect_panic_with matcher=Type_Error (vec.all "invalid argument")
@ -203,55 +205,84 @@ type_spec suite_builder name alter = suite_builder.group name group_builder->
vec.filter (x -> x < 0) . should_equal [] vec.filter (x -> x < 0) . should_equal []
vec.filter (x -> if x == 2 then Error.throw <| My_Error.Error "foo" else True) . should_fail_with My_Error vec.filter (x -> if x == 2 then Error.throw <| My_Error.Error "foo" else True) . should_fail_with My_Error
group_builder.specify "should filter elements by Filter_Condition" <| group_builder.specify "should filter numerical elements by Filter_Condition" <|
vec = alter [1, 2, 3, 4, 5] vec = alter [1, 2, 3, 4, 5]
vec.filter (Filter_Condition.Greater than=3) . should_equal [4, 5] vec.filter (Filter_Condition.Greater 3) . should_equal [4, 5]
vec.filter (Filter_Condition.Less than=3.5) . should_equal [1, 2, 3] vec.filter (Filter_Condition.Greater 3 Filter_Action.Remove) . should_equal [1, 2, 3]
vec.filter (Filter_Condition.Equal to=3) . should_equal [3] vec.filter (Filter_Condition.Less 3.5) . should_equal [1, 2, 3]
vec.filter (Filter_Condition.Equal to=3.0) . should_equal [3] vec.filter (Filter_Condition.Less 3.5 Filter_Action.Remove) . should_equal [4, 5]
vec.filter (Filter_Condition.Equal to=3.1) . should_equal [] vec.filter (Filter_Condition.Equal 3) . should_equal [3]
vec.filter (Filter_Condition.Not_Equal to=3) . should_equal [1, 2, 4, 5] vec.filter (Filter_Condition.Equal 3 Filter_Action.Remove) . should_equal [1, 2, 4, 5]
vec.filter (Filter_Condition.Equal_Or_Greater than=3) . should_equal [3, 4, 5] vec.filter (Filter_Condition.Not_Equal 3) . should_equal [1, 2, 4, 5]
vec.filter (Filter_Condition.Equal_Or_Less than=(-1)) . should_equal [] vec.filter (Filter_Condition.Not_Equal 3 Filter_Action.Remove) . should_equal [3]
vec.filter (Filter_Condition.Equal_Or_Greater 3) . should_equal [3, 4, 5]
vec.filter (Filter_Condition.Equal_Or_Greater 3 Filter_Action.Remove) . should_equal [1, 2]
vec.filter (Filter_Condition.Equal_Or_Less (-1)) . should_equal []
vec.filter (Filter_Condition.Equal_Or_Less (-1) Filter_Action.Remove) . should_equal [1, 2, 3, 4, 5]
vec.filter (Filter_Condition.Between 2 4) . should_equal [2, 3, 4] vec.filter (Filter_Condition.Between 2 4) . should_equal [2, 3, 4]
vec.filter (Filter_Condition.Between 2.1 4.5) . should_equal [3, 4] vec.filter (Filter_Condition.Between 2.1 4.5) . should_equal [3, 4]
vec.filter (Filter_Condition.Between 2 4 Filter_Action.Remove) . should_equal [1, 5]
vec.filter (Filter_Condition.Is_In [7, 3, 2, 2, 2]) . should_equal [2, 3] vec.filter (Filter_Condition.Is_In [7, 3, 2, 2, 2]) . should_equal [2, 3]
vec.filter (Filter_Condition.Is_In []) . should_equal [] vec.filter (Filter_Condition.Is_In [7, 3, 2] Filter_Action.Remove) . should_equal [1, 4, 5]
vec.filter (Filter_Condition.Not_In [7, 3, 2, 2]) . should_equal [1, 4, 5]
Test.expect_panic_with (vec.filter (Filter_Condition.Starts_With "a")) Type_Error
vec.filter Filter_Condition.Is_True . should_equal []
vec.filter Filter_Condition.Is_False . should_equal []
vec.filter Filter_Condition.Is_Nothing . should_equal [] vec.filter Filter_Condition.Is_Nothing . should_equal []
vec.filter Filter_Condition.Not_Nothing . should_equal vec vec.filter (Filter_Condition.Is_Nothing Filter_Action.Remove) . should_equal [1, 2, 3, 4, 5]
vec.filter Filter_Condition.Not_Nothing . should_equal [1, 2, 3, 4, 5]
vec.filter (Filter_Condition.Not_Nothing Filter_Action.Remove) . should_equal []
txtvec = ["aaa", "bbb", "abab", "cccc", "baaa", "ś"] numvec = alter [1, 2.5, Number.nan, Number.positive_infinity, Number.negative_infinity, 0]
# We need to use to_text because NaN!=NaN
numvec.filter Filter_Condition.Is_Nan . map .to_text . should_equal ["NaN"]
numvec.filter (Filter_Condition.Is_Nan Filter_Action.Remove) . should_equal [1, 2.5, Number.positive_infinity, Number.negative_infinity, 0]
numvec.filter Filter_Condition.Is_Infinite . should_equal [Number.positive_infinity, Number.negative_infinity]
numvec.filter (Filter_Condition.Is_Infinite Filter_Action.Remove) . length . should_equal 4
numvec.filter Filter_Condition.Is_Finite . should_equal [1, 2.5, 0]
numvec.filter (Filter_Condition.Is_Finite Filter_Action.Remove) . length . should_equal 3
## Text based filters should fail with type error
Test.expect_panic Type_Error (vec.filter (Filter_Condition.Starts_With "a"))
Test.expect_panic Type_Error (vec.filter (Filter_Condition.Ends_With "a"))
Test.expect_panic Type_Error (vec.filter (Filter_Condition.Contains "a"))
Test.expect_panic Type_Error (vec.filter (Filter_Condition.Equal_Ignore_Case "a"))
Test.expect_panic Type_Error (vec.filter (Filter_Condition.Like "a%"))
Test.expect_panic Type_Error (vec.filter Filter_Condition.Is_Empty)
Test.expect_panic Type_Error (vec.filter Filter_Condition.Not_Empty)
## Boolean based filters should fail with type error
Test.expect_panic Type_Error (vec.filter Filter_Condition.Is_True)
Test.expect_panic Type_Error (vec.filter Filter_Condition.Is_False)
group_builder.specify "should filter text elements by Filter_Condition" <|
txtvec = alter ["aaa", "bbb", "abab", "cccc", "baaa", "ś"]
txtvec.filter (Filter_Condition.Contains "a") . should_equal ["aaa", "abab", "baaa"] txtvec.filter (Filter_Condition.Contains "a") . should_equal ["aaa", "abab", "baaa"]
txtvec.filter (Filter_Condition.Contains "a" action=Filter_Action.Remove) . should_equal ["bbb", "cccc", "ś"]
txtvec.filter (Filter_Condition.Contains 'A' Case_Sensitivity.Sensitive) . should_equal [] txtvec.filter (Filter_Condition.Contains 'A' Case_Sensitivity.Sensitive) . should_equal []
txtvec.filter (Filter_Condition.Contains 'A' Case_Sensitivity.Insensitive) . should_equal ["aaa", "abab", "baaa"] txtvec.filter (Filter_Condition.Contains 'A' Case_Sensitivity.Insensitive) . should_equal ["aaa", "abab", "baaa"]
txtvec.filter (Filter_Condition.Contains 's\u0301') . should_equal ["ś"] txtvec.filter (Filter_Condition.Contains 's\u0301') . should_equal ["ś"]
txtvec.filter (Filter_Condition.Contains 'S\u0301' Case_Sensitivity.Sensitive) . should_equal [] txtvec.filter (Filter_Condition.Contains 'S\u0301' Case_Sensitivity.Sensitive) . should_equal []
txtvec.filter (Filter_Condition.Contains 'S\u0301' Case_Sensitivity.Insensitive) . should_equal ["ś"] txtvec.filter (Filter_Condition.Contains 'S\u0301' Case_Sensitivity.Insensitive) . should_equal ["ś"]
txtvec.filter (Filter_Condition.Not_Contains "a") . should_equal ["bbb", "cccc", "ś"] Test.expect_panic_with (txtvec.filter (Filter_Condition.Contains 42)) Unsupported_Argument_Types
txtvec.filter (Filter_Condition.Not_Contains "A" Case_Sensitivity.Sensitive) . should_equal ["aaa", "bbb", "abab", "cccc", "baaa", "ś"]
txtvec.filter (Filter_Condition.Not_Contains "A" Case_Sensitivity.Insensitive) . should_equal ["bbb", "cccc", "ś"]
txtvec.filter (Filter_Condition.Not_Contains 's\u0301') . should_equal ["aaa", "bbb", "abab", "cccc", "baaa"]
txtvec.filter (Filter_Condition.Not_Contains 'S\u0301' Case_Sensitivity.Sensitive) . should_equal ["aaa", "bbb", "abab", "cccc", "baaa", "ś"]
txtvec.filter (Filter_Condition.Not_Contains 'S\u0301' Case_Sensitivity.Insensitive) . should_equal ["aaa", "bbb", "abab", "cccc", "baaa"]
txtvec.filter (Filter_Condition.Starts_With "a") . should_equal ["aaa", "abab"] txtvec.filter (Filter_Condition.Starts_With "a") . should_equal ["aaa", "abab"]
txtvec.filter (Filter_Condition.Starts_With "a" action=Filter_Action.Remove) . should_equal ["bbb", "cccc", "baaa", "ś"]
txtvec.filter (Filter_Condition.Starts_With "A" Case_Sensitivity.Sensitive) . should_equal [] txtvec.filter (Filter_Condition.Starts_With "A" Case_Sensitivity.Sensitive) . should_equal []
txtvec.filter (Filter_Condition.Starts_With "A" Case_Sensitivity.Insensitive) . should_equal ["aaa", "abab"] txtvec.filter (Filter_Condition.Starts_With "A" Case_Sensitivity.Insensitive) . should_equal ["aaa", "abab"]
Test.expect_panic_with (txtvec.filter (Filter_Condition.Starts_With 42)) Unsupported_Argument_Types
txtvec.filter (Filter_Condition.Ends_With "a") . should_equal ["aaa", "baaa"] txtvec.filter (Filter_Condition.Ends_With "a") . should_equal ["aaa", "baaa"]
txtvec.filter (Filter_Condition.Ends_With "a" action=Filter_Action.Remove) . should_equal ["bbb", "abab", "cccc", "ś"]
txtvec.filter (Filter_Condition.Ends_With "A" Case_Sensitivity.Sensitive) . should_equal [] txtvec.filter (Filter_Condition.Ends_With "A" Case_Sensitivity.Sensitive) . should_equal []
txtvec.filter (Filter_Condition.Ends_With "A" Case_Sensitivity.Insensitive) . should_equal ["aaa", "baaa"] txtvec.filter (Filter_Condition.Ends_With "A" Case_Sensitivity.Insensitive) . should_equal ["aaa", "baaa"]
Test.expect_panic_with (txtvec.filter (Filter_Condition.Ends_With 42)) Unsupported_Argument_Types
txtvec.filter (Filter_Condition.Less than="a") . should_equal [] txtvec.filter (Filter_Condition.Less than="a") . should_equal []
txtvec.filter (Filter_Condition.Greater than="b") . should_equal ["bbb", "cccc", "baaa", "ś"] txtvec.filter (Filter_Condition.Greater than="b") . should_equal ["bbb", "cccc", "baaa", "ś"]
txtvec.filter (Filter_Condition.Between "b" "c") . should_equal ["bbb", "baaa"] txtvec.filter (Filter_Condition.Between "b" "c") . should_equal ["bbb", "baaa"]
Test.expect_panic_with (txtvec.filter (Filter_Condition.Starts_With 42)) Unsupported_Argument_Types
txtvec.filter Filter_Condition.Is_True . should_equal []
txtvec.filter (Filter_Condition.Is_In [1, 2]) . should_equal [] txtvec.filter (Filter_Condition.Is_In [1, 2]) . should_equal []
txtvec.filter (Filter_Condition.Is_In ["bbb", 's\u0301', "bbb", "FOOBAR"]) . should_equal ["bbb", "ś"] txtvec.filter (Filter_Condition.Is_In ["bbb", 's\u0301', "bbb", "FOOBAR"]) . should_equal ["bbb", "ś"]
## Boolean based filters should fail with type error
Test.expect_panic Type_Error (txtvec.filter Filter_Condition.Is_True)
Test.expect_panic Type_Error (txtvec.filter Filter_Condition.Is_False)
alter ["", Nothing, " ", "a"] . filter (Filter_Condition.Is_Empty) . should_equal ["", Nothing] alter ["", Nothing, " ", "a"] . filter (Filter_Condition.Is_Empty) . should_equal ["", Nothing]
alter ["", Nothing, " ", "a"] . filter (Filter_Condition.Not_Empty) . should_equal [" ", "a"] alter ["", Nothing, " ", "a"] . filter (Filter_Condition.Not_Empty) . should_equal [" ", "a"]
alter ["abab", "aaabaaaa", "ba"] . filter (Filter_Condition.Like "ba") . should_equal ["ba"] alter ["abab", "aaabaaaa", "ba"] . filter (Filter_Condition.Like "ba") . should_equal ["ba"]
@ -259,18 +290,23 @@ type_spec suite_builder name alter = suite_builder.group name group_builder->
alter ["abab", "aaabaaaa"] . filter (Filter_Condition.Like "%ba__%") . should_equal ["aaabaaaa"] alter ["abab", "aaabaaaa"] . filter (Filter_Condition.Like "%ba__%") . should_equal ["aaabaaaa"]
alter ["aaaa", "bbbbb", "[ab]aaaa"] . filter (Filter_Condition.Like "[ab]%") . should_equal ["[ab]aaaa"] alter ["aaaa", "bbbbb", "[ab]aaaa"] . filter (Filter_Condition.Like "[ab]%") . should_equal ["[ab]aaaa"]
alter ["f.txt", "abc.*"] . filter (Filter_Condition.Like "%.*") . should_equal ["abc.*"] alter ["f.txt", "abc.*"] . filter (Filter_Condition.Like "%.*") . should_equal ["abc.*"]
alter ["f.txt", "abc.*"] . filter (Filter_Condition.Not_Like "%.*") . should_equal ["f.txt"]
txt2 = alter ['a\n\n\n', 'a\n', 'a\n\n\nb', 'a\nb', 'caa\nbb'] txt2 = alter ['a\n\n\n', 'a\n', 'a\n\n\nb', 'a\nb', 'caa\nbb']
txt2.filter (Filter_Condition.Like 'a_') . should_equal ['a\n'] txt2.filter (Filter_Condition.Like 'a_') . should_equal ['a\n']
txt2.filter (Filter_Condition.Like 'a_' Filter_Action.Remove) . should_equal ['a\n\n\n', 'a\n\n\nb', 'a\nb', 'caa\nbb']
txt2.filter (Filter_Condition.Like 'a%') . should_equal ['a\n\n\n', 'a\n', 'a\n\n\nb', 'a\nb'] txt2.filter (Filter_Condition.Like 'a%') . should_equal ['a\n\n\n', 'a\n', 'a\n\n\nb', 'a\nb']
txt2.filter (Filter_Condition.Like 'a_b') . should_equal ['a\nb'] txt2.filter (Filter_Condition.Like 'a_b') . should_equal ['a\nb']
txt2.filter (Filter_Condition.Like '%\nb') . should_equal ['a\n\n\nb', 'a\nb'] txt2.filter (Filter_Condition.Like '%\nb') . should_equal ['a\n\n\nb', 'a\nb']
## NUmber based filters should fail with type error
Test.expect_panic Type_Error (txtvec.filter Filter_Condition.Is_Nan)
Test.expect_panic Type_Error (txtvec.filter Filter_Condition.Is_Infinite)
Test.expect_panic Type_Error (txtvec.filter Filter_Condition.Is_Finite)
group_builder.specify "should filter unicode text elements by Filter_Condition" <|
txt3 = alter ['śnieg', 's\u0301nieg', 'X', 'połać', 'połac\u0301'] txt3 = alter ['śnieg', 's\u0301nieg', 'X', 'połać', 'połac\u0301']
txt3.filter (Filter_Condition.Starts_With 'ś') . should_equal ['śnieg', 's\u0301nieg'] txt3.filter (Filter_Condition.Starts_With 'ś') . should_equal ['śnieg', 's\u0301nieg']
txt3.filter (Filter_Condition.Contains 'ś') . should_equal ['śnieg', 's\u0301nieg'] txt3.filter (Filter_Condition.Contains 'ś') . should_equal ['śnieg', 's\u0301nieg']
txt3.filter (Filter_Condition.Not_Contains 'ś') . should_equal ['X', 'połać', 'połac\u0301']
txt3.filter (Filter_Condition.Ends_With 'ś') . should_equal [] txt3.filter (Filter_Condition.Ends_With 'ś') . should_equal []
txt3.filter (Filter_Condition.Ends_With 'ć') . should_equal ['połać', 'połac\u0301'] txt3.filter (Filter_Condition.Ends_With 'ć') . should_equal ['połać', 'połac\u0301']
## There is a bug with Java Regex in Unicode normalized mode (CANON_EQ) with quoting. ## There is a bug with Java Regex in Unicode normalized mode (CANON_EQ) with quoting.
@ -284,19 +320,12 @@ type_spec suite_builder name alter = suite_builder.group name group_builder->
txt4.filter (Filter_Condition.Equal_Ignore_Case 's\u0301') . should_equal ['ś', 'Ś'] txt4.filter (Filter_Condition.Equal_Ignore_Case 's\u0301') . should_equal ['ś', 'Ś']
txt4.filter (Filter_Condition.Equal_Ignore_Case 'FFI') . should_equal ['ffi'] txt4.filter (Filter_Condition.Equal_Ignore_Case 'FFI') . should_equal ['ffi']
group_builder.specify "should filter mixed elements by Filter_Condition" <|
mixed = alter [1, Nothing, "b"] mixed = alter [1, Nothing, "b"]
mixed.filter Filter_Condition.Is_Nothing . should_equal [Nothing] mixed.filter Filter_Condition.Is_Nothing . should_equal [Nothing]
mixed.filter Filter_Condition.Not_Nothing . should_equal [1, "b"] mixed.filter Filter_Condition.Not_Nothing . should_equal [1, "b"]
mixed.filter Filter_Condition.Is_Empty . should_equal [Nothing] Test.expect_panic Type_Error (mixed.filter Filter_Condition.Is_Empty)
mixed.filter Filter_Condition.Not_Empty . should_equal [1, "b"] Test.expect_panic Type_Error (mixed.filter Filter_Condition.Not_Empty)
numvec = alter [1, 2.5, Number.nan, Number.positive_infinity, Number.negative_infinity, 0]
# We need to use to_text because NaN!=NaN
numvec.filter Filter_Condition.Is_Nan . map .to_text . should_equal ["NaN"]
numvec.filter Filter_Condition.Is_Infinite . should_equal [Number.positive_infinity, Number.negative_infinity]
numvec.filter Filter_Condition.Is_Finite . should_equal [1, 2.5, 0]
Test.expect_panic Type_Error (txtvec.filter Filter_Condition.Is_Finite)
(alter [2, "a"]).filter (Filter_Condition.Greater 1) . should_fail_with Incomparable_Values (alter [2, "a"]).filter (Filter_Condition.Greater 1) . should_fail_with Incomparable_Values
@ -320,8 +349,6 @@ type_spec suite_builder name alter = suite_builder.group name group_builder->
txtvec.filter (Filter_Condition.Starts_With "a") . should_equal ["abab"] txtvec.filter (Filter_Condition.Starts_With "a") . should_equal ["abab"]
txtvec.filter (Filter_Condition.Ends_With "a") . should_equal ["baaa"] txtvec.filter (Filter_Condition.Ends_With "a") . should_equal ["baaa"]
txtvec.filter (Filter_Condition.Like "b%a") . should_equal ["baaa"] txtvec.filter (Filter_Condition.Like "b%a") . should_equal ["baaa"]
# Nothing is not included in the negation either
txtvec.filter (Filter_Condition.Not_Like "b%a") . should_equal ["abab", "cccc", "BAAA"]
(alter ["a", 2, Nothing, 3]).filter (Filter_Condition.Is_In [Nothing, 2]) . should_equal [2, Nothing] (alter ["a", 2, Nothing, 3]).filter (Filter_Condition.Is_In [Nothing, 2]) . should_equal [2, Nothing]
@ -340,11 +367,12 @@ type_spec suite_builder name alter = suite_builder.group name group_builder->
(alter [1, 2, 3, 4] . filter_with_index ix-> _-> if ix == 1 then Error.throw <| My_Error.Error "foo" else True) . should_fail_with My_Error (alter [1, 2, 3, 4] . filter_with_index ix-> _-> if ix == 1 then Error.throw <| My_Error.Error "foo" else True) . should_fail_with My_Error
group_builder.specify "should partition elements" <| group_builder.specify "should partition elements" <|
vec = alter [1, 2, 3, 4, 5] vec = alter [1, 2, 3, 4, 5, Nothing]
vec.partition (x -> x % 2 == 0) . should_equal <| Pair.new [2, 4] [1, 3, 5] vec.partition (x -> x.is_nothing.not && x%2==0) . should_equal <| Pair.new [2, 4] [1, 3, 5, Nothing]
(vec . partition x-> if x == 1 then Error.throw <| My_Error.Error "foo" else True) . should_fail_with My_Error (vec . partition x-> if x == 1 then Error.throw <| My_Error.Error "foo" else True) . should_fail_with My_Error
vec.partition (Filter_Condition.Between 2 4) . should_equal <| Pair.new [2, 3, 4] [1, 5] vec.partition (Filter_Condition.Between 2 4) . should_equal <| Pair.new [2, 3, 4] [1, 5, Nothing]
vec.partition (Filter_Condition.Between 2 4 Filter_Action.Remove) . should_equal <| Pair.new [1, 5, Nothing] [2, 3, 4]
Test.expect_panic_with matcher=Type_Error (vec.partition "invalid arg") Test.expect_panic_with matcher=Type_Error (vec.partition "invalid arg")
@ -462,6 +490,7 @@ type_spec suite_builder name alter = suite_builder.group name group_builder->
input.find (x -> x%3 == 3) if_missing=Nothing . should_equal Nothing input.find (x -> x%3 == 3) if_missing=Nothing . should_equal Nothing
input.find (Filter_Condition.Greater 5) . should_equal 6 input.find (Filter_Condition.Greater 5) . should_equal 6
input.find (Filter_Condition.Less 5 Filter_Action.Remove) . should_equal 5
Test.expect_panic_with matcher=Type_Error (input.find "invalid arg") Test.expect_panic_with matcher=Type_Error (input.find "invalid arg")
alter ["b", "A", "c"] . find (Filter_Condition.Equal_Ignore_Case "a") . should_equal "A" alter ["b", "A", "c"] . find (Filter_Condition.Equal_Ignore_Case "a") . should_equal "A"
@ -480,6 +509,7 @@ type_spec suite_builder name alter = suite_builder.group name group_builder->
input.index_of 2 start=-11 . should_fail_with Index_Out_Of_Bounds input.index_of 2 start=-11 . should_fail_with Index_Out_Of_Bounds
input.index_of (Filter_Condition.Equal_Or_Greater 2) . should_equal 1 input.index_of (Filter_Condition.Equal_Or_Greater 2) . should_equal 1
input.index_of (Filter_Condition.Less 3 Filter_Action.Remove) . should_equal 2
input.index_of "text" . should_equal Nothing input.index_of "text" . should_equal Nothing
group_builder.specify "should allow finding the last index of a value" <| group_builder.specify "should allow finding the last index of a value" <|
@ -494,6 +524,7 @@ type_spec suite_builder name alter = suite_builder.group name group_builder->
input.last_index_of 2 start=-11 . should_fail_with Index_Out_Of_Bounds input.last_index_of 2 start=-11 . should_fail_with Index_Out_Of_Bounds
input.last_index_of (Filter_Condition.Equal_Or_Greater 2) . should_equal input.length-2 input.last_index_of (Filter_Condition.Equal_Or_Greater 2) . should_equal input.length-2
input.last_index_of (Filter_Condition.Less 3 Filter_Action.Remove) . should_equal 6
input.last_index_of "text" . should_equal Nothing input.last_index_of "text" . should_equal Nothing
group_builder.specify "should be convertible to a list" <| group_builder.specify "should be convertible to a list" <|

View File

@ -596,6 +596,18 @@ add_specs suite_builder setup =
actual.at "col1" . to_vector . should_equal [1000, 200, 1000, 400, 500, 1000] actual.at "col1" . to_vector . should_equal [1000, 200, 1000, 400, 500, 1000]
actual.column_names . should_equal ["col0", "col_between", "col1", "def"] actual.column_names . should_equal ["col0", "col_between", "col1", "def"]
group_builder.specify "fill_nothing should cope with notted boolean columns" <|
t = table_builder [["col0", [True, False, Nothing, True]], ["colTrue", [True, True, True, True]], ["colFalse", [False, False, False, False]]]
s = t.set (t.at "col0" . not) "col1"
s_false = s.fill_nothing ["col1"] False
s_false.at "col1" . to_vector . should_equal [False, True, False, False]
s_false_2 = s.fill_nothing ["col1"] (s.at "colFalse")
s_false_2.at "col1" . to_vector . should_equal [False, True, False, False]
s_true = s.fill_nothing ["col1"] True
s_true.at "col1" . to_vector . should_equal [False, True, True, False]
s_true_2 = s.fill_nothing ["col1"] (s.at "colTrue")
s_true_2.at "col1" . to_vector . should_equal [False, True, True, False]
suite_builder.group prefix+"Table.text_replace" group_builder-> suite_builder.group prefix+"Table.text_replace" group_builder->
data = Data.setup create_connection_fn data = Data.setup create_connection_fn

View File

@ -136,6 +136,7 @@ add_specs suite_builder setup =
group_builder.specify "if" <| group_builder.specify "if" <|
t = table_builder [["A", [1, 100]], ["B", [10, 40]], ["C", [23, 55]]] t = table_builder [["A", [1, 100]], ["B", [10, 40]], ["C", [23, 55]]]
t.set (Column_Operation.If (Column_Ref.Name "A") (Filter_Condition.Greater than=(Column_Ref.Name "B"))) "Z" . at "Z" . to_vector . should_equal [False, True] t.set (Column_Operation.If (Column_Ref.Name "A") (Filter_Condition.Greater than=(Column_Ref.Name "B"))) "Z" . at "Z" . to_vector . should_equal [False, True]
t.set (Column_Operation.If (Column_Ref.Name "A") (Filter_Condition.Greater than=(Column_Ref.Name "B") Filter_Action.Remove)) "Z" . at "Z" . to_vector . should_equal [True, False]
t.set (Column_Operation.If (Column_Ref.Name "A") (Filter_Condition.Greater than=20) "T" "F") "Z" . at "Z" . to_vector . should_equal ["F", "T"] t.set (Column_Operation.If (Column_Ref.Name "A") (Filter_Condition.Greater than=20) "T" "F") "Z" . at "Z" . to_vector . should_equal ["F", "T"]
t.set (Column_Operation.If (Column_Ref.Name "A") (Filter_Condition.Less than=20) (Column_Ref.Name "B") (Column_Ref.Name "C")) "Z" . at "Z" . to_vector . should_equal [10, 55] t.set (Column_Operation.If (Column_Ref.Name "A") (Filter_Condition.Less than=20) (Column_Ref.Name "B") (Column_Ref.Name "C")) "Z" . at "Z" . to_vector . should_equal [10, 55]
@ -148,19 +149,15 @@ add_specs suite_builder setup =
t2.set (Column_Operation.If (Column_Ref.Name "A") (Filter_Condition.Equal_Ignore_Case "C") "==" "!=") "Z" . at "Z" . to_vector . should_equal ["!=", "=="] t2.set (Column_Operation.If (Column_Ref.Name "A") (Filter_Condition.Equal_Ignore_Case "C") "==" "!=") "Z" . at "Z" . to_vector . should_equal ["!=", "=="]
t2.set (Column_Operation.If (Column_Ref.Name "A") (Filter_Condition.Is_In ["x", "a", "dd"]) "TT" "FF") "Z" . at "Z" . to_vector . should_equal ["TT", "FF"] t2.set (Column_Operation.If (Column_Ref.Name "A") (Filter_Condition.Is_In ["x", "a", "dd"]) "TT" "FF") "Z" . at "Z" . to_vector . should_equal ["TT", "FF"]
t2.set (Column_Operation.If (Column_Ref.Name "A") (Filter_Condition.Not_In ["x", "a", "dd"]) "TT" "FF") "Z" . at "Z" . to_vector . should_equal ["FF", "TT"]
t2.set (Column_Operation.If (Column_Ref.Name "A") (Filter_Condition.Is_In []) "TT" "FF") "Z" . at "Z" . to_vector . should_equal ["FF", "FF"] t2.set (Column_Operation.If (Column_Ref.Name "A") (Filter_Condition.Is_In []) "TT" "FF") "Z" . at "Z" . to_vector . should_equal ["FF", "FF"]
t2.set (Column_Operation.If (Column_Ref.Name "A") (Filter_Condition.Not_In []) "TT" "FF") "Z" . at "Z" . to_vector . should_equal ["TT", "TT"]
# Passing a column does not work row-by-row, but looks at whole column contents. # Passing a column does not work row-by-row, but looks at whole column contents.
t2.set (Column_Operation.If (Column_Ref.Name "A") (Filter_Condition.Is_In (t2.at "B")) "TT" "FF") "Z" . at "Z" . to_vector . should_equal ["FF", "TT"] t2.set (Column_Operation.If (Column_Ref.Name "A") (Filter_Condition.Is_In (t2.at "B")) "TT" "FF") "Z" . at "Z" . to_vector . should_equal ["FF", "TT"]
t3 = table_builder [["x", ["e", "e", "a"]]] t3 = table_builder [["x", ["e", "e", "a"]]]
t2.set (Column_Operation.If (Column_Ref.Name "A") (Filter_Condition.Is_In (t3.at "x")) "TT" "FF") "Z" . at "Z" . to_vector . should_equal ["TT", "FF"] t2.set (Column_Operation.If (Column_Ref.Name "A") (Filter_Condition.Is_In (t3.at "x")) "TT" "FF") "Z" . at "Z" . to_vector . should_equal ["TT", "FF"]
# Thus, passing a Column_Ref into Is_In/Not_In is not allowed as it would be confusing. # Thus, passing a Column_Ref into Is_In is not allowed as it would be confusing.
t2.set (Column_Operation.If (Column_Ref.Name "A") (Filter_Condition.Is_In (Column_Ref.Name "B")) "TT" "FF") . should_fail_with Illegal_Argument t2.set (Column_Operation.If (Column_Ref.Name "A") (Filter_Condition.Is_In (Column_Ref.Name "B")) "TT" "FF") . should_fail_with Illegal_Argument
t2.set (Column_Operation.If (Column_Ref.Name "A") (Filter_Condition.Not_In (Column_Ref.Name "B")) "TT" "FF") . should_fail_with Illegal_Argument
t2.set (Column_Operation.If (Column_Ref.Name "A") (Filter_Condition.Not_In [Column_Ref.Name "B", "X"]) "TT" "FF") . should_fail_with Illegal_Argument
group_builder.specify "text" <| group_builder.specify "text" <|
t = table_builder [["A", [" a ", "b"]], ["B", ["c", " d "]]] t = table_builder [["A", [" a ", "b"]], ["B", ["c", " d "]]]

View File

@ -49,19 +49,29 @@ add_specs suite_builder setup =
group_builder.specify "by integer comparisons" <| group_builder.specify "by integer comparisons" <|
t = table_builder [["ix", [1, 2, 3, 4, 5]], ["X", [100, 3, Nothing, 4, 12]], ["Y", [100, 4, 2, Nothing, 11]]] t = table_builder [["ix", [1, 2, 3, 4, 5]], ["X", [100, 3, Nothing, 4, 12]], ["Y", [100, 4, 2, Nothing, 11]]]
t1 = t.filter "X" (Filter_Condition.Less than=10) t.filter "X" (Filter_Condition.Less than=10) . at "X" . to_vector . should_equal [3, 4]
t1.at "ix" . to_vector . should_equal [2, 4]
t1.at "X" . to_vector . should_equal [3, 4]
t.filter "X" (Filter_Condition.Less than=4) . at "X" . to_vector . should_equal [3] t.filter "X" (Filter_Condition.Less than=4) . at "X" . to_vector . should_equal [3]
t.filter "X" (Filter_Condition.Less than=4 action=Filter_Action.Remove) . at "X" . to_vector . should_equal [100, Nothing, 4, 12]
t.filter "X" (Filter_Condition.Equal_Or_Less than=4) . at "X" . to_vector . should_equal [3, 4] t.filter "X" (Filter_Condition.Equal_Or_Less than=4) . at "X" . to_vector . should_equal [3, 4]
t.filter "X" (Filter_Condition.Equal_Or_Less than=4 action=Filter_Action.Remove) . at "X" . to_vector . should_equal [100, Nothing, 12]
t.filter "X" (Filter_Condition.Greater than=4) . at "X" . to_vector . should_equal [100, 12] t.filter "X" (Filter_Condition.Greater than=4) . at "X" . to_vector . should_equal [100, 12]
t.filter "X" (Filter_Condition.Greater than=4 action=Filter_Action.Remove) . at "X" . to_vector . should_equal [3, Nothing, 4]
t.filter "X" (Filter_Condition.Equal_Or_Greater than=4) . at "X" . to_vector . should_equal [100, 4, 12] t.filter "X" (Filter_Condition.Equal_Or_Greater than=4) . at "X" . to_vector . should_equal [100, 4, 12]
t.filter "X" (Filter_Condition.Equal_Or_Greater than=4 action=Filter_Action.Remove) . at "X" . to_vector . should_equal [3, Nothing]
t.filter "X" (Filter_Condition.Between 4 100) . at "X" . to_vector . should_equal [100, 4, 12] t.filter "X" (Filter_Condition.Between 4 100) . at "X" . to_vector . should_equal [100, 4, 12]
t2 = t.filter "X" (Filter_Condition.Equal to=100) t.filter "X" (Filter_Condition.Between 4 100 action=Filter_Action.Remove) . at "X" . to_vector . should_equal [3, Nothing]
t2 . at "X" . to_vector . should_equal [100] t.filter "X" (Filter_Condition.Equal to=100) . at "X" . to_vector . should_equal [100]
t2 . at "ix" . to_vector . should_equal [1]
t.filter "X" (Filter_Condition.Equal to=123) . at "X" . to_vector . should_equal [] t.filter "X" (Filter_Condition.Equal to=123) . at "X" . to_vector . should_equal []
t.filter "X" (Filter_Condition.Equal to=3 action=Filter_Action.Remove) . at "X" . to_vector . should_equal [100, Nothing, 4, 12]
t.filter "X" (Filter_Condition.Is_Finite) . at "ix" . to_vector . should_equal [1, 2, 4, 5]
t.filter "X" (Filter_Condition.Is_Finite action=Filter_Action.Remove) . at "ix" . to_vector . should_equal [3]
t.filter "X" (Filter_Condition.Is_Infinite) . at "ix" . to_vector . should_equal []
t.filter "X" (Filter_Condition.Is_Infinite action=Filter_Action.Remove) . at "ix" . to_vector . should_equal [1, 2, 3, 4, 5]
if test_selection.is_nan_and_nothing_distinct then
t.filter "X" (Filter_Condition.Is_Nan) . at "ix" . to_vector . should_equal []
t.filter "X" (Filter_Condition.Is_Nan action=Filter_Action.Remove) . at "ix" . to_vector . should_equal [1, 2, 3, 4, 5]
v = t.filter "X" (Filter_Condition.Equal to="SOME TEXT :)") . at "X" . to_vector v = t.filter "X" (Filter_Condition.Equal to="SOME TEXT :)") . at "X" . to_vector
## We do not do typechecking at Enso level here, as it is ## We do not do typechecking at Enso level here, as it is
DB-dependent if such mixing is allowed, so we will rely on an SQL DB-dependent if such mixing is allowed, so we will rely on an SQL
@ -71,25 +81,26 @@ add_specs suite_builder setup =
False -> v.should_fail_with SQL_Error False -> v.should_fail_with SQL_Error
t.filter "X" (Filter_Condition.Equal to=(t.at "Y")) . at "X" . to_vector . should_equal [100] t.filter "X" (Filter_Condition.Equal to=(t.at "Y")) . at "X" . to_vector . should_equal [100]
t.filter "X" (Filter_Condition.Equal to=(t.at "Y") action=Filter_Action.Remove) . at "X" . to_vector . should_equal [3, Nothing, 4, 12]
t.filter "X" (Filter_Condition.Less than=(t.at "Y")) . at "X" . to_vector . should_equal [3] t.filter "X" (Filter_Condition.Less than=(t.at "Y")) . at "X" . to_vector . should_equal [3]
t.filter "X" (Filter_Condition.Less than=(t.at "Y") action=Filter_Action.Remove) . at "X" . to_vector . should_equal [100, Nothing, 4, 12]
t.filter "X" (Filter_Condition.Equal_Or_Less than=(t.at "Y")) . at "X" . to_vector . should_equal [100, 3] t.filter "X" (Filter_Condition.Equal_Or_Less than=(t.at "Y")) . at "X" . to_vector . should_equal [100, 3]
t.filter "X" (Filter_Condition.Equal_Or_Less than=(t.at "Y") action=Filter_Action.Remove) . at "X" . to_vector . should_equal [Nothing, 4, 12]
t.filter "X" (Filter_Condition.Equal_Or_Greater than=(t.at "Y")) . at "X" . to_vector . should_equal [100, 12] t.filter "X" (Filter_Condition.Equal_Or_Greater than=(t.at "Y")) . at "X" . to_vector . should_equal [100, 12]
t.filter "X" (Filter_Condition.Equal_Or_Greater than=(t.at "Y") action=Filter_Action.Remove) . at "X" . to_vector . should_equal [3, Nothing, 4]
t.filter "X" (Filter_Condition.Greater than=(t.at "Y")) . at "X" . to_vector . should_equal [12] t.filter "X" (Filter_Condition.Greater than=(t.at "Y")) . at "X" . to_vector . should_equal [12]
t.filter "X" (Filter_Condition.Greater than=(t.at "Y") action=Filter_Action.Remove) . at "X" . to_vector . should_equal [100, 3, Nothing, 4]
t.filter "Y" (Filter_Condition.Between (t.at "ix") 100) . at "Y" . to_vector . should_equal [100, 4, 11] t.filter "Y" (Filter_Condition.Between (t.at "ix") 100) . at "Y" . to_vector . should_equal [100, 4, 11]
t.filter "Y" (Filter_Condition.Between (t.at "ix") 100 action=Filter_Action.Remove) . at "Y" . to_vector . should_equal [2, Nothing]
t.filter "X" (Filter_Condition.Equal to=(Column_Ref.Name "Y")) . at "X" . to_vector . should_equal [100] t.filter "X" (Filter_Condition.Equal to=(Column_Ref.Name "Y")) . at "X" . to_vector . should_equal [100]
t.filter "X" (Filter_Condition.Equal to=(Column_Ref.Expression "[Y]-1")) . at "X" . to_vector . should_equal [3]
t.filter "X" (Filter_Condition.Less than=(Column_Ref.Name "Y")) . at "X" . to_vector . should_equal [3] t.filter "X" (Filter_Condition.Less than=(Column_Ref.Name "Y")) . at "X" . to_vector . should_equal [3]
t.filter "X" (Filter_Condition.Equal_Or_Less than=(Column_Ref.Name "Y")) . at "X" . to_vector . should_equal [100, 3] t.filter "X" (Filter_Condition.Equal_Or_Less than=(Column_Ref.Name "Y")) . at "X" . to_vector . should_equal [100, 3]
t.filter "X" (Filter_Condition.Equal_Or_Greater than=(Column_Ref.Name "Y")) . at "X" . to_vector . should_equal [100, 12] t.filter "X" (Filter_Condition.Equal_Or_Greater than=(Column_Ref.Name "Y")) . at "X" . to_vector . should_equal [100, 12]
t.filter "X" (Filter_Condition.Greater than=(Column_Ref.Name "Y")) . at "X" . to_vector . should_equal [12] t.filter "X" (Filter_Condition.Greater than=(Column_Ref.Name "Y")) . at "X" . to_vector . should_equal [12]
t.filter "Y" (Filter_Condition.Between (Column_Ref.Name "ix") 100) . at "Y" . to_vector . should_equal [100, 4, 11] t.filter "Y" (Filter_Condition.Between (Column_Ref.Name "ix") 100) . at "Y" . to_vector . should_equal [100, 4, 11]
t.filter "X" (Filter_Condition.Is_Finite) . at "ix" . to_vector . should_equal [1, 2, 4, 5]
t.filter "X" (Filter_Condition.Is_Infinite) . at "ix" . to_vector . should_equal []
if test_selection.is_nan_and_nothing_distinct then
t.filter "X" (Filter_Condition.Is_Nan) . at "ix" . to_vector . should_equal []
group_builder.specify "by float operations" <| group_builder.specify "by float operations" <|
t = table_builder [["ix", [1, 2, 3, 4, 5, 6]], ["X", [100.0, 2.5, Nothing, Number.nan, Number.positive_infinity, Number.negative_infinity]]] t = table_builder [["ix", [1, 2, 3, 4, 5, 6]], ["X", [100.0, 2.5, Nothing, Number.nan, Number.positive_infinity, Number.negative_infinity]]]
@ -109,13 +120,14 @@ add_specs suite_builder setup =
if test_selection.is_nan_and_nothing_distinct then if test_selection.is_nan_and_nothing_distinct then
t.filter "X" Filter_Condition.Is_Nan . at "ix" . to_vector . should_equal [4] t.filter "X" Filter_Condition.Is_Nan . at "ix" . to_vector . should_equal [4]
group_builder.specify "Not_Equal test cases" pending="Specification needs clarifying, see: https://github.com/enso-org/enso/issues/5241#issuecomment-1480167927" <| group_builder.specify "Not_Equal test cases" <|
t = table_builder [["ix", [1, 2, 3, 4, 5]], ["X", [100, 3, Nothing, 4, 12]], ["Y", [100, 4, 2, Nothing, 11]]] t = table_builder [["ix", [1, 2, 3, 4, 5]], ["X", [100, 3, Nothing, 4, 12]], ["Y", [100, 4, 2, Nothing, 11]]]
t3 = t.filter "X" (Filter_Condition.Not_Equal to=100) t3 = t.filter "X" (Filter_Condition.Not_Equal to=100)
t3 . at "X" . to_vector . should_equal [3, Nothing, 4, 12] t3 . at "X" . to_vector . should_equal [3, 4, 12]
t3 . at "ix" . to_vector . should_equal [2, 3, 4, 5] t3 . at "ix" . to_vector . should_equal [2, 4, 5]
t.filter "X" (Filter_Condition.Not_Equal to=(t.at "Y")) . at "X" . to_vector . should_equal [3, Nothing, 4, 12] t.filter "X" (Filter_Condition.Not_Equal to=(t.at "Y")) . at "X" . to_vector . should_equal [3, 12]
t.filter "X" (Filter_Condition.Not_Equal to=(Column_Ref.Name "Y")) . at "X" . to_vector . should_equal [3, Nothing, 4, 12] t.filter "X" (Filter_Condition.Not_Equal to=(Column_Ref.Name "Y")) . at "X" . to_vector . should_equal [3, 12]
t.filter "X" (Filter_Condition.Not_Equal to=(Column_Ref.Expression "[Y]")) . at "X" . to_vector . should_equal [3, 12]
group_builder.specify "by text comparisons" <| group_builder.specify "by text comparisons" <|
t = table_builder [["ix", [1, 2, 3, 4, 5]], ["X", ["abb", "baca", "b", Nothing, "c"]], ["Y", ["a", "b", "b", "c", "c"]]] t = table_builder [["ix", [1, 2, 3, 4, 5]], ["X", ["abb", "baca", "b", Nothing, "c"]], ["Y", ["a", "b", "b", "c", "c"]]]
@ -155,19 +167,20 @@ add_specs suite_builder setup =
t = table_builder [["ix", [1, 2, 3, 4, 5]], ["X", ["abb", "bacb", "banana", Nothing, "nana"]], ["Y", ["a", "B", "d", "c", "a"]], ["Z", ["aaaaa", "bbbbb", "[ab]", "[ab]aaaa", "[ab]ccc"]]] t = table_builder [["ix", [1, 2, 3, 4, 5]], ["X", ["abb", "bacb", "banana", Nothing, "nana"]], ["Y", ["a", "B", "d", "c", "a"]], ["Z", ["aaaaa", "bbbbb", "[ab]", "[ab]aaaa", "[ab]ccc"]]]
t.filter "X" (Filter_Condition.Starts_With "ba") . at "X" . to_vector . should_equal ["bacb", "banana"] t.filter "X" (Filter_Condition.Starts_With "ba") . at "X" . to_vector . should_equal ["bacb", "banana"]
t.filter "X" (Filter_Condition.Starts_With "ba" action=Filter_Action.Remove) . at "X" . to_vector . should_equal ["abb", Nothing, "nana"]
t.filter "X" (Filter_Condition.Starts_With "BA" Case_Sensitivity.Sensitive) . at "X" . to_vector . should_equal [] t.filter "X" (Filter_Condition.Starts_With "BA" Case_Sensitivity.Sensitive) . at "X" . to_vector . should_equal []
t.filter "X" (Filter_Condition.Starts_With "BA" Case_Sensitivity.Insensitive) . at "X" . to_vector . should_equal ["bacb", "banana"] t.filter "X" (Filter_Condition.Starts_With "BA" Case_Sensitivity.Insensitive) . at "X" . to_vector . should_equal ["bacb", "banana"]
t.filter "X" (Filter_Condition.Ends_With "na") . at "X" . to_vector . should_equal ["banana", "nana"] t.filter "X" (Filter_Condition.Ends_With "na") . at "X" . to_vector . should_equal ["banana", "nana"]
t.filter "X" (Filter_Condition.Ends_With "na" action=Filter_Action.Remove) . at "X" . to_vector . should_equal ["abb", "bacb", Nothing]
t.filter "X" (Filter_Condition.Ends_With "NA" Case_Sensitivity.Sensitive) . at "X" . to_vector . should_equal [] t.filter "X" (Filter_Condition.Ends_With "NA" Case_Sensitivity.Sensitive) . at "X" . to_vector . should_equal []
t.filter "X" (Filter_Condition.Ends_With "NA" Case_Sensitivity.Insensitive) . at "X" . to_vector . should_equal ["banana", "nana"] t.filter "X" (Filter_Condition.Ends_With "NA" Case_Sensitivity.Insensitive) . at "X" . to_vector . should_equal ["banana", "nana"]
t.filter "X" (Filter_Condition.Contains "ac") . at "X" . to_vector . should_equal ["bacb"] t.filter "X" (Filter_Condition.Contains "ac") . at "X" . to_vector . should_equal ["bacb"]
t.filter "X" (Filter_Condition.Contains "ac" action=Filter_Action.Remove) . at "X" . to_vector . should_equal ["abb", "banana", Nothing, "nana"]
t.filter "X" (Filter_Condition.Contains "AC" Case_Sensitivity.Sensitive) . at "X" . to_vector . should_equal [] t.filter "X" (Filter_Condition.Contains "AC" Case_Sensitivity.Sensitive) . at "X" . to_vector . should_equal []
t.filter "X" (Filter_Condition.Contains "AC" Case_Sensitivity.Insensitive) . at "X" . to_vector . should_equal ["bacb"] t.filter "X" (Filter_Condition.Contains "AC" Case_Sensitivity.Insensitive) . at "X" . to_vector . should_equal ["bacb"]
t.filter "X" (Filter_Condition.Not_Contains "ac") . at "X" . to_vector . should_equal ["abb", "banana", "nana"]
t.filter "X" (Filter_Condition.Not_Contains "AC" Case_Sensitivity.Sensitive) . at "X" . to_vector . should_equal ["abb", "bacb", "banana", "nana"]
t.filter "X" (Filter_Condition.Not_Contains "AC" Case_Sensitivity.Insensitive) . at "X" . to_vector . should_equal ["abb", "banana", "nana"]
t.filter "X" (Filter_Condition.Starts_With (t.at "Y")) . at "X" . to_vector . should_equal ["abb"] t.filter "X" (Filter_Condition.Starts_With (t.at "Y")) . at "X" . to_vector . should_equal ["abb"]
t.filter "X" (Filter_Condition.Starts_With (t.at "Y") action=Filter_Action.Remove) . at "X" . to_vector . should_equal ["bacb", "banana", Nothing, "nana"]
t.filter "X" (Filter_Condition.Starts_With (t.at "Y") Case_Sensitivity.Sensitive) . at "X" . to_vector . should_equal ["abb"] t.filter "X" (Filter_Condition.Starts_With (t.at "Y") Case_Sensitivity.Sensitive) . at "X" . to_vector . should_equal ["abb"]
t.filter "X" (Filter_Condition.Starts_With (t.at "Y") Case_Sensitivity.Insensitive) . at "X" . to_vector . should_equal ["abb", "bacb"] t.filter "X" (Filter_Condition.Starts_With (t.at "Y") Case_Sensitivity.Insensitive) . at "X" . to_vector . should_equal ["abb", "bacb"]
t.filter "X" (Filter_Condition.Ends_With (t.at "Y")) . at "X" . to_vector . should_equal ["nana"] t.filter "X" (Filter_Condition.Ends_With (t.at "Y")) . at "X" . to_vector . should_equal ["nana"]
@ -176,27 +189,21 @@ add_specs suite_builder setup =
t.filter "X" (Filter_Condition.Contains (t.at "Y")) . at "X" . to_vector . should_equal ["abb", "nana"] t.filter "X" (Filter_Condition.Contains (t.at "Y")) . at "X" . to_vector . should_equal ["abb", "nana"]
t.filter "X" (Filter_Condition.Contains (t.at "Y") Case_Sensitivity.Sensitive) . at "X" . to_vector . should_equal ["abb", "nana"] t.filter "X" (Filter_Condition.Contains (t.at "Y") Case_Sensitivity.Sensitive) . at "X" . to_vector . should_equal ["abb", "nana"]
t.filter "X" (Filter_Condition.Contains (t.at "Y") Case_Sensitivity.Insensitive) . at "X" . to_vector . should_equal ["abb", "bacb", "nana"] t.filter "X" (Filter_Condition.Contains (t.at "Y") Case_Sensitivity.Insensitive) . at "X" . to_vector . should_equal ["abb", "bacb", "nana"]
t.filter "X" (Filter_Condition.Not_Contains (t.at "Y")) . at "X" . to_vector . should_equal ["bacb", "banana"]
t.filter "X" (Filter_Condition.Not_Contains (t.at "Y") Case_Sensitivity.Sensitive) . at "X" . to_vector . should_equal ["bacb", "banana"]
t.filter "X" (Filter_Condition.Not_Contains (t.at "Y") Case_Sensitivity.Insensitive) . at "X" . to_vector . should_equal ["banana"]
t.filter "X" (Filter_Condition.Starts_With (Column_Ref.Name "Y")) . at "X" . to_vector . should_equal ["abb"] t.filter "X" (Filter_Condition.Starts_With (Column_Ref.Name "Y")) . at "X" . to_vector . should_equal ["abb"]
t.filter "X" (Filter_Condition.Ends_With (Column_Ref.Name "Y") Case_Sensitivity.Insensitive) . at "X" . to_vector . should_equal ["bacb", "nana"] t.filter "X" (Filter_Condition.Ends_With (Column_Ref.Name "Y") Case_Sensitivity.Insensitive) . at "X" . to_vector . should_equal ["bacb", "nana"]
t.filter "X" (Filter_Condition.Contains (Column_Ref.Name "Y") Case_Sensitivity.Insensitive) . at "X" . to_vector . should_equal ["abb", "bacb", "nana"] t.filter "X" (Filter_Condition.Contains (Column_Ref.Name "Y") Case_Sensitivity.Insensitive) . at "X" . to_vector . should_equal ["abb", "bacb", "nana"]
t.filter "X" (Filter_Condition.Not_Contains (Column_Ref.Name "Y") Case_Sensitivity.Insensitive) . at "X" . to_vector . should_equal ["banana"]
group_builder.specify "by text search (like, not_like)" <| group_builder.specify "by text search (like, not_like)" <|
t = table_builder [["ix", [1, 2, 3, 4, 5]], ["X", ["abb", "bacb", "banana", Nothing, "nana"]], ["Y", ["a", "B", "d", "c", "a"]], ["Z", ["aaaaa", "bbbbb", "[ab]", "[ab]aaaa", "[ab]ccc"]]] t = table_builder [["ix", [1, 2, 3, 4, 5]], ["X", ["abb", "bacb", "banana", Nothing, "nana"]], ["Y", ["a", "B", "d", "c", "a"]], ["Z", ["aaaaa", "bbbbb", "[ab]", "[ab]aaaa", "[ab]ccc"]]]
t.filter "X" (Filter_Condition.Like "%an%") . at "X" . to_vector . should_equal ["banana", "nana"] t.filter "X" (Filter_Condition.Like "%an%") . at "X" . to_vector . should_equal ["banana", "nana"]
t.filter "X" (Filter_Condition.Like "%an%" action=Filter_Action.Remove) . at "X" . to_vector . should_equal ["abb", "bacb", Nothing]
t.filter "X" (Filter_Condition.Like "_a%") . at "X" . to_vector . should_equal ["bacb", "banana", "nana"] t.filter "X" (Filter_Condition.Like "_a%") . at "X" . to_vector . should_equal ["bacb", "banana", "nana"]
t.filter "X" (Filter_Condition.Like "%b") . at "X" . to_vector . should_equal ["abb", "bacb"] t.filter "X" (Filter_Condition.Like "%b") . at "X" . to_vector . should_equal ["abb", "bacb"]
t.filter "X" (Filter_Condition.Like "nana") . at "X" . to_vector . should_equal ["nana"] t.filter "X" (Filter_Condition.Like "nana") . at "X" . to_vector . should_equal ["nana"]
t.filter "Z" (Filter_Condition.Like "[ab]_%") . at "Z" . to_vector . should_equal ["[ab]aaaa", "[ab]ccc"] t.filter "Z" (Filter_Condition.Like "[ab]_%") . at "Z" . to_vector . should_equal ["[ab]aaaa", "[ab]ccc"]
t.filter "X" (Filter_Condition.Not_Like "%b") . at "X" . to_vector . should_equal ["banana", "nana"]
t.filter "Z" (Filter_Condition.Not_Like "[ab]%") . at "Z" . to_vector . should_equal ["aaaaa", "bbbbb"]
group_builder.specify "text operations should also match newlines" <| group_builder.specify "text operations should also match newlines" <|
t = table_builder [["X", ['a\n\n\n', 'a\n', 'a\n\n\nb', 'a\nb', 'caa\nbb']]] t = table_builder [["X", ['a\n\n\n', 'a\n', 'a\n\n\nb', 'a\nb', 'caa\nbb']]]
t.filter "X" (Filter_Condition.Like 'a_') . at "X" . to_vector . should_equal ['a\n'] t.filter "X" (Filter_Condition.Like 'a_') . at "X" . to_vector . should_equal ['a\n']
@ -208,7 +215,6 @@ add_specs suite_builder setup =
t.filter "X" (Filter_Condition.Ends_With '\nb') . at "X" . to_vector . should_equal ['a\n\n\nb', 'a\nb'] t.filter "X" (Filter_Condition.Ends_With '\nb') . at "X" . to_vector . should_equal ['a\n\n\nb', 'a\nb']
t.filter "X" (Filter_Condition.Ends_With '\n') . at "X" . to_vector . should_equal ['a\n\n\n', 'a\n'] t.filter "X" (Filter_Condition.Ends_With '\n') . at "X" . to_vector . should_equal ['a\n\n\n', 'a\n']
t.filter "X" (Filter_Condition.Starts_With 'c') . at "X" . to_vector . should_equal ['caa\nbb'] t.filter "X" (Filter_Condition.Starts_With 'c') . at "X" . to_vector . should_equal ['caa\nbb']
t.filter "X" (Filter_Condition.Not_Contains '\nb') . at "X" . to_vector . should_equal ['a\n\n\n', 'a\n']
if test_selection.supports_unicode_normalization then if test_selection.supports_unicode_normalization then
t = table_builder [["X", ['śnieg', 's\u0301nieg', 'X', Nothing, 'połać', 'połac\u0301']]] t = table_builder [["X", ['śnieg', 's\u0301nieg', 'X', Nothing, 'połać', 'połac\u0301']]]
@ -217,7 +223,6 @@ add_specs suite_builder setup =
t.filter "X" (Filter_Condition.Contains 'ś') . at "X" . to_vector . should_equal ['śnieg', 's\u0301nieg'] t.filter "X" (Filter_Condition.Contains 'ś') . at "X" . to_vector . should_equal ['śnieg', 's\u0301nieg']
t.filter "X" (Filter_Condition.Ends_With 'ś') . at "X" . to_vector . should_equal [] t.filter "X" (Filter_Condition.Ends_With 'ś') . at "X" . to_vector . should_equal []
t.filter "X" (Filter_Condition.Ends_With 'ć') . at "X" . to_vector . should_equal ['połać', 'połac\u0301'] t.filter "X" (Filter_Condition.Ends_With 'ć') . at "X" . to_vector . should_equal ['połać', 'połac\u0301']
t.filter "X" (Filter_Condition.Not_Contains 'ś') . at "X" . to_vector . should_equal ['X', 'połać', 'połac\u0301']
# This should be replaced with the disabled test below, once the related bug is fixed. # This should be replaced with the disabled test below, once the related bug is fixed.
t.filter "X" (Filter_Condition.Like 'ś%') . at "X" . to_vector . should_equal ['śnieg'] t.filter "X" (Filter_Condition.Like 'ś%') . at "X" . to_vector . should_equal ['śnieg']
@ -242,24 +247,18 @@ add_specs suite_builder setup =
check_problem (t.filter "X" (Filter_Condition.Ends_With (t.at "ix"))) check_problem (t.filter "X" (Filter_Condition.Ends_With (t.at "ix")))
check_problem (t.filter "X" (Filter_Condition.Contains (t.at "ix"))) check_problem (t.filter "X" (Filter_Condition.Contains (t.at "ix")))
check_problem (t.filter "X" (Filter_Condition.Like (t.at "ix"))) check_problem (t.filter "X" (Filter_Condition.Like (t.at "ix")))
check_problem (t.filter "X" (Filter_Condition.Not_Like (t.at "ix")))
check_problem (t.filter "X" (Filter_Condition.Not_Contains (t.at "ix")))
check_problem (t.filter "X" (Filter_Condition.Equal_Ignore_Case (Column_Ref.Name "ix"))) check_problem (t.filter "X" (Filter_Condition.Equal_Ignore_Case (Column_Ref.Name "ix")))
check_problem (t.filter "X" (Filter_Condition.Starts_With (Column_Ref.Name "ix"))) check_problem (t.filter "X" (Filter_Condition.Starts_With (Column_Ref.Name "ix")))
check_problem (t.filter "X" (Filter_Condition.Ends_With (Column_Ref.Name "ix"))) check_problem (t.filter "X" (Filter_Condition.Ends_With (Column_Ref.Name "ix")))
check_problem (t.filter "X" (Filter_Condition.Contains (Column_Ref.Name "ix"))) check_problem (t.filter "X" (Filter_Condition.Contains (Column_Ref.Name "ix")))
check_problem (t.filter "X" (Filter_Condition.Like (Column_Ref.Name "ix"))) check_problem (t.filter "X" (Filter_Condition.Like (Column_Ref.Name "ix")))
check_problem (t.filter "X" (Filter_Condition.Not_Like (Column_Ref.Name "ix")))
check_problem (t.filter "X" (Filter_Condition.Not_Contains (Column_Ref.Name "ix")))
check_problem (t.filter "ix" (Filter_Condition.Equal_Ignore_Case "A")) check_problem (t.filter "ix" (Filter_Condition.Equal_Ignore_Case "A"))
check_problem (t.filter "ix" (Filter_Condition.Starts_With "A")) check_problem (t.filter "ix" (Filter_Condition.Starts_With "A"))
check_problem (t.filter "ix" (Filter_Condition.Ends_With "A")) check_problem (t.filter "ix" (Filter_Condition.Ends_With "A"))
check_problem (t.filter "ix" (Filter_Condition.Contains "A")) check_problem (t.filter "ix" (Filter_Condition.Contains "A"))
check_problem (t.filter "ix" (Filter_Condition.Like "A")) check_problem (t.filter "ix" (Filter_Condition.Like "A"))
check_problem (t.filter "ix" (Filter_Condition.Not_Like "A"))
check_problem (t.filter "ix" (Filter_Condition.Not_Contains "A"))
check_problem (t.filter "ix" Filter_Condition.Is_Empty) check_problem (t.filter "ix" Filter_Condition.Is_Empty)
check_problem (t.filter "ix" Filter_Condition.Not_Empty) check_problem (t.filter "ix" Filter_Condition.Not_Empty)
@ -271,8 +270,6 @@ add_specs suite_builder setup =
check_scalar_type_error_handling (t.filter "X" (Filter_Condition.Ends_With 42)) check_scalar_type_error_handling (t.filter "X" (Filter_Condition.Ends_With 42))
check_scalar_type_error_handling (t.filter "X" (Filter_Condition.Contains 42)) check_scalar_type_error_handling (t.filter "X" (Filter_Condition.Contains 42))
check_scalar_type_error_handling (t.filter "X" (Filter_Condition.Like 42)) check_scalar_type_error_handling (t.filter "X" (Filter_Condition.Like 42))
check_scalar_type_error_handling (t.filter "X" (Filter_Condition.Not_Like 42))
check_scalar_type_error_handling (t.filter "X" (Filter_Condition.Not_Contains 42))
group_builder.specify "by nulls" <| group_builder.specify "by nulls" <|
t = table_builder [["ix", [1, 2, 3, 4]], ["X", [Nothing, 1, Nothing, 4]]] t = table_builder [["ix", [1, 2, 3, 4]], ["X", [Nothing, 1, Nothing, 4]]]
@ -287,17 +284,11 @@ add_specs suite_builder setup =
group_builder.specify "by an Is_In check" <| group_builder.specify "by an Is_In check" <|
t = table_builder [["ix", [1, 2, 3, Nothing, 5, 6]], ["X", ["a", "b", "ccc", "X", "f", "2"]]] t = table_builder [["ix", [1, 2, 3, Nothing, 5, 6]], ["X", ["a", "b", "ccc", "X", "f", "2"]]]
t1 = table_builder [["txt", ["X", "a", "c", Nothing]], ["int", [Nothing, 2, 5, 4]], ["bool", [True, Nothing, Nothing, True]]] t1 = table_builder [["txt", ["X", "a", "c", Nothing]], ["int", [Nothing, 2, 5, 4]], ["bool", [True, Nothing, Nothing, True]]]
t2 = table_builder [["txt", ["X", "a", "c", "q"]], ["int", [123, 2, 5, 4]], ["bool", [True, True, True, True]]]
t.filter "X" (Filter_Condition.Is_In (t1.at "txt")) . at "X" . to_vector . should_equal ["a", "X"] t.filter "X" (Filter_Condition.Is_In (t1.at "txt")) . at "X" . to_vector . should_equal ["a", "X"]
t.filter "X" (Filter_Condition.Is_In (t1.at "txt" . to_vector)) . at "X" . to_vector . should_equal ["a", "X"] t.filter "X" (Filter_Condition.Is_In (t1.at "txt" . to_vector)) . at "X" . to_vector . should_equal ["a", "X"]
t.filter "X" (Filter_Condition.Not_In (t1.at "txt")) . at "X" . to_vector . should_equal []
t.filter "X" (Filter_Condition.Not_In (t2.at "txt")) . at "X" . to_vector . should_equal ["b", "ccc", "f", "2"]
t.filter "X" (Filter_Condition.Not_In (t1.at "txt" . to_vector)) . at "X" . to_vector . should_equal []
t.filter "X" (Filter_Condition.Not_In (t2.at "txt" . to_vector)) . at "X" . to_vector . should_equal ["b", "ccc", "f", "2"]
t.filter "X" (Filter_Condition.Is_In ["ccc"]) . at "X" . to_vector . should_equal ["ccc"] t.filter "X" (Filter_Condition.Is_In ["ccc"]) . at "X" . to_vector . should_equal ["ccc"]
t.filter "X" (Filter_Condition.Is_In []) . at "X" . to_vector . should_equal [] t.filter "X" (Filter_Condition.Is_In []) . at "X" . to_vector . should_equal []
t.filter "X" (Filter_Condition.Not_In []) . at "X" . to_vector . should_equal ["a", "b", "ccc", "X", "f", "2"]
if test_selection.allows_mixed_type_comparisons then if test_selection.allows_mixed_type_comparisons then
mixed = t.filter "X" (Filter_Condition.Is_In (t1.at "int")) . at "X" . to_vector mixed = t.filter "X" (Filter_Condition.Is_In (t1.at "int")) . at "X" . to_vector
@ -308,8 +299,6 @@ add_specs suite_builder setup =
t.filter "ix" (Filter_Condition.Is_In (t1.at "int" . to_vector)) . at "ix" . to_vector . should_equal [2, 5] t.filter "ix" (Filter_Condition.Is_In (t1.at "int" . to_vector)) . at "ix" . to_vector . should_equal [2, 5]
t.filter "ix" (Filter_Condition.Is_In [2, 5, 4]) . at "ix" . to_vector . should_equal [2, 5] t.filter "ix" (Filter_Condition.Is_In [2, 5, 4]) . at "ix" . to_vector . should_equal [2, 5]
t.filter "ix" (Filter_Condition.Is_In [Nothing]) . at "ix" . to_vector . should_equal [] t.filter "ix" (Filter_Condition.Is_In [Nothing]) . at "ix" . to_vector . should_equal []
t.filter "ix" (Filter_Condition.Not_In [Nothing]) . at "ix" . to_vector . should_equal []
t.filter "ix" (Filter_Condition.Not_In [1, 3]) . at "ix" . to_vector . should_equal [2, 5, 6]
v1 = t.filter "X" (Filter_Condition.Is_In ["c", "f", "b", "b", "b", 15, Nothing]) . at "X" . to_vector v1 = t.filter "X" (Filter_Condition.Is_In ["c", "f", "b", "b", "b", 15, Nothing]) . at "X" . to_vector
case test_selection.allows_mixed_type_comparisons of case test_selection.allows_mixed_type_comparisons of
@ -329,7 +318,7 @@ add_specs suite_builder setup =
t3.filter "B" (Filter_Condition.Is_In [False]) . at "B" . to_vector . should_equal [False, False, False] t3.filter "B" (Filter_Condition.Is_In [False]) . at "B" . to_vector . should_equal [False, False, False]
t3.filter "C" (Filter_Condition.Is_In [False, False]) . at "C" . to_vector . should_equal [False] t3.filter "C" (Filter_Condition.Is_In [False, False]) . at "C" . to_vector . should_equal [False]
group_builder.specify "does not allow Column_Ref in Is_In/Not_In because that would be confusing" <| group_builder.specify "does not allow Column_Ref in Is_In because that would be confusing" <|
## Is In and Not In check if a value is contained anywhere in a provided collection (e.g. column), ## Is In and Not In check if a value is contained anywhere in a provided collection (e.g. column),
NOT on a row-by-row basis like all other operations. Column_Ref is used with row-by-row ops, NOT on a row-by-row basis like all other operations. Column_Ref is used with row-by-row ops,
so this would only cause confusion. Very rarely someone wants to filter a column by Is_In so this would only cause confusion. Very rarely someone wants to filter a column by Is_In
@ -459,7 +448,6 @@ add_specs suite_builder setup =
+ [Filter_Condition.Less Nothing, Filter_Condition.Equal_Or_Less Nothing] + [Filter_Condition.Less Nothing, Filter_Condition.Equal_Or_Less Nothing]
+ [Filter_Condition.Equal_Or_Greater Nothing, Filter_Condition.Greater Nothing] + [Filter_Condition.Equal_Or_Greater Nothing, Filter_Condition.Greater Nothing]
+ [Filter_Condition.Between Nothing Nothing , Filter_Condition.Is_In [Nothing]] + [Filter_Condition.Between Nothing Nothing , Filter_Condition.Is_In [Nothing]]
+ [Filter_Condition.Not_In [Nothing]]
+ [Filter_Condition.Is_In [1, Nothing, 2]] + [Filter_Condition.Is_In [1, Nothing, 2]]
fcs.map fc-> fcs.map fc->
Test.with_clue fc.to_text <| Test.with_clue fc.to_text <|

View File

@ -75,7 +75,7 @@ add_specs suite_builder setup =
## TODO currently our builder does not allow all-null tables, so we ## TODO currently our builder does not allow all-null tables, so we
create one with a 0 and remove it by filter. See #6159. create one with a 0 and remove it by filter. See #6159.
t0 = table_builder [["X", [0, Nothing, Nothing, Nothing]]] t0 = table_builder [["X", [0, Nothing, Nothing, Nothing]]]
t1 = t0.filter "X" (Filter_Condition.Is_Nothing) t1 = t0.filter "X" Filter_Condition.Is_Nothing
t1.row_count . should_equal 3 t1.row_count . should_equal 3
t1.at "X" . to_vector . should_equal [Nothing, Nothing, Nothing] t1.at "X" . to_vector . should_equal [Nothing, Nothing, Nothing]
@ -171,7 +171,7 @@ add_specs suite_builder setup =
group_builder.specify "select_blank_columns and remove_blank_columns should deal with edge cases" <| group_builder.specify "select_blank_columns and remove_blank_columns should deal with edge cases" <|
t = table_builder [["X", [1, 2, 3, 4]]] t = table_builder [["X", [1, 2, 3, 4]]]
no_rows = t.filter "X" (Filter_Condition.Equal to=0) no_rows = t.filter "X" Filter_Condition.Is_Nothing
no_rows.row_count . should_equal 0 no_rows.row_count . should_equal 0
no_rows.at "X" . to_vector . should_equal [] no_rows.at "X" . to_vector . should_equal []

View File

@ -42,14 +42,17 @@ add_specs suite_builder =
group_builder.teardown <| group_builder.teardown <|
data.teardown data.teardown
group_builder.specify "should serialize Tables and Columns to their SQL representation" pending="ToDo: decide on how we handle ==, see https://github.com/enso-org/enso/issues/5241" <| group_builder.specify "should serialize Tables and Columns to their SQL representation" <|
q1 = data.t1.filter (data.t1.at "A" == 42) . to_json q1 = data.t1.filter (data.t1.at "A" == 42) . to_json
part1 = JS_Object.from_pairs [["sql_code", 'SELECT "T1"."A" AS "A", "T1"."B" AS "B", "T1"."C" AS "C" FROM "T1" AS "T1" WHERE ("T1"."A" = ']] part1 = JS_Object.from_pairs [["sql_code", 'SELECT "T1"."A" AS "A", "T1"."B" AS "B", "T1"."C" AS "C" FROM "T1" AS "T1" WHERE (("T1"."A") = (']]
part2_sub = JS_Object.from_pairs [["value", 42]] part2_sub = JS_Object.from_pairs [["value", 42]]
part2 = JS_Object.from_pairs [["sql_interpolation", part2_sub]] part2 = JS_Object.from_pairs [["sql_interpolation", part2_sub]]
part3 = JS_Object.from_pairs [["sql_code", ")"]] part3 = JS_Object.from_pairs [["sql_code", ")) = ("]]
expected = JS_Object.from_pairs [["query", [part1, part2, part3]]] . to_text part4_sub = JS_Object.from_pairs [["value", True]]
part4 = JS_Object.from_pairs [["sql_interpolation", part4_sub]]
part5 = JS_Object.from_pairs [["sql_code", ")"]]
expected = JS_Object.from_pairs [["query", [part1, part2, part3, part4, part5]]] . to_text
q1.should_equal expected q1.should_equal expected
q2 = data.t1.at "A" . to_json q2 = data.t1.at "A" . to_json
@ -90,6 +93,9 @@ add_specs suite_builder =
t2 = data.t1.filter "A" (Filter_Condition.Between 10 20) t2 = data.t1.filter "A" (Filter_Condition.Between 10 20)
t2.to_sql.prepare . should_equal ['SELECT "T1"."A" AS "A", "T1"."B" AS "B", "T1"."C" AS "C" FROM "T1" AS "T1" WHERE ("T1"."A" BETWEEN ? AND ?)', [10, 20]] t2.to_sql.prepare . should_equal ['SELECT "T1"."A" AS "A", "T1"."B" AS "B", "T1"."C" AS "C" FROM "T1" AS "T1" WHERE ("T1"."A" BETWEEN ? AND ?)', [10, 20]]
t2r = data.t1.filter "A" (Filter_Condition.Between 10 20 Filter_Action.Remove)
t2r.to_sql.prepare . should_equal ['SELECT "T1"."A" AS "A", "T1"."B" AS "B", "T1"."C" AS "C" FROM "T1" AS "T1" WHERE (NOT CAST(COALESCE(("T1"."A" BETWEEN ? AND ?), ?) AS BOOLEAN))', [10, 20, False]]
group_builder.specify "should generate an IN expression" <| group_builder.specify "should generate an IN expression" <|
t2 = data.t1.filter "A" (Filter_Condition.Is_In [1, 2, 'foo']) t2 = data.t1.filter "A" (Filter_Condition.Is_In [1, 2, 'foo'])
t2.to_sql.prepare . should_equal ['SELECT "T1"."A" AS "A", "T1"."B" AS "B", "T1"."C" AS "C" FROM "T1" AS "T1" WHERE "T1"."A" IN (?, ?, ?)', [1, 2, "foo"]] t2.to_sql.prepare . should_equal ['SELECT "T1"."A" AS "A", "T1"."B" AS "B", "T1"."C" AS "C" FROM "T1" AS "T1" WHERE "T1"."A" IN (?, ?, ?)', [1, 2, "foo"]]

View File

@ -4,7 +4,6 @@ from Standard.Table import Table
import Standard.Examples import Standard.Examples
import Standard.Visualization.Table as Table_Visualization import Standard.Visualization.Table as Table_Visualization
import Standard.Visualization.Preprocessor as Preprocessor
from Standard.Test_New import all from Standard.Test_New import all

View File

@ -3,7 +3,6 @@ from Standard.Visualization import all
import Standard.Examples import Standard.Examples
import Standard.Visualization.Text as TextVis import Standard.Visualization.Text as TextVis
import Standard.Visualization.Preprocessor as Preprocessor
from Standard.Test_New import all from Standard.Test_New import all

View File

@ -10,7 +10,7 @@ main =
operator14 = var1.to_column "Color" operator14 = var1.to_column "Color"
operator16 = operator14.to_table operator16 = operator14.to_table
operator40 = enso_project.data/'benchmarks-vectorized-3-2023-07-17.txt' . read (Delimited_Format.Delimited) operator40 = enso_project.data/'benchmarks-vectorized-3-2023-07-17.txt' . read (Delimited_Format.Delimited)
operator1 = operator40.filter 'Column 1' (Filter_Condition.Not_Contains "average") operator1 = operator40.filter 'Column 1' (Filter_Condition.Contains "average" Filter_Action.Remove)
operator3 = operator1.parse_to_columns 'Column 1' text1 operator3 = operator1.parse_to_columns 'Column 1' text1
operator4 = operator3.select_columns ['Operation'] operator4 = operator3.select_columns ['Operation']
operator5 = operator4.distinct operator5 = operator4.distinct