Moving library statics to type for Table. (#3760)

- Generally export types not modules from the `Standard.Table` import.
- Moved `new`, `from_rows` the `Standard.Table` library into the `Table` type.
- Renames `Standard.Table.Data.Storage.Type` to `Standard.Table.Data.Storage.Storage`
- Removed the internal `from_columns` method.
- Removed `join` and `concat` and merged into instance methods.
- Removed `Table` and `Column` from the `Standard.Database` exports.
- Removed `Standard.Table.Data.Column.Aggregate_Column` as not used any more.
This commit is contained in:
James Dunkerley 2022-10-06 18:01:18 +01:00 committed by GitHub
parent 486874216b
commit 185378f07c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
89 changed files with 698 additions and 1063 deletions

View File

@ -1,7 +1,6 @@
from Standard.Base import all
import Standard.Base.Data.Index_Sub_Range
import Standard.Base.Random
import Standard.Base.Runtime.Unsafe
polyglot java import java.lang.IndexOutOfBoundsException
polyglot java import org.enso.base.Array_Builder

View File

@ -40,7 +40,7 @@ type Connection
## Returns the list of databases (or catalogs) for the connection.
databases : [Text]
databases : Vector Text
databases self =
self.jdbc_connection.with_metadata metadata->
read_column metadata.getCatalogs "TABLE_CAT"
@ -60,7 +60,7 @@ type Connection
SQL_Error.throw_sql_error "Changing database is not supported."
## Returns the list of schemas for the connection within the current database (or catalog).
schemas : [Text]
schemas : Vector Text
schemas self =
self.jdbc_connection.with_metadata metadata->
read_column metadata.getSchemas "TABLE_SCHEM"
@ -94,7 +94,7 @@ type Connection
- schema: The schema name to search in (defaults to current schema).
- types: The table types to search for. The list of possible values can be obtained using the `table_types` method.
- all_fields: Return all the fields in the metadata table.
tables : Text -> Text -> Text -> Vector -> Boolean -> Materialized_Table
tables : Text -> Text -> Text -> Vector -> Boolean -> Materialized_Table.Table
tables self name_like=Nothing database=self.database schema=self.schema types=Nothing all_fields=False =
types_array = if types.is_nothing then Nothing else types.to_array
name_map = Map.from_vector [["TABLE_CAT", "Database"], ["TABLE_SCHEM", "Schema"], ["TABLE_NAME", "Name"], ["TABLE_TYPE", "Type"], ["REMARKS", "Description"], ["TYPE_CAT", "Type Database"], ["TYPE_SCHEM", "Type Schema"], ["TYPE_NAME", "Type Name"]]
@ -112,7 +112,7 @@ type Connection
- query: name of the table or sql statement to query.
If supplied as `Text`, the name is checked against the `tables` list to determine if it is a table or a query.
- alias: optionally specify a friendly alias for the query.
query : Text | SQL_Query -> Text -> Database_Table
query : Text | SQL_Query -> Text -> Database_Table.Table
query self query alias="" = handle_sql_errors <| case query of
_ : Text ->
self.query alias=alias <|
@ -134,13 +134,13 @@ type Connection
- query: name of the table or sql statement to query.
If supplied as `Text`, the name is checked against the `tables` list to determine if it is a table or a query.
- limit: the maximum number of rows to return.
read : Text | SQL_Query -> Text -> Integer | Nothing -> Table
read : Text | SQL_Query -> Text -> Integer | Nothing -> Materialized_Table.Table
read self query limit=Nothing =
self.query query . read max_rows=limit
## PRIVATE
Internal read function for a statement with optional types.
read_statement : Statement -> (Nothing | Vector SQL_Type) -> Table
read_statement : Statement -> (Nothing | Vector SQL_Type) -> Materialized_Table.Table
read_statement self statement expected_types=Nothing =
self.jdbc_connection.with_prepared_statement statement stmt->
result_set_to_table stmt.executeQuery expected_types
@ -177,7 +177,7 @@ type Connection
usually not be visible to other connections.
- batch_size: Specifies how many rows should be uploaded in a single
batch.
upload_table : Text -> Materialized_Table -> Boolean -> Integer -> Database_Table
upload_table : Text -> Materialized_Table.Table -> Boolean -> Integer -> Database_Table.Table
upload_table self name table temporary=True batch_size=1000 = Panic.recover Illegal_State_Error_Data <|
create_sql = create_table_statement name table temporary
create_table = self.execute_update create_sql

View File

@ -2,12 +2,13 @@ from Standard.Base import all
import Standard.Database.Internal.Helpers
import Standard.Database.Internal.IR
import Standard.Database.Data.Table
from Standard.Database.Data.Table import Table, freshen_columns
from Standard.Table import Filter_Condition
import Standard.Table.Data.Column as Materialized_Column
import Standard.Table.Data.Sort_Column_Selector
import Standard.Table.Data.Sort_Column
from Standard.Table.Data.Value_Type import Value_Type
import Standard.Table.Data.Column.Column as Materialized_Column
import Standard.Table.Data.Sort_Column_Selector.Sort_Column_Selector
import Standard.Table.Data.Sort_Column.Sort_Column
import Standard.Table.Data.Value_Type.Value_Type
from Standard.Database.Data.SQL import SQL_Type, Statement
from Standard.Database.Data.Table import Integrity_Error
@ -69,7 +70,7 @@ type Column
## UNSTABLE
Converts this column into a single-column table.
to_table : Table.Table
to_table : Table
to_table self =
Table.Table_Data self.name self.connection [self.as_internal] self.context
@ -558,7 +559,7 @@ lift_aggregate new_name connection expected_type expr context =
# TODO [RW] This is a simple workaround for #1643 - we always wrap the
# aggregate into a subquery, thus making it safe to use it everywhere. A
# more complex solution may be adopted at some point.
ixes = Table.freshen_columns [new_name] context.meta_index
ixes = freshen_columns [new_name] context.meta_index
col = IR.Internal_Column_Data new_name expected_type expr
setup = context.as_subquery new_name+"_sub" [[col], ixes]
subquery = setup.first

View File

@ -1,6 +1,6 @@
from Standard.Base import all
import Standard.Table.Internal.Vector_Builder
import Standard.Table.Internal.Vector_Builder.Vector_Builder
polyglot java import java.sql.Types
@ -285,7 +285,7 @@ type Builder
It can be used to concatenate parts of SQL code in O(1) time and at the
end build the actual query in linear time.
Builder_Data (fragments:(Vector_Builder.Vector_Builder SQL_Fragment))
Builder_Data (fragments:(Vector_Builder SQL_Fragment))
## UNSTABLE

View File

@ -7,31 +7,26 @@ import Standard.Database.Internal.IR
from Standard.Database.Data.SQL_Query import Raw_SQL
from Standard.Database.Data.SQL import Statement, SQL_Type
from Standard.Table import Auto_Detect, Aggregate_Column, Data_Formatter, Column_Name_Mapping, Sort_Column_Selector, Sort_Column, Match_Columns, Position
from Standard.Table.Data.Column import get_item_string
import Standard.Table.Data.Table.Table as Materialized_Table
from Standard.Table.Data.Table import print_table
from Standard.Table.Data.Filter_Condition import make_filter_column, Filter_Condition
import Standard.Table.Data.Column as Materialized_Column
import Standard.Table.Data.Table as Materialized_Table
from Standard.Table import Auto_Detect, Aggregate_Column, Data_Formatter, Column_Name_Mapping, Sort_Column_Selector, Sort_Column, Match_Columns
from Standard.Table.Errors import No_Such_Column_Error, No_Such_Column_Error_Data
from Standard.Table.Data.Column_Selector import Column_Selector, By_Index, By_Name
from Standard.Table.Errors import No_Index_Set_Error, No_Such_Column_Error, No_Such_Column_Error_Data
from Standard.Table.Data.Column_Selector import Column_Selector
import Standard.Table.Internal.Java_Exports
import Standard.Table.Internal.Table_Helpers
import Standard.Table.Internal.Problem_Builder
import Standard.Table.Internal.Problem_Builder.Problem_Builder
import Standard.Table.Internal.Aggregate_Column_Helper
from Standard.Database.Data.Column import Column, Column_Data
from Standard.Database.Internal.IR import Internal_Column, Internal_Column_Data
from Standard.Database.Errors import Unsupported_Database_Operation_Error_Data
import Standard.Table.Data.Position
polyglot java import java.sql.JDBCType
# TODO Dubious constructor export
from project.Data.Table.Table import all
from project.Data.Table.Table export all
## Represents a column-oriented table data structure backed by a database.
type Table
@ -124,7 +119,7 @@ type Table
> Example
Select columns by name.
table.select_columns (By_Name ["bar", "foo"])
table.select_columns (Column_Selector.By_Name ["bar", "foo"])
> Example
Select columns using names passed as a Vector.
@ -134,21 +129,21 @@ type Table
> Example
Select columns matching a regular expression.
table.select_columns (By_Name ["foo.+", "b.*"] (Regex_Matcher.Regex_Matcher_Data case_sensitivity=Case_Sensitivity.Insensitive))
table.select_columns (Column_Selector.By_Name ["foo.+", "b.*"] (Regex_Matcher.Regex_Matcher_Data case_sensitivity=Case_Sensitivity.Insensitive))
> Example
Select the first two columns and the last column, moving the last one to front.
table.select_columns (By_Index [-1, 0, 1]) reorder=True
table.select_columns (Column_Selector.By_Index [-1, 0, 1]) reorder=True
> Example
Select columns with the same names as the ones provided.
table.select_columns (By_Column [column1, column2])
table.select_columns (Column_Selector.By_Column [column1, column2])
Icon: select_column
select_columns : Vector Text | Column_Selector -> Boolean -> Problem_Behavior -> Table
select_columns self (columns = By_Index [0]) (reorder = False) (on_problems = Report_Warning) =
select_columns self (columns = Column_Selector.By_Index [0]) (reorder = False) (on_problems = Report_Warning) =
new_columns = Table_Helpers.select_columns internal_columns=self.internal_columns selector=columns reorder=reorder on_problems=on_problems
self.updated_columns new_columns
@ -176,7 +171,7 @@ type Table
> Example
Remove columns with given names.
table.remove_columns (By_Name ["bar", "foo"])
table.remove_columns (Column_Selector.By_Name ["bar", "foo"])
> Example
Remove columns using names passed as a Vector.
@ -186,19 +181,19 @@ type Table
> Example
Remove columns matching a regular expression.
table.remove_columns (By_Name ["foo.+", "b.*"] (Regex_Matcher.Regex_Matcher_Data case_sensitivity=Case_Sensitivity.Insensitive))
table.remove_columns (Column_Selector.By_Name ["foo.+", "b.*"] (Regex_Matcher.Regex_Matcher_Data case_sensitivity=Case_Sensitivity.Insensitive))
> Example
Remove the first two columns and the last column.
table.remove_columns (By_Index [-1, 0, 1])
table.remove_columns (Column_Selector.By_Index [-1, 0, 1])
> Example
Remove columns with the same names as the ones provided.
table.remove_columns (By_Column [column1, column2])
table.remove_columns (Column_Selector.By_Column [column1, column2])
remove_columns : Vector Text | Column_Selector -> Problem_Behavior -> Table
remove_columns self (columns = By_Index [0]) (on_problems = Report_Warning) =
remove_columns self (columns = Column_Selector.By_Index [0]) (on_problems = Report_Warning) =
new_columns = Table_Helpers.remove_columns internal_columns=self.internal_columns selector=columns on_problems=on_problems
self.updated_columns new_columns
@ -241,19 +236,19 @@ type Table
> Example
Swap the first two columns.
table.reorder_columns (By_Index [1, 0]) position=Before_Other_Columns
table.reorder_columns (Column_Selector.By_Index [1, 0]) position=Before_Other_Columns
> Example
Move the first column to back.
table.reorder_columns (By_Index [0]) position=After_Other_Columns
table.reorder_columns (Column_Selector.By_Index [0]) position=After_Other_Columns
> Example
Move the columns with names matching the provided columns to the front.
table.reorder_columns (By_Column [column1, column2])
table.reorder_columns (Column_Selector.By_Column [column1, column2])
reorder_columns : Vector Text | Column_Selector -> Position.Position -> Problem_Behavior -> Table
reorder_columns self (columns = By_Index [0]) (position = Position.Before_Other_Columns) (on_problems = Report_Warning) =
reorder_columns self (columns = Column_Selector.By_Index [0]) (position = Position.Before_Other_Columns) (on_problems = Report_Warning) =
new_columns = Table_Helpers.reorder_columns internal_columns=self.internal_columns selector=columns position=position on_problems=on_problems
self.updated_columns new_columns
@ -531,11 +526,11 @@ type Table
itself).
Throws `No_Index_Set_Error` if there is no index set.
index : Column | Vector Column ! Materialized_Table.No_Index_Set_Error
index : Column | Vector Column ! No_Index_Set_Error
index self =
ixes = self.indices
len = ixes.length
if len == 0 then Error.throw Materialized_Table.No_Index_Set_Error else
if len == 0 then Error.throw No_Index_Set_Error else
if len == 1 then ixes.at 0 else ixes
## Sorts the rows of the table according to the specified columns and order.
@ -632,7 +627,7 @@ type Table
- If floating points values are present in the distinct columns, a
`Floating_Point_Grouping` warning.
distinct : Vector Text | Column_Selector -> Case_Sensitivity -> Problem_Behavior -> Table
distinct self (columns = By_Name (self.columns.map .name)) case_sensitivity=Case_Sensitivity.Sensitive on_problems=Report_Warning =
distinct self (columns = Column_Selector.By_Name (self.columns.map .name)) case_sensitivity=Case_Sensitivity.Sensitive on_problems=Report_Warning =
_ = [columns, case_sensitivity, on_problems]
Error.throw (Unsupported_Database_Operation_Error_Data "`Table.distinct` is not yet implemented for the database backend.")
@ -659,8 +654,8 @@ type Table
Icon: join
join : Table | Column -> Nothing | Text | Column | Vector (Text | Column) -> Boolean -> Text -> Text -> Table
join self other on=Nothing drop_unmatched=False left_suffix='_left' right_suffix='_right' = case other of
Column_Data _ _ _ _ _ -> self.join other.to_table on drop_unmatched left_suffix right_suffix
Table_Data _ _ _ _ -> Panic.recover Any <|
_ : Column -> self.join other.to_table on drop_unmatched left_suffix right_suffix
_ : Table -> Panic.recover Any <|
Panic.rethrow (Helpers.ensure_name_is_sane left_suffix && Helpers.ensure_name_is_sane right_suffix)
if left_suffix == right_suffix then
Panic.throw <| Illegal_State_Error_Data "left_suffix must be different from right_suffix"
@ -729,7 +724,7 @@ type Table
new_limit = Nothing
new_ctx = IR.Context_Data new_from [] [] [] new_index new_limit
Table_Data new_table_name self.connection new_columns new_ctx
Table.Table_Data new_table_name self.connection new_columns new_ctx
## ALIAS group, summarize
@ -833,7 +828,7 @@ type Table
Arguments:
- max_rows: specifies a maximum amount of rows to fetch; if not set, all
available rows are fetched.
read : (Integer | Nothing) -> Materialized_Table.Table
read : (Integer | Nothing) -> Materialized_Table
read self max_rows=Nothing =
case self.context.meta_index.length > 1 of
True -> Error.throw <| Illegal_State_Error_Data "Multi-indexes are not implemented in the dataframes, if you want to materialize such a Table, remove the index first using `set_index`."
@ -841,8 +836,7 @@ type Table
preprocessed = self.reset_index.limit max_rows
case preprocessed.internal_columns.is_empty of
True ->
internal_table = Java_Exports.make_table_without_columns self.row_count
Materialized_Table.Table_Data internal_table
Java_Exports.make_table_without_columns self.row_count
False ->
sql = preprocessed.to_sql
expected_types = preprocessed.internal_columns.map .sql_type
@ -919,7 +913,7 @@ type Table
Arguments:
- columns: The columns with which to update this table.
updated_columns : Vector Internal_Column -> Table
updated_columns self internal_columns = Table_Data self.name self.connection internal_columns self.context
updated_columns self internal_columns = Table.Table_Data self.name self.connection internal_columns self.context
## PRIVATE
@ -928,7 +922,7 @@ type Table
Arguments:
- ctx: The new context for this table.
updated_context : Context -> Table
updated_context self ctx = Table_Data self.name self.connection self.internal_columns ctx
updated_context self ctx = Table.Table_Data self.name self.connection self.internal_columns ctx
## PRIVATE
@ -938,7 +932,7 @@ type Table
- ctx: The new context for this table.
- internal_columns: The new columns to include in the table.
updated_context_and_columns : Context -> Vector Internal_Column -> Table
updated_context_and_columns self ctx internal_columns = Table_Data self.name self.connection internal_columns ctx
updated_context_and_columns self ctx internal_columns = Table.Table_Data self.name self.connection internal_columns ctx
## PRIVATE
@ -1067,7 +1061,7 @@ type Integrity_Error
make_table : Connection -> Text -> Vector -> IR.Context -> Table
make_table connection table_name columns ctx =
cols = columns.map (p -> Internal_Column_Data p.first p.second (IR.Column table_name p.first))
Table_Data table_name connection cols ctx
Table.Table_Data table_name connection cols ctx
## PRIVATE
@ -1085,7 +1079,7 @@ make_table connection table_name columns ctx =
line will be included that will say how many hidden rows there are.
- format_term: A boolean flag, specifying whether to use ANSI escape codes
for rich formatting in the terminal.
display_dataframe : Materialized_Table.Table -> Integer -> Integer -> Boolean -> Text
display_dataframe : Materialized_Table -> Integer -> Integer -> Boolean -> Text
display_dataframe df indices_count all_rows_count format_terminal =
cols = Vector.from_polyglot_array df.java_table.getColumns
col_names = cols.map .getName
@ -1093,8 +1087,8 @@ display_dataframe df indices_count all_rows_count format_terminal =
display_rows = df.row_count
rows = Vector.new display_rows row_num->
col_vals.map col->
if col.isNa row_num then "Nothing" else Materialized_Column.get_item_string col row_num
table = Materialized_Table.print_table col_names rows indices_count format_terminal
if col.isNa row_num then "Nothing" else get_item_string col row_num
table = print_table col_names rows indices_count format_terminal
if display_rows == all_rows_count then table else
missing_rows_count = all_rows_count - display_rows
missing = '\n\u2026 and ' + missing_rows_count.to_text + ' hidden rows.'

View File

@ -1,6 +1,6 @@
from Standard.Base import all hiding First, Last
from Standard.Table.Data.Aggregate_Column import all
from Standard.Table.Data.Aggregate_Column.Aggregate_Column import all
import Standard.Database.Internal.IR
from Standard.Database.Data.SQL import SQL_Type
from Standard.Database.Errors import Unsupported_Database_Operation_Error_Data

View File

@ -7,7 +7,7 @@ import Standard.Database.Data.SQL
from Standard.Database.Data.SQL import SQL_Type, SQL_Type_Data, Statement, Statement_Data
from Standard.Database.Errors import SQL_Error, SQL_Error_Data, SQL_Timeout_Error, SQL_Timeout_Error_Data
import Standard.Database.Internal.Base_Generator
import Standard.Table.Data.Storage
import Standard.Table.Data.Storage.Storage
import Standard.Database.Data.Table as Database_Table
import Standard.Table.Data.Table as Materialized_Table
@ -101,7 +101,7 @@ type JDBC_Connection
Given an insert query template and the associated Database_Table, and a
Materialized_Table of data, load to the database.
load_table : Text -> Database_Table -> Materialized_Table -> Integer -> Nothing
load_table : Text -> Database_Table.Table -> Materialized_Table.Table -> Integer -> Nothing
load_table self insert_template db_table table batch_size =
db_types = db_table.internal_columns.map .sql_type
self.with_connection java_connection->
@ -182,7 +182,7 @@ set_statement_values stmt holes =
## PRIVATE
Given a Materialized_Table, create a SQL statement to build the table.
create_table_statement : Text -> Materialized_Table -> Boolean -> Statement
create_table_statement : Text -> Materialized_Table.Table -> Boolean -> Statement
create_table_statement name table temporary =
column_types = table.columns.map col-> default_storage_type col.storage_type
column_names = table.columns.map .name

View File

@ -57,7 +57,7 @@ type Postgres_Connection
self.make_new database Nothing
## Returns the list of schemas for the connection within the current database (or catalog).
schemas : [Text]
schemas : Vector Text
schemas self = self.connection.schemas
## Returns the name of the current schema.
@ -74,7 +74,7 @@ type Postgres_Connection
self.make_new Nothing schema
## Gets a list of the table types.
table_types : [Text]
table_types : Vector Text
table_types self = self.connection.table_types
## Returns a materialised Table of all the matching views and tables.
@ -85,7 +85,7 @@ type Postgres_Connection
- schema: The schema name to search in (defaults to current schema).
- types: The table types to search for. The list of values can be obtained using the `table_types` method.
- all_fields: Return all the fields in the metadata table.
tables : Text -> Text -> Text -> Vector -> Boolean -> Materialized_Table
tables : Text -> Text -> Text -> Vector -> Boolean -> Materialized_Table.Table
tables self name_like=Nothing database=self.database schema=self.schema types=Nothing all_fields=False =
self.connection.tables name_like database schema types all_fields
@ -95,7 +95,7 @@ type Postgres_Connection
- query: name of the table or sql statement to query.
If supplied as `Text`, the name is checked against the `tables` list to determine if it is a table or a query.
- alias: optionally specify a friendly alias for the query.
query : Text | SQL_Query -> Text -> Database_Table
query : Text | SQL_Query -> Text -> Database_Table.Table
query self query alias="" = self.connection.query query alias
## Execute the query and load the results into memory as a Table.
@ -104,12 +104,12 @@ type Postgres_Connection
- query: name of the table or sql statement to query.
If supplied as `Text`, the name is checked against the `tables` list to determine if it is a table or a query.
- limit: the maximum number of rows to return.
read : Text | SQL_Query -> Integer | Nothing -> Table
read : Text | SQL_Query -> Integer | Nothing -> Materialized_Table.Table
read self query limit=Nothing = self.connection.read query limit
## PRIVATE
Internal read function for a statement with optional types.
read_statement : Statement -> (Nothing | Vector SQL_Type) -> Table
read_statement : Statement -> (Nothing | Vector SQL_Type) -> Materialized_Table.Table
read_statement self statement expected_types=Nothing =
self.connection.read_statement statement expected_types
@ -143,7 +143,7 @@ type Postgres_Connection
usually not be visible to other connections.
- batch_size: Specifies how many rows should be uploaded in a single
batch.
upload_table : Text -> Materialized_Table -> Boolean -> Integer -> Database_Table
upload_table : Text -> Materialized_Table.Table -> Boolean -> Integer -> Database_Table.Table
upload_table self name table temporary=True batch_size=1000 = Panic.recover Illegal_State_Error <|
self.connection.upload_table name table temporary batch_size

View File

@ -1,7 +1,7 @@
from Standard.Base import all hiding First, Last
import Standard.Base.Error.Common as Errors
from Standard.Table.Data.Aggregate_Column import all
from Standard.Table.Data.Aggregate_Column.Aggregate_Column import all
from Standard.Database.Data.SQL import SQL_Type, Statement, code
import Standard.Database.Data.SQL
import Standard.Database.Data.Dialect

View File

@ -1,6 +1,7 @@
from Standard.Base import all
import Standard.Table.Data.Table as Materialized_Table
import Standard.Table.Data.Column as Materialized_Column
import Standard.Table.Internal.Java_Exports
from Standard.Database.Data.SQL import SQL_Type, SQL_Type_Data
@ -23,7 +24,7 @@ read_column result_set column_name =
## PRIVATE
Converts a ResultSet into a Materialized_Table.
result_set_to_table : ResultSet -> (Vector | Nothing) -> Materialized_Table
result_set_to_table : ResultSet -> (Vector | Nothing) -> Materialized_Table.Table
result_set_to_table result_set expected_types=Nothing =
metadata = result_set.getMetaData
ncols = metadata.getColumnCount
@ -42,7 +43,7 @@ result_set_to_table result_set expected_types=Nothing =
go result_set.next
columns = column_builders.zip column_names builder-> name->
builder.make_column name
Materialized_Table.from_columns columns
Materialized_Table.Table.new columns
## PRIVATE
@ -54,14 +55,10 @@ result_set_to_table result_set expected_types=Nothing =
create_builder : SQL_Type -> Builder
create_builder sql_type =
initial_size = 10
if sql_type.is_definitely_boolean then Builder_Boolean (Java_Exports.make_bool_builder) else
if sql_type.is_definitely_integer then Builder_Long (Java_Exports.make_long_builder initial_size) else
if sql_type.is_definitely_double then Builder_Double (Java_Exports.make_double_builder initial_size) else
Builder_Inferred (Java_Exports.make_inferred_builder initial_size)
# TODO Dubious constructor export
from project.Internal.Result_Set.Builder import all
from project.Internal.Result_Set.Builder export all
if sql_type.is_definitely_boolean then Builder.Builder_Boolean (Java_Exports.make_bool_builder) else
if sql_type.is_definitely_integer then Builder.Builder_Long (Java_Exports.make_long_builder initial_size) else
if sql_type.is_definitely_double then Builder.Builder_Double (Java_Exports.make_double_builder initial_size) else
Builder.Builder_Inferred (Java_Exports.make_inferred_builder initial_size)
type Builder
@ -108,20 +105,20 @@ type Builder
ResultSet convention).
fetch_and_append : ResultSet -> Integer -> Nothing
fetch_and_append self rs i = case self of
Builder_Inferred _ ->
Builder.Builder_Inferred _ ->
obj = rs.getObject i
self.java_builder.append obj
Builder_Boolean _ ->
Builder.Builder_Boolean _ ->
bool = rs.getBoolean i
case rs.wasNull of
True -> self.java_builder.appendNulls 1
False -> self.java_builder.appendBoolean bool
Builder_Long _ ->
Builder.Builder_Long _ ->
long = rs.getLong i
case rs.wasNull of
True -> self.java_builder.appendNulls 1
False -> self.java_builder.appendLong long
Builder_Double _ ->
Builder.Builder_Double _ ->
double = rs.getDouble i
case rs.wasNull of
True -> self.java_builder.appendNulls 1
@ -133,7 +130,7 @@ type Builder
Argument:
- name: The name of the column.
make_column : Text -> Java_Exports.Column
make_column : Text -> Materialized_Column.Column
make_column self name =
storage = self.java_builder.seal
Java_Exports.make_column name storage

