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
3 changes: 0 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,6 @@ jobs:
with:
dotnet-version: "10.0.x"

- name: Setup dotnet tools
run: dotnet tool restore

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v6
with:
Expand Down
106 changes: 106 additions & 0 deletions .github/workflows/python-type-checking.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
name: Python Type Checking

on:
pull_request:
branches: [main]
paths:
- 'src/Fable.Transforms/Python/**'
- 'src/fable-library-py/**'
- 'tests/Python/**'
- 'pyrightconfig.ci.json'
- 'pyproject.toml'

permissions:
contents: read
pull-requests: write

jobs:
pyright:
runs-on: ubuntu-latest
env:
UV_LINK_MODE: copy

steps:
- uses: actions/checkout@v5

- name: Setup .NET
uses: actions/setup-dotnet@v5
with:
dotnet-version: "10.0.x"

- name: Setup dotnet tools
run: dotnet tool restore

- name: Set up Python 3.12
uses: actions/setup-python@v6
with:
python-version: "3.12"

- name: Install uv
run: |
pipx install uv
pipx install maturin

- name: Build Python (compile only)
run: ./build.sh test python --compile-only

- name: Run Pyright (standard mode)
id: pyright
continue-on-error: true
run: |
if uv run pyright --project pyrightconfig.ci.json temp/tests/Python/ temp/fable-library-py/; then
echo "result=:white_check_mark: All non-excluded files pass" >> $GITHUB_OUTPUT
echo "passed=true" >> $GITHUB_OUTPUT
else
echo "result=:x: Type errors found in non-excluded files" >> $GITHUB_OUTPUT
echo "passed=false" >> $GITHUB_OUTPUT
fi

- name: Get excluded files
id: excluded
run: |
COUNT=$(grep -c '"temp/' pyrightconfig.ci.json || echo "0")
echo "count=$COUNT" >> $GITHUB_OUTPUT
FILES=$(grep '"temp/' pyrightconfig.ci.json | sed 's/.*"temp/temp/' | sed 's/".*//' | sort)
echo "files<<EOF" >> $GITHUB_OUTPUT
echo "$FILES" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT

- name: Find existing comment
uses: peter-evans/find-comment@v3
id: find-comment
with:
issue-number: ${{ github.event.pull_request.number }}
comment-author: 'github-actions[bot]'
body-includes: Python Type Checking

- name: Create or update PR comment
uses: peter-evans/create-or-update-comment@v4
with:
comment-id: ${{ steps.find-comment.outputs.comment-id }}
issue-number: ${{ github.event.pull_request.number }}
edit-mode: replace
body: |
## Python Type Checking (Pyright) Results

${{ steps.pyright.outputs.result }}

| Metric | Value |
| -------------- | ----------------------------------- |
| Excluded files | ${{ steps.excluded.outputs.count }} |

<details>
<summary>Files excluded from type checking</summary>

These files have known type errors and are excluded from CI. Remove from `pyrightconfig.ci.json` as errors are fixed.

```
${{ steps.excluded.outputs.files }}
```

</details>

- name: Fail if type errors
if: false # Temporarily disabled
# if: steps.pyright.outputs.passed == 'false'
run: exit 1
13 changes: 13 additions & 0 deletions pyrightconfig.ci.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"extends": "./pyrightconfig.json",
"exclude": [
"**/.venv/**",
"**/node_modules/**",
"temp/fable-library-py/fable_library/list.py",
"temp/tests/Python/test_applicative.py",
"temp/tests/Python/test_map.py",
"temp/tests/Python/test_misc.py",
"temp/tests/Python/test_type.py",
"temp/tests/Python/fable_modules/thoth_json_python/encode.py"
]
}
14 changes: 10 additions & 4 deletions src/Fable.Build/FableLibrary/Python.fs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ open Build.Utils
open SimpleExec
open BlackFox.CommandLine

type BuildFableLibraryPython() =
type BuildFableLibraryPython(?skipCore: bool) =
inherit
BuildFableLibrary(
language = "python",
Expand All @@ -16,6 +16,8 @@ type BuildFableLibraryPython() =
outDir = Path.Combine("temp", "fable-library-py", "fable_library")
)

let skipCore = defaultArg skipCore false

