mirror of
https://github.com/enso-org/enso.git
synced 2024-11-22 22:10:15 +03:00
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:
parent
83fffd9c05
commit
0c39f8ec04
@ -612,6 +612,7 @@
|
||||
- [Added `File_By_Line` type allowing processing a file line by line. New faster
|
||||
JSON parser based off Jackson.][8719]
|
||||
- [Implemented `Table.replace` for the in-memory backend.][8935]
|
||||
- [Allow removing rows using a Filter_Condition.][8861]
|
||||
|
||||
[debug-shortcuts]:
|
||||
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
|
||||
[8865]: https://github.com/enso-org/enso/pull/8865
|
||||
[8935]: https://github.com/enso-org/enso/pull/8935
|
||||
[8861]: https://github.com/enso-org/enso/pull/8861
|
||||
|
||||
#### Enso Compiler
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
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.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.ProfileReader
|
||||
|
||||
type AWS_Credential
|
||||
## Access using IAM via an AWS profile.
|
||||
@ -32,7 +32,7 @@ type AWS_Credential
|
||||
make_single_choice [["default", "Nothing"], ["by profile", fqn + ".Profile"], ["by key", fqn + ".Key"]]
|
||||
|
||||
## PRIVATE
|
||||
as_java : AWS_Credential|Nothing -> AwsCredential
|
||||
as_java : AWS_Credential | Nothing -> AwsCredential
|
||||
as_java (credential : AWS_Credential | Nothing) = case credential of
|
||||
AWS_Credential.Profile profile -> AwsCredential.Profile.new profile
|
||||
AWS_Credential.Key access_key_id secret_access_key ->
|
||||
|
@ -146,7 +146,7 @@ read_text path (encoding=Encoding.utf_8) (on_problems=Problem_Behavior.Report_Wa
|
||||
example_list_files =
|
||||
Data.list_directory Examples.data_dir name_filter="**.md" recursive=True
|
||||
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
|
||||
|
||||
## ALIAS download, http get
|
||||
|
@ -1,5 +1,5 @@
|
||||
import project.Data.Text.Text
|
||||
import project.Data.Text.Encoding.Encoding
|
||||
import project.Data.Text.Text
|
||||
import project.Errors.Encoding_Error.Encoding_Error
|
||||
from project.Data.Text.Extensions import all
|
||||
|
||||
|
@ -255,7 +255,7 @@ type Enso_File
|
||||
|
||||
## UNSTABLE
|
||||
Resolves a file or directory within this directory.
|
||||
/ : Text -> Enso_File
|
||||
/ : 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 name.contains "/" then Error.throw (Illegal_Argument.Error "Resolving sub-paths (/) is not implemented. Temporary workaround: use the `/` operator multiple times.") else
|
||||
|
@ -1,6 +1,6 @@
|
||||
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_File
|
||||
import project.Data.Enso_Cloud.Utils
|
||||
import project.Data.Json.JS_Object
|
||||
import project.Data.Text.Text
|
||||
@ -15,8 +15,8 @@ import project.Network.HTTP.Request_Body.Request_Body
|
||||
import project.Nothing.Nothing
|
||||
import project.Runtime.Context
|
||||
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.Text.Extensions import all
|
||||
|
||||
polyglot java import org.enso.base.enso_cloud.EnsoSecretHelper
|
||||
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
|
||||
|
||||
## 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
|
||||
text : Text -> HideableValue.PlainValue.new text
|
||||
secret : Enso_Secret -> HideableValue.SecretValue.new secret.id
|
||||
|
@ -1,6 +1,7 @@
|
||||
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.Enso_Secret
|
||||
import project.Data.Enso_Cloud.Errors.Not_Logged_In
|
||||
import project.Data.Pair.Pair
|
||||
import project.Data.Text.Text
|
||||
|
@ -21,25 +21,25 @@ polyglot java import org.enso.base.Regex_Utils
|
||||
|
||||
type Filter_Condition
|
||||
## 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)?
|
||||
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)?
|
||||
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)?
|
||||
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)?
|
||||
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)?
|
||||
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)?
|
||||
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)?
|
||||
|
||||
@ -54,7 +54,7 @@ type Filter_Condition
|
||||
This ensures that different ways of expressing the same character in
|
||||
the underlying binary representation are considered equal.
|
||||
@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)?
|
||||
|
||||
@ -62,7 +62,7 @@ type Filter_Condition
|
||||
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.
|
||||
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)?
|
||||
|
||||
@ -70,7 +70,7 @@ type Filter_Condition
|
||||
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.
|
||||
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)?
|
||||
|
||||
@ -78,44 +78,36 @@ type Filter_Condition
|
||||
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.
|
||||
Contains (substring : Text | Any) (case_sensitivity:Case_Sensitivity=Case_Sensitivity.Default)
|
||||
|
||||
## 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)
|
||||
Contains (substring : Text | Any) (case_sensitivity:Case_Sensitivity=Case_Sensitivity.Default) action:Filter_Action=Filter_Action.Keep
|
||||
|
||||
## Is equal to Nothing?
|
||||
Is_Nothing
|
||||
Is_Nothing action:Filter_Action=Filter_Action.Keep
|
||||
|
||||
## Is not equal to Nothing?
|
||||
Not_Nothing
|
||||
Not_Nothing action:Filter_Action=Filter_Action.Keep
|
||||
|
||||
## Is the value a NaN (Number only)?
|
||||
Is_Nan
|
||||
Is_Nan action:Filter_Action=Filter_Action.Keep
|
||||
|
||||
## Is the value infinite (Number only)?
|
||||
Is_Infinite
|
||||
Is_Infinite action:Filter_Action=Filter_Action.Keep
|
||||
|
||||
## Is the value finite (Number only)?
|
||||
|
||||
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_True
|
||||
Is_True action:Filter_Action=Filter_Action.Keep
|
||||
|
||||
## 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_Empty
|
||||
Is_Empty action:Filter_Action=Filter_Action.Keep
|
||||
|
||||
## 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)?
|
||||
|
||||
@ -134,26 +126,7 @@ type Filter_Condition
|
||||
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.
|
||||
Like (pattern : Text | Any)
|
||||
|
||||
## 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
|
||||
Like (pattern : Text | Any) action:Filter_Action=Filter_Action.Keep
|
||||
|
||||
## Is the value contained in `values`?
|
||||
|
||||
@ -167,21 +140,7 @@ type Filter_Condition
|
||||
Using Columns can be particularly useful for Database operations, as
|
||||
uploading a temporary table and using its column for an `Is_In` check
|
||||
will likely be faster than using the vector directly.
|
||||
Is_In values:Vector|Any
|
||||
|
||||
## 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)
|
||||
Is_In values:Vector|Any action:Filter_Action=Filter_Action.Keep
|
||||
|
||||
## Converts a `Filter_Condition` condition into a predicate taking an
|
||||
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
|
||||
predicate will raise an error if the value is not of the expected type.
|
||||
to_predicate : (Any -> Boolean)
|
||||
to_predicate self = case self of
|
||||
# == does not need special handling for Nothing
|
||||
Equal value -> ==value
|
||||
Not_Equal value -> !=value
|
||||
Less value -> handle_nothing (<value)
|
||||
Equal_Or_Less value -> handle_nothing (<=value)
|
||||
Equal_Or_Greater value -> handle_nothing (>=value)
|
||||
Greater value -> handle_nothing (>value)
|
||||
Between lower upper -> handle_nothing <| elem->
|
||||
(lower <= elem) && (elem <= upper)
|
||||
Equal_Ignore_Case value locale ->
|
||||
handle_nothing <| txt-> (txt : Text).equals_ignore_case value locale
|
||||
Starts_With prefix case_sensitivity ->
|
||||
handle_nothing <| txt-> (txt : Text).starts_with prefix case_sensitivity
|
||||
Ends_With suffix case_sensitivity ->
|
||||
handle_nothing <| txt-> (txt : Text).ends_with suffix case_sensitivity
|
||||
Contains substring case_sensitivity ->
|
||||
handle_nothing <| txt-> (txt : Text).contains substring case_sensitivity
|
||||
Not_Contains substring case_sensitivity ->
|
||||
handle_nothing <| txt-> (txt : Text).contains substring case_sensitivity . not
|
||||
Is_Nothing -> elem -> case elem of
|
||||
Nothing -> True
|
||||
_ -> False
|
||||
Not_Nothing -> elem -> case elem of
|
||||
Nothing -> False
|
||||
_ -> True
|
||||
Is_Nan -> handle_nothing x-> (x:Number).is_nan
|
||||
Is_Infinite -> handle_nothing x-> (x:Number).is_infinite
|
||||
Is_Finite -> handle_nothing x-> (x:Number).is_finite
|
||||
Is_True -> ==True
|
||||
Is_False -> ==False
|
||||
Is_Empty -> elem -> case elem of
|
||||
Nothing -> True
|
||||
"" -> True
|
||||
_ -> False
|
||||
Not_Empty -> elem -> case elem of
|
||||
Nothing -> False
|
||||
"" -> False
|
||||
_ -> True
|
||||
Like sql_pattern ->
|
||||
regex = sql_like_to_regex sql_pattern
|
||||
handle_nothing <| regex.matches
|
||||
Not_Like sql_pattern ->
|
||||
regex = sql_like_to_regex sql_pattern
|
||||
handle_nothing <| elem-> regex.matches elem . not
|
||||
Is_In values ->
|
||||
set = Set.from_vector values
|
||||
set.contains
|
||||
Not_In values ->
|
||||
set = Set.from_vector values
|
||||
elem-> set.contains elem . not
|
||||
to_predicate self =
|
||||
base = case self of
|
||||
# == does not need special handling for Nothing
|
||||
Equal value _ -> ==value
|
||||
Not_Equal value _ -> !=value
|
||||
Less value _ -> handle_nothing (<value)
|
||||
Equal_Or_Less value _ -> handle_nothing (<=value)
|
||||
Equal_Or_Greater value _ -> handle_nothing (>=value)
|
||||
Greater value _ -> handle_nothing (>value)
|
||||
Between lower upper _ -> handle_nothing <| elem->
|
||||
(lower <= elem) && (elem <= upper)
|
||||
Equal_Ignore_Case value locale _ ->
|
||||
handle_nothing <| txt-> (txt : Text).equals_ignore_case value locale
|
||||
Starts_With prefix case_sensitivity _ ->
|
||||
handle_nothing <| txt-> (txt : Text).starts_with prefix case_sensitivity
|
||||
Ends_With suffix case_sensitivity _ ->
|
||||
handle_nothing <| txt-> (txt : Text).ends_with suffix case_sensitivity
|
||||
Contains substring case_sensitivity _ ->
|
||||
handle_nothing <| txt-> (txt : Text).contains substring case_sensitivity
|
||||
Is_Nothing _ -> elem -> case elem of
|
||||
Nothing -> True
|
||||
_ -> False
|
||||
Not_Nothing _ -> elem -> case elem of
|
||||
Nothing -> False
|
||||
_ -> True
|
||||
Is_Nan _ -> handle_nothing x-> (x:Number).is_nan
|
||||
Is_Infinite _ -> handle_nothing x-> (x:Number).is_infinite
|
||||
Is_Finite _ -> handle_nothing x-> (x:Number).is_finite
|
||||
Is_True _ -> handle_nothing b-> (b:Boolean)==True
|
||||
Is_False _ -> handle_nothing b-> (b:Boolean)==False
|
||||
Is_Empty _ -> elem-> elem.is_nothing || (elem : Text)==""
|
||||
Not_Empty _ -> handle_nothing elem-> (elem : Text)!=""
|
||||
Like sql_pattern _ ->
|
||||
regex = sql_like_to_regex sql_pattern
|
||||
handle_nothing <| regex.matches
|
||||
Is_In values _ ->
|
||||
set = Set.from_vector values
|
||||
set.contains
|
||||
if self.action == Filter_Action.Keep then base else v -> (base v).not
|
||||
|
||||
## PRIVATE
|
||||
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
|
||||
|
||||
condition = case self of
|
||||
Less value -> "<" + value.to_display_text
|
||||
Equal_Or_Less value -> "<=" + value.to_display_text
|
||||
Equal value -> "==" + value.to_display_text
|
||||
Equal_Or_Greater value -> ">=" + value.to_display_text
|
||||
Greater 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
|
||||
Equal_Ignore_Case value locale ->
|
||||
Less value _ -> "<" + value.to_display_text
|
||||
Equal_Or_Less value _ -> "<=" + value.to_display_text
|
||||
Equal value _ -> "==" + value.to_display_text
|
||||
Equal_Or_Greater value _ -> ">=" + value.to_display_text
|
||||
Greater 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
|
||||
Equal_Ignore_Case value locale _ ->
|
||||
suffix = if locale == Locale.default then "" else " (within locale " + locale.to_display_text + ")"
|
||||
"Equal Ignore Case " + value.to_display_text + suffix
|
||||
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)
|
||||
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"
|
||||
Not_Nothing -> "is not Nothing"
|
||||
Is_Nan -> "is NaN"
|
||||
Is_Infinite -> "is Infinite"
|
||||
Is_Finite -> "is Finite"
|
||||
Is_True -> "is True"
|
||||
Is_False -> "is False"
|
||||
Is_Empty -> "is Empty"
|
||||
Not_Empty -> "is not Empty"
|
||||
Like sql_pattern -> "Like " + sql_pattern.to_display_text
|
||||
Not_Like sql_pattern -> "not Like " + sql_pattern.to_display_text
|
||||
Is_In values -> "is in " + values.to_display_text
|
||||
Not_In values -> "is not in " + values.to_display_text
|
||||
"Filter Condition: " + condition
|
||||
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)
|
||||
Contains substring case_sensitivity _ -> "Contains " + substring.to_display_text + (render_case case_sensitivity)
|
||||
Is_Nothing _ -> "is Nothing"
|
||||
Not_Nothing _ -> "is not Nothing"
|
||||
Is_Nan _ -> "is NaN"
|
||||
Is_Infinite _ -> "is Infinite"
|
||||
Is_Finite _ -> "is Finite"
|
||||
Is_True _ -> "is True"
|
||||
Is_False _ -> "is False"
|
||||
Is_Empty _ -> "is Empty"
|
||||
Not_Empty _ -> "is not Empty"
|
||||
Like sql_pattern _ -> "Like " + sql_pattern.to_display_text
|
||||
Is_In values _ -> "is in " + values.to_display_text
|
||||
"Filter Condition: " + condition + (if self.action == Filter_Action.Keep then "" else " (Remove)")
|
||||
|
||||
## PRIVATE
|
||||
Creates a Single_Choice Widget for delimiters.
|
||||
@ -309,11 +253,8 @@ type Filter_Condition
|
||||
options_builder.append "Starts_With"
|
||||
options_builder.append "Ends_With"
|
||||
options_builder.append "Contains"
|
||||
options_builder.append "Not_Contains"
|
||||
options_builder.append "Like"
|
||||
options_builder.append "Not_Like"
|
||||
options_builder.append "Is_In"
|
||||
options_builder.append "Not_In"
|
||||
|
||||
options = options_builder.to_vector.map constructor_name->
|
||||
name = constructor_name.replace "_" " "
|
||||
@ -321,6 +262,13 @@ type Filter_Condition
|
||||
[name, code]
|
||||
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
|
||||
sql_like_to_regex sql_pattern =
|
||||
|
@ -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.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.JsonNodeType
|
||||
polyglot java import com.fasterxml.jackson.databind.node.ObjectNode
|
||||
polyglot java import com.fasterxml.jackson.databind.ObjectMapper
|
||||
|
||||
## PRIVATE
|
||||
Jackson-based JSON Parser
|
||||
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:Text =
|
||||
error_handler js_exception =
|
||||
@ -60,6 +65,8 @@ read_json_array node =
|
||||
|
||||
## PRIVATE
|
||||
type Jackson_Object
|
||||
## PRIVATE
|
||||
Creates a new `Jackson_Object` from an `ObjectNode`.
|
||||
new : ObjectNode -> Jackson_Object
|
||||
new object_node =
|
||||
make_field_names object =
|
||||
|
@ -279,7 +279,7 @@ type JS_Object
|
||||
obj.set_value "foo" "asdf"
|
||||
# => {"foo":"asdf","baz":"quux"}
|
||||
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
|
||||
type JS_Object_Comparator
|
||||
|
@ -1,4 +1,5 @@
|
||||
import project.Any.Any
|
||||
import project.Data.Filter_Condition.Filter_Action
|
||||
import project.Data.Filter_Condition.Filter_Condition
|
||||
import project.Data.Text.Case.Case
|
||||
import project.Data.Text.Text
|
||||
@ -438,7 +439,7 @@ type Locale
|
||||
predefined_locale_fields =
|
||||
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"]
|
||||
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
|
||||
widget_options : Vector Option
|
||||
|
@ -8,11 +8,10 @@ import project.Errors.Common.Incomparable_Values
|
||||
import project.Errors.Common.Unsupported_Argument_Types
|
||||
import project.Errors.Illegal_Argument.Illegal_Argument
|
||||
import project.Function.Function
|
||||
import project.Internal.Rounding_Helpers
|
||||
import project.Nothing.Nothing
|
||||
import project.Panic.Panic
|
||||
from project.Data.Boolean import Boolean, False, True
|
||||
|
||||
import project.Internal.Rounding_Helpers
|
||||
from project.Internal.Number_Builtins import all
|
||||
|
||||
polyglot java import java.lang.Double
|
||||
|
@ -184,12 +184,11 @@ type Range
|
||||
(0.up_to 7).filter (Filter_Condition.Greater than=3)
|
||||
@filter range_default_filter_condition_widget
|
||||
filter : (Filter_Condition | (Integer -> Boolean)) -> Vector Integer
|
||||
filter self filter = case filter of
|
||||
_ : Filter_Condition -> self.filter filter.to_predicate
|
||||
predicate : Function ->
|
||||
builder = self.fold Vector.new_builder builder-> elem->
|
||||
if predicate elem then builder.append elem else builder
|
||||
builder.to_vector
|
||||
filter self filter =
|
||||
predicate = unify_condition_or_predicate filter
|
||||
builder = self.fold Vector.new_builder builder-> elem->
|
||||
if predicate elem then builder.append elem else builder
|
||||
builder.to_vector
|
||||
|
||||
## GROUP Selections
|
||||
Partitions the range into `Vector`s of elements which satisfy a given
|
||||
|
@ -308,7 +308,7 @@ type Date_Time
|
||||
from Standard.Base import Date_Time
|
||||
|
||||
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 =
|
||||
unix_epoch_start + Duration.new milliseconds=milliseconds
|
||||
|
||||
|
@ -5,8 +5,8 @@ import project.Meta
|
||||
import project.Nothing.Nothing
|
||||
import project.Panic.Panic
|
||||
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_Metadata.File_Format_Metadata
|
||||
|
||||
polyglot java import java.io.FileNotFoundException
|
||||
polyglot java import java.io.IOException
|
||||
|
@ -5,6 +5,7 @@ import project.Data.Boolean
|
||||
import project.Data.Enso_Cloud.Enso_File.Enso_File
|
||||
import project.Data.Enso_Cloud.Enso_Secret.Enso_Secret
|
||||
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.Index_Sub_Range.Index_Sub_Range
|
||||
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_Secret.Enso_Secret
|
||||
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.Index_Sub_Range.Index_Sub_Range
|
||||
export project.Data.Interval.Bound
|
||||
|
@ -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.Enso_Secret
|
||||
import project.Data.Enso_Cloud.Utils as Cloud_Utils
|
||||
import project.Data.Numbers.Integer
|
||||
import project.Data.Text.Encoding.Encoding
|
||||
import project.Data.Text.Text
|
||||
import project.Nothing.Nothing
|
||||
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.Ordering import all
|
||||
from project.Data.Text.Extensions import all
|
||||
|
||||
polyglot java import org.graalvm.collections.Pair as Java_Pair
|
||||
@ -22,7 +22,7 @@ type Header
|
||||
- value: The header value.
|
||||
Value name:Text value:(Text|Enso_Secret|Derived_Secret_Value)
|
||||
|
||||
## ALIAS Build a Header
|
||||
## ALIAS build a header
|
||||
|
||||
Create a new Header.
|
||||
|
||||
@ -36,7 +36,7 @@ type Header
|
||||
import Standard.Base.Network.HTTP.Header.Header
|
||||
|
||||
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
|
||||
|
||||
## Create an "Accept" header.
|
||||
@ -64,7 +64,7 @@ type Header
|
||||
accept_all : Header
|
||||
accept_all = Header.accept "*/*"
|
||||
|
||||
## ALIAS Build an Auth Header
|
||||
## ALIAS build an auth header
|
||||
|
||||
Create an "Authorization" header.
|
||||
|
||||
@ -102,7 +102,7 @@ type Header
|
||||
|
||||
Arguments:
|
||||
- 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) =
|
||||
value = ((Derived_Secret_Value.from "Bearer ") + (Derived_Secret_Value.from token))
|
||||
Header.authorization value.simplify
|
||||
|
@ -134,7 +134,7 @@ type Response
|
||||
inferred from response headers. If that fails, UTF-8 is used as the
|
||||
fallback.
|
||||
@encoding Encoding.default_widget
|
||||
decode_as_text : Encoding|Infer -> Text
|
||||
decode_as_text : Encoding | Infer -> Text
|
||||
decode_as_text self (encoding : Encoding | Infer = Infer) =
|
||||
self.body.decode_as_text encoding
|
||||
|
||||
@ -154,7 +154,7 @@ type Response
|
||||
|
||||
example_to_text = Examples.get_geo_data.decode_as_json
|
||||
@encoding Encoding.default_widget
|
||||
decode_as_json : Encoding|Infer -> JS_Object | Boolean | Number | Nothing | Text | Vector
|
||||
decode_as_json : Encoding | Infer -> JS_Object | Boolean | Number | Nothing | Text | Vector
|
||||
decode_as_json self (encoding : Encoding | Infer = Infer) =
|
||||
self.body.decode_as_json encoding
|
||||
|
||||
|
@ -49,7 +49,7 @@ type Response_Body
|
||||
- stream: The body of the response as an InputStream.
|
||||
- metadata: File format metadata associated with 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) =
|
||||
input_stream = Input_Stream.new stream (HTTP_Error.handle_java_exceptions uri)
|
||||
Response_Body.Raw_Stream input_stream metadata uri
|
||||
@ -142,7 +142,7 @@ type Response_Body
|
||||
inferred from response headers. If that fails, UTF-8 is used as the
|
||||
fallback.
|
||||
@encoding Encoding.default_widget
|
||||
decode_as_text : Encoding|Infer -> Text
|
||||
decode_as_text : Encoding | Infer -> Text
|
||||
decode_as_text self (encoding : Encoding | Infer = Infer) = self.decode (Plain_Text_Format.Plain_Text encoding)
|
||||
|
||||
## ALIAS parse as json, parse json
|
||||
@ -161,7 +161,7 @@ type Response_Body
|
||||
|
||||
example_to_text = Examples.get_geo_data.decode_as_json
|
||||
@encoding Encoding.default_widget
|
||||
decode_as_json : Encoding|Infer -> JS_Object | Boolean | Number | Nothing | Text | Vector
|
||||
decode_as_json : Encoding | Infer -> JS_Object | Boolean | Number | Nothing | Text | Vector
|
||||
decode_as_json self (encoding : Encoding | Infer = Infer) =
|
||||
self.decode_as_text encoding . parse_json
|
||||
|
||||
|
@ -155,7 +155,7 @@ type Random
|
||||
import Standard.Base.Random.Random
|
||||
|
||||
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
|
||||
|
||||
## GROUP Random
|
||||
@ -297,7 +297,7 @@ type Random_Generator
|
||||
Vector.from_polyglot_array array
|
||||
|
||||
## PRIVATE
|
||||
date : Date -> Date -> Boolean -> Date
|
||||
date : Date -> Date -> Date
|
||||
date self start_date:Date end_date:Date =
|
||||
date_range = start_date.up_to end_date include_end=True
|
||||
date_range.at (self.integer 0 (date_range.length - 1))
|
||||
|
@ -14,11 +14,11 @@ from project.Data.Range.Extensions import all
|
||||
from project.Data.Text.Extensions 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.arrays.LongArrayList
|
||||
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
|
||||
## Creates a new File_By_Line object.
|
||||
@ -27,7 +27,7 @@ type File_By_Line
|
||||
- file: The file to read.
|
||||
- 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).
|
||||
new : File->Encoding->File_By_Line
|
||||
new : File -> Encoding -> Integer -> File_By_Line
|
||||
new file:File encoding:Encoding=Encoding.utf_8 offset:Integer=0 =
|
||||
create_row_map =
|
||||
row_map = LongArrayList.new
|
||||
@ -52,7 +52,7 @@ type File_By_Line
|
||||
|
||||
Arguments
|
||||
- line: The line to read (0 indexed).
|
||||
get : Integer->Text
|
||||
get : Integer -> Text
|
||||
get self line:Integer = if self.limit_lines.is_nothing.not && line>self.limit_lines then Error.throw (Index_Out_Of_Bounds.Error line self.limit_lines) else
|
||||
read_line self line
|
||||
|
||||
@ -201,13 +201,13 @@ type File_By_Line
|
||||
|
||||
## PRIVATE
|
||||
Reads a specific line from the file.
|
||||
read_line : File_By_Line->Integer->Any->Any
|
||||
read_line : File_By_Line -> Integer -> Any -> Any
|
||||
read_line file:File_By_Line line:Integer=0 ~default=Nothing = File_Error.handle_java_exceptions file.file <|
|
||||
FileLineReader.readSingleLine file.java_file file.file_end file.row_map line file.charset file.filter_func . if_nothing default
|
||||
|
||||
## PRIVATE
|
||||
Performs an action on each line in the file.
|
||||
for_each_lines : File_By_Line->Integer->(Integer|Nothing)->Any->Any
|
||||
for_each_lines : File_By_Line -> Integer -> (Integer|Nothing) -> Any -> Any
|
||||
for_each_lines file:File_By_Line start_at:Integer end_at:(Integer|Nothing) action = File_Error.handle_java_exceptions file.file <|
|
||||
java_file = file.java_file
|
||||
row_map = file.row_map
|
||||
|
@ -19,8 +19,8 @@ make_delimiter_selector : Widget
|
||||
make_delimiter_selector =
|
||||
make_single_choice [',', ';', '|', ['{tab}', "'\t'"], ['{space}', "' '"], ['{newline}', "['\n', '\r\n', '\r']"], '_', ['Custom', "'?'"]]
|
||||
|
||||
## PRIVATE
|
||||
Creates a Single_Choice Widget for file read delimiters.
|
||||
## PRIVATE
|
||||
Creates a Single_Choice Widget for file read delimiters.
|
||||
make_file_read_delimiter_selector : Widget
|
||||
make_file_read_delimiter_selector =
|
||||
make_single_choice [',', ';', '|', ['{tab}', "'\t'"], ['{space}', "' '"], ['{none}', "''"], '_', ['Custom', "'?'"]]
|
||||
|
@ -180,7 +180,7 @@ type Connection
|
||||
True -> result
|
||||
False ->
|
||||
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
|
||||
Checks if the table with the given name exists in the database.
|
||||
|
@ -147,7 +147,7 @@ type Column
|
||||
import Standard.Examples
|
||||
|
||||
example_at = Examples.integer_column.get 0 -1
|
||||
get : Integer -> (Any | Nothing)
|
||||
get : Integer -> Any -> Any | Nothing
|
||||
get self (index : Integer) (~default=Nothing) =
|
||||
self.read index+1 . get index default
|
||||
|
||||
|
@ -32,9 +32,9 @@ from project.Internal.Column_Format import all
|
||||
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.table.data.mask.OrderMask
|
||||
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.mask.OrderMask
|
||||
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.operations.OrderBuilder
|
||||
@ -1063,7 +1063,11 @@ type Column
|
||||
internal_is_empty : Column
|
||||
internal_is_empty self =
|
||||
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
|
||||
Returns a column of booleans, with `True` items at the positions where
|
||||
@ -2072,7 +2076,7 @@ type Column
|
||||
import Standard.Examples
|
||||
|
||||
example_at = Examples.integer_column.get 0 -1
|
||||
get : Integer -> (Any | Nothing)
|
||||
get : Integer -> Any -> Any | Nothing
|
||||
get self (index : Integer) (~default=Nothing) =
|
||||
valid_index = (index >= 0) && (index < self.length)
|
||||
if valid_index.not then default else
|
||||
|
@ -7,3 +7,6 @@ type Column_Ref
|
||||
|
||||
## Reference to a column by index in a table.
|
||||
Index index:Integer
|
||||
|
||||
## Representation of an expression derived in a table.
|
||||
Expression expression:Text
|
||||
|
@ -1,6 +1,6 @@
|
||||
from Standard.Base import all
|
||||
import Standard.Base.Errors.Illegal_Argument.Illegal_Argument
|
||||
import Standard.Base.Data.Java_Json.Jackson_Object
|
||||
import Standard.Base.Errors.Illegal_Argument.Illegal_Argument
|
||||
|
||||
## PRIVATE
|
||||
A special type describing how to convert an object into a set of table
|
||||
|
@ -91,4 +91,4 @@ type Key_Value
|
||||
|
||||
## PRIVATE
|
||||
Convertible_To_Columns.from (that:Key_Value) =
|
||||
Convertible_To_Columns.Value ["Key", "Value"] (k-> if k == "Key" then that.key else that.value)
|
||||
Convertible_To_Columns.Value ["Key", "Value"] (k-> if k == "Key" then that.key else that.value)
|
||||
|
@ -140,8 +140,8 @@ type Delimited_Format
|
||||
self.clone value_formatter=Nothing
|
||||
|
||||
## Creates a clone of this with a changed line ending style.
|
||||
with_line_endings : Line_Ending_Style|Infer -> Delimited_Format
|
||||
with_line_endings self (line_endings : Line_Ending_Style | Infer)=Infer =
|
||||
with_line_endings : Line_Ending_Style | Infer -> Delimited_Format
|
||||
with_line_endings self (line_endings : Line_Ending_Style | Infer = Infer) =
|
||||
self.clone line_endings=line_endings
|
||||
|
||||
## Creates a clone of this with comment parsing enabled.
|
||||
|
@ -34,7 +34,7 @@ type Excel_Workbook
|
||||
- xls_format: Whether to use the old XLS format (default is XLSX).
|
||||
- headers: Whether to use the first row as headers (default is to infer).
|
||||
new : File | Temporary_File -> Boolean -> Boolean | Infer -> Excel_Workbook
|
||||
new file:(File|Temporary_File) xls_format=False headers=Infer =
|
||||
new file:(File | Temporary_File) xls_format=False headers=Infer =
|
||||
file_for_errors = if file.is_a Temporary_File then Nothing else file
|
||||
|
||||
continuation raw_file =
|
||||
|
@ -7,7 +7,7 @@ import project.Data.Column_Ref.Column_Ref
|
||||
import project.Data.Expression.Expression_Error
|
||||
import project.Data.Set_Mode.Set_Mode
|
||||
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
|
||||
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 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
|
||||
Resolve a Column_Ref to a Column, keeping any other values as-is.
|
||||
resolve : Any -> Any ! No_Such_Column | Index_Out_Of_Bounds
|
||||
resolve self value = case value of
|
||||
Column_Ref.Name name -> self.at name
|
||||
Column_Ref.Index index -> self.at index
|
||||
Column_Ref.Expression expression -> self.evaluate_expression expression
|
||||
_ -> value
|
||||
|
||||
## PRIVATE
|
||||
@ -38,28 +50,26 @@ type Table_Ref
|
||||
resolve_as_column self value = case value of
|
||||
Column_Ref.Name name -> self.at name
|
||||
Column_Ref.Index index -> self.at index
|
||||
Column_Ref.Expression expression -> self.evaluate_expression expression
|
||||
_ -> self.underlying.make_constant_column value
|
||||
|
||||
## PRIVATE
|
||||
Transforms a condition, changing any Column_Ref instances into Column instances resolved in this table.
|
||||
resolve_condition : Filter_Condition -> Filter_Condition
|
||||
resolve_condition self condition = case condition of
|
||||
Filter_Condition.Equal value -> Filter_Condition.Equal (self.resolve value)
|
||||
Filter_Condition.Not_Equal value -> Filter_Condition.Not_Equal (self.resolve value)
|
||||
Filter_Condition.Less value -> Filter_Condition.Less (self.resolve value)
|
||||
Filter_Condition.Equal_Or_Less value -> Filter_Condition.Equal_Or_Less (self.resolve value)
|
||||
Filter_Condition.Greater value -> Filter_Condition.Greater (self.resolve value)
|
||||
Filter_Condition.Equal_Or_Greater value -> Filter_Condition.Equal_Or_Greater (self.resolve value)
|
||||
Filter_Condition.Between lower upper -> Filter_Condition.Between (self.resolve lower) (self.resolve upper)
|
||||
Filter_Condition.Equal_Ignore_Case value locale -> Filter_Condition.Equal_Ignore_Case (self.resolve value) locale
|
||||
Filter_Condition.Starts_With prefix case_sensitivity -> Filter_Condition.Starts_With (self.resolve prefix) case_sensitivity
|
||||
Filter_Condition.Ends_With prefix case_sensitivity -> Filter_Condition.Ends_With (self.resolve prefix) case_sensitivity
|
||||
Filter_Condition.Contains prefix case_sensitivity -> Filter_Condition.Contains (self.resolve prefix) case_sensitivity
|
||||
Filter_Condition.Not_Contains prefix case_sensitivity -> Filter_Condition.Not_Contains (self.resolve prefix) case_sensitivity
|
||||
Filter_Condition.Like pattern -> Filter_Condition.Like (self.resolve pattern)
|
||||
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)
|
||||
Filter_Condition.Equal value action -> Filter_Condition.Equal (self.resolve value) action
|
||||
Filter_Condition.Not_Equal value action -> Filter_Condition.Not_Equal (self.resolve value) action
|
||||
Filter_Condition.Less value action -> Filter_Condition.Less (self.resolve value) action
|
||||
Filter_Condition.Equal_Or_Less value action -> Filter_Condition.Equal_Or_Less (self.resolve value) action
|
||||
Filter_Condition.Greater value action -> Filter_Condition.Greater (self.resolve value) action
|
||||
Filter_Condition.Equal_Or_Greater value action -> Filter_Condition.Equal_Or_Greater (self.resolve value) action
|
||||
Filter_Condition.Between lower upper action -> Filter_Condition.Between (self.resolve lower) (self.resolve upper) action
|
||||
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 action -> Filter_Condition.Starts_With (self.resolve prefix) case_sensitivity action
|
||||
Filter_Condition.Ends_With prefix case_sensitivity action -> Filter_Condition.Ends_With (self.resolve prefix) case_sensitivity action
|
||||
Filter_Condition.Contains prefix case_sensitivity action -> Filter_Condition.Contains (self.resolve prefix) case_sensitivity action
|
||||
Filter_Condition.Like pattern action -> Filter_Condition.Like (self.resolve pattern) action
|
||||
Filter_Condition.Is_In values action -> Filter_Condition.Is_In (check_is_in_values "Is_In" values) action
|
||||
_ -> condition
|
||||
|
||||
## PRIVATE
|
||||
|
@ -78,7 +78,7 @@ expand_column (table : Table) (column : Text | Integer) (fields : (Vector Text)
|
||||
# => Table.new [["aaa", [1, 1, 2, 2]], ["bbb", [30, 31, 40, 41]]]
|
||||
@column Widget_Helpers.make_column_name_selector
|
||||
expand_to_rows : Table -> Text | Integer -> Boolean -> Table ! Type_Error | No_Such_Column | Index_Out_Of_Bounds
|
||||
expand_to_rows table column:(Text|Integer) at_least_one_row=False = if column.is_a Integer then expand_to_rows table (table.at column).name at_least_one_row else
|
||||
expand_to_rows table column:(Text | Integer) at_least_one_row=False = if column.is_a Integer then expand_to_rows table (table.at column).name at_least_one_row else
|
||||
row_expander : Any -> Vector
|
||||
row_expander value:Convertible_To_Rows = value.to_vector
|
||||
|
||||
|
@ -13,80 +13,73 @@ from project.Errors import Nothing_Value_In_Filter_Condition
|
||||
|
||||
It also performs validation and will throw errors if unexpected column types
|
||||
are encountered.
|
||||
make_filter_column source_column filter_condition on_problems = case filter_condition of
|
||||
# Equality
|
||||
Equal value ->
|
||||
warn_on_nothing_in_comparison filter_condition value <|
|
||||
Warning.with_suspended source_column source_column->
|
||||
Warning.with_suspended value value->
|
||||
on_problems.escalate_warnings <|
|
||||
source_column == value
|
||||
Not_Equal value ->
|
||||
warn_on_nothing_in_comparison filter_condition value <|
|
||||
Warning.with_suspended source_column source_column->
|
||||
Warning.with_suspended value value->
|
||||
on_problems.escalate_warnings <|
|
||||
source_column != value
|
||||
# Nothing
|
||||
Is_Nothing -> source_column.is_nothing
|
||||
Not_Nothing -> source_column.is_nothing.not
|
||||
# Boolean
|
||||
Is_True ->
|
||||
Value_Type.expect_boolean source_column <| source_column
|
||||
Is_False -> source_column.not
|
||||
# Comparisons
|
||||
Less value ->
|
||||
warn_on_nothing_in_comparison filter_condition value <|
|
||||
source_column < value
|
||||
Equal_Or_Less value ->
|
||||
warn_on_nothing_in_comparison filter_condition value <|
|
||||
source_column <= value
|
||||
Equal_Or_Greater value ->
|
||||
warn_on_nothing_in_comparison filter_condition value <|
|
||||
source_column >= value
|
||||
Greater value ->
|
||||
warn_on_nothing_in_comparison filter_condition value <|
|
||||
source_column > value
|
||||
Between lower upper ->
|
||||
warn_on_nothing_in_comparison filter_condition lower <|
|
||||
warn_on_nothing_in_comparison filter_condition upper <|
|
||||
source_column.between lower upper
|
||||
# Text
|
||||
Equal_Ignore_Case value locale ->
|
||||
source_column.equals_ignore_case value locale
|
||||
Starts_With prefix case_sensitivity ->
|
||||
source_column.starts_with prefix case_sensitivity
|
||||
Ends_With suffix case_sensitivity ->
|
||||
source_column.ends_with suffix case_sensitivity
|
||||
Contains substring case_sensitivity ->
|
||||
source_column.contains substring case_sensitivity
|
||||
Not_Contains substring case_sensitivity ->
|
||||
source_column.contains substring case_sensitivity . not
|
||||
Is_Empty ->
|
||||
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
|
||||
Is_Nan -> source_column.is_nan
|
||||
Is_Infinite -> source_column.is_infinite
|
||||
Is_Finite ->
|
||||
is_infinite_column = source_column.is_infinite
|
||||
is_nan_column = source_column.is_nan
|
||||
## We check is_nan_column for error, since some Database backends may
|
||||
actually not support it and throw Unsupported_Database_Operation here.
|
||||
if is_nan_column.is_error then is_infinite_column.not else
|
||||
(is_infinite_column || is_nan_column).not
|
||||
# Vector
|
||||
Is_In values ->
|
||||
warn_on_nothing_in_comparison_vector filter_condition values <|
|
||||
source_column.is_in values
|
||||
Not_In values ->
|
||||
warn_on_nothing_in_comparison_vector filter_condition values <|
|
||||
source_column.is_in values . not
|
||||
make_filter_column source_column filter_condition on_problems =
|
||||
base_column = case filter_condition of
|
||||
# Equality
|
||||
Equal value _ ->
|
||||
warn_on_nothing_in_comparison filter_condition value <|
|
||||
Warning.with_suspended source_column source_column->
|
||||
Warning.with_suspended value value->
|
||||
on_problems.escalate_warnings <|
|
||||
source_column == value
|
||||
Not_Equal value _ ->
|
||||
warn_on_nothing_in_comparison filter_condition value <|
|
||||
Warning.with_suspended source_column source_column->
|
||||
Warning.with_suspended value value->
|
||||
on_problems.escalate_warnings <|
|
||||
source_column != value
|
||||
# Nothing
|
||||
Is_Nothing _ -> source_column.is_nothing
|
||||
Not_Nothing _ -> source_column.is_nothing.not
|
||||
# Boolean
|
||||
Is_True _ -> Value_Type.expect_boolean source_column <| source_column
|
||||
Is_False _ -> Value_Type.expect_boolean source_column <| source_column.not
|
||||
# Comparisons
|
||||
Less value _ ->
|
||||
warn_on_nothing_in_comparison filter_condition value <|
|
||||
source_column < value
|
||||
Equal_Or_Less value _ ->
|
||||
warn_on_nothing_in_comparison filter_condition value <|
|
||||
source_column <= value
|
||||
Equal_Or_Greater value _ ->
|
||||
warn_on_nothing_in_comparison filter_condition value <|
|
||||
source_column >= value
|
||||
Greater value _ ->
|
||||
warn_on_nothing_in_comparison filter_condition value <|
|
||||
source_column > value
|
||||
Between lower upper _ ->
|
||||
warn_on_nothing_in_comparison filter_condition lower <|
|
||||
warn_on_nothing_in_comparison filter_condition upper <|
|
||||
source_column.between lower upper
|
||||
# Text
|
||||
Equal_Ignore_Case value locale _ ->
|
||||
source_column.equals_ignore_case value locale
|
||||
Starts_With prefix case_sensitivity _ ->
|
||||
source_column.starts_with prefix case_sensitivity
|
||||
Ends_With suffix case_sensitivity _ ->
|
||||
source_column.ends_with suffix case_sensitivity
|
||||
Contains substring case_sensitivity _ ->
|
||||
source_column.contains substring case_sensitivity
|
||||
Is_Empty _ -> source_column.is_empty
|
||||
Not_Empty _ -> source_column.is_empty.not
|
||||
Like pattern _ -> source_column.like pattern
|
||||
# Numeric
|
||||
Is_Nan _ -> source_column.is_nan
|
||||
Is_Infinite _ -> source_column.is_infinite
|
||||
Is_Finite _ ->
|
||||
is_infinite_column = source_column.is_infinite
|
||||
is_nan_column = source_column.is_nan
|
||||
## We check is_nan_column for error, since some Database backends may
|
||||
actually not support it and throw Unsupported_Database_Operation here.
|
||||
if is_nan_column.is_error then is_infinite_column.not else
|
||||
(is_infinite_column || is_nan_column).not
|
||||
# Vector
|
||||
Is_In values _ ->
|
||||
warn_on_nothing_in_comparison_vector filter_condition values <|
|
||||
source_column.is_in values
|
||||
if filter_condition.action == Filter_Action.Keep then base_column else
|
||||
## We need to fill in the Nothing values and then negate the result.
|
||||
(base_column.fill_nothing False).not
|
||||
|
||||
## Attach a warning if the provided value is `Nothing`.
|
||||
warn_on_nothing_in_comparison : Filter_Condition -> Any -> Any -> Any
|
||||
|
@ -17,7 +17,7 @@ split_to_columns table input_column_id delimiter="," column_count=Nothing on_pro
|
||||
Splits a column of text into a set of new rows.
|
||||
See `Table.split_to_rows`.
|
||||
split_to_rows : Table -> Text | Integer -> Text -> Table
|
||||
split_to_rows table input_column_id:(Text|Integer) delimiter="," =
|
||||
split_to_rows table input_column_id:(Text | Integer) delimiter="," =
|
||||
column = table.at input_column_id
|
||||
Value_Type.expect_text column <|
|
||||
fan_out_to_rows table column.name (handle_nothing (_.split delimiter)) at_least_one_row=True
|
||||
|
@ -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=Display.Always =
|
||||
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
|
||||
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 =
|
||||
col_names_options = table.column_names.map (name -> Option name "(Column_Ref.Name "+name.pretty+")")
|
||||
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
|
||||
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+")")
|
||||
custom_text_option = if include_custom_text then [Option "'custom text'" "''"] else []
|
||||
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
|
||||
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 "Ends With" fqn+".Ends_With" [["suffix", 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 Not Nothing" fqn+".Not_Nothing")
|
||||
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 Not Empty" fqn+".Not_Empty")
|
||||
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 "Not In" fqn+".Not_In")
|
||||
Single_Choice builder.to_vector display=display
|
||||
|
||||
## PRIVATE
|
||||
|
@ -5,13 +5,13 @@ from Standard.Base.Runtime import State
|
||||
|
||||
import project.Clue.Clue
|
||||
import project.Group.Group
|
||||
import project.Spec_Result.Spec_Result
|
||||
import project.Spec.Spec
|
||||
import project.Spec_Result.Spec_Result
|
||||
import project.Suite.Suite
|
||||
import project.Suite_Config.Suite_Config
|
||||
import project.Test_Result.Test_Result
|
||||
import project.Test_Reporter
|
||||
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 : 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 : 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) =
|
||||
case specs.is_empty of
|
||||
True -> []
|
||||
|
@ -1,9 +1,10 @@
|
||||
import project.Problems
|
||||
import project.Suite.Suite
|
||||
import project.Test.Test
|
||||
import project.Problems
|
||||
from project.Extensions import all
|
||||
|
||||
export project.Problems
|
||||
export project.Suite.Suite
|
||||
export project.Test.Test
|
||||
export project.Problems
|
||||
from project.Extensions export all
|
||||
|
||||
|
@ -28,7 +28,7 @@ type Suite_Builder
|
||||
`specify` method on group builder. See its docs.
|
||||
- pending: Contains a reason for why the test group should be ignored. If Nothing, the test
|
||||
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_builder = Group_Builder.Impl
|
||||
case pending of
|
||||
@ -62,7 +62,7 @@ type Suite
|
||||
- group_filter: Filter for group names.
|
||||
- spec_filter: Filter for spec names.
|
||||
- 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 =
|
||||
config = Suite_Config.from_environment
|
||||
|
||||
@ -99,9 +99,11 @@ type Suite
|
||||
False ->
|
||||
failed_tests == 0
|
||||
|
||||
## Gets the names of all the groups in this suite.
|
||||
group_names self =
|
||||
self.groups.map (_.name)
|
||||
|
||||
## Print the structure of the suite to the console.
|
||||
print_all self =
|
||||
IO.println "Test Suite:"
|
||||
self.groups.each group->
|
||||
|
@ -1,14 +1,14 @@
|
||||
from Standard.Base import all
|
||||
from Standard.Base.Errors.Common import Uninitialized_State
|
||||
from Standard.Base.Runtime import State
|
||||
import project.Test_Result.Test_Result
|
||||
|
||||
import project.Clue.Clue
|
||||
import project.Group.Group
|
||||
import project.Suite.Suite
|
||||
import project.Suite.Suite_Builder
|
||||
import project.Spec.Spec
|
||||
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
|
||||
type Test
|
||||
@ -46,26 +46,27 @@ type Test
|
||||
if err.is_a matcher then Nothing else
|
||||
Test.fail ("Expected a " + matcher.to_text + ", but " + err.to_text + " was thrown instead.")
|
||||
|
||||
## Expect a function to fail with the provided panic.
|
||||
## Expect a function to fail with the provided panic.
|
||||
|
||||
An alternative API to `expect_panic_with` where the order of arguments is
|
||||
more natural - as it allows blocks without reordering the arguments.
|
||||
An alternative API to `expect_panic_with` where the order of arguments is
|
||||
more natural - as it allows blocks without reordering the arguments.
|
||||
|
||||
Arguments:
|
||||
- matcher: The expected type of the panic thrown by `action`.
|
||||
- action: The action to evaluate that is expected to fail with a panic.
|
||||
Arguments:
|
||||
- matcher: The expected type of the panic thrown by `action`.
|
||||
- action: The action to evaluate that is expected to fail with a panic.
|
||||
|
||||
> Example
|
||||
Expect that a computation should panic as part of a test.
|
||||
> Example
|
||||
Expect that a computation should panic as part of a test.
|
||||
|
||||
import Standard.Examples
|
||||
from Standard.Test import Test
|
||||
import Standard.Examples
|
||||
from Standard.Test import Test
|
||||
|
||||
example_expect_panic_with =
|
||||
Test.expect_panic_with Examples.My_Error <|
|
||||
IO.println 'hello'
|
||||
Examples.throw_panic
|
||||
IO.println 'this is not reached'
|
||||
example_expect_panic_with =
|
||||
Test.expect_panic_with Examples.My_Error <|
|
||||
IO.println 'hello'
|
||||
Examples.throw_panic
|
||||
|
||||
IO.println 'this is not reached'
|
||||
expect_panic : Any -> Any -> Test_Result
|
||||
expect_panic matcher ~action = Test.expect_panic_with action matcher
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
private
|
||||
|
||||
from Standard.Base import all
|
||||
from Standard.Base.Runtime import assert
|
||||
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.Suite_Config.Suite_Config
|
||||
import project.Test.Test
|
||||
import project.Test_Result.Test_Result
|
||||
|
||||
@ -74,7 +74,7 @@ print_single_result (test_result : Test_Result) (config : Suite_Config) =
|
||||
groups.
|
||||
- builder: StringBuilder or Nothing. If StringBuilder, then a jUnit XML format is appended to
|
||||
that StringBuilder.
|
||||
print_report : Vector Test_Result -> Suite_Config -> (StringBuilder|Nothing) -> Nothing
|
||||
print_report : Vector Test_Result -> Suite_Config -> (StringBuilder | Nothing) -> Nothing
|
||||
print_report (test_results : Vector Test_Result) (config : Suite_Config) (builder : (StringBuilder | Nothing)) =
|
||||
distinct_group_names = test_results.map (_.group_name) . distinct
|
||||
results_per_group = distinct_group_names.fold Map.empty acc-> group_name->
|
||||
|
@ -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.
|
||||
type Test_Result
|
||||
## PRIVATE
|
||||
Impl (group_name : Text) (spec_name : Text) (spec_result : Spec_Result) (time_taken : Duration)
|
||||
|
||||
## PRIVATE
|
||||
Render as Test_Result as Text.
|
||||
to_text self =
|
||||
"'" + self.group_name + "' '" + self.spec_name + "': " + self.spec_result.to_text
|
||||
|
||||
|
||||
## Was the test pending?
|
||||
is_pending self =
|
||||
self.spec_result.is_pending
|
||||
|
||||
|
||||
## Was the test successful?
|
||||
is_success self =
|
||||
self.spec_result.is_success
|
||||
|
||||
|
||||
## Was the test a failure?
|
||||
is_fail self =
|
||||
self.spec_result.is_fail
|
||||
|
||||
|
@ -124,7 +124,7 @@ public final class BoolStorage extends Storage<Boolean> {
|
||||
*/
|
||||
private Storage<?> fillMissingBoolean(boolean arg) {
|
||||
final var newValues = (BitSet) values.clone();
|
||||
if (arg) {
|
||||
if (arg != negated) {
|
||||
newValues.or(isMissing);
|
||||
} else {
|
||||
newValues.andNot(isMissing);
|
||||
|
@ -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)
|
||||
|
||||
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 '{"constructor": "Less", "than": 2}' . into Filter_Condition . should_equal (Filter_Condition.Less 2)
|
||||
Json.parse '{"constructor": "NotARealOne", "than": 2}' . into Filter_Condition . should_fail_with Illegal_Argument
|
||||
Json.parse '{"than": 2}' . into Statistic . should_fail_with Illegal_Argument
|
||||
Json.parse '{"constructor": "Skew", "population": true}' . into Statistic . should_equal (Statistic.Skew True)
|
||||
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" <|
|
||||
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]])
|
||||
|
@ -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.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
|
||||
|
||||
@ -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.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
|
||||
|
||||
@ -70,6 +72,7 @@ add_specs suite_builder = suite_builder.group "List" group_builder->
|
||||
empty.find (==1) if_missing=Nothing . should_equal Nothing
|
||||
|
||||
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
|
||||
|
||||
@ -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 (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
|
||||
|
||||
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.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
|
||||
|
||||
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" <|
|
||||
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 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.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
|
||||
@ -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.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.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.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.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
|
||||
@ -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' 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.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" Case_Sensitivity.Sensitive) . should_equal [].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"].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.Not_Like "%ba%") . should_equal List.Nil
|
||||
|
||||
mixed = [1, Nothing, "b"].to_list
|
||||
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.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.first . should_equal List.Nil
|
||||
r3.second . should_equal l
|
||||
|
@ -152,30 +152,48 @@ add_specs suite_builder = suite_builder.group "Range" group_builder->
|
||||
|
||||
group_builder.specify "should filter elements by Filter_Condition" <|
|
||||
range = 1.up_to 6
|
||||
range.filter (Filter_Condition.Greater than=3) . should_equal [4, 5]
|
||||
range.filter (Filter_Condition.Less than=3.5) . should_equal [1, 2, 3]
|
||||
range.filter (Filter_Condition.Equal to=3) . should_equal [3]
|
||||
range.filter (Filter_Condition.Not_Equal to=3) . should_equal [1, 2, 4, 5]
|
||||
range.filter (Filter_Condition.Equal_Or_Greater than=3) . should_equal [3, 4, 5]
|
||||
range.filter (Filter_Condition.Equal_Or_Less than=(-1)) . should_equal []
|
||||
range.filter (Filter_Condition.Greater 3) . should_equal [4, 5]
|
||||
range.filter (Filter_Condition.Greater 3 Filter_Action.Remove) . should_equal [1, 2, 3]
|
||||
range.filter (Filter_Condition.Less 3.5) . should_equal [1, 2, 3]
|
||||
range.filter (Filter_Condition.Less 3.5 Filter_Action.Remove) . should_equal [4, 5]
|
||||
range.filter (Filter_Condition.Equal 3) . should_equal [3]
|
||||
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.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.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 Filter_Action.Remove) . should_equal [1, 2, 3, 4, 5]
|
||||
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_True . should_equal []
|
||||
range.filter Filter_Condition.Is_False . should_equal []
|
||||
range.filter (Filter_Condition.Is_Finite Filter_Action.Remove) . 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.Is_Empty . should_equal []
|
||||
range.filter Filter_Condition.Not_Empty . should_equal [1, 2, 3, 4, 5]
|
||||
range.filter (Filter_Condition.Not_Nothing Filter_Action.Remove) . should_equal []
|
||||
|
||||
## 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" <|
|
||||
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.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.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" <|
|
||||
vec_mut = Vector.new_builder
|
||||
1.up_to 6 . each (i -> vec_mut.append i)
|
||||
vec_mut.to_vector . should_equal [1, 2, 3, 4, 5]
|
||||
|
||||
group_builder.specify "should allow iteration, with error propagation and early exit" <|
|
||||
vec_mut = Vector.new_builder
|
||||
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
|
||||
result . should_fail_with Illegal_Argument
|
||||
vec_mut.to_vector . should_equal [1, 2]
|
||||
|
||||
group_builder.specify "should allow iteration with index" <|
|
||||
vec_mut = Vector.new_builder
|
||||
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->
|
||||
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]
|
||||
|
||||
group_builder.specify "should be able to be folded" <|
|
||||
1.up_to 6 . fold 0 (+) . should_equal 15
|
||||
1.up_to 1 . fold 123 (+) . should_equal 123
|
||||
|
||||
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 1 . running_fold 123 (+) . should_equal []
|
||||
|
||||
group_builder.specify "should be able to be reduced" <|
|
||||
1.up_to 6 . reduce (+) . should_equal 15
|
||||
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 (+) 0 . should_equal 0
|
||||
|
||||
group_builder.specify "should check all" <|
|
||||
1.up_to 10 . all (> 0) . should_be_true
|
||||
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 Filter_Action.Remove) . should_be_true
|
||||
Test.expect_panic_with (1.up_to 10 . all "invalid arg") Type_Error
|
||||
|
||||
group_builder.specify "should check any" <|
|
||||
1.up_to 10 . any (> 5) . should_be_true
|
||||
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.Equal_Or_Greater 1 Filter_Action.Remove) . should_be_false
|
||||
Test.expect_panic_with (1.up_to 10 . any "invalid arg") Type_Error
|
||||
|
||||
group_builder.specify "should find elements" <|
|
||||
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 (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=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)
|
||||
Test.expect_panic_with (1.up_to 10 . find "invalid arg") Type_Error
|
||||
|
||||
group_builder.specify "should find index of elements" <|
|
||||
1.up_to 10 . index_of (> 5) . should_equal 5
|
||||
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=-1 . should_equal Nothing
|
||||
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 2.5 . should_fail_with Illegal_Argument
|
||||
|
||||
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 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=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 (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 2.5 . should_fail_with Illegal_Argument
|
||||
|
||||
group_builder.specify "should allow conversion to vector" <|
|
||||
1.up_to 6 . to_vector . should_equal [1, 2, 3, 4, 5]
|
||||
|
||||
group_builder.specify "should allow reversing" <|
|
||||
1.up_to 6 . reverse . should_equal (5.down_to 0)
|
||||
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 3.0 . should_fail_with Illegal_Argument
|
||||
|
||||
|
||||
verify_contains range expected unexpected =
|
||||
expected.each x->
|
||||
if range.contains x . not then
|
||||
@ -305,10 +343,12 @@ add_specs suite_builder = suite_builder.group "Range" group_builder->
|
||||
unexpected.each x->
|
||||
if range.contains x then
|
||||
Test.fail "Range "+range.to_text+" unexpectedly contained "+x.to_text+"."
|
||||
|
||||
build_with_each range =
|
||||
builder = Vector.new_builder
|
||||
range.each builder.append
|
||||
builder.to_vector
|
||||
|
||||
group_builder.specify "should behave correctly if it is empty" <|
|
||||
check_empty_range r =
|
||||
r.is_empty . should_be_true
|
||||
|
@ -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 (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 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 (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
|
||||
|
||||
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 -> 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.filter (Filter_Condition.Greater than=3) . should_equal [4, 5]
|
||||
vec.filter (Filter_Condition.Less than=3.5) . should_equal [1, 2, 3]
|
||||
vec.filter (Filter_Condition.Equal to=3) . should_equal [3]
|
||||
vec.filter (Filter_Condition.Equal to=3.0) . should_equal [3]
|
||||
vec.filter (Filter_Condition.Equal to=3.1) . should_equal []
|
||||
vec.filter (Filter_Condition.Not_Equal to=3) . should_equal [1, 2, 4, 5]
|
||||
vec.filter (Filter_Condition.Equal_Or_Greater than=3) . should_equal [3, 4, 5]
|
||||
vec.filter (Filter_Condition.Equal_Or_Less than=(-1)) . should_equal []
|
||||
vec.filter (Filter_Condition.Greater 3) . should_equal [4, 5]
|
||||
vec.filter (Filter_Condition.Greater 3 Filter_Action.Remove) . should_equal [1, 2, 3]
|
||||
vec.filter (Filter_Condition.Less 3.5) . should_equal [1, 2, 3]
|
||||
vec.filter (Filter_Condition.Less 3.5 Filter_Action.Remove) . should_equal [4, 5]
|
||||
vec.filter (Filter_Condition.Equal 3) . should_equal [3]
|
||||
vec.filter (Filter_Condition.Equal 3 Filter_Action.Remove) . should_equal [1, 2, 4, 5]
|
||||
vec.filter (Filter_Condition.Not_Equal 3) . should_equal [1, 2, 4, 5]
|
||||
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.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 []) . should_equal []
|
||||
vec.filter (Filter_Condition.Not_In [7, 3, 2, 2]) . should_equal [1, 4, 5]
|
||||
vec.filter (Filter_Condition.Is_In [7, 3, 2] Filter_Action.Remove) . 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.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" 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.Insensitive) . should_equal ["aaa", "abab", "baaa"]
|
||||
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.Insensitive) . should_equal ["ś"]
|
||||
txtvec.filter (Filter_Condition.Not_Contains "a") . should_equal ["bbb", "cccc", "ś"]
|
||||
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"]
|
||||
Test.expect_panic_with (txtvec.filter (Filter_Condition.Contains 42)) Unsupported_Argument_Types
|
||||
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.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" 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.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.Greater than="b") . should_equal ["bbb", "cccc", "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 ["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.Not_Empty) . should_equal [" ", "a"]
|
||||
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 ["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.Not_Like "%.*") . should_equal ["f.txt"]
|
||||
|
||||
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_' 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_b') . should_equal ['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.filter (Filter_Condition.Starts_With 'ś') . 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 ['połać', 'połac\u0301']
|
||||
## 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 'FFI') . should_equal ['ffi']
|
||||
|
||||
group_builder.specify "should filter mixed elements by Filter_Condition" <|
|
||||
mixed = alter [1, Nothing, "b"]
|
||||
mixed.filter Filter_Condition.Is_Nothing . should_equal [Nothing]
|
||||
mixed.filter Filter_Condition.Not_Nothing . should_equal [1, "b"]
|
||||
mixed.filter Filter_Condition.Is_Empty . should_equal [Nothing]
|
||||
mixed.filter Filter_Condition.Not_Empty . should_equal [1, "b"]
|
||||
|
||||
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)
|
||||
Test.expect_panic Type_Error (mixed.filter Filter_Condition.Is_Empty)
|
||||
Test.expect_panic Type_Error (mixed.filter Filter_Condition.Not_Empty)
|
||||
|
||||
(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.Ends_With "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]
|
||||
|
||||
@ -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
|
||||
|
||||
group_builder.specify "should partition elements" <|
|
||||
vec = alter [1, 2, 3, 4, 5]
|
||||
vec.partition (x -> x % 2 == 0) . should_equal <| Pair.new [2, 4] [1, 3, 5]
|
||||
vec = alter [1, 2, 3, 4, 5, Nothing]
|
||||
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 (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")
|
||||
|
||||
@ -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 (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")
|
||||
|
||||
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 (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
|
||||
|
||||
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 (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
|
||||
|
||||
group_builder.specify "should be convertible to a list" <|
|
||||
|
@ -596,6 +596,18 @@ add_specs suite_builder setup =
|
||||
actual.at "col1" . to_vector . should_equal [1000, 200, 1000, 400, 500, 1000]
|
||||
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->
|
||||
data = Data.setup create_connection_fn
|
||||
|
||||
|
@ -136,6 +136,7 @@ add_specs suite_builder setup =
|
||||
group_builder.specify "if" <|
|
||||
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") 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.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.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.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.
|
||||
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"]]]
|
||||
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.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" <|
|
||||
t = table_builder [["A", [" a ", "b"]], ["B", ["c", " d "]]]
|
||||
|
@ -49,19 +49,29 @@ add_specs suite_builder setup =
|
||||
|
||||
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]]]
|
||||
t1 = t.filter "X" (Filter_Condition.Less than=10)
|
||||
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=10) . 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 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 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 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 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]
|
||||
t2 = t.filter "X" (Filter_Condition.Equal to=100)
|
||||
t2 . at "X" . to_vector . should_equal [100]
|
||||
t2 . at "ix" . to_vector . should_equal [1]
|
||||
|
||||
t.filter "X" (Filter_Condition.Between 4 100 action=Filter_Action.Remove) . at "X" . to_vector . should_equal [3, Nothing]
|
||||
t.filter "X" (Filter_Condition.Equal to=100) . at "X" . to_vector . should_equal [100]
|
||||
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
|
||||
## 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
|
||||
@ -71,25 +81,26 @@ add_specs suite_builder setup =
|
||||
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") 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") 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") 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") 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") 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 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.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.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.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 "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" <|
|
||||
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
|
||||
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]]]
|
||||
t3 = t.filter "X" (Filter_Condition.Not_Equal to=100)
|
||||
t3 . at "X" . to_vector . should_equal [3, Nothing, 4, 12]
|
||||
t3 . at "ix" . to_vector . should_equal [2, 3, 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=(Column_Ref.Name "Y")) . 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, 4, 5]
|
||||
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, 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" <|
|
||||
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.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.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" 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.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" 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.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") 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.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"]
|
||||
@ -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") 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.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.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.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)" <|
|
||||
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%" 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 "%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 "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" <|
|
||||
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']
|
||||
@ -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 '\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.Not_Contains '\nb') . at "X" . to_vector . should_equal ['a\n\n\n', 'a\n']
|
||||
|
||||
if test_selection.supports_unicode_normalization then
|
||||
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.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.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.
|
||||
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.Contains (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.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.Contains (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.Starts_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.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.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.Contains 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" <|
|
||||
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" <|
|
||||
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]]]
|
||||
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" . 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 []) . 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
|
||||
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 [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.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
|
||||
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 "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),
|
||||
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
|
||||
@ -459,7 +448,6 @@ add_specs suite_builder setup =
|
||||
+ [Filter_Condition.Less Nothing, Filter_Condition.Equal_Or_Less Nothing]
|
||||
+ [Filter_Condition.Equal_Or_Greater Nothing, Filter_Condition.Greater Nothing]
|
||||
+ [Filter_Condition.Between Nothing Nothing , Filter_Condition.Is_In [Nothing]]
|
||||
+ [Filter_Condition.Not_In [Nothing]]
|
||||
+ [Filter_Condition.Is_In [1, Nothing, 2]]
|
||||
fcs.map fc->
|
||||
Test.with_clue fc.to_text <|
|
||||
|
@ -75,7 +75,7 @@ add_specs suite_builder setup =
|
||||
## TODO currently our builder does not allow all-null tables, so we
|
||||
create one with a 0 and remove it by filter. See #6159.
|
||||
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.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" <|
|
||||
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.at "X" . to_vector . should_equal []
|
||||
|
||||
|
@ -42,14 +42,17 @@ add_specs suite_builder =
|
||||
group_builder.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
|
||||
|
||||
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 = JS_Object.from_pairs [["sql_interpolation", part2_sub]]
|
||||
part3 = JS_Object.from_pairs [["sql_code", ")"]]
|
||||
expected = JS_Object.from_pairs [["query", [part1, part2, part3]]] . to_text
|
||||
part3 = JS_Object.from_pairs [["sql_code", ")) = ("]]
|
||||
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
|
||||
|
||||
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.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" <|
|
||||
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"]]
|
||||
|
@ -4,7 +4,6 @@ from Standard.Table import Table
|
||||
|
||||
import Standard.Examples
|
||||
import Standard.Visualization.Table as Table_Visualization
|
||||
import Standard.Visualization.Preprocessor as Preprocessor
|
||||
|
||||
from Standard.Test_New import all
|
||||
|
||||
|
@ -3,7 +3,6 @@ from Standard.Visualization import all
|
||||
|
||||
import Standard.Examples
|
||||
import Standard.Visualization.Text as TextVis
|
||||
import Standard.Visualization.Preprocessor as Preprocessor
|
||||
|
||||
from Standard.Test_New import all
|
||||
|
||||
|
@ -10,7 +10,7 @@ main =
|
||||
operator14 = var1.to_column "Color"
|
||||
operator16 = operator14.to_table
|
||||
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
|
||||
operator4 = operator3.select_columns ['Operation']
|
||||
operator5 = operator4.distinct
|
||||
|
Loading…
Reference in New Issue
Block a user