Skip to content

Commit b4727a3

Browse files
simontreanorclaude
andcommitted
Add pip packaging: pyproject.toml (maturin bin) + wheels CI
Package the `pyfun` compiler binary as a pip-installable wheel via maturin's bin bindings, so students/users can `pip install` it without a Rust toolchain (the highest-leverage classroom adoption step). Verified locally on Windows: `maturin build --release` produces pyfun_lang-0.0.1-py3-none-win_amd64.whl, and a clean-venv `pip install` yields a working `pyfun` (check + run confirmed). - pyproject.toml: maturin backend, bindings = "bin", version pulled from Cargo.toml, requires-python >=3.12 (emitted code targets 3.12+). PyPI project name is "pyfun-lang" (the `pyfun` name is a dead 2015 package; the console script stays `pyfun` regardless). - .github/workflows/wheels.yml: lean wheel matrix (linux x86_64/aarch64, windows x64, macOS x86_64/aarch64) + sdist fallback; publishes to PyPI on tag via Trusted Publishing (OIDC, no token). LICENSE + NOTICE auto-bundled. - .gitignore: ignore /dist + egg-info. Publishing is gated on making the repo public and configuring the PyPI trusted publisher; the build jobs run on push/PR meanwhile. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wnrmd4ZvuqpMrRNxEdzE5S
1 parent 358d370 commit b4727a3

3 files changed

Lines changed: 153 additions & 0 deletions

File tree

.github/workflows/wheels.yml

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
# Build platform wheels for `pyfun-lang` and publish to PyPI on a version tag.
2+
#
3+
# Publishing uses PyPI Trusted Publishing (OIDC) — there is NO API token to manage.
4+
# One-time setup before the first release: on PyPI, add a Trusted Publisher for this
5+
# repo pointing at workflow `wheels.yml` and environment `pypi`
6+
# (https://docs.pypi.org/trusted-publishers/). Until that exists, the build jobs still
7+
# run on every push/PR; only the final `release` job needs it, and it runs only on tags.
8+
#
9+
# The wheel matrix is deliberately lean (the common student/dev platforms). Any platform
10+
# without a wheel falls back to the sdist and builds from source (needs Rust). To widen
11+
# coverage, regenerate the full skeleton with: maturin generate-ci github
12+
name: wheels
13+
14+
on:
15+
push:
16+
branches: [main]
17+
tags: ['*']
18+
pull_request:
19+
workflow_dispatch:
20+
21+
permissions:
22+
contents: read
23+
24+
concurrency:
25+
group: wheels-${{ github.ref }}
26+
cancel-in-progress: true
27+
28+
jobs:
29+
linux:
30+
runs-on: ubuntu-22.04
31+
strategy:
32+
matrix:
33+
target: [x86_64, aarch64]
34+
steps:
35+
- uses: actions/checkout@v6
36+
- name: Build wheels
37+
uses: PyO3/maturin-action@v1
38+
with:
39+
target: ${{ matrix.target }}
40+
args: --release --out dist
41+
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
42+
manylinux: auto
43+
- uses: actions/upload-artifact@v6
44+
with:
45+
name: wheels-linux-${{ matrix.target }}
46+
path: dist
47+
48+
windows:
49+
runs-on: windows-latest
50+
steps:
51+
- uses: actions/checkout@v6
52+
- name: Build wheels
53+
uses: PyO3/maturin-action@v1
54+
with:
55+
target: x64
56+
args: --release --out dist
57+
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
58+
- uses: actions/upload-artifact@v6
59+
with:
60+
name: wheels-windows-x64
61+
path: dist
62+
63+
macos:
64+
runs-on: ${{ matrix.runner }}
65+
strategy:
66+
matrix:
67+
include:
68+
- runner: macos-15-intel
69+
target: x86_64
70+
- runner: macos-latest
71+
target: aarch64
72+
steps:
73+
- uses: actions/checkout@v6
74+
- name: Build wheels
75+
uses: PyO3/maturin-action@v1
76+
with:
77+
target: ${{ matrix.target }}
78+
args: --release --out dist
79+
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
80+
- uses: actions/upload-artifact@v6
81+
with:
82+
name: wheels-macos-${{ matrix.target }}
83+
path: dist
84+
85+
sdist:
86+
runs-on: ubuntu-latest
87+
steps:
88+
- uses: actions/checkout@v6
89+
- name: Build sdist
90+
uses: PyO3/maturin-action@v1
91+
with:
92+
command: sdist
93+
args: --out dist
94+
- uses: actions/upload-artifact@v6
95+
with:
96+
name: wheels-sdist
97+
path: dist
98+
99+
release:
100+
name: Publish to PyPI
101+
runs-on: ubuntu-latest
102+
if: startsWith(github.ref, 'refs/tags/')
103+
needs: [linux, windows, macos, sdist]
104+
environment: pypi
105+
permissions:
106+
id-token: write # OIDC token for Trusted Publishing
107+
attestations: write # sign the build artifacts
108+
contents: read
109+
steps:
110+
- uses: actions/download-artifact@v7
111+
with:
112+
pattern: wheels-*
113+
path: dist
114+
merge-multiple: true
115+
- name: Generate artifact attestation
116+
uses: actions/attest-build-provenance@v2
117+
with:
118+
subject-path: 'dist/*'
119+
- name: Publish to PyPI
120+
uses: pypa/gh-action-pypi-publish@release/v1
121+
with:
122+
packages-dir: dist

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55

66
# Cargo.lock is committed for binaries (this crate ships a `pyfun` bin).
77

8+
# Python packaging (maturin wheels + build artifacts)
9+
/dist
10+
*.egg-info/
11+
812
# Editor / OS
913
*.swp
1014
.DS_Store

pyproject.toml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
[build-system]
2+
requires = ["maturin>=1.5,<2.0"]
3+
build-backend = "maturin"
4+
5+
[project]
6+
name = "pyfun-lang"
7+
description = "An F#-inspired, functional-first language that compiles to readable Python."
8+
readme = "README.md"
9+
requires-python = ">=3.12"
10+
license = "Apache-2.0"
11+
authors = [{ name = "Simon Treanor" }]
12+
keywords = ["functional", "compiler", "fsharp", "transpiler", "education"]
13+
classifiers = [
14+
"Development Status :: 3 - Alpha",
15+
"Intended Audience :: Developers",
16+
"Intended Audience :: Education",
17+
"Programming Language :: Python",
18+
"Programming Language :: Rust",
19+
"Topic :: Software Development :: Compilers",
20+
]
21+
dynamic = ["version"]
22+
23+
[project.urls]
24+
Repository = "https://github.com/simontreanor/Pyfun"
25+
26+
[tool.maturin]
27+
bindings = "bin"

0 commit comments

Comments
 (0)