diff --git a/src/stdlib/Builtins.fs b/src/stdlib/Builtins.fs index 7495f92..6dcb665 100644 --- a/src/stdlib/Builtins.fs +++ b/src/stdlib/Builtins.fs @@ -200,6 +200,30 @@ type IExports = abstract int: obj -> int /// Object to float abstract float: obj -> float + + /// Return the largest item in an iterable or the largest of two or more arguments. + abstract max: 'T * 'T -> 'T + /// Return the largest item in an iterable or the largest of two or more arguments. + abstract max: 'T * 'T * 'T -> 'T + /// Return the largest item in an iterable or the largest of two or more arguments. + abstract max: IEnumerable<'T> -> 'T + + /// Return the smallest item in an iterable or the smallest of two or more arguments. + abstract min: 'T * 'T -> 'T + /// Return the smallest item in an iterable or the smallest of two or more arguments. + abstract min: 'T * 'T * 'T -> 'T + /// Return the smallest item in an iterable or the smallest of two or more arguments. + abstract min: IEnumerable<'T> -> 'T + + /// Return the sum of a 'start' value (default: 0) plus an iterable of numbers. + abstract sum: IEnumerable<'T> -> 'T + + /// Return True if bool(x) is True for all values x in the iterable. + abstract all: IEnumerable -> bool + + /// Return True if bool(x) is True for any x in the iterable. + abstract any: IEnumerable -> bool + abstract print: obj: obj -> unit [] diff --git a/src/stdlib/Os.fs b/src/stdlib/Os.fs index e482e3e..d366bce 100644 --- a/src/stdlib/Os.fs +++ b/src/stdlib/Os.fs @@ -84,6 +84,18 @@ and [] PathModule = /// Return the base name of pathname path /// See https://docs.python.org/3/library/os.path.html#os.path.basename abstract basename: path: string -> string + /// Return the argument with an initial component of ~ or ~user replaced + /// See https://docs.python.org/3/library/os.path.html#os.path.expanduser + abstract expanduser: path: string -> string + /// Return a normalized absolutized version of the pathname path + /// See https://docs.python.org/3/library/os.path.html#os.path.abspath + abstract abspath: path: string -> string + /// Split the pathname path into a pair (head, tail) + /// See https://docs.python.org/3/library/os.path.html#os.path.split + abstract split: path: string -> string * string + /// Split the pathname path into a pair (root, ext) + /// See https://docs.python.org/3/library/os.path.html#os.path.splitext + abstract splitext: path: string -> string * string /// Miscellaneous operating system interfaces diff --git a/test/Fable.Python.Test.fsproj b/test/Fable.Python.Test.fsproj index fce4bbc..bdd274b 100644 --- a/test/Fable.Python.Test.fsproj +++ b/test/Fable.Python.Test.fsproj @@ -16,6 +16,7 @@ + diff --git a/test/TestBuiltins.fs b/test/TestBuiltins.fs index 6d6206c..8b489cc 100644 --- a/test/TestBuiltins.fs +++ b/test/TestBuiltins.fs @@ -2,6 +2,7 @@ module Fable.Python.Tests.Builtins open Util.Testing open Fable.Python.Builtins +open Fable.Python.Os [] let ``test print works`` () = @@ -12,5 +13,55 @@ let ``test __name__ works`` () = __name__ |> equal "test_builtins" [] let ``test write works`` () = - let result = builtins.``open``("test.txt", OpenTextMode.Write) + let tempFile = os.path.join (os.path.expanduser "~", ".fable_test_temp.txt") + let result = builtins.``open``(tempFile, OpenTextMode.Write) result.write "ABC" |> equal 3 + result.Dispose() + os.remove tempFile + +[] +let ``test max with two arguments works`` () = + builtins.max (3, 5) |> equal 5 + builtins.max (10, 2) |> equal 10 + +[] +let ``test max with three arguments works`` () = + builtins.max (3, 5, 1) |> equal 5 + builtins.max (1, 2, 10) |> equal 10 + +[] +let ``test max with iterable works`` () = + builtins.max [1; 2; 3; 4; 5] |> equal 5 + builtins.max [10; -5; 3] |> equal 10 + +[] +let ``test min with two arguments works`` () = + builtins.min (3, 5) |> equal 3 + builtins.min (10, 2) |> equal 2 + +[] +let ``test min with three arguments works`` () = + builtins.min (3, 5, 1) |> equal 1 + builtins.min (1, 2, 10) |> equal 1 + +[] +let ``test min with iterable works`` () = + builtins.min [1; 2; 3; 4; 5] |> equal 1 + builtins.min [10; -5; 3] |> equal -5 + +[] +let ``test sum works`` () = + builtins.sum [1; 2; 3; 4; 5] |> equal 15 + builtins.sum [10; -5; 3] |> equal 8 + +[] +let ``test all works`` () = + builtins.all [true; true; true] |> equal true + builtins.all [true; false; true] |> equal false + builtins.all [] |> equal true + +[] +let ``test any works`` () = + builtins.any [false; false; true] |> equal true + builtins.any [false; false; false] |> equal false + builtins.any [] |> equal false diff --git a/test/TestJson.fs b/test/TestJson.fs index 76912cc..7e4fb3b 100644 --- a/test/TestJson.fs +++ b/test/TestJson.fs @@ -20,3 +20,33 @@ let ``test json loads works`` () = let object = {| Foo = 10; Bar = "test" |} let result: {| Foo: int; Bar: string |} = unbox (json.loads input) result |> equal object + +[] +let ``test json.dumps with nativeint works`` () = + let value: nativeint = 42n + let result = json.dumps value + result |> equal "42" + +[] +let ``test json.dumps with ResizeArray of nativeint works`` () = + let values = ResizeArray([1n; 2n; 3n]) + let result = json.dumps values + result |> equal "[1, 2, 3]" + +[] +let ``test json.dumps with nested object works`` () = + let obj = {| Name = "test"; Values = ResizeArray([1n; 2n; 3n]) |} + let result = dumps obj + result |> equal """{"Name": "test", "Values": [1, 2, 3]}""" + +[] +let ``test json.loads with array works`` () = + let input = "[1, 2, 3]" + let result: int array = unbox (json.loads input) + result.Length |> equal 3 + +[] +let ``test json.dumps with indent works`` () = + let obj = {| A = 1n |} + let result = dumpsIndented obj 2 + result.Contains("\n") |> equal true diff --git a/test/TestOs.fs b/test/TestOs.fs new file mode 100644 index 0000000..8197f6d --- /dev/null +++ b/test/TestOs.fs @@ -0,0 +1,61 @@ +module Fable.Python.Tests.Os + +open Util.Testing +open Fable.Python.Os + +[] +let ``test os.path.exists works`` () = + os.path.exists "." |> equal true + os.path.exists "nonexistent_path_xyz" |> equal false + +[] +let ``test os.path.isdir works`` () = + os.path.isdir "." |> equal true + +[] +let ``test os.path.join works`` () = + os.path.join ("a", "b", "c") |> equal "a/b/c" + +[] +let ``test os.path.dirname works`` () = + os.path.dirname "/foo/bar/baz.txt" |> equal "/foo/bar" + +[] +let ``test os.path.basename works`` () = + os.path.basename "/foo/bar/baz.txt" |> equal "baz.txt" + +[] +let ``test os.path.expanduser works`` () = + let expanded = os.path.expanduser "~" + // The expanded path should not start with ~ anymore + expanded.StartsWith("~") |> equal false + +[] +let ``test os.path.abspath works`` () = + let absPath = os.path.abspath "." + // Absolute path should start with / + absPath.StartsWith("/") |> equal true + +[] +let ``test os.path.split works`` () = + let head, tail = os.path.split "/foo/bar/baz.txt" + head |> equal "/foo/bar" + tail |> equal "baz.txt" + +[] +let ``test os.path.splitext works`` () = + let root, ext = os.path.splitext "/foo/bar/baz.txt" + root |> equal "/foo/bar/baz" + ext |> equal ".txt" + +[] +let ``test os.getcwd works`` () = + let cwd = os.getcwd () + // Current working directory should be a non-empty string + cwd.Length > 0 |> equal true + +[] +let ``test os.listdir works`` () = + let entries = os.listdir "." + // Current directory should have at least some entries + entries.Length > 0 |> equal true