View File

@ -33,7 +33,7 @@ type SQLite_Connection
close self = self.connection.close
## Returns the list of databases (or catalogs) for the connection.
databases : [Text]
databases : Vector Text
databases self = [Nothing]
## Returns the name of the current database (or catalog).
@ -50,7 +50,7 @@ type SQLite_Connection
SQL_Error.throw_sql_error "Changing database is not supported."
## Returns the list of schemas for the connection within the current database (or catalog).
schemas : [Text]
schemas : Vector Text
schemas self = [Nothing]
## Returns the name of the current schema.
@ -67,7 +67,7 @@ type SQLite_Connection
SQL_Error.throw_sql_error "Changing schema is not supported."
## Gets a list of the table types
table_types : [Text]
table_types : Vector Text
table_types self = self.connection.table_types
## Returns a materialised Table of all the matching views and tables.
@ -78,7 +78,7 @@ type SQLite_Connection
- schema: The schema name to search in (defaults to current schema).
- types: The table types to search for. The list of values can be obtained using the `table_types` method.
- all_fields: Return all the fields in the metadata table.
tables : Text -> Text -> Text -> Vector -> Boolean -> Materialized_Table
tables : Text -> Text -> Text -> Vector -> Boolean -> Materialized_Table.Table
tables self name_like=Nothing database=self.database schema=self.schema types=Nothing all_fields=False =
self.connection.tables name_like database schema types all_fields
@ -88,7 +88,7 @@ type SQLite_Connection
- query: name of the table or sql statement to query.
If supplied as `Text`, the name is checked against the `tables` list to determine if it is a table or a query.
- alias: optionally specify a friendly alias for the query.
query : Text | SQL_Query -> Text -> Database_Table
query : Text | SQL_Query -> Text -> Database_Table.Table
query self query alias="" = self.connection.query query alias
## Execute the query and load the results into memory as a Table.
@ -97,12 +97,12 @@ type SQLite_Connection
- query: name of the table or sql statement to query.
If supplied as `Text`, the name is checked against the `tables` list to determine if it is a table or a query.
- limit: the maximum number of rows to return.
read : Text | SQL_Query -> Integer | Nothing -> Table
read : Text | SQL_Query -> Integer | Nothing -> Materialized_Table.Table
read self query limit=Nothing = self.connection.read query limit
## PRIVATE
Internal read function for a statement with optional types.
read_statement : Statement -> (Nothing | Vector SQL_Type) -> Table
read_statement : Statement -> (Nothing | Vector SQL_Type) -> Materialized_Table.Table
read_statement self statement expected_types=Nothing =
self.connection.read_statement statement expected_types
@ -136,7 +136,7 @@ type SQLite_Connection
usually not be visible to other connections.
- batch_size: Specifies how many rows should be uploaded in a single
batch.
upload_table : Text -> Materialized_Table -> Boolean -> Integer -> Database_Table
upload_table : Text -> Materialized_Table.Table -> Boolean -> Integer -> Database_Table.Table
upload_table self name table temporary=True batch_size=1000 = Panic.recover Illegal_State_Error <|
self.connection.upload_table name table temporary batch_size

View File

@ -1,6 +1,6 @@
from Standard.Base import all hiding First, Last
from Standard.Table.Data.Aggregate_Column import all
from Standard.Table.Data.Aggregate_Column.Aggregate_Column import all
import Standard.Database.Data.SQL
from Standard.Database.Data.SQL import SQL_Type, Statement, code
import Standard.Database.Data.Dialect

View File

@ -1,5 +1,3 @@
import Standard.Database.Data.Table
import Standard.Database.Data.Column
import Standard.Database.Data.SQL_Query
import Standard.Database.Connection.Database
@ -12,9 +10,6 @@ import Standard.Database.Connection.Postgres_Options
import Standard.Database.Connection.SQLite_Options
import Standard.Database.Connection.Redshift_Options
export Standard.Database.Data.Table
export Standard.Database.Data.Column
export Standard.Database.Connection.SSL_Mode
from Standard.Database.Connection.Credentials export Credentials, Username_And_Password

View File

