Merge branch 'develop' into wip/gmt/10480-tweaks

This commit is contained in:
Gregory Travis 2024-07-10 09:35:07 -04:00
commit cafbed4595
37 changed files with 340 additions and 226 deletions

View File

@ -3,8 +3,11 @@
#### Enso IDE
- ["Add node" button is not obscured by output port][10433]
- [Numeric Widget does not accept non-numeric input][10457]. This is to prevent
node being completely altered by accidental code put to the widget.
[10433]: https://github.com/enso-org/enso/pull/10443
[10457]: https://github.com/enso-org/enso/pull/10457
#### Enso Enso Standard Library

View File

@ -37,6 +37,22 @@ pub fn is_ident_or_operator(code: &str) -> u32 {
}
}
#[wasm_bindgen]
pub fn is_numeric_literal(code: &str) -> bool {
let parsed = PARSER.with(|parser| parser.run(code));
let enso_parser::syntax::tree::Variant::BodyBlock(body) = *parsed.variant else { return false };
let [stmt] = &body.statements[..] else { return false };
stmt.expression.as_ref().map_or(false, |expr| match &*expr.variant {
enso_parser::syntax::tree::Variant::Number(_) => true,
enso_parser::syntax::tree::Variant::UnaryOprApp(app) =>
app.opr.code == "-"
&& app.rhs.as_ref().map_or(false, |rhs| {
matches!(*rhs.variant, enso_parser::syntax::tree::Variant::Number(_))
}),
_ => false,
})
}
#[wasm_bindgen(start)]
fn main() {
console_error_panic_hook::set_once();

View File

@ -6,7 +6,12 @@
import { createXXHash128 } from 'hash-wasm'
import type { IDataType } from 'hash-wasm/dist/lib/util'
import init, { is_ident_or_operator, parse, parse_doc_to_json } from '../../rust-ffi/pkg/rust_ffi'
import init, {
is_ident_or_operator,
is_numeric_literal,
parse,
parse_doc_to_json,
} from '../../rust-ffi/pkg/rust_ffi'
import { assertDefined } from '../util/assert'
import { isNode } from '../util/detect'
@ -37,4 +42,4 @@ export async function initializeFFI(path?: string | undefined) {
// await initializeFFI()
/* eslint-disable-next-line camelcase */
export { is_ident_or_operator, parse_doc_to_json, parse as parse_tree }
export { is_ident_or_operator, is_numeric_literal, parse_doc_to_json, parse as parse_tree }

View File

@ -12,10 +12,17 @@ declare global {
function parse_tree(code: string): Uint8Array
function parse_doc_to_json(docs: string): string
function is_ident_or_operator(code: string): number
function is_numeric_literal(code: string): boolean
function xxHash128(input: IDataType): string
}
export async function initializeFFI(_path?: string | undefined) {}
/* eslint-disable-next-line camelcase */
export const { is_ident_or_operator, parse_doc_to_json, parse_tree, xxHash128 } = globalThis
export const {
is_ident_or_operator,
is_numeric_literal,
parse_doc_to_json,
parse_tree,
xxHash128,
} = globalThis

View File

@ -32,6 +32,7 @@ import type { SourceRangeEdit } from '../util/data/text'
import { allKeys } from '../util/types'
import type { ExternalId, VisualizationMetadata } from '../yjsModel'
import { visMetadataEquals } from '../yjsModel'
import { is_numeric_literal } from './ffi'
import * as RawAst from './generated/ast'
import {
applyTextEditsToAst,
@ -1825,6 +1826,10 @@ export class MutableNumericLiteral extends NumericLiteral implements MutableAst
export interface MutableNumericLiteral extends NumericLiteral, MutableAst {}
applyMixins(MutableNumericLiteral, [MutableAst])
export function isNumericLiteral(code: string) {
return is_numeric_literal(code)
}
/** The actual contents of an `ArgumentDefinition` are complex, but probably of more interest to the compiler than the
* GUI. We just need to represent them faithfully and create the simple cases. */
type ArgumentDefinition<T extends TreeRefs = RawRefs> = (T['ast'] | T['token'])[]

View File

@ -104,4 +104,69 @@ registerAutoBlurHandler()
/* Compensate for top bar, render the app below it. */
top: calc(var(--row-height) + var(--top-level-gap, 0px) + var(--top-bar-margin, 0px) + 16px);
}
:deep(*),
:deep(*)::before,
:deep(*)::after {
box-sizing: border-box;
margin: 0;
}
:deep(.icon) {
width: 16px;
height: 16px;
}
/* Scrollbar style definitions for textual visualizations which need support for scrolling.
*
* The 11px width/height (depending on scrollbar orientation)
* is set so that it resembles macOS default scrollbar.
*/
:deep(.scrollable) {
scrollbar-color: rgba(190 190 190 / 50%) transparent;
}
:deep(.scrollable)::-webkit-scrollbar {
-webkit-appearance: none;
}
:deep(.scrollable)::-webkit-scrollbar-track {
-webkit-box-shadow: none;
}
:deep(.scrollable)::-webkit-scrollbar:vertical {
width: 11px;
}
:deep(.scrollable)::-webkit-scrollbar:horizontal {
height: 11px;
}
:deep(.scrollable)::-webkit-scrollbar-thumb {
border-radius: 8px;
border: 1px solid rgba(220, 220, 220, 0.5);
background-color: rgba(190, 190, 190, 0.5);
}
:deep(.scrollable)::-webkit-scrollbar-corner {
background: rgba(0, 0, 0, 0);
}
:deep(.scrollable)::-webkit-scrollbar-button {
height: 8px;
width: 8px;
}
:deep(.draggable) {
cursor: grab;
}
:deep(.clickable) {
cursor: pointer;
}
:deep([data-use-vue-component-wrap]) {
display: contents !important;
}
</style>

View File

@ -60,68 +60,3 @@
--right-dock-default-width: 40%;
--code-editor-default-height: 30%;
}
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
}
.icon {
width: 16px;
height: 16px;
}
.hidden {
display: none;
}
/* Scrollbar style definitions for textual visualizations which need support for scrolling.
*
* The 11px width/height (depending on scrollbar orientation)
* is set so that it resembles macOS default scrollbar.
*/
.scrollable {
scrollbar-color: rgba(190 190 190 / 50%) transparent;
}
.scrollable::-webkit-scrollbar {
-webkit-appearance: none;
}
.scrollable::-webkit-scrollbar-track {
-webkit-box-shadow: none;
}
.scrollable::-webkit-scrollbar:vertical {
width: 11px;
}
.scrollable::-webkit-scrollbar:horizontal {
height: 11px;
}
.scrollable::-webkit-scrollbar-thumb {
border-radius: 8px;
border: 1px solid rgba(220, 220, 220, 0.5);
background-color: rgba(190, 190, 190, 0.5);
}
.scrollable::-webkit-scrollbar-corner {
background: rgba(0, 0, 0, 0);
}
.scrollable::-webkit-scrollbar-button {
height: 8px;
width: 8px;
}
.draggable {
cursor: grab;
}
.clickable {
cursor: pointer;
}

