From c93d43d7e3b0d01e4aeafbb961196517b89f9196 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Sun, 26 Apr 2026 04:17:45 +0000
Subject: [PATCH 1/3] feat(stdlib): add pathlib module bindings with 36 tests
Adds F# bindings for Python's pathlib.Path class:
- Path construction (single string and multi-segment)
- Properties: name, stem, suffix, suffixes, parent, parents, parts, root, anchor, drive
- Path arithmetic: / operator (string and Path), joinpath
- Pure transformations: with_name, with_stem, with_suffix, as_posix, as_uri
- I/O predicates: exists, is_file, is_dir, is_symlink, is_mount, is_absolute
- I/O operations: resolve, relative_to, read_text, read_bytes, write_text, write_bytes
- Directory operations: mkdir, mkdir_p, rmdir, iterdir, glob, rglob
- File operations: unlink, rename, replace, expanduser
- Static factories: Path.cwd, Path.home
- is_relative_to (3.9+)
Includes 36 tests covering construction, properties, path arithmetic,
transformations, predicates, file round-trips, and directory operations.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
src/Fable.Python.fsproj | 1 +
src/stdlib/Pathlib.fs | 262 ++++++++++++++++++++++++++++++++++
test/Fable.Python.Test.fsproj | 1 +
test/TestPathlib.fs | 242 +++++++++++++++++++++++++++++++
4 files changed, 506 insertions(+)
create mode 100644 src/stdlib/Pathlib.fs
create mode 100644 test/TestPathlib.fs
diff --git a/src/Fable.Python.fsproj b/src/Fable.Python.fsproj
index 3dff498..e15d3a2 100644
--- a/src/Fable.Python.fsproj
+++ b/src/Fable.Python.fsproj
@@ -27,6 +27,7 @@
+
diff --git a/src/stdlib/Pathlib.fs b/src/stdlib/Pathlib.fs
new file mode 100644
index 0000000..476cb6d
--- /dev/null
+++ b/src/stdlib/Pathlib.fs
@@ -0,0 +1,262 @@
+/// Type bindings for Python pathlib module: https://docs.python.org/3/library/pathlib.html
+module Fable.Python.Pathlib
+
+open System
+open Fable.Core
+
+// fsharplint:disable MemberNames
+
+/// Represents a filesystem path on the current OS (POSIX or Windows).
+/// Paths are immutable; operations return new Path instances.
+/// See https://docs.python.org/3/library/pathlib.html#pathlib.Path
+[]
+type Path(path: string) =
+ /// Construct a Path by joining multiple path segments.
+ /// Equivalent to Path(parts[0]) / parts[1] / …
+ []
+ new([] paths: string[]) = Path("")
+
+ // -------------------------------------------------------------------------
+ // Properties
+ // -------------------------------------------------------------------------
+
+ /// The final path component (file or directory name).
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.name
+ member _.name: string = nativeOnly
+
+ /// The final path component without its last suffix (file extension).
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.stem
+ member _.stem: string = nativeOnly
+
+ /// The last file extension of the final component (e.g. ".py"), or "" if none.
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.suffix
+ member _.suffix: string = nativeOnly
+
+ /// All file extensions of the final component (e.g. [".tar"; ".gz"]).
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.suffixes
+ member _.suffixes: ResizeArray = nativeOnly
+
+ /// The logical parent of the path (directory containing this path).
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.parent
+ member _.parent: Path = nativeOnly
+
+ /// Immutable sequence of the logical ancestors of the path.
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.parents
+ member _.parents: ResizeArray = nativeOnly
+
+ /// The path's components as a tuple of strings.
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.parts
+ member _.parts: ResizeArray = nativeOnly
+
+ /// The root component of the path (e.g. "/" on POSIX), or "".
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.root
+ member _.root: string = nativeOnly
+
+ /// The concatenation of drive and root (e.g. "/" or "C:\\"), or "".
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.anchor
+ member _.anchor: string = nativeOnly
+
+ /// The drive letter or name (relevant on Windows), or "".
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.drive
+ member _.drive: string = nativeOnly
+
+ // -------------------------------------------------------------------------
+ // Path arithmetic
+ // -------------------------------------------------------------------------
+
+ /// Return a new Path by appending a child string segment.
+ /// This mirrors Python's ``path / "child"`` operator.
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.__truediv__
+ []
+ static member (/) (left: Path, right: string) : Path = nativeOnly
+
+ /// Return a new Path by appending another Path.
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.__truediv__
+ []
+ static member (/) (left: Path, right: Path) : Path = nativeOnly
+
+ /// Join one or more path segments to this path and return the result.
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.joinpath
+ []
+ member _.joinpath([] parts: string[]) : Path = nativeOnly
+
+ // -------------------------------------------------------------------------
+ // Tests (pure — no I/O)
+ // -------------------------------------------------------------------------
+
+ /// Return True if the path is absolute (has both a root and, if applicable, a drive).
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.is_absolute
+ member _.is_absolute() : bool = nativeOnly
+
+ /// Return True if this path is relative to other (3.9+).
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.is_relative_to
+ member _.is_relative_to(other: Path) : bool = nativeOnly
+
+ /// Return True if this path is relative to the string path other (3.9+).
+ []
+ member _.is_relative_to(other: string) : bool = nativeOnly
+
+ // -------------------------------------------------------------------------
+ // Transformations (pure — no I/O)
+ // -------------------------------------------------------------------------
+
+ /// Return a new path with the name component replaced.
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.with_name
+ member _.with_name(name: string) : Path = nativeOnly
+
+ /// Return a new path with the stem component replaced (3.9+).
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.with_stem
+ member _.with_stem(stem: string) : Path = nativeOnly
+
+ /// Return a new path with the suffix component replaced.
+ /// Pass "" to remove the suffix.
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.with_suffix
+ member _.with_suffix(suffix: string) : Path = nativeOnly
+
+ /// Return a string representation of the path.
+ /// Equivalent to Python's ``str(path)``.
+ []
+ member _.str() : string = nativeOnly
+
+ /// Return the path as a POSIX string (forward slashes).
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.as_posix
+ member _.as_posix() : string = nativeOnly
+
+ /// Return the path as a URI (file:// scheme). Only absolute paths are supported.
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.as_uri
+ member _.as_uri() : string = nativeOnly
+
+ // -------------------------------------------------------------------------
+ // I/O queries
+ // -------------------------------------------------------------------------
+
+ /// Return True if the path points to an existing filesystem entry.
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.Path.exists
+ member _.exists() : bool = nativeOnly
+
+ /// Return True if the path points to a regular file (follows symlinks).
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.Path.is_file
+ member _.is_file() : bool = nativeOnly
+
+ /// Return True if the path points to a directory (follows symlinks).
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.Path.is_dir
+ member _.is_dir() : bool = nativeOnly
+
+ /// Return True if the path points to a symbolic link.
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.Path.is_symlink
+ member _.is_symlink() : bool = nativeOnly
+
+ /// Return True if the path is a mount point.
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.Path.is_mount
+ member _.is_mount() : bool = nativeOnly
+
+ // -------------------------------------------------------------------------
+ // I/O operations
+ // -------------------------------------------------------------------------
+
+ /// Make the path absolute and resolve any symlinks or ``..`` components.
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.Path.resolve
+ member _.resolve() : Path = nativeOnly
+
+ /// Make the path relative to other, raising ValueError if impossible.
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.relative_to
+ member _.relative_to(other: Path) : Path = nativeOnly
+
+ /// Make the path relative to a string path.
+ []
+ member _.relative_to(other: string) : Path = nativeOnly
+
+ /// Return the decoded contents of the file as a string (UTF-8 by default).
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.Path.read_text
+ member _.read_text() : string = nativeOnly
+
+ /// Return the decoded contents of the file using the given encoding.
+ []
+ member _.read_text(encoding: string) : string = nativeOnly
+
+ /// Return the binary contents of the file as a bytes object.
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.Path.read_bytes
+ member _.read_bytes() : byte[] = nativeOnly
+
+ /// Write a string to the file, returning the number of characters written.
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.Path.write_text
+ []
+ member _.write_text(data: string) : int = nativeOnly
+
+ /// Write a string to the file with the given encoding.
+ []
+ member _.write_text(data: string, encoding: string) : int = nativeOnly
+
+ /// Write binary data to the file, returning the number of bytes written.
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.Path.write_bytes
+ member _.write_bytes(data: byte[]) : int = nativeOnly
+
+ /// Iterate over the directory contents, yielding Path objects.
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.Path.iterdir
+ member _.iterdir() : Path seq = nativeOnly
+
+ /// Glob the given relative pattern in the directory, returning matching paths.
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.Path.glob
+ member _.glob(pattern: string) : Path seq = nativeOnly
+
+ /// Like glob() but descends into sub-directories recursively.
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.Path.rglob
+ member _.rglob(pattern: string) : Path seq = nativeOnly
+
+ /// Create this directory. Raises FileExistsError if it already exists.
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.Path.mkdir
+ member _.mkdir() : unit = nativeOnly
+
+ /// Create this directory with options.
+ /// parents=true creates any missing parent directories.
+ /// exist_ok=true suppresses FileExistsError.
+ []
+ member _.mkdir(mode: int, parents: bool, exist_ok: bool) : unit = nativeOnly
+
+ /// Create this directory and all missing parents (equivalent to ``mkdir -p``).
+ []
+ member _.mkdir_p() : unit = nativeOnly
+
+ /// Remove this directory. The directory must be empty.
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.Path.rmdir
+ member _.rmdir() : unit = nativeOnly
+
+ /// Remove this file (or symbolic link). Raises FileNotFoundError if missing.
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.Path.unlink
+ member _.unlink() : unit = nativeOnly
+
+ /// Remove this file; if missing_ok is true, no error is raised.
+ []
+ member _.unlink(missing_ok: bool) : unit = nativeOnly
+
+ /// Rename the file or directory to target, returning the new Path.
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.Path.rename
+ member _.rename(target: Path) : Path = nativeOnly
+
+ /// Rename the file or directory to a string target, returning the new Path.
+ []
+ member _.rename(target: string) : Path = nativeOnly
+
+ /// Rename to target, overwriting any existing destination.
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.Path.replace
+ member _.replace(target: Path) : Path = nativeOnly
+
+ /// Rename to a string target, overwriting any existing destination.
+ []
+ member _.replace(target: string) : Path = nativeOnly
+
+ /// Expand the ``~`` user home directory shortcut.
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.Path.expanduser
+ member _.expanduser() : Path = nativeOnly
+
+ // -------------------------------------------------------------------------
+ // Static factory methods
+ // -------------------------------------------------------------------------
+
+ /// Return a new Path representing the current working directory.
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.Path.cwd
+ static member cwd() : Path = nativeOnly
+
+ /// Return a new Path representing the user's home directory.
+ /// See https://docs.python.org/3/library/pathlib.html#pathlib.Path.home
+ static member home() : Path = nativeOnly
diff --git a/test/Fable.Python.Test.fsproj b/test/Fable.Python.Test.fsproj
index 441f8a7..423d846 100644
--- a/test/Fable.Python.Test.fsproj
+++ b/test/Fable.Python.Test.fsproj
@@ -33,6 +33,7 @@
+
diff --git a/test/TestPathlib.fs b/test/TestPathlib.fs
new file mode 100644
index 0000000..ca4cad9
--- /dev/null
+++ b/test/TestPathlib.fs
@@ -0,0 +1,242 @@
+module Fable.Python.Tests.Pathlib
+
+open Fable.Python.Testing
+open Fable.Python.Pathlib
+
+// ============================================================================
+// Construction
+// ============================================================================
+
+[]
+let ``test Path construction from string`` () =
+ let p = Path "/tmp"
+ p.str () |> equal "/tmp"
+
+[]
+let ``test Path cwd returns absolute path`` () =
+ let p = Path.cwd ()
+ p.is_absolute () |> equal true
+
+[]
+let ``test Path home returns absolute path`` () =
+ let p = Path.home ()
+ p.is_absolute () |> equal true
+
+// ============================================================================
+// Properties
+// ============================================================================
+
+[]
+let ``test Path name`` () =
+ let p = Path "/foo/bar/baz.txt"
+ p.name |> equal "baz.txt"
+
+[]
+let ``test Path stem`` () =
+ let p = Path "/foo/bar/baz.txt"
+ p.stem |> equal "baz"
+
+[]
+let ``test Path suffix`` () =
+ let p = Path "/foo/bar/baz.txt"
+ p.suffix |> equal ".txt"
+
+[]
+let ``test Path suffix absent`` () =
+ let p = Path "/foo/bar/README"
+ p.suffix |> equal ""
+
+[]
+let ``test Path suffixes multiple`` () =
+ let p = Path "/foo/bar/archive.tar.gz"
+ p.suffixes |> Seq.toList |> equal [ ".tar"; ".gz" ]
+
+[]
+let ``test Path parent`` () =
+ let p = Path "/foo/bar/baz.txt"
+ p.parent.str () |> equal "/foo/bar"
+
+[]
+let ``test Path root on absolute path`` () =
+ let p = Path "/foo/bar"
+ p.root |> equal "/"
+
+[]
+let ``test Path anchor`` () =
+ let p = Path "/foo/bar"
+ p.anchor |> equal "/"
+
+// ============================================================================
+// Path arithmetic
+// ============================================================================
+
+[]
+let ``test Path slash operator with string`` () =
+ let p = Path "/foo" / "bar"
+ p.str () |> equal "/foo/bar"
+
+[]
+let ``test Path slash operator chained`` () =
+ let p = Path "/foo" / "bar" / "baz"
+ p.str () |> equal "/foo/bar/baz"
+
+[]
+let ``test Path slash operator with Path`` () =
+ let base' = Path "/foo"
+ let child = Path "bar"
+ let p = base' / child
+ p.str () |> equal "/foo/bar"
+
+[]
+let ``test Path joinpath`` () =
+ let p = Path("/foo").joinpath ("bar", "baz")
+ p.str () |> equal "/foo/bar/baz"
+
+// ============================================================================
+// Transformations (pure)
+// ============================================================================
+
+[]
+let ``test Path with_name`` () =
+ let p = Path "/foo/bar/baz.txt"
+ p.with_name("qux.txt").str () |> equal "/foo/bar/qux.txt"
+
+[]
+let ``test Path with_stem`` () =
+ let p = Path "/foo/bar/baz.txt"
+ p.with_stem("qux").str () |> equal "/foo/bar/qux.txt"
+
+[]
+let ``test Path with_suffix`` () =
+ let p = Path "/foo/bar/baz.txt"
+ p.with_suffix(".py").str () |> equal "/foo/bar/baz.py"
+
+[]
+let ``test Path with_suffix empty removes extension`` () =
+ let p = Path "/foo/bar/baz.txt"
+ p.with_suffix("").str () |> equal "/foo/bar/baz"
+
+[]
+let ``test Path as_posix`` () =
+ let p = Path "/foo/bar/baz.txt"
+ p.as_posix () |> equal "/foo/bar/baz.txt"
+
+// ============================================================================
+// is_* predicates
+// ============================================================================
+
+[]
+let ``test Path is_absolute true`` () =
+ let p = Path "/foo/bar"
+ p.is_absolute () |> equal true
+
+[]
+let ``test Path is_absolute false`` () =
+ let p = Path "foo/bar"
+ p.is_absolute () |> equal false
+
+[]
+let ``test Path is_relative_to`` () =
+ let p = Path "/foo/bar/baz"
+ p.is_relative_to (Path "/foo") |> equal true
+
+[]
+let ``test Path is_relative_to string`` () =
+ let p = Path "/foo/bar/baz"
+ p.is_relative_to "/foo" |> equal true
+
+[]
+let ``test Path is_relative_to false`` () =
+ let p = Path "/foo/bar"
+ p.is_relative_to (Path "/baz") |> equal false
+
+// ============================================================================
+// I/O queries on a real temp file
+// ============================================================================
+
+[]
+let ``test Path exists true for cwd`` () =
+ Path.cwd().exists () |> equal true
+
+[]
+let ``test Path exists false for nonexistent`` () =
+ let p = Path "/nonexistent_repo_assist_xyz"
+ p.exists () |> equal false
+
+[]
+let ``test Path is_dir true for cwd`` () =
+ Path.cwd().is_dir () |> equal true
+
+[]
+let ``test Path is_file false for cwd`` () =
+ Path.cwd().is_file () |> equal false
+
+[]
+let ``test Path resolve returns absolute`` () =
+ let p = Path "."
+ p.resolve().is_absolute () |> equal true
+
+[]
+let ``test Path relative_to`` () =
+ let p = Path "/foo/bar/baz"
+ p.relative_to(Path "/foo/bar").str () |> equal "baz"
+
+[]
+let ``test Path relative_to string`` () =
+ let p = Path "/foo/bar/baz"
+ p.relative_to("/foo/bar").str () |> equal "baz"
+
+// ============================================================================
+// File round-trip: write_text / read_text / unlink
+// ============================================================================
+
+[]
+let ``test Path write_text and read_text`` () =
+ let tmp = Path.cwd () / "__pathlib_test_write__.txt"
+ tmp.write_text "hello pathlib" |> ignore
+ let content = tmp.read_text ()
+ tmp.unlink (missing_ok = true)
+ content |> equal "hello pathlib"
+
+[]
+let ``test Path write_bytes and read_bytes`` () =
+ let tmp = Path.cwd () / "__pathlib_test_bytes__.bin"
+ let data: byte[] = [| 0uy; 1uy; 2uy; 255uy |]
+ tmp.write_bytes data |> ignore
+ let result = tmp.read_bytes ()
+ tmp.unlink (missing_ok = true)
+ result |> equal data
+
+[]
+let ``test Path unlink missing_ok suppresses error`` () =
+ let tmp = Path "/nonexistent_repo_assist_unlink_xyz.txt"
+ // Should not raise
+ tmp.unlink (missing_ok = true)
+ true |> equal true
+
+// ============================================================================
+// Directory operations
+// ============================================================================
+
+[]
+let ``test Path mkdir_p and rmdir`` () =
+ let dir = Path.cwd () / "__pathlib_test_dir__"
+ dir.mkdir_p ()
+ dir.is_dir () |> equal true
+ dir.rmdir ()
+ dir.exists () |> equal false
+
+[]
+let ``test Path iterdir returns entries`` () =
+ let dir = Path.cwd ()
+ let entries = dir.iterdir () |> Seq.toList
+ entries.Length > 0 |> equal true
+
+[]
+let ``test Path glob`` () =
+ // Create a file, glob for it, clean up
+ let tmp = Path.cwd () / "__pathlib_glob_test__.txt"
+ tmp.write_text "glob" |> ignore
+ let matches = (Path.cwd ()).glob "__pathlib_glob_test__*.txt" |> Seq.toList
+ tmp.unlink (missing_ok = true)
+ matches.Length >= 1 |> equal true
From 1217c7a6768e11edc83fc08d59f0e9be814b1ade Mon Sep 17 00:00:00 2001
From: Dag Brattli
Date: Sun, 26 Apr 2026 12:58:28 +0200
Subject: [PATCH 2/3] fix(pathlib): make Path constructor emit positional args
Fable emits primary-ctor parameters as Python kwargs, but
pathlib.Path.__init__ does not accept `path=` as a keyword, breaking
27 tests with `TypeError: PurePath.__init__() got an unexpected
keyword argument 'path'`. Switch to a no-arg primary ctor and declare
the string and varargs ctors via [] so emission stays
positional. Also relax suffixes/parents/parts to `seq<_>` to match the
underlying tuple/list/_PathParents return types, and wrap the byte
fixture in builtins.bytes so write_bytes receives a real bytes object
instead of a fable.UInt8Array.
Co-Authored-By: Claude Opus 4.7 (1M context)
---
src/stdlib/Pathlib.fs | 19 +++++++++++++------
test/TestPathlib.fs | 8 +++++++-
2 files changed, 20 insertions(+), 7 deletions(-)
diff --git a/src/stdlib/Pathlib.fs b/src/stdlib/Pathlib.fs
index 476cb6d..4523c62 100644
--- a/src/stdlib/Pathlib.fs
+++ b/src/stdlib/Pathlib.fs
@@ -8,13 +8,20 @@ open Fable.Core
/// Represents a filesystem path on the current OS (POSIX or Windows).
/// Paths are immutable; operations return new Path instances.
+///
+/// `Path()` represents the current directory (`.`). For multi-segment construction
+/// use the `/` operator (`Path "a" / "b" / "c"`) or `joinpath`.
/// See https://docs.python.org/3/library/pathlib.html#pathlib.Path
[]
-type Path(path: string) =
+type Path() =
+ /// Construct a Path from a single string segment.
+ []
+ new(path: string) = Path()
+
/// Construct a Path by joining multiple path segments.
- /// Equivalent to Path(parts[0]) / parts[1] / …
+ /// Equivalent to ``Path(parts[0]) / parts[1] / …``.
[]
- new([] paths: string[]) = Path("")
+ new([] paths: string[]) = Path()
// -------------------------------------------------------------------------
// Properties
@@ -34,7 +41,7 @@ type Path(path: string) =
/// All file extensions of the final component (e.g. [".tar"; ".gz"]).
/// See https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.suffixes
- member _.suffixes: ResizeArray = nativeOnly
+ member _.suffixes: string seq = nativeOnly
/// The logical parent of the path (directory containing this path).
/// See https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.parent
@@ -42,11 +49,11 @@ type Path(path: string) =
/// Immutable sequence of the logical ancestors of the path.
/// See https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.parents
- member _.parents: ResizeArray = nativeOnly
+ member _.parents: Path seq = nativeOnly
/// The path's components as a tuple of strings.
/// See https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.parts
- member _.parts: ResizeArray = nativeOnly
+ member _.parts: string seq = nativeOnly
/// The root component of the path (e.g. "/" on POSIX), or "".
/// See https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.root
diff --git a/test/TestPathlib.fs b/test/TestPathlib.fs
index ca4cad9..25854d4 100644
--- a/test/TestPathlib.fs
+++ b/test/TestPathlib.fs
@@ -2,6 +2,7 @@ module Fable.Python.Tests.Pathlib
open Fable.Python.Testing
open Fable.Python.Pathlib
+open Fable.Python.Builtins
// ============================================================================
// Construction
@@ -12,6 +13,11 @@ let ``test Path construction from string`` () =
let p = Path "/tmp"
p.str () |> equal "/tmp"
+[]
+let ``test Path construction from multiple segments`` () =
+ let p = Path("/foo", "bar", "baz.txt")
+ p.str () |> equal "/foo/bar/baz.txt"
+
[]
let ``test Path cwd returns absolute path`` () =
let p = Path.cwd ()
@@ -201,7 +207,7 @@ let ``test Path write_text and read_text`` () =
[]
let ``test Path write_bytes and read_bytes`` () =
let tmp = Path.cwd () / "__pathlib_test_bytes__.bin"
- let data: byte[] = [| 0uy; 1uy; 2uy; 255uy |]
+ let data = builtins.bytes [| 0uy; 1uy; 2uy; 255uy |]
tmp.write_bytes data |> ignore
let result = tmp.read_bytes ()
tmp.unlink (missing_ok = true)
From e7ad51895029e8626b17288c05b27142f88fbede Mon Sep 17 00:00:00 2001
From: Dag Brattli
Date: Sun, 26 Apr 2026 13:02:54 +0200
Subject: [PATCH 3/3] style: restore indentation on Pathlib.fs/TestPathlib.fs
lines
Lost during the merge conflict resolution.
Co-Authored-By: Claude Opus 4.7 (1M context)
---
src/Fable.Python.fsproj | 2 +-
test/Fable.Python.Test.fsproj | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/Fable.Python.fsproj b/src/Fable.Python.fsproj
index c4817d5..180e747 100644
--- a/src/Fable.Python.fsproj
+++ b/src/Fable.Python.fsproj
@@ -28,7 +28,7 @@
-
+
diff --git a/test/Fable.Python.Test.fsproj b/test/Fable.Python.Test.fsproj
index 910601e..3cf0beb 100644
--- a/test/Fable.Python.Test.fsproj
+++ b/test/Fable.Python.Test.fsproj
@@ -34,7 +34,7 @@
-
+