From 350cd98661307c6bebcf2fcb13a08bbffe7aa7c0 Mon Sep 17 00:00:00 2001 From: Francesco Mecca Date: Sat, 7 Dec 2024 14:27:39 +0100 Subject: [PATCH] path.exists --- Pentole/native.fs | 2 +- Pentole/path.fs | 42 +++++++++++++++++++++++++----------------- tests/path_tests.fs | 6 ++++++ 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/Pentole/native.fs b/Pentole/native.fs index 570e700..398a8cf 100644 --- a/Pentole/native.fs +++ b/Pentole/native.fs @@ -2,6 +2,7 @@ module internal Pentole.Native open System open System.Runtime.InteropServices +open System.Runtime.CompilerServices [] @@ -10,7 +11,6 @@ extern nativeint _realpath (string _path, nativeint _resolved_path) [] extern nativeint _strerror (int _errnum) - let realpath (path: string) = let ptr = _realpath(path, IntPtr.Zero) if ptr = IntPtr.Zero then diff --git a/Pentole/path.fs b/Pentole/path.fs index 312f1c3..8df2dee 100644 --- a/Pentole/path.fs +++ b/Pentole/path.fs @@ -2,8 +2,8 @@ namespace Pentole open System - -module Internal = +/// don't use +module PathInternal = let private invalid_chars = System.IO.Path.GetInvalidPathChars () let trim (a: string) = @@ -28,13 +28,20 @@ module Internal = type IPath = abstract member ToString: unit -> string + /// The string value of the path. Mainly useful for C# interop. abstract member string_value: string inherit IEquatable inherit IComparable +/// Specifies a location in the file system from the root +/// directory. It is not dependent on the current working directory +/// and provides a complete path to a file or directory. Note that an +/// `AbsolutePath` does not have to correspond to an actual file or +/// directory on the file system. To verify its existence or resolve +/// it to a real file, additional methods in the FileSystem module are provided [] [] -[] +[] type AbsolutePath internal (path: string) = interface IPath with member _.ToString () = $"AbsolutePath {path}" @@ -50,8 +57,15 @@ type AbsolutePath internal (path: string) = interface IEquatable with member _.Equals (o: IPath) = - Internal.trim o.string_value = path - + PathInternal.trim o.string_value = path + +/// Specifies a location in the file system relative to the current +/// working directory. It does not provide a complete path and is +/// dependent on the context in which it is used. Similar to +/// `AbsolutePath`, a `RelativePath` does not have to correspond to an +/// actual file or directory. To verify its existence or resolve +/// it to a real file, additional methods in the FileSystem module are provided +/// should be used. [] [] [] @@ -69,11 +83,12 @@ type RelativePath internal (path: string) = interface IEquatable with member _.Equals (o: IPath) = - Internal.trim o.string_value = path + PathInternal.trim o.string_value = path module Path = + /// Construct a IPath object from the given path. let of_string (path: string): Result = - match Internal.construct path with + match PathInternal.construct path with | Ok (path, true) -> AbsolutePath path :> IPath |> Ok | Ok (path, false) -> RelativePath path :> IPath |> Ok | Error e -> Error e @@ -121,13 +136,6 @@ module Path = /// Returns the parent directory of the given path. /// /// If the path is the root directory or does not have a parent, the original path is returned. - /// - /// # Arguments - /// - /// * `path`: The path to get the parent directory of. - /// - /// # Returns - /// The parent directory of the given path, or the original path if it has no parent let parent (path: IPath) = let parent = IO.Path.GetDirectoryName path.string_value if parent = null then @@ -135,12 +143,12 @@ module Path = else parent |> should_not_fail - -// impure functions -// https://docs.python.org/3.8/library/pathlib.html module FileSystem = let resolve (path: IPath) = Native.realpath path.string_value |> Result.bind Path.of_string + + let exists (path: IPath) = + IO.Path.Exists path.string_value (* let relative_to (parent: Path) (child: Path) = diff --git a/tests/path_tests.fs b/tests/path_tests.fs index 19b83c0..7a7c67b 100644 --- a/tests/path_tests.fs +++ b/tests/path_tests.fs @@ -75,3 +75,9 @@ let parent_test () = "/etc/conf" |> test |> Assert.are_equal (p "/etc") "/etc/../etc" |> test |> Assert.are_equal (p "/etc/../") "etc/../etc" |> test |> Assert.are_equal (p "etc/../") + +[] +let exitsts_test () = + let p (n: string ) = Path.of_string n |> Result.Unsafe.get + FileSystem.exists (p "/tmp/") |> Assert.is_true + FileSystem.exists (p "/IHOPE_this_DOESNT_exist/") |> Assert.is_false