From 565d5a4200a3830651a9a3748663e51e4a0e8ba0 Mon Sep 17 00:00:00 2001 From: Dag Brattli Date: Sun, 21 Dec 2025 14:01:43 +0100 Subject: [PATCH 1/2] feat: Added summary chapter --- .vscode/settings.json | 1 + Fable.Literate/App.fs | 13 ++-------- README.md | 11 +++++--- chapters/FableLiterate.fs | 1 + chapters/Summary.fs | 54 +++++++++++++++++++++++++++++++++++++++ fable-python.fsproj | 1 + justfile | 30 ++++++++++++---------- 7 files changed, 82 insertions(+), 29 deletions(-) create mode 120000 chapters/FableLiterate.fs create mode 100644 chapters/Summary.fs diff --git a/.vscode/settings.json b/.vscode/settings.json index 1f0bba0..e787e70 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -19,6 +19,7 @@ "nativeint", "ncave", "pathlib", + "pyfile", "pyname", "Pyxpecto", "stroustrup", diff --git a/Fable.Literate/App.fs b/Fable.Literate/App.fs index d65b882..62c74e3 100644 --- a/Fable.Literate/App.fs +++ b/Fable.Literate/App.fs @@ -464,15 +464,6 @@ dotnet fable Fable.Literate/ --lang python -o output/Fable.Literate/ python output/Fable.Literate/app.py chapters/introduction.fs > docs/introduction.md ``` -That's it! A complete literate programming converter in under 200 lines of F#. - -## The Punchline - -If you're reading this, the code worked. - -This entire blog post - every chapter, every code example, every explanation - -was processed by the F# code you just read, compiled to Python, and output -as Markdown. The proof is in the reading. - -Welcome to Fable.Python. Now go build something. +That's it! A complete literate programming converter in under 200 lines of F`#`, +compiled to Python, processing this very blog post. *) diff --git a/README.md b/README.md index c2b3850..445a20d 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,9 @@ This is a comprehensive guide to [Fable.Python](https://github.com/fable-compile 8. **Libraries** - Existing ecosystem (Thoth.Json, AsyncRx, Siren, etc.) *(coming soon)* 9. **Pydantic** - Pydantic interop with Decorate and ClassAttributes 10. **Units of Measure** - Compile-time dimensional analysis -11. **Testing** - XUnit and Fable.Pyxpecto *(coming soon)* -12. **Fabletext: The Strange Loop** - The self-documenting finale +11. **Testing** - Testing F# code with Python test runners +12. **Fable.Literate** - The self-documenting converter +13. **Summary** - Wrap-up, resources, and contributing ## The Strange Loop @@ -74,7 +75,9 @@ chapters/ ├── Testing.fs # Testing with Python ├── FableV5.fs # What's new in Fable v5 ├── Pydantic.fs # Pydantic interop -└── UnitsOfMeasure.fs # Dimensional analysis +├── UnitsOfMeasure.fs # Dimensional analysis +├── FableLiterate.fs # Symlink → ../Fable.Literate/App.fs +└── Summary.fs # Wrap-up and resources Fable.Literate/ ├── App.fs # Fable.Literate converter (F#) └── Fable.Literate.fsproj @@ -94,7 +97,7 @@ docs/ Defined in `justfile`: ```just -chapters := "Introduction Python GettingStarted Interop Bindings Compatibility AsyncProgramming Testing FableV5 Pydantic UnitsOfMeasure" +chapters := "Introduction Python GettingStarted Interop Bindings Compatibility AsyncProgramming Testing FableV5 Pydantic UnitsOfMeasure FableLiterate Summary" ``` To add a new chapter, just add the file and update this list. diff --git a/chapters/FableLiterate.fs b/chapters/FableLiterate.fs new file mode 120000 index 0000000..461e4c6 --- /dev/null +++ b/chapters/FableLiterate.fs @@ -0,0 +1 @@ +../Fable.Literate/App.fs \ No newline at end of file diff --git a/chapters/Summary.fs b/chapters/Summary.fs new file mode 100644 index 0000000..9e1f9b8 --- /dev/null +++ b/chapters/Summary.fs @@ -0,0 +1,54 @@ +(*** hide ***) +module Summary + +(** +# Summary + +We've covered a lot of ground in this guide: + +- **Introduction**: What Fable.Python is and why it matters +- **F`#` for Python Developers**: Bridging the conceptual gap between languages +- **Getting Started**: Setting up your first Fable.Python project +- **Interop**: Seamlessly calling Python libraries from F`#` +- **Bindings**: Creating type-safe wrappers for Python code +- **Compatibility**: Understanding what F`#` features work (and which don't) +- **Async Programming**: Mapping F`#` async to Python's asyncio +- **Testing**: Running F`#` code with pytest and other Python test runners +- **Fable v5**: The latest features including the Rust core and PyPI packages +- **Pydantic**: Building validated data models with Python's favorite library +- **Units of Measure**: Compile-time dimensional analysis that vanishes at runtime +- **Fable.Literate**: A self-documenting literate programming converter + +## The Punchline + +If you're reading this, the code worked. + +This entire blog post - every chapter, every code example, every explanation - +was processed by F`#` code compiled to Python, and output as Markdown. +The proof is in the reading. + +## Get Involved + +The source code for this entire project is available on GitHub: + +**[github.com/cardamomcode/fable-python](https://github.com/cardamomcode/fable-python)** + +The repository contains: +- All the chapter source files (literate F`#`) +- The Fable.Literate converter +- Build scripts and configuration +- The generated blog post + +Found a typo? Want to improve an explanation? Have a better example? +Pull requests are welcome! This is a living document, and contributions +from the community make it better for everyone. + +## Resources + +- [Fable Documentation](https://fable.io/docs/) +- [Fable.Python on GitHub](https://github.com/fable-compiler/Fable.Python/) +- [F`#` Software Foundation](https://fsharp.org/) +- [Fable Discord](https://discord.gg/8c3Ng9N) - The Fable community is friendly and helpful + +Welcome to Fable.Python. Now go build something. +*) diff --git a/fable-python.fsproj b/fable-python.fsproj index 8a2fe4a..eeab6c0 100644 --- a/fable-python.fsproj +++ b/fable-python.fsproj @@ -22,6 +22,7 @@ + diff --git a/justfile b/justfile index e3c9852..e5334a8 100644 --- a/justfile +++ b/justfile @@ -3,7 +3,7 @@ # Chapter order for documentation generation # Edit this list to reorder or add chapters -chapters := "Introduction Python GettingStarted Interop Bindings Compatibility AsyncProgramming Testing FableV5 Pydantic UnitsOfMeasure" +chapters := "Introduction Python GettingStarted Interop Bindings Compatibility AsyncProgramming Testing FableV5 Pydantic UnitsOfMeasure FableLiterate Summary" # Default: show help default: @@ -38,16 +38,17 @@ generate: build format-python for name in {{chapters}}; do # Convert PascalCase to snake_case for Python file naming pyname=$(echo "$name" | sed 's/\([A-Z]\)/_\1/g' | sed 's/^_//' | tr '[:upper:]' '[:lower:]') + # FableLiterate uses different python output path (symlink to Fable.Literate/App.fs) + if [ "$name" = "FableLiterate" ]; then + pyfile="output/Fable.Literate/python.py" + else + pyfile="output/chapters/chapters/${pyname}.py" + fi uv run python output/Fable.Literate/app.py \ - --python-file "output/chapters/chapters/${pyname}.py" \ + --python-file "$pyfile" \ "chapters/${name}.fs" > "docs/${name}.md" echo "Generated docs/${name}.md" done - # Also generate Fable.Literate documentation - uv run python output/Fable.Literate/app.py \ - --python-file "output/Fable.Literate/python.py" \ - Fable.Literate/App.fs > docs/fable-literate.md - echo "Generated docs/fable-literate.md" # Fix markdown lint issues just lint-markdown @@ -59,25 +60,26 @@ blogpost: build format-python for name in {{chapters}}; do # Convert PascalCase to snake_case for Python file naming pyname=$(echo "$name" | sed 's/\([A-Z]\)/_\1/g' | sed 's/^_//' | tr '[:upper:]' '[:lower:]') + # FableLiterate uses different python output path (symlink to Fable.Literate/App.fs) + if [ "$name" = "FableLiterate" ]; then + pyfile="output/Fable.Literate/python.py" + else + pyfile="output/chapters/chapters/${pyname}.py" + fi if $first; then # First chapter keeps original header levels (has the title) uv run python output/Fable.Literate/app.py \ - --python-file "output/chapters/chapters/${pyname}.py" \ + --python-file "$pyfile" \ "chapters/${name}.fs" > docs/blogpost.md first=false else # Remaining chapters get headers increased by one level echo "" >> docs/blogpost.md uv run python output/Fable.Literate/app.py \ - --python-file "output/chapters/chapters/${pyname}.py" \ + --python-file "$pyfile" \ --increase-headers "chapters/${name}.fs" >> docs/blogpost.md fi done - # Include Fable.Literate documenting itself (the meta twist!) - echo "" >> docs/blogpost.md - uv run python output/Fable.Literate/app.py \ - --python-file "output/Fable.Literate/python.py" \ - --increase-headers Fable.Literate/App.fs >> docs/blogpost.md echo "Generated docs/blogpost.md" # Fix markdown lint issues just lint-markdown From ce06a04d81ede3f87ffe6730ce3e851aa1a2d7d8 Mon Sep 17 00:00:00 2001 From: Dag Brattli Date: Sun, 21 Dec 2025 14:01:59 +0100 Subject: [PATCH 2/2] doc: update claude.md --- CLAUDE.md | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index d991bc6..200b003 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -58,16 +58,19 @@ Use `` F`#` `` (backticks around `#`) in markdown headings to prevent markdownli ```text chapters/ -├── introduction.fs # What is Fable.Python, why use it -├── python.fs # F# concepts for Python developers -├── getting-started.fs # Setup, first project, hello world -├── interop.fs # Using existing Python libraries -├── bindings.fs # Creating Python bindings -├── compatibility.fs # F# features supported, limitations -├── async-programming.fs # async vs task, Python asyncio mapping -├── fable-v5.fs # Fable v5 features, Rust core, PyPI -├── pydantic.fs # Pydantic models, DTOs, validation -└── units-of-measure.fs # Compile-time dimensional analysis +├── Introduction.fs # What is Fable.Python, why use it +├── Python.fs # F# concepts for Python developers +├── GettingStarted.fs # Setup, first project, hello world +├── Interop.fs # Using existing Python libraries +├── Bindings.fs # Creating Python bindings +├── Compatibility.fs # F# features supported, limitations +├── AsyncProgramming.fs # async vs task, Python asyncio mapping +├── Testing.fs # Testing F# code with Python test runners +├── FableV5.fs # Fable v5 features, Rust core, PyPI +├── Pydantic.fs # Pydantic models, DTOs, validation +├── UnitsOfMeasure.fs # Compile-time dimensional analysis +├── FableLiterate.fs # Symlink → ../Fable.Literate/App.fs +└── Summary.fs # Wrap-up, resources, repo link Fable.Literate/ ├── App.fs # Fable.Literate converter source (F#) └── Fable.Literate.fsproj