View File

@ -1,10 +0,0 @@
@import './base.css';
body {
display: flex;
min-height: 100vh;
}
[data-use-vue-component-wrap] {
display: contents !important;
}

View File

@ -1,4 +1,4 @@
import '@/assets/main.css'
import '@/assets/base.css'
export async function AsyncApp() {
const [_, app] = await Promise.all([

View File

@ -10,9 +10,9 @@ import { computed, ref, type ComponentInstance } from 'vue'
const props = defineProps(widgetProps(widgetDefinition))
const inputComponent = ref<ComponentInstance<typeof NumericInputWidget>>()
function setValue(value: number | string) {
function setValue(value: string | undefined) {
props.onUpdate({
portUpdate: { value: value.toString(), origin: props.input.portId },
portUpdate: { value, origin: props.input.portId },
})
}

View File

@ -234,10 +234,8 @@ watchPostEffect(() => {
font-family: var(--font-mono);
font-size: 10px;
}
</style>
<style>
.HeatmapVisualization .label .domain {
.label :deep(.domain) {
display: none;
}
</style>

View File

@ -136,29 +136,27 @@ function renderRegularInterpolation(value: string, fgColor: RGBA, bgColor: RGBA)
.SQLVisualization {
padding: 4px;
}
</style>
<style>
.SQLVisualization .sql {
:deep(.sql) {
font-family: var(--font-mono);
font-size: 12px;
margin-left: 7px;
margin-top: 5px;
}
.SQLVisualization .interpolation {
:deep(.interpolation) {
border-radius: 6px;
padding: 1px 2px 1px 2px;
display: inline;
}
.SQLVisualization .mismatch-parent {
:deep(.mismatch-parent) {
position: relative;
display: inline-flex;
justify-content: center;
}
.SQLVisualization .mismatch-mouse-area {
:deep(.mismatch-mouse-area) {
display: inline;
position: absolute;
width: 150%;
@ -167,15 +165,15 @@ function renderRegularInterpolation(value: string, fgColor: RGBA, bgColor: RGBA)
z-index: 0;
}
.SQLVisualization .mismatch {
:deep(.mismatch) {
z-index: 1;
}
.SQLVisualization .modulepath {
:deep(.modulepath) {
color: rgba(150, 150, 150, 0.9);
}
.SQLVisualization .tooltip {
:deep(.tooltip) {
font-family: DejaVuSansMonoBook, sans-serif;
font-size: 12px;
opacity: 0;

View File

@ -128,6 +128,7 @@ const rowLimit = ref(0)
const page = ref(0)
const pageLimit = ref(0)
const rowCount = ref(0)
const showRowCount = ref(true)
const isTruncated = ref(false)
const tableNode = ref<HTMLElement>()
const dataGroupingMap = shallowRef<Map<string, boolean>>()
@ -159,6 +160,7 @@ const agGridOptions: Ref<GridOptions & Required<Pick<GridOptions, 'defaultColDef
})
const isRowCountSelectorVisible = computed(() => rowCount.value >= 1000)
const selectableRowLimits = computed(() => {
const defaults = [1000, 2500, 5000, 10000, 25000, 50000, 100000].filter(
(r) => r <= rowCount.value,
@ -503,6 +505,7 @@ watchEffect(() => {
// Update paging
const newRowCount = data_.all_rows_count == null ? 1 : data_.all_rows_count
showRowCount.value = !(data_.all_rows_count == null)
rowCount.value = newRowCount
const newPageLimit = Math.ceil(newRowCount / rowLimit.value)
pageLimit.value = newPageLimit
@ -644,13 +647,15 @@ onUnmounted(() => {
v-text="limit"
></option>
</select>
<span
v-if="isRowCountSelectorVisible && isTruncated"
v-text="` of ${rowCount} rows (Sorting/Filtering disabled).`"
></span>
<span v-else-if="isRowCountSelectorVisible" v-text="' rows.'"></span>
<span v-else-if="rowCount === 1" v-text="'1 row.'"></span>
<span v-else v-text="`${rowCount} rows.`"></span>
<div v-if="showRowCount">
<span
v-if="isRowCountSelectorVisible && isTruncated"
v-text="` of ${rowCount} rows (Sorting/Filtering disabled).`"
></span>
<span v-else-if="isRowCountSelectorVisible" v-text="' rows.'"></span>
<span v-else-if="rowCount === 1" v-text="'1 row.'"></span>
<span v-else v-text="`${rowCount} rows.`"></span>
</div>
</div>
<div ref="tableNode" class="scrollable ag-theme-alpine"></div>
</div>
@ -679,18 +684,20 @@ onUnmounted(() => {
padding: 0 5px;
overflow: hidden;
}
</style>
<style>
.TableVisualization > .ag-theme-alpine > .ag-root-wrapper.ag-layout-normal {
.TableVisualization > .ag-theme-alpine > :deep(.ag-root-wrapper.ag-layout-normal) {
border-radius: 0 0 var(--radius-default) var(--radius-default);
}
a {
/* Tag selectors are inefficient to compute, and should be replaced with a class selector
* if possible.
* See https://vuejs.org/api/sfc-css-features.html#scoped-style-tips */
:deep(a) {
color: blue;
text-decoration: underline;
}
a:hover {
:deep(a):hover {
color: darkblue;
}
</style>

View File

@ -24,4 +24,8 @@ const emit = defineEmits<{ 'update:modelValue': [modelValue: boolean] }>()
border-radius: var(--radius-full);
background: var(--color-widget-selected);
}
.hidden {
display: none;
}
</style>

View File

@ -1,5 +1,6 @@
<script setup lang="ts">
import { usePointer } from '@/composables/events'
import { isNumericLiteral } from 'shared/ast/tree'
import { computed, ref, watch, type CSSProperties, type ComponentInstance } from 'vue'
import AutoSizedInput from './AutoSizedInput.vue'
@ -9,7 +10,7 @@ const props = defineProps<{
limits?: { min: number; max: number } | undefined
}>()
const emit = defineEmits<{
'update:modelValue': [modelValue: number | string]
'update:modelValue': [modelValue: string | undefined]
blur: []
focus: []
input: [content: string]
@ -21,6 +22,14 @@ const MIN_CONTENT_WIDTH = 56
// Edited value reflects the `modelValue`, but does not update it until the user defocuses the field.
const editedValue = ref('')
// Last value which is a parseable number. It's a string, because the Enso number literals differ from js
// representations.
const lastValidValue = ref<string>()
watch(editedValue, (newValue) => {
if (newValue == '' || isNumericLiteral(newValue)) {
lastValidValue.value = newValue
}
})
const valueString = computed(() => (props.modelValue != null ? props.modelValue.toString() : ''))
watch(valueString, (newValue) => (editedValue.value = newValue), { immediate: true })
const inputFieldActive = ref(false)
@ -91,13 +100,14 @@ const inputStyle = computed<CSSProperties>(() => {
})
function emitUpdate() {
if (valueString.value !== editedValue.value) {
emit('update:modelValue', editedValue.value)
if (valueString.value !== lastValidValue.value) {
emit('update:modelValue', lastValidValue.value == '' ? undefined : lastValidValue.value)
}
}
function blurred() {
inputFieldActive.value = false
editedValue.value = lastValidValue.value?.toString() ?? ''
emit('blur')
emitUpdate()
}

View File

@ -26,30 +26,37 @@
"electron-is-dev": "^2.0.0",
"enso-content-config": "workspace:*",
"mime-types": "^2.1.35",
"mkcert": "3.2.0",
"opener": "^1.5.2",
"string-length": "^5.0.1",
"tar": "^6.2.0",
"yargs": "17.6.2",
"mkcert": "3.2.0"
"yargs": "17.6.2"
},
"devDependencies": {
"@babel/plugin-syntax-import-attributes": "^7.24.7",
"@electron/notarize": "2.1.0",
"@types/node": "^20.11.21",
"electron": "25.7.0",
"electron-builder": "^24.13.3",
"enso-common": "workspace:*",
"enso-runner": "workspace:*",
"enso-gui2": "workspace:*",
"enso-runner": "workspace:*",
"esbuild": "^0.19.3",
"esbuild-plugin-yaml": "^0.0.1",
"fast-glob": "^3.2.12",
"lightningcss": "^1.24.0",
"portfinder": "^1.0.32",
"rollup": "^4.18.1",
"sharp": "^0.31.2",
"to-ico": "^1.1.5",
"tsx": "^4.7.1",
"vite": "^5.3.3"
},
"//": [
"vite is required for the watch script",
"rollup is required for vite",
"@babel/plugin-syntax-import-attributes is a dependency of the dashboard"
],
"scripts": {
"typecheck": "npm run --workspace=enso-gui2 compile-server && tsc --build",
"start": "tsx start.ts",

View File

@ -39,6 +39,7 @@ const logger = contentConfig.logger
if (process.env.ELECTRON_DEV_MODE === 'true' && process.env.NODE_MODULES_PATH != null) {
require.main?.paths.unshift(process.env.NODE_MODULES_PATH)
console.log(require.main?.paths)
}
// ===========

View File

@ -41,7 +41,7 @@ process.env.ELECTRON_DEV_MODE = 'true'
console.log('Cleaning IDE dist directory.')
await fs.rm(IDE_DIR_PATH, { recursive: true, force: true })
await fs.mkdir(IDE_DIR_PATH, { recursive: true })
const NODE_MODULES_PATH = path.resolve('../../../../node_modules')
const NODE_MODULES_PATH = path.resolve('./node_modules')
const ALL_BUNDLES_READY = new Promise<Watches>((resolve, reject) => {
void (async () => {

View File

@ -26,9 +26,6 @@
"test:e2e": "cross-env NODE_ENV=production playwright test",
"test:e2e:debug": "cross-env NODE_ENV=production playwright test --ui"
},
"//": [
"@fortawesome/fontawesome-svg-core is required as a peer dependency for @fortawesome/react-fontawesome"
],
"dependencies": {
"@aws-amplify/auth": "5.6.5",
"@aws-amplify/core": "5.8.5",

View File

@ -7,6 +7,16 @@ import Modal from '#/components/Modal'
import * as tailwindMerge from '#/utilities/tailwindMerge'
// =================
// === Constants ===
// =================
const DEFAULT_MENU_WIDTH = 256
const MACOS_MENU_WIDTH = 230
/** The width of a single context menu. */
const MENU_WIDTH = detect.isOnMacOS() ? MACOS_MENU_WIDTH : DEFAULT_MENU_WIDTH
const HALF_MENU_WIDTH = Math.floor(MENU_WIDTH / 2)
// ===================
// === ContextMenu ===
// ===================
@ -34,12 +44,9 @@ function ContextMenus(props: ContextMenusProps, ref: React.ForwardedRef<HTMLDivE
<div
data-testid="context-menus"
ref={ref}
style={{ left: event.pageX, top: event.pageY }}
style={{ left: event.pageX - HALF_MENU_WIDTH, top: event.pageY }}
className={tailwindMerge.twMerge(
'pointer-events-none sticky flex w-min items-start gap-context-menus',
detect.isOnMacOS()
? 'ml-context-menu-macos-half-x -translate-x-context-menu-macos-half-x'
: 'ml-context-menu-half-x -translate-x-context-menu-half-x'
'pointer-events-none sticky flex w-min items-start gap-context-menus'
)}
onClick={clickEvent => {
clickEvent.stopPropagation()

View File

@ -42,7 +42,7 @@ interface CategoryMetadata {
readonly textId: Extract<text.TextId, `${Category}Category`>
readonly buttonTextId: Extract<text.TextId, `${Category}CategoryButtonLabel`>
readonly dropZoneTextId: Extract<text.TextId, `${Category}CategoryDropZoneLabel`>
readonly className?: string
readonly nested?: true
}
// =================
@ -63,7 +63,7 @@ const CATEGORY_DATA: readonly CategoryMetadata[] = [
textId: 'recentCategory',
buttonTextId: 'recentCategoryButtonLabel',
dropZoneTextId: 'recentCategoryDropZoneLabel',
className: 'ml-4',
nested: true,
},
{
category: Category.trash,
@ -71,7 +71,7 @@ const CATEGORY_DATA: readonly CategoryMetadata[] = [
textId: 'trashCategory',
buttonTextId: 'trashCategoryButtonLabel',
dropZoneTextId: 'trashCategoryDropZoneLabel',
className: 'ml-4',
nested: true,
},
{
category: Category.local,
@ -120,8 +120,7 @@ function CategorySwitcherItem(props: InternalCategorySwitcherItemProps) {
tooltipPlacement="right"
className={tailwindMerge.twMerge(
isCurrent && 'focus-default',
isDisabled && 'cursor-not-allowed hover:bg-transparent',
data.className
isDisabled && 'cursor-not-allowed hover:bg-transparent'
)}
aria-label={getText(buttonTextId)}
onPress={onPress}
@ -230,7 +229,7 @@ export default function CategorySwitcher(props: CategorySwitcherProps) {
{categoryData.map(data => {
const error = getCategoryError(data.category)
return (
const element = (
<CategorySwitcherItem
key={data.category}
id={data.category}
@ -281,6 +280,14 @@ export default function CategorySwitcher(props: CategorySwitcherProps) {
}}
/>
)
return data.nested ? (
<div className="flex">
<div className="ml-[15px] mr-1 border-r border-primary/20" />
{element}
</div>
) : (
element
)
})}
</div>
</div>

View File

@ -83,8 +83,6 @@
--context-menus-gap: 0.125rem;
--context-menu-padding: 0.5rem;
--context-menu-width: 16rem;
--context-menu-half-width: calc(var(--context-menu-width) / 2);
--context-menu-macos-half-width: calc(var(--context-menu-macos-width) / 2);
--context-menu-macos-width: 14.375rem;
--context-menu-entry-padding-x: 0.75rem;
--separator-margin-y: 0.125rem;

View File

@ -487,7 +487,7 @@
"teamPlanSubtitle": "For small teams",
"teamPlanPricing": "$150 per user / month",
"teamPlanFeatures": "100GB Cloud Storage; Up to 10 users sharing; Datalinks; Version Control for files and workflows; Enso Copilot; Multiple Lifecycle Environments",
"enterprisePlanName": "Organization",
"enterprisePlanName": "Enterprise",
"enterprisePlanSubtitle": "For large organizations",
"enterprisePlanPricing": "Contact Sales",
"enterprisePlanFeatures": "1000+GB Cloud Storage; Unlimited users sharing; Datalinks; Version Control for files and workflows; Enso Copilot; Multiple Lifecycle Environments; Data access and modification logs; Priority Support; Fine-grained files and workflows permissions; Federated Log On",
@ -724,8 +724,8 @@
"soloPlan": "Solo Plan",
"team": "Team",
"teamPlan": "Team Plan",
"enterprise": "Organization",
"enterprisePlan": "Organization",
"enterprise": "Enterprise",
"enterprisePlan": "Enterprise Plan",
"paywallScreenTitle": "Unlock the potential of Enso",
"paywallScreenDescription": "Upgrade to $0 to unlock additional features and get access to priority support.",

View File

@ -321,8 +321,6 @@ export default /** @satisfies {import('tailwindcss').Config} */ ({
'close-icon': 'var(--close-icon-margin)',
'date-input-gap': 'var(--date-input-gap)',
'date-input-calendar-gap': 'var(--date-input-calendar-gap)',
'context-menu-macos-half-x': 'var(--context-menu-macos-half-width)',
'context-menu-half-x': 'var(--context-menu-half-width)',
'chat-header-x': 'var(--chat-header-margin-x)',
'chat-header-t': 'var(--chat-header-margin-top)',
'chat-form-x': 'var(--chat-form-margin-x)',
@ -410,10 +408,6 @@ inset 0 -36px 51px -51px #00000014`,
'fill-news-items': 'repeat(auto-fill, minmax(var(--news-items-column-width), 1fr))',
'fill-samples': 'repeat(auto-fill, minmax(var(--samples-column-width), 1fr))',
},
translate: {
'context-menu-half-x': 'var(--context-menu-half-width)',
'context-menu-macos-half-x': 'var(--context-menu-macos-half-width)',
},
dashArray: {
5: '5-12',
75: '75-12',

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -104,7 +104,7 @@ type Suite
succ_tests = all_results.filter (r-> r.is_success) . length
failed_tests = all_results.filter (r-> r.is_fail)
failed_tests_number = failed_tests.length
failed_tests_names = failed_tests.map (t-> t.spec_name) . distinct . take 10 . join "|"
failed_tests_names = failed_tests.map (t-> t.spec_name.replace ' ' '.') . distinct . take 10 . join "|"
skipped_tests = all_results.filter (r-> r.is_pending) . length
pending_groups = matching_specs.filter (p-> p.first.is_pending) . length
case should_exit of

View File

@ -364,7 +364,7 @@ importers:
version: 5.3.3(@types/node@20.11.21)(lightningcss@1.25.1)
vite-plugin-vue-devtools:
specifier: 7.3.5
version: 7.3.5(rollup@4.18.0)(vite@5.3.3(@types/node@20.11.21)(lightningcss@1.25.1))(vue@3.4.31(typescript@5.5.3))
version: 7.3.5(rollup@4.18.1)(vite@5.3.3(@types/node@20.11.21)(lightningcss@1.25.1))(vue@3.4.31(typescript@5.5.3))
vitest:
specifier: ^1.3.1
version: 1.6.0(@types/node@20.11.21)(jsdom@24.1.0)(lightningcss@1.25.1)
@ -477,6 +477,9 @@ importers:
specifier: 17.6.2
version: 17.6.2
devDependencies:
'@babel/plugin-syntax-import-attributes':
specifier: ^7.24.7
version: 7.24.7(@babel/core@7.24.7)
'@electron/notarize':
specifier: 2.1.0
version: 2.1.0
@ -513,6 +516,9 @@ importers:
portfinder:
specifier: ^1.0.32
version: 1.0.32
rollup:
specifier: ^4.18.1
version: 4.18.1
sharp:
specifier: ^0.31.2
version: 0.31.3
@ -657,7 +663,7 @@ importers:
version: 4.3.0(@vue/compiler-sfc@3.4.31)(prettier@3.3.2)
'@modyfi/vite-plugin-yaml':
specifier: ^1.0.4
version: 1.1.0(rollup@4.18.0)(vite@5.3.3(@types/node@20.11.21)(lightningcss@1.25.1))
version: 1.1.0(rollup@4.18.1)(vite@5.3.3(@types/node@20.11.21)(lightningcss@1.25.1))
'@playwright/experimental-ct-react':
specifier: ^1.40.0
version: 1.45.0(@types/node@20.11.21)(lightningcss@1.25.1)(vite@5.3.3(@types/node@20.11.21)(lightningcss@1.25.1))
@ -2436,83 +2442,83 @@ packages:
rollup:
optional: true
'@rollup/rollup-android-arm-eabi@4.18.0':
resolution: {integrity: sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==}
'@rollup/rollup-android-arm-eabi@4.18.1':
resolution: {integrity: sha512-lncuC4aHicncmbORnx+dUaAgzee9cm/PbIqgWz1PpXuwc+sa1Ct83tnqUDy/GFKleLiN7ZIeytM6KJ4cAn1SxA==}
cpu: [arm]
os: [android]
'@rollup/rollup-android-arm64@4.18.0':
resolution: {integrity: sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==}
'@rollup/rollup-android-arm64@4.18.1':
resolution: {integrity: sha512-F/tkdw0WSs4ojqz5Ovrw5r9odqzFjb5LIgHdHZG65dFI1lWTWRVy32KDJLKRISHgJvqUeUhdIvy43fX41znyDg==}
cpu: [arm64]
os: [android]
'@rollup/rollup-darwin-arm64@4.18.0':
resolution: {integrity: sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==}
'@rollup/rollup-darwin-arm64@4.18.1':
resolution: {integrity: sha512-vk+ma8iC1ebje/ahpxpnrfVQJibTMyHdWpOGZ3JpQ7Mgn/3QNHmPq7YwjZbIE7km73dH5M1e6MRRsnEBW7v5CQ==}
cpu: [arm64]
os: [darwin]
'@rollup/rollup-darwin-x64@4.18.0':
resolution: {integrity: sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==}
'@rollup/rollup-darwin-x64@4.18.1':
resolution: {integrity: sha512-IgpzXKauRe1Tafcej9STjSSuG0Ghu/xGYH+qG6JwsAUxXrnkvNHcq/NL6nz1+jzvWAnQkuAJ4uIwGB48K9OCGA==}
cpu: [x64]
os: [darwin]
'@rollup/rollup-linux-arm-gnueabihf@4.18.0':
resolution: {integrity: sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==}
'@rollup/rollup-linux-arm-gnueabihf@4.18.1':
resolution: {integrity: sha512-P9bSiAUnSSM7EmyRK+e5wgpqai86QOSv8BwvkGjLwYuOpaeomiZWifEos517CwbG+aZl1T4clSE1YqqH2JRs+g==}
cpu: [arm]
os: [linux]
'@rollup/rollup-linux-arm-musleabihf@4.18.0':
resolution: {integrity: sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==}
'@rollup/rollup-linux-arm-musleabihf@4.18.1':
resolution: {integrity: sha512-5RnjpACoxtS+aWOI1dURKno11d7krfpGDEn19jI8BuWmSBbUC4ytIADfROM1FZrFhQPSoP+KEa3NlEScznBTyQ==}
cpu: [arm]
os: [linux]
'@rollup/rollup-linux-arm64-gnu@4.18.0':
resolution: {integrity: sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==}
'@rollup/rollup-linux-arm64-gnu@4.18.1':
resolution: {integrity: sha512-8mwmGD668m8WaGbthrEYZ9CBmPug2QPGWxhJxh/vCgBjro5o96gL04WLlg5BA233OCWLqERy4YUzX3bJGXaJgQ==}
cpu: [arm64]
os: [linux]
'@rollup/rollup-linux-arm64-musl@4.18.0':
resolution: {integrity: sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==}
'@rollup/rollup-linux-arm64-musl@4.18.1':
resolution: {integrity: sha512-dJX9u4r4bqInMGOAQoGYdwDP8lQiisWb9et+T84l2WXk41yEej8v2iGKodmdKimT8cTAYt0jFb+UEBxnPkbXEQ==}
cpu: [arm64]
os: [linux]
'@rollup/rollup-linux-powerpc64le-gnu@4.18.0':
resolution: {integrity: sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==}
'@rollup/rollup-linux-powerpc64le-gnu@4.18.1':
resolution: {integrity: sha512-V72cXdTl4EI0x6FNmho4D502sy7ed+LuVW6Ym8aI6DRQ9hQZdp5sj0a2usYOlqvFBNKQnLQGwmYnujo2HvjCxQ==}
cpu: [ppc64]
os: [linux]
'@rollup/rollup-linux-riscv64-gnu@4.18.0':
resolution: {integrity: sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==}
'@rollup/rollup-linux-riscv64-gnu@4.18.1':
resolution: {integrity: sha512-f+pJih7sxoKmbjghrM2RkWo2WHUW8UbfxIQiWo5yeCaCM0TveMEuAzKJte4QskBp1TIinpnRcxkquY+4WuY/tg==}
cpu: [riscv64]
os: [linux]
'@rollup/rollup-linux-s390x-gnu@4.18.0':
resolution: {integrity: sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==}
'@rollup/rollup-linux-s390x-gnu@4.18.1':
resolution: {integrity: sha512-qb1hMMT3Fr/Qz1OKovCuUM11MUNLUuHeBC2DPPAWUYYUAOFWaxInaTwTQmc7Fl5La7DShTEpmYwgdt2hG+4TEg==}
cpu: [s390x]
os: [linux]
'@rollup/rollup-linux-x64-gnu@4.18.0':
resolution: {integrity: sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==}
'@rollup/rollup-linux-x64-gnu@4.18.1':
resolution: {integrity: sha512-7O5u/p6oKUFYjRbZkL2FLbwsyoJAjyeXHCU3O4ndvzg2OFO2GinFPSJFGbiwFDaCFc+k7gs9CF243PwdPQFh5g==}
cpu: [x64]
os: [linux]
'@rollup/rollup-linux-x64-musl@4.18.0':
resolution: {integrity: sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==}
'@rollup/rollup-linux-x64-musl@4.18.1':
resolution: {integrity: sha512-pDLkYITdYrH/9Cv/Vlj8HppDuLMDUBmgsM0+N+xLtFd18aXgM9Nyqupb/Uw+HeidhfYg2lD6CXvz6CjoVOaKjQ==}
cpu: [x64]
os: [linux]
'@rollup/rollup-win32-arm64-msvc@4.18.0':
resolution: {integrity: sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==}
'@rollup/rollup-win32-arm64-msvc@4.18.1':
resolution: {integrity: sha512-W2ZNI323O/8pJdBGil1oCauuCzmVd9lDmWBBqxYZcOqWD6aWqJtVBQ1dFrF4dYpZPks6F+xCZHfzG5hYlSHZ6g==}
cpu: [arm64]
os: [win32]
'@rollup/rollup-win32-ia32-msvc@4.18.0':
resolution: {integrity: sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==}
'@rollup/rollup-win32-ia32-msvc@4.18.1':
resolution: {integrity: sha512-ELfEX1/+eGZYMaCIbK4jqLxO1gyTSOIlZr6pbC4SRYFaSIDVKOnZNMdoZ+ON0mrFDp4+H5MhwNC1H/AhE3zQLg==}
cpu: [ia32]
os: [win32]
'@rollup/rollup-win32-x64-msvc@4.18.0':
resolution: {integrity: sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==}
'@rollup/rollup-win32-x64-msvc@4.18.1':
resolution: {integrity: sha512-yjk2MAkQmoaPYCSu35RLJ62+dz358nE83VfTePJRp8CG7aMg25mEJYpXFiD+NcevhX8LxD5OP5tktPXnXN7GDw==}
cpu: [x64]
os: [win32]
@ -6322,8 +6328,8 @@ packages:
rollup-pluginutils@2.8.2:
resolution: {integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==}
rollup@4.18.0:
resolution: {integrity: sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==}
rollup@4.18.1:
resolution: {integrity: sha512-Elx2UT8lzxxOXMpy5HWQGZqkrQOtrVDDa/bm9l10+U4rQnVzbL/LgZ4NOM1MPIDyHk69W4InuYDF5dzRh4Kw1A==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
hasBin: true
@ -8663,9 +8669,9 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@modyfi/vite-plugin-yaml@1.1.0(rollup@4.18.0)(vite@5.3.3(@types/node@20.11.21)(lightningcss@1.25.1))':
'@modyfi/vite-plugin-yaml@1.1.0(rollup@4.18.1)(vite@5.3.3(@types/node@20.11.21)(lightningcss@1.25.1))':
dependencies:
'@rollup/pluginutils': 5.1.0(rollup@4.18.0)
'@rollup/pluginutils': 5.1.0(rollup@4.18.1)
js-yaml: 4.1.0
tosource: 2.0.0-alpha.3
vite: 5.3.3(@types/node@20.11.21)(lightningcss@1.25.1)
@ -9695,60 +9701,60 @@ snapshots:
'@remix-run/router@1.17.0': {}
'@rollup/pluginutils@5.1.0(rollup@4.18.0)':
'@rollup/pluginutils@5.1.0(rollup@4.18.1)':
dependencies:
'@types/estree': 1.0.5
estree-walker: 2.0.2
picomatch: 2.3.1
optionalDependencies:
rollup: 4.18.0
rollup: 4.18.1
'@rollup/rollup-android-arm-eabi@4.18.0':
'@rollup/rollup-android-arm-eabi@4.18.1':
optional: true
'@rollup/rollup-android-arm64@4.18.0':
'@rollup/rollup-android-arm64@4.18.1':
optional: true
'@rollup/rollup-darwin-arm64@4.18.0':
'@rollup/rollup-darwin-arm64@4.18.1':
optional: true
'@rollup/rollup-darwin-x64@4.18.0':
'@rollup/rollup-darwin-x64@4.18.1':
optional: true
'@rollup/rollup-linux-arm-gnueabihf@4.18.0':
'@rollup/rollup-linux-arm-gnueabihf@4.18.1':
optional: true
'@rollup/rollup-linux-arm-musleabihf@4.18.0':
'@rollup/rollup-linux-arm-musleabihf@4.18.1':
optional: true
'@rollup/rollup-linux-arm64-gnu@4.18.0':
'@rollup/rollup-linux-arm64-gnu@4.18.1':
optional: true
'@rollup/rollup-linux-arm64-musl@4.18.0':
'@rollup/rollup-linux-arm64-musl@4.18.1':
optional: true
'@rollup/rollup-linux-powerpc64le-gnu@4.18.0':
'@rollup/rollup-linux-powerpc64le-gnu@4.18.1':
optional: true
'@rollup/rollup-linux-riscv64-gnu@4.18.0':
'@rollup/rollup-linux-riscv64-gnu@4.18.1':
optional: true
'@rollup/rollup-linux-s390x-gnu@4.18.0':
'@rollup/rollup-linux-s390x-gnu@4.18.1':
optional: true
'@rollup/rollup-linux-x64-gnu@4.18.0':
'@rollup/rollup-linux-x64-gnu@4.18.1':
optional: true
'@rollup/rollup-linux-x64-musl@4.18.0':
'@rollup/rollup-linux-x64-musl@4.18.1':
optional: true
'@rollup/rollup-win32-arm64-msvc@4.18.0':
'@rollup/rollup-win32-arm64-msvc@4.18.1':
optional: true
'@rollup/rollup-win32-ia32-msvc@4.18.0':
'@rollup/rollup-win32-ia32-msvc@4.18.1':
optional: true
'@rollup/rollup-win32-x64-msvc@4.18.0':
'@rollup/rollup-win32-x64-msvc@4.18.1':
optional: true
'@rushstack/eslint-patch@1.10.3': {}
@ -14196,26 +14202,26 @@ snapshots:
dependencies:
estree-walker: 0.6.1
rollup@4.18.0:
rollup@4.18.1:
dependencies:
'@types/estree': 1.0.5
optionalDependencies:
'@rollup/rollup-android-arm-eabi': 4.18.0
'@rollup/rollup-android-arm64': 4.18.0
'@rollup/rollup-darwin-arm64': 4.18.0
'@rollup/rollup-darwin-x64': 4.18.0
'@rollup/rollup-linux-arm-gnueabihf': 4.18.0
'@rollup/rollup-linux-arm-musleabihf': 4.18.0
'@rollup/rollup-linux-arm64-gnu': 4.18.0
'@rollup/rollup-linux-arm64-musl': 4.18.0
'@rollup/rollup-linux-powerpc64le-gnu': 4.18.0
'@rollup/rollup-linux-riscv64-gnu': 4.18.0
'@rollup/rollup-linux-s390x-gnu': 4.18.0
'@rollup/rollup-linux-x64-gnu': 4.18.0
'@rollup/rollup-linux-x64-musl': 4.18.0
'@rollup/rollup-win32-arm64-msvc': 4.18.0
'@rollup/rollup-win32-ia32-msvc': 4.18.0
'@rollup/rollup-win32-x64-msvc': 4.18.0
'@rollup/rollup-android-arm-eabi': 4.18.1
'@rollup/rollup-android-arm64': 4.18.1
'@rollup/rollup-darwin-arm64': 4.18.1
'@rollup/rollup-darwin-x64': 4.18.1
'@rollup/rollup-linux-arm-gnueabihf': 4.18.1
'@rollup/rollup-linux-arm-musleabihf': 4.18.1
'@rollup/rollup-linux-arm64-gnu': 4.18.1
'@rollup/rollup-linux-arm64-musl': 4.18.1
'@rollup/rollup-linux-powerpc64le-gnu': 4.18.1
'@rollup/rollup-linux-riscv64-gnu': 4.18.1
'@rollup/rollup-linux-s390x-gnu': 4.18.1
'@rollup/rollup-linux-x64-gnu': 4.18.1
'@rollup/rollup-linux-x64-musl': 4.18.1
'@rollup/rollup-win32-arm64-msvc': 4.18.1
'@rollup/rollup-win32-ia32-msvc': 4.18.1
'@rollup/rollup-win32-x64-msvc': 4.18.1
fsevents: 2.3.3
rrweb-cssom@0.6.0: {}
@ -14977,10 +14983,10 @@ snapshots:
- supports-color
- terser
vite-plugin-inspect@0.8.4(rollup@4.18.0)(vite@5.3.3(@types/node@20.11.21)(lightningcss@1.25.1)):
vite-plugin-inspect@0.8.4(rollup@4.18.1)(vite@5.3.3(@types/node@20.11.21)(lightningcss@1.25.1)):
dependencies:
'@antfu/utils': 0.7.10
'@rollup/pluginutils': 5.1.0(rollup@4.18.0)
'@rollup/pluginutils': 5.1.0(rollup@4.18.1)
debug: 4.3.5
error-stack-parser-es: 0.1.4
fs-extra: 11.2.0
@ -14993,7 +14999,7 @@ snapshots:
- rollup
- supports-color
vite-plugin-vue-devtools@7.3.5(rollup@4.18.0)(vite@5.3.3(@types/node@20.11.21)(lightningcss@1.25.1))(vue@3.4.31(typescript@5.5.3)):
vite-plugin-vue-devtools@7.3.5(rollup@4.18.1)(vite@5.3.3(@types/node@20.11.21)(lightningcss@1.25.1))(vue@3.4.31(typescript@5.5.3)):
dependencies:
'@vue/devtools-core': 7.3.5(vite@5.3.3(@types/node@20.11.21)(lightningcss@1.25.1))(vue@3.4.31(typescript@5.5.3))
'@vue/devtools-kit': 7.3.5
@ -15001,7 +15007,7 @@ snapshots:
execa: 8.0.1
sirv: 2.0.4
vite: 5.3.3(@types/node@20.11.21)(lightningcss@1.25.1)
vite-plugin-inspect: 0.8.4(rollup@4.18.0)(vite@5.3.3(@types/node@20.11.21)(lightningcss@1.25.1))
vite-plugin-inspect: 0.8.4(rollup@4.18.1)(vite@5.3.3(@types/node@20.11.21)(lightningcss@1.25.1))
vite-plugin-vue-inspector: 5.1.2(vite@5.3.3(@types/node@20.11.21)(lightningcss@1.25.1))
transitivePeerDependencies:
- '@nuxt/kit'
@ -15028,7 +15034,7 @@ snapshots:
dependencies:
esbuild: 0.21.5
postcss: 8.4.39
rollup: 4.18.0
rollup: 4.18.1
optionalDependencies:
'@types/node': 20.11.21
fsevents: 2.3.3

View File

@ -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);
}
}

View File

@ -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"

View File

@ -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 ą ę

View File

@ -39,6 +39,14 @@ docker pull postgres:latest
docker run -it -e POSTGRES_PASSWORD=pwd -p 5432:5432 postgres
```
then you need to set the following environment variables to use it
```
ENSO_POSTGRES_DATABASE=postgres
ENSO_POSTGRES_USER=postgres
ENSO_POSTGRES_PASSWORD=pwd
```
### Testing SSL connectivity
The SSL connection by providing a root certificate file. The path to this is

View File

@ -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)

View File

@ -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]