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
9 changes: 9 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,15 @@ jobs:
if: matrix.platform == 'ubuntu-latest'
run: ./build.sh fable-library --python

# PEP 561 requires the marker inside the package directory. CopyStage filters
# by extension, so it is easy to drop again; without it mypy refuses to read
# the core/*.pyi stubs at all.
- name: PEP 561 marker survives staging
if: matrix.platform == 'ubuntu-latest'
run: |
test -f temp/fable-library-py/fable_library/py.typed \
|| { echo "::error::fable_library/py.typed missing from staged package; stubs would be inert for mypy"; exit 1; }

- name: Fable Library - Python (Windows)
if: matrix.platform == 'windows-latest'
run: .\build.bat fable-library --python
Expand Down
6 changes: 6 additions & 0 deletions src/Fable.Build/FableLibrary/Python.fs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ type BuildFableLibraryPython(?skipCore: bool, ?postFableBuildStage: unit -> unit
Directory.GetFiles(this.LibraryDir, "*") |> Shell.copyFiles this.BuildDir
Directory.GetFiles(this.SourceDir, "*.py") |> Shell.copyFiles this.OutDir

// PEP 561 marker. It has to sit *inside* the package directory for type
// checkers to read the stubs at all, and the `*.py` filter above drops it --
// which is why every published wheel so far has shipped `core/*.pyi` that no
// consumer could see.
[ Path.Combine(this.SourceDir, "py.typed") ] |> Shell.copyFiles this.OutDir

// Python extension modules
Directory.GetFiles(Path.Combine(this.SourceDir, "core"), "*")
|> Shell.copyFiles (Path.Combine(this.OutDir, "core"))
Expand Down
1 change: 0 additions & 1 deletion src/fable-library-py/py.typed

This file was deleted.

30 changes: 21 additions & 9 deletions src/fable-library-py/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,32 @@ dev = [
"pydantic>=2.13.4",
]

[tool.hatch.build.targets.sdist]
include = ["./fable_library"]

[tool.hatch.build.targets.wheel]
include = ["./fable_library"]

[tool.hatch.build.targets.wheel.sources]
"./fable_library" = "fable_library"
# Note: there is deliberately no [tool.hatch.*] config here. `build-backend` below
# is maturin, so hatch settings would be dead config that merely *looks* like it
# governs what ships -- which is a good way for a packaging bug to go unnoticed.

[tool.maturin]
python-source = "." # Look at project root
module-name = "fable_library.core._core" # Full module path
features = ["pyo3/extension-module"]

# `Fable.Library.Python.fsproj` lives inside the package directory, so `dotnet build`
# drops MSBuild output into `fable_library/obj/`. With `python-source = "."` maturin
# would package that wholesale, and one of those paths contains a comma
# (`.NETCoreApp,Version=v10.0.AssemblyAttributes.fs`) -- RECORD is CSV, so the
# resulting wheel is rejected by `uv pip install` as malformed. `pip` is lenient
# enough to survive it, which makes the failure look intermittent.
#
# None of this shows up in a clean CI checkout, only for contributors who have run
# `dotnet build`. Excluding here fixes it regardless of build order; deleting `obj/`
# in the build script would not, since it regenerates on the next build.
exclude = [
"fable_library/obj/**/*",
"**/__pycache__/**/*",
"fable_library/*.fs",
"fable_library/*.fsproj",
]

[tool.ty.environment]
python-version = "3.12"

Expand All @@ -56,5 +68,5 @@ testpaths = ["tests", "tests-benchmark"]
addopts = "--benchmark-columns=min,max,mean,stddev,iqr"

[build-system]
requires = ["hatchling", "maturin>=1.5,<2.0"]
requires = ["maturin>=1.5,<2.0"]
build-backend = "maturin"
Loading