mirror of
https://github.com/enso-org/enso.git
synced 2024-11-10 12:48:25 +03:00
Date Time Pickers, Temporarily Disable Encoding.default (#10493)
- Widgets for Date_Time, Time_Of_Day and Time_Zone. - Disable Encoding.default for now as big performance impact on CSVs. ![image](https://github.com/enso-org/enso/assets/4699705/c1b936f0-3ab4-490c-8fe5-2310ef1ed079) ![image](https://github.com/enso-org/enso/assets/4699705/d5e29ec4-cc52-41e5-a532-17cd6dff34b9) ![image](https://github.com/enso-org/enso/assets/4699705/61455519-ea63-4275-9c7a-603714ff9f85) ![image](https://github.com/enso-org/enso/assets/4699705/48ccd3ad-5e15-49f9-87cd-4710ca559843)
This commit is contained in:
parent
71a6e2162e
commit
8da06309e9
@ -460,7 +460,7 @@ type Locale
|
||||
to_display_text self = "Locale(" + self.to_text + ")"
|
||||
|
||||
## PRIVATE
|
||||
Gets the default drop down option for this encoding.
|
||||
Gets the default drop down option for Locale.
|
||||
default_widget : Widget
|
||||
default_widget = Widget.Single_Choice values=Locale.widget_options display=Display.When_Modified
|
||||
|
||||
|
@ -71,7 +71,8 @@ type Encoding
|
||||
default -> Encoding =
|
||||
# This factory method is used to publicly expose the `Default` constructor.
|
||||
# The constructor itself has to be private, because we want to make `Value` constructor private, but all constructors must have the same privacy.
|
||||
Encoding.Default
|
||||
# ToDo: This is a workaround for performance issue.
|
||||
Encoding.utf_8
|
||||
|
||||
## PRIVATE
|
||||
A default encoding that will try to guess the encoding based on some heuristics.
|
||||
|
@ -24,7 +24,9 @@ import project.Nothing.Nothing
|
||||
import project.Panic.Panic
|
||||
import project.Warning.Warning
|
||||
from project.Data.Boolean import Boolean, False, True
|
||||
from project.Data.Time.Date import make_day_picker
|
||||
from project.Data.Text.Extensions import all
|
||||
from project.Metadata import Display, Widget
|
||||
from project.Widget_Helpers import make_date_time_format_selector
|
||||
|
||||
polyglot java import java.lang.ArithmeticException
|
||||
@ -148,6 +150,16 @@ type Date_Time
|
||||
from Standard.Base import Date_Time, Time_Zone
|
||||
|
||||
example_new = Date_Time.new 1986 8 5
|
||||
@year (Widget.Numeric_Input display=Display.Always)
|
||||
@month (Widget.Numeric_Input minimum=1 maximum=12 display=Display.Always)
|
||||
@day make_day_picker
|
||||
@hour (Widget.Numeric_Input minimum=0 maximum=23 display=Display.Always)
|
||||
@minute (Widget.Numeric_Input minimum=0 maximum=59 display=Display.Always)
|
||||
@second (Widget.Numeric_Input minimum=0 maximum=59 display=Display.When_Modified)
|
||||
@millisecond (Widget.Numeric_Input minimum=0 maximum=999 display=Display.When_Modified)
|
||||
@microsecond (Widget.Numeric_Input minimum=0 maximum=999 display=Display.When_Modified)
|
||||
@nanosecond (Widget.Numeric_Input minimum=0 maximum=999 display=Display.When_Modified)
|
||||
@zone Time_Zone.default_widget
|
||||
new : Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Time_Zone -> Date_Time ! Time_Error
|
||||
new year (month = 1) (day = 1) (hour = 0) (minute = 0) (second = 0) (millisecond = 0) (microsecond = 0) (nanosecond = 0) (zone = Time_Zone.system) =
|
||||
total_nanoseconds = nanosecond + microsecond * 1000 + millisecond * 1000000
|
||||
|
@ -20,6 +20,7 @@ import project.Nothing.Nothing
|
||||
import project.Panic.Panic
|
||||
from project.Data.Boolean import Boolean, False, True
|
||||
from project.Data.Text.Extensions import all
|
||||
from project.Metadata import Display, Widget
|
||||
from project.Widget_Helpers import make_time_format_selector
|
||||
|
||||
polyglot java import java.lang.Exception as JException
|
||||
@ -92,6 +93,12 @@ type Time_Of_Day
|
||||
from Standard.Base import Time_Of_Day
|
||||
|
||||
example_epoch = Time_Of_Day.new hour=9 minute=30
|
||||
@hour (Widget.Numeric_Input minimum=0 maximum=23 display=Display.Always)
|
||||
@minute (Widget.Numeric_Input minimum=0 maximum=59 display=Display.Always)
|
||||
@second (Widget.Numeric_Input minimum=0 maximum=59 display=Display.When_Modified)
|
||||
@millisecond (Widget.Numeric_Input minimum=0 maximum=999 display=Display.When_Modified)
|
||||
@microsecond (Widget.Numeric_Input minimum=0 maximum=999 display=Display.When_Modified)
|
||||
@nanosecond (Widget.Numeric_Input minimum=0 maximum=999 display=Display.When_Modified)
|
||||
new : Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Time_Of_Day ! Time_Error
|
||||
new (hour = 0) (minute = 0) (second = 0) (millisecond = 0) (microsecond = 0) (nanosecond = 0) =
|
||||
total_nanoseconds = nanosecond + microsecond * 1000 + millisecond * 1000000
|
||||
|
@ -3,11 +3,14 @@ import project.Data.Json.JS_Object
|
||||
import project.Data.Numbers.Integer
|
||||
import project.Data.Text.Text
|
||||
import project.Data.Time.Date_Time.Date_Time
|
||||
import project.Data.Vector.Vector
|
||||
import project.Error.Error
|
||||
import project.Errors.Illegal_Argument.Illegal_Argument
|
||||
import project.Errors.Time_Error.Time_Error
|
||||
import project.Panic.Panic
|
||||
from project.Data.Boolean import Boolean, False, True
|
||||
from project.Metadata import Display, make_single_choice, Widget
|
||||
from project.Metadata.Choice import Option
|
||||
|
||||
polyglot java import java.lang.Exception as JException
|
||||
polyglot java import java.time.ZoneId
|
||||
@ -107,8 +110,11 @@ type Time_Zone
|
||||
from Standard.Base.Time.Time_Zone import Time_Zone
|
||||
|
||||
example_new = Time_Zone.new 1 1 50
|
||||
@hours (Widget.Numeric_Input minimum=-18 maximum=18 display=Display.Always)
|
||||
@minutes (Widget.Numeric_Input minimum=-59 maximum=59 display=Display.When_Modified)
|
||||
@seconds (Widget.Numeric_Input minimum=-59 maximum=59 display=Display.When_Modified)
|
||||
new : Integer -> Integer -> Integer -> Time_Zone
|
||||
new (hours = 0) (minutes = 0) (seconds = 0) =
|
||||
new (hours:Integer = 0) (minutes:Integer = 0) (seconds:Integer = 0) =
|
||||
new_builtin hours minutes seconds
|
||||
|
||||
## ALIAS time zone from text
|
||||
@ -147,8 +153,9 @@ type Time_Zone
|
||||
from Standard.Base import Time_Zone
|
||||
|
||||
example_parse = Time_Zone.parse "+03:02:01"
|
||||
@id (make_single_choice Time_Zone.zone_names Display.Always)
|
||||
parse : Text -> Time_Zone ! Time_Error
|
||||
parse id =
|
||||
parse id:Text =
|
||||
Panic.catch JException handler=(catch -> Error.throw (Time_Error.Error catch.payload.getMessage)) <|
|
||||
parse_builtin id
|
||||
|
||||
@ -194,6 +201,17 @@ type Time_Zone
|
||||
to_display_text : Text
|
||||
to_display_text self = self.to_text
|
||||
|
||||
## PRIVATE
|
||||
Gets the default drop down option for Time_Zone.
|
||||
default_widget : Widget
|
||||
default_widget =
|
||||
options = [Option "System" "Time_Zone.system", Option "Local" "Time_Zone.local", Option "UTC" "Time_Zone.utc", Option "Named" "(Time_Zone.parse 'UTC')", Option "custom" "(Time_Zone.new 1 0 0)"]
|
||||
Widget.Single_Choice values=options display=Display.When_Modified
|
||||
|
||||
## Gets a list of all the time zone names that are predefined.
|
||||
zone_names : Vector Text
|
||||
zone_names = Time_Utils.getZoneNames
|
||||
|
||||
## PRIVATE
|
||||
Time_Zone.from (that:JS_Object) =
|
||||
if that.get "type" == "Time_Zone" && ["id"].all that.contains_key then Time_Zone.parse (that.get "id") else
|
||||
|
@ -246,4 +246,8 @@ public class Time_Utils {
|
||||
LocalDate baseDate = LocalDate.of(minYear, 1, 1);
|
||||
builder.appendValueReduced(yearField, 2, 2, baseDate);
|
||||
}
|
||||
|
||||
public static String[] getZoneNames() {
|
||||
return ZoneId.getAvailableZoneIds().stream().toArray(String[]::new);
|
||||
}
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ add_specs suite_builder =
|
||||
'{"type":"Date_Time","constructor":"new","year":2023,"month":9,"day":29,"hour":11,"second":52}'.should_parse_as (JS_Object.from_pairs [["type", "Date_Time"], ["constructor", "new"], ["year", 2023], ["month", 9], ["day", 29], ["hour", 11], ["second", 52]])
|
||||
'{"type":"Date_Time","constructor":"new","year":2023,"month":9,"day":29,"hour":11,"minute":52,"nanosecond":572104300}'.should_parse_as (JS_Object.from_pairs [["type", "Date_Time"], ["constructor", "new"], ["year", 2023], ["month", 9], ["day", 29], ["hour", 11], ["minute", 52], ["nanosecond", 572104300]])
|
||||
|
||||
group_builder.specify "should be able to read a JSON file with a BOM indicating UTF-16 encoding" <|
|
||||
group_builder.specify "should be able to read a JSON file with a BOM indicating UTF-16 encoding" pending="Encoding.default turned off temporarily" <|
|
||||
utf_16_le_bom = [-1, -2]
|
||||
bytes = utf_16_le_bom + ("{}".bytes Encoding.utf_16_le)
|
||||
f = File.create_temporary_file "json-with-bom" ".json"
|
||||
|
@ -68,7 +68,7 @@ add_specs suite_builder =
|
||||
default_warning.should_equal invalid_ascii_out
|
||||
Problems.get_attached_warnings default_warning . should_contain_the_same_elements_as problems
|
||||
|
||||
suite_builder.group "Default Encoding" group_builder->
|
||||
suite_builder.group "Default Encoding" pending="Encoding.default turned off temporarily" group_builder->
|
||||
group_builder.specify "should try reading as UTF-8 by default" <|
|
||||
bytes = [65, -60, -123, -60, -103]
|
||||
# A ą ę
|
||||
|
@ -475,7 +475,7 @@ add_specs suite_builder =
|
||||
Delimited_Format.Delimited ',' . with_line_endings Line_Ending_Style.Unix . should_equal (Delimited_Format.Delimited ',' line_endings=Line_Ending_Style.Unix)
|
||||
|
||||
utf_16_le_bom = [-1, -2]
|
||||
group_builder.specify "(in default mode) should detect UTF-16 encoding if BOM is present" <|
|
||||
group_builder.specify "(in default mode) should detect UTF-16 encoding if BOM is present" pending="Encoding.default turned off temporarily" <|
|
||||
bytes = utf_16_le_bom + ('a,b\n1,2'.bytes Encoding.utf_16_le)
|
||||
f = File.create_temporary_file "delimited-utf-16-bom" ".csv"
|
||||
bytes.write_bytes f . should_succeed
|
||||
@ -485,7 +485,7 @@ add_specs suite_builder =
|
||||
# No hidden BOM in the column name
|
||||
table.column_names.first.utf_8 . should_equal [97]
|
||||
|
||||
group_builder.specify "(in default mode) should skip UTF-8 BOM if it was present" <|
|
||||
group_builder.specify "(in default mode) should skip UTF-8 BOM if it was present" pending="Encoding.default turned off temporarily" <|
|
||||
utf_8_bom = [-17, -69, -65]
|
||||
bytes = utf_8_bom + ('a,b\n1,2'.bytes Encoding.utf_8)
|
||||
f = File.create_temporary_file "delimited-utf-8-bom" ".csv"
|
||||
@ -506,6 +506,10 @@ add_specs suite_builder =
|
||||
# The first column name now contains this invalid character, because it wasn't a BOM
|
||||
r.column_names.first . should_equal "a"
|
||||
|
||||
group_builder.specify "if UTF-16 encoding was selected but an inverted BOM is detected, a warning is issued (pt 2)" pending="Encoding.default turned off temporarily" <|
|
||||
bytes = utf_16_le_bom + ('a,b\n1,2'.bytes Encoding.utf_16_be)
|
||||
f = File.create_temporary_file "delimited-utf-16-inverted-bom" ".csv"
|
||||
|
||||
# If we read without specifying the encoding, we will infer UTF-16 LE encoding because of the BOM and get garbage:
|
||||
r2 = f.read
|
||||
r2.column_names . should_equal ["Column 1"]
|
||||
@ -523,7 +527,7 @@ add_specs suite_builder =
|
||||
r.first_column.to_vector . should_equal ['\uFFFD']
|
||||
Problems.expect_only_warning Encoding_Error r
|
||||
|
||||
group_builder.specify "should fall back to Windows-1252 encoding if invalid UTF-8 characters are encountered in Default encoding" <|
|
||||
group_builder.specify "should fall back to Windows-1252 encoding if invalid UTF-8 characters are encountered in Default encoding" pending="Encoding.default turned off temporarily" <|
|
||||
f = File.create_temporary_file "delimited-invalid-utf-8" ".csv"
|
||||
# On the simple characters all three encodings (ASCII, UTF-8 and Win-1252) agree, so we can use ASCII bytes.
|
||||
bytes = ('A,B\n1,y'.bytes Encoding.ascii) + [-1] + ('z\n2,-'.bytes Encoding.ascii)
|
||||
|
@ -569,7 +569,7 @@ add_specs suite_builder =
|
||||
|
||||
## If the Delimited config has Encoding.default, the encoding for read will be determined by BOM and Win-1252 fallback heuristics.
|
||||
The same encoding should be used for writing, to ensure that when the resulting file is read, all content is correctly decoded.
|
||||
group_builder.specify "should use the same effective encoding for writing as the one that would be used for reading" <|
|
||||
group_builder.specify "should use the same effective encoding for writing as the one that would be used for reading" pending="Encoding.default turned off temporarily" <|
|
||||
f = File.create_temporary_file "append-detect" ".csv"
|
||||
Test.with_clue "UTF-16 detected by BOM: " <|
|
||||
bom = [-1, -2]
|
||||
|
Loading…
Reference in New Issue
Block a user