@ -6,7 +6,7 @@ import Standard.Base.System.Platform
import Standard.Base.Network.URI
import Standard.Base.Data.Text.Regex.Engine.Default as Default_Engine
import Standard.Table
from Standard.Table import Table, Column
import Standard.Image
import Standard.Image.Codecs
@ -240,41 +240,41 @@ geo_json = Json.parse <| '''
}
## A small table column containing integers.
integer_column : Table.Column.Column
integer_column = Table.Column.from_vector "Integer" [1, 4, 8, 2, 5]
integer_column : Column.Column
integer_column = Column.from_vector "Integer" [1, 4, 8, 2, 5]
## A small table column containing decimal numbers.
decimal_column : Table.Column.Column
decimal_column = Table.Column.from_vector "Decimal" [2.30, -2.1, Nothing, -10.1, 1.0]
decimal_column : Column.Column
decimal_column = Column.from_vector "Decimal" [2.30, -2.1, Nothing, -10.1, 1.0]
## A small table column containing booleans.
bool_column_1 : Table.Column.Column
bool_column_1 = Table.Column.from_vector "Bools" [True, True, False, True, False]
bool_column_1 : Column.Column
bool_column_1 = Column.from_vector "Bools" [True, True, False, True, False]
## A small table column containing booleans.
bool_column_2 : Table.Column.Column
bool_column_2 = Table.Column.from_vector "Bools" [False, True, Nothing, True, True]
bool_column_2 : Column.Column
bool_column_2 = Column.from_vector "Bools" [False, True, Nothing, True, True]
## A small table column containing text.
text_column_1 : Table.Column.Column
text_column_1 = Table.Column.from_vector "Text" ["Hello,", "my", "name", "is", "Enso"]
text_column_1 : Column.Column
text_column_1 = Column.from_vector "Text" ["Hello,", "my", "name", "is", "Enso"]
## A small table column containing text.
text_column_2 : Table.Column.Column
text_column_2 = Table.Column.from_vector "Text" ["He,", "he", "he", "i", "so"]
text_column_2 : Column.Column
text_column_2 = Column.from_vector "Text" ["He,", "he", "he", "i", "so"]
## A simple table that contains basic shop inventory data for the food shop.
inventory_table : Table.Table
inventory_table : Table
inventory_table = csv.read . set_index "item_id"
## A simple table that contains basic item popularity data for the food shop.
popularity_table : Table.Table
popularity_table : Table
popularity_table =
table = (enso_project.data / "food_shop_popularity.csv") . read
table.set_index "item_id"
## A simple tablethat contains basic transaction data for the food shop.
transactions_table : Table.Table
transactions_table : Table
transactions_table =
(enso_project.data / "food_shop_transactions.csv") . read

View File

@ -1,5 +1,5 @@
from Standard.Base import all
import Standard.Table
from Standard.Table import Table
## UNSTABLE
@ -21,6 +21,6 @@ import Standard.Table
import Standard.Geo
example_point = Geo.point 51.509865 -0.118092
point : Decimal -> Decimal -> Decimal -> Table.Table
point : Decimal -> Decimal -> Decimal -> Table
point latitude longitude elevation=0 =
Table.new [["latitude", [latitude]], ["longitude", [longitude]], ["elevation", [elevation]]]

View File

@ -1,5 +1,5 @@
from Standard.Base import all
import Standard.Table
from Standard.Table import Table
polyglot java import com.google.api.client.googleapis.auth.oauth2.GoogleCredential
polyglot java import com.google.api.services.sheets.v4.SheetsScopes

View File

@ -8,7 +8,7 @@
> Example
Read the active sheet of an XLSX from disk and convert it into a table.
import Standard.Table
from Standard.Table import all
import Standard.Examples
example_xlsx_to_table = Examples.xlsx.read
@ -27,12 +27,11 @@
to make sure the indices are correct.
import Standard.Examples
import Standard.Table
example_join =
table_1 = Examples.inventory_table
table_2 = Examples.popularity_table
Table.join [table_1, table_2]
table_1.join table_2
> Example
Select only the items where more than half the stock has been sold.
@ -60,7 +59,6 @@
well as the number of each item sold across those transactions.
import Standard.Examples
import Standard.Table
example_group =
transactions = Examples.transactions_table
@ -68,5 +66,5 @@
aggregated = transactions.group by="item_id"
num_transactions = aggregated.at "transaction_id" . reduce .length . rename "transaction_count"
num_sold = aggregated.at "quantity" . reduce .sum . rename "num_sold"
Table.join [item_names, num_transactions, num_sold]
item_names.join [num_transactions, num_sold]

View File

@ -10,7 +10,6 @@
well as the number of each item sold across those transactions.
import Standard.Examples
import Standard.Table
example_group =
transactions = Examples.transactions_table
@ -18,7 +17,7 @@
aggregated = transactions.group by="item_id"
num_transactions = aggregated.at "transaction_id" . reduce .length . rename "transaction_count"
num_sold = aggregated.at "quantity" . reduce .sum . rename "num_sold"
Table.join [item_names, num_transactions, num_sold]
item_names.join [num_transactions, num_sold]
> Example
Compute the maximum value of a column, the minimum value, the sum of its

View File

@ -9,7 +9,7 @@
> Example
Read the active sheet of an XLSX from disk and convert it into a table.
import Standard.Table
from Standard.Table import Table
import Standard.Examples
example_xlsx_to_table = Examples.xlsx.read
@ -17,7 +17,7 @@
> Example
Read a CSV from disk and convert it into a table.
import Standard.Table
from Standard.Table import Table
import Standard.Examples
example_csv_to_table = Examples.csv.read
@ -25,6 +25,7 @@
> Example
Write a table to an XLSX file.
from Standard.Table import Table
import Standard.Examples
example_to_xlsx =
@ -34,6 +35,7 @@
> Example
Write a table to a CSV file.
from Standard.Table import Table
import Standard.Examples
example_to_csv =

View File

@ -9,16 +9,15 @@
to make sure the indices are correct.
import Standard.Examples
import Standard.Table
example_join =
table_1 = Examples.inventory_table
table_2 = Examples.popularity_table
Table.join [table_1, table_2]
table_1.join table_2
> Example
Join the popularity table and the inventory table to see the relative
popularities of the items in the shop inventory.
popularity of the items in the shop inventory.
import Standard.Examples

View File

@ -46,7 +46,7 @@ number_input = Error.unimplemented "This function should not be called."
Creating a node containing a table with two columns, one titled "name", and
the other titled "stars".
import Standard.Table
from Standard.Table import Table
example_table_input =
column_1 = ["name", "Enso"]

View File

@ -12,9 +12,9 @@ component-groups:
extends:
- Standard.Base.Input:
exports:
- Standard.Table.Data.Table.new
- Standard.Table.Data.Table.from_rows
- Standard.Table.Data.Column.from_vector
- Standard.Table.Data.Table.Table.new
- Standard.Table.Data.Table.Table.from_rows
- Standard.Table.Data.Column.Column.from_vector
- Standard.Base.System.File.read
- Standard.Base.Select:
exports:

View File

@ -1,12 +1,8 @@
from Standard.Base import all
from Standard.Table.Data.Column import Column
from Standard.Table.Data.Column_Selector import Column_Selector
from Standard.Table.Data.Sort_Column_Selector import Sort_Column_Selector
# TODO Dubious constructor export
from project.Data.Aggregate_Column.Aggregate_Column import all
from project.Data.Aggregate_Column.Aggregate_Column export all
import Standard.Table.Data.Column.Column
import Standard.Table.Data.Column_Selector.Column_Selector
import Standard.Table.Data.Sort_Column_Selector.Sort_Column_Selector
## Defines an Aggregate Column
type Aggregate_Column

View File

@ -2,17 +2,19 @@ from Standard.Base import all
import Standard.Base.Data.Ordering.Comparator
import Standard.Base.Data.Index_Sub_Range
import Standard.Table.Data.Table
import Standard.Table.Data.Storage
from Standard.Table.Data.Value_Type import Value_Type
import Standard.Table.Data.Table.Table
from Standard.Table.Data.Table import print_table
import Standard.Table.Data.Storage.Storage
import Standard.Table.Data.Value_Type.Value_Type
# TODO Dubious constructor export
from Standard.Table.Data.Column.Column import all
from Standard.Table.Data.Column.Column export all
from project.Errors import No_Index_Set_Error
polyglot java import org.enso.table.data.table.Column as Java_Column
polyglot java import org.enso.table.operations.OrderBuilder
from project.Data.Column.Column import Column_Data
type Column
## Creates a new column given a name and a vector of elements.
Arguments:
@ -22,15 +24,13 @@ polyglot java import org.enso.table.operations.OrderBuilder
> Example
Create a new column called "My Column" from a vector of numbers.
import Standard.Table
from Standard.Table import Column
example_from_vector =
Table.Column.from_vector "My Column" [1, 2, 3, 4, 5]
Column.from_vector "My Column" [1, 2, 3, 4, 5]
from_vector : Text -> Vector -> Column
from_vector name items = Column_Data (Java_Column.fromItems name items.to_array)
type Column
## PRIVATE
A representation of a column in a Table.
@ -63,7 +63,7 @@ type Column
row = if storage.isNa num then "Nothing" else
get_item_string storage num
[index.ilocString num, row]
table = Table.print_table [index.getName, col_name] items 1 format_terminal
table = print_table [index.getName, col_name] items 1 format_terminal
if num_rows - display_rows <= 0 then table else
missing = '\n\u2026 and ' + (num_rows - display_rows).to_text + ' hidden rows.'
table + missing
@ -687,9 +687,9 @@ type Column
import Standard.Examples
example_index = Examples.decimal_column.index
index : Column ! Table.No_Index_Set_Error
index : Column ! No_Index_Set_Error
index self = case self.java_column.getIndex.toColumn of
Nothing -> Error.throw Table.No_Index_Set_Error
Nothing -> Error.throw No_Index_Set_Error
i -> Column_Data i
## Sets the index of this column, using the provided column.
@ -748,7 +748,7 @@ type Column
import Standard.Examples
example_storage_type = Examples.integer_column.storage_type
storage_type : Storage.Type
storage_type : Storage
storage_type self =
tp = self.java_column.getStorage.getType
storage_types.at tp . catch Index_Out_Of_Bounds_Error _->
@ -816,7 +816,7 @@ type Column
import Standard.Examples
example_join = Examples.integer_column.join Examples.bool_column_1
join : Table.Table | Column -> Text | Nothing -> Boolean -> Text -> Text -> Table
join : Table | Column -> Text | Nothing -> Boolean -> Text -> Text -> Table
join self other on=Nothing drop_unmatched=False left_suffix='_left' right_suffix='_right' =
self.to_table.join other on drop_unmatched left_suffix right_suffix
@ -828,7 +828,7 @@ type Column
import Standard.Examples
example_to_table = Examples.integer_column.to_table
to_table : Table.Table
to_table : Table
to_table self = Table.Table_Data self.java_column.toTable
## UNSTABLE
@ -1091,168 +1091,6 @@ type Column
duplicate_count : Column
duplicate_count self = Column_Data self.java_column.duplicateCount
# TODO Dubious constructor export
from project.Data.Column.Aggregate_Column import all
from project.Data.Column.Aggregate_Column export all
## Wraps a column grouped by its index. Allows performing aggregation operations
on the contained values.
type Aggregate_Column
## PRIVATE
Aggregate_Column_Data java_column
## Converts this aggregate column into a column, aggregating groups
with the provided `function`.
Arguments:
- function: the function used for value aggregation. Values belonging to
each group are passed to this function in a vector.
- skip_missing: controls whether missing values should be included in
groups.
- name_suffix: a suffix that will be appended to the original column name
to generate the resulting column name.
> Example
Convert an aggregate column of transaction ids into a column by
counting the number of transactions. per item.
import Standard.Examples
example_reduce =
Examples.aggregate_column.reduce .length . rename "transaction_count"
reduce : (Vector.Vector -> Any) -> Boolean -> Text -> Column
reduce self function skip_missing=True name_suffix="_result" =
f arr = function (Vector.from_polyglot_array arr)
r = self.java_column.aggregate Nothing name_suffix f skip_missing
Column_Data r
## Sums the values in each group.
Arguments:
- name_suffix: a suffix that will be appended to the original column name
to generate the resulting column name.
> Example
Convert an aggregate column of transaction ids into a column by summing
the transaction IDs together.
import Standard.Examples
example_sum = Examples.aggregate_column.sum . rename "id_sum"
sum : Text -> Column
sum self name_suffix='_sum' =
r = self.java_column.aggregate 'sum' name_suffix (x-> Vector.from_polyglot_array x . reduce (+)) True
Column r
## Computes the maximum element of each group.
Arguments:
- name_suffix: a suffix that will be appended to the original column name
to generate the resulting column name.
> Example
Get the latest (maximum ID) transaction id for each item.
import Standard.Examples
example_max = Examples.aggregate_column.max . rename "latest_transaction"
max : Text -> Column
max self name_suffix='_max' =
r = self.java_column.aggregate 'max' name_suffix (x-> Vector.from_polyglot_array x . reduce Math.max) True
Column_Data r
## Computes the minimum element of each group.
Arguments:
- name_suffix: a suffix that will be appended to the original column name
to generate the resulting column name.
> Example
Get the earliest (mimumum ID) transaction id for each item.
import Standard.Examples
example_min = Examples.aggregate_column.min . rename "first_transaction"
min : Text -> Column
min self name_suffix='_min' =
r = self.java_column.aggregate 'min' name_suffix (x-> Vector.from_polyglot_array x . reduce Math.min) True
Column_Data r
## Computes the number of non-missing elements in each group.
Arguments:
- name_suffix: a suffix that will be appended to the original column name
to generate the resulting column name.
> Example
Count the number of non-missing elements in each group in the column,
which gives the number of transactions in which a given item was sold.
import Standard.Examples
example_count = Examples.aggregate_column.count . rename "transaction_count"
count : Text -> Column
count self name_suffix='_count' =
r = self.java_column.aggregate 'count' name_suffix (x-> x.length) True
Column_Data r
## Computes the mean of non-missing elements in each group.
Arguments:
- name_suffix: a suffix that will be appended to the original column name
to generate the resulting column name.
> Example
Get the mean transaction id for each item.
import Standard.Examples
example_mean = Examples.aggregate_column.mean
mean : Text -> Column
mean self name_suffix='_mean' =
vec_mean v = if v.length == 0 then Nothing else
(Vector.from_polyglot_array v).reduce (+) / v.length
r = self.java_column.aggregate 'mean' name_suffix vec_mean True
Column_Data r
## Gathers all elements in a group into a vector and returns a column of
such vectors.
Arguments:
- name_suffix: a suffix that will be appended to the original column name
to generate the resulting column name.
> Example
Gather the values of the aggregate column together.
import Standard.Examples
example_values = Examples.aggregate_column.values
values : Text -> Column
values self name_suffix='_values' =
r = self.java_column.aggregate Nothing name_suffix Vector.from_polyglot_array False
Column_Data r
## Prints an ASCII-art column with this data to the standard output.
Arguments:
- show_rows: the number of initial rows that should be displayed.
> Example
Pretty-print an aggregate column and display it using the standard
output.
import Standard.Examples
example_print = Examples.aggregate_column.print
print : Nothing
print self = self.values.print
# TODO Dubious constructor export
from project.Data.Column.Empty_Error import all
from project.Data.Column.Empty_Error export all
## UNSTABLE
An error for when the column contains no elements.
@ -1274,17 +1112,17 @@ type Empty_Error
- operand: The operand to apply to the function after `column`.
run_vectorized_binary_op : Column -> Text -> (Any -> Any) -> Any -> Column
run_vectorized_binary_op column name fallback_fn operand = case operand of
Column_Data col2 ->
Column.Column_Data col2 ->
s1 = column.java_column.getStorage
ix = column.java_column.getIndex
s2 = col2.getStorage
rs = s1.zip name fallback_fn s2 True
Column_Data (Java_Column.new "Result" ix rs)
Column.Column_Data (Java_Column.new "Result" ix rs)
_ ->
s1 = column.java_column.getStorage
ix = column.java_column.getIndex
rs = s1.bimap name fallback_fn operand
Column_Data (Java_Column.new "Result" ix rs)
Column.Column_Data (Java_Column.new "Result" ix rs)
## PRIVATE
@ -1299,19 +1137,19 @@ run_vectorized_unary_op column name fallback_fn =
s = column.java_column.getStorage
ix = column.java_column.getIndex
rs = s.map name fallback_fn
Column_Data (Java_Column.new "Result" ix rs)
Column.Column_Data (Java_Column.new "Result" ix rs)
## PRIVATE
Enumerates storage types in a way that is consistent with
`org.enso.table.data.Storage.Type`, i.e.
`storage_type.at org.enso.table.data.Storage.Type.LONG` will yield the
`org.enso.table.data.Storage.Storage`, i.e.
`storage_type.at org.enso.table.data.Storage.Storage.LONG` will yield the
corresponding `Storage.Integer`.
storage_types : Vector Storage.Type
storage_types : Vector Storage
storage_types = [Storage.Any, Storage.Integer, Storage.Decimal, Storage.Text, Storage.Boolean, Storage.Date, Storage.Time_Of_Day, Storage.Date_Time]
## PRIVATE
Keep this in sync with `org.enso.table.data.Storage.Type.STRING`
Keep this in sync with `org.enso.table.data.Storage.Storage.STRING`
storage_type_string : Integer
storage_type_string = 3

View File

@ -1,9 +1,5 @@
from Standard.Base import all
# TODO Dubious constructor export
from project.Data.Column_Name_Mapping.Column_Name_Mapping import all
from project.Data.Column_Name_Mapping.Column_Name_Mapping export all
## Specifies a selection of columns from the table and the new name for them to
become.
type Column_Name_Mapping

View File

@ -1,9 +1,5 @@
from Standard.Base import all
# TODO Dubious constructor export
from project.Data.Column_Selector.Column_Selector import all
from project.Data.Column_Selector.Column_Selector export all
## Specifies a selection of columns from the table on which an operation is
going to be performed.
type Column_Selector

View File

@ -1,8 +1,9 @@
from Standard.Base import all
import Standard.Base.Error.Common as Errors
from Standard.Table.Data.Column_Type_Selection import Auto
import Standard.Table.Data.Storage
import Standard.Table.Data.Column_Type_Selection.Auto
import Standard.Table.Data.Storage.Storage
import Standard.Table.Internal.Parse_Values_Helper
polyglot java import org.enso.table.parsing.IntegerParser
@ -24,10 +25,6 @@ polyglot java import org.enso.table.formatting.DateTimeFormatter
polyglot java import org.enso.table.formatting.TimeFormatter
polyglot java import org.enso.table.formatting.TextFormatter
# TODO Dubious constructor export
from project.Data.Data_Formatter.Data_Formatter import all
from project.Data.Data_Formatter.Data_Formatter export all
type Data_Formatter
## Specifies options for reading text data in a table to more specific types and
serializing them back.
@ -57,7 +54,7 @@ type Data_Formatter
- datetime_locale: The locale to use when parsing dates and times.
- true_values: Values representing True.
- false_values: Values representing False.
Data_Formatter_Data trim_values:Boolean=True allow_leading_zeros:Boolean=False decimal_point:Text='.' thousand_separator:Text='' allow_exponential_notation:Boolean=False datetime_formats:[Text]=["yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm"] date_formats:[Text]=["yyyy-MM-dd"] time_formats:[Text]=["HH:mm:ss", "HH:mm"] datetime_locale:Locale=Locale.default true_values:[Text]=["True","true","TRUE"] false_values:[Text]=["False","false","FALSE"]
Value trim_values:Boolean=True allow_leading_zeros:Boolean=False decimal_point:Text='.' thousand_separator:Text='' allow_exponential_notation:Boolean=False datetime_formats:[Text]=["yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm"] date_formats:[Text]=["yyyy-MM-dd"] time_formats:[Text]=["HH:mm:ss", "HH:mm"] datetime_locale:Locale=Locale.default true_values:[Text]=["True","true","TRUE"] false_values:[Text]=["False","false","FALSE"]
## Parse a Text into a value.
@ -125,14 +122,14 @@ type Data_Formatter
Arguments:
- locale: The locale to use when parsing dates and times.
with_locale : Locale -> Data_Formatter_Data
with_locale : Locale -> Data_Formatter
with_locale self datetime_locale = self.clone datetime_locale=datetime_locale
## PRIVATE
Clone the instance with some properties overridden.
clone : Boolean -> Boolean -> Text -> Text -> Boolean -> [Text] -> [Text] -> [Text] -> Locale -> [Text] -> [Text] -> Data_Formatter
clone self (trim_values=self.trim_values) (allow_leading_zeros=self.allow_leading_zeros) (decimal_point=self.decimal_point) (thousand_separator=self.thousand_separator) (allow_exponential_notation=self.allow_exponential_notation) (datetime_formats=self.datetime_formats) (date_formats=self.date_formats) (time_formats=self.time_formats) (datetime_locale=self.datetime_locale) (true_values=self.true_values) (false_values=self.false_values) =
Data_Formatter_Data trim_values=trim_values allow_leading_zeros=allow_leading_zeros decimal_point=decimal_point thousand_separator=thousand_separator allow_exponential_notation=allow_exponential_notation datetime_formats=datetime_formats date_formats=date_formats time_formats=time_formats datetime_locale=datetime_locale true_values=true_values false_values=false_values
Data_Formatter.Value trim_values=trim_values allow_leading_zeros=allow_leading_zeros decimal_point=decimal_point thousand_separator=thousand_separator allow_exponential_notation=allow_exponential_notation datetime_formats=datetime_formats date_formats=date_formats time_formats=time_formats datetime_locale=datetime_locale true_values=true_values false_values=false_values
## PRIVATE
get_thousand_separator self =

View File

@ -1,9 +1,5 @@
from Standard.Base import all
# TODO Dubious constructor export
from project.Data.Match_Columns.Match_Columns import all
from project.Data.Match_Columns.Match_Columns export all
## Specifies how to join columns in the table to existing data.
type Match_Columns
## Columns are matched by Name against an existing file.

View File

@ -1,9 +1,5 @@
from Standard.Base import all
# TODO Dubious constructor export
from project.Data.Position.Position import all
from project.Data.Position.Position export all
type Position
## UNSTABLE
Selected columns will be moved to the front of the output table.

View File

@ -1,9 +1,5 @@
from Standard.Base import all
# TODO Dubious constructor export
from project.Data.Sort_Column.Sort_Column import all
from project.Data.Sort_Column.Sort_Column export all
type Sort_Column
Name name:Text direction:Sort_Direction=Sort_Direction.Ascending
Index index:Integer direction:Sort_Direction=Sort_Direction.Ascending

View File

@ -1,10 +1,7 @@
from Standard.Base import all
import Standard.Table.Data.Sort_Column
# TODO Dubious constructor export
from project.Data.Sort_Column_Selector.Sort_Column_Selector import all
from project.Data.Sort_Column_Selector.Sort_Column_Selector export all
import Standard.Table.Data.Column.Column
import Standard.Table.Data.Sort_Column.Sort_Column
type Sort_Column_Selector
By_Name (columns : Vector (Sort_Column.Name | Text)) (matcher:Matcher=Text_Matcher.Case_Sensitive)

View File

@ -1,9 +1,5 @@
# TODO Dubious constructor export
from project.Data.Storage.Type import all
from project.Data.Storage.Type export all
## Represents different types of underlying storage for Columns.
type Type
type Storage
## A column storing text data.
Text

View File

@ -6,35 +6,30 @@ import Standard.Base.Data.Ordering.Comparator
import Standard.Base.Data.Text.Case
import Standard.Base.System.Platform
import Standard.Table.Data.Column
import Standard.Table.Data.Column.Column
from Standard.Table.Data.Filter_Condition import make_filter_column, Filter_Condition
import Standard.Table.Internal.Table_Helpers
import Standard.Table.Internal.Aggregate_Column_Helper
import Standard.Table.Internal.Parse_Values_Helper
import Standard.Table.Internal.Problem_Builder
import Standard.Table.Internal.Problem_Builder.Problem_Builder
from Standard.Table.IO.Auto_Detect import Auto_Detect
import Standard.Table.IO.Auto_Detect.Auto_Detect
from Standard.Table.Delimited.Delimited_Format import Delimited_Format, Delimited
import Standard.Table.Delimited.Delimited_Reader
import Standard.Table.Delimited.Delimited_Writer
from Standard.Table.Data.Column_Selector import Column_Selector, By_Index, By_Name
import Standard.Table.Data.Column_Selector.Column_Selector
from Standard.Table.Data.Column_Type_Selection import Column_Type_Selection, Auto
from Standard.Table.Data.Data_Formatter import Data_Formatter, Data_Formatter_Data
import Standard.Table.Data.Data_Formatter.Data_Formatter
from Standard.Table.Errors import Missing_Input_Columns, Column_Indexes_Out_Of_Range, Duplicate_Type_Selector, No_Index_Set_Error, No_Such_Column_Error, No_Such_Column_Error_Data, No_Input_Columns_Selected, No_Output_Columns
import Standard.Table.Data.Match_Columns
import Standard.Table.Data.Match_Columns.Match_Columns
import Standard.Table.Data.Column_Name_Mapping
import Standard.Table.Data.Position
import Standard.Table.Data.Sort_Column_Selector
import Standard.Table.Data.Sort_Column
from Standard.Table.Data.Column_Name_Mapping import Column_Name_Mapping
import Standard.Table.Data.Position.Position
import Standard.Table.Data.Sort_Column_Selector.Sort_Column_Selector
import Standard.Table.Data.Sort_Column.Sort_Column
# TODO Dubious constructor export
from Standard.Table.Data.Table.Table import all
from Standard.Table.Data.Table.Table export all
import Standard.Table.Data.Aggregate_Column
import Standard.Table.Data.Aggregate_Column.Aggregate_Column
import Standard.Visualization
polyglot java import org.enso.table.data.table.Table as Java_Table
@ -42,6 +37,8 @@ polyglot java import org.enso.table.data.table.Column as Java_Column
polyglot java import org.enso.table.operations.OrderBuilder
polyglot java import org.enso.table.data.mask.OrderMask
## Represents a column-oriented table data structure.
type Table
## Creates a new table from a vector of `[name, items]` pairs.
Arguments:
@ -50,7 +47,7 @@ polyglot java import org.enso.table.data.mask.OrderMask
> Example
Create a new table with the given columns.
import Standard.Table
from Standard.Table import Table
example_new =
first_column = ["count", [1, 2, 3]]
@ -62,7 +59,7 @@ new columns =
case c of
_ : Vector.Vector -> Column.from_vector (c.at 0) (c.at 1) . java_column
Column.Column_Data java_col -> java_col
from_columns cols
Table.Table_Data (Java_Table.new cols.to_array)
## Creates a new table from a vector of column names and a vector of vectors
specifying row contents.
@ -76,7 +73,7 @@ new columns =
Create a table with 3 columns, named `foo`, `bar`, and `baz`, containing
`[1, 2, 3]`, `[True, False, True]`, and `['a', 'b', 'c']`, respectively.
import Standard.Table
from Standard.Table import Table
example_from_rows =
header = [ 'foo' , 'bar' , 'baz' ]
@ -87,60 +84,7 @@ new columns =
from_rows : Vector.Vector -> Vector.Vector -> Table
from_rows header rows =
columns = header.map_with_index i-> name-> [name, rows.map (_.at i)]
new columns
## ALIAS Join Tables
Joins a vector of tables (or columns) into a single table, using each table's
index as the join key.
Arguments:
- tables: A vector of tables to join into a single table.
Particularly useful for joining multiple columns derived from one original
table into a new table.
> Example
Join multiple tables together. It joins tables on their indices, so we need
to make sure the indices are correct.
import Standard.Examples
import Standard.Table
example_join =
table_1 = Examples.inventory_table
table_2 = Examples.popularity_table
Table.join [table_1, table_2]
join : Vector -> Table
join tables =
tables.reduce .join
## UNSTABLE
Concatenates multiple tables, resulting in a table with the number of rows
being the sum of numbers of rows of `tables`. Any column that is present in
some tables, but missing in others, will be `Nothing`-padded in the positions
corresponding to the missing values.
Arguments:
- tables: the tables to concatenate.
> Example
Concatenate multiple tables together.
import Standard.Examples
import Standard.Table
example_concat =
table_1 = Examples.inventory_table
table_2 = Examples.popularity_table
Table.concat [table_1, table_2]
concat : Vector -> Table
concat tables =
Table_Data (Java_Table.concat (tables.map .java_table).to_array)
## Represents a column-oriented table data structure.
type Table
Table.new columns
## PRIVATE
@ -301,7 +245,7 @@ type Table
> Example
Select columns by name.
table.select_columns (By_Name ["bar", "foo"])
table.select_columns (Column_Selector.By_Name ["bar", "foo"])
> Example
Select columns using names passed as a Vector.
@ -311,23 +255,23 @@ type Table
> Example
Select columns matching a regular expression.
table.select_columns (By_Name ["foo.+", "b.*"] (Regex_Matcher.Regex_Matcher_Data case_sensitivity=Case_Sensitivity.Insensitive))
table.select_columns (Column_Selector.By_Name ["foo.+", "b.*"] (Regex_Matcher.Regex_Matcher_Data case_sensitivity=Case_Sensitivity.Insensitive))
> Example
Select the first two columns and the last column, moving the last one to front.
table.select_columns (By_Index [-1, 0, 1]) reorder=True
table.select_columns (Column_Selector.By_Index [-1, 0, 1]) reorder=True
> Example
Select columns with the same names as the ones provided.
table.select_columns (By_Column [column1, column2])
table.select_columns (Column_Selector.By_Column [column1, column2])
Icon: select_column
select_columns : Vector Text | Column_Selector -> Boolean -> Problem_Behavior -> Table
select_columns self (columns = By_Index [0]) (reorder = False) (on_problems = Report_Warning) =
select_columns self (columns = Column_Selector.By_Index [0]) (reorder = False) (on_problems = Report_Warning) =
new_columns = Table_Helpers.select_columns internal_columns=self.columns selector=columns reorder=reorder on_problems=on_problems
new new_columns
Table.new new_columns
## Returns a new table with the chosen set of columns, as specified by the
`columns`, removed from the input table. Any unmatched input columns will
@ -353,7 +297,7 @@ type Table
> Example
Remove columns with given names.
table.remove_columns (By_Name ["bar", "foo"])
table.remove_columns (Column_Selector.By_Name ["bar", "foo"])
> Example
Remove columns using names passed as a Vector.
@ -363,21 +307,21 @@ type Table
> Example
Remove columns matching a regular expression.
table.remove_columns (By_Name ["foo.+", "b.*"] (Regex_Matcher.Regex_Matcher_Data case_sensitivity=Case_Sensitivity.Insensitive))
table.remove_columns (Column_Selector.By_Name ["foo.+", "b.*"] (Regex_Matcher.Regex_Matcher_Data case_sensitivity=Case_Sensitivity.Insensitive))
> Example
Remove the first two columns and the last column.
table.remove_columns (By_Index [-1, 0, 1])
table.remove_columns (Column_Selector.By_Index [-1, 0, 1])
> Example
Remove columns with the same names as the ones provided.
table.remove_columns (By_Column [column1, column2])
table.remove_columns (Column_Selector.By_Column [column1, column2])
remove_columns : Vector Text | Column_Selector -> Problem_Behavior -> Table
remove_columns self (columns = By_Index [0]) (on_problems = Report_Warning) =
remove_columns self (columns = Column_Selector.By_Index [0]) (on_problems = Report_Warning) =
new_columns = Table_Helpers.remove_columns internal_columns=self.columns selector=columns on_problems=on_problems
new new_columns
Table.new new_columns
## Returns a new table with the specified selection of columns moved to
either the start or the end in the specified order.
@ -403,7 +347,7 @@ type Table
> Example
Move a column with a specified name to back.
table.reorder_columns (By_Name ["foo"]) position=After_Other_Columns
table.reorder_columns (Column_Selector.By_Name ["foo"]) position=After_Other_Columns
> Example
Move columns using names passed as a Vector.
@ -413,26 +357,26 @@ type Table
> Example
Move columns matching a regular expression to front, keeping columns matching "foo.+" before columns matching "b.*".
table.reorder_columns (By_Name ["foo.+", "b.*"] (Regex_Matcher.Regex_Matcher_Data case_sensitivity=Case_Sensitivity.Insensitive))
table.reorder_columns (Column_Selector.By_Name ["foo.+", "b.*"] (Regex_Matcher.Regex_Matcher_Data case_sensitivity=Case_Sensitivity.Insensitive))
> Example
Swap the first two columns.
table.reorder_columns (By_Index [1, 0]) position=Before_Other_Columns
table.reorder_columns (Column_Selector.By_Index [1, 0]) position=Before_Other_Columns
> Example
Move the first column to back.
table.reorder_columns (By_Index [0]) position=After_Other_Columns
table.reorder_columns (Column_Selector.By_Index [0]) position=After_Other_Columns
> Example
Move the columns with names matching the provided columns to the front.
table.reorder_columns (By_Column [column1, column2])
table.reorder_columns (Column_Selector.By_Column [column1, column2])
reorder_columns : Vector Text | Column_Selector -> Position.Position -> Problem_Behavior -> Table
reorder_columns self (columns = By_Index [0]) (position = Position.Before_Other_Columns) (on_problems = Report_Warning) =
reorder_columns self (columns = Column_Selector.By_Index [0]) (position = Position.Before_Other_Columns) (on_problems = Report_Warning) =
new_columns = Table_Helpers.reorder_columns internal_columns=self.columns selector=columns position=position on_problems=on_problems
new new_columns
Table.new new_columns
## Returns a new table with the columns sorted by name according to the
specified sort method. By default, sorting will be according to
@ -460,7 +404,7 @@ type Table
sort_columns : Sort_Direction -> Text_Ordering -> Table
sort_columns self direction=Sort_Direction.Ascending text_ordering=Text_Ordering.Default =
new_columns = Table_Helpers.sort_columns internal_columns=self.columns direction text_ordering
new new_columns
Table.new new_columns
## Returns a new table with the columns renamed based on either a mapping
from the old name to the new or a positional list of new names.
@ -503,7 +447,7 @@ type Table
new_names = Table_Helpers.rename_columns internal_columns=self.columns mapping=column_map on_problems=on_problems
if new_names.is_error then new_names else
new_columns = self.columns.map_with_index i->c->(c.rename (new_names.at i))
new new_columns
Table.new new_columns
## Returns a new table with the columns renamed based on entries in the
first row.
@ -569,7 +513,7 @@ type Table
new_columns = validated.valid_columns.map c->(Aggregate_Column_Helper.java_aggregator c.first c.second)
java_table = index.makeTable new_columns.to_array
new_table = Table_Data java_table
new_table = Table.Table_Data java_table
on_problems.attach_problems_after new_table <|
problems = java_table.getProblems
@ -657,7 +601,7 @@ type Table
the number of items sold in descending order to break ties.
import Standard.Examples
import Standard.Table
from Standard.Table import Table
example_sort =
table = Examples.inventory_table
@ -673,7 +617,7 @@ type Table
comparator = Comparator.for_text_ordering text_ordering
java_table = Illegal_Argument_Error.handle_java_exception <| Vector.handle_incomparable_value <|
self.java_table.orderBy selected_columns.to_array ordering.to_array comparator
Table_Data java_table
Table.Table_Data java_table
## Returns the distinct set of rows within the specified columns from the
input table.
@ -703,7 +647,7 @@ type Table
- If floating points values are present in the distinct columns, a
`Floating_Point_Grouping` warning.
distinct : Vector Text | Column_Selector -> Case_Sensitivity -> Problem_Behavior -> Table
distinct self (columns = By_Name (self.columns.map .name)) case_sensitivity=Case_Sensitivity.Sensitive on_problems=Report_Warning =
distinct self (columns = Column_Selector.By_Name (self.columns.map .name)) case_sensitivity=Case_Sensitivity.Sensitive on_problems=Report_Warning =
warning_mapper error = case error of
No_Output_Columns -> Maybe.Some No_Input_Columns_Selected
_ -> Nothing
@ -713,7 +657,7 @@ type Table
text_folding_strategy = Case.folding_strategy case_sensitivity
java_table = Illegal_Argument_Error.handle_java_exception <|
self.java_table.distinct java_columns.to_array text_folding_strategy
on_problems.attach_problems_after (Table_Data java_table) <|
on_problems.attach_problems_after (Table.Table_Data java_table) <|
problems = java_table.getProblems
Aggregate_Column_Helper.parse_aggregated_problems problems
@ -729,7 +673,7 @@ type Table
a leading 0). However, settings in the `Data_Formatter` can
control this.
parse_values : Data_Formatter -> (Nothing | [Column_Type_Selection]) -> Problem_Behavior -> Table
parse_values self value_formatter=Data_Formatter_Data column_types=Nothing on_problems=Report_Warning =
parse_values self value_formatter=Data_Formatter.Value column_types=Nothing on_problems=Report_Warning =
columns = self.columns
problem_builder = Vector.new_builder
@ -783,7 +727,7 @@ type Table
## TODO [RW] this case of is a workaround for wrong dataflow handling on arrays, it can be removed once the PR fixing it is merged, the relevant PR is:
https://github.com/enso-org/enso/pull/3400
result = new new_columns
result = Table.new new_columns
on_problems.attach_problems_after result problem_builder.to_vector
## ALIAS Filter Rows
@ -831,8 +775,8 @@ type Table
people.filter "age" (age -> (age%10 == 0))
filter : (Column | Text | Integer) -> (Filter_Condition|(Any->Boolean)) -> Problem_Behavior -> Table
filter self column filter=(Filter_Condition.Is_True) on_problems=Report_Warning = case column of
_ : Column.Column ->
mask filter_column = Table_Data (self.java_table.mask filter_column.java_column)
_ : Column ->
mask filter_column = Table.Table_Data (self.java_table.mask filter_column.java_column)
case Meta.type_of filter of
Filter_Condition ->
on_problems.handle_errors fallback=self.with_no_rows <|
@ -891,7 +835,7 @@ type Table
_ : Vector.Vector ->
self.set name (Column.from_vector name column)
Column.Column_Data _ ->
Table_Data (self.java_table.addOrReplaceColumn (column.rename name . java_column))
Table.Table_Data (self.java_table.addOrReplaceColumn (column.rename name . java_column))
## Returns the vector of columns contained in this table.
@ -918,8 +862,8 @@ type Table
example_set_index = Examples.inventory_table.set_index "item_name"
set_index : Text | Column -> Table
set_index self index = case index of
_ : Text -> Table_Data (self.java_table.indexFromColumn index)
Column.Column_Data c -> Table_Data (self.java_table.indexFromColumn c)
_ : Text -> Table.Table_Data (self.java_table.indexFromColumn index)
Column.Column_Data c -> Table.Table_Data (self.java_table.indexFromColumn c)
## Returns the index of this table, as a column that is indexed by itself.
@ -939,11 +883,12 @@ type Table
## ALIAS Join Table
Efficiently joins two tables based on either the index or the specified
key column.
Efficiently joins two or more tables based on either the index or the
specified key column.
Arguments:
- other: The table being the right operand of this join operation.
- other: The table (or vector of tables) being the right operand of this
join operation.
- on: The column of `self` that should be used as the join key. If this
argument is not provided, the index of `self` will be used.
- drop_unmatched: Whether the rows of `self` without corresponding
@ -960,7 +905,7 @@ type Table
> Example
Join the popularity table and the inventory table to see the relative
popularities of the items in the shop inventory.
popularity of the items in the shop inventory.
import Standard.Examples
@ -968,12 +913,13 @@ type Table
Examples.inventory_table.join Examples.popularity_table
Icon: join
join : Table | Column -> Text | Nothing -> Boolean -> Text -> Text -> Table
join : Vector Table | Table | Column.Column -> Text | Nothing -> Boolean -> Text -> Text -> Table
join self other on=Nothing drop_unmatched=False left_suffix='_left' right_suffix='_right' =
case other of
_ : Vector.Vector -> other.fold self current->item->(current.join item on drop_unmatched left_suffix right_suffix)
Column.Column_Data _ -> self.join other.to_table on drop_unmatched left_suffix right_suffix
Table_Data t ->
Table_Data (self.java_table.join t drop_unmatched on left_suffix right_suffix)
Table.Table_Data t ->
Table.Table_Data (self.java_table.join t drop_unmatched on left_suffix right_suffix)
## DEPRECATED Will be replaced with `filter_incomplete_rows`.
drop_missing_rows : Table
@ -991,7 +937,7 @@ type Table
drop_missing_columns self =
non_missing = self.columns . filter (col -> col.count_missing == 0)
index = self.java_table.getIndex
Table_Data (Java_Table.new (non_missing.map .java_column . to_array) index)
Table.Table_Data (Java_Table.new (non_missing.map .java_column . to_array) index)
## Returns the number of rows in this table.
@ -1018,14 +964,17 @@ type Table
info : Table
info self =
cols = self.columns
new [["Column", cols.map .name], ["Items Count", cols.map .count], ["Storage Type", cols.map .storage_type]] . set_index "Column"
Table.new [["Column", cols.map .name], ["Items Count", cols.map .count], ["Storage Type", cols.map .storage_type]] . set_index "Column"
## UNSTABLE
Concatenates `other` to `self`.
Concatenates `other` to `self`, resulting in a table with the number of rows
being the sum of numbers of rows of `tables`. Any column that is present in
some tables, but missing in others, will be `Nothing`-padded in the positions
corresponding to the missing values.
Arguments:
- other: The table to concatenate to `self`.
- other: The table or vector of tables to concatenate to `self`.
Any column that is present in one table, but missing in another, will be
`Nothing`-padded in the positions corresponding to the missing column.
@ -1037,8 +986,12 @@ type Table
example_concat =
Examples.inventory_table.concat Examples.popularity_table
concat : Table -> Table
concat self other = Table_Data (Java_Table.concat [self.java_table, other.java_table].to_array)
concat : Table | Vector Table -> Table
concat self other = case other of
_ : Vector.Vector ->
java_tables = Vector.new (other.length + 1) i->(if i==0 then self else other.at i).java_table
Table.Table_Data (Java_Table.concat java_tables.to_array)
Table.Table_Data other_java_table -> Table.Table_Data (Java_Table.concat [self.java_table, other_java_table].to_array)
## PRIVATE
Returns a table with a continuous sub-range of rows taken.
@ -1047,7 +1000,7 @@ type Table
length = self.row_count
offset = Math.max (Math.min start length) 0
limit = Math.max (Math.min (end - offset) (length - offset)) 0
Table_Data (self.java_table.slice offset limit)
Table.Table_Data (self.java_table.slice offset limit)
## UNSTABLE
@ -1063,7 +1016,7 @@ type Table
reverse : Table
reverse self =
mask = OrderBuilder.buildReversedMask self.row_count
Table_Data <| self.java_table.applyMask mask
Table.Table_Data <| self.java_table.applyMask mask
## ALIAS Write JSON
UNSTABLE
@ -1134,7 +1087,6 @@ type Table
Write a table to a CSV file, without writing the header.
import Standard.Examples
import Standard.Table
from Standard.Table import Delimited
example_to_csv = Examples.inventory_table.write (Enso_Project.data / "example_csv_output.csv") (Delimited delimiter="," headers=False)
@ -1143,7 +1095,6 @@ type Table
Write a table to an XLSX file.
import Standard.Examples
import Standard.Table
from Standard.Table import Excel
example_to_xlsx = Examples.inventory_table.write (enso_project.data / "example_xlsx_output.xlsx") Excel
@ -1165,9 +1116,6 @@ type Empty_Error
to_display_text : Text
to_display_text self = "The table is empty."
## PRIVATE
from_columns cols = Table_Data (Java_Table.new cols.to_array)
## PRIVATE
Ensures that the `txt` has at least `len` characters by appending spaces at
@ -1222,16 +1170,8 @@ print_table header rows indices_count format_term =
" " + y
([" " + header_line, divider] + row_lines).join '\n'
Table.from (that : Text) (format:Delimited_Format = Delimited '\t') (on_problems:Problem_Behavior=Report_Warning) =
if format.is_a Delimited then Delimited_Reader.read_text that format on_problems else
Errors.unimplemented "Table.from for fixed-width files is not yet implemented."
Text.from (that : Table) (format:Delimited_Format = Delimited '\t') =
if format.is_a Delimited then Delimited_Writer.write_text that format else
Errors.unimplemented "Text.from for fixed-width files is not yet implemented."
## PRIVATE
A helper to create a new table consisting of slices of the original table.
slice_ranges table ranges =
normalized = Index_Sub_Range.normalize_ranges ranges
Table_Data (table.java_table.slice normalized.to_array)
Table.Table_Data (table.java_table.slice normalized.to_array)

View File

@ -0,0 +1,17 @@
from Standard.Base import all
from Standard.Base.Error.Problem_Behavior import Report_Warning
import project.Data.Table.Table
import project.Errors
from project.Delimited.Delimited_Format import Delimited_Format, Delimited
import project.Delimited.Delimited_Reader
import project.Delimited.Delimited_Writer
Table.from (that : Text) (format:Delimited_Format = Delimited '\t') (on_problems:Problem_Behavior=Report_Warning) =
if format.is_a Delimited then Delimited_Reader.read_text that format on_problems else
Errors.unimplemented "Table.from for fixed-width files is not yet implemented."
Text.from (that : Table) (format:Delimited_Format = Delimited '\t') =
if format.is_a Delimited then Delimited_Writer.write_text that format else
Errors.unimplemented "Text.from for fixed-width files is not yet implemented."

View File

@ -1,17 +1,14 @@
from Standard.Base import all
import Standard.Table.Data.Table
import Standard.Table.Data.Match_Columns
from Standard.Table.Data.Table import Table
from Standard.Table.Data.Data_Formatter import Data_Formatter
from Standard.Table.Data.Match_Columns import Match_Columns
import Standard.Table.Delimited.Delimited_Reader
import Standard.Table.Delimited.Delimited_Writer
import Standard.Table.Delimited.Quote_Style.Quote_Style
from Standard.Table.Data.Data_Formatter import Data_Formatter, Data_Formatter_Data
import Standard.Table.Delimited.Quote_Style
# TODO Dubious constructor export
from project.Delimited.Delimited_Format.Delimited_Format import all
from project.Delimited.Delimited_Format.Delimited_Format export all
from project.Delimited.Delimited_Format.Delimited_Format import Delimited
from project.Delimited.Delimited_Format.Delimited_Format export Delimited
## Read delimited files such as CSVs into a Table.
type Delimited_Format
@ -51,7 +48,7 @@ type Delimited_Format
character if it anywhere else than at the beginning of the line. This
option is only applicable for read mode and does not affect writing. It
defaults to `Nothing` which means that comments are disabled.
Delimited (delimiter:Text) (encoding:Encoding=Encoding.utf_8) (skip_rows:Integer=0) (row_limit:Integer|Nothing=Nothing) (quote_style:Quote_Style=Quote_Style.With_Quotes) (headers:Boolean|Infer=Infer) (value_formatter:Data_Formatter|Nothing=Data_Formatter_Data) (keep_invalid_rows:Boolean=True) (line_endings:Line_Ending_Style=Infer) (comment_character:Text|Nothing=Nothing)
Delimited (delimiter:Text) (encoding:Encoding=Encoding.utf_8) (skip_rows:Integer=0) (row_limit:Integer|Nothing=Nothing) (quote_style:Quote_Style=Quote_Style.With_Quotes) (headers:Boolean|Infer=Infer) (value_formatter:Data_Formatter|Nothing=Data_Formatter.Value) (keep_invalid_rows:Boolean=True) (line_endings:Line_Ending_Style=Infer) (comment_character:Text|Nothing=Nothing)
## If the File_Format supports reading from the file, return a configured instance.
for_file : File -> Delimited_Format | Nothing
@ -101,7 +98,7 @@ type Delimited_Format
A custom `Data_Formatter` can be provided to customize parser options.
with_parsing : Data_Formatter -> Delimited_Format
with_parsing self (value_formatter=Data_Formatter_Data) =
with_parsing self (value_formatter=Data_Formatter.Value) =
self.clone value_formatter=value_formatter
## Create a clone of this without value parsing.

View File

@ -2,11 +2,12 @@ from Standard.Base import all
import Standard.Base.Error.Common as Errors
from Standard.Base.Error.Problem_Behavior import Ignore, Report_Error
import Standard.Table.Data.Table
import Standard.Table.Data.Table.Table
import Standard.Table.Data.Data_Formatter.Data_Formatter
import Standard.Table.Delimited.Delimited_Format.Delimited_Format
import Standard.Table.Delimited.Quote_Style.Quote_Style
from Standard.Table.Errors import Duplicate_Output_Column_Names_Data, Invalid_Output_Column_Names_Data, Invalid_Row_Data, Mismatched_Quote, Parser_Error, Additional_Invalid_Rows_Data
from Standard.Table.Data.Data_Formatter import Data_Formatter_Data
from Standard.Table.Delimited.Delimited_Format import Delimited_Format
import Standard.Table.Delimited.Quote_Style
polyglot java import org.enso.base.encoding.NewlineDetector
polyglot java import org.enso.table.read.DelimitedReader
@ -117,7 +118,7 @@ prepare_reader java_reader format max_columns on_problems newline_override=Nothi
wrapped = format.value_formatter.wrap_base_parser base_parser
TypeInferringParser.new format.value_formatter.get_specific_type_parsers.to_array wrapped
cell_type_guesser = if format.headers != Infer then Nothing else
formatter = format.value_formatter.if_nothing Data_Formatter_Data
formatter = format.value_formatter.if_nothing Data_Formatter.Value
TypeInferringParser.new formatter.get_specific_type_parsers.to_array IdentityParser.new
newline = newline_override.if_nothing <| case format.line_endings of
Infer -> Nothing
@ -136,22 +137,14 @@ translate_reader_problem problem =
if found.is_error then problem else
found.second problem
# TODO Dubious constructor export
from project.Delimited.Delimited_Reader.Detected_Headers import all
from project.Delimited.Delimited_Reader.Detected_Headers export all
## PRIVATE
An internal type representing columns deduced from an existing file.
type Detected_Headers
## Represents the headers found in the file.
Existing_Headers (column_names : Vector Text)
Existing (column_names : Vector Text)
## Indicates that the file exists but no headers have been found, so only positional column matching is possible.
No_Headers (column_count : Integer)
# TODO Dubious constructor export
from project.Delimited.Delimited_Reader.Detected_File_Metadata import all
from project.Delimited.Delimited_Reader.Detected_File_Metadata export all
None (column_count : Integer)
type Detected_File_Metadata
## PRIVATE
@ -164,12 +157,12 @@ type Detected_File_Metadata
- ends_with_newline: specifies if the last line ends with a line
separator that is consistent with the detected one.
- has_any_content: specifies if the file contains any content.
Detected_File_Metadata_Data (headers : Detected_Headers) (line_separator : Text|Nothing) (ends_with_newline : Boolean) (has_any_content : Boolean)
Value (headers : Detected_Headers) (line_separator : Text|Nothing) (ends_with_newline : Boolean) (has_any_content : Boolean)
## PRIVATE
Reads the beginning of the file to detect the existing headers and column
count.
detect_metadata : File -> Delimited_Format -> Detected_Headers
detect_metadata : File -> Delimited_Format -> Detected_File_Metadata
detect_metadata file format =
on_problems = Ignore
result = handle_io_exception file <| Illegal_Argument_Error.handle_java_exception <| handle_parsing_failure <| handle_parsing_exception <|
@ -190,8 +183,8 @@ detect_metadata file format =
Nothing ->
column_count = reader.getColumnCount
if column_count == 0 then Nothing else
No_Headers column_count
_ -> Existing_Headers (Vector.from_polyglot_array defined_columns)
Detected_Headers.None column_count
_ -> Detected_Headers.Existing (Vector.from_polyglot_array defined_columns)
line_separator_from_parser = reader.getEffectiveLineSeparator
has_seen_newline = newline_detecting_reader.newlineEncountered
## If the parser has seen a newline, we can trust that it
@ -203,8 +196,8 @@ detect_metadata file format =
True -> line_separator_from_parser
False -> trailing_line_separator
has_any_content = reader.getVisitedCharactersCount > 0
Detected_File_Metadata_Data headers effective_line_separator has_trailing_line_separator has_any_content
result.catch File.File_Not_Found (_->(Detected_File_Metadata_Data Nothing Nothing False False))
Detected_File_Metadata.Value headers effective_line_separator has_trailing_line_separator has_any_content
result.catch File.File_Not_Found (_->(Detected_File_Metadata.Value Nothing Nothing False False))
## PRIVATE
Checks if the file has a newline at the end.

View File

@ -2,14 +2,14 @@ from Standard.Base import all
import Standard.Base.System
import Standard.Base.Error.Common as Errors
import Standard.Table.Data.Table
from Standard.Table.Data.Table import Table
from Standard.Table.Errors import Duplicate_Output_Column_Names, Invalid_Output_Column_Names, Invalid_Row, Mismatched_Quote, Parser_Error, Additional_Invalid_Rows, Column_Count_Mismatch, Column_Name_Mismatch
from Standard.Table.Data.Data_Formatter import Data_Formatter
import Standard.Table.Data.Storage
from Standard.Table.Data.Storage import Storage
from Standard.Table.Delimited.Delimited_Format import Delimited_Format
import Standard.Table.Delimited.Quote_Style
from Standard.Table.Delimited.Delimited_Reader import Existing_Headers, No_Headers, detect_metadata
import Standard.Table.Data.Match_Columns
from Standard.Table.Delimited.Quote_Style import Quote_Style
from Standard.Table.Delimited.Delimited_Reader import Detected_Headers, detect_metadata
from Standard.Table.Data.Match_Columns import Match_Columns
polyglot java import org.enso.table.write.DelimitedWriter
polyglot java import org.enso.table.write.WriteQuoteBehavior
@ -63,13 +63,13 @@ append_to_file table format file match_columns on_problems =
reordered_java_table = case preexisting_headers of
Nothing -> table.java_table
Existing_Headers column_names -> case match_columns of
Detected_Headers.Existing column_names -> case match_columns of
Match_Columns.By_Name ->
ColumnMapper.mapColumnsByName table.java_table column_names.to_array
Match_Columns.By_Position ->
column_count = column_names.length
ColumnMapper.mapColumnsByPosition table.java_table column_count
No_Headers column_count -> case match_columns of
Detected_Headers.None column_count -> case match_columns of
Match_Columns.By_Name ->
Error.throw (Illegal_Argument_Error_Data "Cannot append by name when headers are not present in the existing data.")
Match_Columns.By_Position ->

View File

@ -1,9 +1,5 @@
from Standard.Base import all
# TODO Dubious constructor export
from project.Delimited.Quote_Style.Quote_Style import all
from project.Delimited.Quote_Style.Quote_Style export all
type Quote_Style
## Does not handle quotes at all.

View File

@ -1,11 +1,14 @@
from Standard.Base import all
import Standard.Table.Data.Table
import Standard.Table.Data.Table.Table
from Standard.Table.Excel.Section import Excel_Section, Worksheet, Sheet_Names, Range_Names
import Standard.Table.Excel.Excel_Reader
import Standard.Table.Excel.Excel_Writer
from project.Excel.Excel_Format.Excel_Format import Excel
from project.Excel.Excel_Format.Excel_Format export Excel
## PRIVATE
Resolve the xls_format setting to a boolean.
should_treat_as_xls_format : (Boolean|Infer) -> File -> Boolean | Illegal_Argument
@ -18,9 +21,6 @@ should_treat_as_xls_format xls_format file =
".xlt" -> True
_ -> Error.throw (Illegal_Argument_Error_Data ("Unknown file extension for Excel file (" + file.extension + ")"))
# TODO Dubious constructor export
from project.Excel.Excel_Format.Excel_Format import all
from project.Excel.Excel_Format.Excel_Format export all
## Read the file to a `Table` from an Excel file
type Excel_Format

View File

@ -1,9 +1,9 @@
from Standard.Base import all
import Standard.Base.System.File.Option
import Standard.Table.Data.Table
import Standard.Table.Data.Table.Table
import Standard.Table.Excel.Range.Excel_Range
from Standard.Table.Excel.Range import Excel_Range_Data
from Standard.Table.Excel.Section import Excel_Section, Sheet_Names, Range_Names, Worksheet, Cell_Range
from Standard.Table.Errors import Invalid_Location_Data, Duplicate_Output_Column_Names_Data, Invalid_Output_Column_Names_Data
@ -71,7 +71,7 @@ read_file file section headers on_problems xls_format=False =
_ : Text -> ExcelReader.readSheetByName stream sheet (make_java_headers headers) skip_rows row_limit xls_format
Cell_Range address skip_rows row_limit ->
prepare_reader_table on_problems <| case address of
Excel_Range_Data _ -> ExcelReader.readRange stream address.java_range (make_java_headers headers) skip_rows row_limit xls_format
_ : Excel_Range -> ExcelReader.readRange stream address.java_range (make_java_headers headers) skip_rows row_limit xls_format
_ : Text -> ExcelReader.readRangeByName stream address (make_java_headers headers) skip_rows row_limit xls_format
handle_reader file reader

View File

@ -4,10 +4,10 @@ import Standard.Table.Data.Table
from Standard.Table.Excel.Excel_Reader import handle_reader, make_java_headers
from Standard.Table.Excel.Section import Worksheet, Cell_Range
from Standard.Table.Excel.Range import Excel_Range_Data
import Standard.Table.Excel.Range.Excel_Range
from Standard.Table.Errors import Invalid_Location_Data, Range_Exceeded_Data, Existing_Data_Data, Column_Count_Mismatch, Column_Name_Mismatch
import Standard.Table.Data.Match_Columns
import Standard.Table.Data.Match_Columns.Match_Columns
polyglot java import org.enso.table.read.ExcelReader
polyglot java import org.enso.table.write.ExcelWriter
@ -44,7 +44,7 @@ write_file file table on_existing_file section headers match_columns _ xls_forma
Worksheet sheet skip_rows row_limit ->
ExcelWriter.writeTableToSheet workbook sheet existing_data_mode skip_rows table.java_table row_limit java_headers
Cell_Range address skip_rows row_limit -> case address of
Excel_Range_Data java_range -> ExcelWriter.writeTableToRange workbook java_range existing_data_mode skip_rows table.java_table row_limit java_headers
Excel_Range.Value java_range -> ExcelWriter.writeTableToRange workbook java_range existing_data_mode skip_rows table.java_table row_limit java_headers
_ : Text -> ExcelWriter.writeTableToRange workbook address existing_data_mode skip_rows table.java_table row_limit java_headers
if result.is_error then result else

View File

@ -14,13 +14,9 @@ excel_2007_column_limit = 16384
## PRIVATE
excel_2007_row_limit = 1048576
# TODO Dubious constructor export
from project.Excel.Range.Excel_Range import all
from project.Excel.Range.Excel_Range export all
type Excel_Range
## Specifies a range within an Excel Workbook.
Excel_Range_Data java_range:Java_Range
Value java_range:Java_Range
## Gets the name of the sheet.
sheet_name : Text
@ -89,7 +85,7 @@ type Excel_Range
from_address : Text -> Excel_Range
from_address address =
Illegal_Argument_Error.handle_java_exception <|
Excel_Range_Data (Java_Range.new address)
Excel_Range.Value (Java_Range.new address)
## Create a Range for a single cell.
for_cell : Text -> (Text|Integer) -> Integer -> Excel_Range
@ -100,7 +96,7 @@ type Excel_Range
row_valid = validate (Excel_Range.is_valid_row row) ("Invalid row for Excel: " + row.to_text + ".")
col_valid <| row_valid <|
Excel_Range_Data (Java_Range.new sheet col_index row)
Excel_Range.Value (Java_Range.new sheet col_index row)
## Create an Excel_Range for a range of cells.
for_range : Text -> (Text|Integer) -> Integer -> (Text|Integer) -> Integer -> Excel_Range
@ -114,7 +110,7 @@ type Excel_Range
bottom_valid = validate (Excel_Range.is_valid_row bottom) ("Invalid bottom row for Excel: " + bottom.to_text + ".")
left_valid <| right_valid <| top_valid <| bottom_valid <|
Excel_Range_Data (Java_Range.new sheet left_index top right_index bottom)
Excel_Range.Value (Java_Range.new sheet left_index top right_index bottom)
## Create an Excel_Range for a set of columns.
for_columns : Text -> (Text|Integer) -> (Text|Integer) -> Excel_Range
@ -126,7 +122,7 @@ type Excel_Range
right_valid = validate (Excel_Range.is_valid_column right_index) ("Invalid right column for Excel: " + right.to_text + ".")
left_valid <| right_valid <|
Excel_Range_Data (Java_Range.forColumns sheet left_index right_index)
Excel_Range.Value (Java_Range.forColumns sheet left_index right_index)
## Create an Excel_Range for a set of rows.
for_rows : Text -> Integer -> Integer -> Excel_Range
@ -135,4 +131,4 @@ type Excel_Range
bottom_valid = validate (Excel_Range.is_valid_row bottom) ("Invalid bottom row for Excel: " + bottom.to_text + ".")
top_valid <| bottom_valid <|
Excel_Range_Data (Java_Range.forRows sheet top bottom)
Excel_Range.Value (Java_Range.forRows sheet top bottom)

View File

@ -1,8 +1,7 @@
from Standard.Base import all
from Standard.Table.Excel.Range import Excel_Range
import Standard.Table.Excel.Range.Excel_Range
# TODO Dubious constructor export
from project.Excel.Section.Excel_Section import all
from project.Excel.Section.Excel_Section export all

View File

@ -1,8 +1,8 @@
from Standard.Base import Any, Problem_Behavior, Nothing, Error, Panic, Meta, File, File_Format, Plain_Text_Format, Bytes
from Standard.Base.Error.Common import Unsupported_File_Type, Unsupported_File_Type_Data, No_Such_Method_Error_Data, Illegal_Argument_Error_Data
from Standard.Table.Delimited.Delimited_Format import Delimited_Format
from Standard.Table.Excel.Excel_Format import Excel_Format
import Standard.Table.Delimited.Delimited_Format.Delimited_Format
import Standard.Table.Excel.Excel_Format.Excel_Format
## PRIVATE
Set of File_Format types for read files.
@ -19,7 +19,6 @@ get_format file =
reader 0
type Auto_Detect
## PRIVATE
Implements the `File.read` for this `File_Format`
read : File -> Problem_Behavior -> Any ! Unsupported_File_Type

View File

@ -2,7 +2,7 @@ from Standard.Base import Any, Text, Problem_Behavior, Nothing, Error, Panic, Me
from Standard.Base.Error.Problem_Behavior import Report_Warning
from Standard.Base.Error.Common import Unsupported_File_Type_Data, No_Such_Method_Error_Data, Illegal_Argument_Error_Data
from Standard.Table.IO.Auto_Detect import Auto_Detect
import Standard.Table.IO.Auto_Detect.Auto_Detect
## ALIAS Read Text File, Read File
@ -46,7 +46,7 @@ File.read path (format=Auto_Detect) (on_problems=Report_Warning) =
> Example
Read the first sheet of an XLSX from disk and convert it into a table.
import Standard.Table
from Standard.Table import all
import Standard.Examples
example_xlsx_to_table = Examples.xlsx.read
@ -54,7 +54,7 @@ File.read path (format=Auto_Detect) (on_problems=Report_Warning) =
> Example
Read the sheet named `Dates` from an XLS and convert it to a table.
import Standard.Table
from Standard.Table import all
from Standard.Table import Excel, Worksheet
import Standard.Examples

View File

@ -1,14 +1,16 @@
from Standard.Base import all hiding First, Last
from Standard.Table.Data.Column import Column
from Standard.Table.Data.Aggregate_Column import all
from Standard.Table.Data.Column_Selector import Column_Selector, By_Name, By_Index, By_Column
import Standard.Table.Internal.Problem_Builder
import Standard.Table.Internal.Unique_Name_Strategy
import Standard.Table.Data.Column.Column
from Standard.Table.Data.Aggregate_Column.Aggregate_Column import all
import Standard.Table.Data.Column_Selector.Column_Selector
import Standard.Table.Internal.Problem_Builder.Problem_Builder
import Standard.Table.Internal.Unique_Name_Strategy.Unique_Name_Strategy
import Standard.Table.Internal.Table_Helpers
import Standard.Table.Data.Sort_Column_Selector
import Standard.Table.Data.Sort_Column
import Standard.Table.Data.Sort_Column_Selector.Sort_Column_Selector
import Standard.Table.Data.Sort_Column.Sort_Column
import Standard.Base.Data.Ordering.Comparator
@ -35,16 +37,12 @@ polyglot java import org.enso.table.data.table.problems.InvalidAggregation
polyglot java import org.enso.table.data.table.problems.FloatingPointGrouping
polyglot java import org.enso.table.data.table.problems.UnquotedDelimiter
# TODO Dubious constructor export
from project.Internal.Aggregate_Column_Helper.Validated_Aggregate_Columns import all
from project.Internal.Aggregate_Column_Helper.Validated_Aggregate_Columns export all
## Result type for aggregate_columns validation
- key_columns: Vector of Columns from the table to group by
- valid_columns: Table structure to build as pairs of unique column name and Aggregate_Column
- problems: Set of any problems when validating the input
type Validated_Aggregate_Columns
Validated_Aggregate_Columns_Data (key_columns:[Column]) (valid_columns:[Pair Text Aggregate_Column]) (problems:[Any])
Value (key_columns:[Column]) (valid_columns:[Pair Text Aggregate_Column]) (problems:[Any])
## PRIVATE
Prepares an aggregation input for further processing:
@ -85,7 +83,7 @@ prepare_aggregate_columns aggregates table =
if unique.renames.not_empty then
problem_builder.report_other_warning (Duplicate_Output_Column_Names_Data unique.renames)
Validated_Aggregate_Columns_Data unique_key_columns renamed_columns problem_builder.build_problemset
Validated_Aggregate_Columns.Value unique_key_columns renamed_columns problem_builder.build_problemset
## PRIVATE
Defines the default name of an `Aggregate_Column`.
@ -147,9 +145,9 @@ resolve_aggregate table problem_builder aggregate_column =
Count_Distinct c new_name ignore_nothing ->
new_c = case c of
## TODO once we have sum type pattern matching this could be replaced with a single branch
By_Name _ _ -> resolve_selector_to_vector c
By_Index _ -> resolve_selector_to_vector c
By_Column _ -> resolve_selector_to_vector c
Column_Selector.By_Name _ _ -> resolve_selector_to_vector c
Column_Selector.By_Index _ -> resolve_selector_to_vector c
Column_Selector.By_Column _ -> resolve_selector_to_vector c
_ -> [resolve c]
Count_Distinct new_c new_name ignore_nothing
Count_Not_Nothing c new_name -> Count_Not_Nothing (resolve c) new_name

View File

@ -1,7 +1,11 @@
from Standard.Base import all
polyglot java import org.enso.table.data.table.Column
polyglot java import org.enso.table.data.table.Table
import Standard.Table.Data.Column.Column
polyglot java import org.enso.table.data.table.Column as Java_Column
import Standard.Table.Data.Table.Table
polyglot java import org.enso.table.data.table.Table as Java_Table
polyglot java import org.enso.table.data.index.DefaultIndex
polyglot java import org.enso.table.data.column.builder.object.InferredBuilder
polyglot java import org.enso.table.data.column.builder.object.NumericBuilder
@ -25,10 +29,10 @@ make_inferred_builder initial_size = InferredBuilder.new initial_size
## PRIVATE
make_column : Text -> Storage -> Column
make_column name storage = Column.new name storage
make_column name storage = Column.Column_Data (Java_Column.new name storage)
## PRIVATE
make_table_without_columns : Integer -> Table
make_table_without_columns row_count =
index = DefaultIndex.new row_count
Table.new [].to_array index
Table.Table_Data (Java_Table.new [].to_array index)

View File

@ -2,16 +2,12 @@ from Standard.Base import all
from Standard.Base.Error.Problem_Behavior import Report_Warning
import Standard.Base.Runtime.Ref
import Standard.Table.Internal.Vector_Builder
import Standard.Table.Internal.Vector_Builder.Vector_Builder
from Standard.Table.Errors import Missing_Input_Columns_Data, Column_Indexes_Out_Of_Range_Data, No_Output_Columns, Duplicate_Column_Selectors_Data, Input_Indices_Already_Matched_Data, Too_Many_Column_Names_Provided, Duplicate_Output_Column_Names, Invalid_Output_Column_Names, Column_Matched_By_Multiple_Selectors_Data
# TODO Dubious constructor export
from project.Internal.Problem_Builder.Problem_Builder import all
from project.Internal.Problem_Builder.Problem_Builder export all
type Problem_Builder
Problem_Builder_Data oob_indices duplicate_column_selectors input_indices_already_matched missing_input_columns other
Value oob_indices duplicate_column_selectors input_indices_already_matched missing_input_columns other
report_oob_indices self indices =
append_to_ref self.oob_indices indices
@ -66,7 +62,7 @@ type Problem_Builder
Creates a new helper object for aggregating problems to report.
new : Problem_Builder
new =
Problem_Builder_Data (Ref.new Vector_Builder.empty) (Ref.new Vector_Builder.empty) (Ref.new Vector_Builder.empty) (Ref.new Vector_Builder.empty) other=Vector.new_builder
Problem_Builder.Value (Ref.new Vector_Builder.empty) (Ref.new Vector_Builder.empty) (Ref.new Vector_Builder.empty) (Ref.new Vector_Builder.empty) other=Vector.new_builder
## PRIVATE
Appends a `Vector` to a `Vector_Builder` stored in a `Ref`.

View File

@ -4,14 +4,14 @@ import Standard.Base.Data.Ordering.Vector_Lexicographic_Order
from Standard.Base.Data.Text.Text_Ordering import Text_Ordering
from Standard.Base.Error.Problem_Behavior import Report_Warning
import Standard.Table.Data.Position
import Standard.Table.Data.Position.Position
from Standard.Table.Errors import Missing_Input_Columns_Data, No_Output_Columns, Too_Many_Column_Names_Provided_Data, Duplicate_Output_Column_Names_Data, Invalid_Output_Column_Names_Data, No_Input_Columns_Selected
from Standard.Table.Data.Column_Selector import Column_Selector, By_Name, By_Index, By_Column
import Standard.Table.Data.Column_Name_Mapping
import Standard.Table.Internal.Unique_Name_Strategy
import Standard.Table.Internal.Problem_Builder
import Standard.Table.Data.Sort_Column_Selector
import Standard.Table.Data.Sort_Column
import Standard.Table.Data.Column_Selector.Column_Selector
import Standard.Table.Data.Column_Name_Mapping.Column_Name_Mapping
import Standard.Table.Internal.Unique_Name_Strategy.Unique_Name_Strategy
import Standard.Table.Internal.Problem_Builder.Problem_Builder
import Standard.Table.Data.Sort_Column_Selector.Sort_Column_Selector
import Standard.Table.Data.Sort_Column.Sort_Column
polyglot java import java.util.HashSet
@ -234,20 +234,20 @@ sort_columns internal_columns direction text_ordering =
select_columns_helper : Vector -> Vector | Column_Selector -> Boolean -> Problem_Builder -> Vector
select_columns_helper internal_columns selector reorder problem_builder = case selector of
_ : Vector.Vector ->
select_columns_helper internal_columns (By_Name selector) reorder problem_builder
By_Name names matcher ->
select_columns_helper internal_columns (Column_Selector.By_Name selector) reorder problem_builder
Column_Selector.By_Name names matcher ->
valid_names = validate_unique names problem_builder.report_duplicate_column_selectors
Matching.match_criteria_callback matcher internal_columns valid_names reorder=reorder name_mapper=(_.name) problem_callback=problem_builder.report_missing_input_columns
By_Index indices ->
Column_Selector.By_Index indices ->
good_indices = validate_indices internal_columns.length indices problem_builder . map .first
case reorder of
True ->
select_indices_reordering internal_columns good_indices
False ->
select_indices_preserving_order internal_columns good_indices
By_Column columns ->
Column_Selector.By_Column columns ->
column_names = columns.map .name
new_selector = By_Name column_names Text_Matcher.Case_Sensitive
new_selector = Column_Selector.By_Name column_names Text_Matcher.Case_Sensitive
select_columns_helper internal_columns new_selector reorder=reorder problem_builder=problem_builder
## PRIVATE
@ -356,14 +356,10 @@ validate_unique vector problem_callback on=(x->x) =
acc.at 1 . to_vector
# TODO Dubious constructor export
from project.Internal.Table_Helpers.Column_Transform_Element import all
from project.Internal.Table_Helpers.Column_Transform_Element export all
## PRIVATE
A helper type used by transform helpers.
type Column_Transform_Element
Column_Transform_Element_Data column associated_selector
Value column associated_selector
## PRIVATE
prepare_order_by : Vector -> Problem_Builder -> Vector Column_Transform_Element
@ -422,7 +418,7 @@ transform_columns_by_name internal_columns name_selectors matcher problem_builde
if matching_selectors.length > 1 then
problem_builder.report_column_matched_by_multiple_selectors column.name matching_selectors
matching_selectors.first
Column_Transform_Element column associated_selector
Column_Transform_Element.Value column associated_selector
## PRIVATE
A helper function which can be used by methods that transform a subset of
@ -446,7 +442,7 @@ transform_columns_by_index internal_columns index_selectors problem_builder inde
selectors_map = Map.from_vector good_indices
internal_columns.map_with_index i-> column->
associated_selector = selectors_map.get_or_else i Nothing
Column_Transform_Element_Data column associated_selector
Column_Transform_Element.Value column associated_selector
## PRIVATE
A helper function which can be used by methods that transform a subset of
@ -504,7 +500,7 @@ select_columns_by_name internal_columns name_selectors matcher problem_builder n
problem_builder.report_column_matched_by_multiple_selectors column.name matching_selectors
associated_selector_index = matching_selector_indices.first
associated_selector = name_selectors.at associated_selector_index
element = Column_Transform_Element_Data column associated_selector
element = Column_Transform_Element.Value column associated_selector
results.append (Pair_Data element [associated_selector_index, i])
# We sort the results by the associated selector index, breaking ties by the column index.
sorted = results.to_vector.sort on=(_.second) by=Vector_Lexicographic_Order.compare
@ -531,7 +527,7 @@ select_columns_by_index : Vector -> Vector -> Problem_Builder -> (Any -> Integer
select_columns_by_index internal_columns index_selectors problem_builder index_extractor =
good_selectors = validate_indices internal_columns.length index_selectors problem_builder index_extractor
good_selectors.map pair->
Column_Transform_Element_Data (internal_columns.at pair.first) pair.second
Column_Transform_Element.Value (internal_columns.at pair.first) pair.second
## PRIVATE
A helper function which can be used by methods that select a subset of

View File

@ -2,6 +2,14 @@ from Standard.Base import Any, Vector, Text, Nothing
polyglot java import org.enso.table.util.NameDeduplicator
type Unique_Name_Strategy
## PRIVATE
Creates a Unique_Name_Strategy
Arguments:
- deduplicator: Name deduplicator
Value deduplicator
## Creates a new Unique_Name_Strategy instance.
This is a mutable data structure, that allows for creating a collection
@ -16,20 +24,7 @@ polyglot java import org.enso.table.util.NameDeduplicator
duplicates = unique_name_strategy.renames
invalid = unique_name_strategy.invalid_names
new : Unique_Name_Strategy
new = Unique_Name_Strategy_Data NameDeduplicator.new
# TODO Dubious constructor export
from project.Internal.Unique_Name_Strategy.Unique_Name_Strategy import all
from project.Internal.Unique_Name_Strategy.Unique_Name_Strategy export all
type Unique_Name_Strategy
## PRIVATE
Creates a Unique_Name_Strategy
Arguments:
- deduplicator: Name deduplicator
Unique_Name_Strategy_Data deduplicator
new = Unique_Name_Strategy.Value NameDeduplicator.new
## Vector of any duplicates renamed
renames : Vector

View File

@ -1,8 +1,6 @@
from Standard.Base import all
# TODO Dubious constructor export
from project.Internal.Vector_Builder.Vector_Builder import all
from project.Internal.Vector_Builder.Vector_Builder export all
from project.Internal.Vector_Builder.Vector_Builder import Leaf, Append
## PRIVATE

View File

@ -1,50 +1,53 @@
from Standard.Base import all
from Standard.Base import all
import Standard.Base.System.File_Format
import project.Data.Table
import project.Data.Column
import project.Data.Column_Selector
import project.Data.Sort_Column
import project.Data.Sort_Column_Selector
import project.Data.Column_Name_Mapping
import project.Data.Data_Formatter
import project.Data.Match_Columns
import project.Data.Aggregate_Column
import project.Data.Filter_Condition
import project.Data.Table.Table
import project.Data.Column.Column
import project.Data.Column_Selector.Column_Selector
import project.Data.Sort_Column.Sort_Column
import project.Data.Sort_Column_Selector.Sort_Column_Selector
import project.Data.Column_Name_Mapping.Column_Name_Mapping
import project.Data.Data_Formatter.Data_Formatter
import project.Data.Match_Columns.Match_Columns
import project.Data.Position.Position
import project.Data.Aggregate_Column.Aggregate_Column
import project.Data.Filter_Condition.Filter_Condition
import project.IO.File_Read
import project.IO.Auto_Detect
import project.IO.Auto_Detect.Auto_Detect
import project.Delimited.Quote_Style
import project.Delimited.Quote_Style.Quote_Style
import project.Delimited.Delimited_Format
import project.Data.Table_Conversions
import project.Excel.Section
import project.Excel.Range
import project.Excel.Range.Excel_Range
import project.Excel.Excel_Format
import project.Errors
from project.Data.Table export new, from_columns, from_rows, join, concat, Table, Table_Data
export project.Data.Column
export project.Data.Column_Selector
export project.Data.Sort_Column
export project.Data.Sort_Column_Selector
export project.Data.Column_Name_Mapping
export project.Data.Match_Columns
export project.Data.Aggregate_Column
from project.Data.Filter_Condition export Filter_Condition
export project.Data.Table.Table
export project.Data.Column.Column
export project.Data.Column_Selector.Column_Selector
export project.Data.Sort_Column.Sort_Column
export project.Data.Sort_Column_Selector.Sort_Column_Selector
export project.Data.Column_Name_Mapping.Column_Name_Mapping
export project.Data.Match_Columns.Match_Columns
export project.Data.Position.Position
export project.Data.Aggregate_Column.Aggregate_Column
export project.Data.Filter_Condition.Filter_Condition
export project.IO.File_Read
from project.IO.Auto_Detect export Auto_Detect
export project.IO.Auto_Detect.Auto_Detect
export project.Delimited.Quote_Style
export project.Delimited.Quote_Style.Quote_Style
from project.Delimited.Delimited_Format export Delimited_Format, Delimited
export project.Data.Table_Conversions
from project.Excel.Excel_Format export Excel_Format, Excel
from project.Excel.Section export Excel_Section, Sheet_Names, Range_Names, Worksheet, Cell_Range
from project.Excel.Range export Excel_Range
export project.Excel.Range.Excel_Range
from project.Data.Data_Formatter export Data_Formatter, Data_Formatter_Data
export project.Data.Data_Formatter.Data_Formatter
import Standard.Geo.Geo_Json
@ -74,8 +77,8 @@ import Standard.Geo.Geo_Json
> Example Converts a JSON array containing key-value pairs into a table for the
provided headers.
from Standard.Table import Table
import Standard.Examples
import Standard.Table
example_to_table =
json = Examples.simple_table_json
@ -93,7 +96,7 @@ Json.Json.to_table self fields=Nothing = case self of
[n, rows.map (_.at i)]
Table.new cols
Json.Object _ ->
if self.get_type != Geo_Json.Feature_Collection.to_text then Error.throw (Invalid_Format_Error_Data self "not being a feature collection") else
if self.get_type != Geo_Json.Feature_Collection.to_text then Error.throw (Invalid_Format_Error.Invalid_Format_Error_Data self "not being a feature collection") else
case self.get "features" of
Json.Array items ->
feature_rows = items.map .get_feature_row
@ -110,12 +113,7 @@ Json.Json.to_table self fields=Nothing = case self of
[n, rows.map (_.at i)]
Table.new cols
_ -> Error.throw (Invalid_Format_Error_Data self "not having the 'features' key.")
# TODO Dubious constructor export
from project.Main.Invalid_Format_Error import all
from project.Main.Invalid_Format_Error export all
_ -> Error.throw (Invalid_Format_Error.Invalid_Format_Error_Data self "not having the 'features' key.")
## UNSTABLE

View File

@ -1,6 +1,6 @@
from Standard.Base import all
import Standard.Table
from Standard.Table import Table
import Standard.Test
import Standard.Visualization.Helpers
@ -10,7 +10,7 @@ import Standard.Visualization.Helpers
Arguments:
- table: the Table to be visualized.
json_from_table : Table.Table -> Object
json_from_table : Table -> Object
json_from_table table =
names = ['label', 'latitude', 'longitude', 'radius', 'color']
pairs = names.map <| name->

View File

@ -1,7 +1,7 @@
from Standard.Base import all
from Standard.Table import Table, Column
import Standard.Table.Data.Storage
import Standard.Table.Data.Storage.Storage
## PRIVATE
@ -111,6 +111,6 @@ Table.lookup_ignore_case self name =
## PRIVATE
Checks if the column stores numbers.
Column.Column.is_numeric : Boolean
Column.Column.is_numeric self =
Column.is_numeric : Boolean
Column.is_numeric self =
[Storage.Integer,Storage.Decimal].contains self.storage_type

View File

@ -1,27 +1,22 @@
from Standard.Base import all
from Standard.Table import Table, Column
import Standard.Table
import Standard.Visualization.Helpers
## PRIVATE
Get first numeric column of the table.
Table.Table.first_numeric : Table -> Column ! Nothing
Table.Table.first_numeric self = self.all_columns.find _.is_numeric
Table.first_numeric : Table -> Column ! Nothing
Table.first_numeric self = self.all_columns.find _.is_numeric
## PRIVATE
Get the value column - the column that will be used to create histogram.
Table.Table.value_column : Table -> Column ! Nothing
Table.Table.value_column self =
Table.value_column : Table -> Column ! Nothing
Table.value_column self =
named_col = self.lookup_ignore_case 'value'
named_col.catch_ self.first_numeric
# TODO Dubious constructor export
from project.Histogram.Update import all
from project.Histogram.Update export all
## PRIVATE
Information that are placed in an update sent to a visualization.
@ -48,20 +43,20 @@ from_table table =
col = table.value_column
label = col.name.catch_ Nothing
values = col.to_vector.catch_ []
Update_Data values label
Update.Update_Data values label
## PRIVATE
from_vector : Vector -> Update
from_vector vector =
Update_Data vector Nothing
Update.Update_Data vector Nothing
## PRIVATE
from_value : Any -> Update
from_value value =
case value of
Table.Table_Data _ -> from_table value
_ : Table -> from_table value
_ : Vector.Vector -> from_vector value
Column.Column_Data _ -> from_table value.to_table
_ : Column -> from_table value.to_table
_ -> from_vector value.to_vector
## PRIVATE

View File

@ -1,7 +1,6 @@
from Standard.Base import all
from Standard.Table import Table, Column
import Standard.Table
import Standard.Visualization.Helpers
from Standard.Base.Data.Index_Sub_Range import Sample
@ -106,8 +105,8 @@ type No_Fallback_Column
## PRIVATE
Generates JSON that describes points data.
Table.Table.point_data : Table -> Object
Table.Table.point_data self =
Table.point_data : Table -> Object
Table.point_data self =
get_point_data field = field.lookup_in self . rename field.name . catch Any (_->Nothing)
columns = Point_Data.all_fields.map get_point_data . filter (x -> x.is_nothing.not)
(0.up_to self.row_count).to_vector.map <| row_n->
@ -119,8 +118,8 @@ Table.Table.point_data self =
## PRIVATE
Generates JSON that describes plot axes.
Table.Table.axes : Table -> Object
Table.Table.axes self =
Table.axes : Table -> Object
Table.axes self =
describe_axis field =
col_name = field.lookup_in self . name
label = Json.from_pairs [[label_field, col_name]]
@ -209,8 +208,8 @@ json_from_vector vec bounds limit =
process_to_json_text : Any -> Integer | Nothing -> Integer | Nothing -> Text
process_to_json_text value bounds=Nothing limit=Nothing =
json = case value of
Column.Column_Data _ -> json_from_table value.to_table bounds limit
Table.Table_Data _ -> json_from_table value bounds limit
_ : Column -> json_from_table value.to_table bounds limit
_ : Table -> json_from_table value bounds limit
_ : Vector.Vector -> json_from_vector value bounds limit
_ -> json_from_vector value.to_vector bounds limit

View File

@ -1,10 +1,12 @@
from Standard.Base import all
from Standard.Table.Data.Column_Selector import By_Name
import Standard.Table.Data.Table as Dataframe_Table
import Standard.Table.Data.Column as Dataframe_Column
import Standard.Database.Data.Table as Database_Table
import Standard.Database.Data.Column as Database_Column
import Standard.Table.Data.Table.Table as Dataframe_Table
import Standard.Table.Data.Column.Column as Dataframe_Column
import Standard.Database.Data.Table.Table as Database_Table
import Standard.Database.Data.Column.Column as Database_Column
import Standard.Table.Data.Column_Selector.Column_Selector
import Standard.Visualization.Helpers
# TODO add an initial offset to fully support lazy visualizations
@ -32,8 +34,8 @@ prepare_visualization x max_rows=1000 = Helpers.recover_errors <| case x of
# Materialize a table with indices as normal columns (because dataframe does not support multi-indexing).
df = x.reset_index.read max_rows
# Then split into actual columns and indices.
vis_df = df.select_columns (By_Name (x.columns.map .name))
indices = df.select_columns (By_Name (x.indices.map .name)) . columns
vis_df = df.select_columns (Column_Selector.By_Name (x.columns.map .name))
indices = df.select_columns (Column_Selector.By_Name (x.indices.map .name)) . columns
all_rows_count = x.row_count
make_json vis_df indices all_rows_count
@ -43,11 +45,6 @@ prepare_visualization x max_rows=1000 = Helpers.recover_errors <| case x of
Database_Column.Column_Data _ _ _ _ _ ->
prepare_visualization x.to_table max_rows
# We display aggregates as their ungrouped counterparts.
Dataframe_Column.Aggregate_Column_Data _ ->
ungrouped = Dataframe_Column.Column_Data x.java_column.getColumn
prepare_visualization ungrouped.to_table max_rows
# TODO [RW] Should we truncate Vectors?
# We also visualize Vectors and arrays
_ : Vector.Vector ->

View File

@ -1,7 +1,6 @@
from Standard.Base import all
import Standard.Table
from Standard.Table import Column_Selector
from Standard.Table import Table, Column_Selector
from Standard.Table.Data.Aggregate_Column import all
import Standard.Test.Bench

View File

@ -2,8 +2,7 @@ from Standard.Base import all
from Standard.Base.Data.Index_Sub_Range import Sample
import Standard.Base.Data.Time.Duration
import Standard.Table
from Standard.Table import Sort_Column_Selector
from Standard.Table import Table, Sort_Column_Selector
from Standard.Table.Data.Aggregate_Column import all
import Standard.Test.Bench

View File

@ -1,5 +1,5 @@
from Standard.Base import all
from Standard.Table.Data.Table import Table_Data
from Standard.Table.Data.Table.Table import Table_Data
import Standard.Geo

View File

@ -1,11 +1,10 @@
from Standard.Base import all hiding First, Last
import Standard.Table
from Standard.Table.Data.Aggregate_Column import all
from Standard.Table.Data.Column_Selector import By_Name, By_Index
from Standard.Table import Table, Column_Selector
from Standard.Table.Data.Aggregate_Column.Aggregate_Column import all
import Standard.Table.Internal.Aggregate_Column_Helper
import Standard.Table.Internal.Problem_Builder
import Standard.Table.Internal.Problem_Builder.Problem_Builder
import Standard.Test
@ -150,9 +149,9 @@ spec = Test.group "Aggregate Columns" <|
test_aggregator simple_table (Count_Distinct float_col test_name ignore_nothing=True) test_name 4
Test.specify "should be able to count distinct items on a multiple sets of values" <|
test_aggregator simple_table (Count_Distinct (By_Index [0, 1])) "Count Distinct count is_valid" 5
test_aggregator simple_table (Count_Distinct (By_Name ["is_valid", "float"])) "Count Distinct is_valid float" 5
test_aggregator simple_table (Count_Distinct (By_Name ["is_valid", "float"]) ignore_nothing=True) "Count Distinct is_valid float" 4
test_aggregator simple_table (Count_Distinct (Column_Selector.By_Index [0, 1])) "Count Distinct count is_valid" 5
test_aggregator simple_table (Count_Distinct (Column_Selector.By_Name ["is_valid", "float"])) "Count Distinct is_valid float" 5
test_aggregator simple_table (Count_Distinct (Column_Selector.By_Name ["is_valid", "float"]) ignore_nothing=True) "Count Distinct is_valid float" 4
Test.specify "should be able to get the minimum of a set of values" <|
test_aggregator simple_table (Minimum -2) "Minimum float" 1

View File

@ -1,9 +1,8 @@
from Standard.Base import all hiding First, Last
import Standard.Table
from Standard.Table import Sort_Column, Sort_Column_Selector
from Standard.Table.Data.Column_Selector import By_Name, By_Index
from Standard.Table.Data.Aggregate_Column import all
from Standard.Table import Table, Sort_Column, Sort_Column_Selector, Column_Selector
from Standard.Table.Data.Column_Selector.Column_Selector import By_Name
from Standard.Table.Data.Aggregate_Column.Aggregate_Column import all
from Standard.Table.Errors import Missing_Input_Columns_Data, Column_Indexes_Out_Of_Range_Data, No_Output_Columns, Duplicate_Output_Column_Names_Data, Invalid_Output_Column_Names_Data, Invalid_Aggregation_Data, Floating_Point_Grouping_Data, Unquoted_Delimiter_Data, Additional_Warnings_Data
from Standard.Database.Errors import Unsupported_Database_Operation_Error_Data
@ -12,12 +11,8 @@ import Standard.Test.Problems
polyglot java import java.lang.Double
# TODO Dubious constructor export
from project.Aggregate_Spec.Test_Selection import all
from project.Aggregate_Spec.Test_Selection export all
type Test_Selection
Test_Selection_Data problem_handling=True advanced_stats=True text_concat=True text_shortest_longest=True first_last=True first_last_row_order=True std_dev=True multi_distinct=True aggregation_problems=True nan=True date_support=True
Config problem_handling=True advanced_stats=True text_concat=True text_shortest_longest=True first_last=True first_last_row_order=True std_dev=True multi_distinct=True aggregation_problems=True nan=True date_support=True
spec =
table = (enso_project.data / "data.csv") . read
@ -41,7 +36,7 @@ spec =
skip checks for backends which do not support particular features.
- pending: An optional mark to disable all test groups. Can be used to
indicate that some tests are disabled due to missing test setup.
aggregate_spec prefix table empty_table table_builder materialize is_database test_selection=Test_Selection_Data pending=Nothing =
aggregate_spec prefix table empty_table table_builder materialize is_database test_selection=Test_Selection.Config pending=Nothing =
expect_column_names names table =
table.columns . map .name . should_equal names frames_to_skip=2
@ -1244,7 +1239,7 @@ aggregate_spec prefix table empty_table table_builder materialize is_database te
Problems.test_problem_handling action problems tester
Test.specify "should ignore Count_Distinct if no columns matched" <|
action = table.aggregate [Count_Distinct (By_Index [-100])] on_problems=_
action = table.aggregate [Count_Distinct (Column_Selector.By_Index [-100])] on_problems=_
problems = [Column_Indexes_Out_Of_Range_Data [-100], No_Output_Columns]
tester = expect_column_names []
Problems.test_problem_handling action problems tester

View File

@ -1,6 +1,7 @@
from Standard.Base import all
from Standard.Table import Column
import Standard.Table.Data.Storage
import Standard.Table.Data.Column as Column_Module
import Standard.Table.Data.Storage.Storage
import Standard.Examples
import Standard.Test
@ -12,14 +13,14 @@ spec = Test.group "Columns" <|
empty_column = Column.from_vector "Test" []
Test.specify "should correctly map storage types" <|
Column.storage_types.at Java_Storage.Type.LONG . should_equal Storage.Integer
Column.storage_types.at Java_Storage.Type.DOUBLE . should_equal Storage.Decimal
Column.storage_types.at Java_Storage.Type.STRING . should_equal Storage.Text
Column.storage_types.at Java_Storage.Type.BOOL . should_equal Storage.Boolean
Column.storage_types.at Java_Storage.Type.OBJECT . should_equal Storage.Any
Column.storage_types.at Java_Storage.Type.DATE . should_equal Storage.Date
Column.storage_types.at Java_Storage.Type.TIME_OF_DAY . should_equal Storage.Time_Of_Day
Column.storage_types.at Java_Storage.Type.DATE_TIME . should_equal Storage.Date_Time
Column_Module.storage_types.at Java_Storage.Type.LONG . should_equal Storage.Integer
Column_Module.storage_types.at Java_Storage.Type.DOUBLE . should_equal Storage.Decimal
Column_Module.storage_types.at Java_Storage.Type.STRING . should_equal Storage.Text
Column_Module.storage_types.at Java_Storage.Type.BOOL . should_equal Storage.Boolean
Column_Module.storage_types.at Java_Storage.Type.OBJECT . should_equal Storage.Any
Column_Module.storage_types.at Java_Storage.Type.DATE . should_equal Storage.Date
Column_Module.storage_types.at Java_Storage.Type.TIME_OF_DAY . should_equal Storage.Time_Of_Day
Column_Module.storage_types.at Java_Storage.Type.DATE_TIME . should_equal Storage.Date_Time
Test.specify "should allow getting specific elements" <|
test_column.at 0 . should_equal 1
@ -47,12 +48,12 @@ spec = Test.group "Columns" <|
Test.specify "should be able to get the first / head element" <|
test_column.first . should_equal 1
test_column.head . should_equal 1
empty_column.first.should_fail_with Column.Empty_Error
empty_column.head.should_fail_with Column.Empty_Error
empty_column.first.should_fail_with Column_Module.Empty_Error
empty_column.head.should_fail_with Column_Module.Empty_Error
Test.specify "should be able to get the last element" <|
test_column.last . should_equal 6
empty_column.last.should_fail_with Column.Empty_Error
empty_column.last.should_fail_with Column_Module.Empty_Error
Test.specify "should be able to be reversed" <|
expected_1 = Column.from_vector "Test" [6, 4, 2, 5, 3, 1]

View File

@ -3,11 +3,10 @@ from Standard.Base.Data.Index_Sub_Range import While, Sample, Every
import Standard.Base.Data.Index_Sub_Range
from Standard.Base.Error.Problem_Behavior import Report_Error
from Standard.Table import Column_Name_Mapping, Sort_Column, Sort_Column_Selector
from Standard.Table.Data.Value_Type import Value_Type
from Standard.Table import Column_Name_Mapping, Sort_Column, Sort_Column_Selector, Position
import Standard.Table.Data.Value_Type.Value_Type
from Standard.Table.Data.Column_Selector.Column_Selector import By_Name, By_Index, By_Column
from Standard.Table.Errors import all
from Standard.Table.Data.Column_Selector import all
from Standard.Table.Data.Position import all
from Standard.Table.Data.Filter_Condition import Filter_Condition
from Standard.Database.Errors import SQL_Error_Data
@ -17,12 +16,8 @@ import Standard.Test.Problems
from project.Util import all
# TODO Dubious constructor export
from project.Common_Table_Spec.Test_Selection import all
from project.Common_Table_Spec.Test_Selection export all
type Test_Selection
Test_Selection_Data supports_case_sensitive_columns=True order_by=True natural_ordering=False case_insensitive_ordering=True order_by_unicode_normalization_by_default=False case_insensitive_ascii_only=False take_drop=True allows_mixed_type_comparisons=True
Config supports_case_sensitive_columns=True order_by=True natural_ordering=False case_insensitive_ordering=True order_by_unicode_normalization_by_default=False case_insensitive_ascii_only=False take_drop=True allows_mixed_type_comparisons=True
## A common test suite for shared operations on the Table API.
@ -337,18 +332,18 @@ spec prefix table_builder test_selection pending=Nothing =
Test.group prefix+"Table.reorder_columns" pending=pending <|
Test.specify "should work as shown in the doc examples" <|
expect_column_names ["bar", "Baz", "foo_1", "foo_2", "ab.+123", "abcd123", "foo"] <| table.reorder_columns (By_Name ["foo"]) position=After_Other_Columns
expect_column_names ["Baz", "foo_1", "foo_2", "ab.+123", "abcd123", "foo", "bar"] <| table.reorder_columns ["foo", "bar"] position=After_Other_Columns
expect_column_names ["bar", "Baz", "foo_1", "foo_2", "ab.+123", "abcd123", "foo"] <| table.reorder_columns (By_Name ["foo"]) Position.After_Other_Columns
expect_column_names ["Baz", "foo_1", "foo_2", "ab.+123", "abcd123", "foo", "bar"] <| table.reorder_columns ["foo", "bar"] Position.After_Other_Columns
expect_column_names ["foo_1", "foo_2", "bar", "Baz", "foo", "ab.+123", "abcd123"] <| table.reorder_columns (By_Name ["foo.+", "b.*"] (Regex_Matcher.Regex_Matcher_Data case_sensitivity=Case_Sensitivity.Insensitive))
expect_column_names ["bar", "foo", "Baz", "foo_1", "foo_2", "ab.+123", "abcd123"] <| table.reorder_columns (By_Index [1, 0]) position=Before_Other_Columns
expect_column_names ["bar", "Baz", "foo_1", "foo_2", "ab.+123", "abcd123", "foo"] <| table.reorder_columns (By_Index [0]) position=After_Other_Columns
expect_column_names ["bar", "foo", "Baz", "foo_1", "foo_2", "ab.+123", "abcd123"] <| table.reorder_columns (By_Index [1, 0]) Position.Before_Other_Columns
expect_column_names ["bar", "Baz", "foo_1", "foo_2", "ab.+123", "abcd123", "foo"] <| table.reorder_columns (By_Index [0]) Position.After_Other_Columns
column1 = table.at "foo_1"
column2 = table.at "Baz"
expect_column_names ["foo_1", "Baz", "foo", "bar", "foo_2", "ab.+123", "abcd123"] <| table.reorder_columns (By_Column [column1, column2])
Test.specify "should correctly handle regex matching" <|
expect_column_names ["bar", "Baz", "foo_1", "foo_2", "ab.+123", "abcd123", "foo"] <| table.reorder_columns (By_Name ["foo"] (Regex_Matcher.Regex_Matcher_Data case_sensitivity=Case_Sensitivity.Sensitive)) position=After_Other_Columns
expect_column_names ["bar", "Baz", "foo_1", "foo_2", "ab.+123", "abcd123", "foo"] <| table.reorder_columns (By_Name ["foo"] (Regex_Matcher.Regex_Matcher_Data case_sensitivity=Case_Sensitivity.Sensitive)) Position.After_Other_Columns
rest = ["foo", "bar", "Baz", "foo_1", "foo_2"]
expect_column_names ["ab.+123", "abcd123"]+rest <| table.reorder_columns (By_Name ["a.*"] (Regex_Matcher.Regex_Matcher_Data case_sensitivity=Case_Sensitivity.Sensitive))
expect_column_names ["ab.+123", "abcd123"]+rest <| table.reorder_columns (By_Name ["ab.+123"] (Regex_Matcher.Regex_Matcher_Data case_sensitivity=Case_Sensitivity.Sensitive))
@ -379,21 +374,21 @@ spec prefix table_builder test_selection pending=Nothing =
Test.specify "should correctly handle problems: duplicate indices" <|
selector = By_Index [0, 0, 0]
action = table.reorder_columns selector position=After_Other_Columns on_problems=_
action = table.reorder_columns selector Position.After_Other_Columns on_problems=_
tester = expect_column_names ["bar", "Baz", "foo_1", "foo_2", "ab.+123", "abcd123", "foo"]
problems = [Duplicate_Column_Selectors_Data [0, 0]]
Problems.test_problem_handling action problems tester
Test.specify "should correctly handle problems: aliased indices" <|
selector = By_Index [0, -7, -6, 1]
action = table.reorder_columns selector position=After_Other_Columns on_problems=_
action = table.reorder_columns selector Position.After_Other_Columns on_problems=_
tester = expect_column_names ["Baz", "foo_1", "foo_2", "ab.+123", "abcd123", "foo", "bar"]
problems = [Input_Indices_Already_Matched_Data [-7, 1]]
Problems.test_problem_handling action problems tester
Test.specify "should correctly handle problems: duplicate names" <|
selector = By_Name ["foo", "foo"]
action = table.reorder_columns selector position=After_Other_Columns on_problems=_
action = table.reorder_columns selector Position.After_Other_Columns on_problems=_
tester = expect_column_names ["bar", "Baz", "foo_1", "foo_2", "ab.+123", "abcd123", "foo"]
problems = [Duplicate_Column_Selectors_Data ["foo"]]
Problems.test_problem_handling action problems tester
@ -401,7 +396,7 @@ spec prefix table_builder test_selection pending=Nothing =
Test.specify "should correctly handle problems: unmatched names" <|
weird_name = '.*?-!@#!"'
selector = By_Name ["foo", "hmm", weird_name]
action = table.reorder_columns selector position=After_Other_Columns on_problems=_
action = table.reorder_columns selector Position.After_Other_Columns on_problems=_
tester = expect_column_names ["bar", "Baz", "foo_1", "foo_2", "ab.+123", "abcd123", "foo"]
problems = [Missing_Input_Columns_Data ["hmm", weird_name]]
Problems.test_problem_handling action problems tester
@ -409,7 +404,7 @@ spec prefix table_builder test_selection pending=Nothing =
Test.specify "should correctly handle problems: duplicate columns" <|
foo = table.at "foo"
selector = By_Column [foo, foo]
action = table.reorder_columns selector position=After_Other_Columns on_problems=_
action = table.reorder_columns selector Position.After_Other_Columns on_problems=_
tester = expect_column_names ["bar", "Baz", "foo_1", "foo_2", "ab.+123", "abcd123", "foo"]
problems = [Duplicate_Column_Selectors_Data ["foo"]]
Problems.test_problem_handling action problems tester
@ -421,13 +416,13 @@ spec prefix table_builder test_selection pending=Nothing =
bar = table.at "bar"
selector = By_Column [bar, weird_column, foo]
action = table.reorder_columns selector position=After_Other_Columns on_problems=_
action = table.reorder_columns selector Position.After_Other_Columns on_problems=_
tester = expect_column_names ["Baz", "foo_1", "foo_2", "ab.+123", "abcd123", "bar", "foo"]
problems = [Missing_Input_Columns_Data ["weird_column"]]
Problems.test_problem_handling action problems tester
Test.specify "should correctly handle multiple problems" <|
action = table.reorder_columns (By_Index [0, -7, 0, 100]) position=After_Other_Columns on_problems=_
action = table.reorder_columns (By_Index [0, -7, 0, 100]) Position.After_Other_Columns on_problems=_
problems = [Column_Indexes_Out_Of_Range_Data [100], Duplicate_Column_Selectors_Data [0], Input_Indices_Already_Matched_Data [-7]]
tester = expect_column_names ["bar", "Baz", "foo_1", "foo_2", "ab.+123", "abcd123", "foo"]
Problems.test_problem_handling action problems tester

View File

@ -1,8 +1,6 @@
from Standard.Base import all
import Standard.Table
from Standard.Table import Column, Delimited
from Standard.Table.Data.Column_Selector import By_Index
from Standard.Table import Table, Column, Delimited, Column_Selector
import Standard.Test
@ -17,7 +15,7 @@ spec =
Test.group "Table.from Text" <|
Test.specify "should create a table from a textual CSV" <|
file_contents = (enso_project.data / "simple_empty.csv") . read_text
table = Table.Table.from file_contents (format = Delimited ",")
table = Table.from file_contents (format = Delimited ",")
table.should_equal expected_table
Test.group "File.read (Delimited)" <|
@ -37,13 +35,13 @@ spec =
c_6 = ["Column_6", ['1', '2', '3', '4', '5', '6.25', '7', 'osiem']]
expected = Table.new [c_1, c_3, c_4, c_5, c_6]
varied_column.select_columns (By_Index [0, 2, 3, 4, 5]) . should_equal expected
varied_column.select_columns (Column_Selector.By_Index [0, 2, 3, 4, 5]) . should_equal expected
Test.specify "should handle duplicated columns" <|
csv = """
name,x,y,x,y
foo,10,20,30,20
t = Table.Table.from csv (format = Delimited ",")
t = Table.from csv (format = Delimited ",")
t.columns.map .name . should_equal ['name', 'x', 'y', 'x_1', 'y_1']
Test.group 'Writing' <|

View File

@ -1,52 +1,32 @@
from Standard.Base import all
import Standard.Table
from Standard.Table import Column, Data_Formatter_Data, Quote_Style
from Standard.Table import Table, Column, Data_Formatter, Quote_Style
from Standard.Table.Errors import all
import Standard.Test
import Standard.Test.Problems
# TODO Dubious constructor export
from project.Data_Formatter_Spec.Custom_Type import all
from project.Data_Formatter_Spec.Custom_Type export all
type Custom_Type
Custom_Type_Data field
# TODO Dubious constructor export
from project.Data_Formatter_Spec.Custom_Type_With_To_Text import all
from project.Data_Formatter_Spec.Custom_Type_With_To_Text export all
Value field
type Custom_Type_With_To_Text
Custom_Type_With_To_Text_Data field
Value field
to_text : Text
to_text self = "[CUSTOM = " + self.field.to_text + "]"
# TODO Dubious constructor export
from project.Data_Formatter_Spec.Custom_Type_With_Error import all
from project.Data_Formatter_Spec.Custom_Type_With_Error export all
type Custom_Type_With_Error
to_text : Text
to_text self = Error.throw (Illegal_State_Error_Data "foo_error")
# TODO Dubious constructor export
from project.Data_Formatter_Spec.Custom_Type_With_Panic import all
from project.Data_Formatter_Spec.Custom_Type_With_Panic export all
type Custom_Type_With_Panic
Custom_Type_With_Panic_Data
to_text : Text
to_text self = Panic.throw (Illegal_State_Error_Data "foo_panic")
spec =
Test.group "DataFormatter.parse" <|
Test.specify "should parse numbers" <|
formatter = Data_Formatter_Data
formatter = Data_Formatter.Value
formatter.parse "123" . should_equal 123
formatter.parse "1000000" . should_equal 1000000
formatter.parse "1000000.0" . should_equal 1000000.0
@ -61,7 +41,7 @@ spec =
formatter.parse "NaN" . is_nan . should_be_true
Test.specify "should allow customizing the decimal point and thousand separator" <|
formatter = Data_Formatter_Data thousand_separator="_" decimal_point=","
formatter = Data_Formatter.Value thousand_separator="_" decimal_point=","
formatter.parse "123" . should_equal 123
formatter.parse "1_000_000" . should_equal 1000000
formatter.parse "1_000_000_000" . should_equal (1000 * 1000 * 1000)
@ -73,8 +53,8 @@ spec =
formatter.parse "1,0001" . should_equal 1.0001
Test.specify "should support exponential notation, but only if explicitly enabled" <|
plain_formatter = Data_Formatter_Data
exponential_formatter = Data_Formatter_Data allow_exponential_notation=True
plain_formatter = Data_Formatter.Value
exponential_formatter = Data_Formatter.Value allow_exponential_notation=True
plain_formatter.parse "1E3" . should_equal "1E3"
r1 = plain_formatter.parse "1E3" Decimal
@ -91,27 +71,27 @@ spec =
exponential_formatter.parse "1.2E-3" Decimal . should_equal 0.0012
Test.specify "handle leading zeros, only if enabled" <|
Data_Formatter_Data.parse "0100" . should_equal "0100"
Data_Formatter_Data.parse "000" . should_equal "000"
Data_Formatter_Data.parse "000.0" . should_equal "000.0"
formatter = Data_Formatter_Data allow_leading_zeros=True
Data_Formatter.Value.parse "0100" . should_equal "0100"
Data_Formatter.Value.parse "000" . should_equal "000"
Data_Formatter.Value.parse "000.0" . should_equal "000.0"
formatter = Data_Formatter.Value allow_leading_zeros=True
formatter.parse "0100" . should_equal 100
formatter.parse "000" . should_equal 0
formatter.parse "000.0" . should_equal 0.0
Test.specify "should parse booleans" <|
formatter = Data_Formatter_Data
formatter = Data_Formatter.Value
formatter.parse "True" . should_equal True
formatter.parse "False" . should_equal False
Test.specify "should allow custom boolean formats" <|
formatter = Data_Formatter_Data true_values=["YES", "1", "true"] false_values=["NO", "0", "false"]
formatter = Data_Formatter.Value true_values=["YES", "1", "true"] false_values=["NO", "0", "false"]
formatter.parse "YES" . should_equal True
formatter.parse "NO" . should_equal False
(Data_Formatter_Data true_values=[] false_values=[]).parse "True" datatype=Boolean . should_equal Nothing
(Data_Formatter.Value true_values=[] false_values=[]).parse "True" datatype=Boolean . should_equal Nothing
Test.specify "should parse dates" <|
formatter = Data_Formatter_Data
formatter = Data_Formatter.Value
formatter.parse "2022-01-01" . should_equal (Date.new 2022)
formatter.parse "2020-05-07" datatype=Date . should_equal (Date.new 2020 5 7)
formatter.parse "1999-01-01 00:00:00" . should_equal (Date_Time.new 1999)
@ -130,7 +110,7 @@ spec =
formatter.parse "30:00:65" . should_equal "30:00:65"
Test.specify "should fallback to Text" <|
formatter = Data_Formatter_Data
formatter = Data_Formatter.Value
formatter.parse "Text" . should_equal "Text"
complex_text = """
Text with such 'quotes' and also "that" and `that`
@ -139,10 +119,10 @@ spec =
Test.group "DataFormatter.format" <|
Test.specify "should handle Nothing" <|
Data_Formatter_Data.format Nothing . should_equal Nothing
Data_Formatter.Value.format Nothing . should_equal Nothing
Test.specify "should format numbers" <|
formatter = Data_Formatter_Data
formatter = Data_Formatter.Value
formatter.format 123 . should_equal "123"
formatter.format 1000000 . should_equal "1000000"
formatter.format 1000000.0 . should_equal "1000000.0"
@ -155,7 +135,7 @@ spec =
formatter.format (Number.nan) . should_equal "NaN"
Test.specify "should allow customizing the decimal point and thousand separator" <|
formatter = Data_Formatter_Data thousand_separator="_" decimal_point=","
formatter = Data_Formatter.Value thousand_separator="_" decimal_point=","
formatter.format 123 . should_equal "123"
formatter.format 1000000 . should_equal "1_000_000"
formatter.format (1000 * 1000 * 1000) . should_equal "1_000_000_000"
@ -167,18 +147,18 @@ spec =
formatter.format 1.0001 . should_equal "1,0001"
Test.specify "should format booleans" <|
formatter = Data_Formatter_Data
formatter = Data_Formatter.Value
formatter.format True . should_equal "True"
formatter.format False . should_equal "False"
Test.specify "should allow custom boolean formats" <|
formatter = Data_Formatter_Data true_values=["YES", "1", "true"] false_values=["NO", "0", "false"]
formatter = Data_Formatter.Value true_values=["YES", "1", "true"] false_values=["NO", "0", "false"]
formatter.format True . should_equal "YES"
formatter.format False . should_equal "NO"
(Data_Formatter_Data true_values=[] false_values=[]).format True . should_fail_with Illegal_Argument_Error_Data
(Data_Formatter.Value true_values=[] false_values=[]).format True . should_fail_with Illegal_Argument_Error_Data
Test.specify "should format dates" <|
formatter = Data_Formatter_Data
formatter = Data_Formatter.Value
formatter.format (Date.new 2022) . should_equal "2022-01-01"
formatter.format (Date_Time.new 1999) . should_equal "1999-01-01 00:00:00"
formatter.format (Date_Time.new 1999 zone=Time_Zone.utc) . should_equal "1999-01-01 00:00:00"
@ -186,14 +166,14 @@ spec =
formatter.format (Time_Of_Day.new) . should_equal "00:00:00"
Test.specify "should allow custom date formats" <|
formatter = Data_Formatter_Data date_formats=["E, d MMM y", "d MMM y[ G]"] datetime_formats=["dd/MM/yyyy HH:mm [z]"] time_formats=["h:mma"] datetime_locale=Locale.uk
formatter = Data_Formatter.Value date_formats=["E, d MMM y", "d MMM y[ G]"] datetime_formats=["dd/MM/yyyy HH:mm [z]"] time_formats=["h:mma"] datetime_locale=Locale.uk
formatter.format (Date.new 2022 06 21) . should_equal "Tue, 21 Jun 2022"
formatter.format (Date_Time.new 1999 02 03 04 56 11 zone=Time_Zone.utc) . should_equal "03/02/1999 04:56 UTC"
formatter.format (Date_Time.new 1999 02 03 04 56 11 zone=(Time_Zone.parse "America/Los_Angeles")) . should_equal "03/02/1999 04:56 GMT-08:00"
formatter.format (Time_Of_Day.new 13 55) . should_equal "1:55pm"
Test.specify "should act as identity on Text" <|
formatter = Data_Formatter_Data
formatter = Data_Formatter.Value
formatter.format "Text" . should_equal "Text"
complex_text = """
Text with such 'quotes' and also "that" and `that`
@ -201,19 +181,19 @@ spec =
formatter.format complex_text . should_equal complex_text
Test.specify "should work with custom types, falling back to the `.to_text` method" <|
formatter = Data_Formatter_Data thousand_separator="_"
formatter.format (Custom_Type_Data 42) . should_equal "(Custom_Type_Data 42)"
formatter = Data_Formatter.Value thousand_separator="_"
formatter.format (Custom_Type.Value 42) . should_equal "(Custom_Type.Value 42)"
# We fallback to `to_text`, so obviously the nested numbers will not know about our formatting settings.
formatter.format (Custom_Type_With_To_Text_Data 1000) . should_equal "[CUSTOM = 1000]"
formatter.format (Custom_Type_With_To_Text.Value 1000) . should_equal "[CUSTOM = 1000]"
Test.specify "should correctly pass through errors from custom type's `.to_text` method" pending="TODO: figure out the desired behavior, see: https://www.pivotaltracker.com/story/show/182522644" <|
formatter = Data_Formatter_Data
formatter = Data_Formatter.Value
formatter.format Custom_Type_With_Error . should_fail_with Illegal_State_Error_Data
Test.expect_panic_with (formatter.format Custom_Type_With_Panic) Illegal_State_Error_Data
Test.group "DataFormatter builders" <|
# We create a formatter with all non-default values to ensure that the builders keep the existing values of other properties instead of switching to the constructor's defaults.
formatter_1 = Data_Formatter_Data trim_values=False allow_leading_zeros=True decimal_point=',' thousand_separator='_' allow_exponential_notation=True datetime_formats=["yyyy/MM/dd HH:mm:ss"] date_formats=["dd/MM/yyyy"] time_formats=["HH/mm/ss"] datetime_locale=Locale.uk true_values=["YES"] false_values=["NO"]
formatter_1 = Data_Formatter.Value trim_values=False allow_leading_zeros=True decimal_point=',' thousand_separator='_' allow_exponential_notation=True datetime_formats=["yyyy/MM/dd HH:mm:ss"] date_formats=["dd/MM/yyyy"] time_formats=["HH/mm/ss"] datetime_locale=Locale.uk true_values=["YES"] false_values=["NO"]
Test.specify "should allow changing number formatting settings" <|
formatter_2 = formatter_1.with_number_formatting decimal_point="*"
formatter_2.decimal_point . should_equal "*"

View File

@ -1,8 +1,7 @@
from Standard.Base import all
from Standard.Table import Sort_Column, Sort_Column_Selector
from Standard.Table.Data.Column_Selector import By_Name
from Standard.Table.Data.Aggregate_Column import all
from Standard.Table import Sort_Column, Sort_Column_Selector, Column_Selector
from Standard.Table.Data.Aggregate_Column.Aggregate_Column import all
from Standard.Table.Errors import No_Input_Columns_Selected, Missing_Input_Columns_Data, No_Such_Column_Error_Data
from Standard.Database import all
@ -43,7 +42,7 @@ spec =
Test.group "[Codegen] Basic Select" <|
Test.specify "should select columns from a table" <|
t1.to_sql.prepare . should_equal ['SELECT "T1"."A" AS "A", "T1"."B" AS "B", "T1"."C" AS "C" FROM "T1" AS "T1"', []]
t2 = t1.select_columns (By_Name ["C", "B", "undefined"]) reorder=True
t2 = t1.select_columns (Column_Selector.By_Name ["C", "B", "undefined"]) reorder=True
t2.to_sql.prepare . should_equal ['SELECT "T1"."C" AS "C", "T1"."B" AS "B" FROM "T1" AS "T1"', []]
foo = t1.at "A" . rename "FOO"
@ -60,7 +59,7 @@ spec =
t2.to_sql.prepare . should_equal ['SELECT "T1"."A" AS "A", "T1"."B" AS "B", "T1"."C" AS "C" FROM "T1" AS "T1" LIMIT 5', []]
Test.specify "should work correctly when there are no columns" <|
empty = t1.select_columns (By_Name [])
empty = t1.select_columns (Column_Selector.By_Name [])
json = Json.from_pairs [["query", Nothing], ["message", "The table has no columns so a query cannot be generated."]]
empty.to_json . should_equal json
empty.column_count . should_equal 0

View File

@ -1,9 +1,7 @@
from Standard.Base import all
import Standard.Table as Materialized_Table
from Standard.Table import Sort_Column, Sort_Column_Selector
from Standard.Table.Data.Column_Selector import By_Name
from Standard.Table.Data.Aggregate_Column import all
from Standard.Table import Table, Sort_Column, Column_Selector, Sort_Column_Selector
from Standard.Table.Data.Aggregate_Column.Aggregate_Column import all
from Standard.Table.Errors import No_Input_Columns_Selected, Missing_Input_Columns_Data
from Standard.Database import all
@ -24,7 +22,7 @@ spec prefix connection pending=Nothing =
tables_to_clean.append name
table
t1 = upload "T1" (Materialized_Table.new [["a", [1, 4]], ["b", [2, 5]], ["c", [3, 6]]])
t1 = upload "T1" (Table.new [["a", [1, 4]], ["b", [2, 5]], ["c", [3, 6]]])
Test.group prefix+"Basic Table Access" pending=pending <|
Test.specify "should allow to materialize tables and columns into local memory" <|
df = t1.read
@ -56,17 +54,17 @@ spec prefix connection pending=Nothing =
ix2.name . should_equal 'a'
ix2.to_vector . should_equal [1, 4]
Test.specify "should work correctly when there are no columns" <|
empty = t1.select_columns (By_Name [])
empty = t1.select_columns []
empty.read.column_count . should_equal 0
empty.read.row_count . should_equal empty.row_count
Test.specify "should handle bigger result sets" <|
n = 1000
original = Materialized_Table.new [["a", Vector.new n ix->ix], ["b", Vector.new n ix-> ix * 3.1415926], ["c", Vector.new n ix-> ix.to_text]]
original = Table.new [["a", Vector.new n ix->ix], ["b", Vector.new n ix-> ix * 3.1415926], ["c", Vector.new n ix-> ix.to_text]]
table = upload "Big" original
table.read.row_count . should_equal n
Test.group prefix+"Mapping Operations" pending=pending <|
t2 = upload "T2" <| Materialized_Table.new [["x", [1, 4, 5, Nothing]], ["y", [2, 3, 5, Nothing]], ["b", [False, False, True, Nothing]]]
t2 = upload "T2" <| Table.new [["x", [1, 4, 5, Nothing]], ["y", [2, 3, 5, Nothing]], ["b", [False, False, True, Nothing]]]
x = t2.at "x"
y = t2.at "y"
b = t2.at "b"
@ -98,7 +96,7 @@ spec prefix connection pending=Nothing =
x.is_missing.to_vector . should_equal [False, False, False, True]
(x == Nothing).to_vector . should_equal [Nothing, Nothing, Nothing, Nothing]
t3 = upload "T3" <| Materialized_Table.new [["s1", ["foobar", "bar", "baz", Nothing]], ["s2", ["foo", "ar", "a", Nothing]]]
t3 = upload "T3" <| Table.new [["s1", ["foobar", "bar", "baz", Nothing]], ["s2", ["foo", "ar", "a", Nothing]]]
s1 = t3.at "s1"
s2 = t3.at "s2"
Test.specify "should handle Text operations" <|
@ -126,8 +124,8 @@ spec prefix connection pending=Nothing =
t2.at "c" . to_vector . should_equal [3]
Test.group prefix+"Joining Tables" pending=pending <|
a = upload "TA" <| Materialized_Table.new [["x", [0, 1, 7, 3, 6]], ["y", ["foo", "bar", "baz", "spam", "eggs"]]]
b = upload "TB" <| Materialized_Table.new [["w", [6, 3, 5, 5, 3, 3]], ["z", ["foo", "foo", "bar", "spam", "bar", "eggs"]]]
a = upload "TA" <| Table.new [["x", [0, 1, 7, 3, 6]], ["y", ["foo", "bar", "baz", "spam", "eggs"]]]
b = upload "TB" <| Table.new [["w", [6, 3, 5, 5, 3, 3]], ["z", ["foo", "foo", "bar", "spam", "bar", "eggs"]]]
## The tests below use `sort`, because the SQL backend is not guaranteed
to return the rows in any particular order. This is the `sort` from
@ -162,20 +160,20 @@ spec prefix connection pending=Nothing =
r_2.columns.map .name . should_equal ['y_old', 'y_new']
Test.specify "should correctly handle multi-joins" <|
ta = upload "M_TA" <| Materialized_Table.new [["id", [0, 1]], ["name", ["Foo", "Hmm"]]]
tb = upload "M_TB" <| Materialized_Table.new [["id", [2, 0]], ["name", ["Bar", "Hmm"]]]
tc = upload "M_TC" <| Materialized_Table.new [["id_a", [0, 1]], ["id_b", [2, 0]]]
ta = upload "M_TA" <| Table.new [["id", [0, 1]], ["name", ["Foo", "Hmm"]]]
tb = upload "M_TB" <| Table.new [["id", [2, 0]], ["name", ["Bar", "Hmm"]]]
tc = upload "M_TC" <| Table.new [["id_a", [0, 1]], ["id_b", [2, 0]]]
ta_2 = ta.set_index "id"
tb_2 = tb.set_index "id"
res = (tc.join ta_2 on="id_a") . join tb_2 on="id_b" left_suffix="_a" right_suffix="_b"
sel = res.select_columns (By_Name ["name_a", "name_b"])
sel = res.select_columns (Column_Selector.By_Name ["name_a", "name_b"])
df = sel.read . order_by (Sort_Column_Selector.By_Name [Sort_Column.Name "name_a"])
df . at "name_a" . to_vector . should_equal ["Foo", "Hmm"]
df . at "name_b" . to_vector . should_equal ["Bar", "Hmm"]
Test.group prefix+"Missing Values" pending=pending <|
t4 = upload "T4" <|
Materialized_Table.new [["a", [0, 1, Nothing, 42, Nothing]], ["b", [True, Nothing, True, False, Nothing]], ["c", ["", "foo", "bar", Nothing, Nothing]]]
Table.new [["a", [0, 1, Nothing, 42, Nothing]], ["b", [True, Nothing, True, False, Nothing]], ["c", ["", "foo", "bar", Nothing, Nothing]]]
Test.specify "fill_missing should replace nulls" <|
t4.at 'a' . fill_missing 10 . to_vector . should_equal [0, 1, 10, 42, 10]
t4.at 'b' . fill_missing False . to_vector . should_equal [True, False, True, False, False]
@ -196,7 +194,7 @@ spec prefix connection pending=Nothing =
Test.specify "drop_missing_columns should drop columns that contain at least one missing row in a Table" <|
t5 = upload "T5" <|
Materialized_Table.new [["a", [1, 2, 3]], ["b", [True, False, Nothing]], ["c", ["foo", Nothing, "aaa"]]]
Table.new [["a", [1, 2, 3]], ["b", [True, False, Nothing]], ["c", ["foo", Nothing, "aaa"]]]
r = t5.drop_missing_columns
r.columns.map .name . should_equal ["a"]
@ -209,7 +207,7 @@ spec prefix connection pending=Nothing =
Test.group prefix+"Column-wide statistics" pending=pending <|
Test.specify 'should allow computing basic column-wide stats' <|
t7 = upload "T7" <|
Materialized_Table.new [['price', [0.4, 3.5, Nothing, 6.7, Nothing, 97, Nothing]]]
Table.new [['price', [0.4, 3.5, Nothing, 6.7, Nothing, 97, Nothing]]]
price = t7.at 'price'
price.sum.should_equal 107.6 epsilon=eps
price.min.should_equal 0.4 epsilon=eps
@ -218,7 +216,7 @@ spec prefix connection pending=Nothing =
Test.group prefix+"Sorting" pending=pending <|
df = upload "clothes" <|
Materialized_Table.new [["id", [1,2,3,4,5,6]], ["name", ["shoes","trousers","dress","skirt","blouse","t-shirt"]], ["quantity", [20,10,20,10,30,30]], ["rating", [3.0,Nothing,7.3,3.0,2.2,Nothing]], ["price", [37.2,42.1,64.1,87.4,13.5,64.2]]]
Table.new [["id", [1,2,3,4,5,6]], ["name", ["shoes","trousers","dress","skirt","blouse","t-shirt"]], ["quantity", [20,10,20,10,30,30]], ["rating", [3.0,Nothing,7.3,3.0,2.2,Nothing]], ["price", [37.2,42.1,64.1,87.4,13.5,64.2]]]
Test.specify "should allow sorting by a single column name" <|
r_1 = df.order_by (Sort_Column_Selector.By_Name [Sort_Column.Name 'quantity'])
@ -251,7 +249,7 @@ spec prefix connection pending=Nothing =
bools = [False, False, True, True, False]
texts = ["foo", "foo", "bar", "baz", "spam"]
df = upload "T8" <|
Materialized_Table.new [["ord", [0,3,2,4,1]], ["ints", ints], ["reals", reals], ["bools", bools], ["texts", texts]]
Table.new [["ord", [0,3,2,4,1]], ["ints", ints], ["reals", reals], ["bools", bools], ["texts", texts]]
r = df.order_by (Sort_Column_Selector.By_Name [Sort_Column.Name 'ord'])
r.at 'ints' . to_vector . should_equal [1, 5, 3, 2, 4]
@ -277,7 +275,7 @@ spec prefix connection pending=Nothing =
Test.group prefix+"Index" pending=pending <|
t0 = upload "Tix" <|
Materialized_Table.new [["ix", [1,2,3]], ["c1", [4,5,6]]]
Table.new [["ix", [1,2,3]], ["c1", [4,5,6]]]
t = t0.set_index 'ix'
Test.specify "should be accessible by `at` like other columns" <|
t.at 'ix' . to_vector . should_equal t.index.to_vector
@ -310,7 +308,7 @@ spec prefix connection pending=Nothing =
insert ["zzzz", 0, 0]
insert ["zzzz", Nothing, Nothing]
t = upload "T9" <|
Materialized_Table.new [["name", builders.at 0 . to_vector], ["price", builders.at 1 . to_vector], ["quantity", builders.at 2 . to_vector]]
Table.new [["name", builders.at 0 . to_vector], ["price", builders.at 1 . to_vector], ["quantity", builders.at 2 . to_vector]]
## A helper which makes sure that the groups in a materialized
(InMemory) table are ordered according to a specified column or list

View File

@ -1,18 +1,14 @@
from Standard.Base import all
from Standard.Database import SQL_Query, Raw_SQL, Table_Name
import Standard.Table.Data.Table as Materialized_Table
from Standard.Database import SQL_Query, Raw_SQL, Table_Name
import Standard.Database.Data.Table as Database_Table
from Standard.Database.Data.SQL import Statement, SQL_Type
import Standard.Database.Internal.IR
# TODO Dubious constructor export
from project.Database.Helpers.Fake_Test_Connection.Fake_Test_Connection import all
from project.Database.Helpers.Fake_Test_Connection.Fake_Test_Connection export all
type Fake_Test_Connection
# type Fake_Test_Connection_Data (tables : Map Text (Vector [Text, SQL_Type])) (dialect : Text)
Fake_Test_Connection_Data tables dialect
# type Fake_Test_Connection.Value (tables : Map Text (Vector [Text, SQL_Type])) (dialect : Text)
Value tables dialect
## Set up a query returning a Table object, which can be used to work with data within the database or load it into memory.
@ -36,7 +32,7 @@ type Fake_Test_Connection
If supplied as `Text`, the name is checked against the `tables` list to determine if it is a table or a query.
- alias: optionally specify a friendly alias for the query.
- limit: the maximum number of rows to return (default 1000).
read : Text | SQL_Query -> Text -> Integer | Nothing -> Table
read : Text | SQL_Query -> Text -> Integer | Nothing -> Materialized_Table.Table
read self _ _="" _=Nothing =
Error.throw "Materialization not supported on fake connection."
@ -51,4 +47,4 @@ type Fake_Test_Connection
## PRIVATE
make dialect tables =
Fake_Test_Connection_Data tables dialect
Fake_Test_Connection.Value tables dialect

View File

@ -4,8 +4,8 @@ import Standard.Base.System.Platform
import Standard.Base.System.Process
from Standard.Base.System.Process.Exit_Code import Exit_Success
import Standard.Table as Materialized_Table
from Standard.Table.Data.Aggregate_Column import all hiding First
from Standard.Table import Table
from Standard.Table.Data.Aggregate_Column.Aggregate_Column import all hiding First
import Standard.Database
from Standard.Database import all
@ -160,7 +160,7 @@ run_tests connection db_name pending=Nothing =
name_counter . put ix+1
name = Name_Generator.random_name "table_"+ix.to_text
in_mem_table = Materialized_Table.new columns
in_mem_table = Table.new columns
case connection.upload_table name in_mem_table of
table ->
tables.append name
@ -173,10 +173,10 @@ run_tests connection db_name pending=Nothing =
Common_Spec.spec prefix connection pending=pending
postgres_specific_spec connection db_name pending=pending
common_selection = Common_Table_Spec.Test_Selection_Data supports_case_sensitive_columns=True order_by_unicode_normalization_by_default=True take_drop=False allows_mixed_type_comparisons=False
common_selection = Common_Table_Spec.Test_Selection.Config supports_case_sensitive_columns=True order_by_unicode_normalization_by_default=True take_drop=False allows_mixed_type_comparisons=False
Common_Table_Spec.spec prefix table_builder test_selection=common_selection pending=pending
selection = Aggregate_Spec.Test_Selection_Data first_last_row_order=False aggregation_problems=False date_support=False
selection = Aggregate_Spec.Test_Selection.Config first_last_row_order=False aggregation_problems=False date_support=False
agg_in_memory_table = (enso_project.data / "data.csv") . read
agg_table = connection.upload_table (Name_Generator.random_name "Agg1") agg_in_memory_table
tables.append agg_table.name

View File

@ -1,7 +1,7 @@
from Standard.Base import all
import Standard.Base.Runtime.Ref
import Standard.Table as Materialized_Table
from Standard.Table import Table
import Standard.Database
from Standard.Database import all
@ -42,7 +42,7 @@ run_tests connection pending=Nothing =
name_counter . put ix+1
name = Name_Generator.random_name "table_"+ix.to_text
in_mem_table = Materialized_Table.new columns
in_mem_table = Table.new columns
case connection.upload_table name in_mem_table of
table ->
tables.append name
@ -55,10 +55,10 @@ run_tests connection pending=Nothing =
Common_Spec.spec prefix connection pending=pending
redshift_specific_spec connection pending=pending
common_selection = Common_Table_Spec.Test_Selection_Data supports_case_sensitive_columns=False order_by=False take_drop=False
common_selection = Common_Table_Spec.Test_Selection.Config supports_case_sensitive_columns=False order_by=False take_drop=False
Common_Table_Spec.spec prefix table_builder test_selection=common_selection pending=pending
selection = Aggregate_Spec.Test_Selection_Data text_concat=False text_shortest_longest=False first_last=False first_last_row_order=False multi_distinct=False aggregation_problems=False date_support=False
selection = Aggregate_Spec.Test_Selection.Config text_concat=False text_shortest_longest=False first_last=False first_last_row_order=False multi_distinct=False aggregation_problems=False date_support=False
agg_in_memory_table = (enso_project.data / "data.csv") . read
agg_table = connection.upload_table (Name_Generator.random_name "Agg1") agg_in_memory_table
tables.append agg_table.name

View File

@ -1,7 +1,7 @@
from Standard.Base import all
import Standard.Base.Runtime.Ref
import Standard.Table as Materialized_Table
from Standard.Table import Table
import Standard.Database
from Standard.Database import all
@ -104,13 +104,13 @@ sqlite_spec connection prefix =
name_counter . put ix+1
name = Name_Generator.random_name "table_"+ix.to_text
in_mem_table = Materialized_Table.new columns
in_mem_table = Table.new columns
connection.upload_table name in_mem_table
materialize = .read
Common_Spec.spec prefix connection
sqlite_specific_spec connection
common_selection = Common_Table_Spec.Test_Selection_Data supports_case_sensitive_columns=False order_by=True natural_ordering=False case_insensitive_ordering=True case_insensitive_ascii_only=True take_drop=False
common_selection = Common_Table_Spec.Test_Selection.Config supports_case_sensitive_columns=False order_by=True natural_ordering=False case_insensitive_ordering=True case_insensitive_ascii_only=True take_drop=False
Common_Table_Spec.spec prefix table_builder test_selection=common_selection
## For now `advanced_stats`, `first_last`, `text_shortest_longest` and
@ -121,7 +121,7 @@ sqlite_spec connection prefix =
- creating complex nested queries using NTILE to compute the stats,
- compiling SQLite library on our own and adding native extensions for
the missing statistics.
selection = Aggregate_Spec.Test_Selection_Data advanced_stats=False text_shortest_longest=False first_last=False first_last_row_order=False multi_distinct=False aggregation_problems=False nan=False date_support=False
selection = Aggregate_Spec.Test_Selection.Config advanced_stats=False text_shortest_longest=False first_last=False first_last_row_order=False multi_distinct=False aggregation_problems=False nan=False date_support=False
agg_in_memory_table = (enso_project.data / "data.csv") . read
agg_table = connection.upload_table (Name_Generator.random_name "Agg1") agg_in_memory_table
empty_agg_table = connection.upload_table (Name_Generator.random_name "Agg_Empty") (agg_in_memory_table.take (First 0))

View File

@ -1,7 +1,6 @@
from Standard.Base import all
import Standard.Table
from Standard.Table import Column, Data_Formatter_Data, Quote_Style, Delimited
from Standard.Table import Table, Column, Data_Formatter, Quote_Style, Delimited
from Standard.Table.Errors import all
import Standard.Test
@ -130,7 +129,7 @@ spec =
text = lines.join '\n'
text.write file
format = Delimited ',' headers=False value_formatter=(Data_Formatter_Data trim_values=False)
format = Delimited ',' headers=False value_formatter=(Data_Formatter.Value trim_values=False)
reference_table = Table.new [["Column_1", ["a", "d", "1"]], ["Column_2", ["b", "e", "2"]], ["Column_3", ["c", "f", "3"]]]
collapsed_table = Table.new <|
@ -326,7 +325,7 @@ spec =
t.at "QuotedNumbers" . to_vector . should_equal ["1", "2", Nothing, "34"]
t.at "Mixed Types" . to_vector . should_equal ["33", Nothing, "45", "True"]
t2 = (enso_project.data / "data_small.csv") . read (Delimited "," headers=True value_formatter=(Data_Formatter_Data allow_leading_zeros=True))
t2 = (enso_project.data / "data_small.csv") . read (Delimited "," headers=True value_formatter=(Data_Formatter.Value allow_leading_zeros=True))
t2.at "Leading0s" . to_vector . should_equal [1, 2, 123, Nothing]
Test.specify "should be able to detect types automatically" <|
@ -345,14 +344,14 @@ spec =
a,b,c
1,2,3
4,5,6
t1 = Table.Table.from text1 (format = Delimited ",")
t1 = Table.from text1 (format = Delimited ",")
t1.columns.map .name . should_equal ["a", "b", "c"]
t1.at "a" . to_vector . should_equal [1, 4]
t1.at "b" . to_vector . should_equal [2, 5]
t1.at "c" . to_vector . should_equal [3, 6]
text2 = 'a\tb\n1\t2\n3\t4'
t2 = Table.Table.from text2
t2 = Table.from text2
t2.columns.map .name . should_equal ["a", "b"]
t2.at "a" . to_vector . should_equal [1, 3]
t2.at "b" . to_vector . should_equal [2, 4]
@ -385,7 +384,7 @@ spec =
Delimited ',' . with_parsing . should_equal (Delimited ',')
Delimited ',' . without_parsing . should_equal (Delimited ',' value_formatter=Nothing)
custom_formatter = Data_Formatter_Data true_values=["A", "B", "C"] false_values=["D", "E", "F"]
custom_formatter = Data_Formatter.Value true_values=["A", "B", "C"] false_values=["D", "E", "F"]
Delimited ',' . with_parsing custom_formatter . should_equal (Delimited ',' value_formatter=custom_formatter)
Delimited ',' row_limit=456 . without_parsing . should_equal (Delimited ',' value_formatter=Nothing row_limit=456)

View File

@ -2,23 +2,16 @@ from Standard.Base import all
import Standard.Base.System
from Standard.Base.Error.Problem_Behavior import all
import Standard.Table
from Standard.Table import Column, Data_Formatter, Data_Formatter_Data, Quote_Style, Column_Name_Mapping, Match_Columns, Delimited
from Standard.Table import Table, Column, Data_Formatter, Quote_Style, Column_Name_Mapping, Match_Columns, Delimited
from Standard.Table.Errors import all
from Standard.Table.Data.Column_Selector import By_Name
from Standard.Table.Errors import Column_Count_Mismatch_Data, Column_Name_Mismatch_Data
import Standard.Test
import Standard.Test.Problems
from project.Util import all
# TODO Dubious constructor export
from project.Delimited_Write_Spec.My_Type import all
from project.Delimited_Write_Spec.My_Type export all
type My_Type
My_Type_Data x
Value x
to_text : Text
to_text self = "[[[My Type :: " + self.x.to_text + "]]]"
@ -32,7 +25,7 @@ spec =
line_ending_pairs = [[Line_Ending_Style.Unix, '\n'], [Line_Ending_Style.Windows, '\r\n'], [Line_Ending_Style.Mac_Legacy, '\r']]
Test.group "Delimited File Writing" <|
Test.specify "should correctly write a simple table" <|
table = Table.new [["A", [1,2,3]], ["B", [1.0,1.5,2.2]], ["C", ["x","y","z"]], ["D", ["a", 2, My_Type_Data 10]]]
table = Table.new [["A", [1,2,3]], ["B", [1.0,1.5,2.2]], ["C", ["x","y","z"]], ["D", ["a", 2, My_Type.Value 10]]]
file = (enso_project.data / "transient" / "written.csv")
file.delete_if_exists
table.write file on_problems=Report_Error . should_succeed
@ -67,7 +60,7 @@ spec =
file.delete
Test.specify 'should quote values that contain the delimiter or quotes, in the [,""] variant' <|
data_formatter = Data_Formatter_Data decimal_point=","
data_formatter = Data_Formatter.Value decimal_point=","
table = Table.new [['The Column "Name"', ["foo","'bar'",'"baz"', 'one, two, three']], ["Hello, Column?", [1.0, 1000000.5, 2.2, -1.5]]]
file = (enso_project.data / "transient" / "quotes1.csv")
file.delete_if_exists
@ -83,7 +76,7 @@ spec =
file.delete
Test.specify 'should quote values that contain the delimiter or quotes, in the [;\\\"] variant' <|
data_formatter = Data_Formatter_Data thousand_separator="'"
data_formatter = Data_Formatter.Value thousand_separator="'"
table = Table.new [['"A"', ["foo",'!"baz" ', 'one, two, three', "a;b; c ", "a\b"]], ["B", [1000000.5, 1000.0, 0.0, -1.2, Nothing]]]
file = (enso_project.data / "transient" / "quotes2.csv")
file.delete_if_exists
@ -100,7 +93,7 @@ spec =
file.delete
Test.specify "should quote values that contain the delimiter or quotes, in the [\t''] variant" <|
data_formatter = Data_Formatter_Data thousand_separator="'"
data_formatter = Data_Formatter.Value thousand_separator="'"
table = Table.new [['"A"', [Nothing,"The 'thing'.", 'one, "two", three', 'a\tb']], ["B\C", [1000000.5, 1000.0, Nothing, -1.2]]]
file = (enso_project.data / "transient" / "quotes3.csv")
file.delete_if_exists
@ -151,7 +144,7 @@ spec =
file.delete
Test.specify 'should not quote values if quoting is disabled' <|
format = Delimited "," value_formatter=(Data_Formatter_Data decimal_point=",") . without_quotes
format = Delimited "," value_formatter=(Data_Formatter.Value decimal_point=",") . without_quotes
table = Table.new [['The Column "Name"', ["foo","'bar'",'"baz"', 'one, two, three']], ["Hello, Column?", [1.0, 1000000.5, 2.2, -1.5]]]
file = (enso_project.data / "transient" / "quote_disabled.csv")
file.delete_if_exists
@ -167,8 +160,8 @@ spec =
file.delete
Test.specify 'should allow to always quote text and custom values, but for non-text primitves only if absolutely necessary' <|
format = Delimited "," value_formatter=(Data_Formatter_Data thousand_separator='"' date_formats=["E, d MMM y"]) . with_quotes always_quote=True quote_escape='\\'
table = Table.new [['The Column "Name"', ["foo","'bar'",'"baz"', 'one, two, three']], ["B", [1.0, 1000000.5, 2.2, -1.5]], ["C", ["foo", My_Type_Data 44, (Date.new 2022 06 21), 42]], ["D", [1,2,3,4000]], ["E", [Nothing, (Time_Of_Day.new 13 55), Nothing, Nothing]]]
format = Delimited "," value_formatter=(Data_Formatter.Value thousand_separator='"' date_formats=["E, d MMM y"]) . with_quotes always_quote=True quote_escape='\\'
table = Table.new [['The Column "Name"', ["foo","'bar'",'"baz"', 'one, two, three']], ["B", [1.0, 1000000.5, 2.2, -1.5]], ["C", ["foo", My_Type.Value 44, (Date.new 2022 06 21), 42]], ["D", [1,2,3,4000]], ["E", [Nothing, (Time_Of_Day.new 13 55), Nothing, Nothing]]]
file = (enso_project.data / "transient" / "quote_always.csv")
file.delete_if_exists
table.write file format on_problems=Report_Error . should_succeed

View File

@ -3,10 +3,8 @@ from Standard.Base import all
from Standard.Base.System.File import File_Already_Exists_Error
from Standard.Base.Error.Problem_Behavior import all
import Standard.Table
from Standard.Table import Match_Columns, Column_Name_Mapping, Excel, Excel_Range, Data_Formatter_Data, Sheet_Names, Range_Names, Worksheet, Cell_Range, Delimited
from Standard.Table import Table, Match_Columns, Column_Name_Mapping, Excel, Excel_Range, Data_Formatter, Sheet_Names, Range_Names, Worksheet, Cell_Range, Delimited, Column_Selector
from Standard.Table.Data.Column_Selector import By_Index
from Standard.Table.Errors import Invalid_Output_Column_Names_Data, Duplicate_Output_Column_Names_Data, Invalid_Location_Data, Range_Exceeded_Data, Existing_Data_Data, Column_Count_Mismatch_Data, Column_Name_Mismatch_Data
import Standard.Test
@ -71,12 +69,12 @@ spec_write suffix test_sheet_name =
for these tests. This should ideally be re-enabled with the
completion of the following story:
https://www.pivotaltracker.com/story/show/181755990
no_dates = Delimited "," value_formatter=(Data_Formatter_Data date_formats=[] time_formats=[] datetime_formats=[])
no_dates = Delimited "," value_formatter=(Data_Formatter.Value date_formats=[] time_formats=[] datetime_formats=[])
out = enso_project.data / ('out.' + suffix)
out_bak = enso_project.data / ('out.' + suffix + '.bak')
table = enso_project.data/'varied_column.csv' . read (format = no_dates)
clothes = enso_project.data/'clothes.csv' . read (format = no_dates)
sub_clothes = clothes.select_columns (By_Index [0, 1])
sub_clothes = clothes.select_columns (Column_Selector.By_Index [0, 1])
Test.specify 'should write a table to non-existent file as a new sheet with headers' <|
out.delete_if_exists
@ -190,7 +188,7 @@ spec_write suffix test_sheet_name =
extra_another = Table.new [['AA', ['d', 'e']], ['BB',[4, 5]], ['CC',[True, False]], ['DD', ['2022-01-20', '2022-01-21']]]
expected = Table.new [['AA', ['a','b','c','d', 'e']], ['BB',[1,2,3,4,5]], ['CC',[True, False, False, True, False]]]
extra_another.write out (Excel (Worksheet "Another")) on_existing_file=Existing_File_Behavior.Append on_problems=Report_Error . should_succeed
written = out.read (Excel (Worksheet "Another")) . select_columns (By_Index [0, 1, 2])
written = out.read (Excel (Worksheet "Another")) . select_columns (Column_Selector.By_Index [0, 1, 2])
written.should_equal expected
out.delete_if_exists
@ -200,7 +198,7 @@ spec_write suffix test_sheet_name =
extra_another = Table.new [['A', ['d', 'e']], ['B',[4, 5]], ['C',[True, False]], ['D', ['2022-01-20', '2022-01-21']]]
expected = Table.new [['AA', ['a','b','c','d', 'e']], ['BB',[1,2,3,4,5]], ['CC',[True, False, False, True, False]]]
extra_another.write out (Excel (Worksheet "Another")) on_existing_file=Existing_File_Behavior.Append match_columns=Match_Columns.By_Position on_problems=Report_Error . should_succeed
written = out.read (Excel (Worksheet "Another")) . select_columns (By_Index [0, 1, 2])
written = out.read (Excel (Worksheet "Another")) . select_columns (Column_Selector.By_Index [0, 1, 2])
written.should_equal expected
out.delete_if_exists
@ -210,7 +208,7 @@ spec_write suffix test_sheet_name =
extra_another = Table.new [['CC',[True, False]], ['BB',[4, 5]], ['AA', ['d', 'e']], ['DD', ['2022-01-20', '2022-01-21']]]
expected = Table.new [['AA', ['a','b','c','d', 'e']], ['BB',[1,2,3,4,5]], ['CC',[True, False, False, True, False]]]
extra_another.write out (Excel (Worksheet "Another")) on_existing_file=Existing_File_Behavior.Append on_problems=Report_Error . should_succeed
written = out.read (Excel (Worksheet "Another")) . select_columns (By_Index [0, 1, 2])
written = out.read (Excel (Worksheet "Another")) . select_columns (Column_Selector.By_Index [0, 1, 2])
written.should_equal expected
out.delete_if_exists
@ -220,7 +218,7 @@ spec_write suffix test_sheet_name =
extra_another = Table.new [['AA', ['d', 'e']], ['BB',[4, 5]], ['CC',[True, False]], ['DD', ['2022-01-20', '2022-01-21']]]
expected = Table.new [['AA', ['a','b','c','d', 'e']], ['BB',[1,2,3,4,5]], ['CC',[True, False, False, True, False]]]
extra_another.write out (Excel (Cell_Range "Another!A1")) on_existing_file=Existing_File_Behavior.Append on_problems=Report_Error . should_succeed
written = out.read (Excel (Worksheet "Another")) . select_columns (By_Index [0, 1, 2])
written = out.read (Excel (Worksheet "Another")) . select_columns (Column_Selector.By_Index [0, 1, 2])
written.should_equal expected
out.delete_if_exists
@ -230,7 +228,7 @@ spec_write suffix test_sheet_name =
extra_another = Table.new [['A', ['d', 'e']], ['B',[4, 5]], ['C',[True, False]], ['D', ['2022-01-20', '2022-01-21']]]
expected = Table.new [['AA', ['a','b','c','d', 'e']], ['BB',[1,2,3,4,5]], ['CC',[True, False, False, True, False]]]
extra_another.write out (Excel (Cell_Range "Another!A1")) on_existing_file=Existing_File_Behavior.Append match_columns=Match_Columns.By_Position on_problems=Report_Error . should_succeed
written = out.read (Excel (Worksheet "Another")) . select_columns (By_Index [0, 1, 2])
written = out.read (Excel (Worksheet "Another")) . select_columns (Column_Selector.By_Index [0, 1, 2])
written.should_equal expected
out.delete_if_exists
@ -240,7 +238,7 @@ spec_write suffix test_sheet_name =
extra_another = Table.new [['CC',[True, False]], ['BB',[4, 5]], ['AA', ['d', 'e']], ['DD', ['2022-01-20', '2022-01-21']]]
expected = Table.new [['AA', ['a','b','c','d', 'e']], ['BB',[1,2,3,4,5]], ['CC',[True, False, False, True, False]]]
extra_another.write out (Excel (Cell_Range "Another!A1")) on_existing_file=Existing_File_Behavior.Append on_problems=Report_Error . should_succeed
written = out.read (Excel (Worksheet "Another")) . select_columns (By_Index [0, 1, 2])
written = out.read (Excel (Worksheet "Another")) . select_columns (Column_Selector.By_Index [0, 1, 2])
written.should_equal expected
out.delete_if_exists
@ -250,7 +248,7 @@ spec_write suffix test_sheet_name =
extra_another = Table.new [['AA', ['d', 'e']], ['BB', [4, 5]], ['CC', [True, False]], ['DD', ['2022-01-20', '2022-01-21']]]
expected = Table.new [['AA', ['a', 'b', 'c', 'd', 'e']], ['BB', [1, 2, 3, 4, 5]], ['CC', [True, False, False, True, False]]]
extra_another.write out (Excel (Cell_Range "Another!A1:D6")) on_existing_file=Existing_File_Behavior.Append on_problems=Report_Error . should_succeed
written = out.read (Excel (Worksheet "Another")) . select_columns (By_Index [0, 1, 2])
written = out.read (Excel (Worksheet "Another")) . select_columns (Column_Selector.By_Index [0, 1, 2])
written.should_equal expected
out.delete_if_exists
@ -260,7 +258,7 @@ spec_write suffix test_sheet_name =
extra_another = Table.new [['A', ['d', 'e']], ['B',[4, 5]], ['C',[True, False]], ['D', ['2022-01-20', '2022-01-21']]]
expected = Table.new [['AA', ['a','b','c','d', 'e']], ['BB',[1,2,3,4,5]], ['CC',[True, False, False, True, False]]]
extra_another.write out (Excel (Cell_Range "Another!A1:D6")) on_existing_file=Existing_File_Behavior.Append match_columns=Match_Columns.By_Position on_problems=Report_Error . should_succeed
written = out.read (Excel (Worksheet "Another")) . select_columns (By_Index [0, 1, 2])
written = out.read (Excel (Worksheet "Another")) . select_columns (Column_Selector.By_Index [0, 1, 2])
written.should_equal expected
out.delete_if_exists
@ -270,7 +268,7 @@ spec_write suffix test_sheet_name =
extra_another = Table.new [['AA', ['d', 'e']], ['BB',[4, 5]], ['CC',[True, False]], ['DD', ['2022-01-20', '2022-01-21']]]
expected = Table.new [['AA', ['f', 'g', 'h', 'd', 'e']], ['BB',[1, 2, 3, 4, 5]], ['CC',[True, False, False, True, False]]]
extra_another.write out (Excel (Cell_Range "Random!K9")) on_existing_file=Existing_File_Behavior.Append on_problems=Report_Error . should_succeed
written = out.read (Excel (Cell_Range "Random!K9")) . select_columns (By_Index [0, 1, 2])
written = out.read (Excel (Cell_Range "Random!K9")) . select_columns (Column_Selector.By_Index [0, 1, 2])
written.should_equal expected
out.delete_if_exists
@ -280,7 +278,7 @@ spec_write suffix test_sheet_name =
extra_another = Table.new [['AA', ['d', 'e']], ['BB',[4, 5]], ['AA_1',[True, False]], ['BB_1', ['2022-01-20', '2022-01-21']]]
expected = Table.new [['AA', ['f', 'g', 'h', 'd', 'e']], ['BB',[1, 2, 3, 4, 5]], ['AA_1',[True, False, False, True, False]]]
extra_another.write out (Excel (Cell_Range "Random!S3")) on_existing_file=Existing_File_Behavior.Append on_problems=Report_Error . should_succeed
written = out.read (Excel (Cell_Range "Random!S3")) . select_columns (By_Index [0, 1, 2])
written = out.read (Excel (Cell_Range "Random!S3")) . select_columns (Column_Selector.By_Index [0, 1, 2])
written.should_equal expected
out.delete_if_exists
@ -290,7 +288,7 @@ spec_write suffix test_sheet_name =
extra_another = Table.new [['A', ['d', 'e']], ['B',[4, 5]], ['C',[True, False]], ['D', ['2022-01-20', '2022-01-21']]]
expected = Table.new [['AA', ['f', 'g', 'h', 'd', 'e']], ['BB',[1, 2, 3, 4, 5]], ['CC',[True, False, False, True, False]]]
extra_another.write out (Excel (Cell_Range "Random!K9")) on_existing_file=Existing_File_Behavior.Append match_columns=Match_Columns.By_Position on_problems=Report_Error . should_succeed
written = out.read (Excel (Cell_Range "Random!K9")) . select_columns (By_Index [0, 1, 2])
written = out.read (Excel (Cell_Range "Random!K9")) . select_columns (Column_Selector.By_Index [0, 1, 2])
written.should_equal expected
out.delete_if_exists
@ -300,7 +298,7 @@ spec_write suffix test_sheet_name =
extra_another = Table.new [['CC',[True, False]], ['BB',[4, 5]], ['AA', ['d', 'e']], ['DD', ['2022-01-20', '2022-01-21']]]
expected = Table.new [['AA', ['a','b','c','d', 'e']], ['BB',[1,2,3,4,5]], ['CC',[True, False, False, True, False]]]
extra_another.write out (Excel (Cell_Range "Another!A1:D6")) on_existing_file=Existing_File_Behavior.Append on_problems=Report_Error . should_succeed
written = out.read (Excel (Worksheet "Another")) . select_columns (By_Index [0, 1, 2])
written = out.read (Excel (Worksheet "Another")) . select_columns (Column_Selector.By_Index [0, 1, 2])
written.should_equal expected
out.delete_if_exists

View File

@ -1,5 +1,5 @@
from Standard.Base import all
import Standard.Table
from Standard.Table import Table
import Standard.Test

View File

@ -1,7 +1,6 @@
from Standard.Base import all
import Standard.Table
from Standard.Table import Data_Formatter
from Standard.Table import Table, Data_Formatter
from Standard.Table.Data.Table import Empty_Error
from Standard.Table.Data.Column_Type_Selection import Column_Type_Selection, Auto
from Standard.Table.Errors import Invalid_Format, Leading_Zeros, Missing_Input_Columns, Column_Indexes_Out_Of_Range, Duplicate_Type_Selector

View File

@ -1,8 +1,7 @@
from Standard.Base import all
import Standard.Table
from Standard.Table import Column, Delimited, Data_Formatter_Data
import Standard.Table.Data.Storage
from Standard.Table import Table, Column, Delimited, Data_Formatter
import Standard.Table.Data.Storage.Storage
import Standard.Test
from project.Util import all
@ -46,7 +45,7 @@ spec =
Test.specify "should serialise dates with format" <|
test_table = Table.new [c_from]
expected_text = 'From\n04.05.1979\n28.11.1990\n02.05.1997\n27.06.2007\n11.05.2010\n13.07.2016\n24.07.2019\n'
data_formatter = Data_Formatter_Data . with_datetime_formats date_formats=["dd.MM.yyyy"]
data_formatter = Data_Formatter.Value.with_datetime_formats date_formats=["dd.MM.yyyy"]
delimited = Text.from test_table format=(Delimited "," value_formatter=data_formatter line_endings=Line_Ending_Style.Unix)
delimited.should_equal expected_text

View File

@ -1,13 +1,11 @@
from Standard.Base import all
from Standard.Base.Error.Problem_Behavior import Report_Error
import Standard.Table
from Standard.Table import Column, Sort_Column, Sort_Column_Selector, Aggregate_Column
from Standard.Table.Data.Aggregate_Column import all hiding First, Last
from Standard.Table import Table, Column, Sort_Column, Column_Selector, Sort_Column_Selector, Aggregate_Column
from Standard.Table.Data.Aggregate_Column.Aggregate_Column import all hiding First, Last
from Standard.Table.Data.Table import Empty_Error
from Standard.Table.Errors import Invalid_Output_Column_Names_Data, Duplicate_Output_Column_Names_Data, No_Input_Columns_Selected, Missing_Input_Columns_Data, No_Such_Column_Error_Data
import Standard.Table.Data.Storage
from Standard.Table.Data.Column_Selector import By_Name
from Standard.Table.Data.Storage import Storage
from Standard.Table.Errors import Floating_Point_Grouping_Data
from Standard.Table.Data.Filter_Condition import Filter_Condition
@ -19,21 +17,17 @@ import Standard.Test.Problems
import project.Common_Table_Spec
from project.Util import all
# TODO Dubious constructor export
from project.Table_Spec.My import all
from project.Table_Spec.My export all
type My
My_Data x y
Data x y
My.== self that = case that of
My_Data x1 y1 -> (self.x + self.y) == (x1 + y1)
== self that = case that of
My.Data x1 y1 -> (self.x + self.y) == (x1 + y1)
_ -> False
My.compare_to self that = self.x+self.y . compare_to that.x+that.y
compare_to self that = self.x+self.y . compare_to that.x+that.y
My.frobnicate self = case self of
My_Data x1 y1 -> My_Data y1 x1
frobnicate self = case self of
My.Data x1 y1 -> My.Data y1 x1
spec =
Test.group "JSON construction" <|
@ -98,7 +92,7 @@ spec =
ints = ["ints", [Nothing, 1, 2, 4]]
doubles = ["doubles", [0.0, 1.5, Nothing, 2.0]]
doubles_and_ints = ["doubles_and_ints", [0, 1.5, Nothing, 2]]
custom_objects = ["custom_objects", [My_Data 1 2, My_Data 3 4, Nothing, Nothing]]
custom_objects = ["custom_objects", [My.Data 1 2, My.Data 3 4, Nothing, Nothing]]
dates = ["dates", [Nothing, Date.new 2000, Date.new 2022 8 20, Date.new 1999 1 1]]
times = ["times", [Time_Of_Day.new 18 00, Time_Of_Day.new 1 2 34, Nothing, Time_Of_Day.new]]
datetimes = ["datetimes", [Date_Time.new 2000, Date_Time.new 1999 1 2 3 4 5, Nothing, Date_Time.new 2022 8 27 11 22 25]]
@ -161,7 +155,7 @@ spec =
col_1 = Column.from_vector 'x' [1, 2, 3]
col_1.to_vector.reduce (+) . should_equal 6
col_2 = Column.from_vector 'y' [My_Data 1 2, My_Data 2 3]
col_2 = Column.from_vector 'y' [My.Data 1 2, My.Data 2 3]
col_2.to_vector.map (my -> my.x + my.y) . should_equal [3, 5]
col_3 = Column.from_vector 'z' [False, True, False]
@ -177,8 +171,8 @@ spec =
c_dec.map (+ 1.5) . to_vector . should_equal [3.4, 3.5, 2.7, 7.1, 3.4]
c_bool = Column.from_vector 'x' [True, False, Nothing, True, False]
c_bool.map (_.to_text) . to_vector . should_equal ["True", "False", Nothing, "True", "False"]
c_any = Column.from_vector 'x' [My_Data 1 6, My_Data 6 3, My_Data 2 5, My_Data 3 4, My_Data 200 300]
c_any.map (_.frobnicate) . to_vector . should_equal [My_Data 6 1, My_Data 3 6, My_Data 5 2, My_Data 4 3, My_Data 300 200]
c_any = Column.from_vector 'x' [My.Data 1 6, My.Data 6 3, My.Data 2 5, My.Data 3 4, My.Data 200 300]
c_any.map (_.frobnicate) . to_vector . should_equal [My.Data 6 1, My.Data 3 6, My.Data 5 2, My.Data 4 3, My.Data 300 200]
Test.specify "should correctly handle storage of results" <|
c_int = Column.from_vector 'year' [2022, 2000, 1999]
@ -214,8 +208,8 @@ spec =
(c_dec == 1.9).to_vector.should_equal [True, False, False, False, True]
c_bool = Column.from_vector 'x' [True, False, Nothing, True, False]
(c_bool == False).to_vector.should_equal [False, True, Nothing, False, True]
c_any = Column.from_vector 'x' [My_Data 1 6, My_Data 6 3, My_Data 2 5, My_Data 3 4, My_Data 200 300]
(c_any == My_Data 7 0).to_vector.should_equal [True, False, True, True, False]
c_any = Column.from_vector 'x' [My.Data 1 6, My.Data 6 3, My.Data 2 5, My.Data 3 4, My.Data 200 300]
(c_any == My.Data 7 0).to_vector.should_equal [True, False, True, True, False]
Test.specify "should switch between maps and zips based on argument type" <|
a = Column.from_vector 'x' [0, 1, 7, 3, 6]
@ -447,7 +441,7 @@ spec =
Test.specify 'should respect defined comparison operations for custom types' <|
c_1 = ['id', [1, 2, 3, 4, 5, 6]]
c_2 = ['val', [My_Data 1 2, My_Data 3 4, My_Data 2 1, My_Data 5 2, My_Data 7 0, My_Data 4 -1]]
c_2 = ['val', [My.Data 1 2, My.Data 3 4, My.Data 2 1, My.Data 5 2, My.Data 7 0, My.Data 4 -1]]
df = Table.new [c_1, c_2]
r = df.order_by (Sort_Column_Selector.By_Name ['val'])
r.at 'id' . to_vector . should_equal [1,3,6,2,4,5]
@ -468,7 +462,7 @@ spec =
dates = [Date.new 2020, Date.new 1999, Date.new 2000 10 3, Date.new 1999 12 31, Date.new 2000 2 7]
times = [Time_Of_Day.new 12, Time_Of_Day.new 1 30 40, Time_Of_Day.new 23 59 59, Time_Of_Day.new 12 30 0, Time_Of_Day.new 10 20 30]
datetimes = [Date_Time.new 2020 1 1 12, Date_Time.new 1999 1 1 1 30 40, Date_Time.new 2000 10 3 23 59 59, Date_Time.new 1999 12 31 12 30 0, Date_Time.new 2000 10 3 10 20 30]
objs = [My_Data 100 2, My_Data 2 3, My_Data 6 7, My_Data 8 9, My_Data 10 30]
objs = [My.Data 100 2, My.Data 2 3, My.Data 6 7, My.Data 8 9, My.Data 10 30]
mixed_dates = [Date.new 1999 1 2, Date_Time.new 1999 1 2 3 40, Date.new 1999 1 2, Date_Time.new 1999 1 2 3 40, Date.new 2000]
df = Table.new [['ord', ord], ['ints', ints], ['reals', reals], ['bools', bools], ['texts', texts], ['objs', objs], ['dates', dates], ['times', times], ['datetimes', datetimes], ['mixed_dates', mixed_dates]]
@ -486,7 +480,7 @@ spec =
r.at 'texts' . to_vector . should_equal ['foo', 'spam', 'bar', 'foo', 'baz']
df.at 'texts' . to_vector . should_equal texts
r.at 'objs' . to_vector . should_equal [My_Data 100 2, My_Data 10 30, My_Data 6 7, My_Data 2 3, My_Data 8 9]
r.at 'objs' . to_vector . should_equal [My.Data 100 2, My.Data 10 30, My.Data 6 7, My.Data 2 3, My.Data 8 9]
df.at 'objs' . to_vector . should_equal objs
r.at 'dates' . to_vector . should_equal [Date.new 2020, Date.new 2000 2 7, Date.new 2000 10 3, Date.new 1999, Date.new 1999 12 31]
@ -512,7 +506,7 @@ spec =
r4.at 'ints' . to_vector . should_equal [2, 4, 5, 3, 1]
r5 = df.order_by (Sort_Column_Selector.By_Name ['objs'])
r5.at 'objs' . to_vector . should_equal [My_Data 2 3, My_Data 6 7, My_Data 8 9, My_Data 10 30, My_Data 100 2]
r5.at 'objs' . to_vector . should_equal [My.Data 2 3, My.Data 6 7, My.Data 8 9, My.Data 10 30, My.Data 100 2]
r5.at 'ints' . to_vector . should_equal [2, 3, 4, 5, 1]
r6 = df.order_by (Sort_Column_Selector.By_Name ['mixed_dates'])
@ -532,15 +526,15 @@ spec =
r_3.to_vector.should_equal [Nothing,Nothing,8,7,4,1]
Test.specify 'should respect defined comparison operations for custom types' <|
c = Column.from_vector 'foo' [My_Data 1 2, My_Data 3 4, My_Data 2 1, My_Data 5 2, My_Data 7 0, My_Data 4 -1]
c = Column.from_vector 'foo' [My.Data 1 2, My.Data 3 4, My.Data 2 1, My.Data 5 2, My.Data 7 0, My.Data 4 -1]
r = c.sort
r.to_vector.should_equal [My_Data 1 2, My_Data 2 1, My_Data 4 -1, My_Data 3 4, My_Data 5 2, My_Data 7 0]
r.to_vector.should_equal [My.Data 1 2, My.Data 2 1, My.Data 4 -1, My.Data 3 4, My.Data 5 2, My.Data 7 0]
Test.specify 'should allow passing a custom comparator' <|
c = Column.from_vector 'foo' [My_Data 1 2, My_Data 2 5, My_Data 3 4, My_Data 6 3, Nothing, My_Data 1 0]
c = Column.from_vector 'foo' [My.Data 1 2, My.Data 2 5, My.Data 3 4, My.Data 6 3, Nothing, My.Data 1 0]
cmp a b = (a.x-a.y).abs . compare_to (b.x-b.y).abs
r = c.sort comparator=cmp
r.to_vector.should_equal [My_Data 1 2, My_Data 3 4, My_Data 1 0, My_Data 2 5, My_Data 6 3, Nothing]
r.to_vector.should_equal [My.Data 1 2, My.Data 3 4, My.Data 1 0, My.Data 2 5, My.Data 6 3, Nothing]
Test.specify 'should handle Unicode characters correctly' <|
c = Column.from_vector 'c' ['z', 'a', 'd', 'f', 's', 'e\u0301', 'ś', 'ą', 's\u0301', 'w', 'b']
@ -677,7 +671,7 @@ spec =
t_3 = Table.new [c_3_1, c_3_2, c_3_3]
t_3.default_visualization.should_equal Visualization.Id.table
selection = Common_Table_Spec.Test_Selection_Data supports_case_sensitive_columns=True order_by=True natural_ordering=True case_insensitive_ordering=True order_by_unicode_normalization_by_default=True
selection = Common_Table_Spec.Test_Selection.Config supports_case_sensitive_columns=True order_by=True natural_ordering=True case_insensitive_ordering=True order_by_unicode_normalization_by_default=True
Common_Table_Spec.spec "[In-Memory] " table_builder=Table.new test_selection=selection
Test.group "Use First Row As Names" <|
@ -729,7 +723,7 @@ spec =
mixed = ["mixed", [1, "a", "a", 1]]
ints = ["ints", [0, 1, 1, 0]]
floats = ["floats", [0.1, 1.0, 2.0, 1.5]]
objects = ["objects", [My_Data 0 1, My_Data 0 1, My_Data 2 2, My_Data 2 2]]
objects = ["objects", [My.Data 0 1, My.Data 0 1, My.Data 2 2, My.Data 2 2]]
table = Table.new [dates, texts, mixed, ints, floats, objects]
t1 = table.aggregate [Group_By "dates", Shortest "texts", Aggregate_Column.First "texts", Aggregate_Column.First "objects", Aggregate_Column.First "ints", Aggregate_Column.Last "mixed"]
@ -770,12 +764,12 @@ spec =
c = ["C", [0.1, 0.2, 0.3, 0.4, 0.5, 0.6]]
t = Table.new [a, b, c]
r1 = t.distinct (By_Name ["A"]) on_problems=Report_Error
r1 = t.distinct (Column_Selector.By_Name ["A"]) on_problems=Report_Error
r1.at "A" . to_vector . should_equal ["a"]
r1.at "B" . to_vector . should_equal [1]
r1.at "C" . to_vector . should_equal [0.1]
r2 = t.distinct (By_Name ["A", "B"]) on_problems=Report_Error
r2 = t.distinct (Column_Selector.By_Name ["A", "B"]) on_problems=Report_Error
r2.at "A" . to_vector . should_equal ["a", "a"]
r2.at "B" . to_vector . should_equal [1, 2]
r2.at "C" . to_vector . should_equal [0.1, 0.3]
@ -794,7 +788,7 @@ spec =
a = ["A", ["a", Nothing, "b", "a", "b", Nothing, "a", "b"]]
b = ["B", [1, 2, 3, 4, 5, 6, 7, 8]]
t = Table.new [a, b]
r = t.distinct (By_Name ["A"]) on_problems=Report_Error
r = t.distinct (Column_Selector.By_Name ["A"]) on_problems=Report_Error
r.at "A" . to_vector . should_equal ["a", Nothing, "b"]
r.at "B" . to_vector . should_equal [1, 2, 3]
@ -806,11 +800,11 @@ spec =
x = ["X", ['A', 'a', 'enso', 'śledź', 'Enso', 'A', 's\u0301ledz\u0301']]
y = ["Y", [1, 2, 3, 4, 5, 6, 7]]
t1 = Table.new [x, y]
d1 = t1.distinct (By_Name ["X"]) on_problems=Report_Error
d1 = t1.distinct (Column_Selector.By_Name ["X"]) on_problems=Report_Error
d1.at "X" . to_vector . should_equal ['A', 'a', 'enso', 'śledź', 'Enso']
d1.at "Y" . to_vector . should_equal [1, 2, 3, 4, 5]
d2 = t1.distinct (By_Name ["X"]) case_sensitivity=Case_Sensitivity.Insensitive on_problems=Report_Error
d2 = t1.distinct (Column_Selector.By_Name ["X"]) case_sensitivity=Case_Sensitivity.Insensitive on_problems=Report_Error
d2.at "X" . to_vector . should_equal ['A', 'enso', 'śledź']
d2.at "Y" . to_vector . should_equal [1, 3, 4]
@ -836,16 +830,16 @@ spec =
t = Table.new [["A", [1, 2, 1, 1]]]
test table = table.should_equal t
action1 = t.distinct (By_Name []) on_problems=_
action1 = t.distinct (Column_Selector.By_Name []) on_problems=_
problems1 = [No_Input_Columns_Selected]
Problems.test_problem_handling action1 problems1 test
action2 = t.distinct (By_Name ["mismatched"]) on_problems=_
action2 = t.distinct (Column_Selector.By_Name ["mismatched"]) on_problems=_
problems2 = [Missing_Input_Columns_Data ["mismatched"], No_Input_Columns_Selected]
Problems.test_problem_handling action2 problems2 test
Test.specify "until hashing is supported, should throw an error when trying to aggregate a custom object" <|
t = Table.new [["X", [My_Data 1 2, My_Data 3 4, My_Data 1 2]]]
t = Table.new [["X", [My.Data 1 2, My.Data 3 4, My.Data 1 2]]]
t.distinct . should_fail_with Illegal_Argument_Error_Data
Test.specify "should group by all columns by default" <|
@ -871,20 +865,20 @@ spec =
t3.at "X" . to_vector . should_equal [5, 5, 1]
Test.specify "by custom object comparisons" <|
t = Table.new [["ix", [1, 2, 3, 4, 5]], ["X", [My_Data 1 2, My_Data 300 400, My_Data 100 200, My_Data 5 6, My_Data 7 8]]]
t1 = t.filter "X" (Filter_Condition.Between (My_Data 10 20) (My_Data 300 400))
t = Table.new [["ix", [1, 2, 3, 4, 5]], ["X", [My.Data 1 2, My.Data 300 400, My.Data 100 200, My.Data 5 6, My.Data 7 8]]]
t1 = t.filter "X" (Filter_Condition.Between (My.Data 10 20) (My.Data 300 400))
t1.at "ix" . to_vector . should_equal [2, 3]
t1.at "X" . to_vector . should_equal [My_Data 300 400, My_Data 100 200]
t.filter "X" (Filter_Condition.Less than=(My_Data 5 6)) . at "X" . to_vector . should_equal [My_Data 1 2]
t.filter "X" (Filter_Condition.Equal_Or_Less than=(My_Data 5 6)) . at "X" . to_vector . should_equal [My_Data 1 2, My_Data 5 6]
t.filter "X" (Filter_Condition.Greater than=(My_Data 5 6)) . at "X" . to_vector . should_equal [My_Data 300 400, My_Data 100 200, My_Data 7 8]
t.filter "X" (Filter_Condition.Equal_Or_Greater than=(My_Data 5 6)) . at "X" . to_vector . should_equal [My_Data 300 400, My_Data 100 200, My_Data 5 6, My_Data 7 8]
t.filter "X" (Filter_Condition.Equal to=(My_Data 2 1)) . at "X" . to_vector . should_equal [My_Data 1 2]
t1.at "X" . to_vector . should_equal [My.Data 300 400, My.Data 100 200]
t.filter "X" (Filter_Condition.Less than=(My.Data 5 6)) . at "X" . to_vector . should_equal [My.Data 1 2]
t.filter "X" (Filter_Condition.Equal_Or_Less than=(My.Data 5 6)) . at "X" . to_vector . should_equal [My.Data 1 2, My.Data 5 6]
t.filter "X" (Filter_Condition.Greater than=(My.Data 5 6)) . at "X" . to_vector . should_equal [My.Data 300 400, My.Data 100 200, My.Data 7 8]
t.filter "X" (Filter_Condition.Equal_Or_Greater than=(My.Data 5 6)) . at "X" . to_vector . should_equal [My.Data 300 400, My.Data 100 200, My.Data 5 6, My.Data 7 8]
t.filter "X" (Filter_Condition.Equal to=(My.Data 2 1)) . at "X" . to_vector . should_equal [My.Data 1 2]
t.filter "X" (Filter_Condition.Equal to=42) . at "X" . to_vector . should_equal []
c = Column.from_vector "Y" [My_Data 2 1, My_Data 400 300, My_Data 101 202, My_Data 10 10, My_Data 15 0]
t.filter "X" (Filter_Condition.Equal to=c) . at "X" . to_vector . should_equal [My_Data 1 2, My_Data 300 400, My_Data 7 8]
t.filter "X" (Filter_Condition.Less than=c) . at "X" . to_vector . should_equal [My_Data 100 200, My_Data 5 6]
c = Column.from_vector "Y" [My.Data 2 1, My.Data 400 300, My.Data 101 202, My.Data 10 10, My.Data 15 0]
t.filter "X" (Filter_Condition.Equal to=c) . at "X" . to_vector . should_equal [My.Data 1 2, My.Data 300 400, My.Data 7 8]
t.filter "X" (Filter_Condition.Less than=c) . at "X" . to_vector . should_equal [My.Data 100 200, My.Data 5 6]
t.filter "X" (Filter_Condition.Greater than=c) . at "X" . to_vector . should_equal []
Test.specify "by a boolean mask of varying length" <|

View File

@ -1,7 +1,6 @@
from Standard.Base import all
import Standard.Table
from Standard.Table import Delimited, Column, Data_Formatter
from Standard.Table import Table, Delimited, Column, Data_Formatter
import Standard.Table.Data.Storage
import Standard.Test

View File

@ -1,7 +1,6 @@
from Standard.Base import all
import Standard.Table
from Standard.Table import Delimited, Column, Data_Formatter
from Standard.Table import Table, Delimited, Column, Data_Formatter
import Standard.Table.Data.Storage
import Standard.Test

View File

@ -1,6 +1,6 @@
from Standard.Base import all
import Standard.Table.Internal.Unique_Name_Strategy
import Standard.Table.Internal.Unique_Name_Strategy.Unique_Name_Strategy
import Standard.Test

View File

@ -1,18 +1,17 @@
from Standard.Base import all
import Standard.Base.System
import Standard.Table
from Standard.Table import Column
from Standard.Table import Table, Column
import Standard.Test
Table.Table.should_equal self expected =
Table.should_equal self expected =
self_cols = self.columns
that_cols = expected.columns
self_cols.map .name . should_equal (that_cols.map .name) frames_to_skip=1
self_cols.map .to_vector . should_equal (that_cols.map .to_vector) frames_to_skip=1
Column.Column.should_equal self expected =
Column.should_equal self expected =
if self.name != expected.name then
Test.fail "Expected column name "+expected.name+", but got "+self.name+"."
if self.length != expected.length then

View File

@ -1,7 +1,6 @@
from Standard.Base import all
import Standard.Table
from Standard.Table import Table
import Standard.Visualization.Geo_Map
import Standard.Test

View File

@ -4,7 +4,7 @@ from Standard.Table import Column
import Standard.Test
Column.Column.expect : Text -> Vector -> Test.Success
Column.Column.expect self name contents =
Column.expect : Text -> Vector -> Test.Success
Column.expect self name contents =
self.name.should_equal name
self.to_vector.should_equal contents

View File

@ -1,6 +1,6 @@
from Standard.Base import all
import Standard.Table
from Standard.Table import Table
import Standard.Visualization.Helpers

View File

@ -1,7 +1,6 @@
from Standard.Base import all
from Standard.Table import Table, Column
import Standard.Table
import Standard.Visualization.Histogram

View File

@ -1,7 +1,6 @@
from Standard.Base import all
from Standard.Table import Table, Column
import Standard.Table
import Standard.Visualization.Scatter_Plot

View File

@ -1,11 +1,10 @@
from Standard.Base import all
from Standard.Table import Table, Aggregate_Column
import Standard.Table
from Standard.Database import SQLite
import Standard.Database
import Standard.Database.Data.Table as Database_Table
import Standard.Database.Data.Table.Table as Database_Table
import Standard.Visualization.Table.Visualization as Visualization