Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 34 additions & 1 deletion src/stdlib/Os.fs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ type IExports =
/// Return the value of the environment variable key or default if not set
/// See https://docs.python.org/3/library/os.html#os.getenv
abstract getenv: key: string * ``default``: string -> string
/// Return the current process id.
/// See https://docs.python.org/3/library/os.html#os.getpid
abstract getpid: unit -> int
/// Return the parent process id.
/// See https://docs.python.org/3/library/os.html#os.getppid
abstract getppid: unit -> int
/// Send signal sig to the process pid
/// See https://docs.python.org/3/library/os.html#os.kill
abstract kill: pid: int * ``sig``: int -> unit
Expand All @@ -42,8 +48,14 @@ type IExports =
/// Recursive directory creation function
/// See https://docs.python.org/3/library/os.html#os.makedirs
abstract makedirs: path: string -> unit
/// Recursive directory creation with optional mode and exist_ok flag
/// Recursive directory creation, creating parent directories as needed.
/// Raises FileExistsError if the directory already exists and exist_ok is false.
/// See https://docs.python.org/3/library/os.html#os.makedirs
[<Emit("$0.makedirs($1, exist_ok=$2)")>]
abstract makedirs: path: string * exist_ok: bool -> unit
/// Recursive directory creation with explicit mode and exist_ok flag.
/// See https://docs.python.org/3/library/os.html#os.makedirs
[<Emit("$0.makedirs($1, $2, $3)")>]
abstract makedirs: path: string * mode: int * exist_ok: bool -> unit
/// Set the environment variable named key to the string value
/// See https://docs.python.org/3/library/os.html#os.putenv
Expand All @@ -60,6 +72,15 @@ type IExports =
/// Remove (delete) the directory path
/// See https://docs.python.org/3/library/os.html#os.rmdir
abstract rmdir: path: string -> unit
/// Walk a directory tree, yielding (dirpath, dirnames, filenames) for each directory.
/// When topdown is true (the default) the caller can modify the dirnames list in-place
/// to prune the search or impose a specific visiting order.
/// See https://docs.python.org/3/library/os.html#os.walk
abstract walk: top: string -> seq<string * ResizeArray<string> * ResizeArray<string>>
/// Walk a directory tree top-down or bottom-up (topdown=false).
/// See https://docs.python.org/3/library/os.html#os.walk
[<Emit("$0.walk($1, topdown=$2)")>]
abstract walk: top: string * topdown: bool -> seq<string * ResizeArray<string> * ResizeArray<string>>
/// Test whether a path exists
/// See https://docs.python.org/3/library/os.path.html#os.path.exists
abstract path: PathModule
Expand Down Expand Up @@ -96,6 +117,18 @@ and [<Erase>] PathModule =
/// 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
/// Return True if path is an absolute pathname
/// See https://docs.python.org/3/library/os.path.html#os.path.isabs
abstract isabs: path: string -> bool
/// Return True if path refers to a symbolic link
/// See https://docs.python.org/3/library/os.path.html#os.path.islink
abstract islink: path: string -> bool
/// Return the canonical path of the specified filename, resolving symlinks
/// See https://docs.python.org/3/library/os.path.html#os.path.realpath
abstract realpath: path: string -> string
/// Return the size, in bytes, of path
/// See https://docs.python.org/3/library/os.path.html#os.path.getsize
abstract getsize: path: string -> int64


/// Miscellaneous operating system interfaces
Expand Down
69 changes: 69 additions & 0 deletions test/TestOs.fs
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,72 @@ let ``test os.listdir works`` () =
let entries = os.listdir "."
// Current directory should have at least some entries
entries.Length > 0 |> equal true

[<Fact>]
let ``test os.path.isabs works`` () =
os.path.isabs "/absolute/path" |> equal true
os.path.isabs "relative/path" |> equal false
os.path.isabs "." |> equal false

[<Fact>]
let ``test os.path.realpath works`` () =
let real = os.path.realpath "."
real.StartsWith("/") |> equal true
// realpath should not contain symlink components; at minimum equal to abspath for "."
real.Length > 0 |> equal true

[<Fact>]
let ``test os.path.islink works`` () =
// "." is never a symlink
os.path.islink "." |> equal false

[<Fact>]
let ``test os.path.getsize works`` () =
// The test directory itself has a positive size
os.path.getsize "." > 0L |> equal true

[<Fact>]
let ``test os.getpid works`` () =
let pid = os.getpid ()
pid > 0 |> equal true

[<Fact>]
let ``test os.getppid works`` () =
let ppid = os.getppid ()
ppid > 0 |> equal true

[<Fact>]
let ``test os.makedirs with exist_ok works`` () =
let dir = sprintf "/tmp/fable_test_makedirs_%d" (os.getpid ())
os.makedirs (dir, true)
os.path.isdir dir |> equal true
// Second call must not raise when exist_ok=true
os.makedirs (dir, true)
os.path.isdir dir |> equal true
os.rmdir dir

[<Fact>]
let ``test os.walk yields entries`` () =
let entries = os.walk "." |> Seq.truncate 1 |> Seq.toList
entries.Length |> equal 1
let dirpath, subdirs, files = entries.[0]
dirpath |> equal "."
// The first walk entry's dirnames + filenames should equal listdir of the root
let walkAll = Seq.append subdirs files |> Seq.sort |> Seq.toList
let listdirAll = os.listdir "." |> Array.sort |> Array.toList
walkAll |> equal listdirAll

[<Fact>]
let ``test os.walk with topdown=false works`` () =
let root = sprintf "/tmp/fable_test_walk_%d" (os.getpid ())
let nested = os.path.join (root, "nested")
os.makedirs (nested, true)
let entries = os.walk (root, false) |> Seq.toList
// Bottom-up: deepest dir is yielded first, root is yielded last
entries.Length |> equal 2
let firstDir, _, _ = entries.[0]
let lastDir, _, _ = List.last entries
firstDir |> equal nested
lastDir |> equal root
os.rmdir nested
os.rmdir root
Loading