override this.CopyStage() =
// Copy all Python/F# files to the build directory
Directory.GetFiles(this.LibraryDir, "*") |> Shell.copyFiles this.BuildDir
Expand All @@ -33,7 +35,11 @@ type BuildFableLibraryPython() =
override this.PostFableBuildStage() =
// Install the python dependencies at the root of the project
Command.Run("uv", "sync", this.BuildDir) // Maturin needs a local virtual environment
Command.Run("uv", "run maturin develop --release", this.BuildDir)

if skipCore then
printfn "Skipping fable-library-core (Rust) build"
else
Command.Run("uv", "run maturin develop --release", this.BuildDir)

// Fix issues with Fable .fsproj not supporting links, so we need to copy the
// files ourself to the output directory
Expand All @@ -44,7 +50,7 @@ type BuildFableLibraryPython() =

Shell.deleteDir (this.BuildDir </> "fable_library/fable-library-ts")

// Run Ruff linter checking import sorting and fix any issues
Command.Run("uv", $"run ruff check --select I --fix {this.BuildDir}")
// Run Ruff linter checking import sorting, removing unused imports, and fix any issues
Command.Run("uv", $"run ruff check --select I,F401 --fix {this.BuildDir}")
// Run Ruff formatter on all generated files
Command.Run("uv", $"run ruff format {this.BuildDir}")
3 changes: 2 additions & 1 deletion src/Fable.Build/Main.fs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ Available commands:
--threaded Compile and run the tests with the threaded runtime

Options for Python:
--typing Run type checking with Pyright and show the summary
--type-check Run type checking on the generated code with Pyright
--format Format the code generated code with Ruff formatter

standalone Compile standalone + worker version of Fable running
on top of of Node.js
Expand Down
4 changes: 3 additions & 1 deletion src/Fable.Build/Quicktest/Python.fs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ open Build.Utils
let private fableLibraryBuildDir = Path.Resolve("temp", "fable-library-py")

let handle (args: string list) =
let skipFableLibraryCore = args |> List.contains "--skip-fable-library-core"

// Install local fable-library as editable package for testing
// This ensures quicktest uses the locally built version, not PyPI
if not (args |> List.contains "--skip-fable-library") then
BuildFableLibraryPython().Run(false)
BuildFableLibraryPython(skipCore = skipFableLibraryCore).Run(false)
// Install fable-library in editable mode
Command.Run("uv", $"pip install -e {fableLibraryBuildDir}")

Expand Down
13 changes: 7 additions & 6 deletions src/Fable.Build/Test/Python.fs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ let private fableLibraryBuildDir = Path.Resolve("temp", "fable-library-py")

let handle (args: string list) =
let skipFableLibrary = args |> List.contains "--skip-fable-library"
let skipFableLibraryCore = args |> List.contains "--skip-fable-library-core"
let isWatch = args |> List.contains "--watch"
let noDotnet = args |> List.contains "--no-dotnet"
let runTyping = args |> List.contains "--typing"
let runTyping = args |> List.contains "--type-check"
let runFormat = args |> List.contains "--format"

BuildFableLibraryPython().Run(skipFableLibrary)
BuildFableLibraryPython(skipCore = skipFableLibraryCore).Run(skipFableLibrary)

Directory.clean buildDir

Expand All @@ -40,7 +41,7 @@ let handle (args: string list) =
if isWatch then
let ruffCmd =
if runFormat then
$"uv run ruff check --select I --fix {buildDir} && uv run ruff format {buildDir} && "
$"uv run ruff check --select I,F401 --fix {buildDir} && uv run ruff format {buildDir} && "
else
""

Expand Down Expand Up @@ -71,8 +72,8 @@ let handle (args: string list) =
Command.Fable(fableArgs, workingDirectory = buildDir)

if runFormat then
// Run Ruff linter checking import sorting and fix any issues
Command.Run("uv", $"run ruff check --select I --fix {buildDir}")
// Run Ruff linter checking import sorting and fix any issues, and remove unused imports
Command.Run("uv", $"run ruff check --select I,F401 --fix {buildDir}")
// Run Ruff formatter on all generated files
Command.Run("uv", $"run ruff format {buildDir}")

Expand Down Expand Up @@ -104,4 +105,4 @@ let handle (args: string list) =

printfn "Pyright summary: %s" summaryLine
else
printfn "Skipping type checking (use --typing to enable)"
printfn "Skipping type checking (use --type-check to enable)"
Loading